diff --git a/.gitignore b/.gitignore
index 6e3bf59..6f98bf3 100644
--- a/.gitignore
+++ b/.gitignore
@@ -101,7 +101,6 @@
 /chrome/chrome_version_resources.xml
 /chrome/common/extensions/api/api.xml
 /chrome/common/extensions/api/ledger/
-/chrome/Hammer
 /chrome/installer/linux/internal
 /chrome/installer/mac/internal
 /chrome/installer/mac/third_party/xz/xz
@@ -115,7 +114,6 @@
 /chrome/interactive_ui_tests_run.xml
 /chrome/setup.xml
 /chrome/setup_unittests.xml
-/chrome/supplement.gypi
 /chrome/sync_integration_tests_run.xml
 /chrome/test/android/telemetry_tests/browser_tests/*.wpr
 /chrome/test/chromeos/autotest/files/client/deps/chrome_test/test_src/
@@ -177,7 +175,6 @@
 /googleurl
 /gpu/gles2_conform_test
 /infra/.recipe_deps
-/internal_gyp
 /ios/third_party/earl_grey/src
 /ios/third_party/fishhook/src
 /ios/third_party/gcdwebserver/src
diff --git a/AUTHORS b/AUTHORS
index 01d744c..cc2bfc7 100644
--- a/AUTHORS
+++ b/AUTHORS
@@ -560,6 +560,7 @@
 Nikhil Sahni <nikhil.sahni@samsung.com>
 Nikita Ofitserov <himikof@gmail.com>
 Niklas Schulze <me@jns.io>
+Nikola Kovacs <nikola.kovacs@gmail.com>
 Nils Schneider <nils@nilsschneider.net>
 Nils Schneider <nils.schneider@gmail.com>
 Ningxin Hu <ningxin.hu@intel.com>
@@ -887,6 +888,7 @@
 Jan Rucka <ruckajan10@gmail.com>
 Yannic Bonenberger <contact@yannic-bonenberger.com>
 Kyoungdeok Kwon <kkd927@gmail.com>
+Kyungyoung Heo <bbvch13531@gmail.com>
 
 ACCESS CO., LTD. <*@access-company.com>
 BlackBerry Limited <*@blackberry.com>
diff --git a/DEPS b/DEPS
index 121083e..bd1f0bc 100644
--- a/DEPS
+++ b/DEPS
@@ -38,10 +38,14 @@
   # custom_vars.
   'checkout_src_internal': False,
 
+  # libaom provides support for AV1 but the bitstream is not frozen.
+  'checkout_libaom': False,
+
   # TODO(dpranke): change to != "small" once != is supported.
   'checkout_traffic_annotation_tools': 'checkout_configuration == "default"',
   'checkout_instrumented_libraries': 'checkout_linux and checkout_configuration == "default"',
 
+  'aomedia_git': 'https://aomedia.googlesource.com',
   'chromium_git': 'https://chromium.googlesource.com',
   'swiftshader_git': 'https://swiftshader.googlesource.com',
   'pdfium_git': 'https://pdfium.googlesource.com',
@@ -55,11 +59,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': '6566b97b76d3cb76ee255a3d128d048376d300bd',
+  'skia_revision': '45d6303f6e8403db9499ab28494f672b2bcd034e',
   # 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': '0a86db8f93804983baf12747d07bd631197636c7',
+  'v8_revision': '34cad05e815d5a950b187c9fac4964a9b13d3add',
   # 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.
@@ -67,19 +71,19 @@
   # 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': 'b79e7bb691ae93f576837ffbaa85e30dda36054a',
+  'angle_revision': '163965d5ce2b333f4a017e542b43d5426de96453',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling build tools
   # and whatever else without interference from each other.
-  'buildtools_revision': 'e043d81e9185a2445fa3ec3fc34a4f69b58d4969',
+  'buildtools_revision': '3275a099f3c199b50ff97117aa0184f3e91f8a32',
   # 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': '6e27fea85f863bcc620761efc678e9ad3e5f6ff4',
+  'swiftshader_revision': 'e2febff0f79aab45451c5d20e59e3b55040f2fa6',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling PDFium
   # and whatever else without interference from each other.
-  'pdfium_revision': '704cf8361659c4719d1294048a0e37991fa41748',
+  'pdfium_revision': '8aa3002c673f36909560575514b9a9474e5e66bf',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling openmax_dl
   # and whatever else without interference from each other.
@@ -111,7 +115,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': '52d748d48b4d5b334c0416954ac73f4c352b6627',
+  'catapult_revision': '6fd9f08dcb0bd39f70bdac8d73aa4e87b789d6e5',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling libFuzzer
   # and whatever else without interference from each other.
@@ -130,6 +134,7 @@
 # If you need to add a new host, contact chrome infrastracture team.
 allowed_hosts = [
   'android.googlesource.com',
+  'aomedia.googlesource.com',
   'boringssl.googlesource.com',
   'chrome-internal.googlesource.com',
   'chromium.googlesource.com',
@@ -222,7 +227,7 @@
   },
 
   'src/third_party/android_tools': {
-      'url': Var('chromium_git') + '/android_tools.git' + '@' + '110e5f6c0dcb6f7d586ac0c00f10bc7d1d410088',
+      'url': Var('chromium_git') + '/android_tools.git' + '@' + 'ca0bd083872ad925881736fe2bedc3ff855e08f5',
       'condition': 'checkout_android',
   },
 
@@ -274,7 +279,7 @@
 
   # For Linux and Chromium OS.
   'src/third_party/cros_system_api': {
-      'url': Var('chromium_git') + '/chromiumos/platform/system_api.git' + '@' + '53717bc2de485531ef39c439edaf35a264cb2fb7',
+      'url': Var('chromium_git') + '/chromiumos/platform/system_api.git' + '@' + '47afcabaf957c013418ef2a33481ec1fe764dc94',
       'condition': 'checkout_linux',
   },
 
@@ -284,7 +289,7 @@
   },
 
   'src/third_party/depot_tools':
-    Var('chromium_git') + '/chromium/tools/depot_tools.git' + '@' + '105e11e2516ce928c9efc90364b5ffba74162786',
+    Var('chromium_git') + '/chromium/tools/depot_tools.git' + '@' + '7d1c484ecd93e94c5258dc330602ac37c5efab44',
 
   # DevTools node modules. Used on Linux buildbots only.
   'src/third_party/devtools-node-modules': {
@@ -394,9 +399,14 @@
   'src/third_party/libaddressinput/src':
     Var('chromium_git') + '/external/libaddressinput.git' + '@' + '8200a3221282582ca3291ef219257ca4be7426ca',
 
+  'src/third_party/libaom/source/libaom': {
+    'url': Var('aomedia_git') + '/aom.git' + '@' +  'd9f2286e4c0bbb0fee5719d151653247939c3847',
+    'condition': 'checkout_libaom',
+  },
+
   # Userspace interface to kernel DRM services.
   'src/third_party/libdrm/src': {
-      'url': Var('chromium_git') + '/chromiumos/third_party/libdrm.git' + '@' + '0ce18bedd3e62d4784fa755403801934ba171084',
+      'url': Var('chromium_git') + '/chromiumos/third_party/libdrm.git' + '@' + '16ffb1e6fce0fbd57f7a1e76021c575a40f6dc7a',
       'condition': 'checkout_linux',
   },
 
@@ -595,7 +605,7 @@
     Var('chromium_git') + '/external/khronosgroup/webgl.git' + '@' + '34842fa3c36988840c89f5bc6a68503175acf7d9',
 
   'src/third_party/webrtc':
-    Var('webrtc_git') + '/src.git' + '@' + '5d7fd19c209f703b6abf455bf69793e6741a1a4d', # commit position 20237
+    Var('webrtc_git') + '/src.git' + '@' + '1cf1b7d66fbc8b0abfb0e6c92770597b2102d3ed', # commit position 20237
 
   'src/third_party/xdg-utils': {
       'url': Var('chromium_git') + '/chromium/deps/xdg-utils.git' + '@' + 'd80274d5869b17b8c9067a1022e4416ee7ed5e0d',
@@ -618,7 +628,7 @@
     Var('chromium_git') + '/v8/v8.git' + '@' +  Var('v8_revision'),
 
   'src-internal': {
-    'url': 'https://chrome-internal.googlesource.com/chrome/src-internal.git@cbae27f0a0f7d4fe0d6fb31bc9963a6942de5ec1',
+    'url': 'https://chrome-internal.googlesource.com/chrome/src-internal.git@2c1ee306751c58c05daf7a5c3756d32d8bf2d8aa',
     'condition': 'checkout_src_internal',
   },
 }
@@ -1426,7 +1436,7 @@
     'action': [
       'python',
       'src/build/fuchsia/update_sdk.py',
-      '492eec9e40c9832dd8772f4718b7db6aac4d7921',
+      '04840186b5fc14dc35b12e77f8028330a4bd8333',
     ],
   },
 
diff --git a/PRESUBMIT.py b/PRESUBMIT.py
index f74b057..77338a63 100644
--- a/PRESUBMIT.py
+++ b/PRESUBMIT.py
@@ -924,7 +924,7 @@
   args = [input_api.python_executable, checkperms_tool,
           '--root', input_api.change.RepositoryRoot()]
   for f in input_api.AffectedFiles():
-    args += ['--file', f.LocalPath()]
+    args += ['--file', f.AbsoluteLocalPath()]
   try:
     input_api.subprocess.check_output(args)
     return []
@@ -2669,20 +2669,13 @@
     r'.+%s' % _IMPLEMENTATION_EXTENSIONS
   )
 
-  filter = lambda f: input_api.FilterSourceFile(
-    f, white_list=file_inclusion_pattern, black_list=None)
-  files = [f.LocalPath() for f in
-           input_api.AffectedSourceFiles(filter)]
-
   problems = []
-
-  for file in files:
-    fp = open(file, 'r')
-    for line in fp:
+  source_file_filter = lambda f: input_api.FilterSourceFile(
+      f, white_list=file_inclusion_pattern, black_list=None)
+  for f in input_api.AffectedSourceFiles(source_file_filter):
+    for line_number, line in f.ChangedContents():
       if line.endswith('\r\n'):
-        problems.append(file)
-        break
-    fp.close()
+        problems.append(f.LocalPath())
 
   if problems:
     return [output_api.PresubmitPromptWarning('Are you sure that you want '
diff --git a/ash/BUILD.gn b/ash/BUILD.gn
index 7ef92ce..5aae07f 100644
--- a/ash/BUILD.gn
+++ b/ash/BUILD.gn
@@ -253,6 +253,8 @@
     "login/ui/login_base_bubble_view.h",
     "login/ui/login_bubble.cc",
     "login/ui/login_bubble.h",
+    "login/ui/login_button.cc",
+    "login/ui/login_button.h",
     "login/ui/login_constants.h",
     "login/ui/login_data_dispatcher.cc",
     "login/ui/login_data_dispatcher.h",
diff --git a/ash/accelerators/accelerator_controller.cc b/ash/accelerators/accelerator_controller.cc
index 00d5eab..d3e3a25e 100644
--- a/ash/accelerators/accelerator_controller.cc
+++ b/ash/accelerators/accelerator_controller.cc
@@ -684,7 +684,7 @@
                              const ui::Accelerator& previous_accelerator) {
   chromeos::input_method::InputMethodManager* ime =
       chromeos::input_method::InputMethodManager::Get();
-  if (!ime)
+  if (!ime || !ime->GetImeKeyboard())
     return false;
 
   // This shortcust is set to be trigger on release. Either the current
@@ -698,7 +698,7 @@
             ui::Accelerator::KeyState::PRESSED &&
         (previous_accelerator.key_code() == ui::VKEY_LWIN ||
          previous_accelerator.key_code() == ui::VKEY_MENU)) {
-      return ime->GetImeKeyboard();
+      return true;
     }
   }
 
@@ -712,16 +712,10 @@
             ui::Accelerator::KeyState::PRESSED &&
         (previous_accelerator.key_code() == ui::VKEY_LWIN ||
          previous_accelerator.key_code() == ui::VKEY_MENU)) {
-      return ime->GetImeKeyboard();
+      return true;
     }
   }
 
-  // Caps Lock release
-  if (accelerator.key_code() == ui::VKEY_CAPITAL &&
-      accelerator.key_state() == ui::Accelerator::KeyState::RELEASED) {
-    return ime->GetImeKeyboard();
-  }
-
   return false;
 }
 
diff --git a/ash/accelerators/accelerator_controller_unittest.cc b/ash/accelerators/accelerator_controller_unittest.cc
index 16b5f13..5f9369a 100644
--- a/ash/accelerators/accelerator_controller_unittest.cc
+++ b/ash/accelerators/accelerator_controller_unittest.cc
@@ -118,8 +118,8 @@
   }
   void SetBrightnessPercent(double percent, bool gradual) override {}
   void GetBrightnessPercent(
-      const base::Callback<void(double)>& callback) override {
-    callback.Run(100.0);
+      base::OnceCallback<void(base::Optional<double>)> callback) override {
+    std::move(callback).Run(100.0);
   }
 
   int handle_brightness_down_count() const {
@@ -968,7 +968,7 @@
 
 namespace {
 
-// Tests the five combinations of the TOGGLE_CAPS_LOCK accelerator.
+// Tests the four combinations of the TOGGLE_CAPS_LOCK accelerator.
 TEST_F(AcceleratorControllerTest, ToggleCapsLockAccelerators) {
   chromeos::input_method::InputMethodManager* input_method_manager =
       chromeos::input_method::InputMethodManager::Get();
@@ -1009,15 +1009,6 @@
   EXPECT_TRUE(ProcessInController(release_alt_before_search));
   EXPECT_TRUE(input_method_manager->GetImeKeyboard()->CapsLockIsEnabled());
   input_method_manager->GetImeKeyboard()->SetCapsLockEnabled(false);
-
-  // 5. Press Caps Lock, Release Caps Lock.
-  const ui::Accelerator press_caps_lock(ui::VKEY_CAPITAL, ui::EF_NONE);
-  EXPECT_FALSE(ProcessInController(press_caps_lock));
-  EXPECT_FALSE(input_method_manager->GetImeKeyboard()->CapsLockIsEnabled());
-  const ui::Accelerator release_caps_lock(
-      CreateReleaseAccelerator(ui::VKEY_CAPITAL, ui::EF_NONE));
-  EXPECT_TRUE(ProcessInController(release_caps_lock));
-  EXPECT_TRUE(input_method_manager->GetImeKeyboard()->CapsLockIsEnabled());
 }
 
 class PreferredReservedAcceleratorsTest : public AshTestBase {
diff --git a/ash/accelerators/accelerator_table.cc b/ash/accelerators/accelerator_table.cc
index 5b313ea..c53d39b 100644
--- a/ash/accelerators/accelerator_table.cc
+++ b/ash/accelerators/accelerator_table.cc
@@ -89,7 +89,6 @@
     // down. The key_code here is MENU (for Alt) and Search is a modifier
     // (EF_COMMAND_DOWN is used for Search as a modifier).
     {false, ui::VKEY_MENU, ui::EF_COMMAND_DOWN, TOGGLE_CAPS_LOCK},
-    {false, ui::VKEY_CAPITAL, ui::EF_NONE, TOGGLE_CAPS_LOCK},
     {true, ui::VKEY_VOLUME_MUTE, ui::EF_NONE, VOLUME_MUTE},
     {true, ui::VKEY_VOLUME_DOWN, ui::EF_NONE, VOLUME_DOWN},
     {true, ui::VKEY_VOLUME_UP, ui::EF_NONE, VOLUME_UP},
diff --git a/ash/accelerators/accelerator_table_unittest.cc b/ash/accelerators/accelerator_table_unittest.cc
index 00e72c4..63f2a9b 100644
--- a/ash/accelerators/accelerator_table_unittest.cc
+++ b/ash/accelerators/accelerator_table_unittest.cc
@@ -15,12 +15,12 @@
 
 namespace {
 
-// The number of non-Search-based accelerators as of 2017-07-13.
-constexpr int kNonSearchAcceleratorsNum = 94;
-// The hash of non-Search-based accelerators as of 2017-07-19.
+// The number of non-Search-based accelerators as of 2017-10-26.
+constexpr int kNonSearchAcceleratorsNum = 93;
+// The hash of non-Search-based accelerators as of 2017-10-26.
 // See HashAcceleratorData().
 constexpr char kNonSearchAcceleratorsHash[] =
-    "d36dd12d75b39fe7175858af6077f13b";
+    "f49b50d5990e0d2af99160176c6215f7";
 
 struct Cmp {
   bool operator()(const AcceleratorData& lhs, const AcceleratorData& rhs) {
diff --git a/ash/app_list/app_list_presenter_delegate_unittest.cc b/ash/app_list/app_list_presenter_delegate_unittest.cc
index 2704194..794fd463 100644
--- a/ash/app_list/app_list_presenter_delegate_unittest.cc
+++ b/ash/app_list/app_list_presenter_delegate_unittest.cc
@@ -19,7 +19,6 @@
 #include "ash/wm/window_util.h"
 #include "base/command_line.h"
 #include "base/macros.h"
-#include "base/test/scoped_feature_list.h"
 #include "ui/app_list/app_list_features.h"
 #include "ui/app_list/app_list_switches.h"
 #include "ui/app_list/views/app_list_main_view.h"
@@ -78,49 +77,6 @@
   void SetUp() override {
     AshTestBase::SetUp();
 
-    if (testing::UnitTest::GetInstance()->current_test_info()->value_param() &&
-        GetParam()) {
-      EnableFullscreenAppList();
-    }
-
-    // Make the display big enough to hold the app list.
-    UpdateDisplay("1024x768");
-
-    app_list_presenter_impl_ = std::make_unique<TestAppListPresenterImpl>();
-  }
-
-  void EnableFullscreenAppList() {
-    scoped_feature_list_.InitAndEnableFeature(
-        app_list::features::kEnableFullscreenAppList);
-  }
-
- private:
-  std::unique_ptr<TestAppListPresenterImpl> app_list_presenter_impl_;
-  base::test::ScopedFeatureList scoped_feature_list_;
-
-  DISALLOW_COPY_AND_ASSIGN(AppListPresenterDelegateTest);
-};
-
-// TODO(Newcomer): Remove FullscreenAppListPresenterDelegateTest when the
-// fullscreen app list becomes default.
-class FullscreenAppListPresenterDelegateTest
-    : public AshTestBase,
-      public testing::WithParamInterface<bool> {
- public:
-  FullscreenAppListPresenterDelegateTest() {}
-  ~FullscreenAppListPresenterDelegateTest() override {}
-
-  TestAppListPresenterImpl* app_list_presenter_impl() {
-    return app_list_presenter_impl_.get();
-  }
-
-  // testing::Test:
-  void SetUp() override {
-    AshTestBase::SetUp();
-
-    scoped_feature_list_.InitAndEnableFeature(
-        app_list::features::kEnableFullscreenAppList);
-
     // Make the display big enough to hold the app list.
     UpdateDisplay("1024x768");
 
@@ -143,23 +99,16 @@
 
  private:
   std::unique_ptr<TestAppListPresenterImpl> app_list_presenter_impl_;
-  base::test::ScopedFeatureList scoped_feature_list_;
 
-  DISALLOW_COPY_AND_ASSIGN(FullscreenAppListPresenterDelegateTest);
+  DISALLOW_COPY_AND_ASSIGN(AppListPresenterDelegateTest);
 };
 
-// Instantiate the Boolean which is used to toggle the Fullscreen app list in
-// the parameterized tests.
-INSTANTIATE_TEST_CASE_P(, AppListPresenterDelegateTest, testing::Bool());
-
 // Instantiate the Boolean which is used to toggle mouse and touch events in
 // the parameterized tests.
-INSTANTIATE_TEST_CASE_P(,
-                        FullscreenAppListPresenterDelegateTest,
-                        testing::Bool());
+INSTANTIATE_TEST_CASE_P(, AppListPresenterDelegateTest, testing::Bool());
 
 // Tests that app list hides when focus moves to a normal window.
-TEST_P(AppListPresenterDelegateTest, HideOnFocusOut) {
+TEST_F(AppListPresenterDelegateTest, HideOnFocusOut) {
   app_list_presenter_impl()->ShowAndRunLoop(GetPrimaryDisplayId());
   EXPECT_TRUE(app_list_presenter_impl()->GetTargetVisibility());
 
@@ -170,7 +119,7 @@
 
 // Tests that app list remains visible when focus is moved to a different
 // window in kShellWindowId_AppListContainer.
-TEST_P(AppListPresenterDelegateTest,
+TEST_F(AppListPresenterDelegateTest,
        RemainVisibleWhenFocusingToApplistContainer) {
   app_list_presenter_impl()->ShowAndRunLoop(GetPrimaryDisplayId());
   EXPECT_TRUE(app_list_presenter_impl()->GetTargetVisibility());
@@ -237,7 +186,7 @@
 }
 
 // Tests opening the app list on a secondary display, then deleting the display.
-TEST_P(AppListPresenterDelegateTest, NonPrimaryDisplay) {
+TEST_F(AppListPresenterDelegateTest, NonPrimaryDisplay) {
   // Set up a screen with two displays (horizontally adjacent).
   UpdateDisplay("1024x768,1024x768");
 
@@ -284,7 +233,7 @@
 }
 
 // Tests that the app list is not draggable in side shelf alignment.
-TEST_F(FullscreenAppListPresenterDelegateTest, SideShelfAlignmentDragDisabled) {
+TEST_F(AppListPresenterDelegateTest, SideShelfAlignmentDragDisabled) {
   SetShelfAlignment(ShelfAlignment::SHELF_ALIGNMENT_RIGHT);
   app_list_presenter_impl()->ShowAndRunLoop(GetPrimaryDisplayId());
   const app_list::AppListView* app_list = app_list_presenter_impl()->GetView();
@@ -310,8 +259,7 @@
 
 // Tests that the app list initializes in fullscreen with side shelf alignment
 // and that the state transitions via text input act properly.
-TEST_F(FullscreenAppListPresenterDelegateTest,
-       SideShelfAlignmentTextStateTransitions) {
+TEST_F(AppListPresenterDelegateTest, SideShelfAlignmentTextStateTransitions) {
   // TODO(newcomer): Investigate mash failures crbug.com/726838
   SetShelfAlignment(ShelfAlignment::SHELF_ALIGNMENT_LEFT);
 
@@ -339,8 +287,7 @@
 
 // Tests that the app list initializes in peeking with bottom shelf alignment
 // and that the state transitions via text input act properly.
-TEST_F(FullscreenAppListPresenterDelegateTest,
-       BottomShelfAlignmentTextStateTransitions) {
+TEST_F(AppListPresenterDelegateTest, BottomShelfAlignmentTextStateTransitions) {
   // TODO(newcomer): Investigate mash failures crbug.com/726838
   app_list_presenter_impl()->ShowAndRunLoop(GetPrimaryDisplayId());
   app_list::AppListView* app_list = app_list_presenter_impl()->GetView();
@@ -361,7 +308,7 @@
 
 // Tests that the app list initializes in fullscreen with tablet mode active
 // and that the state transitions via text input act properly.
-TEST_F(FullscreenAppListPresenterDelegateTest, TabletModeTextStateTransitions) {
+TEST_F(AppListPresenterDelegateTest, TabletModeTextStateTransitions) {
   // TODO(newcomer): Investigate mash failures crbug.com/726838
   EnableTabletMode(true);
   app_list_presenter_impl()->ShowAndRunLoop(GetPrimaryDisplayId());
@@ -385,7 +332,7 @@
 
 // Tests that the app list state responds correctly to tablet mode being
 // enabled while the app list is being shown.
-TEST_F(FullscreenAppListPresenterDelegateTest,
+TEST_F(AppListPresenterDelegateTest,
        PeekingToFullscreenWhenTabletModeIsActive) {
   // TODO(newcomer): Investigate mash failures crbug.com/726838
   app_list_presenter_impl()->ShowAndRunLoop(GetPrimaryDisplayId());
@@ -416,8 +363,7 @@
 
 // Tests that the app list state responds correctly to tablet mode being
 // enabled while the app list is being shown with half launcher.
-TEST_F(FullscreenAppListPresenterDelegateTest,
-       HalfToFullscreenWhenTabletModeIsActive) {
+TEST_F(AppListPresenterDelegateTest, HalfToFullscreenWhenTabletModeIsActive) {
   // TODO(newcomer): Investigate mash failures crbug.com/726838
   app_list_presenter_impl()->ShowAndRunLoop(GetPrimaryDisplayId());
   app_list::AppListView* app_list = app_list_presenter_impl()->GetView();
@@ -439,7 +385,7 @@
 }
 
 // Tests that the app list view handles drag properly in laptop mode.
-TEST_F(FullscreenAppListPresenterDelegateTest, AppListViewDragHandler) {
+TEST_F(AppListPresenterDelegateTest, AppListViewDragHandler) {
   // TODO(newcomer): Investigate mash failures crbug.com/726838
   app_list_presenter_impl()->ShowAndRunLoop(GetPrimaryDisplayId());
   app_list::AppListView* app_list = app_list_presenter_impl()->GetView();
@@ -514,7 +460,7 @@
 }
 
 // Tests that the app list view handles drag properly in tablet mode.
-TEST_F(FullscreenAppListPresenterDelegateTest,
+TEST_F(AppListPresenterDelegateTest,
        AppListViewDragHandlerTabletModeFromAllApps) {
   // TODO(newcomer): Investigate mash failures crbug.com/726838
   EnableTabletMode(true);
@@ -533,7 +479,7 @@
 
 // Tests that the state of the app list changes properly with drag input from
 // fullscreen search.
-TEST_F(FullscreenAppListPresenterDelegateTest,
+TEST_F(AppListPresenterDelegateTest,
        AppListViewDragHandlerTabletModeFromSearch) {
   // TODO(newcomer): Investigate mash failures crbug.com/726838
   EnableTabletMode(true);
@@ -556,7 +502,7 @@
 
 // Tests that the bottom shelf background is hidden when the app list is shown
 // in laptop mode.
-TEST_F(FullscreenAppListPresenterDelegateTest,
+TEST_F(AppListPresenterDelegateTest,
        ShelfBackgroundIsHiddenWhenAppListIsShown) {
   app_list_presenter_impl()->ShowAndRunLoop(GetPrimaryDisplayId());
   ShelfLayoutManager* shelf_layout_manager =
@@ -568,8 +514,7 @@
 
 // Tests that the peeking app list closes if the user taps or clicks outside
 // its bounds.
-TEST_P(FullscreenAppListPresenterDelegateTest,
-       TapAndClickOutsideClosesPeekingAppList) {
+TEST_P(AppListPresenterDelegateTest, TapAndClickOutsideClosesPeekingAppList) {
   const bool test_mouse_event = TestMouseEventParam();
   app_list_presenter_impl()->ShowAndRunLoop(GetPrimaryDisplayId());
   EXPECT_EQ(app_list::AppListView::PEEKING,
@@ -593,7 +538,7 @@
   EXPECT_FALSE(app_list_presenter_impl()->IsVisible());
 }
 
-TEST_P(FullscreenAppListPresenterDelegateTest, LongPressOutsideCloseAppList) {
+TEST_P(AppListPresenterDelegateTest, LongPressOutsideCloseAppList) {
   app_list_presenter_impl()->ShowAndRunLoop(GetPrimaryDisplayId());
   EXPECT_TRUE(app_list_presenter_impl()->IsVisible());
 
@@ -610,8 +555,7 @@
   EXPECT_FALSE(app_list_presenter_impl()->IsVisible());
 }
 
-TEST_P(FullscreenAppListPresenterDelegateTest,
-       TwoFingerTapOutsideCloseAppList) {
+TEST_P(AppListPresenterDelegateTest, TwoFingerTapOutsideCloseAppList) {
   app_list_presenter_impl()->ShowAndRunLoop(GetPrimaryDisplayId());
   EXPECT_TRUE(app_list_presenter_impl()->IsVisible());
 
@@ -630,7 +574,7 @@
 
 // Tests that a keypress activates the searchbox and that clearing the
 // searchbox, the searchbox remains active.
-TEST_F(FullscreenAppListPresenterDelegateTest, KeyPressEnablesSearchBox) {
+TEST_F(AppListPresenterDelegateTest, KeyPressEnablesSearchBox) {
   app_list_presenter_impl()->ShowAndRunLoop(GetPrimaryDisplayId());
   ui::test::EventGenerator& generator = GetEventGenerator();
   app_list::SearchBoxView* search_box_view =
@@ -649,7 +593,7 @@
 // Tests that a tap/click on the AppListView from half launcher returns the
 // AppListView to Peeking, and that a tap/click on the AppListView from
 // Peeking closes the app list.
-TEST_P(FullscreenAppListPresenterDelegateTest,
+TEST_P(AppListPresenterDelegateTest,
        StateTransitionsByTapAndClickingAppListBodyFromHalf) {
   const bool test_mouse_event = TestMouseEventParam();
   app_list_presenter_impl()->ShowAndRunLoop(GetPrimaryDisplayId());
@@ -692,7 +636,7 @@
 // Tests that a tap/click on the AppListView from Fullscreen search returns
 // the AppListView to fullscreen all apps, and that a tap/click on the
 // AppListView from fullscreen all apps closes the app list.
-TEST_P(FullscreenAppListPresenterDelegateTest,
+TEST_P(AppListPresenterDelegateTest,
        StateTransitionsByTappingAppListBodyFromFullscreen) {
   const bool test_mouse_event = TestMouseEventParam();
   app_list_presenter_impl()->ShowAndRunLoop(GetPrimaryDisplayId());
@@ -742,7 +686,7 @@
 
 // Tests that the searchbox activates when it is tapped and that the widget is
 // closed after tapping outside the searchbox.
-TEST_P(FullscreenAppListPresenterDelegateTest, TapAndClickEnablesSearchBox) {
+TEST_P(AppListPresenterDelegateTest, TapAndClickEnablesSearchBox) {
   const bool test_mouse_event = TestMouseEventParam();
   app_list_presenter_impl()->ShowAndRunLoop(GetPrimaryDisplayId());
   app_list::SearchBoxView* search_box_view =
@@ -790,7 +734,7 @@
   // TODO(newcomer): Investigate mash failures crbug.com/726838
   if (Shell::GetAshConfig() == Config::MASH)
     return;
-  EnableFullscreenAppList();
+
   GetPrimaryShelf()->SetAlignment(SHELF_ALIGNMENT_BOTTOM);
 
   // Show the app list, the shelf background should be transparent.
@@ -813,7 +757,7 @@
 
 // Tests that the app list in HALF with an active search transitions to PEEKING
 // after the body is clicked/tapped.
-TEST_P(FullscreenAppListPresenterDelegateTest, HalfToPeekingByClickOrTap) {
+TEST_P(AppListPresenterDelegateTest, HalfToPeekingByClickOrTap) {
   app_list_presenter_impl()->ShowAndRunLoop(GetPrimaryDisplayId());
   ui::test::EventGenerator& generator = GetEventGenerator();
 
@@ -845,8 +789,7 @@
 }
 
 // Tests that the half app list closes if the user taps outside its bounds.
-TEST_P(FullscreenAppListPresenterDelegateTest,
-       TapAndClickOutsideClosesHalfAppList) {
+TEST_P(AppListPresenterDelegateTest, TapAndClickOutsideClosesHalfAppList) {
   // TODO(newcomer): Investigate mash failures crbug.com/726838
   app_list_presenter_impl()->ShowAndRunLoop(GetPrimaryDisplayId());
   ui::test::EventGenerator& generator = GetEventGenerator();
@@ -868,7 +811,7 @@
 
 // Tests that the search box is set active with a whitespace query and that the
 // app list state doesn't transition with a whitespace query.
-TEST_F(FullscreenAppListPresenterDelegateTest, WhitespaceQuery) {
+TEST_F(AppListPresenterDelegateTest, WhitespaceQuery) {
   app_list_presenter_impl()->ShowAndRunLoop(GetPrimaryDisplayId());
   app_list::AppListView* view = app_list_presenter_impl()->GetView();
   ui::test::EventGenerator& generator = GetEventGenerator();
@@ -896,7 +839,7 @@
 
 // Tests that an unhandled tap/click in Peeking mode closes the app
 // list.
-TEST_P(FullscreenAppListPresenterDelegateTest, UnhandledEventOnPeeking) {
+TEST_P(AppListPresenterDelegateTest, UnhandledEventOnPeeking) {
   app_list_presenter_impl()->ShowAndRunLoop(GetPrimaryDisplayId());
   app_list::AppListView* view = app_list_presenter_impl()->GetView();
   ASSERT_EQ(view->app_list_state(), app_list::AppListView::PEEKING);
@@ -920,7 +863,7 @@
 
 // Tests that a drag to the bezel from Fullscreen/Peeking will close the app
 // list.
-TEST_P(FullscreenAppListPresenterDelegateTest,
+TEST_P(AppListPresenterDelegateTest,
        DragToBezelClosesAppListFromFullscreenAndPeeking) {
   const bool test_fullscreen = GetParam();
   app_list_presenter_impl()->Show(GetPrimaryDisplayId());
@@ -949,7 +892,7 @@
 }
 
 // Tests that a fling from Fullscreen/Peeking closes the app list.
-TEST_P(FullscreenAppListPresenterDelegateTest,
+TEST_P(AppListPresenterDelegateTest,
        FlingDownClosesAppListFromFullscreenAndPeeking) {
   const bool test_fullscreen = GetParam();
   app_list_presenter_impl()->Show(GetPrimaryDisplayId());
@@ -969,7 +912,7 @@
   EXPECT_FALSE(app_list_presenter_impl()->IsVisible());
 }
 
-TEST_F(FullscreenAppListPresenterDelegateTest,
+TEST_F(AppListPresenterDelegateTest,
        MouseWheelFromAppListPresenterImplTransitionsAppListState) {
   app_list_presenter_impl()->Show(GetPrimaryDisplayId());
   app_list::AppListView* view = app_list_presenter_impl()->GetView();
@@ -980,8 +923,7 @@
   ASSERT_EQ(app_list::AppListView::FULLSCREEN_ALL_APPS, view->app_list_state());
 }
 
-TEST_P(FullscreenAppListPresenterDelegateTest,
-       LongUpwardDragInFullscreenShouldNotClose) {
+TEST_P(AppListPresenterDelegateTest, LongUpwardDragInFullscreenShouldNotClose) {
   const bool test_fullscreen_search = GetParam();
   app_list_presenter_impl()->Show(GetPrimaryDisplayId());
   app_list::AppListView* view = app_list_presenter_impl()->GetView();
@@ -1013,8 +955,7 @@
 }
 
 // Tests that a drag can not make the app list smaller than the shelf height.
-TEST_F(FullscreenAppListPresenterDelegateTest,
-       LauncherCannotGetSmallerThanShelf) {
+TEST_F(AppListPresenterDelegateTest, LauncherCannotGetSmallerThanShelf) {
   app_list_presenter_impl()->Show(GetPrimaryDisplayId());
   app_list::AppListView* view = app_list_presenter_impl()->GetView();
 
diff --git a/ash/ash_strings.grd b/ash/ash_strings.grd
index 255099d..2ab50df5 100644
--- a/ash/ash_strings.grd
+++ b/ash/ash_strings.grd
@@ -879,6 +879,12 @@
       <message name="IDS_ASH_STATUS_TRAY_INITIALIZING_CELLULAR" desc="Message for the status area when initializing the cellular device.">
         Initializing...
       </message>
+      <message name="IDS_ASH_STATUS_TRAY_SIM_CARD_MISSING" desc="Message for the status area when a SIM card is missing.">
+        Missing SIM card
+      </message>
+      <message name="IDS_ASH_STATUS_TRAY_SIM_CARD_LOCKED" desc="Message for the status area when a SIM card is locked.">
+        SIM card is locked
+      </message>
       <message name="IDS_ASH_STATUS_TRAY_NETWORK_ACTIVATING" desc="Message for the network tray tooltip and network list when activating a network.">
         Activating <ph name="NAME">$1<ex>YBH Cellular</ex></ph>
       </message>
diff --git a/ash/frame/caption_buttons/frame_caption_button_container_view.cc b/ash/frame/caption_buttons/frame_caption_button_container_view.cc
index 0cf7773..c78d373 100644
--- a/ash/frame/caption_buttons/frame_caption_button_container_view.cc
+++ b/ash/frame/caption_buttons/frame_caption_button_container_view.cc
@@ -23,6 +23,7 @@
 #include "ui/gfx/geometry/point.h"
 #include "ui/gfx/vector_icon_types.h"
 #include "ui/strings/grit/ui_strings.h"  // Accessibility names
+#include "ui/views/layout/box_layout.h"
 #include "ui/views/widget/widget.h"
 #include "ui/views/widget/widget_delegate.h"
 
@@ -115,6 +116,11 @@
       minimize_button_(NULL),
       size_button_(NULL),
       close_button_(NULL) {
+  auto layout =
+      std::make_unique<views::BoxLayout>(views::BoxLayout::kHorizontal);
+  layout->set_cross_axis_alignment(
+      views::BoxLayout::CROSS_AXIS_ALIGNMENT_CENTER);
+  SetLayoutManager(layout.release());
   bool size_button_visibility = ShouldSizeButtonBeVisible();
   tablet_mode_animation_.reset(new gfx::SlideAnimation(this));
   tablet_mode_animation_->SetTweenType(gfx::Tween::LINEAR);
@@ -211,27 +217,8 @@
   close_button_->SetPreferredSize(size);
 }
 
-gfx::Size FrameCaptionButtonContainerView::CalculatePreferredSize() const {
-  int width = 0;
-  for (int i = 0; i < child_count(); ++i) {
-    const views::View* child = child_at(i);
-    if (child->visible())
-      width += child_at(i)->GetPreferredSize().width();
-  }
-  return gfx::Size(width, close_button_->GetPreferredSize().height());
-}
-
 void FrameCaptionButtonContainerView::Layout() {
-  int x = 0;
-  for (int i = 0; i < child_count(); ++i) {
-    views::View* child = child_at(i);
-    if (!child->visible())
-      continue;
-
-    gfx::Size size = child->GetPreferredSize();
-    child->SetBounds(x, 0, size.width(), size.height());
-    x += size.width();
-  }
+  views::View::Layout();
   if (tablet_mode_animation_->is_animating()) {
     AnimationProgressed(tablet_mode_animation_.get());
   }
diff --git a/ash/frame/caption_buttons/frame_caption_button_container_view.h b/ash/frame/caption_buttons/frame_caption_button_container_view.h
index 7471893..b0e7671 100644
--- a/ash/frame/caption_buttons/frame_caption_button_container_view.h
+++ b/ash/frame/caption_buttons/frame_caption_button_container_view.h
@@ -96,7 +96,6 @@
   void SetButtonSize(const gfx::Size& size);
 
   // views::View:
-  gfx::Size CalculatePreferredSize() const override;
   void Layout() override;
   const char* GetClassName() const override;
 
diff --git a/ash/frame/caption_buttons/frame_caption_button_container_view_unittest.cc b/ash/frame/caption_buttons/frame_caption_button_container_view_unittest.cc
index 1a40f938..692aaf4 100644
--- a/ash/frame/caption_buttons/frame_caption_button_container_view_unittest.cc
+++ b/ash/frame/caption_buttons/frame_caption_button_container_view_unittest.cc
@@ -72,6 +72,7 @@
       container->SetButtonImage(static_cast<CaptionButtonIcon>(icon),
                                 ash::kWindowControlCloseIcon);
     }
+    container->SizeToPreferredSize();
   }
 
   // Tests that |leftmost| and |rightmost| are at |container|'s edges.
@@ -148,7 +149,6 @@
   FrameCaptionButtonContainerView container(
       CreateTestWidget(MAXIMIZE_ALLOWED, MINIMIZE_ALLOWED));
   InitContainer(&container);
-  container.SetBoundsRect(gfx::Rect(container.GetPreferredSize()));
   container.Layout();
 
   FrameCaptionButtonContainerView::TestApi test(&container);
diff --git a/ash/login/ui/login_bubble.cc b/ash/login/ui/login_bubble.cc
index 782974e..3885477e 100644
--- a/ash/login/ui/login_bubble.cc
+++ b/ash/login/ui/login_bubble.cc
@@ -4,6 +4,7 @@
 
 #include "ash/login/ui/login_bubble.h"
 
+#include "ash/login/ui/login_button.h"
 #include "ash/resources/vector_icons/vector_icons.h"
 #include "ash/shell.h"
 #include "ui/gfx/font.h"
@@ -21,14 +22,17 @@
 // The size of the alert icon in the error bubble.
 constexpr int kAlertIconSizeDp = 20;
 
-// Vertical spacing with the anchor view.
-constexpr int kAnchorViewVerticalSpacingDp = 48;
+// Vertical spacing between the anchor view and error bubble.
+constexpr int kAnchorViewErrorBubbleVerticalSpacingDp = 48;
 
 // An alpha value for the sub message in the user menu.
 constexpr SkAlpha kSubMessageColorAlpha = 0x89;
 
 // Horizontal spacing with the anchor view.
-constexpr int kAnchorViewHorizontalSpacingDp = 100;
+constexpr int kAnchorViewHorizontalSpacingDp = 105;
+
+// Vertical spacing between the anchor view and user menu.
+constexpr int kAnchorViewUserMenuVerticalSpacingDp = 4;
 
 views::Label* CreateLabel(const base::string16& message, SkColor color) {
   views::Label* label = new views::Label(message, views::style::CONTEXT_LABEL,
@@ -46,7 +50,8 @@
  public:
   LoginErrorBubbleView(views::StyledLabel* label, views::View* anchor_view)
       : LoginBaseBubbleView(anchor_view) {
-    set_anchor_view_insets(gfx::Insets(kAnchorViewVerticalSpacingDp, 0));
+    set_anchor_view_insets(
+        gfx::Insets(kAnchorViewErrorBubbleVerticalSpacingDp, 0));
 
     views::View* alert_view = new views::View();
     alert_view->SetLayoutManager(
@@ -83,7 +88,8 @@
         sub_message, SkColorSetA(SK_ColorWHITE, kSubMessageColorAlpha));
     AddChildView(label);
     AddChildView(sub_label);
-    set_anchor_view_insets(gfx::Insets(0, kAnchorViewHorizontalSpacingDp));
+    set_anchor_view_insets(gfx::Insets(kAnchorViewUserMenuVerticalSpacingDp,
+                                       kAnchorViewHorizontalSpacingDp));
 
     // TODO: Show remove user in the menu in login screen.
   }
@@ -132,7 +138,7 @@
 void LoginBubble::ShowUserMenu(const base::string16& message,
                                const base::string16& sub_message,
                                views::View* anchor_view,
-                               views::View* bubble_opener,
+                               LoginButton* bubble_opener,
                                bool show_remove_user) {
   DCHECK_EQ(bubble_view_, nullptr);
   bubble_opener_ = bubble_opener;
@@ -151,6 +157,10 @@
 }
 
 void LoginBubble::Close() {
+  if (bubble_opener_)
+    bubble_opener_->AnimateInkDrop(views::InkDropState::DEACTIVATED,
+                                   nullptr /*event*/);
+
   if (bubble_view_)
     bubble_view_->GetWidget()->Close();
 }
@@ -198,6 +208,10 @@
   views::BubbleDialogDelegateView::CreateBubble(bubble_view_)->Show();
   bubble_view_->SetAlignment(views::BubbleBorder::ALIGN_EDGE_TO_ANCHOR_EDGE);
   bubble_view_->GetWidget()->AddObserver(this);
+
+  if (bubble_opener_)
+    bubble_opener_->AnimateInkDrop(views::InkDropState::ACTIVATED,
+                                   nullptr /*event*/);
 }
 
 void LoginBubble::ProcessPressedEvent(const ui::LocatedEvent* event) {
diff --git a/ash/login/ui/login_bubble.h b/ash/login/ui/login_bubble.h
index a68e01d..4604df7 100644
--- a/ash/login/ui/login_bubble.h
+++ b/ash/login/ui/login_bubble.h
@@ -16,6 +16,7 @@
 }
 
 namespace ash {
+class LoginButton;
 
 // A wrapper for the bubble view in the login screen.
 // This class observes keyboard events, mouse clicks and touch down events
@@ -38,7 +39,7 @@
   void ShowUserMenu(const base::string16& message,
                     const base::string16& sub_message,
                     views::View* anchor_view,
-                    views::View* bubble_opener,
+                    LoginButton* bubble_opener,
                     bool show_remove_user);
 
   // Shows a tooltip.
@@ -68,8 +69,8 @@
 
   LoginBaseBubbleView* bubble_view_ = nullptr;
 
-  // A view that could open/close the bubble.
-  views::View* bubble_opener_ = nullptr;
+  // A button that could open/close the bubble.
+  LoginButton* bubble_opener_ = nullptr;
 
   DISALLOW_COPY_AND_ASSIGN(LoginBubble);
 };
diff --git a/ash/login/ui/login_bubble_unittest.cc b/ash/login/ui/login_bubble_unittest.cc
index b010407..0445e56 100644
--- a/ash/login/ui/login_bubble_unittest.cc
+++ b/ash/login/ui/login_bubble_unittest.cc
@@ -5,9 +5,11 @@
 #include <memory>
 
 #include "ash/login/ui/login_bubble.h"
+#include "ash/login/ui/login_button.h"
 #include "ash/login/ui/login_test_base.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "ui/events/test/event_generator.h"
+#include "ui/views/animation/test/ink_drop_host_view_test_api.h"
 #include "ui/views/layout/box_layout.h"
 #include "ui/views/widget/widget.h"
 
@@ -43,7 +45,7 @@
     container_->SetLayoutManager(
         new views::BoxLayout(views::BoxLayout::kVertical));
 
-    bubble_opener_ = new views::View();
+    bubble_opener_ = new LoginButton(nullptr /*listener*/);
     other_view_ = new views::View();
     bubble_opener_->SetFocusBehavior(views::View::FocusBehavior::ALWAYS);
     other_view_->SetFocusBehavior(views::View::FocusBehavior::ALWAYS);
@@ -67,7 +69,7 @@
   // Owned by test widget view hierarchy.
   views::View* container_ = nullptr;
   // Owned by test widget view hierarchy.
-  views::View* bubble_opener_ = nullptr;
+  LoginButton* bubble_opener_ = nullptr;
   // Owned by test widget view hierarchy.
   views::View* other_view_ = nullptr;
 
@@ -176,4 +178,32 @@
   EXPECT_FALSE(bubble_->IsVisible());
 }
 
+// Verifies the ripple effects for the login button.
+TEST_F(LoginBubbleTest, LoginButtonRipple) {
+  views::test::InkDropHostViewTestApi ink_drop_api(bubble_opener_);
+  EXPECT_EQ(ink_drop_api.ink_drop_mode(),
+            views::InkDropHostView::InkDropMode::ON);
+
+  // Show the bubble to activate the ripple effect.
+  bubble_->ShowUserMenu(base::string16(), base::string16(), container_,
+                        bubble_opener_, false /*show_remove_user*/);
+  EXPECT_TRUE(bubble_->IsVisible());
+  EXPECT_TRUE(ink_drop_api.HasInkDrop());
+  EXPECT_EQ(ink_drop_api.GetInkDrop()->GetTargetInkDropState(),
+            views::InkDropState::ACTIVATED);
+  EXPECT_TRUE(ink_drop_api.GetInkDrop()->IsHighlightFadingInOrVisible());
+
+  // Close the bubble should hide the ripple effect.
+  ui::test::EventGenerator& generator = GetEventGenerator();
+  generator.MoveMouseTo(other_view_->GetBoundsInScreen().CenterPoint());
+  generator.ClickLeftButton();
+  EXPECT_FALSE(bubble_->IsVisible());
+
+  // InkDropState::DEACTIVATED state will automatically transition to the
+  // InkDropState::HIDDEN state.
+  EXPECT_EQ(ink_drop_api.GetInkDrop()->GetTargetInkDropState(),
+            views::InkDropState::HIDDEN);
+  EXPECT_FALSE(ink_drop_api.GetInkDrop()->IsHighlightFadingInOrVisible());
+}
+
 }  // namespace ash
diff --git a/ash/login/ui/login_button.cc b/ash/login/ui/login_button.cc
new file mode 100644
index 0000000..3eeb1fb1
--- /dev/null
+++ b/ash/login/ui/login_button.cc
@@ -0,0 +1,75 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ash/login/ui/login_button.h"
+
+#include "ash/ash_constants.h"
+#include "ui/views/animation/flood_fill_ink_drop_ripple.h"
+#include "ui/views/animation/ink_drop_highlight.h"
+#include "ui/views/animation/ink_drop_impl.h"
+#include "ui/views/animation/ink_drop_mask.h"
+
+namespace ash {
+
+namespace {
+
+// Color of the ink drop ripple.
+constexpr SkColor kInkDropRippleColor =
+    SkColorSetARGBMacro(0x0F, 0xFF, 0xFF, 0xFF);
+
+// Color of the ink drop highlight.
+constexpr SkColor kInkDropHighlightColor =
+    SkColorSetARGBMacro(0x14, 0xFF, 0xFF, 0xFF);
+
+}  // namespace
+
+LoginButton::LoginButton(views::ButtonListener* listener)
+    : views::ImageButton(listener) {
+  SetImageAlignment(views::ImageButton::ALIGN_CENTER,
+                    views::ImageButton::ALIGN_MIDDLE);
+  SetFocusPainter(views::Painter::CreateSolidFocusPainter(
+      kFocusBorderColor, kFocusBorderThickness, gfx::InsetsF()));
+  SetInkDropMode(InkDropHostView::InkDropMode::ON);
+  set_has_ink_drop_action_on_click(true);
+}
+
+LoginButton::~LoginButton() = default;
+
+std::unique_ptr<views::InkDrop> LoginButton::CreateInkDrop() {
+  std::unique_ptr<views::InkDropImpl> ink_drop =
+      CreateDefaultFloodFillInkDropImpl();
+  ink_drop->SetShowHighlightOnHover(false);
+  return std::move(ink_drop);
+}
+
+std::unique_ptr<views::InkDropMask> LoginButton::CreateInkDropMask() const {
+  return std::make_unique<views::CircleInkDropMask>(
+      size(), GetLocalBounds().CenterPoint(), GetInkDropRadius());
+}
+
+std::unique_ptr<views::InkDropRipple> LoginButton::CreateInkDropRipple() const {
+  gfx::Point center = GetLocalBounds().CenterPoint();
+  const int radius = GetInkDropRadius();
+  gfx::Rect bounds(center.x() - radius, center.y() - radius, radius * 2,
+                   radius * 2);
+
+  return std::make_unique<views::FloodFillInkDropRipple>(
+      size(), GetLocalBounds().InsetsFrom(bounds),
+      GetInkDropCenterBasedOnLastEvent(), kInkDropRippleColor,
+      1.f /*visible_opacity*/);
+}
+
+std::unique_ptr<views::InkDropHighlight> LoginButton::CreateInkDropHighlight()
+    const {
+  return std::make_unique<views::InkDropHighlight>(
+      gfx::PointF(GetLocalBounds().CenterPoint()),
+      std::make_unique<views::CircleLayerDelegate>(kInkDropHighlightColor,
+                                                   GetInkDropRadius()));
+}
+
+int LoginButton::GetInkDropRadius() const {
+  return std::min(GetLocalBounds().width(), GetLocalBounds().height()) / 2;
+}
+
+}  // namespace ash
diff --git a/ash/login/ui/login_button.h b/ash/login/ui/login_button.h
new file mode 100644
index 0000000..cc6b8cd
--- /dev/null
+++ b/ash/login/ui/login_button.h
@@ -0,0 +1,35 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef ASH_LOGIN_UI_LOGIN_BUTTON_H_
+#define ASH_LOGIN_UI_LOGIN_BUTTON_H_
+
+#include "ash/ash_export.h"
+#include "ui/views/controls/button/image_button.h"
+#include "ui/views/view.h"
+
+namespace ash {
+
+// This class adds ripple effects for touch targets in the lockscreen.
+class ASH_EXPORT LoginButton : public views::ImageButton {
+ public:
+  explicit LoginButton(views::ButtonListener* listener);
+  ~LoginButton() override;
+
+  // views::InkDropHost:
+  std::unique_ptr<views::InkDrop> CreateInkDrop() override;
+  std::unique_ptr<views::InkDropMask> CreateInkDropMask() const override;
+  std::unique_ptr<views::InkDropRipple> CreateInkDropRipple() const override;
+  std::unique_ptr<views::InkDropHighlight> CreateInkDropHighlight()
+      const override;
+
+ private:
+  int GetInkDropRadius() const;
+
+  DISALLOW_COPY_AND_ASSIGN(LoginButton);
+};
+
+}  // namespace ash
+
+#endif  // ASH_LOGIN_UI_LOGIN_BUTTON_H_
diff --git a/ash/login/ui/login_password_view.cc b/ash/login/ui/login_password_view.cc
index 1bac8e1b..7ea199a 100644
--- a/ash/login/ui/login_password_view.cc
+++ b/ash/login/ui/login_password_view.cc
@@ -5,6 +5,7 @@
 #include "ash/login/ui/login_password_view.h"
 
 #include "ash/login/ui/hover_notifier.h"
+#include "ash/login/ui/login_button.h"
 #include "ash/login/ui/login_constants.h"
 #include "ash/login/ui/non_accessible_view.h"
 #include "ash/resources/vector_icons/vector_icons.h"
@@ -401,7 +402,7 @@
   capslock_icon_->SetVisible(false);
 
   // Submit button.
-  submit_button_ = new views::ImageButton(this);
+  submit_button_ = new LoginButton(this);
   submit_button_->SetImage(
       views::Button::STATE_NORMAL,
       gfx::CreateVectorIcon(kLockScreenArrowIcon, kSubmitButtonSizeDp,
@@ -412,8 +413,6 @@
           kLockScreenArrowIcon, kSubmitButtonSizeDp,
           SkColorSetA(login_constants::kButtonEnabledColor,
                       login_constants::kButtonDisabledAlpha)));
-  submit_button_->SetImageAlignment(views::ImageButton::ALIGN_CENTER,
-                                    views::ImageButton::ALIGN_MIDDLE);
   submit_button_->SetAccessibleName(l10n_util::GetStringUTF16(
       IDS_ASH_LOGIN_POD_SUBMIT_BUTTON_ACCESSIBLE_NAME));
   password_row_->AddChildView(submit_button_);
diff --git a/ash/login/ui/login_password_view.h b/ash/login/ui/login_password_view.h
index 57f4a1c..a605ede 100644
--- a/ash/login/ui/login_password_view.h
+++ b/ash/login/ui/login_password_view.h
@@ -19,13 +19,13 @@
 namespace views {
 class Button;
 class ButtonListener;
-class ImageButton;
 class ImageView;
 class Separator;
 class Textfield;
 }  // namespace views
 
 namespace ash {
+class LoginButton;
 
 // Contains a textfield instance with a submit button. The user can type a
 // password into the textfield and hit enter to submit.
@@ -133,7 +133,7 @@
   views::View* password_row_ = nullptr;
 
   views::Textfield* textfield_ = nullptr;
-  views::ImageButton* submit_button_ = nullptr;
+  LoginButton* submit_button_ = nullptr;
   views::ImageView* capslock_icon_ = nullptr;
   views::Separator* separator_ = nullptr;
   EasyUnlockIcon* easy_unlock_icon_ = nullptr;
diff --git a/ash/login/ui/login_pin_view.cc b/ash/login/ui/login_pin_view.cc
index c2db0a3a..55e74b0 100644
--- a/ash/login/ui/login_pin_view.cc
+++ b/ash/login/ui/login_pin_view.cc
@@ -7,6 +7,7 @@
 #include <memory>
 
 #include "ash/ash_constants.h"
+#include "ash/login/ui/login_button.h"
 #include "ash/login/ui/login_constants.h"
 #include "ash/resources/vector_icons/vector_icons.h"
 #include "ash/strings/grit/ash_strings.h"
@@ -47,14 +48,6 @@
 // After the first auto-submit, how long until the next backspace event fires?
 const int kRepeatingBackspaceDelayMs = 150;
 
-// Color of the ink drop ripple.
-constexpr SkColor kInkDropRippleColor =
-    SkColorSetARGBMacro(0xF, 0xFF, 0xFF, 0xFF);
-
-// Color of the ink drop highlight.
-constexpr SkColor kInkDropHighlightColor =
-    SkColorSetARGBMacro(0x14, 0xFF, 0xFF, 0xFF);
-
 base::string16 GetButtonLabelForNumber(int value) {
   DCHECK(value >= 0 && value < int{arraysize(kPinLabels)});
   return base::ASCIIToUTF16(std::to_string(value));
@@ -73,23 +66,18 @@
 }
 
 // A base class for pin button in the pin keyboard.
-class BasePinButton : public views::Button, public views::ButtonListener {
+class BasePinButton : public LoginButton, public views::ButtonListener {
  public:
   explicit BasePinButton(const base::Closure& on_press)
-      : views::Button(this), on_press_(on_press) {
+      : LoginButton(this), on_press_(on_press) {
     SetFocusBehavior(FocusBehavior::ALWAYS);
     SetPreferredSize(
         gfx::Size(LoginPinView::kButtonSizeDp, LoginPinView::kButtonSizeDp));
-    SetFocusPainter(views::Painter::CreateSolidFocusPainter(
-        kFocusBorderColor, kFocusBorderThickness, gfx::InsetsF()));
     auto* layout = new views::BoxLayout(views::BoxLayout::kVertical);
     layout->set_main_axis_alignment(
         views::BoxLayout::MAIN_AXIS_ALIGNMENT_CENTER);
     SetLayoutManager(layout);
 
-    SetInkDropMode(InkDropHostView::InkDropMode::ON);
-    set_has_ink_drop_action_on_click(true);
-
     // Layer rendering is needed for animation. Enable it here for
     // focus painter to paint.
     SetPaintToLayer();
@@ -106,42 +94,6 @@
       on_press_.Run();
   }
 
-  std::unique_ptr<views::InkDrop> CreateInkDrop() override {
-    std::unique_ptr<views::InkDropImpl> ink_drop =
-        std::make_unique<views::InkDropImpl>(this, size());
-    ink_drop->SetShowHighlightOnHover(false);
-    ink_drop->SetShowHighlightOnFocus(false);
-    ink_drop->SetAutoHighlightMode(
-        views::InkDropImpl::AutoHighlightMode::SHOW_ON_RIPPLE);
-    return std::move(ink_drop);
-  }
-
-  std::unique_ptr<views::InkDropMask> CreateInkDropMask() const override {
-    return std::make_unique<views::CircleInkDropMask>(
-        size(), GetLocalBounds().CenterPoint(),
-        LoginPinView::kButtonSizeDp / 2);
-  }
-
-  std::unique_ptr<views::InkDropRipple> CreateInkDropRipple() const override {
-    gfx::Point center = GetLocalBounds().CenterPoint();
-    gfx::Rect bounds(center.x() - LoginPinView::kButtonSizeDp / 2,
-                     center.y() - LoginPinView::kButtonSizeDp / 2,
-                     LoginPinView::kButtonSizeDp, LoginPinView::kButtonSizeDp);
-
-    return std::make_unique<views::FloodFillInkDropRipple>(
-        size(), GetLocalBounds().InsetsFrom(bounds),
-        GetInkDropCenterBasedOnLastEvent(), kInkDropRippleColor,
-        1.f /*visible_opacity*/);
-  }
-
-  std::unique_ptr<views::InkDropHighlight> CreateInkDropHighlight()
-      const override {
-    return std::make_unique<views::InkDropHighlight>(
-        gfx::PointF(GetLocalBounds().CenterPoint()),
-        std::make_unique<views::CircleLayerDelegate>(
-            kInkDropHighlightColor, LoginPinView::kButtonSizeDp / 2));
-  }
-
  protected:
   base::Closure on_press_;
 
@@ -200,12 +152,17 @@
       : BasePinButton(on_press),
         delay_timer_(std::make_unique<base::OneShotTimer>()),
         repeat_timer_(std::make_unique<base::RepeatingTimer>()) {
-    image_ = new views::ImageView();
-    AddChildView(image_);
-
+    SetImage(views::Button::STATE_NORMAL,
+             gfx::CreateVectorIcon(kLockScreenBackspaceIcon,
+                                   login_constants::kButtonEnabledColor));
+    SetImage(views::Button::STATE_DISABLED,
+             gfx::CreateVectorIcon(
+                 kLockScreenBackspaceIcon,
+                 SkColorSetA(login_constants::kButtonEnabledColor,
+                             login_constants::kButtonDisabledAlpha)));
     SetAccessibleName(
         l10n_util::GetStringUTF16(IDS_ASH_PIN_KEYBOARD_DELETE_ACCESSIBLE_NAME));
-    SetDisabled(true);
+    SetEnabled(false);
   }
 
   ~BackspacePinButton() override = default;
@@ -216,17 +173,6 @@
     repeat_timer_ = std::move(repeat_timer);
   }
 
-  void SetDisabled(bool disabled) {
-    if (disabled_ == disabled)
-      return;
-    disabled_ = disabled;
-    image_->SetImage(gfx::CreateVectorIcon(
-        kLockScreenBackspaceIcon,
-        disabled_ ? SkColorSetA(login_constants::kButtonEnabledColor,
-                                login_constants::kButtonDisabledAlpha)
-                  : login_constants::kButtonEnabledColor));
-  }
-
   // BasePinButton:
   bool OnMousePressed(const ui::MouseEvent& event) override {
     did_autosubmit_ = false;
@@ -268,8 +214,6 @@
     on_press_.Run();
   }
 
-  views::ImageView* image_;
-  bool disabled_ = false;
   bool did_autosubmit_ = false;
   std::unique_ptr<base::Timer> delay_timer_;
   std::unique_ptr<base::Timer> repeat_timer_;
@@ -350,7 +294,7 @@
 LoginPinView::~LoginPinView() = default;
 
 void LoginPinView::OnPasswordTextChanged(bool is_empty) {
-  backspace_->SetDisabled(is_empty);
+  backspace_->SetEnabled(!is_empty);
 }
 
 bool LoginPinView::OnKeyPressed(const ui::KeyEvent& event) {
diff --git a/ash/login/ui/login_pin_view_unittest.cc b/ash/login/ui/login_pin_view_unittest.cc
index 0d910bf..2b0f03d 100644
--- a/ash/login/ui/login_pin_view_unittest.cc
+++ b/ash/login/ui/login_pin_view_unittest.cc
@@ -63,6 +63,7 @@
 
   // Verify backspace events are emitted.
   EXPECT_EQ(0, backspace_);
+  test_api.GetBackspaceButton()->SetEnabled(true);
   test_api.GetBackspaceButton()->RequestFocus();
   generator.PressKey(ui::KeyboardCode::VKEY_RETURN, ui::EF_NONE);
   EXPECT_EQ(1, backspace_);
@@ -138,6 +139,7 @@
 
   // Verify backspace events are emitted.
   EXPECT_EQ(0, backspace_);
+  test_api.GetBackspaceButton()->SetEnabled(true);
   generator.MoveMouseTo(
       test_api.GetBackspaceButton()->GetBoundsInScreen().CenterPoint());
   generator.PressLeftButton();
diff --git a/ash/login/ui/login_user_view.cc b/ash/login/ui/login_user_view.cc
index 61536cf..c56a0ff 100644
--- a/ash/login/ui/login_user_view.cc
+++ b/ash/login/ui/login_user_view.cc
@@ -11,6 +11,7 @@
 #include "ash/login/ui/hover_notifier.h"
 #include "ash/login/ui/image_parser.h"
 #include "ash/login/ui/login_bubble.h"
+#include "ash/login/ui/login_button.h"
 #include "ash/login/ui/login_constants.h"
 #include "ash/login/ui/non_accessible_view.h"
 #include "ash/login/ui/user_switch_flip_animation.h"
@@ -36,13 +37,13 @@
 // Vertical spacing between icon, label, and authentication UI.
 constexpr int kVerticalSpacingBetweenEntriesDp = 32;
 // Horizontal spacing between username label and the dropdown icon.
-constexpr int kDistanceBetweenUsernameAndDropdownDp = 12;
+constexpr int kDistanceBetweenUsernameAndDropdownDp = 8;
 // Distance from the top of the user view to the user icon.
 constexpr int kDistanceFromTopOfBigUserViewToUserIconDp = 54;
 // Distance between user icon and the user label in small/extra-small layouts.
 constexpr int kSmallManyDistanceFromUserIconToUserLabelDp = 16;
 
-constexpr int kDropdownIconSizeDp = 20;
+constexpr int kDropdownIconSizeDp = 28;
 
 // Width/height of the user view. Ensures proper centering.
 constexpr int kLargeUserViewWidthDp = 306;
@@ -241,15 +242,14 @@
   user_image_ = new UserImage(GetImageSize(style));
   user_label_ = new UserLabel(style);
   if (show_dropdown) {
-    user_dropdown_ = new views::ImageButton(this);
+    user_dropdown_ = new LoginButton(this);
+    user_dropdown_->set_has_ink_drop_action_on_click(false);
     user_dropdown_->SetPreferredSize(
         gfx::Size(kDropdownIconSizeDp, kDropdownIconSizeDp));
     user_dropdown_->SetImage(
         views::Button::STATE_NORMAL,
         gfx::CreateVectorIcon(kLockScreenDropdownIcon, SK_ColorWHITE));
     user_dropdown_->SetFocusBehavior(FocusBehavior::ALWAYS);
-    user_dropdown_->SetFocusPainter(views::Painter::CreateSolidFocusPainter(
-        kFocusBorderColor, kFocusBorderThickness, gfx::InsetsF()));
   }
 
   switch (style) {
diff --git a/ash/login/ui/login_user_view.h b/ash/login/ui/login_user_view.h
index 5d21b24..a31047b 100644
--- a/ash/login/ui/login_user_view.h
+++ b/ash/login/ui/login_user_view.h
@@ -12,14 +12,11 @@
 #include "ui/views/controls/button/button.h"
 #include "ui/views/view.h"
 
-namespace views {
-class ImageButton;
-}
-
 namespace ash {
 
 class HoverNotifier;
 class LoginBubble;
+class LoginButton;
 
 // Display the user's profile icon, name, and a menu icon in various layout
 // styles.
@@ -99,7 +96,7 @@
   LoginDisplayStyle display_style_;
   UserImage* user_image_ = nullptr;
   UserLabel* user_label_ = nullptr;
-  views::ImageButton* user_dropdown_ = nullptr;
+  LoginButton* user_dropdown_ = nullptr;
   std::unique_ptr<LoginBubble> user_menu_;
 
   // True iff the view is currently opaque (ie, opacity = 1).
diff --git a/ash/mus/BUILD.gn b/ash/mus/BUILD.gn
index 22ab79ff..cccb88a 100644
--- a/ash/mus/BUILD.gn
+++ b/ash/mus/BUILD.gn
@@ -48,6 +48,8 @@
     "property_util.h",
     "shell_delegate_mus.cc",
     "shell_delegate_mus.h",
+    "shell_port_mus.cc",
+    "shell_port_mus.h",
     "top_level_window_factory.cc",
     "top_level_window_factory.h",
     "touch_transform_setter_mus.cc",
@@ -195,7 +197,6 @@
 
   sources = [
     "app_launch_unittest.cc",
-    "bridge/shell_port_mash_test_api.h",
     "display_synchronizer_unittest.cc",
     "non_client_frame_controller_unittest.cc",
     "top_level_window_factory_unittest.cc",
diff --git a/ash/mus/DEPS b/ash/mus/DEPS
index 7d88d9a0..36d694f 100644
--- a/ash/mus/DEPS
+++ b/ash/mus/DEPS
@@ -29,4 +29,8 @@
     # compositor. So this needs to explicitly depend on cc.
     "+cc",
   ],
+
+  "shell_port_mus\.cc": [
+    "+ash/host/ash_window_tree_host_init_params.h"
+  ],
 }
diff --git a/ash/mus/bridge/DEPS b/ash/mus/bridge/DEPS
deleted file mode 100644
index 984553aa6..0000000
--- a/ash/mus/bridge/DEPS
+++ /dev/null
@@ -1,6 +0,0 @@
-specific_include_rules = {
-  "shell_port_mash.cc": [
-    "+ash/host/ash_window_tree_host.h",
-    "+ash/host/ash_window_tree_host_init_params.h"
-  ],
-}
diff --git a/ash/mus/bridge/shell_port_mash.cc b/ash/mus/bridge/shell_port_mash.cc
index 70292bfa..8272765 100644
--- a/ash/mus/bridge/shell_port_mash.cc
+++ b/ash/mus/bridge/shell_port_mash.cc
@@ -8,50 +8,21 @@
 #include <utility>
 
 #include "ash/accelerators/accelerator_controller.h"
-#include "ash/accelerators/accelerator_controller_delegate_classic.h"
-#include "ash/host/ash_window_tree_host_init_params.h"
-#include "ash/laser/laser_pointer_controller.h"
-#include "ash/magnifier/partial_magnification_controller.h"
 #include "ash/mus/accelerators/accelerator_controller_delegate_mus.h"
 #include "ash/mus/accelerators/accelerator_controller_registrar.h"
-#include "ash/mus/ash_window_tree_host_mus.h"
 #include "ash/mus/bridge/immersive_handler_factory_mus.h"
 #include "ash/mus/bridge/workspace_event_handler_mus.h"
-#include "ash/mus/display_synchronizer.h"
 #include "ash/mus/drag_window_resizer.h"
 #include "ash/mus/keyboard_ui_mus.h"
-#include "ash/mus/touch_transform_setter_mus.h"
 #include "ash/mus/window_manager.h"
-#include "ash/pointer_watcher_adapter_classic.h"
 #include "ash/public/cpp/config.h"
 #include "ash/public/cpp/immersive/immersive_fullscreen_controller.h"
-#include "ash/public/cpp/shell_window_ids.h"
-#include "ash/root_window_controller.h"
-#include "ash/root_window_settings.h"
 #include "ash/shell.h"
-#include "ash/virtual_keyboard_controller.h"
-#include "ash/wallpaper/wallpaper_delegate.h"
-#include "ash/wm/drag_window_resizer.h"
-#include "ash/wm/mru_window_tracker.h"
 #include "ash/wm/tablet_mode/tablet_mode_event_handler.h"
-#include "ash/wm/tablet_mode/tablet_mode_event_handler_classic.h"
 #include "ash/wm/window_cycle_event_filter.h"
-#include "ash/wm/window_cycle_event_filter_classic.h"
 #include "ash/wm/window_resizer.h"
-#include "ash/wm/window_util.h"
-#include "ash/wm/workspace/workspace_event_handler_classic.h"
-#include "base/memory/ptr_util.h"
-#include "components/user_manager/user_info_impl.h"
-#include "services/ui/public/interfaces/constants.mojom.h"
 #include "ui/aura/env.h"
-#include "ui/aura/mus/focus_synchronizer.h"
-#include "ui/aura/mus/window_tree_client.h"
-#include "ui/aura/mus/window_tree_host_mus.h"
-#include "ui/aura/mus/window_tree_host_mus_init_params.h"
 #include "ui/aura/window.h"
-#include "ui/display/manager/display_manager.h"
-#include "ui/display/manager/forwarding_display_delegate.h"
-#include "ui/display/types/native_display_delegate.h"
 #include "ui/views/mus/pointer_watcher_event_router.h"
 
 namespace ash {
@@ -61,23 +32,16 @@
 
 ShellPortMash::MashSpecificState::~MashSpecificState() = default;
 
-ShellPortMash::MusSpecificState::MusSpecificState() = default;
-
-ShellPortMash::MusSpecificState::~MusSpecificState() = default;
-
 ShellPortMash::ShellPortMash(
     WindowManager* window_manager,
     views::PointerWatcherEventRouter* pointer_watcher_event_router)
-    : window_manager_(window_manager) {
-  if (GetAshConfig() == Config::MASH) {
-    mash_state_ = std::make_unique<MashSpecificState>();
-    mash_state_->pointer_watcher_event_router = pointer_watcher_event_router;
-    mash_state_->immersive_handler_factory =
-        std::make_unique<ImmersiveHandlerFactoryMus>();
-  } else {
-    DCHECK_EQ(Config::MUS, GetAshConfig());
-    mus_state_ = std::make_unique<MusSpecificState>();
-  }
+    : ShellPortMus(window_manager) {
+  DCHECK(pointer_watcher_event_router);
+  DCHECK_EQ(Config::MASH, GetAshConfig());
+  mash_state_ = std::make_unique<MashSpecificState>();
+  mash_state_->pointer_watcher_event_router = pointer_watcher_event_router;
+  mash_state_->immersive_handler_factory =
+      std::make_unique<ImmersiveHandlerFactoryMus>();
 }
 
 ShellPortMash::~ShellPortMash() {}
@@ -85,44 +49,12 @@
 // static
 ShellPortMash* ShellPortMash::Get() {
   const ash::Config config = ShellPort::Get()->GetAshConfig();
-  CHECK(config == Config::MUS || config == Config::MASH);
+  CHECK_EQ(Config::MASH, config);
   return static_cast<ShellPortMash*>(ShellPort::Get());
 }
 
-RootWindowController* ShellPortMash::GetRootWindowControllerWithDisplayId(
-    int64_t id) {
-  for (RootWindowController* root_window_controller :
-       RootWindowController::root_window_controllers()) {
-    RootWindowSettings* settings =
-        GetRootWindowSettings(root_window_controller->GetRootWindow());
-    DCHECK(settings);
-    if (settings->display_id == id)
-      return root_window_controller;
-  }
-  return nullptr;
-}
-
-aura::WindowTreeClient* ShellPortMash::window_tree_client() {
-  return window_manager_->window_tree_client();
-}
-
-void ShellPortMash::Shutdown() {
-  display_synchronizer_.reset();
-
-  if (mus_state_)
-    mus_state_->pointer_watcher_adapter.reset();
-
-  ShellPort::Shutdown();
-}
-
 Config ShellPortMash::GetAshConfig() const {
-  return window_manager_->config();
-}
-
-std::unique_ptr<display::TouchTransformSetter>
-ShellPortMash::CreateTouchTransformDelegate() {
-  return std::make_unique<TouchTransformSetterMus>(
-      window_manager_->connector());
+  return Config::MASH;
 }
 
 void ShellPortMash::LockCursor() {
@@ -130,89 +62,58 @@
   // window server, but also locally in ash because ash treats the cursor
   // manager as the canonical state for now. NativeCursorManagerAsh will keep
   // this state, while also forwarding it to the window manager for us.
-  if (GetAshConfig() == Config::MUS)
-    Shell::Get()->cursor_manager()->LockCursor();
-  else
-    window_manager_->window_manager_client()->LockCursor();
+  window_manager_->window_manager_client()->LockCursor();
 }
 
 void ShellPortMash::UnlockCursor() {
-  if (GetAshConfig() == Config::MUS)
-    Shell::Get()->cursor_manager()->UnlockCursor();
-  else
-    window_manager_->window_manager_client()->UnlockCursor();
+  window_manager_->window_manager_client()->UnlockCursor();
 }
 
 void ShellPortMash::ShowCursor() {
-  if (GetAshConfig() == Config::MUS)
-    Shell::Get()->cursor_manager()->ShowCursor();
-  else
-    window_manager_->window_manager_client()->SetCursorVisible(true);
+  window_manager_->window_manager_client()->SetCursorVisible(true);
 }
 
 void ShellPortMash::HideCursor() {
-  if (GetAshConfig() == Config::MUS)
-    Shell::Get()->cursor_manager()->HideCursor();
-  else
-    window_manager_->window_manager_client()->SetCursorVisible(false);
+  window_manager_->window_manager_client()->SetCursorVisible(false);
 }
 
 void ShellPortMash::SetCursorSize(ui::CursorSize cursor_size) {
-  if (GetAshConfig() == Config::MUS)
-    Shell::Get()->cursor_manager()->SetCursorSize(cursor_size);
-  else
-    window_manager_->window_manager_client()->SetCursorSize(cursor_size);
+  window_manager_->window_manager_client()->SetCursorSize(cursor_size);
 }
 
 void ShellPortMash::SetGlobalOverrideCursor(
     base::Optional<ui::CursorData> cursor) {
-  DCHECK(mash_state_);
   window_manager_->window_manager_client()->SetGlobalOverrideCursor(
       std::move(cursor));
 }
 
 bool ShellPortMash::IsMouseEventsEnabled() {
-  if (GetAshConfig() == Config::MASH)
-    return cursor_touch_visible_;
-
-  return Shell::Get()->cursor_manager()->IsMouseEventsEnabled();
+  return cursor_touch_visible_;
 }
 
 void ShellPortMash::SetCursorTouchVisible(bool enabled) {
-  DCHECK_EQ(GetAshConfig(), Config::MASH);
   window_manager_->window_manager_client()->SetCursorTouchVisible(enabled);
 }
 
 void ShellPortMash::OnCursorTouchVisibleChanged(bool enabled) {
-  if (GetAshConfig() == Config::MASH)
-    cursor_touch_visible_ = enabled;
+  cursor_touch_visible_ = enabled;
 }
 
 std::unique_ptr<WindowResizer> ShellPortMash::CreateDragWindowResizer(
     std::unique_ptr<WindowResizer> next_window_resizer,
     wm::WindowState* window_state) {
-  if (GetAshConfig() == Config::MUS) {
-    return base::WrapUnique(ash::DragWindowResizer::Create(
-        next_window_resizer.release(), window_state));
-  }
   return std::make_unique<ash::mus::DragWindowResizer>(
       std::move(next_window_resizer), window_state);
 }
 
 std::unique_ptr<WindowCycleEventFilter>
 ShellPortMash::CreateWindowCycleEventFilter() {
-  if (GetAshConfig() == Config::MUS)
-    return std::make_unique<WindowCycleEventFilterClassic>();
-
   // TODO: implement me, http://crbug.com/629191.
   return nullptr;
 }
 
 std::unique_ptr<wm::TabletModeEventHandler>
 ShellPortMash::CreateTabletModeEventHandler() {
-  if (GetAshConfig() == Config::MUS)
-    return std::make_unique<wm::TabletModeEventHandlerClassic>();
-
   // TODO: need support for window manager to get events before client:
   // http://crbug.com/624157.
   NOTIMPLEMENTED();
@@ -221,31 +122,21 @@
 
 std::unique_ptr<WorkspaceEventHandler>
 ShellPortMash::CreateWorkspaceEventHandler(aura::Window* workspace_window) {
-  if (GetAshConfig() == Config::MUS)
-    return std::make_unique<WorkspaceEventHandlerClassic>(workspace_window);
-
   return std::make_unique<WorkspaceEventHandlerMus>(workspace_window);
 }
 
 std::unique_ptr<ImmersiveFullscreenController>
 ShellPortMash::CreateImmersiveFullscreenController() {
+  // TODO: Move to Shell.
   return std::make_unique<ImmersiveFullscreenController>();
 }
 
 std::unique_ptr<KeyboardUI> ShellPortMash::CreateKeyboardUI() {
-  if (GetAshConfig() == Config::MUS)
-    return KeyboardUI::Create();
-
   return KeyboardUIMus::Create(window_manager_->connector());
 }
 
 void ShellPortMash::AddPointerWatcher(views::PointerWatcher* watcher,
                                       views::PointerWatcherEventTypes events) {
-  if (GetAshConfig() == Config::MUS) {
-    mus_state_->pointer_watcher_adapter->AddPointerWatcher(watcher, events);
-    return;
-  }
-
   // TODO: implement drags for mus pointer watcher, http://crbug.com/641164.
   // NOTIMPLEMENTED drags for mus pointer watcher.
   mash_state_->pointer_watcher_event_router->AddPointerWatcher(
@@ -253,47 +144,16 @@
 }
 
 void ShellPortMash::RemovePointerWatcher(views::PointerWatcher* watcher) {
-  if (GetAshConfig() == Config::MUS) {
-    mus_state_->pointer_watcher_adapter->RemovePointerWatcher(watcher);
-    return;
-  }
-
   mash_state_->pointer_watcher_event_router->RemovePointerWatcher(watcher);
 }
 
 bool ShellPortMash::IsTouchDown() {
-  if (GetAshConfig() == Config::MUS)
-    return aura::Env::GetInstance()->is_touch_down();
-
   // TODO: implement me, http://crbug.com/634967.
   // NOTIMPLEMENTED is too spammy here.
   return false;
 }
 
 void ShellPortMash::ToggleIgnoreExternalKeyboard() {
-  if (GetAshConfig() == Config::MUS) {
-    Shell::Get()->virtual_keyboard_controller()->ToggleIgnoreExternalKeyboard();
-    return;
-  }
-
-  NOTIMPLEMENTED();
-}
-
-void ShellPortMash::SetLaserPointerEnabled(bool enabled) {
-  if (GetAshConfig() == Config::MUS) {
-    Shell::Get()->laser_pointer_controller()->SetEnabled(enabled);
-    return;
-  }
-
-  NOTIMPLEMENTED();
-}
-
-void ShellPortMash::SetPartialMagnifierEnabled(bool enabled) {
-  if (GetAshConfig() == Config::MUS) {
-    Shell::Get()->partial_magnification_controller()->SetEnabled(enabled);
-    return;
-  }
-
   NOTIMPLEMENTED();
 }
 
@@ -301,93 +161,10 @@
   // In Config::MUS PointerWatcherAdapterClassic must be created when this
   // function is called (it is order dependent), that is not the case with
   // Config::MASH.
-  if (GetAshConfig() == Config::MUS) {
-    mus_state_->pointer_watcher_adapter =
-        std::make_unique<PointerWatcherAdapterClassic>();
-  }
-}
-
-std::unique_ptr<AshWindowTreeHost> ShellPortMash::CreateAshWindowTreeHost(
-    const AshWindowTreeHostInitParams& init_params) {
-  std::unique_ptr<aura::DisplayInitParams> display_params =
-      std::make_unique<aura::DisplayInitParams>();
-  display_params->viewport_metrics.bounds_in_pixels =
-      init_params.initial_bounds;
-  display_params->viewport_metrics.device_scale_factor =
-      init_params.device_scale_factor;
-  display_params->viewport_metrics.ui_scale_factor =
-      init_params.ui_scale_factor;
-  display::DisplayManager* display_manager = Shell::Get()->display_manager();
-  display::Display mirrored_display =
-      display_manager->GetMirroringDisplayById(init_params.display_id);
-  if (mirrored_display.is_valid()) {
-    display_params->display =
-        std::make_unique<display::Display>(mirrored_display);
-  }
-  display_params->is_primary_display = true;
-  display_params->mirrors = display_manager->software_mirroring_display_list();
-  aura::WindowTreeHostMusInitParams aura_init_params =
-      window_manager_->window_manager_client()->CreateInitParamsForNewDisplay();
-  aura_init_params.display_id = init_params.display_id;
-  aura_init_params.display_init_params = std::move(display_params);
-  aura_init_params.use_classic_ime = !Shell::ShouldUseIMEService();
-  return std::make_unique<AshWindowTreeHostMus>(std::move(aura_init_params));
-}
-
-void ShellPortMash::OnCreatedRootWindowContainers(
-    RootWindowController* root_window_controller) {
-  // TODO: To avoid lots of IPC AddActivationParent() should take an array.
-  // http://crbug.com/682048.
-  aura::Window* root_window = root_window_controller->GetRootWindow();
-  for (size_t i = 0; i < kNumActivatableShellWindowIds; ++i) {
-    window_manager_->window_manager_client()->AddActivationParent(
-        root_window->GetChildById(kActivatableShellWindowIds[i]));
-  }
-
-  UpdateSystemModalAndBlockingContainers();
-}
-
-void ShellPortMash::UpdateSystemModalAndBlockingContainers() {
-  std::vector<aura::BlockingContainers> all_blocking_containers;
-  for (RootWindowController* root_window_controller :
-       Shell::GetAllRootWindowControllers()) {
-    aura::BlockingContainers blocking_containers;
-    wm::GetBlockingContainersForRoot(
-        root_window_controller->GetRootWindow(),
-        &blocking_containers.min_container,
-        &blocking_containers.system_modal_container);
-    all_blocking_containers.push_back(blocking_containers);
-  }
-  window_manager_->window_manager_client()->SetBlockingContainers(
-      all_blocking_containers);
-}
-
-void ShellPortMash::OnHostsInitialized() {
-  display_synchronizer_ = std::make_unique<DisplaySynchronizer>(
-      window_manager_->window_manager_client());
-}
-
-std::unique_ptr<display::NativeDisplayDelegate>
-ShellPortMash::CreateNativeDisplayDelegate() {
-  display::mojom::NativeDisplayDelegatePtr native_display_delegate;
-  if (window_manager_->connector()) {
-    window_manager_->connector()->BindInterface(ui::mojom::kServiceName,
-                                                &native_display_delegate);
-  }
-  return std::make_unique<display::ForwardingDisplayDelegate>(
-      std::move(native_display_delegate));
 }
 
 std::unique_ptr<AcceleratorController>
 ShellPortMash::CreateAcceleratorController() {
-  if (GetAshConfig() == Config::MUS) {
-    DCHECK(!mus_state_->accelerator_controller_delegate);
-    mus_state_->accelerator_controller_delegate =
-        std::make_unique<AcceleratorControllerDelegateClassic>();
-    return std::make_unique<AcceleratorController>(
-        mus_state_->accelerator_controller_delegate.get(), nullptr);
-  }
-
   DCHECK(!mash_state_->accelerator_controller_delegate);
 
   uint16_t accelerator_namespace_id = 0u;
diff --git a/ash/mus/bridge/shell_port_mash.h b/ash/mus/bridge/shell_port_mash.h
index 21db4f1..495fb85 100644
--- a/ash/mus/bridge/shell_port_mash.h
+++ b/ash/mus/bridge/shell_port_mash.h
@@ -10,34 +10,25 @@
 #include <memory>
 #include <vector>
 
-#include "ash/shell_port.h"
+#include "ash/mus/shell_port_mus.h"
 #include "base/macros.h"
 
-namespace aura {
-class WindowTreeClient;
-}
-
 namespace views {
 class PointerWatcherEventRouter;
 }
 
 namespace ash {
-
-class AcceleratorControllerDelegateClassic;
-class DisplaySynchronizer;
-class PointerWatcherAdapterClassic;
-class RootWindowController;
-
 namespace mus {
 
 class AcceleratorControllerDelegateMus;
 class AcceleratorControllerRegistrar;
 class ImmersiveHandlerFactoryMus;
 class WindowManager;
-class ShellPortMashTestApi;
 
-// ShellPort implementation for mash/mus. See ash/README.md for more.
-class ShellPortMash : public ShellPort {
+// ShellPort implementation for mash. See ash/README.md for more. Subclass of
+// ShellPortMus because both configurations talk to the same UI service for
+// things like display management.
+class ShellPortMash : public ShellPortMus {
  public:
   ShellPortMash(WindowManager* window_manager,
                 views::PointerWatcherEventRouter* pointer_watcher_event_router);
@@ -45,24 +36,11 @@
 
   static ShellPortMash* Get();
 
-  ash::RootWindowController* GetRootWindowControllerWithDisplayId(int64_t id);
-
-  AcceleratorControllerDelegateClassic* accelerator_controller_delegate_mus() {
-    return mus_state_->accelerator_controller_delegate.get();
-  }
-
-  aura::WindowTreeClient* window_tree_client();
-
-  WindowManager* window_manager() { return window_manager_; }
-
   // Called when the window server has changed the mouse enabled state.
   void OnCursorTouchVisibleChanged(bool enabled);
 
   // ShellPort:
-  void Shutdown() override;
   Config GetAshConfig() const override;
-  std::unique_ptr<display::TouchTransformSetter> CreateTouchTransformDelegate()
-      override;
   void LockCursor() override;
   void UnlockCursor() override;
   void ShowCursor() override;
@@ -88,22 +66,10 @@
   void RemovePointerWatcher(views::PointerWatcher* watcher) override;
   bool IsTouchDown() override;
   void ToggleIgnoreExternalKeyboard() override;
-  void SetLaserPointerEnabled(bool enabled) override;
-  void SetPartialMagnifierEnabled(bool enabled) override;
   void CreatePointerWatcherAdapter() override;
-  std::unique_ptr<AshWindowTreeHost> CreateAshWindowTreeHost(
-      const AshWindowTreeHostInitParams& init_params) override;
-  void OnCreatedRootWindowContainers(
-      RootWindowController* root_window_controller) override;
-  void UpdateSystemModalAndBlockingContainers() override;
-  void OnHostsInitialized() override;
-  std::unique_ptr<display::NativeDisplayDelegate> CreateNativeDisplayDelegate()
-      override;
   std::unique_ptr<AcceleratorController> CreateAcceleratorController() override;
 
  private:
-  friend class ShellPortMashTestApi;
-
   struct MashSpecificState {
     MashSpecificState();
     ~MashSpecificState();
@@ -116,23 +82,8 @@
     std::unique_ptr<ImmersiveHandlerFactoryMus> immersive_handler_factory;
   };
 
-  struct MusSpecificState {
-    MusSpecificState();
-    ~MusSpecificState();
-
-    std::unique_ptr<PointerWatcherAdapterClassic> pointer_watcher_adapter;
-    std::unique_ptr<AcceleratorControllerDelegateClassic>
-        accelerator_controller_delegate;
-  };
-
-  WindowManager* window_manager_;
-
-  // Only one of |mash_state_| or |mus_state_| is created, depending upon
-  // Config.
+  // TODO(jamescook): Inline the members.
   std::unique_ptr<MashSpecificState> mash_state_;
-  std::unique_ptr<MusSpecificState> mus_state_;
-
-  std::unique_ptr<DisplaySynchronizer> display_synchronizer_;
 
   bool cursor_touch_visible_ = true;
 
diff --git a/ash/mus/bridge/shell_port_mash_test_api.h b/ash/mus/bridge/shell_port_mash_test_api.h
deleted file mode 100644
index 7ab640e..0000000
--- a/ash/mus/bridge/shell_port_mash_test_api.h
+++ /dev/null
@@ -1,30 +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 ASH_MUS_BRIDGE_SHELL_PORT_MASH_TEST_API_H_
-#define ASH_MUS_BRIDGE_SHELL_PORT_MASH_TEST_API_H_
-
-#include "ash/mus/bridge/shell_port_mash.h"
-
-namespace ash {
-namespace mus {
-
-// Use to get at internal state of ShellPortMash.
-class ShellPortMashTestApi {
- public:
-  ShellPortMashTestApi() {}
-  ~ShellPortMashTestApi() {}
-
-  AcceleratorControllerRegistrar* accelerator_controller_registrar() {
-    return ShellPortMash::Get()->accelerator_controller_registrar_.get();
-  }
-
- private:
-  DISALLOW_COPY_AND_ASSIGN(ShellPortMashTestApi);
-};
-
-}  // namespace mus
-}  // namespace ash
-
-#endif  // ASH_MUS_BRIDGE_SHELL_PORT_MASH_TEST_API_H_
diff --git a/ash/mus/shell_port_mus.cc b/ash/mus/shell_port_mus.cc
new file mode 100644
index 0000000..bdfffe3
--- /dev/null
+++ b/ash/mus/shell_port_mus.cc
@@ -0,0 +1,272 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ash/mus/shell_port_mus.h"
+
+#include <memory>
+#include <utility>
+
+#include "ash/accelerators/accelerator_controller.h"
+#include "ash/accelerators/accelerator_controller_delegate_classic.h"
+#include "ash/host/ash_window_tree_host_init_params.h"
+#include "ash/mus/ash_window_tree_host_mus.h"
+#include "ash/mus/display_synchronizer.h"
+#include "ash/mus/keyboard_ui_mus.h"
+#include "ash/mus/touch_transform_setter_mus.h"
+#include "ash/mus/window_manager.h"
+#include "ash/pointer_watcher_adapter_classic.h"
+#include "ash/public/cpp/config.h"
+#include "ash/public/cpp/immersive/immersive_fullscreen_controller.h"
+#include "ash/public/cpp/shell_window_ids.h"
+#include "ash/root_window_controller.h"
+#include "ash/root_window_settings.h"
+#include "ash/shell.h"
+#include "ash/virtual_keyboard_controller.h"
+#include "ash/wallpaper/wallpaper_delegate.h"
+#include "ash/wm/drag_window_resizer.h"
+#include "ash/wm/mru_window_tracker.h"
+#include "ash/wm/tablet_mode/tablet_mode_event_handler_classic.h"
+#include "ash/wm/window_cycle_event_filter_classic.h"
+#include "ash/wm/window_resizer.h"
+#include "ash/wm/window_util.h"
+#include "ash/wm/workspace/workspace_event_handler_classic.h"
+#include "base/memory/ptr_util.h"
+#include "services/ui/public/interfaces/constants.mojom.h"
+#include "ui/aura/env.h"
+#include "ui/aura/mus/focus_synchronizer.h"
+#include "ui/aura/mus/window_tree_client.h"
+#include "ui/aura/mus/window_tree_host_mus.h"
+#include "ui/aura/mus/window_tree_host_mus_init_params.h"
+#include "ui/aura/window.h"
+#include "ui/display/manager/display_manager.h"
+#include "ui/display/manager/forwarding_display_delegate.h"
+#include "ui/display/types/native_display_delegate.h"
+
+namespace ash {
+namespace mus {
+
+ShellPortMus::ShellPortMus(WindowManager* window_manager)
+    : window_manager_(window_manager) {
+  DCHECK_EQ(Config::MUS, GetAshConfig());
+}
+
+ShellPortMus::~ShellPortMus() {}
+
+// static
+ShellPortMus* ShellPortMus::Get() {
+  const ash::Config config = ShellPort::Get()->GetAshConfig();
+  CHECK(config == Config::MUS);
+  return static_cast<ShellPortMus*>(ShellPort::Get());
+}
+
+RootWindowController* ShellPortMus::GetRootWindowControllerWithDisplayId(
+    int64_t id) {
+  for (RootWindowController* root_window_controller :
+       RootWindowController::root_window_controllers()) {
+    RootWindowSettings* settings =
+        GetRootWindowSettings(root_window_controller->GetRootWindow());
+    DCHECK(settings);
+    if (settings->display_id == id)
+      return root_window_controller;
+  }
+  return nullptr;
+}
+
+aura::WindowTreeClient* ShellPortMus::window_tree_client() {
+  return window_manager_->window_tree_client();
+}
+
+void ShellPortMus::Shutdown() {
+  display_synchronizer_.reset();
+
+  pointer_watcher_adapter_.reset();
+
+  ShellPort::Shutdown();
+}
+
+Config ShellPortMus::GetAshConfig() const {
+  return Config::MUS;
+}
+
+std::unique_ptr<display::TouchTransformSetter>
+ShellPortMus::CreateTouchTransformDelegate() {
+  return std::make_unique<TouchTransformSetterMus>(
+      window_manager_->connector());
+}
+
+void ShellPortMus::LockCursor() {
+  // When we are running in mus, we need to keep track of state not just in the
+  // window server, but also locally in ash because ash treats the cursor
+  // manager as the canonical state for now. NativeCursorManagerAsh will keep
+  // this state, while also forwarding it to the window manager for us.
+  Shell::Get()->cursor_manager()->LockCursor();
+}
+
+void ShellPortMus::UnlockCursor() {
+  Shell::Get()->cursor_manager()->UnlockCursor();
+}
+
+void ShellPortMus::ShowCursor() {
+  Shell::Get()->cursor_manager()->ShowCursor();
+}
+
+void ShellPortMus::HideCursor() {
+  Shell::Get()->cursor_manager()->HideCursor();
+}
+
+void ShellPortMus::SetCursorSize(ui::CursorSize cursor_size) {
+  Shell::Get()->cursor_manager()->SetCursorSize(cursor_size);
+}
+
+void ShellPortMus::SetGlobalOverrideCursor(
+    base::Optional<ui::CursorData> cursor) {
+  NOTREACHED();
+}
+
+bool ShellPortMus::IsMouseEventsEnabled() {
+  return Shell::Get()->cursor_manager()->IsMouseEventsEnabled();
+}
+
+void ShellPortMus::SetCursorTouchVisible(bool enabled) {
+  NOTREACHED();
+}
+
+std::unique_ptr<WindowResizer> ShellPortMus::CreateDragWindowResizer(
+    std::unique_ptr<WindowResizer> next_window_resizer,
+    wm::WindowState* window_state) {
+  return base::WrapUnique(ash::DragWindowResizer::Create(
+      next_window_resizer.release(), window_state));
+}
+
+std::unique_ptr<WindowCycleEventFilter>
+ShellPortMus::CreateWindowCycleEventFilter() {
+  return std::make_unique<WindowCycleEventFilterClassic>();
+}
+
+std::unique_ptr<wm::TabletModeEventHandler>
+ShellPortMus::CreateTabletModeEventHandler() {
+  return std::make_unique<wm::TabletModeEventHandlerClassic>();
+}
+
+std::unique_ptr<WorkspaceEventHandler>
+ShellPortMus::CreateWorkspaceEventHandler(aura::Window* workspace_window) {
+  return std::make_unique<WorkspaceEventHandlerClassic>(workspace_window);
+}
+
+std::unique_ptr<ImmersiveFullscreenController>
+ShellPortMus::CreateImmersiveFullscreenController() {
+  // TODO: Move this to Shell.
+  return std::make_unique<ImmersiveFullscreenController>();
+}
+
+std::unique_ptr<KeyboardUI> ShellPortMus::CreateKeyboardUI() {
+  return KeyboardUI::Create();
+}
+
+void ShellPortMus::AddPointerWatcher(views::PointerWatcher* watcher,
+                                     views::PointerWatcherEventTypes events) {
+  pointer_watcher_adapter_->AddPointerWatcher(watcher, events);
+}
+
+void ShellPortMus::RemovePointerWatcher(views::PointerWatcher* watcher) {
+  pointer_watcher_adapter_->RemovePointerWatcher(watcher);
+}
+
+bool ShellPortMus::IsTouchDown() {
+  return aura::Env::GetInstance()->is_touch_down();
+}
+
+void ShellPortMus::ToggleIgnoreExternalKeyboard() {
+  Shell::Get()->virtual_keyboard_controller()->ToggleIgnoreExternalKeyboard();
+}
+
+void ShellPortMus::CreatePointerWatcherAdapter() {
+  // In Config::MUS PointerWatcherAdapterClassic must be created when this
+  // function is called (it is order dependent), that is not the case with
+  // Config::MASH.
+  pointer_watcher_adapter_ = std::make_unique<PointerWatcherAdapterClassic>();
+}
+
+std::unique_ptr<AshWindowTreeHost> ShellPortMus::CreateAshWindowTreeHost(
+    const AshWindowTreeHostInitParams& init_params) {
+  std::unique_ptr<aura::DisplayInitParams> display_params =
+      std::make_unique<aura::DisplayInitParams>();
+  display_params->viewport_metrics.bounds_in_pixels =
+      init_params.initial_bounds;
+  display_params->viewport_metrics.device_scale_factor =
+      init_params.device_scale_factor;
+  display_params->viewport_metrics.ui_scale_factor =
+      init_params.ui_scale_factor;
+  display::DisplayManager* display_manager = Shell::Get()->display_manager();
+  display::Display mirrored_display =
+      display_manager->GetMirroringDisplayById(init_params.display_id);
+  if (mirrored_display.is_valid()) {
+    display_params->display =
+        std::make_unique<display::Display>(mirrored_display);
+  }
+  display_params->is_primary_display = true;
+  display_params->mirrors = display_manager->software_mirroring_display_list();
+  aura::WindowTreeHostMusInitParams aura_init_params =
+      window_manager_->window_manager_client()->CreateInitParamsForNewDisplay();
+  aura_init_params.display_id = init_params.display_id;
+  aura_init_params.display_init_params = std::move(display_params);
+  aura_init_params.use_classic_ime = !Shell::ShouldUseIMEService();
+  return std::make_unique<AshWindowTreeHostMus>(std::move(aura_init_params));
+}
+
+void ShellPortMus::OnCreatedRootWindowContainers(
+    RootWindowController* root_window_controller) {
+  // TODO: To avoid lots of IPC AddActivationParent() should take an array.
+  // http://crbug.com/682048.
+  aura::Window* root_window = root_window_controller->GetRootWindow();
+  for (size_t i = 0; i < kNumActivatableShellWindowIds; ++i) {
+    window_manager_->window_manager_client()->AddActivationParent(
+        root_window->GetChildById(kActivatableShellWindowIds[i]));
+  }
+
+  UpdateSystemModalAndBlockingContainers();
+}
+
+void ShellPortMus::UpdateSystemModalAndBlockingContainers() {
+  std::vector<aura::BlockingContainers> all_blocking_containers;
+  for (RootWindowController* root_window_controller :
+       Shell::GetAllRootWindowControllers()) {
+    aura::BlockingContainers blocking_containers;
+    wm::GetBlockingContainersForRoot(
+        root_window_controller->GetRootWindow(),
+        &blocking_containers.min_container,
+        &blocking_containers.system_modal_container);
+    all_blocking_containers.push_back(blocking_containers);
+  }
+  window_manager_->window_manager_client()->SetBlockingContainers(
+      all_blocking_containers);
+}
+
+void ShellPortMus::OnHostsInitialized() {
+  display_synchronizer_ = std::make_unique<DisplaySynchronizer>(
+      window_manager_->window_manager_client());
+}
+
+std::unique_ptr<display::NativeDisplayDelegate>
+ShellPortMus::CreateNativeDisplayDelegate() {
+  display::mojom::NativeDisplayDelegatePtr native_display_delegate;
+  if (window_manager_->connector()) {
+    window_manager_->connector()->BindInterface(ui::mojom::kServiceName,
+                                                &native_display_delegate);
+  }
+  return std::make_unique<display::ForwardingDisplayDelegate>(
+      std::move(native_display_delegate));
+}
+
+std::unique_ptr<AcceleratorController>
+ShellPortMus::CreateAcceleratorController() {
+  DCHECK(!accelerator_controller_delegate_);
+  accelerator_controller_delegate_ =
+      std::make_unique<AcceleratorControllerDelegateClassic>();
+  return std::make_unique<AcceleratorController>(
+      accelerator_controller_delegate_.get(), nullptr);
+}
+
+}  // namespace mus
+}  // namespace ash
diff --git a/ash/mus/shell_port_mus.h b/ash/mus/shell_port_mus.h
new file mode 100644
index 0000000..3c27396
--- /dev/null
+++ b/ash/mus/shell_port_mus.h
@@ -0,0 +1,107 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef ASH_MUS_SHELL_PORT_MUS_H_
+#define ASH_MUS_SHELL_PORT_MUS_H_
+
+#include <stdint.h>
+
+#include <memory>
+
+#include "ash/shell_port.h"
+#include "base/macros.h"
+
+namespace aura {
+class WindowTreeClient;
+}
+
+namespace ash {
+
+class AcceleratorControllerDelegateClassic;
+class DisplaySynchronizer;
+class PointerWatcherAdapterClassic;
+class RootWindowController;
+
+namespace mus {
+
+class WindowManager;
+
+// ShellPort implementation for mus (and parts of mash). See ash/README.md.
+// Often uses "classic" ash implementations because only the window server
+// pieces are in a different mojo service.
+class ShellPortMus : public ShellPort {
+ public:
+  explicit ShellPortMus(WindowManager* window_manager);
+  ~ShellPortMus() override;
+
+  static ShellPortMus* Get();
+
+  ash::RootWindowController* GetRootWindowControllerWithDisplayId(int64_t id);
+
+  AcceleratorControllerDelegateClassic* accelerator_controller_delegate() {
+    return accelerator_controller_delegate_.get();
+  }
+
+  aura::WindowTreeClient* window_tree_client();
+
+  WindowManager* window_manager() { return window_manager_; }
+
+  // ShellPort:
+  void Shutdown() override;
+  Config GetAshConfig() const override;
+  std::unique_ptr<display::TouchTransformSetter> CreateTouchTransformDelegate()
+      override;
+  void LockCursor() override;
+  void UnlockCursor() override;
+  void ShowCursor() override;
+  void HideCursor() override;
+  void SetCursorSize(ui::CursorSize cursor_size) override;
+  void SetGlobalOverrideCursor(base::Optional<ui::CursorData> cursor) override;
+  bool IsMouseEventsEnabled() override;
+  void SetCursorTouchVisible(bool enabled) override;
+  std::unique_ptr<WindowResizer> CreateDragWindowResizer(
+      std::unique_ptr<WindowResizer> next_window_resizer,
+      wm::WindowState* window_state) override;
+  std::unique_ptr<WindowCycleEventFilter> CreateWindowCycleEventFilter()
+      override;
+  std::unique_ptr<wm::TabletModeEventHandler> CreateTabletModeEventHandler()
+      override;
+  std::unique_ptr<WorkspaceEventHandler> CreateWorkspaceEventHandler(
+      aura::Window* workspace_window) override;
+  std::unique_ptr<ImmersiveFullscreenController>
+  CreateImmersiveFullscreenController() override;
+  std::unique_ptr<KeyboardUI> CreateKeyboardUI() override;
+  void AddPointerWatcher(views::PointerWatcher* watcher,
+                         views::PointerWatcherEventTypes events) override;
+  void RemovePointerWatcher(views::PointerWatcher* watcher) override;
+  bool IsTouchDown() override;
+  void ToggleIgnoreExternalKeyboard() override;
+  void CreatePointerWatcherAdapter() override;
+  std::unique_ptr<AshWindowTreeHost> CreateAshWindowTreeHost(
+      const AshWindowTreeHostInitParams& init_params) override;
+  void OnCreatedRootWindowContainers(
+      RootWindowController* root_window_controller) override;
+  void UpdateSystemModalAndBlockingContainers() override;
+  void OnHostsInitialized() override;
+  std::unique_ptr<display::NativeDisplayDelegate> CreateNativeDisplayDelegate()
+      override;
+  std::unique_ptr<AcceleratorController> CreateAcceleratorController() override;
+
+ protected:
+  WindowManager* window_manager_;
+
+ private:
+  std::unique_ptr<PointerWatcherAdapterClassic> pointer_watcher_adapter_;
+  std::unique_ptr<AcceleratorControllerDelegateClassic>
+      accelerator_controller_delegate_;
+
+  std::unique_ptr<DisplaySynchronizer> display_synchronizer_;
+
+  DISALLOW_COPY_AND_ASSIGN(ShellPortMus);
+};
+
+}  // namespace mus
+}  // namespace ash
+
+#endif  // ASH_MUS_SHELL_PORT_MUS_H_
diff --git a/ash/mus/window_manager.cc b/ash/mus/window_manager.cc
index ba8fefb..c440b99 100644
--- a/ash/mus/window_manager.cc
+++ b/ash/mus/window_manager.cc
@@ -19,6 +19,7 @@
 #include "ash/mus/non_client_frame_controller.h"
 #include "ash/mus/property_util.h"
 #include "ash/mus/shell_delegate_mus.h"
+#include "ash/mus/shell_port_mus.h"
 #include "ash/mus/top_level_window_factory.h"
 #include "ash/mus/window_properties.h"
 #include "ash/public/cpp/config.h"
@@ -141,6 +142,7 @@
   DCHECK_EQ(nullptr, ash::Shell::window_tree_client());
   ash::Shell::set_window_tree_client(window_tree_client_.get());
 
+  // TODO(jamescook): Maybe not needed in Config::MUS?
   pointer_watcher_event_router_ =
       std::make_unique<views::PointerWatcherEventRouter>(
           window_tree_client_.get());
@@ -194,12 +196,15 @@
   DCHECK(!created_shell_);
   created_shell_ = true;
   ShellInitParams init_params;
-  ShellPortMash* shell_port =
-      new ShellPortMash(this, pointer_watcher_event_router_.get());
   // Shell::CreateInstance() takes ownership of ShellDelegate.
   init_params.delegate = shell_delegate_ ? shell_delegate_.release()
                                          : new ShellDelegateMus(connector_);
-  init_params.shell_port = shell_port;
+  if (config_ == Config::MUS) {
+    init_params.shell_port = new ShellPortMus(this);
+  } else {
+    init_params.shell_port =
+        new ShellPortMash(this, pointer_watcher_event_router_.get());
+  }
   Shell::CreateInstance(init_params);
 }
 
diff --git a/ash/shelf/shelf_layout_manager_unittest.cc b/ash/shelf/shelf_layout_manager_unittest.cc
index 482e3bc..0e0f37d 100644
--- a/ash/shelf/shelf_layout_manager_unittest.cc
+++ b/ash/shelf/shelf_layout_manager_unittest.cc
@@ -33,7 +33,6 @@
 #include "base/command_line.h"
 #include "base/message_loop/message_loop.h"
 #include "base/run_loop.h"
-#include "base/test/scoped_feature_list.h"
 #include "ui/app_list/app_list_features.h"
 #include "ui/app_list/presenter/app_list.h"
 #include "ui/app_list/presenter/test/test_app_list_presenter.h"
@@ -314,21 +313,6 @@
     return display::Screen::GetScreen()->GetPrimaryDisplay().id();
   }
 
- private:
-  DISALLOW_COPY_AND_ASSIGN(ShelfLayoutManagerTest);
-};
-
-class ShelfLayoutManagerFullscreenAppListTest : public ShelfLayoutManagerTest {
- public:
-  ShelfLayoutManagerFullscreenAppListTest() {}
-
-  void SetUp() override {
-    ShelfLayoutManagerTest::SetUp();
-
-    scoped_feature_list.InitAndEnableFeature(
-        app_list::features::kEnableFullscreenAppList);
-  }
-
   void StartScroll(gfx::Point start) {
     timestamp_ = base::TimeTicks::Now();
     current_point_ = start;
@@ -364,11 +348,10 @@
   }
 
  private:
-  base::test::ScopedFeatureList scoped_feature_list;
   base::TimeTicks timestamp_;
   gfx::Point current_point_;
 
-  DISALLOW_COPY_AND_ASSIGN(ShelfLayoutManagerFullscreenAppListTest);
+  DISALLOW_COPY_AND_ASSIGN(ShelfLayoutManagerTest);
 };
 
 void ShelfLayoutManagerTest::RunGestureDragTests(gfx::Vector2d delta) {
@@ -1439,8 +1422,7 @@
 
 // If swiping up on shelf ends with fling event, the app list state should
 // depends on the fling velocity.
-TEST_F(ShelfLayoutManagerFullscreenAppListTest,
-       FlingUpOnShelfForFullscreenAppList) {
+TEST_F(ShelfLayoutManagerTest, FlingUpOnShelfForFullscreenAppList) {
   Shelf* shelf = GetPrimaryShelf();
   EXPECT_EQ(SHELF_ALIGNMENT_BOTTOM, shelf->alignment());
   EXPECT_EQ(SHELF_AUTO_HIDE_BEHAVIOR_NEVER, shelf->auto_hide_behavior());
@@ -1490,8 +1472,7 @@
 }
 
 // Change the shelf alignment during dragging should dismiss the app list.
-TEST_F(ShelfLayoutManagerFullscreenAppListTest,
-       ChangeShelfAlignmentDuringAppListDragging) {
+TEST_F(ShelfLayoutManagerTest, ChangeShelfAlignmentDuringAppListDragging) {
   Shelf* shelf = GetPrimaryShelf();
   EXPECT_EQ(SHELF_ALIGNMENT_BOTTOM, shelf->alignment());
   EXPECT_EQ(SHELF_AUTO_HIDE_BEHAVIOR_NEVER, shelf->auto_hide_behavior());
@@ -1514,7 +1495,7 @@
   EXPECT_GE(test_app_list_presenter.set_y_position_count(), 1u);
 }
 
-TEST_F(ShelfLayoutManagerFullscreenAppListTest,
+TEST_F(ShelfLayoutManagerTest,
        SwipingUpOnShelfInTabletModeForFullscreenAppList) {
   Shell* shell = Shell::Get();
   shell->tablet_mode_controller()->EnableTabletModeWindowManager(true);
@@ -1606,7 +1587,7 @@
             test_app_list_presenter.app_list_state());
 }
 
-TEST_F(ShelfLayoutManagerFullscreenAppListTest,
+TEST_F(ShelfLayoutManagerTest,
        SwipingUpOnShelfInLaptopModeForFullscreenAppList) {
   Shelf* shelf = GetPrimaryShelf();
   EXPECT_EQ(SHELF_ALIGNMENT_BOTTOM, shelf->alignment());
@@ -1666,8 +1647,7 @@
 }
 
 // Swiping on shelf when fullscreen app list is opened should have no effect.
-TEST_F(ShelfLayoutManagerFullscreenAppListTest,
-       SwipingOnShelfIfFullscreenAppListOpened) {
+TEST_F(ShelfLayoutManagerTest, SwipingOnShelfIfFullscreenAppListOpened) {
   Shelf* shelf = GetPrimaryShelf();
   ShelfLayoutManager* layout_manager = GetShelfLayoutManager();
   aura::Window* root_window =
diff --git a/ash/shelf/shelf_view_unittest.cc b/ash/shelf/shelf_view_unittest.cc
index 19841f1..b05ce3a 100644
--- a/ash/shelf/shelf_view_unittest.cc
+++ b/ash/shelf/shelf_view_unittest.cc
@@ -45,7 +45,6 @@
 #include "base/strings/string_number_conversions.h"
 #include "base/strings/utf_string_conversions.h"
 #include "base/test/histogram_tester.h"
-#include "base/test/scoped_feature_list.h"
 #include "base/test/scoped_mock_time_message_loop_task_runner.h"
 #include "base/test/user_action_tester.h"
 #include "base/time/time.h"
@@ -2031,10 +2030,6 @@
 }
 
 TEST_F(ShelfViewTest, MouseWheelScrollOnShelfTransitionsAppList) {
-  // Enable the Fullscreen AppList.
-  base::test::ScopedFeatureList scoped_feature_list;
-  scoped_feature_list.InitAndEnableFeature(
-      app_list::features::kEnableFullscreenAppList);
   TestAppListPresenterImpl app_list_presenter_impl;
   app_list_presenter_impl.ShowAndRunLoop(GetPrimaryDisplayId());
   app_list::test::TestAppListPresenter test_app_list_presenter;
@@ -2052,10 +2047,6 @@
 }
 
 TEST_F(ShelfViewTest, MouseWheelScrollOnApplistButtonTransitionsAppList) {
-  // Enable the fullscreen app list.
-  base::test::ScopedFeatureList scoped_feature_list;
-  scoped_feature_list.InitAndEnableFeature(
-      app_list::features::kEnableFullscreenAppList);
   TestAppListPresenterImpl app_list_presenter_impl;
   app_list_presenter_impl.ShowAndRunLoop(GetPrimaryDisplayId());
   app_list::test::TestAppListPresenter test_app_list_presenter;
@@ -2074,10 +2065,6 @@
 }
 
 TEST_F(ShelfViewTest, MouseWheelScrollOnAppIconTransitionsAppList) {
-  // Enable the Fullscreen AppList.
-  base::test::ScopedFeatureList scoped_feature_list;
-  scoped_feature_list.InitAndEnableFeature(
-      app_list::features::kEnableFullscreenAppList);
   TestAppListPresenterImpl app_list_presenter_impl;
   app_list_presenter_impl.ShowAndRunLoop(GetPrimaryDisplayId());
   app_list::test::TestAppListPresenter test_app_list_presenter;
diff --git a/ash/shell_port.cc b/ash/shell_port.cc
index 6ce5db883..21cbb06 100644
--- a/ash/shell_port.cc
+++ b/ash/shell_port.cc
@@ -6,20 +6,15 @@
 
 #include <utility>
 
-#include "ash/accelerators/accelerator_controller.h"
 #include "ash/public/cpp/shell_window_ids.h"
 #include "ash/root_window_controller.h"
 #include "ash/session/session_controller.h"
-#include "ash/shelf/app_list_shelf_item_delegate.h"
 #include "ash/shell.h"
-#include "ash/shell_delegate.h"
 #include "ash/wm/root_window_finder.h"
-#include "ash/wm/system_modal_container_layout_manager.h"
 #include "base/bind.h"
 #include "base/logging.h"
 #include "ui/aura/client/aura_constants.h"
 #include "ui/aura/window.h"
-#include "ui/display/display.h"
 
 namespace ash {
 
@@ -70,10 +65,6 @@
   instance_ = this;
 }
 
-bool ShellPort::IsForceMaximizeOnFirstRun() {
-  return Shell::Get()->shell_delegate()->IsForceMaximizeOnFirstRun();
-}
-
 int ShellPort::GetOpenSystemModalWindowContainerId() {
   if (simulate_modal_window_open_for_testing_)
     return kShellWindowId_SystemModalContainer;
@@ -105,28 +96,4 @@
   return GetOpenSystemModalWindowContainerId() >= 0;
 }
 
-void ShellPort::CreateModalBackground(aura::Window* window) {
-  for (aura::Window* root_window : Shell::GetAllRootWindows()) {
-    RootWindowController::ForWindow(root_window)
-        ->GetSystemModalLayoutManager(window)
-        ->CreateModalBackground();
-  }
-}
-
-void ShellPort::OnModalWindowRemoved(aura::Window* removed) {
-  aura::Window::Windows root_windows = Shell::GetAllRootWindows();
-  for (aura::Window* root_window : root_windows) {
-    if (RootWindowController::ForWindow(root_window)
-            ->GetSystemModalLayoutManager(removed)
-            ->ActivateNextModalWindow()) {
-      return;
-    }
-  }
-  for (aura::Window* root_window : root_windows) {
-    RootWindowController::ForWindow(root_window)
-        ->GetSystemModalLayoutManager(removed)
-        ->DestroyModalBackground();
-  }
-}
-
 }  // namespace ash
diff --git a/ash/shell_port.h b/ash/shell_port.h
index 78d83a8..e784094d 100644
--- a/ash/shell_port.h
+++ b/ash/shell_port.h
@@ -72,11 +72,6 @@
 
   virtual Config GetAshConfig() const = 0;
 
-  // Returns true if the first window shown on first run should be
-  // unconditionally maximized, overriding the heuristic that normally chooses
-  // the window size.
-  bool IsForceMaximizeOnFirstRun();
-
   // If a system-modal dialog window is currently open, returns the ID of the
   // system modal window container that contains the window.
   // If no system-modal dialogs are open it returns -1.
@@ -85,14 +80,6 @@
   // Returns true if a system-modal dialog window is currently open.
   bool IsSystemModalWindowOpen();
 
-  // Creates a modal background (a partially-opaque fullscreen window) on all
-  // displays for |window|.
-  void CreateModalBackground(aura::Window* window);
-
-  // Called when a modal window is removed. It will activate another modal
-  // window if any, or remove modal screens on all displays.
-  void OnModalWindowRemoved(aura::Window* removed);
-
   // The return value from this is supplied to AshTouchTransformController; see
   // it and TouchTransformSetter for details.
   virtual std::unique_ptr<display::TouchTransformSetter>
@@ -169,12 +156,6 @@
   // TODO(jamescook): Remove this when VirtualKeyboardController has been moved.
   virtual void ToggleIgnoreExternalKeyboard() = 0;
 
-  // Enable or disable the laser pointer.
-  virtual void SetLaserPointerEnabled(bool enabled) = 0;
-
-  // Enable or disable the partial magnifier.
-  virtual void SetPartialMagnifierEnabled(bool enabled) = 0;
-
   virtual void CreatePointerWatcherAdapter() = 0;
 
   // Creates an AshWindowTreeHost. A return value of null results in a platform
diff --git a/ash/shell_port_classic.cc b/ash/shell_port_classic.cc
index 233a061..ed77fb5 100644
--- a/ash/shell_port_classic.cc
+++ b/ash/shell_port_classic.cc
@@ -12,8 +12,6 @@
 #include "ash/host/ash_window_tree_host.h"
 #include "ash/host/ash_window_tree_host_init_params.h"
 #include "ash/keyboard/keyboard_ui.h"
-#include "ash/laser/laser_pointer_controller.h"
-#include "ash/magnifier/partial_magnification_controller.h"
 #include "ash/pointer_watcher_adapter_classic.h"
 #include "ash/public/cpp/config.h"
 #include "ash/public/cpp/immersive/immersive_fullscreen_controller.h"
@@ -122,6 +120,7 @@
 
 std::unique_ptr<ImmersiveFullscreenController>
 ShellPortClassic::CreateImmersiveFullscreenController() {
+  // TODO: Move this to Shell.
   return std::make_unique<ImmersiveFullscreenController>();
 }
 
@@ -147,14 +146,6 @@
   Shell::Get()->virtual_keyboard_controller()->ToggleIgnoreExternalKeyboard();
 }
 
-void ShellPortClassic::SetLaserPointerEnabled(bool enabled) {
-  Shell::Get()->laser_pointer_controller()->SetEnabled(enabled);
-}
-
-void ShellPortClassic::SetPartialMagnifierEnabled(bool enabled) {
-  Shell::Get()->partial_magnification_controller()->SetEnabled(enabled);
-}
-
 void ShellPortClassic::CreatePointerWatcherAdapter() {
   pointer_watcher_adapter_ = std::make_unique<PointerWatcherAdapterClassic>();
 }
diff --git a/ash/shell_port_classic.h b/ash/shell_port_classic.h
index 3b2a27e..9cd404b 100644
--- a/ash/shell_port_classic.h
+++ b/ash/shell_port_classic.h
@@ -60,8 +60,6 @@
   void RemovePointerWatcher(views::PointerWatcher* watcher) override;
   bool IsTouchDown() override;
   void ToggleIgnoreExternalKeyboard() override;
-  void SetLaserPointerEnabled(bool enabled) override;
-  void SetPartialMagnifierEnabled(bool enabled) override;
   void CreatePointerWatcherAdapter() override;
   std::unique_ptr<AshWindowTreeHost> CreateAshWindowTreeHost(
       const AshWindowTreeHostInitParams& init_params) override;
diff --git a/ash/system/brightness/brightness_controller_chromeos.cc b/ash/system/brightness/brightness_controller_chromeos.cc
index 9e3a473..b75a90d 100644
--- a/ash/system/brightness/brightness_controller_chromeos.cc
+++ b/ash/system/brightness/brightness_controller_chromeos.cc
@@ -4,6 +4,8 @@
 
 #include "ash/system/brightness/brightness_controller_chromeos.h"
 
+#include <utility>
+
 #include "base/metrics/user_metrics.h"
 #include "chromeos/dbus/dbus_thread_manager.h"
 #include "chromeos/dbus/power_manager_client.h"
@@ -40,10 +42,10 @@
 }
 
 void BrightnessControllerChromeos::GetBrightnessPercent(
-    const base::Callback<void(double)>& callback) {
+    base::OnceCallback<void(base::Optional<double>)> callback) {
   chromeos::DBusThreadManager::Get()
       ->GetPowerManagerClient()
-      ->GetScreenBrightnessPercent(callback);
+      ->GetScreenBrightnessPercent(std::move(callback));
 }
 
 }  // namespace system
diff --git a/ash/system/brightness/brightness_controller_chromeos.h b/ash/system/brightness/brightness_controller_chromeos.h
index f6e7a027..2cb2787 100644
--- a/ash/system/brightness/brightness_controller_chromeos.h
+++ b/ash/system/brightness/brightness_controller_chromeos.h
@@ -9,6 +9,7 @@
 #include "ash/system/brightness_control_delegate.h"
 #include "base/compiler_specific.h"
 #include "base/macros.h"
+#include "base/optional.h"
 
 namespace ash {
 namespace system {
@@ -26,7 +27,7 @@
   void HandleBrightnessUp(const ui::Accelerator& accelerator) override;
   void SetBrightnessPercent(double percent, bool gradual) override;
   void GetBrightnessPercent(
-      const base::Callback<void(double)>& callback) override;
+      base::OnceCallback<void(base::Optional<double>)> callback) override;
 
  private:
   DISALLOW_COPY_AND_ASSIGN(BrightnessControllerChromeos);
diff --git a/ash/system/brightness/tray_brightness.cc b/ash/system/brightness/tray_brightness.cc
index 0cb2768..1c90819 100644
--- a/ash/system/brightness/tray_brightness.cc
+++ b/ash/system/brightness/tray_brightness.cc
@@ -199,13 +199,13 @@
   if (!brightness_control_delegate)
     return;
   brightness_control_delegate->GetBrightnessPercent(
-      base::Bind(&TrayBrightness::HandleInitialBrightness,
-                 weak_ptr_factory_.GetWeakPtr()));
+      base::BindOnce(&TrayBrightness::HandleInitialBrightness,
+                     weak_ptr_factory_.GetWeakPtr()));
 }
 
-void TrayBrightness::HandleInitialBrightness(double percent) {
-  if (!got_current_percent_)
-    HandleBrightnessChanged(percent, false);
+void TrayBrightness::HandleInitialBrightness(base::Optional<double> percent) {
+  if (!got_current_percent_ && percent.has_value())
+    HandleBrightnessChanged(percent.value(), false);
 }
 
 views::View* TrayBrightness::CreateDefaultView(LoginStatus status) {
diff --git a/ash/system/brightness/tray_brightness.h b/ash/system/brightness/tray_brightness.h
index ad3c1b1..ee6cd39 100644
--- a/ash/system/brightness/tray_brightness.h
+++ b/ash/system/brightness/tray_brightness.h
@@ -8,6 +8,7 @@
 #include "ash/system/tray/system_tray_item.h"
 #include "base/macros.h"
 #include "base/memory/weak_ptr.h"
+#include "base/optional.h"
 #include "chromeos/dbus/power_manager_client.h"
 
 namespace ash {
@@ -32,7 +33,7 @@
   // Updates |current_percent_| with the initial brightness requested by
   // GetInitialBrightness(), if we haven't seen the brightness already in the
   // meantime.
-  void HandleInitialBrightness(double percent);
+  void HandleInitialBrightness(base::Optional<double> percent);
 
   // Overridden from SystemTrayItem.
   views::View* CreateDefaultView(LoginStatus status) override;
diff --git a/ash/system/brightness_control_delegate.h b/ash/system/brightness_control_delegate.h
index 153cc92..68ab2f9 100644
--- a/ash/system/brightness_control_delegate.h
+++ b/ash/system/brightness_control_delegate.h
@@ -6,6 +6,7 @@
 #define ASH_SYSTEM_BRIGHTNESS_CONTROL_DELEGATE_H_
 
 #include "base/callback.h"
+#include "base/optional.h"
 
 namespace ui {
 class Accelerator;
@@ -29,9 +30,9 @@
   virtual void SetBrightnessPercent(double percent, bool gradual) = 0;
 
   // Asynchronously invokes |callback| with the current brightness, in the range
-  // [0.0, 100.0].
+  // [0.0, 100.0]. In case of error, it is called with nullopt.
   virtual void GetBrightnessPercent(
-      const base::Callback<void(double)>& callback) = 0;
+      base::OnceCallback<void(base::Optional<double>)> callback) = 0;
 };
 
 }  // namespace ash
diff --git a/ash/system/network/network_list.cc b/ash/system/network/network_list.cc
index b8aae87..dab9c65 100644
--- a/ash/system/network/network_list.cc
+++ b/ash/system/network/network_list.cc
@@ -39,6 +39,7 @@
 #include "base/timer/timer.h"
 #include "chromeos/dbus/dbus_thread_manager.h"
 #include "chromeos/login/login_state.h"
+#include "chromeos/network/device_state.h"
 #include "chromeos/network/managed_network_configuration_handler.h"
 #include "chromeos/network/network_state.h"
 #include "chromeos/network/network_state_handler.h"
@@ -102,6 +103,21 @@
       network->guid(), network->profile_path(), nullptr /* onc_source */);
 }
 
+bool IsCellularSimLocked() {
+  const chromeos::DeviceState* cellular_device =
+      NetworkHandler::Get()->network_state_handler()->GetDeviceStateByType(
+          NetworkTypePattern::Cellular());
+  return cellular_device && cellular_device->IsSimLocked();
+}
+
+void ShowCellularSettings() {
+  const chromeos::NetworkState* cellular_network =
+      NetworkHandler::Get()->network_state_handler()->FirstNetworkByType(
+          NetworkTypePattern::Cellular());
+  Shell::Get()->system_tray_controller()->ShowNetworkSettings(
+      cellular_network ? cellular_network->guid() : std::string());
+}
+
 }  // namespace
 
 // A header row for sections in network detailed view which contains a title and
@@ -118,7 +134,7 @@
 
   ~SectionHeaderRowView() override {}
 
-  void Init(bool enabled) {
+  virtual void Init(bool enabled) {
     InitializeLayout();
     AddExtraButtons(enabled);
     AddToggleButton(enabled);
@@ -138,9 +154,10 @@
                     previous_insets.bottom(), previous_insets.right())));
   }
 
-  virtual void SetIsOn(bool enabled) {
-    toggle_->set_accepts_events(true);
-    toggle_->SetIsOn(enabled, true);
+  virtual void SetToggleState(bool toggle_enabled, bool is_on) {
+    toggle_->SetEnabled(toggle_enabled);
+    toggle_->set_accepts_events(toggle_enabled);
+    toggle_->SetIsOn(is_on, true /* animate */);
   }
 
  protected:
@@ -212,7 +229,9 @@
 
 namespace {
 
-// "Mobile Data" header row.
+// "Mobile Data" header row. Mobile Data reflects both Cellular state and
+// Tether state. When both technologies are available, Cellular state takes
+// precedence over Tether (but in some cases Tether state may be shown).
 class MobileHeaderRowView : public NetworkListView::SectionHeaderRowView,
                             public chromeos::NetworkStateHandlerObserver {
  public:
@@ -227,91 +246,158 @@
     network_state_handler_->RemoveObserver(this, FROM_HERE);
   }
 
-  void SetIsOn(bool enabled) override {
-    // If Mobile data is in the process of being enabled, keep the toggle
-    // enabled. This ensures that the user does not see any UI jank in which the
-    // toggle changes values during this process.
-    enabled |= (status_ != Status::IDLE);
-    SectionHeaderRowView::SetIsOn(enabled);
+  void Init(bool enabled) override {
+    SectionHeaderRowView::Init(enabled);
+    UpdateState();
   }
 
   const char* GetClassName() const override { return "MobileHeaderRowView"; }
 
  protected:
-  enum class Status {
-    IDLE,
-    WAITING_FOR_DEVICE_LIST_CHANGE
-  };
-
   // NetworkListView::SectionHeaderRowView:
   void OnToggleToggled(bool is_on) override {
-    // The Mobile network type contains both Cellular and Tether technologies,
-    // though one or both of these may be unavailable. When Cellular technology
-    // is available, the enabled value of Tether depends on the enabled value of
-    // Cellular, so the toggle should only explicitly change the enabled value
-    // of Cellular.
-    if (network_state_handler_->IsTechnologyAvailable(
-            NetworkTypePattern::Cellular())) {
+    NetworkStateHandler::TechnologyState cellular_state =
+        network_state_handler_->GetTechnologyState(
+            NetworkTypePattern::Cellular());
+
+    // When Cellular is available, the toggle controls Cellular enabled state.
+    // (Tether may be enabled by turning on Bluetooth and turning on
+    // 'Get data connection' in the Settings > Mobile data subpage).
+    if (cellular_state != NetworkStateHandler::TECHNOLOGY_UNAVAILABLE) {
+      if (is_on && IsCellularSimLocked()) {
+        ShowCellularSettings();
+        return;
+      }
       network_state_handler_->SetTechnologyEnabled(
           NetworkTypePattern::Cellular(), is_on,
           chromeos::network_handler::ErrorCallback());
       return;
     }
 
-    // However, if Cellular technology is not available but Tether technology is
-    // available, the toggle should explicitly change the enabled value of
-    // Tether.
-    DCHECK(network_state_handler_->IsTechnologyAvailable(
-        NetworkTypePattern::Tether()));
+    NetworkStateHandler::TechnologyState tether_state =
+        network_state_handler_->GetTechnologyState(
+            NetworkTypePattern::Tether());
 
-    // If Tether is uninitialized, it is disabled because Bluetooth is off. In
-    // this case, enabling the toggle should enable Bluetooth and Tether.
-    if (network_state_handler_->IsTechnologyUninitialized(
-            NetworkTypePattern::Tether())) {
-      DCHECK(is_on);
+    // Tether is also unavailable (edge case).
+    if (tether_state == NetworkStateHandler::TECHNOLOGY_UNAVAILABLE)
+      return;
 
-      // If Bluetooth is in the process of being enabled, continue waiting for
-      // this to occur.
-      if (status_ != Status::IDLE)
-        return;
-
-      EnableBluetooth();
+    // If Tether is available but uninitialized, we expect Bluetooth to be off.
+    // Enable Bluetooth so that Tether will be initialized. Ignore edge cases
+    // (e.g. Bluetooth was disabled from a different UI).
+    if (tether_state == NetworkStateHandler::TECHNOLOGY_UNINITIALIZED) {
+      if (is_on && !waiting_for_tether_initialize_)
+        EnableBluetooth();
       return;
     }
 
-    // Otherwise, simply set the value of the toggle.
+    // Otherwise the toggle controls the Tether enabled state.
     network_state_handler_->SetTechnologyEnabled(
         NetworkTypePattern::Tether(), is_on,
         chromeos::network_handler::ErrorCallback());
   }
 
-  // chromeos::NetworkStateHandlerObserver:
-  void DeviceListChanged() override {
-    if (network_state_handler_->IsTechnologyAvailable(
-            NetworkTypePattern::Cellular())) {
-      status_ = Status::IDLE;
-      SetIsOn(network_state_handler_->IsTechnologyEnabled(
-          NetworkTypePattern::Cellular()));
+  // chromeos::NetworkStateHandlerObserver
+  // Update state if the Cellular or Tether device state may have changed, or if
+  // the list of Cellular or Tether networks may have changed.
+  void DeviceListChanged() override { UpdateState(); }
+  void NetworkListChanged() override { UpdateState(); }
+
+  void UpdateState() {
+    NetworkStateHandler::TechnologyState cellular_state =
+        network_state_handler_->GetTechnologyState(
+            NetworkTypePattern::Cellular());
+    NetworkStateHandler::TechnologyState tether_state =
+        network_state_handler_->GetTechnologyState(
+            NetworkTypePattern::Tether());
+
+    // If Cellular is available, toggle state and subtitle reflect Cellular.
+    if (cellular_state != NetworkStateHandler::TECHNOLOGY_UNAVAILABLE) {
+      const chromeos::DeviceState* cellular_device =
+          network_state_handler_->GetDeviceStateByType(
+              NetworkTypePattern::Cellular());
+      bool cellular_enabled =
+          cellular_state == NetworkStateHandler::TECHNOLOGY_ENABLED;
+      SetToggleState(true /* toggle_enabled */, cellular_enabled);
+
+      int subtitle = 0;
+      if (!cellular_device ||
+          cellular_state == NetworkStateHandler::TECHNOLOGY_UNINITIALIZED) {
+        subtitle = IDS_ASH_STATUS_TRAY_INITIALIZING_CELLULAR;
+      } else if (cellular_device->scanning()) {
+        subtitle = IDS_ASH_STATUS_TRAY_MOBILE_SCANNING;
+      } else if (cellular_device->IsSimAbsent()) {
+        subtitle = IDS_ASH_STATUS_TRAY_SIM_CARD_MISSING;
+      } else if (cellular_device->IsSimLocked()) {
+        subtitle = IDS_ASH_STATUS_TRAY_SIM_CARD_LOCKED;
+      } else {
+        const chromeos::NetworkState* mobile_network =
+            network_state_handler_->FirstNetworkByType(
+                NetworkTypePattern::Mobile());
+        if (cellular_enabled &&
+            (!mobile_network || mobile_network->IsDefaultCellular())) {
+          // If no connectable Cellular network is available (see
+          // network_state_handler.h re: IsDefaultCellular), show 'turn on
+          // Bluetooth' if Tether is available but not initialized, otherwise
+          // show 'no networks'.
+          if (tether_state == NetworkStateHandler::TECHNOLOGY_UNINITIALIZED)
+            subtitle = IDS_ASH_STATUS_TRAY_ENABLE_BLUETOOTH;
+          else
+            subtitle = IDS_ASH_STATUS_TRAY_NO_MOBILE_NETWORKS;
+        }
+      }
+      SetSubtitle(subtitle);
       return;
     }
 
-    if (!network_state_handler_->IsTechnologyAvailable(
-            NetworkTypePattern::Tether())) {
-      // If Tether has become unavailable, it is disabled for some other reason
-      // (e.g., the device could be in the process of being shut down).
-      status_ = Status::IDLE;
-      SetIsOn(false);
+    // Tether is also unavailable (edge case).
+    if (tether_state == NetworkStateHandler::TECHNOLOGY_UNAVAILABLE) {
+      SetToggleState(false /* toggle_enabled */, false /* is_on */);
+      SetSubtitle(IDS_ASH_STATUS_TRAY_NETWORK_MOBILE_DISABLED);
       return;
     }
 
-    if (status_ != Status::WAITING_FOR_DEVICE_LIST_CHANGE ||
-        network_state_handler_->IsTechnologyUninitialized(
-            NetworkTypePattern::Tether())) {
-      // If the device list change was unrelated to Tether, keep waiting.
+    // Otherwise, toggle state and subtitle reflect Tether.
+
+    if (tether_state == NetworkStateHandler::TECHNOLOGY_UNINITIALIZED) {
+      if (waiting_for_tether_initialize_) {
+        SetToggleState(false /* toggle_enabled */, true /* is_on */);
+        // "Initializing...". TODO(stevenjb): Rename the string to _MOBILE.
+        SetSubtitle(IDS_ASH_STATUS_TRAY_INITIALIZING_CELLULAR);
+      } else {
+        SetToggleState(true /* toggle_enabled */, false /* is_on */);
+        SetSubtitle(IDS_ASH_STATUS_TRAY_ENABLING_MOBILE_ENABLES_BLUETOOTH);
+      }
       return;
     }
 
-    OnEnableBluetoothSuccess();
+    bool tether_enabled =
+        tether_state == NetworkStateHandler::TECHNOLOGY_ENABLED;
+
+    if (waiting_for_tether_initialize_) {
+      waiting_for_tether_initialize_ = false;
+      enable_bluetooth_timer_.Stop();
+      if (!tether_enabled) {
+        // We enabled Bluetooth so Tether is now initialized, but it was not
+        // enabled so enable it.
+        network_state_handler_->SetTechnologyEnabled(
+            NetworkTypePattern::Tether(), true /* enabled */,
+            chromeos::network_handler::ErrorCallback());
+        SetToggleState(true /* toggle_enabled */, true /* is_on */);
+        // "Initializing...". TODO(stevenjb): Rename the string to _MOBILE.
+        SetSubtitle(IDS_ASH_STATUS_TRAY_INITIALIZING_CELLULAR);
+        return;
+      }
+    }
+
+    // Ensure that the toggle state and subtitle match the tether state.
+    int subtitle = 0;
+    if (tether_enabled && !network_state_handler_->FirstNetworkByType(
+                              NetworkTypePattern::Tether())) {
+      subtitle = IDS_ASH_STATUS_TRAY_NO_MOBILE_DEVICES_FOUND;
+    }
+    SetToggleState(true /* toggle_enabled */, tether_enabled /* is_on */);
+    SetSubtitle(subtitle);
   }
 
  private:
@@ -320,48 +406,36 @@
   // period, it is assumed that there was an error. In that case, Tether will
   // remain uninitialized and Mobile Data will remain toggled off.
   void EnableBluetooth() {
-    DCHECK(status_ == Status::IDLE);
+    DCHECK(!waiting_for_tether_initialize_);
 
     Shell::Get()
         ->bluetooth_power_controller()
         ->SetPrimaryUserBluetoothPowerSetting(true /* enabled */);
-    status_ = Status::WAITING_FOR_DEVICE_LIST_CHANGE;
-    timer_.Start(FROM_HERE,
-                 base::TimeDelta::FromSeconds(kBluetoothTimeoutDelaySeconds),
-                 base::Bind(&MobileHeaderRowView::OnEnableBluetoothTimeout,
-                            weak_ptr_factory_.GetWeakPtr()));
+    waiting_for_tether_initialize_ = true;
+    enable_bluetooth_timer_.Start(
+        FROM_HERE, base::TimeDelta::FromSeconds(kBluetoothTimeoutDelaySeconds),
+        base::Bind(&MobileHeaderRowView::OnEnableBluetoothTimeout,
+                   weak_ptr_factory_.GetWeakPtr()));
   }
 
   void OnEnableBluetoothTimeout() {
-    DCHECK(status_ == Status::WAITING_FOR_DEVICE_LIST_CHANGE);
-    status_ = Status::IDLE;
-    SetIsOn(false);
+    DCHECK(waiting_for_tether_initialize_);
+    waiting_for_tether_initialize_ = false;
+    SetToggleState(true /* toggle_enabled */, false /* is_on */);
 
-    LOG(ERROR) << "Error enabling Bluetooth adapter. Cannot enable Mobile "
-               << "data.";
-  }
-
-  void OnEnableBluetoothSuccess() {
-    DCHECK(timer_.IsRunning());
-    timer_.Stop();
-
-    status_ = Status::IDLE;
-    network_state_handler_->SetTechnologyEnabled(
-        NetworkTypePattern::Tether(), true /* enabled */,
-        chromeos::network_handler::ErrorCallback());
+    LOG(ERROR) << "Error enabling Bluetooth. Cannot enable Mobile data.";
   }
 
   NetworkStateHandler* network_state_handler_;
 
-  Status status_ = Status::IDLE;
-  base::OneShotTimer timer_;
+  bool waiting_for_tether_initialize_ = false;
+  base::OneShotTimer enable_bluetooth_timer_;
 
   base::WeakPtrFactory<MobileHeaderRowView> weak_ptr_factory_;
 
   DISALLOW_COPY_AND_ASSIGN(MobileHeaderRowView);
 };
 
-
 class WifiHeaderRowView : public NetworkListView::SectionHeaderRowView {
  public:
   WifiHeaderRowView()
@@ -370,9 +444,9 @@
 
   ~WifiHeaderRowView() override {}
 
-  void SetIsOn(bool enabled) override {
-    join_->SetEnabled(enabled);
-    SectionHeaderRowView::SetIsOn(enabled);
+  void SetToggleState(bool toggle_enabled, bool is_on) override {
+    join_->SetEnabled(is_on);
+    SectionHeaderRowView::SetToggleState(toggle_enabled, is_on);
   }
 
   const char* GetClassName() const override { return "WifiHeaderRowView"; }
@@ -605,48 +679,10 @@
   index += new_guids->size();
 
   if (ShouldMobileDataSectionBeShown()) {
-    bool cellular_enabled =
-        handler->IsTechnologyEnabled(NetworkTypePattern::Cellular());
-    bool tether_enabled =
-        handler->IsTechnologyEnabled(NetworkTypePattern::Tether());
-    int mobile_message_id = 0;
-
-    if (handler->IsTechnologyAvailable(NetworkTypePattern::Cellular()) &&
-        !handler->IsTechnologyAvailable(NetworkTypePattern::Tether())) {
-      // If Cellular is available and Tether is not, display cellular-specific
-      // messages if necessary. Note that GetCellularUninitializedMsg() returns
-      // 0 if no special message should be displayed.
-      mobile_message_id = network_icon::GetCellularUninitializedMsg();
-      if (!mobile_message_id &&
-          !handler->FirstNetworkByType(NetworkTypePattern::Cellular())) {
-        mobile_message_id = IDS_ASH_STATUS_TRAY_NO_MOBILE_NETWORKS;
-      }
-    } else {
-      if (handler->IsTechnologyUninitialized(NetworkTypePattern::Tether())) {
-        // If Tether is uninitialized, it is disabled due to Bluetooth being
-        // off. If Cellular is available, the Mobile toggle is on, so display a
-        // message to enable Bluetooth. If Cellular is unavailable, the Mobile
-        // toggle is off, so display a message stating that toggling it on will
-        // enable Bluetooth.
-        mobile_message_id =
-            cellular_enabled
-                ? IDS_ASH_STATUS_TRAY_ENABLE_BLUETOOTH
-                : IDS_ASH_STATUS_TRAY_ENABLING_MOBILE_ENABLES_BLUETOOTH;
-      } else {
-        if (!cellular_enabled && !tether_enabled)
-          mobile_message_id = IDS_ASH_STATUS_TRAY_NETWORK_MOBILE_DISABLED;
-      }
-
-      if (!mobile_message_id &&
-          !handler->FirstNetworkByType(NetworkTypePattern::Mobile())) {
-        mobile_message_id = IDS_ASH_STATUS_TRAY_NO_MOBILE_DEVICES_FOUND;
-      }
-    }
-
+    // Note: Mobile will update its own enabled state.
     index = UpdateSectionHeaderRow(
-        NetworkTypePattern::Mobile(),
-        cellular_enabled || tether_enabled /* enabled */, index,
-        &mobile_header_view_, &mobile_separator_view_, mobile_message_id);
+        NetworkTypePattern::Mobile(), false /* enabled */, index,
+        &mobile_header_view_, &mobile_separator_view_);
 
     std::unique_ptr<std::set<std::string>> new_cellular_guids =
         UpdateNetworkChildren(NetworkInfo::Type::MOBILE, index);
@@ -864,8 +900,7 @@
                                             bool enabled,
                                             int child_index,
                                             SectionHeaderRowView** view,
-                                            views::Separator** separator_view,
-                                            int subtitle_message_id) {
+                                            views::Separator** separator_view) {
   if (!*view) {
     if (pattern.MatchesPattern(NetworkTypePattern::Mobile()))
       *view = new MobileHeaderRowView(
@@ -888,8 +923,9 @@
     *separator_view = nullptr;
   }
 
-  (*view)->SetIsOn(enabled);
-  (*view)->SetSubtitle(subtitle_message_id);
+  // Mobile updates its toggle state independently.
+  if (!pattern.MatchesPattern(NetworkTypePattern::Mobile()))
+    (*view)->SetToggleState(true /* toggle_enabled */, enabled /* is_on */);
   PlaceViewAtIndex(*view, child_index++);
   return child_index;
 }
diff --git a/ash/system/network/network_list.h b/ash/system/network/network_list.h
index a2d9b35..f1f59e8a 100644
--- a/ash/system/network/network_list.h
+++ b/ash/system/network/network_list.h
@@ -111,15 +111,13 @@
 
   // Creates a cellular/tether/Wi-Fi header row |view| and adds it to
   // |scroll_content()| if necessary and reorders the |scroll_content()| placing
-  // the |view| at |child_index|. If |subtitle_message_id| is not 0, a subtitle
-  // will be rendered beneath the title. Returns the index where the next child
-  // should be inserted, i.e., the index directly after the last inserted child.
+  // the |view| at |child_index|. Returns the index where the next child should
+  // be inserted, i.e., the index directly after the last inserted child.
   int UpdateSectionHeaderRow(chromeos::NetworkTypePattern pattern,
                              bool enabled,
                              int child_index,
                              SectionHeaderRowView** view,
-                             views::Separator** separator_view,
-                             int subtitle_message_id = 0);
+                             views::Separator** separator_view);
 
   // network_icon::AnimationObserver:
   void NetworkIconChanged() override;
diff --git a/ash/system/palette/tools/laser_pointer_mode.cc b/ash/system/palette/tools/laser_pointer_mode.cc
index e55a310..7e31862 100644
--- a/ash/system/palette/tools/laser_pointer_mode.cc
+++ b/ash/system/palette/tools/laser_pointer_mode.cc
@@ -4,8 +4,9 @@
 
 #include "ash/system/palette/tools/laser_pointer_mode.h"
 
+#include "ash/laser/laser_pointer_controller.h"
 #include "ash/resources/vector_icons/vector_icons.h"
-#include "ash/shell_port.h"
+#include "ash/shell.h"
 #include "ash/strings/grit/ash_strings.h"
 #include "ash/system/palette/palette_ids.h"
 #include "ui/base/l10n/l10n_util.h"
@@ -29,14 +30,14 @@
 void LaserPointerMode::OnEnable() {
   CommonPaletteTool::OnEnable();
 
-  ShellPort::Get()->SetLaserPointerEnabled(true);
+  Shell::Get()->laser_pointer_controller()->SetEnabled(true);
   delegate()->HidePalette();
 }
 
 void LaserPointerMode::OnDisable() {
   CommonPaletteTool::OnDisable();
 
-  ShellPort::Get()->SetLaserPointerEnabled(false);
+  Shell::Get()->laser_pointer_controller()->SetEnabled(false);
 }
 
 const gfx::VectorIcon& LaserPointerMode::GetActiveTrayIcon() const {
diff --git a/ash/system/palette/tools/magnifier_mode.cc b/ash/system/palette/tools/magnifier_mode.cc
index 3df5ba82..94d4a37 100644
--- a/ash/system/palette/tools/magnifier_mode.cc
+++ b/ash/system/palette/tools/magnifier_mode.cc
@@ -4,8 +4,9 @@
 
 #include "ash/system/palette/tools/magnifier_mode.h"
 
+#include "ash/magnifier/partial_magnification_controller.h"
 #include "ash/resources/vector_icons/vector_icons.h"
-#include "ash/shell_port.h"
+#include "ash/shell.h"
 #include "ash/strings/grit/ash_strings.h"
 #include "ash/system/palette/palette_ids.h"
 #include "ui/base/l10n/l10n_util.h"
@@ -31,13 +32,13 @@
 
 void MagnifierMode::OnEnable() {
   CommonPaletteTool::OnEnable();
-  ShellPort::Get()->SetPartialMagnifierEnabled(true);
+  Shell::Get()->partial_magnification_controller()->SetEnabled(true);
   delegate()->HidePalette();
 }
 
 void MagnifierMode::OnDisable() {
   CommonPaletteTool::OnDisable();
-  ShellPort::Get()->SetPartialMagnifierEnabled(false);
+  Shell::Get()->partial_magnification_controller()->SetEnabled(false);
 }
 
 views::View* MagnifierMode::CreateView() {
diff --git a/ash/system/power/power_button_display_controller.cc b/ash/system/power/power_button_display_controller.cc
index c3358c09..ea71397 100644
--- a/ash/system/power/power_button_display_controller.cc
+++ b/ash/system/power/power_button_display_controller.cc
@@ -137,14 +137,14 @@
 void PowerButtonDisplayController::GetInitialBacklightsForcedOff() {
   chromeos::DBusThreadManager::Get()
       ->GetPowerManagerClient()
-      ->GetBacklightsForcedOff(base::Bind(
+      ->GetBacklightsForcedOff(base::BindOnce(
           &PowerButtonDisplayController::OnGotInitialBacklightsForcedOff,
           weak_ptr_factory_.GetWeakPtr()));
 }
 
 void PowerButtonDisplayController::OnGotInitialBacklightsForcedOff(
-    bool is_forced_off) {
-  backlights_forced_off_ = is_forced_off;
+    base::Optional<bool> is_forced_off) {
+  backlights_forced_off_ = is_forced_off.value_or(false);
   UpdateTouchscreenStatus();
 }
 
diff --git a/ash/system/power/power_button_display_controller.h b/ash/system/power/power_button_display_controller.h
index a78e4f1..f0b1bd2 100644
--- a/ash/system/power/power_button_display_controller.h
+++ b/ash/system/power/power_button_display_controller.h
@@ -8,6 +8,7 @@
 #include "ash/ash_export.h"
 #include "base/macros.h"
 #include "base/memory/weak_ptr.h"
+#include "base/optional.h"
 #include "base/time/time.h"
 #include "chromeos/dbus/power_manager_client.h"
 #include "ui/events/devices/input_device_event_observer.h"
@@ -72,7 +73,7 @@
   void GetInitialBacklightsForcedOff();
 
   // Initializes |backlights_forced_off_|.
-  void OnGotInitialBacklightsForcedOff(bool is_forced_off);
+  void OnGotInitialBacklightsForcedOff(base::Optional<bool> is_forced_off);
 
   // Enables or disables the touchscreen by updating the global touchscreen
   // enabled status. The touchscreen is disabled when backlights are forced off
diff --git a/ash/system/power/power_event_observer.cc b/ash/system/power/power_event_observer.cc
index 7184174..96258e3f 100644
--- a/ash/system/power/power_event_observer.cc
+++ b/ash/system/power/power_event_observer.cc
@@ -70,7 +70,8 @@
   }
 }
 
-void PowerEventObserver::SuspendImminent() {
+void PowerEventObserver::SuspendImminent(
+    power_manager::SuspendImminent::Reason reason) {
   SessionController* controller = Shell::Get()->session_controller();
 
   // This class is responsible for disabling all rendering requests at suspend
diff --git a/ash/system/power/power_event_observer.h b/ash/system/power/power_event_observer.h
index 502484fa..3e6d60c 100644
--- a/ash/system/power/power_event_observer.h
+++ b/ash/system/power/power_event_observer.h
@@ -30,7 +30,7 @@
   void OnLockAnimationsComplete();
 
   // chromeos::PowerManagerClient::Observer overrides:
-  void SuspendImminent() override;
+  void SuspendImminent(power_manager::SuspendImminent::Reason reason) override;
   void SuspendDone(const base::TimeDelta& sleep_duration) override;
 
   // chromeos::SessionManagerClient::Observer overrides.
diff --git a/ash/system/power/power_event_observer_unittest.cc b/ash/system/power/power_event_observer_unittest.cc
index 6c1c5ac..8b1870ad 100644
--- a/ash/system/power/power_event_observer_unittest.cc
+++ b/ash/system/power/power_event_observer_unittest.cc
@@ -14,6 +14,7 @@
 #include "ash/wm/test_session_state_animator.h"
 #include "base/time/time.h"
 #include "chromeos/dbus/dbus_thread_manager.h"
+#include "chromeos/dbus/power_manager/suspend.pb.h"
 #include "chromeos/dbus/power_manager_client.h"
 #include "ui/aura/window.h"
 #include "ui/aura/window_tree_host.h"
@@ -71,7 +72,7 @@
   // that the system is about to suspend.
   SetCanLockScreen(true);
   SetShouldLockScreenAutomatically(true);
-  observer_->SuspendImminent();
+  observer_->SuspendImminent(power_manager::SuspendImminent_Reason_OTHER);
   EXPECT_EQ(1, client->GetNumPendingSuspendReadinessCallbacks());
 
   // It should run the callback when it hears that the screen is locked and the
@@ -85,14 +86,14 @@
   observer_->ScreenIsUnlocked();
   observer_->ScreenIsLocked();
   observer_->OnLockAnimationsComplete();
-  observer_->SuspendImminent();
+  observer_->SuspendImminent(power_manager::SuspendImminent_Reason_OTHER);
   EXPECT_EQ(0, client->GetNumPendingSuspendReadinessCallbacks());
 
   // It also shouldn't request a callback if it isn't instructed to lock the
   // screen.
   observer_->SuspendDone(base::TimeDelta());
   SetShouldLockScreenAutomatically(false);
-  observer_->SuspendImminent();
+  observer_->SuspendImminent(power_manager::SuspendImminent_Reason_OTHER);
   EXPECT_EQ(0, client->GetNumPendingSuspendReadinessCallbacks());
 }
 
@@ -101,7 +102,7 @@
   // request when the screen is not supposed to be locked before a suspend.
   EXPECT_EQ(1, GetNumVisibleCompositors());
 
-  observer_->SuspendImminent();
+  observer_->SuspendImminent(power_manager::SuspendImminent_Reason_OTHER);
   EXPECT_EQ(0, GetNumVisibleCompositors());
   observer_->SuspendDone(base::TimeDelta());
 
@@ -110,7 +111,7 @@
   SetCanLockScreen(true);
   SetShouldLockScreenAutomatically(true);
 
-  observer_->SuspendImminent();
+  observer_->SuspendImminent(power_manager::SuspendImminent_Reason_OTHER);
   EXPECT_EQ(1, GetNumVisibleCompositors());
 
   observer_->ScreenIsLocked();
@@ -128,7 +129,7 @@
   // canceled or the system resumes before the lock screen is ready.
   SetCanLockScreen(true);
   SetShouldLockScreenAutomatically(true);
-  observer_->SuspendImminent();
+  observer_->SuspendImminent(power_manager::SuspendImminent_Reason_OTHER);
   EXPECT_EQ(1, GetNumVisibleCompositors());
 
   observer_->SuspendDone(base::TimeDelta());
@@ -153,12 +154,12 @@
 
   chromeos::PowerManagerClient* client =
       chromeos::DBusThreadManager::Get()->GetPowerManagerClient();
-  observer_->SuspendImminent();
+  observer_->SuspendImminent(power_manager::SuspendImminent_Reason_OTHER);
   EXPECT_EQ(1, client->GetNumPendingSuspendReadinessCallbacks());
 
   observer_->ScreenIsLocked();
   observer_->SuspendDone(base::TimeDelta());
-  observer_->SuspendImminent();
+  observer_->SuspendImminent(power_manager::SuspendImminent_Reason_OTHER);
 
   // The expected number of suspend readiness callbacks is 2 because the
   // observer has not run the callback that it got from the first suspend
@@ -183,7 +184,7 @@
   SetShouldLockScreenAutomatically(true);
   ASSERT_FALSE(GetLockedState());
 
-  observer_->SuspendImminent();
+  observer_->SuspendImminent(power_manager::SuspendImminent_Reason_OTHER);
   // Tests that locking animation starts.
   EXPECT_TRUE(lock_state_test_api.is_animating_lock());
 
diff --git a/ash/system/power/tablet_power_button_controller_unittest.cc b/ash/system/power/tablet_power_button_controller_unittest.cc
index 0c10a49..4cdd531 100644
--- a/ash/system/power/tablet_power_button_controller_unittest.cc
+++ b/ash/system/power/tablet_power_button_controller_unittest.cc
@@ -18,6 +18,7 @@
 #include "base/run_loop.h"
 #include "base/test/simple_test_tick_clock.h"
 #include "chromeos/dbus/fake_power_manager_client.h"
+#include "chromeos/dbus/power_manager/suspend.pb.h"
 #include "ui/events/event.h"
 #include "ui/events/test/event_generator.h"
 
@@ -167,7 +168,8 @@
 // off.
 TEST_F(TabletPowerButtonControllerTest,
        TappingPowerButtonWhenSuspendedWithoutBacklightsForcedOff) {
-  power_manager_client_->SendSuspendImminent();
+  power_manager_client_->SendSuspendImminent(
+      power_manager::SuspendImminent_Reason_OTHER);
   power_manager_client_->SendBrightnessChanged(0, true);
   // There is a power button pressed here, but PowerButtonEvent is sent later.
   power_manager_client_->SendSuspendDone();
@@ -201,7 +203,8 @@
   ReleasePowerButton();
   power_manager_client_->SendBrightnessChanged(0, true);
   ASSERT_TRUE(power_manager_client_->backlights_forced_off());
-  power_manager_client_->SendSuspendImminent();
+  power_manager_client_->SendSuspendImminent(
+      power_manager::SuspendImminent_Reason_OTHER);
   // There is a power button pressed here, but PowerButtonEvent is sent later.
   // Because of backlights forced off, resuming system will not restore
   // brightness.
diff --git a/ash/system/tray/tray_bubble_wrapper.cc b/ash/system/tray/tray_bubble_wrapper.cc
index 969d80c..b605c8b 100644
--- a/ash/system/tray/tray_bubble_wrapper.cc
+++ b/ash/system/tray/tray_bubble_wrapper.cc
@@ -73,9 +73,19 @@
     return;
 
   int container_id = wm::GetContainerForWindow(gained_active)->id();
+  int lost_container_id = lost_active != nullptr
+                              ? wm::GetContainerForWindow(lost_active)->id()
+                              : -1;
 
   // Don't close the bubble if a popup notification is activated.
+  //
+  // When the settings button in a notification popup is clicked,
+  // the notification is activated and hidden almost at the same time.
+  // In such case, the notification is deactivated without OnWindowActivated for
+  // the activation being called.
+  // We also have to ignore such case by checking |lost_container_id|.
   if (container_id == kShellWindowId_StatusContainer ||
+      lost_container_id == kShellWindowId_StatusContainer ||
       container_id == kShellWindowId_SettingBubbleContainer) {
     return;
   }
diff --git a/ash/test/ash_test_helper.cc b/ash/test/ash_test_helper.cc
index 9567bb6..10de212 100644
--- a/ash/test/ash_test_helper.cc
+++ b/ash/test/ash_test_helper.cc
@@ -11,6 +11,7 @@
 #include "ash/accelerators/accelerator_controller_delegate_classic.h"
 #include "ash/display/display_configuration_controller_test_api.h"
 #include "ash/mus/bridge/shell_port_mash.h"
+#include "ash/mus/shell_port_mus.h"
 #include "ash/mus/window_manager.h"
 #include "ash/mus/window_manager_application.h"
 #include "ash/public/cpp/ash_switches.h"
@@ -197,8 +198,8 @@
             std::unique_ptr<ScreenshotDelegate>(test_screenshot_delegate_));
   } else if (config_ == Config::MUS) {
     test_screenshot_delegate_ = new TestScreenshotDelegate();
-    mus::ShellPortMash::Get()
-        ->accelerator_controller_delegate_mus()
+    mus::ShellPortMus::Get()
+        ->accelerator_controller_delegate()
         ->SetScreenshotDelegate(
             std::unique_ptr<ScreenshotDelegate>(test_screenshot_delegate_));
   }
diff --git a/ash/wm/overview/window_grid.cc b/ash/wm/overview/window_grid.cc
index d860e5d..abb5db7 100644
--- a/ash/wm/overview/window_grid.cc
+++ b/ash/wm/overview/window_grid.cc
@@ -580,6 +580,16 @@
   PositionWindows(true /* animate */, ignored_item);
 }
 
+void WindowGrid::SetSelectionWidgetVisibility(bool visible) {
+  if (!selection_widget_)
+    return;
+
+  if (visible)
+    selection_widget_->Show();
+  else
+    selection_widget_->Hide();
+}
+
 void WindowGrid::OnWindowDestroying(aura::Window* window) {
   window_observer_.Remove(window);
   window_state_observer_.Remove(wm::GetWindowState(window));
diff --git a/ash/wm/overview/window_grid.h b/ash/wm/overview/window_grid.h
index df7272c..b62969dc 100644
--- a/ash/wm/overview/window_grid.h
+++ b/ash/wm/overview/window_grid.h
@@ -113,6 +113,10 @@
       const gfx::Rect& bounds,
       WindowSelectorItem* ignored_item);
 
+  // Shows or hides the selection widget. To be called by a window selector item
+  // when it is dragged.
+  void SetSelectionWidgetVisibility(bool visible);
+
   // Returns true if the grid has no more windows.
   bool empty() const { return window_list_.empty(); }
 
diff --git a/ash/wm/overview/window_selector_item.cc b/ash/wm/overview/window_selector_item.cc
index 78bdf9b8..61e4546 100644
--- a/ash/wm/overview/window_selector_item.cc
+++ b/ash/wm/overview/window_selector_item.cc
@@ -838,6 +838,8 @@
 }
 
 void WindowSelectorItem::StartDrag() {
+  window_grid_->SetSelectionWidgetVisibility(false);
+
   gfx::Rect scaled_bounds(target_bounds_);
   scaled_bounds.Inset(-target_bounds_.width() * kDragWindowScale,
                       -target_bounds_.height() * kDragWindowScale);
@@ -855,6 +857,8 @@
 }
 
 void WindowSelectorItem::EndDrag() {
+  window_grid_->SetSelectionWidgetVisibility(true);
+
   // First stack this item's window below the snapped window if split view mode
   // is active.
   aura::Window* dragged_window = GetWindow();
diff --git a/ash/wm/overview/window_selector_unittest.cc b/ash/wm/overview/window_selector_unittest.cc
index 63b91eb0..64a68c18 100644
--- a/ash/wm/overview/window_selector_unittest.cc
+++ b/ash/wm/overview/window_selector_unittest.cc
@@ -2153,11 +2153,6 @@
   EXPECT_EQ(GetSplitViewRightWindowBounds(window1.get()), GetGridBounds());
   window_selector()->Drag(selector_item, center);
   EXPECT_EQ(GetSplitViewRightWindowBounds(window1.get()), GetGridBounds());
-
-  // TODO(sammiequon|xdai): Exit overview as a stop gap solution to avoid memory
-  // leak during shutdown. Fix and remove the ToggleOverview. See
-  // crbug.com/766725
-  ToggleOverview();
 }
 
 // Tests dragging a unsnappable window.
@@ -2557,11 +2552,6 @@
   EXPECT_NE(window1_bounds, window1_bounds_after_resize);
   EXPECT_NE(overview_grid_bounds, overview_grid_bounds_after_resize);
   EXPECT_NE(divider_bounds, divider_bounds_after_resize);
-
-  // TODO(sammiequon|xdai): Exit overview as a stop gap solution to avoid memory
-  // leak during shutdown. Fix and remove the ToggleOverview. See
-  // crbug.com/766725
-  ToggleOverview();
 }
 
 // Verify that selecting an unsnappable window while in split view works as
diff --git a/ash/wm/splitview/split_view_controller_unittest.cc b/ash/wm/splitview/split_view_controller_unittest.cc
index 133acb7..950485a 100644
--- a/ash/wm/splitview/split_view_controller_unittest.cc
+++ b/ash/wm/splitview/split_view_controller_unittest.cc
@@ -418,11 +418,6 @@
   auto iter = std::find(windows.begin(), windows.end(),
                         split_view_controller()->GetDefaultSnappedWindow());
   EXPECT_TRUE(iter == windows.end());
-
-  // TODO(sammiequon|xdai): Exit overview as a stop gap solution to avoid memory
-  // leak during shutdown. Fix and remove the ToggleOverview. See
-  // crbug.com/766725
-  ToggleOverview();
 }
 
 // Tests that the split divider was created when the split view mode is active
diff --git a/ash/wm/system_modal_container_layout_manager.cc b/ash/wm/system_modal_container_layout_manager.cc
index a4fc5c7..69043af9 100644
--- a/ash/wm/system_modal_container_layout_manager.cc
+++ b/ash/wm/system_modal_container_layout_manager.cc
@@ -9,6 +9,7 @@
 
 #include "ash/public/cpp/config.h"
 #include "ash/public/cpp/shell_window_ids.h"
+#include "ash/root_window_controller.h"
 #include "ash/session/session_controller.h"
 #include "ash/shell.h"
 #include "ash/shell_port.h"
@@ -67,7 +68,7 @@
     AddModalWindow(window);
   } else {
     if (RemoveModalWindow(window))
-      ShellPort::Get()->OnModalWindowRemoved(window);
+      OnModalWindowRemoved(window);
   }
 }
 
@@ -126,7 +127,7 @@
     AddModalWindow(window);
   } else {
     if (RemoveModalWindow(window))
-      ShellPort::Get()->OnModalWindowRemoved(window);
+      OnModalWindowRemoved(window);
   }
 }
 
@@ -204,7 +205,12 @@
   DCHECK(!base::ContainsValue(modal_windows_, window));
 
   modal_windows_.push_back(window);
-  ShellPort::Get()->CreateModalBackground(window);
+  // Create the modal background on all displays for |window|.
+  for (aura::Window* root_window : Shell::GetAllRootWindows()) {
+    RootWindowController::ForWindow(root_window)
+        ->GetSystemModalLayoutManager(window)
+        ->CreateModalBackground();
+  }
   window->parent()->StackChildAtTop(window);
 
   gfx::Rect target_bounds = window->bounds();
@@ -221,6 +227,23 @@
   return true;
 }
 
+void SystemModalContainerLayoutManager::OnModalWindowRemoved(
+    aura::Window* removed) {
+  aura::Window::Windows root_windows = Shell::GetAllRootWindows();
+  for (aura::Window* root_window : root_windows) {
+    if (RootWindowController::ForWindow(root_window)
+            ->GetSystemModalLayoutManager(removed)
+            ->ActivateNextModalWindow()) {
+      return;
+    }
+  }
+  for (aura::Window* root_window : root_windows) {
+    RootWindowController::ForWindow(root_window)
+        ->GetSystemModalLayoutManager(removed)
+        ->DestroyModalBackground();
+  }
+}
+
 void SystemModalContainerLayoutManager::PositionDialogsAfterWorkAreaResize() {
   if (modal_windows_.empty())
     return;
diff --git a/ash/wm/system_modal_container_layout_manager.h b/ash/wm/system_modal_container_layout_manager.h
index d1633ef..1a39489 100644
--- a/ash/wm/system_modal_container_layout_manager.h
+++ b/ash/wm/system_modal_container_layout_manager.h
@@ -78,6 +78,10 @@
   // |modal_windows_|.
   bool RemoveModalWindow(aura::Window* window);
 
+  // Called when a modal window is removed. It will activate another modal
+  // window if any, or remove modal screens on all displays.
+  void OnModalWindowRemoved(aura::Window* removed);
+
   // Reposition the dialogs to become visible after the work area changes.
   void PositionDialogsAfterWorkAreaResize();
 
diff --git a/ash/wm/tablet_mode/tablet_mode_controller.cc b/ash/wm/tablet_mode/tablet_mode_controller.cc
index aa36b1e1..1b5ab28 100644
--- a/ash/wm/tablet_mode/tablet_mode_controller.cc
+++ b/ash/wm/tablet_mode/tablet_mode_controller.cc
@@ -137,7 +137,7 @@
   chromeos::PowerManagerClient* power_manager_client =
       chromeos::DBusThreadManager::Get()->GetPowerManagerClient();
   power_manager_client->AddObserver(this);
-  power_manager_client->GetSwitchStates(base::Bind(
+  power_manager_client->GetSwitchStates(base::BindOnce(
       &TabletModeController::OnGetSwitchStates, weak_factory_.GetWeakPtr()));
 }
 
@@ -290,7 +290,8 @@
   }
 }
 
-void TabletModeController::SuspendImminent() {
+void TabletModeController::SuspendImminent(
+    power_manager::SuspendImminent::Reason reason) {
   // The system is about to suspend, so record TabletMode usage interval metrics
   // based on whether TabletMode mode is currently active.
   RecordTabletModeUsageInterval(CurrentTabletModeIntervalType());
@@ -472,10 +473,11 @@
 }
 
 void TabletModeController::OnGetSwitchStates(
-    chromeos::PowerManagerClient::LidState lid_state,
-    chromeos::PowerManagerClient::TabletMode tablet_mode) {
-  LidEventReceived(lid_state, base::TimeTicks::Now());
-  TabletModeEventReceived(tablet_mode, base::TimeTicks::Now());
+    base::Optional<chromeos::PowerManagerClient::SwitchStates> result) {
+  if (!result.has_value())
+    return;
+  LidEventReceived(result->lid_state, base::TimeTicks::Now());
+  TabletModeEventReceived(result->tablet_mode, base::TimeTicks::Now());
 }
 
 bool TabletModeController::WasLidOpenedRecently() const {
diff --git a/ash/wm/tablet_mode/tablet_mode_controller.h b/ash/wm/tablet_mode/tablet_mode_controller.h
index a7a5105b..7237b97 100644
--- a/ash/wm/tablet_mode/tablet_mode_controller.h
+++ b/ash/wm/tablet_mode/tablet_mode_controller.h
@@ -16,6 +16,7 @@
 #include "base/macros.h"
 #include "base/memory/weak_ptr.h"
 #include "base/observer_list.h"
+#include "base/optional.h"
 #include "base/time/time.h"
 #include "chromeos/accelerometer/accelerometer_reader.h"
 #include "chromeos/accelerometer/accelerometer_types.h"
@@ -121,7 +122,7 @@
                         const base::TimeTicks& time) override;
   void TabletModeEventReceived(chromeos::PowerManagerClient::TabletMode mode,
                                const base::TimeTicks& time) override;
-  void SuspendImminent() override;
+  void SuspendImminent(power_manager::SuspendImminent::Reason reason) override;
   void SuspendDone(const base::TimeDelta& sleep_duration) override;
 
  private:
@@ -146,8 +147,8 @@
   void HandleHingeRotation(
       scoped_refptr<const chromeos::AccelerometerUpdate> update);
 
-  void OnGetSwitchStates(chromeos::PowerManagerClient::LidState lid_state,
-                         chromeos::PowerManagerClient::TabletMode tablet_mode);
+  void OnGetSwitchStates(
+      base::Optional<chromeos::PowerManagerClient::SwitchStates> result);
 
   // Returns true if the lid was recently opened.
   bool WasLidOpenedRecently() const;
diff --git a/ash/wm/window_positioner.cc b/ash/wm/window_positioner.cc
index 577c45c3..22160d2 100644
--- a/ash/wm/window_positioner.cc
+++ b/ash/wm/window_positioner.cc
@@ -6,7 +6,7 @@
 
 #include "ash/screen_util.h"
 #include "ash/shell.h"
-#include "ash/shell_port.h"
+#include "ash/shell_delegate.h"
 #include "ash/wm/mru_window_tracker.h"
 #include "ash/wm/window_positioning_utils.h"
 #include "ash/wm/window_state.h"
@@ -248,7 +248,7 @@
 
     if (show_state_in == ui::SHOW_STATE_DEFAULT) {
       const bool maximize_first_window_on_first_run =
-          ShellPort::Get()->IsForceMaximizeOnFirstRun();
+          Shell::Get()->shell_delegate()->IsForceMaximizeOnFirstRun();
       // We want to always open maximized on "small screens" or when policy
       // tells us to.
       const bool set_maximized =
diff --git a/ash/wm/window_state.cc b/ash/wm/window_state.cc
index 7b08728..654d5188 100644
--- a/ash/wm/window_state.cc
+++ b/ash/wm/window_state.cc
@@ -213,18 +213,15 @@
 }
 
 void WindowState::Maximize() {
-  window_->SetProperty(aura::client::kShowStateKey, ui::SHOW_STATE_MAXIMIZED);
+  ::wm::SetWindowState(window_, ui::SHOW_STATE_MAXIMIZED);
 }
 
 void WindowState::Minimize() {
-  window_->SetProperty(aura::client::kShowStateKey, ui::SHOW_STATE_MINIMIZED);
+  ::wm::SetWindowState(window_, ui::SHOW_STATE_MINIMIZED);
 }
 
 void WindowState::Unminimize() {
-  window_->SetProperty(
-      aura::client::kShowStateKey,
-      window_->GetProperty(aura::client::kPreMinimizedShowStateKey));
-  window_->ClearProperty(aura::client::kPreMinimizedShowStateKey);
+  ::wm::Unminimize(window_);
 }
 
 void WindowState::Activate() {
diff --git a/ash/wm/workspace/workspace_layout_manager_unittest.cc b/ash/wm/workspace/workspace_layout_manager_unittest.cc
index 6474efb..352444b 100644
--- a/ash/wm/workspace/workspace_layout_manager_unittest.cc
+++ b/ash/wm/workspace/workspace_layout_manager_unittest.cc
@@ -39,7 +39,6 @@
 #include "ash/wm/workspace_controller_test_api.h"
 #include "base/command_line.h"
 #include "base/run_loop.h"
-#include "base/test/scoped_feature_list.h"
 #include "chromeos/audio/chromeos_sounds.h"
 #include "ui/app_list/app_list_features.h"
 #include "ui/aura/client/aura_constants.h"
@@ -1401,12 +1400,6 @@
       true);
   EXPECT_TRUE(secondary_test_helper.GetBackdropWindow());
 
-  // Enable fullscreen app list.
-  base::test::ScopedFeatureList scoped_feature_list;
-  scoped_feature_list.InitAndEnableFeature(
-      app_list::features::kEnableFullscreenAppList);
-  EXPECT_TRUE(app_list::features::IsFullscreenAppListEnabled());
-
   // Showing the app list on the primary display should not hide the backdrop on
   // the secondary display.
   EXPECT_TRUE(primary_test_helper.GetBackdropWindow());
@@ -1462,10 +1455,6 @@
   ShowTopWindowBackdropForContainer(default_container(), true);
   EXPECT_TRUE(test_helper.GetBackdropWindow());
 
-  // Enable fullscreen app list.
-  base::test::ScopedFeatureList scoped_feature_list;
-  scoped_feature_list.InitAndEnableFeature(
-      app_list::features::kEnableFullscreenAppList);
   EXPECT_TRUE(test_helper.GetBackdropWindow());
   EXPECT_TRUE(app_list::features::IsFullscreenAppListEnabled());
   // Showing the fullscreen app list should hide the backdrop.
diff --git a/base/BUILD.gn b/base/BUILD.gn
index 3c9ead2..92a131a 100644
--- a/base/BUILD.gn
+++ b/base/BUILD.gn
@@ -601,6 +601,7 @@
     "nix/xdg_util.cc",
     "nix/xdg_util.h",
     "observer_list.h",
+    "observer_list_threadsafe.cc",
     "observer_list_threadsafe.h",
     "optional.h",
     "os_compat_android.cc",
@@ -1057,6 +1058,7 @@
     "win/scoped_bstr.cc",
     "win/scoped_bstr.h",
     "win/scoped_co_mem.h",
+    "win/scoped_com_initializer.cc",
     "win/scoped_com_initializer.h",
     "win/scoped_gdi_object.h",
     "win/scoped_handle.cc",
@@ -1071,6 +1073,9 @@
     "win/scoped_select_object.h",
     "win/scoped_variant.cc",
     "win/scoped_variant.h",
+    "win/scoped_windows_thread_environment.h",
+    "win/scoped_winrt_initializer.cc",
+    "win/scoped_winrt_initializer.h",
     "win/shortcut.cc",
     "win/shortcut.h",
     "win/startup_information.cc",
@@ -2281,6 +2286,7 @@
     "win/scoped_hstring_unittest.cc",
     "win/scoped_process_information_unittest.cc",
     "win/scoped_variant_unittest.cc",
+    "win/scoped_winrt_initializer_unittest.cc",
     "win/shortcut_unittest.cc",
     "win/startup_information_unittest.cc",
     "win/wait_chain_unittest.cc",
diff --git a/base/android/linker/legacy_linker_jni.cc b/base/android/linker/legacy_linker_jni.cc
index c13cb3c5..c2c393e 100644
--- a/base/android/linker/legacy_linker_jni.cc
+++ b/base/android/linker/legacy_linker_jni.cc
@@ -52,7 +52,7 @@
     // Ensure libraries located in the same directory as the linker
     // can be loaded before system ones.
     crazy_context_add_search_path_for_address(
-        s_crazy_context, reinterpret_cast<void*>(&s_crazy_context));
+        s_crazy_context, reinterpret_cast<void*>(&GetCrazyContext));
   }
 
   return s_crazy_context;
diff --git a/base/debug/activity_tracker.cc b/base/debug/activity_tracker.cc
index 4e5357f..fa74681 100644
--- a/base/debug/activity_tracker.cc
+++ b/base/debug/activity_tracker.cc
@@ -1414,7 +1414,8 @@
     // TODO(bcwhite): Measure this in UMA.
     NOTREACHED() << "Process #" << process_id
                  << " was previously recorded as \"launched\""
-                 << " with no corresponding exit.";
+                 << " with no corresponding exit.\n"
+                 << known_processes_[pid];
     known_processes_.erase(pid);
   }
 
diff --git a/base/numerics/ranges.h b/base/numerics/ranges.h
index 8640731..f19320ce 100644
--- a/base/numerics/ranges.h
+++ b/base/numerics/ranges.h
@@ -10,8 +10,9 @@
 
 namespace base {
 
-template <typename T>
-T ClampToRange(T value, T min, T max) {
+// To be replaced with std::clamp() from C++17, someday.
+template <class T>
+constexpr const T& ClampToRange(const T& value, const T& min, const T& max) {
   return std::min(std::max(value, min), max);
 }
 
diff --git a/base/observer_list_threadsafe.cc b/base/observer_list_threadsafe.cc
new file mode 100644
index 0000000..95c852f
--- /dev/null
+++ b/base/observer_list_threadsafe.cc
@@ -0,0 +1,16 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "base/observer_list_threadsafe.h"
+
+namespace base {
+namespace internal {
+
+LazyInstance<ThreadLocalPointer<
+    const ObserverListThreadSafeBase::NotificationDataBase>>::Leaky
+    ObserverListThreadSafeBase::tls_current_notification_ =
+        LAZY_INSTANCE_INITIALIZER;
+
+}  // namespace internal
+}  // namespace base
diff --git a/base/observer_list_threadsafe.h b/base/observer_list_threadsafe.h
index fb78676..c85aee89 100644
--- a/base/observer_list_threadsafe.h
+++ b/base/observer_list_threadsafe.h
@@ -7,7 +7,9 @@
 
 #include <unordered_map>
 
+#include "base/base_export.h"
 #include "base/bind.h"
+#include "base/lazy_instance.h"
 #include "base/location.h"
 #include "base/logging.h"
 #include "base/macros.h"
@@ -54,22 +56,47 @@
 namespace base {
 namespace internal {
 
-template <typename ObserverType, typename Method>
-struct Dispatcher;
+class BASE_EXPORT ObserverListThreadSafeBase
+    : public RefCountedThreadSafe<ObserverListThreadSafeBase> {
+ public:
+  ObserverListThreadSafeBase() = default;
 
-template <typename ObserverType, typename ReceiverType, typename... Params>
-struct Dispatcher<ObserverType, void(ReceiverType::*)(Params...)> {
-  static void Run(void(ReceiverType::* m)(Params...),
-                  Params... params, ObserverType* obj) {
-    (obj->*m)(std::forward<Params>(params)...);
-  }
+ protected:
+  template <typename ObserverType, typename Method>
+  struct Dispatcher;
+
+  template <typename ObserverType, typename ReceiverType, typename... Params>
+  struct Dispatcher<ObserverType, void (ReceiverType::*)(Params...)> {
+    static void Run(void (ReceiverType::*m)(Params...),
+                    Params... params,
+                    ObserverType* obj) {
+      (obj->*m)(std::forward<Params>(params)...);
+    }
+  };
+
+  struct NotificationDataBase {
+    NotificationDataBase(void* observer_list_in, const Location& from_here_in)
+        : observer_list(observer_list_in), from_here(from_here_in) {}
+
+    void* observer_list;
+    Location from_here;
+  };
+
+  virtual ~ObserverListThreadSafeBase() = default;
+
+  static LazyInstance<ThreadLocalPointer<const NotificationDataBase>>::Leaky
+      tls_current_notification_;
+
+ private:
+  friend class RefCountedThreadSafe<ObserverListThreadSafeBase>;
+
+  DISALLOW_COPY_AND_ASSIGN(ObserverListThreadSafeBase);
 };
 
 }  // namespace internal
 
 template <class ObserverType>
-class ObserverListThreadSafe
-    : public RefCountedThreadSafe<ObserverListThreadSafe<ObserverType>> {
+class ObserverListThreadSafe : public internal::ObserverListThreadSafeBase {
  public:
   using NotificationType =
       typename ObserverList<ObserverType>::NotificationType;
@@ -98,13 +125,15 @@
     // or may not make it to |observer| depending on the outcome of the race to
     // |lock_|).
     if (type_ == NotificationType::NOTIFY_ALL) {
-      const NotificationData* current_notification =
-          tls_current_notification_.Get();
-      if (current_notification) {
+      const NotificationDataBase* current_notification =
+          tls_current_notification_.Get().Get();
+      if (current_notification && current_notification->observer_list == this) {
         task_runner->PostTask(
             current_notification->from_here,
-            BindOnce(&ObserverListThreadSafe<ObserverType>::NotifyWrapper, this,
-                     observer, *current_notification));
+            BindOnce(
+                &ObserverListThreadSafe<ObserverType>::NotifyWrapper, this,
+                observer,
+                *static_cast<const NotificationData*>(current_notification)));
       }
     }
   }
@@ -134,27 +163,28 @@
   template <typename Method, typename... Params>
   void Notify(const Location& from_here, Method m, Params&&... params) {
     Callback<void(ObserverType*)> method =
-        Bind(&internal::Dispatcher<ObserverType, Method>::Run,
-             m, std::forward<Params>(params)...);
+        Bind(&Dispatcher<ObserverType, Method>::Run, m,
+             std::forward<Params>(params)...);
 
     AutoLock lock(lock_);
     for (const auto& observer : observers_) {
       observer.second->PostTask(
           from_here,
           BindOnce(&ObserverListThreadSafe<ObserverType>::NotifyWrapper, this,
-                   observer.first, NotificationData(from_here, method)));
+                   observer.first, NotificationData(this, from_here, method)));
     }
   }
 
  private:
-  friend class RefCountedThreadSafe<ObserverListThreadSafe<ObserverType>>;
+  friend class RefCountedThreadSafe<ObserverListThreadSafeBase>;
 
-  struct NotificationData {
-    NotificationData(const Location& from_here_in,
+  struct NotificationData : public NotificationDataBase {
+    NotificationData(ObserverListThreadSafe* observer_list_in,
+                     const Location& from_here_in,
                      const Callback<void(ObserverType*)>& method_in)
-        : from_here(from_here_in), method(method_in) {}
+        : NotificationDataBase(observer_list_in, from_here_in),
+          method(method_in) {}
 
-    Location from_here;
     Callback<void(ObserverType*)> method;
   };
 
@@ -178,16 +208,17 @@
     // Note: |tls_current_notification_| may not be nullptr if this runs in a
     // nested loop started by a notification callback. In that case, it is
     // important to save the previous value to restore it later.
-    const NotificationData* const previous_notification =
-        tls_current_notification_.Get();
-    tls_current_notification_.Set(&notification);
+    auto& tls_current_notification = tls_current_notification_.Get();
+    const NotificationDataBase* const previous_notification =
+        tls_current_notification.Get();
+    tls_current_notification.Set(&notification);
 
     // Invoke the callback.
     notification.method.Run(observer);
 
     // Reset the notification being dispatched on the current thread to its
     // previous value.
-    tls_current_notification_.Set(previous_notification);
+    tls_current_notification.Set(previous_notification);
   }
 
   const NotificationType type_ = NotificationType::NOTIFY_ALL;
@@ -200,9 +231,6 @@
   std::unordered_map<ObserverType*, scoped_refptr<SequencedTaskRunner>>
       observers_;
 
-  // Notification being dispatched on the current thread.
-  ThreadLocalPointer<const NotificationData> tls_current_notification_;
-
   DISALLOW_COPY_AND_ASSIGN(ObserverListThreadSafe);
 };
 
diff --git a/base/process/launch_posix.cc b/base/process/launch_posix.cc
index 30341a2..604237b 100644
--- a/base/process/launch_posix.cc
+++ b/base/process/launch_posix.cc
@@ -68,6 +68,13 @@
 
 namespace base {
 
+// Friend and derived class of ScopedAllowBaseSyncPrimitives which allows
+// GetAppOutputInternal() to join a process. GetAppOutputInternal() can't itself
+// be a friend of ScopedAllowBaseSyncPrimitives because it is in the anonymous
+// namespace.
+class GetAppOutputScopedAllowBaseSyncPrimitives
+    : public base::ScopedAllowBaseSyncPrimitives {};
+
 #if !defined(OS_NACL_NONSFI)
 
 namespace {
@@ -540,7 +547,6 @@
     std::string* output,
     bool do_search_path,
     int* exit_code) {
-  // Doing a blocking wait for another command to finish counts as IO.
   base::AssertBlockingAllowed();
   // exit_code must be supplied so calling function can determine success.
   DCHECK(exit_code);
@@ -638,6 +644,9 @@
       // Always wait for exit code (even if we know we'll declare
       // GOT_MAX_OUTPUT).
       Process process(pid);
+      // A process launched with GetAppOutput*() usually doesn't wait on the
+      // process that launched it and thus chances of deadlock are low.
+      GetAppOutputScopedAllowBaseSyncPrimitives allow_base_sync_primitives;
       return process.WaitForExit(exit_code);
     }
   }
diff --git a/base/process/process_posix.cc b/base/process/process_posix.cc
index 11f48f7..b950b66 100644
--- a/base/process/process_posix.cc
+++ b/base/process/process_posix.cc
@@ -16,6 +16,7 @@
 #include "base/posix/eintr_wrapper.h"
 #include "base/process/kill.h"
 #include "base/third_party/dynamic_annotations/dynamic_annotations.h"
+#include "base/threading/thread_restrictions.h"
 #include "build/build_config.h"
 
 #if defined(OS_MACOSX)
@@ -366,6 +367,9 @@
 }
 
 bool Process::WaitForExitWithTimeout(TimeDelta timeout, int* exit_code) const {
+  if (!timeout.is_zero())
+    internal::AssertBaseSyncPrimitivesAllowed();
+
   // Record the event that this thread is blocking upon (for hang diagnosis).
   base::debug::ScopedProcessWaitActivity process_activity(this);
 
diff --git a/base/process/process_win.cc b/base/process/process_win.cc
index 555f575..db73559 100644
--- a/base/process/process_win.cc
+++ b/base/process/process_win.cc
@@ -8,6 +8,7 @@
 #include "base/logging.h"
 #include "base/numerics/safe_conversions.h"
 #include "base/process/kill.h"
+#include "base/threading/thread_restrictions.h"
 
 namespace {
 
@@ -151,6 +152,9 @@
 }
 
 bool Process::WaitForExitWithTimeout(TimeDelta timeout, int* exit_code) const {
+  if (!timeout.is_zero())
+    internal::AssertBaseSyncPrimitivesAllowed();
+
   // Record the event that this thread is blocking upon (for hang diagnosis).
   base::debug::ScopedProcessWaitActivity process_activity(this);
 
diff --git a/base/threading/thread_restrictions.h b/base/threading/thread_restrictions.h
index 86ccafc..5d4f574 100644
--- a/base/threading/thread_restrictions.h
+++ b/base/threading/thread_restrictions.h
@@ -96,6 +96,10 @@
 class TabManagerDelegate;
 }
 
+namespace shell_integration {
+class LaunchXdgUtilityScopedAllowBaseSyncPrimitives;
+}
+
 namespace ui {
 class WindowResizeHelperMac;
 }
@@ -118,6 +122,7 @@
 class TaskTracker;
 }
 
+class GetAppOutputScopedAllowBaseSyncPrimitives;
 class SequencedWorkerPool;
 class SimpleThread;
 class StackSamplingProfiler;
@@ -218,8 +223,10 @@
   DISALLOW_COPY_AND_ASSIGN(ScopedAllowBlockingForTesting);
 };
 
-// "Waiting on a //base sync primitive" refers to calling
-// base::WaitableEvent::*Wait* or base::ConditionVariable::*Wait*.
+// "Waiting on a //base sync primitive" refers to calling one of these methods:
+// - base::WaitableEvent::*Wait*
+// - base::ConditionVariable::*Wait*
+// - base::Process::WaitForExit*
 
 // Disallows waiting on a //base sync primitive on the current thread.
 INLINE_IF_DCHECK_IS_OFF void DisallowBaseSyncPrimitives()
@@ -228,11 +235,15 @@
 // ScopedAllowBaseSyncPrimitives(ForTesting)(OutsideBlockingScope) allow waiting
 // on a //base sync primitive within a scope where this is normally disallowed.
 //
-// Avoid using this. Instead of waiting on a WaitableEvent or a
-// ConditionVariable, put the work that should happen after the wait in a
-// callback and post that callback from where the WaitableEvent or
-// ConditionVariable would have been signaled. If something needs to be
-// scheduled after many tasks have executed, use base::BarrierClosure.
+// Avoid using this.
+//
+// Instead of waiting on a WaitableEvent or a ConditionVariable, put the work
+// that should happen after the wait in a callback and post that callback from
+// where the WaitableEvent or ConditionVariable would have been signaled. If
+// something needs to be scheduled after many tasks have executed, use
+// base::BarrierClosure.
+//
+// On Windows, join processes asynchronously using base::win::ObjectWatcher.
 
 // This can only be used in a scope where blocking is allowed.
 class BASE_EXPORT ScopedAllowBaseSyncPrimitives {
@@ -246,9 +257,11 @@
                            ScopedAllowBaseSyncPrimitivesResetsState);
   FRIEND_TEST_ALL_PREFIXES(ThreadRestrictionsTest,
                            ScopedAllowBaseSyncPrimitivesWithBlockingDisallowed);
+  friend class base::GetAppOutputScopedAllowBaseSyncPrimitives;
   friend class leveldb::LevelDBMojoProxy;
   friend class media::BlockingUrlProtocol;
   friend class net::MultiThreadedCertVerifierScopedAllowBaseSyncPrimitives;
+  friend class shell_integration::LaunchXdgUtilityScopedAllowBaseSyncPrimitives;
 
   ScopedAllowBaseSyncPrimitives() EMPTY_BODY_IF_DCHECK_IS_OFF;
   ~ScopedAllowBaseSyncPrimitives() EMPTY_BODY_IF_DCHECK_IS_OFF;
diff --git a/base/trace_event/heap_profiler.h b/base/trace_event/heap_profiler.h
index cf57524..c8deaf60 100644
--- a/base/trace_event/heap_profiler.h
+++ b/base/trace_event/heap_profiler.h
@@ -25,6 +25,11 @@
 #define TRACE_HEAP_PROFILER_API_SCOPED_TASK_EXECUTION \
   trace_event_internal::HeapProfilerScopedTaskExecutionTracker
 
+// Scoped tracker that tracks the given program counter as a native stack frame
+// in the heap profiler.
+#define TRACE_HEAP_PROFILER_API_SCOPED_WITH_PROGRAM_COUNTER \
+  trace_event_internal::HeapProfilerScopedStackFrame
+
 // A scoped ignore event used to tell heap profiler to ignore all the
 // allocations in the scope. It is useful to exclude allocations made for
 // tracing from the heap profiler dumps.
@@ -62,6 +67,31 @@
   const char* context_;
 };
 
+class HeapProfilerScopedStackFrame {
+ public:
+  inline explicit HeapProfilerScopedStackFrame(const void* program_counter)
+      : program_counter_(program_counter) {
+    using base::trace_event::AllocationContextTracker;
+    if (UNLIKELY(AllocationContextTracker::capture_mode() ==
+                 AllocationContextTracker::CaptureMode::MIXED_STACK)) {
+      AllocationContextTracker::GetInstanceForCurrentThread()
+          ->PushNativeStackFrame(program_counter_);
+    }
+  }
+
+  inline ~HeapProfilerScopedStackFrame() {
+    using base::trace_event::AllocationContextTracker;
+    if (UNLIKELY(AllocationContextTracker::capture_mode() ==
+                 AllocationContextTracker::CaptureMode::MIXED_STACK)) {
+      AllocationContextTracker::GetInstanceForCurrentThread()
+          ->PopNativeStackFrame(program_counter_);
+    }
+  }
+
+ private:
+  const void* const program_counter_;
+};
+
 class BASE_EXPORT HeapProfilerScopedIgnore {
  public:
   inline HeapProfilerScopedIgnore() {
diff --git a/base/trace_event/heap_profiler_allocation_context_tracker.cc b/base/trace_event/heap_profiler_allocation_context_tracker.cc
index ce839fd1..f1fff8b 100644
--- a/base/trace_event/heap_profiler_allocation_context_tracker.cc
+++ b/base/trace_event/heap_profiler_allocation_context_tracker.cc
@@ -10,6 +10,7 @@
 #include "base/atomicops.h"
 #include "base/debug/debugging_flags.h"
 #include "base/debug/leak_annotations.h"
+#include "base/debug/stack_trace.h"
 #include "base/threading/platform_thread.h"
 #include "base/threading/thread_local_storage.h"
 #include "base/trace_event/heap_profiler_allocation_context.h"
@@ -83,7 +84,7 @@
 
 AllocationContextTracker::AllocationContextTracker()
     : thread_name_(nullptr), ignore_scope_depth_(0) {
-  pseudo_stack_.reserve(kMaxStackDepth);
+  tracked_stack_.reserve(kMaxStackDepth);
   task_contexts_.reserve(kMaxTaskDepth);
 }
 AllocationContextTracker::~AllocationContextTracker() {}
@@ -111,10 +112,12 @@
     AllocationContextTracker::PseudoStackFrame stack_frame) {
   // Impose a limit on the height to verify that every push is popped, because
   // in practice the pseudo stack never grows higher than ~20 frames.
-  if (pseudo_stack_.size() < kMaxStackDepth)
-    pseudo_stack_.push_back(stack_frame);
-  else
+  if (tracked_stack_.size() < kMaxStackDepth) {
+    tracked_stack_.push_back(
+        StackFrame::FromTraceEventName(stack_frame.trace_event_name));
+  } else {
     NOTREACHED();
+  }
 }
 
 void AllocationContextTracker::PopPseudoStackFrame(
@@ -122,18 +125,25 @@
   // Guard for stack underflow. If tracing was started with a TRACE_EVENT in
   // scope, the frame was never pushed, so it is possible that pop is called
   // on an empty stack.
-  if (pseudo_stack_.empty())
+  if (tracked_stack_.empty())
     return;
 
-  // Assert that pushes and pops are nested correctly. This DCHECK can be
-  // hit if some TRACE_EVENT macro is unbalanced (a TRACE_EVENT_END* call
-  // without a corresponding TRACE_EVENT_BEGIN).
-  DCHECK(stack_frame == pseudo_stack_.back())
-      << "Encountered an unmatched TRACE_EVENT_END: "
-      << stack_frame.trace_event_name
-      << " vs event in stack: " << pseudo_stack_.back().trace_event_name;
+  tracked_stack_.pop_back();
+}
 
-  pseudo_stack_.pop_back();
+void AllocationContextTracker::PushNativeStackFrame(const void* pc) {
+  if (tracked_stack_.size() < kMaxStackDepth)
+    tracked_stack_.push_back(StackFrame::FromProgramCounter(pc));
+  else
+    NOTREACHED();
+}
+
+void AllocationContextTracker::PopNativeStackFrame(const void* pc) {
+  if (tracked_stack_.empty())
+    return;
+
+  DCHECK_EQ(pc, tracked_stack_.back().value);
+  tracked_stack_.pop_back();
 }
 
 void AllocationContextTracker::PushCurrentTaskContext(const char* context) {
@@ -183,18 +193,16 @@
 
   switch (mode) {
     case CaptureMode::DISABLED:
-    case CaptureMode::NO_STACK:
       {
         break;
       }
     case CaptureMode::PSEUDO_STACK:
+    case CaptureMode::MIXED_STACK:
       {
-        for (const PseudoStackFrame& stack_frame : pseudo_stack_) {
-          if (backtrace == backtrace_end) {
+        for (const StackFrame& stack_frame : tracked_stack_) {
+          if (backtrace == backtrace_end)
             break;
-          }
-          *backtrace++ =
-              StackFrame::FromTraceEventName(stack_frame.trace_event_name);
+          *backtrace++ = stack_frame;
         }
         break;
       }
@@ -243,10 +251,6 @@
   // (component name) in the heap profiler and not piggy back on the type name.
   if (!task_contexts_.empty()) {
     ctx->type_name = task_contexts_.back();
-  } else if (!pseudo_stack_.empty()) {
-    // If task context was unavailable, then the category names are taken from
-    // trace events.
-    ctx->type_name = pseudo_stack_.back().trace_event_category;
   } else {
     ctx->type_name = nullptr;
   }
diff --git a/base/trace_event/heap_profiler_allocation_context_tracker.h b/base/trace_event/heap_profiler_allocation_context_tracker.h
index 308ead5b..9bd656d 100644
--- a/base/trace_event/heap_profiler_allocation_context_tracker.h
+++ b/base/trace_event/heap_profiler_allocation_context_tracker.h
@@ -9,7 +9,6 @@
 
 #include "base/atomicops.h"
 #include "base/base_export.h"
-#include "base/debug/stack_trace.h"
 #include "base/macros.h"
 #include "base/trace_event/heap_profiler_allocation_context.h"
 
@@ -25,9 +24,10 @@
  public:
   enum class CaptureMode : int32_t {
     DISABLED,      // Don't capture anything
-    PSEUDO_STACK,  // GetContextSnapshot() returns pseudo stack trace
-    NATIVE_STACK,  // GetContextSnapshot() returns native (real) stack trace
-    NO_STACK,  // GetContextSnapshot() returns thread names and task contexts.
+    PSEUDO_STACK,  // Backtrace has trace events
+    MIXED_STACK,   // Backtrace has trace events + from
+                   // HeapProfilerScopedStackFrame
+    NATIVE_STACK,  // Backtrace has full native backtraces from stack unwinding
   };
 
   // Stack frame constructed from trace events in codebase.
@@ -79,12 +79,16 @@
       ignore_scope_depth_--;
   }
 
-  // Pushes a frame onto the thread-local pseudo stack.
+  // Pushes and pops a frame onto the thread-local pseudo stack.
+  // TODO(ssid): Change PseudoStackFrame to const char*. Only event name is
+  // used.
   void PushPseudoStackFrame(PseudoStackFrame stack_frame);
-
-  // Pops a frame from the thread-local pseudo stack.
   void PopPseudoStackFrame(PseudoStackFrame stack_frame);
 
+  // Pushes and pops a native stack frame onto thread local tracked stack.
+  void PushNativeStackFrame(const void* pc);
+  void PopNativeStackFrame(const void* pc);
+
   // Push and pop current task's context. A stack is used to support nested
   // tasks and the top of the stack will be used in allocation context.
   void PushCurrentTaskContext(const char* context);
@@ -101,8 +105,8 @@
 
   static subtle::Atomic32 capture_mode_;
 
-  // The pseudo stack where frames are |TRACE_EVENT| names.
-  std::vector<PseudoStackFrame> pseudo_stack_;
+  // The pseudo stack where frames are |TRACE_EVENT| names or inserted PCs.
+  std::vector<StackFrame> tracked_stack_;
 
   // The thread name is used as the first entry in the pseudo stack.
   const char* thread_name_;
diff --git a/base/trace_event/heap_profiler_allocation_context_tracker_unittest.cc b/base/trace_event/heap_profiler_allocation_context_tracker_unittest.cc
index 7f45f38..c26149e 100644
--- a/base/trace_event/heap_profiler_allocation_context_tracker_unittest.cc
+++ b/base/trace_event/heap_profiler_allocation_context_tracker_unittest.cc
@@ -224,22 +224,49 @@
   AssertBacktraceContainsOnlyThreadName();
 }
 
-TEST_F(AllocationContextTrackerTest, NoStackMode) {
+TEST_F(AllocationContextTrackerTest, MixedStackWithProgramCounter) {
   StackFrame t = StackFrame::FromThreadName(kThreadName);
-  StackFrame frame_t[] = {t};
-  const char kContext[] = "context";
+  StackFrame c = StackFrame::FromTraceEventName(kCupcake);
+  StackFrame f = StackFrame::FromTraceEventName(kFroyo);
+  const void* pc1 = reinterpret_cast<void*>(0x1000);
+  const void* pc2 = reinterpret_cast<void*>(0x2000);
+  StackFrame n1 = StackFrame::FromProgramCounter(pc1);
+  StackFrame n2 = StackFrame::FromProgramCounter(pc2);
+
+  StackFrame frame_c[] = {t, c};
+  StackFrame frame_cd[] = {t, c, n1};
+  StackFrame frame_e[] = {t, n2, n1};
+  StackFrame frame_ef[] = {t, n2, n1, f};
+
+  AssertBacktraceContainsOnlyThreadName();
 
   AllocationContextTracker::SetCaptureMode(
-      AllocationContextTracker::CaptureMode::NO_STACK);
-  TRACE_EVENT_BEGIN0("Testing", kCupcake);
-  AssertBacktraceEquals(frame_t);
+      AllocationContextTracker::CaptureMode::MIXED_STACK);
 
-  TRACE_HEAP_PROFILER_API_SCOPED_TASK_EXECUTION event1(kContext);
-  AllocationContext ctx;
-  ASSERT_TRUE(AllocationContextTracker::GetInstanceForCurrentThread()
-                  ->GetContextSnapshot(&ctx));
-  ASSERT_EQ(kContext, ctx.type_name);
-  AssertBacktraceEquals(frame_t);
+  TRACE_EVENT_BEGIN0("Testing", kCupcake);
+  AssertBacktraceEquals(frame_c);
+
+  {
+    TRACE_HEAP_PROFILER_API_SCOPED_WITH_PROGRAM_COUNTER e1(pc1);
+    AssertBacktraceEquals(frame_cd);
+  }
+
+  AssertBacktraceEquals(frame_c);
+  TRACE_EVENT_END0("Testing", kCupcake);
+  AssertBacktraceContainsOnlyThreadName();
+
+  {
+    TRACE_HEAP_PROFILER_API_SCOPED_WITH_PROGRAM_COUNTER e1(pc2);
+    TRACE_HEAP_PROFILER_API_SCOPED_WITH_PROGRAM_COUNTER e2(pc1);
+    AssertBacktraceEquals(frame_e);
+
+    TRACE_EVENT0("Testing", kFroyo);
+    AssertBacktraceEquals(frame_ef);
+  }
+
+  AssertBacktraceContainsOnlyThreadName();
+  AllocationContextTracker::SetCaptureMode(
+      AllocationContextTracker::CaptureMode::DISABLED);
 }
 
 TEST_F(AllocationContextTrackerTest, BacktraceTakesTop) {
@@ -303,22 +330,6 @@
     ASSERT_EQ(kContext2, ctx2.type_name);
   }
 
-  {
-    // Type should be category name of the last seen trace event.
-    TRACE_EVENT0("Testing", kCupcake);
-    AllocationContext ctx1;
-    ASSERT_TRUE(AllocationContextTracker::GetInstanceForCurrentThread()
-                    ->GetContextSnapshot(&ctx1));
-    ASSERT_EQ("Testing", std::string(ctx1.type_name));
-
-    TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("Testing"), kCupcake);
-    AllocationContext ctx2;
-    ASSERT_TRUE(AllocationContextTracker::GetInstanceForCurrentThread()
-                    ->GetContextSnapshot(&ctx2));
-    ASSERT_EQ(TRACE_DISABLED_BY_DEFAULT("Testing"),
-              std::string(ctx2.type_name));
-  }
-
   // Type should be nullptr without task event.
   AllocationContext ctx;
   ASSERT_TRUE(AllocationContextTracker::GetInstanceForCurrentThread()
diff --git a/base/trace_event/heap_profiler_event_filter.cc b/base/trace_event/heap_profiler_event_filter.cc
index 6c91c91..67125ff2 100644
--- a/base/trace_event/heap_profiler_event_filter.cc
+++ b/base/trace_event/heap_profiler_event_filter.cc
@@ -16,8 +16,11 @@
 namespace {
 
 inline bool IsPseudoStackEnabled() {
+  // Only PSEUDO_STACK and MIXED_STACK modes require trace events.
   return AllocationContextTracker::capture_mode() ==
-         AllocationContextTracker::CaptureMode::PSEUDO_STACK;
+             AllocationContextTracker::CaptureMode::PSEUDO_STACK ||
+         AllocationContextTracker::capture_mode() ==
+             AllocationContextTracker::CaptureMode::MIXED_STACK;
 }
 
 inline AllocationContextTracker* GetThreadLocalTracker() {
diff --git a/base/trace_event/memory_dump_manager.cc b/base/trace_event/memory_dump_manager.cc
index 67396c1..3b39806 100644
--- a/base/trace_event/memory_dump_manager.cc
+++ b/base/trace_event/memory_dump_manager.cc
@@ -263,7 +263,7 @@
 
     case kHeapProfilingModeBackground:
       AllocationContextTracker::SetCaptureMode(
-          AllocationContextTracker::CaptureMode::PSEUDO_STACK);
+          AllocationContextTracker::CaptureMode::MIXED_STACK);
       break;
 
     case kHeapProfilingModePseudo:
diff --git a/base/trace_event/memory_dump_manager_unittest.cc b/base/trace_event/memory_dump_manager_unittest.cc
index 6afab3a1..e2d4ee13 100644
--- a/base/trace_event/memory_dump_manager_unittest.cc
+++ b/base/trace_event/memory_dump_manager_unittest.cc
@@ -894,7 +894,7 @@
   EXPECT_EQ(mdm_->GetHeapProfilingMode(), kHeapProfilingModeInvalid);
 }
 
-TEST_F(MemoryDumpManagerTest, EnableHeapProfilingNoStack) {
+TEST_F(MemoryDumpManagerTest, EnableHeapProfilingBackground) {
   InitializeMemoryDumpManagerForInProcessTesting(true /* is_coordinator */);
   MockMemoryDumpProvider mdp1;
   MemoryDumpProvider::Options supported_options;
@@ -916,7 +916,7 @@
 
   EXPECT_TRUE(mdm_->EnableHeapProfiling(kHeapProfilingModeBackground));
   RunLoop().RunUntilIdle();
-  ASSERT_EQ(AllocationContextTracker::CaptureMode::PSEUDO_STACK,
+  ASSERT_EQ(AllocationContextTracker::CaptureMode::MIXED_STACK,
             AllocationContextTracker::capture_mode());
   EXPECT_EQ(mdm_->GetHeapProfilingMode(), kHeapProfilingModeBackground);
   EXPECT_EQ(0u, TraceLog::GetInstance()->enabled_modes());
@@ -925,7 +925,7 @@
   // Do nothing when already enabled.
   EXPECT_FALSE(mdm_->EnableHeapProfiling(kHeapProfilingModeBackground));
   EXPECT_FALSE(mdm_->EnableHeapProfiling(kHeapProfilingModePseudo));
-  ASSERT_EQ(AllocationContextTracker::CaptureMode::PSEUDO_STACK,
+  ASSERT_EQ(AllocationContextTracker::CaptureMode::MIXED_STACK,
             AllocationContextTracker::capture_mode());
   EXPECT_EQ(0u, TraceLog::GetInstance()->enabled_modes());
   EXPECT_EQ(mdm_->GetHeapProfilingMode(), kHeapProfilingModeBackground);
diff --git a/base/trace_event/trace_event.h b/base/trace_event/trace_event.h
index 0087a01..7a524af 100644
--- a/base/trace_event/trace_event.h
+++ b/base/trace_event/trace_event.h
@@ -433,21 +433,27 @@
 // location where it was posted from.
 //
 // This implementation is for when location sources are available.
+// TODO(ssid): The program counter of the current task should be added here.
 #define INTERNAL_TRACE_TASK_EXECUTION(run_function, task)                 \
   TRACE_EVENT2("toplevel", run_function, "src_file",                      \
                (task).posted_from.file_name(), "src_func",                \
                (task).posted_from.function_name());                       \
   TRACE_HEAP_PROFILER_API_SCOPED_TASK_EXECUTION INTERNAL_TRACE_EVENT_UID( \
-      task_event)((task).posted_from.file_name());
+      task_event)((task).posted_from.file_name());                        \
+  TRACE_HEAP_PROFILER_API_SCOPED_WITH_PROGRAM_COUNTER                     \
+  INTERNAL_TRACE_EVENT_UID(task_pc_event)((task).posted_from.program_counter());
 
 #else
 
 // TODO(http://crbug.com760702) remove file name and just pass the program
 // counter to the heap profiler macro.
+// TODO(ssid): The program counter of the current task should be added here.
 #define INTERNAL_TRACE_TASK_EXECUTION(run_function, task)                      \
   TRACE_EVENT1("toplevel", run_function, "src", (task).posted_from.ToString()) \
   TRACE_HEAP_PROFILER_API_SCOPED_TASK_EXECUTION INTERNAL_TRACE_EVENT_UID(      \
-      task_event)((task).posted_from.file_name());
+      task_event)((task).posted_from.file_name());                             \
+  TRACE_HEAP_PROFILER_API_SCOPED_WITH_PROGRAM_COUNTER                          \
+  INTERNAL_TRACE_EVENT_UID(task_pc_event)((task).posted_from.program_counter());
 
 #endif
 
diff --git a/base/win/com_init_util_unittest.cc b/base/win/com_init_util_unittest.cc
index f5387d0..fb897dd 100644
--- a/base/win/com_init_util_unittest.cc
+++ b/base/win/com_init_util_unittest.cc
@@ -20,21 +20,21 @@
   // status will be updated. This covers that case.
   {
     ScopedCOMInitializer com_initializer;
-    ASSERT_TRUE(com_initializer.succeeded());
+    ASSERT_TRUE(com_initializer.Succeeded());
   }
   EXPECT_DCHECK_DEATH(AssertComInitialized());
 }
 
 TEST(ComInitUtil, AssertSTAInitialized) {
   ScopedCOMInitializer com_initializer;
-  ASSERT_TRUE(com_initializer.succeeded());
+  ASSERT_TRUE(com_initializer.Succeeded());
 
   AssertComInitialized();
 }
 
 TEST(ComInitUtil, AssertMTAInitialized) {
   ScopedCOMInitializer com_initializer(ScopedCOMInitializer::kMTA);
-  ASSERT_TRUE(com_initializer.succeeded());
+  ASSERT_TRUE(com_initializer.Succeeded());
 
   AssertComInitialized();
 }
@@ -50,7 +50,7 @@
   // status will be updated. This covers that case.
   {
     ScopedCOMInitializer com_initializer;
-    ASSERT_TRUE(com_initializer.succeeded());
+    ASSERT_TRUE(com_initializer.Succeeded());
   }
   AssertComApartmentType(ComApartmentType::NONE);
   EXPECT_DCHECK_DEATH(AssertComApartmentType(ComApartmentType::STA));
diff --git a/base/win/scoped_com_initializer.cc b/base/win/scoped_com_initializer.cc
new file mode 100644
index 0000000..73e1b5c
--- /dev/null
+++ b/base/win/scoped_com_initializer.cc
@@ -0,0 +1,37 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "base/win/scoped_com_initializer.h"
+
+#include "base/logging.h"
+
+namespace base {
+namespace win {
+
+ScopedCOMInitializer::ScopedCOMInitializer() {
+  Initialize(COINIT_APARTMENTTHREADED);
+}
+
+ScopedCOMInitializer::ScopedCOMInitializer(SelectMTA mta) {
+  Initialize(COINIT_MULTITHREADED);
+}
+
+ScopedCOMInitializer::~ScopedCOMInitializer() {
+  DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
+  if (Succeeded())
+    CoUninitialize();
+}
+
+bool ScopedCOMInitializer::Succeeded() const {
+  return SUCCEEDED(hr_);
+}
+
+void ScopedCOMInitializer::Initialize(COINIT init) {
+  DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
+  hr_ = CoInitializeEx(NULL, init);
+  DCHECK_NE(RPC_E_CHANGED_MODE, hr_) << "Invalid COM thread model change";
+}
+
+}  // namespace win
+}  // namespace base
diff --git a/base/win/scoped_com_initializer.h b/base/win/scoped_com_initializer.h
index 70deba490..3bb5795 100644
--- a/base/win/scoped_com_initializer.h
+++ b/base/win/scoped_com_initializer.h
@@ -7,10 +7,10 @@
 
 #include <objbase.h>
 
-#include "base/logging.h"
+#include "base/base_export.h"
 #include "base/macros.h"
 #include "base/threading/thread_checker.h"
-#include "build/build_config.h"
+#include "base/win/scoped_windows_thread_environment.h"
 
 namespace base {
 namespace win {
@@ -22,35 +22,24 @@
 // similar lifetime as the thread itself.  You should not be using this in
 // random utility functions that make COM calls -- instead ensure these
 // functions are running on a COM-supporting thread!
-class ScopedCOMInitializer {
+class BASE_EXPORT ScopedCOMInitializer : public ScopedWindowsThreadEnvironment {
  public:
   // Enum value provided to initialize the thread as an MTA instead of STA.
   enum SelectMTA { kMTA };
 
   // Constructor for STA initialization.
-  ScopedCOMInitializer() {
-    Initialize(COINIT_APARTMENTTHREADED);
-  }
+  ScopedCOMInitializer();
 
   // Constructor for MTA initialization.
-  explicit ScopedCOMInitializer(SelectMTA mta) {
-    Initialize(COINIT_MULTITHREADED);
-  }
+  explicit ScopedCOMInitializer(SelectMTA mta);
 
-  ~ScopedCOMInitializer() {
-    DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
-    if (succeeded())
-      CoUninitialize();
-  }
+  ~ScopedCOMInitializer() override;
 
-  bool succeeded() const { return SUCCEEDED(hr_); }
+  // ScopedWindowsThreadEnvironment:
+  bool Succeeded() const override;
 
  private:
-  void Initialize(COINIT init) {
-    DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
-    hr_ = CoInitializeEx(NULL, init);
-    DCHECK_NE(RPC_E_CHANGED_MODE, hr_) << "Invalid COM thread model change";
-  }
+  void Initialize(COINIT init);
 
   HRESULT hr_;
   THREAD_CHECKER(thread_checker_);
diff --git a/base/win/scoped_windows_thread_environment.h b/base/win/scoped_windows_thread_environment.h
new file mode 100644
index 0000000..51f2a0d
--- /dev/null
+++ b/base/win/scoped_windows_thread_environment.h
@@ -0,0 +1,28 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef BASE_WIN_SCOPED_WINDOWS_THREAD_ENVIRONMENT_H_
+#define BASE_WIN_SCOPED_WINDOWS_THREAD_ENVIRONMENT_H_
+
+#include "base/macros.h"
+
+namespace base {
+namespace win {
+
+// Serves as a root class for ScopedCOMInitializer and ScopedWinrtInitializer.
+class ScopedWindowsThreadEnvironment {
+ public:
+  ScopedWindowsThreadEnvironment() {}
+  virtual ~ScopedWindowsThreadEnvironment() {}
+
+  virtual bool Succeeded() const = 0;
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(ScopedWindowsThreadEnvironment);
+};
+
+}  // namespace win
+}  // namespace base
+
+#endif  // BASE_WIN_SCOPED_WINDOWS_THREAD_ENVIRONMENT_H_
diff --git a/base/win/scoped_winrt_initializer.cc b/base/win/scoped_winrt_initializer.cc
new file mode 100644
index 0000000..9466edb4
--- /dev/null
+++ b/base/win/scoped_winrt_initializer.cc
@@ -0,0 +1,36 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "base/win/scoped_winrt_initializer.h"
+
+#include "base/logging.h"
+#include "base/win/com_init_util.h"
+#include "base/win/core_winrt_util.h"
+#include "base/win/windows_version.h"
+
+namespace base {
+namespace win {
+
+ScopedWinrtInitializer::ScopedWinrtInitializer()
+    : hr_(base::win::RoInitialize(RO_INIT_MULTITHREADED)) {
+  DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
+  DCHECK_GE(GetVersion(), VERSION_WIN8);
+#if DCHECK_IS_ON()
+  if (SUCCEEDED(hr_))
+    AssertComApartmentType(ComApartmentType::MTA);
+#endif
+}
+
+ScopedWinrtInitializer::~ScopedWinrtInitializer() {
+  DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
+  if (SUCCEEDED(hr_))
+    base::win::RoUninitialize();
+}
+
+bool ScopedWinrtInitializer::Succeeded() const {
+  return SUCCEEDED(hr_);
+}
+
+}  // namespace win
+}  // namespace base
diff --git a/base/win/scoped_winrt_initializer.h b/base/win/scoped_winrt_initializer.h
new file mode 100644
index 0000000..7c76515
--- /dev/null
+++ b/base/win/scoped_winrt_initializer.h
@@ -0,0 +1,48 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef BASE_WIN_SCOPED_WINRT_INITIALIZER_H_
+#define BASE_WIN_SCOPED_WINRT_INITIALIZER_H_
+
+#include <objbase.h>
+
+#include "base/base_export.h"
+#include "base/threading/thread_checker.h"
+#include "base/win/scoped_windows_thread_environment.h"
+
+namespace base {
+namespace win {
+
+// Initializes the Windows Runtime in the constructor and uninitalizes the
+// Windows Runtime in the destructor. As a side effect, COM is also initialized
+// as an MTA in the constructor and correspondingly uninitialized in the
+// destructor.
+//
+// Generally, you should only use this on Windows 8 or above. It is redundant
+// to use ScopedComInitializer in conjunction with ScopedWinrtInitializer.
+//
+// WARNING: This should only be used once per thread, ideally scoped to a
+// similar lifetime as the thread itself. You should not be using this in random
+// utility functions that make Windows Runtime calls -- instead ensure these
+// functions are running on a Windows Runtime supporting thread!
+class BASE_EXPORT ScopedWinrtInitializer
+    : public ScopedWindowsThreadEnvironment {
+ public:
+  ScopedWinrtInitializer();
+  ~ScopedWinrtInitializer() override;
+
+  // ScopedWindowsThreadEnvironment:
+  bool Succeeded() const override;
+
+ private:
+  const HRESULT hr_;
+  THREAD_CHECKER(thread_checker_);
+
+  DISALLOW_COPY_AND_ASSIGN(ScopedWinrtInitializer);
+};
+
+}  // namespace win
+}  // namespace base
+
+#endif  // BASE_WIN_SCOPED_WINRT_INITIALIZER_H_
diff --git a/base/win/scoped_winrt_initializer_unittest.cc b/base/win/scoped_winrt_initializer_unittest.cc
new file mode 100644
index 0000000..abab1132
--- /dev/null
+++ b/base/win/scoped_winrt_initializer_unittest.cc
@@ -0,0 +1,37 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "base/win/scoped_winrt_initializer.h"
+
+#include "base/test/gtest_util.h"
+#include "base/win/com_init_util.h"
+#include "base/win/scoped_com_initializer.h"
+#include "base/win/windows_version.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace base {
+namespace win {
+
+TEST(ScopedWinrtInitializer, BasicFunctionality) {
+  if (GetVersion() < VERSION_WIN8)
+    return;
+
+  AssertComApartmentType(ComApartmentType::NONE);
+  {
+    ScopedWinrtInitializer scoped_winrt_initializer;
+    AssertComApartmentType(ComApartmentType::MTA);
+  }
+  AssertComApartmentType(ComApartmentType::NONE);
+}
+
+TEST(ScopedWinrtInitializer, VersionCheck) {
+  if (GetVersion() >= VERSION_WIN8)
+    return;
+
+  // ScopedWinrtInitializer is unsupported on versions prior to Windows 8.
+  EXPECT_DCHECK_DEATH({ ScopedWinrtInitializer scoped_winrt_initializer; });
+}
+
+}  // namespace win
+}  // namespace base
diff --git a/build/android/gradle/generate_gradle.py b/build/android/gradle/generate_gradle.py
index 899587b..b9fc86a 100755
--- a/build/android/gradle/generate_gradle.py
+++ b/build/android/gradle/generate_gradle.py
@@ -782,15 +782,14 @@
   logging.warning('Building .build_config files...')
   _RunNinja(output_dir, [e.NinjaBuildConfigTarget() for e in main_entries])
 
-  # There are many unused libraries, so restrict to those that are actually used
-  # when using --all.
-  if args.all:
-    main_entries = [e for e in main_entries if (
-        e.GetType() == 'android_apk' or
-        e.GnTarget().endswith('_test_apk__apk') or
-        e.GnTarget().endswith('_junit_tests__java_binary'))]
-
   if args.split_projects:
+    # There are many unused libraries, so restrict to those that are actually
+    # used when using --all with individual project entries.
+    if args.all:
+      main_entries = [e for e in main_entries if (
+          e.GetType() == 'android_apk' or
+          e.GnTarget().endswith('_test_apk__apk') or
+          e.GnTarget().endswith('_junit_tests__java_binary'))]
     main_entries = _FindAllProjectEntries(main_entries)
     logging.info('Found %d dependent build_config targets.', len(main_entries))
 
diff --git a/build/android/incremental_install/generate_android_manifest.py b/build/android/incremental_install/generate_android_manifest.py
index a267716..843ab51 100755
--- a/build/android/incremental_install/generate_android_manifest.py
+++ b/build/android/incremental_install/generate_android_manifest.py
@@ -11,7 +11,12 @@
 
 import argparse
 import os
+import re
+import shutil
+import subprocess
 import sys
+import tempfile
+import zipfile
 from xml.etree import ElementTree
 
 sys.path.append(os.path.join(os.path.dirname(__file__), os.path.pardir, 'gyp'))
@@ -39,7 +44,6 @@
 
 def _ParseArgs():
   parser = argparse.ArgumentParser()
-  build_utils.AddDepfileOption(parser)
   parser.add_argument('--src-manifest',
                       help='The main manifest of the app',
                       required=True)
@@ -50,7 +54,16 @@
                       help='Changes all android:isolatedProcess to false. '
                            'This is required on Android M+',
                       action='store_true')
-  return parser.parse_args()
+  parser.add_argument('--out-apk', help='Path to output .ap_ file')
+  parser.add_argument('--in-apk', help='Path to non-incremental .ap_ file')
+  parser.add_argument('--aapt-path', help='Path to the Android aapt tool')
+  parser.add_argument('--android-sdk-jar', help='Path to the Android SDK jar.')
+
+  ret = parser.parse_args()
+  if ret.out_apk and not (ret.in_apk and ret.aapt_path and ret.android_sdk_jar):
+    parser.error(
+        '--out-apk requires --in-apk, --aapt-path, and --android-sdk-jar.')
+  return ret
 
 
 def _CreateMetaData(parent, name, value):
@@ -102,6 +115,13 @@
   return ElementTree.tostring(doc, encoding='UTF-8')
 
 
+def _ExtractVersionFromApk(aapt_path, apk_path):
+  output = subprocess.check_output([aapt_path, 'dump', 'badging', apk_path])
+  version_code = re.search(r"versionCode='(.*?)'", output).group(1)
+  version_name = re.search(r"versionName='(.*?)'", output).group(1)
+  return version_code, version_name,
+
+
 def main():
   options = _ParseArgs()
   with open(options.src_manifest) as f:
@@ -111,9 +131,19 @@
   with open(options.out_manifest, 'w') as f:
     f.write(new_manifest_data)
 
-  if options.depfile:
-    deps = [options.src_manifest]
-    build_utils.WriteDepfile(options.depfile, options.out_manifest, deps)
+  if options.out_apk:
+    version_code, version_name = _ExtractVersionFromApk(
+        options.aapt_path, options.in_apk)
+    with tempfile.NamedTemporaryFile() as f:
+      cmd = [options.aapt_path, 'package', '-f', '-F', f.name,
+             '-M', options.out_manifest, '-I', options.android_sdk_jar,
+             '-I', options.in_apk, '--replace-version',
+             '--version-code', version_code, '--version-name', version_name]
+      subprocess.check_call(cmd)
+      with zipfile.ZipFile(f.name, 'a') as z:
+        build_utils.MergeZips(
+            z, [options.in_apk], exclude_patterns=['AndroidManifest.xml'])
+      shutil.copyfile(f.name, options.out_apk)
 
 
 if __name__ == '__main__':
diff --git a/build/config/android/abi.gni b/build/config/android/abi.gni
new file mode 100644
index 0000000..24bef19
--- /dev/null
+++ b/build/config/android/abi.gni
@@ -0,0 +1,71 @@
+# Copyright 2017 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+# Logic separated out from config.gni so that it can be used by compiler.gni
+# without introducing a circular dependency.
+
+assert(is_android)
+
+declare_args() {
+  # Adds intrumentation to each function. Writes a file with the order that
+  # functions are called at startup.
+  use_order_profiling = false
+
+  # Use a lightweight variant of order profiling. Does nothing without
+  # use_order_profiling set above. Will either replace use_order_profiling
+  # or be removed.
+  use_lightweight_order_profiling = false
+
+  # Builds secondary abi for APKs, supports build 32-bit arch as secondary
+  # abi in 64-bit Monochrome and WebView.
+  build_apk_secondary_abi = true
+}
+
+if (current_cpu == "x86") {
+  android_app_abi = "x86"
+} else if (current_cpu == "arm") {
+  import("//build/config/arm.gni")
+  if (arm_version < 7) {
+    android_app_abi = "armeabi"
+  } else {
+    android_app_abi = "armeabi-v7a"
+  }
+} else if (current_cpu == "mipsel") {
+  android_app_abi = "mips"
+} else if (current_cpu == "x64") {
+  android_app_abi = "x86_64"
+} else if (current_cpu == "arm64") {
+  android_app_abi = "arm64-v8a"
+} else if (current_cpu == "mips64el") {
+  android_app_abi = "mips64"
+} else {
+  assert(false, "Unknown Android ABI: " + current_cpu)
+}
+
+if (target_cpu == "arm64" || target_cpu == "x64" || target_cpu == "mips64el") {
+  android_64bit_target_cpu = true
+} else if (target_cpu == "arm" || target_cpu == "x86" ||
+           target_cpu == "mipsel") {
+  android_64bit_target_cpu = false
+} else {
+  assert(false, "Unknown target CPU: $target_cpu")
+}
+
+# Intentionally do not define android_app_secondary_abi_cpu and
+# android_app_secondary_abi for 32-bit target_cpu, since they are not used.
+if (target_cpu == "arm64") {
+  android_secondary_abi_cpu = "arm"
+  android_app_secondary_abi = "armeabi-v7a"
+} else if (target_cpu == "x64") {
+  android_secondary_abi_cpu = "x86"
+  android_app_secondary_abi = "x86"
+} else if (target_cpu == "mips64el") {
+  android_secondary_abi_cpu = "mipsel"
+  android_app_secondary_abi = "mips"
+}
+
+if (defined(android_secondary_abi_cpu)) {
+  android_secondary_abi_toolchain =
+      "//build/toolchain/android:android_clang_${android_secondary_abi_cpu}"
+}
diff --git a/build/config/android/config.gni b/build/config/android/config.gni
index 12d1661..f38bd02 100644
--- a/build/config/android/config.gni
+++ b/build/config/android/config.gni
@@ -6,6 +6,7 @@
 
 if (is_android) {
   import("//build_overrides/build.gni")
+  import("abi.gni")
 
   has_chrome_android_internal =
       exec_script("//build/dir_exists.py",
@@ -158,19 +159,6 @@
     # Speeds up incremental compiles by compiling only changed files.
     enable_incremental_javac = false
 
-    # Adds intrumentation to each function. Writes a file with the order that
-    # functions are called at startup.
-    use_order_profiling = false
-
-    # Use a ligthweight variant of order profiling. Does nothing without
-    # use_order_profiling set above. Will either replace use_order_profiling
-    # or be removed.
-    use_lightweight_order_profiling = false
-
-    # Builds secondary abi for APKs, supports build 32-bit arch as secondary
-    # abi in 64-bit Monochrome and WebView.
-    build_apk_secondary_abi = true
-
     # Build incremental targets whenever possible.
     # Ex. with this arg set to true, the chrome_public_apk target result in
     # chrome_public_apk_incremental being built.
@@ -324,60 +312,9 @@
 
   android_libcpp_root = "$android_ndk_root/sources/cxx-stl/llvm-libc++"
 
-  # ABI ------------------------------------------------------------------------
-
-  if (current_cpu == "x86") {
-    android_app_abi = "x86"
-  } else if (current_cpu == "arm") {
-    import("//build/config/arm.gni")
-    if (arm_version < 7) {
-      android_app_abi = "armeabi"
-    } else {
-      android_app_abi = "armeabi-v7a"
-    }
-  } else if (current_cpu == "mipsel") {
-    android_app_abi = "mips"
-  } else if (current_cpu == "x64") {
-    android_app_abi = "x86_64"
-  } else if (current_cpu == "arm64") {
-    android_app_abi = "arm64-v8a"
-  } else if (current_cpu == "mips64el") {
-    android_app_abi = "mips64"
-  } else {
-    assert(false, "Unknown Android ABI: " + current_cpu)
-  }
-
   if (android_libcpp_lib_dir == "") {
     android_libcpp_lib_dir = "${android_libcpp_root}/libs/${android_app_abi}"
   }
-
-  # Secondary ABI -------------------------------------------------------------
-  if (target_cpu == "arm64" || target_cpu == "x64" || target_cpu == "mips64el") {
-    android_64bit_target_cpu = true
-  } else if (target_cpu == "arm" || target_cpu == "x86" ||
-             target_cpu == "mipsel") {
-    android_64bit_target_cpu = false
-  } else {
-    assert(false, "Unknown target CPU: $target_cpu")
-  }
-
-  # Intentionally do not define android_app_secondary_abi_cpu and
-  # android_app_secondary_abi for 32-bit target_cpu, since they are not used.
-  if (target_cpu == "arm64") {
-    android_secondary_abi_cpu = "arm"
-    android_app_secondary_abi = "armeabi-v7a"
-  } else if (target_cpu == "x64") {
-    android_secondary_abi_cpu = "x86"
-    android_app_secondary_abi = "x86"
-  } else if (target_cpu == "mips64el") {
-    android_secondary_abi_cpu = "mipsel"
-    android_app_secondary_abi = "mips"
-  }
-
-  if (defined(android_secondary_abi_cpu)) {
-    android_secondary_abi_toolchain =
-        "//build/toolchain/android:android_clang_${android_secondary_abi_cpu}"
-  }
 }
 
 declare_args() {
diff --git a/build/config/android/internal_rules.gni b/build/config/android/internal_rules.gni
index fe92b30..2172d48e 100644
--- a/build/config/android/internal_rules.gni
+++ b/build/config/android/internal_rules.gni
@@ -1408,6 +1408,315 @@
     }
   }
 
+  # Runs process_resources.py
+  template("process_resources") {
+    action(target_name) {
+      set_sources_assignment_filter([])
+      forward_variables_from(invoker,
+                             [
+                               "deps",
+                               "testonly",
+                               "visibility",
+                             ])
+      script = "//build/android/gyp/process_resources.py"
+
+      depfile = "$target_gen_dir/$target_name.d"
+      outputs = [
+        invoker.zip_path,
+        invoker.r_text_out_path,
+      ]
+
+      _all_resource_dirs = []
+      sources = []
+
+      if (defined(invoker.resource_dirs)) {
+        _all_resource_dirs += invoker.resource_dirs
+
+        # Speed up "gn gen" by short-circuiting the empty directory.
+        if (invoker.resource_dirs != [ "//build/android/empty" ] &&
+            invoker.resource_dirs != []) {
+          _sources_build_rel =
+              exec_script("//build/android/gyp/find.py",
+                          rebase_path(invoker.resource_dirs, root_build_dir),
+                          "list lines")
+          sources += rebase_path(_sources_build_rel, ".", root_build_dir)
+        }
+      }
+
+      if (defined(invoker.generated_resource_dirs)) {
+        assert(defined(invoker.generated_resource_files))
+        _all_resource_dirs += invoker.generated_resource_dirs
+        sources += invoker.generated_resource_files
+      }
+
+      _android_aapt_path = android_default_aapt_path
+
+      _android_sdk_jar = android_sdk_jar
+      if (defined(invoker.alternative_android_sdk_jar)) {
+        _android_sdk_jar = invoker.alternative_android_sdk_jar
+      }
+
+      inputs = [
+        invoker.build_config,
+        invoker.android_manifest,
+        _android_aapt_path,
+        _android_sdk_jar,
+      ]
+
+      _rebased_all_resource_dirs =
+          rebase_path(_all_resource_dirs, root_build_dir)
+      _rebased_build_config = rebase_path(invoker.build_config, root_build_dir)
+
+      args = [
+        "--depfile",
+        rebase_path(depfile, root_build_dir),
+        "--android-sdk-jar",
+        rebase_path(_android_sdk_jar, root_build_dir),
+        "--aapt-path",
+        rebase_path(_android_aapt_path, root_build_dir),
+        "--android-manifest",
+        rebase_path(invoker.android_manifest, root_build_dir),
+        "--resource-dirs=$_rebased_all_resource_dirs",
+        "--resource-zip-out",
+        rebase_path(invoker.zip_path, root_build_dir),
+        "--r-text-out",
+        rebase_path(invoker.r_text_out_path, root_build_dir),
+        "--dependencies-res-zips=@FileArg($_rebased_build_config:resources:dependency_zips)",
+        "--extra-res-packages=@FileArg($_rebased_build_config:resources:extra_package_names)",
+        "--extra-r-text-files=@FileArg($_rebased_build_config:resources:extra_r_text_files)",
+      ]
+      if (defined(invoker.srcjar_path)) {
+        outputs += [ invoker.srcjar_path ]
+        args += [
+          "--srcjar-out",
+          rebase_path(invoker.srcjar_path, root_build_dir),
+        ]
+      }
+
+      if (defined(invoker.r_text_in_path)) {
+        _r_text_in_path = invoker.r_text_in_path
+        inputs += [ _r_text_in_path ]
+        args += [
+          "--r-text-in",
+          rebase_path(_r_text_in_path, root_build_dir),
+        ]
+      }
+
+      if (!defined(invoker.generate_constant_ids) ||
+          !invoker.generate_constant_ids) {
+        args += [ "--non-constant-id" ]
+      }
+
+      if (defined(invoker.custom_package)) {
+        args += [
+          "--custom-package",
+          invoker.custom_package,
+        ]
+      }
+
+      if (defined(invoker.v14_skip) && invoker.v14_skip) {
+        args += [ "--v14-skip" ]
+      }
+
+      if (defined(invoker.shared_resources) && invoker.shared_resources) {
+        args += [ "--shared-resources" ]
+      }
+
+      if (defined(invoker.app_as_shared_lib) && invoker.app_as_shared_lib) {
+        args += [ "--app-as-shared-lib" ]
+      }
+
+      if (defined(invoker.include_all_resources) &&
+          invoker.include_all_resources) {
+        args += [ "--include-all-resources" ]
+      }
+
+      if (defined(invoker.all_resources_zip_path)) {
+        _all_resources_zip = invoker.all_resources_zip_path
+        outputs += [ _all_resources_zip ]
+        args += [
+          "--all-resources-zip-out",
+          rebase_path(_all_resources_zip, root_build_dir),
+        ]
+      }
+
+      if (defined(invoker.proguard_file)) {
+        outputs += [ invoker.proguard_file ]
+        args += [
+          "--proguard-file",
+          rebase_path(invoker.proguard_file, root_build_dir),
+        ]
+      }
+
+      if (defined(invoker.proguard_file_main_dex)) {
+        outputs += [ invoker.proguard_file_main_dex ]
+        args += [
+          "--proguard-file-main-dex",
+          rebase_path(invoker.proguard_file_main_dex, root_build_dir),
+        ]
+      }
+
+      if (defined(invoker.args)) {
+        args += invoker.args
+      }
+    }
+  }
+
+  # Runs aapt to create an .ap_ file, which is a zip file containing
+  # compiled xml and a resources.arsc file.
+  #
+  # Required Variables:
+  #   output: Path to .ap_ to create.
+  #   android_manifest: The AndroidManifest.xml for the apk.
+  #   version_code: The verison code to use.
+  #   version_name: The verison name to use.
+  # Optional Variables:
+  #   aapt_locale_whitelist: If set, all locales not in this list will be
+  #     stripped from resources.arsc.
+  #   alternative_android_sdk_jar: An alternative android sdk jar.
+  #   app_as_shared_lib: Enables --app-as-shared-lib.
+  #   exclude_xxxhdpi: Causes all drawable-xxxhdpi images to be excluded
+  #     (mipmaps are still included).
+  #   png_to_webp: If true, pngs (with the exception of 9-patch) are
+  #     converted to webp.
+  #   post_process_script: Script to call to post-process the .ap_.
+  #   resources_zip: Resource .zip file created by process_resources to package.
+  #   shared_resources: Enables --shared-lib.
+  #   split_densities: A list of densities to create apk splits for.
+  #   split_languages: A list of language codes to create apk splits for.
+  #   xxxhdpi_whitelist: A list of globs used when exclude_xxxhdpi=true. Files
+  #     that match this whitelist will still be included.
+  template("package_resources") {
+    _post_process = defined(invoker.post_process_script)
+    _package_resources_target_name = target_name
+    _resource_packaged_apk_path = invoker.output
+    if (_post_process) {
+      _package_resources_target_name = "${target_name}__intermediate"
+      _resource_packaged_apk_path =
+          get_path_info(_resource_packaged_apk_path, "dir") + "/" +
+          get_path_info(_resource_packaged_apk_path, "name") +
+          ".intermediate.ap_"
+    }
+
+    action(_package_resources_target_name) {
+      forward_variables_from(invoker,
+                             [
+                               "deps",
+                               "testonly",
+                               "visibility",
+                             ])
+
+      script = "//build/android/gyp/package_resources.py"
+      depfile = "${target_gen_dir}/${target_name}.d"
+      outputs = [
+        _resource_packaged_apk_path,
+      ]
+
+      _android_sdk_jar = android_sdk_jar
+      if (defined(invoker.alternative_android_sdk_jar)) {
+        _android_sdk_jar = invoker.alternative_android_sdk_jar
+      }
+
+      inputs = [
+        android_default_aapt_path,
+        _android_sdk_jar,
+        invoker.android_manifest,
+      ]
+
+      args = [
+        "--depfile",
+        rebase_path(depfile, root_build_dir),
+        "--android-sdk-jar",
+        rebase_path(_android_sdk_jar, root_build_dir),
+        "--aapt-path",
+        rebase_path(android_default_aapt_path, root_build_dir),
+        "--android-manifest",
+        rebase_path(invoker.android_manifest, root_build_dir),
+        "--version-code",
+        invoker.version_code,
+        "--version-name",
+        invoker.version_name,
+        "--apk-path",
+        rebase_path(_resource_packaged_apk_path, root_build_dir),
+      ]
+
+      # Useful to have android:debuggable in the manifest even for Release
+      # builds. Just omit it for officai
+      if (debuggable_apks) {
+        args += [ "--debuggable" ]
+      }
+
+      if (defined(invoker.resources_zip)) {
+        inputs += [ invoker.resources_zip ]
+        args += [
+          "--resource-zips",
+          rebase_path(invoker.resources_zip, root_build_dir),
+        ]
+      }
+      if (defined(invoker.shared_resources) && invoker.shared_resources) {
+        args += [ "--shared-resources" ]
+      }
+      if (defined(invoker.app_as_shared_lib) && invoker.app_as_shared_lib) {
+        args += [ "--app-as-shared-lib" ]
+      }
+      if (defined(invoker.split_densities)) {
+        args += [ "--create-density-splits" ]
+        foreach(_density, invoker.split_densities) {
+          outputs += [ "${invoker.output}_${_density}" ]
+        }
+      }
+      if (defined(invoker.split_languages)) {
+        args += [ "--language-splits=${invoker.split_languages}" ]
+        foreach(_language, invoker.split_languages) {
+          outputs += [ "${invoker.output}_${_language}" ]
+        }
+      }
+      if (defined(invoker.aapt_locale_whitelist)) {
+        args += [ "--locale-whitelist=${invoker.aapt_locale_whitelist}" ]
+      }
+      if (defined(invoker.png_to_webp) && invoker.png_to_webp) {
+        _webp_target = "//third_party/libwebp:cwebp($host_toolchain)"
+        deps += [ _webp_target ]
+        args += [
+          "--png-to-webp",
+          "--webp-binary",
+          rebase_path(get_label_info(_webp_target, "root_out_dir") + "/cwebp",
+                      root_build_dir),
+        ]
+      }
+      if (defined(invoker.exclude_xxxhdpi) && invoker.exclude_xxxhdpi) {
+        args += [ "--exclude-xxxhdpi" ]
+        if (defined(invoker.xxxhdpi_whitelist)) {
+          args += [ "--xxxhdpi-whitelist=${invoker.xxxhdpi_whitelist}" ]
+        }
+      }
+    }
+
+    if (_post_process) {
+      action(target_name) {
+        depfile = "${target_gen_dir}/${target_name}.d"
+        script = invoker.post_process_script
+        args = [
+          "--depfile",
+          rebase_path(depfile, root_build_dir),
+          "--apk-path",
+          rebase_path(_resource_packaged_apk_path, root_build_dir),
+          "--output",
+          rebase_path(invoker.output, root_build_dir),
+        ]
+        inputs = [
+          _resource_packaged_apk_path,
+        ]
+        outputs = [
+          invoker.output,
+        ]
+        public_deps = [
+          ":${_package_resources_target_name}",
+        ]
+      }
+    }
+  }
+
   # Creates an unsigned .apk.
   #
   # Variables
@@ -1662,221 +1971,82 @@
       _split_languages = invoker.language_splits
     }
 
-    template("package_resources_helper") {
-      _resource_packaged_apk_path = invoker.resource_packaged_apk_path
-      _package_resources_target = target_name
-      _post_process = defined(invoker.post_process_package_resources_script)
-      if (_post_process) {
-        _package_resources_target = "${_package_resources_target}__intermediate"
-        _post_processed_resource_packaged_apk_path = _resource_packaged_apk_path
-        _resource_packaged_apk_path =
-            get_path_info(_resource_packaged_apk_path, "dir") + "/" +
-            get_path_info(_resource_packaged_apk_path, "name") +
-            ".intermediate.ap_"
-      }
-
-      action(_package_resources_target) {
-        deps = invoker.deps
-
-        script = "//build/android/gyp/package_resources.py"
-        depfile = "${target_gen_dir}/${target_name}.d"
-        outputs = [
-          _resource_packaged_apk_path,
-        ]
-
-        _android_aapt_path = android_default_aapt_path
-        if (defined(invoker.android_aapt_path)) {
-          _android_aapt_path = invoker.android_aapt_path
-        }
-
-        _android_sdk_jar = android_sdk_jar
-        if (defined(invoker.alternative_android_sdk_jar)) {
-          _android_sdk_jar = invoker.alternative_android_sdk_jar
-        }
-
-        inputs = [
-          _android_aapt_path,
-          _android_sdk_jar,
-          invoker.android_manifest,
-        ]
-        if (defined(_resources_zip)) {
-          inputs += [ _resources_zip ]
-        }
-
-        args = [
-          "--depfile",
-          rebase_path(depfile, root_build_dir),
-          "--android-sdk-jar",
-          rebase_path(_android_sdk_jar, root_build_dir),
-          "--aapt-path",
-          rebase_path(_android_aapt_path, root_build_dir),
-          "--android-manifest",
-          rebase_path(invoker.android_manifest, root_build_dir),
-          "--version-code",
-          _version_code,
-          "--version-name",
-          _version_name,
-          "--apk-path",
-          rebase_path(_resource_packaged_apk_path, root_build_dir),
-        ]
-
-        # Useful to have android:debuggable in the manifest even for Release
-        # builds. Just omit it for officai
-        if (debuggable_apks) {
-          args += [ "--debuggable" ]
-        }
-
-        if (defined(_resources_zip)) {
-          args += [
-            "--resource-zips",
-            rebase_path(_resources_zip, root_build_dir),
-          ]
-        }
-        if (_shared_resources) {
-          args += [ "--shared-resources" ]
-        }
-        if (_app_as_shared_lib) {
-          args += [ "--app-as-shared-lib" ]
-        }
-        if (_split_densities != []) {
-          args += [ "--create-density-splits" ]
-          foreach(_density, _split_densities) {
-            outputs += [ "${invoker.resource_packaged_apk_path}_${_density}" ]
-          }
-        }
-        if (_split_languages != []) {
-          args += [ "--language-splits=$_split_languages" ]
-          foreach(_language, _split_languages) {
-            outputs += [ "${invoker.resource_packaged_apk_path}_${_language}" ]
-          }
-        }
-        if (defined(invoker.aapt_locale_whitelist)) {
-          args += [ "--locale-whitelist=${invoker.aapt_locale_whitelist}" ]
-        }
-        if (defined(invoker.extensions_to_not_compress)) {
-          args += [
-            "--no-compress",
-            invoker.extensions_to_not_compress,
-          ]
-        }
-        if (defined(invoker.png_to_webp) && invoker.png_to_webp) {
-          _webp_target = "//third_party/libwebp:cwebp($host_toolchain)"
-          deps += [ _webp_target ]
-          args += [
-            "--png-to-webp",
-            "--webp-binary",
-            rebase_path(get_label_info(_webp_target, "root_out_dir") + "/cwebp",
-                        root_build_dir),
-          ]
-        }
-        if (defined(invoker.exclude_xxxhdpi) && invoker.exclude_xxxhdpi) {
-          args += [ "--exclude-xxxhdpi" ]
-          if (defined(invoker.xxxhdpi_whitelist)) {
-            args += [ "--xxxhdpi-whitelist=${invoker.xxxhdpi_whitelist}" ]
-          }
-        }
-      }
-
-      if (_post_process) {
-        action(target_name) {
-          depfile = "${target_gen_dir}/${target_name}.d"
-          script = invoker.post_process_package_resources_script
-          args = [
-            "--depfile",
-            rebase_path(depfile, root_build_dir),
-            "--apk-path",
-            rebase_path(_resource_packaged_apk_path, root_build_dir),
-            "--output",
-            rebase_path(_post_processed_resource_packaged_apk_path,
-                        root_build_dir),
-          ]
-          inputs = [
-            _resource_packaged_apk_path,
-          ]
-          outputs = [
-            _post_processed_resource_packaged_apk_path,
-          ]
-          deps = [
-            ":${_package_resources_target}",
-          ]
-        }
-      }
-    }
-
     _package_resources_target_name = "${target_name}__package_resources"
-    package_resources_helper(_package_resources_target_name) {
+    package_resources(_package_resources_target_name) {
       forward_variables_from(invoker,
                              [
                                "aapt_locale_whitelist",
                                "alternative_android_sdk_jar",
-                               "android_aapt_path",
+                               "android_manifest",
+                               "app_as_shared_lib",
+                               "deps",
                                "exclude_xxxhdpi",
-                               "extensions_to_not_compress",
                                "png_to_webp",
-                               "post_process_package_resources_script",
+                               "shared_resources",
+                               "version_code",
+                               "version_name",
                                "xxxhdpi_whitelist",
                              ])
-      deps = _deps
-      android_manifest = _android_manifest
-      resource_packaged_apk_path = _resource_packaged_apk_path
+      if (defined(invoker.post_process_package_resources_script)) {
+        post_process_script = invoker.post_process_package_resources_script
+      }
+      output = _resource_packaged_apk_path
+      resources_zip = _resources_zip
+      if (_split_densities != []) {
+        split_densities = _split_densities
+      }
+      if (_split_languages != []) {
+        split_languages = _split_languages
+      }
     }
 
-    _generate_incremental_manifest_target_name =
-        "${target_name}_incremental_generate_manifest"
+    _incremental_package_resources_target_name =
+        "${target_name}_incremental__package_resources"
     _incremental_android_manifest =
-        get_label_info(_generate_incremental_manifest_target_name,
+        get_label_info(_incremental_package_resources_target_name,
                        "target_gen_dir") + "/AndroidManifest.xml"
-    action(_generate_incremental_manifest_target_name) {
-      deps = _incremental_deps
+    action(_incremental_package_resources_target_name) {
+      deps = _incremental_deps + [ ":$_package_resources_target_name" ]
       script =
           "//build/android/incremental_install/generate_android_manifest.py"
-      depfile = "${target_gen_dir}/${target_name}.d"
       inputs = [
+        # Save on a depfile by listing only .py dep here.
+        "//build/android/gyp/util/build_utils.py",
         _android_manifest,
+        _resource_packaged_apk_path,
       ]
       outputs = [
+        # Output the non-compiled manifest for easy debugging (as opposed to
+        # generating to a temp file).
         _incremental_android_manifest,
+        _incremental_resource_packaged_apk_path,
       ]
 
-      _rebased_src_manifest = rebase_path(_android_manifest, root_build_dir)
-      _rebased_incremental_manifest =
-          rebase_path(_incremental_android_manifest, root_build_dir)
-      _rebased_depfile = rebase_path(depfile, root_build_dir)
+      _android_sdk_jar = android_sdk_jar
+      if (defined(invoker.alternative_android_sdk_jar)) {
+        _android_sdk_jar = invoker.alternative_android_sdk_jar
+      }
       args = [
-        "--src-manifest=$_rebased_src_manifest",
-        "--out-manifest=$_rebased_incremental_manifest",
-        "--depfile=$_rebased_depfile",
+        "--src-manifest",
+        rebase_path(_android_manifest, root_build_dir),
+        "--out-manifest",
+        rebase_path(_incremental_android_manifest, root_build_dir),
+        "--in-apk",
+        rebase_path(_resource_packaged_apk_path, root_build_dir),
+        "--out-apk",
+        rebase_path(_incremental_resource_packaged_apk_path, root_build_dir),
+        "--aapt-path",
+        rebase_path(android_default_aapt_path, root_build_dir),
+        "--android-sdk-jar",
+        rebase_path(_android_sdk_jar, root_build_dir),
       ]
       if (disable_incremental_isolated_processes) {
         args += [ "--disable-isolated-processes" ]
       }
     }
 
-    _incremental_package_resources_target_name =
-        "${target_name}_incremental__package_resources"
-
-    # TODO(agrieve): See if we can speed up this step by swapping the manifest
-    # from the result of the main package_resources step.
-    package_resources_helper(_incremental_package_resources_target_name) {
-      forward_variables_from(invoker,
-                             [
-                               "aapt_locale_whitelist",
-                               "alternative_android_sdk_jar",
-                               "android_aapt_path",
-                               "exclude_xxxhdpi",
-                               "extensions_to_not_compress",
-                               "png_to_webp",
-                               "post_process_package_resources_script",
-                               "xxxhdpi_whitelist",
-                             ])
-      deps =
-          _incremental_deps + [ ":$_generate_incremental_manifest_target_name" ]
-      android_manifest = _incremental_android_manifest
-      resource_packaged_apk_path = _incremental_resource_packaged_apk_path
-    }
-
-    package_target = "${target_name}__package"
-    package_apk(package_target) {
+    _package_target = "${target_name}__package_apk"
+    package_apk(_package_target) {
       forward_variables_from(invoker,
                              [
                                "assets_build_config",
@@ -1901,7 +2071,7 @@
       resource_packaged_apk_path = _resource_packaged_apk_path
     }
 
-    _incremental_package_target = "${target_name}_incremental__package"
+    _incremental_package_target = "${target_name}_incremental__package_apk"
     package_apk(_incremental_package_target) {
       forward_variables_from(invoker,
                              [
@@ -1946,7 +2116,7 @@
 
       public_deps = [
         # Generator of the _packaged_apk_path this target takes as input.
-        ":$package_target",
+        ":$_package_target",
       ]
     }
 
@@ -2787,163 +2957,6 @@
     }
   }
 
-  # Runs process_resources.py
-  template("process_resources") {
-    action(target_name) {
-      set_sources_assignment_filter([])
-      forward_variables_from(invoker,
-                             [
-                               "deps",
-                               "testonly",
-                               "visibility",
-                             ])
-      script = "//build/android/gyp/process_resources.py"
-
-      depfile = "$target_gen_dir/$target_name.d"
-      outputs = [
-        invoker.zip_path,
-        invoker.r_text_out_path,
-      ]
-
-      _all_resource_dirs = []
-      sources = []
-
-      if (defined(invoker.resource_dirs)) {
-        _all_resource_dirs += invoker.resource_dirs
-
-        # Speed up "gn gen" by short-circuiting the empty directory.
-        if (invoker.resource_dirs != [ "//build/android/empty" ] &&
-            invoker.resource_dirs != []) {
-          _sources_build_rel =
-              exec_script("//build/android/gyp/find.py",
-                          rebase_path(invoker.resource_dirs, root_build_dir),
-                          "list lines")
-          sources += rebase_path(_sources_build_rel, ".", root_build_dir)
-        }
-      }
-
-      if (defined(invoker.generated_resource_dirs)) {
-        assert(defined(invoker.generated_resource_files))
-        _all_resource_dirs += invoker.generated_resource_dirs
-        sources += invoker.generated_resource_files
-      }
-
-      _android_aapt_path = android_default_aapt_path
-      if (defined(invoker.android_aapt_path)) {
-        _android_aapt_path = invoker.android_aapt_path
-      }
-
-      _android_sdk_jar = android_sdk_jar
-      if (defined(invoker.alternative_android_sdk_jar)) {
-        _android_sdk_jar = invoker.alternative_android_sdk_jar
-      }
-
-      inputs = [
-        invoker.build_config,
-        invoker.android_manifest,
-        _android_aapt_path,
-        _android_sdk_jar,
-      ]
-
-      _rebased_all_resource_dirs =
-          rebase_path(_all_resource_dirs, root_build_dir)
-      _rebased_build_config = rebase_path(invoker.build_config, root_build_dir)
-
-      args = [
-        "--depfile",
-        rebase_path(depfile, root_build_dir),
-        "--android-sdk-jar",
-        rebase_path(_android_sdk_jar, root_build_dir),
-        "--aapt-path",
-        rebase_path(_android_aapt_path, root_build_dir),
-        "--android-manifest",
-        rebase_path(invoker.android_manifest, root_build_dir),
-        "--resource-dirs=$_rebased_all_resource_dirs",
-        "--resource-zip-out",
-        rebase_path(invoker.zip_path, root_build_dir),
-        "--r-text-out",
-        rebase_path(invoker.r_text_out_path, root_build_dir),
-        "--dependencies-res-zips=@FileArg($_rebased_build_config:resources:dependency_zips)",
-        "--extra-res-packages=@FileArg($_rebased_build_config:resources:extra_package_names)",
-        "--extra-r-text-files=@FileArg($_rebased_build_config:resources:extra_r_text_files)",
-      ]
-      if (defined(invoker.srcjar_path)) {
-        outputs += [ invoker.srcjar_path ]
-        args += [
-          "--srcjar-out",
-          rebase_path(invoker.srcjar_path, root_build_dir),
-        ]
-      }
-
-      if (defined(invoker.r_text_in_path)) {
-        _r_text_in_path = invoker.r_text_in_path
-        inputs += [ _r_text_in_path ]
-        args += [
-          "--r-text-in",
-          rebase_path(_r_text_in_path, root_build_dir),
-        ]
-      }
-
-      if (!defined(invoker.generate_constant_ids) ||
-          !invoker.generate_constant_ids) {
-        args += [ "--non-constant-id" ]
-      }
-
-      if (defined(invoker.custom_package)) {
-        args += [
-          "--custom-package",
-          invoker.custom_package,
-        ]
-      }
-
-      if (defined(invoker.v14_skip) && invoker.v14_skip) {
-        args += [ "--v14-skip" ]
-      }
-
-      if (defined(invoker.shared_resources) && invoker.shared_resources) {
-        args += [ "--shared-resources" ]
-      }
-
-      if (defined(invoker.app_as_shared_lib) && invoker.app_as_shared_lib) {
-        args += [ "--app-as-shared-lib" ]
-      }
-
-      if (defined(invoker.include_all_resources) &&
-          invoker.include_all_resources) {
-        args += [ "--include-all-resources" ]
-      }
-
-      if (defined(invoker.all_resources_zip_path)) {
-        _all_resources_zip = invoker.all_resources_zip_path
-        outputs += [ _all_resources_zip ]
-        args += [
-          "--all-resources-zip-out",
-          rebase_path(_all_resources_zip, root_build_dir),
-        ]
-      }
-
-      if (defined(invoker.proguard_file)) {
-        outputs += [ invoker.proguard_file ]
-        args += [
-          "--proguard-file",
-          rebase_path(invoker.proguard_file, root_build_dir),
-        ]
-      }
-
-      if (defined(invoker.proguard_file_main_dex)) {
-        outputs += [ invoker.proguard_file_main_dex ]
-        args += [
-          "--proguard-file-main-dex",
-          rebase_path(invoker.proguard_file_main_dex, root_build_dir),
-        ]
-      }
-
-      if (defined(invoker.args)) {
-        args += invoker.args
-      }
-    }
-  }
-
   # Produces a single .dex.jar out of a set of Java dependencies.
   template("deps_dex") {
     set_sources_assignment_filter([])
diff --git a/build/config/android/rules.gni b/build/config/android/rules.gni
index e1f11c9e..f1c8a16 100644
--- a/build/config/android/rules.gni
+++ b/build/config/android/rules.gni
@@ -1632,8 +1632,6 @@
   # Variables
   #   alternative_android_sdk_jar: The alternative android sdk jar used in
   #     proguard.
-  #   android_aapt_path: Android aapt tool to replace default one to build
-  #     resource.
   #   android_manifest: Path to AndroidManifest.xml.
   #   android_manifest_dep: Target that generates AndroidManifest (if applicable)
   #   chromium_code: If true, extra analysis warning/errors will be enabled.
@@ -2029,7 +2027,6 @@
       forward_variables_from(invoker,
                              [
                                "alternative_android_sdk_jar",
-                               "android_aapt_path",
                                "app_as_shared_lib",
                                "include_all_resources",
                                "shared_resources",
@@ -2403,11 +2400,9 @@
                              [
                                "aapt_locale_whitelist",
                                "alternative_android_sdk_jar",
-                               "android_aapt_path",
                                "app_as_shared_lib",
                                "deps",
                                "exclude_xxxhdpi",
-                               "extensions_to_not_compress",
                                "language_splits",
                                "png_to_webp",
                                "post_process_package_resources_script",
@@ -2429,13 +2424,6 @@
       load_library_from_apk = _load_library_from_apk
       create_density_splits = _create_density_splits
 
-      if (!defined(extensions_to_not_compress)) {
-        # Allow icu data, v8 snapshots, and pak files to be loaded directly from
-        # the .apk.
-        # Note: These are actually suffix matches, not necessarily extensions.
-        extensions_to_not_compress = ".dat,.bin,.pak"
-      }
-
       version_code = _version_code
       version_name = _version_name
 
@@ -2518,7 +2506,6 @@
         forward_variables_from(invoker,
                                [
                                  "alternative_android_sdk_jar",
-                                 "android_aapt_path",
                                  "deps",
                                  "native_lib_placeholders",
                                  "public_deps",
diff --git a/build/config/compiler/compiler.gni b/build/config/compiler/compiler.gni
index 4459033..28886a4 100644
--- a/build/config/compiler/compiler.gni
+++ b/build/config/compiler/compiler.gni
@@ -2,7 +2,9 @@
 # Use of this source code is governed by a BSD-style license that can be
 # found in the LICENSE file.
 
-import("//build/config/android/config.gni")
+if (is_android) {
+  import("//build/config/android/abi.gni")
+}
 import("//build/config/arm.gni")
 import("//build/config/chrome_build.gni")
 import("//build/config/chromecast_build.gni")
diff --git a/build/fuchsia/runner_common.py b/build/fuchsia/runner_common.py
index cbce33d..d03b496 100755
--- a/build/fuchsia/runner_common.py
+++ b/build/fuchsia/runner_common.py
@@ -549,7 +549,12 @@
       _RunAndCheck(dry_run, ['truncate', '-s100M', img_filename,])
       _RunAndCheck(dry_run, [os.path.join(SDK_ROOT, 'tools', 'minfs'),
                              img_filename, 'mkfs'])
-      qemu_command.extend(['-drive', 'file=' + img_filename + ',format=raw'])
+      # Specifically set an AHCI drive, otherwise the drive won't be mountable
+      # on ARM64.
+      qemu_command.extend(['-drive', 'file=' + img_filename +
+                               ',if=none,format=raw,id=resultsdisk',
+                           '-device', 'ahci,id=ahci',
+                           '-device', 'ide-drive,drive=resultsdisk,bus=ahci.0'])
 
     if dry_run:
       print 'Run:', ' '.join(qemu_command)
diff --git a/build/install-build-deps.sh b/build/install-build-deps.sh
index f2ab2668..966a16e 100755
--- a/build/install-build-deps.sh
+++ b/build/install-build-deps.sh
@@ -112,7 +112,7 @@
 
 distro_codename=$(lsb_release --codename --short)
 distro_id=$(lsb_release --id --short)
-supported_codenames="(trusty|xenial|yakkety|zesty)"
+supported_codenames="(trusty|xenial|zesty|artful)"
 supported_ids="(Debian)"
 if [ 0 -eq "${do_unsupported-0}" ] && [ 0 -eq "${do_quick_check-0}" ] ; then
   if [[ ! $distro_codename =~ $supported_codenames &&
@@ -120,8 +120,8 @@
     echo -e "ERROR: The only supported distros are\n" \
       "\tUbuntu 14.04 (trusty)\n" \
       "\tUbuntu 16.04 (xenial)\n" \
-      "\tUbuntu 16.10 (yakkety)\n" \
       "\tUbuntu 17.04 (zesty)\n" \
+      "\tUbuntu 17.10 (artful)\n" \
       "\tDebian 8 (jessie) or later" >&2
     exit 1
   fi
@@ -292,6 +292,7 @@
   libxdamage1-dbg
   libxdmcp6-dbg
   libxext6-dbg
+  libxfixes3-dbg
   libxi6-dbg
   libxinerama1-dbg
   libxrandr2-dbg
@@ -300,10 +301,6 @@
   zlib1g-dbg
 "
 
-if [[ ! $distro_codename =~ "yakkety" ]]; then
-  dbg_list="${dbg_list} libxfixes3-dbg"
-fi
-
 # Find the proper version of libstdc++6-4.x-dbg.
 if [ "x$distro_codename" = "xtrusty" ]; then
   dbg_list="${dbg_list} libstdc++6-4.8-dbg"
@@ -364,7 +361,7 @@
     arm_list+=" g++-4.8-multilib-arm-linux-gnueabihf
                 gcc-4.8-multilib-arm-linux-gnueabihf"
     ;;
-  xenial|yakkety|zesty)
+  xenial|zesty|artful)
     arm_list+=" g++-5-multilib-arm-linux-gnueabihf
                 gcc-5-multilib-arm-linux-gnueabihf
                 gcc-arm-linux-gnueabihf"
@@ -479,7 +476,9 @@
 else
   dev_list="${dev_list} ttf-indic-fonts"
 fi
-if package_exists php7.0-cgi; then
+if package_exists php7.1-cgi; then
+  dev_list="${dev_list} php7.1-cgi libapache2-mod-php7.1"
+elif package_exists php7.0-cgi; then
   dev_list="${dev_list} php7.0-cgi libapache2-mod-php7.0"
 else
   dev_list="${dev_list} php5-cgi libapache2-mod-php5"
diff --git a/build/sanitizers/tsan_suppressions.cc b/build/sanitizers/tsan_suppressions.cc
index 3a18acf..e431eb7 100644
--- a/build/sanitizers/tsan_suppressions.cc
+++ b/build/sanitizers/tsan_suppressions.cc
@@ -255,10 +255,6 @@
     "race:base::i18n::IsRTL\n"
     "race:base::i18n::SetICUDefaultLocale\n"
 
-    // http://crbug.com/778254
-    "race:sw::Renderer::updateConfiguration\n"
-    "race:sw::Renderer::scheduleTask\n"
-
     //
     "race:third_party/harfbuzz-ng/src/*\n"
 
diff --git a/build/secondary/third_party/android_tools/BUILD.gn b/build/secondary/third_party/android_tools/BUILD.gn
index d7a86c8..f748b40 100644
--- a/build/secondary/third_party/android_tools/BUILD.gn
+++ b/build/secondary/third_party/android_tools/BUILD.gn
@@ -46,8 +46,9 @@
 }
 support_lib_alias("emma_device_java") {
 }
-java_group("android_arch_lifecycle_common_java") {
-  # TODO(https://crbug.com/769683): Define when rolling to support lib 26+.
+support_lib_alias("android_arch_lifecycle_common_java") {
+}
+support_lib_alias("android_arch_lifecycle_runtime_java") {
 }
 support_lib_alias("android_support_multidex_java") {
 }
diff --git a/build/secondary/third_party/android_tools/support/BUILD.gn b/build/secondary/third_party/android_tools/support/BUILD.gn
index 8d6a640..adcae68 100644
--- a/build/secondary/third_party/android_tools/support/BUILD.gn
+++ b/build/secondary/third_party/android_tools/support/BUILD.gn
@@ -9,8 +9,11 @@
   "//third_party/android_tools:*",
 ]
 
-lib_version = "25.0.1"
+lib_version = "27.0.0"
 lib_path = "//third_party/android_tools/sdk/extras/android/m2repository/com/android/support"
+arch_lib_version = "1.0.0"
+arch_lib_path =
+    "//third_party/android_tools/sdk/extras/android/m2repository/android/arch"
 build_file_dir = "//build/secondary/third_party/android_tools/support"
 
 android_library("android_support_chromium_java") {
@@ -62,6 +65,32 @@
   info_path = "$build_file_dir/$target_name.info"
 }
 
+android_aar_prebuilt("android_arch_lifecycle_runtime_java") {
+  aar_path = "$arch_lib_path/lifecycle/runtime/$arch_lib_version/runtime-$arch_lib_version.aar"
+  info_path = "$build_file_dir/$target_name.info"
+  deps = [
+    ":android_arch_core_common_java",
+    ":android_arch_lifecycle_common_java",
+    ":android_support_annotations_java",
+  ]
+}
+
+android_java_prebuilt("android_arch_lifecycle_common_java") {
+  output_name = "arch_lifecycle_common"
+  jar_path = "$arch_lib_path/lifecycle/common/$arch_lib_version/common-$arch_lib_version.jar"
+  deps = [
+    ":android_support_annotations_java",
+  ]
+}
+
+android_java_prebuilt("android_arch_core_common_java") {
+  output_name = "arch_core_common"
+  jar_path = "$arch_lib_path/core/common/$arch_lib_version/common-$arch_lib_version.jar"
+  deps = [
+    ":android_support_annotations_java",
+  ]
+}
+
 android_java_prebuilt("android_support_annotations_java") {
   _lib_name = "support-annotations"
   jar_path = "$lib_path/$_lib_name/$lib_version/$_lib_name-$lib_version.jar"
@@ -79,6 +108,7 @@
 
 android_aar_prebuilt("android_support_compat_java") {
   deps = [
+    ":android_arch_lifecycle_runtime_java",
     ":android_support_annotations_java",
   ]
   _lib_name = "support-compat"
@@ -145,6 +175,16 @@
   info_path = "$build_file_dir/$target_name.info"
 }
 
+android_aar_prebuilt("android_support_animated_vector_drawable_java") {
+  deps = [
+    ":android_support_core_ui_java",
+    ":android_support_vector_drawable_java",
+  ]
+  _lib_name = "animated-vector-drawable"
+  aar_path = "$lib_path/$_lib_name/$lib_version/$_lib_name-$lib_version.aar"
+  info_path = "$build_file_dir/$target_name.info"
+}
+
 android_aar_prebuilt("android_support_v7_appcompat_java_internal") {
   deps = [
     ":android_support_v4_java",
@@ -156,6 +196,7 @@
 
 java_group("android_support_v7_appcompat_java") {
   deps = [
+    ":android_support_animated_vector_drawable_java",
     ":android_support_v4_java",
     ":android_support_v7_appcompat_java_internal",
     ":android_support_vector_drawable_java",
diff --git a/build/secondary/third_party/android_tools/support/android_arch_lifecycle_runtime_java.info b/build/secondary/third_party/android_tools/support/android_arch_lifecycle_runtime_java.info
new file mode 100644
index 0000000..acf40e8
--- /dev/null
+++ b/build/secondary/third_party/android_tools/support/android_arch_lifecycle_runtime_java.info
@@ -0,0 +1,13 @@
+# Generated by //build/android/gyp/aar.py
+# To regenerate, use "update_android_aar_prebuilts = true" and run "gn gen".
+
+aidl = [  ]
+assets = [  ]
+has_classes_jar = true
+has_native_libraries = false
+has_proguard_flags = true
+has_r_text_file = false
+is_manifest_empty = false
+resources = [  ]
+subjar_tuples = [  ]
+subjars = [  ]
diff --git a/build/secondary/third_party/android_tools/support/android_support_animated_vector_drawable_java.info b/build/secondary/third_party/android_tools/support/android_support_animated_vector_drawable_java.info
new file mode 100644
index 0000000..7103bc0
--- /dev/null
+++ b/build/secondary/third_party/android_tools/support/android_support_animated_vector_drawable_java.info
@@ -0,0 +1,13 @@
+# Generated by //build/android/gyp/aar.py
+# To regenerate, use "update_android_aar_prebuilts = true" and run "gn gen".
+
+aidl = [  ]
+assets = [  ]
+has_classes_jar = true
+has_native_libraries = false
+has_proguard_flags = true
+has_r_text_file = true
+is_manifest_empty = true
+resources = [  ]
+subjar_tuples = [  ]
+subjars = [  ]
diff --git a/build/secondary/third_party/android_tools/support/android_support_compat_java.info b/build/secondary/third_party/android_tools/support/android_support_compat_java.info
index b68ec40..fc66ea71 100644
--- a/build/secondary/third_party/android_tools/support/android_support_compat_java.info
+++ b/build/secondary/third_party/android_tools/support/android_support_compat_java.info
@@ -6,8 +6,8 @@
 has_classes_jar = true
 has_native_libraries = false
 has_proguard_flags = false
-has_r_text_file = false
+has_r_text_file = true
 is_manifest_empty = true
-resources = [  ]
-subjar_tuples = [ [ "internal_impl_25.0.1", "libs/internal_impl-25.0.1.jar" ] ]
-subjars = [ "libs/internal_impl-25.0.1.jar" ]
+resources = [ "res/values-ur/values-ur.xml", "res/values-ru/values-ru.xml", "res/values-en-rGB/values-en-rGB.xml", "res/values-pt-rBR/values-pt-rBR.xml", "res/values-el/values-el.xml", "res/drawable-hdpi-v4/notification_bg_low_normal.9.png", "res/drawable-hdpi-v4/notify_panel_notification_icon_bg.png", "res/drawable-hdpi-v4/notification_bg_normal_pressed.9.png", "res/drawable-hdpi-v4/notification_bg_normal.9.png", "res/drawable-hdpi-v4/notification_bg_low_pressed.9.png", "res/values-tr/values-tr.xml", "res/values-hu/values-hu.xml", "res/values-km/values-km.xml", "res/values-fr-rCA/values-fr-rCA.xml", "res/values-gu/values-gu.xml", "res/layout/notification_template_icon_group.xml", "res/layout/notification_template_custom_big.xml", "res/layout/notification_template_part_time.xml", "res/layout/notification_template_part_chronometer.xml", "res/layout/notification_action_tombstone.xml", "res/layout/notification_action.xml", "res/values-ms/values-ms.xml", "res/values-v21/values-v21.xml", "res/values-ja/values-ja.xml", "res/values-eu/values-eu.xml", "res/values-sv/values-sv.xml", "res/values-mn/values-mn.xml", "res/layout-v16/notification_template_custom_big.xml", "res/values-ta/values-ta.xml", "res/values-pl/values-pl.xml", "res/values-lt/values-lt.xml", "res/values-bg/values-bg.xml", "res/values-es-rUS/values-es-rUS.xml", "res/values-iw/values-iw.xml", "res/values-mr/values-mr.xml", "res/values-uz/values-uz.xml", "res/values-pa/values-pa.xml", "res/values-fi/values-fi.xml", "res/values-am/values-am.xml", "res/values-pt-rPT/values-pt-rPT.xml", "res/values-ar/values-ar.xml", "res/values-ky/values-ky.xml", "res/drawable-mdpi-v4/notification_bg_low_normal.9.png", "res/drawable-mdpi-v4/notify_panel_notification_icon_bg.png", "res/drawable-mdpi-v4/notification_bg_normal_pressed.9.png", "res/drawable-mdpi-v4/notification_bg_normal.9.png", "res/drawable-mdpi-v4/notification_bg_low_pressed.9.png", "res/values-bs/values-bs.xml", "res/values/values.xml", "res/values-hr/values-hr.xml", "res/values-en-rAU/values-en-rAU.xml", "res/values-ro/values-ro.xml", "res/drawable-xhdpi-v4/notification_bg_low_normal.9.png", "res/drawable-xhdpi-v4/notify_panel_notification_icon_bg.png", "res/drawable-xhdpi-v4/notification_bg_normal_pressed.9.png", "res/drawable-xhdpi-v4/notification_bg_normal.9.png", "res/drawable-xhdpi-v4/notification_bg_low_pressed.9.png", "res/values-vi/values-vi.xml", "res/values-ko/values-ko.xml", "res/values-zh-rTW/values-zh-rTW.xml", "res/values-cs/values-cs.xml", "res/values-ml/values-ml.xml", "res/values-te/values-te.xml", "res/values-si/values-si.xml", "res/values-es/values-es.xml", "res/values-af/values-af.xml", "res/values-zu/values-zu.xml", "res/values-lo/values-lo.xml", "res/values-mk/values-mk.xml", "res/values-sl/values-sl.xml", "res/values-sw/values-sw.xml", "res/values-bn/values-bn.xml", "res/values-sk/values-sk.xml", "res/values-lv/values-lv.xml", "res/values-is/values-is.xml", "res/values-da/values-da.xml", "res/values-it/values-it.xml", "res/values-gl/values-gl.xml", "res/values-de/values-de.xml", "res/values-be/values-be.xml", "res/values-fa/values-fa.xml", "res/values-ca/values-ca.xml", "res/values-th/values-th.xml", "res/values-nl/values-nl.xml", "res/values-hy/values-hy.xml", "res/values-zh-rHK/values-zh-rHK.xml", "res/values-tl/values-tl.xml", "res/values-kk/values-kk.xml", "res/values-pt/values-pt.xml", "res/values-my/values-my.xml", "res/values-et/values-et.xml", "res/values-en-rIN/values-en-rIN.xml", "res/values-sr/values-sr.xml", "res/values-v16/values-v16.xml", "res/values-fr/values-fr.xml", "res/values-kn/values-kn.xml", "res/values-nb/values-nb.xml", "res/values-port/values-port.xml", "res/values-ne/values-ne.xml", "res/drawable/notification_bg_low.xml", "res/drawable/notification_bg.xml", "res/drawable/notification_icon_background.xml", "res/drawable/notification_tile_bg.xml", "res/values-b+sr+Latn/values-b+sr+Latn.xml", "res/values-ka/values-ka.xml", "res/values-zh-rCN/values-zh-rCN.xml", "res/values-az/values-az.xml", "res/values-sq/values-sq.xml", "res/values-hi/values-hi.xml", "res/layout-v21/notification_template_icon_group.xml", "res/layout-v21/notification_template_custom_big.xml", "res/layout-v21/notification_action_tombstone.xml", "res/layout-v21/notification_action.xml", "res/values-in/values-in.xml", "res/values-uk/values-uk.xml", "res/drawable-v21/notification_action_background.xml" ]
+subjar_tuples = [  ]
+subjars = [  ]
diff --git a/build/secondary/third_party/android_tools/support/android_support_core_ui_java.info b/build/secondary/third_party/android_tools/support/android_support_core_ui_java.info
index 5f0071dd..7103bc0 100644
--- a/build/secondary/third_party/android_tools/support/android_support_core_ui_java.info
+++ b/build/secondary/third_party/android_tools/support/android_support_core_ui_java.info
@@ -6,8 +6,8 @@
 has_classes_jar = true
 has_native_libraries = false
 has_proguard_flags = true
-has_r_text_file = false
+has_r_text_file = true
 is_manifest_empty = true
 resources = [  ]
-subjar_tuples = [ [ "internal_impl_25.0.1", "libs/internal_impl-25.0.1.jar" ] ]
-subjars = [ "libs/internal_impl-25.0.1.jar" ]
+subjar_tuples = [  ]
+subjars = [  ]
diff --git a/build/secondary/third_party/android_tools/support/android_support_core_utils_java.info b/build/secondary/third_party/android_tools/support/android_support_core_utils_java.info
index d82eb75..cd54060 100644
--- a/build/secondary/third_party/android_tools/support/android_support_core_utils_java.info
+++ b/build/secondary/third_party/android_tools/support/android_support_core_utils_java.info
@@ -6,8 +6,8 @@
 has_classes_jar = true
 has_native_libraries = false
 has_proguard_flags = false
-has_r_text_file = false
+has_r_text_file = true
 is_manifest_empty = true
 resources = [  ]
-subjar_tuples = [ [ "internal_impl_25.0.1", "libs/internal_impl-25.0.1.jar" ] ]
-subjars = [ "libs/internal_impl-25.0.1.jar" ]
+subjar_tuples = [  ]
+subjars = [  ]
diff --git a/build/secondary/third_party/android_tools/support/android_support_design_java.info b/build/secondary/third_party/android_tools/support/android_support_design_java.info
index 37e2270..ec2b700 100644
--- a/build/secondary/third_party/android_tools/support/android_support_design_java.info
+++ b/build/secondary/third_party/android_tools/support/android_support_design_java.info
@@ -8,6 +8,6 @@
 has_proguard_flags = true
 has_r_text_file = true
 is_manifest_empty = true
-resources = [ "res/drawable-v21/design_bottom_navigation_item_background.xml", "res/values-v21/values-v21.xml", "res/anim-v21/design_bottom_sheet_slide_out.xml", "res/anim-v21/design_appbar_state_list_animator.xml", "res/anim-v21/design_bottom_sheet_slide_in.xml", "res/anim/design_fab_out.xml", "res/anim/design_bottom_sheet_slide_out.xml", "res/anim/design_snackbar_in.xml", "res/anim/design_fab_in.xml", "res/anim/design_snackbar_out.xml", "res/anim/design_bottom_sheet_slide_in.xml", "res/layout/design_layout_tab_text.xml", "res/layout/design_navigation_item_separator.xml", "res/layout/design_bottom_sheet_dialog.xml", "res/layout/design_layout_snackbar_include.xml", "res/layout/design_text_input_password_icon.xml", "res/layout/design_navigation_menu_item.xml", "res/layout/design_menu_item_action_area.xml", "res/layout/design_navigation_item.xml", "res/layout/design_navigation_item_header.xml", "res/layout/design_layout_snackbar.xml", "res/layout/design_navigation_item_subheader.xml", "res/layout/design_navigation_menu.xml", "res/layout/design_layout_tab_icon.xml", "res/layout/design_bottom_navigation_item.xml", "res/values-sw600dp-v13/values-sw600dp-v13.xml", "res/values-land/values-land.xml", "res/color-v23/design_tint_password_toggle.xml", "res/values/values.xml", "res/layout-sw600dp-v13/design_layout_snackbar.xml", "res/color/design_error.xml", "res/color/design_tint_password_toggle.xml", "res/drawable/design_snackbar_background.xml", "res/drawable/design_fab_background.xml", "res/drawable/design_bottom_navigation_item_background.xml", "res/drawable/design_ic_visibility.xml", "res/drawable/navigation_empty_icon.xml" ]
+resources = [ "res/drawable-hdpi-v4/design_ic_visibility.png", "res/drawable-hdpi-v4/design_ic_visibility_off.png", "res/layout/design_bottom_sheet_dialog.xml", "res/layout/design_layout_tab_text.xml", "res/layout/design_bottom_navigation_item.xml", "res/layout/design_navigation_item.xml", "res/layout/design_layout_snackbar_include.xml", "res/layout/design_navigation_menu.xml", "res/layout/design_navigation_item_header.xml", "res/layout/design_navigation_item_separator.xml", "res/layout/design_layout_snackbar.xml", "res/layout/design_text_input_password_icon.xml", "res/layout/design_layout_tab_icon.xml", "res/layout/design_navigation_item_subheader.xml", "res/layout/design_menu_item_action_area.xml", "res/layout/design_navigation_menu_item.xml", "res/values-v21/values-v21.xml", "res/drawable-anydpi-v21/design_ic_visibility.xml", "res/drawable-anydpi-v21/design_ic_visibility_off.xml", "res/layout-sw600dp-v13/design_layout_snackbar.xml", "res/drawable-xxhdpi-v4/design_ic_visibility.png", "res/drawable-xxhdpi-v4/design_ic_visibility_off.png", "res/color/design_error.xml", "res/color/design_tint_password_toggle.xml", "res/animator-v21/design_appbar_state_list_animator.xml", "res/drawable-mdpi-v4/design_ic_visibility.png", "res/drawable-mdpi-v4/design_ic_visibility_off.png", "res/values/values.xml", "res/drawable-xhdpi-v4/design_ic_visibility.png", "res/drawable-xhdpi-v4/design_ic_visibility_off.png", "res/values-land/values-land.xml", "res/values-sw600dp-v13/values-sw600dp-v13.xml", "res/anim/design_snackbar_out.xml", "res/anim/design_snackbar_in.xml", "res/anim/design_bottom_sheet_slide_out.xml", "res/anim/design_bottom_sheet_slide_in.xml", "res/drawable-xxxhdpi-v4/design_ic_visibility.png", "res/drawable-xxxhdpi-v4/design_ic_visibility_off.png", "res/anim-v21/design_bottom_sheet_slide_out.xml", "res/anim-v21/design_bottom_sheet_slide_in.xml", "res/values-v26/values-v26.xml", "res/color-v23/design_tint_password_toggle.xml", "res/drawable/design_snackbar_background.xml", "res/drawable/design_fab_background.xml", "res/drawable/design_password_eye.xml", "res/drawable/navigation_empty_icon.xml", "res/drawable/design_bottom_navigation_item_background.xml", "res/drawable-v21/avd_hide_password.xml", "res/drawable-v21/avd_show_password.xml", "res/drawable-v21/design_password_eye.xml", "res/drawable-v21/design_bottom_navigation_item_background.xml" ]
 subjar_tuples = [  ]
 subjars = [  ]
diff --git a/build/secondary/third_party/android_tools/support/android_support_fragment_java.info b/build/secondary/third_party/android_tools/support/android_support_fragment_java.info
index d82eb75..cd54060 100644
--- a/build/secondary/third_party/android_tools/support/android_support_fragment_java.info
+++ b/build/secondary/third_party/android_tools/support/android_support_fragment_java.info
@@ -6,8 +6,8 @@
 has_classes_jar = true
 has_native_libraries = false
 has_proguard_flags = false
-has_r_text_file = false
+has_r_text_file = true
 is_manifest_empty = true
 resources = [  ]
-subjar_tuples = [ [ "internal_impl_25.0.1", "libs/internal_impl-25.0.1.jar" ] ]
-subjars = [ "libs/internal_impl-25.0.1.jar" ]
+subjar_tuples = [  ]
+subjars = [  ]
diff --git a/build/secondary/third_party/android_tools/support/android_support_media_compat_java.info b/build/secondary/third_party/android_tools/support/android_support_media_compat_java.info
index 347df34..6140dd1 100644
--- a/build/secondary/third_party/android_tools/support/android_support_media_compat_java.info
+++ b/build/secondary/third_party/android_tools/support/android_support_media_compat_java.info
@@ -1,13 +1,13 @@
 # Generated by //build/android/gyp/aar.py
 # To regenerate, use "update_android_aar_prebuilts = true" and run "gn gen".
 
-aidl = [ "aidl/android/support/v4/media/session/MediaSessionCompat.aidl", "aidl/android/support/v4/media/session/PlaybackStateCompat.aidl", "aidl/android/support/v4/media/session/ParcelableVolumeInfo.aidl", "aidl/android/support/v4/media/RatingCompat.aidl", "aidl/android/support/v4/media/MediaMetadataCompat.aidl" ]
+aidl = [ "aidl/android/support/v4/media/session/PlaybackStateCompat.aidl", "aidl/android/support/v4/media/session/MediaSessionCompat.aidl", "aidl/android/support/v4/media/session/ParcelableVolumeInfo.aidl", "aidl/android/support/v4/media/RatingCompat.aidl", "aidl/android/support/v4/media/MediaMetadataCompat.aidl", "aidl/android/support/v4/media/MediaDescriptionCompat.aidl" ]
 assets = [  ]
 has_classes_jar = true
 has_native_libraries = false
-has_proguard_flags = false
-has_r_text_file = false
+has_proguard_flags = true
+has_r_text_file = true
 is_manifest_empty = true
-resources = [  ]
-subjar_tuples = [ [ "internal_impl_25.0.1", "libs/internal_impl-25.0.1.jar" ] ]
-subjars = [ "libs/internal_impl-25.0.1.jar" ]
+resources = [ "res/layout/notification_template_media_custom.xml", "res/layout/notification_template_big_media_narrow_custom.xml", "res/layout/notification_template_media.xml", "res/layout/notification_template_big_media.xml", "res/layout/notification_media_action.xml", "res/layout/notification_template_lines_media.xml", "res/layout/notification_media_cancel_action.xml", "res/layout/notification_template_big_media_custom.xml", "res/layout/notification_template_big_media_narrow.xml", "res/values-v21/values-v21.xml", "res/values/values.xml", "res/values-v24/values-v24.xml" ]
+subjar_tuples = [  ]
+subjars = [  ]
diff --git a/build/secondary/third_party/android_tools/support/android_support_transition_java.info b/build/secondary/third_party/android_tools/support/android_support_transition_java.info
index 28c8330..a25d255 100644
--- a/build/secondary/third_party/android_tools/support/android_support_transition_java.info
+++ b/build/secondary/third_party/android_tools/support/android_support_transition_java.info
@@ -5,7 +5,7 @@
 assets = [  ]
 has_classes_jar = true
 has_native_libraries = false
-has_proguard_flags = false
+has_proguard_flags = true
 has_r_text_file = true
 is_manifest_empty = true
 resources = [ "res/values/values.xml" ]
diff --git a/build/secondary/third_party/android_tools/support/android_support_v13_java.info b/build/secondary/third_party/android_tools/support/android_support_v13_java.info
index d82eb75..cd54060 100644
--- a/build/secondary/third_party/android_tools/support/android_support_v13_java.info
+++ b/build/secondary/third_party/android_tools/support/android_support_v13_java.info
@@ -6,8 +6,8 @@
 has_classes_jar = true
 has_native_libraries = false
 has_proguard_flags = false
-has_r_text_file = false
+has_r_text_file = true
 is_manifest_empty = true
 resources = [  ]
-subjar_tuples = [ [ "internal_impl_25.0.1", "libs/internal_impl-25.0.1.jar" ] ]
-subjars = [ "libs/internal_impl-25.0.1.jar" ]
+subjar_tuples = [  ]
+subjars = [  ]
diff --git a/build/secondary/third_party/android_tools/support/android_support_v14_preference_java.info b/build/secondary/third_party/android_tools/support/android_support_v14_preference_java.info
index e7f9be67..74388f4 100644
--- a/build/secondary/third_party/android_tools/support/android_support_v14_preference_java.info
+++ b/build/secondary/third_party/android_tools/support/android_support_v14_preference_java.info
@@ -8,6 +8,6 @@
 has_proguard_flags = false
 has_r_text_file = true
 is_manifest_empty = true
-resources = [ "res/layout-v17/preference_material.xml", "res/layout-v17/preference_information_material.xml", "res/layout-v17/preference_category_material.xml", "res/layout-v17/preference_dropdown_material.xml", "res/values-v17/values-v17.xml", "res/layout/preference_material.xml", "res/layout/preference_information_material.xml", "res/layout/preference_category_material.xml", "res/layout/preference_dropdown_material.xml", "res/layout/preference_widget_switch.xml", "res/values/values.xml", "res/layout-v21/preference_material.xml", "res/layout-v21/preference_information_material.xml", "res/layout-v21/preference_category_material.xml", "res/layout-v21/preference_dropdown_material.xml", "res/drawable/preference_list_divider_material.xml" ]
+resources = [ "res/layout/preference_information_material.xml", "res/layout/preference_widget_seekbar_material.xml", "res/layout/preference_category_material.xml", "res/layout/preference_dropdown_material.xml", "res/layout/preference_widget_switch.xml", "res/layout/preference_material.xml", "res/values/values.xml", "res/values-v17/values-v17.xml", "res/drawable/preference_list_divider_material.xml", "res/layout-v21/preference_information_material.xml", "res/layout-v21/preference_category_material.xml", "res/layout-v21/preference_dropdown_material.xml", "res/layout-v21/preference_material.xml", "res/drawable-v21/preference_list_divider_material.xml", "res/layout-v17/preference_information_material.xml", "res/layout-v17/preference_category_material.xml", "res/layout-v17/preference_dropdown_material.xml", "res/layout-v17/preference_material.xml" ]
 subjar_tuples = [  ]
 subjars = [  ]
diff --git a/build/secondary/third_party/android_tools/support/android_support_v17_leanback_java.info b/build/secondary/third_party/android_tools/support/android_support_v17_leanback_java.info
index 93dae49..34d36936 100644
--- a/build/secondary/third_party/android_tools/support/android_support_v17_leanback_java.info
+++ b/build/secondary/third_party/android_tools/support/android_support_v17_leanback_java.info
@@ -8,6 +8,6 @@
 has_proguard_flags = false
 has_r_text_file = true
 is_manifest_empty = true
-resources = [ "res/values-km-rKH/values-km-rKH.xml", "res/values-nl/values-nl.xml", "res/values-az-rAZ/values-az-rAZ.xml", "res/values-gl-rES/values-gl-rES.xml", "res/values-bg/values-bg.xml", "res/values-ldrtl-v17/values-ldrtl-v17.xml", "res/values-pt-rBR/values-pt-rBR.xml", "res/values-eu-rES/values-eu-rES.xml", "res/values-el/values-el.xml", "res/animator/lb_onboarding_page_indicator_enter.xml", "res/animator/lb_guidedactions_item_unpressed.xml", "res/animator/lb_onboarding_logo_enter.xml", "res/animator/lb_guidedactions_item_pressed.xml", "res/animator/lb_onboarding_start_button_fade_out.xml", "res/animator/lb_playback_rows_fade_out.xml", "res/animator/lb_onboarding_start_button_fade_in.xml", "res/animator/lb_decelerator_4.xml", "res/animator/lb_onboarding_logo_exit.xml", "res/animator/lb_guidedstep_slide_up.xml", "res/animator/lb_onboarding_title_enter.xml", "res/animator/lb_onboarding_page_indicator_fade_out.xml", "res/animator/lb_playback_controls_fade_in.xml", "res/animator/lb_playback_rows_fade_in.xml", "res/animator/lb_playback_description_fade_in.xml", "res/animator/lb_playback_controls_fade_out.xml", "res/animator/lb_onboarding_page_indicator_fade_in.xml", "res/animator/lb_playback_description_fade_out.xml", "res/animator/lb_playback_bg_fade_out.xml", "res/animator/lb_decelerator_2.xml", "res/animator/lb_guidedstep_slide_down.xml", "res/animator/lb_playback_bg_fade_in.xml", "res/animator/lb_onboarding_description_enter.xml", "res/values-mk-rMK/values-mk-rMK.xml", "res/values-af/values-af.xml", "res/raw/lb_voice_open.ogg", "res/raw/lb_voice_no_input.ogg", "res/raw/lb_voice_failure.ogg", "res/raw/lb_voice_success.ogg", "res/drawable-v21/lb_card_foreground.xml", "res/drawable-v21/lb_selectable_item_rounded_rect.xml", "res/drawable-v21/lb_action_bg.xml", "res/drawable-v21/lb_control_button_secondary.xml", "res/drawable-v21/lb_control_button_primary.xml", "res/values-uk/values-uk.xml", "res/transition-v21/lb_vertical_grid_entrance_transition.xml", "res/transition-v21/lb_vertical_grid_enter_transition.xml", "res/transition-v21/lb_browse_headers_in.xml", "res/transition-v21/lb_browse_return_transition.xml", "res/transition-v21/lb_title_in.xml", "res/transition-v21/lb_return_transition.xml", "res/transition-v21/lb_browse_enter_transition.xml", "res/transition-v21/lb_guidedstep_activity_enter.xml", "res/transition-v21/lb_browse_headers_out.xml", "res/transition-v21/lb_shared_element_enter_transition.xml", "res/transition-v21/lb_details_return_transition.xml", "res/transition-v21/lb_shared_element_return_transition.xml", "res/transition-v21/lb_title_out.xml", "res/transition-v21/lb_guidedstep_activity_enter_bottom.xml", "res/transition-v21/lb_enter_transition.xml", "res/transition-v21/lb_vertical_grid_return_transition.xml", "res/transition-v21/lb_browse_entrance_transition.xml", "res/transition-v21/lb_details_enter_transition.xml", "res/values-zu/values-zu.xml", "res/values-et-rEE/values-et-rEE.xml", "res/values-v21/values-v21.xml", "res/values-lo-rLA/values-lo-rLA.xml", "res/drawable-hdpi-v4/lb_ic_search_mic_out.png", "res/drawable-hdpi-v4/lb_ic_sad_cloud.png", "res/drawable-hdpi-v4/lb_in_app_search_shadow_normal.9.png", "res/drawable-hdpi-v4/lb_in_app_search_shadow_focused.9.png", "res/drawable-hdpi-v4/lb_ic_actions_right_arrow.png", "res/drawable-hdpi-v4/lb_action_bg_focused.9.png", "res/drawable-hdpi-v4/lb_in_app_search_bg.9.png", "res/drawable-hdpi-v4/lb_ic_search_mic.png", "res/drawable-hdpi-v4/lb_ic_in_app_search.png", "res/values-v22/values-v22.xml", "res/values-bn-rBD/values-bn-rBD.xml", "res/values-is-rIS/values-is-rIS.xml", "res/values-gu-rIN/values-gu-rIN.xml", "res/drawable-mdpi-v4/lb_ic_search_mic_out.png", "res/drawable-mdpi-v4/lb_ic_sad_cloud.png", "res/drawable-mdpi-v4/lb_in_app_search_shadow_normal.9.png", "res/drawable-mdpi-v4/lb_in_app_search_shadow_focused.9.png", "res/drawable-mdpi-v4/lb_ic_actions_right_arrow.png", "res/drawable-mdpi-v4/lb_action_bg_focused.9.png", "res/drawable-mdpi-v4/lb_in_app_search_bg.9.png", "res/drawable-mdpi-v4/lb_ic_search_mic.png", "res/drawable-mdpi-v4/lb_ic_in_app_search.png", "res/values-pa-rIN/values-pa-rIN.xml", "res/values-mr-rIN/values-mr-rIN.xml", "res/values-ru/values-ru.xml", "res/values-pl/values-pl.xml", "res/values-fa/values-fa.xml", "res/values-be-rBY/values-be-rBY.xml", "res/values-si-rLK/values-si-rLK.xml", "res/values-sv/values-sv.xml", "res/values-my-rMM/values-my-rMM.xml", "res/values-b+sr+Latn/values-b+sr+Latn.xml", "res/values-fr/values-fr.xml", "res/values-uz-rUZ/values-uz-rUZ.xml", "res/values-ms-rMY/values-ms-rMY.xml", "res/values-ka-rGE/values-ka-rGE.xml", "res/values-fi/values-fi.xml", "res/values-fr-rCA/values-fr-rCA.xml", "res/values-ca/values-ca.xml", "res/values-in/values-in.xml", "res/values-vi/values-vi.xml", "res/layout/lb_row_media_item_action.xml", "res/layout/lb_error_fragment.xml", "res/layout/lb_picker.xml", "res/layout/lb_speech_orb.xml", "res/layout/lb_details_fragment.xml", "res/layout/lb_divider.xml", "res/layout/lb_guidedstep_fragment.xml", "res/layout/lb_background_window.xml", "res/layout/lb_rows_fragment.xml", "res/layout/lb_guidedstep_background.xml", "res/layout/lb_details_description.xml", "res/layout/lb_media_item_number_view_flipper.xml", "res/layout/lb_action_1_line.xml", "res/layout/lb_guidedbuttonactions.xml", "res/layout/lb_control_bar.xml", "res/layout/lb_vertical_grid_fragment.xml", "res/layout/lb_headers_fragment.xml", "res/layout/lb_guidance.xml", "res/layout/lb_fullwidth_details_overview_logo.xml", "res/layout/lb_header.xml", "res/layout/lb_browse_fragment.xml", "res/layout/lb_row_header.xml", "res/layout/lb_vertical_grid.xml", "res/layout/lb_control_button_secondary.xml", "res/layout/lb_details_overview.xml", "res/layout/lb_image_card_view_themed_badge_left.xml", "res/layout/lb_search_bar.xml", "res/layout/lb_list_row_hovercard.xml", "res/layout/lb_picker_column.xml", "res/layout/lb_image_card_view_themed_content.xml", "res/layout/lb_playback_now_playing_bars.xml", "res/layout/lb_row_media_item.xml", "res/layout/lb_shadow.xml", "res/layout/lb_picker_item.xml", "res/layout/lb_playback_controls_row.xml", "res/layout/lb_fullwidth_details_overview.xml", "res/layout/lb_guidedactions_item.xml", "res/layout/lb_control_button_primary.xml", "res/layout/lb_section_header.xml", "res/layout/lb_playback_controls.xml", "res/layout/lb_image_card_view_themed_badge_right.xml", "res/layout/lb_picker_separator.xml", "res/layout/lb_title_view.xml", "res/layout/lb_image_card_view.xml", "res/layout/lb_guidedactions_datepicker_item.xml", "res/layout/lb_action_2_lines.xml", "res/layout/lb_guidedactions.xml", "res/layout/lb_search_orb.xml", "res/layout/lb_search_fragment.xml", "res/layout/lb_row_container.xml", "res/layout/lb_list_row.xml", "res/layout/lb_browse_title.xml", "res/layout/lb_media_list_header.xml", "res/layout/lb_onboarding_fragment.xml", "res/layout/lb_image_card_view_themed_title.xml", "res/values-en-rGB/values-en-rGB.xml", "res/values-ja/values-ja.xml", "res/values-zh-rCN/values-zh-rCN.xml", "res/values-am/values-am.xml", "res/values-sq-rAL/values-sq-rAL.xml", "res/values-sl/values-sl.xml", "res/values-de/values-de.xml", "res/values-kk-rKZ/values-kk-rKZ.xml", "res/values-en-rAU/values-en-rAU.xml", "res/values-en-rIN/values-en-rIN.xml", "res/values-zh-rTW/values-zh-rTW.xml", "res/values-sw/values-sw.xml", "res/values-nb/values-nb.xml", "res/values-bs-rBA/values-bs-rBA.xml", "res/values-tr/values-tr.xml", "res/values-kn-rIN/values-kn-rIN.xml", "res/transition-v19/lb_browse_headers_in.xml", "res/transition-v19/lb_browse_headers_out.xml", "res/values-hy-rAM/values-hy-rAM.xml", "res/values-es-rUS/values-es-rUS.xml", "res/values-zh-rHK/values-zh-rHK.xml", "res/values-ko/values-ko.xml", "res/values-pt-rPT/values-pt-rPT.xml", "res/values-iw/values-iw.xml", "res/values-lt/values-lt.xml", "res/values-ro/values-ro.xml", "res/animator-v21/lb_playback_description_fade_out.xml", "res/animator-v21/lb_playback_bg_fade_out.xml", "res/animator-v21/lb_playback_bg_fade_in.xml", "res/values-pt/values-pt.xml", "res/values-ar/values-ar.xml", "res/values-ur-rPK/values-ur-rPK.xml", "res/values-ml-rIN/values-ml-rIN.xml", "res/drawable-xhdpi-v4/lb_ic_replay.png", "res/drawable-xhdpi-v4/lb_ic_nav_arrow.png", "res/drawable-xhdpi-v4/lb_text_dot_two_small.png", "res/drawable-xhdpi-v4/lb_text_dot_one_small.png", "res/drawable-xhdpi-v4/lb_ic_skip_previous.png", "res/drawable-xhdpi-v4/lb_ic_thumb_down.png", "res/drawable-xhdpi-v4/lb_ic_thumb_up_outline.png", "res/drawable-xhdpi-v4/lb_ic_search_mic_out.png", "res/drawable-xhdpi-v4/lb_ic_loop.png", "res/drawable-xhdpi-v4/lb_ic_play_fit.png", "res/drawable-xhdpi-v4/lb_ic_thumb_up.png", "res/drawable-xhdpi-v4/lb_ic_guidedactions_item_chevron.png", "res/drawable-xhdpi-v4/lb_ic_fast_rewind.png", "res/drawable-xhdpi-v4/lb_ic_shuffle.png", "res/drawable-xhdpi-v4/lb_ic_sad_cloud.png", "res/drawable-xhdpi-v4/lb_in_app_search_shadow_normal.9.png", "res/drawable-xhdpi-v4/lb_ic_fast_forward.png", "res/drawable-xhdpi-v4/lb_card_shadow_focused.9.png", "res/drawable-xhdpi-v4/lb_in_app_search_shadow_focused.9.png", "res/drawable-xhdpi-v4/lb_ic_actions_right_arrow.png", "res/drawable-xhdpi-v4/lb_action_bg_focused.9.png", "res/drawable-xhdpi-v4/lb_ic_hq.png", "res/drawable-xhdpi-v4/lb_in_app_search_bg.9.png", "res/drawable-xhdpi-v4/lb_ic_stop.png", "res/drawable-xhdpi-v4/lb_ic_search_mic.png", "res/drawable-xhdpi-v4/lb_card_shadow_normal.9.png", "res/drawable-xhdpi-v4/lb_ic_loop_one.png", "res/drawable-xhdpi-v4/lb_ic_in_app_search.png", "res/drawable-xhdpi-v4/lb_text_dot_one.png", "res/drawable-xhdpi-v4/lb_ic_pip.png", "res/drawable-xhdpi-v4/lb_text_dot_two.png", "res/drawable-xhdpi-v4/lb_ic_more.png", "res/drawable-xhdpi-v4/lb_ic_pause.png", "res/drawable-xhdpi-v4/lb_ic_cc.png", "res/drawable-xhdpi-v4/lb_ic_skip_next.png", "res/drawable-xhdpi-v4/lb_ic_thumb_down_outline.png", "res/drawable-xhdpi-v4/lb_ic_playback_loop.png", "res/drawable-xhdpi-v4/lb_ic_play.png", "res/values/values.xml", "res/values-hr/values-hr.xml", "res/values-mn-rMN/values-mn-rMN.xml", "res/values-da/values-da.xml", "res/values-hi/values-hi.xml", "res/values-it/values-it.xml", "res/values-es/values-es.xml", "res/values-sk/values-sk.xml", "res/values-lv/values-lv.xml", "res/values-ky-rKG/values-ky-rKG.xml", "res/values-hu/values-hu.xml", "res/drawable-xxhdpi-v4/lb_ic_search_mic_out.png", "res/drawable-xxhdpi-v4/lb_ic_sad_cloud.png", "res/drawable-xxhdpi-v4/lb_in_app_search_shadow_normal.9.png", "res/drawable-xxhdpi-v4/lb_in_app_search_shadow_focused.9.png", "res/drawable-xxhdpi-v4/lb_ic_actions_right_arrow.png", "res/drawable-xxhdpi-v4/lb_action_bg_focused.9.png", "res/drawable-xxhdpi-v4/lb_in_app_search_bg.9.png", "res/drawable-xxhdpi-v4/lb_ic_search_mic.png", "res/drawable-xxhdpi-v4/lb_ic_in_app_search.png", "res/values-v19/values-v19.xml", "res/values-th/values-th.xml", "res/values-cs/values-cs.xml", "res/values-sr/values-sr.xml", "res/values-tl/values-tl.xml", "res/values-te-rIN/values-te-rIN.xml", "res/values-ne-rNP/values-ne-rNP.xml", "res/values-ta-rIN/values-ta-rIN.xml", "res/drawable/lb_speech_orb.xml", "res/drawable/lb_playback_progress_bar.xml", "res/drawable/lb_card_foreground.xml", "res/drawable/lb_onboarding_start_button_background.xml", "res/drawable/lb_control_button_secondary.xml", "res/drawable/lb_playback_now_playing_bar.xml", "res/drawable/lb_control_button_primary.xml", "res/drawable/lb_background.xml", "res/drawable/lb_headers_right_fading.xml", "res/drawable/lb_search_orb.xml" ]
+resources = [ "res/values-ur/values-ur.xml", "res/values-ru/values-ru.xml", "res/values-en-rGB/values-en-rGB.xml", "res/values-pt-rBR/values-pt-rBR.xml", "res/values-el/values-el.xml", "res/drawable-hdpi-v4/lb_action_bg_focused.9.png", "res/drawable-hdpi-v4/lb_ic_search_mic.png", "res/drawable-hdpi-v4/lb_in_app_search_shadow_focused.9.png", "res/drawable-hdpi-v4/lb_ic_search_mic_out.png", "res/drawable-hdpi-v4/lb_in_app_search_bg.9.png", "res/drawable-hdpi-v4/lb_in_app_search_shadow_normal.9.png", "res/drawable-hdpi-v4/lb_ic_actions_right_arrow.png", "res/drawable-hdpi-v4/lb_ic_sad_cloud.png", "res/drawable-hdpi-v4/lb_ic_in_app_search.png", "res/values-tr/values-tr.xml", "res/values-hu/values-hu.xml", "res/values-v18/values-v18.xml", "res/values-km/values-km.xml", "res/values-fr-rCA/values-fr-rCA.xml", "res/values-gu/values-gu.xml", "res/layout/lb_browse_fragment.xml", "res/layout/lb_image_card_view_themed_title.xml", "res/layout/lb_list_row_hovercard.xml", "res/layout/lb_guidedactions.xml", "res/layout/lb_guidedactions_item.xml", "res/layout/lb_playback_transport_controls.xml", "res/layout/lb_image_card_view_themed_content.xml", "res/layout/lb_image_card_view_themed_badge_right.xml", "res/layout/lb_image_card_view.xml", "res/layout/lb_media_item_number_view_flipper.xml", "res/layout/lb_title_view.xml", "res/layout/lb_browse_title.xml", "res/layout/lb_control_bar.xml", "res/layout/lb_divider.xml", "res/layout/lb_background_window.xml", "res/layout/lb_guidance.xml", "res/layout/lb_shadow.xml", "res/layout/lb_video_surface.xml", "res/layout/lb_control_button_primary.xml", "res/layout/lb_fullwidth_details_overview_logo.xml", "res/layout/lb_onboarding_fragment.xml", "res/layout/lb_error_fragment.xml", "res/layout/lb_vertical_grid_fragment.xml", "res/layout/lb_action_1_line.xml", "res/layout/video_surface_fragment.xml", "res/layout/lb_guidedbuttonactions.xml", "res/layout/lb_picker_item.xml", "res/layout/lb_guidedstep_background.xml", "res/layout/lb_details_fragment.xml", "res/layout/lb_playback_controls_row.xml", "res/layout/lb_row_header.xml", "res/layout/lb_playback_transport_controls_row.xml", "res/layout/lb_search_orb.xml", "res/layout/lb_guidedstep_fragment.xml", "res/layout/lb_picker.xml", "res/layout/lb_speech_orb.xml", "res/layout/lb_playback_now_playing_bars.xml", "res/layout/lb_list_row.xml", "res/layout/lb_row_media_item_action.xml", "res/layout/lb_vertical_grid.xml", "res/layout/lb_header.xml", "res/layout/lb_row_media_item.xml", "res/layout/lb_playback_fragment.xml", "res/layout/lb_search_fragment.xml", "res/layout/lb_playback_controls.xml", "res/layout/lb_section_header.xml", "res/layout/lb_guidedactions_datepicker_item.xml", "res/layout/lb_details_description.xml", "res/layout/lb_details_overview.xml", "res/layout/lb_picker_column.xml", "res/layout/lb_media_list_header.xml", "res/layout/lb_image_card_view_themed_badge_left.xml", "res/layout/lb_rows_fragment.xml", "res/layout/lb_headers_fragment.xml", "res/layout/lb_action_2_lines.xml", "res/layout/lb_control_button_secondary.xml", "res/layout/lb_search_bar.xml", "res/layout/lb_row_container.xml", "res/layout/lb_fullwidth_details_overview.xml", "res/layout/lb_picker_separator.xml", "res/values-ms/values-ms.xml", "res/values-v21/values-v21.xml", "res/values-ja/values-ja.xml", "res/values-eu/values-eu.xml", "res/values-sv/values-sv.xml", "res/values-mn/values-mn.xml", "res/values-ta/values-ta.xml", "res/values-pl/values-pl.xml", "res/drawable-xxhdpi-v4/lb_action_bg_focused.9.png", "res/drawable-xxhdpi-v4/lb_ic_search_mic.png", "res/drawable-xxhdpi-v4/lb_in_app_search_shadow_focused.9.png", "res/drawable-xxhdpi-v4/lb_ic_search_mic_out.png", "res/drawable-xxhdpi-v4/lb_in_app_search_bg.9.png", "res/drawable-xxhdpi-v4/lb_in_app_search_shadow_normal.9.png", "res/drawable-xxhdpi-v4/lb_ic_actions_right_arrow.png", "res/drawable-xxhdpi-v4/lb_ic_sad_cloud.png", "res/drawable-xxhdpi-v4/lb_ic_in_app_search.png", "res/values-lt/values-lt.xml", "res/values-bg/values-bg.xml", "res/values-es-rUS/values-es-rUS.xml", "res/values-iw/values-iw.xml", "res/values-en-rXC/values-en-rXC.xml", "res/values-mr/values-mr.xml", "res/values-uz/values-uz.xml", "res/values-pa/values-pa.xml", "res/values-v22/values-v22.xml", "res/animator-v21/lb_onboarding_logo_exit.xml", "res/animator-v21/lb_onboarding_title_enter.xml", "res/animator-v21/lb_playback_bg_fade_out.xml", "res/animator-v21/lb_playback_bg_fade_in.xml", "res/animator-v21/lb_playback_description_fade_out.xml", "res/animator-v21/lb_onboarding_description_enter.xml", "res/animator-v21/lb_onboarding_logo_enter.xml", "res/animator-v21/lb_onboarding_page_indicator_enter.xml", "res/values-fi/values-fi.xml", "res/values-am/values-am.xml", "res/values-pt-rPT/values-pt-rPT.xml", "res/values-ar/values-ar.xml", "res/values-ky/values-ky.xml", "res/drawable-mdpi-v4/lb_action_bg_focused.9.png", "res/drawable-mdpi-v4/lb_ic_search_mic.png", "res/drawable-mdpi-v4/lb_in_app_search_shadow_focused.9.png", "res/drawable-mdpi-v4/lb_ic_search_mic_out.png", "res/drawable-mdpi-v4/lb_in_app_search_bg.9.png", "res/drawable-mdpi-v4/lb_in_app_search_shadow_normal.9.png", "res/drawable-mdpi-v4/lb_ic_actions_right_arrow.png", "res/drawable-mdpi-v4/lb_ic_sad_cloud.png", "res/drawable-mdpi-v4/lb_ic_in_app_search.png", "res/values-bs/values-bs.xml", "res/values/values.xml", "res/values-hr/values-hr.xml", "res/values-en-rAU/values-en-rAU.xml", "res/values-ro/values-ro.xml", "res/drawable-xhdpi-v4/lb_ic_pause.png", "res/drawable-xhdpi-v4/lb_ic_more.png", "res/drawable-xhdpi-v4/lb_action_bg_focused.9.png", "res/drawable-xhdpi-v4/lb_ic_skip_next.png", "res/drawable-xhdpi-v4/lb_ic_search_mic.png", "res/drawable-xhdpi-v4/lb_ic_fast_forward.png", "res/drawable-xhdpi-v4/lb_ic_shuffle.png", "res/drawable-xhdpi-v4/lb_ic_hq.png", "res/drawable-xhdpi-v4/lb_ic_skip_previous.png", "res/drawable-xhdpi-v4/lb_ic_replay.png", "res/drawable-xhdpi-v4/lb_text_dot_two.png", "res/drawable-xhdpi-v4/lb_ic_cc.png", "res/drawable-xhdpi-v4/lb_ic_thumb_up_outline.png", "res/drawable-xhdpi-v4/lb_ic_thumb_up.png", "res/drawable-xhdpi-v4/lb_in_app_search_shadow_focused.9.png", "res/drawable-xhdpi-v4/lb_ic_playback_loop.png", "res/drawable-xhdpi-v4/lb_text_dot_one.png", "res/drawable-xhdpi-v4/lb_ic_search_mic_out.png", "res/drawable-xhdpi-v4/lb_ic_loop_one.png", "res/drawable-xhdpi-v4/lb_text_dot_one_small.png", "res/drawable-xhdpi-v4/lb_ic_stop.png", "res/drawable-xhdpi-v4/lb_ic_pip.png", "res/drawable-xhdpi-v4/lb_card_shadow_normal.9.png", "res/drawable-xhdpi-v4/lb_ic_nav_arrow.png", "res/drawable-xhdpi-v4/lb_text_dot_two_small.png", "res/drawable-xhdpi-v4/lb_ic_loop.png", "res/drawable-xhdpi-v4/lb_ic_play.png", "res/drawable-xhdpi-v4/lb_ic_play_fit.png", "res/drawable-xhdpi-v4/lb_ic_fast_rewind.png", "res/drawable-xhdpi-v4/lb_in_app_search_bg.9.png", "res/drawable-xhdpi-v4/lb_ic_thumb_down_outline.png", "res/drawable-xhdpi-v4/lb_in_app_search_shadow_normal.9.png", "res/drawable-xhdpi-v4/lb_card_shadow_focused.9.png", "res/drawable-xhdpi-v4/lb_ic_actions_right_arrow.png", "res/drawable-xhdpi-v4/lb_ic_sad_cloud.png", "res/drawable-xhdpi-v4/lb_ic_thumb_down.png", "res/drawable-xhdpi-v4/lb_ic_guidedactions_item_chevron.png", "res/drawable-xhdpi-v4/lb_ic_in_app_search.png", "res/values-vi/values-vi.xml", "res/values-ko/values-ko.xml", "res/values-zh-rTW/values-zh-rTW.xml", "res/values-cs/values-cs.xml", "res/values-ml/values-ml.xml", "res/values-ldrtl-v17/values-ldrtl-v17.xml", "res/values-te/values-te.xml", "res/values-si/values-si.xml", "res/values-es/values-es.xml", "res/values-af/values-af.xml", "res/values-zu/values-zu.xml", "res/values-lo/values-lo.xml", "res/values-v19/values-v19.xml", "res/values-mk/values-mk.xml", "res/values-sl/values-sl.xml", "res/values-sw/values-sw.xml", "res/values-bn/values-bn.xml", "res/raw/lb_voice_open.ogg", "res/raw/lb_voice_success.ogg", "res/raw/lb_voice_failure.ogg", "res/raw/lb_voice_no_input.ogg", "res/transition-v21/lb_browse_headers_out.xml", "res/transition-v21/lb_browse_enter_transition.xml", "res/transition-v21/lb_return_transition.xml", "res/transition-v21/lb_details_return_transition.xml", "res/transition-v21/lb_browse_entrance_transition.xml", "res/transition-v21/lb_details_enter_transition.xml", "res/transition-v21/lb_enter_transition.xml", "res/transition-v21/lb_vertical_grid_entrance_transition.xml", "res/transition-v21/lb_shared_element_enter_transition.xml", "res/transition-v21/lb_guidedstep_activity_enter.xml", "res/transition-v21/lb_shared_element_return_transition.xml", "res/transition-v21/lb_title_in.xml", "res/transition-v21/lb_guidedstep_activity_enter_bottom.xml", "res/transition-v21/lb_title_out.xml", "res/transition-v21/lb_browse_return_transition.xml", "res/transition-v21/lb_vertical_grid_enter_transition.xml", "res/transition-v21/lb_vertical_grid_return_transition.xml", "res/transition-v21/lb_browse_headers_in.xml", "res/values-sk/values-sk.xml", "res/values-lv/values-lv.xml", "res/anim/lb_decelerator_4.xml", "res/anim/lb_decelerator_2.xml", "res/values-is/values-is.xml", "res/values-da/values-da.xml", "res/values-it/values-it.xml", "res/values-gl/values-gl.xml", "res/values-de/values-de.xml", "res/values-be/values-be.xml", "res/values-en-rCA/values-en-rCA.xml", "res/animator/lb_onboarding_page_indicator_fade_in.xml", "res/animator/lb_guidedstep_slide_down.xml", "res/animator/lb_onboarding_logo_exit.xml", "res/animator/lb_onboarding_title_enter.xml", "res/animator/lb_onboarding_start_button_fade_out.xml", "res/animator/lb_playback_rows_fade_out.xml", "res/animator/lb_playback_controls_fade_in.xml", "res/animator/lb_playback_description_fade_in.xml", "res/animator/lb_playback_bg_fade_out.xml", "res/animator/lb_playback_bg_fade_in.xml", "res/animator/lb_guidedactions_item_unpressed.xml", "res/animator/lb_playback_description_fade_out.xml", "res/animator/lb_onboarding_start_button_fade_in.xml", "res/animator/lb_playback_rows_fade_in.xml", "res/animator/lb_guidedactions_item_pressed.xml", "res/animator/lb_onboarding_description_enter.xml", "res/animator/lb_guidedstep_slide_up.xml", "res/animator/lb_onboarding_logo_enter.xml", "res/animator/lb_onboarding_page_indicator_enter.xml", "res/animator/lb_playback_controls_fade_out.xml", "res/animator/lb_onboarding_page_indicator_fade_out.xml", "res/values-fa/values-fa.xml", "res/values-ca/values-ca.xml", "res/values-th/values-th.xml", "res/values-nl/values-nl.xml", "res/values-hy/values-hy.xml", "res/values-zh-rHK/values-zh-rHK.xml", "res/values-tl/values-tl.xml", "res/values-kk/values-kk.xml", "res/values-pt/values-pt.xml", "res/values-my/values-my.xml", "res/values-et/values-et.xml", "res/values-en-rIN/values-en-rIN.xml", "res/values-sr/values-sr.xml", "res/values-fr/values-fr.xml", "res/values-kn/values-kn.xml", "res/values-nb/values-nb.xml", "res/values-ne/values-ne.xml", "res/transition-v19/lb_browse_headers_out.xml", "res/transition-v19/lb_browse_headers_in.xml", "res/drawable/lb_card_foreground.xml", "res/drawable/lb_control_button_primary.xml", "res/drawable/lb_playback_progress_bar.xml", "res/drawable/lb_onboarding_start_button_background.xml", "res/drawable/lb_search_orb.xml", "res/drawable/lb_speech_orb.xml", "res/drawable/lb_headers_right_fading.xml", "res/drawable/lb_background.xml", "res/drawable/lb_playback_now_playing_bar.xml", "res/drawable/lb_control_button_secondary.xml", "res/values-b+sr+Latn/values-b+sr+Latn.xml", "res/values-ka/values-ka.xml", "res/values-zh-rCN/values-zh-rCN.xml", "res/values-az/values-az.xml", "res/values-sq/values-sq.xml", "res/values-hi/values-hi.xml", "res/values-in/values-in.xml", "res/values-uk/values-uk.xml", "res/drawable-v21/lb_card_foreground.xml", "res/drawable-v21/lb_selectable_item_rounded_rect.xml", "res/drawable-v21/lb_control_button_primary.xml", "res/drawable-v21/lb_action_bg.xml", "res/drawable-v21/lb_control_button_secondary.xml" ]
 subjar_tuples = [  ]
 subjars = [  ]
diff --git a/build/secondary/third_party/android_tools/support/android_support_v17_preference_java.info b/build/secondary/third_party/android_tools/support/android_support_v17_preference_java.info
index e97682c1..87ea13e 100644
--- a/build/secondary/third_party/android_tools/support/android_support_v17_preference_java.info
+++ b/build/secondary/third_party/android_tools/support/android_support_v17_preference_java.info
@@ -8,6 +8,6 @@
 has_proguard_flags = false
 has_r_text_file = true
 is_manifest_empty = true
-resources = [ "res/layout/leanback_preference_category.xml", "res/layout/leanback_list_preference_item_single.xml", "res/layout/leanback_list_preference_fragment.xml", "res/layout/leanback_list_preference_item_multi.xml", "res/layout/leanback_settings_fragment.xml", "res/layout/leanback_preference_fragment.xml", "res/layout/leanback_preferences_list.xml", "res/layout/leanback_preference_information.xml", "res/layout/leanback_preference.xml", "res/values/values.xml", "res/layout-v21/leanback_settings_fragment.xml", "res/color/lb_preference_item_secondary_text_color.xml", "res/color/lb_preference_item_primary_text_color.xml" ]
+resources = [ "res/layout/leanback_preference_widget_seekbar.xml", "res/layout/leanback_preference_information.xml", "res/layout/leanback_preference.xml", "res/layout/leanback_preferences_list.xml", "res/layout/leanback_settings_fragment.xml", "res/layout/leanback_list_preference_item_single.xml", "res/layout/leanback_preference_category.xml", "res/layout/leanback_list_preference_fragment.xml", "res/layout/leanback_list_preference_item_multi.xml", "res/layout/leanback_preference_fragment.xml", "res/color/lb_preference_item_primary_text_color.xml", "res/color/lb_preference_item_secondary_text_color.xml", "res/values/values.xml", "res/layout-v21/leanback_settings_fragment.xml", "res/layout-v21/leanback_preference_category.xml" ]
 subjar_tuples = [  ]
 subjars = [  ]
diff --git a/build/secondary/third_party/android_tools/support/android_support_v7_appcompat_java_internal.info b/build/secondary/third_party/android_tools/support/android_support_v7_appcompat_java_internal.info
index 780717bb..e99e4de 100644
--- a/build/secondary/third_party/android_tools/support/android_support_v7_appcompat_java_internal.info
+++ b/build/secondary/third_party/android_tools/support/android_support_v7_appcompat_java_internal.info
@@ -8,6 +8,6 @@
 has_proguard_flags = false
 has_r_text_file = true
 is_manifest_empty = true
-resources = [ "res/values-v23/values-v23.xml", "res/values-km-rKH/values-km-rKH.xml", "res/values-nl/values-nl.xml", "res/values-az-rAZ/values-az-rAZ.xml", "res/values-port/values-port.xml", "res/values-gl-rES/values-gl-rES.xml", "res/values-bg/values-bg.xml", "res/values-v18/values-v18.xml", "res/values-xlarge-v4/values-xlarge-v4.xml", "res/values-pt-rBR/values-pt-rBR.xml", "res/values-eu-rES/values-eu-rES.xml", "res/values-el/values-el.xml", "res/values-mk-rMK/values-mk-rMK.xml", "res/values-af/values-af.xml", "res/drawable-ldrtl-xhdpi-v17/abc_spinner_mtrl_am_alpha.9.png", "res/drawable-ldrtl-xhdpi-v17/abc_ic_menu_copy_mtrl_am_alpha.png", "res/drawable-ldrtl-xhdpi-v17/abc_ic_menu_cut_mtrl_alpha.png", "res/drawable-ldrtl-xxxhdpi-v17/abc_spinner_mtrl_am_alpha.9.png", "res/drawable-ldrtl-xxxhdpi-v17/abc_ic_menu_copy_mtrl_am_alpha.png", "res/drawable-ldrtl-xxxhdpi-v17/abc_ic_menu_cut_mtrl_alpha.png", "res/drawable-v21/abc_btn_colored_material.xml", "res/drawable-v21/abc_edit_text_material.xml", "res/drawable-v21/notification_action_background.xml", "res/drawable-v21/abc_action_bar_item_background_material.xml", "res/values-uk/values-uk.xml", "res/values-zu/values-zu.xml", "res/values-et-rEE/values-et-rEE.xml", "res/values-v21/values-v21.xml", "res/values-lo-rLA/values-lo-rLA.xml", "res/drawable-hdpi-v4/abc_ic_menu_share_mtrl_alpha.png", "res/drawable-hdpi-v4/abc_list_pressed_holo_light.9.png", "res/drawable-hdpi-v4/abc_btn_switch_to_on_mtrl_00012.9.png", "res/drawable-hdpi-v4/abc_scrubber_control_off_mtrl_alpha.png", "res/drawable-hdpi-v4/abc_list_focused_holo.9.png", "res/drawable-hdpi-v4/abc_menu_hardkey_panel_mtrl_mult.9.png", "res/drawable-hdpi-v4/abc_textfield_activated_mtrl_alpha.9.png", "res/drawable-hdpi-v4/abc_popup_background_mtrl_mult.9.png", "res/drawable-hdpi-v4/abc_ic_star_black_36dp.png", "res/drawable-hdpi-v4/abc_list_selector_disabled_holo_dark.9.png", "res/drawable-hdpi-v4/abc_spinner_mtrl_am_alpha.9.png", "res/drawable-hdpi-v4/abc_text_select_handle_left_mtrl_light.png", "res/drawable-hdpi-v4/abc_list_longpressed_holo.9.png", "res/drawable-hdpi-v4/abc_btn_check_to_on_mtrl_000.png", "res/drawable-hdpi-v4/abc_list_pressed_holo_dark.9.png", "res/drawable-hdpi-v4/abc_cab_background_top_mtrl_alpha.9.png", "res/drawable-hdpi-v4/abc_btn_check_to_on_mtrl_015.png", "res/drawable-hdpi-v4/abc_text_select_handle_left_mtrl_dark.png", "res/drawable-hdpi-v4/abc_text_select_handle_middle_mtrl_light.png", "res/drawable-hdpi-v4/abc_switch_track_mtrl_alpha.9.png", "res/drawable-hdpi-v4/abc_ic_menu_selectall_mtrl_alpha.png", "res/drawable-hdpi-v4/notification_bg_low_normal.9.png", "res/drawable-hdpi-v4/abc_btn_radio_to_on_mtrl_015.png", "res/drawable-hdpi-v4/abc_text_select_handle_middle_mtrl_dark.png", "res/drawable-hdpi-v4/abc_tab_indicator_mtrl_alpha.9.png", "res/drawable-hdpi-v4/abc_ic_star_black_48dp.png", "res/drawable-hdpi-v4/abc_ic_menu_copy_mtrl_am_alpha.png", "res/drawable-hdpi-v4/abc_list_divider_mtrl_alpha.9.png", "res/drawable-hdpi-v4/abc_textfield_search_activated_mtrl_alpha.9.png", "res/drawable-hdpi-v4/abc_text_select_handle_right_mtrl_dark.png", "res/drawable-hdpi-v4/abc_scrubber_track_mtrl_alpha.9.png", "res/drawable-hdpi-v4/abc_scrubber_primary_mtrl_alpha.9.png", "res/drawable-hdpi-v4/abc_scrubber_control_to_pressed_mtrl_000.png", "res/drawable-hdpi-v4/abc_ic_star_half_black_16dp.png", "res/drawable-hdpi-v4/abc_scrubber_control_to_pressed_mtrl_005.png", "res/drawable-hdpi-v4/notification_bg_normal.9.png", "res/drawable-hdpi-v4/abc_ic_star_half_black_36dp.png", "res/drawable-hdpi-v4/notify_panel_notification_icon_bg.png", "res/drawable-hdpi-v4/abc_textfield_search_default_mtrl_alpha.9.png", "res/drawable-hdpi-v4/abc_text_select_handle_right_mtrl_light.png", "res/drawable-hdpi-v4/notification_bg_low_pressed.9.png", "res/drawable-hdpi-v4/abc_textfield_default_mtrl_alpha.9.png", "res/drawable-hdpi-v4/notification_bg_normal_pressed.9.png", "res/drawable-hdpi-v4/abc_ic_menu_paste_mtrl_am_alpha.png", "res/drawable-hdpi-v4/abc_btn_switch_to_on_mtrl_00001.9.png", "res/drawable-hdpi-v4/abc_ic_star_black_16dp.png", "res/drawable-hdpi-v4/abc_list_selector_disabled_holo_light.9.png", "res/drawable-hdpi-v4/abc_ic_commit_search_api_mtrl_alpha.png", "res/drawable-hdpi-v4/abc_ab_share_pack_mtrl_alpha.9.png", "res/drawable-hdpi-v4/abc_btn_radio_to_on_mtrl_000.png", "res/drawable-hdpi-v4/abc_ic_star_half_black_48dp.png", "res/drawable-hdpi-v4/abc_ic_menu_cut_mtrl_alpha.png", "res/values-v22/values-v22.xml", "res/values-bn-rBD/values-bn-rBD.xml", "res/values-v24/values-v24.xml", "res/values-is-rIS/values-is-rIS.xml", "res/values-gu-rIN/values-gu-rIN.xml", "res/drawable-mdpi-v4/abc_ic_menu_share_mtrl_alpha.png", "res/drawable-mdpi-v4/abc_list_pressed_holo_light.9.png", "res/drawable-mdpi-v4/abc_btn_switch_to_on_mtrl_00012.9.png", "res/drawable-mdpi-v4/abc_scrubber_control_off_mtrl_alpha.png", "res/drawable-mdpi-v4/abc_list_focused_holo.9.png", "res/drawable-mdpi-v4/abc_menu_hardkey_panel_mtrl_mult.9.png", "res/drawable-mdpi-v4/abc_textfield_activated_mtrl_alpha.9.png", "res/drawable-mdpi-v4/abc_popup_background_mtrl_mult.9.png", "res/drawable-mdpi-v4/abc_ic_star_black_36dp.png", "res/drawable-mdpi-v4/abc_list_selector_disabled_holo_dark.9.png", "res/drawable-mdpi-v4/abc_spinner_mtrl_am_alpha.9.png", "res/drawable-mdpi-v4/abc_text_select_handle_left_mtrl_light.png", "res/drawable-mdpi-v4/abc_list_longpressed_holo.9.png", "res/drawable-mdpi-v4/abc_btn_check_to_on_mtrl_000.png", "res/drawable-mdpi-v4/abc_list_pressed_holo_dark.9.png", "res/drawable-mdpi-v4/abc_cab_background_top_mtrl_alpha.9.png", "res/drawable-mdpi-v4/abc_btn_check_to_on_mtrl_015.png", "res/drawable-mdpi-v4/abc_text_select_handle_left_mtrl_dark.png", "res/drawable-mdpi-v4/abc_text_select_handle_middle_mtrl_light.png", "res/drawable-mdpi-v4/abc_switch_track_mtrl_alpha.9.png", "res/drawable-mdpi-v4/abc_ic_menu_selectall_mtrl_alpha.png", "res/drawable-mdpi-v4/notification_bg_low_normal.9.png", "res/drawable-mdpi-v4/abc_btn_radio_to_on_mtrl_015.png", "res/drawable-mdpi-v4/abc_text_select_handle_middle_mtrl_dark.png", "res/drawable-mdpi-v4/abc_tab_indicator_mtrl_alpha.9.png", "res/drawable-mdpi-v4/abc_ic_star_black_48dp.png", "res/drawable-mdpi-v4/abc_ic_menu_copy_mtrl_am_alpha.png", "res/drawable-mdpi-v4/abc_list_divider_mtrl_alpha.9.png", "res/drawable-mdpi-v4/abc_textfield_search_activated_mtrl_alpha.9.png", "res/drawable-mdpi-v4/abc_text_select_handle_right_mtrl_dark.png", "res/drawable-mdpi-v4/abc_scrubber_track_mtrl_alpha.9.png", "res/drawable-mdpi-v4/abc_scrubber_primary_mtrl_alpha.9.png", "res/drawable-mdpi-v4/abc_scrubber_control_to_pressed_mtrl_000.png", "res/drawable-mdpi-v4/abc_ic_star_half_black_16dp.png", "res/drawable-mdpi-v4/abc_scrubber_control_to_pressed_mtrl_005.png", "res/drawable-mdpi-v4/notification_bg_normal.9.png", "res/drawable-mdpi-v4/abc_ic_star_half_black_36dp.png", "res/drawable-mdpi-v4/notify_panel_notification_icon_bg.png", "res/drawable-mdpi-v4/abc_textfield_search_default_mtrl_alpha.9.png", "res/drawable-mdpi-v4/abc_text_select_handle_right_mtrl_light.png", "res/drawable-mdpi-v4/notification_bg_low_pressed.9.png", "res/drawable-mdpi-v4/abc_textfield_default_mtrl_alpha.9.png", "res/drawable-mdpi-v4/notification_bg_normal_pressed.9.png", "res/drawable-mdpi-v4/abc_ic_menu_paste_mtrl_am_alpha.png", "res/drawable-mdpi-v4/abc_btn_switch_to_on_mtrl_00001.9.png", "res/drawable-mdpi-v4/abc_ic_star_black_16dp.png", "res/drawable-mdpi-v4/abc_list_selector_disabled_holo_light.9.png", "res/drawable-mdpi-v4/abc_ic_commit_search_api_mtrl_alpha.png", "res/drawable-mdpi-v4/abc_ab_share_pack_mtrl_alpha.9.png", "res/drawable-mdpi-v4/abc_btn_radio_to_on_mtrl_000.png", "res/drawable-mdpi-v4/abc_ic_star_half_black_48dp.png", "res/drawable-mdpi-v4/abc_ic_menu_cut_mtrl_alpha.png", "res/values-pa-rIN/values-pa-rIN.xml", "res/values-mr-rIN/values-mr-rIN.xml", "res/values-ru/values-ru.xml", "res/values-pl/values-pl.xml", "res/values-fa/values-fa.xml", "res/values-v11/values-v11.xml", "res/values-be-rBY/values-be-rBY.xml", "res/values-si-rLK/values-si-rLK.xml", "res/values-sv/values-sv.xml", "res/anim/abc_popup_exit.xml", "res/anim/abc_slide_out_top.xml", "res/anim/abc_grow_fade_in_from_bottom.xml", "res/anim/abc_popup_enter.xml", "res/anim/abc_slide_in_bottom.xml", "res/anim/abc_shrink_fade_out_from_bottom.xml", "res/anim/abc_slide_in_top.xml", "res/anim/abc_fade_out.xml", "res/anim/abc_slide_out_bottom.xml", "res/anim/abc_fade_in.xml", "res/values-my-rMM/values-my-rMM.xml", "res/values-b+sr+Latn/values-b+sr+Latn.xml", "res/values-fr/values-fr.xml", "res/values-uz-rUZ/values-uz-rUZ.xml", "res/values-ms-rMY/values-ms-rMY.xml", "res/values-ka-rGE/values-ka-rGE.xml", "res/values-fi/values-fi.xml", "res/values-fr-rCA/values-fr-rCA.xml", "res/values-v17/values-v17.xml", "res/values-ca/values-ca.xml", "res/values-in/values-in.xml", "res/values-vi/values-vi.xml", "res/drawable-ldrtl-hdpi-v17/abc_spinner_mtrl_am_alpha.9.png", "res/drawable-ldrtl-hdpi-v17/abc_ic_menu_copy_mtrl_am_alpha.png", "res/drawable-ldrtl-hdpi-v17/abc_ic_menu_cut_mtrl_alpha.png", "res/layout/notification_media_cancel_action.xml", "res/layout/select_dialog_item_material.xml", "res/layout/notification_template_custom_big.xml", "res/layout/abc_action_bar_up_container.xml", "res/layout/abc_dialog_title_material.xml", "res/layout/notification_template_big_media_narrow.xml", "res/layout/abc_select_dialog_material.xml", "res/layout/abc_list_menu_item_layout.xml", "res/layout/notification_template_part_chronometer.xml", "res/layout/abc_popup_menu_header_item_layout.xml", "res/layout/notification_template_lines_media.xml", "res/layout/notification_template_part_time.xml", "res/layout/abc_list_menu_item_icon.xml", "res/layout/notification_action_tombstone.xml", "res/layout/abc_action_mode_bar.xml", "res/layout/notification_template_media_custom.xml", "res/layout/abc_popup_menu_item_layout.xml", "res/layout/abc_action_menu_item_layout.xml", "res/layout/abc_activity_chooser_view_list_item.xml", "res/layout/abc_list_menu_item_radio.xml", "res/layout/abc_screen_content_include.xml", "res/layout/abc_activity_chooser_view.xml", "res/layout/abc_alert_dialog_button_bar_material.xml", "res/layout/abc_action_menu_layout.xml", "res/layout/notification_template_big_media_narrow_custom.xml", "res/layout/notification_template_big_media_custom.xml", "res/layout/abc_list_menu_item_checkbox.xml", "res/layout/notification_media_action.xml", "res/layout/notification_template_icon_group.xml", "res/layout/abc_screen_simple.xml", "res/layout/abc_screen_simple_overlay_action_mode.xml", "res/layout/abc_screen_toolbar.xml", "res/layout/abc_alert_dialog_material.xml", "res/layout/abc_expanded_menu_layout.xml", "res/layout/abc_search_view.xml", "res/layout/notification_template_big_media.xml", "res/layout/abc_search_dropdown_item_icons_2line.xml", "res/layout/abc_action_bar_view_list_nav_layout.xml", "res/layout/select_dialog_multichoice_material.xml", "res/layout/abc_action_mode_close_item_material.xml", "res/layout/notification_template_media.xml", "res/layout/support_simple_spinner_dropdown_item.xml", "res/layout/notification_action.xml", "res/layout/abc_action_bar_title_item.xml", "res/layout/select_dialog_singlechoice_material.xml", "res/values-en-rGB/values-en-rGB.xml", "res/values-ja/values-ja.xml", "res/values-zh-rCN/values-zh-rCN.xml", "res/values-am/values-am.xml", "res/values-sq-rAL/values-sq-rAL.xml", "res/values-v16/values-v16.xml", "res/values-sl/values-sl.xml", "res/values-de/values-de.xml", "res/values-kk-rKZ/values-kk-rKZ.xml", "res/drawable-xxxhdpi-v4/abc_ic_menu_share_mtrl_alpha.png", "res/drawable-xxxhdpi-v4/abc_btn_switch_to_on_mtrl_00012.9.png", "res/drawable-xxxhdpi-v4/abc_ic_star_black_36dp.png", "res/drawable-xxxhdpi-v4/abc_spinner_mtrl_am_alpha.9.png", "res/drawable-xxxhdpi-v4/abc_text_select_handle_left_mtrl_light.png", "res/drawable-xxxhdpi-v4/abc_btn_check_to_on_mtrl_000.png", "res/drawable-xxxhdpi-v4/abc_btn_check_to_on_mtrl_015.png", "res/drawable-xxxhdpi-v4/abc_text_select_handle_left_mtrl_dark.png", "res/drawable-xxxhdpi-v4/abc_switch_track_mtrl_alpha.9.png", "res/drawable-xxxhdpi-v4/abc_ic_menu_selectall_mtrl_alpha.png", "res/drawable-xxxhdpi-v4/abc_btn_radio_to_on_mtrl_015.png", "res/drawable-xxxhdpi-v4/abc_tab_indicator_mtrl_alpha.9.png", "res/drawable-xxxhdpi-v4/abc_ic_star_black_48dp.png", "res/drawable-xxxhdpi-v4/abc_ic_menu_copy_mtrl_am_alpha.png", "res/drawable-xxxhdpi-v4/abc_text_select_handle_right_mtrl_dark.png", "res/drawable-xxxhdpi-v4/abc_scrubber_control_to_pressed_mtrl_000.png", "res/drawable-xxxhdpi-v4/abc_ic_star_half_black_16dp.png", "res/drawable-xxxhdpi-v4/abc_scrubber_control_to_pressed_mtrl_005.png", "res/drawable-xxxhdpi-v4/abc_ic_star_half_black_36dp.png", "res/drawable-xxxhdpi-v4/abc_text_select_handle_right_mtrl_light.png", "res/drawable-xxxhdpi-v4/abc_ic_menu_paste_mtrl_am_alpha.png", "res/drawable-xxxhdpi-v4/abc_btn_switch_to_on_mtrl_00001.9.png", "res/drawable-xxxhdpi-v4/abc_ic_star_black_16dp.png", "res/drawable-xxxhdpi-v4/abc_btn_radio_to_on_mtrl_000.png", "res/drawable-xxxhdpi-v4/abc_ic_star_half_black_48dp.png", "res/drawable-xxxhdpi-v4/abc_ic_menu_cut_mtrl_alpha.png", "res/values-en-rAU/values-en-rAU.xml", "res/values-en-rIN/values-en-rIN.xml", "res/values-zh-rTW/values-zh-rTW.xml", "res/values-sw/values-sw.xml", "res/values-nb/values-nb.xml", "res/values-h720dp-v13/values-h720dp-v13.xml", "res/values-bs-rBA/values-bs-rBA.xml", "res/values-tr/values-tr.xml", "res/drawable-ldrtl-mdpi-v17/abc_spinner_mtrl_am_alpha.9.png", "res/drawable-ldrtl-mdpi-v17/abc_ic_menu_copy_mtrl_am_alpha.png", "res/drawable-ldrtl-mdpi-v17/abc_ic_menu_cut_mtrl_alpha.png", "res/drawable-v23/abc_control_background_material.xml", "res/values-kn-rIN/values-kn-rIN.xml", "res/values-hy-rAM/values-hy-rAM.xml", "res/values-sw600dp-v13/values-sw600dp-v13.xml", "res/values-es-rUS/values-es-rUS.xml", "res/values-land/values-land.xml", "res/values-zh-rHK/values-zh-rHK.xml", "res/drawable-ldrtl-xxhdpi-v17/abc_spinner_mtrl_am_alpha.9.png", "res/drawable-ldrtl-xxhdpi-v17/abc_ic_menu_copy_mtrl_am_alpha.png", "res/drawable-ldrtl-xxhdpi-v17/abc_ic_menu_cut_mtrl_alpha.png", "res/values-large-v4/values-large-v4.xml", "res/values-ko/values-ko.xml", "res/values-pt-rPT/values-pt-rPT.xml", "res/values-iw/values-iw.xml", "res/values-lt/values-lt.xml", "res/values-ro/values-ro.xml", "res/values-v14/values-v14.xml", "res/values-pt/values-pt.xml", "res/layout-v16/notification_template_custom_big.xml", "res/values-ar/values-ar.xml", "res/color-v23/abc_tint_seek_thumb.xml", "res/color-v23/abc_tint_btn_checkable.xml", "res/color-v23/abc_tint_edittext.xml", "res/color-v23/abc_tint_switch_thumb.xml", "res/color-v23/abc_btn_colored_borderless_text_material.xml", "res/color-v23/abc_tint_default.xml", "res/color-v23/abc_color_highlight_material.xml", "res/color-v23/abc_tint_spinner.xml", "res/color-v23/abc_tint_switch_track.xml", "res/values-hdpi-v4/values-hdpi-v4.xml", "res/values-ur-rPK/values-ur-rPK.xml", "res/values-ml-rIN/values-ml-rIN.xml", "res/drawable-xhdpi-v4/abc_ic_menu_share_mtrl_alpha.png", "res/drawable-xhdpi-v4/abc_list_pressed_holo_light.9.png", "res/drawable-xhdpi-v4/abc_btn_switch_to_on_mtrl_00012.9.png", "res/drawable-xhdpi-v4/abc_scrubber_control_off_mtrl_alpha.png", "res/drawable-xhdpi-v4/abc_list_focused_holo.9.png", "res/drawable-xhdpi-v4/abc_menu_hardkey_panel_mtrl_mult.9.png", "res/drawable-xhdpi-v4/abc_textfield_activated_mtrl_alpha.9.png", "res/drawable-xhdpi-v4/abc_popup_background_mtrl_mult.9.png", "res/drawable-xhdpi-v4/abc_ic_star_black_36dp.png", "res/drawable-xhdpi-v4/abc_list_selector_disabled_holo_dark.9.png", "res/drawable-xhdpi-v4/abc_spinner_mtrl_am_alpha.9.png", "res/drawable-xhdpi-v4/abc_text_select_handle_left_mtrl_light.png", "res/drawable-xhdpi-v4/abc_list_longpressed_holo.9.png", "res/drawable-xhdpi-v4/abc_btn_check_to_on_mtrl_000.png", "res/drawable-xhdpi-v4/abc_list_pressed_holo_dark.9.png", "res/drawable-xhdpi-v4/abc_cab_background_top_mtrl_alpha.9.png", "res/drawable-xhdpi-v4/abc_btn_check_to_on_mtrl_015.png", "res/drawable-xhdpi-v4/abc_text_select_handle_left_mtrl_dark.png", "res/drawable-xhdpi-v4/abc_text_select_handle_middle_mtrl_light.png", "res/drawable-xhdpi-v4/abc_switch_track_mtrl_alpha.9.png", "res/drawable-xhdpi-v4/abc_ic_menu_selectall_mtrl_alpha.png", "res/drawable-xhdpi-v4/notification_bg_low_normal.9.png", "res/drawable-xhdpi-v4/abc_btn_radio_to_on_mtrl_015.png", "res/drawable-xhdpi-v4/abc_text_select_handle_middle_mtrl_dark.png", "res/drawable-xhdpi-v4/abc_tab_indicator_mtrl_alpha.9.png", "res/drawable-xhdpi-v4/abc_ic_star_black_48dp.png", "res/drawable-xhdpi-v4/abc_ic_menu_copy_mtrl_am_alpha.png", "res/drawable-xhdpi-v4/abc_list_divider_mtrl_alpha.9.png", "res/drawable-xhdpi-v4/abc_textfield_search_activated_mtrl_alpha.9.png", "res/drawable-xhdpi-v4/abc_text_select_handle_right_mtrl_dark.png", "res/drawable-xhdpi-v4/abc_scrubber_track_mtrl_alpha.9.png", "res/drawable-xhdpi-v4/abc_scrubber_primary_mtrl_alpha.9.png", "res/drawable-xhdpi-v4/abc_scrubber_control_to_pressed_mtrl_000.png", "res/drawable-xhdpi-v4/abc_ic_star_half_black_16dp.png", "res/drawable-xhdpi-v4/abc_scrubber_control_to_pressed_mtrl_005.png", "res/drawable-xhdpi-v4/notification_bg_normal.9.png", "res/drawable-xhdpi-v4/abc_ic_star_half_black_36dp.png", "res/drawable-xhdpi-v4/notify_panel_notification_icon_bg.png", "res/drawable-xhdpi-v4/abc_textfield_search_default_mtrl_alpha.9.png", "res/drawable-xhdpi-v4/abc_text_select_handle_right_mtrl_light.png", "res/drawable-xhdpi-v4/notification_bg_low_pressed.9.png", "res/drawable-xhdpi-v4/abc_textfield_default_mtrl_alpha.9.png", "res/drawable-xhdpi-v4/notification_bg_normal_pressed.9.png", "res/drawable-xhdpi-v4/abc_ic_menu_paste_mtrl_am_alpha.png", "res/drawable-xhdpi-v4/abc_btn_switch_to_on_mtrl_00001.9.png", "res/drawable-xhdpi-v4/abc_ic_star_black_16dp.png", "res/drawable-xhdpi-v4/abc_list_selector_disabled_holo_light.9.png", "res/drawable-xhdpi-v4/abc_ic_commit_search_api_mtrl_alpha.png", "res/drawable-xhdpi-v4/abc_ab_share_pack_mtrl_alpha.9.png", "res/drawable-xhdpi-v4/abc_btn_radio_to_on_mtrl_000.png", "res/drawable-xhdpi-v4/abc_ic_star_half_black_48dp.png", "res/drawable-xhdpi-v4/abc_ic_menu_cut_mtrl_alpha.png", "res/values/values.xml", "res/values-hr/values-hr.xml", "res/values-mn-rMN/values-mn-rMN.xml", "res/values-da/values-da.xml", "res/values-hi/values-hi.xml", "res/values-it/values-it.xml", "res/color-v11/abc_background_cache_hint_selector_material_light.xml", "res/color-v11/abc_background_cache_hint_selector_material_dark.xml", "res/values-night-v8/values-night-v8.xml", "res/values-es/values-es.xml", "res/values-sk/values-sk.xml", "res/layout-v21/notification_template_custom_big.xml", "res/layout-v21/notification_action_tombstone.xml", "res/layout-v21/notification_template_icon_group.xml", "res/layout-v21/notification_action.xml", "res/values-lv/values-lv.xml", "res/values-ky-rKG/values-ky-rKG.xml", "res/values-v25/values-v25.xml", "res/values-hu/values-hu.xml", "res/drawable-xxhdpi-v4/abc_ic_menu_share_mtrl_alpha.png", "res/drawable-xxhdpi-v4/abc_list_pressed_holo_light.9.png", "res/drawable-xxhdpi-v4/abc_btn_switch_to_on_mtrl_00012.9.png", "res/drawable-xxhdpi-v4/abc_scrubber_control_off_mtrl_alpha.png", "res/drawable-xxhdpi-v4/abc_list_focused_holo.9.png", "res/drawable-xxhdpi-v4/abc_menu_hardkey_panel_mtrl_mult.9.png", "res/drawable-xxhdpi-v4/abc_textfield_activated_mtrl_alpha.9.png", "res/drawable-xxhdpi-v4/abc_popup_background_mtrl_mult.9.png", "res/drawable-xxhdpi-v4/abc_ic_star_black_36dp.png", "res/drawable-xxhdpi-v4/abc_list_selector_disabled_holo_dark.9.png", "res/drawable-xxhdpi-v4/abc_spinner_mtrl_am_alpha.9.png", "res/drawable-xxhdpi-v4/abc_text_select_handle_left_mtrl_light.png", "res/drawable-xxhdpi-v4/abc_list_longpressed_holo.9.png", "res/drawable-xxhdpi-v4/abc_btn_check_to_on_mtrl_000.png", "res/drawable-xxhdpi-v4/abc_list_pressed_holo_dark.9.png", "res/drawable-xxhdpi-v4/abc_cab_background_top_mtrl_alpha.9.png", "res/drawable-xxhdpi-v4/abc_btn_check_to_on_mtrl_015.png", "res/drawable-xxhdpi-v4/abc_text_select_handle_left_mtrl_dark.png", "res/drawable-xxhdpi-v4/abc_text_select_handle_middle_mtrl_light.png", "res/drawable-xxhdpi-v4/abc_switch_track_mtrl_alpha.9.png", "res/drawable-xxhdpi-v4/abc_ic_menu_selectall_mtrl_alpha.png", "res/drawable-xxhdpi-v4/abc_btn_radio_to_on_mtrl_015.png", "res/drawable-xxhdpi-v4/abc_text_select_handle_middle_mtrl_dark.png", "res/drawable-xxhdpi-v4/abc_tab_indicator_mtrl_alpha.9.png", "res/drawable-xxhdpi-v4/abc_ic_star_black_48dp.png", "res/drawable-xxhdpi-v4/abc_ic_menu_copy_mtrl_am_alpha.png", "res/drawable-xxhdpi-v4/abc_list_divider_mtrl_alpha.9.png", "res/drawable-xxhdpi-v4/abc_textfield_search_activated_mtrl_alpha.9.png", "res/drawable-xxhdpi-v4/abc_text_select_handle_right_mtrl_dark.png", "res/drawable-xxhdpi-v4/abc_scrubber_track_mtrl_alpha.9.png", "res/drawable-xxhdpi-v4/abc_scrubber_primary_mtrl_alpha.9.png", "res/drawable-xxhdpi-v4/abc_scrubber_control_to_pressed_mtrl_000.png", "res/drawable-xxhdpi-v4/abc_ic_star_half_black_16dp.png", "res/drawable-xxhdpi-v4/abc_scrubber_control_to_pressed_mtrl_005.png", "res/drawable-xxhdpi-v4/abc_ic_star_half_black_36dp.png", "res/drawable-xxhdpi-v4/abc_textfield_search_default_mtrl_alpha.9.png", "res/drawable-xxhdpi-v4/abc_text_select_handle_right_mtrl_light.png", "res/drawable-xxhdpi-v4/abc_textfield_default_mtrl_alpha.9.png", "res/drawable-xxhdpi-v4/abc_ic_menu_paste_mtrl_am_alpha.png", "res/drawable-xxhdpi-v4/abc_btn_switch_to_on_mtrl_00001.9.png", "res/drawable-xxhdpi-v4/abc_ic_star_black_16dp.png", "res/drawable-xxhdpi-v4/abc_list_selector_disabled_holo_light.9.png", "res/drawable-xxhdpi-v4/abc_ic_commit_search_api_mtrl_alpha.png", "res/drawable-xxhdpi-v4/abc_ab_share_pack_mtrl_alpha.9.png", "res/drawable-xxhdpi-v4/abc_btn_radio_to_on_mtrl_000.png", "res/drawable-xxhdpi-v4/abc_ic_star_half_black_48dp.png", "res/drawable-xxhdpi-v4/abc_ic_menu_cut_mtrl_alpha.png", "res/color/abc_search_url_text.xml", "res/color/switch_thumb_material_dark.xml", "res/color/abc_hint_foreground_material_light.xml", "res/color/abc_secondary_text_material_dark.xml", "res/color/abc_tint_seek_thumb.xml", "res/color/abc_tint_btn_checkable.xml", "res/color/abc_tint_edittext.xml", "res/color/abc_hint_foreground_material_dark.xml", "res/color/switch_thumb_material_light.xml", "res/color/abc_tint_switch_thumb.xml", "res/color/abc_btn_colored_borderless_text_material.xml", "res/color/abc_primary_text_material_light.xml", "res/color/abc_background_cache_hint_selector_material_light.xml", "res/color/abc_secondary_text_material_light.xml", "res/color/abc_primary_text_disable_only_material_light.xml", "res/color/abc_primary_text_disable_only_material_dark.xml", "res/color/abc_tint_default.xml", "res/color/abc_tint_spinner.xml", "res/color/abc_tint_switch_track.xml", "res/color/abc_background_cache_hint_selector_material_dark.xml", "res/color/abc_primary_text_material_dark.xml", "res/values-v12/values-v12.xml", "res/values-th/values-th.xml", "res/values-cs/values-cs.xml", "res/values-sr/values-sr.xml", "res/values-v13/values-v13.xml", "res/values-tl/values-tl.xml", "res/values-te-rIN/values-te-rIN.xml", "res/values-ne-rNP/values-ne-rNP.xml", "res/values-ta-rIN/values-ta-rIN.xml", "res/values-ldltr-v21/values-ldltr-v21.xml", "res/drawable/abc_switch_thumb_material.xml", "res/drawable/abc_btn_borderless_material.xml", "res/drawable/abc_textfield_search_material.xml", "res/drawable/abc_seekbar_track_material.xml", "res/drawable/abc_btn_colored_material.xml", "res/drawable/abc_ratingbar_indicator_material.xml", "res/drawable/notification_tile_bg.xml", "res/drawable/abc_ic_ab_back_material.xml", "res/drawable/notification_icon_background.xml", "res/drawable/notification_bg_low.xml", "res/drawable/abc_btn_default_mtrl_shape.xml", "res/drawable/abc_seekbar_thumb_material.xml", "res/drawable/abc_cab_background_internal_bg.xml", "res/drawable/abc_dialog_material_background.xml", "res/drawable/abc_text_cursor_material.xml", "res/drawable/notification_bg.xml", "res/drawable/abc_btn_radio_material.xml", "res/drawable/abc_item_background_holo_dark.xml", "res/drawable/abc_list_selector_holo_light.xml", "res/drawable/abc_ic_voice_search_api_material.xml", "res/drawable/abc_ic_search_api_material.xml", "res/drawable/abc_cab_background_top_material.xml", "res/drawable/abc_list_selector_background_transition_holo_dark.xml", "res/drawable/abc_edit_text_material.xml", "res/drawable/abc_tab_indicator_material.xml", "res/drawable/abc_ratingbar_material.xml", "res/drawable/abc_seekbar_tick_mark_material.xml", "res/drawable/abc_ic_go_search_api_material.xml", "res/drawable/abc_list_selector_holo_dark.xml", "res/drawable/abc_ic_arrow_drop_right_black_24dp.xml", "res/drawable/abc_btn_check_material.xml", "res/drawable/abc_spinner_textfield_background_material.xml", "res/drawable/abc_ic_clear_material.xml", "res/drawable/abc_item_background_holo_light.xml", "res/drawable/abc_list_selector_background_transition_holo_light.xml", "res/drawable/abc_ic_menu_overflow_material.xml", "res/drawable/abc_vector_test.xml", "res/drawable/abc_ratingbar_small_material.xml" ]
+resources = [ "res/values-ur/values-ur.xml", "res/values-ru/values-ru.xml", "res/values-en-rGB/values-en-rGB.xml", "res/values-pt-rBR/values-pt-rBR.xml", "res/values-el/values-el.xml", "res/drawable-hdpi-v4/abc_ab_share_pack_mtrl_alpha.9.png", "res/drawable-hdpi-v4/abc_btn_switch_to_on_mtrl_00012.9.png", "res/drawable-hdpi-v4/abc_list_longpressed_holo.9.png", "res/drawable-hdpi-v4/abc_ic_star_black_48dp.png", "res/drawable-hdpi-v4/abc_ic_commit_search_api_mtrl_alpha.png", "res/drawable-hdpi-v4/abc_text_select_handle_middle_mtrl_light.png", "res/drawable-hdpi-v4/abc_list_focused_holo.9.png", "res/drawable-hdpi-v4/abc_popup_background_mtrl_mult.9.png", "res/drawable-hdpi-v4/abc_ic_star_black_36dp.png", "res/drawable-hdpi-v4/abc_text_select_handle_right_mtrl_dark.png", "res/drawable-hdpi-v4/abc_btn_switch_to_on_mtrl_00001.9.png", "res/drawable-hdpi-v4/abc_btn_check_to_on_mtrl_000.png", "res/drawable-hdpi-v4/abc_text_select_handle_left_mtrl_light.png", "res/drawable-hdpi-v4/abc_ic_menu_selectall_mtrl_alpha.png", "res/drawable-hdpi-v4/abc_textfield_default_mtrl_alpha.9.png", "res/drawable-hdpi-v4/abc_scrubber_primary_mtrl_alpha.9.png", "res/drawable-hdpi-v4/abc_scrubber_control_to_pressed_mtrl_000.png", "res/drawable-hdpi-v4/abc_switch_track_mtrl_alpha.9.png", "res/drawable-hdpi-v4/abc_ic_star_black_16dp.png", "res/drawable-hdpi-v4/abc_scrubber_control_off_mtrl_alpha.png", "res/drawable-hdpi-v4/abc_ic_menu_cut_mtrl_alpha.png", "res/drawable-hdpi-v4/abc_ic_star_half_black_36dp.png", "res/drawable-hdpi-v4/abc_list_selector_disabled_holo_light.9.png", "res/drawable-hdpi-v4/abc_text_select_handle_left_mtrl_dark.png", "res/drawable-hdpi-v4/abc_ic_menu_paste_mtrl_am_alpha.png", "res/drawable-hdpi-v4/abc_btn_radio_to_on_mtrl_015.png", "res/drawable-hdpi-v4/abc_list_pressed_holo_dark.9.png", "res/drawable-hdpi-v4/abc_list_pressed_holo_light.9.png", "res/drawable-hdpi-v4/abc_tab_indicator_mtrl_alpha.9.png", "res/drawable-hdpi-v4/abc_textfield_search_default_mtrl_alpha.9.png", "res/drawable-hdpi-v4/abc_text_select_handle_right_mtrl_light.png", "res/drawable-hdpi-v4/abc_btn_check_to_on_mtrl_015.png", "res/drawable-hdpi-v4/abc_list_selector_disabled_holo_dark.9.png", "res/drawable-hdpi-v4/abc_ic_star_half_black_16dp.png", "res/drawable-hdpi-v4/abc_ic_star_half_black_48dp.png", "res/drawable-hdpi-v4/abc_ic_menu_share_mtrl_alpha.png", "res/drawable-hdpi-v4/abc_textfield_search_activated_mtrl_alpha.9.png", "res/drawable-hdpi-v4/abc_btn_radio_to_on_mtrl_000.png", "res/drawable-hdpi-v4/abc_list_divider_mtrl_alpha.9.png", "res/drawable-hdpi-v4/abc_ic_menu_copy_mtrl_am_alpha.png", "res/drawable-hdpi-v4/abc_spinner_mtrl_am_alpha.9.png", "res/drawable-hdpi-v4/abc_scrubber_track_mtrl_alpha.9.png", "res/drawable-hdpi-v4/abc_text_select_handle_middle_mtrl_dark.png", "res/drawable-hdpi-v4/abc_scrubber_control_to_pressed_mtrl_005.png", "res/drawable-hdpi-v4/abc_menu_hardkey_panel_mtrl_mult.9.png", "res/drawable-hdpi-v4/abc_cab_background_top_mtrl_alpha.9.png", "res/drawable-hdpi-v4/abc_textfield_activated_mtrl_alpha.9.png", "res/values-tr/values-tr.xml", "res/values-hu/values-hu.xml", "res/values-v18/values-v18.xml", "res/values-km/values-km.xml", "res/values-fr-rCA/values-fr-rCA.xml", "res/values-gu/values-gu.xml", "res/layout/abc_list_menu_item_layout.xml", "res/layout/abc_action_menu_layout.xml", "res/layout/abc_search_dropdown_item_icons_2line.xml", "res/layout/support_simple_spinner_dropdown_item.xml", "res/layout/abc_screen_simple.xml", "res/layout/abc_action_menu_item_layout.xml", "res/layout/abc_list_menu_item_radio.xml", "res/layout/abc_alert_dialog_title_material.xml", "res/layout/abc_alert_dialog_material.xml", "res/layout/abc_screen_toolbar.xml", "res/layout/abc_screen_simple_overlay_action_mode.xml", "res/layout/abc_select_dialog_material.xml", "res/layout/abc_action_mode_bar.xml", "res/layout/abc_dialog_title_material.xml", "res/layout/abc_list_menu_item_checkbox.xml", "res/layout/abc_popup_menu_header_item_layout.xml", "res/layout/abc_action_bar_up_container.xml", "res/layout/select_dialog_singlechoice_material.xml", "res/layout/abc_action_mode_close_item_material.xml", "res/layout/tooltip.xml", "res/layout/select_dialog_multichoice_material.xml", "res/layout/abc_action_bar_title_item.xml", "res/layout/abc_activity_chooser_view_list_item.xml", "res/layout/abc_popup_menu_item_layout.xml", "res/layout/abc_alert_dialog_button_bar_material.xml", "res/layout/abc_list_menu_item_icon.xml", "res/layout/abc_expanded_menu_layout.xml", "res/layout/select_dialog_item_material.xml", "res/layout/abc_activity_chooser_view.xml", "res/layout/abc_search_view.xml", "res/layout/abc_screen_content_include.xml", "res/values-ms/values-ms.xml", "res/values-v21/values-v21.xml", "res/values-ja/values-ja.xml", "res/values-eu/values-eu.xml", "res/values-hdpi-v4/values-hdpi-v4.xml", "res/values-sv/values-sv.xml", "res/values-mn/values-mn.xml", "res/values-v14/values-v14.xml", "res/values-ta/values-ta.xml", "res/values-v23/values-v23.xml", "res/values-pl/values-pl.xml", "res/drawable-xxhdpi-v4/abc_ab_share_pack_mtrl_alpha.9.png", "res/drawable-xxhdpi-v4/abc_btn_switch_to_on_mtrl_00012.9.png", "res/drawable-xxhdpi-v4/abc_list_longpressed_holo.9.png", "res/drawable-xxhdpi-v4/abc_ic_star_black_48dp.png", "res/drawable-xxhdpi-v4/abc_ic_commit_search_api_mtrl_alpha.png", "res/drawable-xxhdpi-v4/abc_text_select_handle_middle_mtrl_light.png", "res/drawable-xxhdpi-v4/abc_list_focused_holo.9.png", "res/drawable-xxhdpi-v4/abc_popup_background_mtrl_mult.9.png", "res/drawable-xxhdpi-v4/abc_ic_star_black_36dp.png", "res/drawable-xxhdpi-v4/abc_text_select_handle_right_mtrl_dark.png", "res/drawable-xxhdpi-v4/abc_btn_switch_to_on_mtrl_00001.9.png", "res/drawable-xxhdpi-v4/abc_btn_check_to_on_mtrl_000.png", "res/drawable-xxhdpi-v4/abc_text_select_handle_left_mtrl_light.png", "res/drawable-xxhdpi-v4/abc_ic_menu_selectall_mtrl_alpha.png", "res/drawable-xxhdpi-v4/abc_textfield_default_mtrl_alpha.9.png", "res/drawable-xxhdpi-v4/abc_scrubber_primary_mtrl_alpha.9.png", "res/drawable-xxhdpi-v4/abc_scrubber_control_to_pressed_mtrl_000.png", "res/drawable-xxhdpi-v4/abc_switch_track_mtrl_alpha.9.png", "res/drawable-xxhdpi-v4/abc_ic_star_black_16dp.png", "res/drawable-xxhdpi-v4/abc_scrubber_control_off_mtrl_alpha.png", "res/drawable-xxhdpi-v4/abc_ic_menu_cut_mtrl_alpha.png", "res/drawable-xxhdpi-v4/abc_ic_star_half_black_36dp.png", "res/drawable-xxhdpi-v4/abc_list_selector_disabled_holo_light.9.png", "res/drawable-xxhdpi-v4/abc_text_select_handle_left_mtrl_dark.png", "res/drawable-xxhdpi-v4/abc_ic_menu_paste_mtrl_am_alpha.png", "res/drawable-xxhdpi-v4/abc_btn_radio_to_on_mtrl_015.png", "res/drawable-xxhdpi-v4/abc_list_pressed_holo_dark.9.png", "res/drawable-xxhdpi-v4/abc_list_pressed_holo_light.9.png", "res/drawable-xxhdpi-v4/abc_tab_indicator_mtrl_alpha.9.png", "res/drawable-xxhdpi-v4/abc_textfield_search_default_mtrl_alpha.9.png", "res/drawable-xxhdpi-v4/abc_text_select_handle_right_mtrl_light.png", "res/drawable-xxhdpi-v4/abc_btn_check_to_on_mtrl_015.png", "res/drawable-xxhdpi-v4/abc_list_selector_disabled_holo_dark.9.png", "res/drawable-xxhdpi-v4/abc_ic_star_half_black_16dp.png", "res/drawable-xxhdpi-v4/abc_ic_star_half_black_48dp.png", "res/drawable-xxhdpi-v4/abc_ic_menu_share_mtrl_alpha.png", "res/drawable-xxhdpi-v4/abc_textfield_search_activated_mtrl_alpha.9.png", "res/drawable-xxhdpi-v4/abc_btn_radio_to_on_mtrl_000.png", "res/drawable-xxhdpi-v4/abc_list_divider_mtrl_alpha.9.png", "res/drawable-xxhdpi-v4/abc_ic_menu_copy_mtrl_am_alpha.png", "res/drawable-xxhdpi-v4/abc_spinner_mtrl_am_alpha.9.png", "res/drawable-xxhdpi-v4/abc_scrubber_track_mtrl_alpha.9.png", "res/drawable-xxhdpi-v4/abc_text_select_handle_middle_mtrl_dark.png", "res/drawable-xxhdpi-v4/abc_scrubber_control_to_pressed_mtrl_005.png", "res/drawable-xxhdpi-v4/abc_menu_hardkey_panel_mtrl_mult.9.png", "res/drawable-xxhdpi-v4/abc_cab_background_top_mtrl_alpha.9.png", "res/drawable-xxhdpi-v4/abc_textfield_activated_mtrl_alpha.9.png", "res/color/abc_search_url_text.xml", "res/color/abc_btn_colored_borderless_text_material.xml", "res/color/abc_primary_text_material_light.xml", "res/color/abc_tint_seek_thumb.xml", "res/color/abc_tint_btn_checkable.xml", "res/color/abc_secondary_text_material_dark.xml", "res/color/abc_tint_edittext.xml", "res/color/abc_tint_spinner.xml", "res/color/abc_primary_text_material_dark.xml", "res/color/abc_secondary_text_material_light.xml", "res/color/switch_thumb_material_dark.xml", "res/color/abc_hint_foreground_material_dark.xml", "res/color/abc_tint_switch_track.xml", "res/color/abc_primary_text_disable_only_material_dark.xml", "res/color/abc_btn_colored_text_material.xml", "res/color/abc_hint_foreground_material_light.xml", "res/color/switch_thumb_material_light.xml", "res/color/abc_tint_default.xml", "res/color/abc_primary_text_disable_only_material_light.xml", "res/values-ldltr-v21/values-ldltr-v21.xml", "res/values-lt/values-lt.xml", "res/values-bg/values-bg.xml", "res/values-es-rUS/values-es-rUS.xml", "res/values-iw/values-iw.xml", "res/values-en-rXC/values-en-rXC.xml", "res/values-mr/values-mr.xml", "res/values-uz/values-uz.xml", "res/values-large-v4/values-large-v4.xml", "res/values-v11/values-v11.xml", "res/color-v11/abc_background_cache_hint_selector_material_light.xml", "res/color-v11/abc_background_cache_hint_selector_material_dark.xml", "res/values-pa/values-pa.xml", "res/values-v22/values-v22.xml", "res/values-v25/values-v25.xml", "res/values-fi/values-fi.xml", "res/values-am/values-am.xml", "res/values-pt-rPT/values-pt-rPT.xml", "res/values-ar/values-ar.xml", "res/values-ky/values-ky.xml", "res/values-v12/values-v12.xml", "res/drawable-mdpi-v4/abc_ab_share_pack_mtrl_alpha.9.png", "res/drawable-mdpi-v4/abc_btn_switch_to_on_mtrl_00012.9.png", "res/drawable-mdpi-v4/abc_list_longpressed_holo.9.png", "res/drawable-mdpi-v4/abc_ic_star_black_48dp.png", "res/drawable-mdpi-v4/abc_ic_commit_search_api_mtrl_alpha.png", "res/drawable-mdpi-v4/abc_text_select_handle_middle_mtrl_light.png", "res/drawable-mdpi-v4/abc_list_focused_holo.9.png", "res/drawable-mdpi-v4/abc_popup_background_mtrl_mult.9.png", "res/drawable-mdpi-v4/abc_ic_star_black_36dp.png", "res/drawable-mdpi-v4/abc_text_select_handle_right_mtrl_dark.png", "res/drawable-mdpi-v4/abc_btn_switch_to_on_mtrl_00001.9.png", "res/drawable-mdpi-v4/abc_btn_check_to_on_mtrl_000.png", "res/drawable-mdpi-v4/abc_text_select_handle_left_mtrl_light.png", "res/drawable-mdpi-v4/abc_ic_menu_selectall_mtrl_alpha.png", "res/drawable-mdpi-v4/abc_textfield_default_mtrl_alpha.9.png", "res/drawable-mdpi-v4/abc_scrubber_primary_mtrl_alpha.9.png", "res/drawable-mdpi-v4/abc_scrubber_control_to_pressed_mtrl_000.png", "res/drawable-mdpi-v4/abc_switch_track_mtrl_alpha.9.png", "res/drawable-mdpi-v4/abc_ic_star_black_16dp.png", "res/drawable-mdpi-v4/abc_scrubber_control_off_mtrl_alpha.png", "res/drawable-mdpi-v4/abc_ic_menu_cut_mtrl_alpha.png", "res/drawable-mdpi-v4/abc_ic_star_half_black_36dp.png", "res/drawable-mdpi-v4/abc_list_selector_disabled_holo_light.9.png", "res/drawable-mdpi-v4/abc_text_select_handle_left_mtrl_dark.png", "res/drawable-mdpi-v4/abc_ic_menu_paste_mtrl_am_alpha.png", "res/drawable-mdpi-v4/abc_btn_radio_to_on_mtrl_015.png", "res/drawable-mdpi-v4/abc_list_pressed_holo_dark.9.png", "res/drawable-mdpi-v4/abc_list_pressed_holo_light.9.png", "res/drawable-mdpi-v4/abc_tab_indicator_mtrl_alpha.9.png", "res/drawable-mdpi-v4/abc_textfield_search_default_mtrl_alpha.9.png", "res/drawable-mdpi-v4/abc_text_select_handle_right_mtrl_light.png", "res/drawable-mdpi-v4/abc_btn_check_to_on_mtrl_015.png", "res/drawable-mdpi-v4/abc_list_selector_disabled_holo_dark.9.png", "res/drawable-mdpi-v4/abc_ic_star_half_black_16dp.png", "res/drawable-mdpi-v4/abc_ic_star_half_black_48dp.png", "res/drawable-mdpi-v4/abc_ic_menu_share_mtrl_alpha.png", "res/drawable-mdpi-v4/abc_textfield_search_activated_mtrl_alpha.9.png", "res/drawable-mdpi-v4/abc_btn_radio_to_on_mtrl_000.png", "res/drawable-mdpi-v4/abc_list_divider_mtrl_alpha.9.png", "res/drawable-mdpi-v4/abc_ic_menu_copy_mtrl_am_alpha.png", "res/drawable-mdpi-v4/abc_spinner_mtrl_am_alpha.9.png", "res/drawable-mdpi-v4/abc_scrubber_track_mtrl_alpha.9.png", "res/drawable-mdpi-v4/abc_text_select_handle_middle_mtrl_dark.png", "res/drawable-mdpi-v4/abc_scrubber_control_to_pressed_mtrl_005.png", "res/drawable-mdpi-v4/abc_menu_hardkey_panel_mtrl_mult.9.png", "res/drawable-mdpi-v4/abc_cab_background_top_mtrl_alpha.9.png", "res/drawable-mdpi-v4/abc_textfield_activated_mtrl_alpha.9.png", "res/values-bs/values-bs.xml", "res/values/values.xml", "res/values-hr/values-hr.xml", "res/values-v24/values-v24.xml", "res/drawable-ldrtl-xxhdpi-v17/abc_ic_menu_cut_mtrl_alpha.png", "res/drawable-ldrtl-xxhdpi-v17/abc_ic_menu_copy_mtrl_am_alpha.png", "res/drawable-ldrtl-xxhdpi-v17/abc_spinner_mtrl_am_alpha.9.png", "res/drawable-ldrtl-xhdpi-v17/abc_ic_menu_cut_mtrl_alpha.png", "res/drawable-ldrtl-xhdpi-v17/abc_ic_menu_copy_mtrl_am_alpha.png", "res/drawable-ldrtl-xhdpi-v17/abc_spinner_mtrl_am_alpha.9.png", "res/values-en-rAU/values-en-rAU.xml", "res/values-ro/values-ro.xml", "res/drawable-xhdpi-v4/abc_ab_share_pack_mtrl_alpha.9.png", "res/drawable-xhdpi-v4/abc_btn_switch_to_on_mtrl_00012.9.png", "res/drawable-xhdpi-v4/abc_list_longpressed_holo.9.png", "res/drawable-xhdpi-v4/abc_ic_star_black_48dp.png", "res/drawable-xhdpi-v4/abc_ic_commit_search_api_mtrl_alpha.png", "res/drawable-xhdpi-v4/abc_text_select_handle_middle_mtrl_light.png", "res/drawable-xhdpi-v4/abc_list_focused_holo.9.png", "res/drawable-xhdpi-v4/abc_popup_background_mtrl_mult.9.png", "res/drawable-xhdpi-v4/abc_ic_star_black_36dp.png", "res/drawable-xhdpi-v4/abc_text_select_handle_right_mtrl_dark.png", "res/drawable-xhdpi-v4/abc_btn_switch_to_on_mtrl_00001.9.png", "res/drawable-xhdpi-v4/abc_btn_check_to_on_mtrl_000.png", "res/drawable-xhdpi-v4/abc_text_select_handle_left_mtrl_light.png", "res/drawable-xhdpi-v4/abc_ic_menu_selectall_mtrl_alpha.png", "res/drawable-xhdpi-v4/abc_textfield_default_mtrl_alpha.9.png", "res/drawable-xhdpi-v4/abc_scrubber_primary_mtrl_alpha.9.png", "res/drawable-xhdpi-v4/abc_scrubber_control_to_pressed_mtrl_000.png", "res/drawable-xhdpi-v4/abc_switch_track_mtrl_alpha.9.png", "res/drawable-xhdpi-v4/abc_ic_star_black_16dp.png", "res/drawable-xhdpi-v4/abc_scrubber_control_off_mtrl_alpha.png", "res/drawable-xhdpi-v4/abc_ic_menu_cut_mtrl_alpha.png", "res/drawable-xhdpi-v4/abc_ic_star_half_black_36dp.png", "res/drawable-xhdpi-v4/abc_list_selector_disabled_holo_light.9.png", "res/drawable-xhdpi-v4/abc_text_select_handle_left_mtrl_dark.png", "res/drawable-xhdpi-v4/abc_ic_menu_paste_mtrl_am_alpha.png", "res/drawable-xhdpi-v4/abc_btn_radio_to_on_mtrl_015.png", "res/drawable-xhdpi-v4/abc_list_pressed_holo_dark.9.png", "res/drawable-xhdpi-v4/abc_list_pressed_holo_light.9.png", "res/drawable-xhdpi-v4/abc_tab_indicator_mtrl_alpha.9.png", "res/drawable-xhdpi-v4/abc_textfield_search_default_mtrl_alpha.9.png", "res/drawable-xhdpi-v4/abc_text_select_handle_right_mtrl_light.png", "res/drawable-xhdpi-v4/abc_btn_check_to_on_mtrl_015.png", "res/drawable-xhdpi-v4/abc_list_selector_disabled_holo_dark.9.png", "res/drawable-xhdpi-v4/abc_ic_star_half_black_16dp.png", "res/drawable-xhdpi-v4/abc_ic_star_half_black_48dp.png", "res/drawable-xhdpi-v4/abc_ic_menu_share_mtrl_alpha.png", "res/drawable-xhdpi-v4/abc_textfield_search_activated_mtrl_alpha.9.png", "res/drawable-xhdpi-v4/abc_btn_radio_to_on_mtrl_000.png", "res/drawable-xhdpi-v4/abc_list_divider_mtrl_alpha.9.png", "res/drawable-xhdpi-v4/abc_ic_menu_copy_mtrl_am_alpha.png", "res/drawable-xhdpi-v4/abc_spinner_mtrl_am_alpha.9.png", "res/drawable-xhdpi-v4/abc_scrubber_track_mtrl_alpha.9.png", "res/drawable-xhdpi-v4/abc_text_select_handle_middle_mtrl_dark.png", "res/drawable-xhdpi-v4/abc_scrubber_control_to_pressed_mtrl_005.png", "res/drawable-xhdpi-v4/abc_menu_hardkey_panel_mtrl_mult.9.png", "res/drawable-xhdpi-v4/abc_cab_background_top_mtrl_alpha.9.png", "res/drawable-xhdpi-v4/abc_textfield_activated_mtrl_alpha.9.png", "res/values-vi/values-vi.xml", "res/values-ko/values-ko.xml", "res/values-zh-rTW/values-zh-rTW.xml", "res/drawable-ldrtl-mdpi-v17/abc_ic_menu_cut_mtrl_alpha.png", "res/drawable-ldrtl-mdpi-v17/abc_ic_menu_copy_mtrl_am_alpha.png", "res/drawable-ldrtl-mdpi-v17/abc_spinner_mtrl_am_alpha.9.png", "res/values-cs/values-cs.xml", "res/values-ml/values-ml.xml", "res/values-te/values-te.xml", "res/values-si/values-si.xml", "res/values-es/values-es.xml", "res/values-af/values-af.xml", "res/values-zu/values-zu.xml", "res/values-lo/values-lo.xml", "res/values-land/values-land.xml", "res/values-mk/values-mk.xml", "res/values-sl/values-sl.xml", "res/values-xlarge-v4/values-xlarge-v4.xml", "res/values-sw600dp-v13/values-sw600dp-v13.xml", "res/values-sw/values-sw.xml", "res/values-bn/values-bn.xml", "res/values-sk/values-sk.xml", "res/values-lv/values-lv.xml", "res/anim/abc_shrink_fade_out_from_bottom.xml", "res/anim/abc_slide_in_bottom.xml", "res/anim/abc_fade_out.xml", "res/anim/abc_slide_in_top.xml", "res/anim/abc_slide_out_top.xml", "res/anim/tooltip_exit.xml", "res/anim/abc_popup_exit.xml", "res/anim/abc_grow_fade_in_from_bottom.xml", "res/anim/tooltip_enter.xml", "res/anim/abc_fade_in.xml", "res/anim/abc_slide_out_bottom.xml", "res/anim/abc_popup_enter.xml", "res/values-is/values-is.xml", "res/values-da/values-da.xml", "res/values-it/values-it.xml", "res/values-gl/values-gl.xml", "res/values-de/values-de.xml", "res/values-be/values-be.xml", "res/values-en-rCA/values-en-rCA.xml", "res/drawable-ldrtl-xxxhdpi-v17/abc_ic_menu_cut_mtrl_alpha.png", "res/drawable-ldrtl-xxxhdpi-v17/abc_ic_menu_copy_mtrl_am_alpha.png", "res/drawable-ldrtl-xxxhdpi-v17/abc_spinner_mtrl_am_alpha.9.png", "res/values-fa/values-fa.xml", "res/values-ca/values-ca.xml", "res/values-th/values-th.xml", "res/values-nl/values-nl.xml", "res/values-hy/values-hy.xml", "res/values-zh-rHK/values-zh-rHK.xml", "res/values-tl/values-tl.xml", "res/values-kk/values-kk.xml", "res/values-pt/values-pt.xml", "res/values-my/values-my.xml", "res/values-night-v8/values-night-v8.xml", "res/drawable-v23/abc_control_background_material.xml", "res/drawable-xxxhdpi-v4/abc_btn_switch_to_on_mtrl_00012.9.png", "res/drawable-xxxhdpi-v4/abc_ic_star_black_48dp.png", "res/drawable-xxxhdpi-v4/abc_ic_star_black_36dp.png", "res/drawable-xxxhdpi-v4/abc_text_select_handle_right_mtrl_dark.png", "res/drawable-xxxhdpi-v4/abc_btn_switch_to_on_mtrl_00001.9.png", "res/drawable-xxxhdpi-v4/abc_btn_check_to_on_mtrl_000.png", "res/drawable-xxxhdpi-v4/abc_text_select_handle_left_mtrl_light.png", "res/drawable-xxxhdpi-v4/abc_ic_menu_selectall_mtrl_alpha.png", "res/drawable-xxxhdpi-v4/abc_scrubber_control_to_pressed_mtrl_000.png", "res/drawable-xxxhdpi-v4/abc_switch_track_mtrl_alpha.9.png", "res/drawable-xxxhdpi-v4/abc_ic_star_black_16dp.png", "res/drawable-xxxhdpi-v4/abc_ic_menu_cut_mtrl_alpha.png", "res/drawable-xxxhdpi-v4/abc_ic_star_half_black_36dp.png", "res/drawable-xxxhdpi-v4/abc_text_select_handle_left_mtrl_dark.png", "res/drawable-xxxhdpi-v4/abc_ic_menu_paste_mtrl_am_alpha.png", "res/drawable-xxxhdpi-v4/abc_btn_radio_to_on_mtrl_015.png", "res/drawable-xxxhdpi-v4/abc_tab_indicator_mtrl_alpha.9.png", "res/drawable-xxxhdpi-v4/abc_text_select_handle_right_mtrl_light.png", "res/drawable-xxxhdpi-v4/abc_btn_check_to_on_mtrl_015.png", "res/drawable-xxxhdpi-v4/abc_ic_star_half_black_16dp.png", "res/drawable-xxxhdpi-v4/abc_ic_star_half_black_48dp.png", "res/drawable-xxxhdpi-v4/abc_ic_menu_share_mtrl_alpha.png", "res/drawable-xxxhdpi-v4/abc_btn_radio_to_on_mtrl_000.png", "res/drawable-xxxhdpi-v4/abc_ic_menu_copy_mtrl_am_alpha.png", "res/drawable-xxxhdpi-v4/abc_spinner_mtrl_am_alpha.9.png", "res/drawable-xxxhdpi-v4/abc_scrubber_control_to_pressed_mtrl_005.png", "res/values-et/values-et.xml", "res/values-en-rIN/values-en-rIN.xml", "res/values-sr/values-sr.xml", "res/values-v16/values-v16.xml", "res/values-fr/values-fr.xml", "res/values-kn/values-kn.xml", "res/values-nb/values-nb.xml", "res/drawable-ldrtl-hdpi-v17/abc_ic_menu_cut_mtrl_alpha.png", "res/drawable-ldrtl-hdpi-v17/abc_ic_menu_copy_mtrl_am_alpha.png", "res/drawable-ldrtl-hdpi-v17/abc_spinner_mtrl_am_alpha.9.png", "res/layout-v26/abc_screen_toolbar.xml", "res/values-v26/values-v26.xml", "res/values-port/values-port.xml", "res/color-v23/abc_btn_colored_borderless_text_material.xml", "res/color-v23/abc_color_highlight_material.xml", "res/color-v23/abc_tint_seek_thumb.xml", "res/color-v23/abc_tint_btn_checkable.xml", "res/color-v23/abc_tint_edittext.xml", "res/color-v23/abc_tint_spinner.xml", "res/color-v23/abc_tint_switch_track.xml", "res/color-v23/abc_btn_colored_text_material.xml", "res/color-v23/abc_tint_default.xml", "res/values-v17/values-v17.xml", "res/values-ne/values-ne.xml", "res/values-v13/values-v13.xml", "res/drawable/abc_tab_indicator_material.xml", "res/drawable/abc_item_background_holo_dark.xml", "res/drawable/abc_edit_text_material.xml", "res/drawable/abc_ic_voice_search_api_material.xml", "res/drawable/abc_ic_menu_overflow_material.xml", "res/drawable/abc_ic_search_api_material.xml", "res/drawable/abc_cab_background_top_material.xml", "res/drawable/abc_list_selector_holo_light.xml", "res/drawable/abc_ic_arrow_drop_right_black_24dp.xml", "res/drawable/abc_spinner_textfield_background_material.xml", "res/drawable/abc_ratingbar_small_material.xml", "res/drawable/tooltip_frame_dark.xml", "res/drawable/abc_item_background_holo_light.xml", "res/drawable/abc_btn_colored_material.xml", "res/drawable/abc_ratingbar_material.xml", "res/drawable/abc_cab_background_internal_bg.xml", "res/drawable/abc_btn_radio_material.xml", "res/drawable/tooltip_frame_light.xml", "res/drawable/abc_ic_clear_material.xml", "res/drawable/abc_ic_ab_back_material.xml", "res/drawable/abc_textfield_search_material.xml", "res/drawable/abc_ic_go_search_api_material.xml", "res/drawable/abc_seekbar_track_material.xml", "res/drawable/abc_dialog_material_background.xml", "res/drawable/abc_seekbar_tick_mark_material.xml", "res/drawable/abc_list_selector_background_transition_holo_light.xml", "res/drawable/abc_text_cursor_material.xml", "res/drawable/abc_btn_default_mtrl_shape.xml", "res/drawable/abc_ratingbar_indicator_material.xml", "res/drawable/abc_switch_thumb_material.xml", "res/drawable/abc_seekbar_thumb_material.xml", "res/drawable/abc_list_selector_background_transition_holo_dark.xml", "res/drawable/abc_btn_check_material.xml", "res/drawable/abc_list_selector_holo_dark.xml", "res/drawable/abc_btn_borderless_material.xml", "res/drawable/abc_vector_test.xml", "res/values-b+sr+Latn/values-b+sr+Latn.xml", "res/values-h720dp-v13/values-h720dp-v13.xml", "res/values-ka/values-ka.xml", "res/values-zh-rCN/values-zh-rCN.xml", "res/values-az/values-az.xml", "res/values-sq/values-sq.xml", "res/values-hi/values-hi.xml", "res/values-in/values-in.xml", "res/values-uk/values-uk.xml", "res/drawable-v21/abc_edit_text_material.xml", "res/drawable-v21/abc_btn_colored_material.xml", "res/drawable-v21/abc_action_bar_item_background_material.xml" ]
 subjar_tuples = [  ]
 subjars = [  ]
diff --git a/build/secondary/third_party/android_tools/support/android_support_v7_mediarouter_java.info b/build/secondary/third_party/android_tools/support/android_support_v7_mediarouter_java.info
index 55b51f5..6fc7871 100644
--- a/build/secondary/third_party/android_tools/support/android_support_v7_mediarouter_java.info
+++ b/build/secondary/third_party/android_tools/support/android_support_v7_mediarouter_java.info
@@ -8,6 +8,6 @@
 has_proguard_flags = false
 has_r_text_file = true
 is_manifest_empty = true
-resources = [ "res/values-km-rKH/values-km-rKH.xml", "res/values-nl/values-nl.xml", "res/values-az-rAZ/values-az-rAZ.xml", "res/values-gl-rES/values-gl-rES.xml", "res/values-bg/values-bg.xml", "res/values-pt-rBR/values-pt-rBR.xml", "res/values-eu-rES/values-eu-rES.xml", "res/values-el/values-el.xml", "res/values-sw720dp-v13/values-sw720dp-v13.xml", "res/values-mk-rMK/values-mk-rMK.xml", "res/values-af/values-af.xml", "res/values-uk/values-uk.xml", "res/values-zu/values-zu.xml", "res/values-et-rEE/values-et-rEE.xml", "res/values-lo-rLA/values-lo-rLA.xml", "res/drawable-hdpi-v4/ic_mr_button_disconnected_light.png", "res/drawable-hdpi-v4/ic_vol_type_speaker_group_light.png", "res/drawable-hdpi-v4/ic_audiotrack_light.png", "res/drawable-hdpi-v4/ic_vol_type_speaker_light.png", "res/drawable-hdpi-v4/ic_vol_type_tv_dark.png", "res/drawable-hdpi-v4/ic_dialog_close_dark.png", "res/drawable-hdpi-v4/ic_vol_type_tv_light.png", "res/drawable-hdpi-v4/ic_mr_button_disabled_dark.png", "res/drawable-hdpi-v4/ic_mr_button_disabled_light.png", "res/drawable-hdpi-v4/ic_dialog_close_light.png", "res/drawable-hdpi-v4/ic_mr_button_disconnected_dark.png", "res/drawable-hdpi-v4/ic_vol_type_speaker_group_dark.png", "res/drawable-hdpi-v4/ic_vol_type_speaker_dark.png", "res/drawable-hdpi-v4/ic_media_pause_light.png", "res/drawable-hdpi-v4/ic_mr_button_grey.png", "res/drawable-hdpi-v4/ic_audiotrack_dark.png", "res/drawable-hdpi-v4/ic_media_play_light.png", "res/drawable-hdpi-v4/ic_media_pause_dark.png", "res/drawable-hdpi-v4/ic_media_play_dark.png", "res/values-bn-rBD/values-bn-rBD.xml", "res/values-is-rIS/values-is-rIS.xml", "res/values-gu-rIN/values-gu-rIN.xml", "res/drawable-mdpi-v4/ic_mr_button_disconnected_light.png", "res/drawable-mdpi-v4/ic_vol_type_speaker_group_light.png", "res/drawable-mdpi-v4/ic_audiotrack_light.png", "res/drawable-mdpi-v4/ic_vol_type_speaker_light.png", "res/drawable-mdpi-v4/ic_vol_type_tv_dark.png", "res/drawable-mdpi-v4/ic_dialog_close_dark.png", "res/drawable-mdpi-v4/ic_vol_type_tv_light.png", "res/drawable-mdpi-v4/ic_mr_button_disabled_dark.png", "res/drawable-mdpi-v4/ic_mr_button_disabled_light.png", "res/drawable-mdpi-v4/ic_dialog_close_light.png", "res/drawable-mdpi-v4/ic_mr_button_disconnected_dark.png", "res/drawable-mdpi-v4/ic_vol_type_speaker_group_dark.png", "res/drawable-mdpi-v4/ic_vol_type_speaker_dark.png", "res/drawable-mdpi-v4/ic_media_pause_light.png", "res/drawable-mdpi-v4/ic_mr_button_grey.png", "res/drawable-mdpi-v4/ic_audiotrack_dark.png", "res/drawable-mdpi-v4/ic_media_play_light.png", "res/drawable-mdpi-v4/ic_media_pause_dark.png", "res/drawable-mdpi-v4/ic_media_play_dark.png", "res/values-pa-rIN/values-pa-rIN.xml", "res/values-mr-rIN/values-mr-rIN.xml", "res/values-ru/values-ru.xml", "res/values-pl/values-pl.xml", "res/values-fa/values-fa.xml", "res/values-be-rBY/values-be-rBY.xml", "res/values-si-rLK/values-si-rLK.xml", "res/values-sv/values-sv.xml", "res/values-my-rMM/values-my-rMM.xml", "res/values-b+sr+Latn/values-b+sr+Latn.xml", "res/interpolator/mr_linear_out_slow_in.xml", "res/interpolator/mr_fast_out_slow_in.xml", "res/values-fr/values-fr.xml", "res/values-uz-rUZ/values-uz-rUZ.xml", "res/values-ms-rMY/values-ms-rMY.xml", "res/values-ka-rGE/values-ka-rGE.xml", "res/values-fi/values-fi.xml", "res/values-fr-rCA/values-fr-rCA.xml", "res/values-ca/values-ca.xml", "res/values-in/values-in.xml", "res/values-vi/values-vi.xml", "res/layout/mr_controller_material_dialog_b.xml", "res/layout/mr_chooser_dialog.xml", "res/layout/mr_chooser_list_item.xml", "res/layout/mr_volume_control.xml", "res/layout/mr_playback_control.xml", "res/layout/mr_controller_volume_item.xml", "res/values-en-rGB/values-en-rGB.xml", "res/values-ja/values-ja.xml", "res/values-zh-rCN/values-zh-rCN.xml", "res/values-am/values-am.xml", "res/values-sq-rAL/values-sq-rAL.xml", "res/values-sl/values-sl.xml", "res/values-de/values-de.xml", "res/values-kk-rKZ/values-kk-rKZ.xml", "res/drawable-xxxhdpi-v4/ic_group_collapse_03.png", "res/drawable-xxxhdpi-v4/ic_group_expand_15.png", "res/drawable-xxxhdpi-v4/ic_group_expand_13.png", "res/drawable-xxxhdpi-v4/ic_group_expand_10.png", "res/drawable-xxxhdpi-v4/ic_group_collapse_14.png", "res/drawable-xxxhdpi-v4/ic_group_expand_06.png", "res/drawable-xxxhdpi-v4/ic_group_collapse_11.png", "res/drawable-xxxhdpi-v4/ic_group_expand_11.png", "res/drawable-xxxhdpi-v4/ic_group_collapse_01.png", "res/drawable-xxxhdpi-v4/ic_group_collapse_10.png", "res/drawable-xxxhdpi-v4/ic_group_expand_07.png", "res/drawable-xxxhdpi-v4/ic_group_expand_09.png", "res/drawable-xxxhdpi-v4/ic_group_collapse_13.png", "res/drawable-xxxhdpi-v4/ic_group_expand_01.png", "res/drawable-xxxhdpi-v4/ic_group_collapse_00.png", "res/drawable-xxxhdpi-v4/ic_group_expand_00.png", "res/drawable-xxxhdpi-v4/ic_group_collapse_04.png", "res/drawable-xxxhdpi-v4/ic_group_expand_12.png", "res/drawable-xxxhdpi-v4/ic_group_expand_08.png", "res/drawable-xxxhdpi-v4/ic_group_expand_04.png", "res/drawable-xxxhdpi-v4/ic_group_collapse_08.png", "res/drawable-xxxhdpi-v4/ic_group_expand_03.png", "res/drawable-xxxhdpi-v4/ic_group_expand_02.png", "res/drawable-xxxhdpi-v4/ic_group_expand_05.png", "res/drawable-xxxhdpi-v4/ic_group_collapse_02.png", "res/drawable-xxxhdpi-v4/ic_group_collapse_07.png", "res/drawable-xxxhdpi-v4/ic_mr_button_grey.png", "res/drawable-xxxhdpi-v4/ic_group_collapse_05.png", "res/drawable-xxxhdpi-v4/ic_group_expand_14.png", "res/drawable-xxxhdpi-v4/ic_group_collapse_12.png", "res/drawable-xxxhdpi-v4/ic_group_collapse_06.png", "res/drawable-xxxhdpi-v4/ic_group_collapse_09.png", "res/drawable-xxxhdpi-v4/ic_group_collapse_15.png", "res/values-en-rAU/values-en-rAU.xml", "res/values-en-rIN/values-en-rIN.xml", "res/values-zh-rTW/values-zh-rTW.xml", "res/values-sw/values-sw.xml", "res/values-nb/values-nb.xml", "res/values-bs-rBA/values-bs-rBA.xml", "res/values-tr/values-tr.xml", "res/values-kn-rIN/values-kn-rIN.xml", "res/values-hy-rAM/values-hy-rAM.xml", "res/values-sw600dp-v13/values-sw600dp-v13.xml", "res/values-es-rUS/values-es-rUS.xml", "res/values-land/values-land.xml", "res/values-zh-rHK/values-zh-rHK.xml", "res/values-ko/values-ko.xml", "res/values-pt-rPT/values-pt-rPT.xml", "res/values-iw/values-iw.xml", "res/values-lt/values-lt.xml", "res/values-ro/values-ro.xml", "res/values-pt/values-pt.xml", "res/values-ar/values-ar.xml", "res/values-ur-rPK/values-ur-rPK.xml", "res/values-ml-rIN/values-ml-rIN.xml", "res/drawable-xhdpi-v4/ic_mr_button_connected_20_light.png", "res/drawable-xhdpi-v4/ic_mr_button_disconnected_light.png", "res/drawable-xhdpi-v4/ic_mr_button_connected_06_light.png", "res/drawable-xhdpi-v4/ic_mr_button_connecting_14_dark.png", "res/drawable-xhdpi-v4/ic_vol_type_speaker_group_light.png", "res/drawable-xhdpi-v4/ic_mr_button_connected_18_light.png", "res/drawable-xhdpi-v4/ic_mr_button_connected_12_light.png", "res/drawable-xhdpi-v4/ic_mr_button_connecting_15_dark.png", "res/drawable-xhdpi-v4/ic_audiotrack_light.png", "res/drawable-xhdpi-v4/ic_mr_button_connected_01_dark.png", "res/drawable-xhdpi-v4/ic_mr_button_connected_18_dark.png", "res/drawable-xhdpi-v4/ic_mr_button_connected_04_dark.png", "res/drawable-xhdpi-v4/ic_mr_button_connected_04_light.png", "res/drawable-xhdpi-v4/ic_mr_button_connected_09_dark.png", "res/drawable-xhdpi-v4/ic_vol_type_speaker_light.png", "res/drawable-xhdpi-v4/ic_mr_button_connecting_03_light.png", "res/drawable-xhdpi-v4/ic_mr_button_connected_19_light.png", "res/drawable-xhdpi-v4/ic_mr_button_connected_15_light.png", "res/drawable-xhdpi-v4/ic_mr_button_connected_17_dark.png", "res/drawable-xhdpi-v4/ic_mr_button_connecting_20_light.png", "res/drawable-xhdpi-v4/ic_mr_button_connecting_07_dark.png", "res/drawable-xhdpi-v4/ic_mr_button_connected_12_dark.png", "res/drawable-xhdpi-v4/ic_mr_button_connecting_19_light.png", "res/drawable-xhdpi-v4/ic_mr_button_connected_11_light.png", "res/drawable-xhdpi-v4/ic_mr_button_connecting_22_light.png", "res/drawable-xhdpi-v4/ic_mr_button_connecting_10_light.png", "res/drawable-xhdpi-v4/ic_vol_type_tv_dark.png", "res/drawable-xhdpi-v4/ic_mr_button_connected_13_dark.png", "res/drawable-xhdpi-v4/ic_mr_button_connecting_16_light.png", "res/drawable-xhdpi-v4/ic_mr_button_connecting_08_light.png", "res/drawable-xhdpi-v4/ic_mr_button_connecting_07_light.png", "res/drawable-xhdpi-v4/ic_mr_button_connected_05_light.png", "res/drawable-xhdpi-v4/ic_dialog_close_dark.png", "res/drawable-xhdpi-v4/ic_vol_type_tv_light.png", "res/drawable-xhdpi-v4/ic_mr_button_disabled_dark.png", "res/drawable-xhdpi-v4/ic_mr_button_disabled_light.png", "res/drawable-xhdpi-v4/ic_mr_button_connecting_13_light.png", "res/drawable-xhdpi-v4/ic_mr_button_connected_00_light.png", "res/drawable-xhdpi-v4/ic_mr_button_connected_09_light.png", "res/drawable-xhdpi-v4/ic_mr_button_connecting_02_dark.png", "res/drawable-xhdpi-v4/ic_mr_button_connecting_02_light.png", "res/drawable-xhdpi-v4/ic_mr_button_connected_21_dark.png", "res/drawable-xhdpi-v4/ic_mr_button_connecting_21_light.png", "res/drawable-xhdpi-v4/ic_dialog_close_light.png", "res/drawable-xhdpi-v4/ic_mr_button_connected_15_dark.png", "res/drawable-xhdpi-v4/ic_mr_button_connected_13_light.png", "res/drawable-xhdpi-v4/ic_mr_button_connected_07_light.png", "res/drawable-xhdpi-v4/ic_mr_button_connected_17_light.png", "res/drawable-xhdpi-v4/ic_mr_button_connected_21_light.png", "res/drawable-xhdpi-v4/ic_mr_button_connecting_01_light.png", "res/drawable-xhdpi-v4/ic_mr_button_connected_19_dark.png", "res/drawable-xhdpi-v4/ic_mr_button_connected_02_light.png", "res/drawable-xhdpi-v4/ic_mr_button_connected_02_dark.png", "res/drawable-xhdpi-v4/ic_mr_button_connecting_09_dark.png", "res/drawable-xhdpi-v4/ic_mr_button_connecting_18_light.png", "res/drawable-xhdpi-v4/ic_mr_button_connecting_05_light.png", "res/drawable-xhdpi-v4/ic_mr_button_disconnected_dark.png", "res/drawable-xhdpi-v4/ic_mr_button_connected_10_dark.png", "res/drawable-xhdpi-v4/ic_mr_button_connecting_14_light.png", "res/drawable-xhdpi-v4/ic_mr_button_connecting_00_light.png", "res/drawable-xhdpi-v4/ic_mr_button_connecting_03_dark.png", "res/drawable-xhdpi-v4/ic_mr_button_connecting_15_light.png", "res/drawable-xhdpi-v4/ic_vol_type_speaker_group_dark.png", "res/drawable-xhdpi-v4/ic_mr_button_connecting_06_light.png", "res/drawable-xhdpi-v4/ic_mr_button_connecting_11_light.png", "res/drawable-xhdpi-v4/ic_vol_type_speaker_dark.png", "res/drawable-xhdpi-v4/ic_mr_button_connecting_10_dark.png", "res/drawable-xhdpi-v4/ic_mr_button_connecting_16_dark.png", "res/drawable-xhdpi-v4/ic_mr_button_connecting_08_dark.png", "res/drawable-xhdpi-v4/ic_mr_button_connecting_09_light.png", "res/drawable-xhdpi-v4/ic_mr_button_connected_11_dark.png", "res/drawable-xhdpi-v4/ic_mr_button_connecting_05_dark.png", "res/drawable-xhdpi-v4/ic_media_pause_light.png", "res/drawable-xhdpi-v4/ic_mr_button_connected_10_light.png", "res/drawable-xhdpi-v4/ic_mr_button_connecting_22_dark.png", "res/drawable-xhdpi-v4/ic_mr_button_connecting_17_dark.png", "res/drawable-xhdpi-v4/ic_mr_button_grey.png", "res/drawable-xhdpi-v4/ic_mr_button_connected_08_light.png", "res/drawable-xhdpi-v4/ic_mr_button_connecting_04_light.png", "res/drawable-xhdpi-v4/ic_mr_button_connected_16_light.png", "res/drawable-xhdpi-v4/ic_mr_button_connecting_20_dark.png", "res/drawable-xhdpi-v4/ic_mr_button_connected_03_dark.png", "res/drawable-xhdpi-v4/ic_mr_button_connected_14_light.png", "res/drawable-xhdpi-v4/ic_mr_button_connecting_17_light.png", "res/drawable-xhdpi-v4/ic_mr_button_connected_06_dark.png", "res/drawable-xhdpi-v4/ic_mr_button_connecting_06_dark.png", "res/drawable-xhdpi-v4/ic_mr_button_connected_20_dark.png", "res/drawable-xhdpi-v4/ic_mr_button_connecting_01_dark.png", "res/drawable-xhdpi-v4/ic_mr_button_connected_16_dark.png", "res/drawable-xhdpi-v4/ic_mr_button_connecting_21_dark.png", "res/drawable-xhdpi-v4/ic_mr_button_connecting_12_light.png", "res/drawable-xhdpi-v4/ic_mr_button_connecting_12_dark.png", "res/drawable-xhdpi-v4/ic_mr_button_connected_22_light.png", "res/drawable-xhdpi-v4/ic_audiotrack_dark.png", "res/drawable-xhdpi-v4/ic_media_play_light.png", "res/drawable-xhdpi-v4/ic_mr_button_connecting_19_dark.png", "res/drawable-xhdpi-v4/ic_mr_button_connected_05_dark.png", "res/drawable-xhdpi-v4/ic_media_pause_dark.png", "res/drawable-xhdpi-v4/ic_mr_button_connected_22_dark.png", "res/drawable-xhdpi-v4/ic_mr_button_connected_14_dark.png", "res/drawable-xhdpi-v4/ic_mr_button_connecting_11_dark.png", "res/drawable-xhdpi-v4/ic_mr_button_connecting_00_dark.png", "res/drawable-xhdpi-v4/ic_mr_button_connected_08_dark.png", "res/drawable-xhdpi-v4/ic_mr_button_connecting_13_dark.png", "res/drawable-xhdpi-v4/ic_mr_button_connecting_18_dark.png", "res/drawable-xhdpi-v4/ic_mr_button_connecting_04_dark.png", "res/drawable-xhdpi-v4/ic_mr_button_connected_07_dark.png", "res/drawable-xhdpi-v4/ic_mr_button_connected_00_dark.png", "res/drawable-xhdpi-v4/ic_mr_button_connected_01_light.png", "res/drawable-xhdpi-v4/ic_media_play_dark.png", "res/drawable-xhdpi-v4/ic_mr_button_connected_03_light.png", "res/values/values.xml", "res/values-hr/values-hr.xml", "res/values-mn-rMN/values-mn-rMN.xml", "res/values-da/values-da.xml", "res/values-hi/values-hi.xml", "res/values-it/values-it.xml", "res/values-es/values-es.xml", "res/values-sk/values-sk.xml", "res/values-lv/values-lv.xml", "res/values-ky-rKG/values-ky-rKG.xml", "res/values-hu/values-hu.xml", "res/drawable-xxhdpi-v4/ic_mr_button_connected_20_light.png", "res/drawable-xxhdpi-v4/ic_mr_button_disconnected_light.png", "res/drawable-xxhdpi-v4/ic_mr_button_connected_06_light.png", "res/drawable-xxhdpi-v4/ic_mr_button_connecting_14_dark.png", "res/drawable-xxhdpi-v4/ic_vol_type_speaker_group_light.png", "res/drawable-xxhdpi-v4/ic_mr_button_connected_18_light.png", "res/drawable-xxhdpi-v4/ic_mr_button_connected_12_light.png", "res/drawable-xxhdpi-v4/ic_mr_button_connecting_15_dark.png", "res/drawable-xxhdpi-v4/ic_audiotrack_light.png", "res/drawable-xxhdpi-v4/ic_mr_button_connected_01_dark.png", "res/drawable-xxhdpi-v4/ic_mr_button_connected_18_dark.png", "res/drawable-xxhdpi-v4/ic_mr_button_connected_04_dark.png", "res/drawable-xxhdpi-v4/ic_mr_button_connected_04_light.png", "res/drawable-xxhdpi-v4/ic_mr_button_connected_09_dark.png", "res/drawable-xxhdpi-v4/ic_vol_type_speaker_light.png", "res/drawable-xxhdpi-v4/ic_mr_button_connecting_03_light.png", "res/drawable-xxhdpi-v4/ic_mr_button_connected_19_light.png", "res/drawable-xxhdpi-v4/ic_mr_button_connected_15_light.png", "res/drawable-xxhdpi-v4/ic_mr_button_connected_17_dark.png", "res/drawable-xxhdpi-v4/ic_mr_button_connecting_20_light.png", "res/drawable-xxhdpi-v4/ic_mr_button_connecting_07_dark.png", "res/drawable-xxhdpi-v4/ic_mr_button_connected_12_dark.png", "res/drawable-xxhdpi-v4/ic_mr_button_connecting_19_light.png", "res/drawable-xxhdpi-v4/ic_mr_button_connected_11_light.png", "res/drawable-xxhdpi-v4/ic_mr_button_connecting_22_light.png", "res/drawable-xxhdpi-v4/ic_mr_button_connecting_10_light.png", "res/drawable-xxhdpi-v4/ic_vol_type_tv_dark.png", "res/drawable-xxhdpi-v4/ic_mr_button_connected_13_dark.png", "res/drawable-xxhdpi-v4/ic_mr_button_connecting_16_light.png", "res/drawable-xxhdpi-v4/ic_mr_button_connecting_08_light.png", "res/drawable-xxhdpi-v4/ic_mr_button_connecting_07_light.png", "res/drawable-xxhdpi-v4/ic_mr_button_connected_05_light.png", "res/drawable-xxhdpi-v4/ic_dialog_close_dark.png", "res/drawable-xxhdpi-v4/ic_vol_type_tv_light.png", "res/drawable-xxhdpi-v4/ic_mr_button_disabled_dark.png", "res/drawable-xxhdpi-v4/ic_mr_button_disabled_light.png", "res/drawable-xxhdpi-v4/ic_mr_button_connecting_13_light.png", "res/drawable-xxhdpi-v4/ic_mr_button_connected_00_light.png", "res/drawable-xxhdpi-v4/ic_mr_button_connected_09_light.png", "res/drawable-xxhdpi-v4/ic_mr_button_connecting_02_dark.png", "res/drawable-xxhdpi-v4/ic_mr_button_connecting_02_light.png", "res/drawable-xxhdpi-v4/ic_mr_button_connected_21_dark.png", "res/drawable-xxhdpi-v4/ic_mr_button_connecting_21_light.png", "res/drawable-xxhdpi-v4/ic_dialog_close_light.png", "res/drawable-xxhdpi-v4/ic_mr_button_connected_15_dark.png", "res/drawable-xxhdpi-v4/ic_mr_button_connected_13_light.png", "res/drawable-xxhdpi-v4/ic_mr_button_connected_07_light.png", "res/drawable-xxhdpi-v4/ic_mr_button_connected_17_light.png", "res/drawable-xxhdpi-v4/ic_mr_button_connected_21_light.png", "res/drawable-xxhdpi-v4/ic_mr_button_connecting_01_light.png", "res/drawable-xxhdpi-v4/ic_mr_button_connected_19_dark.png", "res/drawable-xxhdpi-v4/ic_mr_button_connected_02_light.png", "res/drawable-xxhdpi-v4/ic_mr_button_connected_02_dark.png", "res/drawable-xxhdpi-v4/ic_mr_button_connecting_09_dark.png", "res/drawable-xxhdpi-v4/ic_mr_button_connecting_18_light.png", "res/drawable-xxhdpi-v4/ic_mr_button_connecting_05_light.png", "res/drawable-xxhdpi-v4/ic_mr_button_disconnected_dark.png", "res/drawable-xxhdpi-v4/ic_mr_button_connected_10_dark.png", "res/drawable-xxhdpi-v4/ic_mr_button_connecting_14_light.png", "res/drawable-xxhdpi-v4/ic_mr_button_connecting_00_light.png", "res/drawable-xxhdpi-v4/ic_mr_button_connecting_03_dark.png", "res/drawable-xxhdpi-v4/ic_mr_button_connecting_15_light.png", "res/drawable-xxhdpi-v4/ic_vol_type_speaker_group_dark.png", "res/drawable-xxhdpi-v4/ic_mr_button_connecting_06_light.png", "res/drawable-xxhdpi-v4/ic_mr_button_connecting_11_light.png", "res/drawable-xxhdpi-v4/ic_vol_type_speaker_dark.png", "res/drawable-xxhdpi-v4/ic_mr_button_connecting_10_dark.png", "res/drawable-xxhdpi-v4/ic_mr_button_connecting_16_dark.png", "res/drawable-xxhdpi-v4/ic_mr_button_connecting_08_dark.png", "res/drawable-xxhdpi-v4/ic_mr_button_connecting_09_light.png", "res/drawable-xxhdpi-v4/ic_mr_button_connected_11_dark.png", "res/drawable-xxhdpi-v4/ic_mr_button_connecting_05_dark.png", "res/drawable-xxhdpi-v4/ic_media_pause_light.png", "res/drawable-xxhdpi-v4/ic_mr_button_connected_10_light.png", "res/drawable-xxhdpi-v4/ic_mr_button_connecting_22_dark.png", "res/drawable-xxhdpi-v4/ic_mr_button_connecting_17_dark.png", "res/drawable-xxhdpi-v4/ic_mr_button_grey.png", "res/drawable-xxhdpi-v4/ic_mr_button_connected_08_light.png", "res/drawable-xxhdpi-v4/ic_mr_button_connecting_04_light.png", "res/drawable-xxhdpi-v4/ic_mr_button_connected_16_light.png", "res/drawable-xxhdpi-v4/ic_mr_button_connecting_20_dark.png", "res/drawable-xxhdpi-v4/ic_mr_button_connected_03_dark.png", "res/drawable-xxhdpi-v4/ic_mr_button_connected_14_light.png", "res/drawable-xxhdpi-v4/ic_mr_button_connecting_17_light.png", "res/drawable-xxhdpi-v4/ic_mr_button_connected_06_dark.png", "res/drawable-xxhdpi-v4/ic_mr_button_connecting_06_dark.png", "res/drawable-xxhdpi-v4/ic_mr_button_connected_20_dark.png", "res/drawable-xxhdpi-v4/ic_mr_button_connecting_01_dark.png", "res/drawable-xxhdpi-v4/ic_mr_button_connected_16_dark.png", "res/drawable-xxhdpi-v4/ic_mr_button_connecting_21_dark.png", "res/drawable-xxhdpi-v4/ic_mr_button_connecting_12_light.png", "res/drawable-xxhdpi-v4/ic_mr_button_connecting_12_dark.png", "res/drawable-xxhdpi-v4/ic_mr_button_connected_22_light.png", "res/drawable-xxhdpi-v4/ic_audiotrack_dark.png", "res/drawable-xxhdpi-v4/ic_media_play_light.png", "res/drawable-xxhdpi-v4/ic_mr_button_connecting_19_dark.png", "res/drawable-xxhdpi-v4/ic_mr_button_connected_05_dark.png", "res/drawable-xxhdpi-v4/ic_media_pause_dark.png", "res/drawable-xxhdpi-v4/ic_mr_button_connected_22_dark.png", "res/drawable-xxhdpi-v4/ic_mr_button_connected_14_dark.png", "res/drawable-xxhdpi-v4/ic_mr_button_connecting_11_dark.png", "res/drawable-xxhdpi-v4/ic_mr_button_connecting_00_dark.png", "res/drawable-xxhdpi-v4/ic_mr_button_connected_08_dark.png", "res/drawable-xxhdpi-v4/ic_mr_button_connecting_13_dark.png", "res/drawable-xxhdpi-v4/ic_mr_button_connecting_18_dark.png", "res/drawable-xxhdpi-v4/ic_mr_button_connecting_04_dark.png", "res/drawable-xxhdpi-v4/ic_mr_button_connected_07_dark.png", "res/drawable-xxhdpi-v4/ic_mr_button_connected_00_dark.png", "res/drawable-xxhdpi-v4/ic_mr_button_connected_01_light.png", "res/drawable-xxhdpi-v4/ic_media_play_dark.png", "res/drawable-xxhdpi-v4/ic_mr_button_connected_03_light.png", "res/values-th/values-th.xml", "res/values-cs/values-cs.xml", "res/values-sr/values-sr.xml", "res/values-tl/values-tl.xml", "res/values-te-rIN/values-te-rIN.xml", "res/values-ne-rNP/values-ne-rNP.xml", "res/values-ta-rIN/values-ta-rIN.xml", "res/drawable/mr_button_connecting_light.xml", "res/drawable/mr_group_collapse.xml", "res/drawable/mr_button_connecting_dark.xml", "res/drawable/mr_dialog_close_dark.xml", "res/drawable/mr_vol_type_audiotrack_dark.xml", "res/drawable/mr_media_pause_light.xml", "res/drawable/mr_group_expand.xml", "res/drawable/mr_vol_type_audiotrack_light.xml", "res/drawable/mr_dialog_material_background_light.xml", "res/drawable/mr_media_play_dark.xml", "res/drawable/mr_button_dark.xml", "res/drawable/mr_media_pause_dark.xml", "res/drawable/mr_dialog_material_background_dark.xml", "res/drawable/mr_button_connected_light.xml", "res/drawable/mr_dialog_close_light.xml", "res/drawable/mr_media_play_light.xml", "res/drawable/mr_button_connected_dark.xml", "res/drawable/mr_button_light.xml" ]
-subjar_tuples = [ [ "internal_impl_25.0.1", "libs/internal_impl-25.0.1.jar" ] ]
-subjars = [ "libs/internal_impl-25.0.1.jar" ]
+resources = [ "res/values-ur/values-ur.xml", "res/values-ru/values-ru.xml", "res/values-en-rGB/values-en-rGB.xml", "res/values-pt-rBR/values-pt-rBR.xml", "res/values-el/values-el.xml", "res/drawable-hdpi-v4/ic_dialog_close_light.png", "res/drawable-hdpi-v4/ic_media_pause_light.png", "res/drawable-hdpi-v4/ic_mr_button_disabled_light.png", "res/drawable-hdpi-v4/ic_mr_button_grey.png", "res/drawable-hdpi-v4/ic_media_play_light.png", "res/drawable-hdpi-v4/ic_dialog_close_dark.png", "res/drawable-hdpi-v4/ic_vol_type_tv_dark.png", "res/drawable-hdpi-v4/ic_media_pause_dark.png", "res/drawable-hdpi-v4/ic_vol_type_tv_light.png", "res/drawable-hdpi-v4/ic_media_stop_dark.png", "res/drawable-hdpi-v4/ic_vol_type_speaker_dark.png", "res/drawable-hdpi-v4/ic_mr_button_disabled_dark.png", "res/drawable-hdpi-v4/ic_audiotrack_light.png", "res/drawable-hdpi-v4/ic_vol_type_speaker_group_dark.png", "res/drawable-hdpi-v4/ic_media_stop_light.png", "res/drawable-hdpi-v4/ic_media_play_dark.png", "res/drawable-hdpi-v4/ic_audiotrack_dark.png", "res/drawable-hdpi-v4/ic_vol_type_speaker_light.png", "res/drawable-hdpi-v4/ic_mr_button_disconnected_dark.png", "res/drawable-hdpi-v4/ic_mr_button_disconnected_light.png", "res/drawable-hdpi-v4/ic_vol_type_speaker_group_light.png", "res/values-tr/values-tr.xml", "res/values-hu/values-hu.xml", "res/values-km/values-km.xml", "res/values-fr-rCA/values-fr-rCA.xml", "res/values-gu/values-gu.xml", "res/interpolator/mr_fast_out_slow_in.xml", "res/interpolator/mr_linear_out_slow_in.xml", "res/layout/mr_controller_material_dialog_b.xml", "res/layout/mr_volume_control.xml", "res/layout/mr_controller_volume_item.xml", "res/layout/mr_chooser_list_item.xml", "res/layout/mr_chooser_dialog.xml", "res/layout/mr_playback_control.xml", "res/values-ms/values-ms.xml", "res/values-ja/values-ja.xml", "res/values-eu/values-eu.xml", "res/values-sv/values-sv.xml", "res/values-mn/values-mn.xml", "res/values-ta/values-ta.xml", "res/values-pl/values-pl.xml", "res/drawable-xxhdpi-v4/ic_mr_button_connected_28_light.png", "res/drawable-xxhdpi-v4/ic_mr_button_connected_00_light.png", "res/drawable-xxhdpi-v4/ic_mr_button_connected_28_dark.png", "res/drawable-xxhdpi-v4/ic_mr_button_connected_04_dark.png", "res/drawable-xxhdpi-v4/ic_mr_button_connecting_28_dark.png", "res/drawable-xxhdpi-v4/ic_mr_button_connecting_06_light.png", "res/drawable-xxhdpi-v4/ic_dialog_close_light.png", "res/drawable-xxhdpi-v4/ic_mr_button_connecting_29_dark.png", "res/drawable-xxhdpi-v4/ic_mr_button_connected_01_light.png", "res/drawable-xxhdpi-v4/ic_mr_button_connected_23_dark.png", "res/drawable-xxhdpi-v4/ic_mr_button_connecting_18_light.png", "res/drawable-xxhdpi-v4/ic_mr_button_connecting_04_dark.png", "res/drawable-xxhdpi-v4/ic_mr_button_connecting_12_light.png", "res/drawable-xxhdpi-v4/ic_media_pause_light.png", "res/drawable-xxhdpi-v4/ic_mr_button_disabled_light.png", "res/drawable-xxhdpi-v4/ic_mr_button_grey.png", "res/drawable-xxhdpi-v4/ic_mr_button_connecting_14_dark.png", "res/drawable-xxhdpi-v4/ic_media_play_light.png", "res/drawable-xxhdpi-v4/ic_mr_button_connecting_12_dark.png", "res/drawable-xxhdpi-v4/ic_mr_button_connected_14_light.png", "res/drawable-xxhdpi-v4/ic_dialog_close_dark.png", "res/drawable-xxhdpi-v4/ic_mr_button_connecting_30_dark.png", "res/drawable-xxhdpi-v4/ic_mr_button_connected_27_dark.png", "res/drawable-xxhdpi-v4/ic_mr_button_connecting_07_light.png", "res/drawable-xxhdpi-v4/ic_mr_button_connecting_25_dark.png", "res/drawable-xxhdpi-v4/ic_mr_button_connecting_18_dark.png", "res/drawable-xxhdpi-v4/ic_mr_button_connected_23_light.png", "res/drawable-xxhdpi-v4/ic_mr_button_connected_11_light.png", "res/drawable-xxhdpi-v4/ic_mr_button_connecting_08_light.png", "res/drawable-xxhdpi-v4/ic_mr_button_connected_02_dark.png", "res/drawable-xxhdpi-v4/ic_mr_button_connecting_22_dark.png", "res/drawable-xxhdpi-v4/ic_mr_button_connected_08_light.png", "res/drawable-xxhdpi-v4/ic_mr_button_connecting_20_light.png", "res/drawable-xxhdpi-v4/ic_mr_button_connected_18_light.png", "res/drawable-xxhdpi-v4/ic_mr_button_connected_19_light.png", "res/drawable-xxhdpi-v4/ic_vol_type_tv_dark.png", "res/drawable-xxhdpi-v4/ic_mr_button_connecting_05_light.png", "res/drawable-xxhdpi-v4/ic_mr_button_connecting_10_dark.png", "res/drawable-xxhdpi-v4/ic_mr_button_connecting_02_dark.png", "res/drawable-xxhdpi-v4/ic_mr_button_connected_25_dark.png", "res/drawable-xxhdpi-v4/ic_mr_button_connected_18_dark.png", "res/drawable-xxhdpi-v4/ic_mr_button_connecting_22_light.png", "res/drawable-xxhdpi-v4/ic_mr_button_connected_22_light.png", "res/drawable-xxhdpi-v4/ic_mr_button_connecting_24_dark.png", "res/drawable-xxhdpi-v4/ic_media_pause_dark.png", "res/drawable-xxhdpi-v4/ic_mr_button_connected_29_light.png", "res/drawable-xxhdpi-v4/ic_mr_button_connected_03_light.png", "res/drawable-xxhdpi-v4/ic_vol_type_tv_light.png", "res/drawable-xxhdpi-v4/ic_mr_button_connected_11_dark.png", "res/drawable-xxhdpi-v4/ic_mr_button_connected_30_light.png", "res/drawable-xxhdpi-v4/ic_mr_button_connecting_23_light.png", "res/drawable-xxhdpi-v4/ic_mr_button_connected_29_dark.png", "res/drawable-xxhdpi-v4/ic_media_stop_dark.png", "res/drawable-xxhdpi-v4/ic_mr_button_connected_27_light.png", "res/drawable-xxhdpi-v4/ic_mr_button_connected_25_light.png", "res/drawable-xxhdpi-v4/ic_mr_button_connected_06_dark.png", "res/drawable-xxhdpi-v4/ic_mr_button_connected_00_dark.png", "res/drawable-xxhdpi-v4/ic_mr_button_connected_02_light.png", "res/drawable-xxhdpi-v4/ic_mr_button_connected_17_light.png", "res/drawable-xxhdpi-v4/ic_mr_button_connecting_03_dark.png", "res/drawable-xxhdpi-v4/ic_mr_button_connected_09_dark.png", "res/drawable-xxhdpi-v4/ic_vol_type_speaker_dark.png", "res/drawable-xxhdpi-v4/ic_mr_button_connecting_00_dark.png", "res/drawable-xxhdpi-v4/ic_mr_button_connected_24_light.png", "res/drawable-xxhdpi-v4/ic_mr_button_connected_26_light.png", "res/drawable-xxhdpi-v4/ic_mr_button_connecting_29_light.png", "res/drawable-xxhdpi-v4/ic_mr_button_connecting_30_light.png", "res/drawable-xxhdpi-v4/ic_mr_button_connected_05_dark.png", "res/drawable-xxhdpi-v4/ic_mr_button_connecting_08_dark.png", "res/drawable-xxhdpi-v4/ic_mr_button_connecting_15_light.png", "res/drawable-xxhdpi-v4/ic_mr_button_connecting_17_dark.png", "res/drawable-xxhdpi-v4/ic_mr_button_disabled_dark.png", "res/drawable-xxhdpi-v4/ic_mr_button_connecting_26_light.png", "res/drawable-xxhdpi-v4/ic_mr_button_connected_24_dark.png", "res/drawable-xxhdpi-v4/ic_mr_button_connecting_16_light.png", "res/drawable-xxhdpi-v4/ic_mr_button_connecting_27_dark.png", "res/drawable-xxhdpi-v4/ic_audiotrack_light.png", "res/drawable-xxhdpi-v4/ic_mr_button_connected_13_dark.png", "res/drawable-xxhdpi-v4/ic_mr_button_connected_16_dark.png", "res/drawable-xxhdpi-v4/ic_mr_button_connecting_04_light.png", "res/drawable-xxhdpi-v4/ic_vol_type_speaker_group_dark.png", "res/drawable-xxhdpi-v4/ic_mr_button_connecting_13_light.png", "res/drawable-xxhdpi-v4/ic_media_stop_light.png", "res/drawable-xxhdpi-v4/ic_mr_button_connecting_17_light.png", "res/drawable-xxhdpi-v4/ic_mr_button_connected_16_light.png", "res/drawable-xxhdpi-v4/ic_mr_button_connecting_16_dark.png", "res/drawable-xxhdpi-v4/ic_mr_button_connecting_01_light.png", "res/drawable-xxhdpi-v4/ic_mr_button_connected_07_dark.png", "res/drawable-xxhdpi-v4/ic_mr_button_connected_13_light.png", "res/drawable-xxhdpi-v4/ic_mr_button_connected_19_dark.png", "res/drawable-xxhdpi-v4/ic_mr_button_connecting_00_light.png", "res/drawable-xxhdpi-v4/ic_mr_button_connected_14_dark.png", "res/drawable-xxhdpi-v4/ic_mr_button_connecting_03_light.png", "res/drawable-xxhdpi-v4/ic_mr_button_connecting_15_dark.png", "res/drawable-xxhdpi-v4/ic_mr_button_connected_20_light.png", "res/drawable-xxhdpi-v4/ic_media_play_dark.png", "res/drawable-xxhdpi-v4/ic_mr_button_connected_03_dark.png", "res/drawable-xxhdpi-v4/ic_mr_button_connecting_27_light.png", "res/drawable-xxhdpi-v4/ic_mr_button_connected_21_light.png", "res/drawable-xxhdpi-v4/ic_mr_button_connecting_28_light.png", "res/drawable-xxhdpi-v4/ic_mr_button_connecting_02_light.png", "res/drawable-xxhdpi-v4/ic_mr_button_connecting_10_light.png", "res/drawable-xxhdpi-v4/ic_mr_button_connecting_23_dark.png", "res/drawable-xxhdpi-v4/ic_mr_button_connected_15_dark.png", "res/drawable-xxhdpi-v4/ic_mr_button_connected_21_dark.png", "res/drawable-xxhdpi-v4/ic_mr_button_connecting_05_dark.png", "res/drawable-xxhdpi-v4/ic_mr_button_connecting_19_dark.png", "res/drawable-xxhdpi-v4/ic_mr_button_connecting_20_dark.png", "res/drawable-xxhdpi-v4/ic_mr_button_connecting_06_dark.png", "res/drawable-xxhdpi-v4/ic_audiotrack_dark.png", "res/drawable-xxhdpi-v4/ic_mr_button_connecting_21_dark.png", "res/drawable-xxhdpi-v4/ic_mr_button_connecting_09_dark.png", "res/drawable-xxhdpi-v4/ic_mr_button_connected_20_dark.png", "res/drawable-xxhdpi-v4/ic_vol_type_speaker_light.png", "res/drawable-xxhdpi-v4/ic_mr_button_disconnected_dark.png", "res/drawable-xxhdpi-v4/ic_mr_button_connecting_19_light.png", "res/drawable-xxhdpi-v4/ic_mr_button_connected_22_dark.png", "res/drawable-xxhdpi-v4/ic_mr_button_connecting_25_light.png", "res/drawable-xxhdpi-v4/ic_mr_button_connecting_09_light.png", "res/drawable-xxhdpi-v4/ic_mr_button_connecting_11_light.png", "res/drawable-xxhdpi-v4/ic_mr_button_connected_12_dark.png", "res/drawable-xxhdpi-v4/ic_mr_button_connected_10_light.png", "res/drawable-xxhdpi-v4/ic_mr_button_connecting_13_dark.png", "res/drawable-xxhdpi-v4/ic_mr_button_connecting_24_light.png", "res/drawable-xxhdpi-v4/ic_mr_button_connecting_01_dark.png", "res/drawable-xxhdpi-v4/ic_mr_button_connecting_26_dark.png", "res/drawable-xxhdpi-v4/ic_mr_button_connected_26_dark.png", "res/drawable-xxhdpi-v4/ic_mr_button_connecting_07_dark.png", "res/drawable-xxhdpi-v4/ic_mr_button_connected_04_light.png", "res/drawable-xxhdpi-v4/ic_mr_button_connected_10_dark.png", "res/drawable-xxhdpi-v4/ic_mr_button_connected_17_dark.png", "res/drawable-xxhdpi-v4/ic_mr_button_connected_05_light.png", "res/drawable-xxhdpi-v4/ic_mr_button_connected_07_light.png", "res/drawable-xxhdpi-v4/ic_mr_button_connected_15_light.png", "res/drawable-xxhdpi-v4/ic_mr_button_connected_08_dark.png", "res/drawable-xxhdpi-v4/ic_mr_button_connecting_11_dark.png", "res/drawable-xxhdpi-v4/ic_mr_button_connected_09_light.png", "res/drawable-xxhdpi-v4/ic_mr_button_disconnected_light.png", "res/drawable-xxhdpi-v4/ic_mr_button_connected_12_light.png", "res/drawable-xxhdpi-v4/ic_vol_type_speaker_group_light.png", "res/drawable-xxhdpi-v4/ic_mr_button_connecting_14_light.png", "res/drawable-xxhdpi-v4/ic_mr_button_connecting_21_light.png", "res/drawable-xxhdpi-v4/ic_mr_button_connected_30_dark.png", "res/drawable-xxhdpi-v4/ic_mr_button_connected_06_light.png", "res/drawable-xxhdpi-v4/ic_mr_button_connected_01_dark.png", "res/values-lt/values-lt.xml", "res/values-bg/values-bg.xml", "res/values-es-rUS/values-es-rUS.xml", "res/values-iw/values-iw.xml", "res/values-en-rXC/values-en-rXC.xml", "res/values-mr/values-mr.xml", "res/values-uz/values-uz.xml", "res/values-pa/values-pa.xml", "res/values-fi/values-fi.xml", "res/values-am/values-am.xml", "res/values-pt-rPT/values-pt-rPT.xml", "res/values-ar/values-ar.xml", "res/values-ky/values-ky.xml", "res/drawable-mdpi-v4/ic_dialog_close_light.png", "res/drawable-mdpi-v4/ic_media_pause_light.png", "res/drawable-mdpi-v4/ic_mr_button_disabled_light.png", "res/drawable-mdpi-v4/ic_mr_button_grey.png", "res/drawable-mdpi-v4/ic_media_play_light.png", "res/drawable-mdpi-v4/ic_dialog_close_dark.png", "res/drawable-mdpi-v4/ic_vol_type_tv_dark.png", "res/drawable-mdpi-v4/ic_media_pause_dark.png", "res/drawable-mdpi-v4/ic_vol_type_tv_light.png", "res/drawable-mdpi-v4/ic_media_stop_dark.png", "res/drawable-mdpi-v4/ic_vol_type_speaker_dark.png", "res/drawable-mdpi-v4/ic_mr_button_disabled_dark.png", "res/drawable-mdpi-v4/ic_audiotrack_light.png", "res/drawable-mdpi-v4/ic_vol_type_speaker_group_dark.png", "res/drawable-mdpi-v4/ic_media_stop_light.png", "res/drawable-mdpi-v4/ic_media_play_dark.png", "res/drawable-mdpi-v4/ic_audiotrack_dark.png", "res/drawable-mdpi-v4/ic_vol_type_speaker_light.png", "res/drawable-mdpi-v4/ic_mr_button_disconnected_dark.png", "res/drawable-mdpi-v4/ic_mr_button_disconnected_light.png", "res/drawable-mdpi-v4/ic_vol_type_speaker_group_light.png", "res/values-bs/values-bs.xml", "res/values/values.xml", "res/values-hr/values-hr.xml", "res/values-en-rAU/values-en-rAU.xml", "res/values-ro/values-ro.xml", "res/drawable-xhdpi-v4/ic_mr_button_connected_28_light.png", "res/drawable-xhdpi-v4/ic_mr_button_connected_00_light.png", "res/drawable-xhdpi-v4/ic_mr_button_connected_28_dark.png", "res/drawable-xhdpi-v4/ic_mr_button_connected_04_dark.png", "res/drawable-xhdpi-v4/ic_mr_button_connecting_28_dark.png", "res/drawable-xhdpi-v4/ic_mr_button_connecting_06_light.png", "res/drawable-xhdpi-v4/ic_dialog_close_light.png", "res/drawable-xhdpi-v4/ic_mr_button_connecting_29_dark.png", "res/drawable-xhdpi-v4/ic_mr_button_connected_01_light.png", "res/drawable-xhdpi-v4/ic_mr_button_connected_23_dark.png", "res/drawable-xhdpi-v4/ic_mr_button_connecting_18_light.png", "res/drawable-xhdpi-v4/ic_mr_button_connecting_04_dark.png", "res/drawable-xhdpi-v4/ic_mr_button_connecting_12_light.png", "res/drawable-xhdpi-v4/ic_media_pause_light.png", "res/drawable-xhdpi-v4/ic_mr_button_disabled_light.png", "res/drawable-xhdpi-v4/ic_mr_button_grey.png", "res/drawable-xhdpi-v4/ic_mr_button_connecting_14_dark.png", "res/drawable-xhdpi-v4/ic_media_play_light.png", "res/drawable-xhdpi-v4/ic_mr_button_connecting_12_dark.png", "res/drawable-xhdpi-v4/ic_mr_button_connected_14_light.png", "res/drawable-xhdpi-v4/ic_dialog_close_dark.png", "res/drawable-xhdpi-v4/ic_mr_button_connecting_30_dark.png", "res/drawable-xhdpi-v4/ic_mr_button_connected_27_dark.png", "res/drawable-xhdpi-v4/ic_mr_button_connecting_07_light.png", "res/drawable-xhdpi-v4/ic_mr_button_connecting_25_dark.png", "res/drawable-xhdpi-v4/ic_mr_button_connecting_18_dark.png", "res/drawable-xhdpi-v4/ic_mr_button_connected_23_light.png", "res/drawable-xhdpi-v4/ic_mr_button_connected_11_light.png", "res/drawable-xhdpi-v4/ic_mr_button_connecting_08_light.png", "res/drawable-xhdpi-v4/ic_mr_button_connected_02_dark.png", "res/drawable-xhdpi-v4/ic_mr_button_connecting_22_dark.png", "res/drawable-xhdpi-v4/ic_mr_button_connected_08_light.png", "res/drawable-xhdpi-v4/ic_mr_button_connecting_20_light.png", "res/drawable-xhdpi-v4/ic_mr_button_connected_18_light.png", "res/drawable-xhdpi-v4/ic_mr_button_connected_19_light.png", "res/drawable-xhdpi-v4/ic_vol_type_tv_dark.png", "res/drawable-xhdpi-v4/ic_mr_button_connecting_05_light.png", "res/drawable-xhdpi-v4/ic_mr_button_connecting_10_dark.png", "res/drawable-xhdpi-v4/ic_mr_button_connecting_02_dark.png", "res/drawable-xhdpi-v4/ic_mr_button_connected_25_dark.png", "res/drawable-xhdpi-v4/ic_mr_button_connected_18_dark.png", "res/drawable-xhdpi-v4/ic_mr_button_connecting_22_light.png", "res/drawable-xhdpi-v4/ic_mr_button_connected_22_light.png", "res/drawable-xhdpi-v4/ic_mr_button_connecting_24_dark.png", "res/drawable-xhdpi-v4/ic_media_pause_dark.png", "res/drawable-xhdpi-v4/ic_mr_button_connected_29_light.png", "res/drawable-xhdpi-v4/ic_mr_button_connected_03_light.png", "res/drawable-xhdpi-v4/ic_vol_type_tv_light.png", "res/drawable-xhdpi-v4/ic_mr_button_connected_11_dark.png", "res/drawable-xhdpi-v4/ic_mr_button_connected_30_light.png", "res/drawable-xhdpi-v4/ic_mr_button_connecting_23_light.png", "res/drawable-xhdpi-v4/ic_mr_button_connected_29_dark.png", "res/drawable-xhdpi-v4/ic_media_stop_dark.png", "res/drawable-xhdpi-v4/ic_mr_button_connected_27_light.png", "res/drawable-xhdpi-v4/ic_mr_button_connected_25_light.png", "res/drawable-xhdpi-v4/ic_mr_button_connected_06_dark.png", "res/drawable-xhdpi-v4/ic_mr_button_connected_00_dark.png", "res/drawable-xhdpi-v4/ic_mr_button_connected_02_light.png", "res/drawable-xhdpi-v4/ic_mr_button_connected_17_light.png", "res/drawable-xhdpi-v4/ic_mr_button_connecting_03_dark.png", "res/drawable-xhdpi-v4/ic_mr_button_connected_09_dark.png", "res/drawable-xhdpi-v4/ic_vol_type_speaker_dark.png", "res/drawable-xhdpi-v4/ic_mr_button_connecting_00_dark.png", "res/drawable-xhdpi-v4/ic_mr_button_connected_24_light.png", "res/drawable-xhdpi-v4/ic_mr_button_connected_26_light.png", "res/drawable-xhdpi-v4/ic_mr_button_connecting_29_light.png", "res/drawable-xhdpi-v4/ic_mr_button_connecting_30_light.png", "res/drawable-xhdpi-v4/ic_mr_button_connected_05_dark.png", "res/drawable-xhdpi-v4/ic_mr_button_connecting_08_dark.png", "res/drawable-xhdpi-v4/ic_mr_button_connecting_15_light.png", "res/drawable-xhdpi-v4/ic_mr_button_connecting_17_dark.png", "res/drawable-xhdpi-v4/ic_mr_button_disabled_dark.png", "res/drawable-xhdpi-v4/ic_mr_button_connecting_26_light.png", "res/drawable-xhdpi-v4/ic_mr_button_connected_24_dark.png", "res/drawable-xhdpi-v4/ic_mr_button_connecting_16_light.png", "res/drawable-xhdpi-v4/ic_mr_button_connecting_27_dark.png", "res/drawable-xhdpi-v4/ic_audiotrack_light.png", "res/drawable-xhdpi-v4/ic_mr_button_connected_13_dark.png", "res/drawable-xhdpi-v4/ic_mr_button_connected_16_dark.png", "res/drawable-xhdpi-v4/ic_mr_button_connecting_04_light.png", "res/drawable-xhdpi-v4/ic_vol_type_speaker_group_dark.png", "res/drawable-xhdpi-v4/ic_mr_button_connecting_13_light.png", "res/drawable-xhdpi-v4/ic_media_stop_light.png", "res/drawable-xhdpi-v4/ic_mr_button_connecting_17_light.png", "res/drawable-xhdpi-v4/ic_mr_button_connected_16_light.png", "res/drawable-xhdpi-v4/ic_mr_button_connecting_16_dark.png", "res/drawable-xhdpi-v4/ic_mr_button_connecting_01_light.png", "res/drawable-xhdpi-v4/ic_mr_button_connected_07_dark.png", "res/drawable-xhdpi-v4/ic_mr_button_connected_13_light.png", "res/drawable-xhdpi-v4/ic_mr_button_connected_19_dark.png", "res/drawable-xhdpi-v4/ic_mr_button_connecting_00_light.png", "res/drawable-xhdpi-v4/ic_mr_button_connected_14_dark.png", "res/drawable-xhdpi-v4/ic_mr_button_connecting_03_light.png", "res/drawable-xhdpi-v4/ic_mr_button_connecting_15_dark.png", "res/drawable-xhdpi-v4/ic_mr_button_connected_20_light.png", "res/drawable-xhdpi-v4/ic_media_play_dark.png", "res/drawable-xhdpi-v4/ic_mr_button_connected_03_dark.png", "res/drawable-xhdpi-v4/ic_mr_button_connecting_27_light.png", "res/drawable-xhdpi-v4/ic_mr_button_connected_21_light.png", "res/drawable-xhdpi-v4/ic_mr_button_connecting_28_light.png", "res/drawable-xhdpi-v4/ic_mr_button_connecting_02_light.png", "res/drawable-xhdpi-v4/ic_mr_button_connecting_10_light.png", "res/drawable-xhdpi-v4/ic_mr_button_connecting_23_dark.png", "res/drawable-xhdpi-v4/ic_mr_button_connected_15_dark.png", "res/drawable-xhdpi-v4/ic_mr_button_connected_21_dark.png", "res/drawable-xhdpi-v4/ic_mr_button_connecting_05_dark.png", "res/drawable-xhdpi-v4/ic_mr_button_connecting_19_dark.png", "res/drawable-xhdpi-v4/ic_mr_button_connecting_20_dark.png", "res/drawable-xhdpi-v4/ic_mr_button_connecting_06_dark.png", "res/drawable-xhdpi-v4/ic_audiotrack_dark.png", "res/drawable-xhdpi-v4/ic_mr_button_connecting_21_dark.png", "res/drawable-xhdpi-v4/ic_mr_button_connecting_09_dark.png", "res/drawable-xhdpi-v4/ic_mr_button_connected_20_dark.png", "res/drawable-xhdpi-v4/ic_vol_type_speaker_light.png", "res/drawable-xhdpi-v4/ic_mr_button_disconnected_dark.png", "res/drawable-xhdpi-v4/ic_mr_button_connecting_19_light.png", "res/drawable-xhdpi-v4/ic_mr_button_connected_22_dark.png", "res/drawable-xhdpi-v4/ic_mr_button_connecting_25_light.png", "res/drawable-xhdpi-v4/ic_mr_button_connecting_09_light.png", "res/drawable-xhdpi-v4/ic_mr_button_connecting_11_light.png", "res/drawable-xhdpi-v4/ic_mr_button_connected_12_dark.png", "res/drawable-xhdpi-v4/ic_mr_button_connected_10_light.png", "res/drawable-xhdpi-v4/ic_mr_button_connecting_13_dark.png", "res/drawable-xhdpi-v4/ic_mr_button_connecting_24_light.png", "res/drawable-xhdpi-v4/ic_mr_button_connecting_01_dark.png", "res/drawable-xhdpi-v4/ic_mr_button_connecting_26_dark.png", "res/drawable-xhdpi-v4/ic_mr_button_connected_26_dark.png", "res/drawable-xhdpi-v4/ic_mr_button_connecting_07_dark.png", "res/drawable-xhdpi-v4/ic_mr_button_connected_04_light.png", "res/drawable-xhdpi-v4/ic_mr_button_connected_10_dark.png", "res/drawable-xhdpi-v4/ic_mr_button_connected_17_dark.png", "res/drawable-xhdpi-v4/ic_mr_button_connected_05_light.png", "res/drawable-xhdpi-v4/ic_mr_button_connected_07_light.png", "res/drawable-xhdpi-v4/ic_mr_button_connected_15_light.png", "res/drawable-xhdpi-v4/ic_mr_button_connected_08_dark.png", "res/drawable-xhdpi-v4/ic_mr_button_connecting_11_dark.png", "res/drawable-xhdpi-v4/ic_mr_button_connected_09_light.png", "res/drawable-xhdpi-v4/ic_mr_button_disconnected_light.png", "res/drawable-xhdpi-v4/ic_mr_button_connected_12_light.png", "res/drawable-xhdpi-v4/ic_vol_type_speaker_group_light.png", "res/drawable-xhdpi-v4/ic_mr_button_connecting_14_light.png", "res/drawable-xhdpi-v4/ic_mr_button_connecting_21_light.png", "res/drawable-xhdpi-v4/ic_mr_button_connected_30_dark.png", "res/drawable-xhdpi-v4/ic_mr_button_connected_06_light.png", "res/drawable-xhdpi-v4/ic_mr_button_connected_01_dark.png", "res/values-vi/values-vi.xml", "res/values-ko/values-ko.xml", "res/values-zh-rTW/values-zh-rTW.xml", "res/values-cs/values-cs.xml", "res/values-ml/values-ml.xml", "res/values-te/values-te.xml", "res/values-si/values-si.xml", "res/values-es/values-es.xml", "res/values-af/values-af.xml", "res/values-zu/values-zu.xml", "res/values-lo/values-lo.xml", "res/values-land/values-land.xml", "res/values-mk/values-mk.xml", "res/values-sl/values-sl.xml", "res/values-sw600dp-v13/values-sw600dp-v13.xml", "res/values-sw/values-sw.xml", "res/values-bn/values-bn.xml", "res/values-sk/values-sk.xml", "res/values-lv/values-lv.xml", "res/values-is/values-is.xml", "res/values-da/values-da.xml", "res/values-it/values-it.xml", "res/values-gl/values-gl.xml", "res/values-de/values-de.xml", "res/values-be/values-be.xml", "res/values-en-rCA/values-en-rCA.xml", "res/values-fa/values-fa.xml", "res/values-ca/values-ca.xml", "res/values-th/values-th.xml", "res/values-nl/values-nl.xml", "res/values-hy/values-hy.xml", "res/values-zh-rHK/values-zh-rHK.xml", "res/values-tl/values-tl.xml", "res/values-kk/values-kk.xml", "res/values-pt/values-pt.xml", "res/values-my/values-my.xml", "res/drawable-xxxhdpi-v4/ic_group_collapse_13.png", "res/drawable-xxxhdpi-v4/ic_mr_button_grey.png", "res/drawable-xxxhdpi-v4/ic_group_collapse_09.png", "res/drawable-xxxhdpi-v4/ic_group_expand_06.png", "res/drawable-xxxhdpi-v4/ic_group_expand_03.png", "res/drawable-xxxhdpi-v4/ic_group_expand_09.png", "res/drawable-xxxhdpi-v4/ic_group_expand_07.png", "res/drawable-xxxhdpi-v4/ic_group_expand_08.png", "res/drawable-xxxhdpi-v4/ic_group_expand_14.png", "res/drawable-xxxhdpi-v4/ic_group_collapse_04.png", "res/drawable-xxxhdpi-v4/ic_group_collapse_14.png", "res/drawable-xxxhdpi-v4/ic_group_expand_04.png", "res/drawable-xxxhdpi-v4/ic_group_collapse_05.png", "res/drawable-xxxhdpi-v4/ic_group_expand_11.png", "res/drawable-xxxhdpi-v4/ic_group_expand_10.png", "res/drawable-xxxhdpi-v4/ic_group_expand_05.png", "res/drawable-xxxhdpi-v4/ic_group_expand_13.png", "res/drawable-xxxhdpi-v4/ic_group_collapse_06.png", "res/drawable-xxxhdpi-v4/ic_group_expand_15.png", "res/drawable-xxxhdpi-v4/ic_group_expand_02.png", "res/drawable-xxxhdpi-v4/ic_group_collapse_10.png", "res/drawable-xxxhdpi-v4/ic_group_collapse_15.png", "res/drawable-xxxhdpi-v4/ic_group_expand_00.png", "res/drawable-xxxhdpi-v4/ic_group_collapse_02.png", "res/drawable-xxxhdpi-v4/ic_group_expand_12.png", "res/drawable-xxxhdpi-v4/ic_group_collapse_03.png", "res/drawable-xxxhdpi-v4/ic_group_collapse_08.png", "res/drawable-xxxhdpi-v4/ic_group_collapse_01.png", "res/drawable-xxxhdpi-v4/ic_group_expand_01.png", "res/drawable-xxxhdpi-v4/ic_group_collapse_00.png", "res/drawable-xxxhdpi-v4/ic_group_collapse_12.png", "res/drawable-xxxhdpi-v4/ic_group_collapse_07.png", "res/drawable-xxxhdpi-v4/ic_group_collapse_11.png", "res/values-et/values-et.xml", "res/values-en-rIN/values-en-rIN.xml", "res/values-sr/values-sr.xml", "res/values-fr/values-fr.xml", "res/values-kn/values-kn.xml", "res/values-nb/values-nb.xml", "res/values-sw720dp-v13/values-sw720dp-v13.xml", "res/values-ne/values-ne.xml", "res/drawable/mr_media_pause_dark.xml", "res/drawable/mr_dialog_close_dark.xml", "res/drawable/mr_media_stop_light.xml", "res/drawable/mr_button_dark.xml", "res/drawable/mr_button_connected_dark.xml", "res/drawable/mr_dialog_material_background_dark.xml", "res/drawable/mr_button_connecting_light.xml", "res/drawable/mr_media_play_light.xml", "res/drawable/mr_media_pause_light.xml", "res/drawable/mr_dialog_material_background_light.xml", "res/drawable/mr_button_connecting_dark.xml", "res/drawable/mr_media_stop_dark.xml", "res/drawable/mr_dialog_close_light.xml", "res/drawable/mr_group_expand.xml", "res/drawable/mr_vol_type_audiotrack_dark.xml", "res/drawable/mr_vol_type_audiotrack_light.xml", "res/drawable/mr_media_play_dark.xml", "res/drawable/mr_group_collapse.xml", "res/drawable/mr_button_light.xml", "res/drawable/mr_button_connected_light.xml", "res/values-b+sr+Latn/values-b+sr+Latn.xml", "res/values-ka/values-ka.xml", "res/values-zh-rCN/values-zh-rCN.xml", "res/values-az/values-az.xml", "res/values-sq/values-sq.xml", "res/values-hi/values-hi.xml", "res/values-in/values-in.xml", "res/values-uk/values-uk.xml" ]
+subjar_tuples = [  ]
+subjars = [  ]
diff --git a/build/secondary/third_party/android_tools/support/android_support_v7_palette_java.info b/build/secondary/third_party/android_tools/support/android_support_v7_palette_java.info
index a2ebd4a..cd54060 100644
--- a/build/secondary/third_party/android_tools/support/android_support_v7_palette_java.info
+++ b/build/secondary/third_party/android_tools/support/android_support_v7_palette_java.info
@@ -6,7 +6,7 @@
 has_classes_jar = true
 has_native_libraries = false
 has_proguard_flags = false
-has_r_text_file = false
+has_r_text_file = true
 is_manifest_empty = true
 resources = [  ]
 subjar_tuples = [  ]
diff --git a/build/secondary/third_party/android_tools/support/android_support_v7_preference_java.info b/build/secondary/third_party/android_tools/support/android_support_v7_preference_java.info
index fc60261..25a4927 100644
--- a/build/secondary/third_party/android_tools/support/android_support_v7_preference_java.info
+++ b/build/secondary/third_party/android_tools/support/android_support_v7_preference_java.info
@@ -8,6 +8,6 @@
 has_proguard_flags = true
 has_r_text_file = true
 is_manifest_empty = true
-resources = [ "res/values-v17/values-v17.xml", "res/layout/preference_dropdown.xml", "res/layout/preference_list_fragment.xml", "res/layout/preference.xml", "res/layout/preference_category.xml", "res/layout/preference_widget_checkbox.xml", "res/layout/preference_widget_switch_compat.xml", "res/layout/preference_information.xml", "res/layout/preference_recyclerview.xml", "res/layout/preference_dialog_edittext.xml", "res/values/values.xml", "res/layout-v11/preference_dropdown.xml", "res/layout-v11/preference.xml" ]
+resources = [ "res/layout-v11/preference.xml", "res/layout-v11/preference_dropdown.xml", "res/layout/preference_recyclerview.xml", "res/layout/preference_widget_checkbox.xml", "res/layout/preference_widget_seekbar.xml", "res/layout/preference_widget_switch_compat.xml", "res/layout/preference_list_fragment.xml", "res/layout/preference_dialog_edittext.xml", "res/layout/preference_information.xml", "res/layout/preference_category.xml", "res/values/values.xml", "res/values-v17/values-v17.xml" ]
 subjar_tuples = [  ]
 subjars = [  ]
diff --git a/build/secondary/third_party/android_tools/support/android_support_vector_drawable_java.info b/build/secondary/third_party/android_tools/support/android_support_vector_drawable_java.info
index a2ebd4a..cd54060 100644
--- a/build/secondary/third_party/android_tools/support/android_support_vector_drawable_java.info
+++ b/build/secondary/third_party/android_tools/support/android_support_vector_drawable_java.info
@@ -6,7 +6,7 @@
 has_classes_jar = true
 has_native_libraries = false
 has_proguard_flags = false
-has_r_text_file = false
+has_r_text_file = true
 is_manifest_empty = true
 resources = [  ]
 subjar_tuples = [  ]
diff --git a/build/secondary/third_party/crashpad/crashpad/client/BUILD.gn b/build/secondary/third_party/crashpad/crashpad/client/BUILD.gn
index 0d9a0c3f..d1fe139 100644
--- a/build/secondary/third_party/crashpad/crashpad/client/BUILD.gn
+++ b/build/secondary/third_party/crashpad/crashpad/client/BUILD.gn
@@ -8,6 +8,10 @@
 
 static_library("client") {
   sources = [
+    "annotation.cc",
+    "annotation.h",
+    "annotation_list.cc",
+    "annotation_list.h",
     "crash_report_database.cc",
     "crash_report_database.h",
     "crash_report_database_mac.mm",
diff --git a/build/secondary/third_party/crashpad/crashpad/compat/BUILD.gn b/build/secondary/third_party/crashpad/crashpad/compat/BUILD.gn
index 276dd58a9..cbffb36 100644
--- a/build/secondary/third_party/crashpad/crashpad/compat/BUILD.gn
+++ b/build/secondary/third_party/crashpad/crashpad/compat/BUILD.gn
@@ -40,6 +40,7 @@
       "win/sys/types.h",
       "win/time.cc",
       "win/time.h",
+      "win/winbase.h",
       "win/winnt.h",
       "win/winternl.h",
     ]
diff --git a/build/secondary/third_party/crashpad/crashpad/test/BUILD.gn b/build/secondary/third_party/crashpad/crashpad/test/BUILD.gn
index c9375a1..a194928d 100644
--- a/build/secondary/third_party/crashpad/crashpad/test/BUILD.gn
+++ b/build/secondary/third_party/crashpad/crashpad/test/BUILD.gn
@@ -10,6 +10,8 @@
     "file.cc",
     "file.h",
     "gtest_death_check.h",
+    "gtest_disabled.cc",
+    "gtest_disabled.h",
     "hex_string.cc",
     "hex_string.h",
     "mac/dyld.cc",
@@ -58,30 +60,38 @@
   }
 }
 
-static_library("crashpad_gtest_main") {
+static_library("crashpad_gmock_main") {
   testonly = true
-  defines = [ "CRASHPAD_IN_CHROMIUM" ]
+  defines = [
+    "CRASHPAD_IN_CHROMIUM",
+    "CRASHPAD_TEST_LAUNCHER_GMOCK",
+  ]
   sources = [
     "gtest_main.cc",
   ]
   deps = [
     ":crashpad_test",
+    "//base",
     "//base/test:test_support",
+    "//testing/gmock",
     "//testing/gtest",
   ]
   include_dirs = [ ".." ]
 }
 
-static_library("crashpad_gmock_main") {
+static_library("crashpad_gtest_main") {
   testonly = true
-  defines = [ "CRASHPAD_IN_CHROMIUM" ]
+  defines = [
+    "CRASHPAD_IN_CHROMIUM",
+    "CRASHPAD_TEST_LAUNCHER_GTEST",
+  ]
   sources = [
-    "gmock_main.cc",
+    "gtest_main.cc",
   ]
   deps = [
     ":crashpad_test",
+    "//base",
     "//base/test:test_support",
-    "//testing/gmock",
     "//testing/gtest",
   ]
   include_dirs = [ ".." ]
diff --git a/build/secondary/third_party/crashpad/crashpad/util/BUILD.gn b/build/secondary/third_party/crashpad/crashpad/util/BUILD.gn
index e83602b..65367b93 100644
--- a/build/secondary/third_party/crashpad/crashpad/util/BUILD.gn
+++ b/build/secondary/third_party/crashpad/crashpad/util/BUILD.gn
@@ -322,8 +322,12 @@
 test("crashpad_util_test") {
   sources = [
     "file/delimited_file_reader_test.cc",
+    "file/directory_reader_test.cc",
     "file/file_io_test.cc",
     "file/file_reader_test.cc",
+    "file/filesystem_test.cc",
+    "file/filesystem_test_util.cc",
+    "file/filesystem_test_util.h",
     "file/string_file_test.cc",
     "mac/launchd_test.mm",
     "mac/mac_util_test.mm",
@@ -419,19 +423,9 @@
       ":crashpad_util_test_safe_terminate_process_test_child",
     ]
     libs = [ "rpcrt4.lib" ]
-  } else {
-    # These tests use symbolic links, which require admin priviledges on
-    # Windows before Windows 10.
-    sources += [
-      "file/directory_reader_test.cc",
-      "file/filesystem_test.cc",
-      "file/filesystem_test_util.cc",
-      "file/filesystem_test_util.h",
-    ]
   }
 
   include_dirs = [ ".." ]
-  defines = [ "CRASHPAD_IN_CHROMIUM" ]
 
   data = [
     "net/http_transport_test_server.py",
diff --git a/cc/BUILD.gn b/cc/BUILD.gn
index fb611f3..725c089 100644
--- a/cc/BUILD.gn
+++ b/cc/BUILD.gn
@@ -335,6 +335,8 @@
     "trees/transform_node.h",
     "trees/tree_synchronizer.cc",
     "trees/tree_synchronizer.h",
+    "trees/ukm_manager.cc",
+    "trees/ukm_manager.h",
   ]
 
   if (current_cpu == "x86" || current_cpu == "x64") {
@@ -356,6 +358,7 @@
     "//base",
     "//base/third_party/dynamic_annotations",
     "//cc/paint",
+    "//components/ukm",
     "//components/viz/common",
     "//gpu",
     "//gpu/command_buffer/client:gles2_implementation",
@@ -365,6 +368,7 @@
     "//gpu/vulkan:features",
     "//media",
     "//mojo/public/cpp/bindings:struct_traits",
+    "//services/metrics/public/cpp:ukm_builders",
     "//third_party/libyuv",
     "//ui/events:events_base",
     "//ui/gfx",
@@ -512,6 +516,8 @@
     "test/test_tile_priorities.h",
     "test/test_tile_task_runner.cc",
     "test/test_tile_task_runner.h",
+    "test/test_ukm_recorder_factory.cc",
+    "test/test_ukm_recorder_factory.h",
     "test/test_web_graphics_context_3d.cc",
     "test/test_web_graphics_context_3d.h",
   ]
@@ -526,6 +532,8 @@
     "//base/test:test_support",
     "//base/third_party/dynamic_annotations",
     "//cc/paint",
+    "//components/ukm",
+    "//components/ukm:test_support",
     "//components/viz/common",
     "//components/viz/service",
     "//components/viz/test:test_support",
@@ -671,6 +679,7 @@
     "trees/property_tree_unittest.cc",
     "trees/swap_promise_manager_unittest.cc",
     "trees/tree_synchronizer_unittest.cc",
+    "trees/ukm_manager_unittest.cc",
 
     # Animation test files.
     "animation/animation_host_unittest.cc",
@@ -704,6 +713,7 @@
     "//base/test:test_support",
     "//cc/ipc",
     "//cc/paint",
+    "//components/ukm:test_support",
     "//components/viz/common",
     "//components/viz/service",
     "//components/viz/test:test_support",
diff --git a/cc/DEPS b/cc/DEPS
index 6899c79..0e483c8 100644
--- a/cc/DEPS
+++ b/cc/DEPS
@@ -1,4 +1,5 @@
 include_rules = [
+  "+components/ukm/test_ukm_recorder.h",
   "+components/viz/common",
   "+gpu/GLES2",
   "+gpu/command_buffer/client/context_support.h",
@@ -15,6 +16,7 @@
   "+gpu/vulkan",
   "+media",
   "+skia/ext",
+  "+services/metrics/public/cpp",
   "+third_party/khronos/GLES2/gl2.h",
   "+third_party/khronos/GLES2/gl2ext.h",
   "+third_party/libyuv",
diff --git a/cc/paint/record_paint_canvas.cc b/cc/paint/record_paint_canvas.cc
index 1ecd86f2..f8d27db 100644
--- a/cc/paint/record_paint_canvas.cc
+++ b/cc/paint/record_paint_canvas.cc
@@ -166,18 +166,22 @@
 }
 
 SkRect RecordPaintCanvas::getLocalClipBounds() const {
+  DCHECK(InitializedWithRecordingBounds());
   return GetCanvas()->getLocalClipBounds();
 }
 
 bool RecordPaintCanvas::getLocalClipBounds(SkRect* bounds) const {
+  DCHECK(InitializedWithRecordingBounds());
   return GetCanvas()->getLocalClipBounds(bounds);
 }
 
 SkIRect RecordPaintCanvas::getDeviceClipBounds() const {
+  DCHECK(InitializedWithRecordingBounds());
   return GetCanvas()->getDeviceClipBounds();
 }
 
 bool RecordPaintCanvas::getDeviceClipBounds(SkIRect* bounds) const {
+  DCHECK(InitializedWithRecordingBounds());
   return GetCanvas()->getDeviceClipBounds(bounds);
 }
 
@@ -287,10 +291,12 @@
 }
 
 bool RecordPaintCanvas::isClipEmpty() const {
+  DCHECK(InitializedWithRecordingBounds());
   return GetCanvas()->isClipEmpty();
 }
 
 bool RecordPaintCanvas::isClipRect() const {
+  DCHECK(InitializedWithRecordingBounds());
   return GetCanvas()->isClipRect();
 }
 
@@ -327,4 +333,11 @@
   return &*canvas_;
 }
 
+bool RecordPaintCanvas::InitializedWithRecordingBounds() const {
+  // If the RecordPaintCanvas is initialized with an empty bounds then
+  // the various clip related functions are not valid and should not
+  // be called.
+  return !recording_bounds_.isEmpty();
+}
+
 }  // namespace cc
diff --git a/cc/paint/record_paint_canvas.h b/cc/paint/record_paint_canvas.h
index cc187c5..12b6dcc 100644
--- a/cc/paint/record_paint_canvas.h
+++ b/cc/paint/record_paint_canvas.h
@@ -116,6 +116,8 @@
   const SkNoDrawCanvas* GetCanvas() const;
   SkNoDrawCanvas* GetCanvas();
 
+  bool InitializedWithRecordingBounds() const;
+
   DisplayItemList* list_;
 
   // TODO(enne): Although RecordPaintCanvas is mostly a write-only interface
diff --git a/cc/raster/raster_buffer_provider_unittest.cc b/cc/raster/raster_buffer_provider_unittest.cc
index b79ef73..d0a1b79 100644
--- a/cc/raster/raster_buffer_provider_unittest.cc
+++ b/cc/raster/raster_buffer_provider_unittest.cc
@@ -237,11 +237,21 @@
     tile_task_manager_->ScheduleTasks(&graph_);
   }
 
-  void AppendTask(unsigned id, const gfx::Size& size) {
+  std::unique_ptr<ScopedResource> AllocateResource(const gfx::Size& size) {
     auto resource = std::make_unique<ScopedResource>(resource_provider_.get());
-    resource->Allocate(size, ResourceProvider::TEXTURE_HINT_DEFAULT,
-                       viz::RGBA_8888, gfx::ColorSpace());
+    if (GetParam() == RASTER_BUFFER_PROVIDER_TYPE_ZERO_COPY) {
+      resource->AllocateWithGpuMemoryBuffer(
+          size, viz::RGBA_8888, gfx::BufferUsage::GPU_READ_CPU_READ_WRITE,
+          gfx::ColorSpace());
+    } else {
+      resource->Allocate(size, ResourceProvider::TEXTURE_HINT_DEFAULT,
+                         viz::RGBA_8888, gfx::ColorSpace());
+    }
+    return resource;
+  }
 
+  void AppendTask(unsigned id, const gfx::Size& size) {
+    auto resource = AllocateResource(size);
     // The raster buffer has no tile ids associated with it for partial update,
     // so doesn't need to provide a valid dirty rect.
     std::unique_ptr<RasterBuffer> raster_buffer =
@@ -255,12 +265,7 @@
   void AppendTask(unsigned id) { AppendTask(id, gfx::Size(1, 1)); }
 
   void AppendBlockingTask(unsigned id, base::Lock* lock) {
-    const gfx::Size size(1, 1);
-
-    auto resource = std::make_unique<ScopedResource>(resource_provider_.get());
-    resource->Allocate(size, ResourceProvider::TEXTURE_HINT_DEFAULT,
-                       viz::RGBA_8888, gfx::ColorSpace());
-
+    auto resource = AllocateResource(gfx::Size(1, 1));
     std::unique_ptr<RasterBuffer> raster_buffer =
         raster_buffer_provider_->AcquireBufferForRaster(resource.get(), 0, 0);
     TileTask::Vector empty;
diff --git a/cc/resources/display_resource_provider.cc b/cc/resources/display_resource_provider.cc
index 125cc4c..ca32459 100644
--- a/cc/resources/display_resource_provider.cc
+++ b/cc/resources/display_resource_provider.cc
@@ -14,6 +14,12 @@
 
 namespace cc {
 
+namespace {
+// The Resouce id in DisplayResourceProvider starts from 2 to avoid conflicts
+// with id from LayerTreeResourceProvider.
+const unsigned int kInitialResourceId = 2;
+}  // namespace
+
 DisplayResourceProvider::DisplayResourceProvider(
     viz::ContextProvider* compositor_context_provider,
     viz::SharedBitmapManager* shared_bitmap_manager,
@@ -23,7 +29,8 @@
                        shared_bitmap_manager,
                        gpu_memory_buffer_manager,
                        false,
-                       resource_settings) {}
+                       resource_settings,
+                       kInitialResourceId) {}
 
 DisplayResourceProvider::~DisplayResourceProvider() {
   while (!children_.empty())
@@ -205,7 +212,7 @@
 
     viz::ReturnedResource returned;
     returned.id = child_id;
-    returned.sync_token = resource.mailbox().sync_token();
+    returned.sync_token = resource.sync_token();
     returned.count = resource.imported_count;
     returned.lost = is_lost;
     to_return.push_back(returned);
@@ -287,19 +294,24 @@
     viz::ResourceId local_id = next_id_++;
     Resource* resource = nullptr;
     if (it->is_software) {
-      resource = InsertResource(local_id,
-                                Resource(it->mailbox_holder.mailbox, it->size,
-                                         Resource::DELEGATED, GL_LINEAR));
+      resource = InsertResource(
+          local_id,
+          Resource(it->size, Resource::DELEGATED, TEXTURE_HINT_DEFAULT,
+                   RESOURCE_TYPE_BITMAP, viz::RGBA_8888, it->color_space));
+      resource->has_shared_bitmap_id = true;
+      resource->shared_bitmap_id = it->mailbox_holder.mailbox;
     } else {
       resource = InsertResource(
           local_id,
-          Resource(0, it->size, Resource::DELEGATED,
-                   it->mailbox_holder.texture_target, it->filter,
-                   TEXTURE_HINT_DEFAULT, RESOURCE_TYPE_GL_TEXTURE, it->format));
+          Resource(it->size, Resource::DELEGATED, TEXTURE_HINT_DEFAULT,
+                   RESOURCE_TYPE_GL_TEXTURE, it->format, it->color_space));
+      resource->target = it->mailbox_holder.texture_target;
+      resource->filter = it->filter;
+      resource->original_filter = it->filter;
+      resource->min_filter = it->filter;
       resource->buffer_format = it->buffer_format;
-      resource->SetMailbox(viz::TextureMailbox(
-          it->mailbox_holder.mailbox, it->mailbox_holder.sync_token,
-          it->mailbox_holder.texture_target));
+      resource->mailbox = it->mailbox_holder.mailbox;
+      resource->UpdateSyncToken(it->mailbox_holder.sync_token);
       resource->read_lock_fences_enabled = it->read_lock_fences_enabled;
       resource->is_overlay_candidate = it->is_overlay_candidate;
 #if defined(OS_ANDROID)
@@ -308,7 +320,6 @@
       if (resource->wants_promotion_hint)
         wants_promotion_hints_set_.insert(local_id);
 #endif
-      resource->color_space = it->color_space;
     }
     resource->child_id = child;
     // Don't allocate a texture for a child.
@@ -375,12 +386,12 @@
 
   if (IsGpuResourceType(resource->type) && !resource->gl_id) {
     DCHECK(resource->origin != Resource::INTERNAL);
-    DCHECK(resource->mailbox().IsTexture());
+    DCHECK(!resource->mailbox.IsZero());
 
     GLES2Interface* gl = ContextGL();
     DCHECK(gl);
     resource->gl_id = gl->CreateAndConsumeTextureCHROMIUM(
-        resource->mailbox().target(), resource->mailbox().name());
+        resource->target, resource->mailbox.name);
     resource->SetLocallyUsed();
   }
 
@@ -390,8 +401,8 @@
         shared_bitmap_manager_->GetSharedBitmapFromId(
             resource->size, resource->shared_bitmap_id);
     if (bitmap) {
-      resource->shared_bitmap = bitmap.release();
-      resource->pixels = resource->shared_bitmap->pixels();
+      resource->SetSharedBitmap(bitmap.get());
+      resource->owned_shared_bitmap = std::move(bitmap);
     }
   }
 
diff --git a/cc/resources/layer_tree_resource_provider.cc b/cc/resources/layer_tree_resource_provider.cc
index 118c7f9..138c09f 100644
--- a/cc/resources/layer_tree_resource_provider.cc
+++ b/cc/resources/layer_tree_resource_provider.cc
@@ -15,6 +15,12 @@
 
 namespace cc {
 
+namespace {
+// The Resouce id in LayerTreeResourceProvider starts from 1 to avoid conflicts
+// with id from DisplayResourceProvider.
+const unsigned int kInitialResourceId = 1;
+}  // namespace
+
 LayerTreeResourceProvider::LayerTreeResourceProvider(
     viz::ContextProvider* compositor_context_provider,
     viz::SharedBitmapManager* shared_bitmap_manager,
@@ -25,7 +31,8 @@
                        shared_bitmap_manager,
                        gpu_memory_buffer_manager,
                        delegated_sync_points_required,
-                       resource_settings) {}
+                       resource_settings,
+                       kInitialResourceId) {}
 
 LayerTreeResourceProvider::~LayerTreeResourceProvider() {}
 
@@ -39,26 +46,25 @@
   // DisplayResourceProvider::LockForRead().
   viz::ResourceId id = next_id_++;
   DCHECK(mailbox.IsValid());
-  Resource* resource = nullptr;
+  Resource* resource = resource =
+      InsertResource(id, Resource(mailbox.size_in_pixels(), Resource::EXTERNAL,
+                                  TEXTURE_HINT_DEFAULT,
+                                  mailbox.IsTexture() ? RESOURCE_TYPE_GL_TEXTURE
+                                                      : RESOURCE_TYPE_BITMAP,
+                                  viz::RGBA_8888, mailbox.color_space()));
   if (mailbox.IsTexture()) {
-    resource = InsertResource(
-        id, Resource(0, mailbox.size_in_pixels(), Resource::EXTERNAL,
-                     mailbox.target(),
-                     mailbox.nearest_neighbor() ? GL_NEAREST : GL_LINEAR,
-                     TEXTURE_HINT_DEFAULT, RESOURCE_TYPE_GL_TEXTURE,
-                     viz::RGBA_8888));
+    GLenum filter = mailbox.nearest_neighbor() ? GL_NEAREST : GL_LINEAR;
+    resource->filter = filter;
+    resource->original_filter = filter;
+    resource->min_filter = filter;
+    resource->target = mailbox.target();
+    resource->UpdateSyncToken(mailbox.sync_token());
   } else {
     DCHECK(mailbox.IsSharedMemory());
-    viz::SharedBitmap* shared_bitmap = mailbox.shared_bitmap();
-    uint8_t* pixels = shared_bitmap->pixels();
-    DCHECK(pixels);
-    resource = InsertResource(
-        id, Resource(pixels, shared_bitmap, mailbox.size_in_pixels(),
-                     Resource::EXTERNAL, GL_LINEAR));
+    resource->SetSharedBitmap(mailbox.shared_bitmap());
   }
   resource->allocated = true;
-  resource->SetMailbox(mailbox);
-  resource->color_space = mailbox.color_space();
+  resource->mailbox = mailbox.mailbox();
   resource->release_callback =
       base::Bind(&viz::SingleReleaseCallback::Run,
                  base::Owned(release_callback.release()));
@@ -97,7 +103,7 @@
     const ResourceIdArray& resource_ids) {
   gpu::SyncToken latest_sync_token;
   for (viz::ResourceId id : resource_ids) {
-    const gpu::SyncToken& sync_token = GetResource(id)->mailbox().sync_token();
+    const gpu::SyncToken& sync_token = GetResource(id)->sync_token();
     if (sync_token.release_count() > latest_sync_token.release_count())
       latest_sync_token = sync_token;
   }
@@ -129,7 +135,7 @@
     if (settings_.delegated_sync_points_required) {
       if (resource->needs_sync_token()) {
         need_synchronization_resources.push_back(resource);
-      } else if (!resource->mailbox().sync_token().verified_flush()) {
+      } else if (!resource->sync_token().verified_flush()) {
         unverified_sync_tokens.push_back(resource->GetSyncTokenData());
       }
     }
@@ -230,7 +236,6 @@
     viz::TransferableResource* resource) {
   DCHECK(!source->locked_for_write);
   DCHECK(!source->lock_for_read_count);
-  DCHECK(source->origin != Resource::EXTERNAL || source->mailbox().IsValid());
   DCHECK(source->allocated);
   resource->id = id;
   resource->format = source->format;
@@ -247,22 +252,18 @@
   resource->color_space = source->color_space;
 
   if (source->type == RESOURCE_TYPE_BITMAP) {
+    DCHECK(source->shared_bitmap);
     resource->mailbox_holder.mailbox = source->shared_bitmap_id;
     resource->is_software = true;
-    if (source->shared_bitmap) {
-      resource->shared_bitmap_sequence_number =
-          source->shared_bitmap->sequence_number();
-    } else {
-      resource->shared_bitmap_sequence_number = 0;
-    }
+    resource->shared_bitmap_sequence_number =
+        source->shared_bitmap->sequence_number();
   } else {
-    DCHECK(source->mailbox().IsValid());
-    DCHECK(source->mailbox().IsTexture());
+    DCHECK(!source->mailbox.IsZero());
     // This is either an external resource, or a compositor resource that we
     // already exported. Make sure to forward the sync point that we were given.
-    resource->mailbox_holder.mailbox = source->mailbox().mailbox();
-    resource->mailbox_holder.texture_target = source->mailbox().target();
-    resource->mailbox_holder.sync_token = source->mailbox().sync_token();
+    resource->mailbox_holder.mailbox = source->mailbox;
+    resource->mailbox_holder.texture_target = source->target;
+    resource->mailbox_holder.sync_token = source->sync_token();
   }
 }
 
@@ -271,7 +272,7 @@
                                    viz::ResourceId resource_id)
     : resource_provider_(resource_provider), resource_id_(resource_id) {
   Resource* resource = resource_provider->LockForWrite(resource_id);
-  DCHECK(IsGpuResourceType(resource->type));
+  DCHECK_EQ(resource->type, ResourceProvider::RESOURCE_TYPE_GPU_MEMORY_BUFFER);
   size_ = resource->size;
   format_ = resource->format;
   usage_ = resource->usage;
@@ -287,12 +288,6 @@
   if (gpu_memory_buffer_) {
     resource->gpu_memory_buffer = std::move(gpu_memory_buffer_);
     resource->allocated = true;
-    resource->is_overlay_candidate = true;
-    resource->buffer_format = resource->gpu_memory_buffer->GetFormat();
-    // GpuMemoryBuffer provides direct access to the memory used by the GPU.
-    // Read lock fences are required to ensure that we're not trying to map a
-    // buffer that is currently in-use by the GPU.
-    resource->read_lock_fences_enabled = true;
     resource_provider_->CreateAndBindImage(resource);
   }
   resource_provider_->UnlockForWrite(resource);
@@ -307,7 +302,7 @@
     // Avoid crashing in release builds if GpuMemoryBuffer allocation fails.
     // http://crbug.com/554541
     if (gpu_memory_buffer_ && color_space_.IsValid())
-      gpu_memory_buffer_->SetColorSpaceForScanout(color_space_);
+      gpu_memory_buffer_->SetColorSpace(color_space_);
   }
   return gpu_memory_buffer_.get();
 }
diff --git a/cc/resources/resource_provider.cc b/cc/resources/resource_provider.cc
index 38b98f3..809731d 100644
--- a/cc/resources/resource_provider.cc
+++ b/cc/resources/resource_provider.cc
@@ -89,50 +89,33 @@
 
 namespace {
 
-GLenum TextureToStorageFormat(viz::ResourceFormat format) {
-  GLenum storage_format = GL_RGBA8_OES;
+GLenum TextureStorageFormat(viz::ResourceFormat format) {
   switch (format) {
     case viz::RGBA_8888:
-      break;
+      return GL_RGBA8_OES;
     case viz::BGRA_8888:
-      storage_format = GL_BGRA8_EXT;
-      break;
+      return GL_BGRA8_EXT;
     case viz::RGBA_F16:
-      storage_format = GL_RGBA16F_EXT;
-      break;
+      return GL_RGBA16F_EXT;
     case viz::RGBA_4444:
+      return GL_RGBA4;
     case viz::ALPHA_8:
+      return GL_ALPHA8_EXT;
     case viz::LUMINANCE_8:
+      return GL_LUMINANCE8_EXT;
     case viz::RGB_565:
-    case viz::ETC1:
+      return GL_RGB565;
     case viz::RED_8:
+      return GL_R8_EXT;
     case viz::LUMINANCE_F16:
+      return GL_LUMINANCE16F_EXT;
     case viz::R16_EXT:
-      NOTREACHED();
+      return GL_R16_EXT;
+    case viz::ETC1:
       break;
   }
-
-  return storage_format;
-}
-
-bool IsFormatSupportedForStorage(viz::ResourceFormat format, bool use_bgra) {
-  switch (format) {
-    case viz::RGBA_8888:
-    case viz::RGBA_F16:
-      return true;
-    case viz::BGRA_8888:
-      return use_bgra;
-    case viz::RGBA_4444:
-    case viz::ALPHA_8:
-    case viz::LUMINANCE_8:
-    case viz::RGB_565:
-    case viz::ETC1:
-    case viz::RED_8:
-    case viz::LUMINANCE_F16:
-    case viz::R16_EXT:
-      return false;
-  }
-  return false;
+  NOTREACHED();
+  return GL_RGBA8_OES;
 }
 
 class ScopedSetActiveTexture {
@@ -162,21 +145,13 @@
 
 }  // namespace
 
-ResourceProvider::Resource::Resource(GLuint texture_id,
-                                     const gfx::Size& size,
+ResourceProvider::Resource::Resource(const gfx::Size& size,
                                      Origin origin,
-                                     GLenum target,
-                                     GLenum filter,
                                      TextureHint hint,
                                      ResourceType type,
-                                     viz::ResourceFormat format)
-    : child_id(0),
-      gl_id(texture_id),
-      pixels(nullptr),
-      lock_for_read_count(0),
-      imported_count(0),
-      exported_count(0),
-      locked_for_write(false),
+                                     viz::ResourceFormat format,
+                                     const gfx::ColorSpace& color_space)
+    : locked_for_write(false),
       lost(false),
       marked_for_deletion(false),
       allocated(false),
@@ -189,109 +164,29 @@
 #endif
       size(size),
       origin(origin),
-      target(target),
-      original_filter(filter),
-      filter(filter),
-      min_filter(filter),
-      image_id(0),
       hint(hint),
       type(type),
-      usage(gfx::BufferUsage::GPU_READ_CPU_READ_WRITE),
-      buffer_format(gfx::BufferFormat::RGBA_8888),
       format(format),
-      shared_bitmap(nullptr) {
-}
-
-ResourceProvider::Resource::Resource(uint8_t* pixels,
-                                     viz::SharedBitmap* bitmap,
-                                     const gfx::Size& size,
-                                     Origin origin,
-                                     GLenum filter)
-    : child_id(0),
-      gl_id(0),
-      pixels(pixels),
-      lock_for_read_count(0),
-      imported_count(0),
-      exported_count(0),
-      locked_for_write(false),
-      lost(false),
-      marked_for_deletion(false),
-      allocated(false),
-      read_lock_fences_enabled(false),
-      has_shared_bitmap_id(!!bitmap),
-      is_overlay_candidate(false),
-#if defined(OS_ANDROID)
-      is_backed_by_surface_texture(false),
-      wants_promotion_hint(false),
-#endif
-      size(size),
-      origin(origin),
-      target(0),
-      original_filter(filter),
-      filter(filter),
-      min_filter(filter),
-      image_id(0),
-      hint(TEXTURE_HINT_DEFAULT),
-      type(RESOURCE_TYPE_BITMAP),
-      buffer_format(gfx::BufferFormat::RGBA_8888),
-      format(viz::RGBA_8888),
-      shared_bitmap(bitmap) {
-  DCHECK(origin == DELEGATED || pixels);
-  if (bitmap)
-    shared_bitmap_id = bitmap->id();
-}
-
-ResourceProvider::Resource::Resource(const viz::SharedBitmapId& bitmap_id,
-                                     const gfx::Size& size,
-                                     Origin origin,
-                                     GLenum filter)
-    : child_id(0),
-      gl_id(0),
-      pixels(nullptr),
-      lock_for_read_count(0),
-      imported_count(0),
-      exported_count(0),
-      locked_for_write(false),
-      lost(false),
-      marked_for_deletion(false),
-      allocated(false),
-      read_lock_fences_enabled(false),
-      has_shared_bitmap_id(true),
-      is_overlay_candidate(false),
-#if defined(OS_ANDROID)
-      is_backed_by_surface_texture(false),
-      wants_promotion_hint(false),
-#endif
-      size(size),
-      origin(origin),
-      target(0),
-      original_filter(filter),
-      filter(filter),
-      min_filter(filter),
-      image_id(0),
-      hint(TEXTURE_HINT_DEFAULT),
-      type(RESOURCE_TYPE_BITMAP),
-      buffer_format(gfx::BufferFormat::RGBA_8888),
-      format(viz::RGBA_8888),
-      shared_bitmap_id(bitmap_id),
-      shared_bitmap(nullptr) {
+      color_space(color_space) {
 }
 
 ResourceProvider::Resource::Resource(Resource&& other) = default;
 
 ResourceProvider::Resource::~Resource() = default;
 
-void ResourceProvider::Resource::SetMailbox(
-    const viz::TextureMailbox& mailbox) {
-  DCHECK(!mailbox.sync_token().HasData() || IsGpuResourceType(type));
-  mailbox_ = mailbox;
-  synchronization_state_ =
-      mailbox.sync_token().HasData() ? NEEDS_WAIT : SYNCHRONIZED;
+void ResourceProvider::Resource::SetSharedBitmap(viz::SharedBitmap* bitmap) {
+  DCHECK(bitmap);
+  DCHECK(bitmap->pixels());
+  allocated = true;
+  shared_bitmap = bitmap;
+  pixels = bitmap->pixels();
+  has_shared_bitmap_id = true;
+  shared_bitmap_id = bitmap->id();
 }
 
 void ResourceProvider::Resource::SetLocallyUsed() {
   synchronization_state_ = LOCALLY_USED;
-  mailbox_.set_sync_token(gpu::SyncToken());
+  sync_token_.Clear();
 }
 
 void ResourceProvider::Resource::SetSynchronized() {
@@ -303,12 +198,12 @@
   DCHECK(IsGpuResourceType(type));
   // An empty sync token may be used if commands are guaranteed to have run on
   // the gpu process or in case of context loss.
-  mailbox_.set_sync_token(sync_token);
+  sync_token_ = sync_token;
   synchronization_state_ = sync_token.HasData() ? NEEDS_WAIT : SYNCHRONIZED;
 }
 
 int8_t* ResourceProvider::Resource::GetSyncTokenData() {
-  return mailbox_.GetSyncTokenData();
+  return sync_token_.GetData();
 }
 
 void ResourceProvider::Resource::WaitSyncToken(gpu::gles2::GLES2Interface* gl) {
@@ -319,7 +214,7 @@
   // the UpdateSyncToken() function). The WaitSyncTokenCHROMIUM() function
   // handles empty sync tokens properly so just wait anyways and update the
   // state the synchronized.
-  gl->WaitSyncTokenCHROMIUM(mailbox_.sync_token().GetConstData());
+  gl->WaitSyncTokenCHROMIUM(sync_token_.GetConstData());
   SetSynchronized();
 }
 
@@ -335,29 +230,26 @@
     viz::ContextProvider* compositor_context_provider,
     bool delegated_sync_points_required,
     const viz::ResourceSettings& resource_settings)
-    : default_resource_type(resource_settings.use_gpu_memory_buffer_resources
-                                ? RESOURCE_TYPE_GPU_MEMORY_BUFFER
-                                : RESOURCE_TYPE_GL_TEXTURE),
-      yuv_highbit_resource_format(resource_settings.high_bit_for_testing
+    : yuv_highbit_resource_format(resource_settings.high_bit_for_testing
                                       ? viz::R16_EXT
                                       : viz::LUMINANCE_8),
+      use_gpu_memory_buffer_resources(
+          resource_settings.use_gpu_memory_buffer_resources),
       delegated_sync_points_required(delegated_sync_points_required) {
   if (!compositor_context_provider) {
-    default_resource_type = RESOURCE_TYPE_BITMAP;
     // Pick an arbitrary limit here similar to what hardware might.
     max_texture_size = 16 * 1024;
     best_texture_format = viz::RGBA_8888;
     return;
   }
 
-  DCHECK(IsGpuResourceType(default_resource_type));
-
   const auto& caps = compositor_context_provider->ContextCapabilities();
-  use_texture_storage_ext = caps.texture_storage;
+  use_texture_storage = caps.texture_storage;
   use_texture_format_bgra = caps.texture_format_bgra8888;
   use_texture_usage_hint = caps.texture_usage;
   use_texture_npot = caps.texture_npot;
   use_sync_query = caps.sync_query;
+  use_texture_storage_image = caps.texture_storage_image;
 
   if (caps.disable_one_component_textures) {
     yuv_resource_format = yuv_highbit_resource_format = viz::RGBA_8888;
@@ -383,14 +275,15 @@
     viz::SharedBitmapManager* shared_bitmap_manager,
     gpu::GpuMemoryBufferManager* gpu_memory_buffer_manager,
     bool delegated_sync_points_required,
-    const viz::ResourceSettings& resource_settings)
+    const viz::ResourceSettings& resource_settings,
+    viz::ResourceId next_id)
     : settings_(compositor_context_provider,
                 delegated_sync_points_required,
                 resource_settings),
       compositor_context_provider_(compositor_context_provider),
       shared_bitmap_manager_(shared_bitmap_manager),
       gpu_memory_buffer_manager_(gpu_memory_buffer_manager),
-      next_id_(1),
+      next_id_(next_id),
       next_child_(1),
       lost_context_provider_(false),
       buffer_to_texture_target_map_(
@@ -423,14 +316,9 @@
   while (!resources_.empty())
     DeleteResourceInternal(resources_.begin(), FOR_SHUTDOWN);
 
-  GLES2Interface* gl = ContextGL();
-  if (!IsGpuResourceType(settings_.default_resource_type)) {
-    // We are not in GL mode, but double check before returning.
-    DCHECK(!gl);
+  if (!compositor_context_provider_)
     return;
-  }
 
-  DCHECK(gl);
 #if DCHECK_IS_ON()
   // Check that all GL resources has been deleted.
   for (ResourceMap::const_iterator itr = resources_.begin();
@@ -440,6 +328,9 @@
 #endif  // DCHECK_IS_ON()
 
   texture_id_allocator_ = nullptr;
+
+  GLES2Interface* gl = ContextGL();
+  DCHECK(gl);
   gl->Finish();
 }
 
@@ -507,6 +398,31 @@
   return false;
 }
 
+bool ResourceProvider::IsGpuMemoryBufferFormatSupported(
+    viz::ResourceFormat format,
+    gfx::BufferUsage usage) const {
+  switch (format) {
+    case viz::BGRA_8888:
+    case viz::RED_8:
+    case viz::R16_EXT:
+    case viz::RGBA_4444:
+    case viz::RGBA_8888:
+    case viz::ETC1:
+    case viz::RGBA_F16:
+      return buffer_to_texture_target_map_.find(
+                 viz::BufferToTextureTargetKey(usage, BufferFormat(format))) !=
+             buffer_to_texture_target_map_.end();
+    // These formats have no BufferFormat equivalent.
+    case viz::ALPHA_8:
+    case viz::LUMINANCE_8:
+    case viz::RGB_565:
+    case viz::LUMINANCE_F16:
+      return false;
+  }
+  NOTREACHED();
+  return false;
+}
+
 bool ResourceProvider::InUseByConsumer(viz::ResourceId id) {
   Resource* resource = GetResource(id);
   return resource->lock_for_read_count > 0 || resource->exported_count > 0 ||
@@ -538,27 +454,12 @@
     viz::ResourceFormat format,
     const gfx::ColorSpace& color_space) {
   DCHECK(!size.IsEmpty());
-  switch (settings_.default_resource_type) {
-    case RESOURCE_TYPE_GPU_MEMORY_BUFFER:
-      // GPU memory buffers don't support viz::LUMINANCE_F16 yet.
-      if (format != viz::LUMINANCE_F16) {
-        return CreateGpuResource(
-            size, hint, RESOURCE_TYPE_GPU_MEMORY_BUFFER, format,
-            gfx::BufferUsage::GPU_READ_CPU_READ_WRITE, color_space);
-      }
-    // Fall through and use a regular texture.
-    case RESOURCE_TYPE_GL_TEXTURE:
-      return CreateGpuResource(size, hint, RESOURCE_TYPE_GL_TEXTURE, format,
-                               gfx::BufferUsage::GPU_READ_CPU_READ_WRITE,
-                               color_space);
 
-    case RESOURCE_TYPE_BITMAP:
-      DCHECK_EQ(viz::RGBA_8888, format);
-      return CreateBitmapResource(size, color_space);
-  }
+  if (compositor_context_provider_)
+    return CreateGpuTextureResource(size, hint, format, color_space);
 
-  LOG(FATAL) << "Invalid default resource type.";
-  return 0;
+  DCHECK_EQ(viz::RGBA_8888, format);
+  return CreateBitmapResource(size, color_space);
 }
 
 viz::ResourceId ResourceProvider::CreateGpuMemoryBufferResource(
@@ -568,46 +469,51 @@
     gfx::BufferUsage usage,
     const gfx::ColorSpace& color_space) {
   DCHECK(!size.IsEmpty());
-  switch (settings_.default_resource_type) {
-    case RESOURCE_TYPE_GPU_MEMORY_BUFFER:
-    case RESOURCE_TYPE_GL_TEXTURE: {
-      return CreateGpuResource(size, hint, RESOURCE_TYPE_GPU_MEMORY_BUFFER,
-                               format, usage, color_space);
-    }
-    case RESOURCE_TYPE_BITMAP:
-      DCHECK_EQ(viz::RGBA_8888, format);
-      return CreateBitmapResource(size, color_space);
-  }
-
-  LOG(FATAL) << "Invalid default resource type.";
-  return 0;
-}
-
-viz::ResourceId ResourceProvider::CreateGpuResource(
-    const gfx::Size& size,
-    TextureHint hint,
-    ResourceType type,
-    viz::ResourceFormat format,
-    gfx::BufferUsage usage,
-    const gfx::ColorSpace& color_space) {
+  DCHECK(compositor_context_provider_);
   DCHECK_LE(size.width(), settings_.max_texture_size);
   DCHECK_LE(size.height(), settings_.max_texture_size);
   DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
 
-  // TODO(crbug.com/590317): We should not assume that all resources created by
-  // ResourceProvider are GPU_READ_CPU_READ_WRITE. We should determine this
-  // based on the current RasterBufferProvider's needs.
-  GLenum target = type == RESOURCE_TYPE_GPU_MEMORY_BUFFER
-                      ? GetImageTextureTarget(usage, format)
-                      : GL_TEXTURE_2D;
+  viz::ResourceId id = next_id_++;
+  Resource* resource = InsertResource(
+      id, Resource(size, Resource::INTERNAL, hint,
+                   RESOURCE_TYPE_GPU_MEMORY_BUFFER, format, color_space));
+  resource->target = GetImageTextureTarget(usage, format);
+  resource->buffer_format = BufferFormat(format);
+  resource->usage = usage;
+  resource->is_overlay_candidate = true;
+  // GpuMemoryBuffer provides direct access to the memory used by the GPU. Read
+  // lock fences are required to ensure that we're not trying to map a buffer
+  // that is currently in-use by the GPU.
+  resource->read_lock_fences_enabled = true;
+  return id;
+}
+
+viz::ResourceId ResourceProvider::CreateGpuTextureResource(
+    const gfx::Size& size,
+    TextureHint hint,
+    viz::ResourceFormat format,
+    const gfx::ColorSpace& color_space) {
+  DCHECK_LE(size.width(), settings_.max_texture_size);
+  DCHECK_LE(size.height(), settings_.max_texture_size);
+  DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
+  DCHECK(IsTextureFormatSupported(format));
+
+  bool use_overlay = settings_.use_gpu_memory_buffer_resources ||
+                     (hint & TEXTURE_HINT_OVERLAY);
+  DCHECK(!use_overlay || !(hint & TEXTURE_HINT_MIPMAP));
 
   viz::ResourceId id = next_id_++;
-  Resource* resource =
-      InsertResource(id, Resource(0, size, Resource::INTERNAL, target,
-                                  GL_LINEAR, hint, type, format));
-  resource->usage = usage;
-  resource->allocated = false;
-  resource->color_space = color_space;
+  Resource* resource = InsertResource(
+      id, Resource(size, Resource::INTERNAL, hint, RESOURCE_TYPE_GL_TEXTURE,
+                   format, color_space));
+  if (use_overlay && settings_.use_texture_storage_image &&
+      IsGpuMemoryBufferFormatSupported(format, gfx::BufferUsage::SCANOUT)) {
+    resource->usage = gfx::BufferUsage::SCANOUT;
+    resource->target = GetImageTextureTarget(resource->usage, format);
+    resource->buffer_format = BufferFormat(format);
+    resource->is_overlay_candidate = true;
+  }
   return id;
 }
 
@@ -618,15 +524,15 @@
 
   std::unique_ptr<viz::SharedBitmap> bitmap =
       shared_bitmap_manager_->AllocateSharedBitmap(size);
-  uint8_t* pixels = bitmap->pixels();
-  DCHECK(pixels);
+  DCHECK(bitmap);
+  DCHECK(bitmap->pixels());
 
   viz::ResourceId id = next_id_++;
   Resource* resource = InsertResource(
-      id,
-      Resource(pixels, bitmap.release(), size, Resource::INTERNAL, GL_LINEAR));
-  resource->allocated = true;
-  resource->color_space = color_space;
+      id, Resource(size, Resource::INTERNAL, TEXTURE_HINT_DEFAULT,
+                   RESOURCE_TYPE_BITMAP, viz::RGBA_8888, color_space));
+  resource->SetSharedBitmap(bitmap.get());
+  resource->owned_shared_bitmap = std::move(bitmap);
   return id;
 }
 
@@ -674,18 +580,10 @@
   if (!lost_resource && resource->origin == Resource::INTERNAL)
     resource->WaitSyncToken(ContextGL());
 
-  if (resource->image_id) {
-    DCHECK(resource->origin == Resource::INTERNAL);
-    GLES2Interface* gl = ContextGL();
-    DCHECK(gl);
-    gl->DestroyImageCHROMIUM(resource->image_id);
-  }
-
   if (resource->origin == Resource::EXTERNAL) {
-    DCHECK(resource->mailbox().IsValid());
-    gpu::SyncToken sync_token = resource->mailbox().sync_token();
+    gpu::SyncToken sync_token = resource->sync_token();
     if (IsGpuResourceType(resource->type)) {
-      DCHECK(resource->mailbox().IsTexture());
+      DCHECK(!resource->mailbox.IsZero());
       GLES2Interface* gl = ContextGL();
       DCHECK(gl);
       if (resource->gl_id) {
@@ -699,35 +597,41 @@
         }
       }
     } else {
-      DCHECK(resource->mailbox().IsSharedMemory());
+      DCHECK(resource->shared_bitmap);
       resource->shared_bitmap = nullptr;
       resource->pixels = nullptr;
     }
     resource->release_callback.Run(sync_token, lost_resource);
   }
 
+  if (resource->image_id) {
+    DCHECK_EQ(resource->origin, Resource::INTERNAL);
+    GLES2Interface* gl = ContextGL();
+    DCHECK(gl);
+    gl->DestroyImageCHROMIUM(resource->image_id);
+  }
+
   if (resource->gl_id) {
     GLES2Interface* gl = ContextGL();
     DCHECK(gl);
     gl->DeleteTextures(1, &resource->gl_id);
     resource->gl_id = 0;
   }
-  if (resource->shared_bitmap) {
-    DCHECK(resource->origin != Resource::EXTERNAL);
+
+  if (resource->owned_shared_bitmap) {
+    DCHECK_NE(resource->origin, Resource::EXTERNAL);
     DCHECK_EQ(RESOURCE_TYPE_BITMAP, resource->type);
-    delete resource->shared_bitmap;
+    resource->shared_bitmap = nullptr;
     resource->pixels = nullptr;
+    resource->owned_shared_bitmap = nullptr;
   }
-  if (resource->pixels) {
-    DCHECK(resource->origin == Resource::INTERNAL);
-    delete[] resource->pixels;
-    resource->pixels = nullptr;
-  }
+
   if (resource->gpu_memory_buffer) {
-    DCHECK(resource->origin == Resource::INTERNAL ||
-           resource->origin == Resource::DELEGATED);
-    resource->gpu_memory_buffer.reset();
+    DCHECK_NE(resource->origin, Resource::EXTERNAL);
+    DCHECK_EQ(RESOURCE_TYPE_GPU_MEMORY_BUFFER, resource->type);
+    resource->gpu_memory_buffer = nullptr;
   }
+
   resources_.erase(it);
 }
 
@@ -796,12 +700,14 @@
       gl->CompressedTexImage2D(resource->target, 0, GLInternalFormat(viz::ETC1),
                                image_size.width(), image_size.height(), 0,
                                image_bytes, image);
+      lock.set_allocated();
     } else {
       gl->TexSubImage2D(resource->target, 0, 0, 0, image_size.width(),
                         image_size.height(), GLDataFormat(resource->format),
                         GLDataType(resource->format), image);
     }
   }
+  DCHECK(resource->allocated);
 }
 
 ResourceProvider::Resource* ResourceProvider::InsertResource(
@@ -881,41 +787,24 @@
     viz::ResourceId resource_id)
     : resource_provider_(resource_provider), resource_id_(resource_id) {
   Resource* resource = resource_provider->LockForWrite(resource_id);
-  DCHECK(IsGpuResourceType(resource->type));
+  DCHECK_EQ(resource->type, ResourceProvider::RESOURCE_TYPE_GL_TEXTURE);
   resource_provider->CreateTexture(resource);
-  type_ = resource->type;
   size_ = resource->size;
   format_ = resource->format;
-  usage_ = resource->usage;
   color_space_ = resource_provider_->GetResourceColorSpaceForRaster(resource);
   texture_id_ = resource->gl_id;
   target_ = resource->target;
   hint_ = resource->hint;
-  gpu_memory_buffer_ = std::move(resource->gpu_memory_buffer);
-  image_id_ = resource->image_id;
-  mailbox_ = resource->mailbox().mailbox();
+  mailbox_ = resource->mailbox;
+  is_overlay_ = resource->is_overlay_candidate;
   allocated_ = resource->allocated;
 }
 
-GrPixelConfig ResourceProvider::ScopedWriteLockGL::PixelConfig() const {
-  return ToGrPixelConfig(format());
-}
-
 ResourceProvider::ScopedWriteLockGL::~ScopedWriteLockGL() {
   Resource* resource = resource_provider_->GetResource(resource_id_);
   DCHECK(resource->locked_for_write);
   resource->allocated = allocated_;
-  if (gpu_memory_buffer_) {
-    resource->gpu_memory_buffer = std::move(gpu_memory_buffer_);
-    resource->allocated = true;
-    resource->is_overlay_candidate = true;
-    resource->buffer_format = resource->gpu_memory_buffer->GetFormat();
-    // GpuMemoryBuffer provides direct access to the memory used by the GPU.
-    // Read lock fences are required to ensure that we're not trying to map a
-    // buffer that is currently in-use by the GPU.
-    resource->read_lock_fences_enabled = true;
-    resource->image_id = image_id_;
-  }
+  resource->mailbox = mailbox_;
   // Don't set empty sync token otherwise resource will be marked synchronized.
   if (has_sync_token_)
     resource->UpdateSyncToken(sync_token_);
@@ -926,6 +815,10 @@
   resource_provider_->UnlockForWrite(resource);
 }
 
+GrPixelConfig ResourceProvider::ScopedWriteLockGL::PixelConfig() const {
+  return ToGrPixelConfig(format_);
+}
+
 GLuint ResourceProvider::ScopedWriteLockGL::GetTexture() {
   LazyAllocate(resource_provider_->ContextGL(), texture_id_);
   return texture_id_;
@@ -934,9 +827,10 @@
 void ResourceProvider::ScopedWriteLockGL::CreateMailbox() {
   if (!mailbox_.IsZero())
     return;
-  Resource* resource = resource_provider_->GetResource(resource_id_);
-  resource_provider_->CreateMailbox(resource);
-  mailbox_ = resource->mailbox().mailbox();
+  gpu::gles2::GLES2Interface* gl = resource_provider_->ContextGL();
+  DCHECK(gl);
+  gl->GenMailboxCHROMIUM(mailbox_.name);
+  gl->ProduceTextureDirectCHROMIUM(texture_id_, target_, mailbox_.name);
 }
 
 GLuint ResourceProvider::ScopedWriteLockGL::ConsumeTexture(
@@ -956,66 +850,35 @@
 void ResourceProvider::ScopedWriteLockGL::LazyAllocate(
     gpu::gles2::GLES2Interface* gl,
     GLuint texture_id) {
+  // ETC1 resources cannot be preallocated.
+  if (format_ == viz::ETC1)
+    return;
+
   if (allocated_)
     return;
   allocated_ = true;
-  if (type_ == RESOURCE_TYPE_GPU_MEMORY_BUFFER) {
-    AllocateGpuMemoryBuffer(gl, texture_id);
-  } else {
-    AllocateTexture(gl, texture_id);
-  }
-}
 
-void ResourceProvider::ScopedWriteLockGL::AllocateGpuMemoryBuffer(
-    gpu::gles2::GLES2Interface* gl,
-    GLuint texture_id) {
-  DCHECK(!gpu_memory_buffer_);
-  DCHECK(!image_id_);
-
-  gpu_memory_buffer_ =
-      resource_provider_->gpu_memory_buffer_manager()->CreateGpuMemoryBuffer(
-          size_, BufferFormat(format_), usage_, gpu::kNullSurfaceHandle);
-  // Avoid crashing in release builds if GpuMemoryBuffer allocation fails.
-  // http://crbug.com/554541
-  if (!gpu_memory_buffer_)
-    return;
-
-  if (color_space_.IsValid())
-    gpu_memory_buffer_->SetColorSpaceForScanout(color_space_);
-
-#if defined(OS_CHROMEOS) && defined(ARCH_CPU_ARM_FAMILY)
-  // TODO(reveman): This avoids a performance problem on ARM ChromeOS
-  // devices. This only works with shared memory backed buffers.
-  // crbug.com/580166
-  DCHECK_EQ(gpu_memory_buffer_->GetHandle().type, gfx::SHARED_MEMORY_BUFFER);
-#endif
-
-  image_id_ = gl->CreateImageCHROMIUM(gpu_memory_buffer_->AsClientBuffer(),
-                                      size_.width(), size_.height(),
-                                      GLInternalFormat(format_));
-  DCHECK(image_id_ || gl->GetGraphicsResetStatusKHR() != GL_NO_ERROR);
-  gl->BindTexture(target_, texture_id);
-  gl->BindTexImage2DCHROMIUM(target_, image_id_);
-}
-
-void ResourceProvider::ScopedWriteLockGL::AllocateTexture(
-    gpu::gles2::GLES2Interface* gl,
-    GLuint texture_id) {
-  DCHECK(gl);
-  if (format_ == viz::ETC1)  // ETC1 does not support preallocation.
-    return;
-  gl->BindTexture(target_, texture_id);
   const ResourceProvider::Settings& settings = resource_provider_->settings_;
-  if (settings.use_texture_storage_ext &&
-      IsFormatSupportedForStorage(format_, settings.use_texture_format_bgra)) {
-    GLenum storage_format = TextureToStorageFormat(format_);
+
+  gl->BindTexture(target_, texture_id);
+
+  if (is_overlay_) {
+    DCHECK(settings.use_texture_storage_image);
+    gl->TexStorage2DImageCHROMIUM(target_, TextureStorageFormat(format_),
+                                  GL_SCANOUT_CHROMIUM, size_.width(),
+                                  size_.height());
+    if (color_space_.IsValid()) {
+      gl->SetColorSpaceMetadataCHROMIUM(
+          texture_id, reinterpret_cast<GLColorSpace>(&color_space_));
+    }
+  } else if (settings.use_texture_storage) {
     GLint levels = 1;
     if (settings.use_texture_npot &&
         (hint_ & ResourceProvider::TEXTURE_HINT_MIPMAP)) {
       levels += base::bits::Log2Floor(std::max(size_.width(), size_.height()));
     }
-    gl->TexStorage2DEXT(target_, levels, storage_format, size_.width(),
-                        size_.height());
+    gl->TexStorage2DEXT(target_, levels, TextureStorageFormat(format_),
+                        size_.width(), size_.height());
   } else {
     gl->TexImage2D(target_, 0, GLInternalFormat(format_), size_.width(),
                    size_.height(), 0, GLDataFormat(format_),
@@ -1159,7 +1022,7 @@
     return;
 
   DCHECK_EQ(resource->origin, Resource::INTERNAL);
-  DCHECK(!resource->mailbox().IsValid());
+  DCHECK(resource->mailbox.IsZero());
 
   resource->gl_id = texture_id_allocator_->NextId();
   DCHECK(resource->gl_id);
@@ -1186,7 +1049,7 @@
   if (!IsGpuResourceType(resource->type))
     return;
 
-  if (resource->mailbox().IsValid())
+  if (!resource->mailbox.IsZero())
     return;
 
   CreateTexture(resource);
@@ -1196,14 +1059,9 @@
 
   gpu::gles2::GLES2Interface* gl = ContextGL();
   DCHECK(gl);
-
-  gpu::MailboxHolder mailbox_holder;
-  mailbox_holder.texture_target = resource->target;
-  gl->GenMailboxCHROMIUM(mailbox_holder.mailbox.name);
-  gl->ProduceTextureDirectCHROMIUM(resource->gl_id,
-                                   mailbox_holder.texture_target,
-                                   mailbox_holder.mailbox.name);
-  resource->SetMailbox(viz::TextureMailbox(mailbox_holder));
+  gl->GenMailboxCHROMIUM(resource->mailbox.name);
+  gl->ProduceTextureDirectCHROMIUM(resource->gl_id, resource->target,
+                                   resource->mailbox.name);
   resource->SetLocallyUsed();
 }
 
@@ -1232,16 +1090,18 @@
   gpu::gles2::GLES2Interface* gl = ContextGL();
   DCHECK(gl);
 
+  gl->BindTexture(resource->target, resource->gl_id);
+
   if (!resource->image_id) {
     resource->image_id = gl->CreateImageCHROMIUM(
         resource->gpu_memory_buffer->AsClientBuffer(), resource->size.width(),
         resource->size.height(), GLInternalFormat(resource->format));
+
     DCHECK(resource->image_id ||
            gl->GetGraphicsResetStatusKHR() != GL_NO_ERROR);
-    gl->BindTexture(resource->target, resource->gl_id);
+
     gl->BindTexImage2DCHROMIUM(resource->target, resource->image_id);
   } else {
-    gl->BindTexture(resource->target, resource->gl_id);
     gl->ReleaseTexImage2DCHROMIUM(resource->target, resource->image_id);
     gl->BindTexImage2DCHROMIUM(resource->target, resource->image_id);
   }
@@ -1275,8 +1135,9 @@
   return sync_token;
 }
 
-GLenum ResourceProvider::GetImageTextureTarget(gfx::BufferUsage usage,
-                                               viz::ResourceFormat format) {
+GLenum ResourceProvider::GetImageTextureTarget(
+    gfx::BufferUsage usage,
+    viz::ResourceFormat format) const {
   gfx::BufferFormat buffer_format = BufferFormat(format);
   auto found = buffer_to_texture_target_map_.find(
       viz::BufferToTextureTargetKey(usage, buffer_format));
diff --git a/cc/resources/resource_provider.h b/cc/resources/resource_provider.h
index e92911e..70df61b 100644
--- a/cc/resources/resource_provider.h
+++ b/cc/resources/resource_provider.h
@@ -81,11 +81,12 @@
   using ResourceIdArray = std::vector<viz::ResourceId>;
   using ResourceIdMap = std::unordered_map<viz::ResourceId, viz::ResourceId>;
   enum TextureHint {
-    TEXTURE_HINT_DEFAULT = 0x0,
-    TEXTURE_HINT_MIPMAP = 0x1,
-    TEXTURE_HINT_FRAMEBUFFER = 0x2,
+    TEXTURE_HINT_DEFAULT = 0,
+    TEXTURE_HINT_MIPMAP = 1 << 0,
+    TEXTURE_HINT_FRAMEBUFFER = 1 << 2,
     TEXTURE_HINT_MIPMAP_FRAMEBUFFER =
-        TEXTURE_HINT_MIPMAP | TEXTURE_HINT_FRAMEBUFFER
+        TEXTURE_HINT_MIPMAP | TEXTURE_HINT_FRAMEBUFFER,
+    TEXTURE_HINT_OVERLAY = 1 << 3,
   };
   enum ResourceType {
     RESOURCE_TYPE_GPU_MEMORY_BUFFER,
@@ -97,7 +98,8 @@
                    viz::SharedBitmapManager* shared_bitmap_manager,
                    gpu::GpuMemoryBufferManager* gpu_memory_buffer_manager,
                    bool delegated_sync_points_required,
-                   const viz::ResourceSettings& resource_settings);
+                   const viz::ResourceSettings& resource_settings,
+                   viz::ResourceId next_id);
   ~ResourceProvider() override;
 
   static bool IsGpuResourceType(ResourceProvider::ResourceType type) {
@@ -106,6 +108,8 @@
 
   void Initialize();
 
+  bool IsSoftware() const { return !compositor_context_provider_; }
+
   void DidLoseVulkanContextProvider() { lost_context_provider_ = true; }
 
   int max_texture_size() const { return settings_.max_texture_size; }
@@ -128,6 +132,9 @@
   // Note that render buffer support implies texture support.
   bool IsRenderBufferFormatSupported(viz::ResourceFormat format) const;
 
+  bool IsGpuMemoryBufferFormatSupported(viz::ResourceFormat format,
+                                        gfx::BufferUsage usage) const;
+
   // Checks whether a resource is in use by a consumer.
   bool InUseByConsumer(viz::ResourceId id);
 
@@ -137,10 +144,6 @@
   void EnableReadLockFencesForTesting(viz::ResourceId id);
 
   // Producer interface.
-
-  ResourceType default_resource_type() const {
-    return settings_.default_resource_type;
-  }
   ResourceType GetResourceType(viz::ResourceId id);
   GLenum GetResourceTextureTarget(viz::ResourceId id);
   TextureHint GetTextureHint(viz::ResourceId id);
@@ -190,13 +193,15 @@
       return color_space_;
     }
 
+    GrPixelConfig PixelConfig() const;
+
+    void set_allocated() { allocated_ = true; }
+
     void set_sync_token(const gpu::SyncToken& sync_token) {
       sync_token_ = sync_token;
       has_sync_token_ = true;
     }
 
-    GrPixelConfig PixelConfig() const;
-
     void set_synchronized() { synchronized_ = true; }
 
     void set_generate_mipmap() { generate_mipmap_ = true; }
@@ -214,26 +219,18 @@
    private:
     void LazyAllocate(gpu::gles2::GLES2Interface* gl, GLuint texture_id);
 
-    void AllocateGpuMemoryBuffer(gpu::gles2::GLES2Interface* gl,
-                                 GLuint texture_id);
-
-    void AllocateTexture(gpu::gles2::GLES2Interface* gl, GLuint texture_id);
-
     ResourceProvider* const resource_provider_;
     const viz::ResourceId resource_id_;
 
     // The following are copied from the resource.
-    ResourceProvider::ResourceType type_;
     gfx::Size size_;
     viz::ResourceFormat format_;
-    gfx::BufferUsage usage_;
     gfx::ColorSpace color_space_;
     GLuint texture_id_;
     GLenum target_;
     ResourceProvider::TextureHint hint_;
-    std::unique_ptr<gfx::GpuMemoryBuffer> gpu_memory_buffer_;
-    GLuint image_id_;
     gpu::Mailbox mailbox_;
+    bool is_overlay_;
     bool allocated_;
 
     // Set by the user.
@@ -363,7 +360,7 @@
   void ValidateResource(viz::ResourceId id) const;
 
   GLenum GetImageTextureTarget(gfx::BufferUsage usage,
-                               viz::ResourceFormat format);
+                               viz::ResourceFormat format) const;
 
   // base::trace_event::MemoryDumpProvider implementation.
   bool OnMemoryDump(const base::trace_event::MemoryDumpArgs& args,
@@ -405,23 +402,12 @@
     };
     enum MipmapState { INVALID, GENERATE, VALID };
 
-    Resource(GLuint texture_id,
-             const gfx::Size& size,
+    Resource(const gfx::Size& size,
              Origin origin,
-             GLenum target,
-             GLenum filter,
              TextureHint hint,
              ResourceType type,
-             viz::ResourceFormat format);
-    Resource(uint8_t* pixels,
-             viz::SharedBitmap* bitmap,
-             const gfx::Size& size,
-             Origin origin,
-             GLenum filter);
-    Resource(const viz::SharedBitmapId& bitmap_id,
-             const gfx::Size& size,
-             Origin origin,
-             GLenum filter);
+             viz::ResourceFormat format,
+             const gfx::ColorSpace& color_space);
     Resource(Resource&& other);
     ~Resource();
 
@@ -430,28 +416,22 @@
              synchronization_state_ == LOCALLY_USED;
     }
 
+    const gpu::SyncToken& sync_token() const { return sync_token_; }
+
     SynchronizationState synchronization_state() const {
       return synchronization_state_;
     }
 
-    const viz::TextureMailbox& mailbox() const { return mailbox_; }
-    void SetMailbox(const viz::TextureMailbox& mailbox);
+    void SetSharedBitmap(viz::SharedBitmap* bitmap);
 
     void SetLocallyUsed();
     void SetSynchronized();
     void UpdateSyncToken(const gpu::SyncToken& sync_token);
+    void WaitSyncToken(gpu::gles2::GLES2Interface* gl);
     int8_t* GetSyncTokenData();
-    void WaitSyncToken(gpu::gles2::GLES2Interface* sync_token);
     void SetGenerateMipmap();
 
-    int child_id;
-    viz::ResourceId id_in_child;
-    GLuint gl_id;
-    viz::ReleaseCallback release_callback;
-    uint8_t* pixels;
-    int lock_for_read_count;
-    int imported_count;
-    int exported_count;
+    // Bitfield flags
     bool locked_for_write : 1;
     bool lost : 1;
     bool marked_for_deletion : 1;
@@ -473,44 +453,57 @@
     // Indicates that this resource would like a promotion hint.
     bool wants_promotion_hint : 1;
 #endif
+
+    int child_id = 0;
+    viz::ResourceId id_in_child = 0;
+    GLuint gl_id = 0;
+    gpu::Mailbox mailbox;
+    viz::ReleaseCallback release_callback;
+    uint8_t* pixels = nullptr;
+    int lock_for_read_count = 0;
+    int imported_count = 0;
+    int exported_count = 0;
     scoped_refptr<Fence> read_lock_fence;
     gfx::Size size;
-    Origin origin;
-    GLenum target;
+    Origin origin = INTERNAL;
+    GLenum target = GL_TEXTURE_2D;
     // TODO(skyostil): Use a separate sampler object for filter state.
-    GLenum original_filter;
-    GLenum filter;
-    GLenum min_filter;
-    GLuint image_id;
-    TextureHint hint;
-    ResourceType type;
+    GLenum original_filter = GL_LINEAR;
+    GLenum filter = GL_LINEAR;
+    GLenum min_filter = GL_LINEAR;
+    GLuint image_id = 0;
+    TextureHint hint = TEXTURE_HINT_DEFAULT;
+    ResourceType type = RESOURCE_TYPE_BITMAP;
     // GpuMemoryBuffer resource allocation needs to know how the resource will
     // be used.
-    gfx::BufferUsage usage;
+    gfx::BufferUsage usage = gfx::BufferUsage::GPU_READ_CPU_READ_WRITE;
     // This is the the actual format of the underlaying GpuMemoryBuffer, if any,
     // and might not correspond to viz::ResourceFormat. This format is needed to
     // scanout the buffer as HW overlay.
-    gfx::BufferFormat buffer_format;
+    gfx::BufferFormat buffer_format = gfx::BufferFormat::RGBA_8888;
     // Resource format is the format as seen from the compositor and might not
     // correspond to buffer_format (e.g: A resouce that was created from a YUV
     // buffer could be seen as RGB from the compositor/GL.)
-    viz::ResourceFormat format;
+    viz::ResourceFormat format = viz::ResourceFormat::RGBA_8888;
     viz::SharedBitmapId shared_bitmap_id;
-    viz::SharedBitmap* shared_bitmap;
+    viz::SharedBitmap* shared_bitmap = nullptr;
+    std::unique_ptr<viz::SharedBitmap> owned_shared_bitmap;
     std::unique_ptr<gfx::GpuMemoryBuffer> gpu_memory_buffer;
     gfx::ColorSpace color_space;
     MipmapState mipmap_state = INVALID;
 
    private:
     SynchronizationState synchronization_state_ = SYNCHRONIZED;
-    viz::TextureMailbox mailbox_;
+    gpu::SyncToken sync_token_;
 
     DISALLOW_COPY_AND_ASSIGN(Resource);
   };
   using ResourceMap = std::unordered_map<viz::ResourceId, Resource>;
 
   Resource* InsertResource(viz::ResourceId id, Resource resource);
+
   Resource* GetResource(viz::ResourceId id);
+
   Resource* LockForWrite(viz::ResourceId id);
   void UnlockForWrite(Resource* resource);
 
@@ -533,6 +526,7 @@
     NORMAL,
     FOR_SHUTDOWN,
   };
+
   void DeleteResourceInternal(ResourceMap::iterator it, DeleteStyle style);
 
   void CreateMailbox(Resource* resource);
@@ -552,16 +546,18 @@
              const viz::ResourceSettings& resource_settings);
 
     int max_texture_size = 0;
-    bool use_texture_storage_ext = false;
+    bool use_texture_storage = false;
     bool use_texture_format_bgra = false;
     bool use_texture_usage_hint = false;
     bool use_texture_npot = false;
     bool use_sync_query = false;
+    bool use_texture_storage_image = false;
     ResourceType default_resource_type = RESOURCE_TYPE_GL_TEXTURE;
     viz::ResourceFormat yuv_resource_format = viz::LUMINANCE_8;
     viz::ResourceFormat yuv_highbit_resource_format = viz::LUMINANCE_8;
     viz::ResourceFormat best_texture_format = viz::RGBA_8888;
     viz::ResourceFormat best_render_buffer_format = viz::RGBA_8888;
+    bool use_gpu_memory_buffer_resources = false;
     bool delegated_sync_points_required = false;
   } const settings_;
 
@@ -589,12 +585,11 @@
 #endif
 
  private:
-  viz::ResourceId CreateGpuResource(const gfx::Size& size,
-                                    TextureHint hint,
-                                    ResourceType type,
-                                    viz::ResourceFormat format,
-                                    gfx::BufferUsage usage,
-                                    const gfx::ColorSpace& color_space);
+  viz::ResourceId CreateGpuTextureResource(const gfx::Size& size,
+                                           TextureHint hint,
+                                           viz::ResourceFormat format,
+                                           const gfx::ColorSpace& color_space);
+
   viz::ResourceId CreateBitmapResource(const gfx::Size& size,
                                        const gfx::ColorSpace& color_space);
 
diff --git a/cc/resources/resource_provider_unittest.cc b/cc/resources/resource_provider_unittest.cc
index 41bec52..54728ba 100644
--- a/cc/resources/resource_provider_unittest.cc
+++ b/cc/resources/resource_provider_unittest.cc
@@ -42,6 +42,7 @@
 using testing::Return;
 using testing::StrictMock;
 using testing::_;
+using testing::AnyNumber;
 
 namespace cc {
 namespace {
@@ -400,22 +401,16 @@
                        viz::ResourceFormat format,
                        uint8_t* pixels) {
   resource_provider->WaitSyncToken(id);
-  switch (resource_provider->default_resource_type()) {
-    case ResourceProvider::RESOURCE_TYPE_GPU_MEMORY_BUFFER:
-    case ResourceProvider::RESOURCE_TYPE_GL_TEXTURE: {
-      DisplayResourceProvider::ScopedReadLockGL lock_gl(resource_provider, id);
-      ASSERT_NE(0U, lock_gl.texture_id());
-      context->bindTexture(GL_TEXTURE_2D, lock_gl.texture_id());
-      context->GetPixels(size, format, pixels);
-      break;
-    }
-    case ResourceProvider::RESOURCE_TYPE_BITMAP: {
-      DisplayResourceProvider::ScopedReadLockSoftware lock_software(
-          resource_provider, id);
-      memcpy(pixels, lock_software.sk_bitmap()->getPixels(),
-             lock_software.sk_bitmap()->computeByteSize());
-      break;
-    }
+  if (resource_provider->IsSoftware()) {
+    DisplayResourceProvider::ScopedReadLockSoftware lock_software(
+        resource_provider, id);
+    memcpy(pixels, lock_software.sk_bitmap()->getPixels(),
+           lock_software.sk_bitmap()->computeByteSize());
+  } else {
+    DisplayResourceProvider::ScopedReadLockGL lock_gl(resource_provider, id);
+    ASSERT_NE(0U, lock_gl.texture_id());
+    context->bindTexture(GL_TEXTURE_2D, lock_gl.texture_id());
+    context->GetPixels(size, format, pixels);
   }
 }
 
@@ -423,9 +418,7 @@
     : public testing::TestWithParam<ResourceProvider::ResourceType> {
  public:
   explicit ResourceProviderTest(bool child_needs_sync_token)
-      : shared_data_(ContextSharedData::Create()),
-        context3d_(nullptr),
-        child_context_(nullptr) {
+      : shared_data_(ContextSharedData::Create()) {
     switch (GetParam()) {
       case ResourceProvider::RESOURCE_TYPE_GPU_MEMORY_BUFFER:
       case ResourceProvider::RESOURCE_TYPE_GL_TEXTURE: {
@@ -523,8 +516,8 @@
 
  protected:
   std::unique_ptr<ContextSharedData> shared_data_;
-  ResourceProviderContext* context3d_;
-  ResourceProviderContext* child_context_;
+  ResourceProviderContext* context3d_ = nullptr;
+  ResourceProviderContext* child_context_ = nullptr;
   scoped_refptr<TestContextProvider> context_provider_;
   scoped_refptr<TestContextProvider> child_context_provider_;
   std::unique_ptr<viz::TestGpuMemoryBufferManager> gpu_memory_buffer_manager_;
@@ -538,7 +531,8 @@
 void CheckCreateResource(ResourceProvider::ResourceType expected_default_type,
                          DisplayResourceProvider* resource_provider,
                          ResourceProviderContext* context) {
-  DCHECK_EQ(expected_default_type, resource_provider->default_resource_type());
+  DCHECK_EQ(resource_provider->IsSoftware(),
+            expected_default_type == ResourceProvider::RESOURCE_TYPE_BITMAP);
 
   gfx::Size size(1, 1);
   viz::ResourceFormat format = viz::RGBA_8888;
@@ -551,12 +545,12 @@
   if (expected_default_type == ResourceProvider::RESOURCE_TYPE_GL_TEXTURE)
     EXPECT_EQ(0u, context->NumTextures());
 
-  uint8_t data[4] = { 1, 2, 3, 4 };
+  uint8_t data[4] = {1, 2, 3, 4};
   resource_provider->CopyToResource(id, data, size);
   if (expected_default_type == ResourceProvider::RESOURCE_TYPE_GL_TEXTURE)
     EXPECT_EQ(1u, context->NumTextures());
 
-  uint8_t result[4] = { 0 };
+  uint8_t result[4] = {0};
   GetResourcePixels(resource_provider, context, id, size, format, result);
   EXPECT_EQ(0, memcmp(data, result, pixel_size));
 
@@ -654,60 +648,61 @@
   int child_id =
       resource_provider_->CreateChild(GetReturnCallback(&returned_to_child));
 
-  {
-    // Transfer some resources to the parent.
-    ResourceProvider::ResourceIdArray resource_ids_to_transfer;
-    resource_ids_to_transfer.push_back(id1);
-    resource_ids_to_transfer.push_back(id2);
-    resource_ids_to_transfer.push_back(id3);
-    resource_ids_to_transfer.push_back(id4);
+  // Transfer some resources to the parent.
+  ResourceProvider::ResourceIdArray resource_ids_to_transfer;
+  resource_ids_to_transfer.push_back(id1);
+  resource_ids_to_transfer.push_back(id2);
+  resource_ids_to_transfer.push_back(id3);
+  resource_ids_to_transfer.push_back(id4);
 
-    std::vector<viz::TransferableResource> list;
-    child_resource_provider_->PrepareSendToParent(resource_ids_to_transfer,
-                                                  &list);
-    ASSERT_EQ(4u, list.size());
-    EXPECT_TRUE(list[0].mailbox_holder.sync_token.HasData());
-    EXPECT_TRUE(list[1].mailbox_holder.sync_token.HasData());
-    EXPECT_EQ(list[0].mailbox_holder.sync_token,
-              list[1].mailbox_holder.sync_token);
-    EXPECT_TRUE(list[2].mailbox_holder.sync_token.HasData());
-    EXPECT_EQ(list[0].mailbox_holder.sync_token,
-              list[2].mailbox_holder.sync_token);
-    EXPECT_EQ(external_sync_token, list[3].mailbox_holder.sync_token);
-    EXPECT_EQ(static_cast<GLenum>(GL_TEXTURE_2D),
-              list[0].mailbox_holder.texture_target);
-    EXPECT_EQ(static_cast<GLenum>(GL_TEXTURE_2D),
-              list[1].mailbox_holder.texture_target);
-    EXPECT_EQ(static_cast<GLenum>(GL_TEXTURE_2D),
-              list[2].mailbox_holder.texture_target);
-    EXPECT_EQ(static_cast<GLenum>(GL_TEXTURE_EXTERNAL_OES),
-              list[3].mailbox_holder.texture_target);
-    EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id1));
-    EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id2));
-    EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id3));
-    EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id4));
-    resource_provider_->ReceiveFromChild(child_id, list);
-    EXPECT_NE(list[0].mailbox_holder.sync_token,
-              context3d_->last_waited_sync_token());
-    {
-      resource_provider_->WaitSyncToken(list[0].id);
-      DisplayResourceProvider::ScopedReadLockGL lock(resource_provider_.get(),
-                                                     list[0].id);
-    }
-    EXPECT_EQ(list[0].mailbox_holder.sync_token,
-              context3d_->last_waited_sync_token());
-    viz::ResourceIdSet resource_ids_to_receive;
-    resource_ids_to_receive.insert(id1);
-    resource_ids_to_receive.insert(id2);
-    resource_ids_to_receive.insert(id3);
-    resource_ids_to_receive.insert(id4);
-    resource_provider_->DeclareUsedResourcesFromChild(child_id,
-                                                      resource_ids_to_receive);
-  }
+  std::vector<viz::TransferableResource> list;
+  child_resource_provider_->PrepareSendToParent(resource_ids_to_transfer,
+                                                &list);
+  ASSERT_EQ(4u, list.size());
+  EXPECT_TRUE(list[0].mailbox_holder.sync_token.HasData());
+  EXPECT_TRUE(list[1].mailbox_holder.sync_token.HasData());
+  EXPECT_EQ(list[0].mailbox_holder.sync_token,
+            list[1].mailbox_holder.sync_token);
+  EXPECT_TRUE(list[2].mailbox_holder.sync_token.HasData());
+  EXPECT_EQ(list[0].mailbox_holder.sync_token,
+            list[2].mailbox_holder.sync_token);
+  EXPECT_EQ(external_sync_token, list[3].mailbox_holder.sync_token);
+  EXPECT_EQ(static_cast<GLenum>(GL_TEXTURE_2D),
+            list[0].mailbox_holder.texture_target);
+  EXPECT_EQ(static_cast<GLenum>(GL_TEXTURE_2D),
+            list[1].mailbox_holder.texture_target);
+  EXPECT_EQ(static_cast<GLenum>(GL_TEXTURE_2D),
+            list[2].mailbox_holder.texture_target);
+  EXPECT_EQ(static_cast<GLenum>(GL_TEXTURE_EXTERNAL_OES),
+            list[3].mailbox_holder.texture_target);
+  EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id1));
+  EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id2));
+  EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id3));
+  EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id4));
+  resource_provider_->ReceiveFromChild(child_id, list);
+  EXPECT_NE(list[0].mailbox_holder.sync_token,
+            context3d_->last_waited_sync_token());
 
-  EXPECT_EQ(4u, resource_provider_->num_resources());
+  // In DisplayResourceProvider's namespace, use the mapped resource id.
   ResourceProvider::ResourceIdMap resource_map =
       resource_provider_->GetChildToParentMap(child_id);
+  {
+    viz::ResourceId mapped_resource_id = resource_map[list[0].id];
+    resource_provider_->WaitSyncToken(mapped_resource_id);
+    DisplayResourceProvider::ScopedReadLockGL lock(resource_provider_.get(),
+                                                   mapped_resource_id);
+  }
+  EXPECT_EQ(list[0].mailbox_holder.sync_token,
+            context3d_->last_waited_sync_token());
+  viz::ResourceIdSet resource_ids_to_receive;
+  resource_ids_to_receive.insert(id1);
+  resource_ids_to_receive.insert(id2);
+  resource_ids_to_receive.insert(id3);
+  resource_ids_to_receive.insert(id4);
+  resource_provider_->DeclareUsedResourcesFromChild(child_id,
+                                                    resource_ids_to_receive);
+
+  EXPECT_EQ(4u, resource_provider_->num_resources());
   viz::ResourceId mapped_id1 = resource_map[id1];
   viz::ResourceId mapped_id2 = resource_map[id2];
   viz::ResourceId mapped_id3 = resource_map[id3];
@@ -716,10 +711,10 @@
   EXPECT_NE(0u, mapped_id2);
   EXPECT_NE(0u, mapped_id3);
   EXPECT_NE(0u, mapped_id4);
-  EXPECT_FALSE(resource_provider_->InUseByConsumer(id1));
-  EXPECT_FALSE(resource_provider_->InUseByConsumer(id2));
-  EXPECT_FALSE(resource_provider_->InUseByConsumer(id3));
-  EXPECT_FALSE(resource_provider_->InUseByConsumer(id4));
+  EXPECT_FALSE(resource_provider_->InUseByConsumer(mapped_id1));
+  EXPECT_FALSE(resource_provider_->InUseByConsumer(mapped_id2));
+  EXPECT_FALSE(resource_provider_->InUseByConsumer(mapped_id3));
+  EXPECT_FALSE(resource_provider_->InUseByConsumer(mapped_id4));
 
   uint8_t result[4] = { 0 };
   GetResourcePixels(
@@ -810,9 +805,9 @@
   // Ensure copying to resource doesn't fail.
   child_resource_provider_->CopyToResource(id2, data2, size);
   {
-    child_resource_provider_->WaitSyncToken(id3);
+    child_resource_provider_->WaitSyncToken(id2);
     ResourceProvider::ScopedWriteLockGL lock(child_resource_provider_.get(),
-                                             id3);
+                                             id2);
     ASSERT_NE(0U, lock.GetTexture());
   }
   {
@@ -913,37 +908,36 @@
   int child_id =
       resource_provider_->CreateChild(GetReturnCallback(&returned_to_child));
 
-  {
-    // Transfer some resources to the parent.
-    ResourceProvider::ResourceIdArray resource_ids_to_transfer;
-    resource_ids_to_transfer.push_back(id1);
-    resource_ids_to_transfer.push_back(id2);
+  // Transfer some resources to the parent.
+  ResourceProvider::ResourceIdArray resource_ids_to_transfer;
+  resource_ids_to_transfer.push_back(id1);
+  resource_ids_to_transfer.push_back(id2);
 
-    std::vector<viz::TransferableResource> list;
-    child_resource_provider_->PrepareSendToParent(resource_ids_to_transfer,
-                                                  &list);
-    ASSERT_EQ(2u, list.size());
-    resource_provider_->ReceiveFromChild(child_id, list);
-    {
-      resource_provider_->WaitSyncToken(list[0].id);
-      DisplayResourceProvider::ScopedReadLockGL lock(resource_provider_.get(),
-                                                     list[0].id);
-    }
-
-    EXPECT_EQ(list[0].mailbox_holder.sync_token,
-              context3d_->last_waited_sync_token());
-    viz::ResourceIdSet resource_ids_to_receive;
-    resource_ids_to_receive.insert(id1);
-    resource_ids_to_receive.insert(id2);
-    resource_provider_->DeclareUsedResourcesFromChild(child_id,
-                                                      resource_ids_to_receive);
-  }
-
-  EXPECT_EQ(2u, resource_provider_->num_resources());
+  std::vector<viz::TransferableResource> list;
+  child_resource_provider_->PrepareSendToParent(resource_ids_to_transfer,
+                                                &list);
+  ASSERT_EQ(2u, list.size());
+  resource_provider_->ReceiveFromChild(child_id, list);
   ResourceProvider::ResourceIdMap resource_map =
       resource_provider_->GetChildToParentMap(child_id);
-  viz::ResourceId mapped_id1 = resource_map[id1];
-  viz::ResourceId mapped_id2 = resource_map[id2];
+  viz::ResourceId mapped_id1 = resource_map[list[0].id];
+  viz::ResourceId mapped_id2 = resource_map[list[1].id];
+  {
+    resource_provider_->WaitSyncToken(mapped_id1);
+    DisplayResourceProvider::ScopedReadLockGL lock(resource_provider_.get(),
+                                                   mapped_id1);
+  }
+
+  EXPECT_EQ(list[0].mailbox_holder.sync_token,
+            context3d_->last_waited_sync_token());
+  viz::ResourceIdSet resource_ids_to_receive;
+  resource_ids_to_receive.insert(id1);
+  resource_ids_to_receive.insert(id2);
+  resource_provider_->DeclareUsedResourcesFromChild(child_id,
+                                                    resource_ids_to_receive);
+
+  EXPECT_EQ(2u, resource_provider_->num_resources());
+
   EXPECT_NE(0u, mapped_id1);
   EXPECT_NE(0u, mapped_id2);
 
@@ -1116,13 +1110,18 @@
 
   resource_provider_->ReceiveFromChild(child_id, list);
 
+  // In DisplayResourceProvider's namespace, use the mapped resource id.
+  ResourceProvider::ResourceIdMap resource_map =
+      resource_provider_->GetChildToParentMap(child_id);
+
   std::vector<std::unique_ptr<DisplayResourceProvider::ScopedReadLockGL>>
       read_locks;
-  for (auto& parent_resource : list) {
-    resource_provider_->WaitSyncToken(parent_resource.id);
+  for (auto& resource_id : list) {
+    unsigned int mapped_resource_id = resource_map[resource_id.id];
+    resource_provider_->WaitSyncToken(mapped_resource_id);
     read_locks.push_back(
         std::make_unique<DisplayResourceProvider::ScopedReadLockGL>(
-            resource_provider_.get(), parent_resource.id));
+            resource_provider_.get(), mapped_resource_id));
   }
 
   resource_provider_->DeclareUsedResourcesFromChild(child_id,
@@ -1174,9 +1173,13 @@
 
     resource_provider_->ReceiveFromChild(child_id, list);
 
-    resource_provider_->WaitSyncToken(list[0].id);
+    // In DisplayResourceProvider's namespace, use the mapped resource id.
+    ResourceProvider::ResourceIdMap resource_map =
+        resource_provider_->GetChildToParentMap(child_id);
+    viz::ResourceId mapped_resource_id = resource_map[list[0].id];
+    resource_provider_->WaitSyncToken(mapped_resource_id);
     DisplayResourceProvider::ScopedReadLockGL lock(resource_provider_.get(),
-                                                   list[0].id);
+                                                   mapped_resource_id);
 
     resource_provider_->DeclareUsedResourcesFromChild(child_id,
                                                       viz::ResourceIdSet());
@@ -1236,10 +1239,14 @@
 
   resource_provider_->ReceiveFromChild(child_id, list);
 
+  // In DisplayResourceProvider's namespace, use the mapped resource id.
+  ResourceProvider::ResourceIdMap resource_map =
+      resource_provider_->GetChildToParentMap(child_id);
+
   scoped_refptr<TestFence> fence(new TestFence);
   resource_provider_->SetReadLockFence(fence.get());
   {
-    unsigned parent_id = list.front().id;
+    unsigned parent_id = resource_map[list.front().id];
     resource_provider_->WaitSyncToken(parent_id);
     DisplayResourceProvider::ScopedReadLockGL lock(resource_provider_.get(),
                                                    parent_id);
@@ -1296,11 +1303,15 @@
 
   resource_provider_->ReceiveFromChild(child_id, list);
 
+  // In DisplayResourceProvider's namespace, use the mapped resource id.
+  ResourceProvider::ResourceIdMap resource_map =
+      resource_provider_->GetChildToParentMap(child_id);
+
   scoped_refptr<TestFence> fence(new TestFence);
   resource_provider_->SetReadLockFence(fence.get());
   {
     for (size_t i = 0; i < list.size(); i++) {
-      unsigned parent_id = list[i].id;
+      unsigned parent_id = resource_map[list[i].id];
       resource_provider_->WaitSyncToken(parent_id);
       DisplayResourceProvider::ScopedReadLockGL lock(resource_provider_.get(),
                                                      parent_id);
@@ -1359,11 +1370,15 @@
 
   resource_provider_->ReceiveFromChild(child_id, list);
 
+  // In DisplayResourceProvider's namespace, use the mapped resource id.
+  ResourceProvider::ResourceIdMap resource_map =
+      resource_provider_->GetChildToParentMap(child_id);
+
   scoped_refptr<TestFence> fence(new TestFence);
   resource_provider_->SetReadLockFence(fence.get());
   {
     for (size_t i = 0; i < list.size(); i++) {
-      unsigned parent_id = list[i].id;
+      unsigned parent_id = resource_map[list[i].id];
       resource_provider_->WaitSyncToken(parent_id);
       DisplayResourceProvider::ScopedReadLockGL lock(resource_provider_.get(),
                                                      parent_id);
@@ -1447,9 +1462,9 @@
   EXPECT_NE(0u, mapped_id1);
   EXPECT_NE(0u, mapped_id2);
   EXPECT_NE(0u, mapped_id3);
-  EXPECT_FALSE(resource_provider_->InUseByConsumer(id1));
-  EXPECT_FALSE(resource_provider_->InUseByConsumer(id2));
-  EXPECT_FALSE(resource_provider_->InUseByConsumer(id3));
+  EXPECT_FALSE(resource_provider_->InUseByConsumer(mapped_id1));
+  EXPECT_FALSE(resource_provider_->InUseByConsumer(mapped_id2));
+  EXPECT_FALSE(resource_provider_->InUseByConsumer(mapped_id3));
 
   uint8_t result[4] = { 0 };
   GetResourcePixels(
@@ -1908,45 +1923,45 @@
     std::vector<viz::ReturnedResource> returned_to_child;
     int child_id = parent_resource_provider->CreateChild(
         GetReturnCallback(&returned_to_child));
-    {
-      // Transfer some resource to the parent.
-      ResourceProvider::ResourceIdArray resource_ids_to_transfer;
-      resource_ids_to_transfer.push_back(id);
-      std::vector<viz::TransferableResource> list;
 
-      EXPECT_CALL(*child_context,
-                  produceTextureDirectCHROMIUM(_, GL_TEXTURE_2D, _));
+    // Transfer some resource to the parent.
+    ResourceProvider::ResourceIdArray resource_ids_to_transfer;
+    resource_ids_to_transfer.push_back(id);
+    std::vector<viz::TransferableResource> list;
 
-      child_resource_provider->PrepareSendToParent(resource_ids_to_transfer,
-                                                   &list);
-      Mock::VerifyAndClearExpectations(child_context);
+    EXPECT_CALL(*child_context,
+                produceTextureDirectCHROMIUM(_, GL_TEXTURE_2D, _));
 
-      ASSERT_EQ(1u, list.size());
-      EXPECT_EQ(static_cast<unsigned>(child_filter), list[0].filter);
+    child_resource_provider->PrepareSendToParent(resource_ids_to_transfer,
+                                                 &list);
+    Mock::VerifyAndClearExpectations(child_context);
 
-      EXPECT_CALL(*parent_context,
-                  createAndConsumeTextureCHROMIUM(GL_TEXTURE_2D, _))
-          .WillOnce(Return(parent_texture_id));
+    ASSERT_EQ(1u, list.size());
+    EXPECT_EQ(static_cast<unsigned>(child_filter), list[0].filter);
 
-      parent_resource_provider->ReceiveFromChild(child_id, list);
-      {
-        parent_resource_provider->WaitSyncToken(list[0].id);
-        DisplayResourceProvider::ScopedReadLockGL lock(
-            parent_resource_provider.get(), list[0].id);
-      }
-      Mock::VerifyAndClearExpectations(parent_context);
+    EXPECT_CALL(*parent_context,
+                createAndConsumeTextureCHROMIUM(GL_TEXTURE_2D, _))
+        .WillOnce(Return(parent_texture_id));
 
-      viz::ResourceIdSet resource_ids_to_receive;
-      resource_ids_to_receive.insert(id);
-      parent_resource_provider->DeclareUsedResourcesFromChild(
-          child_id, resource_ids_to_receive);
-      Mock::VerifyAndClearExpectations(parent_context);
-    }
+    parent_resource_provider->ReceiveFromChild(child_id, list);
     ResourceProvider::ResourceIdMap resource_map =
         parent_resource_provider->GetChildToParentMap(child_id);
     viz::ResourceId mapped_id = resource_map[id];
     EXPECT_NE(0u, mapped_id);
 
+    {
+      parent_resource_provider->WaitSyncToken(mapped_id);
+      DisplayResourceProvider::ScopedReadLockGL lock(
+          parent_resource_provider.get(), mapped_id);
+    }
+    Mock::VerifyAndClearExpectations(parent_context);
+
+    viz::ResourceIdSet resource_ids_to_receive;
+    resource_ids_to_receive.insert(id);
+    parent_resource_provider->DeclareUsedResourcesFromChild(
+        child_id, resource_ids_to_receive);
+    Mock::VerifyAndClearExpectations(parent_context);
+
     // The texture is set to |parent_filter| in the parent.
     EXPECT_CALL(*parent_context, bindTexture(GL_TEXTURE_2D, parent_texture_id));
     EXPECT_CALL(
@@ -3015,12 +3030,18 @@
  public:
   MOCK_METHOD0(NextTextureId, GLuint());
   MOCK_METHOD1(RetireTextureId, void(GLuint id));
+  MOCK_METHOD5(texStorage2DImageCHROMIUM,
+               void(GLenum target,
+                    GLenum internalformat,
+                    GLenum bufferusage,
+                    GLsizei width,
+                    GLsizei height));
   MOCK_METHOD5(texStorage2DEXT,
                void(GLenum target,
-                    GLint levels,
-                    GLuint internalformat,
-                    GLint width,
-                    GLint height));
+                    GLsizei levels,
+                    GLenum internalformat,
+                    GLsizei width,
+                    GLsizei height));
   MOCK_METHOD9(texImage2D,
                void(GLenum target,
                     GLint level,
@@ -3076,11 +3097,7 @@
   MOCK_METHOD1(destroyImageCHROMIUM, void(GLuint));
   MOCK_METHOD2(bindTexImage2DCHROMIUM, void(GLenum, GLint));
   MOCK_METHOD2(releaseTexImage2DCHROMIUM, void(GLenum, GLint));
-
-  // We're mocking bindTexture, so we override
-  // TestWebGraphicsContext3D::texParameteri to avoid assertions related to the
-  // currently bound texture.
-  void texParameteri(GLenum target, GLenum pname, GLint param) override {}
+  MOCK_METHOD3(texParameteri, void(GLenum target, GLenum pname, GLint param));
 };
 
 TEST_P(ResourceProviderTest, TextureAllocation) {
@@ -3104,6 +3121,7 @@
   uint8_t pixels[16] = { 0 };
   int texture_id = 123;
 
+  EXPECT_CALL(*context, texParameteri(_, _, _)).Times(AnyNumber());
   // Lazy allocation. Don't allocate when creating the resource.
   id = resource_provider->CreateResource(
       size, ResourceProvider::TEXTURE_HINT_DEFAULT, format, gfx::ColorSpace());
@@ -3116,6 +3134,7 @@
   resource_provider->DeleteResource(id);
 
   Mock::VerifyAndClearExpectations(context);
+  EXPECT_CALL(*context, texParameteri(_, _, _)).Times(AnyNumber());
 
   // Do allocate when we set the pixels.
   id = resource_provider->CreateResource(
@@ -3123,8 +3142,10 @@
 
   EXPECT_CALL(*context, NextTextureId()).WillOnce(Return(texture_id));
   EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, texture_id)).Times(3);
-  EXPECT_CALL(*context, texImage2D(_, _, _, 2, 2, _, _, _, _)).Times(1);
-  EXPECT_CALL(*context, texSubImage2D(_, _, _, _, 2, 2, _, _, _)).Times(1);
+  EXPECT_CALL(*context, texImage2D(GL_TEXTURE_2D, _, _, 2, 2, _, _, _, _))
+      .Times(1);
+  EXPECT_CALL(*context, texSubImage2D(GL_TEXTURE_2D, _, _, _, 2, 2, _, _, _))
+      .Times(1);
   resource_provider->CopyToResource(id, pixels, size);
 
   EXPECT_CALL(*context, RetireTextureId(texture_id)).Times(1);
@@ -3133,58 +3154,17 @@
   Mock::VerifyAndClearExpectations(context);
 }
 
-static void TestTextureAllocationHint(
-    AllocationTrackingContext3D* context,
-    LayerTreeResourceProvider* resource_provider) {
-  gfx::Size size(2, 2);
-
-  const viz::ResourceFormat formats[3] = {viz::RGBA_8888, viz::BGRA_8888,
-                                          viz::RGBA_F16};
-  const ResourceProvider::TextureHint hints[2] = {
-      ResourceProvider::TEXTURE_HINT_DEFAULT,
-      ResourceProvider::TEXTURE_HINT_FRAMEBUFFER,
-  };
-  for (size_t i = 0; i < arraysize(formats); ++i) {
-    for (GLuint texture_id = 1; texture_id <= arraysize(hints); ++texture_id) {
-      // Lazy allocation. Don't allocate when creating the resource.
-      viz::ResourceId id = resource_provider->CreateResource(
-          size, hints[texture_id - 1], formats[i], gfx::ColorSpace());
-
-      EXPECT_CALL(*context, NextTextureId()).WillOnce(Return(texture_id));
-      EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, texture_id)).Times(2);
-      // Resources are immutable when possible, so texStorage2DEXT should happen
-      // instead of texImage2D when the context support or format allows.
-      bool support_immutable_texture =
-          context->test_capabilities().texture_format_bgra8888 ||
-          formats[i] != viz::BGRA_8888;
-      EXPECT_CALL(*context, texStorage2DEXT(_, _, _, 2, 2))
-          .Times(support_immutable_texture ? 1 : 0);
-      EXPECT_CALL(*context, texImage2D(_, _, _, 2, 2, _, _, _, _))
-          .Times(support_immutable_texture ? 0 : 1);
-      resource_provider->AllocateForTesting(id);
-
-      EXPECT_CALL(*context, RetireTextureId(texture_id)).Times(1);
-      resource_provider->DeleteResource(id);
-
-      Mock::VerifyAndClearExpectations(context);
-    }
-  }
-}
-
-TEST_P(ResourceProviderTest, TextureAllocationHint) {
-  // Only for GL textures.
+TEST_P(ResourceProviderTest, TextureStorageAllocation) {
   if (GetParam() != ResourceProvider::RESOURCE_TYPE_GL_TEXTURE)
     return;
 
-  auto context = base::MakeUnique<StrictMock<AllocationTrackingContext3D>>();
-  auto* context_ptr = context.get();
-
-  // BGRA storage is not supported.
-  context->set_support_texture_format_bgra8888(false);
-
+  auto context_owned =
+      base::MakeUnique<StrictMock<AllocationTrackingContext3D>>();
+  auto* context = context_owned.get();
   context->set_support_texture_storage(true);
   context->set_support_texture_usage(true);
-  auto context_provider = TestContextProvider::Create(std::move(context));
+
+  auto context_provider = TestContextProvider::Create(std::move(context_owned));
   context_provider->BindToCurrentThread();
 
   auto resource_provider(std::make_unique<LayerTreeResourceProvider>(
@@ -3192,36 +3172,24 @@
       gpu_memory_buffer_manager_.get(), kDelegatedSyncPointsRequired,
       CreateResourceSettings()));
 
-  TestTextureAllocationHint(context_ptr, resource_provider.get());
+  viz::ResourceId id = resource_provider->CreateResource(
+      gfx::Size(2, 2), ResourceProvider::TEXTURE_HINT_DEFAULT, viz::RGBA_8888,
+      gfx::ColorSpace());
+
+  const GLuint kTextureId = 123u;
+  EXPECT_CALL(*context, NextTextureId()).WillOnce(Return(kTextureId));
+  EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, kTextureId)).Times(2);
+  EXPECT_CALL(*context, texStorage2DEXT(GL_TEXTURE_2D, 1, GL_RGBA8_OES, 2, 2))
+      .Times(1);
+  EXPECT_CALL(*context, texParameteri(GL_TEXTURE_2D, _, _)).Times(AnyNumber());
+  resource_provider->AllocateForTesting(id);
+
+  EXPECT_CALL(*context, RetireTextureId(kTextureId));
+  resource_provider->DeleteResource(id);
 }
 
-TEST_P(ResourceProviderTest, TextureAllocationHint_BGRA) {
-  // Only for GL textures.
-  if (GetParam() != ResourceProvider::RESOURCE_TYPE_GL_TEXTURE)
-    return;
-
-  auto context = base::MakeUnique<StrictMock<AllocationTrackingContext3D>>();
-  auto* context_ptr = context.get();
-
-  // BGRA storage is supported.
-  context->set_support_texture_format_bgra8888(true);
-
-  context->set_support_texture_storage(true);
-  context->set_support_texture_usage(true);
-  auto context_provider = TestContextProvider::Create(std::move(context));
-  context_provider->BindToCurrentThread();
-
-  auto resource_provider(std::make_unique<LayerTreeResourceProvider>(
-      context_provider.get(), shared_bitmap_manager_.get(),
-      gpu_memory_buffer_manager_.get(), kDelegatedSyncPointsRequired,
-      CreateResourceSettings()));
-
-  TestTextureAllocationHint(context_ptr, resource_provider.get());
-}
-
-TEST_P(ResourceProviderTest, Image_GLTexture) {
-  // Only for GL textures.
-  if (GetParam() != ResourceProvider::RESOURCE_TYPE_GL_TEXTURE)
+TEST_P(ResourceProviderTest, ScopedWriteLockGpuMemoryBuffer) {
+  if (GetParam() != ResourceProvider::RESOURCE_TYPE_GPU_MEMORY_BUFFER)
     return;
 
   std::unique_ptr<AllocationTrackingContext3D> context_owned(
@@ -3251,27 +3219,26 @@
     LayerTreeResourceProvider::ScopedWriteLockGpuMemoryBuffer lock(
         resource_provider.get(), id);
     EXPECT_TRUE(lock.GetGpuMemoryBuffer());
-    // Create texture and image upon releasing the lock.
-    EXPECT_CALL(*context, NextTextureId()).WillOnce(Return(kTextureId));
-    EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, kTextureId));
-    EXPECT_CALL(*context, createImageCHROMIUM(_, kWidth, kHeight, GL_RGBA))
-        .WillOnce(Return(kImageId));
-    EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, kTextureId));
-    EXPECT_CALL(*context, bindTexImage2DCHROMIUM(GL_TEXTURE_2D, kImageId));
   }
-  // The image is created in the lock's destructor.
+  // Create texture and image upon releasing the lock.
+  EXPECT_CALL(*context, NextTextureId()).WillOnce(Return(kTextureId));
+  EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, kTextureId));
+  EXPECT_CALL(*context, texParameteri(_, _, _)).Times(AnyNumber());
+  EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, kTextureId));
+  EXPECT_CALL(*context, createImageCHROMIUM(_, kWidth, kHeight, GL_RGBA))
+      .WillOnce(Return(kImageId));
+  EXPECT_CALL(*context, bindTexImage2DCHROMIUM(GL_TEXTURE_2D, kImageId));
   Mock::VerifyAndClearExpectations(context);
 
   {
     LayerTreeResourceProvider::ScopedWriteLockGpuMemoryBuffer lock(
         resource_provider.get(), id);
     EXPECT_TRUE(lock.GetGpuMemoryBuffer());
-    // Upload to GPU again since image is dirty after the write lock.
-    EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, kTextureId));
-    EXPECT_CALL(*context, releaseTexImage2DCHROMIUM(GL_TEXTURE_2D, kImageId));
-    EXPECT_CALL(*context, bindTexImage2DCHROMIUM(GL_TEXTURE_2D, kImageId));
   }
-  // The image is updated in the lock's destructor.
+  // Upload to GPU again since image is dirty after the write lock.
+  EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, kTextureId));
+  EXPECT_CALL(*context, releaseTexImage2DCHROMIUM(GL_TEXTURE_2D, kImageId));
+  EXPECT_CALL(*context, bindTexImage2DCHROMIUM(GL_TEXTURE_2D, kImageId));
   Mock::VerifyAndClearExpectations(context);
 
   EXPECT_CALL(*context, destroyImageCHROMIUM(kImageId));
@@ -3464,7 +3431,9 @@
   // First use will allocate lazily when accessing the texture.
   {
     EXPECT_CALL(*context, NextTextureId()).WillOnce(Return(kTextureId));
-    EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, kTextureId)).Times(2);
+    EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, kTextureId));
+    EXPECT_CALL(*context, texParameteri(_, _, _)).Times(AnyNumber());
+    EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, kTextureId));
     EXPECT_CALL(*context, texImage2D(GL_TEXTURE_2D, 0, GLInternalFormat(format),
                                      kWidth, kHeight, 0, GLDataFormat(format),
                                      GLDataType(format), nullptr));
@@ -3483,12 +3452,14 @@
   resource_provider->DeleteResource(id);
 }
 
-TEST_P(ResourceProviderTest, ScopedWriteLockGL_GpuMemoryBuffer) {
+TEST_P(ResourceProviderTest, ScopedWriteLockGL_Overlay) {
   if (GetParam() != ResourceProvider::RESOURCE_TYPE_GL_TEXTURE)
     return;
   std::unique_ptr<AllocationTrackingContext3D> context_owned(
       new StrictMock<AllocationTrackingContext3D>);
   AllocationTrackingContext3D* context = context_owned.get();
+  context->set_support_texture_storage_image(true);
+
   auto context_provider = TestContextProvider::Create(std::move(context_owned));
   context_provider->BindToCurrentThread();
 
@@ -3496,16 +3467,15 @@
   const int kHeight = 2;
   const viz::ResourceFormat format = viz::RGBA_8888;
   const unsigned kTextureId = 123u;
-  const unsigned kImageId = 234u;
 
   auto resource_provider(std::make_unique<LayerTreeResourceProvider>(
       context_provider.get(), shared_bitmap_manager_.get(),
       gpu_memory_buffer_manager_.get(), kDelegatedSyncPointsRequired,
       CreateResourceSettings()));
 
-  viz::ResourceId id = resource_provider->CreateGpuMemoryBufferResource(
-      gfx::Size(kWidth, kHeight), ResourceProvider::TEXTURE_HINT_DEFAULT,
-      format, gfx::BufferUsage::GPU_READ_CPU_READ_WRITE, gfx::ColorSpace());
+  viz::ResourceId id = resource_provider->CreateResource(
+      gfx::Size(kWidth, kHeight), ResourceProvider::TEXTURE_HINT_OVERLAY,
+      format, gfx::ColorSpace());
 
   InSequence sequence;
 
@@ -3513,11 +3483,11 @@
   {
     EXPECT_CALL(*context, NextTextureId()).WillOnce(Return(kTextureId));
     EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, kTextureId));
-    EXPECT_CALL(*context, createImageCHROMIUM(_, kWidth, kHeight,
-                                              GLInternalFormat(format)))
-        .WillOnce(Return(kImageId));
+    EXPECT_CALL(*context, texParameteri(_, _, _)).Times(AnyNumber());
     EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, kTextureId));
-    EXPECT_CALL(*context, bindTexImage2DCHROMIUM(GL_TEXTURE_2D, kImageId));
+    EXPECT_CALL(*context, texStorage2DImageCHROMIUM(GL_TEXTURE_2D, GL_RGBA8_OES,
+                                                    GL_SCANOUT_CHROMIUM, kWidth,
+                                                    kHeight));
     ResourceProvider::ScopedWriteLockGL lock(resource_provider.get(), id);
     EXPECT_EQ(lock.GetTexture(), kTextureId);
     Mock::VerifyAndClearExpectations(context);
@@ -3529,7 +3499,6 @@
     EXPECT_EQ(lock.GetTexture(), kTextureId);
   }
 
-  EXPECT_CALL(*context, destroyImageCHROMIUM(kImageId));
   EXPECT_CALL(*context, RetireTextureId(kTextureId));
   resource_provider->DeleteResource(id);
 }
@@ -3566,6 +3535,7 @@
   {
     EXPECT_CALL(*context, NextTextureId()).WillOnce(Return(kTextureId));
     EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, kTextureId));
+    EXPECT_CALL(*context, texParameteri(_, _, _)).Times(AnyNumber());
     ResourceProvider::ScopedWriteLockGL lock(resource_provider.get(), id);
     Mock::VerifyAndClearExpectations(context);
 
@@ -3616,12 +3586,15 @@
   resource_provider->DeleteResource(id);
 }
 
-TEST_P(ResourceProviderTest, ScopedWriteLockGL_GpuMemoryBuffer_Mailbox) {
+TEST_P(ResourceProviderTest, ScopedWriteLockGL_Mailbox_Overlay) {
   if (GetParam() != ResourceProvider::RESOURCE_TYPE_GL_TEXTURE)
     return;
+
   std::unique_ptr<AllocationTrackingContext3D> context_owned(
       new StrictMock<AllocationTrackingContext3D>);
   AllocationTrackingContext3D* context = context_owned.get();
+  context->set_support_texture_storage_image(true);
+
   auto context_provider = TestContextProvider::Create(std::move(context_owned));
   context_provider->BindToCurrentThread();
 
@@ -3630,16 +3603,15 @@
   const viz::ResourceFormat format = viz::RGBA_8888;
   const unsigned kTextureId = 123u;
   const unsigned kWorkerTextureId = 234u;
-  const unsigned kImageId = 345u;
 
   auto resource_provider(std::make_unique<LayerTreeResourceProvider>(
       context_provider.get(), shared_bitmap_manager_.get(),
       gpu_memory_buffer_manager_.get(), kDelegatedSyncPointsRequired,
       CreateResourceSettings()));
 
-  viz::ResourceId id = resource_provider->CreateGpuMemoryBufferResource(
-      gfx::Size(kWidth, kHeight), ResourceProvider::TEXTURE_HINT_DEFAULT,
-      format, gfx::BufferUsage::GPU_READ_CPU_READ_WRITE, gfx::ColorSpace());
+  viz::ResourceId id = resource_provider->CreateResource(
+      gfx::Size(kWidth, kHeight), ResourceProvider::TEXTURE_HINT_OVERLAY,
+      format, gfx::ColorSpace());
 
   InSequence sequence;
   gpu::SyncToken sync_token;
@@ -3649,6 +3621,7 @@
   {
     EXPECT_CALL(*context, NextTextureId()).WillOnce(Return(kTextureId));
     EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, kTextureId));
+    EXPECT_CALL(*context, texParameteri(_, _, _)).Times(AnyNumber());
     ResourceProvider::ScopedWriteLockGL lock(resource_provider.get(), id);
     Mock::VerifyAndClearExpectations(context);
 
@@ -3659,11 +3632,10 @@
 
     EXPECT_CALL(*context, createAndConsumeTextureCHROMIUM(GL_TEXTURE_2D, _))
         .WillOnce(Return(kWorkerTextureId));
-    EXPECT_CALL(*context, createImageCHROMIUM(_, kWidth, kHeight,
-                                              GLInternalFormat(format)))
-        .WillOnce(Return(kImageId));
     EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, kWorkerTextureId));
-    EXPECT_CALL(*context, bindTexImage2DCHROMIUM(GL_TEXTURE_2D, kImageId));
+    EXPECT_CALL(*context, texStorage2DImageCHROMIUM(GL_TEXTURE_2D, GL_RGBA8_OES,
+                                                    GL_SCANOUT_CHROMIUM, kWidth,
+                                                    kHeight));
     EXPECT_EQ(kWorkerTextureId,
               lock.ConsumeTexture(context_provider->ContextGL()));
     Mock::VerifyAndClearExpectations(context);
@@ -3696,7 +3668,6 @@
 
   // Wait for worker context sync token before deleting texture.
   EXPECT_CALL(*context, waitSyncToken(MatchesSyncToken(sync_token)));
-  EXPECT_CALL(*context, destroyImageCHROMIUM(kImageId));
   EXPECT_CALL(*context, RetireTextureId(kTextureId));
   resource_provider->DeleteResource(id);
 }
diff --git a/cc/scheduler/scheduler_state_machine.cc b/cc/scheduler/scheduler_state_machine.cc
index d2f6b201..cd259f0 100644
--- a/cc/scheduler/scheduler_state_machine.cc
+++ b/cc/scheduler/scheduler_state_machine.cc
@@ -595,26 +595,24 @@
   if (!needs_impl_side_invalidation_)
     return false;
 
-  // Only perform impl side invalidation after the frame ends so that we wait
-  // for any commit to happen before invalidating.
-  // TODO(khushalsagar): Invalidate at the beginning of the frame if there is no
-  // commit request from the main thread.
-  if (begin_impl_frame_state_ != BEGIN_IMPL_FRAME_STATE_INSIDE_DEADLINE)
-    return false;
-
-  if (!CouldCreatePendingTree())
-    return false;
-
-  // If the main thread is ready to commit, the impl-side invalidations will be
-  // merged with the incoming main frame.
-  if (begin_main_frame_state_ == BEGIN_MAIN_FRAME_STATE_READY_TO_COMMIT)
-    return false;
-
   // Don't invalidate if we've already done so either from the scheduler or as
   // part of commit.
   if (did_perform_impl_side_invalidation_)
     return false;
 
+  // No invalidations should be done outside the impl frame.
+  if (begin_impl_frame_state_ == BEGIN_IMPL_FRAME_STATE_IDLE)
+    return false;
+
+  // We need to be able to create a pending tree to perform an invalidation.
+  if (!CouldCreatePendingTree())
+    return false;
+
+  // Check if we should defer invalidating so we can merge these invalidations
+  // with the main frame.
+  if (ShouldDeferInvalidatingForMainFrame())
+    return false;
+
   // If invalidations go to the active tree and we are waiting for the previous
   // frame to be drawn, submitted and acked.
   if (settings_.commit_to_active_tree &&
@@ -625,6 +623,58 @@
   return true;
 }
 
+bool SchedulerStateMachine::ShouldDeferInvalidatingForMainFrame() const {
+  DCHECK_NE(begin_impl_frame_state_, BEGIN_IMPL_FRAME_STATE_IDLE);
+
+  // If the main thread is ready to commit, the impl-side invalidations will be
+  // merged with the incoming main frame.
+  if (begin_main_frame_state_ == BEGIN_MAIN_FRAME_STATE_READY_TO_COMMIT)
+    return true;
+
+  // If we are inside the deadline, and haven't performed an invalidation yet,
+  // do it now.
+  // TODO(khushalsagar): We could do better by scheduling a deadline for
+  // invalidating prior to the draw deadline. Since invalidating now implies
+  // this pending tree will miss the draw for this frame. And scheduling this
+  // deadline should only be required if:
+  // a) There is a request for impl-side invalidation.
+  // b) We have to wait on the main thread to respond to a main frame.
+  // In addition, the deadline task can be cancelled if the main thread
+  // responds before it runs.
+  if (begin_impl_frame_state_ == BEGIN_IMPL_FRAME_STATE_INSIDE_DEADLINE)
+    return false;
+
+  // If commits are being aborted (which would be the common case for a
+  // compositor scroll), don't defer the invalidation.
+  if (last_frame_events_.commit_had_no_updates)
+    return false;
+
+  // If there is a request for a main frame, then this could either be a
+  // request that we need to respond to in this impl frame or its possible the
+  // request is for the next frame (a rAF issued at the beginning of the current
+  // main frame). In either case, defer invalidating so we can merge it with the
+  // main frame.
+  if (needs_begin_main_frame_)
+    return true;
+
+  // If the main frame was already sent, wait for the main thread to respond.
+  if (begin_main_frame_state_ == BEGIN_MAIN_FRAME_STATE_SENT ||
+      begin_main_frame_state_ == BEGIN_MAIN_FRAME_STATE_STARTED)
+    return true;
+
+  // If the main thread committed during the last frame, i.e. it was not
+  // aborted, then we might get another main frame request later in the impl
+  // frame. This could be the case for a timer based animation running on the
+  // main thread which doesn't align with our vsync. For such cases,
+  // conservatively defer invalidating until the deadline.
+  if (last_frame_events_.did_commit_during_frame)
+    return true;
+
+  // If the main thread is not requesting any frames, perform the invalidation
+  // at the beginning of the impl frame.
+  return false;
+}
+
 void SchedulerStateMachine::WillPerformImplSideInvalidation() {
   current_pending_tree_is_impl_side_ = true;
   WillPerformImplSideInvalidationInternal();
@@ -958,6 +1008,11 @@
   begin_impl_frame_state_ = BEGIN_IMPL_FRAME_STATE_INSIDE_BEGIN_FRAME;
   current_frame_number_++;
 
+  // Cache the values from the previous impl frame before reseting them for this
+  // frame.
+  last_frame_events_.commit_had_no_updates = last_commit_had_no_updates_;
+  last_frame_events_.did_commit_during_frame = did_commit_during_frame_;
+
   last_commit_had_no_updates_ = false;
   did_draw_in_last_frame_ = false;
   did_submit_in_last_frame_ = false;
diff --git a/cc/scheduler/scheduler_state_machine.h b/cc/scheduler/scheduler_state_machine.h
index 9985bfe6..050d3c9 100644
--- a/cc/scheduler/scheduler_state_machine.h
+++ b/cc/scheduler/scheduler_state_machine.h
@@ -301,6 +301,7 @@
 
   bool ShouldPerformImplSideInvalidation() const;
   bool CouldCreatePendingTree() const;
+  bool ShouldDeferInvalidatingForMainFrame() const;
 
   bool ShouldTriggerBeginImplFrameDeadlineImmediately() const;
   bool ShouldBlockDeadlineIndefinitely() const;
@@ -336,6 +337,15 @@
   int last_frame_number_begin_main_frame_sent_ = -1;
   int last_frame_number_invalidate_layer_tree_frame_sink_performed_ = -1;
 
+  // Inputs from the last impl frame that are required for decisions made in
+  // this impl frame. The values from the last frame are cached before being
+  // reset in OnBeginImplFrame.
+  struct FrameEvents {
+    bool commit_had_no_updates = false;
+    bool did_commit_during_frame = false;
+  };
+  FrameEvents last_frame_events_;
+
   // These are used to ensure that an action only happens once per frame,
   // deadline, etc.
   bool did_draw_ = false;
diff --git a/cc/scheduler/scheduler_state_machine_unittest.cc b/cc/scheduler/scheduler_state_machine_unittest.cc
index 9e77c27c..c670aa7 100644
--- a/cc/scheduler/scheduler_state_machine_unittest.cc
+++ b/cc/scheduler/scheduler_state_machine_unittest.cc
@@ -2199,7 +2199,10 @@
   EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE);
 }
 
-TEST(SchedulerStateMachineTest, ImplSideInvalidationOnlyInsideDeadline) {
+TEST(SchedulerStateMachineTest,
+     ImplSideInvalidationAndMainFrame_NoMainFrameRequest) {
+  // No main frame request or any update in the last frame, invalidation runs
+  // immediately.
   SchedulerSettings settings;
   StateMachine state(settings);
   SET_UP_STATE(state);
@@ -2207,6 +2210,53 @@
   bool needs_first_draw_on_activation = true;
   state.SetNeedsImplSideInvalidation(needs_first_draw_on_activation);
   state.IssueNextBeginImplFrame();
+  EXPECT_ACTION_UPDATE_STATE(
+      SchedulerStateMachine::ACTION_PERFORM_IMPL_SIDE_INVALIDATION);
+}
+
+TEST(SchedulerStateMachineTest,
+     ImplSideInvalidationAndMainFrame_MainFrameRequest) {
+  // Main frame request and no abort history from the last frame, invalidation
+  // waits until deadline.
+  SchedulerSettings settings;
+  StateMachine state(settings);
+  SET_UP_STATE(state);
+
+  bool needs_first_draw_on_activation = true;
+  state.SetNeedsBeginMainFrame();
+  state.SetNeedsImplSideInvalidation(needs_first_draw_on_activation);
+  state.IssueNextBeginImplFrame();
+  EXPECT_ACTION_UPDATE_STATE(
+      SchedulerStateMachine::ACTION_SEND_BEGIN_MAIN_FRAME);
+  state.OnBeginImplFrameDeadline();
+  EXPECT_ACTION_UPDATE_STATE(
+      SchedulerStateMachine::ACTION_PERFORM_IMPL_SIDE_INVALIDATION);
+}
+
+TEST(SchedulerStateMachineTest,
+     ImplSideInvalidationAndMainFrame_LastFrameCommit) {
+  // Main frame committed in the last impl frame, invalidation waits until the
+  // deadline.
+  SchedulerSettings settings;
+  StateMachine state(settings);
+  SET_UP_STATE(state);
+
+  state.SetNeedsBeginMainFrame();
+  state.IssueNextBeginImplFrame();
+  EXPECT_ACTION_UPDATE_STATE(
+      SchedulerStateMachine::ACTION_SEND_BEGIN_MAIN_FRAME);
+  state.NotifyBeginMainFrameStarted();
+  state.NotifyReadyToCommit();
+  EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_COMMIT);
+  state.NotifyReadyToActivate();
+  EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_ACTIVATE_SYNC_TREE);
+  state.OnBeginImplFrameDeadline();
+  EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_DRAW_IF_POSSIBLE);
+  EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE);
+
+  bool needs_first_draw_on_activation = true;
+  state.SetNeedsImplSideInvalidation(needs_first_draw_on_activation);
+  state.IssueNextBeginImplFrame();
   EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE);
   state.OnBeginImplFrameDeadline();
   EXPECT_ACTION_UPDATE_STATE(
@@ -2214,6 +2264,32 @@
 }
 
 TEST(SchedulerStateMachineTest,
+     ImplSideInvalidationAndMainFrame_LastFrameAborted) {
+  // Last main frame was aborted. An invalidation is performed even if a main
+  // frame request is pending.
+  SchedulerSettings settings;
+  StateMachine state(settings);
+  SET_UP_STATE(state);
+
+  state.SetNeedsBeginMainFrame();
+  state.IssueNextBeginImplFrame();
+  EXPECT_ACTION_UPDATE_STATE(
+      SchedulerStateMachine::ACTION_SEND_BEGIN_MAIN_FRAME);
+  state.NotifyBeginMainFrameStarted();
+  state.BeginMainFrameAborted(CommitEarlyOutReason::FINISHED_NO_UPDATES);
+  EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE);
+  state.OnBeginImplFrameDeadline();
+  EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE);
+
+  bool needs_first_draw_on_activation = true;
+  state.SetNeedsImplSideInvalidation(needs_first_draw_on_activation);
+  state.SetNeedsBeginMainFrame();
+  state.IssueNextBeginImplFrame();
+  EXPECT_ACTION_UPDATE_STATE(
+      SchedulerStateMachine::ACTION_PERFORM_IMPL_SIDE_INVALIDATION);
+}
+
+TEST(SchedulerStateMachineTest,
      NoImplSideInvalidationWithoutLayerTreeFrameSink) {
   SchedulerSettings settings;
   StateMachine state(settings);
diff --git a/cc/scheduler/scheduler_unittest.cc b/cc/scheduler/scheduler_unittest.cc
index 843d648..f2bf083 100644
--- a/cc/scheduler/scheduler_unittest.cc
+++ b/cc/scheduler/scheduler_unittest.cc
@@ -3218,21 +3218,16 @@
   EXPECT_ACTIONS("ScheduledActionBeginLayerTreeFrameSinkCreation");
 }
 
-TEST_F(SchedulerTest, ImplSideInvalidationsInDeadline) {
+TEST_F(SchedulerTest, ImplSideInvalidationInsideImplFrame) {
   SetUpScheduler(EXTERNAL_BFS);
 
-  // Request an impl-side invalidation and trigger the deadline. Ensure that the
-  // invalidation runs inside the deadline.
+  // Request an impl-side invalidation. Ensure that it runs before the deadline.
   bool needs_first_draw_on_activation = true;
   scheduler_->SetNeedsImplSideInvalidation(needs_first_draw_on_activation);
   client_->Reset();
   EXPECT_SCOPED(AdvanceFrame());
-  EXPECT_ACTIONS("WillBeginImplFrame");
-
-  // Deadline.
-  client_->Reset();
-  task_runner_->RunTasksWhile(client_->InsideBeginImplFrame(true));
-  EXPECT_ACTIONS("ScheduledActionPerformImplSideInvalidation");
+  EXPECT_ACTIONS("WillBeginImplFrame",
+                 "ScheduledActionPerformImplSideInvalidation");
 }
 
 TEST_F(SchedulerTest, ImplSideInvalidationsMergedWithCommit) {
diff --git a/cc/test/fake_proxy.h b/cc/test/fake_proxy.h
index daf017f..24e4523 100644
--- a/cc/test/fake_proxy.h
+++ b/cc/test/fake_proxy.h
@@ -8,6 +8,7 @@
 #include "base/single_thread_task_runner.h"
 #include "cc/trees/layer_tree_host.h"
 #include "cc/trees/proxy.h"
+#include "services/metrics/public/cpp/ukm_recorder.h"
 
 namespace cc {
 
@@ -41,6 +42,7 @@
                                   BrowserControlsState current,
                                   bool animate) override {}
   void RequestBeginMainFrameNotExpected(bool new_state) override {}
+  void SetURLForUkm(const GURL& url) override {}
 
  private:
   LayerTreeHost* layer_tree_host_;
diff --git a/cc/test/fake_resource_provider.h b/cc/test/fake_resource_provider.h
index 2c9bdcb0..01a3c16 100644
--- a/cc/test/fake_resource_provider.h
+++ b/cc/test/fake_resource_provider.h
@@ -84,7 +84,8 @@
                          shared_bitmap_manager,
                          gpu_memory_buffer_manager,
                          delegated_sync_points_required,
-                         resource_settings) {}
+                         resource_settings,
+                         1) {}
 };
 
 }  // namespace cc
diff --git a/cc/test/layer_test_common.cc b/cc/test/layer_test_common.cc
index 89039e7..83f23f8 100644
--- a/cc/test/layer_test_common.cc
+++ b/cc/test/layer_test_common.cc
@@ -225,8 +225,7 @@
   surface_impl->set_occlusion_in_content_space(
       Occlusion(gfx::Transform(), SimpleEnclosedRegion(occluded),
                 SimpleEnclosedRegion()));
-  surface_impl->AppendQuads(resource_provider()->default_resource_type() ==
-                                    ResourceProvider::RESOURCE_TYPE_BITMAP
+  surface_impl->AppendQuads(resource_provider()->IsSoftware()
                                 ? DRAW_MODE_SOFTWARE
                                 : DRAW_MODE_HARDWARE,
                             render_pass_.get(), &data);
diff --git a/cc/test/layer_tree_pixel_resource_test.cc b/cc/test/layer_tree_pixel_resource_test.cc
index 167042e..a31fd65 100644
--- a/cc/test/layer_tree_pixel_resource_test.cc
+++ b/cc/test/layer_tree_pixel_resource_test.cc
@@ -17,104 +17,21 @@
 
 namespace cc {
 
-namespace {
-
-bool IsTestCaseSupported(PixelResourceTestCase test_case) {
-  switch (test_case) {
-    case SOFTWARE:
-    case GL_GPU_RASTER_2D_DRAW:
-    case GL_ZERO_COPY_2D_DRAW:
-    case GL_ZERO_COPY_RECT_DRAW:
-    case GL_ONE_COPY_2D_STAGING_2D_DRAW:
-    case GL_ONE_COPY_RECT_STAGING_2D_DRAW:
-      return true;
-    case GL_ZERO_COPY_EXTERNAL_DRAW:
-    case GL_ONE_COPY_EXTERNAL_STAGING_2D_DRAW:
-      // These should all be enabled in practice.
-      // TODO(enne): look into getting texture external oes enabled.
-      return false;
-  }
-
-  NOTREACHED();
-  return false;
-}
-
-}  // namespace
-
 LayerTreeHostPixelResourceTest::LayerTreeHostPixelResourceTest(
     PixelResourceTestCase test_case,
     Layer::LayerMaskType mask_type)
-    : draw_texture_target_(GL_INVALID_VALUE),
-      raster_buffer_provider_type_(RASTER_BUFFER_PROVIDER_TYPE_BITMAP),
-      texture_hint_(ResourceProvider::TEXTURE_HINT_DEFAULT),
-      mask_type_(mask_type),
-      initialized_(false),
-      test_case_(test_case) {
+    : mask_type_(mask_type) {
   InitializeFromTestCase(test_case);
 }
 
-LayerTreeHostPixelResourceTest::LayerTreeHostPixelResourceTest()
-    : draw_texture_target_(GL_INVALID_VALUE),
-      raster_buffer_provider_type_(RASTER_BUFFER_PROVIDER_TYPE_BITMAP),
-      mask_type_(Layer::LayerMaskType::SINGLE_TEXTURE_MASK),
-      initialized_(false),
-      test_case_(SOFTWARE) {}
+LayerTreeHostPixelResourceTest::LayerTreeHostPixelResourceTest() = default;
 
 void LayerTreeHostPixelResourceTest::InitializeFromTestCase(
     PixelResourceTestCase test_case) {
   DCHECK(!initialized_);
+  test_case_ = test_case;
+  test_type_ = (test_case == SOFTWARE) ? PIXEL_TEST_SOFTWARE : PIXEL_TEST_GL;
   initialized_ = true;
-  switch (test_case) {
-    case SOFTWARE:
-      test_type_ = PIXEL_TEST_SOFTWARE;
-      draw_texture_target_ = GL_INVALID_VALUE;
-      raster_buffer_provider_type_ = RASTER_BUFFER_PROVIDER_TYPE_BITMAP;
-      texture_hint_ = ResourceProvider::TEXTURE_HINT_DEFAULT;
-      return;
-    case GL_GPU_RASTER_2D_DRAW:
-      test_type_ = PIXEL_TEST_GL;
-      draw_texture_target_ = GL_TEXTURE_2D;
-      raster_buffer_provider_type_ = RASTER_BUFFER_PROVIDER_TYPE_GPU;
-      texture_hint_ = ResourceProvider::TEXTURE_HINT_FRAMEBUFFER;
-      return;
-    case GL_ONE_COPY_2D_STAGING_2D_DRAW:
-      test_type_ = PIXEL_TEST_GL;
-      draw_texture_target_ = GL_TEXTURE_2D;
-      raster_buffer_provider_type_ = RASTER_BUFFER_PROVIDER_TYPE_ONE_COPY;
-      texture_hint_ = ResourceProvider::TEXTURE_HINT_DEFAULT;
-      return;
-    case GL_ONE_COPY_RECT_STAGING_2D_DRAW:
-      test_type_ = PIXEL_TEST_GL;
-      draw_texture_target_ = GL_TEXTURE_2D;
-      raster_buffer_provider_type_ = RASTER_BUFFER_PROVIDER_TYPE_ONE_COPY;
-      texture_hint_ = ResourceProvider::TEXTURE_HINT_DEFAULT;
-      return;
-    case GL_ONE_COPY_EXTERNAL_STAGING_2D_DRAW:
-      test_type_ = PIXEL_TEST_GL;
-      draw_texture_target_ = GL_TEXTURE_2D;
-      raster_buffer_provider_type_ = RASTER_BUFFER_PROVIDER_TYPE_ONE_COPY;
-      texture_hint_ = ResourceProvider::TEXTURE_HINT_DEFAULT;
-      return;
-    case GL_ZERO_COPY_2D_DRAW:
-      test_type_ = PIXEL_TEST_GL;
-      draw_texture_target_ = GL_TEXTURE_2D;
-      raster_buffer_provider_type_ = RASTER_BUFFER_PROVIDER_TYPE_ZERO_COPY;
-      texture_hint_ = ResourceProvider::TEXTURE_HINT_DEFAULT;
-      return;
-    case GL_ZERO_COPY_RECT_DRAW:
-      test_type_ = PIXEL_TEST_GL;
-      draw_texture_target_ = GL_TEXTURE_RECTANGLE_ARB;
-      raster_buffer_provider_type_ = RASTER_BUFFER_PROVIDER_TYPE_ZERO_COPY;
-      texture_hint_ = ResourceProvider::TEXTURE_HINT_DEFAULT;
-      return;
-    case GL_ZERO_COPY_EXTERNAL_DRAW:
-      test_type_ = PIXEL_TEST_GL;
-      draw_texture_target_ = GL_TEXTURE_EXTERNAL_OES;
-      raster_buffer_provider_type_ = RASTER_BUFFER_PROVIDER_TYPE_ZERO_COPY;
-      texture_hint_ = ResourceProvider::TEXTURE_HINT_DEFAULT;
-      return;
-  }
-  NOTREACHED();
 }
 
 void LayerTreeHostPixelResourceTest::CreateResourceAndRasterBufferProvider(
@@ -136,20 +53,19 @@
   int max_bytes_per_copy_operation = 1024 * 1024;
   int max_staging_buffer_usage_in_bytes = 32 * 1024 * 1024;
 
-  // Create resource pool.
-  *resource_pool =
-      ResourcePool::Create(resource_provider, task_runner, texture_hint_,
-                           ResourcePool::kDefaultExpirationDelay, false);
-
-  switch (raster_buffer_provider_type_) {
-    case RASTER_BUFFER_PROVIDER_TYPE_BITMAP:
+  switch (test_case_) {
+    case SOFTWARE:
       EXPECT_FALSE(compositor_context_provider);
       EXPECT_EQ(PIXEL_TEST_SOFTWARE, test_type_);
 
       *raster_buffer_provider =
           BitmapRasterBufferProvider::Create(resource_provider);
+      *resource_pool =
+          ResourcePool::Create(resource_provider, task_runner,
+                               ResourceProvider::TEXTURE_HINT_DEFAULT,
+                               ResourcePool::kDefaultExpirationDelay, false);
       break;
-    case RASTER_BUFFER_PROVIDER_TYPE_GPU:
+    case GPU:
       EXPECT_TRUE(compositor_context_provider);
       EXPECT_TRUE(worker_context_provider);
       EXPECT_EQ(PIXEL_TEST_GL, test_type_);
@@ -158,15 +74,23 @@
           compositor_context_provider, worker_context_provider,
           resource_provider, false, 0, viz::PlatformColor::BestTextureFormat(),
           false, false);
+      *resource_pool =
+          ResourcePool::Create(resource_provider, task_runner,
+                               ResourceProvider::TEXTURE_HINT_FRAMEBUFFER,
+                               ResourcePool::kDefaultExpirationDelay, false);
       break;
-    case RASTER_BUFFER_PROVIDER_TYPE_ZERO_COPY:
+    case ZERO_COPY:
       EXPECT_TRUE(compositor_context_provider);
       EXPECT_EQ(PIXEL_TEST_GL, test_type_);
 
       *raster_buffer_provider = ZeroCopyRasterBufferProvider::Create(
           resource_provider, viz::PlatformColor::BestTextureFormat());
+      *resource_pool = ResourcePool::CreateForGpuMemoryBufferResources(
+          resource_provider, task_runner,
+          gfx::BufferUsage::GPU_READ_CPU_READ_WRITE,
+          ResourcePool::kDefaultExpirationDelay, false);
       break;
-    case RASTER_BUFFER_PROVIDER_TYPE_ONE_COPY:
+    case ONE_COPY:
       EXPECT_TRUE(compositor_context_provider);
       EXPECT_TRUE(worker_context_provider);
       EXPECT_EQ(PIXEL_TEST_GL, test_type_);
@@ -176,6 +100,10 @@
           resource_provider, max_bytes_per_copy_operation, false,
           max_staging_buffer_usage_in_bytes,
           viz::PlatformColor::BestTextureFormat(), false);
+      *resource_pool =
+          ResourcePool::Create(resource_provider, task_runner,
+                               ResourceProvider::TEXTURE_HINT_DEFAULT,
+                               ResourcePool::kDefaultExpirationDelay, false);
       break;
   }
 }
@@ -183,8 +111,6 @@
 void LayerTreeHostPixelResourceTest::RunPixelResourceTest(
     scoped_refptr<Layer> content_root,
     base::FilePath file_name) {
-  if (!IsTestCaseSupported(test_case_))
-    return;
   RunPixelTest(test_type_, content_root, file_name);
 }
 
diff --git a/cc/test/layer_tree_pixel_resource_test.h b/cc/test/layer_tree_pixel_resource_test.h
index ddf639d..fe6e391f 100644
--- a/cc/test/layer_tree_pixel_resource_test.h
+++ b/cc/test/layer_tree_pixel_resource_test.h
@@ -14,19 +14,11 @@
 class RasterBufferProvider;
 class ResourcePool;
 
-// Enumerate the various combinations of renderer, resource pool, staging
-// texture type, and drawing texture types.  Not all of the combinations
-// are possible (or worth testing independently), so this is the minimal
-// list to hit all codepaths.
 enum PixelResourceTestCase {
   SOFTWARE,
-  GL_GPU_RASTER_2D_DRAW,
-  GL_ONE_COPY_2D_STAGING_2D_DRAW,
-  GL_ONE_COPY_RECT_STAGING_2D_DRAW,
-  GL_ONE_COPY_EXTERNAL_STAGING_2D_DRAW,
-  GL_ZERO_COPY_2D_DRAW,
-  GL_ZERO_COPY_RECT_DRAW,
-  GL_ZERO_COPY_EXTERNAL_DRAW,
+  GPU,
+  ONE_COPY,
+  ZERO_COPY,
 };
 
 class LayerTreeHostPixelResourceTest : public LayerTreePixelTest {
@@ -43,36 +35,20 @@
   void RunPixelResourceTest(scoped_refptr<Layer> content_root,
                             base::FilePath file_name);
 
-  enum RasterBufferProviderType {
-    RASTER_BUFFER_PROVIDER_TYPE_ZERO_COPY,
-    RASTER_BUFFER_PROVIDER_TYPE_ONE_COPY,
-    RASTER_BUFFER_PROVIDER_TYPE_GPU,
-    RASTER_BUFFER_PROVIDER_TYPE_BITMAP
-  };
-
  protected:
-  unsigned draw_texture_target_;
-  RasterBufferProviderType raster_buffer_provider_type_;
-  ResourceProvider::TextureHint texture_hint_;
+  PixelResourceTestCase test_case_;
   Layer::LayerMaskType mask_type_;
-  bool initialized_;
+  bool initialized_ = false;
 
   void InitializeFromTestCase(PixelResourceTestCase test_case);
-
- private:
-  PixelResourceTestCase test_case_;
 };
 
-#define INSTANTIATE_PIXEL_RESOURCE_TEST_CASE_P(framework_name)                 \
-  INSTANTIATE_TEST_CASE_P(                                                     \
-      PixelResourceTest, framework_name,                                       \
-      ::testing::Combine(                                                      \
-          ::testing::Values(                                                   \
-              SOFTWARE, GL_GPU_RASTER_2D_DRAW, GL_ONE_COPY_2D_STAGING_2D_DRAW, \
-              GL_ONE_COPY_RECT_STAGING_2D_DRAW,                                \
-              GL_ONE_COPY_EXTERNAL_STAGING_2D_DRAW, GL_ZERO_COPY_2D_DRAW,      \
-              GL_ZERO_COPY_RECT_DRAW, GL_ZERO_COPY_EXTERNAL_DRAW),             \
-          ::testing::Values(Layer::LayerMaskType::SINGLE_TEXTURE_MASK,         \
+#define INSTANTIATE_PIXEL_RESOURCE_TEST_CASE_P(framework_name)         \
+  INSTANTIATE_TEST_CASE_P(                                             \
+      PixelResourceTest, framework_name,                               \
+      ::testing::Combine(                                              \
+          ::testing::Values(SOFTWARE, GPU, ONE_COPY, ZERO_COPY),       \
+          ::testing::Values(Layer::LayerMaskType::SINGLE_TEXTURE_MASK, \
                             Layer::LayerMaskType::MULTI_TEXTURE_MASK)))
 
 class ParameterizedPixelResourceTest
diff --git a/cc/test/layer_tree_test.cc b/cc/test/layer_tree_test.cc
index 90403793..e22d27e 100644
--- a/cc/test/layer_tree_test.cc
+++ b/cc/test/layer_tree_test.cc
@@ -24,6 +24,7 @@
 #include "cc/test/fake_output_surface.h"
 #include "cc/test/test_context_provider.h"
 #include "cc/test/test_shared_bitmap_manager.h"
+#include "cc/test/test_ukm_recorder_factory.h"
 #include "cc/trees/layer_tree_host_client.h"
 #include "cc/trees/layer_tree_host_impl.h"
 #include "cc/trees/layer_tree_host_single_thread_client.h"
@@ -31,6 +32,7 @@
 #include "cc/trees/proxy_impl.h"
 #include "cc/trees/proxy_main.h"
 #include "cc/trees/single_thread_proxy.h"
+#include "components/ukm/test_ukm_recorder.h"
 #include "components/viz/common/resources/buffer_to_texture_target_map.h"
 #include "components/viz/test/begin_frame_args_test.h"
 #include "components/viz/test/test_layer_tree_frame_sink.h"
@@ -406,6 +408,7 @@
     params.settings = &settings;
     params.mutator_host = mutator_host;
     params.image_worker_task_runner = std::move(image_worker_task_runner);
+    params.ukm_recorder_factory = std::make_unique<TestUkmRecorderFactory>();
 
     std::unique_ptr<LayerTreeHostForTesting> layer_tree_host(
         new LayerTreeHostForTesting(test_hooks, &params, mode));
@@ -436,6 +439,8 @@
             test_hooks_, GetSettings(), host_impl_client,
             GetTaskRunnerProvider(), task_graph_runner(),
             rendering_stats_instrumentation(), image_worker_task_runner_);
+
+    host_impl->InitializeUkm(ukm_recorder_factory_->CreateRecorder());
     input_handler_weak_ptr_ = host_impl->AsWeakPtr();
     return host_impl;
   }
diff --git a/cc/test/render_pass_test_utils.cc b/cc/test/render_pass_test_utils.cc
index cb37f625..0b9628b7 100644
--- a/cc/test/render_pass_test_utils.cc
+++ b/cc/test/render_pass_test_utils.cc
@@ -368,6 +368,7 @@
       resource_provider->GetChildToParentMap(child_id);
   viz::ResourceId mapped_resource1 = resource_map[resource1];
   viz::ResourceId mapped_resource2 = resource_map[resource2];
+  viz::ResourceId mapped_resource3 = resource_map[resource3];
   viz::ResourceId mapped_resource4 = resource_map[resource4];
   viz::ResourceId mapped_resource5 = resource_map[resource5];
   viz::ResourceId mapped_resource6 = resource_map[resource6];
@@ -385,7 +386,6 @@
   viz::DebugBorderDrawQuad* debug_border_quad =
       to_pass->CreateAndAppendDrawQuad<viz::DebugBorderDrawQuad>();
   debug_border_quad->SetNew(shared_state, rect, visible_rect, SK_ColorRED, 1);
-
   if (child_pass_id) {
     viz::RenderPassDrawQuad* render_pass_quad =
         to_pass->CreateAndAppendDrawQuad<viz::RenderPassDrawQuad>();
@@ -435,7 +435,7 @@
   viz::TileDrawQuad* transformed_tile_quad =
       to_pass->CreateAndAppendDrawQuad<viz::TileDrawQuad>();
   transformed_tile_quad->SetNew(
-      transformed_state, rect, visible_rect, needs_blending, resource3,
+      transformed_state, rect, visible_rect, needs_blending, mapped_resource3,
       gfx::RectF(0, 0, 100, 100), gfx::Size(100, 100), false, false, false);
 
   viz::SharedQuadState* shared_state2 =
diff --git a/cc/test/test_context_provider.h b/cc/test/test_context_provider.h
index e598939..acd2384 100644
--- a/cc/test/test_context_provider.h
+++ b/cc/test/test_context_provider.h
@@ -68,6 +68,7 @@
   // InitializeOnCurrentThread on the context returned from this method.
   TestWebGraphicsContext3D* UnboundTestContext3d();
 
+  TestGLES2Interface* TestContextGL() { return context_gl_.get(); }
   TestContextSupport* support() { return support_.get(); }
 
  protected:
diff --git a/cc/test/test_gles2_interface.cc b/cc/test/test_gles2_interface.cc
index 5450919..29a0aed 100644
--- a/cc/test/test_gles2_interface.cc
+++ b/cc/test/test_gles2_interface.cc
@@ -222,6 +222,15 @@
   test_context_->texStorage2DEXT(target, levels, internalformat, width, height);
 }
 
+void TestGLES2Interface::TexStorage2DImageCHROMIUM(GLenum target,
+                                                   GLenum internalformat,
+                                                   GLenum bufferusage,
+                                                   GLsizei width,
+                                                   GLsizei height) {
+  test_context_->texStorage2DImageCHROMIUM(target, internalformat, bufferusage,
+                                           width, height);
+}
+
 void TestGLES2Interface::TexParameteri(GLenum target,
                                        GLenum pname,
                                        GLint param) {
diff --git a/cc/test/test_gles2_interface.h b/cc/test/test_gles2_interface.h
index b3233b8d..bcaae230 100644
--- a/cc/test/test_gles2_interface.h
+++ b/cc/test/test_gles2_interface.h
@@ -90,6 +90,11 @@
                        GLenum internalformat,
                        GLsizei width,
                        GLsizei height) override;
+  void TexStorage2DImageCHROMIUM(GLenum target,
+                                 GLenum internalformat,
+                                 GLenum bufferusage,
+                                 GLsizei width,
+                                 GLsizei height) override;
   void TexParameteri(GLenum target, GLenum pname, GLint param) override;
 
   void CompressedTexImage2D(GLenum target,
diff --git a/cc/test/test_ukm_recorder_factory.cc b/cc/test/test_ukm_recorder_factory.cc
new file mode 100644
index 0000000..156072b
--- /dev/null
+++ b/cc/test/test_ukm_recorder_factory.cc
@@ -0,0 +1,17 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "cc/test/test_ukm_recorder_factory.h"
+
+#include "components/ukm/test_ukm_recorder.h"
+
+namespace cc {
+
+TestUkmRecorderFactory::~TestUkmRecorderFactory() = default;
+
+std::unique_ptr<ukm::UkmRecorder> TestUkmRecorderFactory::CreateRecorder() {
+  return std::make_unique<ukm::TestUkmRecorder>();
+}
+
+}  // namespace cc
diff --git a/cc/test/test_ukm_recorder_factory.h b/cc/test/test_ukm_recorder_factory.h
new file mode 100644
index 0000000..113a61f
--- /dev/null
+++ b/cc/test/test_ukm_recorder_factory.h
@@ -0,0 +1,21 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CC_TEST_TEST_UKM_RECORDER_FACTORY_H_
+#define CC_TEST_TEST_UKM_RECORDER_FACTORY_H_
+
+#include "cc/trees/ukm_manager.h"
+
+namespace cc {
+
+class TestUkmRecorderFactory : public UkmRecorderFactory {
+ public:
+  ~TestUkmRecorderFactory() override;
+
+  std::unique_ptr<ukm::UkmRecorder> CreateRecorder() override;
+};
+
+}  // namespace cc
+
+#endif  // CC_TEST_TEST_UKM_RECORDER_FACTORY_H_
diff --git a/cc/test/test_web_graphics_context_3d.cc b/cc/test/test_web_graphics_context_3d.cc
index eb92b61..8ccc1535 100644
--- a/cc/test/test_web_graphics_context_3d.cc
+++ b/cc/test/test_web_graphics_context_3d.cc
@@ -771,6 +771,16 @@
   test_capabilities_.max_samples = max_samples;
 }
 
+size_t TestWebGraphicsContext3D::NumFramebuffers() const {
+  base::AutoLock lock_for_framebuffer_access(namespace_->lock);
+  return framebuffer_set_.size();
+}
+
+size_t TestWebGraphicsContext3D::NumRenderbuffers() const {
+  base::AutoLock lock_for_renderbuffer_access(namespace_->lock);
+  return namespace_->renderbuffer_set.size();
+}
+
 TestWebGraphicsContext3D::TextureTargets::TextureTargets() {
   // Initialize default bindings.
   bound_textures_[GL_TEXTURE_2D] = 0;
diff --git a/cc/test/test_web_graphics_context_3d.h b/cc/test/test_web_graphics_context_3d.h
index 841e9648..6fab5680 100644
--- a/cc/test/test_web_graphics_context_3d.h
+++ b/cc/test/test_web_graphics_context_3d.h
@@ -153,10 +153,15 @@
   virtual void deleteShader(GLuint id);
 
   virtual void texStorage2DEXT(GLenum target,
-                               GLint levels,
-                               GLuint internalformat,
-                               GLint width,
-                               GLint height) {}
+                               GLsizei levels,
+                               GLenum internalformat,
+                               GLsizei width,
+                               GLsizei height) {}
+  virtual void texStorage2DImageCHROMIUM(GLenum target,
+                                         GLenum internalformat,
+                                         GLenum bufferusage,
+                                         GLsizei width,
+                                         GLsizei height) {}
 
   virtual GLuint createQueryEXT();
   virtual void deleteQueryEXT(GLuint query) {}
@@ -187,8 +192,7 @@
                              const void* pixels) {}
 
   virtual void genMailboxCHROMIUM(GLbyte* mailbox);
-  virtual void produceTextureCHROMIUM(GLenum target,
-                                      const GLbyte* mailbox) { }
+  virtual void produceTextureCHROMIUM(GLenum target, const GLbyte* mailbox) {}
   virtual void produceTextureDirectCHROMIUM(GLuint texture,
                                             GLenum target,
                                             const GLbyte* mailbox) {}
@@ -253,8 +257,7 @@
                           const void* data,
                           GLenum usage);
   virtual void pixelStorei(GLenum pname, GLint param);
-  virtual void* mapBufferCHROMIUM(GLenum target,
-                                  GLenum access);
+  virtual void* mapBufferCHROMIUM(GLenum target, GLenum access);
   virtual GLboolean unmapBufferCHROMIUM(GLenum target);
 
   virtual GLuint createImageCHROMIUM(ClientBuffer buffer,
@@ -360,6 +363,9 @@
   void set_support_multisample_compatibility(bool support) {
     test_capabilities_.multisample_compatibility = support;
   }
+  void set_support_texture_storage_image(bool support) {
+    test_capabilities_.texture_storage_image = support;
+  }
 
   // When this context is lost, all contexts in its share group are also lost.
   void add_share_group_context(TestWebGraphicsContext3D* context3d) {
@@ -401,6 +407,9 @@
 
   UpdateType last_update_type() { return last_update_type_; }
 
+  size_t NumFramebuffers() const;
+  size_t NumRenderbuffers() const;
+
  protected:
   struct TextureTargets {
     TextureTargets();
diff --git a/cc/tiles/gpu_image_decode_cache_unittest.cc b/cc/tiles/gpu_image_decode_cache_unittest.cc
index 6830574d..fac3fdac 100644
--- a/cc/tiles/gpu_image_decode_cache_unittest.cc
+++ b/cc/tiles/gpu_image_decode_cache_unittest.cc
@@ -22,6 +22,7 @@
 
 class FakeDiscardableManager {
  public:
+  void SetGLES2Interface(TestGLES2Interface* gl) { gl_ = gl; }
   void Initialize(GLuint texture_id) {
     EXPECT_EQ(textures_.end(), textures_.find(texture_id));
     textures_[texture_id] = kHandleLockedStart;
@@ -29,7 +30,7 @@
   }
   void Unlock(GLuint texture_id) {
     EXPECT_NE(textures_.end(), textures_.find(texture_id));
-    EXPECT_GE(textures_[texture_id], kHandleLockedStart);
+    ExpectLocked(texture_id);
     textures_[texture_id]--;
   }
   bool Lock(GLuint texture_id) {
@@ -43,9 +44,11 @@
     return false;
   }
 
-  void DeleteImage(GLuint texture_id) {
-    EXPECT_NE(textures_.end(), textures_.find(texture_id));
-    EXPECT_EQ(textures_[texture_id], kHandleUnlocked);
+  void DeleteTexture(GLuint texture_id) {
+    if (textures_.end() == textures_.find(texture_id))
+      return;
+
+    ExpectLocked(texture_id);
     textures_[texture_id] = kHandleDeleted;
     live_textures_count_--;
   }
@@ -63,17 +66,30 @@
         continue;
 
       it->second = kHandleDeleted;
+      gl_->TestGLES2Interface::DeleteTextures(1, &it->first);
       live_textures_count_--;
     }
   }
 
+  void ExpectLocked(GLuint texture_id) {
+    EXPECT_TRUE(textures_.end() != textures_.find(texture_id));
+
+    // Any value > kHandleLockedStart represents a locked texture. As we
+    // increment this value with each lock, we need the entire range and can't
+    // add additional values > kHandleLockedStart in the future.
+    EXPECT_GE(textures_[texture_id], kHandleLockedStart);
+    EXPECT_LE(textures_[texture_id], kHandleLockedEnd);
+  }
+
   const int32_t kHandleDeleted = 0;
   const int32_t kHandleUnlocked = 1;
   const int32_t kHandleLockedStart = 2;
+  const int32_t kHandleLockedEnd = std::numeric_limits<int32_t>::max();
 
   std::map<GLuint, int32_t> textures_;
   size_t live_textures_count_ = 0;
   size_t cached_textures_limit_ = std::numeric_limits<size_t>::max();
+  TestGLES2Interface* gl_ = nullptr;
 };
 
 class FakeDiscardableGLES2Interface : public TestGLES2Interface,
@@ -84,6 +100,15 @@
       : extension_string_("GL_EXT_texture_format_BGRA8888 GL_OES_rgb8_rgba8"),
         discardable_manager_(discardable_manager) {}
 
+  ~FakeDiscardableGLES2Interface() override {
+    // All textures / framebuffers / renderbuffers should be cleaned up.
+    if (test_context_) {
+      EXPECT_EQ(0u, test_context_->NumTextures());
+      EXPECT_EQ(0u, test_context_->NumFramebuffers());
+      EXPECT_EQ(0u, test_context_->NumRenderbuffers());
+    }
+  }
+
   void InitializeDiscardableTextureCHROMIUM(GLuint texture_id) override {
     discardable_manager_->Initialize(texture_id);
   }
@@ -94,8 +119,6 @@
     return discardable_manager_->Lock(texture_id);
   }
 
-  void DeleteTextures(GLsizei n, const GLuint* textures) override {}
-
   bool ThreadSafeShallowLockDiscardableTexture(uint32_t texture_id) override {
     return discardable_manager_->Lock(texture_id);
   }
@@ -131,6 +154,12 @@
     }
     TestGLES2Interface::GetIntegerv(name, params);
   }
+  void DeleteTextures(GLsizei n, const GLuint* textures) override {
+    for (GLsizei i = 0; i < n; i++) {
+      discardable_manager_->DeleteTexture(textures[i]);
+    }
+    TestGLES2Interface::DeleteTextures(n, textures);
+  }
 
  private:
   const std::string extension_string_;
@@ -169,6 +198,7 @@
   void SetUp() override {
     context_provider_ =
         DiscardableTextureMockContextProvider::Create(&discardable_manager_);
+    discardable_manager_.SetGLES2Interface(context_provider_->TestContextGL());
     context_provider_->BindToCurrentThread();
   }
   std::unique_ptr<GpuImageDecodeCache> CreateCache() {
diff --git a/cc/tiles/tile_manager.cc b/cc/tiles/tile_manager.cc
index 007fff3b..8f85cb7 100644
--- a/cc/tiles/tile_manager.cc
+++ b/cc/tiles/tile_manager.cc
@@ -884,11 +884,17 @@
     const gfx::ColorSpace& raster_color_space,
     std::vector<DrawImage>* sync_decoded_images,
     std::vector<PaintImage>* checkered_images,
+    const gfx::Rect* invalidated_rect,
     base::flat_map<PaintImage::Id, size_t>* image_to_frame_index) {
   Tile* tile = prioritized_tile.tile();
   std::vector<const DrawImage*> images_in_tile;
-  prioritized_tile.raster_source()->GetDiscardableImagesInRect(
-      tile->enclosing_layer_rect(), &images_in_tile);
+  gfx::Rect enclosing_rect = tile->enclosing_layer_rect();
+  if (invalidated_rect) {
+    enclosing_rect = ToEnclosingRect(
+        tile->raster_transform().InverseMapRect(gfx::RectF(*invalidated_rect)));
+  }
+  prioritized_tile.raster_source()->GetDiscardableImagesInRect(enclosing_rect,
+                                                               &images_in_tile);
   WhichTree tree = tile->tiling()->tree();
 
   for (const auto* original_draw_image : images_in_tile) {
@@ -1016,7 +1022,8 @@
     std::vector<DrawImage> sync_decoded_images;
     std::vector<PaintImage> checkered_images;
     PartitionImagesForCheckering(prioritized_tile, raster_color_space,
-                                 &sync_decoded_images, &checkered_images);
+                                 &sync_decoded_images, &checkered_images,
+                                 nullptr);
 
     // Add the sync decoded images to |new_locked_images| so they can be added
     // to the task graph.
@@ -1121,9 +1128,11 @@
         &invalidated_rect);
   }
 
+  bool partial_tile_decode = false;
   if (resource) {
     resource_content_id = tile->invalidated_id();
     DCHECK_EQ(DetermineResourceFormat(tile), resource->format());
+    partial_tile_decode = true;
   } else {
     resource = resource_pool_->AcquireResource(tile->desired_texture_size(),
                                                DetermineResourceFormat(tile),
@@ -1148,9 +1157,10 @@
   base::flat_map<PaintImage::Id, size_t> image_id_to_current_frame_index;
   if (!skip_images) {
     std::vector<PaintImage> checkered_images;
-    PartitionImagesForCheckering(prioritized_tile, color_space,
-                                 &sync_decoded_images, &checkered_images,
-                                 &image_id_to_current_frame_index);
+    PartitionImagesForCheckering(
+        prioritized_tile, color_space, &sync_decoded_images, &checkered_images,
+        partial_tile_decode ? &invalidated_rect : nullptr,
+        &image_id_to_current_frame_index);
     for (const auto& image : checkered_images) {
       DCHECK(!image.ShouldAnimate());
 
diff --git a/cc/tiles/tile_manager.h b/cc/tiles/tile_manager.h
index 58de5f05..1f5bef07 100644
--- a/cc/tiles/tile_manager.h
+++ b/cc/tiles/tile_manager.h
@@ -272,6 +272,10 @@
     return checker_image_tracker_;
   }
 
+  const std::vector<DrawImage>& decode_tasks_for_testing(Tile::Id id) {
+    return scheduled_draw_images_[id];
+  }
+
  protected:
   friend class Tile;
   // Must be called by tile during destruction.
@@ -365,6 +369,7 @@
       const gfx::ColorSpace& raster_color_space,
       std::vector<DrawImage>* sync_decoded_images,
       std::vector<PaintImage>* checkered_images,
+      const gfx::Rect* invalidated_rect,
       base::flat_map<PaintImage::Id, size_t>* image_to_frame_index = nullptr);
   void AddCheckeredImagesToDecodeQueue(
       const PrioritizedTile& prioritized_tile,
diff --git a/cc/tiles/tile_manager_unittest.cc b/cc/tiles/tile_manager_unittest.cc
index 7c31968..47ff044 100644
--- a/cc/tiles/tile_manager_unittest.cc
+++ b/cc/tiles/tile_manager_unittest.cc
@@ -1934,7 +1934,6 @@
   host_impl->CreatePendingTree();
   LayerTreeImpl* pending_tree = host_impl->pending_tree();
 
-  // Steal from the recycled tree.
   std::unique_ptr<FakePictureLayerImpl> pending_layer =
       FakePictureLayerImpl::CreateWithRasterSource(pending_tree, kLayerId,
                                                    pending_raster_source);
@@ -1964,12 +1963,113 @@
   host_impl = nullptr;
 }
 
+void RunPartialTileDecodeCheck(std::unique_ptr<LayerTreeHostImpl> host_impl,
+                               bool partial_raster_enabled) {
+  // Pick arbitrary IDs - they don't really matter as long as they're constant.
+  const int kLayerId = 7;
+  const uint64_t kInvalidatedId = 43;
+  const uint64_t kExpectedId = partial_raster_enabled ? kInvalidatedId : 0u;
+  const gfx::Size kTileSize(400, 400);
+
+  host_impl->tile_manager()->SetTileTaskManagerForTesting(
+      std::make_unique<FakeTileTaskManagerImpl>());
+
+  // Create a VerifyResourceContentIdTileTaskManager to ensure that the
+  // raster task we see is created with |kExpectedId|.
+  VerifyResourceContentIdRasterBufferProvider raster_buffer_provider(
+      kExpectedId);
+  host_impl->tile_manager()->SetRasterBufferProviderForTesting(
+      &raster_buffer_provider);
+
+  // Ensure there's a resource with our |kInvalidatedId| in the resource pool.
+  auto* resource = host_impl->resource_pool()->AcquireResource(
+      kTileSize, viz::RGBA_8888, gfx::ColorSpace());
+  host_impl->resource_pool()->OnContentReplaced(resource->id(), kInvalidatedId);
+  host_impl->resource_pool()->ReleaseResource(resource);
+  host_impl->resource_pool()->CheckBusyResources();
+
+  const gfx::Size layer_bounds(500, 500);
+
+  std::unique_ptr<FakeRecordingSource> recording_source =
+      FakeRecordingSource::CreateFilledRecordingSource(layer_bounds);
+  recording_source->set_fill_with_nonsolid_color(true);
+
+  int dimension = 250;
+  PaintImage image1 =
+      CreateDiscardablePaintImage(gfx::Size(dimension, dimension));
+  PaintImage image2 =
+      CreateDiscardablePaintImage(gfx::Size(dimension, dimension));
+  PaintImage image3 =
+      CreateDiscardablePaintImage(gfx::Size(dimension, dimension));
+  PaintImage image4 =
+      CreateDiscardablePaintImage(gfx::Size(dimension, dimension));
+  recording_source->add_draw_image(image1, gfx::Point(0, 0));
+  recording_source->add_draw_image(image2, gfx::Point(300, 0));
+  recording_source->add_draw_image(image3, gfx::Point(0, 300));
+  recording_source->add_draw_image(image4, gfx::Point(300, 300));
+
+  recording_source->Rerecord();
+
+  scoped_refptr<FakeRasterSource> pending_raster_source =
+      FakeRasterSource::CreateFromRecordingSource(recording_source.get());
+
+  host_impl->CreatePendingTree();
+  LayerTreeImpl* pending_tree = host_impl->pending_tree();
+
+  // Steal from the recycled tree.
+  std::unique_ptr<FakePictureLayerImpl> pending_layer =
+      FakePictureLayerImpl::CreateWithRasterSource(pending_tree, kLayerId,
+                                                   pending_raster_source);
+  pending_layer->SetDrawsContent(true);
+
+  // The bounds() just mirror the raster source size.
+  pending_layer->SetBounds(pending_layer->raster_source()->GetSize());
+  pending_tree->SetRootLayerForTesting(std::move(pending_layer));
+
+  // Add tilings/tiles for the layer.
+  host_impl->pending_tree()->BuildLayerListAndPropertyTreesForTesting();
+  host_impl->pending_tree()->UpdateDrawProperties();
+
+  // Build the raster queue and invalidate the top tile if partial raster is
+  // enabled.
+  std::unique_ptr<RasterTilePriorityQueue> queue(host_impl->BuildRasterQueue(
+      SAME_PRIORITY_FOR_BOTH_TREES, RasterTilePriorityQueue::Type::ALL));
+  ASSERT_FALSE(queue->IsEmpty());
+  Tile* tile = queue->Top().tile();
+  if (partial_raster_enabled)
+    tile->SetInvalidated(gfx::Rect(200, 200), kInvalidatedId);
+
+  // PrepareTiles to schedule tasks. Due to the
+  // VerifyPreviousContentRasterBufferProvider, these tasks will verified and
+  // cancelled.
+  host_impl->tile_manager()->PrepareTiles(host_impl->global_tile_state());
+
+  // Tile will have 1 dependent decode task if we decode images only in the
+  // invalidated rect. Otherwise it will have 4.
+  EXPECT_EQ(
+      host_impl->tile_manager()->decode_tasks_for_testing(tile->id()).size(),
+      partial_raster_enabled ? 1u : 4u);
+
+  // Free our host_impl before the verifying_task_manager we passed it, as it
+  // will use that class in clean up.
+  host_impl = nullptr;
+}
+
 // Ensures that the tile manager successfully reuses tiles when partial
 // raster is enabled.
 TEST_F(PartialRasterTileManagerTest, PartialRasterSuccessfullyEnabled) {
   RunPartialRasterCheck(TakeHostImpl(), true /* partial_raster_enabled */);
 }
 
+TEST_F(PartialRasterTileManagerTest, PartialTileImageDecode) {
+  RunPartialTileDecodeCheck(TakeHostImpl(), true /* partial_raster_enabled */);
+}
+
+TEST_F(PartialRasterTileManagerTest, CompleteTileImageDecode) {
+  RunPartialTileDecodeCheck(TakeHostImpl(),
+                            false /* partial_raster_disabled */);
+}
+
 // Ensures that the tile manager does not attempt to reuse tiles when partial
 // raster is disabled.
 TEST_F(TileManagerTest, PartialRasterSuccessfullyDisabled) {
diff --git a/cc/trees/layer_tree_host.cc b/cc/trees/layer_tree_host.cc
index 90058b8..a93bc46 100644
--- a/cc/trees/layer_tree_host.cc
+++ b/cc/trees/layer_tree_host.cc
@@ -55,6 +55,8 @@
 #include "cc/trees/swap_promise_manager.h"
 #include "cc/trees/transform_node.h"
 #include "cc/trees/tree_synchronizer.h"
+#include "cc/trees/ukm_manager.h"
+#include "services/metrics/public/cpp/ukm_recorder.h"
 #include "ui/gfx/geometry/size_conversions.h"
 #include "ui/gfx/geometry/vector2d_conversions.h"
 
@@ -75,6 +77,7 @@
   DCHECK(params->main_task_runner.get());
   DCHECK(impl_task_runner.get());
   DCHECK(params->settings);
+  DCHECK(params->ukm_recorder_factory);
   std::unique_ptr<LayerTreeHost> layer_tree_host(
       new LayerTreeHost(params, CompositorMode::THREADED));
   layer_tree_host->InitializeThreaded(params->main_task_runner,
@@ -97,6 +100,7 @@
 LayerTreeHost::LayerTreeHost(InitParams* params, CompositorMode mode)
     : micro_benchmark_controller_(this),
       image_worker_task_runner_(params->image_worker_task_runner),
+      ukm_recorder_factory_(std::move(params->ukm_recorder_factory)),
       compositor_mode_(mode),
       ui_resource_manager_(std::make_unique<UIResourceManager>()),
       client_(params->client),
@@ -485,6 +489,11 @@
       settings_, client, task_runner_provider_.get(),
       rendering_stats_instrumentation_.get(), task_graph_runner_,
       std::move(mutator_host_impl), id_, std::move(image_worker_task_runner_));
+  if (ukm_recorder_factory_) {
+    host_impl->InitializeUkm(ukm_recorder_factory_->CreateRecorder());
+    ukm_recorder_factory_.reset();
+  }
+
   host_impl->SetHasGpuRasterizationTrigger(has_gpu_rasterization_trigger_);
   host_impl->SetContentHasSlowPaths(content_has_slow_paths_);
   host_impl->SetContentHasNonAAPaint(content_has_non_aa_paint_);
@@ -1515,4 +1524,8 @@
   proxy_->RequestBeginMainFrameNotExpected(new_state);
 }
 
+void LayerTreeHost::SetURLForUkm(const GURL& url) {
+  proxy_->SetURLForUkm(url);
+}
+
 }  // namespace cc
diff --git a/cc/trees/layer_tree_host.h b/cc/trees/layer_tree_host.h
index 6e38ab76..561f95c6 100644
--- a/cc/trees/layer_tree_host.h
+++ b/cc/trees/layer_tree_host.h
@@ -45,6 +45,7 @@
 #include "components/viz/common/resources/resource_format.h"
 #include "components/viz/common/surfaces/surface_reference_owner.h"
 #include "components/viz/common/surfaces/surface_sequence_generator.h"
+#include "services/metrics/public/cpp/ukm_source_id.h"
 #include "third_party/skia/include/core/SkColor.h"
 #include "ui/gfx/geometry/rect.h"
 
@@ -63,6 +64,7 @@
 struct ScrollBoundaryBehavior;
 class TaskGraphRunner;
 class UIResourceManager;
+class UkmRecorderFactory;
 struct RenderingStats;
 struct ScrollAndScaleSet;
 
@@ -81,6 +83,8 @@
     // raster worker threads.
     scoped_refptr<base::SequencedTaskRunner> image_worker_task_runner;
 
+    std::unique_ptr<UkmRecorderFactory> ukm_recorder_factory;
+
     InitParams();
     ~InitParams();
   };
@@ -502,6 +506,8 @@
 
   float recording_scale_factor() const { return recording_scale_factor_; }
 
+  void SetURLForUkm(const GURL& url);
+
  protected:
   LayerTreeHost(InitParams* params, CompositorMode mode);
 
@@ -532,6 +538,7 @@
   base::WeakPtr<InputHandler> input_handler_weak_ptr_;
 
   scoped_refptr<base::SequencedTaskRunner> image_worker_task_runner_;
+  std::unique_ptr<UkmRecorderFactory> ukm_recorder_factory_;
 
  private:
   friend class LayerTreeHostSerializationTest;
diff --git a/cc/trees/layer_tree_host_impl.cc b/cc/trees/layer_tree_host_impl.cc
index f20a8a9..105b5d7 100644
--- a/cc/trees/layer_tree_host_impl.cc
+++ b/cc/trees/layer_tree_host_impl.cc
@@ -87,6 +87,7 @@
 #include "gpu/GLES2/gl2extchromium.h"
 #include "gpu/command_buffer/client/context_support.h"
 #include "gpu/command_buffer/client/gles2_interface.h"
+#include "services/metrics/public/cpp/ukm_recorder.h"
 #include "third_party/skia/include/gpu/GrContext.h"
 #include "ui/gfx/geometry/point_conversions.h"
 #include "ui/gfx/geometry/rect_conversions.h"
@@ -917,6 +918,7 @@
   int num_incomplete_tiles = 0;
   int64_t checkerboarded_no_recording_content_area = 0;
   int64_t checkerboarded_needs_raster_content_area = 0;
+  int64_t total_visible_area = 0;
   bool have_copy_request =
       active_tree()->property_trees()->effect_tree.HasCopyRequests();
   bool have_missing_animated_tiles = false;
@@ -980,6 +982,7 @@
           append_quads_data.checkerboarded_no_recording_content_area;
       checkerboarded_needs_raster_content_area +=
           append_quads_data.checkerboarded_needs_raster_content_area;
+      total_visible_area += append_quads_data.visible_layer_area;
       if (append_quads_data.num_missing_tiles > 0) {
         have_missing_animated_tiles |=
             layer->screen_space_transform_is_animating();
@@ -1044,6 +1047,13 @@
     active_tree()->set_needs_update_draw_properties();
   }
 
+  if (ukm_manager_) {
+    ukm_manager_->AddCheckerboardStatsForFrame(
+        checkerboarded_no_recording_content_area +
+            checkerboarded_needs_raster_content_area,
+        num_missing_tiles, total_visible_area);
+  }
+
   if (active_tree_->has_ever_been_drawn()) {
     UMA_HISTOGRAM_COUNTS_100(
         "Compositing.RenderPass.AppendQuadData.NumMissingTiles",
@@ -4574,4 +4584,10 @@
   client_->NeedsImplSideInvalidation(needs_first_draw_on_activation);
 }
 
+void LayerTreeHostImpl::InitializeUkm(
+    std::unique_ptr<ukm::UkmRecorder> recorder) {
+  DCHECK(!ukm_manager_);
+  ukm_manager_ = std::make_unique<UkmManager>(std::move(recorder));
+}
+
 }  // namespace cc
diff --git a/cc/trees/layer_tree_host_impl.h b/cc/trees/layer_tree_host_impl.h
index 996698bc..ed2c071 100644
--- a/cc/trees/layer_tree_host_impl.h
+++ b/cc/trees/layer_tree_host_impl.h
@@ -40,6 +40,7 @@
 #include "cc/trees/managed_memory_policy.h"
 #include "cc/trees/mutator_host_client.h"
 #include "cc/trees/task_runner_provider.h"
+#include "cc/trees/ukm_manager.h"
 #include "components/viz/common/frame_sinks/begin_frame_args.h"
 #include "components/viz/common/gpu/context_cache_controller.h"
 #include "components/viz/common/quads/render_pass.h"
@@ -636,6 +637,11 @@
       base::flat_map<PaintImage::Id, PaintImage::DecodingMode>
           decoding_mode_map);
 
+  void InitializeUkm(std::unique_ptr<ukm::UkmRecorder> recorder);
+  UkmManager* ukm_manager() { return ukm_manager_.get(); }
+
+  void RenewTreePriorityForTesting() { client_->RenewTreePriority(); }
+
  protected:
   LayerTreeHostImpl(
       const LayerTreeSettings& settings,
@@ -928,6 +934,8 @@
 
   base::Optional<ImageAnimationController> image_animation_controller_;
 
+  std::unique_ptr<UkmManager> ukm_manager_;
+
   DISALLOW_COPY_AND_ASSIGN(LayerTreeHostImpl);
 };
 
diff --git a/cc/trees/layer_tree_host_impl_unittest.cc b/cc/trees/layer_tree_host_impl_unittest.cc
index 2dff6350..3025274b4 100644
--- a/cc/trees/layer_tree_host_impl_unittest.cc
+++ b/cc/trees/layer_tree_host_impl_unittest.cc
@@ -9080,7 +9080,9 @@
   std::unique_ptr<TestWebGraphicsContext3D> context =
       TestWebGraphicsContext3D::Create();
   TestWebGraphicsContext3D* context3d = context.get();
-  CreateHostImpl(DefaultSettings(), FakeLayerTreeFrameSink::Create3d());
+  context3d->set_support_compressed_texture_etc1(true);
+  CreateHostImpl(DefaultSettings(),
+                 FakeLayerTreeFrameSink::Create3d(std::move(context)));
 
   EXPECT_EQ(0u, context3d->NumTextures());
 
diff --git a/cc/trees/layer_tree_host_pixeltest_blending.cc b/cc/trees/layer_tree_host_pixeltest_blending.cc
index d2585931..b6769a03 100644
--- a/cc/trees/layer_tree_host_pixeltest_blending.cc
+++ b/cc/trees/layer_tree_host_pixeltest_blending.cc
@@ -290,7 +290,7 @@
 };
 
 TEST_F(LayerTreeHostBlendingPixelTest, BlendingWithRoot_GL) {
-  RunBlendingWithRootPixelTestType(GL_ZERO_COPY_RECT_DRAW);
+  RunBlendingWithRootPixelTestType(ZERO_COPY);
 }
 
 TEST_F(LayerTreeHostBlendingPixelTest, BlendingWithRoot_Software) {
@@ -302,7 +302,7 @@
   const int kLaneHeight = kLaneWidth;
   const int kRootWidth = (kBlendModesCount + 2) * kLaneWidth;
   const int kRootHeight = 2 * kLaneWidth + kLaneHeight;
-  InitializeFromTestCase(GL_ZERO_COPY_RECT_DRAW);
+  InitializeFromTestCase(ZERO_COPY);
 
   scoped_refptr<SolidColorLayer> background =
       CreateSolidColorLayer(gfx::Rect(kRootWidth, kRootHeight), kCSSOrange);
@@ -327,7 +327,7 @@
 }
 
 TEST_F(LayerTreeHostBlendingPixelTest, BlendingWithTransparent_GL) {
-  RunBlendingWithTransparentPixelTestType(GL_ZERO_COPY_RECT_DRAW);
+  RunBlendingWithTransparentPixelTestType(ZERO_COPY);
 }
 
 TEST_F(LayerTreeHostBlendingPixelTest, BlendingWithTransparent_Software) {
@@ -336,7 +336,7 @@
 
 // Tests for render passes
 TEST_F(LayerTreeHostBlendingPixelTest, BlendingWithRenderPass_GL) {
-  RunBlendingWithRenderPass(GL_ZERO_COPY_RECT_DRAW,
+  RunBlendingWithRenderPass(ZERO_COPY,
                             FILE_PATH_LITERAL("blending_render_pass.png"), 0);
 }
 
@@ -346,7 +346,7 @@
 }
 
 TEST_F(LayerTreeHostBlendingPixelTest, BlendingWithRenderPassAA_GL) {
-  RunBlendingWithRenderPass(GL_ZERO_COPY_RECT_DRAW,
+  RunBlendingWithRenderPass(ZERO_COPY,
                             FILE_PATH_LITERAL("blending_render_pass.png"),
                             kUseAntialiasing);
 }
@@ -358,9 +358,8 @@
 }
 
 TEST_F(LayerTreeHostBlendingPixelTest, BlendingWithRenderPassWithMask_GL) {
-  RunBlendingWithRenderPass(GL_ZERO_COPY_RECT_DRAW,
-                            FILE_PATH_LITERAL("blending_render_pass_mask.png"),
-                            kUseMasks);
+  RunBlendingWithRenderPass(
+      ZERO_COPY, FILE_PATH_LITERAL("blending_render_pass_mask.png"), kUseMasks);
 }
 
 TEST_F(LayerTreeHostBlendingPixelTest,
@@ -370,7 +369,7 @@
 }
 
 TEST_F(LayerTreeHostBlendingPixelTest, BlendingWithRenderPassWithMaskAA_GL) {
-  RunBlendingWithRenderPass(GL_ZERO_COPY_RECT_DRAW,
+  RunBlendingWithRenderPass(ZERO_COPY,
                             FILE_PATH_LITERAL("blending_render_pass_mask.png"),
                             kUseMasks | kUseAntialiasing);
 }
@@ -383,7 +382,7 @@
 }
 
 TEST_F(LayerTreeHostBlendingPixelTest, BlendingWithRenderPassColorMatrix_GL) {
-  RunBlendingWithRenderPass(GL_ZERO_COPY_RECT_DRAW,
+  RunBlendingWithRenderPass(ZERO_COPY,
                             FILE_PATH_LITERAL("blending_render_pass.png"),
                             kUseColorMatrix);
 }
@@ -395,7 +394,7 @@
 }
 
 TEST_F(LayerTreeHostBlendingPixelTest, BlendingWithRenderPassColorMatrixAA_GL) {
-  RunBlendingWithRenderPass(GL_ZERO_COPY_RECT_DRAW,
+  RunBlendingWithRenderPass(ZERO_COPY,
                             FILE_PATH_LITERAL("blending_render_pass.png"),
                             kUseAntialiasing | kUseColorMatrix);
 }
@@ -409,7 +408,7 @@
 
 TEST_F(LayerTreeHostBlendingPixelTest,
        BlendingWithRenderPassWithMaskColorMatrix_GL) {
-  RunBlendingWithRenderPass(GL_ZERO_COPY_RECT_DRAW,
+  RunBlendingWithRenderPass(ZERO_COPY,
                             FILE_PATH_LITERAL("blending_render_pass_mask.png"),
                             kUseMasks | kUseColorMatrix);
 }
@@ -423,7 +422,7 @@
 
 TEST_F(LayerTreeHostBlendingPixelTest,
        BlendingWithRenderPassWithMaskColorMatrixAA_GL) {
-  RunBlendingWithRenderPass(GL_ZERO_COPY_RECT_DRAW,
+  RunBlendingWithRenderPass(ZERO_COPY,
                             FILE_PATH_LITERAL("blending_render_pass_mask.png"),
                             kUseMasks | kUseAntialiasing | kUseColorMatrix);
 }
@@ -437,69 +436,68 @@
 
 // Tests for render passes forcing shaders for all the blend modes.
 TEST_F(LayerTreeHostBlendingPixelTest, BlendingWithRenderPassShaders_GL) {
-  RunBlendingWithRenderPass(GL_ZERO_COPY_RECT_DRAW,
-                            FILE_PATH_LITERAL("blending_render_pass.png"),
-                            kForceShaders);
+  RunBlendingWithRenderPass(
+      ZERO_COPY, FILE_PATH_LITERAL("blending_render_pass.png"), kForceShaders);
 }
 
 TEST_F(LayerTreeHostBlendingPixelTest, BlendingWithRenderPassShadersAA_GL) {
-  RunBlendingWithRenderPass(GL_ZERO_COPY_RECT_DRAW,
+  RunBlendingWithRenderPass(ZERO_COPY,
                             FILE_PATH_LITERAL("blending_render_pass.png"),
                             kUseAntialiasing | kForceShaders);
 }
 
 TEST_F(LayerTreeHostBlendingPixelTest,
        BlendingWithRenderPassShadersWithMask_GL) {
-  RunBlendingWithRenderPass(GL_ZERO_COPY_RECT_DRAW,
+  RunBlendingWithRenderPass(ZERO_COPY,
                             FILE_PATH_LITERAL("blending_render_pass_mask.png"),
                             kUseMasks | kForceShaders);
 }
 
 TEST_F(LayerTreeHostBlendingPixelTest,
        BlendingWithRenderPassShadersWithMask_GL_TextureRect) {
-  RunBlendingWithRenderPass(GL_ZERO_COPY_RECT_DRAW,
+  RunBlendingWithRenderPass(ZERO_COPY,
                             FILE_PATH_LITERAL("blending_render_pass_mask.png"),
                             kUseMasks | kForceShaders);
 }
 
 TEST_F(LayerTreeHostBlendingPixelTest,
        BlendingWithRenderPassShadersWithMaskAA_GL) {
-  RunBlendingWithRenderPass(GL_ZERO_COPY_RECT_DRAW,
+  RunBlendingWithRenderPass(ZERO_COPY,
                             FILE_PATH_LITERAL("blending_render_pass_mask.png"),
                             kUseMasks | kUseAntialiasing | kForceShaders);
 }
 
 TEST_F(LayerTreeHostBlendingPixelTest,
        BlendingWithRenderPassShadersWithMaskAA_GL_TextureRect) {
-  RunBlendingWithRenderPass(GL_ZERO_COPY_RECT_DRAW,
+  RunBlendingWithRenderPass(ZERO_COPY,
                             FILE_PATH_LITERAL("blending_render_pass_mask.png"),
                             kUseMasks | kUseAntialiasing | kForceShaders);
 }
 
 TEST_F(LayerTreeHostBlendingPixelTest,
        BlendingWithRenderPassShadersColorMatrix_GL) {
-  RunBlendingWithRenderPass(GL_ZERO_COPY_RECT_DRAW,
+  RunBlendingWithRenderPass(ZERO_COPY,
                             FILE_PATH_LITERAL("blending_render_pass.png"),
                             kUseColorMatrix | kForceShaders);
 }
 
 TEST_F(LayerTreeHostBlendingPixelTest,
        BlendingWithRenderPassShadersColorMatrixAA_GL) {
-  RunBlendingWithRenderPass(GL_ZERO_COPY_RECT_DRAW,
+  RunBlendingWithRenderPass(ZERO_COPY,
                             FILE_PATH_LITERAL("blending_render_pass.png"),
                             kUseAntialiasing | kUseColorMatrix | kForceShaders);
 }
 
 TEST_F(LayerTreeHostBlendingPixelTest,
        BlendingWithRenderPassShadersWithMaskColorMatrix_GL) {
-  RunBlendingWithRenderPass(GL_ZERO_COPY_RECT_DRAW,
+  RunBlendingWithRenderPass(ZERO_COPY,
                             FILE_PATH_LITERAL("blending_render_pass_mask.png"),
                             kUseMasks | kUseColorMatrix | kForceShaders);
 }
 
 TEST_F(LayerTreeHostBlendingPixelTest,
        BlendingWithRenderPassShadersWithMaskColorMatrix_GL_TextureRect) {
-  RunBlendingWithRenderPass(GL_ZERO_COPY_RECT_DRAW,
+  RunBlendingWithRenderPass(ZERO_COPY,
                             FILE_PATH_LITERAL("blending_render_pass_mask.png"),
                             kUseMasks | kUseColorMatrix | kForceShaders);
 }
@@ -507,8 +505,7 @@
 TEST_F(LayerTreeHostBlendingPixelTest,
        BlendingWithRenderPassShadersWithMaskColorMatrixAA_GL) {
   RunBlendingWithRenderPass(
-      GL_ZERO_COPY_RECT_DRAW,
-      FILE_PATH_LITERAL("blending_render_pass_mask.png"),
+      ZERO_COPY, FILE_PATH_LITERAL("blending_render_pass_mask.png"),
       kUseMasks | kUseAntialiasing | kUseColorMatrix | kForceShaders);
 }
 
diff --git a/cc/trees/layer_tree_host_pixeltest_masks.cc b/cc/trees/layer_tree_host_pixeltest_masks.cc
index 7d0b8f16..de2ebdf0 100644
--- a/cc/trees/layer_tree_host_pixeltest_masks.cc
+++ b/cc/trees/layer_tree_host_pixeltest_masks.cc
@@ -272,14 +272,7 @@
     PixelResourceTest,
     LayerTreeHostMasksForBackgroundFiltersPixelTest,
     ::testing::Combine(
-        ::testing::Values(SOFTWARE,
-                          GL_GPU_RASTER_2D_DRAW,
-                          GL_ONE_COPY_2D_STAGING_2D_DRAW,
-                          GL_ONE_COPY_RECT_STAGING_2D_DRAW,
-                          GL_ONE_COPY_EXTERNAL_STAGING_2D_DRAW,
-                          GL_ZERO_COPY_2D_DRAW,
-                          GL_ZERO_COPY_RECT_DRAW,
-                          GL_ZERO_COPY_EXTERNAL_DRAW),
+        ::testing::Values(SOFTWARE, GPU, ONE_COPY, ZERO_COPY),
         ::testing::Values(Layer::LayerMaskType::SINGLE_TEXTURE_MASK,
                           Layer::LayerMaskType::MULTI_TEXTURE_MASK)));
 
@@ -412,7 +405,7 @@
  public:
   LayerTreeHostMaskAsBlendingPixelTest()
       : LayerTreeHostPixelResourceTest(
-            GetParam() ? GL_ZERO_COPY_RECT_DRAW : SOFTWARE,
+            GetParam() ? ZERO_COPY : SOFTWARE,
             Layer::LayerMaskType::SINGLE_TEXTURE_MASK),
         use_antialiasing_(GetParam() == 2 || GetParam() == 4),
         force_shaders_(GetParam() == 3 || GetParam() == 4) {
diff --git a/cc/trees/layer_tree_host_unittest.cc b/cc/trees/layer_tree_host_unittest.cc
index 33045f4..2ddb18a0 100644
--- a/cc/trees/layer_tree_host_unittest.cc
+++ b/cc/trees/layer_tree_host_unittest.cc
@@ -57,6 +57,7 @@
 #include "cc/trees/swap_promise.h"
 #include "cc/trees/swap_promise_manager.h"
 #include "cc/trees/transform_node.h"
+#include "components/ukm/test_ukm_recorder.h"
 #include "components/viz/common/frame_sinks/begin_frame_args.h"
 #include "components/viz/common/frame_sinks/copy_output_request.h"
 #include "components/viz/common/frame_sinks/copy_output_result.h"
@@ -83,6 +84,10 @@
 
 namespace cc {
 namespace {
+const char kUserInteraction[] = "Compositor.UserInteraction";
+const char kCheckerboardArea[] = "CheckerboardedContentArea";
+const char kCheckerboardAreaRatio[] = "CheckerboardedContentAreaRatio";
+const char kMissingTiles[] = "NumMissingTiles";
 
 class LayerTreeHostTest : public LayerTreeTest {};
 
@@ -8184,5 +8189,70 @@
 };
 
 MULTI_THREAD_TEST_F(LayerTreeHostTestImageDecodingHints);
+
+class LayerTreeHostTestCheckerboardUkm : public LayerTreeHostTest {
+ public:
+  LayerTreeHostTestCheckerboardUkm() : url_(GURL("chrome://test")) {}
+
+  void BeginTest() override {
+    PostSetNeedsCommitToMainThread();
+    layer_tree_host()->SetURLForUkm(url_);
+  }
+
+  void SetupTree() override {
+    gfx::Size layer_size(100, 100);
+    content_layer_client_.set_bounds(layer_size);
+    content_layer_client_.set_fill_with_nonsolid_color(true);
+    layer_tree_host()->SetRootLayer(
+        FakePictureLayer::Create(&content_layer_client_));
+    layer_tree_host()->root_layer()->SetBounds(layer_size);
+    LayerTreeTest::SetupTree();
+  }
+
+  void DidActivateTreeOnThread(LayerTreeHostImpl* impl) override {
+    if (impl->active_tree()->source_frame_number() != 0)
+      return;
+
+    // We have an active tree. Start a pinch gesture so we start recording
+    // stats.
+    impl->PinchGestureBegin();
+  }
+
+  void DrawLayersOnThread(LayerTreeHostImpl* impl) override {
+    if (!impl->pinch_gesture_active())
+      return;
+
+    // We just drew a frame, stats for it should have been recorded. End the
+    // gesture so they are flushed to the recorder.
+    impl->PinchGestureEnd();
+
+    // RenewTreePriority will run when the smoothness expiration timer fires.
+    // Synthetically do it here so the UkmManager is notified.
+    impl->RenewTreePriorityForTesting();
+
+    auto* recorder = static_cast<ukm::TestUkmRecorder*>(
+        impl->ukm_manager()->recorder_for_testing());
+    auto* source = recorder->GetSourceForUrl(url_);
+    ASSERT_TRUE(source);
+
+    EXPECT_EQ(recorder->entries_count(), 1u);
+    recorder->ExpectMetric(*source, kUserInteraction, kCheckerboardArea, 0);
+    recorder->ExpectMetric(*source, kUserInteraction, kMissingTiles, 0);
+    recorder->ExpectMetric(*source, kUserInteraction, kCheckerboardAreaRatio,
+                           0);
+
+    EndTest();
+  }
+
+  void AfterTest() override {}
+
+ private:
+  const GURL url_;
+  FakeContentLayerClient content_layer_client_;
+};
+
+// Only multi-thread mode needs to record UKMs.
+MULTI_THREAD_TEST_F(LayerTreeHostTestCheckerboardUkm);
+
 }  // namespace
 }  // namespace cc
diff --git a/cc/trees/layer_tree_host_unittest_scroll.cc b/cc/trees/layer_tree_host_unittest_scroll.cc
index 409d991c..8298948 100644
--- a/cc/trees/layer_tree_host_unittest_scroll.cc
+++ b/cc/trees/layer_tree_host_unittest_scroll.cc
@@ -23,6 +23,7 @@
 #include "cc/test/geometry_test_utils.h"
 #include "cc/test/layer_tree_test.h"
 #include "cc/test/test_task_graph_runner.h"
+#include "cc/test/test_ukm_recorder_factory.h"
 #include "cc/trees/layer_tree_host_common.h"
 #include "cc/trees/layer_tree_impl.h"
 #include "cc/trees/scroll_node.h"
@@ -1361,6 +1362,7 @@
   params.settings = &settings;
   params.main_task_runner = base::ThreadTaskRunnerHandle::Get();
   params.mutator_host = animation_host.get();
+  params.ukm_recorder_factory = std::make_unique<TestUkmRecorderFactory>();
   std::unique_ptr<LayerTreeHost> layer_tree_host =
       LayerTreeHost::CreateThreaded(impl_thread.task_runner(), &params);
 
diff --git a/cc/trees/layer_tree_impl.cc b/cc/trees/layer_tree_impl.cc
index 29ca64b7..5566a3d 100644
--- a/cc/trees/layer_tree_impl.cc
+++ b/cc/trees/layer_tree_impl.cc
@@ -387,7 +387,7 @@
 
   target_tree->SetPropertyTrees(&property_trees_);
 
-  ScrollNode* scrolling_node = nullptr;
+  const ScrollNode* scrolling_node = nullptr;
   if (scrolling_element_id) {
     auto& scroll_tree = target_tree->property_trees()->scroll_tree;
     scrolling_node = scroll_tree.FindNodeFromElementId(scrolling_element_id);
@@ -623,7 +623,7 @@
   return last_scrolled_scroll_node_index_;
 }
 
-void LayerTreeImpl::SetCurrentlyScrollingNode(ScrollNode* node) {
+void LayerTreeImpl::SetCurrentlyScrollingNode(const ScrollNode* node) {
   if (node)
     last_scrolled_scroll_node_index_ = node->id;
 
diff --git a/cc/trees/layer_tree_impl.h b/cc/trees/layer_tree_impl.h
index cedd995..ee0eb73 100644
--- a/cc/trees/layer_tree_impl.h
+++ b/cc/trees/layer_tree_impl.h
@@ -216,7 +216,7 @@
   ScrollNode* CurrentlyScrollingNode();
   const ScrollNode* CurrentlyScrollingNode() const;
   int LastScrolledScrollNodeIndex() const;
-  void SetCurrentlyScrollingNode(ScrollNode* node);
+  void SetCurrentlyScrollingNode(const ScrollNode* node);
   void ClearCurrentlyScrollingNode();
 
   struct ViewportLayerIds {
diff --git a/cc/trees/property_tree.cc b/cc/trees/property_tree.cc
index b6a8513..f09843a 100644
--- a/cc/trees/property_tree.cc
+++ b/cc/trees/property_tree.cc
@@ -1193,7 +1193,7 @@
 }
 #endif
 
-ScrollNode* ScrollTree::FindNodeFromElementId(ElementId id) {
+const ScrollNode* ScrollTree::FindNodeFromElementId(ElementId id) const {
   auto iterator = property_trees()->element_id_to_scroll_node_index.find(id);
   if (iterator == property_trees()->element_id_to_scroll_node_index.end())
     return nullptr;
diff --git a/cc/trees/property_tree.h b/cc/trees/property_tree.h
index d89b0d6..bc9f67d 100644
--- a/cc/trees/property_tree.h
+++ b/cc/trees/property_tree.h
@@ -458,7 +458,7 @@
   void CopyCompleteTreeState(const ScrollTree& other);
 #endif
 
-  ScrollNode* FindNodeFromElementId(ElementId id);
+  const ScrollNode* FindNodeFromElementId(ElementId id) const;
 
  private:
   using ScrollOffsetMap = base::flat_map<ElementId, gfx::ScrollOffset>;
diff --git a/cc/trees/proxy.h b/cc/trees/proxy.h
index 35a6399..c68bdb56 100644
--- a/cc/trees/proxy.h
+++ b/cc/trees/proxy.h
@@ -17,6 +17,8 @@
 #include "cc/input/browser_controls_state.h"
 #include "cc/trees/task_runner_provider.h"
 #include "components/viz/common/frame_sinks/begin_frame_source.h"
+#include "services/metrics/public/cpp/ukm_source_id.h"
+#include "url/gurl.h"
 
 namespace gfx {
 class Rect;
@@ -74,6 +76,8 @@
 
   // Testing hooks
   virtual bool MainFrameWillHappenForTesting() = 0;
+
+  virtual void SetURLForUkm(const GURL& url) = 0;
 };
 
 }  // namespace cc
diff --git a/cc/trees/proxy_impl.cc b/cc/trees/proxy_impl.cc
index f143117501..bf3e8b3 100644
--- a/cc/trees/proxy_impl.cc
+++ b/cc/trees/proxy_impl.cc
@@ -28,6 +28,7 @@
 #include "components/viz/common/frame_sinks/delay_based_time_source.h"
 #include "components/viz/common/gpu/context_provider.h"
 #include "gpu/command_buffer/client/gles2_interface.h"
+#include "services/metrics/public/cpp/ukm_recorder.h"
 
 namespace cc {
 
@@ -402,12 +403,15 @@
 
 void ProxyImpl::RenewTreePriority() {
   DCHECK(IsImplThread());
-  bool smoothness_takes_priority = host_impl_->pinch_gesture_active() ||
-                                   host_impl_->page_scale_animation_active() ||
-                                   host_impl_->IsActivelyScrolling();
+  const bool user_interaction_in_progress =
+      host_impl_->pinch_gesture_active() ||
+      host_impl_->page_scale_animation_active() ||
+      host_impl_->IsActivelyScrolling();
+  host_impl_->ukm_manager()->SetUserInteractionInProgress(
+      user_interaction_in_progress);
 
   // Schedule expiration if smoothness currently takes priority.
-  if (smoothness_takes_priority)
+  if (user_interaction_in_progress)
     smoothness_priority_expiration_notifier_.Schedule();
 
   // We use the same priority for both trees by default.
@@ -718,4 +722,16 @@
   return task_runner_provider_->MainThreadTaskRunner();
 }
 
+void ProxyImpl::SetURLForUkm(const GURL& url) {
+  DCHECK(IsImplThread());
+  DCHECK(host_impl_->ukm_manager());
+  // The active tree might still be from content for the previous page when the
+  // recorder is updated here, since new content will be pushed with the next
+  // main frame. But we should only get a few impl frames wrong here in that
+  // case. Also, since checkerboard stats are only recorded with user
+  // interaction, it must be in progress when the navigation commits for this
+  // case to occur.
+  host_impl_->ukm_manager()->SetSourceURL(url);
+}
+
 }  // namespace cc
diff --git a/cc/trees/proxy_impl.h b/cc/trees/proxy_impl.h
index 916446b..40700e5 100644
--- a/cc/trees/proxy_impl.h
+++ b/cc/trees/proxy_impl.h
@@ -53,6 +53,7 @@
                                  LayerTreeHost* layer_tree_host,
                                  base::TimeTicks main_thread_start_time,
                                  bool hold_commit_for_activation);
+  void SetURLForUkm(const GURL& url);
 
   void MainFrameWillHappenOnImplForTesting(CompletionEvent* completion,
                                            bool* main_frame_will_happen);
diff --git a/cc/trees/proxy_main.cc b/cc/trees/proxy_main.cc
index 73bc8fbe..8245573 100644
--- a/cc/trees/proxy_main.cc
+++ b/cc/trees/proxy_main.cc
@@ -20,6 +20,7 @@
 #include "cc/trees/proxy_impl.h"
 #include "cc/trees/scoped_abort_remaining_swap_promises.h"
 #include "cc/trees/swap_promise.h"
+#include "services/metrics/public/cpp/ukm_recorder.h"
 
 namespace cc {
 
@@ -539,4 +540,11 @@
   return task_runner_provider_->ImplThreadTaskRunner();
 }
 
+void ProxyMain::SetURLForUkm(const GURL& url) {
+  DCHECK(IsMainThread());
+  ImplThreadTaskRunner()->PostTask(
+      FROM_HERE, base::BindOnce(&ProxyImpl::SetURLForUkm,
+                                base::Unretained(proxy_impl_.get()), url));
+}
+
 }  // namespace cc
diff --git a/cc/trees/proxy_main.h b/cc/trees/proxy_main.h
index 5007bb29..df55511 100644
--- a/cc/trees/proxy_main.h
+++ b/cc/trees/proxy_main.h
@@ -88,6 +88,7 @@
                                   BrowserControlsState current,
                                   bool animate) override;
   void RequestBeginMainFrameNotExpected(bool new_state) override;
+  void SetURLForUkm(const GURL& url) override;
 
   // Returns |true| if the request was actually sent, |false| if one was
   // already outstanding.
diff --git a/cc/trees/single_thread_proxy.h b/cc/trees/single_thread_proxy.h
index 12f988ba..cf14f11 100644
--- a/cc/trees/single_thread_proxy.h
+++ b/cc/trees/single_thread_proxy.h
@@ -57,6 +57,11 @@
   void SetMutator(std::unique_ptr<LayerTreeMutator> mutator) override;
   bool SupportsImplScrolling() const override;
   bool MainFrameWillHappenForTesting() override;
+  void SetURLForUkm(const GURL& url) override {
+    // Single-threaded mode is only for browser compositing and for renderers in
+    // layout tests. This will still get called in the latter case, but we don't
+    // need to record UKM in that case.
+  }
 
   // Blink layout tests might call into this even though an unthreaded CC
   // doesn't have BrowserControls itself.
diff --git a/cc/trees/ukm_manager.cc b/cc/trees/ukm_manager.cc
new file mode 100644
index 0000000..8a817d5
--- /dev/null
+++ b/cc/trees/ukm_manager.cc
@@ -0,0 +1,69 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "cc/trees/ukm_manager.h"
+
+#include "services/metrics/public/cpp/ukm_builders.h"
+#include "services/metrics/public/cpp/ukm_recorder.h"
+
+namespace cc {
+
+UkmManager::UkmManager(std::unique_ptr<ukm::UkmRecorder> recorder)
+    : recorder_(std::move(recorder)) {
+  DCHECK(recorder_);
+}
+
+UkmManager::~UkmManager() = default;
+
+void UkmManager::SetSourceURL(const GURL& url) {
+  // If we accumulating any metrics, record them before reseting the source.
+  RecordCheckerboardUkm();
+
+  source_id_ = recorder_->GetNewSourceID();
+  recorder_->UpdateSourceURL(source_id_, url);
+}
+
+void UkmManager::SetUserInteractionInProgress(bool in_progress) {
+  if (user_interaction_in_progress_ == in_progress)
+    return;
+
+  user_interaction_in_progress_ = in_progress;
+  if (!user_interaction_in_progress_)
+    RecordCheckerboardUkm();
+}
+
+void UkmManager::AddCheckerboardStatsForFrame(int64_t checkerboard_area,
+                                              int64_t num_missing_tiles,
+                                              int64_t total_visible_area) {
+  DCHECK_GE(total_visible_area, checkerboard_area);
+  if (source_id_ == ukm::kInvalidSourceId || !user_interaction_in_progress_)
+    return;
+
+  checkerboarded_content_area_ += checkerboard_area;
+  num_missing_tiles_ += num_missing_tiles;
+  total_visible_area_ += total_visible_area;
+  num_of_frames_++;
+}
+
+void UkmManager::RecordCheckerboardUkm() {
+  // Only make a recording if there was any visible area from PictureLayers,
+  // which can be checkerboarded.
+  if (num_of_frames_ > 0 && total_visible_area_ > 0) {
+    DCHECK_NE(source_id_, ukm::kInvalidSourceId);
+    ukm::builders::Compositor_UserInteraction(source_id_)
+        .SetCheckerboardedContentArea(checkerboarded_content_area_ /
+                                      num_of_frames_)
+        .SetNumMissingTiles(num_missing_tiles_ / num_of_frames_)
+        .SetCheckerboardedContentAreaRatio(
+            (checkerboarded_content_area_ * 100) / total_visible_area_)
+        .Record(recorder_.get());
+  }
+
+  checkerboarded_content_area_ = 0;
+  num_missing_tiles_ = 0;
+  num_of_frames_ = 0;
+  total_visible_area_ = 0;
+}
+
+}  // namespace cc
diff --git a/cc/trees/ukm_manager.h b/cc/trees/ukm_manager.h
new file mode 100644
index 0000000..7521ccc
--- /dev/null
+++ b/cc/trees/ukm_manager.h
@@ -0,0 +1,54 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CC_TREES_UKM_MANAGER_H_
+#define CC_TREES_UKM_MANAGER_H_
+
+#include "cc/cc_export.h"
+#include "services/metrics/public/cpp/ukm_source_id.h"
+#include "url/gurl.h"
+
+namespace ukm {
+class UkmRecorder;
+}  // namespace ukm
+
+namespace cc {
+
+class CC_EXPORT UkmRecorderFactory {
+ public:
+  virtual ~UkmRecorderFactory() {}
+
+  virtual std::unique_ptr<ukm::UkmRecorder> CreateRecorder() = 0;
+};
+
+class CC_EXPORT UkmManager {
+ public:
+  explicit UkmManager(std::unique_ptr<ukm::UkmRecorder> recorder);
+  ~UkmManager();
+
+  void SetSourceURL(const GURL& url);
+
+  void SetUserInteractionInProgress(bool in_progress);
+  void AddCheckerboardStatsForFrame(int64_t checkerboard_area,
+                                    int64_t num_missing_tiles,
+                                    int64_t total_visible_area);
+
+  ukm::UkmRecorder* recorder_for_testing() { return recorder_.get(); }
+
+ private:
+  void RecordCheckerboardUkm();
+
+  bool user_interaction_in_progress_ = false;
+  int64_t checkerboarded_content_area_ = 0;
+  int64_t num_missing_tiles_ = 0;
+  int64_t total_visible_area_ = 0;
+  int64_t num_of_frames_ = 0;
+
+  ukm::SourceId source_id_ = ukm::kInvalidSourceId;
+  std::unique_ptr<ukm::UkmRecorder> recorder_;
+};
+
+}  // namespace cc
+
+#endif  // CC_TREES_UKM_MANAGER_H_
diff --git a/cc/trees/ukm_manager_unittest.cc b/cc/trees/ukm_manager_unittest.cc
new file mode 100644
index 0000000..d59604d
--- /dev/null
+++ b/cc/trees/ukm_manager_unittest.cc
@@ -0,0 +1,94 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "cc/trees/ukm_manager.h"
+
+#include "components/ukm/test_ukm_recorder.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace cc {
+namespace {
+const char kUserInteraction[] = "Compositor.UserInteraction";
+const char kCheckerboardArea[] = "CheckerboardedContentArea";
+const char kCheckerboardAreaRatio[] = "CheckerboardedContentAreaRatio";
+const char kMissingTiles[] = "NumMissingTiles";
+
+class UkmRecorderForTest : public ukm::TestUkmRecorder {
+ public:
+  UkmRecorderForTest() = default;
+  ~UkmRecorderForTest() override {
+    ExpectMetrics(*source_, kUserInteraction, kCheckerboardArea,
+                  expected_final_checkerboard_);
+    ExpectMetrics(*source_, kUserInteraction, kMissingTiles,
+                  expected_final_missing_tiles_);
+    ExpectMetrics(*source_, kUserInteraction, kCheckerboardAreaRatio,
+                  expected_final_checkerboard_ratio_);
+  }
+
+  std::vector<int64_t> expected_final_checkerboard_;
+  std::vector<int64_t> expected_final_missing_tiles_;
+  std::vector<int64_t> expected_final_checkerboard_ratio_;
+  ukm::UkmSource* source_ = nullptr;
+};
+
+class UkmManagerTest : public testing::Test {
+ public:
+  UkmManagerTest() : manager_(std::make_unique<UkmRecorderForTest>()) {
+    UpdateURL(GURL("chrome://test"));
+  }
+
+  void TearDown() override { ukm_source_ = nullptr; }
+
+  UkmRecorderForTest* recorder() {
+    return static_cast<UkmRecorderForTest*>(manager_.recorder_for_testing());
+  }
+
+ protected:
+  void UpdateURL(const GURL& url) {
+    manager_.SetSourceURL(url);
+    ukm_source_ = const_cast<ukm::UkmSource*>(recorder()->GetSourceForUrl(url));
+  }
+
+  UkmManager manager_;
+  ukm::UkmSource* ukm_source_ = nullptr;
+};
+
+TEST_F(UkmManagerTest, Basic) {
+  manager_.SetUserInteractionInProgress(true);
+  manager_.AddCheckerboardStatsForFrame(5, 1, 10);
+  manager_.AddCheckerboardStatsForFrame(15, 3, 30);
+  manager_.SetUserInteractionInProgress(false);
+
+  // We should see a single entry for the interaction above.
+  EXPECT_EQ(recorder()->entries_count(), 1u);
+  EXPECT_TRUE(recorder()->HasEntry(*ukm_source_, kUserInteraction));
+  recorder()->ExpectMetric(*ukm_source_, kUserInteraction, kCheckerboardArea,
+                           10);
+  recorder()->ExpectMetric(*ukm_source_, kUserInteraction, kMissingTiles, 2);
+  recorder()->ExpectMetric(*ukm_source_, kUserInteraction,
+                           kCheckerboardAreaRatio, 50);
+
+  // Try pushing some stats while no user interaction is happening. No entries
+  // should be pushed.
+  manager_.AddCheckerboardStatsForFrame(6, 1, 10);
+  manager_.AddCheckerboardStatsForFrame(99, 3, 100);
+  EXPECT_EQ(recorder()->entries_count(), 1u);
+  manager_.SetUserInteractionInProgress(true);
+  EXPECT_EQ(recorder()->entries_count(), 1u);
+
+  // Record a few entries and change the source before the interaction ends. The
+  // stats collected up till this point should be recorded before the source is
+  // swapped.
+  manager_.AddCheckerboardStatsForFrame(10, 1, 100);
+  manager_.AddCheckerboardStatsForFrame(30, 5, 100);
+  recorder()->expected_final_checkerboard_ = {10, 20};
+  recorder()->expected_final_missing_tiles_ = {2, 3};
+  recorder()->expected_final_checkerboard_ratio_ = {50, 20};
+  recorder()->source_ = ukm_source_;
+
+  UpdateURL(GURL("chrome://test2"));
+}
+
+}  // namespace
+}  // namespace cc
diff --git a/chrome/VERSION b/chrome/VERSION
index cf15b88..e4b4497 100644
--- a/chrome/VERSION
+++ b/chrome/VERSION
@@ -1,4 +1,4 @@
 MAJOR=64
 MINOR=0
-BUILD=3252
+BUILD=3254
 PATCH=0
diff --git a/chrome/android/BUILD.gn b/chrome/android/BUILD.gn
index be938cb..556bb3a 100644
--- a/chrome/android/BUILD.gn
+++ b/chrome/android/BUILD.gn
@@ -243,8 +243,11 @@
     "//third_party/android_media:android_media_java",
     "//third_party/android_protobuf:protobuf_nano_javalib",
     "//third_party/android_swipe_refresh:android_swipe_refresh_java",
+    "//third_party/android_tools:android_arch_lifecycle_common_java",
+    "//third_party/android_tools:android_arch_lifecycle_runtime_java",
     "//third_party/android_tools:android_gcm_java",
     "//third_party/android_tools:android_support_annotations_java",
+    "//third_party/android_tools:android_support_compat_java",
     "//third_party/android_tools:android_support_design_java",
     "//third_party/android_tools:android_support_transition_java",
     "//third_party/android_tools:android_support_v13_java",
@@ -422,6 +425,7 @@
     "//third_party/WebKit/public:android_mojo_bindings_java",
     "//third_party/WebKit/public:blink_headers_java",
     "//third_party/android_protobuf:protobuf_nano_javalib",
+    "//third_party/android_tools:android_arch_lifecycle_common_java",
     "//third_party/android_tools:android_support_annotations_java",
     "//third_party/android_tools:android_support_v7_appcompat_java",
     "//third_party/android_tools:android_support_v7_mediarouter_java",
@@ -531,6 +535,7 @@
     "//third_party/android_protobuf:protobuf_nano_javalib",
     "//third_party/android_support_test_runner:rules_java",
     "//third_party/android_support_test_runner:runner_java",
+    "//third_party/android_tools:android_arch_lifecycle_common_java",
     "//third_party/android_tools:android_support_annotations_java",
     "//third_party/android_tools:android_support_design_java",
     "//third_party/android_tools:android_support_transition_java",
@@ -632,6 +637,7 @@
       "//third_party/android_protobuf:protobuf_nano_javalib",
       "//third_party/android_support_test_runner:rules_java",
       "//third_party/android_support_test_runner:runner_java",
+      "//third_party/android_tools:android_arch_lifecycle_common_java",
       "//third_party/android_tools:android_support_v7_appcompat_java",
       "//third_party/android_tools:android_support_v7_recyclerview_java",
       "//third_party/custom_tabs_client:custom_tabs_support_java",
@@ -1177,6 +1183,7 @@
     "//content/public/test/android:content_java_test_support",
     "//third_party/android_support_test_runner:rules_java",
     "//third_party/android_support_test_runner:runner_java",
+    "//third_party/android_tools:android_arch_lifecycle_common_java",
     "//third_party/android_tools:android_support_v7_appcompat_java",
     "//third_party/junit",
     "//ui/android:ui_java",
diff --git a/chrome/android/chrome_public_apk_tmpl.gni b/chrome/android/chrome_public_apk_tmpl.gni
index 49b8148..cc5ba77c 100644
--- a/chrome/android/chrome_public_apk_tmpl.gni
+++ b/chrome/android/chrome_public_apk_tmpl.gni
@@ -112,7 +112,6 @@
     app_as_shared_lib = true
     use_chromium_linker = false
     requires_sdk_api_level_23 = true
-    extensions_to_not_compress = ".lpak,.pak,.bin,.dat"
 
     # Webview supports all locales (has no omitted ones).
     aapt_locale_whitelist = locales
diff --git a/chrome/android/java/AndroidManifest.xml b/chrome/android/java/AndroidManifest.xml
index a68dd09..cee74b6 100644
--- a/chrome/android/java/AndroidManifest.xml
+++ b/chrome/android/java/AndroidManifest.xml
@@ -27,16 +27,16 @@
     <!--
       Enable runtime permissions as uses-permission in tip of tree builds
       only for ease of development on Android L and earlier. For consumer
-      channels use "runtime permission" uses-permission-sdk-m which provides
+      channels use "runtime permission" uses-permission-sdk-23 which provides
       permission on Android M and later without a prompt.
     -->
     {% if channel in ['default'] %}
         <uses-permission android:name="android.permission.REQUEST_INSTALL_PACKAGES"/>
     {% endif %}
-    <uses-permission-sdk-m android:name="android.permission.BLUETOOTH"/>
-    <uses-permission-sdk-m android:name="android.permission.BLUETOOTH_ADMIN"/>
-    <uses-permission-sdk-m android:name="android.permission.REORDER_TASKS"/>
-    <uses-permission-sdk-m android:name="android.permission.REQUEST_INSTALL_PACKAGES"/>
+    <uses-permission-sdk-23 android:name="android.permission.BLUETOOTH"/>
+    <uses-permission-sdk-23 android:name="android.permission.BLUETOOTH_ADMIN"/>
+    <uses-permission-sdk-23 android:name="android.permission.REORDER_TASKS"/>
+    <uses-permission-sdk-23 android:name="android.permission.REQUEST_INSTALL_PACKAGES"/>
 
     <uses-permission android:name="android.permission.CAMERA" />
     <uses-permission android:name="android.permission.DOWNLOAD_WITHOUT_NOTIFICATION" />
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/ChromeActivity.java b/chrome/android/java/src/org/chromium/chrome/browser/ChromeActivity.java
index fea318b..a440cf1 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/ChromeActivity.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/ChromeActivity.java
@@ -14,7 +14,6 @@
 import android.content.Intent;
 import android.content.res.Configuration;
 import android.graphics.Color;
-import android.graphics.Rect;
 import android.graphics.drawable.ColorDrawable;
 import android.graphics.drawable.Drawable;
 import android.net.Uri;
@@ -210,8 +209,6 @@
      * Timeout in ms for reading PartnerBrowserCustomizations provider.
      */
     private static final int PARTNER_BROWSER_CUSTOMIZATIONS_TIMEOUT_MS = 10000;
-    private static final String TAG = "ChromeActivity";
-    private static final Rect EMPTY_RECT = new Rect();
 
     private static AppMenuHandlerFactory sAppMenuHandlerFactory =
             (activity, delegate, menuResourceId) -> new AppMenuHandler(activity, delegate,
@@ -236,7 +233,7 @@
     private boolean mDeferredStartupPosted;
 
     private boolean mTabModelsInitialized;
-    private boolean mNativeInitialized;
+    protected boolean mNativeInitialized;
     private boolean mRemoveWindowBackgroundDone;
 
     // The class cannot implement TouchExplorationStateChangeListener,
@@ -295,7 +292,7 @@
     private boolean mDidAddPolicyChangeListener;
 
     /**
-     * @param factory The {@link AppMenuHandlerFactory} for creating {@link mAppMenuHandler}
+     * @param factory The {@link AppMenuHandlerFactory} for creating {@link #mAppMenuHandler}
      */
     @VisibleForTesting
     public static void setAppMenuHandlerFactoryForTesting(AppMenuHandlerFactory factory) {
@@ -443,7 +440,7 @@
                             ((ViewStub) findViewById(R.id.control_container_stub));
 
                     toolbarContainerStub.setLayoutResource(controlContainerLayoutId);
-                    View container = toolbarContainerStub.inflate();
+                    toolbarContainerStub.inflate();
                 }
 
                 // It cannot be assumed that the result of toolbarContainerStub.inflate() will be
@@ -1237,8 +1234,9 @@
      * Called when the accessibility status of this device changes.  This might be triggered by
      * touch exploration or general accessibility status updates.  It is an aggregate of two other
      * accessibility update methods.
-     * @see #onAccessibilityModeChanged(boolean)
-     * @see #onTouchExplorationStateChanged(boolean)
+     *
+     * @see #onAccessibilityStateChanged
+     * @see #mTouchExplorationStateChangeListener
      * @param enabled Whether or not accessibility and touch exploration are currently enabled.
      */
     protected void onAccessibilityModeChanged(boolean enabled) {
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/ChromeTabbedActivity.java b/chrome/android/java/src/org/chromium/chrome/browser/ChromeTabbedActivity.java
index be3b220..dcbeb0f 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/ChromeTabbedActivity.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/ChromeTabbedActivity.java
@@ -555,29 +555,35 @@
             // TODO(tedchoc): Unify promo dialog logic as the search engine promo dialog checks
             //                might not have completed at this point and we could show multiple
             //                promos.
-            if (!mLocaleManager.hasShownSearchEnginePromoThisSession() && !mIntentWithEffect
-                    && FirstRunStatus.getFirstRunFlowComplete()
+            boolean isShowingPromo = mLocaleManager.hasShownSearchEnginePromoThisSession();
+            if (!isShowingPromo && !mIntentWithEffect && FirstRunStatus.getFirstRunFlowComplete()
                     && preferenceManager.getPromosSkippedOnFirstStart()
                     && !VrShellDelegate.isInVr()) {
                 // Data reduction promo should be temporarily suppressed if the sign in promo is
                 // shown to avoid nagging users too much.
-                TabModel currentModel = mTabModelSelectorImpl.getCurrentModel();
-                if (!SigninPromoUtil.launchSigninPromoIfNeeded(this)) {
-                    if (!DataReductionPromoScreen.launchDataReductionPromo(
-                                this, currentModel.isIncognito())) {
-                        if (FeatureUtilities.shouldShowChromeHomePromoForStartup()) {
-                            new ChromeHomePromoDialog(
-                                    this, ChromeHomePromoDialog.ShowReason.STARTUP)
-                                    .show();
-                        } else if (getBottomSheet() != null) {
-                            getBottomSheet().showHelpBubbleIfNecessary();
-                        }
+                isShowingPromo = SigninPromoUtil.launchSigninPromoIfNeeded(this)
+                        || DataReductionPromoScreen.launchDataReductionPromo(
+                                   this, mTabModelSelectorImpl.getCurrentModel().isIncognito());
+                if (!isShowingPromo) {
+                    if (FeatureUtilities.shouldShowChromeHomePromoForStartup()) {
+                        new ChromeHomePromoDialog(this, ChromeHomePromoDialog.ShowReason.STARTUP)
+                                .show();
+                        isShowingPromo = true;
+                    } else if (getBottomSheet() != null) {
+                        getBottomSheet().showHelpBubbleIfNecessary();
                     }
                 }
             } else {
                 preferenceManager.setPromosSkippedOnFirstStart(true);
             }
 
+            if (!isShowingPromo) {
+                final Tracker tracker =
+                        TrackerFactory.getTrackerForProfile(Profile.getLastUsedProfile());
+                tracker.addOnInitializedCallback(
+                        (Callback<Boolean>) success -> maybeShowDownloadHomeTextBubble(tracker));
+            }
+
             super.finishNativeInitialization();
         } finally {
             TraceEvent.end("ChromeTabbedActivity.finishNativeInitialization");
@@ -846,11 +852,6 @@
                 mLayoutManager.hideOverview(false);
             }
 
-            final Tracker tracker =
-                    TrackerFactory.getTrackerForProfile(Profile.getLastUsedProfile());
-            tracker.addOnInitializedCallback(
-                    (Callback<Boolean>) success -> maybeShowDownloadHomeTextBubble(tracker));
-
             mScreenshotMonitor = ScreenshotMonitor.create(ChromeTabbedActivity.this);
 
             mUIInitialized = true;
@@ -2247,7 +2248,7 @@
     @Override
     public void onMultiWindowModeChanged(boolean isInMultiWindowMode) {
         super.onMultiWindowModeChanged(isInMultiWindowMode);
-        if (!FeatureUtilities.isTabModelMergingEnabled()) return;
+        if (!FeatureUtilities.isTabModelMergingEnabled() || !mNativeInitialized) return;
         if (!isInMultiWindowMode) {
             // If the activity is currently resumed when multi-window mode is exited, try to merge
             // tabs from the other activity instance.
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/bookmarks/BookmarkActionBar.java b/chrome/android/java/src/org/chromium/chrome/browser/bookmarks/BookmarkActionBar.java
index 1f23456..ced796b 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/bookmarks/BookmarkActionBar.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/bookmarks/BookmarkActionBar.java
@@ -129,6 +129,16 @@
         getMenu().findItem(R.id.edit_menu_id).setVisible(false);
     }
 
+    @Override
+    protected void showNormalView() {
+        super.showNormalView();
+
+        if (mDelegate == null) {
+            getMenu().findItem(R.id.search_menu_id).setVisible(false);
+            getMenu().findItem(R.id.edit_menu_id).setVisible(false);
+        }
+    }
+
     // BookmarkUIObserver implementations.
 
     @Override
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/browseractions/BrowserActionActivity.java b/chrome/android/java/src/org/chromium/chrome/browser/browseractions/BrowserActionActivity.java
index fec2201..bd8df64 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/browseractions/BrowserActionActivity.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/browseractions/BrowserActionActivity.java
@@ -27,6 +27,7 @@
 import org.chromium.chrome.browser.rappor.RapporServiceBridge;
 import org.chromium.chrome.browser.util.IntentUtils;
 import org.chromium.content_public.common.Referrer;
+import org.chromium.ui.base.MenuSourceType;
 
 import java.util.ArrayList;
 import java.util.List;
@@ -132,7 +133,8 @@
 
         return new ContextMenuParams(mType, mUri.toString(), mUri.toString(), mUri.toString(),
                 mUri.toString(), mUri.toString(), mUri.toString(), false /* imageWasFetchedLoFi */,
-                referrer, false /* canSaveMedia */, touchX, touchY);
+                referrer, false /* canSaveMedia */, touchX, touchY,
+                MenuSourceType.MENU_SOURCE_TOUCH);
     }
 
     @Override
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/browseractions/BrowserActionsContextMenuHelper.java b/chrome/android/java/src/org/chromium/chrome/browser/browseractions/BrowserActionsContextMenuHelper.java
index 7b663e90..f837c115 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/browseractions/BrowserActionsContextMenuHelper.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/browseractions/BrowserActionsContextMenuHelper.java
@@ -10,6 +10,7 @@
 import android.app.ProgressDialog;
 import android.content.Intent;
 import android.net.Uri;
+import android.support.annotation.IntDef;
 import android.support.customtabs.browseractions.BrowserActionItem;
 import android.support.customtabs.browseractions.BrowserActionsIntent;
 import android.support.customtabs.browseractions.BrowserActionsIntent.BrowserActionsItemId;
@@ -24,6 +25,7 @@
 import org.chromium.base.Callback;
 import org.chromium.base.Log;
 import org.chromium.base.VisibleForTesting;
+import org.chromium.base.metrics.RecordHistogram;
 import org.chromium.base.metrics.RecordUserAction;
 import org.chromium.chrome.R;
 import org.chromium.chrome.browser.contextmenu.ChromeContextMenuItem;
@@ -35,6 +37,8 @@
 import org.chromium.chrome.browser.contextmenu.TabularContextMenuUi;
 import org.chromium.ui.base.WindowAndroid.OnCloseContextMenuListener;
 
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.List;
@@ -65,6 +69,23 @@
                 ProgressDialog progressDialog);
     }
 
+    /**
+     * Defines the actions shown on the Browser Actions context menu.
+     * Note: these values must match the BrowserActionsMenuOption enum in enums.xml.
+     * And the values are persisted to logs so they cannot be renumbered or reused.
+     */
+    @IntDef({ACTION_OPEN_IN_NEW_CHROME_TAB, ACTION_OPEN_IN_INCOGNITO_TAB, ACTION_DOWNLOAD_PAGE,
+            ACTION_COPY_LINK, ACTION_SHARE, ACTION_APP_PROVIDED})
+    @Retention(RetentionPolicy.SOURCE)
+    public @interface BrowserActionsActionId {}
+    private static final int ACTION_OPEN_IN_NEW_CHROME_TAB = 0;
+    private static final int ACTION_OPEN_IN_INCOGNITO_TAB = 1;
+    private static final int ACTION_DOWNLOAD_PAGE = 2;
+    private static final int ACTION_COPY_LINK = 3;
+    private static final int ACTION_SHARE = 4;
+    // Actions for selecting custom items.
+    private static final int ACTION_APP_PROVIDED = 5;
+    private static final int NUM_ACTIONS = 6;
 
     static final List<Integer> CUSTOM_BROWSER_ACTIONS_ID_GROUP =
             Arrays.asList(R.id.browser_actions_custom_item_one,
@@ -190,33 +211,44 @@
     boolean onItemSelected(int itemId) {
         if (itemId == R.id.browser_actions_open_in_background) {
             if (mIsNativeInitialized) {
+                recordBrowserActionsSelection(ACTION_OPEN_IN_NEW_CHROME_TAB);
                 handleOpenInBackground();
             } else {
                 mPendingItemId = itemId;
                 waitNativeInitialized();
             }
         } else if (itemId == R.id.browser_actions_open_in_incognito_tab) {
+            recordBrowserActionsSelection(ACTION_OPEN_IN_INCOGNITO_TAB);
             mMenuItemDelegate.onOpenInIncognitoTab(mCurrentContextMenuParams.getLinkUrl());
             notifyBrowserActionSelected(BrowserActionsIntent.ITEM_OPEN_IN_INCOGNITO);
         } else if (itemId == R.id.browser_actions_save_link_as) {
             if (mIsNativeInitialized) {
+                recordBrowserActionsSelection(ACTION_DOWNLOAD_PAGE);
                 handleDownload();
             } else {
                 mPendingItemId = itemId;
                 waitNativeInitialized();
             }
         } else if (itemId == R.id.browser_actions_copy_address) {
+            recordBrowserActionsSelection(ACTION_COPY_LINK);
             mMenuItemDelegate.onSaveToClipboard(mCurrentContextMenuParams.getLinkUrl());
             notifyBrowserActionSelected(BrowserActionsIntent.ITEM_COPY);
         } else if (itemId == R.id.browser_actions_share) {
+            recordBrowserActionsSelection(ACTION_SHARE);
             mMenuItemDelegate.share(false, mCurrentContextMenuParams.getLinkUrl());
             notifyBrowserActionSelected(BrowserActionsIntent.ITEM_SHARE);
         } else if (mCustomItemActionMap.indexOfKey(itemId) >= 0) {
+            recordBrowserActionsSelection(ACTION_APP_PROVIDED);
             mMenuItemDelegate.onCustomItemSelected(mCustomItemActionMap.get(itemId));
         }
         return true;
     }
 
+    private void recordBrowserActionsSelection(@BrowserActionsActionId int itemId) {
+        RecordHistogram.recordEnumeratedHistogram(
+                "BrowserActions.SelectedOption", itemId, NUM_ACTIONS);
+    }
+
     private void notifyBrowserActionSelected(@BrowserActionsItemId int menuId) {
         if (mOnBrowserActionSelectedCallback == null) return;
         Intent additionalData = new Intent();
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/compositor/bottombar/OverlayPanelAnimation.java b/chrome/android/java/src/org/chromium/chrome/browser/compositor/bottombar/OverlayPanelAnimation.java
index 9d47eed5..cf31a02 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/compositor/bottombar/OverlayPanelAnimation.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/compositor/bottombar/OverlayPanelAnimation.java
@@ -5,7 +5,6 @@
 package org.chromium.chrome.browser.compositor.bottombar;
 
 import android.animation.Animator;
-import android.animation.AnimatorListenerAdapter;
 import android.content.Context;
 
 import org.chromium.base.VisibleForTesting;
@@ -16,6 +15,7 @@
 import org.chromium.chrome.browser.compositor.bottombar.OverlayPanel.StateChangeReason;
 import org.chromium.chrome.browser.compositor.layouts.LayoutUpdateHost;
 import org.chromium.chrome.browser.util.MathUtils;
+import org.chromium.chrome.browser.widget.animation.CancelAwareAnimatorListener;
 
 /**
  * Base abstract class for animating the Overlay Panel.
@@ -353,9 +353,9 @@
                 setPanelHeight(animator.getAnimatedValue());
             }
         });
-        mHeightAnimator.addListener(new AnimatorListenerAdapter() {
+        mHeightAnimator.addListener(new CancelAwareAnimatorListener() {
             @Override
-            public void onAnimationEnd(Animator animation) {
+            public void onEnd(Animator animation) {
                 onHeightAnimationFinished();
             }
         });
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/contextmenu/ContextMenuParams.java b/chrome/android/java/src/org/chromium/chrome/browser/contextmenu/ContextMenuParams.java
index 4aff3d9..d5cb2b1 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/contextmenu/ContextMenuParams.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/contextmenu/ContextMenuParams.java
@@ -11,6 +11,7 @@
 import org.chromium.blink_public.web.WebContextMenuMediaType;
 import org.chromium.chrome.browser.UrlConstants;
 import org.chromium.content_public.common.Referrer;
+import org.chromium.ui.base.MenuSourceType;
 /**
  * A list of parameters that explain what kind of context menu to show the user.  This data is
  * generated from content/public/common/context_menu_params.h.
@@ -34,6 +35,8 @@
     private final int mTriggeringTouchXDp;
     private final int mTriggeringTouchYDp;
 
+    private final int mSourceType;
+
     /**
      * @return The URL associated with the main frame of the page that triggered the context menu.
      */
@@ -142,6 +145,14 @@
     }
 
     /**
+     * @return The method used to cause the context menu to be shown. For example, right mouse click
+     *         or long press.
+     */
+    public int getSourceType() {
+        return mSourceType;
+    }
+
+    /**
      * @return The valid url of a ContextMenuParams.
      */
     public String getUrl() {
@@ -155,7 +166,7 @@
     public ContextMenuParams(@WebContextMenuMediaType int mediaType, String pageUrl, String linkUrl,
             String linkText, String unfilteredLinkUrl, String srcUrl, String titleText,
             boolean imageWasFetchedLoFi, Referrer referrer, boolean canSaveMedia,
-            int triggeringTouchXDp, int triggeringTouchYDp) {
+            int triggeringTouchXDp, int triggeringTouchYDp, @MenuSourceType int sourceType) {
         mPageUrl = pageUrl;
         mLinkUrl = linkUrl;
         mLinkText = linkText;
@@ -171,6 +182,7 @@
         mCanSaveMedia = canSaveMedia;
         mTriggeringTouchXDp = triggeringTouchXDp;
         mTriggeringTouchYDp = triggeringTouchYDp;
+        mSourceType = sourceType;
     }
 
     @CalledByNative
@@ -178,11 +190,11 @@
             String linkUrl, String linkText, String unfilteredLinkUrl, String srcUrl,
             String titleText, boolean imageWasFetchedLoFi, String sanitizedReferrer,
             int referrerPolicy, boolean canSaveMedia, int triggeringTouchXDp,
-            int triggeringTouchYDp) {
+            int triggeringTouchYDp, @MenuSourceType int sourceType) {
         Referrer referrer = TextUtils.isEmpty(sanitizedReferrer)
                 ? null : new Referrer(sanitizedReferrer, referrerPolicy);
         return new ContextMenuParams(mediaType, pageUrl, linkUrl, linkText, unfilteredLinkUrl,
                 srcUrl, titleText, imageWasFetchedLoFi, referrer, canSaveMedia, triggeringTouchXDp,
-                triggeringTouchYDp);
+                triggeringTouchYDp, sourceType);
     }
 }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabBottomBarDelegate.java b/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabBottomBarDelegate.java
index ef00996d..877983b 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabBottomBarDelegate.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabBottomBarDelegate.java
@@ -131,14 +131,14 @@
             hideBottomBar();
             mClickableIDs = null;
             mClickPendingIntent = null;
+            return true;
         } else {
             // TODO: investigate updating the RemoteViews without replacing the entire hierarchy.
             mClickableIDs = clickableIDs;
             mClickPendingIntent = pendingIntent;
             if (getBottomBarView().getChildCount() > 1) getBottomBarView().removeViewAt(1);
-            showRemoteViews(remoteViews);
+            return showRemoteViews(remoteViews);
         }
-        return true;
     }
 
     /**
@@ -206,12 +206,12 @@
         mFullscreenManager.setBottomControlsHeight(0);
     }
 
-    private void showRemoteViews(RemoteViews remoteViews) {
+    private boolean showRemoteViews(RemoteViews remoteViews) {
         try {
             final View inflatedView = remoteViews.apply(mActivity, getBottomBarView());
             if (mClickableIDs != null && mClickPendingIntent != null) {
                 for (int id: mClickableIDs) {
-                    if (id < 0) return;
+                    if (id < 0) return false;
                     View view = inflatedView.findViewById(id);
                     if (view != null) view.setOnClickListener(mBottomBarClickListener);
                 }
@@ -225,8 +225,10 @@
                     mFullscreenManager.setBottomControlsHeight(v.getHeight());
                 }
             });
+            return true;
         } catch (RemoteViews.ActionException e) {
             Log.e(TAG, "Failed to inflate the RemoteViews", e);
+            return false;
         }
     }
 
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/media/ui/MediaNotificationManager.java b/chrome/android/java/src/org/chromium/chrome/browser/media/ui/MediaNotificationManager.java
index ff53e59..9ce6fe0 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/media/ui/MediaNotificationManager.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/media/ui/MediaNotificationManager.java
@@ -24,11 +24,11 @@
 import android.os.Handler;
 import android.os.IBinder;
 import android.support.annotation.NonNull;
+import android.support.v4.app.NotificationCompat;
 import android.support.v4.app.NotificationManagerCompat;
 import android.support.v4.media.MediaMetadataCompat;
 import android.support.v4.media.session.MediaSessionCompat;
 import android.support.v4.media.session.PlaybackStateCompat;
-import android.support.v7.app.NotificationCompat;
 import android.support.v7.media.MediaRouter;
 import android.text.TextUtils;
 import android.util.SparseArray;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/multiwindow/MultiWindowUtils.java b/chrome/android/java/src/org/chromium/chrome/browser/multiwindow/MultiWindowUtils.java
index eda03aa..8121429 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/multiwindow/MultiWindowUtils.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/multiwindow/MultiWindowUtils.java
@@ -115,6 +115,15 @@
         intent.setClass(activity, targetActivity);
         intent.addFlags(Intent.FLAG_ACTIVITY_LAUNCH_ADJACENT);
 
+        // Remove LAUNCH_ADJACENT flag if we want to start CTA, but it's already running.
+        // If arleady running CTA was started via .Main activity alias, starting it again with
+        // LAUNCH_ADJACENT will create another CTA instance with just a single tab. There doesn't
+        // seem to be a reliable way to check if an activity was started via an alias, so we're
+        // removing the flag if any CTA instance is running. See crbug.com/771516 for details.
+        if (targetActivity.equals(ChromeTabbedActivity.class) && isPrimaryTabbedActivityRunning()) {
+            intent.setFlags(intent.getFlags() & ~Intent.FLAG_ACTIVITY_LAUNCH_ADJACENT);
+        }
+
         // Let Chrome know that this intent is from Chrome, so that it does not close the app when
         // the user presses 'back' button.
         intent.putExtra(Browser.EXTRA_APPLICATION_ID, activity.getPackageName());
@@ -271,17 +280,14 @@
     }
 
     /**
-     * @return Whether there is already an browser instance of Chrome already running.
+     * @return Whether ChromeTabbedActivity (exact activity, not a subclass of) is currently
+     *         running.
      */
-    private static boolean isChromeBrowserActivityRunning() {
+    private static boolean isPrimaryTabbedActivityRunning() {
         for (WeakReference<Activity> reference : ApplicationStatus.getRunningActivities()) {
             Activity activity = reference.get();
             if (activity == null) continue;
-
-            String className = activity.getClass().getName();
-            if (TextUtils.equals(className, ChromeTabbedActivity.class.getName())) {
-                return true;
-            }
+            if (activity.getClass().equals(ChromeTabbedActivity.class)) return true;
         }
         return false;
     }
@@ -292,7 +298,7 @@
     public boolean shouldRunInLegacyMultiInstanceMode(Activity activity, Intent intent) {
         return Build.VERSION.SDK_INT > Build.VERSION_CODES.LOLLIPOP
                 && TextUtils.equals(intent.getAction(), Intent.ACTION_MAIN)
-                && isLegacyMultiWindow(activity) && isChromeBrowserActivityRunning();
+                && isLegacyMultiWindow(activity) && isPrimaryTabbedActivityRunning();
     }
 
     /**
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/notifications/NotificationCompatBuilder.java b/chrome/android/java/src/org/chromium/chrome/browser/notifications/NotificationCompatBuilder.java
index 9b1e0e7..fd0ceba 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/notifications/NotificationCompatBuilder.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/notifications/NotificationCompatBuilder.java
@@ -10,8 +10,8 @@
 import android.graphics.Bitmap;
 import android.graphics.drawable.Icon;
 import android.os.Bundle;
+import android.support.v4.app.NotificationCompat;
 import android.support.v4.media.session.MediaSessionCompat;
-import android.support.v7.app.NotificationCompat;
 import android.widget.RemoteViews;
 
 /**
@@ -206,7 +206,8 @@
     @Override
     public ChromeNotificationBuilder setMediaStyle(MediaSessionCompat session, int[] actions,
             PendingIntent intent, boolean showCancelButton) {
-        NotificationCompat.MediaStyle style = new NotificationCompat.MediaStyle();
+        android.support.v4.media.app.NotificationCompat.MediaStyle style =
+                new android.support.v4.media.app.NotificationCompat.MediaStyle();
         style.setMediaSession(session.getSessionToken());
         style.setShowActionsInCompactView(actions);
         style.setCancelButtonIntent(intent);
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/offlinepages/OfflinePageUtils.java b/chrome/android/java/src/org/chromium/chrome/browser/offlinepages/OfflinePageUtils.java
index a985feb5..0464028 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/offlinepages/OfflinePageUtils.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/offlinepages/OfflinePageUtils.java
@@ -51,12 +51,8 @@
     /** Background task tag to differentiate from other task types */
     public static final String TASK_TAG = "OfflinePageUtils";
 
-    public static final String EXTERNAL_MHTML_FILE_PATH = "offline-pages";
-
     private static final int DEFAULT_SNACKBAR_DURATION_MS = 6 * 1000; // 6 second
 
-    private static final long STORAGE_ALMOST_FULL_THRESHOLD_BYTES = 10L * (1 << 20); // 10M
-
     /**
      * Bit flags to be OR-ed together to build the context of a tab restore to be used to identify
      * the appropriate TabRestoreType in a lookup table.
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/omnibox/LocationBarLayout.java b/chrome/android/java/src/org/chromium/chrome/browser/omnibox/LocationBarLayout.java
index 63c4d4a..24500c05 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/omnibox/LocationBarLayout.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/omnibox/LocationBarLayout.java
@@ -1552,16 +1552,24 @@
 
         assert urlContainerChildIndex != -1;
         int urlContainerMarginEnd = 0;
-        for (int i = urlContainerChildIndex + 1; i < getChildCount(); i++) {
-            View childView = getChildAt(i);
-            if (childView.getVisibility() != GONE) {
-                LayoutParams childLayoutParams = (LayoutParams) childView.getLayoutParams();
-                urlContainerMarginEnd = Math.max(urlContainerMarginEnd,
-                        childLayoutParams.width
-                                + ApiCompatibilityUtils.getMarginStart(childLayoutParams)
-                                + ApiCompatibilityUtils.getMarginEnd(childLayoutParams));
+
+        // When Chrome Home is enabled, the URL actions container slides out of view during the
+        // URL defocus animation. Adding margin during this animation creates a hole.
+        boolean addMarginForActionsContainer =
+                mBottomSheet == null || !mUrlFocusChangeInProgress || mUrlHasFocus;
+        if (addMarginForActionsContainer) {
+            for (int i = urlContainerChildIndex + 1; i < getChildCount(); i++) {
+                View childView = getChildAt(i);
+                if (childView.getVisibility() != GONE) {
+                    LayoutParams childLayoutParams = (LayoutParams) childView.getLayoutParams();
+                    urlContainerMarginEnd = Math.max(urlContainerMarginEnd,
+                            childLayoutParams.width
+                                    + ApiCompatibilityUtils.getMarginStart(childLayoutParams)
+                                    + ApiCompatibilityUtils.getMarginEnd(childLayoutParams));
+                }
             }
         }
+
         LayoutParams urlLayoutParams = (LayoutParams) mUrlBar.getLayoutParams();
         if (ApiCompatibilityUtils.getMarginEnd(urlLayoutParams) != urlContainerMarginEnd) {
             ApiCompatibilityUtils.setMarginEnd(urlLayoutParams, urlContainerMarginEnd);
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/share/ShareHelper.java b/chrome/android/java/src/org/chromium/chrome/browser/share/ShareHelper.java
index 1d3983c2..c5f5c8d 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/share/ShareHelper.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/share/ShareHelper.java
@@ -316,9 +316,9 @@
             return;
         }
 
-        new AsyncTask<Void, Void, File>() {
+        new AsyncTask<Void, Void, Uri>() {
             @Override
-            protected File doInBackground(Void... params) {
+            protected Uri doInBackground(Void... params) {
                 FileOutputStream fOut = null;
                 try {
                     File path = new File(UiUtils.getDirectoryForImageCapture(activity),
@@ -329,32 +329,26 @@
                         fOut = new FileOutputStream(saveFile);
                         fOut.write(jpegImageData);
                         fOut.flush();
-                        fOut.close();
 
-                        return saveFile;
+                        return ApiCompatibilityUtils.getUriForImageCaptureFile(saveFile);
                     } else {
                         Log.w(TAG, "Share failed -- Unable to create share image directory.");
                     }
                 } catch (IOException ie) {
-                    if (fOut != null) {
-                        try {
-                            fOut.close();
-                        } catch (IOException e) {
-                            // Ignore exception.
-                        }
-                    }
+                    // Ignore exception.
+                } finally {
+                    StreamUtil.closeQuietly(fOut);
                 }
 
                 return null;
             }
 
             @Override
-            protected void onPostExecute(File saveFile) {
-                if (saveFile == null) return;
+            protected void onPostExecute(Uri imageUri) {
+                if (imageUri == null) return;
 
                 if (ApplicationStatus.getStateForApplication()
                         != ApplicationState.HAS_DESTROYED_ACTIVITIES) {
-                    Uri imageUri = ApiCompatibilityUtils.getUriForImageCaptureFile(saveFile);
                     Intent shareIntent = getShareImageIntent(imageUri);
                     if (name == null) {
                         if (TargetChosenReceiver.isSupported()) {
@@ -390,9 +384,9 @@
             return;
         }
 
-        new AsyncTask<Void, Void, File>() {
+        new AsyncTask<Void, Void, Uri>() {
             @Override
-            protected File doInBackground(Void... params) {
+            protected Uri doInBackground(Void... params) {
                 FileOutputStream fOut = null;
                 try {
                     File path = new File(UiUtils.getDirectoryForImageCapture(context) + "/"
@@ -402,7 +396,7 @@
                         File saveFile = File.createTempFile(fileName, JPEG_EXTENSION, path);
                         fOut = new FileOutputStream(saveFile);
                         screenshot.compress(Bitmap.CompressFormat.JPEG, 85, fOut);
-                        return saveFile;
+                        return ApiCompatibilityUtils.getUriForImageCaptureFile(saveFile);
                     }
                 } catch (IOException ie) {
                     Log.w(TAG, "Ignoring IOException when saving screenshot.", ie);
@@ -414,13 +408,11 @@
             }
 
             @Override
-            protected void onPostExecute(File savedFile) {
-                Uri fileUri = null;
-                if (ApplicationStatus.getStateForApplication()
-                        != ApplicationState.HAS_DESTROYED_ACTIVITIES
-                        && savedFile != null) {
-                    fileUri = ApiCompatibilityUtils.getUriForImageCaptureFile(savedFile);
-                }
+            protected void onPostExecute(Uri fileUri) {
+                fileUri = ApplicationStatus.getStateForApplication()
+                                != ApplicationState.HAS_DESTROYED_ACTIVITIES
+                        ? fileUri
+                        : null;
                 callback.onResult(fileUri);
             }
         }.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/widget/bottomsheet/BottomSheetContentController.java b/chrome/android/java/src/org/chromium/chrome/browser/widget/bottomsheet/BottomSheetContentController.java
index 223dc0b..6539a42 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/widget/bottomsheet/BottomSheetContentController.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/widget/bottomsheet/BottomSheetContentController.java
@@ -181,8 +181,12 @@
                 return;
             }
 
-            if (mBottomSheet.getSheetState() == BottomSheet.SHEET_STATE_PEEK) {
-                clearBottomSheetContents(mBottomSheet.getCurrentSheetContent() == null);
+            // If the home content is showing and the sheet is closed, destroy sheet contents that
+            // are no longer needed.
+            if (mBottomSheet.getSheetState() == BottomSheet.SHEET_STATE_PEEK
+                    && (newContent == null
+                               || newContent == mBottomSheetContents.get(getHomeContentId()))) {
+                clearBottomSheetContents(newContent == null);
             }
         }
     };
@@ -348,8 +352,6 @@
         ViewGroup snackbarContainer =
                 (ViewGroup) mActivity.findViewById(R.id.bottom_sheet_snackbar_container);
         ((MarginLayoutParams) snackbarContainer.getLayoutParams()).bottomMargin = mBottomNavHeight;
-
-        setMenuBackgroundColor(mTabModelSelector.isIncognitoSelected());
     }
 
     /**
@@ -467,6 +469,11 @@
         return createAndCacheContentForId(navItemId);
     }
 
+    private int getHomeContentId() {
+        if (mTabModelSelector.isIncognitoSelected()) return INCOGNITO_HOME_ID;
+        return R.id.action_home;
+    }
+
     /**
      * Create and return the content for the provided nav button id.
      * @param navItemId The id to create and get the content for.
diff --git a/chrome/android/java/strings/android_chrome_strings.grd b/chrome/android/java/strings/android_chrome_strings.grd
index 48be5cb..3532fb62 100644
--- a/chrome/android/java/strings/android_chrome_strings.grd
+++ b/chrome/android/java/strings/android_chrome_strings.grd
@@ -3211,7 +3211,7 @@
       <message name="IDS_BOTTOM_SHEET_ACCESSIBILITY_EXPAND_BUTTON_HELP_BUBBLE_MESSAGE" desc="Text displayed in a help bubble above the toolbar expand button prompting users to tap the button to see their bookmarks and other content when accessibility is enabled.">
         Tap to see downloads, bookmarks, and history
       </message>
-      <message name="IDS_BOTTOM_SHEET_EXPAND_BUTTON_ACCESSIBILITY" desc="Part of the accessibility string read when the expand button is tapped informing users that tapping button will show downloads, bookmarks, and history. 'access' is a noun. 'Downloads', 'Bookmarks', and 'History' should use the same translations as in Chrome settings and menu items. TalkBack will read 'Expand navigation panel button. Double tap to access downloads, bookmarks, and history'.">
+      <message name="IDS_BOTTOM_SHEET_EXPAND_BUTTON_ACCESSIBILITY" desc="Part of the accessibility string read when the expand button is tapped informing users that tapping button will show downloads, bookmarks, and history. 'access' is a verb. 'Downloads', 'Bookmarks', and 'History' should use the same translations as in Chrome settings and menu items. TalkBack will read 'Expand navigation panel button. Double tap to access downloads, bookmarks, and history'.">
         access downloads, bookmarks, and history.
       </message>
      <message name="IDS_BOTTOM_SHEET_ACCESSIBILITY_DESCRIPTION" desc="Accessibility string read when the navigation panel is focused informing the user that the panel can be closed by swiping down.">
diff --git a/chrome/android/java_sources.gni b/chrome/android/java_sources.gni
index be027ec8..dbf7a42e 100644
--- a/chrome/android/java_sources.gni
+++ b/chrome/android/java_sources.gni
@@ -1900,7 +1900,7 @@
   "junit/src/org/chromium/chrome/browser/omnibox/KeyboardHideHelperUnitTest.java",
   "junit/src/org/chromium/chrome/browser/omnibox/LocationBarLayoutTest.java",
   "junit/src/org/chromium/chrome/browser/omnibox/SpannableAutocompleteEditTextModelUnitTest.java",
-  "junit/src/org/chromium/chrome/browser/omnibox/geo/GeolocationHeaderTest.java",
+  "junit/src/org/chromium/chrome/browser/omnibox/geo/GeolocationHeaderUnitTest.java",
   "junit/src/org/chromium/chrome/browser/omnibox/geo/VisibleNetworksTest.java",
   "junit/src/org/chromium/chrome/browser/omnibox/geo/VisibleNetworksTrackerTest.java",
   "junit/src/org/chromium/chrome/browser/omnibox/geo/PlatformNetworksManagerTest.java",
@@ -1926,7 +1926,7 @@
   "junit/src/org/chromium/chrome/browser/webapps/WebappRegistryTest.java",
   "junit/src/org/chromium/chrome/browser/webapps/WebappInfoTest.java",
   "junit/src/org/chromium/chrome/browser/webapps/WebApkInfoTest.java",
-  "junit/src/org/chromium/chrome/browser/webapps/WebApkUpdateManagerTest.java",
+  "junit/src/org/chromium/chrome/browser/webapps/WebApkUpdateManagerUnitTest.java",
   "junit/src/org/chromium/chrome/browser/widget/selection/SelectionDelegateTest.java",
 ]
 
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/bookmarks/BookmarkTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/bookmarks/BookmarkTest.java
index 68a5e5a55..88854fd 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/bookmarks/BookmarkTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/bookmarks/BookmarkTest.java
@@ -29,8 +29,8 @@
 import org.chromium.base.ThreadUtils;
 import org.chromium.base.test.util.CallbackHelper;
 import org.chromium.base.test.util.CommandLineFlags;
+import org.chromium.base.test.util.DisableIf;
 import org.chromium.base.test.util.Feature;
-import org.chromium.base.test.util.Restriction;
 import org.chromium.base.test.util.RetryOnFailure;
 import org.chromium.chrome.R;
 import org.chromium.chrome.browser.ChromeActivity;
@@ -51,7 +51,7 @@
 import org.chromium.content.browser.test.util.TouchCommon;
 import org.chromium.net.test.EmbeddedTestServer;
 import org.chromium.ui.base.DeviceFormFactor;
-import org.chromium.ui.test.util.UiRestriction;
+import org.chromium.ui.test.util.UiDisableIf;
 
 import java.util.ArrayList;
 import java.util.concurrent.Callable;
@@ -220,6 +220,7 @@
         openBookmarkManager();
         BookmarkDelegate delegate =
                 ((BookmarkItemsAdapter) mItemsContainer.getAdapter()).getDelegateForTesting();
+
         Assert.assertEquals(BookmarkUIState.STATE_FOLDER, delegate.getCurrentState());
         Assert.assertEquals("chrome-native://bookmarks/folder/3",
                 BookmarkUtils.getLastUsedUrl(mActivityTestRule.getActivity()));
@@ -227,31 +228,45 @@
 
     @Test
     @MediumTest
-    public void testTopLevelFolders() throws InterruptedException {
+    // https://crbug.com/779518
+    @DisableIf.Device(type = {UiDisableIf.TABLET, UiDisableIf.LARGETABLET})
+    public void testFolderNavigation() throws InterruptedException, ExecutionException {
+        BookmarkId testFolder = addFolder(TEST_FOLDER_TITLE);
         openBookmarkManager();
         final BookmarkDelegate delegate =
                 ((BookmarkItemsAdapter) mItemsContainer.getAdapter()).getDelegateForTesting();
         final BookmarkActionBar toolbar = ((BookmarkManager) delegate).getToolbarForTests();
 
         // Open the "Mobile bookmarks" folder.
-        ThreadUtils.runOnUiThreadBlocking(new Runnable() {
-            @Override
-            public void run() {
-                delegate.openFolder(mBookmarkModel.getMobileFolderId());
-            }
-        });
+        ThreadUtils.runOnUiThreadBlocking(
+                () -> { delegate.openFolder(mBookmarkModel.getMobileFolderId()); });
 
+        // Check that we are in the mobile bookmarks folder.
+        Assert.assertEquals("Mobile bookmarks", toolbar.getTitle());
+        Assert.assertEquals(SelectableListToolbar.NAVIGATION_BUTTON_BACK,
+                toolbar.getNavigationButtonForTests());
+        Assert.assertFalse(toolbar.getMenu().findItem(R.id.edit_menu_id).isVisible());
+
+        // Open the new test folder.
+        ThreadUtils.runOnUiThreadBlocking(() -> { delegate.openFolder(testFolder); });
+
+        // Check that we are in the editable test folder.
+        Assert.assertEquals(TEST_FOLDER_TITLE, toolbar.getTitle());
+        Assert.assertEquals(SelectableListToolbar.NAVIGATION_BUTTON_BACK,
+                toolbar.getNavigationButtonForTests());
+        Assert.assertTrue(toolbar.getMenu().findItem(R.id.edit_menu_id).isVisible());
+
+        // Call BookmarkActionBar#onClick() to activate the navigation button.
+        ThreadUtils.runOnUiThreadBlocking(() -> { toolbar.onClick(toolbar); });
+
+        // Check that we are back in the mobile folder
+        Assert.assertEquals("Mobile bookmarks", toolbar.getTitle());
         Assert.assertEquals(SelectableListToolbar.NAVIGATION_BUTTON_BACK,
                 toolbar.getNavigationButtonForTests());
         Assert.assertFalse(toolbar.getMenu().findItem(R.id.edit_menu_id).isVisible());
 
         // Call BookmarkActionBar#onClick() to activate the navigation button.
-        ThreadUtils.runOnUiThreadBlocking(new Runnable() {
-            @Override
-            public void run() {
-                toolbar.onClick(toolbar);
-            }
-        });
+        ThreadUtils.runOnUiThreadBlocking(() -> { toolbar.onClick(toolbar); });
 
         // Check that we are in the root folder.
         Assert.assertEquals("Bookmarks", toolbar.getTitle());
@@ -345,7 +360,8 @@
 
     @Test
     @MediumTest
-    @Restriction({UiRestriction.RESTRICTION_TYPE_PHONE})
+    // https://crbug.com/779518
+    @DisableIf.Device(type = {UiDisableIf.TABLET, UiDisableIf.LARGETABLET})
     public void testCloseBookmarksWhileStillLoading() throws Exception {
         BookmarkManager.preventLoadingForTesting(true);
 
@@ -370,23 +386,39 @@
         BookmarkManager.preventLoadingForTesting(false);
     }
 
+    @Test
+    @MediumTest
+    // https://crbug.com/779518
+    @DisableIf.Device(type = {UiDisableIf.TABLET, UiDisableIf.LARGETABLET})
+    public void testEditHiddenWhileStillLoading() throws Exception {
+        BookmarkManager.preventLoadingForTesting(true);
+
+        openBookmarkManager();
+
+        final BookmarkActionBar toolbar =
+                mBookmarkActivity.getManagerForTesting().getToolbarForTests();
+        Assert.assertFalse(toolbar.getMenu().findItem(R.id.edit_menu_id).isVisible());
+
+        BookmarkManager.preventLoadingForTesting(false);
+    }
+
     /**
-     * Asserts the number of bookmark items being shown, taking large device deviders into account.
+     * Asserts the number of bookmark items being shown, taking large device dividers into account.
      *
-     * @param errorMessage              Error message to display in case the assert fails.
-     * @param exepectedOnRegularDevice  Expected count of items on small tablets.
-     * @param adapter                   Adapter to retrieve the bookmark item count from.
-     * @param delegate                  BookmarkDelegate to check the bookmark UI state.
+     * @param errorMessage Error message to display in case the assert fails.
+     * @param expectedOnRegularDevice Expected count of items on small tablets.
+     * @param adapter Adapter to retrieve the bookmark item count from.
+     * @param delegate BookmarkDelegate to check the bookmark UI state.
      */
-    private void assertBookmarkItems(final String errorMessage, final int exepectedOnRegularDevice,
-            final Adapter adapter, final BookmarkDelegate delegate) {
+    private void assertBookmarkItems(final String errorMessage, final int expectedOnRegularDevice,
+            final Adapter<?> adapter, final BookmarkDelegate delegate) {
         // TODO(twellington): Remove after bookmarks redesign is complete.
         // The +1 for large devices stems from the divider being added to the state folder for now,
         // which will offset all counts by one.
         final int expectedCount = DeviceFormFactor.isLargeTablet(mActivityTestRule.getActivity())
                         && BookmarkUIState.STATE_FOLDER == delegate.getCurrentState()
-                ? exepectedOnRegularDevice + 1
-                : exepectedOnRegularDevice;
+                ? expectedOnRegularDevice + 1
+                : expectedOnRegularDevice;
         Assert.assertEquals(errorMessage, expectedCount, adapter.getItemCount());
     }
 
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/contextmenu/TabularContextMenuUiTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/contextmenu/TabularContextMenuUiTest.java
index accbff73..e906776 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/contextmenu/TabularContextMenuUiTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/contextmenu/TabularContextMenuUiTest.java
@@ -27,6 +27,7 @@
 import org.chromium.chrome.test.ChromeActivityTestRule;
 import org.chromium.chrome.test.ChromeJUnit4ClassRunner;
 import org.chromium.content_public.common.Referrer;
+import org.chromium.ui.base.MenuSourceType;
 
 import java.util.ArrayList;
 import java.util.Collections;
@@ -52,13 +53,15 @@
         private MockMenuParams(int mediaType, String pageUrl, String linkUrl, String linkText,
                 String unfilteredLinkUrl, String srcUrl, String titleText,
                 boolean imageWasFetchedLoFi, Referrer referrer, boolean canSavemedia,
-                int touchPointXDp, int touchPointYDp) {
+                int touchPointXDp, int touchPointYDp, @MenuSourceType int sourceType) {
             super(mediaType, pageUrl, linkUrl, linkText, unfilteredLinkUrl, srcUrl, titleText,
-                    imageWasFetchedLoFi, referrer, canSavemedia, touchPointXDp, touchPointYDp);
+                    imageWasFetchedLoFi, referrer, canSavemedia, touchPointXDp, touchPointYDp,
+                    sourceType);
         }
 
         private MockMenuParams(String url) {
-            this(0, "", "", "", "", "", "", false, null, true, 0, 0);
+            this(0, "", "", "", "", "", "", false, null, true, 0, 0,
+                    MenuSourceType.MENU_SOURCE_TOUCH);
             mUrl = url;
         }
 
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchManagerTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchManagerTest.java
index 96bce1d..4ab9ef3b 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchManagerTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchManagerTest.java
@@ -3219,8 +3219,8 @@
             }
         });
 
-        KeyUtils.singleKeyEventView(InstrumentationRegistry.getInstrumentation(),
-                mActivityTestRule.getActivity().findViewById(R.id.find_query), KeyEvent.KEYCODE_T);
+        // Don't type anything to Find because that may cause scrolling which makes clicking in the
+        // page flaky.
 
         View findToolbar = mActivityTestRule.getActivity().findViewById(R.id.find_toolbar);
         Assert.assertTrue(findToolbar.isShown());
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/suggestions/HomeSheetUiCaptureTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/suggestions/HomeSheetUiCaptureTest.java
index d0ef0bb..9206074 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/suggestions/HomeSheetUiCaptureTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/suggestions/HomeSheetUiCaptureTest.java
@@ -8,6 +8,7 @@
 
 import static org.chromium.chrome.test.BottomSheetTestRule.waitForWindowUpdates;
 
+import android.support.test.InstrumentationRegistry;
 import android.support.test.filters.MediumTest;
 import android.support.v7.widget.RecyclerView;
 
@@ -28,6 +29,7 @@
 import org.chromium.chrome.browser.test.ScreenShooter;
 import org.chromium.chrome.browser.widget.bottomsheet.BottomSheet;
 import org.chromium.chrome.test.ChromeJUnit4ClassRunner;
+import org.chromium.chrome.test.util.MenuUtils;
 import org.chromium.chrome.test.util.browser.ChromeHome;
 import org.chromium.chrome.test.util.browser.suggestions.FakeSuggestionsSource;
 import org.chromium.chrome.test.util.browser.suggestions.SuggestionsDependenciesRule;
@@ -107,4 +109,18 @@
 
         mScreenShooter.shoot("All_dismissed");
     }
+
+    @Test
+    @MediumTest
+    @Feature({"UiCatalogue"})
+    @CommandLineFlags.Add(ChromeHome.ENABLE_FLAGS)
+    @ScreenShooter.Directory("NewTab")
+    public void testNewTab() {
+        // Select "New tab" from the menu.
+        MenuUtils.invokeCustomMenuActionSync(InstrumentationRegistry.getInstrumentation(),
+                mActivityRule.getActivity(), org.chromium.chrome.R.id.new_tab_menu_id);
+        waitForWindowUpdates();
+
+        mScreenShooter.shoot("NewTab");
+    }
 }
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/vr_shell/WebVrInputTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/vr_shell/WebVrInputTest.java
index 23e7957..1cf933c 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/vr_shell/WebVrInputTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/vr_shell/WebVrInputTest.java
@@ -128,6 +128,29 @@
         // Wait to enter VR
         VrTransitionUtils.enterPresentationAndWait(
                 mVrTestFramework.getFirstTabCvc(), mVrTestFramework.getFirstTabWebContents());
+        // The Gamepad API can flakily fail to detect the gamepad from a single button press, so
+        // spam it with button presses
+        boolean controllerConnected = false;
+        for (int i = 0; i < 10; i++) {
+            // The Gamepad API doesn't like detecting pressReleaseTouchpadButton() as it's too fast,
+            // so manually send the up and down events with a delay
+            controller.sendClickButtonToggleEvent();
+            SystemClock.sleep(100);
+            controller.sendClickButtonToggleEvent();
+            SystemClock.sleep(100);
+            if (VrTestFramework
+                            .runJavaScriptOrFail("index != -1", POLL_TIMEOUT_SHORT_MS,
+                                    mVrTestFramework.getFirstTabWebContents())
+                            .equals("true")) {
+                controllerConnected = true;
+                break;
+            }
+        }
+        Assert.assertTrue("Gamepad API detected controller", controllerConnected);
+        // Have a separate start condition so that the above presses/releases don't get
+        // accidentally detected during the actual test
+        VrTestFramework.runJavaScriptOrFail("canStartTest = true;", POLL_TIMEOUT_SHORT_MS,
+                mVrTestFramework.getFirstTabWebContents());
         // Send a controller click and wait for JavaScript to receive it.
         controller.sendClickButtonToggleEvent();
         VrTestFramework.waitOnJavaScriptStep(mVrTestFramework.getFirstTabWebContents());
@@ -148,6 +171,10 @@
     public void testScreenTapsRegisteredOnCardboard() throws InterruptedException {
         mVrTestFramework.loadUrlAndAwaitInitialization(
                 VrTestFramework.getHtmlTestFile("test_gamepad_button"), PAGE_LOAD_TIMEOUT_S);
+        // This boolean is used by testControllerClicksRegisteredOnDaydream to prevent some
+        // flakiness, but is unnecessary here, so set immediately
+        VrTestFramework.runJavaScriptOrFail("canStartTest = true;", POLL_TIMEOUT_SHORT_MS,
+                mVrTestFramework.getFirstTabWebContents());
         // Wait to enter VR
         VrTransitionUtils.enterPresentationAndWait(
                 mVrTestFramework.getFirstTabCvc(), mVrTestFramework.getFirstTabWebContents());
diff --git a/chrome/android/junit/src/org/chromium/chrome/browser/contextmenu/ChromeContextMenuPopulatorTest.java b/chrome/android/junit/src/org/chromium/chrome/browser/contextmenu/ChromeContextMenuPopulatorTest.java
index 4aba388e..305daac 100644
--- a/chrome/android/junit/src/org/chromium/chrome/browser/contextmenu/ChromeContextMenuPopulatorTest.java
+++ b/chrome/android/junit/src/org/chromium/chrome/browser/contextmenu/ChromeContextMenuPopulatorTest.java
@@ -28,6 +28,7 @@
 import org.chromium.chrome.browser.search_engines.TemplateUrlService;
 import org.chromium.chrome.test.util.browser.Features;
 import org.chromium.testing.local.LocalRobolectricTestRunner;
+import org.chromium.ui.base.MenuSourceType;
 
 import java.util.ArrayList;
 import java.util.List;
@@ -147,17 +148,19 @@
     }
 
     private static ContextMenuParams createLinkContextParams() {
-        return new ContextMenuParams(
-                0, PAGE_URL, LINK_URL, LINK_TEXT, "", "", "", false, null, false, 0, 0);
+        return new ContextMenuParams(0, PAGE_URL, LINK_URL, LINK_TEXT, "", "", "", false, null,
+                false, 0, 0, MenuSourceType.MENU_SOURCE_TOUCH);
     }
 
     private static ContextMenuParams createImageContextParams() {
         return new ContextMenuParams(WebContextMenuMediaType.MEDIA_TYPE_IMAGE, PAGE_URL, "", "",
-                IMAGE_SRC_URL, IMAGE_TITLE_TEXT, "", false, null, true, 0, 0);
+                IMAGE_SRC_URL, IMAGE_TITLE_TEXT, "", false, null, true, 0, 0,
+                MenuSourceType.MENU_SOURCE_TOUCH);
     }
 
     private static ContextMenuParams createImageLinkContextParams() {
         return new ContextMenuParams(WebContextMenuMediaType.MEDIA_TYPE_IMAGE, PAGE_URL, PAGE_URL,
-                LINK_URL, IMAGE_SRC_URL, IMAGE_TITLE_TEXT, "", false, null, true, 0, 0);
+                LINK_URL, IMAGE_SRC_URL, IMAGE_TITLE_TEXT, "", false, null, true, 0, 0,
+                MenuSourceType.MENU_SOURCE_TOUCH);
     }
 }
diff --git a/chrome/android/junit/src/org/chromium/chrome/browser/omnibox/geo/GeolocationHeaderTest.java b/chrome/android/junit/src/org/chromium/chrome/browser/omnibox/geo/GeolocationHeaderTest.java
deleted file mode 100644
index ebfe4a9..0000000
--- a/chrome/android/junit/src/org/chromium/chrome/browser/omnibox/geo/GeolocationHeaderTest.java
+++ /dev/null
@@ -1,338 +0,0 @@
-// Copyright 2017 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-package org.chromium.chrome.browser.omnibox.geo;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertNull;
-import static org.mockito.Mockito.when;
-
-import android.content.Context;
-import android.location.Location;
-import android.os.Build;
-import android.os.SystemClock;
-
-import org.junit.Before;
-import org.junit.Rule;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.mockito.Mock;
-import org.mockito.MockitoAnnotations;
-import org.robolectric.annotation.Config;
-import org.robolectric.annotation.Implementation;
-import org.robolectric.annotation.Implements;
-
-import org.chromium.base.library_loader.ProcessInitException;
-import org.chromium.base.metrics.RecordHistogram;
-import org.chromium.chrome.browser.omnibox.geo.GeolocationHeaderTest.ShadowRecordHistogram;
-import org.chromium.chrome.browser.omnibox.geo.GeolocationHeaderTest.ShadowUrlUtilities;
-import org.chromium.chrome.browser.omnibox.geo.GeolocationHeaderTest.ShadowWebsitePreferenceBridge;
-import org.chromium.chrome.browser.omnibox.geo.VisibleNetworks.VisibleCell;
-import org.chromium.chrome.browser.omnibox.geo.VisibleNetworks.VisibleWifi;
-import org.chromium.chrome.browser.preferences.website.WebsitePreferenceBridge;
-import org.chromium.chrome.browser.tab.Tab;
-import org.chromium.chrome.browser.util.UrlUtilities;
-import org.chromium.chrome.test.util.browser.Features;
-import org.chromium.testing.local.LocalRobolectricTestRunner;
-
-import java.util.Arrays;
-import java.util.HashSet;
-
-/**
- * Robolectric tests for {@link GeolocationHeader}.
- */
-@RunWith(LocalRobolectricTestRunner.class)
-@Config(manifest = Config.NONE,
-        shadows = {ShadowUrlUtilities.class, ShadowRecordHistogram.class,
-                ShadowWebsitePreferenceBridge.class})
-public class GeolocationHeaderTest {
-    private static final String SEARCH_URL = "https://www.google.com/search?q=potatoes";
-
-    private static final double LOCATION_LAT = 20.3;
-    private static final double LOCATION_LONG = 155.8;
-    private static final float LOCATION_ACCURACY = 20f;
-    private static final long LOCATION_TIME = 400;
-    // Encoded location for LOCATION_LAT, LOCATION_LONG, LOCATION_ACCURACY and LOCATION_TIME.
-    private static final String ENCODED_PROTO_LOCATION = "CAEQDBiAtRgqCg3AiBkMFYAx3Vw9AECcRg==";
-
-    private static final VisibleWifi VISIBLE_WIFI1 =
-            VisibleWifi.create("ssid1", "11:11:11:11:11:11", -1, 10L);
-    private static final VisibleWifi VISIBLE_WIFI_NO_LEVEL =
-            VisibleWifi.create("ssid1", "11:11:11:11:11:11", null, 10L);
-    private static final VisibleWifi VISIBLE_WIFI2 =
-            VisibleWifi.create("ssid2", "11:11:11:11:11:12", -10, 20L);
-    private static final VisibleWifi VISIBLE_WIFI3 =
-            VisibleWifi.create("ssid3", "11:11:11:11:11:13", -30, 30L);
-    private static final VisibleWifi VISIBLE_WIFI_NOMAP =
-            VisibleWifi.create("ssid1_nomap", "11:11:11:11:11:11", -1, 10L);
-    private static final VisibleWifi VISIBLE_WIFI_OPTOUT =
-            VisibleWifi.create("ssid1_optout", "11:11:11:11:11:11", -1, 10L);
-    private static final VisibleCell VISIBLE_CELL1 =
-            VisibleCell.builder(VisibleCell.CDMA_RADIO_TYPE)
-                    .setCellId(10)
-                    .setLocationAreaCode(11)
-                    .setMobileCountryCode(12)
-                    .setMobileNetworkCode(13)
-                    .setTimestamp(10L)
-                    .build();
-    private static final VisibleCell VISIBLE_CELL2 = VisibleCell.builder(VisibleCell.GSM_RADIO_TYPE)
-                                                             .setCellId(20)
-                                                             .setLocationAreaCode(21)
-                                                             .setMobileCountryCode(22)
-                                                             .setMobileNetworkCode(23)
-                                                             .setTimestamp(20L)
-                                                             .build();
-    // Encoded proto location for VISIBLE_WIFI1 connected, VISIBLE_WIFI3 not connected,
-    // VISIBLE_CELL1 connected, VISIBLE_CELL2 not connected.
-    private static final String ENCODED_PROTO_VISIBLE_NETWORKS =
-            "CAEQDLoBJAoeChExMToxMToxMToxMToxMToxMRD___________8BGAEgCroBJAoeChExMToxMToxMToxMTox"
-            + "MToxMxDi__________8BGAAgHroBEBIKCAMQChgLIAwoDRgBIAq6ARASCggBEBQYFSAWKBcYACAU";
-
-    private static int sRefreshVisibleNetworksRequests = 0;
-    private static int sRefreshLastKnownLocation = 0;
-
-    @Rule
-    public Features.Processor mFeatureProcessor = new Features.Processor();
-
-    @Mock
-    private Tab mTab;
-
-    @Before
-    public void setUp() {
-        MockitoAnnotations.initMocks(this);
-        GeolocationTracker.setLocationAgeForTesting(null);
-        GeolocationHeader.setLocationSourceForTesting(
-                GeolocationHeader.LOCATION_SOURCE_HIGH_ACCURACY);
-        GeolocationHeader.setAppPermissionGrantedForTesting(true);
-        when(mTab.isIncognito()).thenReturn(false);
-        sRefreshVisibleNetworksRequests = 0;
-        sRefreshLastKnownLocation = 0;
-    }
-
-    @Test
-    public void testEncodeProtoLocation() throws ProcessInitException {
-        Location location = generateMockLocation("should_not_matter", LOCATION_TIME);
-        String encodedProtoLocation = GeolocationHeader.encodeProtoLocation(location);
-        assertEquals(ENCODED_PROTO_LOCATION, encodedProtoLocation);
-    }
-
-    @Test
-    public void voidtestTrimVisibleNetworks() throws ProcessInitException {
-        VisibleNetworks visibleNetworks =
-                VisibleNetworks.create(VISIBLE_WIFI_NO_LEVEL, VISIBLE_CELL1,
-                        new HashSet(Arrays.asList(VISIBLE_WIFI1, VISIBLE_WIFI2, VISIBLE_WIFI3)),
-                        new HashSet(Arrays.asList(VISIBLE_CELL1, VISIBLE_CELL2)));
-
-        // We expect trimming to replace connected Wifi (since it will have level), and select only
-        // the visible wifi different from the connected one, with strongest level.
-        VisibleNetworks expectedTrimmed = VisibleNetworks.create(VISIBLE_WIFI1, VISIBLE_CELL1,
-                new HashSet(Arrays.asList(VISIBLE_WIFI3)),
-                new HashSet(Arrays.asList(VISIBLE_CELL2)));
-
-        VisibleNetworks trimmed = GeolocationHeader.trimVisibleNetworks(visibleNetworks);
-        assertEquals(expectedTrimmed, trimmed);
-    }
-
-    @Test
-    public void testTrimVisibleNetworksEmptyOrNull() throws ProcessInitException {
-        VisibleNetworks visibleNetworks = VisibleNetworks.create(
-                VisibleWifi.create("whatever", null, null, null),
-                null, new HashSet(), new HashSet());
-        assertNull(GeolocationHeader.trimVisibleNetworks(visibleNetworks));
-        assertNull(GeolocationHeader.trimVisibleNetworks(null));
-    }
-
-    @Test
-    public void testEncodeProtoVisibleNetworks() throws ProcessInitException {
-        VisibleNetworks visibleNetworks = VisibleNetworks.create(VISIBLE_WIFI1, VISIBLE_CELL1,
-                new HashSet(Arrays.asList(VISIBLE_WIFI3)),
-                new HashSet(Arrays.asList(VISIBLE_CELL2)));
-        String encodedProtoLocation = GeolocationHeader.encodeProtoVisibleNetworks(visibleNetworks);
-        assertEquals(ENCODED_PROTO_VISIBLE_NETWORKS, encodedProtoLocation);
-    }
-
-    @Test
-    public void testEncodeProtoVisibleNetworksEmptyOrNull() throws ProcessInitException {
-        VisibleNetworks visibleNetworks =
-                VisibleNetworks.create(null, null, new HashSet(), new HashSet());
-        assertNull(GeolocationHeader.encodeProtoVisibleNetworks(visibleNetworks));
-        assertNull(GeolocationHeader.encodeProtoVisibleNetworks(null));
-    }
-
-    @Test
-    public void testEncodeProtoVisibleNetworksExcludeNoMapOrOptout() throws ProcessInitException {
-        VisibleNetworks visibleNetworks = VisibleNetworks.create(VISIBLE_WIFI_NOMAP, null,
-                new HashSet(Arrays.asList(VISIBLE_WIFI_OPTOUT)), new HashSet());
-        String encodedProtoLocation = GeolocationHeader.encodeProtoVisibleNetworks(visibleNetworks);
-        assertNull(encodedProtoLocation);
-    }
-
-    @Test
-    public void testGetGeoHeaderFreshLocation() throws ProcessInitException {
-        VisibleNetworks visibleNetworks = VisibleNetworks.create(VISIBLE_WIFI1, VISIBLE_CELL1,
-                new HashSet(Arrays.asList(VISIBLE_WIFI3)),
-                new HashSet(Arrays.asList(VISIBLE_CELL2)));
-        VisibleNetworksTracker.setVisibleNetworksForTesting(visibleNetworks);
-        Location location = generateMockLocation("should_not_matter", LOCATION_TIME);
-        GeolocationTracker.setLocationForTesting(location, null);
-        // 1 minute should be good enough and not require visible networks.
-        GeolocationTracker.setLocationAgeForTesting(1 * 60 * 1000L);
-        String header = GeolocationHeader.getGeoHeader(SEARCH_URL, mTab);
-        assertEquals("X-Geo: w " + ENCODED_PROTO_LOCATION, header);
-    }
-
-    @Test
-    public void testGetGeoHeaderLocationMissing() throws ProcessInitException {
-        VisibleNetworks visibleNetworks = VisibleNetworks.create(VISIBLE_WIFI1, VISIBLE_CELL1,
-                new HashSet(Arrays.asList(VISIBLE_WIFI3)),
-                new HashSet(Arrays.asList(VISIBLE_CELL2)));
-        VisibleNetworksTracker.setVisibleNetworksForTesting(visibleNetworks);
-        GeolocationTracker.setLocationForTesting(null, null);
-        String header = GeolocationHeader.getGeoHeader(SEARCH_URL, mTab);
-        assertEquals("X-Geo: w " + ENCODED_PROTO_VISIBLE_NETWORKS, header);
-    }
-
-    @Test
-    public void testGetGeoHeaderOldLocationHighAccuracy() throws ProcessInitException {
-        GeolocationHeader.setLocationSourceForTesting(
-                GeolocationHeader.LOCATION_SOURCE_HIGH_ACCURACY);
-        // Visible networks should be included
-        checkOldLocation(
-                "X-Geo: w " + ENCODED_PROTO_LOCATION + " w " + ENCODED_PROTO_VISIBLE_NETWORKS);
-    }
-
-    @Test
-    public void testGetGeoHeaderOldLocationBatterySaving() throws ProcessInitException {
-        GeolocationHeader.setLocationSourceForTesting(
-                GeolocationHeader.LOCATION_SOURCE_BATTERY_SAVING);
-        checkOldLocation(
-                "X-Geo: w " + ENCODED_PROTO_LOCATION + " w " + ENCODED_PROTO_VISIBLE_NETWORKS);
-    }
-
-    @Test
-    public void testGetGeoHeaderOldLocationGpsOnly() throws ProcessInitException {
-        GeolocationHeader.setLocationSourceForTesting(GeolocationHeader.LOCATION_SOURCE_GPS_ONLY);
-        // In GPS only mode, networks should never be included.
-        checkOldLocation("X-Geo: w " + ENCODED_PROTO_LOCATION);
-    }
-
-    @Test
-    public void testGetGeoHeaderOldLocationLocationOff() throws ProcessInitException {
-        GeolocationHeader.setLocationSourceForTesting(GeolocationHeader.LOCATION_SOURCE_MASTER_OFF);
-        // If the master switch is off, networks should never be included (old location might).
-        checkOldLocation("X-Geo: w " + ENCODED_PROTO_LOCATION);
-    }
-
-    @Test
-    public void testGetGeoHeaderOldLocationAppPermissionDenied() throws ProcessInitException {
-        GeolocationHeader.setLocationSourceForTesting(
-                GeolocationHeader.LOCATION_SOURCE_HIGH_ACCURACY);
-        GeolocationHeader.setAppPermissionGrantedForTesting(false);
-        // Nothing should be included when app permission is missing.
-        checkOldLocation(null);
-    }
-
-    @Test
-    @Config(shadows = {ShadowVisibleNetworksTracker.class, ShadowGeolocationTracker.class})
-    public void testPrimeLocationForGeoHeader() throws ProcessInitException {
-        GeolocationHeader.primeLocationForGeoHeader();
-        assertEquals(1, sRefreshLastKnownLocation);
-        assertEquals(1, sRefreshVisibleNetworksRequests);
-    }
-
-    @Test
-    @Config(shadows = {ShadowVisibleNetworksTracker.class, ShadowGeolocationTracker.class})
-    public void testPrimeLocationForGeoHeaderPermissionOff() throws ProcessInitException {
-        GeolocationHeader.setAppPermissionGrantedForTesting(false);
-        GeolocationHeader.primeLocationForGeoHeader();
-        assertEquals(0, sRefreshLastKnownLocation);
-        assertEquals(0, sRefreshVisibleNetworksRequests);
-    }
-
-    private void checkOldLocation(String expectedHeader) throws ProcessInitException {
-        VisibleNetworks visibleNetworks = VisibleNetworks.create(VISIBLE_WIFI1, VISIBLE_CELL1,
-                new HashSet(Arrays.asList(VISIBLE_WIFI3)),
-                new HashSet(Arrays.asList(VISIBLE_CELL2)));
-        VisibleNetworksTracker.setVisibleNetworksForTesting(visibleNetworks);
-        Location location = generateMockLocation("should_not_matter", LOCATION_TIME);
-        GeolocationTracker.setLocationForTesting(location, null);
-        // 6 minutes should hit the age limit, but the feature is off.
-        GeolocationTracker.setLocationAgeForTesting(6 * 60 * 1000L);
-        String header = GeolocationHeader.getGeoHeader(SEARCH_URL, mTab);
-        assertEquals(expectedHeader, header);
-    }
-
-    private Location generateMockLocation(String provider, long time) {
-        Location location = new Location(provider);
-        location.setLatitude(LOCATION_LAT);
-        location.setLongitude(LOCATION_LONG);
-        location.setAccuracy(LOCATION_ACCURACY);
-        location.setTime(time);
-        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
-            location.setElapsedRealtimeNanos(SystemClock.elapsedRealtimeNanos()
-                    + 1000000 * (time - System.currentTimeMillis()));
-        }
-        return location;
-    }
-
-    /**
-     * Shadow for UrlUtilities
-     */
-    @Implements(UrlUtilities.class)
-    public static class ShadowUrlUtilities {
-        @Implementation
-        public static boolean nativeIsGoogleSearchUrl(String url) {
-            return true;
-        }
-    }
-
-    /**
-     * Shadow for RecordHistogram
-     */
-    @Implements(RecordHistogram.class)
-    public static class ShadowRecordHistogram {
-        @Implementation
-        public static void recordEnumeratedHistogram(String name, int sample, int boundary) {
-            // Noop.
-        }
-    }
-
-    /**
-     * Shadow for WebsitePreferenceBridge
-     */
-    @Implements(WebsitePreferenceBridge.class)
-    public static class ShadowWebsitePreferenceBridge {
-        @Implementation
-        public static boolean shouldUseDSEGeolocationSetting(String origin, boolean isIncognito) {
-            return true;
-        }
-
-        @Implementation
-        public static boolean getDSEGeolocationSetting() {
-            return true;
-        }
-    }
-
-    /**
-     * Shadow for VisibleNetworksTracker
-     */
-    @Implements(VisibleNetworksTracker.class)
-    public static class ShadowVisibleNetworksTracker {
-        @Implementation
-        public static void refreshVisibleNetworks(final Context context) {
-            sRefreshVisibleNetworksRequests++;
-        }
-    }
-
-    /**
-     * Shadow for GeolocationTracker
-     */
-    @Implements(GeolocationTracker.class)
-    public static class ShadowGeolocationTracker {
-        @Implementation
-        public static void refreshLastKnownLocation(Context context, long maxAge) {
-            sRefreshLastKnownLocation++;
-        }
-    }
-}
diff --git a/chrome/android/junit/src/org/chromium/chrome/browser/omnibox/geo/GeolocationHeaderUnitTest.java b/chrome/android/junit/src/org/chromium/chrome/browser/omnibox/geo/GeolocationHeaderUnitTest.java
new file mode 100644
index 0000000..7981580
--- /dev/null
+++ b/chrome/android/junit/src/org/chromium/chrome/browser/omnibox/geo/GeolocationHeaderUnitTest.java
@@ -0,0 +1,338 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+package org.chromium.chrome.browser.omnibox.geo;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNull;
+import static org.mockito.Mockito.when;
+
+import android.content.Context;
+import android.location.Location;
+import android.os.Build;
+import android.os.SystemClock;
+
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.robolectric.annotation.Config;
+import org.robolectric.annotation.Implementation;
+import org.robolectric.annotation.Implements;
+
+import org.chromium.base.library_loader.ProcessInitException;
+import org.chromium.base.metrics.RecordHistogram;
+import org.chromium.chrome.browser.omnibox.geo.GeolocationHeaderUnitTest.ShadowRecordHistogram;
+import org.chromium.chrome.browser.omnibox.geo.GeolocationHeaderUnitTest.ShadowUrlUtilities;
+import org.chromium.chrome.browser.omnibox.geo.GeolocationHeaderUnitTest.ShadowWebsitePreferenceBridge;
+import org.chromium.chrome.browser.omnibox.geo.VisibleNetworks.VisibleCell;
+import org.chromium.chrome.browser.omnibox.geo.VisibleNetworks.VisibleWifi;
+import org.chromium.chrome.browser.preferences.website.WebsitePreferenceBridge;
+import org.chromium.chrome.browser.tab.Tab;
+import org.chromium.chrome.browser.util.UrlUtilities;
+import org.chromium.chrome.test.util.browser.Features;
+import org.chromium.testing.local.LocalRobolectricTestRunner;
+
+import java.util.Arrays;
+import java.util.HashSet;
+
+/**
+ * Robolectric tests for {@link GeolocationHeader}.
+ */
+@RunWith(LocalRobolectricTestRunner.class)
+@Config(manifest = Config.NONE,
+        shadows = {ShadowUrlUtilities.class, ShadowRecordHistogram.class,
+                ShadowWebsitePreferenceBridge.class})
+public class GeolocationHeaderUnitTest {
+    private static final String SEARCH_URL = "https://www.google.com/search?q=potatoes";
+
+    private static final double LOCATION_LAT = 20.3;
+    private static final double LOCATION_LONG = 155.8;
+    private static final float LOCATION_ACCURACY = 20f;
+    private static final long LOCATION_TIME = 400;
+    // Encoded location for LOCATION_LAT, LOCATION_LONG, LOCATION_ACCURACY and LOCATION_TIME.
+    private static final String ENCODED_PROTO_LOCATION = "CAEQDBiAtRgqCg3AiBkMFYAx3Vw9AECcRg==";
+
+    private static final VisibleWifi VISIBLE_WIFI1 =
+            VisibleWifi.create("ssid1", "11:11:11:11:11:11", -1, 10L);
+    private static final VisibleWifi VISIBLE_WIFI_NO_LEVEL =
+            VisibleWifi.create("ssid1", "11:11:11:11:11:11", null, 10L);
+    private static final VisibleWifi VISIBLE_WIFI2 =
+            VisibleWifi.create("ssid2", "11:11:11:11:11:12", -10, 20L);
+    private static final VisibleWifi VISIBLE_WIFI3 =
+            VisibleWifi.create("ssid3", "11:11:11:11:11:13", -30, 30L);
+    private static final VisibleWifi VISIBLE_WIFI_NOMAP =
+            VisibleWifi.create("ssid1_nomap", "11:11:11:11:11:11", -1, 10L);
+    private static final VisibleWifi VISIBLE_WIFI_OPTOUT =
+            VisibleWifi.create("ssid1_optout", "11:11:11:11:11:11", -1, 10L);
+    private static final VisibleCell VISIBLE_CELL1 =
+            VisibleCell.builder(VisibleCell.CDMA_RADIO_TYPE)
+                    .setCellId(10)
+                    .setLocationAreaCode(11)
+                    .setMobileCountryCode(12)
+                    .setMobileNetworkCode(13)
+                    .setTimestamp(10L)
+                    .build();
+    private static final VisibleCell VISIBLE_CELL2 = VisibleCell.builder(VisibleCell.GSM_RADIO_TYPE)
+                                                             .setCellId(20)
+                                                             .setLocationAreaCode(21)
+                                                             .setMobileCountryCode(22)
+                                                             .setMobileNetworkCode(23)
+                                                             .setTimestamp(20L)
+                                                             .build();
+    // Encoded proto location for VISIBLE_WIFI1 connected, VISIBLE_WIFI3 not connected,
+    // VISIBLE_CELL1 connected, VISIBLE_CELL2 not connected.
+    private static final String ENCODED_PROTO_VISIBLE_NETWORKS =
+            "CAEQDLoBJAoeChExMToxMToxMToxMToxMToxMRD___________8BGAEgCroBJAoeChExMToxMToxMToxMTox"
+            + "MToxMxDi__________8BGAAgHroBEBIKCAMQChgLIAwoDRgBIAq6ARASCggBEBQYFSAWKBcYACAU";
+
+    private static int sRefreshVisibleNetworksRequests = 0;
+    private static int sRefreshLastKnownLocation = 0;
+
+    @Rule
+    public Features.Processor mFeatureProcessor = new Features.Processor();
+
+    @Mock
+    private Tab mTab;
+
+    @Before
+    public void setUp() {
+        MockitoAnnotations.initMocks(this);
+        GeolocationTracker.setLocationAgeForTesting(null);
+        GeolocationHeader.setLocationSourceForTesting(
+                GeolocationHeader.LOCATION_SOURCE_HIGH_ACCURACY);
+        GeolocationHeader.setAppPermissionGrantedForTesting(true);
+        when(mTab.isIncognito()).thenReturn(false);
+        sRefreshVisibleNetworksRequests = 0;
+        sRefreshLastKnownLocation = 0;
+    }
+
+    @Test
+    public void testEncodeProtoLocation() throws ProcessInitException {
+        Location location = generateMockLocation("should_not_matter", LOCATION_TIME);
+        String encodedProtoLocation = GeolocationHeader.encodeProtoLocation(location);
+        assertEquals(ENCODED_PROTO_LOCATION, encodedProtoLocation);
+    }
+
+    @Test
+    public void voidtestTrimVisibleNetworks() throws ProcessInitException {
+        VisibleNetworks visibleNetworks =
+                VisibleNetworks.create(VISIBLE_WIFI_NO_LEVEL, VISIBLE_CELL1,
+                        new HashSet(Arrays.asList(VISIBLE_WIFI1, VISIBLE_WIFI2, VISIBLE_WIFI3)),
+                        new HashSet(Arrays.asList(VISIBLE_CELL1, VISIBLE_CELL2)));
+
+        // We expect trimming to replace connected Wifi (since it will have level), and select only
+        // the visible wifi different from the connected one, with strongest level.
+        VisibleNetworks expectedTrimmed = VisibleNetworks.create(VISIBLE_WIFI1, VISIBLE_CELL1,
+                new HashSet(Arrays.asList(VISIBLE_WIFI3)),
+                new HashSet(Arrays.asList(VISIBLE_CELL2)));
+
+        VisibleNetworks trimmed = GeolocationHeader.trimVisibleNetworks(visibleNetworks);
+        assertEquals(expectedTrimmed, trimmed);
+    }
+
+    @Test
+    public void testTrimVisibleNetworksEmptyOrNull() throws ProcessInitException {
+        VisibleNetworks visibleNetworks =
+                VisibleNetworks.create(VisibleWifi.create("whatever", null, null, null), null,
+                        new HashSet(), new HashSet());
+        assertNull(GeolocationHeader.trimVisibleNetworks(visibleNetworks));
+        assertNull(GeolocationHeader.trimVisibleNetworks(null));
+    }
+
+    @Test
+    public void testEncodeProtoVisibleNetworks() throws ProcessInitException {
+        VisibleNetworks visibleNetworks = VisibleNetworks.create(VISIBLE_WIFI1, VISIBLE_CELL1,
+                new HashSet(Arrays.asList(VISIBLE_WIFI3)),
+                new HashSet(Arrays.asList(VISIBLE_CELL2)));
+        String encodedProtoLocation = GeolocationHeader.encodeProtoVisibleNetworks(visibleNetworks);
+        assertEquals(ENCODED_PROTO_VISIBLE_NETWORKS, encodedProtoLocation);
+    }
+
+    @Test
+    public void testEncodeProtoVisibleNetworksEmptyOrNull() throws ProcessInitException {
+        VisibleNetworks visibleNetworks =
+                VisibleNetworks.create(null, null, new HashSet(), new HashSet());
+        assertNull(GeolocationHeader.encodeProtoVisibleNetworks(visibleNetworks));
+        assertNull(GeolocationHeader.encodeProtoVisibleNetworks(null));
+    }
+
+    @Test
+    public void testEncodeProtoVisibleNetworksExcludeNoMapOrOptout() throws ProcessInitException {
+        VisibleNetworks visibleNetworks = VisibleNetworks.create(VISIBLE_WIFI_NOMAP, null,
+                new HashSet(Arrays.asList(VISIBLE_WIFI_OPTOUT)), new HashSet());
+        String encodedProtoLocation = GeolocationHeader.encodeProtoVisibleNetworks(visibleNetworks);
+        assertNull(encodedProtoLocation);
+    }
+
+    @Test
+    public void testGetGeoHeaderFreshLocation() throws ProcessInitException {
+        VisibleNetworks visibleNetworks = VisibleNetworks.create(VISIBLE_WIFI1, VISIBLE_CELL1,
+                new HashSet(Arrays.asList(VISIBLE_WIFI3)),
+                new HashSet(Arrays.asList(VISIBLE_CELL2)));
+        VisibleNetworksTracker.setVisibleNetworksForTesting(visibleNetworks);
+        Location location = generateMockLocation("should_not_matter", LOCATION_TIME);
+        GeolocationTracker.setLocationForTesting(location, null);
+        // 1 minute should be good enough and not require visible networks.
+        GeolocationTracker.setLocationAgeForTesting(1 * 60 * 1000L);
+        String header = GeolocationHeader.getGeoHeader(SEARCH_URL, mTab);
+        assertEquals("X-Geo: w " + ENCODED_PROTO_LOCATION, header);
+    }
+
+    @Test
+    public void testGetGeoHeaderLocationMissing() throws ProcessInitException {
+        VisibleNetworks visibleNetworks = VisibleNetworks.create(VISIBLE_WIFI1, VISIBLE_CELL1,
+                new HashSet(Arrays.asList(VISIBLE_WIFI3)),
+                new HashSet(Arrays.asList(VISIBLE_CELL2)));
+        VisibleNetworksTracker.setVisibleNetworksForTesting(visibleNetworks);
+        GeolocationTracker.setLocationForTesting(null, null);
+        String header = GeolocationHeader.getGeoHeader(SEARCH_URL, mTab);
+        assertEquals("X-Geo: w " + ENCODED_PROTO_VISIBLE_NETWORKS, header);
+    }
+
+    @Test
+    public void testGetGeoHeaderOldLocationHighAccuracy() throws ProcessInitException {
+        GeolocationHeader.setLocationSourceForTesting(
+                GeolocationHeader.LOCATION_SOURCE_HIGH_ACCURACY);
+        // Visible networks should be included
+        checkOldLocation(
+                "X-Geo: w " + ENCODED_PROTO_LOCATION + " w " + ENCODED_PROTO_VISIBLE_NETWORKS);
+    }
+
+    @Test
+    public void testGetGeoHeaderOldLocationBatterySaving() throws ProcessInitException {
+        GeolocationHeader.setLocationSourceForTesting(
+                GeolocationHeader.LOCATION_SOURCE_BATTERY_SAVING);
+        checkOldLocation(
+                "X-Geo: w " + ENCODED_PROTO_LOCATION + " w " + ENCODED_PROTO_VISIBLE_NETWORKS);
+    }
+
+    @Test
+    public void testGetGeoHeaderOldLocationGpsOnly() throws ProcessInitException {
+        GeolocationHeader.setLocationSourceForTesting(GeolocationHeader.LOCATION_SOURCE_GPS_ONLY);
+        // In GPS only mode, networks should never be included.
+        checkOldLocation("X-Geo: w " + ENCODED_PROTO_LOCATION);
+    }
+
+    @Test
+    public void testGetGeoHeaderOldLocationLocationOff() throws ProcessInitException {
+        GeolocationHeader.setLocationSourceForTesting(GeolocationHeader.LOCATION_SOURCE_MASTER_OFF);
+        // If the master switch is off, networks should never be included (old location might).
+        checkOldLocation("X-Geo: w " + ENCODED_PROTO_LOCATION);
+    }
+
+    @Test
+    public void testGetGeoHeaderOldLocationAppPermissionDenied() throws ProcessInitException {
+        GeolocationHeader.setLocationSourceForTesting(
+                GeolocationHeader.LOCATION_SOURCE_HIGH_ACCURACY);
+        GeolocationHeader.setAppPermissionGrantedForTesting(false);
+        // Nothing should be included when app permission is missing.
+        checkOldLocation(null);
+    }
+
+    @Test
+    @Config(shadows = {ShadowVisibleNetworksTracker.class, ShadowGeolocationTracker.class})
+    public void testPrimeLocationForGeoHeader() throws ProcessInitException {
+        GeolocationHeader.primeLocationForGeoHeader();
+        assertEquals(1, sRefreshLastKnownLocation);
+        assertEquals(1, sRefreshVisibleNetworksRequests);
+    }
+
+    @Test
+    @Config(shadows = {ShadowVisibleNetworksTracker.class, ShadowGeolocationTracker.class})
+    public void testPrimeLocationForGeoHeaderPermissionOff() throws ProcessInitException {
+        GeolocationHeader.setAppPermissionGrantedForTesting(false);
+        GeolocationHeader.primeLocationForGeoHeader();
+        assertEquals(0, sRefreshLastKnownLocation);
+        assertEquals(0, sRefreshVisibleNetworksRequests);
+    }
+
+    private void checkOldLocation(String expectedHeader) throws ProcessInitException {
+        VisibleNetworks visibleNetworks = VisibleNetworks.create(VISIBLE_WIFI1, VISIBLE_CELL1,
+                new HashSet(Arrays.asList(VISIBLE_WIFI3)),
+                new HashSet(Arrays.asList(VISIBLE_CELL2)));
+        VisibleNetworksTracker.setVisibleNetworksForTesting(visibleNetworks);
+        Location location = generateMockLocation("should_not_matter", LOCATION_TIME);
+        GeolocationTracker.setLocationForTesting(location, null);
+        // 6 minutes should hit the age limit, but the feature is off.
+        GeolocationTracker.setLocationAgeForTesting(6 * 60 * 1000L);
+        String header = GeolocationHeader.getGeoHeader(SEARCH_URL, mTab);
+        assertEquals(expectedHeader, header);
+    }
+
+    private Location generateMockLocation(String provider, long time) {
+        Location location = new Location(provider);
+        location.setLatitude(LOCATION_LAT);
+        location.setLongitude(LOCATION_LONG);
+        location.setAccuracy(LOCATION_ACCURACY);
+        location.setTime(time);
+        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
+            location.setElapsedRealtimeNanos(SystemClock.elapsedRealtimeNanos()
+                    + 1000000 * (time - System.currentTimeMillis()));
+        }
+        return location;
+    }
+
+    /**
+     * Shadow for UrlUtilities
+     */
+    @Implements(UrlUtilities.class)
+    public static class ShadowUrlUtilities {
+        @Implementation
+        public static boolean nativeIsGoogleSearchUrl(String url) {
+            return true;
+        }
+    }
+
+    /**
+     * Shadow for RecordHistogram
+     */
+    @Implements(RecordHistogram.class)
+    public static class ShadowRecordHistogram {
+        @Implementation
+        public static void recordEnumeratedHistogram(String name, int sample, int boundary) {
+            // Noop.
+        }
+    }
+
+    /**
+     * Shadow for WebsitePreferenceBridge
+     */
+    @Implements(WebsitePreferenceBridge.class)
+    public static class ShadowWebsitePreferenceBridge {
+        @Implementation
+        public static boolean shouldUseDSEGeolocationSetting(String origin, boolean isIncognito) {
+            return true;
+        }
+
+        @Implementation
+        public static boolean getDSEGeolocationSetting() {
+            return true;
+        }
+    }
+
+    /**
+     * Shadow for VisibleNetworksTracker
+     */
+    @Implements(VisibleNetworksTracker.class)
+    public static class ShadowVisibleNetworksTracker {
+        @Implementation
+        public static void refreshVisibleNetworks(final Context context) {
+            sRefreshVisibleNetworksRequests++;
+        }
+    }
+
+    /**
+     * Shadow for GeolocationTracker
+     */
+    @Implements(GeolocationTracker.class)
+    public static class ShadowGeolocationTracker {
+        @Implementation
+        public static void refreshLastKnownLocation(Context context, long maxAge) {
+            sRefreshLastKnownLocation++;
+        }
+    }
+}
diff --git a/chrome/android/junit/src/org/chromium/chrome/browser/webapps/WebApkUpdateManagerTest.java b/chrome/android/junit/src/org/chromium/chrome/browser/webapps/WebApkUpdateManagerTest.java
deleted file mode 100644
index 3d0ec4c..0000000
--- a/chrome/android/junit/src/org/chromium/chrome/browser/webapps/WebApkUpdateManagerTest.java
+++ /dev/null
@@ -1,873 +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.
-
-package org.chromium.chrome.browser.webapps;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertNull;
-import static org.junit.Assert.assertTrue;
-
-import static org.chromium.webapk.lib.client.WebApkVersion.CURRENT_SHELL_APK_VERSION;
-
-import android.content.Intent;
-import android.graphics.Bitmap;
-import android.graphics.Color;
-import android.os.Bundle;
-import android.text.TextUtils;
-
-import org.junit.Before;
-import org.junit.Rule;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.mockito.Mockito;
-import org.robolectric.RuntimeEnvironment;
-import org.robolectric.annotation.Config;
-import org.robolectric.shadows.ShadowApplication;
-import org.robolectric.shadows.ShadowBitmap;
-
-import org.chromium.base.Callback;
-import org.chromium.base.CommandLine;
-import org.chromium.base.ContextUtils;
-import org.chromium.base.PathUtils;
-import org.chromium.blink_public.platform.WebDisplayMode;
-import org.chromium.chrome.browser.DisableHistogramsRule;
-import org.chromium.chrome.browser.ShortcutHelper;
-import org.chromium.chrome.browser.tab.Tab;
-import org.chromium.content_public.common.ScreenOrientationValues;
-import org.chromium.testing.local.CustomShadowAsyncTask;
-import org.chromium.testing.local.LocalRobolectricTestRunner;
-import org.chromium.webapk.lib.common.WebApkConstants;
-import org.chromium.webapk.lib.common.WebApkMetaDataKeys;
-import org.chromium.webapk.test.WebApkTestHelper;
-
-import java.io.File;
-import java.io.FileOutputStream;
-import java.util.HashMap;
-import java.util.Map;
-
-/**
- * Unit tests for WebApkUpdateManager.
- */
-@RunWith(LocalRobolectricTestRunner.class)
-@Config(manifest = Config.NONE, shadows = {CustomShadowAsyncTask.class})
-public class WebApkUpdateManagerTest {
-    @Rule
-    public DisableHistogramsRule mDisableHistogramsRule = new DisableHistogramsRule();
-
-    private static final String WEBAPK_PACKAGE_NAME = "org.chromium.webapk.test_package";
-    private static final String UNBOUND_WEBAPK_PACKAGE_NAME = "com.webapk.test_package";
-
-    /** Web Manifest URL */
-    private static final String WEB_MANIFEST_URL = "manifest.json";
-
-    private static final String START_URL = "/start_url.html";
-    private static final String SCOPE_URL = "/";
-    private static final String NAME = "Long Name";
-    private static final String SHORT_NAME = "Short Name";
-    private static final String PRIMARY_ICON_URL = "/icon.png";
-    private static final String PRIMARY_ICON_MURMUR2_HASH = "3";
-    private static final String BADGE_ICON_URL = "/badge.png";
-    private static final String BADGE_ICON_MURMUR2_HASH = "4";
-    private static final @WebDisplayMode int DISPLAY_MODE = WebDisplayMode.UNDEFINED;
-    private static final int ORIENTATION = ScreenOrientationValues.DEFAULT;
-    private static final long THEME_COLOR = 1L;
-    private static final long BACKGROUND_COLOR = 2L;
-
-    /** Different name than the one used in {@link defaultManifestData()}. */
-    private static final String DIFFERENT_NAME = "Different Name";
-
-    /** {@link WebappDataStorage#Clock} subclass which enables time to be manually advanced. */
-    private static class MockClock extends WebappDataStorage.Clock {
-        // 0 has a special meaning: {@link WebappDataStorage#TIMESTAMP_INVALID}.
-        private long mTimeMillis = 1;
-
-        public void advance(long millis) {
-            mTimeMillis += millis;
-        }
-
-        @Override
-        public long currentTimeMillis() {
-            return mTimeMillis;
-        }
-    }
-
-    /** Mock {@link WebApkUpdateDataFetcher}. */
-    private static class TestWebApkUpdateDataFetcher extends WebApkUpdateDataFetcher {
-        private boolean mStarted;
-
-        public boolean wasStarted() {
-            return mStarted;
-        }
-
-        @Override
-        public boolean start(Tab tab, WebApkInfo oldInfo, Observer observer) {
-            mStarted = true;
-            return true;
-        }
-    }
-
-    private static class TestWebApkUpdateManager extends WebApkUpdateManager {
-        private Callback<Boolean> mStoreUpdateRequestCallback;
-        private WebApkUpdateManager.WebApkUpdateCallback mUpdateCallback;
-        private TestWebApkUpdateDataFetcher mFetcher;
-        private String mUpdateName;
-        private boolean mDestroyedFetcher;
-
-        public TestWebApkUpdateManager(WebappDataStorage storage) {
-            super(storage);
-        }
-
-        /**
-         * Returns whether the is-update-needed check has been triggered.
-         */
-        public boolean updateCheckStarted() {
-            return mFetcher != null && mFetcher.wasStarted();
-        }
-
-        /**
-         * Returns whether an update has been requested.
-         */
-        public boolean updateRequested() {
-            return mStoreUpdateRequestCallback != null;
-        }
-
-        /**
-         * Returns the "name" from the requested update. Null if an update has not been requested.
-         */
-        public String requestedUpdateName() {
-            return mUpdateName;
-        }
-
-        public boolean destroyedFetcher() {
-            return mDestroyedFetcher;
-        }
-
-        public Callback<Boolean> getStoreUpdateRequestCallback() {
-            return mStoreUpdateRequestCallback;
-        }
-
-        public WebApkUpdateManager.WebApkUpdateCallback getUpdateCallback() {
-            return mUpdateCallback;
-        }
-
-        @Override
-        protected WebApkUpdateDataFetcher buildFetcher() {
-            mFetcher = new TestWebApkUpdateDataFetcher();
-            return mFetcher;
-        }
-
-        @Override
-        protected void storeWebApkUpdateRequestToFile(String updateRequestPath, WebApkInfo info,
-                String primaryIconUrl, String badgeIconUrl, boolean isManifestStale,
-                Callback<Boolean> callback) {
-            mStoreUpdateRequestCallback = callback;
-            mUpdateName = info.name();
-            writeRandomTextToFile(updateRequestPath);
-        }
-
-        @Override
-        protected void updateWebApkFromFile(
-                String updateRequestPath, WebApkUpdateCallback callback) {
-            mUpdateCallback = callback;
-        }
-
-        @Override
-        protected void destroyFetcher() {
-            mFetcher = null;
-            mDestroyedFetcher = true;
-        }
-
-        // Stubbed out because real implementation uses native.
-        @Override
-        protected boolean urlsMatchIgnoringFragments(String url1, String url2) {
-            return TextUtils.equals(url1, url2);
-        }
-    }
-
-    private static class ManifestData {
-        public String startUrl;
-        public String scopeUrl;
-        public String name;
-        public String shortName;
-        public Map<String, String> iconUrlToMurmur2HashMap;
-        public String primaryIconUrl;
-        public Bitmap primaryIcon;
-        public String badgeIconUrl;
-        public Bitmap badgeIcon;
-        public @WebDisplayMode int displayMode;
-        public int orientation;
-        public long themeColor;
-        public long backgroundColor;
-    }
-
-    private MockClock mClock;
-
-    private static String getWebApkId(String packageName) {
-        return WebApkConstants.WEBAPK_ID_PREFIX + packageName;
-    }
-
-    private WebappDataStorage getStorage(String packageName) {
-        return WebappRegistry.getInstance().getWebappDataStorage(getWebApkId(packageName));
-    }
-
-    /**
-     * Registers WebAPK with default package name. Overwrites previous registrations.
-     * @param packageName         Package name for which to register the WebApk.
-     * @param manifestData        <meta-data> values for WebAPK's Android Manifest.
-     * @param shellApkVersionCode WebAPK's version of the //chrome/android/webapk/shell_apk code.
-     */
-    private void registerWebApk(
-            String packageName, ManifestData manifestData, int shellApkVersionCode) {
-        Bundle metaData = new Bundle();
-        metaData.putInt(
-                WebApkMetaDataKeys.SHELL_APK_VERSION, shellApkVersionCode);
-        metaData.putString(WebApkMetaDataKeys.START_URL, manifestData.startUrl);
-        metaData.putString(WebApkMetaDataKeys.SCOPE, manifestData.scopeUrl);
-        metaData.putString(WebApkMetaDataKeys.NAME, manifestData.name);
-        metaData.putString(WebApkMetaDataKeys.SHORT_NAME, manifestData.shortName);
-        metaData.putString(WebApkMetaDataKeys.THEME_COLOR, manifestData.themeColor + "L");
-        metaData.putString(WebApkMetaDataKeys.BACKGROUND_COLOR, manifestData.backgroundColor + "L");
-        metaData.putString(WebApkMetaDataKeys.WEB_MANIFEST_URL, WEB_MANIFEST_URL);
-
-        String iconUrlsAndIconMurmur2Hashes = "";
-        for (Map.Entry<String, String> mapEntry : manifestData.iconUrlToMurmur2HashMap.entrySet()) {
-            String murmur2Hash = mapEntry.getValue();
-            if (murmur2Hash == null) {
-                murmur2Hash = "0";
-            }
-            iconUrlsAndIconMurmur2Hashes += " " + mapEntry.getKey() + " " + murmur2Hash;
-        }
-        iconUrlsAndIconMurmur2Hashes = iconUrlsAndIconMurmur2Hashes.trim();
-        metaData.putString(WebApkMetaDataKeys.ICON_URLS_AND_ICON_MURMUR2_HASHES,
-                iconUrlsAndIconMurmur2Hashes);
-
-        WebApkTestHelper.registerWebApkWithMetaData(packageName, metaData);
-    }
-
-    private static ManifestData defaultManifestData() {
-        ManifestData manifestData = new ManifestData();
-        manifestData.startUrl = START_URL;
-        manifestData.scopeUrl = SCOPE_URL;
-        manifestData.name = NAME;
-        manifestData.shortName = SHORT_NAME;
-
-        manifestData.iconUrlToMurmur2HashMap = new HashMap<>();
-        manifestData.iconUrlToMurmur2HashMap.put(PRIMARY_ICON_URL, PRIMARY_ICON_MURMUR2_HASH);
-        manifestData.iconUrlToMurmur2HashMap.put(BADGE_ICON_URL, BADGE_ICON_MURMUR2_HASH);
-
-        manifestData.primaryIconUrl = PRIMARY_ICON_URL;
-        manifestData.primaryIcon = createBitmap(Color.GREEN);
-        manifestData.badgeIconUrl = BADGE_ICON_URL;
-        manifestData.badgeIcon = createBitmap(Color.BLUE);
-        manifestData.displayMode = DISPLAY_MODE;
-        manifestData.orientation = ORIENTATION;
-        manifestData.themeColor = THEME_COLOR;
-        manifestData.backgroundColor = BACKGROUND_COLOR;
-        return manifestData;
-    }
-
-    private static WebApkInfo infoFromManifestData(ManifestData manifestData) {
-        if (manifestData == null) return null;
-
-        final String kPackageName = "org.random.webapk";
-        return WebApkInfo.create(getWebApkId(kPackageName), "", manifestData.scopeUrl,
-                new WebApkInfo.Icon(manifestData.primaryIcon),
-                new WebApkInfo.Icon(manifestData.badgeIcon), manifestData.name,
-                manifestData.shortName, manifestData.displayMode, manifestData.orientation, -1,
-                manifestData.themeColor, manifestData.backgroundColor, kPackageName, -1,
-                WEB_MANIFEST_URL, manifestData.startUrl, manifestData.iconUrlToMurmur2HashMap,
-                false /* forceNavigation */);
-    }
-
-    /**
-     * Creates 1x1 bitmap.
-     * @param color The bitmap color.
-     */
-    private static Bitmap createBitmap(int color) {
-        int colors[] = { color };
-        return ShadowBitmap.createBitmap(colors, 1, 1, Bitmap.Config.ALPHA_8);
-    }
-
-    private static void updateIfNeeded(WebApkUpdateManager updateManager) {
-        updateIfNeeded(WEBAPK_PACKAGE_NAME, updateManager);
-    }
-
-    private static void updateIfNeeded(String packageName, WebApkUpdateManager updateManager) {
-        // Use the intent version of {@link WebApkInfo#create()} in order to test default values
-        // set by the intent version of {@link WebApkInfo#create()}.
-        Intent intent = new Intent();
-        intent.putExtra(ShortcutHelper.EXTRA_URL, "");
-        intent.putExtra(WebApkConstants.EXTRA_WEBAPK_PACKAGE_NAME, packageName);
-        WebApkInfo info = WebApkInfo.create(intent);
-
-        updateManager.updateIfNeeded(null, info);
-    }
-
-    private static void onGotUnchangedWebManifestData(WebApkUpdateManager updateManager) {
-        onGotManifestData(updateManager, defaultManifestData());
-    }
-
-    private static void onGotDifferentData(WebApkUpdateManager updateManager) {
-        ManifestData manifestData = defaultManifestData();
-        manifestData.name = DIFFERENT_NAME;
-        onGotManifestData(updateManager, manifestData);
-    }
-
-    private static void onGotManifestData(WebApkUpdateManager updateManager,
-            ManifestData fetchedManifestData) {
-        String primaryIconUrl = randomIconUrl(fetchedManifestData);
-        String badgeIconUrl = randomIconUrl(fetchedManifestData);
-        updateManager.onGotManifestData(
-                infoFromManifestData(fetchedManifestData), primaryIconUrl, badgeIconUrl);
-    }
-
-    /**
-     * Tries to complete update request.
-     * @param updateManager
-     * @param result The result of the update task. Emulates the proto creation as always
-     *               succeeding.
-     */
-    private static void tryCompletingUpdate(
-            TestWebApkUpdateManager updateManager, @WebApkInstallResult int result) {
-        // Emulate proto creation as always succeeding.
-        Callback<Boolean> storeUpdateRequestCallback =
-                updateManager.getStoreUpdateRequestCallback();
-        if (storeUpdateRequestCallback == null) return;
-
-        storeUpdateRequestCallback.onResult(true);
-
-        updateManager.updateWhileNotRunning(Mockito.mock(Runnable.class));
-        WebApkUpdateManager.WebApkUpdateCallback updateCallback = updateManager.getUpdateCallback();
-        if (updateCallback == null) return;
-
-        updateCallback.onResultFromNative(result, false /* relaxUpdates */);
-        ShadowApplication.getInstance().runBackgroundTasks();
-    }
-
-    private static void writeRandomTextToFile(String path) {
-        File file = new File(path);
-        new File(file.getParent()).mkdirs();
-        try (FileOutputStream out = new FileOutputStream(file)) {
-            String text = "something";
-            out.write(text.getBytes());
-        } catch (Exception e) {
-        }
-    }
-
-    private static String randomIconUrl(ManifestData fetchedManifestData) {
-        if (fetchedManifestData == null || fetchedManifestData.iconUrlToMurmur2HashMap.isEmpty()) {
-            return null;
-        }
-        return fetchedManifestData.iconUrlToMurmur2HashMap.keySet().iterator().next();
-    }
-
-    /**
-     * Checks whether the WebAPK is updated given data from the WebAPK's Android Manifest and data
-     * from the fetched Web Manifest.
-     */
-    private boolean checkUpdateNeededForFetchedManifest(
-            ManifestData androidManifestData, ManifestData fetchedManifestData) {
-        registerWebApk(WEBAPK_PACKAGE_NAME, androidManifestData, CURRENT_SHELL_APK_VERSION);
-        mClock.advance(WebappDataStorage.UPDATE_INTERVAL);
-
-        TestWebApkUpdateManager updateManager =
-                new TestWebApkUpdateManager(getStorage(WEBAPK_PACKAGE_NAME));
-        updateIfNeeded(updateManager);
-        assertTrue(updateManager.updateCheckStarted());
-        updateManager.onGotManifestData(infoFromManifestData(fetchedManifestData),
-                fetchedManifestData.primaryIconUrl, fetchedManifestData.badgeIconUrl);
-        return updateManager.updateRequested();
-    }
-
-    @Before
-    public void setUp() {
-        ContextUtils.initApplicationContextForTests(RuntimeEnvironment.application);
-        PathUtils.setPrivateDataDirectorySuffix("chrome");
-        CommandLine.init(null);
-
-        registerWebApk(WEBAPK_PACKAGE_NAME, defaultManifestData(), CURRENT_SHELL_APK_VERSION);
-        mClock = new MockClock();
-        WebappDataStorage.setClockForTests(mClock);
-
-        WebappRegistry.getInstance().register(getWebApkId(WEBAPK_PACKAGE_NAME),
-                new WebappRegistry.FetchWebappDataStorageCallback() {
-                    @Override
-                    public void onWebappDataStorageRetrieved(WebappDataStorage storage) {}
-                });
-        ShadowApplication.getInstance().runBackgroundTasks();
-
-        WebappDataStorage storage = getStorage(WEBAPK_PACKAGE_NAME);
-        storage.updateTimeOfLastCheckForUpdatedWebManifest();
-        storage.updateTimeOfLastWebApkUpdateRequestCompletion();
-        storage.updateDidLastWebApkUpdateRequestSucceed(true);
-    }
-
-    /**
-     * Test that the is-update-needed check is tried the next time that the WebAPK is launched if
-     * Chrome is killed prior to the initial URL finishing loading.
-     */
-    @Test
-    public void testCheckOnNextLaunchIfClosePriorToFirstPageLoad() {
-        mClock.advance(WebappDataStorage.UPDATE_INTERVAL);
-        {
-            TestWebApkUpdateManager updateManager =
-                    new TestWebApkUpdateManager(getStorage(WEBAPK_PACKAGE_NAME));
-            updateIfNeeded(updateManager);
-            assertTrue(updateManager.updateCheckStarted());
-        }
-
-        // Chrome is killed. {@link WebApkUpdateManager#OnGotManifestData()} is not called.
-
-        {
-            // Relaunching the WebAPK should do an is-update-needed check.
-            TestWebApkUpdateManager updateManager =
-                    new TestWebApkUpdateManager(getStorage(WEBAPK_PACKAGE_NAME));
-            updateIfNeeded(updateManager);
-            assertTrue(updateManager.updateCheckStarted());
-            onGotUnchangedWebManifestData(updateManager);
-        }
-
-        {
-            // Relaunching the WebAPK should not do an is-update-needed-check.
-            TestWebApkUpdateManager updateManager =
-                    new TestWebApkUpdateManager(getStorage(WEBAPK_PACKAGE_NAME));
-            updateIfNeeded(updateManager);
-            assertFalse(updateManager.updateCheckStarted());
-        }
-    }
-
-    /**
-     * Test that the completion time of the previous WebAPK update is not modified if:
-     * - The previous WebAPK update succeeded.
-     * AND
-     * - A WebAPK update is not required.
-     */
-    @Test
-    public void testUpdateNotNeeded() {
-        long initialTime = mClock.currentTimeMillis();
-        mClock.advance(WebappDataStorage.UPDATE_INTERVAL);
-
-        TestWebApkUpdateManager updateManager =
-                new TestWebApkUpdateManager(getStorage(WEBAPK_PACKAGE_NAME));
-        updateIfNeeded(updateManager);
-        assertTrue(updateManager.updateCheckStarted());
-        onGotUnchangedWebManifestData(updateManager);
-        assertFalse(updateManager.updateRequested());
-
-        WebappDataStorage storage = getStorage(WEBAPK_PACKAGE_NAME);
-        assertTrue(storage.getDidLastWebApkUpdateRequestSucceed());
-        assertEquals(initialTime, storage.getLastWebApkUpdateRequestCompletionTime());
-    }
-
-    /**
-     * Test that the last WebAPK update is marked as having succeeded if:
-     * - The previous WebAPK update failed.
-     * AND
-     * - A WebAPK update is no longer required.
-     */
-    @Test
-    public void testMarkUpdateAsSucceededIfUpdateNoLongerNeeded() {
-        WebappDataStorage storage = getStorage(WEBAPK_PACKAGE_NAME);
-        storage.updateDidLastWebApkUpdateRequestSucceed(false);
-        mClock.advance(WebappDataStorage.RETRY_UPDATE_DURATION);
-
-        TestWebApkUpdateManager updateManager =
-                new TestWebApkUpdateManager(getStorage(WEBAPK_PACKAGE_NAME));
-        updateIfNeeded(updateManager);
-        assertTrue(updateManager.updateCheckStarted());
-        onGotUnchangedWebManifestData(updateManager);
-        assertFalse(updateManager.updateRequested());
-
-        assertTrue(storage.getDidLastWebApkUpdateRequestSucceed());
-        assertEquals(
-                mClock.currentTimeMillis(), storage.getLastWebApkUpdateRequestCompletionTime());
-    }
-
-    /**
-     * Test that the WebAPK update is marked as having failed if Chrome is killed prior to the
-     * WebAPK update completing.
-     */
-    @Test
-    public void testMarkUpdateAsFailedIfClosePriorToUpdateCompleting() {
-        mClock.advance(WebappDataStorage.UPDATE_INTERVAL);
-
-        TestWebApkUpdateManager updateManager =
-                new TestWebApkUpdateManager(getStorage(WEBAPK_PACKAGE_NAME));
-        updateIfNeeded(updateManager);
-        assertTrue(updateManager.updateCheckStarted());
-        onGotDifferentData(updateManager);
-        assertTrue(updateManager.updateRequested());
-
-        // Chrome is killed. {@link WebApkUpdateCallback#onResultFromNative} is never called.
-
-        // Check {@link WebappDataStorage} state.
-        WebappDataStorage storage = getStorage(WEBAPK_PACKAGE_NAME);
-        assertFalse(storage.getDidLastWebApkUpdateRequestSucceed());
-        assertEquals(
-                mClock.currentTimeMillis(), storage.getLastWebApkUpdateRequestCompletionTime());
-    }
-
-    /**
-     * Test that the pending update file is deleted after update completes regardless of whether
-     * update succeeded.
-     */
-    @Test
-    public void testPendingUpdateFileDeletedAfterUpdateCompletion() {
-        mClock.advance(WebappDataStorage.UPDATE_INTERVAL);
-
-        WebappDataStorage storage = getStorage(WEBAPK_PACKAGE_NAME);
-        TestWebApkUpdateManager updateManager = new TestWebApkUpdateManager(storage);
-        updateIfNeeded(updateManager);
-
-        onGotDifferentData(updateManager);
-        assertTrue(updateManager.updateRequested());
-        String updateRequestPath = storage.getPendingUpdateRequestPath();
-        assertNotNull(updateRequestPath);
-        assertTrue(new File(updateRequestPath).exists());
-
-        tryCompletingUpdate(updateManager, WebApkInstallResult.FAILURE);
-
-        assertNull(storage.getPendingUpdateRequestPath());
-        assertFalse(new File(updateRequestPath).exists());
-    }
-
-    /**
-     * Test that the pending update file is deleted if
-     * {@link WebApkUpdateManager#nativeStoreWebApkUpdateRequestToFile} creates the pending update
-     * file but fails.
-     */
-    @Test
-    public void testFileDeletedIfStoreWebApkUpdateRequestToFileFails() {
-        mClock.advance(WebappDataStorage.UPDATE_INTERVAL);
-
-        WebappDataStorage storage = getStorage(WEBAPK_PACKAGE_NAME);
-        TestWebApkUpdateManager updateManager = new TestWebApkUpdateManager(storage);
-        updateIfNeeded(updateManager);
-
-        onGotDifferentData(updateManager);
-        assertTrue(updateManager.updateRequested());
-        String updateRequestPath = storage.getPendingUpdateRequestPath();
-        assertNotNull(updateRequestPath);
-        assertTrue(new File(updateRequestPath).exists());
-
-        updateManager.getStoreUpdateRequestCallback().onResult(false);
-        ShadowApplication.getInstance().runBackgroundTasks();
-
-        assertNull(storage.getPendingUpdateRequestPath());
-        assertFalse(new File(updateRequestPath).exists());
-    }
-
-    /**
-     * Test that an update with data from the WebAPK's Android manifest is done if:
-     * - WebAPK's code is out of date
-     * AND
-     * - WebAPK's start_url does not refer to a Web Manifest.
-     *
-     * It is good to minimize the number of users with out of date WebAPKs. We try to keep WebAPKs
-     * up to date even if the web developer has removed the Web Manifest from their site.
-     */
-    @Test
-    public void testShellApkOutOfDateNoWebManifest() {
-        registerWebApk(WEBAPK_PACKAGE_NAME, defaultManifestData(), CURRENT_SHELL_APK_VERSION - 1);
-        mClock.advance(WebappDataStorage.UPDATE_INTERVAL);
-
-        TestWebApkUpdateManager updateManager =
-                new TestWebApkUpdateManager(getStorage(WEBAPK_PACKAGE_NAME));
-        updateIfNeeded(updateManager);
-        assertTrue(updateManager.updateCheckStarted());
-
-        updateManager.onGotManifestData(null, null, null);
-        assertTrue(updateManager.updateRequested());
-        assertEquals(NAME, updateManager.requestedUpdateName());
-
-        // Check that the {@link WebApkUpdateDataFetcher} has been destroyed. This prevents
-        // {@link #onGotManifestData()} from getting called.
-        assertTrue(updateManager.destroyedFetcher());
-    }
-
-    /**
-     * Test that an update with data from the fetched Web Manifest is done if the WebAPK's code is
-     * out of date and the WebAPK's start_url refers to a Web Manifest.
-     */
-    @Test
-    public void testShellApkOutOfDateStillHasWebManifest() {
-        registerWebApk(WEBAPK_PACKAGE_NAME, defaultManifestData(), CURRENT_SHELL_APK_VERSION - 1);
-        mClock.advance(WebappDataStorage.UPDATE_INTERVAL);
-
-        TestWebApkUpdateManager updateManager =
-                new TestWebApkUpdateManager(getStorage(WEBAPK_PACKAGE_NAME));
-        updateIfNeeded(updateManager);
-        assertTrue(updateManager.updateCheckStarted());
-
-        onGotManifestData(updateManager, defaultManifestData());
-        assertTrue(updateManager.updateRequested());
-        assertEquals(NAME, updateManager.requestedUpdateName());
-
-        assertTrue(updateManager.destroyedFetcher());
-    }
-
-    /**
-     * Test that an update is requested if:
-     * - start_url does not refer to a Web Manifest.
-     * AND
-     * - The user eventually navigates to a page pointing to a Web Manifest with the correct URL.
-     * AND
-     * - The Web Manifest has changed.
-     */
-    @Test
-    public void testStartUrlRedirectsToPageWithUpdatedWebManifest() {
-        mClock.advance(WebappDataStorage.UPDATE_INTERVAL);
-
-        TestWebApkUpdateManager updateManager =
-                new TestWebApkUpdateManager(getStorage(WEBAPK_PACKAGE_NAME));
-        updateIfNeeded(updateManager);
-        assertTrue(updateManager.updateCheckStarted());
-
-        // start_url does not have a Web Manifest. {@link #onGotManifestData} is called as a result
-        // of update manager timing out. No update should be requested.
-        updateManager.onGotManifestData(null, null, null);
-        assertFalse(updateManager.updateRequested());
-        // {@link WebApkUpdateDataFetcher} should still be alive so that it can get
-        // {@link #onGotManifestData} when page with the Web Manifest finishes loading.
-        assertFalse(updateManager.destroyedFetcher());
-
-        // User eventually navigates to page with Web Manifest.
-
-        ManifestData manifestData = defaultManifestData();
-        manifestData.name = DIFFERENT_NAME;
-        onGotManifestData(updateManager, manifestData);
-        assertTrue(updateManager.updateRequested());
-        assertEquals(DIFFERENT_NAME, updateManager.requestedUpdateName());
-
-        assertTrue(updateManager.destroyedFetcher());
-    }
-
-    /**
-     * Test that an update is not requested if:
-     * - start_url does not refer to a Web Manifest.
-     * AND
-     * - The user eventually navigates to a page pointing to a Web Manifest with the correct URL.
-     * AND
-     * - The Web Manifest has not changed.
-     */
-    @Test
-    public void testStartUrlRedirectsToPageWithUnchangedWebManifest() {
-        mClock.advance(WebappDataStorage.UPDATE_INTERVAL);
-
-        TestWebApkUpdateManager updateManager =
-                new TestWebApkUpdateManager(getStorage(WEBAPK_PACKAGE_NAME));
-        updateIfNeeded(updateManager);
-
-        // Update manager times out.
-        updateManager.onGotManifestData(null, null, null);
-        onGotManifestData(updateManager, defaultManifestData());
-        assertFalse(updateManager.updateRequested());
-
-        // We got the Web Manifest. The {@link WebApkUpdateDataFetcher} should be destroyed to stop
-        // it from fetching the Web Manifest for subsequent page loads.
-        assertTrue(updateManager.destroyedFetcher());
-    }
-
-    @Test
-    public void testManifestDoesNotUpgrade() {
-        assertFalse(
-                checkUpdateNeededForFetchedManifest(defaultManifestData(), defaultManifestData()));
-    }
-
-    /**
-     * Test that a webapk with an unexpected package name does not request updates.
-     */
-    @Test
-    public void testUnboundWebApkDoesNotUpgrade() {
-        ManifestData androidManifestData = defaultManifestData();
-
-        registerWebApk(UNBOUND_WEBAPK_PACKAGE_NAME, androidManifestData, CURRENT_SHELL_APK_VERSION);
-        mClock.advance(WebappDataStorage.UPDATE_INTERVAL);
-
-        TestWebApkUpdateManager updateManager =
-                new TestWebApkUpdateManager(getStorage(UNBOUND_WEBAPK_PACKAGE_NAME));
-        updateIfNeeded(UNBOUND_WEBAPK_PACKAGE_NAME, updateManager);
-        assertFalse(updateManager.updateCheckStarted());
-        assertFalse(updateManager.updateRequested());
-    }
-
-    /**
-     * Test that an upgrade is not requested when the Web Manifest did not change and the Web
-     * Manifest scope is empty.
-     */
-    @Test
-    public void testManifestEmptyScopeShouldNotUpgrade() {
-        ManifestData oldData = defaultManifestData();
-        // webapk_installer.cc sets the scope to the default scope if the scope is empty.
-        oldData.scopeUrl = ShortcutHelper.getScopeFromUrl(oldData.startUrl);
-        ManifestData fetchedData = defaultManifestData();
-        fetchedData.scopeUrl = "";
-        assertTrue(!oldData.scopeUrl.equals(fetchedData.scopeUrl));
-        assertFalse(checkUpdateNeededForFetchedManifest(oldData, fetchedData));
-    }
-
-    /**
-     * Test that an upgrade is requested when the Web Manifest is updated from using a non-empty
-     * scope to an empty scope.
-     */
-    @Test
-    public void testManifestNonEmptyScopeToEmptyScopeShouldUpgrade() {
-        ManifestData oldData = defaultManifestData();
-        oldData.startUrl = "/fancy/scope/special/snowflake.html";
-        oldData.scopeUrl = "/fancy/scope/";
-        assertTrue(
-                !oldData.scopeUrl.equals(ShortcutHelper.getScopeFromUrl(oldData.startUrl)));
-        ManifestData fetchedData = defaultManifestData();
-        fetchedData.startUrl = "/fancy/scope/special/snowflake.html";
-        fetchedData.scopeUrl = "";
-
-        assertTrue(checkUpdateNeededForFetchedManifest(oldData, fetchedData));
-    }
-
-    /**
-     * Test that an upgrade is requested when:
-     * - WebAPK was generated using icon at {@link PRIMARY_ICON_URL} from Web Manifest.
-     * - Bitmap at {@link PRIMARY_ICON_URL} has changed.
-     */
-    @Test
-    public void testPrimaryIconChangeShouldUpgrade() {
-        ManifestData fetchedData = defaultManifestData();
-        fetchedData.iconUrlToMurmur2HashMap.put(
-                fetchedData.primaryIconUrl, PRIMARY_ICON_MURMUR2_HASH + "1");
-        fetchedData.primaryIcon = createBitmap(Color.BLUE);
-        assertTrue(checkUpdateNeededForFetchedManifest(defaultManifestData(), fetchedData));
-    }
-
-    /**
-     * Test that an upgrade is requested when:
-     * - WebAPK was generated using icon at {@link BADGE_ICON_URL} from Web Manifest.
-     * - Bitmap at {@link BADGE_ICON_URL} has changed.
-     */
-    @Test
-    public void testBadgeIconChangeShouldUpgrade() {
-        ManifestData fetchedData = defaultManifestData();
-        fetchedData.iconUrlToMurmur2HashMap.put(
-                fetchedData.badgeIconUrl, BADGE_ICON_MURMUR2_HASH + "1");
-        fetchedData.badgeIcon = createBitmap(Color.GREEN);
-        assertTrue(checkUpdateNeededForFetchedManifest(defaultManifestData(), fetchedData));
-    }
-
-    /**
-     * Test that an upgrade is requested when:
-     * - WebAPK is generated using icon at {@link PRIMARY_ICON_URL} from Web Manifest.
-     * - A new icon URL is added to the Web Manifest. And InstallableManager selects the new icon as
-     *   the primary icon.
-     */
-    @Test
-    public void testPrimaryIconUrlChangeShouldUpgrade() {
-        ManifestData fetchedData = defaultManifestData();
-        fetchedData.iconUrlToMurmur2HashMap.put("/icon2.png", "22");
-        fetchedData.primaryIconUrl = "/icon2.png";
-        assertTrue(checkUpdateNeededForFetchedManifest(defaultManifestData(), fetchedData));
-    }
-
-    /**
-     * Test that an upgrade is requested when:
-     * - WebAPK is generated using icon at {@link BADGE_ICON_URL} from Web Manifest.
-     * - A new icon URL is added to the Web Manifest. And InstallableManager selects the new icon as
-     *   the badge icon.
-     */
-    @Test
-    public void testBadgeIconUrlChangeShouldUpgrade() {
-        ManifestData fetchedData = defaultManifestData();
-        fetchedData.iconUrlToMurmur2HashMap.put("/badge2.png", "44");
-        fetchedData.badgeIconUrl = "/badge2.png";
-        assertTrue(checkUpdateNeededForFetchedManifest(defaultManifestData(), fetchedData));
-    }
-
-    /**
-     * Test that an upgrade is not requested if:
-     * - icon URL is added to the Web Manifest
-     * AND
-     * - "best" icon URL for the primary icon did not change.
-     * AND
-     * - "best" icon URL for the badge icon did not change.
-     */
-    @Test
-    public void testIconUrlsChangeShouldNotUpgradeIfPrimaryIconUrlAndBadgeIconUrlDoNotChange() {
-        ManifestData fetchedData = defaultManifestData();
-        fetchedData.iconUrlToMurmur2HashMap.put("/icon2.png", null);
-        assertFalse(checkUpdateNeededForFetchedManifest(defaultManifestData(), fetchedData));
-    }
-
-    /**
-     * Test that an upgrade is not requested if:
-     * - the WebAPK's meta data has murmur2 hashes for all of the icons.
-     * AND
-     * - the Web Manifest has not changed
-     * AND
-     * - the computed best icon URLs are different from the one stored in the WebAPK's meta data.
-     */
-    @Test
-    public void testWebManifestSameButBestIconUrlChangedShouldNotUpgrade() {
-        String iconUrl1 = "/icon1.png";
-        String iconUrl2 = "/icon2.png";
-        String badgeUrl1 = "/badge1.png";
-        String badgeUrl2 = "/badge2.pgn";
-        String hash1 = "11";
-        String hash2 = "22";
-        String hash3 = "33";
-        String hash4 = "44";
-
-        ManifestData androidManifestData = defaultManifestData();
-        androidManifestData.primaryIconUrl = iconUrl1;
-        androidManifestData.badgeIconUrl = badgeUrl1;
-        androidManifestData.iconUrlToMurmur2HashMap.clear();
-        androidManifestData.iconUrlToMurmur2HashMap.put(iconUrl1, hash1);
-        androidManifestData.iconUrlToMurmur2HashMap.put(iconUrl2, hash2);
-        androidManifestData.iconUrlToMurmur2HashMap.put(badgeUrl1, hash3);
-        androidManifestData.iconUrlToMurmur2HashMap.put(badgeUrl2, hash4);
-
-        ManifestData fetchedManifestData = defaultManifestData();
-        fetchedManifestData.primaryIconUrl = iconUrl2;
-        fetchedManifestData.badgeIconUrl = badgeUrl2;
-        fetchedManifestData.iconUrlToMurmur2HashMap.clear();
-        fetchedManifestData.iconUrlToMurmur2HashMap.put(iconUrl1, null);
-        fetchedManifestData.iconUrlToMurmur2HashMap.put(iconUrl2, hash2);
-        fetchedManifestData.iconUrlToMurmur2HashMap.put(badgeUrl1, null);
-        fetchedManifestData.iconUrlToMurmur2HashMap.put(badgeUrl2, hash4);
-
-        assertFalse(checkUpdateNeededForFetchedManifest(androidManifestData, fetchedManifestData));
-    }
-
-    /**
-     * Tests that a WebAPK update is requested immediately if:
-     * the Shell APK is out of date,
-     * AND
-     * there wasn't a previous request for this ShellAPK version.
-     */
-    @Test
-    public void testShellApkOutOfDate() {
-        registerWebApk(WEBAPK_PACKAGE_NAME, defaultManifestData(), CURRENT_SHELL_APK_VERSION - 1);
-        TestWebApkUpdateManager updateManager =
-                new TestWebApkUpdateManager(getStorage(WEBAPK_PACKAGE_NAME));
-
-        // There have not been any update requests for the current ShellAPK version. A WebAPK update
-        // should be requested immediately.
-        updateIfNeeded(updateManager);
-        assertTrue(updateManager.updateCheckStarted());
-        onGotManifestData(updateManager, defaultManifestData());
-        assertTrue(updateManager.updateRequested());
-        tryCompletingUpdate(updateManager, WebApkInstallResult.FAILURE);
-
-        mClock.advance(1);
-        updateIfNeeded(updateManager);
-        assertFalse(updateManager.updateCheckStarted());
-
-        // A previous update request was made for the current ShellAPK version. A WebAPK update
-        // should be requested after the regular delay.
-        mClock.advance(WebappDataStorage.UPDATE_INTERVAL - 1);
-        updateIfNeeded(updateManager);
-        assertTrue(updateManager.updateCheckStarted());
-        onGotManifestData(updateManager, defaultManifestData());
-        assertTrue(updateManager.updateRequested());
-    }
-}
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
new file mode 100644
index 0000000..1238c421
--- /dev/null
+++ b/chrome/android/junit/src/org/chromium/chrome/browser/webapps/WebApkUpdateManagerUnitTest.java
@@ -0,0 +1,871 @@
+// 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.
+
+package org.chromium.chrome.browser.webapps;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+
+import static org.chromium.webapk.lib.client.WebApkVersion.CURRENT_SHELL_APK_VERSION;
+
+import android.content.Intent;
+import android.graphics.Bitmap;
+import android.graphics.Color;
+import android.os.Bundle;
+import android.text.TextUtils;
+
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mockito;
+import org.robolectric.RuntimeEnvironment;
+import org.robolectric.annotation.Config;
+import org.robolectric.shadows.ShadowApplication;
+import org.robolectric.shadows.ShadowBitmap;
+
+import org.chromium.base.Callback;
+import org.chromium.base.CommandLine;
+import org.chromium.base.ContextUtils;
+import org.chromium.base.PathUtils;
+import org.chromium.blink_public.platform.WebDisplayMode;
+import org.chromium.chrome.browser.DisableHistogramsRule;
+import org.chromium.chrome.browser.ShortcutHelper;
+import org.chromium.chrome.browser.tab.Tab;
+import org.chromium.content_public.common.ScreenOrientationValues;
+import org.chromium.testing.local.CustomShadowAsyncTask;
+import org.chromium.testing.local.LocalRobolectricTestRunner;
+import org.chromium.webapk.lib.common.WebApkConstants;
+import org.chromium.webapk.lib.common.WebApkMetaDataKeys;
+import org.chromium.webapk.test.WebApkTestHelper;
+
+import java.io.File;
+import java.io.FileOutputStream;
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * Unit tests for WebApkUpdateManager.
+ */
+@RunWith(LocalRobolectricTestRunner.class)
+@Config(manifest = Config.NONE, shadows = {CustomShadowAsyncTask.class})
+public class WebApkUpdateManagerUnitTest {
+    @Rule
+    public DisableHistogramsRule mDisableHistogramsRule = new DisableHistogramsRule();
+
+    private static final String WEBAPK_PACKAGE_NAME = "org.chromium.webapk.test_package";
+    private static final String UNBOUND_WEBAPK_PACKAGE_NAME = "com.webapk.test_package";
+
+    /** Web Manifest URL */
+    private static final String WEB_MANIFEST_URL = "manifest.json";
+
+    private static final String START_URL = "/start_url.html";
+    private static final String SCOPE_URL = "/";
+    private static final String NAME = "Long Name";
+    private static final String SHORT_NAME = "Short Name";
+    private static final String PRIMARY_ICON_URL = "/icon.png";
+    private static final String PRIMARY_ICON_MURMUR2_HASH = "3";
+    private static final String BADGE_ICON_URL = "/badge.png";
+    private static final String BADGE_ICON_MURMUR2_HASH = "4";
+    private static final @WebDisplayMode int DISPLAY_MODE = WebDisplayMode.UNDEFINED;
+    private static final int ORIENTATION = ScreenOrientationValues.DEFAULT;
+    private static final long THEME_COLOR = 1L;
+    private static final long BACKGROUND_COLOR = 2L;
+
+    /** Different name than the one used in {@link defaultManifestData()}. */
+    private static final String DIFFERENT_NAME = "Different Name";
+
+    /** {@link WebappDataStorage#Clock} subclass which enables time to be manually advanced. */
+    private static class MockClock extends WebappDataStorage.Clock {
+        // 0 has a special meaning: {@link WebappDataStorage#TIMESTAMP_INVALID}.
+        private long mTimeMillis = 1;
+
+        public void advance(long millis) {
+            mTimeMillis += millis;
+        }
+
+        @Override
+        public long currentTimeMillis() {
+            return mTimeMillis;
+        }
+    }
+
+    /** Mock {@link WebApkUpdateDataFetcher}. */
+    private static class TestWebApkUpdateDataFetcher extends WebApkUpdateDataFetcher {
+        private boolean mStarted;
+
+        public boolean wasStarted() {
+            return mStarted;
+        }
+
+        @Override
+        public boolean start(Tab tab, WebApkInfo oldInfo, Observer observer) {
+            mStarted = true;
+            return true;
+        }
+    }
+
+    private static class TestWebApkUpdateManager extends WebApkUpdateManager {
+        private Callback<Boolean> mStoreUpdateRequestCallback;
+        private WebApkUpdateManager.WebApkUpdateCallback mUpdateCallback;
+        private TestWebApkUpdateDataFetcher mFetcher;
+        private String mUpdateName;
+        private boolean mDestroyedFetcher;
+
+        public TestWebApkUpdateManager(WebappDataStorage storage) {
+            super(storage);
+        }
+
+        /**
+         * Returns whether the is-update-needed check has been triggered.
+         */
+        public boolean updateCheckStarted() {
+            return mFetcher != null && mFetcher.wasStarted();
+        }
+
+        /**
+         * Returns whether an update has been requested.
+         */
+        public boolean updateRequested() {
+            return mStoreUpdateRequestCallback != null;
+        }
+
+        /**
+         * Returns the "name" from the requested update. Null if an update has not been requested.
+         */
+        public String requestedUpdateName() {
+            return mUpdateName;
+        }
+
+        public boolean destroyedFetcher() {
+            return mDestroyedFetcher;
+        }
+
+        public Callback<Boolean> getStoreUpdateRequestCallback() {
+            return mStoreUpdateRequestCallback;
+        }
+
+        public WebApkUpdateManager.WebApkUpdateCallback getUpdateCallback() {
+            return mUpdateCallback;
+        }
+
+        @Override
+        protected WebApkUpdateDataFetcher buildFetcher() {
+            mFetcher = new TestWebApkUpdateDataFetcher();
+            return mFetcher;
+        }
+
+        @Override
+        protected void storeWebApkUpdateRequestToFile(String updateRequestPath, WebApkInfo info,
+                String primaryIconUrl, String badgeIconUrl, boolean isManifestStale,
+                Callback<Boolean> callback) {
+            mStoreUpdateRequestCallback = callback;
+            mUpdateName = info.name();
+            writeRandomTextToFile(updateRequestPath);
+        }
+
+        @Override
+        protected void updateWebApkFromFile(
+                String updateRequestPath, WebApkUpdateCallback callback) {
+            mUpdateCallback = callback;
+        }
+
+        @Override
+        protected void destroyFetcher() {
+            mFetcher = null;
+            mDestroyedFetcher = true;
+        }
+
+        // Stubbed out because real implementation uses native.
+        @Override
+        protected boolean urlsMatchIgnoringFragments(String url1, String url2) {
+            return TextUtils.equals(url1, url2);
+        }
+    }
+
+    private static class ManifestData {
+        public String startUrl;
+        public String scopeUrl;
+        public String name;
+        public String shortName;
+        public Map<String, String> iconUrlToMurmur2HashMap;
+        public String primaryIconUrl;
+        public Bitmap primaryIcon;
+        public String badgeIconUrl;
+        public Bitmap badgeIcon;
+        public @WebDisplayMode int displayMode;
+        public int orientation;
+        public long themeColor;
+        public long backgroundColor;
+    }
+
+    private MockClock mClock;
+
+    private static String getWebApkId(String packageName) {
+        return WebApkConstants.WEBAPK_ID_PREFIX + packageName;
+    }
+
+    private WebappDataStorage getStorage(String packageName) {
+        return WebappRegistry.getInstance().getWebappDataStorage(getWebApkId(packageName));
+    }
+
+    /**
+     * Registers WebAPK with default package name. Overwrites previous registrations.
+     * @param packageName         Package name for which to register the WebApk.
+     * @param manifestData        <meta-data> values for WebAPK's Android Manifest.
+     * @param shellApkVersionCode WebAPK's version of the //chrome/android/webapk/shell_apk code.
+     */
+    private void registerWebApk(
+            String packageName, ManifestData manifestData, int shellApkVersionCode) {
+        Bundle metaData = new Bundle();
+        metaData.putInt(WebApkMetaDataKeys.SHELL_APK_VERSION, shellApkVersionCode);
+        metaData.putString(WebApkMetaDataKeys.START_URL, manifestData.startUrl);
+        metaData.putString(WebApkMetaDataKeys.SCOPE, manifestData.scopeUrl);
+        metaData.putString(WebApkMetaDataKeys.NAME, manifestData.name);
+        metaData.putString(WebApkMetaDataKeys.SHORT_NAME, manifestData.shortName);
+        metaData.putString(WebApkMetaDataKeys.THEME_COLOR, manifestData.themeColor + "L");
+        metaData.putString(WebApkMetaDataKeys.BACKGROUND_COLOR, manifestData.backgroundColor + "L");
+        metaData.putString(WebApkMetaDataKeys.WEB_MANIFEST_URL, WEB_MANIFEST_URL);
+
+        String iconUrlsAndIconMurmur2Hashes = "";
+        for (Map.Entry<String, String> mapEntry : manifestData.iconUrlToMurmur2HashMap.entrySet()) {
+            String murmur2Hash = mapEntry.getValue();
+            if (murmur2Hash == null) {
+                murmur2Hash = "0";
+            }
+            iconUrlsAndIconMurmur2Hashes += " " + mapEntry.getKey() + " " + murmur2Hash;
+        }
+        iconUrlsAndIconMurmur2Hashes = iconUrlsAndIconMurmur2Hashes.trim();
+        metaData.putString(
+                WebApkMetaDataKeys.ICON_URLS_AND_ICON_MURMUR2_HASHES, iconUrlsAndIconMurmur2Hashes);
+
+        WebApkTestHelper.registerWebApkWithMetaData(packageName, metaData);
+    }
+
+    private static ManifestData defaultManifestData() {
+        ManifestData manifestData = new ManifestData();
+        manifestData.startUrl = START_URL;
+        manifestData.scopeUrl = SCOPE_URL;
+        manifestData.name = NAME;
+        manifestData.shortName = SHORT_NAME;
+
+        manifestData.iconUrlToMurmur2HashMap = new HashMap<>();
+        manifestData.iconUrlToMurmur2HashMap.put(PRIMARY_ICON_URL, PRIMARY_ICON_MURMUR2_HASH);
+        manifestData.iconUrlToMurmur2HashMap.put(BADGE_ICON_URL, BADGE_ICON_MURMUR2_HASH);
+
+        manifestData.primaryIconUrl = PRIMARY_ICON_URL;
+        manifestData.primaryIcon = createBitmap(Color.GREEN);
+        manifestData.badgeIconUrl = BADGE_ICON_URL;
+        manifestData.badgeIcon = createBitmap(Color.BLUE);
+        manifestData.displayMode = DISPLAY_MODE;
+        manifestData.orientation = ORIENTATION;
+        manifestData.themeColor = THEME_COLOR;
+        manifestData.backgroundColor = BACKGROUND_COLOR;
+        return manifestData;
+    }
+
+    private static WebApkInfo infoFromManifestData(ManifestData manifestData) {
+        if (manifestData == null) return null;
+
+        final String kPackageName = "org.random.webapk";
+        return WebApkInfo.create(getWebApkId(kPackageName), "", manifestData.scopeUrl,
+                new WebApkInfo.Icon(manifestData.primaryIcon),
+                new WebApkInfo.Icon(manifestData.badgeIcon), manifestData.name,
+                manifestData.shortName, manifestData.displayMode, manifestData.orientation, -1,
+                manifestData.themeColor, manifestData.backgroundColor, kPackageName, -1,
+                WEB_MANIFEST_URL, manifestData.startUrl, manifestData.iconUrlToMurmur2HashMap,
+                false /* forceNavigation */);
+    }
+
+    /**
+     * Creates 1x1 bitmap.
+     * @param color The bitmap color.
+     */
+    private static Bitmap createBitmap(int color) {
+        int colors[] = {color};
+        return ShadowBitmap.createBitmap(colors, 1, 1, Bitmap.Config.ALPHA_8);
+    }
+
+    private static void updateIfNeeded(WebApkUpdateManager updateManager) {
+        updateIfNeeded(WEBAPK_PACKAGE_NAME, updateManager);
+    }
+
+    private static void updateIfNeeded(String packageName, WebApkUpdateManager updateManager) {
+        // Use the intent version of {@link WebApkInfo#create()} in order to test default values
+        // set by the intent version of {@link WebApkInfo#create()}.
+        Intent intent = new Intent();
+        intent.putExtra(ShortcutHelper.EXTRA_URL, "");
+        intent.putExtra(WebApkConstants.EXTRA_WEBAPK_PACKAGE_NAME, packageName);
+        WebApkInfo info = WebApkInfo.create(intent);
+
+        updateManager.updateIfNeeded(null, info);
+    }
+
+    private static void onGotUnchangedWebManifestData(WebApkUpdateManager updateManager) {
+        onGotManifestData(updateManager, defaultManifestData());
+    }
+
+    private static void onGotDifferentData(WebApkUpdateManager updateManager) {
+        ManifestData manifestData = defaultManifestData();
+        manifestData.name = DIFFERENT_NAME;
+        onGotManifestData(updateManager, manifestData);
+    }
+
+    private static void onGotManifestData(
+            WebApkUpdateManager updateManager, ManifestData fetchedManifestData) {
+        String primaryIconUrl = randomIconUrl(fetchedManifestData);
+        String badgeIconUrl = randomIconUrl(fetchedManifestData);
+        updateManager.onGotManifestData(
+                infoFromManifestData(fetchedManifestData), primaryIconUrl, badgeIconUrl);
+    }
+
+    /**
+     * Tries to complete update request.
+     * @param updateManager
+     * @param result The result of the update task. Emulates the proto creation as always
+     *               succeeding.
+     */
+    private static void tryCompletingUpdate(
+            TestWebApkUpdateManager updateManager, @WebApkInstallResult int result) {
+        // Emulate proto creation as always succeeding.
+        Callback<Boolean> storeUpdateRequestCallback =
+                updateManager.getStoreUpdateRequestCallback();
+        if (storeUpdateRequestCallback == null) return;
+
+        storeUpdateRequestCallback.onResult(true);
+
+        updateManager.updateWhileNotRunning(Mockito.mock(Runnable.class));
+        WebApkUpdateManager.WebApkUpdateCallback updateCallback = updateManager.getUpdateCallback();
+        if (updateCallback == null) return;
+
+        updateCallback.onResultFromNative(result, false /* relaxUpdates */);
+        ShadowApplication.getInstance().runBackgroundTasks();
+    }
+
+    private static void writeRandomTextToFile(String path) {
+        File file = new File(path);
+        new File(file.getParent()).mkdirs();
+        try (FileOutputStream out = new FileOutputStream(file)) {
+            String text = "something";
+            out.write(text.getBytes());
+        } catch (Exception e) {
+        }
+    }
+
+    private static String randomIconUrl(ManifestData fetchedManifestData) {
+        if (fetchedManifestData == null || fetchedManifestData.iconUrlToMurmur2HashMap.isEmpty()) {
+            return null;
+        }
+        return fetchedManifestData.iconUrlToMurmur2HashMap.keySet().iterator().next();
+    }
+
+    /**
+     * Checks whether the WebAPK is updated given data from the WebAPK's Android Manifest and data
+     * from the fetched Web Manifest.
+     */
+    private boolean checkUpdateNeededForFetchedManifest(
+            ManifestData androidManifestData, ManifestData fetchedManifestData) {
+        registerWebApk(WEBAPK_PACKAGE_NAME, androidManifestData, CURRENT_SHELL_APK_VERSION);
+        mClock.advance(WebappDataStorage.UPDATE_INTERVAL);
+
+        TestWebApkUpdateManager updateManager =
+                new TestWebApkUpdateManager(getStorage(WEBAPK_PACKAGE_NAME));
+        updateIfNeeded(updateManager);
+        assertTrue(updateManager.updateCheckStarted());
+        updateManager.onGotManifestData(infoFromManifestData(fetchedManifestData),
+                fetchedManifestData.primaryIconUrl, fetchedManifestData.badgeIconUrl);
+        return updateManager.updateRequested();
+    }
+
+    @Before
+    public void setUp() {
+        ContextUtils.initApplicationContextForTests(RuntimeEnvironment.application);
+        PathUtils.setPrivateDataDirectorySuffix("chrome");
+        CommandLine.init(null);
+
+        registerWebApk(WEBAPK_PACKAGE_NAME, defaultManifestData(), CURRENT_SHELL_APK_VERSION);
+        mClock = new MockClock();
+        WebappDataStorage.setClockForTests(mClock);
+
+        WebappRegistry.getInstance().register(getWebApkId(WEBAPK_PACKAGE_NAME),
+                new WebappRegistry.FetchWebappDataStorageCallback() {
+                    @Override
+                    public void onWebappDataStorageRetrieved(WebappDataStorage storage) {}
+                });
+        ShadowApplication.getInstance().runBackgroundTasks();
+
+        WebappDataStorage storage = getStorage(WEBAPK_PACKAGE_NAME);
+        storage.updateTimeOfLastCheckForUpdatedWebManifest();
+        storage.updateTimeOfLastWebApkUpdateRequestCompletion();
+        storage.updateDidLastWebApkUpdateRequestSucceed(true);
+    }
+
+    /**
+     * Test that the is-update-needed check is tried the next time that the WebAPK is launched if
+     * Chrome is killed prior to the initial URL finishing loading.
+     */
+    @Test
+    public void testCheckOnNextLaunchIfClosePriorToFirstPageLoad() {
+        mClock.advance(WebappDataStorage.UPDATE_INTERVAL);
+        {
+            TestWebApkUpdateManager updateManager =
+                    new TestWebApkUpdateManager(getStorage(WEBAPK_PACKAGE_NAME));
+            updateIfNeeded(updateManager);
+            assertTrue(updateManager.updateCheckStarted());
+        }
+
+        // Chrome is killed. {@link WebApkUpdateManager#OnGotManifestData()} is not called.
+
+        {
+            // Relaunching the WebAPK should do an is-update-needed check.
+            TestWebApkUpdateManager updateManager =
+                    new TestWebApkUpdateManager(getStorage(WEBAPK_PACKAGE_NAME));
+            updateIfNeeded(updateManager);
+            assertTrue(updateManager.updateCheckStarted());
+            onGotUnchangedWebManifestData(updateManager);
+        }
+
+        {
+            // Relaunching the WebAPK should not do an is-update-needed-check.
+            TestWebApkUpdateManager updateManager =
+                    new TestWebApkUpdateManager(getStorage(WEBAPK_PACKAGE_NAME));
+            updateIfNeeded(updateManager);
+            assertFalse(updateManager.updateCheckStarted());
+        }
+    }
+
+    /**
+     * Test that the completion time of the previous WebAPK update is not modified if:
+     * - The previous WebAPK update succeeded.
+     * AND
+     * - A WebAPK update is not required.
+     */
+    @Test
+    public void testUpdateNotNeeded() {
+        long initialTime = mClock.currentTimeMillis();
+        mClock.advance(WebappDataStorage.UPDATE_INTERVAL);
+
+        TestWebApkUpdateManager updateManager =
+                new TestWebApkUpdateManager(getStorage(WEBAPK_PACKAGE_NAME));
+        updateIfNeeded(updateManager);
+        assertTrue(updateManager.updateCheckStarted());
+        onGotUnchangedWebManifestData(updateManager);
+        assertFalse(updateManager.updateRequested());
+
+        WebappDataStorage storage = getStorage(WEBAPK_PACKAGE_NAME);
+        assertTrue(storage.getDidLastWebApkUpdateRequestSucceed());
+        assertEquals(initialTime, storage.getLastWebApkUpdateRequestCompletionTime());
+    }
+
+    /**
+     * Test that the last WebAPK update is marked as having succeeded if:
+     * - The previous WebAPK update failed.
+     * AND
+     * - A WebAPK update is no longer required.
+     */
+    @Test
+    public void testMarkUpdateAsSucceededIfUpdateNoLongerNeeded() {
+        WebappDataStorage storage = getStorage(WEBAPK_PACKAGE_NAME);
+        storage.updateDidLastWebApkUpdateRequestSucceed(false);
+        mClock.advance(WebappDataStorage.RETRY_UPDATE_DURATION);
+
+        TestWebApkUpdateManager updateManager =
+                new TestWebApkUpdateManager(getStorage(WEBAPK_PACKAGE_NAME));
+        updateIfNeeded(updateManager);
+        assertTrue(updateManager.updateCheckStarted());
+        onGotUnchangedWebManifestData(updateManager);
+        assertFalse(updateManager.updateRequested());
+
+        assertTrue(storage.getDidLastWebApkUpdateRequestSucceed());
+        assertEquals(
+                mClock.currentTimeMillis(), storage.getLastWebApkUpdateRequestCompletionTime());
+    }
+
+    /**
+     * Test that the WebAPK update is marked as having failed if Chrome is killed prior to the
+     * WebAPK update completing.
+     */
+    @Test
+    public void testMarkUpdateAsFailedIfClosePriorToUpdateCompleting() {
+        mClock.advance(WebappDataStorage.UPDATE_INTERVAL);
+
+        TestWebApkUpdateManager updateManager =
+                new TestWebApkUpdateManager(getStorage(WEBAPK_PACKAGE_NAME));
+        updateIfNeeded(updateManager);
+        assertTrue(updateManager.updateCheckStarted());
+        onGotDifferentData(updateManager);
+        assertTrue(updateManager.updateRequested());
+
+        // Chrome is killed. {@link WebApkUpdateCallback#onResultFromNative} is never called.
+
+        // Check {@link WebappDataStorage} state.
+        WebappDataStorage storage = getStorage(WEBAPK_PACKAGE_NAME);
+        assertFalse(storage.getDidLastWebApkUpdateRequestSucceed());
+        assertEquals(
+                mClock.currentTimeMillis(), storage.getLastWebApkUpdateRequestCompletionTime());
+    }
+
+    /**
+     * Test that the pending update file is deleted after update completes regardless of whether
+     * update succeeded.
+     */
+    @Test
+    public void testPendingUpdateFileDeletedAfterUpdateCompletion() {
+        mClock.advance(WebappDataStorage.UPDATE_INTERVAL);
+
+        WebappDataStorage storage = getStorage(WEBAPK_PACKAGE_NAME);
+        TestWebApkUpdateManager updateManager = new TestWebApkUpdateManager(storage);
+        updateIfNeeded(updateManager);
+
+        onGotDifferentData(updateManager);
+        assertTrue(updateManager.updateRequested());
+        String updateRequestPath = storage.getPendingUpdateRequestPath();
+        assertNotNull(updateRequestPath);
+        assertTrue(new File(updateRequestPath).exists());
+
+        tryCompletingUpdate(updateManager, WebApkInstallResult.FAILURE);
+
+        assertNull(storage.getPendingUpdateRequestPath());
+        assertFalse(new File(updateRequestPath).exists());
+    }
+
+    /**
+     * Test that the pending update file is deleted if
+     * {@link WebApkUpdateManager#nativeStoreWebApkUpdateRequestToFile} creates the pending update
+     * file but fails.
+     */
+    @Test
+    public void testFileDeletedIfStoreWebApkUpdateRequestToFileFails() {
+        mClock.advance(WebappDataStorage.UPDATE_INTERVAL);
+
+        WebappDataStorage storage = getStorage(WEBAPK_PACKAGE_NAME);
+        TestWebApkUpdateManager updateManager = new TestWebApkUpdateManager(storage);
+        updateIfNeeded(updateManager);
+
+        onGotDifferentData(updateManager);
+        assertTrue(updateManager.updateRequested());
+        String updateRequestPath = storage.getPendingUpdateRequestPath();
+        assertNotNull(updateRequestPath);
+        assertTrue(new File(updateRequestPath).exists());
+
+        updateManager.getStoreUpdateRequestCallback().onResult(false);
+        ShadowApplication.getInstance().runBackgroundTasks();
+
+        assertNull(storage.getPendingUpdateRequestPath());
+        assertFalse(new File(updateRequestPath).exists());
+    }
+
+    /**
+     * Test that an update with data from the WebAPK's Android manifest is done if:
+     * - WebAPK's code is out of date
+     * AND
+     * - WebAPK's start_url does not refer to a Web Manifest.
+     *
+     * It is good to minimize the number of users with out of date WebAPKs. We try to keep WebAPKs
+     * up to date even if the web developer has removed the Web Manifest from their site.
+     */
+    @Test
+    public void testShellApkOutOfDateNoWebManifest() {
+        registerWebApk(WEBAPK_PACKAGE_NAME, defaultManifestData(), CURRENT_SHELL_APK_VERSION - 1);
+        mClock.advance(WebappDataStorage.UPDATE_INTERVAL);
+
+        TestWebApkUpdateManager updateManager =
+                new TestWebApkUpdateManager(getStorage(WEBAPK_PACKAGE_NAME));
+        updateIfNeeded(updateManager);
+        assertTrue(updateManager.updateCheckStarted());
+
+        updateManager.onGotManifestData(null, null, null);
+        assertTrue(updateManager.updateRequested());
+        assertEquals(NAME, updateManager.requestedUpdateName());
+
+        // Check that the {@link WebApkUpdateDataFetcher} has been destroyed. This prevents
+        // {@link #onGotManifestData()} from getting called.
+        assertTrue(updateManager.destroyedFetcher());
+    }
+
+    /**
+     * Test that an update with data from the fetched Web Manifest is done if the WebAPK's code is
+     * out of date and the WebAPK's start_url refers to a Web Manifest.
+     */
+    @Test
+    public void testShellApkOutOfDateStillHasWebManifest() {
+        registerWebApk(WEBAPK_PACKAGE_NAME, defaultManifestData(), CURRENT_SHELL_APK_VERSION - 1);
+        mClock.advance(WebappDataStorage.UPDATE_INTERVAL);
+
+        TestWebApkUpdateManager updateManager =
+                new TestWebApkUpdateManager(getStorage(WEBAPK_PACKAGE_NAME));
+        updateIfNeeded(updateManager);
+        assertTrue(updateManager.updateCheckStarted());
+
+        onGotManifestData(updateManager, defaultManifestData());
+        assertTrue(updateManager.updateRequested());
+        assertEquals(NAME, updateManager.requestedUpdateName());
+
+        assertTrue(updateManager.destroyedFetcher());
+    }
+
+    /**
+     * Test that an update is requested if:
+     * - start_url does not refer to a Web Manifest.
+     * AND
+     * - The user eventually navigates to a page pointing to a Web Manifest with the correct URL.
+     * AND
+     * - The Web Manifest has changed.
+     */
+    @Test
+    public void testStartUrlRedirectsToPageWithUpdatedWebManifest() {
+        mClock.advance(WebappDataStorage.UPDATE_INTERVAL);
+
+        TestWebApkUpdateManager updateManager =
+                new TestWebApkUpdateManager(getStorage(WEBAPK_PACKAGE_NAME));
+        updateIfNeeded(updateManager);
+        assertTrue(updateManager.updateCheckStarted());
+
+        // start_url does not have a Web Manifest. {@link #onGotManifestData} is called as a result
+        // of update manager timing out. No update should be requested.
+        updateManager.onGotManifestData(null, null, null);
+        assertFalse(updateManager.updateRequested());
+        // {@link WebApkUpdateDataFetcher} should still be alive so that it can get
+        // {@link #onGotManifestData} when page with the Web Manifest finishes loading.
+        assertFalse(updateManager.destroyedFetcher());
+
+        // User eventually navigates to page with Web Manifest.
+
+        ManifestData manifestData = defaultManifestData();
+        manifestData.name = DIFFERENT_NAME;
+        onGotManifestData(updateManager, manifestData);
+        assertTrue(updateManager.updateRequested());
+        assertEquals(DIFFERENT_NAME, updateManager.requestedUpdateName());
+
+        assertTrue(updateManager.destroyedFetcher());
+    }
+
+    /**
+     * Test that an update is not requested if:
+     * - start_url does not refer to a Web Manifest.
+     * AND
+     * - The user eventually navigates to a page pointing to a Web Manifest with the correct URL.
+     * AND
+     * - The Web Manifest has not changed.
+     */
+    @Test
+    public void testStartUrlRedirectsToPageWithUnchangedWebManifest() {
+        mClock.advance(WebappDataStorage.UPDATE_INTERVAL);
+
+        TestWebApkUpdateManager updateManager =
+                new TestWebApkUpdateManager(getStorage(WEBAPK_PACKAGE_NAME));
+        updateIfNeeded(updateManager);
+
+        // Update manager times out.
+        updateManager.onGotManifestData(null, null, null);
+        onGotManifestData(updateManager, defaultManifestData());
+        assertFalse(updateManager.updateRequested());
+
+        // We got the Web Manifest. The {@link WebApkUpdateDataFetcher} should be destroyed to stop
+        // it from fetching the Web Manifest for subsequent page loads.
+        assertTrue(updateManager.destroyedFetcher());
+    }
+
+    @Test
+    public void testManifestDoesNotUpgrade() {
+        assertFalse(
+                checkUpdateNeededForFetchedManifest(defaultManifestData(), defaultManifestData()));
+    }
+
+    /**
+     * Test that a webapk with an unexpected package name does not request updates.
+     */
+    @Test
+    public void testUnboundWebApkDoesNotUpgrade() {
+        ManifestData androidManifestData = defaultManifestData();
+
+        registerWebApk(UNBOUND_WEBAPK_PACKAGE_NAME, androidManifestData, CURRENT_SHELL_APK_VERSION);
+        mClock.advance(WebappDataStorage.UPDATE_INTERVAL);
+
+        TestWebApkUpdateManager updateManager =
+                new TestWebApkUpdateManager(getStorage(UNBOUND_WEBAPK_PACKAGE_NAME));
+        updateIfNeeded(UNBOUND_WEBAPK_PACKAGE_NAME, updateManager);
+        assertFalse(updateManager.updateCheckStarted());
+        assertFalse(updateManager.updateRequested());
+    }
+
+    /**
+     * Test that an upgrade is not requested when the Web Manifest did not change and the Web
+     * Manifest scope is empty.
+     */
+    @Test
+    public void testManifestEmptyScopeShouldNotUpgrade() {
+        ManifestData oldData = defaultManifestData();
+        // webapk_installer.cc sets the scope to the default scope if the scope is empty.
+        oldData.scopeUrl = ShortcutHelper.getScopeFromUrl(oldData.startUrl);
+        ManifestData fetchedData = defaultManifestData();
+        fetchedData.scopeUrl = "";
+        assertTrue(!oldData.scopeUrl.equals(fetchedData.scopeUrl));
+        assertFalse(checkUpdateNeededForFetchedManifest(oldData, fetchedData));
+    }
+
+    /**
+     * Test that an upgrade is requested when the Web Manifest is updated from using a non-empty
+     * scope to an empty scope.
+     */
+    @Test
+    public void testManifestNonEmptyScopeToEmptyScopeShouldUpgrade() {
+        ManifestData oldData = defaultManifestData();
+        oldData.startUrl = "/fancy/scope/special/snowflake.html";
+        oldData.scopeUrl = "/fancy/scope/";
+        assertTrue(!oldData.scopeUrl.equals(ShortcutHelper.getScopeFromUrl(oldData.startUrl)));
+        ManifestData fetchedData = defaultManifestData();
+        fetchedData.startUrl = "/fancy/scope/special/snowflake.html";
+        fetchedData.scopeUrl = "";
+
+        assertTrue(checkUpdateNeededForFetchedManifest(oldData, fetchedData));
+    }
+
+    /**
+     * Test that an upgrade is requested when:
+     * - WebAPK was generated using icon at {@link PRIMARY_ICON_URL} from Web Manifest.
+     * - Bitmap at {@link PRIMARY_ICON_URL} has changed.
+     */
+    @Test
+    public void testPrimaryIconChangeShouldUpgrade() {
+        ManifestData fetchedData = defaultManifestData();
+        fetchedData.iconUrlToMurmur2HashMap.put(
+                fetchedData.primaryIconUrl, PRIMARY_ICON_MURMUR2_HASH + "1");
+        fetchedData.primaryIcon = createBitmap(Color.BLUE);
+        assertTrue(checkUpdateNeededForFetchedManifest(defaultManifestData(), fetchedData));
+    }
+
+    /**
+     * Test that an upgrade is requested when:
+     * - WebAPK was generated using icon at {@link BADGE_ICON_URL} from Web Manifest.
+     * - Bitmap at {@link BADGE_ICON_URL} has changed.
+     */
+    @Test
+    public void testBadgeIconChangeShouldUpgrade() {
+        ManifestData fetchedData = defaultManifestData();
+        fetchedData.iconUrlToMurmur2HashMap.put(
+                fetchedData.badgeIconUrl, BADGE_ICON_MURMUR2_HASH + "1");
+        fetchedData.badgeIcon = createBitmap(Color.GREEN);
+        assertTrue(checkUpdateNeededForFetchedManifest(defaultManifestData(), fetchedData));
+    }
+
+    /**
+     * Test that an upgrade is requested when:
+     * - WebAPK is generated using icon at {@link PRIMARY_ICON_URL} from Web Manifest.
+     * - A new icon URL is added to the Web Manifest. And InstallableManager selects the new icon as
+     *   the primary icon.
+     */
+    @Test
+    public void testPrimaryIconUrlChangeShouldUpgrade() {
+        ManifestData fetchedData = defaultManifestData();
+        fetchedData.iconUrlToMurmur2HashMap.put("/icon2.png", "22");
+        fetchedData.primaryIconUrl = "/icon2.png";
+        assertTrue(checkUpdateNeededForFetchedManifest(defaultManifestData(), fetchedData));
+    }
+
+    /**
+     * Test that an upgrade is requested when:
+     * - WebAPK is generated using icon at {@link BADGE_ICON_URL} from Web Manifest.
+     * - A new icon URL is added to the Web Manifest. And InstallableManager selects the new icon as
+     *   the badge icon.
+     */
+    @Test
+    public void testBadgeIconUrlChangeShouldUpgrade() {
+        ManifestData fetchedData = defaultManifestData();
+        fetchedData.iconUrlToMurmur2HashMap.put("/badge2.png", "44");
+        fetchedData.badgeIconUrl = "/badge2.png";
+        assertTrue(checkUpdateNeededForFetchedManifest(defaultManifestData(), fetchedData));
+    }
+
+    /**
+     * Test that an upgrade is not requested if:
+     * - icon URL is added to the Web Manifest
+     * AND
+     * - "best" icon URL for the primary icon did not change.
+     * AND
+     * - "best" icon URL for the badge icon did not change.
+     */
+    @Test
+    public void testIconUrlsChangeShouldNotUpgradeIfPrimaryIconUrlAndBadgeIconUrlDoNotChange() {
+        ManifestData fetchedData = defaultManifestData();
+        fetchedData.iconUrlToMurmur2HashMap.put("/icon2.png", null);
+        assertFalse(checkUpdateNeededForFetchedManifest(defaultManifestData(), fetchedData));
+    }
+
+    /**
+     * Test that an upgrade is not requested if:
+     * - the WebAPK's meta data has murmur2 hashes for all of the icons.
+     * AND
+     * - the Web Manifest has not changed
+     * AND
+     * - the computed best icon URLs are different from the one stored in the WebAPK's meta data.
+     */
+    @Test
+    public void testWebManifestSameButBestIconUrlChangedShouldNotUpgrade() {
+        String iconUrl1 = "/icon1.png";
+        String iconUrl2 = "/icon2.png";
+        String badgeUrl1 = "/badge1.png";
+        String badgeUrl2 = "/badge2.pgn";
+        String hash1 = "11";
+        String hash2 = "22";
+        String hash3 = "33";
+        String hash4 = "44";
+
+        ManifestData androidManifestData = defaultManifestData();
+        androidManifestData.primaryIconUrl = iconUrl1;
+        androidManifestData.badgeIconUrl = badgeUrl1;
+        androidManifestData.iconUrlToMurmur2HashMap.clear();
+        androidManifestData.iconUrlToMurmur2HashMap.put(iconUrl1, hash1);
+        androidManifestData.iconUrlToMurmur2HashMap.put(iconUrl2, hash2);
+        androidManifestData.iconUrlToMurmur2HashMap.put(badgeUrl1, hash3);
+        androidManifestData.iconUrlToMurmur2HashMap.put(badgeUrl2, hash4);
+
+        ManifestData fetchedManifestData = defaultManifestData();
+        fetchedManifestData.primaryIconUrl = iconUrl2;
+        fetchedManifestData.badgeIconUrl = badgeUrl2;
+        fetchedManifestData.iconUrlToMurmur2HashMap.clear();
+        fetchedManifestData.iconUrlToMurmur2HashMap.put(iconUrl1, null);
+        fetchedManifestData.iconUrlToMurmur2HashMap.put(iconUrl2, hash2);
+        fetchedManifestData.iconUrlToMurmur2HashMap.put(badgeUrl1, null);
+        fetchedManifestData.iconUrlToMurmur2HashMap.put(badgeUrl2, hash4);
+
+        assertFalse(checkUpdateNeededForFetchedManifest(androidManifestData, fetchedManifestData));
+    }
+
+    /**
+     * Tests that a WebAPK update is requested immediately if:
+     * the Shell APK is out of date,
+     * AND
+     * there wasn't a previous request for this ShellAPK version.
+     */
+    @Test
+    public void testShellApkOutOfDate() {
+        registerWebApk(WEBAPK_PACKAGE_NAME, defaultManifestData(), CURRENT_SHELL_APK_VERSION - 1);
+        TestWebApkUpdateManager updateManager =
+                new TestWebApkUpdateManager(getStorage(WEBAPK_PACKAGE_NAME));
+
+        // There have not been any update requests for the current ShellAPK version. A WebAPK update
+        // should be requested immediately.
+        updateIfNeeded(updateManager);
+        assertTrue(updateManager.updateCheckStarted());
+        onGotManifestData(updateManager, defaultManifestData());
+        assertTrue(updateManager.updateRequested());
+        tryCompletingUpdate(updateManager, WebApkInstallResult.FAILURE);
+
+        mClock.advance(1);
+        updateIfNeeded(updateManager);
+        assertFalse(updateManager.updateCheckStarted());
+
+        // A previous update request was made for the current ShellAPK version. A WebAPK update
+        // should be requested after the regular delay.
+        mClock.advance(WebappDataStorage.UPDATE_INTERVAL - 1);
+        updateIfNeeded(updateManager);
+        assertTrue(updateManager.updateCheckStarted());
+        onGotManifestData(updateManager, defaultManifestData());
+        assertTrue(updateManager.updateRequested());
+    }
+}
diff --git a/chrome/app/chromeos_strings.grdp b/chrome/app/chromeos_strings.grdp
index fedfa94..68d80bd 100644
--- a/chrome/app/chromeos_strings.grdp
+++ b/chrome/app/chromeos_strings.grdp
@@ -5346,6 +5346,6 @@
     Taking notes with <ph name="LOCK_SCREEN_APP_NAME">$1<ex>Lock Screen Enabled App</ex></ph>
   </message>
   <message name="IDS_LOCK_SCREEN_NOTE_APP_TOAST_DIALOG_MESSAGE" desc="Message shown in the body of the dialog shown to the user when they launch note taking app from the lock screen for the first time - the message has a placeholder for the launched app's name.">
-    Lock screen notes are accessible from the lock screen and automatically saved to <ph name="LOCK_SCREEN_APP_NAME">$1<ex>Lock Screen Enabled App</ex></ph>.
+    Lock screen notes are automatically saved to <ph name="LOCK_SCREEN_APP_NAME">$1<ex>Lock Screen Enabled App</ex></ph>. Your most recent note will remain on the lock screen.
   </message>
 </grit-part>
diff --git a/chrome/app/md_extensions_strings.grdp b/chrome/app/md_extensions_strings.grdp
index d0b8795..995be14 100644
--- a/chrome/app/md_extensions_strings.grdp
+++ b/chrome/app/md_extensions_strings.grdp
@@ -55,9 +55,21 @@
   <message name="IDS_MD_EXTENSIONS_ITEM_DETAILS" desc="The text on the button to show more details for a given extension.">
     Details
   </message>
+  <message name="IDS_MD_EXTENSIONS_APP_ICON" desc="The alt text for the app's icon. Used for accessibility.">
+    App Icon
+  </message>
+  <message name="IDS_MD_EXTENSIONS_EXTENSION_ICON" desc="The alt text for the extension's icon. Used for accessibility.">
+    Extension Icon
+  </message>
   <message name="IDS_MD_EXTENSIONS_ITEM_ID_HEADING" desc="The heading above the ID of the extension.">
     ID
   </message>
+  <message name="IDS_MD_EXTENSIONS_EXTENSION_ENABLED" desc="The label for the toggle that enables an extension.">
+    Extension Enabled
+  </message>
+  <message name="IDS_MD_EXTENSIONS_APP_ENABLED" desc="The label for the toggle that enables an app.">
+    App Enabled
+  </message>
   <message name="IDS_MD_EXTENSIONS_ITEM_OFF" desc="The label to indicate that a specific extension is not currently enabled.">
     Off
   </message>
diff --git a/chrome/app/settings_strings.grdp b/chrome/app/settings_strings.grdp
index f652f87..4af0e225 100644
--- a/chrome/app/settings_strings.grdp
+++ b/chrome/app/settings_strings.grdp
@@ -1288,9 +1288,15 @@
     <message name="IDS_SETTINGS_INTERNET" desc="Name of the settings page which displays internet preferences.">
       Network
     </message>
-    <message name="IDS_SETTINGS_INTERNET_CONFIG" desc="Name of the settings page for configuring a network.">
+    <message name="IDS_SETTINGS_INTERNET_CONFIG" desc="Title for the network configuration dialog.">
       Configure network
     </message>
+    <message name="IDS_SETTINGS_INTERNET_CONFIG_NAME" desc="Title for the network configuration dialog for an existing network.">
+      Configure <ph name="NAME">$1<ex>My WiFi network</ex></ph>
+    </message>
+    <message name="IDS_SETTINGS_INTERNET_JOIN_TYPE" desc="Title for the network configuration dialog for a new network.">
+      Join <ph name="TYPE">$1<ex>WiFi</ex></ph> network
+    </message>
     <message name="IDS_SETTINGS_INTERNET_DETAIL" desc="Name of the settings page which displays network details.">
       Network Details
     </message>
diff --git a/chrome/browser/BUILD.gn b/chrome/browser/BUILD.gn
index 60f69e44..2a917ee 100644
--- a/chrome/browser/BUILD.gn
+++ b/chrome/browser/BUILD.gn
@@ -2449,8 +2449,12 @@
       "media_galleries/win/snapshot_file_details.h",
       "memory/oom_memory_details.cc",
       "memory/oom_memory_details.h",
-      "memory/swap_thrashing_monitor_win.cc",
-      "memory/swap_thrashing_monitor_win.h",
+      "memory/swap_thrashing_monitor.cc",
+      "memory/swap_thrashing_monitor.h",
+      "memory/swap_thrashing_monitor_delegate.cc",
+      "memory/swap_thrashing_monitor_delegate.h",
+      "memory/swap_thrashing_monitor_delegate_win.cc",
+      "memory/swap_thrashing_monitor_delegate_win.h",
       "metrics/first_web_contents_profiler.cc",
       "metrics/first_web_contents_profiler.h",
       "metrics/tab_reactivation_tracker.cc",
@@ -3933,7 +3937,7 @@
   }
 
   if (enable_vr) {
-    if (enable_daydream) {
+    if (enable_gvr_services) {
       deps += [ "android/vr_shell:vr_android" ]
       configs += [ "//third_party/gvr-android-sdk:libgvr_config" ]
     }
diff --git a/chrome/browser/about_flags.cc b/chrome/browser/about_flags.cc
index 7b9465e..ad7f06f 100644
--- a/chrome/browser/about_flags.cc
+++ b/chrome/browser/about_flags.cc
@@ -152,6 +152,7 @@
 
 #if defined(OS_WIN)
 #include "base/win/windows_version.h"
+#include "chrome/browser/ui/tabs/tab_features.h"
 #endif  // OS_WIN
 
 using flags_ui::FeatureEntry;
@@ -1511,12 +1512,6 @@
      flag_descriptions::kEasyUnlockPromotionsDescription, kOsCrOS,
      FEATURE_VALUE_TYPE(features::kEasyUnlockPromotions)},
     {
-        "enable-fullscreen-app-list",
-        flag_descriptions::kEnableFullscreenAppListName,
-        flag_descriptions::kEnableFullscreenAppListDescription, kOsCrOS,
-        FEATURE_VALUE_TYPE(app_list::features::kEnableFullscreenAppList),
-    },
-    {
         "enable-pinch", flag_descriptions::kPinchScaleName,
         flag_descriptions::kPinchScaleDescription, kOsLinux | kOsWin | kOsCrOS,
         ENABLE_DISABLE_VALUE_TYPE(switches::kEnablePinch,
@@ -2054,6 +2049,9 @@
     {"enable-http-form-warning", flag_descriptions::kEnableHttpFormWarningName,
      flag_descriptions::kEnableHttpFormWarningDescription, kOsAll,
      FEATURE_VALUE_TYPE(security_state::kHttpFormWarningFeature)},
+    {"committed-interstitials", flag_descriptions::kCommittedInterstitialsName,
+     flag_descriptions::kCommittedInterstitialsDescription, kOsAll,
+     SINGLE_VALUE_TYPE(switches::kCommittedInterstitials)},
     {"enable-site-per-process", flag_descriptions::kSitePerProcessName,
      flag_descriptions::kSitePerProcessDescription, kOsAll,
      SINGLE_VALUE_TYPE(switches::kSitePerProcess)},
@@ -3453,6 +3451,14 @@
      flag_descriptions::kManualPasswordSavingDescription, kOsDesktop,
      FEATURE_VALUE_TYPE(password_manager::features::kEnableManualSaving)},
 
+#if !defined(OS_ANDROID)
+    {"remove-deprecared-gaia-signin-endpoint",
+     flag_descriptions::kRemoveUsageOfDeprecatedGaiaSigninEndpointName,
+     flag_descriptions::kRemoveUsageOfDeprecatedGaiaSigninEndpointDescription,
+     kOsWin | kOsMac | kOsLinux,
+     FEATURE_VALUE_TYPE(features::kRemoveUsageOfDeprecatedGaiaSigninEndpoint)},
+#endif
+
 #if defined(OS_ANDROID)
     {"third-party-doodles", flag_descriptions::kThirdPartyDoodlesName,
      flag_descriptions::kThirdPartyDoodlesDescription, kOsAndroid,
@@ -3597,6 +3603,13 @@
      flag_descriptions::kStopLoadingInBackgroundDescription, kOsAll,
      FEATURE_VALUE_TYPE(features::kStopLoadingInBackground)},
 
+#if defined(OS_WIN)
+    {"experimental-tab-controller",
+     flag_descriptions::kExperimentalTabControllerName,
+     flag_descriptions::kExperimentalTabControllerDescription, kOsWin,
+     FEATURE_VALUE_TYPE(kExperimentalTabControllerFeature)},
+#endif  // defined(OS_WIN)
+
     // 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/contextualsearch/contextual_search_delegate.cc b/chrome/browser/android/contextualsearch/contextual_search_delegate.cc
index 8919171d..66b9a20d 100644
--- a/chrome/browser/android/contextualsearch/contextual_search_delegate.cc
+++ b/chrome/browser/android/contextualsearch/contextual_search_delegate.cc
@@ -405,7 +405,7 @@
   Profile* profile = ProfileManager::GetActiveUserProfile();
   PrefService* pref_service = profile->GetPrefs();
   language::LanguageModel* language_model =
-      LanguageModelFactory::GetInstance()->GetForBrowserContext(profile);
+      LanguageModelFactory::GetForBrowserContext(profile);
   std::string result =
       TranslateService::GetTargetLanguage(pref_service, language_model);
   DCHECK(!result.empty());
diff --git a/chrome/browser/app_controller_mac.h b/chrome/browser/app_controller_mac.h
index 08160cef..adf019c 100644
--- a/chrome/browser/app_controller_mac.h
+++ b/chrome/browser/app_controller_mac.h
@@ -14,10 +14,8 @@
 
 #include "base/files/file_path.h"
 #include "base/mac/scoped_nsobject.h"
-#include "base/observer_list.h"
 #include "base/time/time.h"
 #include "components/prefs/pref_change_registrar.h"
-#include "ui/base/work_area_watcher_observer.h"
 
 class AppControllerProfileObserver;
 @class AppShimMenuController;
@@ -33,10 +31,6 @@
 class ScopedKeepAlive;
 @class ShareMenuController;
 
-namespace ui {
-class WorkAreaWatcherObserver;
-}
-
 // The application controller object, created by loading the MainMenu nib.
 // This handles things like responding to menus when there are no windows
 // open, etc and acts as the NSApplication delegate.
@@ -97,9 +91,6 @@
   // event, the time we got the event. A null time otherwise.
   base::TimeTicks reopenTime_;
 
-  // Observers that listen to the work area changes.
-  base::ObserverList<ui::WorkAreaWatcherObserver> workAreaChangeObservers_;
-
   std::unique_ptr<PrefChangeRegistrar> profilePrefRegistrar_;
   PrefChangeRegistrar localPrefRegistrar_;
 
@@ -168,10 +159,6 @@
 - (BookmarkMenuBridge*)bookmarkMenuBridge;
 - (HistoryMenuBridge*)historyMenuBridge;
 
-// Subscribes/unsubscribes from the work area change notification.
-- (void)addObserverForWorkAreaChange:(ui::WorkAreaWatcherObserver*)observer;
-- (void)removeObserverForWorkAreaChange:(ui::WorkAreaWatcherObserver*)observer;
-
 // Initializes the AppShimMenuController. This enables changing the menu bar for
 // apps.
 - (void)initAppShimMenuController;
diff --git a/chrome/browser/app_controller_mac.mm b/chrome/browser/app_controller_mac.mm
index 7f68155..ff639a9 100644
--- a/chrome/browser/app_controller_mac.mm
+++ b/chrome/browser/app_controller_mac.mm
@@ -1535,14 +1535,6 @@
   return historyMenuBridge_.get();
 }
 
-- (void)addObserverForWorkAreaChange:(ui::WorkAreaWatcherObserver*)observer {
-  workAreaChangeObservers_.AddObserver(observer);
-}
-
-- (void)removeObserverForWorkAreaChange:(ui::WorkAreaWatcherObserver*)observer {
-  workAreaChangeObservers_.RemoveObserver(observer);
-}
-
 - (void)initAppShimMenuController {
   if (!appShimMenuController_)
     appShimMenuController_.reset([[AppShimMenuController alloc] init]);
@@ -1599,18 +1591,6 @@
                  lastProfile_));
 }
 
-- (void)applicationDidChangeScreenParameters:(NSNotification*)notification {
-  // During this callback the working area is not always already updated. Defer.
-  [self performSelector:@selector(delayedScreenParametersUpdate)
-             withObject:nil
-             afterDelay:0];
-}
-
-- (void)delayedScreenParametersUpdate {
-  for (auto& observer : workAreaChangeObservers_)
-    observer.WorkAreaChanged();
-}
-
 - (BOOL)application:(NSApplication*)application
     willContinueUserActivityWithType:(NSString*)userActivityType
     API_AVAILABLE(macos(10.10)) {
diff --git a/chrome/browser/apps/drive/drive_app_converter.cc b/chrome/browser/apps/drive/drive_app_converter.cc
index ad3ffb4..3e94828 100644
--- a/chrome/browser/apps/drive/drive_app_converter.cc
+++ b/chrome/browser/apps/drive/drive_app_converter.cc
@@ -20,14 +20,14 @@
 #include "chrome/browser/image_decoder.h"
 #include "chrome/browser/profiles/profile.h"
 #include "content/public/browser/browser_thread.h"
+#include "content/public/browser/storage_partition.h"
+#include "content/public/common/resource_request.h"
+#include "content/public/common/simple_url_loader.h"
+#include "content/public/common/url_loader_factory.mojom.h"
 #include "extensions/browser/extension_system.h"
 #include "extensions/common/constants.h"
 #include "net/base/load_flags.h"
-#include "net/http/http_status_code.h"
 #include "net/traffic_annotation/network_traffic_annotation.h"
-#include "net/url_request/url_fetcher.h"
-#include "net/url_request/url_fetcher_delegate.h"
-#include "net/url_request/url_request_status.h"
 #include "third_party/skia/include/core/SkBitmap.h"
 
 using content::BrowserThread;
@@ -37,8 +37,7 @@
 // in Drive API:
 //   https://developers.google.com/drive/v2/reference/apps#resource
 // Each icon url represents a single image associated with a certain size.
-class DriveAppConverter::IconFetcher : public net::URLFetcherDelegate,
-                                       public ImageDecoder::ImageRequest {
+class DriveAppConverter::IconFetcher : public ImageDecoder::ImageRequest {
  public:
   IconFetcher(DriveAppConverter* converter,
               const GURL& icon_url,
@@ -72,32 +71,33 @@
             policy_exception_justification:
               "Not implemented, considered not useful."
           })");
-    fetcher_ = net::URLFetcher::Create(icon_url_, net::URLFetcher::GET, this,
-                                       traffic_annotation);
-    fetcher_->SetRequestContext(converter_->profile_->GetRequestContext());
-    fetcher_->SetLoadFlags(net::LOAD_DO_NOT_SAVE_COOKIES);
-    fetcher_->Start();
+    simple_loader_ = content::SimpleURLLoader::Create();
+    content::ResourceRequest resource_request = content::ResourceRequest();
+    resource_request.url = icon_url_;
+    resource_request.load_flags = net::LOAD_DO_NOT_SAVE_COOKIES;
+    content::mojom::URLLoaderFactory* loader_factory =
+        content::BrowserContext::GetDefaultStoragePartition(
+            converter_->profile_)
+            ->GetURLLoaderFactoryForBrowserProcess();
+    simple_loader_->DownloadToStringOfUnboundedSizeUntilCrashAndDie(
+        resource_request, loader_factory, traffic_annotation,
+        base::BindOnce(&DriveAppConverter::IconFetcher::OnCompleteCallback,
+                       base::Unretained(this)));
   }
 
   const GURL& icon_url() const { return icon_url_; }
   const SkBitmap& icon() const { return icon_; }
 
  private:
-  // net::URLFetcherDelegate overrides:
-  void OnURLFetchComplete(const net::URLFetcher* source) override {
-    CHECK_EQ(fetcher_.get(), source);
-    std::unique_ptr<net::URLFetcher> fetcher(std::move(fetcher_));
-
-    if (!fetcher->GetStatus().is_success() ||
-        fetcher->GetResponseCode() != net::HTTP_OK) {
+  void OnCompleteCallback(std::unique_ptr<std::string> response_body) {
+    if (!response_body) {
       converter_->OnIconFetchComplete(this);
       return;
     }
 
-    std::string unsafe_icon_data;
-    fetcher->GetResponseAsString(&unsafe_icon_data);
-
-    ImageDecoder::Start(this, unsafe_icon_data);
+    // Call start to begin decoding.  The ImageDecoder will call OnImageDecoded
+    // with the data when it is done.
+    ImageDecoder::Start(this, *response_body);
   }
 
   // ImageDecoder::ImageRequest overrides:
@@ -113,7 +113,7 @@
   const GURL icon_url_;
   const int expected_size_;
 
-  std::unique_ptr<net::URLFetcher> fetcher_;
+  std::unique_ptr<content::SimpleURLLoader> simple_loader_;
   SkBitmap icon_;
 
   DISALLOW_COPY_AND_ASSIGN(IconFetcher);
diff --git a/chrome/browser/apps/guest_view/web_view_browsertest.cc b/chrome/browser/apps/guest_view/web_view_browsertest.cc
index aafc46e..9a4182a 100644
--- a/chrome/browser/apps/guest_view/web_view_browsertest.cc
+++ b/chrome/browser/apps/guest_view/web_view_browsertest.cc
@@ -1528,6 +1528,66 @@
   TestHelper("testNewWindowNoReferrerLink", "web_view/shim", NEEDS_TEST_SERVER);
 }
 
+IN_PROC_BROWSER_TEST_P(WebViewNewWindowTest,
+                       Shim_TestWebViewAndEmbedderInNewWindow) {
+  ASSERT_TRUE(StartEmbeddedTestServer());  // For serving guest pages.
+
+  // Launch the app and wait until it's ready to load a test.
+  LoadAndLaunchPlatformApp("web_view/shim", "Launched");
+
+  content::WebContents* embedder_web_contents = GetFirstAppWindowWebContents();
+  ASSERT_TRUE(embedder_web_contents);
+
+  GURL::Replacements replace_host;
+  replace_host.SetHostStr("localhost");
+
+  std::string empty_guest_path(
+      "/extensions/platform_apps/web_view/shim/empty_guest.html");
+  GURL empty_guest_url = embedded_test_server()->GetURL(empty_guest_path);
+  empty_guest_url = empty_guest_url.ReplaceComponents(replace_host);
+
+  ui_test_utils::UrlLoadObserver empty_guest_observer(
+      empty_guest_url, content::NotificationService::AllSources());
+
+  // Run the test and wait until the guest WebContents is available and has
+  // finished loading.
+  ExtensionTestMessageListener done_listener("TEST_PASSED", false);
+  done_listener.set_failure_message("TEST_FAILED");
+  EXPECT_TRUE(content::ExecuteScript(
+      embedder_web_contents, "runTest('testWebViewAndEmbedderInNewWindow')"));
+
+  empty_guest_observer.Wait();
+
+  content::Source<content::NavigationController> source =
+      empty_guest_observer.source();
+  EXPECT_TRUE(source->GetWebContents()
+                  ->GetMainFrame()
+                  ->GetProcess()
+                  ->IsForGuestsOnly());
+  ASSERT_TRUE(done_listener.WaitUntilSatisfied());
+
+  // Make sure opener and owner for the empty_guest source are different.
+  // In general, we should have two guests and two embedders. Once we know the
+  // guests are different and the embedders are different, then we have four
+  // distinct WebContents, as we expect.
+  std::vector<content::WebContents*> guest_contents_list;
+  GetGuestViewManager()->GetGuestWebContentsList(&guest_contents_list);
+  ASSERT_EQ(2u, guest_contents_list.size());
+  content::WebContents* new_window_guest_contents = guest_contents_list[0];
+
+  content::WebContents* empty_guest_web_contents = source->GetWebContents();
+  ASSERT_EQ(empty_guest_web_contents, guest_contents_list[1]);
+  ASSERT_NE(empty_guest_web_contents, new_window_guest_contents);
+  content::WebContents* empty_guest_embedder =
+      GetEmbedderForGuest(empty_guest_web_contents);
+  ASSERT_NE(empty_guest_embedder, embedder_web_contents);
+  ASSERT_TRUE(empty_guest_embedder);
+  content::RenderFrameHost* empty_guest_opener =
+      empty_guest_web_contents->GetOriginalOpener();
+  ASSERT_TRUE(empty_guest_opener);
+  ASSERT_NE(empty_guest_opener, empty_guest_embedder->GetMainFrame());
+}
+
 IN_PROC_BROWSER_TEST_P(WebViewTest, Shim_TestContentLoadEvent) {
   TestHelper("testContentLoadEvent", "web_view/shim", NO_TEST_SERVER);
 }
diff --git a/chrome/browser/background_fetch/background_fetch_delegate_impl.cc b/chrome/browser/background_fetch/background_fetch_delegate_impl.cc
index 07a3b20..a0e6e74 100644
--- a/chrome/browser/background_fetch/background_fetch_delegate_impl.cc
+++ b/chrome/browser/background_fetch/background_fetch_delegate_impl.cc
@@ -52,6 +52,7 @@
       origin(origin),
       completed_parts(completed_parts),
       total_parts(total_parts),
+      cancelled(false),
       offline_item(offline_items_collection::ContentId("background_fetch",
                                                        job_unique_id)) {
   UpdateOfflineItem();
@@ -76,10 +77,14 @@
   }
   // TODO(delphick): Figure out what to put in offline_item.description.
   offline_item.is_transient = true;
-  offline_item.state =
-      (completed_parts == total_parts)
-          ? offline_items_collection::OfflineItemState::COMPLETE
-          : offline_items_collection::OfflineItemState::IN_PROGRESS;
+
+  using OfflineItemState = offline_items_collection::OfflineItemState;
+  if (cancelled)
+    offline_item.state = OfflineItemState::CANCELLED;
+  else if (completed_parts == total_parts)
+    offline_item.state = OfflineItemState::COMPLETE;
+  else
+    offline_item.state = OfflineItemState::IN_PROGRESS;
 }
 
 void BackgroundFetchDelegateImpl::CreateDownloadJob(
@@ -148,6 +153,8 @@
     return;
 
   JobDetails& job_details = job_details_iter->second;
+  job_details.cancelled = true;
+  UpdateOfflineItemAndUpdateObservers(&job_details);
 
   for (const auto& download_guid : job_details.current_download_guids) {
     download_service_->CancelDownload(download_guid);
@@ -162,8 +169,19 @@
     std::unique_ptr<content::BackgroundFetchResponse> response) {
   DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
 
-  if (client())
-    client()->OnDownloadStarted(download_guid, std::move(response));
+  auto download_job_unique_id_iter =
+      download_job_unique_id_map_.find(download_guid);
+  // TODO(crbug.com/779012): When DownloadService fixes cancelled jobs calling
+  // OnDownload* methods, then this can be a DCHECK.
+  if (download_job_unique_id_iter == download_job_unique_id_map_.end())
+    return;
+
+  const std::string& job_unique_id = download_job_unique_id_iter->second;
+
+  if (client()) {
+    client()->OnDownloadStarted(job_unique_id, download_guid,
+                                std::move(response));
+  }
 }
 
 void BackgroundFetchDelegateImpl::OnDownloadUpdated(
@@ -171,8 +189,17 @@
     uint64_t bytes_downloaded) {
   DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
 
+  auto download_job_unique_id_iter =
+      download_job_unique_id_map_.find(download_guid);
+  // TODO(crbug.com/779012): When DownloadService fixes cancelled jobs calling
+  // OnDownload* methods, then this can be a DCHECK.
+  if (download_job_unique_id_iter == download_job_unique_id_map_.end())
+    return;
+
+  const std::string& job_unique_id = download_job_unique_id_iter->second;
+
   if (client())
-    client()->OnDownloadUpdated(download_guid, bytes_downloaded);
+    client()->OnDownloadUpdated(job_unique_id, download_guid, bytes_downloaded);
 }
 
 void BackgroundFetchDelegateImpl::OnDownloadFailed(
@@ -185,14 +212,16 @@
 
   auto download_job_unique_id_iter =
       download_job_unique_id_map_.find(download_guid);
-  // Cancelled downloads will already have been deleted so just return.
+  // TODO(crbug.com/779012): When DownloadService fixes cancelled jobs
+  // potentially calling OnDownloadFailed with a reason other than
+  // CANCELLED/ABORTED, we should add a DCHECK here.
   if (download_job_unique_id_iter == download_job_unique_id_map_.end())
     return;
 
   const std::string& job_unique_id = download_job_unique_id_iter->second;
   JobDetails& job_details = job_details_map_.find(job_unique_id)->second;
   ++job_details.completed_parts;
-  job_details.UpdateOfflineItem();
+  UpdateOfflineItemAndUpdateObservers(&job_details);
 
   switch (reason) {
     case download::Client::FailureReason::NETWORK:
@@ -219,8 +248,9 @@
 
   if (client()) {
     client()->OnDownloadComplete(
-        download_guid, std::make_unique<content::BackgroundFetchResult>(
-                           base::Time::Now(), failure_reason));
+        job_unique_id, download_guid,
+        std::make_unique<content::BackgroundFetchResult>(base::Time::Now(),
+                                                         failure_reason));
   }
 
   job_details.current_download_guids.erase(
@@ -234,18 +264,23 @@
     uint64_t size) {
   DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
 
-  const std::string& job_unique_id = download_job_unique_id_map_[download_guid];
+  auto download_job_unique_id_iter =
+      download_job_unique_id_map_.find(download_guid);
+  // TODO(crbug.com/779012): When DownloadService fixes cancelled jobs calling
+  // OnDownload* methods, then this can be a DCHECK.
+  if (download_job_unique_id_iter == download_job_unique_id_map_.end())
+    return;
+
+  const std::string& job_unique_id = download_job_unique_id_iter->second;
   JobDetails& job_details = job_details_map_.find(job_unique_id)->second;
   ++job_details.completed_parts;
-  job_details.UpdateOfflineItem();
-
-  for (auto* observer : observers_)
-    observer->OnItemUpdated(job_details.offline_item);
+  UpdateOfflineItemAndUpdateObservers(&job_details);
 
   if (client()) {
     client()->OnDownloadComplete(
-        download_guid, std::make_unique<content::BackgroundFetchResult>(
-                           base::Time::Now(), path, size));
+        job_unique_id, download_guid,
+        std::make_unique<content::BackgroundFetchResult>(base::Time::Now(),
+                                                         path, size));
   }
 
   job_details.current_download_guids.erase(
@@ -287,6 +322,16 @@
   }
 }
 
+// Much of the code in offline_item_collection is not re-entrant, so this should
+// not be called from any of the OfflineContentProvider-inherited methods.
+void BackgroundFetchDelegateImpl::UpdateOfflineItemAndUpdateObservers(
+    JobDetails* job_details) {
+  job_details->UpdateOfflineItem();
+
+  for (auto* observer : observers_)
+    observer->OnItemUpdated(job_details->offline_item);
+}
+
 bool BackgroundFetchDelegateImpl::AreItemsAvailable() {
   return true;
 }
@@ -314,16 +359,12 @@
 
   for (auto& download_guid : job_details.current_download_guids) {
     download_service_->CancelDownload(download_guid);
-    if (client()) {
-      client()->OnDownloadComplete(
-          download_guid,
-          std::make_unique<content::BackgroundFetchResult>(
-              base::Time::Now(),
-              content::BackgroundFetchResult::FailureReason::CANCELLED));
-    }
     download_job_unique_id_map_.erase(download_guid);
   }
 
+  if (client())
+    client()->OnJobCancelled(id.id);
+
   job_details_map_.erase(job_details_iter);
 }
 
diff --git a/chrome/browser/background_fetch/background_fetch_delegate_impl.h b/chrome/browser/background_fetch/background_fetch_delegate_impl.h
index 2205302..c4d60880 100644
--- a/chrome/browser/background_fetch/background_fetch_delegate_impl.h
+++ b/chrome/browser/background_fetch/background_fetch_delegate_impl.h
@@ -109,6 +109,7 @@
     const url::Origin origin;
     int completed_parts;
     const int total_parts;
+    bool cancelled;
 
     // Set of DownloadService GUIDs that are currently downloading. They are
     // added by DownloadUrl and are removed when the download completes, fails
@@ -121,6 +122,11 @@
     DISALLOW_COPY_AND_ASSIGN(JobDetails);
   };
 
+  // Updates the OfflineItem that controls the contents of download
+  // notifications and notifies any OfflineContentProvider::Observer that was
+  // registered with this instance.
+  void UpdateOfflineItemAndUpdateObservers(JobDetails* job_details);
+
   void OnDownloadReceived(const std::string& guid,
                           download::DownloadParams::StartResult result);
 
diff --git a/chrome/browser/browsing_data/chrome_browsing_data_remover_delegate.cc b/chrome/browser/browsing_data/chrome_browsing_data_remover_delegate.cc
index 725114e1..9d91b57b 100644
--- a/chrome/browser/browsing_data/chrome_browsing_data_remover_delegate.cc
+++ b/chrome/browser/browsing_data/chrome_browsing_data_remover_delegate.cc
@@ -492,8 +492,7 @@
     }
 
     language::UrlLanguageHistogram* language_histogram =
-        UrlLanguageHistogramFactory::GetInstance()->GetForBrowserContext(
-            profile_);
+        UrlLanguageHistogramFactory::GetForBrowserContext(profile_);
     if (language_histogram) {
       language_histogram->ClearHistory(delete_begin_, delete_end_);
     }
diff --git a/chrome/browser/browsing_data/chrome_browsing_data_remover_delegate_unittest.cc b/chrome/browser/browsing_data/chrome_browsing_data_remover_delegate_unittest.cc
index 23ec19b1..5933ab8 100644
--- a/chrome/browser/browsing_data/chrome_browsing_data_remover_delegate_unittest.cc
+++ b/chrome/browser/browsing_data/chrome_browsing_data_remover_delegate_unittest.cc
@@ -2249,8 +2249,7 @@
 TEST_F(ChromeBrowsingDataRemoverDelegateTest,
        LanguageHistogramClearedOnClearingCompleteHistory) {
   language::UrlLanguageHistogram* language_histogram =
-      UrlLanguageHistogramFactory::GetInstance()->GetForBrowserContext(
-          GetProfile());
+      UrlLanguageHistogramFactory::GetForBrowserContext(GetProfile());
 
   // Simulate browsing.
   for (int i = 0; i < 100; i++) {
diff --git a/chrome/browser/chrome_browser_application_mac.mm b/chrome/browser/chrome_browser_application_mac.mm
index f465664..1e56890 100644
--- a/chrome/browser/chrome_browser_application_mac.mm
+++ b/chrome/browser/chrome_browser_application_mac.mm
@@ -166,19 +166,7 @@
   [appController stopTryingToTerminateApplication:self];
 }
 
-// The event |mask| has historically been declared as an NSUInteger
-// (unsigned long). Starting in the 10.12 SDK, the mask type changed to
-// NSEventMask (unsigned long long) if __LP64__ and NSUInteger otherwise.
-// These types are incompatible, which creates an issue for suppporting
-// both 10.10/10.11 and 10.12 SDKs. Work around it using the #if below.
-- (NSEvent*)nextEventMatchingMask:
-#if !defined(MAC_OS_X_VERSION_10_12) || \
-    MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_12 || \
-    !defined(__LP64__)
-                                  (NSUInteger)mask
-#else
-                                  (NSEventMask)mask
-#endif
+- (NSEvent*)nextEventMatchingMask:(NSEventMask)mask
                         untilDate:(NSDate*)expiration
                            inMode:(NSString*)mode
                           dequeue:(BOOL)dequeue {
diff --git a/chrome/browser/chrome_browser_main_win.cc b/chrome/browser/chrome_browser_main_win.cc
index 13c73bea..3c5235b 100644
--- a/chrome/browser/chrome_browser_main_win.cc
+++ b/chrome/browser/chrome_browser_main_win.cc
@@ -42,6 +42,7 @@
 #include "chrome/browser/conflicts/module_event_sink_impl_win.h"
 #include "chrome/browser/first_run/first_run.h"
 #include "chrome/browser/install_verification/win/install_verification.h"
+#include "chrome/browser/memory/swap_thrashing_monitor.h"
 #include "chrome/browser/profiles/profile_manager.h"
 #include "chrome/browser/profiles/profile_shortcut_manager.h"
 #include "chrome/browser/safe_browsing/chrome_cleaner/settings_resetter_win.h"
@@ -546,6 +547,9 @@
       FROM_HERE,
       base::Bind(&DetectFaultTolerantHeap),
       base::TimeDelta::FromMinutes(1));
+
+  // Start the swap thrashing monitor.
+  memory::SwapThrashingMonitor::Initialize();
 }
 
 // static
diff --git a/chrome/browser/chrome_content_browser_client.cc b/chrome/browser/chrome_content_browser_client.cc
index 865a0b9..96aeab39 100644
--- a/chrome/browser/chrome_content_browser_client.cc
+++ b/chrome/browser/chrome_content_browser_client.cc
@@ -184,6 +184,7 @@
 #include "content/public/browser/browser_thread.h"
 #include "content/public/browser/browser_url_handler.h"
 #include "content/public/browser/browsing_data_remover.h"
+#include "content/public/browser/certificate_request_result_type.h"
 #include "content/public/browser/child_process_data.h"
 #include "content/public/browser/child_process_security_policy.h"
 #include "content/public/browser/client_certificate_delegate.h"
@@ -2246,6 +2247,15 @@
     return;
   }
 
+  if (base::CommandLine::ForCurrentProcess()->HasSwitch(
+          switches::kCommittedInterstitials)) {
+    // We deny the request here in order to trigger the committed interstitials
+    // code path (committing certificate error pages as navigations) instead of
+    // the old code path.
+    callback.Run(content::CERTIFICATE_REQUEST_RESULT_TYPE_DENY);
+    return;
+  }
+
   // Otherwise, display an SSL blocking page. The interstitial page takes
   // ownership of ssl_blocking_page.
 
diff --git a/chrome/browser/chrome_navigation_browsertest.cc b/chrome/browser/chrome_navigation_browsertest.cc
index 230e9fd..b767357 100644
--- a/chrome/browser/chrome_navigation_browsertest.cc
+++ b/chrome/browser/chrome_navigation_browsertest.cc
@@ -186,7 +186,6 @@
   content::ContextMenuParams params;
   params.page_url = local_page_with_iframe_url;
   params.frame_url = frame->GetLastCommittedURL();
-  params.frame_page_state = content::PageState::CreateFromURL(params.frame_url);
   TestRenderViewContextMenu menu(frame, params);
   menu.Init();
   menu.ExecuteCommand(IDC_CONTENT_CONTEXT_VIEWFRAMESOURCE, 0);
diff --git a/chrome/browser/chromeos/arc/voice_interaction/arc_voice_interaction_framework_service_unittest.cc b/chrome/browser/chromeos/arc/voice_interaction/arc_voice_interaction_framework_service_unittest.cc
index e54b037..19f2e2c 100644
--- a/chrome/browser/chromeos/arc/voice_interaction/arc_voice_interaction_framework_service_unittest.cc
+++ b/chrome/browser/chromeos/arc/voice_interaction/arc_voice_interaction_framework_service_unittest.cc
@@ -34,15 +34,9 @@
 class TestHighlighterController : public ash::mojom::HighlighterController,
                                   public service_manager::Service {
  public:
-  TestHighlighterController()
-      : binding_(this),
-        connector_factory_(this),
-        connector_(connector_factory_.CreateConnector()) {}
-
+  TestHighlighterController() : binding_(this) {}
   ~TestHighlighterController() override = default;
 
-  service_manager::Connector* connector() { return connector_.get(); }
-
   void CallHandleSelection(const gfx::Rect& rect) {
     client_->HandleSelection(rect);
   }
@@ -90,8 +84,6 @@
   }
 
   mojo::Binding<ash::mojom::HighlighterController> binding_;
-  service_manager::TestConnectorFactory connector_factory_;
-  std::unique_ptr<service_manager::Connector> connector_;
   ash::mojom::HighlighterControllerClientPtr client_;
   bool is_enabled_ = false;
 
@@ -119,11 +111,18 @@
     arc_session_manager_ = std::make_unique<ArcSessionManager>(
         std::make_unique<ArcSessionRunner>(base::Bind(FakeArcSession::Create)));
     arc_bridge_service_ = std::make_unique<ArcBridgeService>();
-    highlighter_controller_ = std::make_unique<TestHighlighterController>();
+
+    auto highlighter_controller_ptr =
+        std::make_unique<TestHighlighterController>();
+    highlighter_controller_ = highlighter_controller_ptr.get();
+    connector_factory_ =
+        std::make_unique<service_manager::TestConnectorFactory>(
+            std::move(highlighter_controller_ptr));
+    connector_ = connector_factory_->CreateConnector();
     framework_service_ = std::make_unique<ArcVoiceInteractionFrameworkService>(
         profile_.get(), arc_bridge_service_.get());
     framework_service_->GetHighlighterClientForTesting()
-        ->SetConnectorForTesting(highlighter_controller_->connector());
+        ->SetConnectorForTesting(connector_.get());
     framework_instance_ =
         std::make_unique<FakeVoiceInteractionFrameworkInstance>();
     arc_bridge_service_->voice_interaction_framework()->SetInstance(
@@ -146,18 +145,20 @@
   }
 
  protected:
-  ArcBridgeService* arc_bridge_service() { return arc_bridge_service_.get(); }
+  ArcBridgeService* arc_bridge_service() const {
+    return arc_bridge_service_.get();
+  }
 
-  ArcVoiceInteractionFrameworkService* framework_service() {
+  ArcVoiceInteractionFrameworkService* framework_service() const {
     return framework_service_.get();
   }
 
-  FakeVoiceInteractionFrameworkInstance* framework_instance() {
+  FakeVoiceInteractionFrameworkInstance* framework_instance() const {
     return framework_instance_.get();
   }
 
-  TestHighlighterController* highlighter_controller() {
-    return highlighter_controller_.get();
+  TestHighlighterController* highlighter_controller() const {
+    return highlighter_controller_;
   }
 
   void FlushHighlighterControllerMojo() {
@@ -170,7 +171,10 @@
   std::unique_ptr<session_manager::SessionManager> session_manager_;
   std::unique_ptr<ArcBridgeService> arc_bridge_service_;
   std::unique_ptr<ArcSessionManager> arc_session_manager_;
-  std::unique_ptr<TestHighlighterController> highlighter_controller_;
+  std::unique_ptr<service_manager::TestConnectorFactory> connector_factory_;
+  std::unique_ptr<service_manager::Connector> connector_;
+  // |highlighter_controller_| is valid until |connector_factory_| is deleted.
+  TestHighlighterController* highlighter_controller_;
   std::unique_ptr<ArcVoiceInteractionFrameworkService> framework_service_;
   std::unique_ptr<FakeVoiceInteractionFrameworkInstance> framework_instance_;
 
diff --git a/chrome/browser/chromeos/events/event_rewriter_unittest.cc b/chrome/browser/chromeos/events/event_rewriter_unittest.cc
index 8c3a7a61..e2e53566 100644
--- a/chrome/browser/chromeos/events/event_rewriter_unittest.cc
+++ b/chrome/browser/chromeos/events/event_rewriter_unittest.cc
@@ -975,7 +975,10 @@
   InitModifierKeyPref(&search, prefs::kLanguageRemapSearchKeyTo,
                       ui::chromeos::ModifierKey::kCapsLockKey);
 
+  chromeos::input_method::FakeImeKeyboard ime_keyboard;
   rewriter_->KeyboardDeviceAddedForTesting(kKeyboardDeviceId, "PC Keyboard");
+  rewriter_->set_ime_keyboard_for_testing(&ime_keyboard);
+  EXPECT_FALSE(ime_keyboard.caps_lock_is_enabled_);
 
   // Press Search.
   EXPECT_EQ(GetExpectedResultAsString(
@@ -984,6 +987,7 @@
             GetRewrittenEventAsString(rewriter_, ui::ET_KEY_PRESSED,
                                       ui::VKEY_LWIN, ui::DomCode::META_LEFT,
                                       ui::EF_COMMAND_DOWN, ui::DomKey::META));
+  EXPECT_FALSE(ime_keyboard.caps_lock_is_enabled_);
 
   // Release Search.
   EXPECT_EQ(GetExpectedResultAsString(ui::ET_KEY_RELEASED, ui::VKEY_CAPITAL,
@@ -992,6 +996,7 @@
             GetRewrittenEventAsString(rewriter_, ui::ET_KEY_RELEASED,
                                       ui::VKEY_LWIN, ui::DomCode::META_LEFT,
                                       ui::EF_NONE, ui::DomKey::META));
+  EXPECT_TRUE(ime_keyboard.caps_lock_is_enabled_);
 
   // Press Search.
   EXPECT_EQ(GetExpectedResultAsString(
@@ -1001,6 +1006,7 @@
                                       ui::VKEY_LWIN, ui::DomCode::META_LEFT,
                                       ui::EF_COMMAND_DOWN | ui::EF_CAPS_LOCK_ON,
                                       ui::DomKey::META));
+  EXPECT_TRUE(ime_keyboard.caps_lock_is_enabled_);
 
   // Release Search.
   EXPECT_EQ(GetExpectedResultAsString(ui::ET_KEY_RELEASED, ui::VKEY_CAPITAL,
@@ -1009,6 +1015,7 @@
             GetRewrittenEventAsString(rewriter_, ui::ET_KEY_RELEASED,
                                       ui::VKEY_LWIN, ui::DomCode::META_LEFT,
                                       ui::EF_NONE, ui::DomKey::META));
+  EXPECT_FALSE(ime_keyboard.caps_lock_is_enabled_);
 
   // Press Caps Lock (on an external keyboard).
   EXPECT_EQ(GetExpectedResultAsString(
@@ -1018,6 +1025,7 @@
                                       ui::VKEY_CAPITAL, ui::DomCode::CAPS_LOCK,
                                       ui::EF_CAPS_LOCK_ON | ui::EF_MOD3_DOWN,
                                       ui::DomKey::CAPS_LOCK));
+  EXPECT_FALSE(ime_keyboard.caps_lock_is_enabled_);
 
   // Release Caps Lock (on an external keyboard).
   EXPECT_EQ(GetExpectedResultAsString(ui::ET_KEY_RELEASED, ui::VKEY_CAPITAL,
@@ -1026,6 +1034,7 @@
             GetRewrittenEventAsString(rewriter_, ui::ET_KEY_RELEASED,
                                       ui::VKEY_CAPITAL, ui::DomCode::CAPS_LOCK,
                                       ui::EF_NONE, ui::DomKey::CAPS_LOCK));
+  EXPECT_TRUE(ime_keyboard.caps_lock_is_enabled_);
 }
 
 TEST_F(EventRewriterTest, TestRewriteCapsLock) {
@@ -1043,6 +1052,15 @@
             GetRewrittenEventAsString(rewriter_, ui::ET_KEY_PRESSED,
                                       ui::VKEY_F16, ui::DomCode::F16,
                                       ui::EF_MOD3_DOWN, ui::DomKey::F16));
+  EXPECT_FALSE(ime_keyboard.caps_lock_is_enabled_);
+
+  EXPECT_EQ(GetExpectedResultAsString(ui::ET_KEY_RELEASED, ui::VKEY_CAPITAL,
+                                      ui::DomCode::CAPS_LOCK, ui::EF_NONE,
+                                      ui::DomKey::CAPS_LOCK),
+            GetRewrittenEventAsString(rewriter_, ui::ET_KEY_RELEASED,
+                                      ui::VKEY_F16, ui::DomCode::F16,
+                                      ui::EF_MOD3_DOWN, ui::DomKey::F16));
+  EXPECT_TRUE(ime_keyboard.caps_lock_is_enabled_);
 }
 
 TEST_F(EventRewriterTest, TestRewriteDiamondKey) {
diff --git a/chrome/browser/chromeos/extensions/file_manager/device_event_router.cc b/chrome/browser/chromeos/extensions/file_manager/device_event_router.cc
index ad8161ac..c97b214 100644
--- a/chrome/browser/chromeos/extensions/file_manager/device_event_router.cc
+++ b/chrome/browser/chromeos/extensions/file_manager/device_event_router.cc
@@ -139,7 +139,8 @@
                 device_path);
 }
 
-void DeviceEventRouter::SuspendImminent() {
+void DeviceEventRouter::SuspendImminent(
+    power_manager::SuspendImminent::Reason reason) {
   DCHECK(thread_checker_.CalledOnValidThread());
   is_resuming_ = true;
 }
diff --git a/chrome/browser/chromeos/extensions/file_manager/device_event_router.h b/chrome/browser/chromeos/extensions/file_manager/device_event_router.h
index cd4136d4..35e654cd4 100644
--- a/chrome/browser/chromeos/extensions/file_manager/device_event_router.h
+++ b/chrome/browser/chromeos/extensions/file_manager/device_event_router.h
@@ -58,7 +58,7 @@
   void OnRenameCompleted(const std::string& device_path, bool success) override;
 
   // PowerManagerClient::Observer overrides.
-  void SuspendImminent() override;
+  void SuspendImminent(power_manager::SuspendImminent::Reason reason) override;
   void SuspendDone(const base::TimeDelta& sleep_duration) override;
 
   bool is_resuming() const { return is_resuming_; }
diff --git a/chrome/browser/chromeos/file_manager/file_manager_browsertest_base.cc b/chrome/browser/chromeos/file_manager/file_manager_browsertest_base.cc
index e35aa82..17943d12 100644
--- a/chrome/browser/chromeos/file_manager/file_manager_browsertest_base.cc
+++ b/chrome/browser/chromeos/file_manager/file_manager_browsertest_base.cc
@@ -716,7 +716,7 @@
 
   if (name == "useCellularNetwork") {
     net::NetworkChangeNotifier::NotifyObserversOfMaxBandwidthChangeForTests(
-        net::NetworkChangeNotifier::GetMaxBandwidthForConnectionSubtype(
+        net::NetworkChangeNotifier::GetMaxBandwidthMbpsForConnectionSubtype(
             net::NetworkChangeNotifier::SUBTYPE_HSPA),
         net::NetworkChangeNotifier::CONNECTION_3G);
     return;
diff --git a/chrome/browser/chromeos/file_manager/volume_manager_unittest.cc b/chrome/browser/chromeos/file_manager/volume_manager_unittest.cc
index 5e58355..89ba234 100644
--- a/chrome/browser/chromeos/file_manager/volume_manager_unittest.cc
+++ b/chrome/browser/chromeos/file_manager/volume_manager_unittest.cc
@@ -20,6 +20,7 @@
 #include "chrome/common/pref_names.h"
 #include "chrome/test/base/testing_profile.h"
 #include "chromeos/dbus/fake_power_manager_client.h"
+#include "chromeos/dbus/power_manager/suspend.pb.h"
 #include "chromeos/disks/disk_mount_manager.h"
 #include "components/prefs/pref_service.h"
 #include "components/storage_monitor/storage_info.h"
@@ -588,7 +589,8 @@
 
   // Emulate system suspend and then resume.
   {
-    power_manager_client_->SendSuspendImminent();
+    power_manager_client_->SendSuspendImminent(
+        power_manager::SuspendImminent_Reason_OTHER);
     power_manager_client_->SendSuspendDone();
 
     // After resume, the device is unmounted and then mounted.
diff --git a/chrome/browser/chromeos/lock_screen_apps/first_app_run_toast_manager.cc b/chrome/browser/chromeos/lock_screen_apps/first_app_run_toast_manager.cc
index 6eb66752e..1823ddad 100644
--- a/chrome/browser/chromeos/lock_screen_apps/first_app_run_toast_manager.cc
+++ b/chrome/browser/chromeos/lock_screen_apps/first_app_run_toast_manager.cc
@@ -86,7 +86,7 @@
 
 void FirstAppRunToastManager::CreateAndShowToastDialog() {
   auto* toast_dialog = new ToastDialogView(
-      base::UTF8ToUTF16(app_window_->GetExtension()->name()),
+      base::UTF8ToUTF16(app_window_->GetExtension()->short_name()),
       base::Bind(&FirstAppRunToastManager::ToastDialogDismissed,
                  weak_ptr_factory_.GetWeakPtr()));
   toast_dialog->Show();
diff --git a/chrome/browser/chromeos/lock_screen_apps/state_controller.cc b/chrome/browser/chromeos/lock_screen_apps/state_controller.cc
index be27ed0..ecd59220 100644
--- a/chrome/browser/chromeos/lock_screen_apps/state_controller.cc
+++ b/chrome/browser/chromeos/lock_screen_apps/state_controller.cc
@@ -416,7 +416,8 @@
   SetScreenState(level == 0 ? ScreenState::kOff : ScreenState::kOn);
 }
 
-void StateController::SuspendImminent() {
+void StateController::SuspendImminent(
+    power_manager::SuspendImminent::Reason reason) {
   ResetNoteTakingWindowAndMoveToNextState(true /*close_window*/,
                                           CloseLockScreenNoteReason::kSuspend);
 }
@@ -508,11 +509,13 @@
   note_app_window_->web_contents()->Focus();
 }
 
-void StateController::SetInitialScreenState(double screen_brightness) {
-  if (screen_state_ != ScreenState::kUnknown)
+void StateController::SetInitialScreenState(
+    base::Optional<double> screen_brightness) {
+  if (screen_state_ != ScreenState::kUnknown || !screen_brightness.has_value())
     return;
 
-  SetScreenState(screen_brightness == 0 ? ScreenState::kOff : ScreenState::kOn);
+  SetScreenState(screen_brightness.value() == 0 ? ScreenState::kOff
+                                                : ScreenState::kOn);
 }
 
 void StateController::SetScreenState(ScreenState screen_state) {
diff --git a/chrome/browser/chromeos/lock_screen_apps/state_controller.h b/chrome/browser/chromeos/lock_screen_apps/state_controller.h
index caf54a10..688b8ba 100644
--- a/chrome/browser/chromeos/lock_screen_apps/state_controller.h
+++ b/chrome/browser/chromeos/lock_screen_apps/state_controller.h
@@ -12,6 +12,7 @@
 #include "base/callback.h"
 #include "base/memory/weak_ptr.h"
 #include "base/observer_list.h"
+#include "base/optional.h"
 #include "base/scoped_observer.h"
 #include "base/time/time.h"
 #include "chrome/browser/chromeos/lock_screen_apps/app_manager.h"
@@ -148,7 +149,7 @@
 
   // chromeos::PowerManagerClient::Observer
   void BrightnessChanged(int level, bool user_initiated) override;
-  void SuspendImminent() override;
+  void SuspendImminent(power_manager::SuspendImminent::Reason reason) override;
 
   // Creates and registers an app window as action handler for the action on
   // Chrome OS lock screen. The ownership of the returned app window is passed
@@ -235,7 +236,7 @@
 
   // Updates the screen state to match the current screen brightness - no-op
   // unless the current screen state is unknown.
-  void SetInitialScreenState(double screen_brightness);
+  void SetInitialScreenState(base::Optional<double> screen_brightness);
 
   // Updates ths screen state - if the stylus was recently removed and screen
   // has turned on, this will launch a new note action (stylus being removed
diff --git a/chrome/browser/chromeos/lock_screen_apps/state_controller_unittest.cc b/chrome/browser/chromeos/lock_screen_apps/state_controller_unittest.cc
index 6abcb41..63ebfc0 100644
--- a/chrome/browser/chromeos/lock_screen_apps/state_controller_unittest.cc
+++ b/chrome/browser/chromeos/lock_screen_apps/state_controller_unittest.cc
@@ -41,6 +41,7 @@
 #include "chrome/test/base/testing_profile_manager.h"
 #include "chromeos/dbus/dbus_thread_manager.h"
 #include "chromeos/dbus/fake_power_manager_client.h"
+#include "chromeos/dbus/power_manager/suspend.pb.h"
 #include "components/arc/arc_service_manager.h"
 #include "components/arc/arc_session.h"
 #include "components/session_manager/core/session_manager.h"
@@ -1505,7 +1506,8 @@
   ASSERT_TRUE(InitializeNoteTakingApp(TrayActionState::kActive,
                                       true /* enable_app_launch */));
 
-  GetPowerManagerClient()->SendSuspendImminent();
+  GetPowerManagerClient()->SendSuspendImminent(
+      power_manager::SuspendImminent_Reason_OTHER);
   EXPECT_EQ(TrayActionState::kAvailable,
             state_controller()->GetLockScreenNoteState());
 
diff --git a/chrome/browser/chromeos/login/lock/webui_screen_locker.cc b/chrome/browser/chromeos/login/lock/webui_screen_locker.cc
index 774a30c..6dc8a5c89 100644
--- a/chrome/browser/chromeos/login/lock/webui_screen_locker.cc
+++ b/chrome/browser/chromeos/login/lock/webui_screen_locker.cc
@@ -401,7 +401,8 @@
   }
 }
 
-void WebUIScreenLocker::SuspendImminent() {
+void WebUIScreenLocker::SuspendImminent(
+    power_manager::SuspendImminent::Reason reason) {
   content::BrowserThread::PostTask(
       content::BrowserThread::UI, FROM_HERE,
       base::BindOnce(&WebUIScreenLocker::ResetAndFocusUserPod,
diff --git a/chrome/browser/chromeos/login/lock/webui_screen_locker.h b/chrome/browser/chromeos/login/lock/webui_screen_locker.h
index 697b659..048a31a 100644
--- a/chrome/browser/chromeos/login/lock/webui_screen_locker.h
+++ b/chrome/browser/chromeos/login/lock/webui_screen_locker.h
@@ -111,7 +111,7 @@
   void OnWidgetDestroying(views::Widget* widget) override;
 
   // PowerManagerClient::Observer:
-  void SuspendImminent() override;
+  void SuspendImminent(power_manager::SuspendImminent::Reason reason) override;
   void SuspendDone(const base::TimeDelta& sleep_duration) override;
   void LidEventReceived(PowerManagerClient::LidState state,
                         const base::TimeTicks& time) override;
diff --git a/chrome/browser/chromeos/login/signin/oauth2_token_fetcher.cc b/chrome/browser/chromeos/login/signin/oauth2_token_fetcher.cc
index 0ddc0f0..7f2419af 100644
--- a/chrome/browser/chromeos/login/signin/oauth2_token_fetcher.cc
+++ b/chrome/browser/chromeos/login/signin/oauth2_token_fetcher.cc
@@ -58,7 +58,7 @@
         base::TimeDelta::FromMilliseconds(kRequestRestartDelay));
     return;
   }
-  auth_fetcher_.StartCookieForOAuthLoginTokenExchangeWithDeviceId(
+  auth_fetcher_.DeprecatedStartCookieForOAuthLoginTokenExchangeWithDeviceId(
       session_index, signin_scoped_device_id);
 }
 
diff --git a/chrome/browser/chromeos/login/wizard_controller.cc b/chrome/browser/chromeos/login/wizard_controller.cc
index 657c6c10..0b0ad35 100644
--- a/chrome/browser/chromeos/login/wizard_controller.cc
+++ b/chrome/browser/chromeos/login/wizard_controller.cc
@@ -93,6 +93,7 @@
 #include "chromeos/timezone/timezone_provider.h"
 #include "components/arc/arc_bridge_service.h"
 #include "components/arc/arc_prefs.h"
+#include "components/arc/arc_util.h"
 #include "components/crash/content/app/breakpad_linux.h"
 #include "components/pairing/bluetooth_controller_pairing_controller.h"
 #include "components/pairing/bluetooth_host_pairing_controller.h"
@@ -875,7 +876,8 @@
 
 void WizardController::OnVoiceInteractionValuePropAccepted() {
   const Profile* profile = ProfileManager::GetActiveUserProfile();
-  if (is_in_session_oobe_ && !arc::IsArcPlayStoreEnabledForProfile(profile)) {
+  if (is_in_session_oobe_ && !arc::IsArcPlayStoreEnabledForProfile(profile) &&
+      !arc::ShouldArcAlwaysStart()) {
     ShowArcTermsOfServiceScreen();
     return;
   }
diff --git a/chrome/browser/chromeos/note_taking_helper_unittest.cc b/chrome/browser/chromeos/note_taking_helper_unittest.cc
index 8659d4b..2f25e59 100644
--- a/chrome/browser/chromeos/note_taking_helper_unittest.cc
+++ b/chrome/browser/chromeos/note_taking_helper_unittest.cc
@@ -149,15 +149,10 @@
 class TestNoteTakingController : public ash::mojom::NoteTakingController,
                                  public service_manager::Service {
  public:
-  TestNoteTakingController()
-      : binding_(this),
-        connector_factory_(this),
-        connector_(connector_factory_.CreateConnector()) {}
+  TestNoteTakingController() : binding_(this) {}
 
   ~TestNoteTakingController() override = default;
 
-  service_manager::Connector* connector() const { return connector_.get(); }
-
   void CallCreateNote() {
     client_->CreateNote();
     client_.FlushForTesting();
@@ -190,8 +185,6 @@
   }
 
   mojo::Binding<ash::mojom::NoteTakingController> binding_;
-  service_manager::TestConnectorFactory connector_factory_;
-  std::unique_ptr<service_manager::Connector> connector_;
   ash::mojom::NoteTakingControllerClientPtr client_;
 
   DISALLOW_COPY_AND_ASSIGN(TestNoteTakingController);
@@ -252,7 +245,7 @@
   static NoteTakingHelper* helper() { return NoteTakingHelper::Get(); }
 
   TestNoteTakingController* test_note_taking_controller() {
-    return test_note_taking_controller_.get();
+    return test_note_taking_controller_;
   }
 
   NoteTakingControllerClient* note_taking_client() {
@@ -302,9 +295,15 @@
     NoteTakingHelper::Get()->set_launch_chrome_app_callback_for_test(base::Bind(
         &NoteTakingHelperTest::LaunchChromeApp, base::Unretained(this)));
 
-    test_note_taking_controller_ = std::make_unique<TestNoteTakingController>();
-    note_taking_client()->SetConnectorForTesting(
-        test_note_taking_controller_->connector());
+    auto test_note_taking_controller_ptr =
+        std::make_unique<TestNoteTakingController>();
+    test_note_taking_controller_ = test_note_taking_controller_ptr.get();
+    connector_factory_ =
+        std::make_unique<service_manager::TestConnectorFactory>(
+            std::move(test_note_taking_controller_ptr));
+    connector_ = connector_factory_->CreateConnector();
+
+    note_taking_client()->SetConnectorForTesting(connector_.get());
   }
 
   // Creates an extension.
@@ -512,7 +511,10 @@
 
   FakeSessionManagerClient* session_manager_client_ = nullptr;  // Not owned.
   ArcAppTest arc_test_;
-  std::unique_ptr<TestNoteTakingController> test_note_taking_controller_;
+  std::unique_ptr<service_manager::TestConnectorFactory> connector_factory_;
+  // |test_note_taking_controller_| is owned by |connector_factory_|.
+  TestNoteTakingController* test_note_taking_controller_;
+  std::unique_ptr<service_manager::Connector> connector_;
 
   DISALLOW_COPY_AND_ASSIGN(NoteTakingHelperTest);
 };
diff --git a/chrome/browser/chromeos/policy/blocking_login_browsertest.cc b/chrome/browser/chromeos/policy/blocking_login_browsertest.cc
index aa9e1895..cace55c 100644
--- a/chrome/browser/chromeos/policy/blocking_login_browsertest.cc
+++ b/chrome/browser/chromeos/policy/blocking_login_browsertest.cc
@@ -180,7 +180,8 @@
     std::unique_ptr<net::test_server::HttpResponse> response;
 
     GaiaUrls* gaia = GaiaUrls::GetInstance();
-    if (request.relative_url == gaia->client_login_to_oauth2_url().path() ||
+    if (request.relative_url ==
+            gaia->deprecated_client_login_to_oauth2_url().path() ||
         request.relative_url == gaia->oauth2_token_url().path() ||
         base::StartsWith(request.relative_url, kDMRegisterRequest,
                          base::CompareCase::SENSITIVE) ||
diff --git a/chrome/browser/chromeos/policy/policy_oauth2_token_fetcher.cc b/chrome/browser/chromeos/policy/policy_oauth2_token_fetcher.cc
index 077b3b9..3787e97 100644
--- a/chrome/browser/chromeos/policy/policy_oauth2_token_fetcher.cc
+++ b/chrome/browser/chromeos/policy/policy_oauth2_token_fetcher.cc
@@ -179,7 +179,7 @@
   if (auth_code_.empty()) {
     refresh_token_fetcher_.reset(new GaiaAuthFetcher(
         this, GaiaConstants::kChromeSource, auth_context_getter_.get()));
-    refresh_token_fetcher_->StartCookieForOAuthLoginTokenExchange(
+    refresh_token_fetcher_->DeprecatedStartCookieForOAuthLoginTokenExchange(
         std::string());
   } else {
     refresh_token_fetcher_.reset(new GaiaAuthFetcher(
diff --git a/chrome/browser/chromeos/policy/user_cloud_policy_manager_chromeos_unittest.cc b/chrome/browser/chromeos/policy/user_cloud_policy_manager_chromeos_unittest.cc
index 8963fa75..e0d000d 100644
--- a/chrome/browser/chromeos/policy/user_cloud_policy_manager_chromeos_unittest.cc
+++ b/chrome/browser/chromeos/policy/user_cloud_policy_manager_chromeos_unittest.cc
@@ -224,7 +224,8 @@
       net::TestURLFetcher* fetcher = NULL;
 
       // Issue the oauth_token cookie first.
-      fetcher = PrepareOAuthFetcher(gaia_urls->client_login_to_oauth2_url());
+      fetcher = PrepareOAuthFetcher(
+          gaia_urls->deprecated_client_login_to_oauth2_url());
       if (!fetcher)
         return NULL;
 
@@ -466,7 +467,7 @@
   // The PolicyOAuth2TokenFetcher posts delayed retries on some errors. This
   // data will make it fail immediately.
   net::TestURLFetcher* fetcher = PrepareOAuthFetcher(
-      GaiaUrls::GetInstance()->client_login_to_oauth2_url());
+      GaiaUrls::GetInstance()->deprecated_client_login_to_oauth2_url());
   ASSERT_TRUE(fetcher);
   fetcher->set_response_code(400);
   fetcher->SetResponseString("Error=BadAuthentication");
diff --git a/chrome/browser/chromeos/power/extension_event_observer.cc b/chrome/browser/chromeos/power/extension_event_observer.cc
index 47f95ac..c7aed00 100644
--- a/chrome/browser/chromeos/power/extension_event_observer.cc
+++ b/chrome/browser/chromeos/power/extension_event_observer.cc
@@ -205,7 +205,8 @@
   }
 }
 
-void ExtensionEventObserver::SuspendImminent() {
+void ExtensionEventObserver::SuspendImminent(
+    power_manager::SuspendImminent::Reason reason) {
   if (should_delay_suspend_)
     OnSuspendImminent(false);
 }
diff --git a/chrome/browser/chromeos/power/extension_event_observer.h b/chrome/browser/chromeos/power/extension_event_observer.h
index d8cf3670..7d4510e 100644
--- a/chrome/browser/chromeos/power/extension_event_observer.h
+++ b/chrome/browser/chromeos/power/extension_event_observer.h
@@ -95,7 +95,7 @@
                             uint64_t request_id) override;
 
   // PowerManagerClient::Observer overrides.
-  void SuspendImminent() override;
+  void SuspendImminent(power_manager::SuspendImminent::Reason reason) override;
   void DarkSuspendImminent() override;
   void SuspendDone(const base::TimeDelta& duration) override;
 
diff --git a/chrome/browser/chromeos/power/extension_event_observer_unittest.cc b/chrome/browser/chromeos/power/extension_event_observer_unittest.cc
index 32782aa..63f07ca9 100644
--- a/chrome/browser/chromeos/power/extension_event_observer_unittest.cc
+++ b/chrome/browser/chromeos/power/extension_event_observer_unittest.cc
@@ -23,6 +23,7 @@
 #include "chrome/test/base/testing_profile_manager.h"
 #include "chromeos/dbus/dbus_thread_manager.h"
 #include "chromeos/dbus/fake_power_manager_client.h"
+#include "chromeos/dbus/power_manager/suspend.pb.h"
 #include "content/public/test/test_browser_thread_bundle.h"
 #include "content/public/test/test_renderer_host.h"
 #include "extensions/browser/extension_host.h"
@@ -160,7 +161,8 @@
 // Tests that the ExtensionEventObserver reports readiness for suspend when
 // there is nothing interesting going on.
 TEST_F(ExtensionEventObserverTest, BasicSuspendAndDarkSuspend) {
-  power_manager_client_->SendSuspendImminent();
+  power_manager_client_->SendSuspendImminent(
+      power_manager::SuspendImminent_Reason_OTHER);
   EXPECT_EQ(1, power_manager_client_->GetNumPendingSuspendReadinessCallbacks());
 
   EXPECT_TRUE(test_api_->MaybeRunSuspendReadinessCallback());
@@ -176,7 +178,8 @@
 // Tests that the ExtensionEventObserver properly handles a canceled suspend
 // attempt.
 TEST_F(ExtensionEventObserverTest, CanceledSuspend) {
-  power_manager_client_->SendSuspendImminent();
+  power_manager_client_->SendSuspendImminent(
+      power_manager::SuspendImminent_Reason_OTHER);
   EXPECT_EQ(1, power_manager_client_->GetNumPendingSuspendReadinessCallbacks());
 
   power_manager_client_->SendSuspendDone();
@@ -197,7 +200,8 @@
   const int kSuspendPushId = 23874;
   extension_event_observer_->OnBackgroundEventDispatched(
       host, extensions::api::gcm::OnMessage::kEventName, kSuspendPushId);
-  power_manager_client_->SendSuspendImminent();
+  power_manager_client_->SendSuspendImminent(
+      power_manager::SuspendImminent_Reason_OTHER);
 
   EXPECT_TRUE(test_api_->MaybeRunSuspendReadinessCallback());
   EXPECT_EQ(1, power_manager_client_->GetNumPendingSuspendReadinessCallbacks());
@@ -235,7 +239,8 @@
 
   EXPECT_FALSE(test_api_->WillDelaySuspendForExtensionHost(host));
 
-  power_manager_client_->SendSuspendImminent();
+  power_manager_client_->SendSuspendImminent(
+      power_manager::SuspendImminent_Reason_OTHER);
   EXPECT_TRUE(test_api_->MaybeRunSuspendReadinessCallback());
   EXPECT_EQ(0, power_manager_client_->GetNumPendingSuspendReadinessCallbacks());
 }
@@ -252,7 +257,8 @@
   // are ignored.
   const uint64_t kNonPushRequestId = 5170725;
   extension_event_observer_->OnNetworkRequestStarted(host, kNonPushRequestId);
-  power_manager_client_->SendSuspendImminent();
+  power_manager_client_->SendSuspendImminent(
+      power_manager::SuspendImminent_Reason_OTHER);
 
   EXPECT_TRUE(test_api_->MaybeRunSuspendReadinessCallback());
   EXPECT_EQ(0, power_manager_client_->GetNumPendingSuspendReadinessCallbacks());
@@ -301,7 +307,8 @@
   // ExtensionHosts.
   profile_manager_->DeleteTestingProfile(kProfileName);
 
-  power_manager_client_->SendSuspendImminent();
+  power_manager_client_->SendSuspendImminent(
+      power_manager::SuspendImminent_Reason_OTHER);
   EXPECT_TRUE(test_api_->MaybeRunSuspendReadinessCallback());
   EXPECT_EQ(0, power_manager_client_->GetNumPendingSuspendReadinessCallbacks());
 }
@@ -320,7 +327,8 @@
   const int kPushId = 416753;
   extension_event_observer_->OnBackgroundEventDispatched(
       host, extensions::api::gcm::OnMessage::kEventName, kPushId);
-  power_manager_client_->SendSuspendImminent();
+  power_manager_client_->SendSuspendImminent(
+      power_manager::SuspendImminent_Reason_OTHER);
   EXPECT_EQ(1, power_manager_client_->GetNumPendingSuspendReadinessCallbacks());
 
   extension_event_observer_->SetShouldDelaySuspend(false);
diff --git a/chrome/browser/chromeos/power/renderer_freezer_unittest.cc b/chrome/browser/chromeos/power/renderer_freezer_unittest.cc
index a2af7b3..a8ba431 100644
--- a/chrome/browser/chromeos/power/renderer_freezer_unittest.cc
+++ b/chrome/browser/chromeos/power/renderer_freezer_unittest.cc
@@ -23,6 +23,7 @@
 #include "chrome/test/base/testing_profile_manager.h"
 #include "chromeos/dbus/dbus_thread_manager.h"
 #include "chromeos/dbus/fake_power_manager_client.h"
+#include "chromeos/dbus/power_manager/suspend.pb.h"
 #include "content/public/browser/notification_service.h"
 #include "content/public/browser/notification_source.h"
 #include "content/public/browser/notification_types.h"
@@ -168,7 +169,8 @@
 TEST_F(RendererFreezerTest, SuspendResume) {
   Init();
 
-  power_manager_client_->SendSuspendImminent();
+  power_manager_client_->SendSuspendImminent(
+      power_manager::SuspendImminent_Reason_OTHER);
   EXPECT_EQ(kFreezeRenderers, test_delegate_->GetActions());
 
   // The renderers should be thawed when we resume.
@@ -183,7 +185,8 @@
   Init();
 
   // Nothing happens on suspend.
-  power_manager_client_->SendSuspendImminent();
+  power_manager_client_->SendSuspendImminent(
+      power_manager::SuspendImminent_Reason_OTHER);
   EXPECT_EQ(kNoActions, test_delegate_->GetActions());
 
   // Nothing happens on resume.
@@ -202,7 +205,8 @@
   Init();
   test_delegate_->set_thaw_renderers_result(false);
 
-  power_manager_client_->SendSuspendImminent();
+  power_manager_client_->SendSuspendImminent(
+      power_manager::SuspendImminent_Reason_OTHER);
   EXPECT_EQ(kFreezeRenderers, test_delegate_->GetActions());
 
   EXPECT_DEATH(power_manager_client_->SendSuspendDone(), "Unable to thaw");
diff --git a/chrome/browser/chromeos/tether/fake_tether_service.cc b/chrome/browser/chromeos/tether/fake_tether_service.cc
index b29ac83d..d05b9ad 100644
--- a/chrome/browser/chromeos/tether/fake_tether_service.cc
+++ b/chrome/browser/chromeos/tether/fake_tether_service.cc
@@ -11,12 +11,10 @@
 FakeTetherService::FakeTetherService(
     Profile* profile,
     chromeos::PowerManagerClient* power_manager_client,
-    chromeos::SessionManagerClient* session_manager_client,
     cryptauth::CryptAuthService* cryptauth_service,
     chromeos::NetworkStateHandler* network_state_handler)
     : TetherService(profile,
                     power_manager_client,
-                    session_manager_client,
                     cryptauth_service,
                     network_state_handler) {}
 
diff --git a/chrome/browser/chromeos/tether/fake_tether_service.h b/chrome/browser/chromeos/tether/fake_tether_service.h
index 41bd56e..f1b13232 100644
--- a/chrome/browser/chromeos/tether/fake_tether_service.h
+++ b/chrome/browser/chromeos/tether/fake_tether_service.h
@@ -14,7 +14,6 @@
  public:
   FakeTetherService(Profile* profile,
                     chromeos::PowerManagerClient* power_manager_client,
-                    chromeos::SessionManagerClient* session_manager_client,
                     cryptauth::CryptAuthService* cryptauth_service,
                     chromeos::NetworkStateHandler* network_state_handler);
 
diff --git a/chrome/browser/chromeos/tether/tether_service.cc b/chrome/browser/chromeos/tether/tether_service.cc
index df43fa0..4154fe93 100644
--- a/chrome/browser/chromeos/tether/tether_service.cc
+++ b/chrome/browser/chromeos/tether/tether_service.cc
@@ -80,8 +80,6 @@
       return "[other or unknown]";
     case (TetherFeatureState::BLE_ADVERTISING_NOT_SUPPORTED):
       return "[BLE advertising not supported]";
-    case (TetherFeatureState::SCREEN_LOCKED):
-      return "[screen is locked]";
     case (TetherFeatureState::NO_AVAILABLE_HOSTS):
       return "[no potential Tether hosts]";
     case (TetherFeatureState::CELLULAR_DISABLED):
@@ -106,12 +104,10 @@
 TetherService::TetherService(
     Profile* profile,
     chromeos::PowerManagerClient* power_manager_client,
-    chromeos::SessionManagerClient* session_manager_client,
     cryptauth::CryptAuthService* cryptauth_service,
     chromeos::NetworkStateHandler* network_state_handler)
     : profile_(profile),
       power_manager_client_(power_manager_client),
-      session_manager_client_(session_manager_client),
       cryptauth_service_(cryptauth_service),
       network_state_handler_(network_state_handler),
       notification_presenter_(
@@ -122,7 +118,6 @@
       timer_(base::MakeUnique<base::OneShotTimer>()),
       weak_ptr_factory_(this) {
   power_manager_client_->AddObserver(this);
-  session_manager_client_->AddObserver(this);
   cryptauth_service_->GetCryptAuthDeviceManager()->AddObserver(this);
   network_state_handler_->AddObserver(this, FROM_HERE);
 
@@ -195,7 +190,6 @@
   // Remove all observers. This ensures that once Shutdown() is called, no more
   // calls to UpdateTetherTechnologyState() will be triggered.
   power_manager_client_->RemoveObserver(this);
-  session_manager_client_->RemoveObserver(this);
   cryptauth_service_->GetCryptAuthDeviceManager()->RemoveObserver(this);
   network_state_handler_->RemoveObserver(this, FROM_HERE);
   if (adapter_)
@@ -210,7 +204,8 @@
   notification_presenter_.reset();
 }
 
-void TetherService::SuspendImminent() {
+void TetherService::SuspendImminent(
+    power_manager::SuspendImminent::Reason reason) {
   suspended_ = true;
   UpdateTetherTechnologyState();
 }
@@ -229,14 +224,6 @@
   UpdateTetherTechnologyState();
 }
 
-void TetherService::ScreenIsLocked() {
-  UpdateTetherTechnologyState();
-}
-
-void TetherService::ScreenIsUnlocked() {
-  UpdateTetherTechnologyState();
-}
-
 void TetherService::OnSyncFinished(
     cryptauth::CryptAuthDeviceManager::SyncResult sync_result,
     cryptauth::CryptAuthDeviceManager::DeviceChangeResult
@@ -365,7 +352,6 @@
     case BLE_NOT_PRESENT:
     case BLE_ADVERTISING_NOT_SUPPORTED:
     case WIFI_NOT_PRESENT:
-    case SCREEN_LOCKED:
     case NO_AVAILABLE_HOSTS:
     case CELLULAR_DISABLED:
       return chromeos::NetworkStateHandler::TechnologyState::
@@ -489,9 +475,6 @@
   if (!GetIsBleAdvertisingSupportedPref())
     return BLE_ADVERTISING_NOT_SUPPORTED;
 
-  if (session_manager_client_->IsScreenLocked())
-    return SCREEN_LOCKED;
-
   if (!HasSyncedTetherHosts())
     return NO_AVAILABLE_HOSTS;
 
diff --git a/chrome/browser/chromeos/tether/tether_service.h b/chrome/browser/chromeos/tether/tether_service.h
index 4226042..ab6b630 100644
--- a/chrome/browser/chromeos/tether/tether_service.h
+++ b/chrome/browser/chromeos/tether/tether_service.h
@@ -13,7 +13,6 @@
 #include "base/timer/timer.h"
 #include "chromeos/components/tether/tether_component.h"
 #include "chromeos/dbus/power_manager_client.h"
-#include "chromeos/dbus/session_manager_client.h"
 #include "chromeos/network/network_state_handler.h"
 #include "chromeos/network/network_state_handler_observer.h"
 #include "components/cryptauth/cryptauth_device_manager.h"
@@ -37,7 +36,6 @@
 
 class TetherService : public KeyedService,
                       public chromeos::PowerManagerClient::Observer,
-                      public chromeos::SessionManagerClient::Observer,
                       public cryptauth::CryptAuthDeviceManager::Observer,
                       public device::BluetoothAdapter::Observer,
                       public chromeos::NetworkStateHandlerObserver,
@@ -45,7 +43,6 @@
  public:
   TetherService(Profile* profile,
                 chromeos::PowerManagerClient* power_manager_client,
-                chromeos::SessionManagerClient* session_manager_client,
                 cryptauth::CryptAuthService* cryptauth_service,
                 chromeos::NetworkStateHandler* network_state_handler);
   ~TetherService() override;
@@ -69,13 +66,9 @@
   void Shutdown() override;
 
   // chromeos::PowerManagerClient::Observer:
-  void SuspendImminent() override;
+  void SuspendImminent(power_manager::SuspendImminent::Reason reason) override;
   void SuspendDone(const base::TimeDelta& sleep_duration) override;
 
-  // chromeos::SessionManagerClient::Observer:
-  void ScreenIsLocked() override;
-  void ScreenIsUnlocked() override;
-
   // cryptauth::CryptAuthDeviceManager::Observer
   void OnSyncFinished(cryptauth::CryptAuthDeviceManager::SyncResult sync_result,
                       cryptauth::CryptAuthDeviceManager::DeviceChangeResult
@@ -120,7 +113,6 @@
       TestBleAdvertisingNotSupportedAndRecorded_BluetoothIsInitiallyNotPowered);
   FRIEND_TEST_ALL_PREFIXES(TetherServiceTest,
                            TestBleAdvertisingSupportedButIncorrectlyRecorded);
-  FRIEND_TEST_ALL_PREFIXES(TetherServiceTest, TestScreenLock);
   FRIEND_TEST_ALL_PREFIXES(TetherServiceTest, TestFeatureFlagEnabled);
   FRIEND_TEST_ALL_PREFIXES(TetherServiceTest, TestNoTetherHosts);
   FRIEND_TEST_ALL_PREFIXES(TetherServiceTest, TestProhibitedByPolicy);
@@ -140,6 +132,7 @@
   enum TetherFeatureState {
     OTHER_OR_UNKNOWN = 0,
     BLE_ADVERTISING_NOT_SUPPORTED = 1,
+    // Note: SCREEN_LOCKED is an obsolete value, and should not be used.
     SCREEN_LOCKED = 2,
     NO_AVAILABLE_HOSTS = 3,
     CELLULAR_DISABLED = 4,
@@ -222,7 +215,6 @@
 
   Profile* profile_;
   chromeos::PowerManagerClient* power_manager_client_;
-  chromeos::SessionManagerClient* session_manager_client_;
   cryptauth::CryptAuthService* cryptauth_service_;
   chromeos::NetworkStateHandler* network_state_handler_;
   std::unique_ptr<chromeos::tether::NotificationPresenter>
diff --git a/chrome/browser/chromeos/tether/tether_service_factory.cc b/chrome/browser/chromeos/tether/tether_service_factory.cc
index 400aa6a..f23540ae 100644
--- a/chrome/browser/chromeos/tether/tether_service_factory.cc
+++ b/chrome/browser/chromeos/tether/tether_service_factory.cc
@@ -49,7 +49,6 @@
     FakeTetherService* fake_tether_service = new FakeTetherService(
         Profile::FromBrowserContext(context),
         chromeos::DBusThreadManager::Get()->GetPowerManagerClient(),
-        chromeos::DBusThreadManager::Get()->GetSessionManagerClient(),
         ChromeCryptAuthServiceFactory::GetForBrowserContext(
             Profile::FromBrowserContext(context)),
         chromeos::NetworkHandler::Get()->network_state_handler());
@@ -66,7 +65,6 @@
   return new TetherService(
       Profile::FromBrowserContext(context),
       chromeos::DBusThreadManager::Get()->GetPowerManagerClient(),
-      chromeos::DBusThreadManager::Get()->GetSessionManagerClient(),
       ChromeCryptAuthServiceFactory::GetForBrowserContext(
           Profile::FromBrowserContext(context)),
       chromeos::NetworkHandler::Get()->network_state_handler());
diff --git a/chrome/browser/chromeos/tether/tether_service_unittest.cc b/chrome/browser/chromeos/tether/tether_service_unittest.cc
index 9529c2e..40db980 100644
--- a/chrome/browser/chromeos/tether/tether_service_unittest.cc
+++ b/chrome/browser/chromeos/tether/tether_service_unittest.cc
@@ -25,10 +25,9 @@
 #include "chromeos/components/tether/tether_component_impl.h"
 #include "chromeos/dbus/dbus_thread_manager.h"
 #include "chromeos/dbus/fake_power_manager_client.h"
-#include "chromeos/dbus/fake_session_manager_client.h"
 #include "chromeos/dbus/fake_shill_manager_client.h"
+#include "chromeos/dbus/power_manager/suspend.pb.h"
 #include "chromeos/dbus/power_manager_client.h"
-#include "chromeos/dbus/session_manager_client.h"
 #include "chromeos/dbus/shill_device_client.h"
 #include "chromeos/network/network_connect.h"
 #include "chromeos/network/network_handler.h"
@@ -53,19 +52,6 @@
 
 namespace {
 
-class ExtendedFakeSessionManagerClient
-    : public chromeos::FakeSessionManagerClient {
- public:
-  bool IsScreenLocked() const override { return is_screen_locked_; }
-
-  void set_is_screen_locked(bool is_screen_locked) {
-    is_screen_locked_ = is_screen_locked;
-  }
-
- private:
-  bool is_screen_locked_ = false;
-};
-
 class MockCryptAuthDeviceManager : public cryptauth::CryptAuthDeviceManager {
  public:
   ~MockCryptAuthDeviceManager() override {}
@@ -104,12 +90,10 @@
  public:
   TestTetherService(Profile* profile,
                     chromeos::PowerManagerClient* power_manager_client,
-                    chromeos::SessionManagerClient* session_manager_client,
                     cryptauth::CryptAuthService* cryptauth_service,
                     chromeos::NetworkStateHandler* network_state_handler)
       : TetherService(profile,
                       power_manager_client,
-                      session_manager_client,
                       cryptauth_service,
                       network_state_handler) {}
   ~TestTetherService() override {}
@@ -198,8 +182,6 @@
 
     fake_power_manager_client_ =
         base::MakeUnique<chromeos::FakePowerManagerClient>();
-    fake_session_manager_client_ =
-        base::MakeUnique<ExtendedFakeSessionManagerClient>();
 
     std::vector<cryptauth::ExternalDeviceInfo> test_device_infos;
     test_device_infos.push_back(cryptauth::ExternalDeviceInfo());
@@ -244,8 +226,7 @@
   void CreateTetherService() {
     tether_service_ = base::WrapUnique(new TestTetherService(
         profile_.get(), fake_power_manager_client_.get(),
-        fake_session_manager_client_.get(), fake_cryptauth_service_.get(),
-        network_state_handler()));
+        fake_cryptauth_service_.get(), network_state_handler()));
 
     fake_notification_presenter_ =
         new chromeos::tether::FakeNotificationPresenter();
@@ -272,14 +253,6 @@
       tether_service_->Shutdown();
   }
 
-  void SetIsScreenLocked(bool is_screen_locked) {
-    fake_session_manager_client_->set_is_screen_locked(is_screen_locked);
-    if (is_screen_locked)
-      tether_service_->ScreenIsLocked();
-    else
-      tether_service_->ScreenIsUnlocked();
-  }
-
   void SetTetherTechnologyStateEnabled(bool enabled) {
     network_state_handler()->SetTetherTechnologyState(
         enabled
@@ -340,8 +313,6 @@
 
   std::unique_ptr<TestingProfile> profile_;
   std::unique_ptr<chromeos::FakePowerManagerClient> fake_power_manager_client_;
-  std::unique_ptr<ExtendedFakeSessionManagerClient>
-      fake_session_manager_client_;
   std::unique_ptr<TestingPrefServiceSimple> test_pref_service_;
   std::unique_ptr<NiceMock<MockCryptAuthDeviceManager>>
       mock_cryptauth_device_manager_;
@@ -417,7 +388,8 @@
   CreateTetherService();
   VerifyTetherActiveStatus(true /* expected_active */);
 
-  fake_power_manager_client_->SendSuspendImminent();
+  fake_power_manager_client_->SendSuspendImminent(
+      power_manager::SuspendImminent_Reason_OTHER);
 
   EXPECT_EQ(
       chromeos::NetworkStateHandler::TechnologyState::TECHNOLOGY_UNAVAILABLE,
@@ -432,7 +404,8 @@
                 chromeos::NetworkTypePattern::Tether()));
   VerifyTetherActiveStatus(true /* expected_active */);
 
-  fake_power_manager_client_->SendSuspendImminent();
+  fake_power_manager_client_->SendSuspendImminent(
+      power_manager::SuspendImminent_Reason_OTHER);
 
   VerifyTetherFeatureStateRecorded(
       TetherService::TetherFeatureState::OTHER_OR_UNKNOWN,
@@ -541,31 +514,6 @@
                                    1 /* expected_count */);
 }
 
-TEST_F(TetherServiceTest, TestScreenLock) {
-  CreateTetherService();
-  VerifyTetherActiveStatus(true /* expected_active */);
-
-  SetIsScreenLocked(true);
-
-  EXPECT_EQ(
-      chromeos::NetworkStateHandler::TechnologyState::TECHNOLOGY_UNAVAILABLE,
-      network_state_handler()->GetTechnologyState(
-          chromeos::NetworkTypePattern::Tether()));
-  VerifyTetherActiveStatus(false /* expected_active */);
-
-  SetIsScreenLocked(false);
-
-  EXPECT_EQ(chromeos::NetworkStateHandler::TechnologyState::TECHNOLOGY_ENABLED,
-            network_state_handler()->GetTechnologyState(
-                chromeos::NetworkTypePattern::Tether()));
-  VerifyTetherActiveStatus(true /* expected_active */);
-
-  SetIsScreenLocked(true);
-
-  VerifyTetherFeatureStateRecorded(
-      TetherService::TetherFeatureState::SCREEN_LOCKED, 2 /* expected_count */);
-}
-
 TEST_F(TetherServiceTest, TestFeatureFlagDisabled) {
   base::test::ScopedFeatureList feature_list;
   feature_list.InitAndDisableFeature(features::kInstantTethering);
diff --git a/chrome/browser/data_use_measurement/chrome_data_use_ascriber.cc b/chrome/browser/data_use_measurement/chrome_data_use_ascriber.cc
index 4794e39..587c3082 100644
--- a/chrome/browser/data_use_measurement/chrome_data_use_ascriber.cc
+++ b/chrome/browser/data_use_measurement/chrome_data_use_ascriber.cc
@@ -25,20 +25,6 @@
 
 namespace data_use_measurement {
 
-namespace {
-
-bool IsDisabledPlatform() {
-#if defined(OS_MACOSX)
-  // TODO(rajendrant): Fix mac os specific race conditions and enable.
-  // crbug.com/753559
-  return true;
-#else
-  return false;
-#endif
-}
-
-}  // namespace
-
 // static
 const void* const ChromeDataUseAscriber::DataUseRecorderEntryAsUserData::
     kDataUseAscriberUserDataKey =
@@ -193,9 +179,6 @@
     bool started) {
   DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
 
-  if (IsDisabledPlatform())
-    return;
-
   ChromeDataUseRecorder* recorder = GetDataUseRecorder(request);
 
   if (!recorder)
@@ -221,9 +204,6 @@
 void ChromeDataUseAscriber::OnUrlRequestDestroyed(net::URLRequest* request) {
   DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
 
-  if (IsDisabledPlatform())
-    return;
-
   const DataUseRecorderEntry entry = GetDataUseRecorderEntry(request);
 
   if (entry == data_use_recorders_.end())
@@ -270,8 +250,6 @@
                                                int main_render_process_id,
                                                int main_render_frame_id) {
   DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
-  if (IsDisabledPlatform())
-    return;
 
   const auto render_frame =
       RenderFrameHostID(render_process_id, render_frame_id);
@@ -301,8 +279,6 @@
                                                int main_render_process_id,
                                                int main_render_frame_id) {
   DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
-  if (IsDisabledPlatform())
-    return;
 
   RenderFrameHostID key(render_process_id, render_frame_id);
 
@@ -334,8 +310,6 @@
     int render_process_id,
     int render_frame_id) {
   DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
-  if (IsDisabledPlatform())
-    return;
 
   main_render_frame_entry_map_
       .find(RenderFrameHostID(render_process_id, render_frame_id))
@@ -351,9 +325,6 @@
     base::TimeTicks time) {
   DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
 
-  if (IsDisabledPlatform())
-    return;
-
   RenderFrameHostID main_frame(render_process_id, render_frame_id);
 
   auto main_frame_it = main_render_frame_entry_map_.find(main_frame);
@@ -508,9 +479,6 @@
                                              bool visible) {
   DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
 
-  if (IsDisabledPlatform())
-    return;
-
   auto main_frame_it = main_render_frame_entry_map_.find(
       RenderFrameHostID(main_render_process_id, main_render_frame_id));
   if (main_frame_it != main_render_frame_entry_map_.end()) {
@@ -526,9 +494,6 @@
                                                    int new_render_frame_id) {
   DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
 
-  if (IsDisabledPlatform())
-    return;
-
   auto old_frame_iter = main_render_frame_entry_map_.find(
       RenderFrameHostID(old_render_process_id, old_render_frame_id));
 
diff --git a/chrome/browser/data_use_measurement/chrome_data_use_ascriber_unittest.cc b/chrome/browser/data_use_measurement/chrome_data_use_ascriber_unittest.cc
index 97fea41..3980255 100644
--- a/chrome/browser/data_use_measurement/chrome_data_use_ascriber_unittest.cc
+++ b/chrome/browser/data_use_measurement/chrome_data_use_ascriber_unittest.cc
@@ -22,8 +22,6 @@
 #include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
-#ifndef OS_MACOSX
-
 namespace {
 
 int kRenderProcessId = 1;
@@ -476,5 +474,3 @@
 }
 
 }  // namespace data_use_measurement
-
-#endif  // OS_MACOSX
diff --git a/chrome/browser/download/download_danger_prompt_browsertest.cc b/chrome/browser/download/download_danger_prompt_browsertest.cc
index e78c4e7..7758a53 100644
--- a/chrome/browser/download/download_danger_prompt_browsertest.cc
+++ b/chrome/browser/download/download_danger_prompt_browsertest.cc
@@ -17,6 +17,7 @@
 #include "chrome/browser/ui/browser_commands.h"
 #include "chrome/browser/ui/browser_tabstrip.h"
 #include "chrome/browser/ui/tabs/tab_strip_model.h"
+#include "chrome/browser/ui/test/test_browser_dialog.h"
 #include "chrome/test/base/in_process_browser_test.h"
 #include "chrome/test/base/ui_test_utils.h"
 #include "components/safe_browsing/db/database_manager.h"
@@ -342,4 +343,86 @@
                                           SecondaryUiMd::DISABLED),
                         &SecondaryUiMdStatusToString);
 
+// Class for testing interactive dialogs.
+class DownloadDangerPromptBrowserTest : public DialogBrowserTest {
+ protected:
+  enum InvocationType { USER_INITIATED, FROM_DOWNLOAD_API };
+  DownloadDangerPromptBrowserTest() : download_url_(kTestDownloadUrl) {}
+
+  void RunTest(content::DownloadDangerType danger_type,
+               InvocationType invocation_type) {
+    danger_type_ = danger_type;
+    invocation_type_ = invocation_type;
+
+    RunDialog();
+  }
+
+ private:
+  void ShowDialog(const std::string& name) override {
+    ON_CALL(download_, GetURL()).WillByDefault(ReturnRef(download_url_));
+    ON_CALL(download_, GetReferrerUrl())
+        .WillByDefault(ReturnRef(GURL::EmptyGURL()));
+    ON_CALL(download_, GetBrowserContext())
+        .WillByDefault(Return(browser()->profile()));
+    ON_CALL(download_, GetTargetFilePath())
+        .WillByDefault(ReturnRef(empty_file_path_));
+    ON_CALL(download_, IsDangerous()).WillByDefault(Return(true));
+    ON_CALL(download_, GetFileNameToReportUser())
+        .WillByDefault(Return(base::FilePath(FILE_PATH_LITERAL("evil.exe"))));
+
+    // Set up test-specific parameters
+    ON_CALL(download_, GetDangerType()).WillByDefault(Return(danger_type_));
+
+    DownloadDangerPrompt::Create(
+        &download_, browser()->tab_strip_model()->GetActiveWebContents(),
+        invocation_type_ == FROM_DOWNLOAD_API, DownloadDangerPrompt::OnDone());
+  }
+
+  const GURL download_url_;
+  const base::FilePath empty_file_path_;
+
+  content::DownloadDangerType danger_type_;
+  InvocationType invocation_type_;
+  content::MockDownloadItem download_;
+
+  DISALLOW_COPY_AND_ASSIGN(DownloadDangerPromptBrowserTest);
+};
+
+IN_PROC_BROWSER_TEST_F(DownloadDangerPromptBrowserTest,
+                       InvokeDialog_DangerousFile) {
+  RunTest(content::DOWNLOAD_DANGER_TYPE_DANGEROUS_FILE, USER_INITIATED);
+}
+IN_PROC_BROWSER_TEST_F(DownloadDangerPromptBrowserTest,
+                       InvokeDialog_DangerousFileFromApi) {
+  RunTest(content::DOWNLOAD_DANGER_TYPE_DANGEROUS_FILE, FROM_DOWNLOAD_API);
+}
+
+IN_PROC_BROWSER_TEST_F(DownloadDangerPromptBrowserTest,
+                       InvokeDialog_DangerousUrl) {
+  RunTest(content::DOWNLOAD_DANGER_TYPE_DANGEROUS_URL, USER_INITIATED);
+}
+IN_PROC_BROWSER_TEST_F(DownloadDangerPromptBrowserTest,
+                       InvokeDialog_DangerousUrlFromApi) {
+  RunTest(content::DOWNLOAD_DANGER_TYPE_DANGEROUS_URL, FROM_DOWNLOAD_API);
+}
+
+IN_PROC_BROWSER_TEST_F(DownloadDangerPromptBrowserTest,
+                       InvokeDialog_UncommonContent) {
+  RunTest(content::DOWNLOAD_DANGER_TYPE_UNCOMMON_CONTENT, USER_INITIATED);
+}
+IN_PROC_BROWSER_TEST_F(DownloadDangerPromptBrowserTest,
+                       InvokeDialog_UncommonContentFromApi) {
+  RunTest(content::DOWNLOAD_DANGER_TYPE_UNCOMMON_CONTENT, FROM_DOWNLOAD_API);
+}
+
+IN_PROC_BROWSER_TEST_F(DownloadDangerPromptBrowserTest,
+                       InvokeDialog_PotentiallyUnwanted) {
+  RunTest(content::DOWNLOAD_DANGER_TYPE_POTENTIALLY_UNWANTED, USER_INITIATED);
+}
+IN_PROC_BROWSER_TEST_F(DownloadDangerPromptBrowserTest,
+                       InvokeDialog_PotentiallyUnwantedFromApi) {
+  RunTest(content::DOWNLOAD_DANGER_TYPE_POTENTIALLY_UNWANTED,
+          FROM_DOWNLOAD_API);
+}
+
 }  // namespace safe_browsing
diff --git a/chrome/browser/download/save_page_browsertest.cc b/chrome/browser/download/save_page_browsertest.cc
index 387a250..3d33ae71 100644
--- a/chrome/browser/download/save_page_browsertest.cc
+++ b/chrome/browser/download/save_page_browsertest.cc
@@ -30,7 +30,6 @@
 #include "chrome/browser/download/download_history.h"
 #include "chrome/browser/download/download_prefs.h"
 #include "chrome/browser/download/save_package_file_picker.h"
-#include "chrome/browser/net/url_request_mock_util.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/ui/browser.h"
 #include "chrome/browser/ui/browser_commands.h"
@@ -61,7 +60,6 @@
 #include "net/base/filename_util.h"
 #include "net/dns/mock_host_resolver.h"
 #include "net/test/embedded_test_server/embedded_test_server.h"
-#include "net/test/url_request/url_request_mock_http_job.h"
 #include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
@@ -72,7 +70,6 @@
 using content::RenderFrameHost;
 using content::RenderProcessHost;
 using content::WebContents;
-using net::URLRequestMockHTTPJob;
 using testing::ContainsRegex;
 using testing::HasSubstr;
 
@@ -90,6 +87,15 @@
   return base::CollapseWhitespaceASCII(file_contents, false);
 }
 
+// Takes a string with "url=(%04d)%s", and replaces that with the length and
+// contents of the path the response was saved from, |url|, to match output by
+// the SavePageAs logic.
+std::string WriteSavedFromPath(const std::string& file_contents,
+                               const GURL& url) {
+  return base::StringPrintf(file_contents.c_str(), url.spec().length(),
+                            url.spec().c_str());
+}
+
 // Waits for an item record in the downloads database to match |filter|. See
 // DownloadStoredProperly() below for an example filter.
 class DownloadPersistedObserver : public DownloadHistory::Observer {
@@ -280,6 +286,10 @@
 
  protected:
   void SetUp() override {
+    ASSERT_TRUE(embedded_test_server()->InitializeAndListen());
+    content::SetupCrossSiteRedirector(embedded_test_server());
+    embedded_test_server()->StartAcceptingConnections();
+
     ASSERT_TRUE(PathService::Get(chrome::DIR_TEST_DATA, &test_dir_));
     ASSERT_TRUE(save_dir_.CreateUniqueTempDir());
     InProcessBrowserTest::SetUp();
@@ -290,14 +300,10 @@
         prefs::kDownloadDefaultDirectory, save_dir_.GetPath());
     browser()->profile()->GetPrefs()->SetFilePath(
         prefs::kSaveFileDefaultDirectory, save_dir_.GetPath());
-    BrowserThread::PostTask(
-        BrowserThread::IO, FROM_HERE,
-        base::BindOnce(&chrome_browser_net::SetUrlRequestMocksEnabled, true));
   }
 
   GURL NavigateToMockURL(const std::string& prefix) {
-    GURL url = URLRequestMockHTTPJob::GetMockUrl(
-        "save_page/" + prefix + ".htm");
+    GURL url = embedded_test_server()->GetURL("/save_page/" + prefix + ".htm");
     ui_test_utils::NavigateToURL(browser(), url);
     return url;
   }
@@ -505,11 +511,10 @@
 }
 
 IN_PROC_BROWSER_TEST_F(SavePageBrowserTest, SaveViewSourceHTMLOnly) {
-  GURL mock_url = URLRequestMockHTTPJob::GetMockUrl("save_page/a.htm");
+  GURL mock_url = embedded_test_server()->GetURL("/save_page/a.htm");
   GURL view_source_url =
       GURL(content::kViewSourceScheme + std::string(":") + mock_url.spec());
-  GURL actual_page_url = URLRequestMockHTTPJob::GetMockUrl(
-      "save_page/a.htm");
+  GURL actual_page_url = embedded_test_server()->GetURL("/save_page/a.htm");
   ui_test_utils::NavigateToURL(browser(), view_source_url);
 
   base::FilePath full_file_name, dir;
@@ -535,8 +540,10 @@
   EXPECT_TRUE(base::PathExists(full_file_name));
   EXPECT_TRUE(base::PathExists(dir));
 
-  EXPECT_EQ(ReadFileAndCollapseWhitespace(full_file_name),
-            ReadFileAndCollapseWhitespace(GetTestDirFile("b.saved1.htm")));
+  EXPECT_EQ(
+      ReadFileAndCollapseWhitespace(full_file_name),
+      WriteSavedFromPath(
+          ReadFileAndCollapseWhitespace(GetTestDirFile("b.saved1.htm")), url));
   EXPECT_TRUE(
       base::ContentsEqual(GetTestDirFile("1.png"), dir.AppendASCII("1.png")));
   EXPECT_EQ(ReadFileAndCollapseWhitespace(dir.AppendASCII("1.css")),
@@ -554,7 +561,7 @@
       BrowserContext::GetDownloadManager(incognito->profile()));
 
   // Navigate, unblocking with new tab.
-  GURL url = URLRequestMockHTTPJob::GetMockUrl("save_page/b.htm");
+  GURL url = embedded_test_server()->GetURL("/save_page/b.htm");
   NavigateToURLWithDisposition(incognito, url,
                                WindowOpenDisposition::NEW_FOREGROUND_TAB,
                                ui_test_utils::BROWSER_TEST_WAIT_FOR_TAB);
@@ -611,8 +618,10 @@
   EXPECT_TRUE(base::PathExists(full_file_name));
   EXPECT_TRUE(base::PathExists(dir));
 
-  EXPECT_EQ(ReadFileAndCollapseWhitespace(full_file_name),
-            ReadFileAndCollapseWhitespace(GetTestDirFile("b.saved2.htm")));
+  EXPECT_EQ(
+      ReadFileAndCollapseWhitespace(full_file_name),
+      WriteSavedFromPath(
+          ReadFileAndCollapseWhitespace(GetTestDirFile("b.saved2.htm")), url));
   EXPECT_TRUE(
       base::ContentsEqual(GetTestDirFile("1.png"), dir.AppendASCII("1.png")));
   EXPECT_EQ(ReadFileAndCollapseWhitespace(dir.AppendASCII("1.css")),
@@ -656,7 +665,7 @@
 
   base::ScopedAllowBlockingForTesting allow_blocking;
   EXPECT_FALSE(base::PathExists(full_file_name));
-  GURL url = URLRequestMockHTTPJob::GetMockUrl("save_page/c.htm");
+  GURL url = embedded_test_server()->GetURL("/save_page/c.htm");
   ui_test_utils::NavigateToURL(browser(), url);
 
   SavePackageFilePicker::SetShouldPromptUser(false);
@@ -749,7 +758,7 @@
 // extension appended so that they won't be accidentally executed by the user.
 IN_PROC_BROWSER_TEST_F(SavePageBrowserTest, DangerousSubresources) {
   GURL url =
-      URLRequestMockHTTPJob::GetMockUrl("/save_page/dubious-subresources.html");
+      embedded_test_server()->GetURL("/save_page/dubious-subresources.html");
 
   ui_test_utils::NavigateToURL(browser(), url);
   base::FilePath full_file_name, dir;
@@ -765,13 +774,14 @@
 // Test that we don't crash when the page contains an iframe that
 // was handled as a download (http://crbug.com/42212).
 IN_PROC_BROWSER_TEST_F(SavePageBrowserTest, SaveDownloadableIFrame) {
-  GURL url = URLRequestMockHTTPJob::GetMockUrl(
-      "downloads/iframe-src-is-a-download.htm");
+  GURL url =
+      embedded_test_server()->GetURL("/downloads/iframe-src-is-a-download.htm");
 
   // Wait for and then dismiss the non-save-page-as-related download item
   // (the one associated with downloading of "thisdayinhistory.xls" file).
   {
-    GURL download_url("http://mock.http/downloads/thisdayinhistory.xls");
+    GURL download_url =
+        embedded_test_server()->GetURL("/downloads/thisdayinhistory.xls");
     DownloadPersistedObserver persisted(
         browser()->profile(),
         base::Bind(&DownloadStoredProperly, download_url, base::FilePath(), -1,
@@ -855,9 +865,6 @@
     // resolving to 127.0.0.1
     host_resolver()->AddRule("no.such.host", "128.0.0.1");
     host_resolver()->AddRule("*", "127.0.0.1");
-    ASSERT_TRUE(embedded_test_server()->InitializeAndListen());
-    content::SetupCrossSiteRedirector(embedded_test_server());
-    embedded_test_server()->StartAcceptingConnections();
   }
 
  private:
diff --git a/chrome/browser/extensions/api/feedback_private/feedback_browsertest.cc b/chrome/browser/extensions/api/feedback_private/feedback_browsertest.cc
index 2e5263c..ab1b5fb 100644
--- a/chrome/browser/extensions/api/feedback_private/feedback_browsertest.cc
+++ b/chrome/browser/extensions/api/feedback_private/feedback_browsertest.cc
@@ -85,14 +85,7 @@
   }
 };
 
-// Disabled for ASan due to flakiness on Mac ASan 64 Tests (1).
-// See crbug.com/757243.
-#if defined(ADDRESS_SANITIZER)
-#define MAYBE_ShowFeedback DISABLED_ShowFeedback
-#else
-#define MAYBE_ShowFeedback ShowFeedback
-#endif
-IN_PROC_BROWSER_TEST_F(FeedbackTest, MAYBE_ShowFeedback) {
+IN_PROC_BROWSER_TEST_F(FeedbackTest, ShowFeedback) {
   WaitForExtensionViewsToLoad();
 
   ASSERT_TRUE(IsFeedbackAppAvailable());
@@ -100,14 +93,7 @@
   VerifyFeedbackAppLaunch();
 }
 
-// Disabled for ASan due to flakiness on Mac ASan 64 Tests (1).
-// See crbug.com/757243.
-#if defined(ADDRESS_SANITIZER)
-#define MAYBE_ShowLoginFeedback DISABLED_ShowLoginFeedback
-#else
-#define MAYBE_ShowLoginFeedback ShowLoginFeedback
-#endif
-IN_PROC_BROWSER_TEST_F(FeedbackTest, MAYBE_ShowLoginFeedback) {
+IN_PROC_BROWSER_TEST_F(FeedbackTest, ShowLoginFeedback) {
   WaitForExtensionViewsToLoad();
 
   ASSERT_TRUE(IsFeedbackAppAvailable());
@@ -131,14 +117,7 @@
 
 // Tests that there's an option in the email drop down box with a value
 // 'anonymous_user'.
-// Disabled for ASan due to flakiness on Mac ASan 64 Tests (1).
-// See crbug.com/757243.
-#if defined(ADDRESS_SANITIZER)
-#define MAYBE_AnonymousUser DISABLED_AnonymousUser
-#else
-#define MAYBE_AnonymousUser AnonymousUser
-#endif
-IN_PROC_BROWSER_TEST_F(FeedbackTest, MAYBE_AnonymousUser) {
+IN_PROC_BROWSER_TEST_F(FeedbackTest, AnonymousUser) {
   WaitForExtensionViewsToLoad();
 
   ASSERT_TRUE(IsFeedbackAppAvailable());
diff --git a/chrome/browser/extensions/api/language_settings_private/language_settings_private_api.cc b/chrome/browser/extensions/api/language_settings_private/language_settings_private_api.cc
index 67b3a21..9dfd1f52 100644
--- a/chrome/browser/extensions/api/language_settings_private/language_settings_private_api.cc
+++ b/chrome/browser/extensions/api/language_settings_private/language_settings_private_api.cc
@@ -485,7 +485,7 @@
 LanguageSettingsPrivateGetTranslateTargetLanguageFunction::Run() {
   Profile* profile = chrome_details_.GetProfile();
   language::LanguageModel* language_model =
-      LanguageModelFactory::GetInstance()->GetForBrowserContext(profile);
+      LanguageModelFactory::GetForBrowserContext(profile);
   return RespondNow(OneArgument(
       base::MakeUnique<base::Value>(TranslateService::GetTargetLanguage(
           profile->GetPrefs(), language_model))));
diff --git a/chrome/browser/extensions/api/passwords_private/passwords_private_delegate_impl.cc b/chrome/browser/extensions/api/passwords_private/passwords_private_delegate_impl.cc
index ae2f63a9..e787a2f 100644
--- a/chrome/browser/extensions/api/passwords_private/passwords_private_delegate_impl.cc
+++ b/chrome/browser/extensions/api/passwords_private/passwords_private_delegate_impl.cc
@@ -25,11 +25,23 @@
 #include "content/public/browser/web_contents.h"
 #include "ui/base/l10n/l10n_util.h"
 
+#if defined(OS_WIN)
+#include "chrome/browser/password_manager/password_manager_util_win.h"
+#elif defined(OS_MACOSX)
+#include "chrome/browser/password_manager/password_manager_util_mac.h"
+#endif
+
 namespace extensions {
 
 PasswordsPrivateDelegateImpl::PasswordsPrivateDelegateImpl(Profile* profile)
     : profile_(profile),
-      password_manager_presenter_(new PasswordManagerPresenter(this)),
+      password_manager_presenter_(
+          std::make_unique<PasswordManagerPresenter>(this)),
+      password_manager_porter_(std::make_unique<PasswordManagerPorter>(
+          password_manager_presenter_.get())),
+      password_access_authenticator_(
+          base::BindRepeating(&PasswordsPrivateDelegateImpl::OsReauthCall,
+                              base::Unretained(this))),
       current_entries_initialized_(false),
       current_exceptions_initialized_(false),
       is_initialized_(false),
@@ -120,11 +132,24 @@
   // TODO(stevenjb): Pass this directly to RequestShowPassword(); see
   // crbug.com/495290.
   web_contents_ = web_contents;
+  if (!password_access_authenticator_.EnsureUserIsAuthenticated()) {
+    return;
+  }
 
   // Request the password. When it is retrieved, ShowPassword() will be called.
   password_manager_presenter_->RequestShowPassword(index);
 }
 
+bool PasswordsPrivateDelegateImpl::OsReauthCall() {
+#if defined(OS_WIN)
+  return password_manager_util_win::AuthenticateUser(GetNativeWindow());
+#elif defined(OS_MACOSX)
+  return password_manager_util_mac::AuthenticateUser();
+#else
+  return true;
+#endif
+}
+
 Profile* PasswordsPrivateDelegateImpl::GetProfile() {
   return profile_;
 }
@@ -210,12 +235,23 @@
 
 void PasswordsPrivateDelegateImpl::ImportPasswords(
     content::WebContents* web_contents) {
-  password_manager_presenter_->ImportPasswords(web_contents);
+  password_manager_porter_->set_web_contents(web_contents);
+  password_manager_porter_->Load();
 }
 
 void PasswordsPrivateDelegateImpl::ExportPasswords(
     content::WebContents* web_contents) {
-  password_manager_presenter_->ExportPasswords(web_contents);
+  // Save |web_contents| so that it can be used later when GetNativeWindow() is
+  // called. Note: This is safe because the |web_contents| is used before
+  // exiting this method. TODO(crbug.com/495290): Pass the native window
+  // directly to the reauth-handling code.
+  web_contents_ = web_contents;
+  if (!password_access_authenticator_.EnsureUserIsAuthenticated()) {
+    return;
+  }
+
+  password_manager_porter_->set_web_contents(web_contents);
+  password_manager_porter_->Store();
 }
 
 #if !defined(OS_ANDROID)
@@ -227,6 +263,13 @@
 
 void PasswordsPrivateDelegateImpl::Shutdown() {
   password_manager_presenter_.reset();
+  password_manager_porter_.reset();
+}
+
+void PasswordsPrivateDelegateImpl::SetOsReauthCallForTesting(
+    base::RepeatingCallback<bool()> os_reauth_call) {
+  password_access_authenticator_.SetOsReauthCallForTesting(
+      std::move(os_reauth_call));
 }
 
 void PasswordsPrivateDelegateImpl::ExecuteFunction(
diff --git a/chrome/browser/extensions/api/passwords_private/passwords_private_delegate_impl.h b/chrome/browser/extensions/api/passwords_private/passwords_private_delegate_impl.h
index db3af4d..a7c7e4a 100644
--- a/chrome/browser/extensions/api/passwords_private/passwords_private_delegate_impl.h
+++ b/chrome/browser/extensions/api/passwords_private/passwords_private_delegate_impl.h
@@ -16,6 +16,8 @@
 #include "base/observer_list.h"
 #include "build/build_config.h"
 #include "chrome/browser/extensions/api/passwords_private/passwords_private_delegate.h"
+#include "chrome/browser/ui/passwords/password_access_authenticator.h"
+#include "chrome/browser/ui/passwords/password_manager_porter.h"
 #include "chrome/browser/ui/passwords/password_manager_presenter.h"
 #include "chrome/browser/ui/passwords/password_ui_view.h"
 #include "chrome/common/extensions/api/passwords_private.h"
@@ -69,6 +71,10 @@
   // KeyedService overrides:
   void Shutdown() override;
 
+  // Use this in tests to mock the OS-level reauthentication.
+  void SetOsReauthCallForTesting(
+      base::RepeatingCallback<bool()> os_reauth_call);
+
  private:
   // Called after the lists are fetched. Once both lists have been set, the
   // class is considered initialized and any queued functions (which could
@@ -85,12 +91,21 @@
   void RequestShowPasswordInternal(size_t index,
                                    content::WebContents* web_contents);
 
+  // Triggers an OS-dependent UI to present OS account login challenge and
+  // returns true if the user passed that challenge.
+  bool OsReauthCall();
+
   // Not owned by this class.
   Profile* profile_;
 
   // Used to communicate with the password store.
   std::unique_ptr<PasswordManagerPresenter> password_manager_presenter_;
 
+  // Used to control the export and import flows.
+  std::unique_ptr<PasswordManagerPorter> password_manager_porter_;
+
+  PasswordAccessAuthenticator password_access_authenticator_;
+
   // The current list of entries/exceptions. Cached here so that when new
   // observers are added, this delegate can send the current lists without
   // having to request them from |password_manager_presenter_| again.
diff --git a/chrome/browser/extensions/api/passwords_private/passwords_private_delegate_impl_unittest.cc b/chrome/browser/extensions/api/passwords_private/passwords_private_delegate_impl_unittest.cc
index c8dba57..257c90b 100644
--- a/chrome/browser/extensions/api/passwords_private/passwords_private_delegate_impl_unittest.cc
+++ b/chrome/browser/extensions/api/passwords_private/passwords_private_delegate_impl_unittest.cc
@@ -4,18 +4,35 @@
 
 #include <stddef.h>
 
+#include <memory>
+#include <utility>
+#include <vector>
+
 #include "base/bind.h"
 #include "base/bind_helpers.h"
 #include "base/macros.h"
 #include "base/memory/ptr_util.h"
+#include "base/run_loop.h"
+#include "base/strings/utf_string_conversions.h"
+#include "base/values.h"
 #include "chrome/browser/extensions/api/passwords_private/passwords_private_delegate_impl.h"
+#include "chrome/browser/extensions/api/passwords_private/passwords_private_event_router.h"
+#include "chrome/browser/extensions/api/passwords_private/passwords_private_event_router_factory.h"
+#include "chrome/browser/password_manager/password_store_factory.h"
 #include "chrome/test/base/testing_profile.h"
 #include "components/autofill/core/common/password_form.h"
+#include "components/password_manager/core/browser/password_manager_test_utils.h"
+#include "components/password_manager/core/browser/test_password_store.h"
 #include "content/public/test/test_browser_thread_bundle.h"
+#include "extensions/browser/test_event_router.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
+using PasswordFormList = std::vector<std::unique_ptr<autofill::PasswordForm>>;
+
 namespace extensions {
 
+namespace {
+
 template <typename T>
 class CallbackTracker {
  public:
@@ -41,14 +58,124 @@
   DISALLOW_COPY_AND_ASSIGN(CallbackTracker);
 };
 
-using PasswordFormList = std::vector<std::unique_ptr<autofill::PasswordForm>>;
+class PasswordEventObserver
+    : public extensions::TestEventRouter::EventObserver {
+ public:
+  // The observer will only listen to events with the |event_name|.
+  explicit PasswordEventObserver(const std::string& event_name);
 
-TEST(PasswordsPrivateDelegateImplTest, GetSavedPasswordsList) {
+  ~PasswordEventObserver() override;
+
+  // Removes |event_args_| from |*this| and returns them.
+  base::Value PassEventArgs();
+
+  // extensions::TestEventRouter::EventObserver:
+  void OnBroadcastEvent(const extensions::Event& event) override;
+
+ private:
+  // The name of the observed event.
+  const std::string event_name_;
+
+  // The arguments passed for the last observed event.
+  base::Value event_args_;
+
+  DISALLOW_COPY_AND_ASSIGN(PasswordEventObserver);
+};
+
+PasswordEventObserver::PasswordEventObserver(const std::string& event_name)
+    : event_name_(event_name) {}
+
+PasswordEventObserver::~PasswordEventObserver() = default;
+
+base::Value PasswordEventObserver::PassEventArgs() {
+  return std::move(event_args_);
+}
+
+void PasswordEventObserver::OnBroadcastEvent(const extensions::Event& event) {
+  if (event.event_name != event_name_) {
+    return;
+  }
+  event_args_ = event.event_args->Clone();
+}
+
+enum class ReauthResult { PASS, FAIL };
+
+bool FakeOsReauthCall(bool* reauth_called, ReauthResult result) {
+  *reauth_called = true;
+  return result == ReauthResult::PASS;
+}
+
+std::unique_ptr<KeyedService> BuildPasswordsPrivateEventRouter(
+    content::BrowserContext* context) {
+  return std::unique_ptr<KeyedService>(
+      PasswordsPrivateEventRouter::Create(context));
+}
+
+autofill::PasswordForm CreateSampleForm() {
+  autofill::PasswordForm form;
+  form.origin = GURL("http://abc1.com");
+  form.username_value = base::ASCIIToUTF16("test@gmail.com");
+  form.password_value = base::ASCIIToUTF16("test");
+  return form;
+}
+
+}  // namespace
+
+class PasswordsPrivateDelegateImplTest : public testing::Test {
+ public:
+  PasswordsPrivateDelegateImplTest();
+  ~PasswordsPrivateDelegateImplTest() override;
+
+  // Sets up a testing password store and fills it with |forms|.
+  void SetUpPasswordStore(std::vector<autofill::PasswordForm> forms);
+
+  // Sets up a testing EventRouter with a production
+  // PasswordsPrivateEventRouter.
+  void SetUpRouters();
+
+ protected:
+  content::TestBrowserThreadBundle thread_bundle_;
+  TestingProfile profile_;
+  extensions::TestEventRouter* event_router_ = nullptr;
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(PasswordsPrivateDelegateImplTest);
+};
+
+PasswordsPrivateDelegateImplTest::PasswordsPrivateDelegateImplTest() = default;
+
+PasswordsPrivateDelegateImplTest::~PasswordsPrivateDelegateImplTest() = default;
+
+void PasswordsPrivateDelegateImplTest::SetUpPasswordStore(
+    std::vector<autofill::PasswordForm> forms) {
+  scoped_refptr<password_manager::TestPasswordStore>
+  password_store(static_cast<password_manager::TestPasswordStore*>(
+      PasswordStoreFactory::GetInstance()
+          ->SetTestingFactoryAndUse(
+              &profile_,
+              password_manager::BuildPasswordStore<
+                  content::BrowserContext, password_manager::TestPasswordStore>)
+          .get()));
+  for (const autofill::PasswordForm& form : forms) {
+    password_store->AddLogin(form);
+  }
+  // Spin the loop to allow PasswordStore tasks being processed.
+  base::RunLoop().RunUntilIdle();
+}
+
+void PasswordsPrivateDelegateImplTest::SetUpRouters() {
+  event_router_ = extensions::CreateAndUseTestEventRouter(&profile_);
+  // Set the production PasswordsPrivateEventRouter::Create as a testing
+  // factory, because at some point during the preceding initialization, a null
+  // factory is set, resulting in nul PasswordsPrivateEventRouter.
+  PasswordsPrivateEventRouterFactory::GetInstance()->SetTestingFactory(
+      &profile_, BuildPasswordsPrivateEventRouter);
+}
+
+TEST_F(PasswordsPrivateDelegateImplTest, GetSavedPasswordsList) {
   CallbackTracker<PasswordsPrivateDelegate::UiEntries> tracker;
 
-  content::TestBrowserThreadBundle thread_bundle;
-  TestingProfile profile;
-  PasswordsPrivateDelegateImpl delegate(&profile);
+  PasswordsPrivateDelegateImpl delegate(&profile_);
 
   delegate.GetSavedPasswordsList(tracker.callback());
   EXPECT_EQ(0u, tracker.call_count());
@@ -62,12 +189,10 @@
   EXPECT_EQ(2u, tracker.call_count());
 }
 
-TEST(PasswordsPrivateDelegateImplTest, GetPasswordExceptionsList) {
+TEST_F(PasswordsPrivateDelegateImplTest, GetPasswordExceptionsList) {
   CallbackTracker<PasswordsPrivateDelegate::ExceptionEntries> tracker;
 
-  content::TestBrowserThreadBundle thread_bundle;
-  TestingProfile profile;
-  PasswordsPrivateDelegateImpl delegate(&profile);
+  PasswordsPrivateDelegateImpl delegate(&profile_);
 
   delegate.GetPasswordExceptionsList(tracker.callback());
   EXPECT_EQ(0u, tracker.call_count());
@@ -81,4 +206,72 @@
   EXPECT_EQ(2u, tracker.call_count());
 }
 
+TEST_F(PasswordsPrivateDelegateImplTest, TestPassedReauthOnView) {
+  SetUpPasswordStore({CreateSampleForm()});
+
+  PasswordsPrivateDelegateImpl delegate(&profile_);
+  // Spin the loop to allow PasswordStore tasks posted on the creation of
+  // |delegate| to be completed.
+  base::RunLoop().RunUntilIdle();
+
+  SetUpRouters();
+  PasswordEventObserver event_observer(
+      api::passwords_private::OnPlaintextPasswordRetrieved::kEventName);
+  event_router_->AddEventObserver(&event_observer);
+
+  bool reauth_called = false;
+  delegate.SetOsReauthCallForTesting(base::BindRepeating(
+      &FakeOsReauthCall, &reauth_called, ReauthResult::PASS));
+
+  delegate.RequestShowPassword(0, nullptr);
+  EXPECT_TRUE(reauth_called);
+  EXPECT_EQ("test", event_observer.PassEventArgs()
+                        .GetList()[0]
+                        .FindKey("plaintextPassword")
+                        ->GetString());
+}
+
+TEST_F(PasswordsPrivateDelegateImplTest, TestFailedReauthOnView) {
+  SetUpPasswordStore({CreateSampleForm()});
+
+  PasswordsPrivateDelegateImpl delegate(&profile_);
+  // Spin the loop to allow PasswordStore tasks posted on the creation of
+  // |delegate| to be completed.
+  base::RunLoop().RunUntilIdle();
+
+  SetUpRouters();
+  PasswordEventObserver event_observer(
+      api::passwords_private::OnPlaintextPasswordRetrieved::kEventName);
+  event_router_->AddEventObserver(&event_observer);
+
+  bool reauth_called = false;
+  delegate.SetOsReauthCallForTesting(base::BindRepeating(
+      &FakeOsReauthCall, &reauth_called, ReauthResult::FAIL));
+
+  delegate.RequestShowPassword(0, nullptr);
+  EXPECT_TRUE(reauth_called);
+  base::Value captured_args = event_observer.PassEventArgs();
+  EXPECT_EQ(base::Value::Type::NONE, captured_args.type()) << captured_args;
+}
+
+TEST_F(PasswordsPrivateDelegateImplTest, TestReauthOnExport) {
+  SetUpPasswordStore({CreateSampleForm()});
+
+  PasswordsPrivateDelegateImpl delegate(&profile_);
+  // Spin the loop to allow PasswordStore tasks posted on the creation of
+  // |delegate| to be completed.
+  base::RunLoop().RunUntilIdle();
+
+  bool reauth_called = false;
+  delegate.SetOsReauthCallForTesting(base::BindRepeating(
+      &FakeOsReauthCall, &reauth_called, ReauthResult::PASS));
+
+  delegate.ExportPasswords(nullptr);
+  EXPECT_TRUE(reauth_called);
+
+  // TODO(crbug.com/341477): Once the export flow has defined messages to UI,
+  // such as progress indication, intercept them with PasswordEventObserver and
+  // check that exporting is aborted if the authentication failed.
+}
+
 }  // namespace extensions
diff --git a/chrome/browser/extensions/api/virtual_keyboard_private/chrome_virtual_keyboard_delegate.cc b/chrome/browser/extensions/api/virtual_keyboard_private/chrome_virtual_keyboard_delegate.cc
index 251299b..c44fc01f 100644
--- a/chrome/browser/extensions/api/virtual_keyboard_private/chrome_virtual_keyboard_delegate.cc
+++ b/chrome/browser/extensions/api/virtual_keyboard_private/chrome_virtual_keyboard_delegate.cc
@@ -192,8 +192,17 @@
   results->SetBoolean("hotrodmode", keyboard::GetHotrodKeyboardEnabled());
   std::unique_ptr<base::ListValue> features(new base::ListValue());
 
+  // 'floatingvirtualkeyboard' is the name of the feature flag for the legacy
+  // floating keyboard that was prototyped quite some time ago. It is currently
+  // referenced by the extension even though we never enable this value and so
+  // re-using that value is not feasible due to the semi-tandem nature of the
+  // keyboard extension. The 'floatingkeybard' flag represents the new floating
+  // keyboard and should be used for new extension-side feature work for the
+  // floating keyboard.
+  // TODO(blakeo): once the old flag's usages have been removed from the
+  // extension and all pushes have settled, remove this overly verbose comment.
   features->AppendString(GenerateFeatureFlag(
-      "floatingvirtualkeyboard", keyboard::IsFloatingVirtualKeyboardEnabled()));
+      "floatingkeyboard", keyboard::IsFloatingVirtualKeyboardEnabled()));
   features->AppendString(
       GenerateFeatureFlag("gesturetyping", keyboard::IsGestureTypingEnabled()));
   features->AppendString(GenerateFeatureFlag(
diff --git a/chrome/browser/extensions/api/web_navigation/web_navigation_api.cc b/chrome/browser/extensions/api/web_navigation/web_navigation_api.cc
index 4874f47..c155c07 100644
--- a/chrome/browser/extensions/api/web_navigation/web_navigation_api.cc
+++ b/chrome/browser/extensions/api/web_navigation/web_navigation_api.cc
@@ -388,6 +388,8 @@
 
   WebNavigationAPI* api = WebNavigationAPI::GetFactoryInstance()->Get(
       web_contents()->GetBrowserContext());
+  if (!api)
+    return;  // Possible in unit tests.
   WebNavigationEventRouter* router = api->web_navigation_event_router_.get();
   if (!router)
     return;
diff --git a/chrome/browser/extensions/api/webstore_private/webstore_private_apitest.cc b/chrome/browser/extensions/api/webstore_private/webstore_private_apitest.cc
index c674bd9c..ef75b258 100644
--- a/chrome/browser/extensions/api/webstore_private/webstore_private_apitest.cc
+++ b/chrome/browser/extensions/api/webstore_private/webstore_private_apitest.cc
@@ -34,6 +34,7 @@
 #include "extensions/browser/extension_dialog_auto_confirm.h"
 #include "extensions/browser/extension_system.h"
 #include "extensions/browser/install/extension_install_ui.h"
+#include "gpu/config/gpu_feature_type.h"
 #include "net/dns/mock_host_resolver.h"
 #include "net/test/embedded_test_server/embedded_test_server.h"
 #include "ui/gl/gl_switches.h"
@@ -386,14 +387,6 @@
 class ExtensionWebstoreGetWebGLStatusTest : public InProcessBrowserTest {
  protected:
   void RunTest(bool webgl_allowed) {
-#if defined(OS_CHROMEOS) && BUILDFLAG(ENABLE_PACKAGE_MASH_SERVICES)
-    // TODO(zmo): crbug.com/777681
-    // In Mus GpuFeatureInfo computed in GPU process isn't wired back to
-    // browser process, therefore GpuFeatureChecker times out.
-    base::CommandLine* command_line = base::CommandLine::ForCurrentProcess();
-    if (command_line->HasSwitch(switches::kMus))
-      return;
-#endif
     // If Gpu access is disallowed then WebGL will not be available.
     if (!content::GpuDataManager::GetInstance()->GpuAccessAllowed(NULL))
       webgl_allowed = false;
@@ -423,9 +416,8 @@
 // Tests getWebGLStatus function when WebGL is blacklisted.
 IN_PROC_BROWSER_TEST_F(ExtensionWebstoreGetWebGLStatusTest, Blocked) {
   content::GpuDataManager::GetInstance()->BlacklistWebGLForTesting();
-  EXPECT_EQ(gpu::kGpuFeatureStatusBlacklisted,
-            content::GpuDataManager::GetInstance()->GetFeatureStatus(
-                gpu::GPU_FEATURE_TYPE_ACCELERATED_WEBGL));
+  EXPECT_TRUE(content::GpuDataManager::GetInstance()->IsFeatureBlacklisted(
+      gpu::GPU_FEATURE_TYPE_ACCELERATED_WEBGL));
 
   bool webgl_allowed = false;
   RunTest(webgl_allowed);
diff --git a/chrome/browser/flag_descriptions.cc b/chrome/browser/flag_descriptions.cc
index 8b544eb..6e465535 100644
--- a/chrome/browser/flag_descriptions.cc
+++ b/chrome/browser/flag_descriptions.cc
@@ -94,6 +94,11 @@
     "eligibility requirements for showing app banners, such as having a "
     "manifest, are met.";
 
+const char kCommittedInterstitialsName[] = "Committed Interstitials";
+const char kCommittedInterstitialsDescription[] =
+    "Use committed error pages instead of transient navigation entries "
+    "for interstitial error pages (e.g. certificate errors).";
+
 const char kCaptureThumbnailOnNavigatingAwayName[] =
     "Capture page thumbnail on navigating away";
 const char kCaptureThumbnailOnNavigatingAwayDescription[] =
@@ -1118,6 +1123,13 @@
     "reduce the amount of information in the 'referer' header for cross-origin "
     "requests.";
 
+const char kRemoveUsageOfDeprecatedGaiaSigninEndpointName[] =
+    "Remove usage of the deprecated GAIA sign-in endpoint";
+const char kRemoveUsageOfDeprecatedGaiaSigninEndpointDescription[] =
+    "The Gaia sign-in endpoint used for full-tab sign-in page is deprecated. "
+    "This flags controls wheter it should no longer be used during a sign-in "
+    " flow.";
+
 const char kRequestTabletSiteName[] =
     "Request tablet site option in the settings menu";
 const char kRequestTabletSiteDescription[] =
@@ -2205,6 +2217,10 @@
     "Enable Desktop to iOS promotions, and allow users to see them if they are "
     "eligible.";
 
+const char kExperimentalTabControllerName[] = "Experimental tab controller.";
+const char kExperimentalTabControllerDescription[] =
+    "Enable controller for highly experimental tab policies.";
+
 const char kGdiTextPrinting[] = "GDI Text Printing";
 const char kGdiTextPrintingDescription[] =
     "Use GDI to print text as simply text";
@@ -2414,11 +2430,6 @@
 const char kDisableSystemTimezoneAutomaticDetectionDescription[] =
     "Disable system timezone automatic detection device policy.";
 
-const char kEnableFullscreenAppListName[] = "Enable The Peeking Launcher";
-const char kEnableFullscreenAppListDescription[] =
-    "The peeking launcher UI supports touch and provides more space for "
-    "upcoming features.";
-
 const char kEnableBackgroundBlurName[] = "Enable background blur.";
 const char kEnableBackgroundBlurDescription[] =
     "Enables background blur for the Peeking Launcher, Lock Screen, and Tab "
diff --git a/chrome/browser/flag_descriptions.h b/chrome/browser/flag_descriptions.h
index 8ebb125..43fa941 100644
--- a/chrome/browser/flag_descriptions.h
+++ b/chrome/browser/flag_descriptions.h
@@ -81,6 +81,9 @@
 extern const char kBypassAppBannerEngagementChecksName[];
 extern const char kBypassAppBannerEngagementChecksDescription[];
 
+extern const char kCommittedInterstitialsName[];
+extern const char kCommittedInterstitialsDescription[];
+
 extern const char kCaptureThumbnailOnNavigatingAwayName[];
 extern const char kCaptureThumbnailOnNavigatingAwayDescription[];
 
@@ -691,6 +694,9 @@
 extern const char kReducedReferrerGranularityName[];
 extern const char kReducedReferrerGranularityDescription[];
 
+extern const char kRemoveUsageOfDeprecatedGaiaSigninEndpointName[];
+extern const char kRemoveUsageOfDeprecatedGaiaSigninEndpointDescription[];
+
 extern const char kRequestTabletSiteName[];
 extern const char kRequestTabletSiteDescription[];
 
@@ -1350,6 +1356,9 @@
 extern const char kEnableDesktopIosPromotionsName[];
 extern const char kEnableDesktopIosPromotionsDescription[];
 
+extern const char kExperimentalTabControllerName[];
+extern const char kExperimentalTabControllerDescription[];
+
 extern const char kGdiTextPrinting[];
 extern const char kGdiTextPrintingDescription[];
 
@@ -1488,9 +1497,6 @@
 extern const char kDisableSystemTimezoneAutomaticDetectionName[];
 extern const char kDisableSystemTimezoneAutomaticDetectionDescription[];
 
-extern const char kEnableFullscreenAppListName[];
-extern const char kEnableFullscreenAppListDescription[];
-
 extern const char kEnableBackgroundBlurName[];
 extern const char kEnableBackgroundBlurDescription[];
 
diff --git a/chrome/browser/internal_auth.cc b/chrome/browser/internal_auth.cc
index d06f4df..e197553f 100644
--- a/chrome/browser/internal_auth.cc
+++ b/chrome/browser/internal_auth.cc
@@ -193,8 +193,6 @@
 
 }  // namespace
 
-namespace chrome {
-
 class InternalAuthVerificationService {
  public:
   InternalAuthVerificationService()
@@ -321,19 +319,15 @@
   DISALLOW_COPY_AND_ASSIGN(InternalAuthVerificationService);
 };
 
-}  // namespace chrome
-
 namespace {
 
-static base::LazyInstance<chrome::InternalAuthVerificationService>::
-    DestructorAtExit g_verification_service = LAZY_INSTANCE_INITIALIZER;
+static base::LazyInstance<InternalAuthVerificationService>::DestructorAtExit
+    g_verification_service = LAZY_INSTANCE_INITIALIZER;
 static base::LazyInstance<base::Lock>::Leaky
     g_verification_service_lock = LAZY_INSTANCE_INITIALIZER;
 
 }  // namespace
 
-namespace chrome {
-
 class InternalAuthGenerationService : public base::ThreadChecker {
  public:
   InternalAuthGenerationService() : key_regeneration_tick_(0) {
@@ -428,17 +422,13 @@
   DISALLOW_COPY_AND_ASSIGN(InternalAuthGenerationService);
 };
 
-}  // namespace chrome
-
 namespace {
 
-static base::LazyInstance<chrome::InternalAuthGenerationService>::
-    DestructorAtExit g_generation_service = LAZY_INSTANCE_INITIALIZER;
+static base::LazyInstance<InternalAuthGenerationService>::DestructorAtExit
+    g_generation_service = LAZY_INSTANCE_INITIALIZER;
 
 }  // namespace
 
-namespace chrome {
-
 // static
 bool InternalAuthVerification::VerifyPassport(
     const std::string& passport,
@@ -477,4 +467,3 @@
   g_generation_service.Get().GenerateNewKey();
 }
 
-}  // namespace chrome
diff --git a/chrome/browser/internal_auth.h b/chrome/browser/internal_auth.h
index 9f5df11a..23e2ee8e 100644
--- a/chrome/browser/internal_auth.h
+++ b/chrome/browser/internal_auth.h
@@ -11,8 +11,6 @@
 #include "base/gtest_prod_util.h"
 #include "base/macros.h"
 
-namespace chrome {
-
 // Call InternalAuthVerification methods on any thread.
 class InternalAuthVerification {
  public:
@@ -66,6 +64,4 @@
   static void GenerateNewKey();
 };
 
-}  // namespace chrome
-
 #endif  // CHROME_BROWSER_INTERNAL_AUTH_H_
diff --git a/chrome/browser/internal_auth_unittest.cc b/chrome/browser/internal_auth_unittest.cc
index f9dd9324..450992e 100644
--- a/chrome/browser/internal_auth_unittest.cc
+++ b/chrome/browser/internal_auth_unittest.cc
@@ -13,8 +13,6 @@
 #include "base/time/time.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
-namespace chrome {
-
 class InternalAuthTest : public ::testing::Test {
  public:
   InternalAuthTest() {
@@ -184,5 +182,3 @@
   // Passport should not survive series of key changes.
   ASSERT_FALSE(InternalAuthVerification::VerifyPassport(token, "zapata", map));
 }
-
-}  // namespace chrome
diff --git a/chrome/browser/language/chrome_language_detection_client.cc b/chrome/browser/language/chrome_language_detection_client.cc
index da0c20c..ebee91ad 100644
--- a/chrome/browser/language/chrome_language_detection_client.cc
+++ b/chrome/browser/language/chrome_language_detection_client.cc
@@ -18,9 +18,8 @@
 ChromeLanguageDetectionClient::ChromeLanguageDetectionClient(
     content::WebContents* const web_contents)
     : content::WebContentsObserver(web_contents),
-      language_histogram_(
-          UrlLanguageHistogramFactory::GetInstance()->GetForBrowserContext(
-              web_contents->GetBrowserContext())) {}
+      language_histogram_(UrlLanguageHistogramFactory::GetForBrowserContext(
+          web_contents->GetBrowserContext())) {}
 
 ChromeLanguageDetectionClient::~ChromeLanguageDetectionClient() = default;
 
diff --git a/chrome/browser/local_discovery/service_discovery_client_mac.mm b/chrome/browser/local_discovery/service_discovery_client_mac.mm
index 6a87b322..44f4227 100644
--- a/chrome/browser/local_discovery/service_discovery_client_mac.mm
+++ b/chrome/browser/local_discovery/service_discovery_client_mac.mm
@@ -357,6 +357,9 @@
 
 void ServiceResolverImplMac::NetServiceContainer::OnResolveUpdate(
     RequestStatus status) {
+  if (callback_.is_null())
+    return;
+
   if (status != STATUS_SUCCESS) {
     callback_runner_->PostTask(
         FROM_HERE,
@@ -435,7 +438,8 @@
 
   has_resolved_ = true;
 
-  std::move(callback_).Run(status, description);
+  if (!callback_.is_null())
+    std::move(callback_).Run(status, description);
 }
 
 ServiceResolverImplMac::NetServiceContainer*
diff --git a/chrome/browser/media/encrypted_media_browsertest.cc b/chrome/browser/media/encrypted_media_browsertest.cc
index 9e633e85..9037ed5 100644
--- a/chrome/browser/media/encrypted_media_browsertest.cc
+++ b/chrome/browser/media/encrypted_media_browsertest.cc
@@ -770,12 +770,6 @@
 }
 
 IN_PROC_BROWSER_TEST_P(ECKEncryptedMediaTest, FileIOTest) {
-  // TODO(jrummell): Support file IO in mojo CDM. See http://crbug.com/479923
-  if (IsUsingMojoCdm()) {
-    DVLOG(0) << "Skipping test; Not working with mojo CDM yet.";
-    return;
-  }
-
   TestNonPlaybackCases(kExternalClearKeyFileIOTestKeySystem, kUnitTestSuccess);
 }
 
@@ -807,22 +801,10 @@
 }
 
 IN_PROC_BROWSER_TEST_P(ECKEncryptedMediaTest, LoadLoadableSession) {
-  // TODO(jrummell): Support file IO in mojo CDM. See http://crbug.com/479923
-  if (IsUsingMojoCdm()) {
-    DVLOG(0) << "Skipping test; Not working with mojo CDM yet.";
-    return;
-  }
-
   TestPlaybackCase(kExternalClearKeyKeySystem, kLoadableSession, kEnded);
 }
 
 IN_PROC_BROWSER_TEST_P(ECKEncryptedMediaTest, LoadUnknownSession) {
-  // TODO(jrummell): Support file IO in mojo CDM. See http://crbug.com/479923
-  if (IsUsingMojoCdm()) {
-    DVLOG(0) << "Skipping test; Not working with mojo CDM yet.";
-    return;
-  }
-
   TestPlaybackCase(kExternalClearKeyKeySystem, kUnknownSession,
                    kEmeSessionNotFound);
 }
diff --git a/chrome/browser/media/router/BUILD.gn b/chrome/browser/media/router/BUILD.gn
index 9ffad96..b83a689 100644
--- a/chrome/browser/media/router/BUILD.gn
+++ b/chrome/browser/media/router/BUILD.gn
@@ -28,6 +28,10 @@
     "issue_manager.h",
     "issues_observer.cc",
     "issues_observer.h",
+    "local_presentation_manager.cc",
+    "local_presentation_manager.h",
+    "local_presentation_manager_factory.cc",
+    "local_presentation_manager_factory.h",
     "media_router.h",
     "media_router_base.cc",
     "media_router_base.h",
@@ -41,10 +45,6 @@
     "media_routes_observer.h",
     "media_sinks_observer.cc",
     "media_sinks_observer.h",
-    "offscreen_presentation_manager.cc",
-    "offscreen_presentation_manager.h",
-    "offscreen_presentation_manager_factory.cc",
-    "offscreen_presentation_manager_factory.h",
     "presentation_media_sinks_observer.cc",
     "presentation_media_sinks_observer.h",
     "presentation_service_delegate_impl.cc",
diff --git a/chrome/browser/media/router/local_presentation_manager.cc b/chrome/browser/media/router/local_presentation_manager.cc
new file mode 100644
index 0000000..614cebc2
--- /dev/null
+++ b/chrome/browser/media/router/local_presentation_manager.cc
@@ -0,0 +1,163 @@
+// 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 "chrome/browser/media/router/local_presentation_manager.h"
+
+#include <utility>
+
+#include "base/memory/ptr_util.h"
+#include "content/public/browser/render_frame_host.h"
+#include "content/public/browser/render_process_host.h"
+#include "content/public/browser/web_contents.h"
+#include "url/gurl.h"
+
+namespace media_router {
+
+// LocalPresentationManager implementation.
+LocalPresentationManager::LocalPresentationManager() {}
+
+LocalPresentationManager::~LocalPresentationManager() {}
+
+LocalPresentationManager::LocalPresentation*
+LocalPresentationManager::GetOrCreateLocalPresentation(
+    const content::PresentationInfo& presentation_info) {
+  auto it = local_presentations_.find(presentation_info.presentation_id);
+  if (it == local_presentations_.end()) {
+    it = local_presentations_
+             .insert(std::make_pair(
+                 presentation_info.presentation_id,
+                 base::MakeUnique<LocalPresentation>(presentation_info)))
+             .first;
+  }
+  return it->second.get();
+}
+
+void LocalPresentationManager::RegisterLocalPresentationController(
+    const content::PresentationInfo& presentation_info,
+    const RenderFrameHostId& render_frame_host_id,
+    content::PresentationConnectionPtr controller_connection_ptr,
+    content::PresentationConnectionRequest receiver_connection_request,
+    const MediaRoute& route) {
+  DVLOG(2) << __func__
+           << " [presentation_id]: " << presentation_info.presentation_id
+           << ", [render_frame_host_id]: " << render_frame_host_id.second;
+  DCHECK(thread_checker_.CalledOnValidThread());
+
+  auto* presentation = GetOrCreateLocalPresentation(presentation_info);
+  presentation->RegisterController(
+      render_frame_host_id, std::move(controller_connection_ptr),
+      std::move(receiver_connection_request), route);
+}
+
+void LocalPresentationManager::UnregisterLocalPresentationController(
+    const std::string& presentation_id,
+    const RenderFrameHostId& render_frame_host_id) {
+  DVLOG(2) << __func__ << " [presentation_id]: " << presentation_id
+           << ", [render_frame_host_id]: " << render_frame_host_id.second;
+  DCHECK(thread_checker_.CalledOnValidThread());
+
+  auto it = local_presentations_.find(presentation_id);
+  if (it == local_presentations_.end())
+    return;
+
+  // Remove presentation if no controller and receiver.
+  it->second->UnregisterController(render_frame_host_id);
+  if (!it->second->IsValid()) {
+    DLOG(WARNING) << __func__ << " no receiver callback has been registered to "
+                  << "[presentation_id]: " << presentation_id;
+    local_presentations_.erase(presentation_id);
+  }
+}
+
+void LocalPresentationManager::OnLocalPresentationReceiverCreated(
+    const content::PresentationInfo& presentation_info,
+    const content::ReceiverConnectionAvailableCallback& receiver_callback) {
+  DVLOG(2) << __func__
+           << " [presentation_id]: " << presentation_info.presentation_id;
+  DCHECK(thread_checker_.CalledOnValidThread());
+  auto* presentation = GetOrCreateLocalPresentation(presentation_info);
+  presentation->RegisterReceiver(receiver_callback);
+}
+
+void LocalPresentationManager::OnLocalPresentationReceiverTerminated(
+    const std::string& presentation_id) {
+  DVLOG(2) << __func__ << " [presentation_id]: " << presentation_id;
+  DCHECK(thread_checker_.CalledOnValidThread());
+
+  local_presentations_.erase(presentation_id);
+}
+
+bool LocalPresentationManager::IsLocalPresentation(
+    const std::string& presentation_id) {
+  return base::ContainsKey(local_presentations_, presentation_id);
+}
+
+const MediaRoute* LocalPresentationManager::GetRoute(
+    const std::string& presentation_id) {
+  auto it = local_presentations_.find(presentation_id);
+  return (it != local_presentations_.end() && it->second->route_.has_value())
+             ? &(it->second->route_.value())
+             : nullptr;
+}
+
+// LocalPresentation implementation.
+LocalPresentationManager::LocalPresentation::LocalPresentation(
+    const content::PresentationInfo& presentation_info)
+    : presentation_info_(presentation_info) {}
+
+LocalPresentationManager::LocalPresentation::~LocalPresentation() {}
+
+void LocalPresentationManager::LocalPresentation::RegisterController(
+    const RenderFrameHostId& render_frame_host_id,
+    content::PresentationConnectionPtr controller_connection_ptr,
+    content::PresentationConnectionRequest receiver_connection_request,
+    const MediaRoute& route) {
+  if (!receiver_callback_.is_null()) {
+    receiver_callback_.Run(presentation_info_,
+                           std::move(controller_connection_ptr),
+                           std::move(receiver_connection_request));
+  } else {
+    pending_controllers_.insert(std::make_pair(
+        render_frame_host_id, base::MakeUnique<ControllerConnection>(
+                                  std::move(controller_connection_ptr),
+                                  std::move(receiver_connection_request))));
+  }
+
+  route_ = route;
+}
+
+void LocalPresentationManager::LocalPresentation::UnregisterController(
+    const RenderFrameHostId& render_frame_host_id) {
+  pending_controllers_.erase(render_frame_host_id);
+}
+
+void LocalPresentationManager::LocalPresentation::RegisterReceiver(
+    const content::ReceiverConnectionAvailableCallback& receiver_callback) {
+  DCHECK(receiver_callback_.is_null());
+
+  for (auto& controller : pending_controllers_) {
+    receiver_callback.Run(
+        presentation_info_,
+        std::move(controller.second->controller_connection_ptr),
+        std::move(controller.second->receiver_connection_request));
+  }
+  receiver_callback_ = receiver_callback;
+  pending_controllers_.clear();
+}
+
+bool LocalPresentationManager::LocalPresentation::IsValid() const {
+  return !(pending_controllers_.empty() && receiver_callback_.is_null());
+}
+
+LocalPresentationManager::LocalPresentation::ControllerConnection::
+    ControllerConnection(
+        content::PresentationConnectionPtr controller_connection_ptr,
+        content::PresentationConnectionRequest receiver_connection_request)
+    : controller_connection_ptr(std::move(controller_connection_ptr)),
+      receiver_connection_request(std::move(receiver_connection_request)) {}
+
+LocalPresentationManager::LocalPresentation::ControllerConnection::
+    ~ControllerConnection() {}
+
+}  // namespace media_router
diff --git a/chrome/browser/media/router/local_presentation_manager.h b/chrome/browser/media/router/local_presentation_manager.h
new file mode 100644
index 0000000..47f33d4
--- /dev/null
+++ b/chrome/browser/media/router/local_presentation_manager.h
@@ -0,0 +1,252 @@
+// 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 CHROME_BROWSER_MEDIA_ROUTER_LOCAL_PRESENTATION_MANAGER_H_
+#define CHROME_BROWSER_MEDIA_ROUTER_LOCAL_PRESENTATION_MANAGER_H_
+
+#include <map>
+#include <memory>
+#include <string>
+#include <unordered_map>
+
+#include "base/macros.h"
+#include "base/optional.h"
+#include "base/threading/thread_checker.h"
+#include "chrome/browser/media/router/render_frame_host_id.h"
+#include "chrome/common/media_router/media_route.h"
+#include "components/keyed_service/core/keyed_service.h"
+#include "content/public/browser/presentation_service_delegate.h"
+
+namespace content {
+struct PresentationInfo;
+}
+
+namespace media_router {
+// Manages all local presentations started in the associated Profile and
+// facilitates communication between the controllers and the receiver of a
+// local presentation. A local presentation may be an offscreen presentation for
+// Presentation API 1-UA mode, or a presentation to a wired display.
+//
+// Design doc:
+// https://docs.google.com/document/d/1XM3jhMJTQyhEC5PDAAJFNIaKh6UUEihqZDz_ztEe4Co/edit#heading=h.hadpx5oi0gml
+//
+// Example usage:
+//
+// Receiver is created to host the local presentation and registers itself
+// so that controller frames can connect to it:
+//
+//   LocalPresentationManager* manager =
+//       LocalPresentationManagerFactory::GetOrCreateForBrowserContext(
+//           web_contents_->GetBrowserContext());
+//   manager->OnLocalPresentationReceiverCreated(presentation_info,
+//       base::Bind(&PresentationServiceImpl::OnReceiverConnectionAvailable));
+//
+// Controlling frame establishes connection with the receiver side, resulting
+// in a connection with the two endpoints being the controller
+// PresentationConnectionPtr and receiver PresentationConnectionPtr.
+// Note calling this will trigger receiver frame's
+// PresentationServiceImpl::OnReceiverConnectionAvailable.
+//
+//   manager->RegisterLocalPresentationController(
+//       presentation_info,
+//       std::move(controller_connection_ptr,
+//       std::move(receiver_connection_request));
+//
+// Invoked on receiver's PresentationServiceImpl when controller connection is
+// established.
+//
+//   |presentation_receiver_client_|: blink::mojom::PresentationServiceClienPtr
+//   for the presentation receiver.
+//   |controller_connection_ptr|: blink::mojom::PresentationConnectionPtr for
+//   blink::PresentationConnection object in controlling frame's render process.
+//   |receiver_connection_request|: Mojo InterfaceRequest to be bind to
+//   blink::PresentationConnection object in receiver frame's render process.
+//   void PresentationServiceImpl::OnReceiverConnectionAvailable(
+//       const content::PresentationInfo& presentation_info,
+//       PresentationConnectionPtr controller_connection_ptr,
+//       PresentationConnectionRequest receiver_connection_request) {
+//     presentation_receiver_client_->OnReceiverConnectionAvailable(
+//         blink::mojom::PresentationInfo::From(presentation_info),
+//         std::move(controller_connection_ptr),
+//         std::move(receiver_connection_request));
+//   }
+//
+// Send message from controlling/receiver frame to receiver/controlling frame:
+//
+//   |target_connection_|: member variable of
+//                         blink::mojom::PresentationConnectionPtr type,
+//                         refering to remote PresentationConnectionProxy
+//                         object on receiver/controlling frame.
+//   |message|: Text message to be sent.
+//   PresentationConnctionPtr::SendString(
+//       const blink::WebString& message) {
+//     target_connection_->OnMessage(
+//         content::PresentationConnectionMessage(message.Utf8()),
+//         base::Bind(&OnMessageReceived));
+//   }
+//
+// A controller or receiver leaves the local presentation (e.g., due to
+// navigation) by unregistering themselves from LocalPresentation object.
+//
+// When the receiver is no longer associated with a local presentation, it
+// shall unregister itself with LocalPresentationManager. Unregistration
+// will prevent additional controllers from establishing a connection with the
+// receiver:
+//
+//   In receiver's PSImpl::Reset() {
+//     local_presentation_manager->
+//         OnLocalPresentationReceiverTerminated(presentation_id);
+//   }
+//
+// This class is not thread safe. All functions must be invoked on the UI
+// thread. All callbacks passed into this class will also be invoked on UI
+// thread.
+class LocalPresentationManager : public KeyedService {
+ public:
+  ~LocalPresentationManager() override;
+
+  // Registers controller PresentationConnectionPtr to presentation with
+  // |presentation_id| and |render_frame_id|.
+  // Creates a new presentation if no presentation with |presentation_id|
+  // exists.
+  // |controller_connection_ptr|, |receiver_connection_request|: Not owned by
+  // this class. Ownership is transferred to presentation receiver via
+  // |receiver_callback| passed below.
+  virtual void RegisterLocalPresentationController(
+      const content::PresentationInfo& presentation_info,
+      const RenderFrameHostId& render_frame_id,
+      content::PresentationConnectionPtr controller_connection_ptr,
+      content::PresentationConnectionRequest receiver_connection_request,
+      const MediaRoute& route);
+
+  // Unregisters controller PresentationConnectionPtr to presentation with
+  // |presentation_id|, |render_frame_id|. It does nothing if there is no
+  // controller that matches the provided arguments. It removes presentation
+  // that matches the arguments if the presentation has no |receiver_callback|
+  // and any other pending controller.
+  virtual void UnregisterLocalPresentationController(
+      const std::string& presentation_id,
+      const RenderFrameHostId& render_frame_id);
+
+  // Registers |receiver_callback| to presentation with |presentation_info|.
+  virtual void OnLocalPresentationReceiverCreated(
+      const content::PresentationInfo& presentation_info,
+      const content::ReceiverConnectionAvailableCallback& receiver_callback);
+
+  // Unregisters ReceiverConnectionAvailableCallback associated with
+  // |presentation_id|.
+  virtual void OnLocalPresentationReceiverTerminated(
+      const std::string& presentation_id);
+
+  // Returns true if this class has a local presentation with
+  // |presentation_id|.
+  virtual bool IsLocalPresentation(const std::string& presentation_id);
+
+  // Returns nullptr if |presentation_id| is not associated with a local
+  // presentation.
+  virtual const MediaRoute* GetRoute(const std::string& presentation_id);
+
+ private:
+  // Represents a local presentation registered with
+  // LocalPresentationManager. Contains callback to the receiver to inform
+  // it of new connections established from a controller. Contains set of
+  // controllers registered to LocalPresentationManager before corresponding
+  // receiver.
+  class LocalPresentation {
+   public:
+    explicit LocalPresentation(
+        const content::PresentationInfo& presentation_info);
+    ~LocalPresentation();
+
+    // Register controller with |render_frame_id|. If |receiver_callback_| has
+    // been set, invoke |receiver_callback_| with |controller_connection_ptr|
+    // and |receiver_connection_request| as parameter, else creates a
+    // ControllerConnection object with |controller_connection_ptr| and
+    // |receiver_connection_request|, and store it in |pending_controllers_|
+    // map.
+    void RegisterController(
+        const RenderFrameHostId& render_frame_id,
+        content::PresentationConnectionPtr controller_connection_ptr,
+        content::PresentationConnectionRequest receiver_connection_request,
+        const MediaRoute& route);
+
+    // Unregister controller with |render_frame_id|. Do nothing if there is no
+    // pending controller with |render_frame_id|.
+    void UnregisterController(const RenderFrameHostId& render_frame_id);
+
+    // Register |receiver_callback| to current local_presentation object.
+    // For each controller in |pending_controllers_| map, invoke
+    // |receiver_callback| with controller as parameter. Clear
+    // |pending_controllers_| map afterwards.
+    void RegisterReceiver(
+        const content::ReceiverConnectionAvailableCallback& receiver_callback);
+
+   private:
+    friend class LocalPresentationManagerTest;
+    friend class LocalPresentationManager;
+
+    // Returns false if receiver_callback_ is null and there are no pending
+    // controllers.
+    bool IsValid() const;
+
+    const content::PresentationInfo presentation_info_;
+    base::Optional<MediaRoute> route_;
+
+    // Callback to invoke whenever a receiver connection is available.
+    content::ReceiverConnectionAvailableCallback receiver_callback_;
+
+    // Stores controller information.
+    // |controller_connection_ptr|: Mojo::InterfacePtr to
+    // blink::PresentationConnection object in controlling frame;
+    // |receiver_connection_request|: Mojo::InterfaceRequest to be bind to
+    // blink::PresentationConnection object in receiver frame.
+    struct ControllerConnection {
+     public:
+      ControllerConnection(
+          content::PresentationConnectionPtr controller_connection_ptr,
+          content::PresentationConnectionRequest receiver_connection_request);
+      ~ControllerConnection();
+
+      content::PresentationConnectionPtr controller_connection_ptr;
+      content::PresentationConnectionRequest receiver_connection_request;
+    };
+
+    // Contains ControllerConnection objects registered via
+    // |RegisterController()| before |receiver_callback_| is set.
+    std::unordered_map<RenderFrameHostId,
+                       std::unique_ptr<ControllerConnection>,
+                       RenderFrameHostIdHasher>
+        pending_controllers_;
+
+    DISALLOW_COPY_AND_ASSIGN(LocalPresentation);
+  };
+
+ private:
+  friend class LocalPresentationManagerFactory;
+  friend class LocalPresentationManagerTest;
+  friend class MockLocalPresentationManager;
+  FRIEND_TEST_ALL_PREFIXES(PresentationServiceDelegateImplTest,
+                           ConnectToLocalPresentation);
+
+  // Used by LocalPresentationManagerFactory::GetOrCreateForBrowserContext.
+  LocalPresentationManager();
+
+  using LocalPresentationMap =
+      std::map<std::string, std::unique_ptr<LocalPresentation>>;
+
+  // Creates a local presentation with |presentation_info|.
+  LocalPresentation* GetOrCreateLocalPresentation(
+      const content::PresentationInfo& presentation_info);
+
+  // Maps from presentation ID to LocalPresentation.
+  LocalPresentationMap local_presentations_;
+
+  base::ThreadChecker thread_checker_;
+
+  DISALLOW_COPY_AND_ASSIGN(LocalPresentationManager);
+};
+
+}  // namespace media_router
+
+#endif  // CHROME_BROWSER_MEDIA_ROUTER_LOCAL_PRESENTATION_MANAGER_H_
diff --git a/chrome/browser/media/router/local_presentation_manager_factory.cc b/chrome/browser/media/router/local_presentation_manager_factory.cc
new file mode 100644
index 0000000..a7519b83
--- /dev/null
+++ b/chrome/browser/media/router/local_presentation_manager_factory.cc
@@ -0,0 +1,65 @@
+// 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 "chrome/browser/media/router/local_presentation_manager_factory.h"
+
+#include "base/lazy_instance.h"
+
+#include "chrome/browser/media/router/local_presentation_manager.h"
+#include "chrome/browser/profiles/incognito_helpers.h"
+#include "chrome/browser/profiles/profile.h"
+#include "components/keyed_service/content/browser_context_dependency_manager.h"
+#include "content/public/browser/web_contents.h"
+
+namespace media_router {
+
+namespace {
+
+base::LazyInstance<LocalPresentationManagerFactory>::DestructorAtExit
+    service_factory = LAZY_INSTANCE_INITIALIZER;
+
+}  // namespace
+
+// static
+LocalPresentationManager*
+LocalPresentationManagerFactory::GetOrCreateForWebContents(
+    content::WebContents* web_contents) {
+  DCHECK(web_contents);
+  return LocalPresentationManagerFactory::GetOrCreateForBrowserContext(
+      web_contents->GetBrowserContext());
+}
+
+// static
+LocalPresentationManager*
+LocalPresentationManagerFactory::GetOrCreateForBrowserContext(
+    content::BrowserContext* context) {
+  DCHECK(context);
+  return static_cast<LocalPresentationManager*>(
+      service_factory.Get().GetServiceForBrowserContext(context, true));
+}
+
+// static
+LocalPresentationManagerFactory*
+LocalPresentationManagerFactory::GetInstanceForTest() {
+  return &service_factory.Get();
+}
+
+LocalPresentationManagerFactory::LocalPresentationManagerFactory()
+    : BrowserContextKeyedServiceFactory(
+          "LocalPresentationManager",
+          BrowserContextDependencyManager::GetInstance()) {}
+
+LocalPresentationManagerFactory::~LocalPresentationManagerFactory() {}
+
+content::BrowserContext*
+LocalPresentationManagerFactory::GetBrowserContextToUse(
+    content::BrowserContext* context) const {
+  return chrome::GetBrowserContextRedirectedInIncognito(context);
+}
+KeyedService* LocalPresentationManagerFactory::BuildServiceInstanceFor(
+    content::BrowserContext* context) const {
+  return new LocalPresentationManager;
+}
+
+}  // namespace media_router
diff --git a/chrome/browser/media/router/local_presentation_manager_factory.h b/chrome/browser/media/router/local_presentation_manager_factory.h
new file mode 100644
index 0000000..1e2bbcb
--- /dev/null
+++ b/chrome/browser/media/router/local_presentation_manager_factory.h
@@ -0,0 +1,54 @@
+// 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.
+
+#ifndef CHROME_BROWSER_MEDIA_ROUTER_LOCAL_PRESENTATION_MANAGER_FACTORY_H_
+#define CHROME_BROWSER_MEDIA_ROUTER_LOCAL_PRESENTATION_MANAGER_FACTORY_H_
+
+#include "base/lazy_instance.h"
+#include "components/keyed_service/content/browser_context_keyed_service_factory.h"
+
+namespace content {
+class BrowserContext;
+class WebContents;
+}  // namespace content
+
+namespace media_router {
+
+class LocalPresentationManager;
+
+// LocalPresentationManager is shared between a Profile and
+// its associated incognito Profiles.
+class LocalPresentationManagerFactory
+    : public BrowserContextKeyedServiceFactory {
+ public:
+  // If |web_contents| is normal profile, use it as browser context;
+  // If |web_contents| is incognito profile, |GetBrowserContextToUse| will
+  // redirect incognito profile to original profile, and use original one as
+  // browser context.
+  static LocalPresentationManager* GetOrCreateForWebContents(
+      content::WebContents* web_contents);
+  static LocalPresentationManager* GetOrCreateForBrowserContext(
+      content::BrowserContext* context);
+
+  // For test use only.
+  static LocalPresentationManagerFactory* GetInstanceForTest();
+
+ private:
+  friend struct base::LazyInstanceTraitsBase<LocalPresentationManagerFactory>;
+
+  LocalPresentationManagerFactory();
+  ~LocalPresentationManagerFactory() override;
+
+  // BrowserContextKeyedServiceFactory interface.
+  content::BrowserContext* GetBrowserContextToUse(
+      content::BrowserContext* context) const override;
+  KeyedService* BuildServiceInstanceFor(
+      content::BrowserContext* context) const override;
+
+  DISALLOW_COPY_AND_ASSIGN(LocalPresentationManagerFactory);
+};
+
+}  // namespace media_router
+
+#endif  // CHROME_BROWSER_MEDIA_ROUTER_LOCAL_PRESENTATION_MANAGER_FACTORY_H_
diff --git a/chrome/browser/media/router/local_presentation_manager_factory_unittest.cc b/chrome/browser/media/router/local_presentation_manager_factory_unittest.cc
new file mode 100644
index 0000000..3cb0a0b
--- /dev/null
+++ b/chrome/browser/media/router/local_presentation_manager_factory_unittest.cc
@@ -0,0 +1,50 @@
+// 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 <memory>
+
+#include "chrome/browser/media/router/local_presentation_manager_factory.h"
+#include "chrome/test/base/testing_profile.h"
+#include "content/public/browser/browser_context.h"
+#include "content/public/test/test_browser_thread_bundle.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace media_router {
+
+class LocalPresentationManagerFactoryTest : public testing::Test {
+ protected:
+  LocalPresentationManagerFactoryTest() {}
+  ~LocalPresentationManagerFactoryTest() override {}
+
+  Profile* profile() { return &profile_; }
+
+ private:
+  content::TestBrowserThreadBundle thread_bundle_;
+  TestingProfile profile_;
+};
+
+TEST_F(LocalPresentationManagerFactoryTest, CreateForRegularProfile) {
+  ASSERT_TRUE(
+      LocalPresentationManagerFactory::GetOrCreateForBrowserContext(profile()));
+}
+
+TEST_F(LocalPresentationManagerFactoryTest, CreateForOffTheRecordProfile) {
+  Profile* incognito_profile = profile()->GetOffTheRecordProfile();
+  ASSERT_TRUE(incognito_profile);
+
+  // Makes sure a LocalPresentationManager can be created from an incognito
+  // Profile.
+  LocalPresentationManager* manager =
+      LocalPresentationManagerFactory::GetOrCreateForBrowserContext(
+          incognito_profile);
+  ASSERT_TRUE(manager);
+
+  // A Profile and its incognito Profile share the same
+  // LocalPresentationManager instance.
+  ASSERT_EQ(
+      manager,
+      LocalPresentationManagerFactory::GetOrCreateForBrowserContext(profile()));
+}
+
+}  // namespace media_router
diff --git a/chrome/browser/media/router/local_presentation_manager_unittest.cc b/chrome/browser/media/router/local_presentation_manager_unittest.cc
new file mode 100644
index 0000000..369713a
--- /dev/null
+++ b/chrome/browser/media/router/local_presentation_manager_unittest.cc
@@ -0,0 +1,334 @@
+// 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 <vector>
+
+#include "base/bind.h"
+#include "base/stl_util.h"
+#include "chrome/browser/media/router/local_presentation_manager.h"
+#include "chrome/browser/media/router/test_helper.h"
+#include "testing/gmock/include/gmock/gmock.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "url/gurl.h"
+
+using testing::_;
+
+namespace media_router {
+
+namespace {
+const char kPresentationId[] = "presentationId";
+const char kPresentationId2[] = "presentationId2";
+const char kPresentationUrl[] = "http://www.example.com/presentation.html";
+}  // namespace
+
+class MockReceiverConnectionAvailableCallback {
+ public:
+  void OnReceiverConnectionAvailable(
+      const content::PresentationInfo& presentation_info,
+      content::PresentationConnectionPtr controller_conn,
+      content::PresentationConnectionRequest receiver_conn_request) {
+    OnReceiverConnectionAvailableRaw(presentation_info, controller_conn.get());
+  }
+
+  MOCK_METHOD2(OnReceiverConnectionAvailableRaw,
+               void(const content::PresentationInfo&,
+                    blink::mojom::PresentationConnection*));
+};
+
+class LocalPresentationManagerTest : public ::testing::Test {
+ public:
+  LocalPresentationManagerTest()
+      : render_frame_host_id_(1, 1),
+        presentation_info_(GURL(kPresentationUrl), kPresentationId),
+        route_("route_1",
+               MediaSource("source_1"),
+               "sink_1",
+               "",
+               false,
+               "",
+               false) {}
+
+  LocalPresentationManager* manager() { return &manager_; }
+
+  void VerifyPresentationsSize(size_t expected) {
+    EXPECT_EQ(expected, manager_.local_presentations_.size());
+  }
+
+  void VerifyControllerSize(size_t expected,
+                            const std::string& presentationId) {
+    EXPECT_TRUE(
+        base::ContainsKey(manager_.local_presentations_, presentationId));
+    EXPECT_EQ(expected, manager_.local_presentations_[presentationId]
+                            ->pending_controllers_.size());
+  }
+
+  void RegisterController(const std::string& presentation_id,
+                          content::PresentationConnectionPtr controller) {
+    RegisterController(
+        content::PresentationInfo(GURL(kPresentationUrl), presentation_id),
+        render_frame_host_id_, std::move(controller));
+  }
+
+  void RegisterController(const RenderFrameHostId& render_frame_id,
+                          content::PresentationConnectionPtr controller) {
+    RegisterController(presentation_info_, render_frame_id,
+                       std::move(controller));
+  }
+
+  void RegisterController(content::PresentationConnectionPtr controller) {
+    RegisterController(presentation_info_, render_frame_host_id_,
+                       std::move(controller));
+  }
+
+  void RegisterController(const content::PresentationInfo& presentation_info,
+                          const RenderFrameHostId& render_frame_id,
+                          content::PresentationConnectionPtr controller) {
+    content::PresentationConnectionRequest receiver_conn_request;
+    manager()->RegisterLocalPresentationController(
+        presentation_info, render_frame_id, std::move(controller),
+        std::move(receiver_conn_request), route_);
+  }
+
+  void RegisterReceiver(
+      MockReceiverConnectionAvailableCallback& receiver_callback) {
+    RegisterReceiver(kPresentationId, receiver_callback);
+  }
+
+  void RegisterReceiver(
+      const std::string& presentation_id,
+      MockReceiverConnectionAvailableCallback& receiver_callback) {
+    manager()->OnLocalPresentationReceiverCreated(
+        content::PresentationInfo(GURL(kPresentationUrl), presentation_id),
+        base::Bind(&MockReceiverConnectionAvailableCallback::
+                       OnReceiverConnectionAvailable,
+                   base::Unretained(&receiver_callback)));
+  }
+
+  void UnregisterController(const RenderFrameHostId& render_frame_id) {
+    manager()->UnregisterLocalPresentationController(kPresentationId,
+                                                     render_frame_id);
+  }
+
+  void UnregisterController() {
+    manager()->UnregisterLocalPresentationController(kPresentationId,
+                                                     render_frame_host_id_);
+  }
+
+  void UnregisterReceiver() {
+    manager()->OnLocalPresentationReceiverTerminated(kPresentationId);
+  }
+
+ private:
+  const RenderFrameHostId render_frame_host_id_;
+  const content::PresentationInfo presentation_info_;
+  LocalPresentationManager manager_;
+  MediaRoute route_;
+};
+
+TEST_F(LocalPresentationManagerTest, RegisterUnregisterController) {
+  content::PresentationConnectionPtr controller;
+  RegisterController(std::move(controller));
+  VerifyPresentationsSize(1);
+  UnregisterController();
+  VerifyPresentationsSize(0);
+}
+
+TEST_F(LocalPresentationManagerTest, RegisterUnregisterReceiver) {
+  MockReceiverConnectionAvailableCallback receiver_callback;
+  RegisterReceiver(receiver_callback);
+  VerifyPresentationsSize(1);
+  UnregisterReceiver();
+  VerifyPresentationsSize(0);
+}
+
+TEST_F(LocalPresentationManagerTest, UnregisterNonexistentController) {
+  UnregisterController();
+  VerifyPresentationsSize(0);
+}
+
+TEST_F(LocalPresentationManagerTest, UnregisterNonexistentReceiver) {
+  UnregisterReceiver();
+  VerifyPresentationsSize(0);
+}
+
+TEST_F(LocalPresentationManagerTest,
+       RegisterMultipleControllersSamePresentation) {
+  content::PresentationConnectionPtr controller1;
+  RegisterController(RenderFrameHostId(1, 1), std::move(controller1));
+  content::PresentationConnectionPtr controller2;
+  RegisterController(RenderFrameHostId(1, 2), std::move(controller2));
+  VerifyPresentationsSize(1);
+}
+
+TEST_F(LocalPresentationManagerTest,
+       RegisterMultipleControllersDifferentPresentations) {
+  content::PresentationConnectionPtr controller1;
+  RegisterController(kPresentationId, std::move(controller1));
+  content::PresentationConnectionPtr controller2;
+  RegisterController(kPresentationId2, std::move(controller2));
+  VerifyPresentationsSize(2);
+}
+
+TEST_F(LocalPresentationManagerTest,
+       RegisterControllerThenReceiverInvokesCallback) {
+  content::PresentationConnectionPtr controller;
+  MockReceiverConnectionAvailableCallback receiver_callback;
+
+  VerifyPresentationsSize(0);
+
+  RegisterController(std::move(controller));
+  EXPECT_CALL(receiver_callback, OnReceiverConnectionAvailableRaw(_, _));
+  RegisterReceiver(receiver_callback);
+}
+
+TEST_F(LocalPresentationManagerTest,
+       UnregisterReceiverFromConnectedPresentation) {
+  content::PresentationConnectionPtr controller;
+  MockReceiverConnectionAvailableCallback receiver_callback;
+
+  VerifyPresentationsSize(0);
+
+  RegisterController(std::move(controller));
+  EXPECT_CALL(receiver_callback, OnReceiverConnectionAvailableRaw(_, _));
+  RegisterReceiver(receiver_callback);
+  UnregisterReceiver();
+
+  VerifyPresentationsSize(0);
+}
+
+TEST_F(LocalPresentationManagerTest,
+       UnregisterControllerFromConnectedPresentation) {
+  content::PresentationConnectionPtr controller;
+  MockReceiverConnectionAvailableCallback receiver_callback;
+
+  VerifyPresentationsSize(0);
+
+  RegisterController(std::move(controller));
+  EXPECT_CALL(receiver_callback, OnReceiverConnectionAvailableRaw(_, _));
+  RegisterReceiver(receiver_callback);
+  UnregisterController();
+
+  VerifyPresentationsSize(1);
+}
+
+TEST_F(LocalPresentationManagerTest,
+       UnregisterReceiverThenControllerFromConnectedPresentation) {
+  content::PresentationConnectionPtr controller;
+  MockReceiverConnectionAvailableCallback receiver_callback;
+
+  VerifyPresentationsSize(0);
+
+  RegisterController(std::move(controller));
+  EXPECT_CALL(receiver_callback, OnReceiverConnectionAvailableRaw(_, _));
+  RegisterReceiver(receiver_callback);
+  UnregisterReceiver();
+  UnregisterController();
+
+  VerifyPresentationsSize(0);
+}
+
+TEST_F(LocalPresentationManagerTest,
+       UnregisterControllerThenReceiverFromConnectedPresentation) {
+  content::PresentationConnectionPtr controller;
+  MockReceiverConnectionAvailableCallback receiver_callback;
+
+  VerifyPresentationsSize(0);
+
+  RegisterController(std::move(controller));
+  EXPECT_CALL(receiver_callback, OnReceiverConnectionAvailableRaw(_, _));
+  RegisterReceiver(receiver_callback);
+  UnregisterController();
+  UnregisterReceiver();
+
+  VerifyPresentationsSize(0);
+}
+
+TEST_F(LocalPresentationManagerTest,
+       RegisterTwoControllersThenReceiverInvokesCallbackTwice) {
+  content::PresentationConnectionPtr controller1;
+  RegisterController(RenderFrameHostId(1, 1), std::move(controller1));
+  content::PresentationConnectionPtr controller2;
+  RegisterController(RenderFrameHostId(1, 2), std::move(controller2));
+
+  MockReceiverConnectionAvailableCallback receiver_callback;
+  EXPECT_CALL(receiver_callback, OnReceiverConnectionAvailableRaw(_, _))
+      .Times(2);
+  RegisterReceiver(receiver_callback);
+}
+
+TEST_F(LocalPresentationManagerTest,
+       RegisterControllerReceiverConontrollerInvokesCallbackTwice) {
+  content::PresentationConnectionPtr controller1;
+  RegisterController(RenderFrameHostId(1, 1), std::move(controller1));
+
+  MockReceiverConnectionAvailableCallback receiver_callback;
+  EXPECT_CALL(receiver_callback, OnReceiverConnectionAvailableRaw(_, _))
+      .Times(2);
+  RegisterReceiver(receiver_callback);
+
+  content::PresentationConnectionPtr controller2;
+  RegisterController(RenderFrameHostId(1, 2), std::move(controller2));
+}
+
+TEST_F(LocalPresentationManagerTest,
+       UnregisterFirstControllerFromeConnectedPresentation) {
+  content::PresentationConnectionPtr controller1;
+  RegisterController(RenderFrameHostId(1, 1), std::move(controller1));
+  content::PresentationConnectionPtr controller2;
+  RegisterController(RenderFrameHostId(1, 2), std::move(controller2));
+
+  MockReceiverConnectionAvailableCallback receiver_callback;
+  EXPECT_CALL(receiver_callback, OnReceiverConnectionAvailableRaw(_, _))
+      .Times(2);
+  RegisterReceiver(receiver_callback);
+  UnregisterController(RenderFrameHostId(1, 1));
+  UnregisterController(RenderFrameHostId(1, 1));
+
+  VerifyPresentationsSize(1);
+}
+
+TEST_F(LocalPresentationManagerTest, TwoPresentations) {
+  content::PresentationConnectionPtr controller1;
+  RegisterController(kPresentationId, std::move(controller1));
+
+  MockReceiverConnectionAvailableCallback receiver_callback1;
+  EXPECT_CALL(receiver_callback1, OnReceiverConnectionAvailableRaw(_, _))
+      .Times(1);
+  RegisterReceiver(kPresentationId, receiver_callback1);
+
+  content::PresentationConnectionPtr controller2;
+  RegisterController(kPresentationId2, std::move(controller2));
+
+  MockReceiverConnectionAvailableCallback receiver_callback2;
+  EXPECT_CALL(receiver_callback2, OnReceiverConnectionAvailableRaw(_, _))
+      .Times(1);
+  RegisterReceiver(kPresentationId2, receiver_callback2);
+
+  VerifyPresentationsSize(2);
+
+  UnregisterReceiver();
+  VerifyPresentationsSize(1);
+}
+
+TEST_F(LocalPresentationManagerTest, TestIsLocalPresentation) {
+  EXPECT_FALSE(manager()->IsLocalPresentation(kPresentationId));
+  content::PresentationConnectionPtr controller1;
+  RegisterController(kPresentationId, std::move(controller1));
+  EXPECT_TRUE(manager()->IsLocalPresentation(kPresentationId));
+}
+
+TEST_F(LocalPresentationManagerTest, TestRegisterAndGetRoute) {
+  MediaSource source("source_1");
+  MediaRoute route("route_1", source, "sink_1", "", false, "", false);
+
+  EXPECT_FALSE(manager()->GetRoute(kPresentationId));
+  content::PresentationConnectionPtr controller;
+  RegisterController(std::move(controller));
+
+  auto* actual_route = manager()->GetRoute(kPresentationId);
+  EXPECT_TRUE(actual_route);
+  EXPECT_TRUE(route.Equals(*actual_route));
+}
+
+}  // namespace media_router
diff --git a/chrome/browser/media/router/offscreen_presentation_manager.cc b/chrome/browser/media/router/offscreen_presentation_manager.cc
deleted file mode 100644
index 02283715..0000000
--- a/chrome/browser/media/router/offscreen_presentation_manager.cc
+++ /dev/null
@@ -1,164 +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 "chrome/browser/media/router/offscreen_presentation_manager.h"
-
-#include <utility>
-
-#include "base/memory/ptr_util.h"
-#include "content/public/browser/render_frame_host.h"
-#include "content/public/browser/render_process_host.h"
-#include "content/public/browser/web_contents.h"
-#include "url/gurl.h"
-
-namespace media_router {
-
-// OffscreenPresentationManager implementation.
-OffscreenPresentationManager::OffscreenPresentationManager() {}
-
-OffscreenPresentationManager::~OffscreenPresentationManager() {}
-
-OffscreenPresentationManager::OffscreenPresentation*
-OffscreenPresentationManager::GetOrCreateOffscreenPresentation(
-    const content::PresentationInfo& presentation_info) {
-  auto it = offscreen_presentations_.find(presentation_info.presentation_id);
-  if (it == offscreen_presentations_.end()) {
-    it = offscreen_presentations_
-             .insert(std::make_pair(
-                 presentation_info.presentation_id,
-                 base::MakeUnique<OffscreenPresentation>(presentation_info)))
-             .first;
-  }
-  return it->second.get();
-}
-
-void OffscreenPresentationManager::RegisterOffscreenPresentationController(
-    const content::PresentationInfo& presentation_info,
-    const RenderFrameHostId& render_frame_host_id,
-    content::PresentationConnectionPtr controller_connection_ptr,
-    content::PresentationConnectionRequest receiver_connection_request,
-    const MediaRoute& route) {
-  DVLOG(2) << __func__
-           << " [presentation_id]: " << presentation_info.presentation_id
-           << ", [render_frame_host_id]: " << render_frame_host_id.second;
-  DCHECK(thread_checker_.CalledOnValidThread());
-
-  auto* presentation = GetOrCreateOffscreenPresentation(presentation_info);
-  presentation->RegisterController(
-      render_frame_host_id, std::move(controller_connection_ptr),
-      std::move(receiver_connection_request), route);
-}
-
-void OffscreenPresentationManager::UnregisterOffscreenPresentationController(
-    const std::string& presentation_id,
-    const RenderFrameHostId& render_frame_host_id) {
-  DVLOG(2) << __func__ << " [presentation_id]: " << presentation_id
-           << ", [render_frame_host_id]: " << render_frame_host_id.second;
-  DCHECK(thread_checker_.CalledOnValidThread());
-
-  auto it = offscreen_presentations_.find(presentation_id);
-  if (it == offscreen_presentations_.end())
-    return;
-
-  // Remove presentation if no controller and receiver.
-  it->second->UnregisterController(render_frame_host_id);
-  if (!it->second->IsValid()) {
-    DLOG(WARNING) << __func__ << " no receiver callback has been registered to "
-                  << "[presentation_id]: " << presentation_id;
-    offscreen_presentations_.erase(presentation_id);
-  }
-}
-
-void OffscreenPresentationManager::OnOffscreenPresentationReceiverCreated(
-    const content::PresentationInfo& presentation_info,
-    const content::ReceiverConnectionAvailableCallback& receiver_callback) {
-  DVLOG(2) << __func__
-           << " [presentation_id]: " << presentation_info.presentation_id;
-  DCHECK(thread_checker_.CalledOnValidThread());
-  auto* presentation = GetOrCreateOffscreenPresentation(presentation_info);
-  presentation->RegisterReceiver(receiver_callback);
-}
-
-void OffscreenPresentationManager::OnOffscreenPresentationReceiverTerminated(
-    const std::string& presentation_id) {
-  DVLOG(2) << __func__ << " [presentation_id]: " << presentation_id;
-  DCHECK(thread_checker_.CalledOnValidThread());
-
-  offscreen_presentations_.erase(presentation_id);
-}
-
-bool OffscreenPresentationManager::IsOffscreenPresentation(
-    const std::string& presentation_id) {
-  return base::ContainsKey(offscreen_presentations_, presentation_id);
-}
-
-const MediaRoute* OffscreenPresentationManager::GetRoute(
-    const std::string& presentation_id) {
-  auto it = offscreen_presentations_.find(presentation_id);
-  return (it != offscreen_presentations_.end() &&
-          it->second->route_.has_value())
-             ? &(it->second->route_.value())
-             : nullptr;
-}
-
-// OffscreenPresentation implementation.
-OffscreenPresentationManager::OffscreenPresentation::OffscreenPresentation(
-    const content::PresentationInfo& presentation_info)
-    : presentation_info_(presentation_info) {}
-
-OffscreenPresentationManager::OffscreenPresentation::~OffscreenPresentation() {}
-
-void OffscreenPresentationManager::OffscreenPresentation::RegisterController(
-    const RenderFrameHostId& render_frame_host_id,
-    content::PresentationConnectionPtr controller_connection_ptr,
-    content::PresentationConnectionRequest receiver_connection_request,
-    const MediaRoute& route) {
-  if (!receiver_callback_.is_null()) {
-    receiver_callback_.Run(presentation_info_,
-                           std::move(controller_connection_ptr),
-                           std::move(receiver_connection_request));
-  } else {
-    pending_controllers_.insert(std::make_pair(
-        render_frame_host_id, base::MakeUnique<ControllerConnection>(
-                                  std::move(controller_connection_ptr),
-                                  std::move(receiver_connection_request))));
-  }
-
-  route_ = route;
-}
-
-void OffscreenPresentationManager::OffscreenPresentation::UnregisterController(
-    const RenderFrameHostId& render_frame_host_id) {
-  pending_controllers_.erase(render_frame_host_id);
-}
-
-void OffscreenPresentationManager::OffscreenPresentation::RegisterReceiver(
-    const content::ReceiverConnectionAvailableCallback& receiver_callback) {
-  DCHECK(receiver_callback_.is_null());
-
-  for (auto& controller : pending_controllers_) {
-    receiver_callback.Run(
-        presentation_info_,
-        std::move(controller.second->controller_connection_ptr),
-        std::move(controller.second->receiver_connection_request));
-  }
-  receiver_callback_ = receiver_callback;
-  pending_controllers_.clear();
-}
-
-bool OffscreenPresentationManager::OffscreenPresentation::IsValid() const {
-  return !(pending_controllers_.empty() && receiver_callback_.is_null());
-}
-
-OffscreenPresentationManager::OffscreenPresentation::ControllerConnection::
-    ControllerConnection(
-        content::PresentationConnectionPtr controller_connection_ptr,
-        content::PresentationConnectionRequest receiver_connection_request)
-    : controller_connection_ptr(std::move(controller_connection_ptr)),
-      receiver_connection_request(std::move(receiver_connection_request)) {}
-
-OffscreenPresentationManager::OffscreenPresentation::ControllerConnection::
-    ~ControllerConnection() {}
-
-}  // namespace media_router
diff --git a/chrome/browser/media/router/offscreen_presentation_manager.h b/chrome/browser/media/router/offscreen_presentation_manager.h
deleted file mode 100644
index bde4342..0000000
--- a/chrome/browser/media/router/offscreen_presentation_manager.h
+++ /dev/null
@@ -1,251 +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 CHROME_BROWSER_MEDIA_ROUTER_OFFSCREEN_PRESENTATION_MANAGER_H_
-#define CHROME_BROWSER_MEDIA_ROUTER_OFFSCREEN_PRESENTATION_MANAGER_H_
-
-#include <map>
-#include <memory>
-#include <string>
-#include <unordered_map>
-
-#include "base/macros.h"
-#include "base/optional.h"
-#include "base/threading/thread_checker.h"
-#include "chrome/browser/media/router/render_frame_host_id.h"
-#include "chrome/common/media_router/media_route.h"
-#include "components/keyed_service/core/keyed_service.h"
-#include "content/public/browser/presentation_service_delegate.h"
-
-namespace content {
-struct PresentationInfo;
-}
-
-namespace media_router {
-// Manages all offscreen presentations started in the associated Profile and
-// facilitates communication between the controllers and the receiver of an
-// offscreen presentation.
-//
-// Design doc:
-// https://docs.google.com/document/d/1XM3jhMJTQyhEC5PDAAJFNIaKh6UUEihqZDz_ztEe4Co/edit#heading=h.hadpx5oi0gml
-//
-// Example usage:
-//
-// Receiver is created to host the offscreen presentation and registers itself
-// so that controller frames can connect to it:
-//
-//   OffscreenPresentationManager* manager =
-//       OffscreenPresentationManagerFactory::GetOrCreateForBrowserContext(
-//           web_contents_->GetBrowserContext());
-//   manager->OnOffscreenPresentationReceiverCreated(presentation_info,
-//       base::Bind(&PresentationServiceImpl::OnReceiverConnectionAvailable));
-//
-// Controlling frame establishes connection with the receiver side, resulting
-// in a connection with the two endpoints being the controller
-// PresentationConnectionPtr and receiver PresentationConnectionPtr.
-// Note calling this will trigger receiver frame's
-// PresentationServiceImpl::OnReceiverConnectionAvailable.
-//
-//   manager->RegisterOffscreenPresentationController(
-//       presentation_info,
-//       std::move(controller_connection_ptr,
-//       std::move(receiver_connection_request));
-//
-// Invoked on receiver's PresentationServiceImpl when controller connection is
-// established.
-//
-//   |presentation_receiver_client_|: blink::mojom::PresentationServiceClienPtr
-//   for the presentation receiver.
-//   |controller_connection_ptr|: blink::mojom::PresentationConnectionPtr for
-//   blink::PresentationConnection object in controlling frame's render process.
-//   |receiver_connection_request|: Mojo InterfaceRequest to be bind to
-//   blink::PresentationConnection object in receiver frame's render process.
-//   void PresentationServiceImpl::OnReceiverConnectionAvailable(
-//       const content::PresentationInfo& presentation_info,
-//       PresentationConnectionPtr controller_connection_ptr,
-//       PresentationConnectionRequest receiver_connection_request) {
-//     presentation_receiver_client_->OnReceiverConnectionAvailable(
-//         blink::mojom::PresentationInfo::From(presentation_info),
-//         std::move(controller_connection_ptr),
-//         std::move(receiver_connection_request));
-//   }
-//
-// Send message from controlling/receiver frame to receiver/controlling frame:
-//
-//   |target_connection_|: member variable of
-//                         blink::mojom::PresentationConnectionPtr type,
-//                         refering to remote PresentationConnectionProxy
-//                         object on receiver/controlling frame.
-//   |message|: Text message to be sent.
-//   PresentationConnctionPtr::SendString(
-//       const blink::WebString& message) {
-//     target_connection_->OnMessage(
-//         content::PresentationConnectionMessage(message.Utf8()),
-//         base::Bind(&OnMessageReceived));
-//   }
-//
-// A controller or receiver leaves the offscreen presentation (e.g., due to
-// navigation) by unregistering themselves from OffscreenPresentation object.
-//
-// When the receiver is no longer associated with an offscreen presentation, it
-// shall unregister itself with OffscreenPresentationManager. Unregistration
-// will prevent additional controllers from establishing a connection with the
-// receiver:
-//
-//   In receiver's PSImpl::Reset() {
-//     offscreen_presentation_manager->
-//         OnOffscreenPresentationReceiverTerminated(presentation_id);
-//   }
-//
-// This class is not thread safe. All functions must be invoked on the UI
-// thread. All callbacks passed into this class will also be invoked on UI
-// thread.
-class OffscreenPresentationManager : public KeyedService {
- public:
-  ~OffscreenPresentationManager() override;
-
-  // Registers controller PresentationConnectionPtr to presentation with
-  // |presentation_id| and |render_frame_id|.
-  // Creates a new presentation if no presentation with |presentation_id|
-  // exists.
-  // |controller_connection_ptr|, |receiver_connection_request|: Not owned by
-  // this class. Ownership is transferred to presentation receiver via
-  // |receiver_callback| passed below.
-  virtual void RegisterOffscreenPresentationController(
-      const content::PresentationInfo& presentation_info,
-      const RenderFrameHostId& render_frame_id,
-      content::PresentationConnectionPtr controller_connection_ptr,
-      content::PresentationConnectionRequest receiver_connection_request,
-      const MediaRoute& route);
-
-  // Unregisters controller PresentationConnectionPtr to presentation with
-  // |presentation_id|, |render_frame_id|. It does nothing if there is no
-  // controller that matches the provided arguments. It removes presentation
-  // that matches the arguments if the presentation has no |receiver_callback|
-  // and any other pending controller.
-  virtual void UnregisterOffscreenPresentationController(
-      const std::string& presentation_id,
-      const RenderFrameHostId& render_frame_id);
-
-  // Registers |receiver_callback| to presentation with |presentation_info|.
-  virtual void OnOffscreenPresentationReceiverCreated(
-      const content::PresentationInfo& presentation_info,
-      const content::ReceiverConnectionAvailableCallback& receiver_callback);
-
-  // Unregisters ReceiverConnectionAvailableCallback associated with
-  // |presentation_id|.
-  virtual void OnOffscreenPresentationReceiverTerminated(
-      const std::string& presentation_id);
-
-  // Returns true if this class has an offscreen presentation with
-  // |presentation_id|.
-  virtual bool IsOffscreenPresentation(const std::string& presentation_id);
-
-  // Returns nullptr if |presentation_id| is not associated with an offscreen
-  // presentation.
-  virtual const MediaRoute* GetRoute(const std::string& presentation_id);
-
- private:
-  // Represents an offscreen presentation registered with
-  // OffscreenPresentationManager. Contains callback to the receiver to inform
-  // it of new connections established from a controller. Contains set of
-  // controllers registered to OffscreenPresentationManager before corresponding
-  // receiver.
-  class OffscreenPresentation {
-   public:
-    explicit OffscreenPresentation(
-        const content::PresentationInfo& presentation_info);
-    ~OffscreenPresentation();
-
-    // Register controller with |render_frame_id|. If |receiver_callback_| has
-    // been set, invoke |receiver_callback_| with |controller_connection_ptr|
-    // and |receiver_connection_request| as parameter, else creates a
-    // ControllerConnection object with |controller_connection_ptr| and
-    // |receiver_connection_request|, and store it in |pending_controllers_|
-    // map.
-    void RegisterController(
-        const RenderFrameHostId& render_frame_id,
-        content::PresentationConnectionPtr controller_connection_ptr,
-        content::PresentationConnectionRequest receiver_connection_request,
-        const MediaRoute& route);
-
-    // Unregister controller with |render_frame_id|. Do nothing if there is no
-    // pending controller with |render_frame_id|.
-    void UnregisterController(const RenderFrameHostId& render_frame_id);
-
-    // Register |receiver_callback| to current offscreen_presentation object.
-    // For each controller in |pending_controllers_| map, invoke
-    // |receiver_callback| with controller as parameter. Clear
-    // |pending_controllers_| map afterwards.
-    void RegisterReceiver(
-        const content::ReceiverConnectionAvailableCallback& receiver_callback);
-
-   private:
-    friend class OffscreenPresentationManagerTest;
-    friend class OffscreenPresentationManager;
-
-    // Returns false if receiver_callback_ is null and there are no pending
-    // controllers.
-    bool IsValid() const;
-
-    const content::PresentationInfo presentation_info_;
-    base::Optional<MediaRoute> route_;
-
-    // Callback to invoke whenever a receiver connection is available.
-    content::ReceiverConnectionAvailableCallback receiver_callback_;
-
-    // Stores controller information.
-    // |controller_connection_ptr|: Mojo::InterfacePtr to
-    // blink::PresentationConnection object in controlling frame;
-    // |receiver_connection_request|: Mojo::InterfaceRequest to be bind to
-    // blink::PresentationConnection object in receiver frame.
-    struct ControllerConnection {
-     public:
-      ControllerConnection(
-          content::PresentationConnectionPtr controller_connection_ptr,
-          content::PresentationConnectionRequest receiver_connection_request);
-      ~ControllerConnection();
-
-      content::PresentationConnectionPtr controller_connection_ptr;
-      content::PresentationConnectionRequest receiver_connection_request;
-    };
-
-    // Contains ControllerConnection objects registered via
-    // |RegisterController()| before |receiver_callback_| is set.
-    std::unordered_map<RenderFrameHostId,
-                       std::unique_ptr<ControllerConnection>,
-                       RenderFrameHostIdHasher>
-        pending_controllers_;
-
-    DISALLOW_COPY_AND_ASSIGN(OffscreenPresentation);
-  };
-
- private:
-  friend class OffscreenPresentationManagerFactory;
-  friend class OffscreenPresentationManagerTest;
-  friend class MockOffscreenPresentationManager;
-  FRIEND_TEST_ALL_PREFIXES(PresentationServiceDelegateImplTest,
-                           ConnectToOffscreenPresentation);
-
-  // Used by OffscreenPresentationManagerFactory::GetOrCreateForBrowserContext.
-  OffscreenPresentationManager();
-
-  using OffscreenPresentationMap =
-      std::map<std::string, std::unique_ptr<OffscreenPresentation>>;
-
-  // Creates an offscreen presentation with |presentation_info|.
-  OffscreenPresentation* GetOrCreateOffscreenPresentation(
-      const content::PresentationInfo& presentation_info);
-
-  // Maps from presentation ID to OffscreenPresentation.
-  OffscreenPresentationMap offscreen_presentations_;
-
-  base::ThreadChecker thread_checker_;
-
-  DISALLOW_COPY_AND_ASSIGN(OffscreenPresentationManager);
-};
-
-}  // namespace media_router
-
-#endif  // CHROME_BROWSER_MEDIA_ROUTER_OFFSCREEN_PRESENTATION_MANAGER_H_
diff --git a/chrome/browser/media/router/offscreen_presentation_manager_factory.cc b/chrome/browser/media/router/offscreen_presentation_manager_factory.cc
deleted file mode 100644
index 3dda0733..0000000
--- a/chrome/browser/media/router/offscreen_presentation_manager_factory.cc
+++ /dev/null
@@ -1,65 +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 "chrome/browser/media/router/offscreen_presentation_manager_factory.h"
-
-#include "base/lazy_instance.h"
-
-#include "chrome/browser/media/router/offscreen_presentation_manager.h"
-#include "chrome/browser/profiles/incognito_helpers.h"
-#include "chrome/browser/profiles/profile.h"
-#include "components/keyed_service/content/browser_context_dependency_manager.h"
-#include "content/public/browser/web_contents.h"
-
-namespace media_router {
-
-namespace {
-
-base::LazyInstance<OffscreenPresentationManagerFactory>::DestructorAtExit
-    service_factory = LAZY_INSTANCE_INITIALIZER;
-
-}  // namespace
-
-// static
-OffscreenPresentationManager*
-OffscreenPresentationManagerFactory::GetOrCreateForWebContents(
-    content::WebContents* web_contents) {
-  DCHECK(web_contents);
-  return OffscreenPresentationManagerFactory::GetOrCreateForBrowserContext(
-      web_contents->GetBrowserContext());
-}
-
-// static
-OffscreenPresentationManager*
-OffscreenPresentationManagerFactory::GetOrCreateForBrowserContext(
-    content::BrowserContext* context) {
-  DCHECK(context);
-  return static_cast<OffscreenPresentationManager*>(
-      service_factory.Get().GetServiceForBrowserContext(context, true));
-}
-
-// static
-OffscreenPresentationManagerFactory*
-OffscreenPresentationManagerFactory::GetInstanceForTest() {
-  return &service_factory.Get();
-}
-
-OffscreenPresentationManagerFactory::OffscreenPresentationManagerFactory()
-    : BrowserContextKeyedServiceFactory(
-          "OffscreenPresentationManager",
-          BrowserContextDependencyManager::GetInstance()) {}
-
-OffscreenPresentationManagerFactory::~OffscreenPresentationManagerFactory() {}
-
-content::BrowserContext*
-OffscreenPresentationManagerFactory::GetBrowserContextToUse(
-    content::BrowserContext* context) const {
-  return chrome::GetBrowserContextRedirectedInIncognito(context);
-}
-KeyedService* OffscreenPresentationManagerFactory::BuildServiceInstanceFor(
-    content::BrowserContext* context) const {
-  return new OffscreenPresentationManager;
-}
-
-}  // namespace media_router
diff --git a/chrome/browser/media/router/offscreen_presentation_manager_factory.h b/chrome/browser/media/router/offscreen_presentation_manager_factory.h
deleted file mode 100644
index 97a3eea..0000000
--- a/chrome/browser/media/router/offscreen_presentation_manager_factory.h
+++ /dev/null
@@ -1,55 +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.
-
-#ifndef CHROME_BROWSER_MEDIA_ROUTER_OFFSCREEN_PRESENTATION_MANAGER_FACTORY_H_
-#define CHROME_BROWSER_MEDIA_ROUTER_OFFSCREEN_PRESENTATION_MANAGER_FACTORY_H_
-
-#include "base/lazy_instance.h"
-#include "components/keyed_service/content/browser_context_keyed_service_factory.h"
-
-namespace content {
-class BrowserContext;
-class WebContents;
-}
-
-namespace media_router {
-
-class OffscreenPresentationManager;
-
-// OffscreenPresentation manager is shared between a Profile and
-// its associated incognito Profiles.
-class OffscreenPresentationManagerFactory
-    : public BrowserContextKeyedServiceFactory {
- public:
-  // If |web_contents| is normal profile, use it as browser context;
-  // If |web_contents| is incognito profile, |GetBrowserContextToUse| will
-  // redirect incognito profile to original profile, and use original one as
-  // browser context.
-  static OffscreenPresentationManager* GetOrCreateForWebContents(
-      content::WebContents* web_contents);
-  static OffscreenPresentationManager* GetOrCreateForBrowserContext(
-      content::BrowserContext* context);
-
-  // For test use only.
-  static OffscreenPresentationManagerFactory* GetInstanceForTest();
-
- private:
-  friend struct base::LazyInstanceTraitsBase<
-      OffscreenPresentationManagerFactory>;
-
-  OffscreenPresentationManagerFactory();
-  ~OffscreenPresentationManagerFactory() override;
-
-  // BrowserContextKeyedServiceFactory interface.
-  content::BrowserContext* GetBrowserContextToUse(
-      content::BrowserContext* context) const override;
-  KeyedService* BuildServiceInstanceFor(
-      content::BrowserContext* context) const override;
-
-  DISALLOW_COPY_AND_ASSIGN(OffscreenPresentationManagerFactory);
-};
-
-}  // namespace media_router
-
-#endif  // CHROME_BROWSER_MEDIA_ROUTER_OFFSCREEN_PRESENTATION_MANAGER_FACTORY_H_
diff --git a/chrome/browser/media/router/offscreen_presentation_manager_factory_unittest.cc b/chrome/browser/media/router/offscreen_presentation_manager_factory_unittest.cc
deleted file mode 100644
index 4d69630..0000000
--- a/chrome/browser/media/router/offscreen_presentation_manager_factory_unittest.cc
+++ /dev/null
@@ -1,50 +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 <memory>
-
-#include "chrome/browser/media/router/offscreen_presentation_manager_factory.h"
-#include "chrome/test/base/testing_profile.h"
-#include "content/public/browser/browser_context.h"
-#include "content/public/test/test_browser_thread_bundle.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace media_router {
-
-class OffscreenPresentationManagerFactoryTest : public testing::Test {
- protected:
-  OffscreenPresentationManagerFactoryTest() {}
-  ~OffscreenPresentationManagerFactoryTest() override {}
-
-  Profile* profile() { return &profile_; }
-
- private:
-  content::TestBrowserThreadBundle thread_bundle_;
-  TestingProfile profile_;
-};
-
-TEST_F(OffscreenPresentationManagerFactoryTest, CreateForRegularProfile) {
-  ASSERT_TRUE(OffscreenPresentationManagerFactory::GetOrCreateForBrowserContext(
-      profile()));
-}
-
-TEST_F(OffscreenPresentationManagerFactoryTest, CreateForOffTheRecordProfile) {
-  Profile* incognito_profile = profile()->GetOffTheRecordProfile();
-  ASSERT_TRUE(incognito_profile);
-
-  // Makes sure a OffscreenPresentationManager can be created from an incognito
-  // Profile.
-  OffscreenPresentationManager* manager =
-      OffscreenPresentationManagerFactory::GetOrCreateForBrowserContext(
-          incognito_profile);
-  ASSERT_TRUE(manager);
-
-  // A Profile and its incognito Profile share the same
-  // OffscreenPresentationManager instance.
-  ASSERT_EQ(manager,
-            OffscreenPresentationManagerFactory::GetOrCreateForBrowserContext(
-                profile()));
-}
-
-}  // namespace media_router
diff --git a/chrome/browser/media/router/offscreen_presentation_manager_unittest.cc b/chrome/browser/media/router/offscreen_presentation_manager_unittest.cc
deleted file mode 100644
index 892a39e..0000000
--- a/chrome/browser/media/router/offscreen_presentation_manager_unittest.cc
+++ /dev/null
@@ -1,334 +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 <vector>
-
-#include "base/bind.h"
-#include "base/stl_util.h"
-#include "chrome/browser/media/router/offscreen_presentation_manager.h"
-#include "chrome/browser/media/router/test_helper.h"
-#include "testing/gmock/include/gmock/gmock.h"
-#include "testing/gtest/include/gtest/gtest.h"
-#include "url/gurl.h"
-
-using testing::_;
-
-namespace media_router {
-
-namespace {
-const char kPresentationId[] = "presentationId";
-const char kPresentationId2[] = "presentationId2";
-const char kPresentationUrl[] = "http://www.example.com/presentation.html";
-}  // namespace
-
-class MockReceiverConnectionAvailableCallback {
- public:
-  void OnReceiverConnectionAvailable(
-      const content::PresentationInfo& presentation_info,
-      content::PresentationConnectionPtr controller_conn,
-      content::PresentationConnectionRequest receiver_conn_request) {
-    OnReceiverConnectionAvailableRaw(presentation_info, controller_conn.get());
-  }
-
-  MOCK_METHOD2(OnReceiverConnectionAvailableRaw,
-               void(const content::PresentationInfo&,
-                    blink::mojom::PresentationConnection*));
-};
-
-class OffscreenPresentationManagerTest : public ::testing::Test {
- public:
-  OffscreenPresentationManagerTest()
-      : render_frame_host_id_(1, 1),
-        presentation_info_(GURL(kPresentationUrl), kPresentationId),
-        route_("route_1",
-               MediaSource("source_1"),
-               "sink_1",
-               "",
-               false,
-               "",
-               false) {}
-
-  OffscreenPresentationManager* manager() { return &manager_; }
-
-  void VerifyPresentationsSize(size_t expected) {
-    EXPECT_EQ(expected, manager_.offscreen_presentations_.size());
-  }
-
-  void VerifyControllerSize(size_t expected,
-                            const std::string& presentationId) {
-    EXPECT_TRUE(
-        base::ContainsKey(manager_.offscreen_presentations_, presentationId));
-    EXPECT_EQ(expected, manager_.offscreen_presentations_[presentationId]
-                            ->pending_controllers_.size());
-  }
-
-  void RegisterController(const std::string& presentation_id,
-                          content::PresentationConnectionPtr controller) {
-    RegisterController(
-        content::PresentationInfo(GURL(kPresentationUrl), presentation_id),
-        render_frame_host_id_, std::move(controller));
-  }
-
-  void RegisterController(const RenderFrameHostId& render_frame_id,
-                          content::PresentationConnectionPtr controller) {
-    RegisterController(presentation_info_, render_frame_id,
-                       std::move(controller));
-  }
-
-  void RegisterController(content::PresentationConnectionPtr controller) {
-    RegisterController(presentation_info_, render_frame_host_id_,
-                       std::move(controller));
-  }
-
-  void RegisterController(const content::PresentationInfo& presentation_info,
-                          const RenderFrameHostId& render_frame_id,
-                          content::PresentationConnectionPtr controller) {
-    content::PresentationConnectionRequest receiver_conn_request;
-    manager()->RegisterOffscreenPresentationController(
-        presentation_info, render_frame_id, std::move(controller),
-        std::move(receiver_conn_request), route_);
-  }
-
-  void RegisterReceiver(
-      MockReceiverConnectionAvailableCallback& receiver_callback) {
-    RegisterReceiver(kPresentationId, receiver_callback);
-  }
-
-  void RegisterReceiver(
-      const std::string& presentation_id,
-      MockReceiverConnectionAvailableCallback& receiver_callback) {
-    manager()->OnOffscreenPresentationReceiverCreated(
-        content::PresentationInfo(GURL(kPresentationUrl), presentation_id),
-        base::Bind(&MockReceiverConnectionAvailableCallback::
-                       OnReceiverConnectionAvailable,
-                   base::Unretained(&receiver_callback)));
-  }
-
-  void UnregisterController(const RenderFrameHostId& render_frame_id) {
-    manager()->UnregisterOffscreenPresentationController(kPresentationId,
-                                                         render_frame_id);
-  }
-
-  void UnregisterController() {
-    manager()->UnregisterOffscreenPresentationController(kPresentationId,
-                                                         render_frame_host_id_);
-  }
-
-  void UnregisterReceiver() {
-    manager()->OnOffscreenPresentationReceiverTerminated(kPresentationId);
-  }
-
- private:
-  const RenderFrameHostId render_frame_host_id_;
-  const content::PresentationInfo presentation_info_;
-  OffscreenPresentationManager manager_;
-  MediaRoute route_;
-};
-
-TEST_F(OffscreenPresentationManagerTest, RegisterUnregisterController) {
-  content::PresentationConnectionPtr controller;
-  RegisterController(std::move(controller));
-  VerifyPresentationsSize(1);
-  UnregisterController();
-  VerifyPresentationsSize(0);
-}
-
-TEST_F(OffscreenPresentationManagerTest, RegisterUnregisterReceiver) {
-  MockReceiverConnectionAvailableCallback receiver_callback;
-  RegisterReceiver(receiver_callback);
-  VerifyPresentationsSize(1);
-  UnregisterReceiver();
-  VerifyPresentationsSize(0);
-}
-
-TEST_F(OffscreenPresentationManagerTest, UnregisterNonexistentController) {
-  UnregisterController();
-  VerifyPresentationsSize(0);
-}
-
-TEST_F(OffscreenPresentationManagerTest, UnregisterNonexistentReceiver) {
-  UnregisterReceiver();
-  VerifyPresentationsSize(0);
-}
-
-TEST_F(OffscreenPresentationManagerTest,
-       RegisterMultipleControllersSamePresentation) {
-  content::PresentationConnectionPtr controller1;
-  RegisterController(RenderFrameHostId(1, 1), std::move(controller1));
-  content::PresentationConnectionPtr controller2;
-  RegisterController(RenderFrameHostId(1, 2), std::move(controller2));
-  VerifyPresentationsSize(1);
-}
-
-TEST_F(OffscreenPresentationManagerTest,
-       RegisterMultipleControllersDifferentPresentations) {
-  content::PresentationConnectionPtr controller1;
-  RegisterController(kPresentationId, std::move(controller1));
-  content::PresentationConnectionPtr controller2;
-  RegisterController(kPresentationId2, std::move(controller2));
-  VerifyPresentationsSize(2);
-}
-
-TEST_F(OffscreenPresentationManagerTest,
-       RegisterControllerThenReceiverInvokesCallback) {
-  content::PresentationConnectionPtr controller;
-  MockReceiverConnectionAvailableCallback receiver_callback;
-
-  VerifyPresentationsSize(0);
-
-  RegisterController(std::move(controller));
-  EXPECT_CALL(receiver_callback, OnReceiverConnectionAvailableRaw(_, _));
-  RegisterReceiver(receiver_callback);
-}
-
-TEST_F(OffscreenPresentationManagerTest,
-       UnregisterReceiverFromConnectedPresentation) {
-  content::PresentationConnectionPtr controller;
-  MockReceiverConnectionAvailableCallback receiver_callback;
-
-  VerifyPresentationsSize(0);
-
-  RegisterController(std::move(controller));
-  EXPECT_CALL(receiver_callback, OnReceiverConnectionAvailableRaw(_, _));
-  RegisterReceiver(receiver_callback);
-  UnregisterReceiver();
-
-  VerifyPresentationsSize(0);
-}
-
-TEST_F(OffscreenPresentationManagerTest,
-       UnregisterControllerFromConnectedPresentation) {
-  content::PresentationConnectionPtr controller;
-  MockReceiverConnectionAvailableCallback receiver_callback;
-
-  VerifyPresentationsSize(0);
-
-  RegisterController(std::move(controller));
-  EXPECT_CALL(receiver_callback, OnReceiverConnectionAvailableRaw(_, _));
-  RegisterReceiver(receiver_callback);
-  UnregisterController();
-
-  VerifyPresentationsSize(1);
-}
-
-TEST_F(OffscreenPresentationManagerTest,
-       UnregisterReceiverThenControllerFromConnectedPresentation) {
-  content::PresentationConnectionPtr controller;
-  MockReceiverConnectionAvailableCallback receiver_callback;
-
-  VerifyPresentationsSize(0);
-
-  RegisterController(std::move(controller));
-  EXPECT_CALL(receiver_callback, OnReceiverConnectionAvailableRaw(_, _));
-  RegisterReceiver(receiver_callback);
-  UnregisterReceiver();
-  UnregisterController();
-
-  VerifyPresentationsSize(0);
-}
-
-TEST_F(OffscreenPresentationManagerTest,
-       UnregisterControllerThenReceiverFromConnectedPresentation) {
-  content::PresentationConnectionPtr controller;
-  MockReceiverConnectionAvailableCallback receiver_callback;
-
-  VerifyPresentationsSize(0);
-
-  RegisterController(std::move(controller));
-  EXPECT_CALL(receiver_callback, OnReceiverConnectionAvailableRaw(_, _));
-  RegisterReceiver(receiver_callback);
-  UnregisterController();
-  UnregisterReceiver();
-
-  VerifyPresentationsSize(0);
-}
-
-TEST_F(OffscreenPresentationManagerTest,
-       RegisterTwoControllersThenReceiverInvokesCallbackTwice) {
-  content::PresentationConnectionPtr controller1;
-  RegisterController(RenderFrameHostId(1, 1), std::move(controller1));
-  content::PresentationConnectionPtr controller2;
-  RegisterController(RenderFrameHostId(1, 2), std::move(controller2));
-
-  MockReceiverConnectionAvailableCallback receiver_callback;
-  EXPECT_CALL(receiver_callback, OnReceiverConnectionAvailableRaw(_, _))
-      .Times(2);
-  RegisterReceiver(receiver_callback);
-}
-
-TEST_F(OffscreenPresentationManagerTest,
-       RegisterControllerReceiverConontrollerInvokesCallbackTwice) {
-  content::PresentationConnectionPtr controller1;
-  RegisterController(RenderFrameHostId(1, 1), std::move(controller1));
-
-  MockReceiverConnectionAvailableCallback receiver_callback;
-  EXPECT_CALL(receiver_callback, OnReceiverConnectionAvailableRaw(_, _))
-      .Times(2);
-  RegisterReceiver(receiver_callback);
-
-  content::PresentationConnectionPtr controller2;
-  RegisterController(RenderFrameHostId(1, 2), std::move(controller2));
-}
-
-TEST_F(OffscreenPresentationManagerTest,
-       UnregisterFirstControllerFromeConnectedPresentation) {
-  content::PresentationConnectionPtr controller1;
-  RegisterController(RenderFrameHostId(1, 1), std::move(controller1));
-  content::PresentationConnectionPtr controller2;
-  RegisterController(RenderFrameHostId(1, 2), std::move(controller2));
-
-  MockReceiverConnectionAvailableCallback receiver_callback;
-  EXPECT_CALL(receiver_callback, OnReceiverConnectionAvailableRaw(_, _))
-      .Times(2);
-  RegisterReceiver(receiver_callback);
-  UnregisterController(RenderFrameHostId(1, 1));
-  UnregisterController(RenderFrameHostId(1, 1));
-
-  VerifyPresentationsSize(1);
-}
-
-TEST_F(OffscreenPresentationManagerTest, TwoPresentations) {
-  content::PresentationConnectionPtr controller1;
-  RegisterController(kPresentationId, std::move(controller1));
-
-  MockReceiverConnectionAvailableCallback receiver_callback1;
-  EXPECT_CALL(receiver_callback1, OnReceiverConnectionAvailableRaw(_, _))
-      .Times(1);
-  RegisterReceiver(kPresentationId, receiver_callback1);
-
-  content::PresentationConnectionPtr controller2;
-  RegisterController(kPresentationId2, std::move(controller2));
-
-  MockReceiverConnectionAvailableCallback receiver_callback2;
-  EXPECT_CALL(receiver_callback2, OnReceiverConnectionAvailableRaw(_, _))
-      .Times(1);
-  RegisterReceiver(kPresentationId2, receiver_callback2);
-
-  VerifyPresentationsSize(2);
-
-  UnregisterReceiver();
-  VerifyPresentationsSize(1);
-}
-
-TEST_F(OffscreenPresentationManagerTest, TestIsOffscreenPresentation) {
-  EXPECT_FALSE(manager()->IsOffscreenPresentation(kPresentationId));
-  content::PresentationConnectionPtr controller1;
-  RegisterController(kPresentationId, std::move(controller1));
-  EXPECT_TRUE(manager()->IsOffscreenPresentation(kPresentationId));
-}
-
-TEST_F(OffscreenPresentationManagerTest, TestRegisterAndGetRoute) {
-  MediaSource source("source_1");
-  MediaRoute route("route_1", source, "sink_1", "", false, "", false);
-
-  EXPECT_FALSE(manager()->GetRoute(kPresentationId));
-  content::PresentationConnectionPtr controller;
-  RegisterController(std::move(controller));
-
-  auto* actual_route = manager()->GetRoute(kPresentationId);
-  EXPECT_TRUE(actual_route);
-  EXPECT_TRUE(route.Equals(*actual_route));
-}
-
-}  // namespace media_router
diff --git a/chrome/browser/media/router/presentation_service_delegate_impl.cc b/chrome/browser/media/router/presentation_service_delegate_impl.cc
index 741f5eb1..43f8f180 100644
--- a/chrome/browser/media/router/presentation_service_delegate_impl.cc
+++ b/chrome/browser/media/router/presentation_service_delegate_impl.cc
@@ -14,12 +14,12 @@
 #include "base/memory/ptr_util.h"
 #include "base/strings/string_util.h"
 #include "chrome/browser/media/router/browser_presentation_connection_proxy.h"
+#include "chrome/browser/media/router/local_presentation_manager.h"
+#include "chrome/browser/media/router/local_presentation_manager_factory.h"
 #include "chrome/browser/media/router/media_router.h"
 #include "chrome/browser/media/router/media_router_dialog_controller.h"
 #include "chrome/browser/media/router/media_router_factory.h"
 #include "chrome/browser/media/router/media_router_metrics.h"
-#include "chrome/browser/media/router/offscreen_presentation_manager.h"
-#include "chrome/browser/media/router/offscreen_presentation_manager_factory.h"
 #include "chrome/browser/media/router/presentation_media_sinks_observer.h"
 #include "chrome/browser/media/router/route_message_observer.h"
 #include "chrome/browser/sessions/session_tab_helper.h"
@@ -198,11 +198,11 @@
 
 void PresentationFrame::Reset() {
   for (const auto& pid_route : presentation_id_to_route_) {
-    if (pid_route.second.is_offscreen_presentation()) {
-      auto* offscreen_presentation_manager =
-          OffscreenPresentationManagerFactory::GetOrCreateForWebContents(
+    if (pid_route.second.is_local_presentation()) {
+      auto* local_presentation_manager =
+          LocalPresentationManagerFactory::GetOrCreateForWebContents(
               web_contents_);
-      offscreen_presentation_manager->UnregisterOffscreenPresentationController(
+      local_presentation_manager->UnregisterLocalPresentationController(
           pid_route.first, render_frame_host_id_);
     } else {
       router_->DetachRoute(pid_route.second.media_route_id());
@@ -234,11 +234,11 @@
     return;
   }
 
-  if (pid_route_it->second.is_offscreen_presentation()) {
-    auto* offscreen_presentation_manager =
-        OffscreenPresentationManagerFactory::GetOrCreateForWebContents(
+  if (pid_route_it->second.is_local_presentation()) {
+    auto* local_presentation_manager =
+        LocalPresentationManagerFactory::GetOrCreateForWebContents(
             web_contents_);
-    offscreen_presentation_manager->RegisterOffscreenPresentationController(
+    local_presentation_manager->RegisterLocalPresentationController(
         presentation_info, render_frame_host_id_,
         std::move(controller_connection_ptr),
         std::move(receiver_connection_request), pid_route_it->second);
@@ -507,13 +507,11 @@
   }
 #endif  // !defined(OS_ANDROID)
 
-  auto* offscreen_presentation_manager =
-      OffscreenPresentationManagerFactory::GetOrCreateForWebContents(
-          web_contents_);
-  // Check offscreen presentation across frames.
-  if (offscreen_presentation_manager->IsOffscreenPresentation(
-          presentation_id)) {
-    auto* route = offscreen_presentation_manager->GetRoute(presentation_id);
+  auto* local_presentation_manager =
+      LocalPresentationManagerFactory::GetOrCreateForWebContents(web_contents_);
+  // Check local presentation across frames.
+  if (local_presentation_manager->IsLocalPresentation(presentation_id)) {
+    auto* route = local_presentation_manager->GetRoute(presentation_id);
 
     if (!route) {
       LOG(WARNING) << "No route found for [presentation_id]: "
@@ -558,13 +556,11 @@
     return;
   }
 
-  auto* offscreen_presentation_manager =
-      OffscreenPresentationManagerFactory::GetOrCreateForWebContents(
-          web_contents_);
+  auto* local_presentation_manager =
+      LocalPresentationManagerFactory::GetOrCreateForWebContents(web_contents_);
 
-  if (offscreen_presentation_manager->IsOffscreenPresentation(
-          presentation_id)) {
-    offscreen_presentation_manager->UnregisterOffscreenPresentationController(
+  if (local_presentation_manager->IsLocalPresentation(presentation_id)) {
+    local_presentation_manager->UnregisterLocalPresentationController(
         presentation_id, rfh_id);
   } else {
     router_->DetachRoute(route_id);
diff --git a/chrome/browser/media/router/presentation_service_delegate_impl.h b/chrome/browser/media/router/presentation_service_delegate_impl.h
index d5e14b2..8a822644 100644
--- a/chrome/browser/media/router/presentation_service_delegate_impl.h
+++ b/chrome/browser/media/router/presentation_service_delegate_impl.h
@@ -167,9 +167,9 @@
   FRIEND_TEST_ALL_PREFIXES(PresentationServiceDelegateImplTest,
                            DefaultPresentationUrlCallback);
   FRIEND_TEST_ALL_PREFIXES(PresentationServiceDelegateImplTest,
-                           TestCloseConnectionForOffscreenPresentation);
+                           TestCloseConnectionForLocalPresentation);
   FRIEND_TEST_ALL_PREFIXES(PresentationServiceDelegateImplTest,
-                           ConnectToOffscreenPresentation);
+                           ConnectToLocalPresentation);
   FRIEND_TEST_ALL_PREFIXES(PresentationServiceDelegateImplTest,
                            ConnectToPresentation);
 
diff --git a/chrome/browser/media/router/presentation_service_delegate_impl_unittest.cc b/chrome/browser/media/router/presentation_service_delegate_impl_unittest.cc
index b04bf81..330e4aec 100644
--- a/chrome/browser/media/router/presentation_service_delegate_impl_unittest.cc
+++ b/chrome/browser/media/router/presentation_service_delegate_impl_unittest.cc
@@ -6,10 +6,10 @@
 
 #include "base/memory/ptr_util.h"
 #include "base/test/mock_callback.h"
+#include "chrome/browser/media/router/local_presentation_manager.h"
+#include "chrome/browser/media/router/local_presentation_manager_factory.h"
 #include "chrome/browser/media/router/mock_media_router.h"
 #include "chrome/browser/media/router/mock_screen_availability_listener.h"
-#include "chrome/browser/media/router/offscreen_presentation_manager.h"
-#include "chrome/browser/media/router/offscreen_presentation_manager_factory.h"
 #include "chrome/browser/media/router/test_helper.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/common/media_router/media_source.h"
@@ -79,39 +79,38 @@
                void(const content::PresentationError& error));
 };
 
-class MockOffscreenPresentationManager : public OffscreenPresentationManager {
+class MockLocalPresentationManager : public LocalPresentationManager {
  public:
-  void RegisterOffscreenPresentationController(
+  void RegisterLocalPresentationController(
       const content::PresentationInfo& presentation_info,
       const RenderFrameHostId& render_frame_id,
       content::PresentationConnectionPtr controller,
       content::PresentationConnectionRequest,
       const MediaRoute& route) override {
-    RegisterOffscreenPresentationController(presentation_info, render_frame_id,
-                                            route);
+    RegisterLocalPresentationController(presentation_info, render_frame_id,
+                                        route);
   }
 
-  MOCK_METHOD3(RegisterOffscreenPresentationController,
+  MOCK_METHOD3(RegisterLocalPresentationController,
                void(const content::PresentationInfo& presentation_info,
                     const RenderFrameHostId& render_frame_id,
                     const MediaRoute& route));
-  MOCK_METHOD2(UnregisterOffscreenPresentationController,
+  MOCK_METHOD2(UnregisterLocalPresentationController,
                void(const std::string& presentation_id,
                     const RenderFrameHostId& render_frame_id));
-  MOCK_METHOD2(OnOffscreenPresentationReceiverCreated,
+  MOCK_METHOD2(OnLocalPresentationReceiverCreated,
                void(const content::PresentationInfo& presentation_info,
                     const content::ReceiverConnectionAvailableCallback&
                         receiver_callback));
-  MOCK_METHOD1(OnOffscreenPresentationReceiverTerminated,
+  MOCK_METHOD1(OnLocalPresentationReceiverTerminated,
                void(const std::string& presentation_id));
-  MOCK_METHOD1(IsOffscreenPresentation,
-               bool(const std::string& presentation_id));
+  MOCK_METHOD1(IsLocalPresentation, bool(const std::string& presentation_id));
   MOCK_METHOD1(GetRoute, MediaRoute*(const std::string& presentation_id));
 };
 
-std::unique_ptr<KeyedService> BuildMockOffscreenPresentationManager(
+std::unique_ptr<KeyedService> BuildMockLocalPresentationManager(
     content::BrowserContext* context) {
-  return base::MakeUnique<MockOffscreenPresentationManager>();
+  return base::MakeUnique<MockLocalPresentationManager>();
 }
 
 class PresentationServiceDelegateImplTest
@@ -140,7 +139,7 @@
     presentation_request_ = base::MakeUnique<content::PresentationRequest>(
         RenderFrameHostId(main_frame_process_id_, main_frame_routing_id_),
         presentation_urls_, frame_origin_);
-    SetMockOffscreenPresentationManager();
+    SetMockLocalPresentationManager();
   }
 
   MOCK_METHOD1(OnDefaultPresentationStarted,
@@ -149,8 +148,8 @@
  protected:
   virtual content::WebContents* GetWebContents() { return web_contents(); }
 
-  MockOffscreenPresentationManager& GetMockOffscreenPresentationManager() {
-    return *mock_offscreen_manager_;
+  MockLocalPresentationManager& GetMockLocalPresentationManager() {
+    return *mock_local_manager_;
   }
 
   void RunDefaultPresentationUrlCallbackTest(bool incognito) {
@@ -197,11 +196,11 @@
     main_frame_routing_id_ = main_frame->GetRoutingID();
   }
 
-  void SetMockOffscreenPresentationManager() {
-    OffscreenPresentationManagerFactory::GetInstanceForTest()
-        ->SetTestingFactory(profile(), &BuildMockOffscreenPresentationManager);
-    mock_offscreen_manager_ = static_cast<MockOffscreenPresentationManager*>(
-        OffscreenPresentationManagerFactory::GetOrCreateForBrowserContext(
+  void SetMockLocalPresentationManager() {
+    LocalPresentationManagerFactory::GetInstanceForTest()->SetTestingFactory(
+        profile(), &BuildMockLocalPresentationManager);
+    mock_local_manager_ = static_cast<MockLocalPresentationManager*>(
+        LocalPresentationManagerFactory::GetOrCreateForBrowserContext(
             profile()));
   }
 
@@ -212,7 +211,7 @@
   std::vector<GURL> presentation_urls_;
   const GURL frame_url_;
   const url::Origin frame_origin_;
-  MockOffscreenPresentationManager* mock_offscreen_manager_;
+  MockLocalPresentationManager* mock_local_manager_;
 
   // |source1_| and |source2_| correspond to |presentation_url1_| and
   // |presentation_url2_|, respectively.
@@ -435,8 +434,8 @@
   const std::string kPresentationId("pid");
   presentation_urls_.push_back(GURL(kPresentationUrl3));
 
-  auto& mock_offscreen_manager = GetMockOffscreenPresentationManager();
-  EXPECT_CALL(mock_offscreen_manager, IsOffscreenPresentation(kPresentationId))
+  auto& mock_local_manager = GetMockLocalPresentationManager();
+  EXPECT_CALL(mock_local_manager, IsLocalPresentation(kPresentationId))
       .WillRepeatedly(Return(false));
 
   MockCreatePresentationConnnectionCallbacks mock_create_connection_callbacks;
@@ -509,7 +508,7 @@
 }
 
 TEST_F(PresentationServiceDelegateImplTest,
-       TestCloseConnectionForOffscreenPresentation) {
+       TestCloseConnectionForLocalPresentation) {
   GURL presentation_url = GURL("http://www.example.com/presentation.html");
   content::PresentationInfo presentation_info(presentation_url,
                                               kPresentationId);
@@ -517,10 +516,10 @@
   MediaRoute media_route("route_id",
                          MediaSourceForPresentationUrl(presentation_url),
                          "mediaSinkId", "", true, "", true);
-  media_route.set_offscreen_presentation(true);
+  media_route.set_local_presentation(true);
 
-  auto& mock_offscreen_manager = GetMockOffscreenPresentationManager();
-  EXPECT_CALL(mock_offscreen_manager, IsOffscreenPresentation(kPresentationId))
+  auto& mock_local_manager = GetMockLocalPresentationManager();
+  EXPECT_CALL(mock_local_manager, IsLocalPresentation(kPresentationId))
       .WillRepeatedly(Return(true));
 
   base::MockCallback<content::PresentationConnectionCallback> success_cb;
@@ -529,8 +528,8 @@
   delegate_impl_->OnStartPresentationSucceeded(rfh_id, success_cb.Get(),
                                                presentation_info, media_route);
 
-  EXPECT_CALL(mock_offscreen_manager, UnregisterOffscreenPresentationController(
-                                          kPresentationId, rfh_id))
+  EXPECT_CALL(mock_local_manager,
+              UnregisterLocalPresentationController(kPresentationId, rfh_id))
       .Times(1);
   EXPECT_CALL(router_, DetachRoute(_)).Times(0);
 
@@ -539,23 +538,23 @@
 }
 
 TEST_F(PresentationServiceDelegateImplTest,
-       TestReconnectPresentationForOffscreenPresentation) {
+       TestReconnectPresentationForLocalPresentation) {
   MediaRoute media_route("route_id",
                          MediaSourceForPresentationUrl(presentation_url1_),
                          "mediaSinkId", "", true, "", true);
-  media_route.set_offscreen_presentation(true);
+  media_route.set_local_presentation(true);
 
-  auto& mock_offscreen_manager = GetMockOffscreenPresentationManager();
-  EXPECT_CALL(mock_offscreen_manager, IsOffscreenPresentation(kPresentationId))
+  auto& mock_local_manager = GetMockLocalPresentationManager();
+  EXPECT_CALL(mock_local_manager, IsLocalPresentation(kPresentationId))
       .WillRepeatedly(Return(true));
-  EXPECT_CALL(mock_offscreen_manager, GetRoute(kPresentationId))
+  EXPECT_CALL(mock_local_manager, GetRoute(kPresentationId))
       .WillRepeatedly(Return(&media_route));
 
   base::MockCallback<content::PresentationConnectionCallback> success_cb;
   base::MockCallback<content::PresentationConnectionErrorCallback> error_cb;
   EXPECT_CALL(success_cb, Run(_));
-  EXPECT_CALL(mock_offscreen_manager,
-              UnregisterOffscreenPresentationController(
+  EXPECT_CALL(mock_local_manager,
+              UnregisterLocalPresentationController(
                   kPresentationId, RenderFrameHostId(main_frame_process_id_,
                                                      main_frame_routing_id_)));
 
@@ -564,7 +563,7 @@
   delegate_impl_->Reset(main_frame_process_id_, main_frame_routing_id_);
 }
 
-TEST_F(PresentationServiceDelegateImplTest, ConnectToOffscreenPresentation) {
+TEST_F(PresentationServiceDelegateImplTest, ConnectToLocalPresentation) {
   RenderFrameHostId rfh_id(main_frame_process_id_, main_frame_routing_id_);
   content::PresentationInfo presentation_info(presentation_url1_,
                                               kPresentationId);
@@ -573,7 +572,7 @@
       "route_id",
       MediaSourceForPresentationUrl(presentation_info.presentation_url),
       "mediaSinkId", "", true, "", true);
-  media_route.set_offscreen_presentation(true);
+  media_route.set_local_presentation(true);
 
   base::MockCallback<content::PresentationConnectionCallback> success_cb;
   EXPECT_CALL(success_cb, Run(_));
@@ -581,10 +580,10 @@
   delegate_impl_->OnStartPresentationSucceeded(rfh_id, success_cb.Get(),
                                                presentation_info, media_route);
 
-  auto& mock_offscreen_manager = GetMockOffscreenPresentationManager();
-  EXPECT_CALL(mock_offscreen_manager,
-              RegisterOffscreenPresentationController(
-                  InfoEquals(presentation_info), rfh_id, Equals(media_route)));
+  auto& mock_local_manager = GetMockLocalPresentationManager();
+  EXPECT_CALL(mock_local_manager,
+              RegisterLocalPresentationController(InfoEquals(presentation_info),
+                                                  rfh_id, Equals(media_route)));
 
   content::PresentationConnectionPtr connection_ptr;
   content::PresentationConnectionRequest connection_request;
@@ -592,8 +591,8 @@
       main_frame_process_id_, main_frame_routing_id_, presentation_info,
       std::move(connection_ptr), std::move(connection_request));
 
-  EXPECT_CALL(mock_offscreen_manager, UnregisterOffscreenPresentationController(
-                                          kPresentationId, rfh_id));
+  EXPECT_CALL(mock_local_manager,
+              UnregisterLocalPresentationController(kPresentationId, rfh_id));
   EXPECT_CALL(router_, DetachRoute(_)).Times(0);
   delegate_impl_->Reset(main_frame_process_id_, main_frame_routing_id_);
 }
@@ -647,8 +646,8 @@
     update->AppendIfNotPresent(base::MakeUnique<base::Value>(origin));
   }
 
-  auto& mock_offscreen_manager = GetMockOffscreenPresentationManager();
-  EXPECT_CALL(mock_offscreen_manager, IsOffscreenPresentation(kPresentationId))
+  auto& mock_local_manager = GetMockLocalPresentationManager();
+  EXPECT_CALL(mock_local_manager, IsLocalPresentation(kPresentationId))
       .WillRepeatedly(Return(false));
 
   // Auto-join requests should be rejected.
@@ -700,8 +699,8 @@
     update->AppendIfNotPresent(base::MakeUnique<base::Value>(origin));
   }
 
-  auto& mock_offscreen_manager = GetMockOffscreenPresentationManager();
-  EXPECT_CALL(mock_offscreen_manager, IsOffscreenPresentation(kPresentationId))
+  auto& mock_local_manager = GetMockLocalPresentationManager();
+  EXPECT_CALL(mock_local_manager, IsLocalPresentation(kPresentationId))
       .WillRepeatedly(Return(false));
 
   // Setting the pref in incognito shouldn't set it for the non-incognito
diff --git a/chrome/browser/media/router/receiver_presentation_service_delegate_impl.cc b/chrome/browser/media/router/receiver_presentation_service_delegate_impl.cc
index 71985066..a6230a8e6 100644
--- a/chrome/browser/media/router/receiver_presentation_service_delegate_impl.cc
+++ b/chrome/browser/media/router/receiver_presentation_service_delegate_impl.cc
@@ -5,8 +5,8 @@
 #include "chrome/browser/media/router/receiver_presentation_service_delegate_impl.h"
 
 #include "base/memory/ptr_util.h"
-#include "chrome/browser/media/router/offscreen_presentation_manager.h"
-#include "chrome/browser/media/router/offscreen_presentation_manager_factory.h"
+#include "chrome/browser/media/router/local_presentation_manager.h"
+#include "chrome/browser/media/router/local_presentation_manager_factory.h"
 
 DEFINE_WEB_CONTENTS_USER_DATA_KEY(
     media_router::ReceiverPresentationServiceDelegateImpl);
@@ -47,7 +47,7 @@
 void ReceiverPresentationServiceDelegateImpl::Reset(int render_process_id,
                                                     int render_frame_id) {
   DVLOG(2) << __FUNCTION__ << render_process_id << ", " << render_frame_id;
-  offscreen_presentation_manager_->OnOffscreenPresentationReceiverTerminated(
+  local_presentation_manager_->OnLocalPresentationReceiverTerminated(
       presentation_id_);
 }
 
@@ -56,19 +56,19 @@
                                             const std::string& presentation_id)
     : web_contents_(web_contents),
       presentation_id_(presentation_id),
-      offscreen_presentation_manager_(
-          OffscreenPresentationManagerFactory::GetOrCreateForWebContents(
+      local_presentation_manager_(
+          LocalPresentationManagerFactory::GetOrCreateForWebContents(
               web_contents_)) {
   DCHECK(web_contents_);
   DCHECK(!presentation_id.empty());
-  DCHECK(offscreen_presentation_manager_);
+  DCHECK(local_presentation_manager_);
 }
 
 void ReceiverPresentationServiceDelegateImpl::
     RegisterReceiverConnectionAvailableCallback(
         const content::ReceiverConnectionAvailableCallback&
             receiver_available_callback) {
-  offscreen_presentation_manager_->OnOffscreenPresentationReceiverCreated(
+  local_presentation_manager_->OnLocalPresentationReceiverCreated(
       content::PresentationInfo(web_contents_->GetLastCommittedURL(),
                                 presentation_id_),
       receiver_available_callback);
diff --git a/chrome/browser/media/router/receiver_presentation_service_delegate_impl.h b/chrome/browser/media/router/receiver_presentation_service_delegate_impl.h
index 5985fd3..2ecbaae 100644
--- a/chrome/browser/media/router/receiver_presentation_service_delegate_impl.h
+++ b/chrome/browser/media/router/receiver_presentation_service_delegate_impl.h
@@ -17,13 +17,15 @@
 
 namespace media_router {
 
-class OffscreenPresentationManager;
+class LocalPresentationManager;
 
-// Implements the receiver side of Presentation API for offscreen presentation.
-// Created with offscreen WebContents for an offscreen presentation. Each
-// instance is tied to a single offscreen presentation whose ID is given during
-// construction. As such, the receiver APIs are contextual with the offscreen
-// presentation. Only the main frame of the offscreen WebContents is allowed to
+// Implements the receiver side of Presentation API for local presentation
+// (an offscreen presentation that is mirrored to a wireless display, or a
+// presentation on a wired display).
+// Created with the WebContents for a local presentation. Each
+// instance is tied to a single local presentation whose ID is given during
+// construction. As such, the receiver APIs are contextual with the local
+// presentation. Only the main frame of the WebContents is allowed to
 // make receiver Presentation API requests; requests made from any other frame
 // will be rejected.
 class ReceiverPresentationServiceDelegateImpl
@@ -32,8 +34,8 @@
       public content::ReceiverPresentationServiceDelegate {
  public:
   // Creates an instance of ReceiverPresentationServiceDelegateImpl under
-  // |web_contents| and registers it as the receiver of the offscreen
-  // presentation |presentation_id| with OffscreenPresentationManager.
+  // |web_contents| and registers it as the receiver of the local
+  // presentation |presentation_id| with LocalPresentationManager.
   // No-op if a ReceiverPresentationServiceDelegateImpl instance already
   // exists under |web_contents|. This class does not take ownership of
   // |web_contents|.
@@ -63,8 +65,8 @@
 
   const std::string presentation_id_;
 
-  // This is an unowned pointer to the OffscreenPresentationManager.
-  OffscreenPresentationManager* const offscreen_presentation_manager_;
+  // This is an unowned pointer to the LocalPresentationManager.
+  LocalPresentationManager* const local_presentation_manager_;
 
   PresentationServiceDelegateObservers observers_;
 
diff --git a/chrome/browser/memory/swap_thrashing_monitor.cc b/chrome/browser/memory/swap_thrashing_monitor.cc
new file mode 100644
index 0000000..17a367a
--- /dev/null
+++ b/chrome/browser/memory/swap_thrashing_monitor.cc
@@ -0,0 +1,165 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/memory/swap_thrashing_monitor.h"
+
+#include "base/bind.h"
+#include "base/logging.h"
+#include "base/memory/ptr_util.h"
+#include "base/metrics/histogram_macros.h"
+#include "base/time/time.h"
+
+#if defined(OS_WIN)
+#include "chrome/browser/memory/swap_thrashing_monitor_delegate_win.h"
+#endif
+
+namespace memory {
+namespace {
+
+constexpr base::TimeDelta kSamplingInterval = base::TimeDelta::FromSeconds(2);
+
+// Enumeration of UMA swap thrashing levels. This needs to be kept in sync with
+// tools/metrics/histograms/enums.xml and the swap_thrashing levels defined in
+// swap_thrashing_common.h.
+//
+// These values are persisted to logs, and should therefore never be renumbered
+// nor reused
+enum SwapThrashingLevelUMA {
+  UMA_SWAP_THRASHING_LEVEL_NONE = 0,
+  UMA_SWAP_THRASHING_LEVEL_SUSPECTED = 1,
+  UMA_SWAP_THRASHING_LEVEL_CONFIRMED = 2,
+  // This must be the last value in the enum.
+  UMA_SWAP_THRASHING_LEVEL_COUNT,
+};
+
+// Enumeration of UMA swap thrashing level changes. This needs to be kept in
+// sync with tools/metrics/histograms/enums.xml.
+//
+// These values are persisted to logs, and should therefore never be renumbered
+// nor reused
+enum SwapThrashingLevelChangesUMA {
+  UMA_SWAP_THRASHING_LEVEL_CHANGE_NONE_TO_SUSPECTED = 0,
+  UMA_SWAP_THRASHING_LEVEL_CHANGE_SUSPECTED_TO_CONFIRMED = 1,
+  UMA_SWAP_THRASHING_LEVEL_CHANGE_CONFIRMED_TO_SUSPECTED = 2,
+  UMA_SWAP_THRASHING_LEVEL_CHANGE_SUSPECTED_TO_NONE = 3,
+  // This must be the last value in the enum.
+  UMA_SWAP_THRASHING_LEVEL_CHANGE_COUNT,
+};
+
+// Converts a swap thrashing level to an UMA enumeration value.
+SwapThrashingLevelUMA SwapThrashingLevelToUmaEnumValue(
+    SwapThrashingLevel level) {
+  switch (level) {
+    case SwapThrashingLevel::SWAP_THRASHING_LEVEL_NONE:
+      return UMA_SWAP_THRASHING_LEVEL_NONE;
+    case SwapThrashingLevel::SWAP_THRASHING_LEVEL_SUSPECTED:
+      return UMA_SWAP_THRASHING_LEVEL_SUSPECTED;
+    case SwapThrashingLevel::SWAP_THRASHING_LEVEL_CONFIRMED:
+      return UMA_SWAP_THRASHING_LEVEL_CONFIRMED;
+  }
+  NOTREACHED();
+  return UMA_SWAP_THRASHING_LEVEL_NONE;
+}
+
+}  // namespace
+
+// static
+void SwapThrashingMonitor::Initialize() {
+  GetInstance();
+}
+
+SwapThrashingMonitor* SwapThrashingMonitor::GetInstance() {
+  static SwapThrashingMonitor* instance = new SwapThrashingMonitor();
+  return instance;
+}
+
+SwapThrashingMonitor::SwapThrashingMonitor()
+    : current_swap_thrashing_level_(
+          SwapThrashingLevel::SWAP_THRASHING_LEVEL_NONE) {
+#if defined(OS_WIN)
+  delegate_ = base::MakeUnique<SwapThrashingMonitorDelegateWin>();
+#else
+  delegate_ = base::MakeUnique<SwapThrashingMonitorDelegate>();
+#endif
+  StartObserving();
+}
+
+SwapThrashingMonitor::~SwapThrashingMonitor() {
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+}
+
+SwapThrashingLevel SwapThrashingMonitor::GetCurrentSwapThrashingLevel() {
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+  return current_swap_thrashing_level_;
+}
+
+void SwapThrashingMonitor::CheckSwapThrashingPressureAndRecordStatistics() {
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+
+  SwapThrashingLevel swap_thrashing_level =
+      delegate_->SampleAndCalculateSwapThrashingLevel();
+
+  // Record the state changes.
+  if (swap_thrashing_level != current_swap_thrashing_level_) {
+    SwapThrashingLevelChangesUMA level_change =
+        UMA_SWAP_THRASHING_LEVEL_CHANGE_COUNT;
+
+    switch (current_swap_thrashing_level_) {
+      case SwapThrashingLevel::SWAP_THRASHING_LEVEL_NONE: {
+        DCHECK_EQ(SwapThrashingLevel::SWAP_THRASHING_LEVEL_SUSPECTED,
+                  swap_thrashing_level);
+        level_change = UMA_SWAP_THRASHING_LEVEL_CHANGE_NONE_TO_SUSPECTED;
+        break;
+      }
+      case SwapThrashingLevel::SWAP_THRASHING_LEVEL_SUSPECTED: {
+        if (swap_thrashing_level ==
+            SwapThrashingLevel::SWAP_THRASHING_LEVEL_NONE) {
+          level_change = UMA_SWAP_THRASHING_LEVEL_CHANGE_SUSPECTED_TO_NONE;
+        } else {
+          level_change = UMA_SWAP_THRASHING_LEVEL_CHANGE_SUSPECTED_TO_CONFIRMED;
+        }
+        break;
+      }
+      case SwapThrashingLevel::SWAP_THRASHING_LEVEL_CONFIRMED: {
+        DCHECK_EQ(SwapThrashingLevel::SWAP_THRASHING_LEVEL_SUSPECTED,
+                  swap_thrashing_level);
+        level_change = UMA_SWAP_THRASHING_LEVEL_CHANGE_CONFIRMED_TO_SUSPECTED;
+        break;
+      }
+      default:
+        break;
+    }
+    base::HistogramBase* level_change_histogram =
+        base::LinearHistogram::FactoryGet(
+            "Memory.SwapThrashingLevelChanges", 1,
+            UMA_SWAP_THRASHING_LEVEL_CHANGE_COUNT,
+            UMA_SWAP_THRASHING_LEVEL_CHANGE_COUNT + 1,
+            base::HistogramBase::kUmaTargetedHistogramFlag);
+    level_change_histogram->AddCount(level_change, 1);
+  }
+
+  current_swap_thrashing_level_ = swap_thrashing_level;
+
+  base::HistogramBase* level_histogram = base::LinearHistogram::FactoryGet(
+      "Memory.SwapThrashingLevel", 1, UMA_SWAP_THRASHING_LEVEL_COUNT,
+      UMA_SWAP_THRASHING_LEVEL_COUNT + 1,
+      base::HistogramBase::kUmaTargetedHistogramFlag);
+  level_histogram->AddCount(
+      SwapThrashingLevelToUmaEnumValue(current_swap_thrashing_level_), 1);
+}
+
+void SwapThrashingMonitor::StartObserving() {
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+  // TODO(sebmarchand): Determine if the system is using on-disk swap, abort if
+  // it isn't as there won't be any swap-paging to observe (on-disk swap could
+  // later become available if the user turn it on but this case is rare that
+  // it's safe to ignore it). See crbug.com/779309.
+  check_timer_.Start(
+      FROM_HERE, kSamplingInterval,
+      base::Bind(
+          &SwapThrashingMonitor::CheckSwapThrashingPressureAndRecordStatistics,
+          base::Unretained(this)));
+}
+
+}  // namespace memory
diff --git a/chrome/browser/memory/swap_thrashing_monitor.h b/chrome/browser/memory/swap_thrashing_monitor.h
new file mode 100644
index 0000000..7487c57
--- /dev/null
+++ b/chrome/browser/memory/swap_thrashing_monitor.h
@@ -0,0 +1,81 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// SwapThrashingMonitor defines a state-based interface for a swap thrashing
+// monitor. Thrashing is continuous swap activity, caused by processes needing
+// to touch more pages than fit in physical memory, over a given period of time.
+//
+// The systems interested in observing these signals should query this monitor
+// directly, it doesn't offer a notification API. Handling these signals should
+// be done carefully in order to not aggravate the problem, in its initial
+// implementation this monitor is meant to be used to measure the impact of
+// thrashing on the core speed metrics.
+//
+// The different thrashing states are defined in the
+// swap_thrashing_monitor_delegate.h header file.
+//
+// This monitor is responsible for initiating the observation of the
+// swap-thrashing signals and it also enforce the state transition logic, the
+// actual swap-thrashing observation logic should be done in a platform-specific
+// implementation of the SwapThrashingDelegate class.
+
+#ifndef CHROME_BROWSER_MEMORY_SWAP_THRASHING_MONITOR_H_
+#define CHROME_BROWSER_MEMORY_SWAP_THRASHING_MONITOR_H_
+
+#include "base/base_export.h"
+#include "base/macros.h"
+#include "base/timer/timer.h"
+#include "build/build_config.h"
+#include "chrome/browser/memory/swap_thrashing_monitor_delegate.h"
+
+namespace memory {
+
+// Class for monitoring the swap-thrashing activity on the system.
+//
+// It is meant to be used as a singleton by calling the Initialize method,
+// e.g.:
+//     SwapThrashingMonitor::Initialize();
+//
+// Then the current thrashing level can be obtained by calling
+// SwapThrashingMonitor::GetInstance()->GetCurrentSwapThrashingLevel();
+//
+// This class requires sequence-affinity, through use of ThreadChecker.
+class SwapThrashingMonitor {
+ public:
+  // Sets the |SwapThrashingMonitor| global instance. This is a no-op if the
+  // instance has already been initialized.
+  static void Initialize();
+
+  // Returns the |SwapThrashingMonitor| global instance.
+  static SwapThrashingMonitor* GetInstance();
+
+  // Returns the currently observed swap-thrashing pressure.
+  SwapThrashingLevel GetCurrentSwapThrashingLevel();
+
+ protected:
+  SwapThrashingMonitor();
+  virtual ~SwapThrashingMonitor();
+
+  // Takes fresh measurements from the OS, calculates and stores the level from
+  // them, and emits metrics if necessary.
+  void CheckSwapThrashingPressureAndRecordStatistics();
+
+  void StartObserving();
+
+ private:
+  // The delegate responsible for measuring the swap-thrashing activity.
+  std::unique_ptr<SwapThrashingMonitorDelegate> delegate_;
+
+  SwapThrashingLevel current_swap_thrashing_level_;
+
+  base::RepeatingTimer check_timer_;
+
+  SEQUENCE_CHECKER(sequence_checker_);
+
+  DISALLOW_COPY_AND_ASSIGN(SwapThrashingMonitor);
+};
+
+}  // namespace memory
+
+#endif  // CHROME_BROWSER_MEMORY_SWAP_THRASHING_MONITOR_H_
diff --git a/chrome/browser/memory/swap_thrashing_monitor_delegate.cc b/chrome/browser/memory/swap_thrashing_monitor_delegate.cc
new file mode 100644
index 0000000..37a11d8
--- /dev/null
+++ b/chrome/browser/memory/swap_thrashing_monitor_delegate.cc
@@ -0,0 +1,17 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/memory/swap_thrashing_monitor_delegate.h"
+
+#include "base/logging.h"
+
+namespace memory {
+
+SwapThrashingLevel
+SwapThrashingMonitorDelegate::SampleAndCalculateSwapThrashingLevel() {
+  NOTIMPLEMENTED();
+  return SwapThrashingLevel::SWAP_THRASHING_LEVEL_NONE;
+}
+
+}  // namespace memory
diff --git a/chrome/browser/memory/swap_thrashing_monitor_delegate.h b/chrome/browser/memory/swap_thrashing_monitor_delegate.h
new file mode 100644
index 0000000..de761a7
--- /dev/null
+++ b/chrome/browser/memory/swap_thrashing_monitor_delegate.h
@@ -0,0 +1,52 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_MEMORY_SWAP_THRASHING_MONITOR_DELEGATE_H_
+#define CHROME_BROWSER_MEMORY_SWAP_THRASHING_MONITOR_DELEGATE_H_
+
+#include "base/macros.h"
+#include "build/build_config.h"
+
+namespace memory {
+
+enum class SwapThrashingLevel {
+  // There's no thrashing happening on the system or the state is undetermined.
+  //
+  // There's no possible transition from this state to the confirmed one, the
+  // system always go through the suspected state before confirming thrashing.
+  SWAP_THRASHING_LEVEL_NONE,
+
+  // Indicates that there's a suspicion of swap-thrashing but the swapping
+  // activity is not sustained.
+  SWAP_THRASHING_LEVEL_SUSPECTED,
+
+  // Swap-thrashing is confirmed to affect the system.
+  SWAP_THRASHING_LEVEL_CONFIRMED,
+};
+
+// Dummy definition of a SwapThrashingMonitorDelegate, the platforms interested
+// in monitoring the swap thrashing state should implement this class. They
+// should also ensure that the SampleAndCalculateSwapThrashingLevel function
+// gets called periodically as it is responsible for querying the state of the
+// system. It is recommended to use a frequency around 0.5 and 1Hz.
+class SwapThrashingMonitorDelegate {
+ public:
+  SwapThrashingMonitorDelegate() {}
+  virtual ~SwapThrashingMonitorDelegate() {}
+
+  // Calculates the swap-thrashing level over the interval between now and the
+  // last time this function was called. This function will always return
+  // SWAP_THRASHING_LEVEL_NONE when it gets called for the first time.
+  //
+  // This function requires sequence-affinity, through use of ThreadChecker. It
+  // is also blocking and should be run on a blocking sequenced task runner.
+  virtual SwapThrashingLevel SampleAndCalculateSwapThrashingLevel();
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(SwapThrashingMonitorDelegate);
+};
+
+}  // namespace memory
+
+#endif  // CHROME_BROWSER_MEMORY_SWAP_THRASHING_MONITOR_DELEGATE_H_
diff --git a/chrome/browser/memory/swap_thrashing_monitor_delegate_win.cc b/chrome/browser/memory/swap_thrashing_monitor_delegate_win.cc
new file mode 100644
index 0000000..a21dcb6d
--- /dev/null
+++ b/chrome/browser/memory/swap_thrashing_monitor_delegate_win.cc
@@ -0,0 +1,214 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/memory/swap_thrashing_monitor_delegate_win.h"
+
+#include <windows.h>
+#include <winternl.h>
+
+#include "base/files/file_path.h"
+#include "base/memory/ptr_util.h"
+#include "base/win/win_util.h"
+#include "chrome/common/chrome_constants.h"
+
+namespace memory {
+
+namespace {
+
+// The signature of the NtQuerySystemInformation function.
+typedef NTSTATUS(WINAPI* NtQuerySystemInformationPtr)(SYSTEM_INFORMATION_CLASS,
+                                                      PVOID,
+                                                      ULONG,
+                                                      PULONG);
+
+// The threshold that we use to consider that an hard page-fault delta sample is
+// high, in hard page-fault / [sampling frequency].
+//
+// TODO(sebmarchand): Confirm that this value is adequate, crbug.com/779332.
+const size_t kHighSwappingThreshold = 8;
+
+// The minimum number of samples that need to be above the threshold to be in
+// the suspected state.
+const size_t kSampleCountToBecomeSuspectedState = 5;
+
+// The minimum number of samples that need to be above the threshold to be in
+// the confirmed state.
+const size_t kSampleCountToBecomeConfirmedState = 10;
+
+// ntstatus.h conflicts with windows.h so define this locally.
+#define STATUS_SUCCESS ((NTSTATUS)0x00000000L)
+#define STATUS_BUFFER_TOO_SMALL ((NTSTATUS)0xC0000023L)
+#define STATUS_INFO_LENGTH_MISMATCH ((NTSTATUS)0xC0000004L)
+
+// The struct used to return system process information via the NT internal
+// QuerySystemInformation call. This is partially documented at
+// http://goo.gl/Ja9MrH and fully documented at http://goo.gl/QJ70rn
+// This structure is laid out in the same format on both 32-bit and 64-bit
+// systems, but has a different size due to the various pointer-sized fields.
+struct SYSTEM_PROCESS_INFORMATION_EX {
+  ULONG NextEntryOffset;
+  ULONG NumberOfThreads;
+  LARGE_INTEGER WorkingSetPrivateSize;
+  ULONG HardFaultCount;
+  ULONG NumberOfThreadsHighWatermark;
+  ULONGLONG CycleTime;
+  LARGE_INTEGER CreateTime;
+  LARGE_INTEGER UserTime;
+  LARGE_INTEGER KernelTime;
+  UNICODE_STRING ImageName;
+  LONG KPriority;
+  // This is labeled a handle so that it expands to the correct size for 32-bit
+  // and 64-bit operating systems. However, under the hood it's a 32-bit DWORD
+  // containing the process ID.
+  HANDLE UniqueProcessId;
+  PVOID Reserved3;
+  ULONG HandleCount;
+  BYTE Reserved4[4];
+  PVOID Reserved5[11];
+  SIZE_T PeakPagefileUsage;
+  SIZE_T PrivatePageCount;
+  LARGE_INTEGER Reserved6[6];
+  // Array of SYSTEM_THREAD_INFORMATION structs follows.
+};
+
+// Gets the hard fault count of the current process through |hard_fault_count|.
+// Returns true on success.
+//
+// TODO(sebmarchand): Use TaskManager to get this information, crbug.com/779329.
+base::Optional<int64_t> GetHardFaultCountForChromeProcesses() {
+  base::Optional<int64_t> hard_fault_count = 0;
+
+  static const auto query_system_information_ptr =
+      reinterpret_cast<decltype(&::NtQuerySystemInformation)>(GetProcAddress(
+          GetModuleHandle(L"ntdll.dll"), "NtQuerySystemInformation"));
+  if (!query_system_information_ptr)
+    return base::nullopt;
+
+  // The output of this system call depends on the number of threads and
+  // processes on the entire system, and this can change between calls. Retry
+  // a small handful of times growing the buffer along the way.
+  // NOTE: The actual required size depends entirely on the number of processes
+  //       and threads running on the system. The initial guess suffices for
+  //       ~100s of processes and ~1000s of threads.
+  std::vector<uint8_t> buffer(32 * 1024);
+  for (size_t tries = 0; tries < 3; ++tries) {
+    ULONG return_length = 0;
+    const NTSTATUS status = query_system_information_ptr(
+        SystemProcessInformation, buffer.data(),
+        static_cast<ULONG>(buffer.size()), &return_length);
+
+    if (status == STATUS_SUCCESS)
+      break;
+
+    if (status == STATUS_INFO_LENGTH_MISMATCH ||
+        status == STATUS_BUFFER_TOO_SMALL) {
+      // Insufficient buffer. Grow to the returned |return_length| plus 10%
+      // extra to avoid frequent reallocations and try again.
+      DCHECK_GT(return_length, buffer.size());
+      buffer.resize(static_cast<ULONG>(return_length * 1.1));
+    } else {
+      // An error other than the two above.
+      return base::nullopt;
+    }
+  }
+
+  // Look for the struct housing information for the Chrome processes.
+  size_t index = 0;
+  while (index < buffer.size()) {
+    DCHECK_LE(index + sizeof(SYSTEM_PROCESS_INFORMATION_EX), buffer.size());
+    SYSTEM_PROCESS_INFORMATION_EX* proc_info =
+        reinterpret_cast<SYSTEM_PROCESS_INFORMATION_EX*>(buffer.data() + index);
+    if (base::FilePath::CompareEqualIgnoreCase(
+            proc_info->ImageName.Buffer,
+            chrome::kBrowserProcessExecutableName)) {
+      hard_fault_count = hard_fault_count.value() + proc_info->HardFaultCount;
+    }
+    // The list ends when NextEntryOffset is zero. This also prevents busy
+    // looping if the data is in fact invalid.
+    if (proc_info->NextEntryOffset <= 0)
+      break;
+    index += proc_info->NextEntryOffset;
+  }
+  return hard_fault_count;
+}
+
+}  // namespace
+
+// The number of sample that we'll keep track of.
+const size_t SwapThrashingMonitorDelegateWin::HardFaultDeltasWindow::
+    kHardFaultDeltasWindowSize = 12;
+
+SwapThrashingMonitorDelegateWin::SwapThrashingMonitorDelegateWin()
+    : hard_fault_deltas_window_(base::MakeUnique<HardFaultDeltasWindow>()) {}
+
+SwapThrashingMonitorDelegateWin::~SwapThrashingMonitorDelegateWin() {}
+
+SwapThrashingMonitorDelegateWin::HardFaultDeltasWindow::HardFaultDeltasWindow()
+    : latest_hard_fault_count_(), observation_above_threshold_count_(0U) {}
+
+SwapThrashingMonitorDelegateWin::HardFaultDeltasWindow::
+    ~HardFaultDeltasWindow() {}
+
+void SwapThrashingMonitorDelegateWin::HardFaultDeltasWindow::OnObservation(
+    uint64_t hard_fault_count) {
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+
+  if (!latest_hard_fault_count_) {
+    latest_hard_fault_count_ = hard_fault_count;
+    return;
+  }
+
+  // Start by removing the sample that have expired.
+  if (observation_deltas_.size() == kHardFaultDeltasWindowSize) {
+    if (observation_deltas_.front() >= kHighSwappingThreshold) {
+      DCHECK_GT(observation_above_threshold_count_, 0U);
+      --observation_above_threshold_count_;
+    }
+    observation_deltas_.pop_front();
+  }
+
+  size_t delta = hard_fault_count - latest_hard_fault_count_.value();
+  observation_deltas_.push_back(delta);
+  latest_hard_fault_count_ = hard_fault_count;
+  if (delta >= kHighSwappingThreshold)
+    ++observation_above_threshold_count_;
+}
+
+SwapThrashingLevel
+SwapThrashingMonitorDelegateWin::SampleAndCalculateSwapThrashingLevel() {
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+  if (!RecordHardFaultCountForChromeProcesses())
+    return SwapThrashingLevel::SWAP_THRASHING_LEVEL_NONE;
+
+  SwapThrashingLevel level = SwapThrashingLevel::SWAP_THRASHING_LEVEL_NONE;
+
+  // This delegate looks at a fixed number of past samples to determine if the
+  // system is now in a thrashing state. To do this it counts how many samples
+  // exceed a certain threshold.
+  size_t sample_above_threshold =
+      hard_fault_deltas_window_->observation_above_threshold_count();
+  if (sample_above_threshold >= kSampleCountToBecomeConfirmedState) {
+    level = SwapThrashingLevel::SWAP_THRASHING_LEVEL_CONFIRMED;
+  } else if (sample_above_threshold >= kSampleCountToBecomeSuspectedState) {
+    level = SwapThrashingLevel::SWAP_THRASHING_LEVEL_SUSPECTED;
+  }
+
+  return level;
+}
+
+bool SwapThrashingMonitorDelegateWin::RecordHardFaultCountForChromeProcesses() {
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+  base::Optional<int64_t> hard_fault_count =
+      GetHardFaultCountForChromeProcesses();
+  if (!hard_fault_count) {
+    LOG(ERROR) << "Unable to retrieve the hard fault counts for Chrome "
+               << "processes.";
+    return false;
+  }
+  hard_fault_deltas_window_->OnObservation(hard_fault_count.value());
+
+  return true;
+}
+
+}  // namespace memory
diff --git a/chrome/browser/memory/swap_thrashing_monitor_delegate_win.h b/chrome/browser/memory/swap_thrashing_monitor_delegate_win.h
new file mode 100644
index 0000000..594306c
--- /dev/null
+++ b/chrome/browser/memory/swap_thrashing_monitor_delegate_win.h
@@ -0,0 +1,77 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// The Windows implementation of the delegate used by the swap thrashing
+// monitor.
+
+#ifndef CHROME_BROWSER_MEMORY_SWAP_THRASHING_MONITOR_DELEGATE_WIN_H_
+#define CHROME_BROWSER_MEMORY_SWAP_THRASHING_MONITOR_DELEGATE_WIN_H_
+
+#include <list>
+
+#include "base/containers/circular_deque.h"
+#include "base/macros.h"
+#include "base/optional.h"
+#include "base/sequence_checker.h"
+#include "chrome/browser/memory/swap_thrashing_monitor_delegate.h"
+
+namespace memory {
+
+class SwapThrashingMonitorDelegateWin : public SwapThrashingMonitorDelegate {
+ public:
+  SwapThrashingMonitorDelegateWin();
+  ~SwapThrashingMonitorDelegateWin() override;
+
+  SwapThrashingLevel SampleAndCalculateSwapThrashingLevel() override;
+
+ protected:
+  // Used to compute how many of the recent samples are above a given threshold.
+  class HardFaultDeltasWindow {
+   public:
+    HardFaultDeltasWindow();
+
+    // Virtual for unittesting.
+    virtual ~HardFaultDeltasWindow();
+
+    // Should be called when a new hard-page fault observation is made. The
+    // delta with the previous observation will be added to the list of deltas.
+    void OnObservation(uint64_t hard_fault_count);
+
+    size_t observation_above_threshold_count() {
+      return observation_above_threshold_count_;
+    }
+
+   protected:
+    static const size_t kHardFaultDeltasWindowSize;
+
+    base::Optional<uint64_t> latest_hard_fault_count_;
+
+    // Delta between each observation.
+    base::circular_deque<size_t> observation_deltas_;
+
+    // Number of observations that are above the high swapping threshold.
+    size_t observation_above_threshold_count_;
+
+   private:
+    SEQUENCE_CHECKER(sequence_checker_);
+
+    DISALLOW_COPY_AND_ASSIGN(HardFaultDeltasWindow);
+  };
+
+  // Record the sum of the hard page-fault count for all the Chrome processes.
+  //
+  // Virtual for unittesting.
+  virtual bool RecordHardFaultCountForChromeProcesses();
+
+  std::unique_ptr<HardFaultDeltasWindow> hard_fault_deltas_window_;
+
+ private:
+  SEQUENCE_CHECKER(sequence_checker_);
+
+  DISALLOW_COPY_AND_ASSIGN(SwapThrashingMonitorDelegateWin);
+};
+
+}  // namespace memory
+
+#endif  // CHROME_BROWSER_MEMORY_SWAP_THRASHING_MONITOR_DELEGATE_WIN_H_
diff --git a/chrome/browser/memory/swap_thrashing_monitor_delegate_win_unittest.cc b/chrome/browser/memory/swap_thrashing_monitor_delegate_win_unittest.cc
new file mode 100644
index 0000000..6a170704
--- /dev/null
+++ b/chrome/browser/memory/swap_thrashing_monitor_delegate_win_unittest.cc
@@ -0,0 +1,157 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/memory/swap_thrashing_monitor_delegate_win.h"
+
+#include "base/memory/ptr_util.h"
+#include "base/test/scoped_task_environment.h"
+#include "base/timer/mock_timer.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace memory {
+
+namespace {
+
+class MockHardFaultDeltasWindow;
+
+class TestSwapThrashingMonitorDelegateWin
+    : public SwapThrashingMonitorDelegateWin {
+ public:
+  using HardFaultDeltasWindow =
+      SwapThrashingMonitorDelegateWin::HardFaultDeltasWindow;
+
+  TestSwapThrashingMonitorDelegateWin()
+      : SwapThrashingMonitorDelegateWin::SwapThrashingMonitorDelegateWin(),
+        observation_override_(0U) {
+    SetMockWindow();
+  }
+  ~TestSwapThrashingMonitorDelegateWin() override {}
+
+  void SetMockWindow();
+
+  bool RecordHardFaultCountForChromeProcesses() override {
+    hard_fault_deltas_window_->OnObservation(observation_override_);
+    return true;
+  }
+
+  // Override the next observations that the window will receive.
+  void OverrideNextObservationDelta(uint64_t observation_delta) {
+    observation_override_ += observation_delta;
+  }
+
+  MockHardFaultDeltasWindow* sample_window() { return mock_window_; }
+
+ private:
+  uint64_t observation_override_;
+
+  MockHardFaultDeltasWindow* mock_window_;
+};
+
+// A mock for the HardFaultDeltasWindow class.
+//
+// Used to access some protected fields of the HardFaultDeltasWindow class.
+class MockHardFaultDeltasWindow
+    : public TestSwapThrashingMonitorDelegateWin::HardFaultDeltasWindow {
+ public:
+  MockHardFaultDeltasWindow()
+      : TestSwapThrashingMonitorDelegateWin::HardFaultDeltasWindow() {}
+  ~MockHardFaultDeltasWindow() override {}
+
+  size_t SampleCount() { return observation_deltas_.size(); }
+
+  size_t WindowLength() { return kHardFaultDeltasWindowSize; }
+};
+
+void TestSwapThrashingMonitorDelegateWin::SetMockWindow() {
+  std::unique_ptr<MockHardFaultDeltasWindow> mock_window =
+      base::MakeUnique<MockHardFaultDeltasWindow>();
+  mock_window_ = mock_window.get();
+  hard_fault_deltas_window_.reset(mock_window.release());
+}
+
+}  // namespace
+
+TEST(SwapThrashingMonitorDelegateWinTest, StateTransition) {
+  TestSwapThrashingMonitorDelegateWin monitor;
+
+  // Arbitrarily chosen high thrashing rate.
+  const uint64_t kHighSwappingRate = 5000;
+
+  // This state test the transitions from the SWAP_THRASHING_LEVEL_NONE state
+  // to the SWAP_THRASHING_LEVEL_CONFIRMED one and then ensure that the cooldown
+  // mechanism works.
+
+  // We expect the system to initially be in the SWAP_THRASHING_LEVEL_NONE
+  // state.
+  EXPECT_EQ(SwapThrashingLevel::SWAP_THRASHING_LEVEL_NONE,
+            monitor.SampleAndCalculateSwapThrashingLevel());
+
+  // Fill the sample window with 0s.
+  while (monitor.sample_window()->SampleCount() <
+         monitor.sample_window()->WindowLength()) {
+    monitor.OverrideNextObservationDelta(0);
+    EXPECT_EQ(SwapThrashingLevel::SWAP_THRASHING_LEVEL_NONE,
+              monitor.SampleAndCalculateSwapThrashingLevel());
+  }
+
+  EXPECT_EQ(SwapThrashingLevel::SWAP_THRASHING_LEVEL_NONE,
+            monitor.SampleAndCalculateSwapThrashingLevel());
+  EXPECT_EQ(monitor.sample_window()->SampleCount(),
+            monitor.sample_window()->WindowLength());
+
+  // Adds high samples until we reach the suspected status.
+  size_t high_sample_count = 0;
+  while (high_sample_count < monitor.sample_window()->WindowLength()) {
+    high_sample_count++;
+    monitor.OverrideNextObservationDelta(kHighSwappingRate);
+    if (monitor.SampleAndCalculateSwapThrashingLevel() ==
+        SwapThrashingLevel::SWAP_THRASHING_LEVEL_SUSPECTED) {
+      break;
+    }
+  }
+  size_t suspected_state_sample_count = high_sample_count;
+  EXPECT_LT(suspected_state_sample_count,
+            monitor.sample_window()->WindowLength());
+
+  // And now add samples until we reach the confirmed value.
+  while (high_sample_count < monitor.sample_window()->WindowLength()) {
+    high_sample_count++;
+    monitor.OverrideNextObservationDelta(kHighSwappingRate);
+    if (monitor.SampleAndCalculateSwapThrashingLevel() ==
+        SwapThrashingLevel::SWAP_THRASHING_LEVEL_CONFIRMED) {
+      break;
+    }
+  }
+  size_t confirmed_state_sample_count = high_sample_count;
+
+  EXPECT_LE(confirmed_state_sample_count,
+            monitor.sample_window()->WindowLength());
+  EXPECT_GT(confirmed_state_sample_count, suspected_state_sample_count);
+
+  // Finish filling the window with high values.
+  while (high_sample_count < monitor.sample_window()->WindowLength()) {
+    high_sample_count++;
+    monitor.OverrideNextObservationDelta(kHighSwappingRate);
+    EXPECT_EQ(SwapThrashingLevel::SWAP_THRASHING_LEVEL_CONFIRMED,
+              monitor.SampleAndCalculateSwapThrashingLevel());
+  }
+
+  // Add 0s to the windows, the thrashing level should slowly decrease.
+  while (high_sample_count > 0) {
+    monitor.OverrideNextObservationDelta(0);
+    if (high_sample_count > confirmed_state_sample_count) {
+      EXPECT_EQ(SwapThrashingLevel::SWAP_THRASHING_LEVEL_CONFIRMED,
+                monitor.SampleAndCalculateSwapThrashingLevel());
+    } else if (high_sample_count > suspected_state_sample_count) {
+      EXPECT_EQ(SwapThrashingLevel::SWAP_THRASHING_LEVEL_SUSPECTED,
+                monitor.SampleAndCalculateSwapThrashingLevel());
+    } else {
+      EXPECT_EQ(SwapThrashingLevel::SWAP_THRASHING_LEVEL_NONE,
+                monitor.SampleAndCalculateSwapThrashingLevel());
+    }
+    high_sample_count--;
+  }
+}
+
+}  // namespace memory
diff --git a/chrome/browser/memory/swap_thrashing_monitor_win.cc b/chrome/browser/memory/swap_thrashing_monitor_win.cc
deleted file mode 100644
index 343436f..0000000
--- a/chrome/browser/memory/swap_thrashing_monitor_win.cc
+++ /dev/null
@@ -1,342 +0,0 @@
-// Copyright 2017 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "chrome/browser/memory/swap_thrashing_monitor_win.h"
-
-#include <windows.h>
-#include <winternl.h>
-
-#include "base/files/file_path.h"
-#include "base/logging.h"
-#include "base/memory/ptr_util.h"
-#include "base/win/win_util.h"
-#include "chrome/common/chrome_constants.h"
-
-namespace memory {
-
-namespace {
-
-using SwapThrashingLevel = SwapThrashingMonitorWin::SwapThrashingLevel;
-
-// The signature of the NtQuerySystemInformation function.
-typedef NTSTATUS(WINAPI* NtQuerySystemInformationPtr)(SYSTEM_INFORMATION_CLASS,
-                                                      PVOID,
-                                                      ULONG,
-                                                      PULONG);
-
-// The period of time during which swap-thrashing has to be observed in order
-// to switch from the SWAP_THRASHING_LEVEL_NONE to the
-// SWAP_THRASHING_LEVEL_SUSPECTED level.
-// TODO(sebmarchand): Confirm that this value is appropriate.
-constexpr base::TimeDelta kNoneToSuspectedInterval =
-    base::TimeDelta::FromMilliseconds(6000);
-
-// The period of time during which swap-thrashing should not be observed in
-// order to switch from the SWAP_THRASHING_LEVEL_SUSPECTED to the
-// SWAP_THRASHING_LEVEL_NONE level.
-// TODO(sebmarchand): Confirm that this value is appropriate.
-constexpr base::TimeDelta kSuspectedToNoneInterval =
-    base::TimeDelta::FromMilliseconds(8000);
-
-// The period of time during which swap-thrashing has to be observed while
-// being in the SWAP_THRASHING_LEVEL_SUSPECTED state in order to switch to the
-// SWAP_THRASHING_LEVEL_CONFIRMED level.
-// TODO(sebmarchand): Confirm that this value is appropriate.
-constexpr base::TimeDelta kSuspectedToConfirmedInterval =
-    base::TimeDelta::FromMilliseconds(10000);
-
-// The period of time during which swap-thrashing should not be observed in
-// order to switch from the SWAP_THRASHING_LEVEL_CONFIRMED to the
-// SWAP_THRASHING_LEVEL_SUSPECTED level.
-// TODO(sebmarchand): Confirm that this value is appropriate.
-constexpr base::TimeDelta kConfirmedToSuspectedInterval =
-    base::TimeDelta::FromMilliseconds(16000);
-
-// The struct used to return system process information via the NT internal
-// QuerySystemInformation call. This is partially documented at
-// http://goo.gl/Ja9MrH and fully documented at http://goo.gl/QJ70rn
-// This structure is laid out in the same format on both 32-bit and 64-bit
-// systems, but has a different size due to the various pointer-sized fields.
-struct SYSTEM_PROCESS_INFORMATION_EX {
-  ULONG NextEntryOffset;
-  ULONG NumberOfThreads;
-  LARGE_INTEGER WorkingSetPrivateSize;
-  ULONG HardFaultCount;
-  ULONG NumberOfThreadsHighWatermark;
-  ULONGLONG CycleTime;
-  LARGE_INTEGER CreateTime;
-  LARGE_INTEGER UserTime;
-  LARGE_INTEGER KernelTime;
-  UNICODE_STRING ImageName;
-  LONG KPriority;
-  // This is labeled a handle so that it expands to the correct size for 32-bit
-  // and 64-bit operating systems. However, under the hood it's a 32-bit DWORD
-  // containing the process ID.
-  HANDLE UniqueProcessId;
-  PVOID Reserved3;
-  ULONG HandleCount;
-  BYTE Reserved4[4];
-  PVOID Reserved5[11];
-  SIZE_T PeakPagefileUsage;
-  SIZE_T PrivatePageCount;
-  LARGE_INTEGER Reserved6[6];
-  // Array of SYSTEM_THREAD_INFORMATION structs follows.
-};
-
-// Gets the hard fault count of the current process through |hard_fault_count|.
-// Returns true on success.
-//
-// TODO(sebmarchand): Ideally we should reduce code duplication by re-using the
-// TaskManager's code to gather these metrics, but it's not as simple as it
-// should. It'll either require a lot of duct tape code to connect these 2
-// things together, or the QuerySystemProcessInformation function in
-// chrome/browser/task_manager/sampling/shared_sampler_win.cc should be moved
-// somewhere else to make it easier to re-use it without having to implement
-// all the task manager specific stuff.
-bool GetHardFaultCountForChromeProcesses(uint64_t* hard_fault_count) {
-  DCHECK(hard_fault_count);
-
-  *hard_fault_count = 0;
-
-  // Get the function pointer.
-  static const NtQuerySystemInformationPtr query_sys_info =
-      reinterpret_cast<NtQuerySystemInformationPtr>(::GetProcAddress(
-          GetModuleHandle(L"ntdll.dll"), "NtQuerySystemInformation"));
-  if (query_sys_info == nullptr)
-    return false;
-
-  // The output of this system call depends on the number of threads and
-  // processes on the entire system, and this can change between calls. Retry
-  // a small handful of times growing the buffer along the way.
-  // NOTE: The actual required size depends entirely on the number of processes
-  //       and threads running on the system. The initial guess suffices for
-  //       ~100s of processes and ~1000s of threads.
-  std::vector<uint8_t> buffer(32 * 1024);
-  for (size_t tries = 0; tries < 3; ++tries) {
-    ULONG return_length = 0;
-    const NTSTATUS status =
-        query_sys_info(SystemProcessInformation, buffer.data(),
-                       static_cast<ULONG>(buffer.size()), &return_length);
-    // Insufficient space in the buffer.
-    if (return_length > buffer.size()) {
-      buffer.resize(return_length);
-      continue;
-    }
-    if (NT_SUCCESS(status) && return_length <= buffer.size())
-      break;
-    return false;
-  }
-
-  // Look for the struct housing information for the Chrome processes.
-  size_t index = 0;
-  while (index < buffer.size()) {
-    DCHECK_LE(index + sizeof(SYSTEM_PROCESS_INFORMATION_EX), buffer.size());
-    SYSTEM_PROCESS_INFORMATION_EX* proc_info =
-        reinterpret_cast<SYSTEM_PROCESS_INFORMATION_EX*>(buffer.data() + index);
-    if (base::FilePath::CompareEqualIgnoreCase(
-            proc_info->ImageName.Buffer,
-            chrome::kBrowserProcessExecutableName)) {
-      *hard_fault_count += proc_info->HardFaultCount;
-      return true;
-    }
-    // The list ends when NextEntryOffset is zero. This also prevents busy
-    // looping if the data is in fact invalid.
-    if (proc_info->NextEntryOffset <= 0)
-      return false;
-    index += proc_info->NextEntryOffset;
-  }
-
-  return true;
-}
-
-}  // namespace
-
-const double SwapThrashingMonitorWin::kPageFaultEscalationThreshold = 5;
-const double SwapThrashingMonitorWin::kPageFaultCooldownThreshold = 3;
-
-SwapThrashingMonitorWin::SwapThrashingMonitorWin()
-    : last_thrashing_state_(SwapThrashingLevel::SWAP_THRASHING_LEVEL_NONE) {
-  // Initialize the observation windows. Initially we can only transition to the
-  // suspected state.
-  ResetEscalationWindow(kNoneToSuspectedInterval);
-  swap_thrashing_cooldown_window_.reset(nullptr);
-}
-
-SwapThrashingMonitorWin::~SwapThrashingMonitorWin() {}
-
-SwapThrashingMonitorWin::PageFaultAverageRate::PageFaultAverageRate(
-    base::TimeDelta window_length)
-    : window_length_(window_length) {
-  Reset(window_length);
-}
-
-SwapThrashingMonitorWin::PageFaultAverageRate::~PageFaultAverageRate() {}
-
-void SwapThrashingMonitorWin::PageFaultAverageRate::Reset(
-    base::TimeDelta window_length) {
-  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
-  base::Optional<PageFaultObservation> last_observation;
-  if (observations_.size() > 0U)
-    last_observation = observations_.back();
-  observations_.clear();
-  window_length_ = window_length;
-  if (last_observation)
-    observations_.push_back(last_observation.value());
-}
-
-void SwapThrashingMonitorWin::PageFaultAverageRate::OnObservation(
-    PageFaultObservation observation) {
-  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
-  observations_.push_back(observation);
-
-  // No need to remove any observation if there's only 1 or 2 of them.
-  if (observations_.size() <= 2)
-    return;
-
-  // Find the oldest observation that we should keep.
-
-  const auto& last_observation = observations_.back();
-  // Start by looking at the second to last observation.
-  auto last_iterator_to_keep = observations_.end();
-  std::advance(last_iterator_to_keep, -2);
-
-  // Look for the most recent iteration that gives us a full coverage of this
-  // time window, if none is found then |last_iterator_to_keep| will point to
-  // the first observation and none will be removed.
-  while (last_iterator_to_keep != observations_.begin()) {
-    if ((last_observation.timestamp - last_iterator_to_keep->timestamp) >=
-        window_length_) {
-      break;
-    }
-    last_iterator_to_keep--;
-  }
-
-  observations_.erase(observations_.begin(), last_iterator_to_keep);
-
-  DCHECK_GE(observations_.size(), 2U);
-}
-
-base::Optional<double>
-SwapThrashingMonitorWin::PageFaultAverageRate::AveragePageFaultRate() const {
-  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
-  base::Optional<double> ret = base::nullopt;
-  if (observations_.size() < 2)
-    return ret;
-  base::TimeDelta observation_length =
-      observations_.back().timestamp - observations_.begin()->timestamp;
-  if (observation_length < window_length_)
-    return ret;
-
-  ret = (observations_.back().page_fault_count -
-         observations_.begin()->page_fault_count) /
-        observation_length.InSecondsF();
-
-  return ret;
-}
-
-SwapThrashingLevel
-SwapThrashingMonitorWin::SampleAndCalculateSwapThrashingLevel() {
-  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
-  if (!RecordHardFaultCountForChromeProcesses())
-    return SwapThrashingLevel::SWAP_THRASHING_LEVEL_NONE;
-
-  bool transition_to_higher_state = false;
-  // Check if the observation window has expired and if there should be a state
-  // change.
-  if (swap_thrashing_escalation_window_) {
-    base::Optional<double> average_rate =
-        swap_thrashing_escalation_window_->AveragePageFaultRate();
-    if (average_rate != base::nullopt) {
-      transition_to_higher_state =
-          average_rate >= kPageFaultEscalationThreshold;
-    }
-  }
-  bool transition_to_lower_state = false;
-  // Check if the cooldown window has expired and if there should be a state
-  // change.
-  if (swap_thrashing_cooldown_window_ && !transition_to_higher_state) {
-    base::Optional<double> average_rate =
-        swap_thrashing_cooldown_window_->AveragePageFaultRate();
-    if (average_rate != base::nullopt)
-      transition_to_lower_state = average_rate <= kPageFaultCooldownThreshold;
-  }
-
-  switch (last_thrashing_state_) {
-    case SwapThrashingLevel::SWAP_THRASHING_LEVEL_NONE: {
-      if (transition_to_higher_state) {
-        ResetEscalationWindow(kSuspectedToConfirmedInterval);
-        ResetCooldownWindow(kSuspectedToNoneInterval);
-        last_thrashing_state_ =
-            SwapThrashingLevel::SWAP_THRASHING_LEVEL_SUSPECTED;
-      }
-      break;
-    }
-    case SwapThrashingLevel::SWAP_THRASHING_LEVEL_SUSPECTED: {
-      if (transition_to_higher_state) {
-        swap_thrashing_escalation_window_.reset(nullptr);
-        ResetCooldownWindow(kConfirmedToSuspectedInterval);
-        last_thrashing_state_ =
-            SwapThrashingLevel::SWAP_THRASHING_LEVEL_CONFIRMED;
-      } else if (transition_to_lower_state) {
-        ResetEscalationWindow(kNoneToSuspectedInterval);
-        swap_thrashing_cooldown_window_.reset(nullptr);
-        last_thrashing_state_ = SwapThrashingLevel::SWAP_THRASHING_LEVEL_NONE;
-      }
-      break;
-    }
-    case SwapThrashingLevel::SWAP_THRASHING_LEVEL_CONFIRMED: {
-      if (transition_to_lower_state) {
-        ResetEscalationWindow(kSuspectedToConfirmedInterval);
-        ResetCooldownWindow(kSuspectedToNoneInterval);
-        last_thrashing_state_ =
-            SwapThrashingLevel::SWAP_THRASHING_LEVEL_SUSPECTED;
-      }
-      break;
-    }
-    default:
-      NOTREACHED();
-  }
-
-  return last_thrashing_state_;
-}
-
-bool SwapThrashingMonitorWin::RecordHardFaultCountForChromeProcesses() {
-  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
-  uint64_t hard_fault_count = 0;
-  if (!GetHardFaultCountForChromeProcesses(&hard_fault_count)) {
-    LOG(ERROR) << "Unable to retrieve the hard fault counts for Chrome "
-               << "processes.";
-    return false;
-  }
-  PageFaultObservation observation = {hard_fault_count, base::TimeTicks::Now()};
-
-  if (swap_thrashing_escalation_window_)
-    swap_thrashing_escalation_window_->OnObservation(observation);
-  if (swap_thrashing_cooldown_window_)
-    swap_thrashing_cooldown_window_->OnObservation(observation);
-
-  return true;
-}
-
-void SwapThrashingMonitorWin::ResetEscalationWindow(
-    base::TimeDelta window_length) {
-  if (swap_thrashing_escalation_window_) {
-    swap_thrashing_escalation_window_->Reset(window_length);
-  } else {
-    swap_thrashing_escalation_window_ =
-        base::MakeUnique<PageFaultAverageRate>(window_length);
-  }
-}
-
-void SwapThrashingMonitorWin::ResetCooldownWindow(
-    base::TimeDelta window_length) {
-  if (swap_thrashing_cooldown_window_) {
-    swap_thrashing_cooldown_window_->Reset(window_length);
-  } else {
-    swap_thrashing_cooldown_window_ =
-        base::MakeUnique<PageFaultAverageRate>(window_length);
-  }
-}
-
-}  // namespace memory
diff --git a/chrome/browser/memory/swap_thrashing_monitor_win.h b/chrome/browser/memory/swap_thrashing_monitor_win.h
deleted file mode 100644
index 1a38f9c..0000000
--- a/chrome/browser/memory/swap_thrashing_monitor_win.h
+++ /dev/null
@@ -1,160 +0,0 @@
-// Copyright 2017 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-// SwapThrashingMonitorWin defines a state-based swap thrashing monitor on
-// Windows. Thrashing is continuous swap activity, caused by processes needing
-// to touch more pages than fit in physical memory, over a given period of time.
-//
-// The systems interested in observing these signals should ensure that the
-// SampleAndCalculateSwapThrashingLevel function of this detector gets called
-// periodically as it is responsible for querying the state of the system.
-//
-// This monitor defines the following state and transitions:
-//
-//       ┎─────────────────────────┐
-//       ┃SWAP_THRASHING_LEVEL_NONE┃
-//       ┖─────────────────────────┚
-//           |              ▲
-//           | (T1)         | (T1')
-//           ▼              |
-//    ┎──────────────────────────────┒
-//    ┃SWAP_THRASHING_LEVEL_SUSPECTED┃
-//    ┖──────────────────────────────┚
-//           |              ▲
-//           | (T2)         | (T2')
-//           ▼              |
-//    ┎──────────────────────────────┒
-//    ┃SWAP_THRASHING_LEVEL_CONFIRMED┃
-//    ┖──────────────────────────────┚
-//
-// SWAP_THRASHING_LEVEL_NONE is the initial level, it means that there's no
-// thrashing happening on the system or that it is undetermined. The monitor
-// should regularly observe the hard page-fault counters and when a sustained
-// thrashing activity is observed over a period of time T1 it'll enter into the
-// SWAP_THRASHING_LEVEL_SUSPECTED state.
-//
-// If the system continues observing a sustained thrashing activity on the
-// system over a second period of time T2 then it'll enter into the
-// SWAP_THRASHING_LEVEL_CONFIRMED state to indicate that the system is now in
-// a confirmed swap-thrashing state, otherwise it'll go back to the
-// SWAP_THRASHING_LEVEL_NONE state if there's no swap-thrashing observed during
-// another interval of time T1' (T1 with an hysteresis).
-//
-// From the SWAP_THRASHING_LEVEL_CONFIRMED level the monitor can only go back
-// to the SWAP_THRASHING_LEVEL_SUSPECTED state if there's no swap-thrashing
-// observed during an interval of time T2' (T2 with an hysteresis).
-
-#ifndef CHROME_BROWSER_MEMORY_SWAP_THRASHING_MONITOR_WIN_H_
-#define CHROME_BROWSER_MEMORY_SWAP_THRASHING_MONITOR_WIN_H_
-
-#include <list>
-
-#include "base/containers/circular_deque.h"
-#include "base/optional.h"
-#include "base/sequence_checker.h"
-#include "base/time/time.h"
-
-namespace memory {
-
-class SwapThrashingMonitorWin {
- public:
-  enum class SwapThrashingLevel {
-    SWAP_THRASHING_LEVEL_NONE,
-    SWAP_THRASHING_LEVEL_SUSPECTED,
-    SWAP_THRASHING_LEVEL_CONFIRMED,
-  };
-
-  SwapThrashingMonitorWin();
-  virtual ~SwapThrashingMonitorWin();
-
-  // Calculates the swap-thrashing level over the interval between now and the
-  // last time this function was called. This function will always return
-  // SWAP_THRASHING_LEVEL_NONE when it gets called for the first time.
-  //
-  // This function requires sequence-affinity, through use of ThreadChecker. It
-  // is also blocking and should be run on a blocking sequenced task runner.
-  //
-  // TODO(sebmarchand): Check if this should be posted to a task runner and run
-  // asynchronously.
-  SwapThrashingLevel SampleAndCalculateSwapThrashingLevel();
-
- protected:
-  struct PageFaultObservation {
-    uint64_t page_fault_count;
-    base::TimeTicks timestamp;
-  };
-
-  // The average hard page-fault rate (/sec) that we expect to see when
-  // switching to a higher swap-thrashing level.
-  // TODO(sebmarchand): Confirm that this value is appropriate.
-  static const double kPageFaultEscalationThreshold;
-
-  // The average hard page-fault rate (/sec) that we use to go down to a lower
-  // swap-thrashing level.
-  // TODO(sebmarchand): Confirm that this value is appropriate.
-  static const double kPageFaultCooldownThreshold;
-
-  // Used to calculate the average page-fault rate across a specified time
-  // window.
-  class PageFaultAverageRate {
-   public:
-    // |window_length| is the minimum observation period before starting to
-    // compute the average rate.
-    explicit PageFaultAverageRate(base::TimeDelta window_length);
-    virtual ~PageFaultAverageRate();
-
-    // Reset the window to the value provided. Keep the most recent observation
-    // if the observation list is not empty.
-    void Reset(base::TimeDelta window_length);
-
-    // Should be called when a new hard-page fault observation is made. The
-    // observation will be added to the list of observations and the one that
-    // are not needed anymore will be removed.
-    virtual void OnObservation(PageFaultObservation observation);
-
-    // Computes the average hard page-fault rate during this observation window.
-    //
-    // Returns true if the window of time has expired and store the average
-    // value in |average_rate|, returns false otherwise.
-    virtual base::Optional<double> AveragePageFaultRate() const;
-
-   protected:
-    base::TimeDelta window_length_;
-
-    // The observation, in the order they have been received.
-    base::circular_deque<PageFaultObservation> observations_;
-
-   private:
-    SEQUENCE_CHECKER(sequence_checker_);
-
-    DISALLOW_COPY_AND_ASSIGN(PageFaultAverageRate);
-  };
-
-  // Record the sum of the hard page-fault count for all the Chrome processes.
-  virtual bool RecordHardFaultCountForChromeProcesses();
-
-  // Reset the escalation/cooldown windows.
-  //
-  // These functions are virtual for unittesting purposes.
-  virtual void ResetEscalationWindow(base::TimeDelta window_length);
-  virtual void ResetCooldownWindow(base::TimeDelta window_length);
-
-  // The escalation window to detect the changes to a higher thrashing state.
-  std::unique_ptr<PageFaultAverageRate> swap_thrashing_escalation_window_;
-
-  // The cooldown window to detect the changes to a lower thrashing state.
-  std::unique_ptr<PageFaultAverageRate> swap_thrashing_cooldown_window_;
-
-  // The most recent swap-thrashing level measurement.
-  SwapThrashingLevel last_thrashing_state_;
-
- private:
-  SEQUENCE_CHECKER(sequence_checker_);
-
-  DISALLOW_COPY_AND_ASSIGN(SwapThrashingMonitorWin);
-};
-
-}  // namespace memory
-
-#endif  // CHROME_BROWSER_MEMORY_SWAP_THRASHING_MONITOR_WIN_H_
diff --git a/chrome/browser/memory/swap_thrashing_monitor_win_unittest.cc b/chrome/browser/memory/swap_thrashing_monitor_win_unittest.cc
deleted file mode 100644
index 432839d..0000000
--- a/chrome/browser/memory/swap_thrashing_monitor_win_unittest.cc
+++ /dev/null
@@ -1,364 +0,0 @@
-// Copyright 2017 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "chrome/browser/memory/swap_thrashing_monitor_win.h"
-
-#include "base/memory/ptr_util.h"
-#include "base/test/scoped_task_environment.h"
-#include "base/timer/mock_timer.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace memory {
-
-namespace {
-
-using SwapThrashingLevel = SwapThrashingMonitorWin::SwapThrashingLevel;
-
-class MockPageFaultAverageRate;
-
-class TestSwapThrashingMonitorWin : public SwapThrashingMonitorWin {
- public:
-  using PageFaultAverageRate = SwapThrashingMonitorWin::PageFaultAverageRate;
-  using PageFaultObservation = SwapThrashingMonitorWin::PageFaultObservation;
-
-  TestSwapThrashingMonitorWin()
-      : SwapThrashingMonitorWin::SwapThrashingMonitorWin() {}
-  ~TestSwapThrashingMonitorWin() override {}
-
-  bool RecordHardFaultCountForChromeProcesses() override {
-    PageFaultObservation observation = {0, base::TimeTicks::Now()};
-
-    if (swap_thrashing_escalation_window_)
-      swap_thrashing_escalation_window_->OnObservation(observation);
-    if (swap_thrashing_cooldown_window_)
-      swap_thrashing_cooldown_window_->OnObservation(observation);
-
-    return true;
-  }
-
-  // Override these functions to make this detector use mock detection windows.
-  void ResetEscalationWindow(base::TimeDelta window_length) override;
-  void ResetCooldownWindow(base::TimeDelta window_length) override;
-
-  MockPageFaultAverageRate* escalation_window() {
-    EXPECT_NE(nullptr, escalation_window_);
-    return escalation_window_;
-  }
-  MockPageFaultAverageRate* cooldown_window() {
-    EXPECT_NE(nullptr, cooldown_window_);
-    return cooldown_window_;
-  }
-
-  // Returns a page-fault value that will set the hard page-fault rate during
-  // the observation to a value that will cause a state change.
-  uint64_t ComputeHighThrashingRate(base::TimeTicks window_beginning,
-                                    base::TimeTicks next_timestamp);
-
- private:
-  MockPageFaultAverageRate* escalation_window_;
-  MockPageFaultAverageRate* cooldown_window_;
-};
-
-// A mock for the PageFaultAverageRate class.
-//
-// Used to induce state transitions in TestSwapThrashingMonitorWin.
-class MockPageFaultAverageRate
-    : public TestSwapThrashingMonitorWin::PageFaultAverageRate {
- public:
-  using PageFaultObservation =
-      TestSwapThrashingMonitorWin::PageFaultObservation;
-
-  MockPageFaultAverageRate()
-      : TestSwapThrashingMonitorWin::PageFaultAverageRate(
-            base::TimeDelta::FromMilliseconds(1000)),
-        observation_override_({0, base::TimeTicks::Now()}),
-        invalidated_(false) {}
-  ~MockPageFaultAverageRate() override {}
-
-  // Override this function so we can use the mocked expectations rather than
-  // the real ones.
-  void OnObservation(PageFaultObservation observation) override {
-    TestSwapThrashingMonitorWin::PageFaultAverageRate::OnObservation(
-        observation_override_);
-  }
-
-  void Invalidate() { invalidated_ = true; }
-
-  base::Optional<double> AveragePageFaultRate() const override {
-    if (invalidated_)
-      return base::nullopt;
-    return TestSwapThrashingMonitorWin::PageFaultAverageRate::
-        AveragePageFaultRate();
-  }
-
-  // Override the next observations that this window will receive.
-  void OverrideNextObservation(PageFaultObservation observation_override) {
-    observation_override_ = observation_override;
-  }
-
-  void AddObservation(PageFaultObservation observation) {
-    OverrideNextObservation(observation);
-    OnObservation({0, base::TimeTicks::Now()});
-  }
-
-  base::TimeDelta window_length() const { return window_length_; }
-
-  base::TimeTicks window_beginning() {
-    return observations_.begin()->timestamp;
-  }
-
-  // Compute the timestamp that correspond to the end of this window.
-  base::TimeTicks GetEndOfWindowTimestamp() {
-    return window_beginning() + window_length();
-  }
-
-  const base::circular_deque<PageFaultObservation>& observations() {
-    return observations_;
-  }
-
- private:
-  PageFaultObservation observation_override_;
-  bool invalidated_;
-};
-
-void TestSwapThrashingMonitorWin::ResetEscalationWindow(
-    base::TimeDelta window_length) {
-  std::unique_ptr<MockPageFaultAverageRate> escalation_window =
-      base::MakeUnique<MockPageFaultAverageRate>();
-  escalation_window_ = escalation_window.get();
-  swap_thrashing_escalation_window_.reset(escalation_window.release());
-}
-
-void TestSwapThrashingMonitorWin::ResetCooldownWindow(
-    base::TimeDelta window_length) {
-  std::unique_ptr<MockPageFaultAverageRate> cooldown_window =
-      base::MakeUnique<MockPageFaultAverageRate>();
-  cooldown_window_ = cooldown_window.get();
-  swap_thrashing_cooldown_window_.reset(cooldown_window.release());
-}
-
-uint64_t TestSwapThrashingMonitorWin::ComputeHighThrashingRate(
-    base::TimeTicks window_beginning,
-    base::TimeTicks next_timestamp) {
-  return SwapThrashingMonitorWin::kPageFaultEscalationThreshold *
-         (next_timestamp - window_beginning).InSeconds();
-}
-
-}  // namespace
-
-class SwapThrashingMonitorWinTest : public testing::Test {
- public:
-  using PageFaultObservation =
-      TestSwapThrashingMonitorWin::PageFaultObservation;
-
-  void SetUp() override {
-    mock_escalation_window_ = nullptr;
-    mock_cooldown_window_ = nullptr;
-  }
-
-  void TearDown() override {}
-
-  void ResetObservationWindows(bool enable_escalation_window,
-                               bool enable_cooldown_window) {
-    // Reset the windows to turn it into mock ones.
-    monitor_.ResetEscalationWindow(base::TimeDelta());
-    mock_escalation_window_ = monitor_.escalation_window();
-    monitor_.ResetCooldownWindow(base::TimeDelta());
-    mock_cooldown_window_ = monitor_.cooldown_window();
-    if (enable_escalation_window) {
-      mock_escalation_window_->AddObservation({0, base::TimeTicks::Now()});
-    } else {
-      mock_escalation_window_->Invalidate();
-    }
-    if (enable_cooldown_window) {
-      mock_cooldown_window_->AddObservation({0, base::TimeTicks::Now()});
-    } else {
-      mock_cooldown_window_->Invalidate();
-    }
-  }
-
- protected:
-  TestSwapThrashingMonitorWin monitor_;
-
-  MockPageFaultAverageRate* mock_escalation_window_;
-  MockPageFaultAverageRate* mock_cooldown_window_;
-};
-
-TEST_F(SwapThrashingMonitorWinTest, StateTransition) {
-  // This state test the transitions from the SWAP_THRASHING_LEVEL_NONE state
-  // to the SWAP_THRASHING_LEVEL_CONFIRMED one and then ensure that the cooldown
-  // mechanism works.
-
-  // Only enable the detection window
-  ResetObservationWindows(true, false);
-
-  // We expect the system to initially be in the SWAP_THRASHING_LEVEL_NONE
-  // state.
-  EXPECT_EQ(SwapThrashingLevel::SWAP_THRASHING_LEVEL_NONE,
-            monitor_.SampleAndCalculateSwapThrashingLevel());
-
-  // Override the next observation with a timestamp that is inferior to the
-  // window length.
-  PageFaultObservation next_observation = {
-      0, mock_escalation_window_->GetEndOfWindowTimestamp() -
-             base::TimeDelta::FromMilliseconds(1)};
-  mock_escalation_window_->OverrideNextObservation(next_observation);
-  // There should be no state transition as the window hasn't expired yet.
-  EXPECT_EQ(SwapThrashingLevel::SWAP_THRASHING_LEVEL_NONE,
-            monitor_.SampleAndCalculateSwapThrashingLevel());
-
-  // Use a timestamp equal to the window length.
-  next_observation.timestamp =
-      mock_escalation_window_->GetEndOfWindowTimestamp();
-  // Set the thrashing level to a rate that is inferior to the state change
-  // threshold.
-  next_observation.page_fault_count =
-      monitor_.ComputeHighThrashingRate(
-          mock_escalation_window_->window_beginning(),
-          next_observation.timestamp) -
-      1;
-  mock_escalation_window_->OverrideNextObservation(next_observation);
-  EXPECT_EQ(SwapThrashingLevel::SWAP_THRASHING_LEVEL_NONE,
-            monitor_.SampleAndCalculateSwapThrashingLevel());
-
-  // Set the thrashing rate to the threshold, this should cause a state change.
-  next_observation.page_fault_count++;
-  mock_escalation_window_->OverrideNextObservation(next_observation);
-  EXPECT_EQ(SwapThrashingLevel::SWAP_THRASHING_LEVEL_SUSPECTED,
-            monitor_.SampleAndCalculateSwapThrashingLevel());
-
-  // Reset the detection window as it has been invalidated by the state change,
-  // invalidate the cooldown window to make sure the system doesn't switch to a
-  // lower state.
-  ResetObservationWindows(true, false);
-
-  // Use a timestamp just before the end of the window.
-  next_observation.timestamp =
-      mock_escalation_window_->GetEndOfWindowTimestamp() -
-      base::TimeDelta::FromMilliseconds(1);
-  next_observation.page_fault_count = 0;
-  mock_escalation_window_->OverrideNextObservation(next_observation);
-  EXPECT_EQ(SwapThrashingLevel::SWAP_THRASHING_LEVEL_SUSPECTED,
-            monitor_.SampleAndCalculateSwapThrashingLevel());
-
-  // Make the window expire but keep the page-fault rate low, this shouldn't
-  // cause a state change.
-  next_observation.timestamp =
-      mock_escalation_window_->GetEndOfWindowTimestamp();
-  mock_escalation_window_->OverrideNextObservation(next_observation);
-  EXPECT_EQ(SwapThrashingLevel::SWAP_THRASHING_LEVEL_SUSPECTED,
-            monitor_.SampleAndCalculateSwapThrashingLevel());
-
-  ResetObservationWindows(true, false);
-
-  next_observation.timestamp =
-      mock_escalation_window_->GetEndOfWindowTimestamp();
-
-  // Increase the page-fault rate to induce a change to the confirmed state.
-  next_observation.page_fault_count = monitor_.ComputeHighThrashingRate(
-      mock_escalation_window_->window_beginning(), next_observation.timestamp);
-  mock_escalation_window_->OverrideNextObservation(next_observation);
-  EXPECT_EQ(SwapThrashingLevel::SWAP_THRASHING_LEVEL_CONFIRMED,
-            monitor_.SampleAndCalculateSwapThrashingLevel());
-
-  // Reset the detection windows as they have been invalidated by the state
-  // change.
-  ResetObservationWindows(false, true);
-
-  // Keep the hard page-fault rate high, the state shouldn't change at the end
-  // of the cooldown window.
-  next_observation.timestamp = mock_cooldown_window_->GetEndOfWindowTimestamp();
-  next_observation.page_fault_count = monitor_.ComputeHighThrashingRate(
-      mock_cooldown_window_->window_beginning(), next_observation.timestamp);
-  mock_cooldown_window_->OverrideNextObservation(next_observation);
-  EXPECT_EQ(SwapThrashingLevel::SWAP_THRASHING_LEVEL_CONFIRMED,
-            monitor_.SampleAndCalculateSwapThrashingLevel());
-
-  // Set the hard page-fault rate to 0, this will induce a transition to a lower
-  // state.
-  ResetObservationWindows(false, true);
-  next_observation.timestamp = mock_cooldown_window_->GetEndOfWindowTimestamp();
-  next_observation.page_fault_count = 0;
-  mock_cooldown_window_->OverrideNextObservation(next_observation);
-  EXPECT_EQ(SwapThrashingLevel::SWAP_THRASHING_LEVEL_SUSPECTED,
-            monitor_.SampleAndCalculateSwapThrashingLevel());
-
-  // And finally return to the NONE state.
-  ResetObservationWindows(false, true);
-  next_observation.timestamp = mock_cooldown_window_->GetEndOfWindowTimestamp();
-  mock_cooldown_window_->OverrideNextObservation(next_observation);
-  EXPECT_EQ(SwapThrashingLevel::SWAP_THRASHING_LEVEL_NONE,
-            monitor_.SampleAndCalculateSwapThrashingLevel());
-}
-
-TEST_F(SwapThrashingMonitorWinTest, PageFaultAverageRateTests) {
-  constexpr base::TimeDelta kObservationWindowLength =
-      base::TimeDelta::FromSeconds(8);
-  MockPageFaultAverageRate escalation_window;
-
-  base::TimeTicks reference_tick = base::TimeTicks::Now();
-  PageFaultObservation first_observation = {0, reference_tick};
-  escalation_window.Reset(kObservationWindowLength);
-  escalation_window.OnObservation(first_observation);
-
-  EXPECT_EQ(1U, escalation_window.observations().size());
-
-  // Add an observation with a timestamp inferior to the window length.
-  PageFaultObservation second_observation = {
-      400, reference_tick + base::TimeDelta::FromSeconds(2)};
-
-  escalation_window.AddObservation(second_observation);
-  // It shouldn't be able to compute the average as the window hasn't expired
-  // yet.
-  base::Optional<double> average = escalation_window.AveragePageFaultRate();
-  EXPECT_EQ(base::nullopt, average);
-
-  EXPECT_EQ(2U, escalation_window.observations().size());
-
-  // Add another observation that correspond to the end of the observation
-  // window.
-  PageFaultObservation third_observation = {
-      800, reference_tick + kObservationWindowLength};
-  escalation_window.AddObservation(third_observation);
-  average = escalation_window.AveragePageFaultRate();
-  EXPECT_NE(base::nullopt, average);
-  double expected_rate =
-      (third_observation.page_fault_count -
-       first_observation.page_fault_count) /
-      (third_observation.timestamp - first_observation.timestamp).InSecondsF();
-  EXPECT_NEAR(expected_rate, average.value(), 0.01);
-
-  EXPECT_EQ(3U, escalation_window.observations().size());
-
-  // Adding an observation that should force the removal of the first one.
-  PageFaultObservation fourth_observation = {
-      1200, third_observation.timestamp +
-                (second_observation.timestamp - first_observation.timestamp)};
-  escalation_window.AddObservation(fourth_observation);
-  average = escalation_window.AveragePageFaultRate();
-  EXPECT_NE(base::nullopt, average);
-  expected_rate = (fourth_observation.page_fault_count -
-                   second_observation.page_fault_count) /
-                  (fourth_observation.timestamp - second_observation.timestamp)
-                      .InSecondsF();
-  EXPECT_NEAR(expected_rate, average.value(), 0.01);
-  EXPECT_EQ(3U, escalation_window.observations().size());
-
-  // And finally add an observation that should force the removal of all the
-  // previous ones expect the last 2.
-  PageFaultObservation fifth_observation = {
-      fourth_observation.page_fault_count,
-      fourth_observation.timestamp + kObservationWindowLength * 2};
-  escalation_window.AddObservation(fifth_observation);
-  average = escalation_window.AveragePageFaultRate();
-  EXPECT_NE(base::nullopt, average);
-  expected_rate =
-      (fifth_observation.page_fault_count -
-       fourth_observation.page_fault_count) /
-      (fifth_observation.timestamp - fourth_observation.timestamp).InSecondsF();
-  EXPECT_NEAR(expected_rate, average.value(), 0.01);
-  EXPECT_EQ(2U, escalation_window.observations().size());
-}
-
-}  // namespace memory
diff --git a/chrome/browser/metrics/antivirus_metrics_provider_win.cc b/chrome/browser/metrics/antivirus_metrics_provider_win.cc
index 06ba011..2e6f90d 100644
--- a/chrome/browser/metrics/antivirus_metrics_provider_win.cc
+++ b/chrome/browser/metrics/antivirus_metrics_provider_win.cc
@@ -234,7 +234,7 @@
   base::AssertBlockingAllowed();
   base::win::ScopedCOMInitializer com_initializer;
 
-  if (!com_initializer.succeeded())
+  if (!com_initializer.Succeeded())
     return RESULT_FAILED_TO_INITIALIZE_COM;
 
   Microsoft::WRL::ComPtr<IWSCProductList> product_list;
@@ -335,7 +335,7 @@
   base::AssertBlockingAllowed();
   base::win::ScopedCOMInitializer com_initializer;
 
-  if (!com_initializer.succeeded())
+  if (!com_initializer.Succeeded())
     return RESULT_FAILED_TO_INITIALIZE_COM;
 
   Microsoft::WRL::ComPtr<IWbemLocator> wmi_locator;
diff --git a/chrome/browser/metrics/perf/perf_output.cc b/chrome/browser/metrics/perf/perf_output.cc
index 2006625bb..093df81 100644
--- a/chrome/browser/metrics/perf/perf_output.cc
+++ b/chrome/browser/metrics/perf/perf_output.cc
@@ -18,12 +18,13 @@
       weak_factory_(this) {
   DCHECK(thread_checker_.CalledOnValidThread());
 
-  perf_data_pipe_reader_.reset(new chromeos::PipeReaderForString(
-      base::CreateTaskRunnerWithTraits(
-          {base::MayBlock(), base::TaskPriority::USER_VISIBLE}),
-      base::Bind(&PerfOutputCall::OnIOComplete, weak_factory_.GetWeakPtr())));
+  perf_data_pipe_reader_ =
+      std::make_unique<chromeos::PipeReader>(base::CreateTaskRunnerWithTraits(
+          {base::MayBlock(), base::TaskPriority::USER_VISIBLE}));
 
-  base::ScopedFD pipe_write_end = perf_data_pipe_reader_->StartIO();
+  base::ScopedFD pipe_write_end =
+      perf_data_pipe_reader_->StartIO(base::BindOnce(
+          &PerfOutputCall::OnIOComplete, weak_factory_.GetWeakPtr()));
   chromeos::DebugDaemonClient* client =
       chromeos::DBusThreadManager::Get()->GetDebugDaemonClient();
   client->GetPerfOutput(duration_, perf_args_, pipe_write_end.get(),
@@ -33,13 +34,10 @@
 
 PerfOutputCall::~PerfOutputCall() {}
 
-void PerfOutputCall::OnIOComplete() {
+void PerfOutputCall::OnIOComplete(base::Optional<std::string> result) {
   DCHECK(thread_checker_.CalledOnValidThread());
-
-  std::string stdout_data;
-  perf_data_pipe_reader_->GetData(&stdout_data);
-
-  done_callback_.Run(stdout_data);
+  perf_data_pipe_reader_.reset();
+  done_callback_.Run(result.value_or(std::string()));
   // The callback may delete us, so it's hammertime: Can't touch |this|.
 }
 
@@ -47,7 +45,9 @@
                                           const std::string& error_message) {
   DCHECK(thread_checker_.CalledOnValidThread());
 
-  // Signal pipe reader to shut down. This will cause
-  // OnIOComplete to be called, probably with an empty string.
-  perf_data_pipe_reader_->OnDataReady(-1);
+  // Signal pipe reader to shut down.
+  if (perf_data_pipe_reader_.get()) {
+    perf_data_pipe_reader_.reset();
+    done_callback_.Run(std::string());
+  }
 }
diff --git a/chrome/browser/metrics/perf/perf_output.h b/chrome/browser/metrics/perf/perf_output.h
index 0a2ad05..c5e8117 100644
--- a/chrome/browser/metrics/perf/perf_output.h
+++ b/chrome/browser/metrics/perf/perf_output.h
@@ -11,6 +11,7 @@
 
 #include "base/memory/ref_counted.h"
 #include "base/memory/weak_ptr.h"
+#include "base/optional.h"
 #include "base/threading/thread_checker.h"
 #include "base/time/time.h"
 #include "chromeos/dbus/pipe_reader.h"
@@ -34,12 +35,12 @@
 
  private:
   // Internal callbacks.
-  void OnIOComplete();
+  void OnIOComplete(base::Optional<std::string> data);
   void OnGetPerfOutputError(const std::string& error_name,
                             const std::string& error_message);
 
   // Used to capture perf data written to a pipe.
-  std::unique_ptr<chromeos::PipeReaderForString> perf_data_pipe_reader_;
+  std::unique_ptr<chromeos::PipeReader> perf_data_pipe_reader_;
 
   // Saved arguments.
   base::TimeDelta duration_;
diff --git a/chrome/browser/metrics/thread_watcher.cc b/chrome/browser/metrics/thread_watcher.cc
index fce991e..17b13f10 100644
--- a/chrome/browser/metrics/thread_watcher.cc
+++ b/chrome/browser/metrics/thread_watcher.cc
@@ -466,13 +466,11 @@
     crash_on_hang_thread_names =
         command_line.GetSwitchValueASCII(switches::kCrashOnHangThreads);
   } else if (channel != version_info::Channel::STABLE) {
-    // Default to crashing the browser if UI or IO or FILE threads are not
-    // responsive except in stable channel.
-    crash_on_hang_thread_names = base::StringPrintf(
-        "UI:%d:%d,IO:%d:%d,FILE:%d:%d",
-        kLiveThreadsThreshold, crash_seconds,
-        kLiveThreadsThreshold, crash_seconds,
-        kLiveThreadsThreshold, crash_seconds * 5);
+    // Default to crashing the browser if UI or IO threads are not responsive
+    // except in stable channel.
+    crash_on_hang_thread_names =
+        base::StringPrintf("UI:%d:%d,IO:%d:%d", kLiveThreadsThreshold,
+                           crash_seconds, kLiveThreadsThreshold, crash_seconds);
   }
 
   ParseCommandLineCrashOnHangThreads(crash_on_hang_thread_names,
@@ -552,12 +550,6 @@
                 unresponsive_threshold, crash_on_hang_threads);
   StartWatching(BrowserThread::IO, "IO", kSleepTime, kUnresponsiveTime,
                 unresponsive_threshold, crash_on_hang_threads);
-  StartWatching(BrowserThread::DB, "DB", kSleepTime, kUnresponsiveTime,
-                unresponsive_threshold, crash_on_hang_threads);
-  StartWatching(BrowserThread::FILE, "FILE", kSleepTime, kUnresponsiveTime,
-                unresponsive_threshold, crash_on_hang_threads);
-  StartWatching(BrowserThread::CACHE, "CACHE", kSleepTime, kUnresponsiveTime,
-                unresponsive_threshold, crash_on_hang_threads);
 }
 
 // static
diff --git a/chrome/browser/metrics/thread_watcher_report_hang.cc b/chrome/browser/metrics/thread_watcher_report_hang.cc
index 93fd6c6..7bae67a 100644
--- a/chrome/browser/metrics/thread_watcher_report_hang.cc
+++ b/chrome/browser/metrics/thread_watcher_report_hang.cc
@@ -50,36 +50,12 @@
   ReportThreadHang();
 }
 
-NOINLINE void ThreadUnresponsive_DB() {
-  volatile int inhibit_comdat = __LINE__;
-  ALLOW_UNUSED_LOCAL(inhibit_comdat);
-  ReportThreadHang();
-}
-
-NOINLINE void ThreadUnresponsive_FILE() {
-  volatile int inhibit_comdat = __LINE__;
-  ALLOW_UNUSED_LOCAL(inhibit_comdat);
-  ReportThreadHang();
-}
-
-NOINLINE void ThreadUnresponsive_FILE_USER_BLOCKING() {
-  volatile int inhibit_comdat = __LINE__;
-  ALLOW_UNUSED_LOCAL(inhibit_comdat);
-  ReportThreadHang();
-}
-
 NOINLINE void ThreadUnresponsive_PROCESS_LAUNCHER() {
   volatile int inhibit_comdat = __LINE__;
   ALLOW_UNUSED_LOCAL(inhibit_comdat);
   ReportThreadHang();
 }
 
-NOINLINE void ThreadUnresponsive_CACHE() {
-  volatile int inhibit_comdat = __LINE__;
-  ALLOW_UNUSED_LOCAL(inhibit_comdat);
-  ReportThreadHang();
-}
-
 NOINLINE void ThreadUnresponsive_IO() {
   volatile int inhibit_comdat = __LINE__;
   ALLOW_UNUSED_LOCAL(inhibit_comdat);
@@ -91,19 +67,16 @@
   switch (thread_id) {
     case content::BrowserThread::UI:
       return ThreadUnresponsive_UI();
-    case content::BrowserThread::DB:
-      return ThreadUnresponsive_DB();
-    case content::BrowserThread::FILE:
-      return ThreadUnresponsive_FILE();
-    case content::BrowserThread::FILE_USER_BLOCKING:
-      return ThreadUnresponsive_FILE_USER_BLOCKING();
     case content::BrowserThread::PROCESS_LAUNCHER:
       return ThreadUnresponsive_PROCESS_LAUNCHER();
-    case content::BrowserThread::CACHE:
-      return ThreadUnresponsive_CACHE();
     case content::BrowserThread::IO:
       return ThreadUnresponsive_IO();
     case content::BrowserThread::ID_COUNT:
+    // TODO(gab): Get rid of deprecated BrowserThread IDs.
+    case content::BrowserThread::DB:
+    case content::BrowserThread::FILE:
+    case content::BrowserThread::FILE_USER_BLOCKING:
+    case content::BrowserThread::CACHE:
       NOTREACHED();
       break;
   }
diff --git a/chrome/browser/net/nqe/ui_network_quality_estimator_service.cc b/chrome/browser/net/nqe/ui_network_quality_estimator_service.cc
index a118d4e..08cbedb 100644
--- a/chrome/browser/net/nqe/ui_network_quality_estimator_service.cc
+++ b/chrome/browser/net/nqe/ui_network_quality_estimator_service.cc
@@ -150,7 +150,7 @@
     : type_(net::EFFECTIVE_CONNECTION_TYPE_UNKNOWN),
       http_rtt_(net::nqe::internal::InvalidRTT()),
       transport_rtt_(net::nqe::internal::InvalidRTT()),
-      downstream_throughput_kbps_(net::nqe::internal::kInvalidThroughput),
+      downstream_throughput_kbps_(net::nqe::internal::INVALID_RTT_THROUGHPUT),
       weak_factory_(this) {
   DCHECK(profile);
   // If this is running in a context without an IOThread, don't try to create
@@ -264,7 +264,7 @@
 UINetworkQualityEstimatorService::GetDownstreamThroughputKbps() const {
   DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
 
-  if (downstream_throughput_kbps_ == net::nqe::internal::kInvalidThroughput)
+  if (downstream_throughput_kbps_ == net::nqe::internal::INVALID_RTT_THROUGHPUT)
     return base::Optional<int32_t>();
   return downstream_throughput_kbps_;
 }
diff --git a/chrome/browser/notifications/notification_template_builder.cc b/chrome/browser/notifications/notification_template_builder.cc
index ecb2b13..bb14a94 100644
--- a/chrome/browser/notifications/notification_template_builder.cc
+++ b/chrome/browser/notifications/notification_template_builder.cc
@@ -4,10 +4,13 @@
 
 #include "chrome/browser/notifications/notification_template_builder.h"
 
+#include "base/i18n/time_formatting.h"
 #include "base/memory/ptr_util.h"
 #include "base/strings/string_number_conversions.h"
 #include "base/strings/string_util.h"
+#include "base/strings/stringprintf.h"
 #include "base/strings/utf_string_conversions.h"
+#include "base/time/time.h"
 #include "components/url_formatter/elide_url.h"
 #include "third_party/libxml/chromium/libxml_utils.h"
 #include "ui/message_center/notification.h"
@@ -39,6 +42,7 @@
 const char kTextElement[] = "text";
 const char kToastElement[] = "toast";
 const char kToastElementLaunchAttribute[] = "launch";
+const char kToastElementDisplayTimestamp[] = "displayTimestamp";
 const char kVisualElement[] = "visual";
 
 // Name of the template used for default Chrome notifications.
@@ -58,7 +62,7 @@
 
   // TODO(finnur): Can we set <toast scenario="reminder"> for notifications
   // that have set the never_timeout() flag?
-  builder->StartToastElement(notification_id);
+  builder->StartToastElement(notification_id, notification.timestamp());
   builder->StartVisualElement();
 
   // TODO(finnur): Set the correct binding template based on the |notification|.
@@ -114,9 +118,20 @@
 }
 
 void NotificationTemplateBuilder::StartToastElement(
-    const std::string& notification_id) {
+    const std::string& notification_id,
+    const base::Time& timestamp) {
   xml_writer_->StartElement(kToastElement);
   xml_writer_->AddAttribute(kToastElementLaunchAttribute, notification_id);
+
+  if (!timestamp.is_null()) {
+    base::Time::Exploded exploded;
+    timestamp.UTCExplode(&exploded);
+    xml_writer_->AddAttribute(
+        kToastElementDisplayTimestamp,
+        base::StringPrintf("%04d-%02d-%02dT%02d:%02d:%02dZ", exploded.year,
+                           exploded.month, exploded.day_of_month, exploded.hour,
+                           exploded.minute, exploded.second));
+  }
 }
 
 void NotificationTemplateBuilder::EndToastElement() {
diff --git a/chrome/browser/notifications/notification_template_builder.h b/chrome/browser/notifications/notification_template_builder.h
index 9b4ca345..4de2eadf 100644
--- a/chrome/browser/notifications/notification_template_builder.h
+++ b/chrome/browser/notifications/notification_template_builder.h
@@ -15,6 +15,10 @@
 class GURL;
 class XmlWriter;
 
+namespace base {
+class Time;
+}
+
 namespace message_center {
 struct ButtonInfo;
 class Notification;
@@ -51,7 +55,8 @@
 
   // Writes the <toast> element with the |notification_id| as the launch string.
   // Also closes the |xml_writer_| for writing as the toast is now complete.
-  void StartToastElement(const std::string& notification_id);
+  void StartToastElement(const std::string& notification_id,
+                         const base::Time& timastamp);
   void EndToastElement();
 
   // Writes the <visual> element.
diff --git a/chrome/browser/notifications/notification_template_builder_unittest.cc b/chrome/browser/notifications/notification_template_builder_unittest.cc
index cab5bc5..0bce7984 100644
--- a/chrome/browser/notifications/notification_template_builder_unittest.cc
+++ b/chrome/browser/notifications/notification_template_builder_unittest.cc
@@ -25,35 +25,66 @@
 const char kNotificationMessage[] = "My Message";
 const char kNotificationOrigin[] = "https://example.com";
 
+// Intermediary format for the options available when creating a notification,
+// with default values specific to this test suite to avoid endless repetition.
+struct NotificationData {
+  NotificationData()
+      : id(kNotificationId),
+        title(kNotificationTitle),
+        message(kNotificationMessage),
+        origin(kNotificationOrigin) {}
+
+  std::string id;
+  std::string title;
+  std::string message;
+  GURL origin;
 };
 
+bool FixedTime(base::Time* time) {
+  base::Time::Exploded exploded = {0};
+  exploded.year = 1998;
+  exploded.month = 9;
+  exploded.day_of_month = 4;
+  exploded.hour = 1;
+  exploded.minute = 2;
+  exploded.second = 3;
+  return base::Time::FromUTCExploded(exploded, time);
+}
+
+}  // namespace
+
 class NotificationTemplateBuilderTest : public ::testing::Test {
  public:
   NotificationTemplateBuilderTest() = default;
   ~NotificationTemplateBuilderTest() override = default;
 
  protected:
-  // Builds a notification object and initializes it to default values.
-  std::unique_ptr<message_center::Notification> InitializeBasicNotification() {
-    GURL origin_url(kNotificationOrigin);
+  // Builds the message_center::Notification object and then the template for
+  // the given |notification_data|, and writes that to |*xml_template|. Calls
+  // must be wrapped in ASSERT_NO_FATAL_FAILURE().
+  void BuildTemplate(const NotificationData& notification_data,
+                     const std::vector<message_center::ButtonInfo>& buttons,
+                     base::string16* xml_template) {
+    GURL origin_url(notification_data.origin);
 
-    return std::make_unique<message_center::Notification>(
-        message_center::NOTIFICATION_TYPE_SIMPLE, kNotificationId,
-        base::UTF8ToUTF16(kNotificationTitle),
-        base::UTF8ToUTF16(kNotificationMessage), gfx::Image() /* icon */,
+    message_center::Notification notification(
+        message_center::NOTIFICATION_TYPE_SIMPLE, notification_data.id,
+        base::UTF8ToUTF16(notification_data.title),
+        base::UTF8ToUTF16(notification_data.message), gfx::Image() /* icon */,
         base::string16() /* display_source */, origin_url,
         NotifierId(origin_url), RichNotificationData(), nullptr /* delegate */);
-  }
+    // TODO(finnur): Test with null timestamp.
+    base::Time timestamp;
+    ASSERT_TRUE(FixedTime(&timestamp));
+    notification.set_timestamp(timestamp);
+    if (buttons.size())
+      notification.set_buttons(buttons);
 
-  // Converts the notification data to XML and verifies it is as expected. Calls
-  // must be wrapped in ASSERT_NO_FATAL_FAILURE().
-  void VerifyXml(const message_center::Notification& notification,
-                 const base::string16& xml_template) {
     template_ =
-        NotificationTemplateBuilder::Build(kNotificationId, notification);
+        NotificationTemplateBuilder::Build(notification_data.id, notification);
     ASSERT_TRUE(template_);
 
-    EXPECT_EQ(template_->GetNotificationTemplate(), xml_template);
+    *xml_template = template_->GetNotificationTemplate();
   }
 
  protected:
@@ -64,11 +95,15 @@
 };
 
 TEST_F(NotificationTemplateBuilderTest, SimpleToast) {
-  std::unique_ptr<message_center::Notification> notification =
-      InitializeBasicNotification();
+  NotificationData notification_data;
+  base::string16 xml_template;
+  std::vector<message_center::ButtonInfo> buttons;
+
+  ASSERT_NO_FATAL_FAILURE(
+      BuildTemplate(notification_data, buttons, &xml_template));
 
   const wchar_t kExpectedXml[] =
-      LR"(<toast launch="notification_id">
+      LR"(<toast launch="notification_id" displayTimestamp="1998-09-04T01:02:03Z">
  <visual>
   <binding template="ToastGeneric">
    <text>My Title</text>
@@ -79,20 +114,22 @@
 </toast>
 )";
 
-  ASSERT_NO_FATAL_FAILURE(VerifyXml(*notification, kExpectedXml));
+  EXPECT_EQ(xml_template, kExpectedXml);
 }
 
 TEST_F(NotificationTemplateBuilderTest, Buttons) {
-  std::unique_ptr<message_center::Notification> notification =
-      InitializeBasicNotification();
+  NotificationData notification_data;
+  base::string16 xml_template;
 
   std::vector<message_center::ButtonInfo> buttons;
   buttons.emplace_back(base::ASCIIToUTF16("Button1"));
   buttons.emplace_back(base::ASCIIToUTF16("Button2"));
-  notification->set_buttons(buttons);
+
+  ASSERT_NO_FATAL_FAILURE(
+      BuildTemplate(notification_data, buttons, &xml_template));
 
   const wchar_t kExpectedXml[] =
-      LR"(<toast launch="notification_id">
+      LR"(<toast launch="notification_id" displayTimestamp="1998-09-04T01:02:03Z">
  <visual>
   <binding template="ToastGeneric">
    <text>My Title</text>
@@ -107,12 +144,12 @@
 </toast>
 )";
 
-  ASSERT_NO_FATAL_FAILURE(VerifyXml(*notification, kExpectedXml));
+  EXPECT_EQ(xml_template, kExpectedXml);
 }
 
 TEST_F(NotificationTemplateBuilderTest, InlineReplies) {
-  std::unique_ptr<message_center::Notification> notification =
-      InitializeBasicNotification();
+  NotificationData notification_data;
+  base::string16 xml_template;
 
   std::vector<message_center::ButtonInfo> buttons;
   message_center::ButtonInfo button1(base::ASCIIToUTF16("Button1"));
@@ -120,10 +157,12 @@
   button1.placeholder = base::ASCIIToUTF16("Reply here");
   buttons.emplace_back(button1);
   buttons.emplace_back(base::ASCIIToUTF16("Button2"));
-  notification->set_buttons(buttons);
+
+  ASSERT_NO_FATAL_FAILURE(
+      BuildTemplate(notification_data, buttons, &xml_template));
 
   const wchar_t kExpectedXml[] =
-      LR"(<toast launch="notification_id">
+      LR"(<toast launch="notification_id" displayTimestamp="1998-09-04T01:02:03Z">
  <visual>
   <binding template="ToastGeneric">
    <text>My Title</text>
@@ -139,12 +178,12 @@
 </toast>
 )";
 
-  ASSERT_NO_FATAL_FAILURE(VerifyXml(*notification, kExpectedXml));
+  EXPECT_EQ(xml_template, kExpectedXml);
 }
 
 TEST_F(NotificationTemplateBuilderTest, InlineRepliesDoubleInput) {
-  std::unique_ptr<message_center::Notification> notification =
-      InitializeBasicNotification();
+  NotificationData notification_data;
+  base::string16 xml_template;
 
   std::vector<message_center::ButtonInfo> buttons;
   message_center::ButtonInfo button1(base::ASCIIToUTF16("Button1"));
@@ -155,10 +194,12 @@
   button2.type = message_center::ButtonType::TEXT;
   button2.placeholder = base::ASCIIToUTF16("Should not appear");
   buttons.emplace_back(button2);
-  notification->set_buttons(buttons);
+
+  ASSERT_NO_FATAL_FAILURE(
+      BuildTemplate(notification_data, buttons, &xml_template));
 
   const wchar_t kExpectedXml[] =
-      LR"(<toast launch="notification_id">
+      LR"(<toast launch="notification_id" displayTimestamp="1998-09-04T01:02:03Z">
  <visual>
   <binding template="ToastGeneric">
    <text>My Title</text>
@@ -174,12 +215,12 @@
 </toast>
 )";
 
-  ASSERT_NO_FATAL_FAILURE(VerifyXml(*notification, kExpectedXml));
+  EXPECT_EQ(xml_template, kExpectedXml);
 }
 
 TEST_F(NotificationTemplateBuilderTest, InlineRepliesTextTypeNotFirst) {
-  std::unique_ptr<message_center::Notification> notification =
-      InitializeBasicNotification();
+  NotificationData notification_data;
+  base::string16 xml_template;
 
   std::vector<message_center::ButtonInfo> buttons;
   buttons.emplace_back(base::ASCIIToUTF16("Button1"));
@@ -187,10 +228,12 @@
   button2.type = message_center::ButtonType::TEXT;
   button2.placeholder = base::ASCIIToUTF16("Reply here");
   buttons.emplace_back(button2);
-  notification->set_buttons(buttons);
+
+  ASSERT_NO_FATAL_FAILURE(
+      BuildTemplate(notification_data, buttons, &xml_template));
 
   const wchar_t kExpectedXml[] =
-      LR"(<toast launch="notification_id">
+      LR"(<toast launch="notification_id" displayTimestamp="1998-09-04T01:02:03Z">
  <visual>
   <binding template="ToastGeneric">
    <text>My Title</text>
@@ -206,26 +249,5 @@
 </toast>
 )";
 
-  ASSERT_NO_FATAL_FAILURE(VerifyXml(*notification, kExpectedXml));
-}
-
-TEST_F(NotificationTemplateBuilderTest, Silent) {
-  std::unique_ptr<message_center::Notification> notification =
-      InitializeBasicNotification();
-  notification->set_silent(true);
-
-  const wchar_t kExpectedXml[] =
-      LR"(<toast launch="notification_id">
- <visual>
-  <binding template="ToastGeneric">
-   <text>My Title</text>
-   <text>My Message</text>
-   <text placement="attribution">example.com</text>
-  </binding>
- </visual>
- <audio silent="true"/>
-</toast>
-)";
-
-  ASSERT_NO_FATAL_FAILURE(VerifyXml(*notification, kExpectedXml));
+  EXPECT_EQ(xml_template, kExpectedXml);
 }
diff --git a/chrome/browser/notifications/platform_notification_service_impl.cc b/chrome/browser/notifications/platform_notification_service_impl.cc
index 7122d6fe..e795e88a 100644
--- a/chrome/browser/notifications/platform_notification_service_impl.cc
+++ b/chrome/browser/notifications/platform_notification_service_impl.cc
@@ -75,25 +75,6 @@
 // permission without having an associated renderer process yet.
 const int kInvalidRenderProcessId = -1;
 
-void OnCloseNonPersistentNotificationProfileLoaded(
-    const std::string& notification_id,
-    Profile* profile) {
-  NotificationDisplayServiceFactory::GetForProfile(profile)->Close(
-      NotificationCommon::NON_PERSISTENT, notification_id);
-}
-
-// Callback used to close an non-persistent notification from blink.
-void CancelNotification(const std::string& notification_id,
-                        std::string profile_id,
-                        bool incognito) {
-  ProfileManager* profile_manager = g_browser_process->profile_manager();
-  DCHECK(profile_manager);
-  profile_manager->LoadProfile(
-      profile_id, incognito,
-      base::Bind(&OnCloseNonPersistentNotificationProfileLoaded,
-                 notification_id));
-}
-
 void ReportNotificationImageOnIOThread(
     scoped_refptr<safe_browsing::SafeBrowsingService> safe_browsing_service,
     Profile* profile,
@@ -310,8 +291,7 @@
     const std::string& notification_id,
     const GURL& origin,
     const content::PlatformNotificationData& notification_data,
-    const content::NotificationResources& notification_resources,
-    base::Closure* cancel_callback) {
+    const content::NotificationResources& notification_resources) {
   DCHECK_CURRENTLY_ON(BrowserThread::UI);
 
   // Posted tasks can request notifications to be added, which would cause a
@@ -333,16 +313,6 @@
 
   NotificationDisplayServiceFactory::GetForProfile(profile)->Display(
       NotificationCommon::NON_PERSISTENT, notification_id, notification);
-  if (cancel_callback) {
-#if defined(OS_WIN)
-    std::string profile_id =
-        base::WideToUTF8(profile->GetPath().BaseName().value());
-#elif defined(OS_POSIX)
-    std::string profile_id = profile->GetPath().BaseName().value();
-#endif
-    *cancel_callback = base::Bind(&CancelNotification, notification_id,
-                                  profile_id, profile->IsOffTheRecord());
-  }
 }
 
 void PlatformNotificationServiceImpl::DisplayPersistentNotification(
@@ -377,6 +347,18 @@
   base::RecordAction(base::UserMetricsAction("Notifications.Persistent.Shown"));
 }
 
+void PlatformNotificationServiceImpl::CloseNotification(
+    BrowserContext* browser_context,
+    const std::string& notification_id) {
+  DCHECK_CURRENTLY_ON(BrowserThread::UI);
+
+  Profile* profile = Profile::FromBrowserContext(browser_context);
+  DCHECK(profile);
+
+  NotificationDisplayServiceFactory::GetForProfile(profile)->Close(
+      NotificationCommon::NON_PERSISTENT, notification_id);
+}
+
 void PlatformNotificationServiceImpl::ClosePersistentNotification(
     BrowserContext* browser_context,
     const std::string& notification_id) {
diff --git a/chrome/browser/notifications/platform_notification_service_impl.h b/chrome/browser/notifications/platform_notification_service_impl.h
index e001b1d..484bc76c 100644
--- a/chrome/browser/notifications/platform_notification_service_impl.h
+++ b/chrome/browser/notifications/platform_notification_service_impl.h
@@ -80,8 +80,7 @@
       const std::string& notification_id,
       const GURL& origin,
       const content::PlatformNotificationData& notification_data,
-      const content::NotificationResources& notification_resources,
-      base::Closure* cancel_callback) override;
+      const content::NotificationResources& notification_resources) override;
   void DisplayPersistentNotification(
       content::BrowserContext* browser_context,
       const std::string& notification_id,
@@ -89,6 +88,8 @@
       const GURL& origin,
       const content::PlatformNotificationData& notification_data,
       const content::NotificationResources& notification_resources) override;
+  void CloseNotification(content::BrowserContext* browser_context,
+                         const std::string& notification_id) override;
   void ClosePersistentNotification(content::BrowserContext* browser_context,
                                    const std::string& notification_id) override;
   void GetDisplayedNotifications(
diff --git a/chrome/browser/notifications/platform_notification_service_unittest.cc b/chrome/browser/notifications/platform_notification_service_unittest.cc
index 08bd8de..672d9b7 100644
--- a/chrome/browser/notifications/platform_notification_service_unittest.cc
+++ b/chrome/browser/notifications/platform_notification_service_unittest.cc
@@ -70,19 +70,6 @@
   }
 
  protected:
-  // Displays a simple, fake notification. The close closure may be specified if
-  // desired.
-  void CreateSimplePageNotificationWithCloseClosure(
-      base::Closure* close_closure) {
-    PlatformNotificationData notification_data;
-    notification_data.title = base::ASCIIToUTF16("My Notification");
-    notification_data.body = base::ASCIIToUTF16("Hello, world!");
-
-    service()->DisplayNotification(
-        profile_, kNotificationId, GURL("https://chrome.com/"),
-        notification_data, NotificationResources(), close_closure);
-  }
-
   // Returns the Platform Notification Service these unit tests are for.
   PlatformNotificationServiceImpl* service() const {
     return PlatformNotificationServiceImpl::GetInstance();
@@ -110,21 +97,22 @@
   std::unique_ptr<NotificationDisplayServiceTester> display_service_tester_;
 };
 
+TEST_F(PlatformNotificationServiceTest, DisplayNonPersistentClosure) {
+  PlatformNotificationData notification_data;
+  notification_data.title = base::ASCIIToUTF16("My Notification");
+  notification_data.body = base::ASCIIToUTF16("Hello, world!");
 
-TEST_F(PlatformNotificationServiceTest, DisplayPageCloseClosure) {
-  base::Closure close_closure;
-  CreateSimplePageNotificationWithCloseClosure(&close_closure);
+  service()->DisplayNotification(profile_, kNotificationId,
+                                 GURL("https://chrome.com/"), notification_data,
+                                 NotificationResources());
 
   EXPECT_EQ(1u,
             GetNotificationCountForType(NotificationCommon::NON_PERSISTENT));
 
-  ASSERT_FALSE(close_closure.is_null());
-  close_closure.Run();
+  service()->CloseNotification(profile_, kNotificationId);
 
   EXPECT_EQ(0u,
             GetNotificationCountForType(NotificationCommon::NON_PERSISTENT));
-  // Note that we cannot verify whether the closed event was called on the
-  // delegate given that it'd result in a use-after-free.
 }
 
 TEST_F(PlatformNotificationServiceTest, PersistentNotificationDisplay) {
@@ -163,7 +151,7 @@
 
   service()->DisplayNotification(profile_, kNotificationId,
                                  GURL("https://chrome.com/"), notification_data,
-                                 NotificationResources(), nullptr);
+                                 NotificationResources());
 
   ASSERT_EQ(1u,
             GetNotificationCountForType(NotificationCommon::NON_PERSISTENT));
diff --git a/chrome/browser/ntp_snippets/content_suggestions_service_factory.cc b/chrome/browser/ntp_snippets/content_suggestions_service_factory.cc
index 80ee01e..515c067 100644
--- a/chrome/browser/ntp_snippets/content_suggestions_service_factory.cc
+++ b/chrome/browser/ntp_snippets/content_suggestions_service_factory.cc
@@ -341,7 +341,7 @@
   OAuth2TokenService* token_service =
       ProfileOAuth2TokenServiceFactory::GetForProfile(profile);
   UrlLanguageHistogram* language_histogram =
-      UrlLanguageHistogramFactory::GetInstance()->GetForBrowserContext(profile);
+      UrlLanguageHistogramFactory::GetForBrowserContext(profile);
 
   scoped_refptr<net::URLRequestContextGetter> request_context =
       content::BrowserContext::GetDefaultStoragePartition(profile)
diff --git a/chrome/browser/performance_monitor/process_metrics_history.cc b/chrome/browser/performance_monitor/process_metrics_history.cc
index 558ed70..582eae3 100644
--- a/chrome/browser/performance_monitor/process_metrics_history.cc
+++ b/chrome/browser/performance_monitor/process_metrics_history.cc
@@ -79,7 +79,9 @@
 
 void ProcessMetricsHistory::SampleMetrics() {
   cpu_usage_ = process_metrics_->GetPlatformIndependentCPUUsage();
+#if defined(OS_MACOSX) || defined(OS_LINUX) || defined(OS_AIX)
   idle_wakeups_ = process_metrics_->GetIdleWakeupsPerSecond();
+#endif
 #if defined(OS_MACOSX)
   package_idle_wakeups_ = process_metrics_->GetPackageIdleWakeupsPerSecond();
 #endif
@@ -105,8 +107,10 @@
         UMA_HISTOGRAM_BOOLEAN("PerformanceMonitor.HighCPU.BrowserProcess",
                               true);
       }
+#if defined(OS_MACOSX) || defined(OS_LINUX) || defined(OS_AIX)
       UMA_HISTOGRAM_COUNTS_10000(
           "PerformanceMonitor.IdleWakeups.BrowserProcess", idle_wakeups_);
+#endif
 #if defined(OS_MACOSX)
       UMA_HISTOGRAM_COUNTS_1000(
           "PerformanceMonitor.PackageExitIdleWakeups.BrowserProcess",
@@ -121,8 +125,10 @@
         UMA_HISTOGRAM_BOOLEAN("PerformanceMonitor.HighCPU.RendererProcess",
                               true);
       }
+#if defined(OS_MACOSX) || defined(OS_LINUX) || defined(OS_AIX)
       UMA_HISTOGRAM_COUNTS_10000(
           "PerformanceMonitor.IdleWakeups.RendererProcess", idle_wakeups_);
+#endif
 #if defined(OS_MACOSX)
       UMA_HISTOGRAM_COUNTS_1000(
           "PerformanceMonitor.PackageExitIdleWakeups.RendererProcess",
@@ -136,8 +142,10 @@
                                   kHistogramBucketCount);
       if (cpu_usage_ > kHighCPUUtilizationThreshold)
         UMA_HISTOGRAM_BOOLEAN("PerformanceMonitor.HighCPU.GPUProcess", true);
+#if defined(OS_MACOSX) || defined(OS_LINUX) || defined(OS_AIX)
       UMA_HISTOGRAM_COUNTS_10000("PerformanceMonitor.IdleWakeups.GPUProcess",
                                  idle_wakeups_);
+#endif
 #if defined(OS_MACOSX)
       UMA_HISTOGRAM_COUNTS_1000(
           "PerformanceMonitor.PackageExitIdleWakeups.GPUProcess",
diff --git a/chrome/browser/performance_monitor/process_metrics_history.h b/chrome/browser/performance_monitor/process_metrics_history.h
index 2a4a7c5..651b5bd 100644
--- a/chrome/browser/performance_monitor/process_metrics_history.h
+++ b/chrome/browser/performance_monitor/process_metrics_history.h
@@ -70,7 +70,9 @@
 
   double cpu_usage_;
 
+#if defined(OS_MACOSX) || defined(OS_LINUX) || defined(OS_AIX)
   int idle_wakeups_;
+#endif
 #if defined(OS_MACOSX)
   int package_idle_wakeups_;
 #endif
diff --git a/chrome/browser/printing/pwg_raster_converter_browsertest.cc b/chrome/browser/printing/pwg_raster_converter_browsertest.cc
index f7c3ebf..fcc9c5eb 100644
--- a/chrome/browser/printing/pwg_raster_converter_browsertest.cc
+++ b/chrome/browser/printing/pwg_raster_converter_browsertest.cc
@@ -8,9 +8,12 @@
 #include "base/memory/ref_counted_memory.h"
 #include "base/path_service.h"
 #include "base/run_loop.h"
+#include "base/sha1.h"
+#include "base/strings/string_number_conversions.h"
 #include "base/threading/thread_restrictions.h"
 #include "build/build_config.h"
 #include "chrome/browser/printing/pwg_raster_converter.h"
+#include "chrome/common/chrome_paths.h"
 #include "printing/pdf_render_settings.h"
 #include "printing/pwg_raster_settings.h"
 
@@ -56,6 +59,11 @@
   std::unique_ptr<PWGRasterConverter> converter_;
 };
 
+std::string HashFile(const std::string& file_data) {
+  std::string sha1 = base::SHA1HashString(file_data);
+  return base::HexEncode(sha1.c_str(), sha1.length());
+}
+
 }  // namespace
 
 IN_PROC_BROWSER_TEST_F(PDFToPWGRasterBrowserTest, TestFailure) {
@@ -70,9 +78,10 @@
   base::ScopedAllowBlockingForTesting allow_blocking;
 
   base::FilePath test_data_dir;
-  ASSERT_TRUE(PathService::Get(base::DIR_SOURCE_ROOT, &test_data_dir));
-  base::FilePath pdf_file = test_data_dir.AppendASCII(
-      "chrome/test/data/printing/pdf_to_pwg_raster_test.pdf");
+  ASSERT_TRUE(PathService::Get(chrome::DIR_TEST_DATA, &test_data_dir));
+  test_data_dir = test_data_dir.AppendASCII("printing");
+  base::FilePath pdf_file =
+      test_data_dir.AppendASCII("pdf_to_pwg_raster_test.pdf");
   std::string pdf_data_str;
   ASSERT_TRUE(base::ReadFileToString(pdf_file, &pdf_data_str));
   ASSERT_GT(pdf_data_str.length(), 0U);
@@ -96,16 +105,17 @@
   // platform (32 or 64 bits) on Linux.
   base::FilePath pwg_file = test_data_dir.AppendASCII(
 #if defined(OS_LINUX) && defined(ARCH_CPU_32_BITS)
-      "chrome/test/data/printing/pdf_to_pwg_raster_test_32.pwg");
+      "pdf_to_pwg_raster_test_32.pwg");
 #else
-      "chrome/test/data/printing/pdf_to_pwg_raster_test.pwg");
+      "pdf_to_pwg_raster_test.pwg");
 #endif
 
   std::string pwg_expected_data_str;
   ASSERT_TRUE(base::ReadFileToString(pwg_file, &pwg_expected_data_str));
   std::string pwg_actual_data_str;
   ASSERT_TRUE(base::ReadFileToString(temp_file, &pwg_actual_data_str));
-  ASSERT_EQ(pwg_expected_data_str, pwg_actual_data_str);
+  EXPECT_EQ(pwg_expected_data_str.length(), pwg_actual_data_str.length());
+  EXPECT_EQ(HashFile(pwg_expected_data_str), HashFile(pwg_actual_data_str));
 }
 
 }  // namespace printing
diff --git a/chrome/browser/profiles/host_zoom_map_browsertest.cc b/chrome/browser/profiles/host_zoom_map_browsertest.cc
index e15e821..080230d 100644
--- a/chrome/browser/profiles/host_zoom_map_browsertest.cc
+++ b/chrome/browser/profiles/host_zoom_map_browsertest.cc
@@ -131,7 +131,7 @@
   }
 
   std::string GetSigninPromoURL() {
-    return signin::GetPromoURL(
+    return signin::GetPromoURLForTab(
                signin_metrics::AccessPoint::ACCESS_POINT_START_PAGE,
                signin_metrics::Reason::REASON_SIGNIN_PRIMARY_ACCOUNT, false)
         .spec();
diff --git a/chrome/browser/profiles/off_the_record_profile_impl.cc b/chrome/browser/profiles/off_the_record_profile_impl.cc
index 86fbbab..3e80507 100644
--- a/chrome/browser/profiles/off_the_record_profile_impl.cc
+++ b/chrome/browser/profiles/off_the_record_profile_impl.cc
@@ -467,6 +467,15 @@
   return ChromeBrowsingDataRemoverDelegateFactory::GetForProfile(this);
 }
 
+media::VideoDecodePerfHistory*
+OffTheRecordProfileImpl::GetVideoDecodePerfHistory() {
+  // Defer to the original profile for VideoDecodePerfHistory. The incognito
+  // profile will have no history of its own (we don't save it for incognito)
+  // and the two profiles should have the same video performance. The history is
+  // not exposed directly to the web, so privacy is not compromised.
+  return GetOriginalProfile()->GetVideoDecodePerfHistory();
+}
+
 bool OffTheRecordProfileImpl::IsSameProfile(Profile* profile) {
   return (profile == this) || (profile == profile_);
 }
diff --git a/chrome/browser/profiles/off_the_record_profile_impl.h b/chrome/browser/profiles/off_the_record_profile_impl.h
index 116b307..f0b7cb5 100644
--- a/chrome/browser/profiles/off_the_record_profile_impl.h
+++ b/chrome/browser/profiles/off_the_record_profile_impl.h
@@ -111,6 +111,7 @@
   content::BackgroundSyncController* GetBackgroundSyncController() override;
   content::BrowsingDataRemoverDelegate* GetBrowsingDataRemoverDelegate()
       override;
+  media::VideoDecodePerfHistory* GetVideoDecodePerfHistory() override;
 
  private:
   void InitIoData();
diff --git a/chrome/browser/renderer_context_menu/render_view_context_menu.cc b/chrome/browser/renderer_context_menu/render_view_context_menu.cc
index df319d3..c858e8c7 100644
--- a/chrome/browser/renderer_context_menu/render_view_context_menu.cc
+++ b/chrome/browser/renderer_context_menu/render_view_context_menu.cc
@@ -945,8 +945,7 @@
   std::unique_ptr<translate::TranslatePrefs> prefs(
       ChromeTranslateClient::CreateTranslatePrefs(GetPrefs(browser_context_)));
   language::LanguageModel* language_model =
-      LanguageModelFactory::GetInstance()->GetForBrowserContext(
-          browser_context_);
+      LanguageModelFactory::GetForBrowserContext(browser_context_);
   return translate::TranslateManager::GetTargetLanguage(prefs.get(),
                                                         language_model);
 }
@@ -1925,7 +1924,7 @@
       break;
 
     case IDC_VIEW_SOURCE:
-      embedder_web_contents_->ViewSource();
+      embedder_web_contents_->GetMainFrame()->ViewSource();
       break;
 
     case IDC_CONTENT_CONTEXT_INSPECTELEMENT:
@@ -1948,8 +1947,8 @@
       break;
 
     case IDC_CONTENT_CONTEXT_VIEWFRAMESOURCE:
-      source_web_contents_->ViewFrameSource(params_.frame_url,
-                                            params_.frame_page_state);
+      if (GetRenderFrameHost())
+        GetRenderFrameHost()->ViewSource();
       break;
 
     case IDC_CONTENT_CONTEXT_UNDO:
diff --git a/chrome/browser/renderer_context_menu/render_view_context_menu_browsertest.cc b/chrome/browser/renderer_context_menu/render_view_context_menu_browsertest.cc
index acd678e..5576784 100644
--- a/chrome/browser/renderer_context_menu/render_view_context_menu_browsertest.cc
+++ b/chrome/browser/renderer_context_menu/render_view_context_menu_browsertest.cc
@@ -252,8 +252,6 @@
     content::ContextMenuParams params;
     params.page_url = page_url;
     params.frame_url = frame->GetLastCommittedURL();
-    params.frame_page_state =
-        content::PageState::CreateFromURL(params.frame_url);
     params.media_type = blink::WebContextMenuData::kMediaTypePlugin;
     TestRenderViewContextMenu menu(frame, params);
     menu.Init();
@@ -1025,7 +1023,6 @@
   content::ContextMenuParams params;
   params.page_url = page_url;
   params.frame_url = frame->GetLastCommittedURL();
-  params.frame_page_state = content::PageState::CreateFromURL(params.frame_url);
   params.media_type = blink::WebContextMenuData::kMediaTypePlugin;
   TestRenderViewContextMenu menu(frame, params);
   menu.Init();
diff --git a/chrome/browser/resources/chromeos/bluetooth_dialog_host.html b/chrome/browser/resources/chromeos/bluetooth_dialog_host.html
index 1973abc..f545f4e 100644
--- a/chrome/browser/resources/chromeos/bluetooth_dialog_host.html
+++ b/chrome/browser/resources/chromeos/bluetooth_dialog_host.html
@@ -12,7 +12,7 @@
     </style>
 
     <bluetooth-dialog id="deviceDialog"
-        title="[[i18n('bluetoothPairDevicePageTitle')]]"
+        dialog-title="[[i18n('bluetoothPairDevicePageTitle')]]"
         on-close="onDialogClose_"
         pairing-device="[[pairingDevice_]]">
     </bluetooth-dialog>
diff --git a/chrome/browser/resources/chromeos/internet_config_dialog.html b/chrome/browser/resources/chromeos/internet_config_dialog.html
index 68e2b9c6..14636cc 100644
--- a/chrome/browser/resources/chromeos/internet_config_dialog.html
+++ b/chrome/browser/resources/chromeos/internet_config_dialog.html
@@ -28,16 +28,14 @@
   <template>
     <style include="network-shared iron-flex">
       .button-strip {
+        border-top: var(--cr-separator-line);
         justify-content: flex-end;
       }
 
       .section {
         @apply(--cr-section);
-        margin-bottom: 10px;
-      }
-
-      .section.first {
         border-top: none;
+        margin-bottom: 10px;
       }
 
       .section.single-column {
@@ -56,15 +54,18 @@
         font-size: 107.69%;  /* 14px / 13px */
         font-weight: 500;
       }
+
+      network-config {
+        /* Give the network-config section some extra padding for the dialog. */
+        -webkit-padding-start: 20px;
+      }
     </style>
 
     <!-- Title section: Icon + name. -->
-    <div class="section first">
-      <div class="start layout horizontal center">
-        <cr-network-icon network-state="[[networkProperties_]]" is-list-item>
-        </cr-network-icon>
-        <div class="title">[[getTitle_(networkProperties_.*)]]</div>
-      </div>
+    <div class="section layout horizontal center">
+      <cr-network-icon network-state="[[networkProperties_]]" is-list-item>
+      </cr-network-icon>
+      <div class="title">[[getDialogTitle_(networkProperties_)]]</div>
     </div>
 
     <div class="section single-column">
diff --git a/chrome/browser/resources/chromeos/internet_config_dialog.js b/chrome/browser/resources/chromeos/internet_config_dialog.js
index 31deee1d..741fa9a 100644
--- a/chrome/browser/resources/chromeos/internet_config_dialog.js
+++ b/chrome/browser/resources/chromeos/internet_config_dialog.js
@@ -84,9 +84,9 @@
    * @return {string}
    * @private
    */
-  getTitle_: function() {
-    return this.networkProperties_.Name ||
-        this.i18n('OncType' + this.networkProperties_.Type);
+  getDialogTitle_: function() {
+    var type = this.i18n('OncType' + this.networkProperties_.Type);
+    return this.i18n('internetJoinType', type);
   },
 
   /** @private */
diff --git a/chrome/browser/resources/chromeos/internet_detail_dialog.html b/chrome/browser/resources/chromeos/internet_detail_dialog.html
index a00c3ec..a31041f 100644
--- a/chrome/browser/resources/chromeos/internet_detail_dialog.html
+++ b/chrome/browser/resources/chromeos/internet_detail_dialog.html
@@ -15,6 +15,7 @@
 <link rel="import" href="chrome://resources/cr_components/chromeos/network/network_property_list.html">
 <link rel="import" href="chrome://resources/cr_components/chromeos/network/network_proxy.html">
 <link rel="import" href="chrome://resources/cr_components/chromeos/network/network_shared_css.html">
+<link rel="import" href="chrome://resources/cr_components/chromeos/network/network_siminfo.html">
 <link rel="import" href="chrome://resources/cr_elements/chromeos/network/cr_network_icon.html">
 <link rel="import" href="chrome://resources/cr_elements/chromeos/network/cr_onc_types.html">
 <link rel="import" href="chrome://resources/cr_elements/icons.html">
@@ -88,14 +89,15 @@
       </paper-button>
     </div>
 
-    <!-- Device properties (Cellular only) -->
-    <template is="dom-if" if="[[isCellular_(networkProperties)]]">
+    <!-- SIM Info (Cellular only). -->
+    <template is="dom-if" if="[[showCellularSim_(networkProperties)]]"
+        restamp>
       <div class="section single-column">
-        <network-property-list
-            hidden$="[[!hasDeviceFields_(networkProperties)]]"
-            fields="[[getDeviceFields_(networkProperties)]]"
-            property-dict="[[networkProperties]]">
-        </network-property-list>
+        <network-siminfo
+            editable on-siminfo-change="onNetworkPropertyChange_"
+            network-properties="[[networkProperties]]"
+            networking-private="[[networkingPrivate]]">
+        </network-siminfo>
       </div>
     </template>
 
diff --git a/chrome/browser/resources/chromeos/internet_detail_dialog.js b/chrome/browser/resources/chromeos/internet_detail_dialog.js
index 8d229d2..f810020 100644
--- a/chrome/browser/resources/chromeos/internet_detail_dialog.js
+++ b/chrome/browser/resources/chromeos/internet_detail_dialog.js
@@ -225,6 +225,17 @@
    * @return {boolean}
    * @private
    */
+  showCellularSim_: function(networkProperties) {
+    return networkProperties.Type == CrOnc.Type.CELLULAR &&
+        !!networkProperties.Cellular &&
+        networkProperties.Cellular.Family != 'CDMA';
+  },
+
+  /**
+   * @param {!CrOnc.NetworkProperties} networkProperties
+   * @return {boolean}
+   * @private
+   */
   showCellularChooseNetwork_: function(networkProperties) {
     return networkProperties.Type == CrOnc.Type.CELLULAR &&
         !!this.get('Cellular.SupportNetworkScan', this.networkProperties);
@@ -302,6 +313,8 @@
     var onc = this.getEmptyNetworkProperties_();
     if (field == 'APN') {
       CrOnc.setTypeProperty(onc, 'APN', value);
+    } else if (field == 'SIMLockStatus') {
+      CrOnc.setTypeProperty(onc, 'SIMLockStatus', value);
     } else {
       console.error('Unexpected property change event: ' + field);
       return;
@@ -425,29 +438,6 @@
    * @return {boolean}
    * @private
    */
-  hasDeviceFields_: function() {
-    return this.hasVisibleFields_(this.getDeviceFields_());
-  },
-
-  /**
-   * @return {!Array<string>} The fields to display in the device section.
-   * @private
-   */
-  getDeviceFields_: function() {
-    /** @type {!Array<string>} */ var fields = [];
-    if (this.networkProperties.Type == CrOnc.Type.CELLULAR) {
-      fields.push(
-          'Cellular.HomeProvider.Name', 'Cellular.ESN', 'Cellular.ICCID',
-          'Cellular.IMEI', 'Cellular.IMSI', 'Cellular.MDN', 'Cellular.MEID',
-          'Cellular.MIN');
-    }
-    return fields;
-  },
-
-  /**
-   * @return {boolean}
-   * @private
-   */
   hasInfoFields_: function() {
     return this.hasVisibleFields_(this.getInfoFields_());
   },
@@ -461,8 +451,11 @@
     var type = this.networkProperties.Type;
     if (type == CrOnc.Type.CELLULAR && !!this.networkProperties.Cellular) {
       fields.push(
+          'Cellular.HomeProvider.Name', 'Cellular.ServingOperator.Name',
           'Cellular.ActivationState', 'Cellular.RoamingState',
-          'RestrictedConnectivity', 'Cellular.ServingOperator.Name');
+          'RestrictedConnectivity', 'Cellular.MEID', 'Cellular.ESN',
+          'Cellular.ICCID', 'Cellular.IMEI', 'Cellular.IMSI', 'Cellular.MDN',
+          'Cellular.MIN');
     } else if (type == CrOnc.Type.WI_FI) {
       fields.push('RestrictedConnectivity');
     } else if (type == CrOnc.Type.WI_MAX) {
diff --git a/chrome/browser/resources/chromeos/login/screen_gaia_signin.js b/chrome/browser/resources/chromeos/login/screen_gaia_signin.js
index 0732821b..5dbc5a7 100644
--- a/chrome/browser/resources/chromeos/login/screen_gaia_signin.js
+++ b/chrome/browser/resources/chromeos/login/screen_gaia_signin.js
@@ -1017,7 +1017,10 @@
       }
 
       this.loading = true;
+      // Hide the back button and the border line as they are not useful
+      // when the loading screen is shown.
       $('signin-back-button').hidden = true;
+      $('signin-frame-dialog').setAttribute('hide-shadow', true);
 
       // Now that we're in logged in state header should be hidden.
       Oobe.getInstance().headerHidden = true;
diff --git a/chrome/browser/resources/chromeos/login/screen_supervised_user_creation.css b/chrome/browser/resources/chromeos/login/screen_supervised_user_creation.css
index fda6cbb..0af0542 100644
--- a/chrome/browser/resources/chromeos/login/screen_supervised_user_creation.css
+++ b/chrome/browser/resources/chromeos/login/screen_supervised_user_creation.css
@@ -420,10 +420,6 @@
   display: none;
 }
 
-.camera #supervised-user-creation-image-preview-img {
-  transform: rotateY(180deg);
-}
-
 .default-image #supervised-user-creation-image-preview-img {
   background: white;
   border: solid 1px #cacaca;
diff --git a/chrome/browser/resources/chromeos/user_images_grid.js b/chrome/browser/resources/chromeos/user_images_grid.js
index 1d6b5ef..9ea6d1d 100644
--- a/chrome/browser/resources/chromeos/user_images_grid.js
+++ b/chrome/browser/resources/chromeos/user_images_grid.js
@@ -462,9 +462,10 @@
         this.cameraTitle_ = this.capturedImageTitle_;
         this.cameraImage = previewImg.src;
       }.bind(this));
-      previewImg.src = canvas.toDataURL('image/png');
+      var imageUrl = this.flipFrame_(canvas);
+      previewImg.src = imageUrl;
       var e = new Event('phototaken');
-      e.dataURL = this.flipFrame_(canvas);
+      e.dataURL = imageUrl;
       this.dispatchEvent(e);
       return true;
     },
diff --git a/chrome/browser/resources/md_extensions/compiled_resources2.gyp b/chrome/browser/resources/md_extensions/compiled_resources2.gyp
index 7689bd4..9a12bf8 100644
--- a/chrome/browser/resources/md_extensions/compiled_resources2.gyp
+++ b/chrome/browser/resources/md_extensions/compiled_resources2.gyp
@@ -21,6 +21,7 @@
         '<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:load_time_data',
         '<(EXTERNS_GYP):developer_private',
         'item',
+        'item_behavior',
         'item_util',
         'navigation_helper',
       ],
@@ -75,12 +76,21 @@
         '<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:i18n_behavior',
         '<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:load_time_data',
         '<(EXTERNS_GYP):developer_private',
+        'item_behavior',
         'item_util',
         'navigation_helper',
       ],
       'includes': ['../../../../third_party/closure_compiler/compile_js2.gypi'],
     },
     {
+      'target_name': 'item_behavior',
+      'dependencies': [
+        '<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:cr',
+        '<(EXTERNS_GYP):developer_private',
+      ],
+      'includes': ['../../../../third_party/closure_compiler/compile_js2.gypi'],
+    },
+    {
       'target_name': 'item_list',
       'dependencies': [
         '<(DEPTH)/ui/webui/resources/cr_elements/compiled_resources2.gyp:cr_container_shadow_behavior',
@@ -110,6 +120,7 @@
         '<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:assert',
         '<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:cr',
         '<(EXTERNS_GYP):developer_private',
+        'item_behavior',
       ],
       'includes': ['../../../../third_party/closure_compiler/compile_js2.gypi'],
     },
@@ -117,6 +128,7 @@
       'target_name': 'kiosk_browser_proxy',
       'dependencies': [
         '<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:cr',
+        'item_behavior',
       ],
       'includes': ['../../../../third_party/closure_compiler/compile_js2.gypi'],
     },
@@ -175,6 +187,7 @@
         '<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:assert',
         '<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:cr',
         '<(EXTERNS_GYP):developer_private',
+        'item_behavior',
         'navigation_helper',
       ],
       'includes': ['../../../../third_party/closure_compiler/compile_js2.gypi'],
diff --git a/chrome/browser/resources/md_extensions/detail_view.html b/chrome/browser/resources/md_extensions/detail_view.html
index be807b8..554ce7d 100644
--- a/chrome/browser/resources/md_extensions/detail_view.html
+++ b/chrome/browser/resources/md_extensions/detail_view.html
@@ -16,6 +16,7 @@
 <link rel="import" href="chrome://resources/polymer/v1_0/iron-icons/iron-icons.html">
 <link rel="import" href="chrome://resources/polymer/v1_0/paper-icon-button/paper-icon-button-light.html">
 <link rel="import" href="chrome://resources/polymer/v1_0/paper-styles/color.html">
+<link rel="import" href="item_behavior.html">
 <link rel="import" href="item_util.html">
 <link rel="import" href="navigation_helper.html">
 <link rel="import" href="strings.html">
@@ -176,7 +177,11 @@
           <button id="close-button" is="paper-icon-button-light"
               class="icon-arrow-back no-overlap"
               on-tap="onCloseButtonTap_"></button>
-          <img alt="" id="icon" src="[[data.iconUrl]]">
+          <img id="icon" src="[[data.iconUrl]]"
+              alt$="[[appOrExtension(
+                  data.type,
+                  '$i18nPolymer{appIcon}',
+                  '$i18nPolymer{extensionIcon}')]]">
           <span id="name">[[data.name]]</span>
         </div>
         <div class="section continuation control-line" id="enable-section">
@@ -190,6 +195,11 @@
                 icon-aria-label="[[data.controlledInfo.type]]">
             </cr-tooltip-icon>
             <cr-toggle id="enable-toggle"
+                aria-label$="[[appOrExtension(
+                    data.type,
+                    '$i18nPolymer{appEnabled}',
+                    '$i18nPolymer{extensionEnabled}')]]"
+                aria-describedby="name"
                 checked="[[isEnabled_(data.state)]]"
                 on-change="onEnableChange_"
                 disabled="[[!isEnableToggleEnabled_(data.*)]]">
diff --git a/chrome/browser/resources/md_extensions/detail_view.js b/chrome/browser/resources/md_extensions/detail_view.js
index c351593..74255a8 100644
--- a/chrome/browser/resources/md_extensions/detail_view.js
+++ b/chrome/browser/resources/md_extensions/detail_view.js
@@ -8,7 +8,11 @@
   const DetailView = Polymer({
     is: 'extensions-detail-view',
 
-    behaviors: [I18nBehavior, CrContainerShadowBehavior],
+    behaviors: [
+      I18nBehavior,
+      CrContainerShadowBehavior,
+      extensions.ItemBehavior,
+    ],
 
     properties: {
       /**
diff --git a/chrome/browser/resources/md_extensions/extensions_resources.grd b/chrome/browser/resources/md_extensions/extensions_resources.grd
index b5d2188..9b45a8e1 100644
--- a/chrome/browser/resources/md_extensions/extensions_resources.grd
+++ b/chrome/browser/resources/md_extensions/extensions_resources.grd
@@ -12,6 +12,12 @@
   </outputs>
   <release seq="1">
     <structures>
+      <structure name="IDR_MD_EXTENSIONS_ITEM_BEHAVIOR_HTML"
+                 file="item_behavior.html"
+                 type="chrome_html" />
+      <structure name="IDR_MD_EXTENSIONS_ITEM_BEHAVIOR_JS"
+                 file="item_behavior.js"
+                 type="chrome_html" />
       <structure name="IDR_MD_EXTENSIONS_EXTENSIONS_HTML"
                  file="extensions.html"
                  flattenhtml="true"
diff --git a/chrome/browser/resources/md_extensions/item.html b/chrome/browser/resources/md_extensions/item.html
index f8090b51..32e77470 100644
--- a/chrome/browser/resources/md_extensions/item.html
+++ b/chrome/browser/resources/md_extensions/item.html
@@ -9,6 +9,7 @@
 <link rel="import" href="chrome://resources/html/assert.html">
 <link rel="import" href="chrome://resources/html/cr.html">
 <link rel="import" href="chrome://resources/html/i18n_behavior.html">
+<link rel="import" href="item_behavior.html">
 <link rel="import" href="icons.html">
 <link rel="import" href="item_util.html">
 <link rel="import" href="strings.html">
@@ -190,7 +191,11 @@
           </div>
         </template>
         <div id="icon-wrapper">
-          <img alt="" id="icon" src="[[data.iconUrl]]">
+          <img id="icon" src="[[data.iconUrl]]"
+              alt$="[[appOrExtension(
+                  data.type,
+                  '$i18nPolymer{appIcon}',
+                  '$i18nPolymer{extensionIcon}')]]">
         </div>
         <div id="content">
           <div id="name-and-version" class="layout horizontal center">
@@ -268,6 +273,11 @@
           $i18n{itemReload}
         </paper-button>
         <cr-toggle id="enable-toggle" class="action-button"
+            aria-label$="[[appOrExtension(
+                data.type,
+                '$i18nPolymer{appEnabled}',
+                '$i18nPolymer{extensionEnabled}')]]"
+            aria-describedby="name"
             checked="[[isEnabled_(data.state)]]" on-change="onEnableChange_"
             disabled="[[!isEnableToggleEnabled_(data.*)]]"
             hidden$="[[!showEnableToggle_(data.*)]]">
diff --git a/chrome/browser/resources/md_extensions/item.js b/chrome/browser/resources/md_extensions/item.js
index f76a9fc..29ff232 100644
--- a/chrome/browser/resources/md_extensions/item.js
+++ b/chrome/browser/resources/md_extensions/item.js
@@ -57,7 +57,7 @@
   const Item = Polymer({
     is: 'extensions-item',
 
-    behaviors: [I18nBehavior],
+    behaviors: [I18nBehavior, extensions.ItemBehavior],
 
     properties: {
       // The item's delegate, or null.
diff --git a/chrome/browser/resources/md_extensions/item_behavior.html b/chrome/browser/resources/md_extensions/item_behavior.html
new file mode 100644
index 0000000..b0369e6
--- /dev/null
+++ b/chrome/browser/resources/md_extensions/item_behavior.html
@@ -0,0 +1 @@
+<script src="item_behavior.js"></script>
diff --git a/chrome/browser/resources/md_extensions/item_behavior.js b/chrome/browser/resources/md_extensions/item_behavior.js
new file mode 100644
index 0000000..9abf7df
--- /dev/null
+++ b/chrome/browser/resources/md_extensions/item_behavior.js
@@ -0,0 +1,22 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+cr.define('extensions', function() {
+  /** @polymerBehavior */
+  const ItemBehavior = {
+    /**
+     * @param {chrome.developerPrivate.ExtensionType} type
+     * @param {string} appLabel
+     * @param {string} extensionLabel
+     * @return {string} The app or extension label depending on |type|.
+     */
+    appOrExtension: function(type, appLabel, extensionLabel) {
+      return (type == chrome.developerPrivate.ExtensionType.EXTENSION) ?
+          extensionLabel :
+          appLabel;
+    },
+  };
+
+  return {ItemBehavior: ItemBehavior};
+});
diff --git a/chrome/browser/resources/md_extensions/keyboard_shortcuts.html b/chrome/browser/resources/md_extensions/keyboard_shortcuts.html
index ecde827..1e38e2a 100644
--- a/chrome/browser/resources/md_extensions/keyboard_shortcuts.html
+++ b/chrome/browser/resources/md_extensions/keyboard_shortcuts.html
@@ -7,6 +7,7 @@
 <link rel="import" href="chrome://resources/html/md_select_css.html">
 <link rel="import" href="chrome://resources/polymer/v1_0/paper-styles/color.html">
 <link rel="import" href="chrome://resources/polymer/v1_0/paper-styles/shadow.html">
+<link rel="import" href="item_behavior.html">
 <link rel="import" href="shortcut_input.html">
 
 <dom-module id="extensions-keyboard-shortcuts">
@@ -84,15 +85,19 @@
       <template is="dom-repeat" items="[[calculateShownItems_(items.*)]]">
         <div class="shortcut-card">
           <div class="card-title">
-            <img class="icon" src="[[item.iconUrl]]">
+            <img class="icon" src="[[item.iconUrl]]"
+                alt$="[[appOrExtension(
+                    data.type,
+                    '$i18nPolymer{appIcon}',
+                    '$i18nPolymer{extensionIcon}')]]">
             <span>[[item.name]]</span>
           </div>
           <div class="card-controls">
             <template is="dom-repeat" items="[[item.commands]]" as="command">
               <div class="command-entry" command="[[command]]">
                 <span class="command-name">[[command.description]]</span>
-                <extensions-shortcut-input item="[[item.id]]"
-                    shortcut="[[command.keybinding]]"
+                <extensions-shortcut-input delegate="[[delegate]]"
+                    item="[[item.id]]" shortcut="[[command.keybinding]]"
                     command-name="[[command.name]]">
                 </extensions-shortcut-input>
                 <div class="md-select-wrapper">
diff --git a/chrome/browser/resources/md_extensions/keyboard_shortcuts.js b/chrome/browser/resources/md_extensions/keyboard_shortcuts.js
index e75b5ce..f0c98326 100644
--- a/chrome/browser/resources/md_extensions/keyboard_shortcuts.js
+++ b/chrome/browser/resources/md_extensions/keyboard_shortcuts.js
@@ -9,7 +9,7 @@
   const KeyboardShortcuts = Polymer({
     is: 'extensions-keyboard-shortcuts',
 
-    behaviors: [CrContainerShadowBehavior],
+    behaviors: [CrContainerShadowBehavior, extensions.ItemBehavior],
 
     properties: {
       /** @type {Array<!chrome.developerPrivate.ExtensionInfo>} */
diff --git a/chrome/browser/resources/md_extensions/kiosk_dialog.html b/chrome/browser/resources/md_extensions/kiosk_dialog.html
index 51100a4ec5..2709a386 100644
--- a/chrome/browser/resources/md_extensions/kiosk_dialog.html
+++ b/chrome/browser/resources/md_extensions/kiosk_dialog.html
@@ -12,6 +12,7 @@
 <link rel="import" href="chrome://resources/polymer/v1_0/paper-checkbox/paper-checkbox.html">
 <link rel="import" href="chrome://resources/polymer/v1_0/paper-icon-button/paper-icon-button-light.html">
 <link rel="import" href="chrome://resources/polymer/v1_0/paper-input/paper-input.html">
+<link rel="import" href="item_behavior.html">
 <link rel="import" href="kiosk_browser_proxy.html">
 
 <dom-module id="extensions-kiosk-dialog">
@@ -82,7 +83,11 @@
           <template is="dom-repeat" items="[[apps_]]">
             <div class="list-item">
               <div class="item-name">
-                <img class="item-icon" src="[[item.iconURL]]">
+                <img class="item-icon" src="[[item.iconURL]]"
+                    alt$="[[appOrExtension(
+                        data.type,
+                        '$i18nPolymer{appIcon}',
+                        '$i18nPolymer{extensionIcon}')]]">
                 [[item.name]]
                 <span hidden="[[!item.autoLaunch]]">
                   $i18n{kioskAutoLaunch}
diff --git a/chrome/browser/resources/md_extensions/kiosk_dialog.js b/chrome/browser/resources/md_extensions/kiosk_dialog.js
index 254c2c1..66ada3f 100644
--- a/chrome/browser/resources/md_extensions/kiosk_dialog.js
+++ b/chrome/browser/resources/md_extensions/kiosk_dialog.js
@@ -7,7 +7,7 @@
 
   const KioskDialog = Polymer({
     is: 'extensions-kiosk-dialog',
-    behaviors: [WebUIListenerBehavior],
+    behaviors: [WebUIListenerBehavior, extensions.ItemBehavior],
     properties: {
       /** @private {?string} */
       addAppInput_: {
diff --git a/chrome/browser/resources/md_extensions/manager.html b/chrome/browser/resources/md_extensions/manager.html
index 1e3bab0..0244796 100644
--- a/chrome/browser/resources/md_extensions/manager.html
+++ b/chrome/browser/resources/md_extensions/manager.html
@@ -1,6 +1,7 @@
 <link rel="import" href="chrome://resources/html/polymer.html">
 
 <link rel="import" href="chrome://resources/cr_elements/cr_drawer/cr_drawer.html">
+<link rel="import" href="chrome://resources/cr_elements/cr_lazy_render/cr_lazy_render.html">
 <link rel="import" href="chrome://resources/cr_elements/cr_toolbar/cr_toolbar.html">
 <link rel="import" href="chrome://resources/cr_elements/hidden_style_css.html">
 <link rel="import" href="chrome://resources/html/assert.html">
@@ -79,16 +80,21 @@
           filter="[[filter]]" hidden$="[[!didInitPage_]]" slot="view"
           apps="[[apps]]" extensions="[[extensions]]">
       </extensions-item-list>
-      <extensions-detail-view id="details-view" delegate="[[delegate]]"
-          in-dev-mode="[[inDevMode]]" data="[[detailViewItem_]]"
-          slot="view">
-      </extensions-detail-view>
-      <extensions-keyboard-shortcuts id="keyboard-shortcuts"
-          items="[[extensions]]" slot="view">
-      </extensions-keyboard-shortcuts>
-      <extensions-error-page id="error-page"
-          data="[[errorPageItem_]]" delegate="[[delegate]]" slot="view">
-      </extensions-error-page>
+      <template id="details-view" is="cr-lazy-render">
+        <extensions-detail-view delegate="[[delegate]]" slot="view"
+            in-dev-mode="[[inDevMode]]" data="[[detailViewItem_]]">
+        </extensions-detail-view>
+      </template>
+      <template id="keyboard-shortcuts" is="cr-lazy-render">
+        <extensions-keyboard-shortcuts delegate="[[delegate]]" slot="view"
+            items="[[extensions]]">
+        </extensions-keyboard-shortcuts>
+      </template>
+      <template id="error-page" is="cr-lazy-render">
+        <extensions-error-page data="[[errorPageItem_]]" slot="view"
+            delegate="[[delegate]]" slot="view">
+        </extensions-error-page>
+      </template>
     </extensions-view-manager>
     <template is="dom-if" if="[[showOptionsDialog_]]" restamp>
       <extensions-options-dialog id="options-dialog"
diff --git a/chrome/browser/resources/md_extensions/manager.js b/chrome/browser/resources/md_extensions/manager.js
index b4e94a6..d67863eb 100644
--- a/chrome/browser/resources/md_extensions/manager.js
+++ b/chrome/browser/resources/md_extensions/manager.js
@@ -177,14 +177,6 @@
       this.navigationListener_ = null;
     },
 
-    get keyboardShortcuts() {
-      return this.$['keyboard-shortcuts'];
-    },
-
-    get errorPage() {
-      return this.$['error-page'];
-    },
-
     /**
      * Initializes the page to reflect what's specified in the url so that if
      * the user visits chrome://extensions/?id=..., we land on the proper page.
@@ -325,27 +317,6 @@
     },
 
     /**
-     * @param {Page} page
-     * @return {!(extensions.KeyboardShortcuts |
-     *            extensions.DetailView |
-     *            extensions.ItemList)}
-     * @private
-     */
-    getPage_: function(page) {
-      switch (page) {
-        case Page.LIST:
-          return this.$['items-list'];
-        case Page.DETAILS:
-          return this.$['details-view'];
-        case Page.SHORTCUTS:
-          return this.$['keyboard-shortcuts'];
-        case Page.ERRORS:
-          return this.$['error-page'];
-      }
-      assertNotReached();
-    },
-
-    /**
      * Changes the active page selection.
      * @param {PageState} newPage
      * @private
diff --git a/chrome/browser/resources/md_extensions/options_dialog.html b/chrome/browser/resources/md_extensions/options_dialog.html
index a2d36a8..ef43c8d 100644
--- a/chrome/browser/resources/md_extensions/options_dialog.html
+++ b/chrome/browser/resources/md_extensions/options_dialog.html
@@ -3,6 +3,7 @@
 <link rel="import" href="chrome://resources/cr_elements/cr_dialog/cr_dialog.html">
 <link rel="import" href="chrome://resources/html/assert.html">
 <link rel="import" href="chrome://resources/html/cr.html">
+<link rel="import" href="item_behavior.html">
 <link rel="import" href="navigation_helper.html">
 
 <dom-module id="extensions-options-dialog">
@@ -32,7 +33,11 @@
         on-close="onClose_">
       <div slot="title">
         <div id="icon-and-name-wrapper">
-          <img id="icon" src="[[data_.iconUrl]]">
+          <img id="icon" src="[[data_.iconUrl]]"
+              alt$="[[appOrExtension(
+                  data.type,
+                  '$i18nPolymer{appIcon}',
+                  '$i18nPolymer{extensionIcon}')]]">
           <span>[[data_.name]]</span>
         </div>
       </div>
diff --git a/chrome/browser/resources/md_extensions/options_dialog.js b/chrome/browser/resources/md_extensions/options_dialog.js
index 591c4b70..09eb518 100644
--- a/chrome/browser/resources/md_extensions/options_dialog.js
+++ b/chrome/browser/resources/md_extensions/options_dialog.js
@@ -14,6 +14,9 @@
 
   const OptionsDialog = Polymer({
     is: 'extensions-options-dialog',
+
+    behaviors: [extensions.ItemBehavior],
+
     properties: {
       /** @private {Object} */
       extensionOptions_: Object,
diff --git a/chrome/browser/resources/md_extensions/service.js b/chrome/browser/resources/md_extensions/service.js
index 98132ca..4d5112b 100644
--- a/chrome/browser/resources/md_extensions/service.js
+++ b/chrome/browser/resources/md_extensions/service.js
@@ -37,15 +37,6 @@
         return;
       }
 
-      const keyboardShortcuts = this.manager_.keyboardShortcuts;
-      keyboardShortcuts.addEventListener(
-          'shortcut-updated', this.onExtensionCommandUpdated_.bind(this));
-      keyboardShortcuts.addEventListener(
-          'shortcut-capture-started',
-          this.onShortcutCaptureChanged_.bind(this, true));
-      keyboardShortcuts.addEventListener(
-          'shortcut-capture-ended',
-          this.onShortcutCaptureChanged_.bind(this, false));
       chrome.developerPrivate.onProfileStateChanged.addListener(
           this.onProfileStateChanged_.bind(this));
       chrome.developerPrivate.onItemStateChanged.addListener(
@@ -135,14 +126,15 @@
 
     /**
      * Updates an extension command.
-     * @param {!CustomEvent} e
-     * @private
+     * @param {string} extensionId
+     * @param {string} commandName
+     * @param {string} keybinding
      */
-    onExtensionCommandUpdated_(e) {
+    updateExtensionCommand(extensionId, commandName, keybinding) {
       chrome.developerPrivate.updateExtensionCommand({
-        extensionId: e.detail.item,
-        commandName: e.detail.commandName,
-        keybinding: e.detail.keybinding,
+        extensionId: extensionId,
+        commandName: commandName,
+        keybinding: keybinding,
       });
     }
 
@@ -154,10 +146,8 @@
      * the default handling on the event also does this. Investigate more in the
      * future.
      * @param {boolean} isCapturing
-     * @param {!CustomEvent} e
-     * @private
      */
-    onShortcutCaptureChanged_(isCapturing, e) {
+    setShortcutHandlingSuspended(isCapturing) {
       chrome.developerPrivate.setShortcutHandlingSuspended(isCapturing);
     }
 
diff --git a/chrome/browser/resources/md_extensions/shortcut_input.js b/chrome/browser/resources/md_extensions/shortcut_input.js
index a6abd7b3..6622e67 100644
--- a/chrome/browser/resources/md_extensions/shortcut_input.js
+++ b/chrome/browser/resources/md_extensions/shortcut_input.js
@@ -12,23 +12,30 @@
     behaviors: [I18nBehavior],
 
     properties: {
+      /** @type {!Object} */
+      delegate: Object,
+
       item: {
         type: String,
         value: '',
       },
+
       commandName: {
         type: String,
         value: '',
       },
+
       shortcut: {
         type: String,
         value: '',
       },
+
       /** @private */
       capturing_: {
         type: Boolean,
         value: false,
       },
+
       /** @private */
       pendingShortcut_: {
         type: String,
@@ -36,6 +43,7 @@
       },
     },
 
+    /** @override */
     ready: function() {
       const node = this.$['input'];
       node.addEventListener('mouseup', this.startCapture_.bind(this));
@@ -50,7 +58,7 @@
       if (this.capturing_)
         return;
       this.capturing_ = true;
-      this.fire('shortcut-capture-started');
+      this.delegate.setShortcutHandlingSuspended(true);
     },
 
     /** @private */
@@ -60,7 +68,7 @@
       this.pendingShortcut_ = '';
       this.capturing_ = false;
       this.$['input'].blur();
-      this.fire('shortcut-capture-ended');
+      this.delegate.setShortcutHandlingSuspended(false);
     },
 
     /**
@@ -131,11 +139,8 @@
     /** @private */
     commitPending_: function() {
       this.shortcut = this.pendingShortcut_;
-      this.fire('shortcut-updated', {
-        keybinding: this.shortcut,
-        item: this.item,
-        commandName: this.commandName
-      });
+      this.delegate.updateExtensionCommand(
+          this.item, this.commandName, this.shortcut);
     },
 
     /**
diff --git a/chrome/browser/resources/md_extensions/sidebar.html b/chrome/browser/resources/md_extensions/sidebar.html
index 8a450ef4c..f7a68767 100644
--- a/chrome/browser/resources/md_extensions/sidebar.html
+++ b/chrome/browser/resources/md_extensions/sidebar.html
@@ -2,7 +2,6 @@
 
 <link rel="import" href="chrome://resources/html/cr.html">
 <link rel="import" href="chrome://resources/polymer/v1_0/paper-icon-button/paper-icon-button-light.html">
-<link rel="import" href="chrome://resources/polymer/v1_0/paper-item/paper-item.html">
 <link rel="import" href="chrome://resources/polymer/v1_0/paper-menu/paper-menu.html">
 <link rel="import" href="chrome://resources/polymer/v1_0/paper-styles/color.html">
 <link rel="import" href="navigation_helper.html">
@@ -30,19 +29,23 @@
 
       #more-extensions {
         -webkit-padding-end: 16px;
-        align-items: center;
-        display: flex;
         justify-content: space-between;
         text-decoration: none;
       }
 
       .section-item {
         -webkit-padding-start: 24px;
+        align-items: center;
         color: #5A5A5A;
         cursor: pointer;
+        display: flex;
         height: 48px;
       }
 
+      div.section-item {
+        font-size: 123%;  /* 16px when 100% is 13px */
+      }
+
       button[is='paper-icon-button-light'].open-in-new {
         background-image: url(chrome://resources/images/open_in_new.svg);
         background-size: contain;
@@ -51,15 +54,14 @@
       }
     </style>
     <paper-menu id="section-menu" selected="{{selected_}}">
-      <!-- TODO(scottchen): replace paper-item with a simple div. -->
-      <paper-item class="section-item" id="sections-extensions"
+      <div class="section-item" id="sections-extensions"
           on-tap="onExtensionsTap_">
-        <span>$i18n{sidebarExtensions}</span>
-      </paper-item>
-      <paper-item class="section-item" id="sections-shortcuts"
+        $i18n{sidebarExtensions}
+      </div>
+      <div class="section-item" id="sections-shortcuts"
           on-tap="onKeyboardShortcutsTap_">
-        <span>$i18n{keyboardShortcuts}</span>
-      </paper-item>
+        $i18n{keyboardShortcuts}
+      </div>
     </paper-menu>
     <a class="section-item" id="more-extensions" target="_blank"
         href="$i18n{getMoreExtensionsUrl}">
diff --git a/chrome/browser/resources/md_extensions/toolbar.html b/chrome/browser/resources/md_extensions/toolbar.html
index c57b165..4a4781d1 100644
--- a/chrome/browser/resources/md_extensions/toolbar.html
+++ b/chrome/browser/resources/md_extensions/toolbar.html
@@ -40,6 +40,8 @@
 
       #button-strip {
         margin-bottom: 4px;
+        /* Prevent selection of the blank space between buttons. */
+        user-select: none;
         /* We left-align the text of the left button with the left edge of the
            search field. Since the buttons have 12px padding, add 24px to the
            width of the button strip (12px each side) to make centering easy. */
diff --git a/chrome/browser/resources/md_extensions/view_manager.js b/chrome/browser/resources/md_extensions/view_manager.js
index 36e5383..bf2d69e 100644
--- a/chrome/browser/resources/md_extensions/view_manager.js
+++ b/chrome/browser/resources/md_extensions/view_manager.js
@@ -71,19 +71,22 @@
     },
 
     /**
-     * @param {!Element} element
-     * @param {!string} animation
+     * @param {!Element} view
+     * @param {string} animation
      * @return {!Promise}
      * @private
      */
-    enter_: function(element, animation) {
+    enter_: function(view, animation) {
       const animationFunction = extensions.viewAnimations.get(animation);
       assert(animationFunction);
 
-      element.classList.add('active');
-      element.dispatchEvent(new CustomEvent('view-enter-start'));
-      return animationFunction(element).then(function() {
-        element.dispatchEvent(new CustomEvent('view-enter-finish'));
+      let effectiveView =
+          view.matches('[is=cr-lazy-render]') ? view.get() : view;
+
+      effectiveView.classList.add('active');
+      effectiveView.dispatchEvent(new CustomEvent('view-enter-start'));
+      return animationFunction(effectiveView).then(() => {
+        effectiveView.dispatchEvent(new CustomEvent('view-enter-finish'));
       });
     },
 
diff --git a/chrome/browser/resources/md_user_manager/user_manager_pages.html b/chrome/browser/resources/md_user_manager/user_manager_pages.html
index 10f655aa..8a4acecd 100644
--- a/chrome/browser/resources/md_user_manager/user_manager_pages.html
+++ b/chrome/browser/resources/md_user_manager/user_manager_pages.html
@@ -28,7 +28,7 @@
     <neon-animated-pages id="animatedPages" attr-for-selected="id"
         selected="[[selectedPage_]]" entry-animation="fade-in-animation"
         exit-animation="fade-out-animation">
-      <neon-animatable id="create-user-page">
+      <neon-animatable id="create-user-page" on-keydown="stopPropagation_">
         <!-- Keep the page alive while visiting the Learn More page. -->
         <template is="dom-if"
             if="[[isPresentIn_(selectedPage_,
@@ -40,13 +40,15 @@
       <neon-animatable id="user-pods-page">
           <slot></slot>
       </neon-animatable>
-      <neon-animatable id="supervised-learn-more-page">
+      <neon-animatable id="supervised-learn-more-page"
+          on-keydown="stopPropagation_">
         <template is="dom-if"
             if="[[isPresentIn_(selectedPage_, 'supervised-learn-more-page')]]">
           <supervised-user-learn-more></supervised-user-learn-more>
         </template>
       </neon-animatable>
-      <neon-animatable id="supervised-create-confirm-page">
+      <neon-animatable id="supervised-create-confirm-page"
+          on-keydown="stopPropagation_">
         <template is="dom-if"
             if="[[isPresentIn_(selectedPage_,
                                'supervised-create-confirm-page')]]">
diff --git a/chrome/browser/resources/md_user_manager/user_manager_pages.js b/chrome/browser/resources/md_user_manager/user_manager_pages.js
index 39b932f..a579c3d5 100644
--- a/chrome/browser/resources/md_user_manager/user_manager_pages.js
+++ b/chrome/browser/resources/md_user_manager/user_manager_pages.js
@@ -46,6 +46,20 @@
   },
 
   /**
+   * This is to prevent events from propagating to the document element, which
+   * erroneously triggers user-pod selections.
+   *
+   * TODO(scottchen): re-examine if its necessary for user_pod_row.js to bind
+   * listeners on the entire document element.
+   *
+   * @param {!Event} e
+   * @private
+   */
+  stopPropagation_: function(e) {
+    e.stopPropagation();
+  },
+
+  /**
    * Returns True if the first argument is present in the given set of values.
    * @param {string} selectedPage ID of the currently selected page.
    * @param {...string} var_args Pages IDs to check the first argument against.
diff --git a/chrome/browser/resources/print_preview/new/app.html b/chrome/browser/resources/print_preview/new/app.html
index 3f53f832..ae455b6 100644
--- a/chrome/browser/resources/print_preview/new/app.html
+++ b/chrome/browser/resources/print_preview/new/app.html
@@ -1,8 +1,54 @@
 <link rel="import" href="chrome://resources/html/polymer.html">
 
+<link rel="import" href="header.html">
+
 <dom-module id="print-preview-app">
   <template>
-    <p>New Print Preview UI is coming... Stay tuned</p>
+    <style>
+      :host {
+        display: flex;
+        height: 100%;
+      }
+
+      #sidebar {
+        -webkit-border-end: 1px solid #c8c8c8;
+        background-color: white;
+        min-width: 310px;
+      }
+
+      #settings {
+        background: #fbfbfb;
+        border-top: 1px solid #f3f3f3;
+        height: 100%;
+        overflow: auto;
+      }
+
+      #previewArea {
+        -webkit-border-start: 1px solid #dcdcdc;
+        align-items: center;
+        background-color: #e6e6e6;
+        display: flex;
+        flex: 1;
+        justify-content: center;
+      }
+    </style>
+    <div id="sidebar">
+      <print-preview-header></print-preview-header>
+      <div id="settings">
+        <div>Destination</div>
+        <div>Pages</div>
+        <div>Copies</div>
+        <div>Layout</div>
+        <div>Color</div>
+        <div>Paper size</div>
+        <div>Margins</div>
+        <div>Quality</div>
+        <div>Scale</div>
+        <div>Options</div>
+        <div>Advanced</div>
+      </div>
+    </div>
+    <div id="previewArea">preview area</div>
   </template>
   <script src="app.js"></script>
 </dom-module>
diff --git a/chrome/browser/resources/print_preview/new/header.html b/chrome/browser/resources/print_preview/new/header.html
new file mode 100644
index 0000000..cb12fa70
--- /dev/null
+++ b/chrome/browser/resources/print_preview/new/header.html
@@ -0,0 +1,15 @@
+<link rel="import" href="chrome://resources/html/polymer.html">
+
+<dom-module id="print-preview-header">
+  <template>
+    <style>
+      :host {
+        background-color: #f6f6f6;
+        border-bottom: 1px solid #d2d2d2;
+        display: block;
+      }
+    </style>
+    <div>Header</div>
+  </template>
+  <script src="header.js"></script>
+</dom-module>
diff --git a/chrome/browser/resources/print_preview/new/header.js b/chrome/browser/resources/print_preview/new/header.js
new file mode 100644
index 0000000..724824b9
--- /dev/null
+++ b/chrome/browser/resources/print_preview/new/header.js
@@ -0,0 +1,7 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+Polymer({
+  is: 'print-preview-header',
+});
diff --git a/chrome/browser/resources/print_preview/print_preview_new.html b/chrome/browser/resources/print_preview/print_preview_new.html
index 4a56952..03281d37 100644
--- a/chrome/browser/resources/print_preview/print_preview_new.html
+++ b/chrome/browser/resources/print_preview/print_preview_new.html
@@ -5,6 +5,15 @@
   <title></title>
 </head>
 <body>
+  <style>
+    html,
+    body {
+      height: 100%;
+      margin: 0;
+      overflow: hidden;
+      width: 100%;
+    }
+  </style>
   <print-preview-app></print-preview-app>
   <link rel="import" href="new/app.html">
 </body>
diff --git a/chrome/browser/resources/print_preview/print_preview_resources.grd b/chrome/browser/resources/print_preview/print_preview_resources.grd
index 9dbfb7e3..3cb8a8b 100644
--- a/chrome/browser/resources/print_preview/print_preview_resources.grd
+++ b/chrome/browser/resources/print_preview/print_preview_resources.grd
@@ -23,6 +23,12 @@
       <structure name="IDR_PRINT_PREVIEW_NEW_APP_JS"
                  file="new/app.js"
                  type="chrome_html" />
+      <structure name="IDR_PRINT_PREVIEW_NEW_HEADER_HTML"
+                 file="new/header.html"
+                 type="chrome_html" />
+      <structure name="IDR_PRINT_PREVIEW_NEW_HEADER_JS"
+                 file="new/header.js"
+                 type="chrome_html" />
     </structures>
   </release>
 </grit>
diff --git a/chrome/browser/resources/safe_browsing/download_file_types.asciipb b/chrome/browser/resources/safe_browsing/download_file_types.asciipb
index 4fd285af..c057ab0 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: 13
+version_id: 14
 sampled_ping_probability: 0.01
 default_file_type {
   uma_value: 18
@@ -786,6 +786,41 @@
   uma_value: 23
   ping_setting: FULL_PING
 }
+file_types {
+  # Opened by uTorrent and Transmission (can be a renamed .torrent)
+  # Added crbug.com/767502
+  extension: "btapp"
+  uma_value: 298
+  ping_setting: FULL_PING
+}
+file_types {
+  # Opened by uTorrent and Transmission (can be a renamed .torrent)
+  # Added crbug.com/767502
+  extension: "btbtskin"
+  uma_value: 299
+  ping_setting: FULL_PING
+}
+file_types {
+  # Opened by uTorrent and Transmission (can be a renamed .torrent)
+  # Added crbug.com/767502
+  extension: "btinstall"
+  uma_value: 300
+  ping_setting: FULL_PING
+}
+file_types {
+  # Opened by uTorrent and Transmission (can be a renamed .torrent)
+  # Added crbug.com/767502
+  extension: "btkey"
+  uma_value: 301
+  ping_setting: FULL_PING
+}
+file_types {
+  # Opened by uTorrent and Transmission (can be a renamed .torrent)
+  # Added crbug.com/767502
+  extension: "btsearch"
+  uma_value: 302
+  ping_setting: FULL_PING
+}
 
 ##
 ## Windows-specific files
@@ -1529,7 +1564,7 @@
   }
 }
 
-# Other Windows files
+# Other Windows files (some cross-platform too)
 file_types {
   extension: "ad"
   uma_value: 262
@@ -1695,6 +1730,30 @@
   }
 }
 file_types {
+  # HTML-like file. This extension can be abused by UwS campaigns to evade
+  # referrer attribution via a two-level download scheme. crbug.com/719784
+  # Added in https://crbug.com/762702
+  extension: "dhtml"
+  uma_value: 303
+  ping_setting: FULL_PING
+}
+file_types {
+  # HTML-like file. This extension can be abused by UwS campaigns to evade
+  # referrer attribution via a two-level download scheme. crbug.com/719784
+  # Added in https://crbug.com/762702
+  extension: "dhtm"
+  uma_value: 304
+  ping_setting: FULL_PING
+}
+file_types {
+  # HTML-like file. This extension can be abused by UwS campaigns to evade
+  # referrer attribution via a two-level download scheme. crbug.com/719784
+  # Added in https://crbug.com/762702
+  extension: "dht"
+  uma_value: 305
+  ping_setting: FULL_PING
+}
+file_types {
   # Windows executable. It can gain control of an executable launched from the
   # same directory, so it can do bad things without ever being clicked on.
   extension: "dll"
@@ -1814,10 +1873,6 @@
   extension: "htm"
   uma_value: 284
   ping_setting: FULL_PING
-  platform_settings {
-    danger_level: NOT_DANGEROUS
-    auto_open_hint: ALLOW_AUTO_OPEN
-  }
 }
 file_types {
   # HTML file. This extension is abused by UwS campaigns to evade referrer
@@ -1825,10 +1880,6 @@
   extension: "html"
   uma_value: 285
   ping_setting: FULL_PING
-  platform_settings {
-    danger_level: NOT_DANGEROUS
-    auto_open_hint: ALLOW_AUTO_OPEN
-  }
 }
 file_types {
   # Hypertext Template File. See https://support.microsoft.com/kb/181689.
@@ -2131,6 +2182,30 @@
   }
 }
 file_types {
+  # HTML-like file. This extension can be abused by UwS campaigns to evade
+  # referrer attribution via a two-level download scheme. crbug.com/719784
+  # Added in https://crbug.com/762702
+  extension: "shtml"
+  uma_value: 306
+  ping_setting: FULL_PING
+}
+file_types {
+  # HTML-like file. This extension can be abused by UwS campaigns to evade
+  # referrer attribution via a two-level download scheme. crbug.com/719784
+  # Added in https://crbug.com/762702
+  extension: "shtm"
+  uma_value: 307
+  ping_setting: FULL_PING
+}
+file_types {
+  # HTML-like file. This extension can be abused by UwS campaigns to evade
+  # referrer attribution via a two-level download scheme. crbug.com/719784
+  # Added in https://crbug.com/762702
+  extension: "sht"
+  uma_value: 308
+  ping_setting: FULL_PING
+}
+file_types {
   # System executable. Windows tries hard to prevent you from opening these
   # types of files.
   extension: "sys"
@@ -2154,6 +2229,112 @@
   }
 }
 file_types {
+  # A Visio file type. Added in https://crbug.com/771469
+  extension: "vdx"
+  uma_value: 289
+  ping_setting: FULL_PING
+  platform_settings {
+    platform: PLATFORM_WINDOWS
+    danger_level: ALLOW_ON_USER_GESTURE
+    auto_open_hint: ALLOW_AUTO_OPEN
+  }
+}
+file_types {
+  # A Visio file type. Added in https://crbug.com/771469
+  extension: "vsx"
+  uma_value: 290
+  ping_setting: FULL_PING
+  platform_settings {
+    platform: PLATFORM_WINDOWS
+    danger_level: ALLOW_ON_USER_GESTURE
+    auto_open_hint: ALLOW_AUTO_OPEN
+  }
+}
+file_types {
+  # A Visio file type. Added in https://crbug.com/771469
+  extension: "vtx"
+  uma_value: 291
+  ping_setting: FULL_PING
+  platform_settings {
+    platform: PLATFORM_WINDOWS
+    danger_level: ALLOW_ON_USER_GESTURE
+    auto_open_hint: ALLOW_AUTO_OPEN
+  }
+}
+file_types {
+  # A Visio file type. Added in https://crbug.com/771469
+  extension: "vsdx"
+  uma_value: 292
+  ping_setting: FULL_PING
+  platform_settings {
+    platform: PLATFORM_WINDOWS
+    danger_level: ALLOW_ON_USER_GESTURE
+    auto_open_hint: ALLOW_AUTO_OPEN
+  }
+  # TODO(nparker): Unpack these as ZIP files. https://crbug.com/628796
+}
+file_types {
+  # A Visio file type. Added in https://crbug.com/771469
+  extension: "vssx"
+  uma_value: 293
+  ping_setting: FULL_PING
+  platform_settings {
+    platform: PLATFORM_WINDOWS
+    danger_level: ALLOW_ON_USER_GESTURE
+    auto_open_hint: ALLOW_AUTO_OPEN
+  }
+  # TODO(nparker): Unpack these as ZIP files. https://crbug.com/628796
+}
+file_types {
+  # A Visio file type. Added in https://crbug.com/771469
+  extension: "vstx"
+  uma_value: 294
+  ping_setting: FULL_PING
+  platform_settings {
+    platform: PLATFORM_WINDOWS
+    danger_level: ALLOW_ON_USER_GESTURE
+    auto_open_hint: ALLOW_AUTO_OPEN
+  }
+  # TODO(nparker): Unpack these as ZIP files. https://crbug.com/628796
+}
+file_types {
+  # A Visio file type. Added in https://crbug.com/771469
+  extension: "vsdm"
+  uma_value: 295
+  ping_setting: FULL_PING
+  platform_settings {
+    platform: PLATFORM_WINDOWS
+    danger_level: ALLOW_ON_USER_GESTURE
+    auto_open_hint: ALLOW_AUTO_OPEN
+  }
+  # TODO(nparker): Unpack these as ZIP files. https://crbug.com/628796
+}
+file_types {
+  # A Visio file type. Added in https://crbug.com/771469
+  extension: "vssm"
+  uma_value: 296
+  ping_setting: FULL_PING
+  platform_settings {
+    platform: PLATFORM_WINDOWS
+    danger_level: ALLOW_ON_USER_GESTURE
+    auto_open_hint: ALLOW_AUTO_OPEN
+  }
+  # TODO(nparker): Unpack these as ZIP files. https://crbug.com/628796
+}
+file_types {
+  # A Visio file type. Added in https://crbug.com/771469
+  extension: "vstm"
+  uma_value: 297
+  ping_setting: FULL_PING
+  platform_settings {
+    platform: PLATFORM_WINDOWS
+    danger_level: ALLOW_ON_USER_GESTURE
+    auto_open_hint: ALLOW_AUTO_OPEN
+  }
+  # TODO(nparker): Unpack these as ZIP files. https://crbug.com/628796
+}
+file_types {
+  # An older Visio file type. See https://crbug.com/771469
   extension: "vsd"
   uma_value: 118
   ping_setting: FULL_PING
@@ -2175,6 +2356,7 @@
   }
 }
 file_types {
+  # An older Visio file type. See https://crbug.com/771469
   extension: "vss"
   uma_value: 120
   ping_setting: FULL_PING
@@ -2185,6 +2367,7 @@
   }
 }
 file_types {
+  # An older Visio file type. See https://crbug.com/771469
   extension: "vst"
   uma_value: 121
   ping_setting: FULL_PING
@@ -2221,30 +2404,18 @@
   extension: "xht"
   uma_value: 286
   ping_setting: FULL_PING
-  platform_settings {
-    danger_level: NOT_DANGEROUS
-    auto_open_hint: ALLOW_AUTO_OPEN
-  }
 }
 file_types {
   # Similar to "html".  Added for https://crbug.com/762702
   extension: "xhtm"
   uma_value: 287
   ping_setting: FULL_PING
-  platform_settings {
-    danger_level: NOT_DANGEROUS
-    auto_open_hint: ALLOW_AUTO_OPEN
-  }
 }
 file_types {
   # Similar to "html".  Added for https://crbug.com/762702
   extension: "xhtml"
   uma_value: 288
   ping_setting: FULL_PING
-  platform_settings {
-    danger_level: NOT_DANGEROUS
-    auto_open_hint: ALLOW_AUTO_OPEN
-  }
 }
 file_types {
   # Microsoft Exchange Public Folder Shortcut
diff --git a/chrome/browser/resources/settings/bluetooth_page/bluetooth_page.js b/chrome/browser/resources/settings/bluetooth_page/bluetooth_page.js
index cd949285..2a6445c 100644
--- a/chrome/browser/resources/settings/bluetooth_page/bluetooth_page.js
+++ b/chrome/browser/resources/settings/bluetooth_page/bluetooth_page.js
@@ -168,7 +168,6 @@
     this.adapterState_ = state;
     this.bluetoothToggleState_ = state.powered;
     this.bluetoothToggleDisabled_ = !state.available;
-    this.setPrefValue('ash.user.bluetooth.adapter_enabled', state.powered);
   },
 
   /** @private */
@@ -206,10 +205,15 @@
     }
     this.bluetoothToggleDisabled_ = true;
     this.bluetoothPrivate.setAdapterState(
-        {powered: this.bluetoothToggleState_}, function() {
+        {powered: this.bluetoothToggleState_}, () => {
           var error = chrome.runtime.lastError;
-          if (error && error != 'Error setting adapter properties: powered')
+          if (error && error != 'Error setting adapter properties: powered') {
             console.error('Error enabling bluetooth: ' + error.message);
+            return;
+          }
+          this.setPrefValue(
+              'ash.user.bluetooth.adapter_enabled',
+              this.bluetoothToggleState_);
         });
   },
 
diff --git a/chrome/browser/resources/settings/bluetooth_page/bluetooth_subpage.html b/chrome/browser/resources/settings/bluetooth_page/bluetooth_subpage.html
index c73eff1..e3fc960d 100644
--- a/chrome/browser/resources/settings/bluetooth_page/bluetooth_subpage.html
+++ b/chrome/browser/resources/settings/bluetooth_page/bluetooth_subpage.html
@@ -102,7 +102,7 @@
     <bluetooth-dialog id="deviceDialog"
         bluetooth="[[bluetooth]]"
         bluetooth-private="[[bluetoothPrivate]]"
-        title="$i18n{bluetoothPairDevicePageTitle}"
+        dialog-title="$i18n{bluetoothPairDevicePageTitle}"
         on-close="onDialogClose_"
         pairing-device="[[pairingDevice_]]">
     </bluetooth-dialog>
diff --git a/chrome/browser/resources/settings/icons.html b/chrome/browser/resources/settings/icons.html
index 0ddc1933..ba91b97 100644
--- a/chrome/browser/resources/settings/icons.html
+++ b/chrome/browser/resources/settings/icons.html
@@ -80,9 +80,6 @@
 </if>
       <g id="list"><path d="M3 13h2v-2H3v2zm0 4h2v-2H3v2zm0-8h2V7H3v2zm4 4h14v-2H7v2zm0 4h14v-2H7v2zM7 7v2h14V7H7z"></path></g>
       <g id="location-on"><path d="M12 2C8.13 2 5 5.13 5 9c0 5.25 7 13 7 13s7-7.75 7-13c0-3.87-3.13-7-7-7zm0 9.5c-1.38 0-2.5-1.12-2.5-2.5s1.12-2.5 2.5-2.5 2.5 1.12 2.5 2.5-1.12 2.5-2.5 2.5z"></path></g>
-<if expr="chromeos">
-      <g id="lock"><path d="M18 8h-1V6c0-2.76-2.24-5-5-5S7 3.24 7 6v2H6c-1.1 0-2 .9-2 2v10c0 1.1.9 2 2 2h12c1.1 0 2-.9 2-2V10c0-1.1-.9-2-2-2zm-6 9c-1.1 0-2-.9-2-2s.9-2 2-2 2 .9 2 2-.9 2-2 2zm3.1-9H8.9V6c0-1.71 1.39-3.1 3.1-3.1 1.71 0 3.1 1.39 3.1 3.1v2z"></path></g>
-</if>
       <g id="mic"><path d="M12 14c1.66 0 2.99-1.34 2.99-3L15 5c0-1.66-1.34-3-3-3S9 3.34 9 5v6c0 1.66 1.34 3 3 3zm5.3-3c0 3-2.54 5.1-5.3 5.1S6.7 14 6.7 11H5c0 3.41 2.72 6.23 6 6.72V21h2v-3.28c3.28-.48 6-3.3 6-6.72h-1.7z"></path></g>
       <g id="midi"><path d="M21,19.1H3V5h18V19.1z M21,3H3C1.9,3,1,3.9,1,5v14c0,1.1,0.9,2,2,2h18c1.1,0,2-0.9,2-2V5C23,3.9,22.1,3,21,3z"></path><path fill="none" d="M21,19.1H3V5h18V19.1z M21,3H3C1.9,3,1,3.9,1,5v14c0,1.1,0.9,2,2,2h18c1.1,0,2-0.9,2-2V5C23,3.9,22.1,3,21,3z"></path><path d="M14,5h3v8h-3V5z"></path><path d="M15,12h1v8h-1V12z"></path><path fill="none" d="M0,0h24v24H0V0z"></path><rect x="7" y="5" width="3" height="8"></rect><rect x="8" y="12" width="1" height="8"></rect></g>
 <if expr="chromeos">
@@ -108,7 +105,6 @@
       <g id="signal-cellular-2-bar"><path fill-opacity=".3" d="M2 22h20V2z"></path><path d="M14 10L2 22h12z"></path></g>
       <g id="signal-cellular-3-bar"><path fill-opacity=".3" d="M2 22h20V2z"></path><path d="M17 7L2 22h15z"></path></g>
       <g id="signal-cellular-4-bar"><path d="M2 22h20V2z"></path></g>
-      <g id="sim-card-alert"><path d="M18 2h-8L4.02 8 4 20c0 1.1.9 2 2 2h12c1.1 0 2-.9 2-2V4c0-1.1-.9-2-2-2zm-5 15h-2v-2h2v2zm0-4h-2V8h2v5z"></path></g>
       <g id="smartphone"><path d="M17 1.01L7 1c-1.1 0-2 .9-2 2v18c0 1.1.9 2 2 2h10c1.1 0 2-.9 2-2V3c0-1.1-.9-1.99-2-1.99zM17 19H7V5h10v14z"></path></g>
 </if>
       <g id="supervisor-account"><path d="M16.5 12c1.38 0 2.49-1.12 2.49-2.5S17.88 7 16.5 7C15.12 7 14 8.12 14 9.5s1.12 2.5 2.5 2.5zM9 11c1.66 0 2.99-1.34 2.99-3S10.66 5 9 5C7.34 5 6 6.34 6 8s1.34 3 3 3zm7.5 3c-1.83 0-5.5.92-5.5 2.75V19h11v-2.25c0-1.83-3.67-2.75-5.5-2.75zM9 13c-2.33 0-7 1.17-7 3.5V19h7v-2.25c0-.85.33-2.34 2.37-3.47C10.5 13.1 9.66 13 9 13z"></path></g>
diff --git a/chrome/browser/resources/settings/internet_page/compiled_resources2.gyp b/chrome/browser/resources/settings/internet_page/compiled_resources2.gyp
index 18f9191..ec95eba 100644
--- a/chrome/browser/resources/settings/internet_page/compiled_resources2.gyp
+++ b/chrome/browser/resources/settings/internet_page/compiled_resources2.gyp
@@ -15,6 +15,7 @@
         '<(EXTERNS_GYP):management',
         '<(EXTERNS_GYP):networking_private',
         '<(INTERFACES_GYP):networking_private_interface',
+        'internet_config',
       ],
       'includes': ['../../../../../third_party/closure_compiler/compile_js2.gypi'],
     },
@@ -24,6 +25,7 @@
         '../compiled_resources2.gyp:route',
         '<(DEPTH)/ui/webui/resources/cr_components/chromeos/network/compiled_resources2.gyp:network_config',
         '<(DEPTH)/ui/webui/resources/cr_elements/chromeos/network/compiled_resources2.gyp:cr_onc_types',
+        '<(DEPTH)/ui/webui/resources/cr_elements/cr_dialog/compiled_resources2.gyp:cr_dialog',
         '<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:assert',
         '<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:i18n_behavior',
         '<(EXTERNS_GYP):networking_private',
@@ -86,17 +88,6 @@
       'includes': ['../../../../../third_party/closure_compiler/compile_js2.gypi'],
     },
     {
-      'target_name': 'network_siminfo',
-      'dependencies': [
-        '<(DEPTH)/third_party/polymer/v1_0/components-chromium/paper-input/compiled_resources2.gyp:paper-input-extracted',
-        '<(DEPTH)/ui/webui/resources/cr_elements/chromeos/network/compiled_resources2.gyp:cr_onc_types',
-        '<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:assert',
-        '<(DEPTH)/ui/webui/resources/js/cr/ui/compiled_resources2.gyp:focus_without_ink',
-        '<(INTERFACES_GYP):networking_private_interface',
-      ],
-      'includes': ['../../../../../third_party/closure_compiler/compile_js2.gypi'],
-    },
-    {
       'target_name': 'network_summary',
       'dependencies': [
         '<(DEPTH)/ui/webui/resources/cr_elements/chromeos/network/compiled_resources2.gyp:cr_onc_types',
diff --git a/chrome/browser/resources/settings/internet_page/internet_config.html b/chrome/browser/resources/settings/internet_page/internet_config.html
index 9cba9c8..5ea3841 100644
--- a/chrome/browser/resources/settings/internet_page/internet_config.html
+++ b/chrome/browser/resources/settings/internet_page/internet_config.html
@@ -3,45 +3,53 @@
 <link rel="import" href="chrome://resources/cr_components/chromeos/network/network_config.html">
 <link rel="import" href="chrome://resources/cr_elements/chromeos/network/cr_network_icon.html">
 <link rel="import" href="chrome://resources/cr_elements/chromeos/network/cr_onc_types.html">
+<link rel="import" href="chrome://resources/cr_elements/cr_dialog/cr_dialog.html">
 <link rel="import" href="chrome://resources/html/i18n_behavior.html">
 <link rel="import" href="chrome://resources/polymer/v1_0/iron-flex-layout/iron-flex-layout-classes.html">
 <link rel="import" href="chrome://resources/polymer/v1_0/paper-button/paper-button.html">
 <link rel="import" href="internet_shared_css.html">
 
-<dom-module id="settings-internet-config">
+<dom-module id="internet-config">
   <template>
     <style include="internet-shared iron-flex">
+      dialog {
+        width: 460px;
+      }
     </style>
 
-    <!-- Title section: Icon + name. -->
-    <div class="settings-box first">
-      <div class="start layout horizontal center">
-        <cr-network-icon network-state="[[networkProperties_]]" is-list-item>
-        </cr-network-icon>
-        <div class="title">[[getTitle_(networkProperties_.*)]]</div>
+    <dialog is="cr-dialog" id="dialog" close-text="$i18n{close}">
+      <div slot="title">
+        <div class="layout horizontal center">
+          <cr-network-icon network-state="[[networkProperties_]]" is-list-item>
+          </cr-network-icon>
+          <div class="title">[[getDialogTitle_(networkProperties_)]]</div>
+        </div>
       </div>
-      <div id="buttonDiv">
-        <paper-button class="secondary-button" on-tap="onCancelTap_">
+      <div slot="body">
+        <div class="settings-box first">
+          <network-config id="networkConfig" class="flex"
+              networking-private="[[networkingPrivate]]"
+              network-properties="{{networkProperties_}}"
+              enable-connect="{{enableConnect_}}" enable-save="{{enableSave_}}"
+              share-allow-enable="[[shareAllowEnable_]]"
+              share-default="[[shareDefault_]]"
+              on-close="close_">
+          </network-config>
+        </div>
+      </div>
+
+      <div slot="button-container">
+        <paper-button class="cancel-button" on-tap="onCancelTap_">
           $i18n{cancel}
         </paper-button>
         <paper-button class="primary-button" on-tap="onSaveOrConnectTap_"
             disabled="[[!getSaveOrConnectEnabled_(
-                guid_, networkProperties_, enableSave_, enableConnect_)]]">
-          [[getSaveOrConnectLabel_(guid_, networkProperties_)]]
+                guid, networkProperties_, enableSave_, enableConnect_)]]">
+          [[getSaveOrConnectLabel_(guid, networkProperties_)]]
         </paper-button>
       </div>
-    </div>
 
-    <div class="settings-box">
-      <network-config id="networkConfig" class="flex"
-          networking-private="[[networkingPrivate]]"
-          network-properties="{{networkProperties_}}"
-          enable-connect="{{enableConnect_}}" enable-save="{{enableSave_}}"
-          share-allow-enable="[[shareAllowEnable_]]"
-          share-default="[[shareDefault_]]"
-          on-close="close_">
-      </network-config>
-    </div>
+    </dialog>
   </template>
   <script src="internet_config.js"></script>
 </dom-module>
diff --git a/chrome/browser/resources/settings/internet_page/internet_config.js b/chrome/browser/resources/settings/internet_page/internet_config.js
index 3790f300..3550646 100644
--- a/chrome/browser/resources/settings/internet_page/internet_config.js
+++ b/chrome/browser/resources/settings/internet_page/internet_config.js
@@ -4,12 +4,12 @@
 
 /**
  * @fileoverview
- * 'settings-internet-config' is a Settings wrapper for network-config.
+ * 'internet-config' is a Settings dialog wrapper for network-config.
  */
 Polymer({
-  is: 'settings-internet-config',
+  is: 'internet-config',
 
-  behaviors: [settings.RouteObserverBehavior, I18nBehavior],
+  behaviors: [I18nBehavior],
 
   properties: {
     /**
@@ -39,7 +39,19 @@
      * empty when configuring a new network.
      * @private
      */
-    guid_: String,
+    guid: String,
+
+    /**
+     * The type of network to be configured.
+     * @private {!chrome.networkingPrivate.NetworkType}
+     */
+    type: String,
+
+    /**
+     * The name of network (for display while the network details are fetched).
+     * @private
+     */
+    name: String,
 
     /** @private */
     enableConnect_: Boolean,
@@ -56,55 +68,38 @@
     networkProperties_: Object,
   },
 
-  /**
-   * settings.RouteObserverBehavior
-   * @param {!settings.Route} route
-   * @protected
-   */
-  currentRouteChanged: function(route) {
-    if (route != settings.routes.NETWORK_CONFIG)
-      return;
-
-    var queryParams = settings.getQueryParameters();
-    this.guid_ = queryParams.get('guid') || '';
+  open: function() {
+    var dialog = /** @type {!CrDialogElement} */ (this.$.dialog);
+    if (!dialog.open)
+      dialog.showModal();
 
     // Set networkProperties for new configurations and for existing
     // configurations until the current properties are loaded.
-    var name = queryParams.get('name') || '';
-    var typeParam = queryParams.get('type');
-    var type = (typeParam && CrOnc.getValidType(typeParam)) || CrOnc.Type.WI_FI;
-    assert(type && type != CrOnc.Type.ALL);
+    assert(this.type && this.type != CrOnc.Type.ALL);
     this.networkProperties_ = {
-      GUID: this.guid_,
-      Name: name,
-      Type: type,
+      GUID: this.guid,
+      Name: this.name,
+      Type: this.type,
     };
-
-    // First focus this page (which will focus a button), then init the config
-    // element which will focus an enabled element if any.
-    this.focus();
     this.$.networkConfig.init();
   },
 
-  focus() {
-    var e = this.$$('paper-button:not([disabled])');
-    assert(e);  // The 'cancel' button should never be disabled.
-    e.focus();
-  },
-
-  /** @private */
-  close_: function() {
-    if (settings.getCurrentRoute() == settings.routes.NETWORK_CONFIG)
-      settings.navigateToPreviousRoute();
+  close: function() {
+    var dialog = /** @type {!CrDialogElement} */ (this.$.dialog);
+    if (dialog.open)
+      dialog.close();
   },
 
   /**
    * @return {string}
    * @private
    */
-  getTitle_: function() {
-    return this.networkProperties_.Name ||
-        this.i18n('OncType' + this.networkProperties_.Type);
+  getDialogTitle_: function() {
+    var name = this.networkProperties_.Name;
+    if (name)
+      return this.i18n('internetConfigName', name);
+    var type = this.i18n('OncType' + this.networkProperties_.Type);
+    return this.i18n('internetJoinType', type);
   },
 
   /**
@@ -113,7 +108,7 @@
    */
   isConfigured_: function() {
     var source = this.networkProperties_.Source;
-    return !!this.guid_ && !!source && source != CrOnc.Source.NONE;
+    return !!this.guid && !!source && source != CrOnc.Source.NONE;
   },
 
   /**
@@ -134,7 +129,7 @@
 
   /** @private */
   onCancelTap_: function() {
-    this.close_();
+    this.close();
   },
 
   /** @private */
diff --git a/chrome/browser/resources/settings/internet_page/internet_detail_page.html b/chrome/browser/resources/settings/internet_page/internet_detail_page.html
index 9bcf9f0..77aeebef 100644
--- a/chrome/browser/resources/settings/internet_page/internet_detail_page.html
+++ b/chrome/browser/resources/settings/internet_page/internet_detail_page.html
@@ -5,6 +5,7 @@
 <link rel="import" href="chrome://resources/cr_components/chromeos/network/network_ip_config.html">
 <link rel="import" href="chrome://resources/cr_components/chromeos/network/network_nameservers.html">
 <link rel="import" href="chrome://resources/cr_components/chromeos/network/network_property_list.html">
+<link rel="import" href="chrome://resources/cr_components/chromeos/network/network_siminfo.html">
 <link rel="import" href="chrome://resources/cr_elements/chromeos/network/cr_network_icon.html">
 <link rel="import" href="chrome://resources/cr_elements/chromeos/network/cr_onc_types.html">
 <link rel="import" href="chrome://resources/cr_elements/cr_expand_button/cr_expand_button.html">
@@ -23,7 +24,6 @@
 <link rel="import" href="../route.html">
 <link rel="import" href="internet_shared_css.html">
 <link rel="import" href="network_proxy_section.html">
-<link rel="import" href="network_siminfo.html">
 <link rel="import" href="tether_connection_dialog.html">
 
 <dom-module id="settings-internet-detail-page">
diff --git a/chrome/browser/resources/settings/internet_page/internet_page.html b/chrome/browser/resources/settings/internet_page/internet_page.html
index f77ea97..ba794ee 100644
--- a/chrome/browser/resources/settings/internet_page/internet_page.html
+++ b/chrome/browser/resources/settings/internet_page/internet_page.html
@@ -84,13 +84,6 @@
         </template>
       </neon-animatable>
 
-      <template is="dom-if" route-path="/networkConfig" no-search>
-        <settings-subpage page-title="$i18n{internetConfigTitle}">
-          <settings-internet-config networking-private="[[networkingPrivate]]">
-          </settings-internet-config>
-        </settings-subpage>
-      </template>
-
       <template is="dom-if" route-path="/networkDetail" no-search>
         <settings-subpage page-title="$i18n{internetDetailPageTitle}">
           <settings-internet-detail-page prefs="{{prefs}}"
@@ -126,6 +119,11 @@
       </template>
 
     </settings-animated-pages>
+
+    <internet-config id="configDialog"
+        networking-private="[[networkingPrivate]]">
+    </internet-config>
+
   </template>
   <script src="internet_page.js"></script>
 </dom-module>
diff --git a/chrome/browser/resources/settings/internet_page/internet_page.js b/chrome/browser/resources/settings/internet_page/internet_page.js
index 85c7a78..7ea0e3c9 100644
--- a/chrome/browser/resources/settings/internet_page/internet_page.js
+++ b/chrome/browser/resources/settings/internet_page/internet_page.js
@@ -233,13 +233,13 @@
    * @private
    */
   showConfig_: function(type, guid, name) {
-    var params = new URLSearchParams;
-    params.append('type', type);
-    if (guid)
-      params.append('guid', guid);
-    if (name)
-      params.append('name', name);
-    settings.navigateTo(settings.routes.NETWORK_CONFIG, params);
+    var configDialog =
+        /** @type {!InternetConfigElement} */ (this.$.configDialog);
+    configDialog.type =
+        /** @type {chrome.networkingPrivate.NetworkType} */ (type);
+    configDialog.guid = guid || '';
+    configDialog.name = name || '';
+    configDialog.open();
   },
 
   /**
diff --git a/chrome/browser/resources/settings/internet_page/network_siminfo.html b/chrome/browser/resources/settings/internet_page/network_siminfo.html
deleted file mode 100644
index 8f4df0b..0000000
--- a/chrome/browser/resources/settings/internet_page/network_siminfo.html
+++ /dev/null
@@ -1,199 +0,0 @@
-<link rel="import" href="chrome://resources/html/polymer.html">
-
-<link rel="import" href="chrome://resources/cr_elements/chromeos/network/cr_onc_types.html">
-<link rel="import" href="chrome://resources/cr_elements/cr_dialog/cr_dialog.html">
-<link rel="import" href="chrome://resources/html/assert.html">
-<link rel="import" href="chrome://resources/html/cr/ui/focus_without_ink.html">
-<link rel="import" href="chrome://resources/polymer/v1_0/iron-a11y-keys/iron-a11y-keys.html">
-<link rel="import" href="chrome://resources/polymer/v1_0/iron-flex-layout/iron-flex-layout-classes.html">
-<link rel="import" href="chrome://resources/polymer/v1_0/iron-icon/iron-icon.html">
-<link rel="import" href="chrome://resources/polymer/v1_0/paper-button/paper-button.html">
-<link rel="import" href="chrome://resources/polymer/v1_0/paper-input/paper-input.html">
-<link rel="import" href="chrome://resources/polymer/v1_0/paper-toggle-button/paper-toggle-button.html">
-<link rel="import" href="../icons.html">
-<link rel="import" href="internet_shared_css.html">
-
-<dom-module id="network-siminfo">
-  <template>
-    <style include="settings-shared internet-shared iron-flex">
-      iron-icon {
-       -webkit-margin-end: 10px;
-      }
-
-      .dialog-error {
-        color: red;
-        font-size: 125%;
-        font-weight: 500;
-        margin-top: 10px;
-      }
-
-      .error {
-        color: red;
-        font-weight: 500;
-      }
-
-      .pin {
-        min-width: 100px;
-      }
-
-      .puk {
-        min-width: 200px;
-      }
-
-      /* Siminfo is embedded; remove the padding. */
-      .settings-box {
-        padding: 0;
-      }
-
-      .settings-box:first-of-type {
-        border-top: none;
-      }
-
-      paper-toggle-button {
-        -webkit-margin-start: var(--settings-control-label-spacing);
-      }
-    </style>
-
-    <!-- SIM missing UI -->
-    <div class="settings-box two-line"
-        hidden$="[[networkProperties.Cellular.SIMPresent]]">
-      <div class="start layout horizontal center">
-        <iron-icon icon="settings:sim-card-alert"></iron-icon>
-        <div class="error">$i18n{networkSimCardMissing}</div>
-      </div>
-    </div>
-
-    <!-- SIM locked -->
-    <div class="settings-box two-line"
-        hidden$="[[!showSimLocked_(networkProperties)]]">
-      <div class="start layout horizontal center">
-        <iron-icon icon="settings:lock"></iron-icon>
-        <div class="error">$i18n{networkSimCardLocked}</div>
-      </div>
-      <div class="separator"></div>
-      <paper-button id="unlockPinButton" on-tap="onUnlockPinTap_">
-        $i18n{networkSimUnlock}
-      </paper-button>
-    </div>
-
-    <!-- SIM unlocked -->
-    <div class="settings-box two-line"
-        hidden$="[[!showSimUnlocked_(networkProperties)]]">
-      <div id="simLockToggleLabel" class="start">
-        $i18n{networkSimLockEnable}
-      </div>
-      <paper-button id="changePinButton" on-tap="onChangePinTap_"
-          hidden$="[[!networkProperties.Cellular.SIMLockStatus.LockEnabled]]">
-        $i18n{networkSimChangePin}
-      </paper-button>
-      <paper-toggle-button id="simLockButton"
-          on-change="onSimLockEnabledChange_" checked="{{lockEnabled_}}"
-          aria-labelledby="simLockToggleLabel">
-      </paper-toggle-button>
-    </div>
-
-    <!-- Enter PIN dialog -->
-    <dialog is="cr-dialog" id="enterPinDialog" close-text="$i18n{close}"
-        on-cancel="onEnterPinDialogCancel_"
-        on-close="onEnterPinDialogClose_">
-      <div slot="title">$i18n{networkSimEnterPinTitle}</div>
-      <div slot="body">
-        <paper-input id="enterPin" class="pin" no-label-float autofocus
-            label="$i18n{networkSimEnterPin}">
-          <iron-a11y-keys keys="enter" on-keys-pressed="sendEnterPin_">
-          </iron-a11y-keys>
-        </paper-input>
-        <div class="dialog-error">
-          [[getErrorMsg_(error_, networkProperties)]]
-        </div>
-      </div>
-      <div slot="button-container">
-        <paper-button on-tap="sendEnterPin_">
-          $i18n{networkSimEnter}
-        </paper-button>
-      </div>
-    </dialog>
-
-    <!-- Change PIN dialog -->
-    <dialog is="cr-dialog" id="changePinDialog" close-text="$i18n{close}"
-        on-close="onChangePinDialogClose_">
-      <div slot="title">$i18n{networkSimChangePinTitle}</div>
-      <div slot="body">
-        <paper-input id="changePinOld" class="pin" no-label-float autofocus
-            label="$i18n{networkSimEnterOldPin}">
-        </paper-input>
-        <paper-input id="changePinNew1" class="pin" no-label-float
-            label="$i18n{networkSimEnterNewPin}">
-        </paper-input>
-        <paper-input id="changePinNew2" class="pin" no-label-float
-            label="$i18n{networkSimReEnterNewPin}">
-          <iron-a11y-keys keys="enter" on-keys-pressed="sendChangePin_">
-          </iron-a11y-keys>
-        </paper-input>
-        <div class="dialog-error">
-          [[getErrorMsg_(error_, networkProperties)]]
-        </div>
-      </div>
-      <div slot="button-container">
-        <paper-button on-tap="sendChangePin_">
-          $i18n{networkSimChange}
-        </paper-button>
-      </div>
-    </dialog>
-
-    <!-- Unlock PIN dialog -->
-    <dialog is="cr-dialog" id="unlockPinDialog" close-text="$i18n{close}"
-        on-close="onUnlockPinDialogClose_">
-      <div slot="title">$i18n{networkSimLockedTitle}</div>
-      <div slot="body">
-        <paper-input id="unlockPin" class="pin" no-label-float autofocus
-            label="$i18n{networkSimEnterPin}">
-          <iron-a11y-keys keys="enter" on-keys-pressed="sendUnlockPin_">
-          </iron-a11y-keys>
-        </paper-input>
-        <div class="dialog-error">
-          [[getErrorMsg_(error_, networkProperties)]]
-        </div>
-      </div>
-      <div slot="button-container">
-        <paper-button on-tap="sendUnlockPin_">
-          $i18n{networkSimUnlock}
-        </paper-button>
-      </div>
-    </dialog>
-
-    <!-- Unlock PUK dialog -->
-    <dialog is="cr-dialog" id="unlockPukDialog" close-text="$i18n{close}"
-        on-close="onUnlockPinDialogClose_">
-      <div slot="title">$i18n{networkSimLockedTitle}</div>
-      <div slot="body">
-        <div>
-          Enter the 8-digit PIN Unblocking Key provided by your carrier
-        </div>
-        <paper-input id="unlockPuk" class="puk" no-label-float autofocus
-            label="$i18n{networkSimEnterPuk}">
-        </paper-input>
-        <paper-input id="unlockPin1" class="pin" no-label-float
-            label="$i18n{networkSimEnterNewPin}">
-        </paper-input>
-        <paper-input id="unlockPin2" class="pin" no-label-float
-            label="$i18n{networkSimReEnterNewPin}">
-          <iron-a11y-keys keys="enter" on-keys-pressed="sendUnlockPuk_">
-          </iron-a11y-keys>
-        </paper-input>
-        <div class="dialog-error">
-          $i18n{networkSimLockedWarning}
-        </div>
-        <div class="dialog-error">
-          [[getErrorMsg_(error_, networkProperties)]]
-        </div>
-      </div>
-      <div slot="button-container">
-        <paper-button on-tap="sendUnlockPuk_">
-          $i18n{networkSimUnlock}
-        </paper-button>
-      </div>
-    </dialog>
-  </template>
-  <script src="network_siminfo.js"></script>
-</dom-module>
diff --git a/chrome/browser/resources/settings/internet_page/network_siminfo.js b/chrome/browser/resources/settings/internet_page/network_siminfo.js
deleted file mode 100644
index 2ea134f..0000000
--- a/chrome/browser/resources/settings/internet_page/network_siminfo.js
+++ /dev/null
@@ -1,402 +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.
-
-/**
- * @fileoverview Polymer element for displaying and modifying cellular sim info.
- */
-(function() {
-
-/** @enum {string} */
-var ErrorType = {
-  NONE: 'none',
-  INCORRECT_PIN: 'incorrect-pin',
-  INCORRECT_PUK: 'incorrect-puk',
-  MISMATCHED_PIN: 'mismatched-pin',
-  INVALID_PIN: 'invalid-pin',
-  INVALID_PUK: 'invalid-puk'
-};
-
-var PIN_MIN_LENGTH = 4;
-var PUK_MIN_LENGTH = 8;
-
-Polymer({
-  is: 'network-siminfo',
-
-  properties: {
-    /**
-     * The network properties associated with the element.
-     * @type {!CrOnc.NetworkProperties|undefined}
-     */
-    networkProperties: {
-      type: Object,
-      observer: 'networkPropertiesChanged_',
-    },
-
-    /**
-     * Interface for networkingPrivate calls, passed from internet_page.
-     * @type {NetworkingPrivate}
-     */
-    networkingPrivate: Object,
-
-    /**
-     * Reflects networkProperties.Cellular.SIMLockStatus.LockEnabled for the
-     * toggle button.
-     * @private
-     */
-    lockEnabled_: {
-      type: Boolean,
-      value: false,
-    },
-
-    /**
-     * Set to true when a PUK is required to unlock the SIM.
-     * @private
-     */
-    pukRequired_: {
-      type: Boolean,
-      value: false,
-      observer: 'pukRequiredChanged_',
-    },
-
-    /**
-     * Set to an ErrorType value after an incorrect PIN or PUK entry.
-     * @private {ErrorType}
-     */
-    error_: {
-      type: Object,
-      value: ErrorType.NONE,
-    },
-  },
-
-  sendSimLockEnabled_: false,
-
-  /** @override */
-  detached: function() {
-    if (this.$.enterPinDialog.open)
-      this.$.enterPinDialog.close();
-    if (this.$.changePinDialog.open)
-      this.$.changePinDialog.close();
-    if (this.$.unlockPinDialog.open)
-      this.$.unlockPinDialog.close();
-    if (this.$.unlockPukDialog.open)
-      this.$.unlockPukDialog.close();
-  },
-
-  /** @private */
-  networkPropertiesChanged_: function() {
-    if (!this.networkProperties || !this.networkProperties.Cellular)
-      return;
-    var simLockStatus = this.networkProperties.Cellular.SIMLockStatus;
-    this.pukRequired_ =
-        !!simLockStatus && simLockStatus.LockType == CrOnc.LockType.PUK;
-    this.lockEnabled_ = !!simLockStatus && simLockStatus.LockEnabled;
-  },
-
-  /** @private */
-  pukRequiredChanged_: function() {
-    if (this.$.unlockPukDialog.open) {
-      if (this.pukRequired_)
-        this.$.unlockPuk.focus();
-      else
-        this.$.unlockPukDialog.close();
-      return;
-    }
-
-    if (!this.pukRequired_)
-      return;
-
-    // If the PUK was activated while attempting to enter or change a pin,
-    // close the dialog and open the unlock PUK dialog.
-    var showUnlockPuk = false;
-    if (this.$.enterPinDialog.open) {
-      this.$.enterPinDialog.close();
-      showUnlockPuk = true;
-    }
-    if (this.$.changePinDialog.open) {
-      this.$.changePinDialog.close();
-      showUnlockPuk = true;
-    }
-    if (this.$.unlockPinDialog.open) {
-      this.$.unlockPinDialog.close();
-      showUnlockPuk = true;
-    }
-    if (!showUnlockPuk)
-      return;
-
-    this.showUnlockPukDialog_();
-  },
-
-  /**
-   * Opens the pin dialog when the sim lock enabled state changes.
-   * @param {!Event} event
-   * @private
-   */
-  onSimLockEnabledChange_: function(event) {
-    if (!this.networkProperties || !this.networkProperties.Cellular)
-      return;
-    this.sendSimLockEnabled_ = event.target.checked;
-    this.error_ = ErrorType.NONE;
-    this.$.enterPin.value = '';
-    this.$.enterPinDialog.showModal();
-  },
-
-  /**
-   * Sends the PIN value from the Enter PIN dialog.
-   * @param {!Event} event
-   * @private
-   */
-  sendEnterPin_: function(event) {
-    event.stopPropagation();
-    var guid = (this.networkProperties && this.networkProperties.GUID) || '';
-    var pin = this.$.enterPin.value;
-    if (!this.validatePin_(pin)) {
-      this.onEnterPinDialogCancel_();
-      return;
-    }
-    var simState = /** @type {!CrOnc.CellularSimState} */ ({
-      currentPin: pin,
-      requirePin: this.sendSimLockEnabled_,
-    });
-    this.networkingPrivate.setCellularSimState(guid, simState, () => {
-      if (chrome.runtime.lastError) {
-        this.error_ = ErrorType.INCORRECT_PIN;
-        this.$.enterPin.inputElement.select();
-      } else {
-        this.error_ = ErrorType.NONE;
-        this.$.enterPinDialog.close();
-      }
-    });
-  },
-
-  /**
-   * Opens the Change PIN dialog.
-   * @param {!Event} event
-   * @private
-   */
-  onChangePinTap_: function(event) {
-    event.stopPropagation();
-    if (!this.networkProperties || !this.networkProperties.Cellular)
-      return;
-    this.error_ = ErrorType.NONE;
-    this.$.changePinOld.value = '';
-    this.$.changePinNew1.value = '';
-    this.$.changePinNew2.value = '';
-    this.$.changePinDialog.showModal();
-  },
-
-  /**
-   * Sends the old and new PIN values from the Change PIN dialog.
-   * @param {!Event} event
-   * @private
-   */
-  sendChangePin_: function(event) {
-    event.stopPropagation();
-    var guid = (this.networkProperties && this.networkProperties.GUID) || '';
-    var newPin = this.$.changePinNew1.value;
-    if (!this.validatePin_(newPin, this.$.changePinNew2.value))
-      return;
-
-    var simState = /** @type {!CrOnc.CellularSimState} */ ({
-      requirePin: true,
-      currentPin: this.$.changePinOld.value,
-      newPin: newPin
-    });
-    this.networkingPrivate.setCellularSimState(guid, simState, () => {
-      if (chrome.runtime.lastError) {
-        this.error_ = ErrorType.INCORRECT_PIN;
-        this.$.changePinOld.inputElement.select();
-      } else {
-        this.error_ = ErrorType.NONE;
-        this.$.changePinDialog.close();
-      }
-    });
-  },
-
-  /**
-   * Opens the Unlock PIN / PUK dialog.
-   * @param {!Event} event
-   * @private
-   */
-  onUnlockPinTap_: function(event) {
-    event.stopPropagation();
-    if (this.pukRequired_) {
-      this.showUnlockPukDialog_();
-    } else {
-      this.showUnlockPinDialog_();
-    }
-  },
-
-  /**
-   * Sends the PIN value from the Unlock PIN dialog.
-   * @param {!Event} event
-   * @private
-   */
-  sendUnlockPin_: function(event) {
-    event.stopPropagation();
-    var guid = (this.networkProperties && this.networkProperties.GUID) || '';
-    var pin = this.$.unlockPin.value;
-    if (!this.validatePin_(pin))
-      return;
-
-    this.networkingPrivate.unlockCellularSim(guid, pin, '', () => {
-      if (chrome.runtime.lastError) {
-        this.error_ = ErrorType.INCORRECT_PIN;
-        this.$.unlockPin.inputElement.select();
-      } else {
-        this.error_ = ErrorType.NONE;
-        this.$.unlockPinDialog.close();
-      }
-    });
-  },
-
-  /** @private */
-  showUnlockPinDialog_: function() {
-    this.error_ = ErrorType.NONE;
-    this.$.unlockPin.value = '';
-    this.$.unlockPinDialog.showModal();
-  },
-
-  /** @private */
-  showUnlockPukDialog_: function() {
-    this.error_ = ErrorType.NONE;
-    this.$.unlockPuk.value = '';
-    this.$.unlockPin1.value = '';
-    this.$.unlockPin2.value = '';
-    this.$.unlockPukDialog.showModal();
-  },
-
-  /**
-   * Sends the PUK value and new PIN value from the Unblock PUK dialog.
-   * @param {!Event} event
-   * @private
-   */
-  sendUnlockPuk_: function(event) {
-    event.stopPropagation();
-    var guid = (this.networkProperties && this.networkProperties.GUID) || '';
-    var puk = this.$.unlockPuk.value;
-    if (!this.validatePuk_(puk))
-      return;
-    var pin = this.$.unlockPin1.value;
-    if (!this.validatePin_(pin, this.$.unlockPin2.value))
-      return;
-
-    this.networkingPrivate.unlockCellularSim(guid, pin, puk, () => {
-      if (chrome.runtime.lastError) {
-        this.error_ = ErrorType.INCORRECT_PUK;
-        this.$.unlockPuk.inputElement.select();
-      } else {
-        this.error_ = ErrorType.NONE;
-        this.$.unlockPukDialog.close();
-      }
-    });
-  },
-
-  /**
-   * @return {boolean}
-   * @private
-   */
-  showSimLocked_: function() {
-    if (!this.networkProperties || !this.networkProperties.Cellular ||
-        !this.networkProperties.Cellular.SIMPresent) {
-      return false;
-    }
-    return CrOnc.isSimLocked(this.networkProperties);
-  },
-
-  /**
-   * @return {boolean}
-   * @private
-   */
-  showSimUnlocked_: function() {
-    if (!this.networkProperties || !this.networkProperties.Cellular ||
-        !this.networkProperties.Cellular.SIMPresent) {
-      return false;
-    }
-    return !CrOnc.isSimLocked(this.networkProperties);
-  },
-
-  /** @private */
-  getErrorMsg_: function() {
-    if (this.error_ == ErrorType.NONE)
-      return '';
-    // TODO(stevenjb): Translate
-    var msg;
-    if (this.error_ == ErrorType.INCORRECT_PIN)
-      msg = 'Incorrect PIN.';
-    else if (this.error_ == ErrorType.INCORRECT_PUK)
-      msg = 'Incorrect PUK.';
-    else if (this.error_ == ErrorType.MISMATCHED_PIN)
-      msg = 'PIN values do not match.';
-    else if (this.error_ == ErrorType.INVALID_PIN)
-      msg = 'Invalid PIN.';
-    else if (this.error_ == ErrorType.INVALID_PUK)
-      msg = 'Invalid PUK.';
-    else
-      return 'UNKNOWN ERROR';
-    var retriesLeft =
-        this.get('Cellular.SIMLockStatus.RetriesLeft', this.networkProperties);
-    if (retriesLeft) {
-      msg += ' Retries left: ' + retriesLeft.toString();
-    }
-    return msg;
-  },
-
-  /**
-   * Checks whether |pin1| is of the proper length and if opt_pin2 is not
-   * undefined, whether pin1 and opt_pin2 match. On any failure, sets
-   * |this.error_| and returns false.
-   * @param {string} pin1
-   * @param {string=} opt_pin2
-   * @return {boolean} True if the pins match and are of minimum length.
-   * @private
-   */
-  validatePin_: function(pin1, opt_pin2) {
-    if (pin1.length < PIN_MIN_LENGTH) {
-      this.error_ = ErrorType.INVALID_PIN;
-      return false;
-    }
-    if (opt_pin2 != undefined && pin1 != opt_pin2) {
-      this.error_ = ErrorType.MISMATCHED_PIN;
-      return false;
-    }
-    return true;
-  },
-
-  /**
-   * Checks whether |puk| is of the proper length. If not, sets |this.error_|
-   * and returns false.
-   * @param {string} puk
-   * @return {boolean} True if the puk is of minimum length.
-   * @private
-   */
-  validatePuk_: function(puk) {
-    if (puk.length < PUK_MIN_LENGTH) {
-      this.error_ = ErrorType.INVALID_PUK;
-      return false;
-    }
-    return true;
-  },
-
-  /** @private */
-  onEnterPinDialogCancel_: function() {
-    this.lockEnabled_ =
-        this.networkProperties.Cellular.SIMLockStatus.LockEnabled;
-  },
-
-  /** @private */
-  onEnterPinDialogClose_: function() {
-    cr.ui.focusWithoutInk(assert(this.$$('#simLockButton')));
-  },
-
-  /** @private */
-  onChangePinDialogClose_: function() {
-    cr.ui.focusWithoutInk(assert(this.$$('#changePinButton')));
-  },
-
-  /** @private */
-  onUnlockPinDialogClose_: function() {
-    cr.ui.focusWithoutInk(assert(this.$$('#unlockPinButton')));
-  },
-});
-})();
diff --git a/chrome/browser/resources/settings/internet_page/network_summary_item.html b/chrome/browser/resources/settings/internet_page/network_summary_item.html
index 0c535cf..29e95aeb 100644
--- a/chrome/browser/resources/settings/internet_page/network_summary_item.html
+++ b/chrome/browser/resources/settings/internet_page/network_summary_item.html
@@ -1,5 +1,6 @@
 <link rel="import" href="chrome://resources/html/polymer.html">
 
+<link rel="import" href="chrome://resources/cr_components/chromeos/network/network_siminfo.html">
 <link rel="import" href="chrome://resources/cr_elements/chromeos/network/cr_network_icon.html">
 <link rel="import" href="chrome://resources/cr_elements/policy/cr_policy_indicator.html">
 <link rel="import" href="chrome://resources/html/i18n_behavior.html">
@@ -8,7 +9,6 @@
 <link rel="import" href="chrome://resources/polymer/v1_0/paper-toggle-button/paper-toggle-button.html">
 <link rel="import" href="../settings_page/settings_subpage.html">
 <link rel="import" href="../settings_shared_css.html">
-<link rel="import" href="network_siminfo.html">
 
 <dom-module id="network-summary-item">
   <template>
diff --git a/chrome/browser/resources/settings/internet_page/network_summary_item.js b/chrome/browser/resources/settings/internet_page/network_summary_item.js
index 9555d96..1171557 100644
--- a/chrome/browser/resources/settings/internet_page/network_summary_item.js
+++ b/chrome/browser/resources/settings/internet_page/network_summary_item.js
@@ -130,17 +130,24 @@
   },
 
   /**
-   * Show the <network-siminfo> element if this is a disabled and locked
-   * cellular device.
    * @param {!CrOnc.DeviceStateProperties|undefined} deviceState
    * @return {boolean}
    * @private
    */
   showSimInfo_: function(deviceState) {
-    if (!deviceState || deviceState.Type != CrOnc.Type.CELLULAR ||
-        this.deviceIsEnabled_(deviceState)) {
+    if (!deviceState || deviceState.Type != CrOnc.Type.CELLULAR)
       return false;
-    }
+    return this.simLockedOrAbsent_(deviceState);
+  },
+
+  /**
+   * @param {!CrOnc.DeviceStateProperties} deviceState
+   * @return {boolean}
+   * @private
+   */
+  simLockedOrAbsent_: function(deviceState) {
+    if (this.deviceIsEnabled_(deviceState))
+      return false;
     if (deviceState.SIMPresent === false)
       return true;
     var simLockType =
@@ -184,10 +191,23 @@
    * @private
    */
   enableToggleIsVisible_: function(deviceState) {
-    return !!deviceState && deviceState.Type != CrOnc.Type.ETHERNET &&
-        deviceState.Type != CrOnc.Type.VPN &&
-        (deviceState.Type == CrOnc.Type.TETHER ||
-         deviceState.State != CrOnc.DeviceState.UNINITIALIZED);
+    if (!deviceState)
+      return false;
+    switch (deviceState.Type) {
+      case CrOnc.Type.ETHERNET:
+      case CrOnc.Type.VPN:
+        return false;
+      case CrOnc.Type.TETHER:
+        return true;
+      case CrOnc.Type.WI_FI:
+      case CrOnc.Type.WI_MAX:
+        return deviceState.State != CrOnc.DeviceState.UNINITIALIZED;
+      case CrOnc.Type.CELLULAR:
+        return deviceState.State != CrOnc.DeviceState.UNINITIALIZED &&
+            !this.simLockedOrAbsent_(deviceState);
+    }
+    assertNotReached();
+    return false;
   },
 
   /**
diff --git a/chrome/browser/resources/settings/internet_page/tether_connection_dialog.html b/chrome/browser/resources/settings/internet_page/tether_connection_dialog.html
index 67d7e60..e22b6467 100644
--- a/chrome/browser/resources/settings/internet_page/tether_connection_dialog.html
+++ b/chrome/browser/resources/settings/internet_page/tether_connection_dialog.html
@@ -1,6 +1,7 @@
 <link rel="import" href="chrome://resources/html/polymer.html">
 <link rel="import" href="chrome://resources/cr_elements/chromeos/network/cr_network_icon.html">
 <link rel="import" href="chrome://resources/cr_elements/chromeos/network/cr_onc_types.html">
+<link rel="import" href="chrome://resources/cr_elements/cr_dialog/cr_dialog.html">
 <link rel="import" href="chrome://resources/polymer/v1_0/iron-icon/iron-icon.html">
 <link rel="import" href="chrome://resources/polymer/v1_0/paper-button/paper-button.html">
 <link rel="import" href="../icons.html">
diff --git a/chrome/browser/resources/settings/route.js b/chrome/browser/resources/settings/route.js
index aa37425b..59fca70 100644
--- a/chrome/browser/resources/settings/route.js
+++ b/chrome/browser/resources/settings/route.js
@@ -46,7 +46,6 @@
  *   MANAGE_PASSWORDS: (undefined|!settings.Route),
  *   MANAGE_PROFILE: (undefined|!settings.Route),
  *   MULTIDEVICE: (undefined|!settings.Route),
- *   NETWORK_CONFIG: (undefined|!settings.Route),
  *   NETWORK_DETAIL: (undefined|!settings.Route),
  *   ON_STARTUP: (undefined|!settings.Route),
  *   PASSWORDS: (undefined|!settings.Route),
@@ -217,7 +216,6 @@
     // <if expr="chromeos">
     r.INTERNET = r.BASIC.createSection('/internet', 'internet');
     r.INTERNET_NETWORKS = r.INTERNET.createChild('/networks');
-    r.NETWORK_CONFIG = r.INTERNET.createChild('/networkConfig');
     r.NETWORK_DETAIL = r.INTERNET.createChild('/networkDetail');
     r.KNOWN_NETWORKS = r.INTERNET.createChild('/knownNetworks');
     r.BLUETOOTH = r.BASIC.createSection('/bluetooth', 'bluetooth');
diff --git a/chrome/browser/resources/settings/settings_resources.grd b/chrome/browser/resources/settings/settings_resources.grd
index 93c5edf..bd3a378 100644
--- a/chrome/browser/resources/settings/settings_resources.grd
+++ b/chrome/browser/resources/settings/settings_resources.grd
@@ -1150,12 +1150,6 @@
         <structure name="IDR_SETTINGS_NETWORK_PROXY_SECTION_JS"
                    file="internet_page/network_proxy_section.js"
                    type="chrome_html" />
-        <structure name="IDR_SETTINGS_NETWORK_SIMINFO_HTML"
-                   file="internet_page/network_siminfo.html"
-                   type="chrome_html" />
-        <structure name="IDR_SETTINGS_NETWORK_SIMINFO_JS"
-                   file="internet_page/network_siminfo.js"
-                   type="chrome_html" />
         <structure name="IDR_SETTINGS_NETWORK_SUMMARY_HTML"
                    file="internet_page/network_summary.html"
                    type="chrome_html" />
diff --git a/chrome/browser/safe_browsing/browser_feature_extractor_unittest.cc b/chrome/browser/safe_browsing/browser_feature_extractor_unittest.cc
index aff2da21..3579cf9 100644
--- a/chrome/browser/safe_browsing/browser_feature_extractor_unittest.cc
+++ b/chrome/browser/safe_browsing/browser_feature_extractor_unittest.cc
@@ -31,6 +31,7 @@
 #include "content/public/browser/navigation_entry.h"
 #include "content/public/browser/web_contents.h"
 #include "content/public/common/referrer.h"
+#include "content/public/test/navigation_simulator.h"
 #include "content/public/test/test_browser_thread.h"
 #include "content/public/test/web_contents_tester.h"
 #include "testing/gmock/include/gmock/gmock.h"
@@ -128,22 +129,12 @@
   void NavigateAndCommit(const GURL& url,
                          const GURL& referrer,
                          ui::PageTransition type) {
-    web_contents()->GetController().LoadURL(
-        url, content::Referrer(referrer, blink::kWebReferrerPolicyDefault),
-        type, std::string());
-    int pending_id =
-        web_contents()->GetController().GetPendingEntry()->GetUniqueID();
-
-    content::RenderFrameHost* rfh = pending_main_rfh();
-    if (!rfh) {
-      rfh = web_contents()->GetMainFrame();
-    }
-    WebContentsTester::For(web_contents())->ProceedWithCrossSiteNavigation();
-    WebContentsTester::For(web_contents())
-        ->TestDidNavigateWithReferrer(
-            rfh, pending_id, true, url,
-            content::Referrer(referrer, blink::kWebReferrerPolicyDefault),
-            type);
+    auto navigation = content::NavigationSimulator::CreateBrowserInitiated(
+        url, web_contents());
+    navigation->SetReferrer(
+        content::Referrer(referrer, blink::kWebReferrerPolicyDefault));
+    navigation->SetTransition(type);
+    navigation->Commit();
   }
 
   bool ExtractFeatures(ClientPhishingRequest* request) {
diff --git a/chrome/browser/safe_browsing/chrome_password_protection_service.cc b/chrome/browser/safe_browsing/chrome_password_protection_service.cc
index b47f387..2df6cc0 100644
--- a/chrome/browser/safe_browsing/chrome_password_protection_service.cc
+++ b/chrome/browser/safe_browsing/chrome_password_protection_service.cc
@@ -159,8 +159,10 @@
   pref_change_registrar_->Init(profile_->GetPrefs());
   pref_change_registrar_->Add(
       password_manager::prefs::kSyncPasswordHash,
-      base::Bind(&ChromePasswordProtectionService::OnGaiaPasswordChanged,
+      base::Bind(&ChromePasswordProtectionService::CheckGaiaPasswordChange,
                  base::Unretained(this)));
+  gaia_password_hash_ = profile_->GetPrefs()->GetString(
+      password_manager::prefs::kSyncPasswordHash);
 }
 
 ChromePasswordProtectionService::~ChromePasswordProtectionService() {
@@ -610,6 +612,15 @@
                                     /*is_pending=*/true, threat_type);
 }
 
+void ChromePasswordProtectionService::CheckGaiaPasswordChange() {
+  std::string new_gaia_password_hash = profile_->GetPrefs()->GetString(
+      password_manager::prefs::kSyncPasswordHash);
+  if (gaia_password_hash_ != new_gaia_password_hash) {
+    gaia_password_hash_ = new_gaia_password_hash;
+    OnGaiaPasswordChanged();
+  }
+}
+
 void ChromePasswordProtectionService::OnGaiaPasswordChanged() {
   DictionaryPrefUpdate unhandled_sync_password_reuses(
       profile_->GetPrefs(), prefs::kSafeBrowsingUnhandledSyncPasswordReuses);
diff --git a/chrome/browser/safe_browsing/chrome_password_protection_service.h b/chrome/browser/safe_browsing/chrome_password_protection_service.h
index 478315c..8adeb98 100644
--- a/chrome/browser/safe_browsing/chrome_password_protection_service.h
+++ b/chrome/browser/safe_browsing/chrome_password_protection_service.h
@@ -112,6 +112,9 @@
   void MaybeFinishCollectingThreatDetails(content::WebContents* web_contents,
                                           bool did_proceed);
 
+  // Check if Gaia password hash is changed.
+  void CheckGaiaPasswordChange();
+
   // Called when sync user's Gaia password changed.
   void OnGaiaPasswordChanged();
 
@@ -176,6 +179,10 @@
       content::WebContents* web_contents,
       PasswordProtectionService::WarningAction action);
 
+  void SetGaiaPasswordHashForTesting(const std::string& new_password_hash) {
+    gaia_password_hash_ = new_password_hash;
+  }
+
   FRIEND_TEST_ALL_PREFIXES(ChromePasswordProtectionServiceTest,
                            VerifyUserPopulationForPasswordOnFocusPing);
   FRIEND_TEST_ALL_PREFIXES(ChromePasswordProtectionServiceTest,
@@ -195,6 +202,8 @@
                            VerifyUpdateSecurityState);
   FRIEND_TEST_ALL_PREFIXES(ChromePasswordProtectionServiceTest,
                            VerifyGetChangePasswordURL);
+  FRIEND_TEST_ALL_PREFIXES(ChromePasswordProtectionServiceBrowserTest,
+                           VerifyCheckGaiaPasswordChange);
 
  private:
   friend class MockChromePasswordProtectionService;
@@ -240,6 +249,8 @@
   TriggerManager* trigger_manager_;
   // Profile associated with this instance.
   Profile* profile_;
+  // Current Gaia password hash.
+  std::string gaia_password_hash_;
   scoped_refptr<SafeBrowsingNavigationObserverManager>
       navigation_observer_manager_;
   base::ObserverList<Observer> observer_list_;
diff --git a/chrome/browser/safe_browsing/chrome_password_protection_service_browsertest.cc b/chrome/browser/safe_browsing/chrome_password_protection_service_browsertest.cc
index af31c99..91c8b7fc 100644
--- a/chrome/browser/safe_browsing/chrome_password_protection_service_browsertest.cc
+++ b/chrome/browser/safe_browsing/chrome_password_protection_service_browsertest.cc
@@ -51,13 +51,14 @@
                      : browser()->profile());
   }
 
-  void SimulateGaiaPasswordChange(bool is_incognito) {
+  void SimulateGaiaPasswordChange(bool is_incognito,
+                                  const std::string& new_password_hash) {
     if (is_incognito) {
       browser()->profile()->GetOffTheRecordProfile()->GetPrefs()->SetString(
-          password_manager::prefs::kSyncPasswordHash, "new_password_hash");
+          password_manager::prefs::kSyncPasswordHash, new_password_hash);
     } else {
       browser()->profile()->GetPrefs()->SetString(
-          password_manager::prefs::kSyncPasswordHash, "new_password_hash");
+          password_manager::prefs::kSyncPasswordHash, new_password_hash);
     }
   }
 
@@ -306,7 +307,7 @@
           profile));
 
   // Simulates a Gaia password change.
-  SimulateGaiaPasswordChange(/*is_incognito=*/false);
+  SimulateGaiaPasswordChange(/*is_incognito=*/false, "new_password_hash");
   base::RunLoop().RunUntilIdle();
   EXPECT_EQ(0u,
             profile->GetPrefs()
@@ -320,6 +321,41 @@
 }
 
 IN_PROC_BROWSER_TEST_F(ChromePasswordProtectionServiceBrowserTest,
+                       VerifyCheckGaiaPasswordChange) {
+  Profile* profile = browser()->profile();
+  ChromePasswordProtectionService* service = GetService(/*is_incognito=*/false);
+  service->SetGaiaPasswordHashForTesting("password_hash_1");
+  ui_test_utils::NavigateToURL(browser(), embedded_test_server()->GetURL("/"));
+
+  // Shows modal dialog on current web_contents.
+  content::WebContents* web_contents =
+      browser()->tab_strip_model()->GetActiveWebContents();
+  service->ShowModalWarning(web_contents, "unused_token");
+  base::RunLoop().RunUntilIdle();
+  EXPECT_EQ(1u,
+            profile->GetPrefs()
+                ->GetDictionary(prefs::kSafeBrowsingUnhandledSyncPasswordReuses)
+                ->size());
+
+  // Save the same password will not trigger OnGaiaPasswordChanged(), thus no
+  // change to size of unhandled_password_reuses().
+  SimulateGaiaPasswordChange(/*is_incognito=*/false, "password_hash_1");
+  base::RunLoop().RunUntilIdle();
+  EXPECT_EQ(1u,
+            profile->GetPrefs()
+                ->GetDictionary(prefs::kSafeBrowsingUnhandledSyncPasswordReuses)
+                ->size());
+
+  // Save a different password will clear unhandled_password_reuses().
+  SimulateGaiaPasswordChange(/*is_incognito=*/false, "password_hash_2");
+  base::RunLoop().RunUntilIdle();
+  EXPECT_EQ(0u,
+            profile->GetPrefs()
+                ->GetDictionary(prefs::kSafeBrowsingUnhandledSyncPasswordReuses)
+                ->size());
+}
+
+IN_PROC_BROWSER_TEST_F(ChromePasswordProtectionServiceBrowserTest,
                        VerifyShouldShowChangePasswordSettingUI) {
   Profile* profile = browser()->profile();
   EXPECT_FALSE(
diff --git a/chrome/browser/safe_browsing/test_safe_browsing_database_helper.cc b/chrome/browser/safe_browsing/test_safe_browsing_database_helper.cc
index d3e18b5..557ae4c 100644
--- a/chrome/browser/safe_browsing/test_safe_browsing_database_helper.cc
+++ b/chrome/browser/safe_browsing/test_safe_browsing_database_helper.cc
@@ -10,7 +10,6 @@
 #include "base/files/file_path.h"
 #include "base/files/file_util.h"
 #include "base/location.h"
-#include "base/memory/ptr_util.h"
 #include "base/memory/ref_counted.h"
 #include "base/strings/stringprintf.h"
 #include "chrome/browser/safe_browsing/safe_browsing_service.h"
@@ -83,30 +82,35 @@
 
 TestSafeBrowsingDatabaseHelper::TestSafeBrowsingDatabaseHelper()
     : TestSafeBrowsingDatabaseHelper(
+          std::make_unique<
+              safe_browsing::TestV4GetHashProtocolManagerFactory>(),
           std::vector<safe_browsing::ListIdentifier>()) {}
 
 TestSafeBrowsingDatabaseHelper::TestSafeBrowsingDatabaseHelper(
-    std::vector<safe_browsing::ListIdentifier> lists_to_insert) {
-  sb_factory_ = base::MakeUnique<safe_browsing::TestSafeBrowsingServiceFactory>(
+    std::unique_ptr<safe_browsing::TestV4GetHashProtocolManagerFactory>
+        v4_get_hash_factory,
+    std::vector<safe_browsing::ListIdentifier> lists_to_insert)
+    : v4_get_hash_factory_(v4_get_hash_factory.get()) {
+  sb_factory_ = std::make_unique<safe_browsing::TestSafeBrowsingServiceFactory>(
       safe_browsing::V4FeatureList::V4UsageStatus::V4_ONLY);
   sb_factory_->SetTestUIManager(new FakeSafeBrowsingUIManager());
   safe_browsing::SafeBrowsingService::RegisterFactory(sb_factory_.get());
 
-  auto store_factory = base::MakeUnique<safe_browsing::TestV4StoreFactory>();
-  auto v4_db_factory = base::MakeUnique<InsertingDatabaseFactory>(
+  auto store_factory = std::make_unique<safe_browsing::TestV4StoreFactory>();
+  auto v4_db_factory = std::make_unique<InsertingDatabaseFactory>(
       store_factory.get(), lists_to_insert);
-  auto v4_get_hash_factory =
-      base::MakeUnique<safe_browsing::TestV4GetHashProtocolManagerFactory>();
 
   v4_db_factory_ = v4_db_factory.get();
-  v4_get_hash_factory_ = v4_get_hash_factory.get();
 
   safe_browsing::V4Database::RegisterStoreFactoryForTest(
       std::move(store_factory));
   safe_browsing::V4Database::RegisterDatabaseFactoryForTest(
       std::move(v4_db_factory));
-  safe_browsing::V4GetHashProtocolManager::RegisterFactory(
-      std::move(v4_get_hash_factory));
+
+  if (v4_get_hash_factory) {
+    safe_browsing::V4GetHashProtocolManager::RegisterFactory(
+        std::move(v4_get_hash_factory));
+  }
 }
 
 TestSafeBrowsingDatabaseHelper::~TestSafeBrowsingDatabaseHelper() {
@@ -116,16 +120,27 @@
   safe_browsing::SafeBrowsingService::RegisterFactory(nullptr);
 }
 
-void TestSafeBrowsingDatabaseHelper::MarkUrlAsMatchingListIdWithMetadata(
+void TestSafeBrowsingDatabaseHelper::AddFullHashToDbAndFullHashCache(
     const GURL& bad_url,
     const safe_browsing::ListIdentifier& list_id,
     const safe_browsing::ThreatMetadata& threat_metadata) {
+  // Should only be called if we are mocking the v4 hash factory.
+  DCHECK(v4_get_hash_factory_);
+
+  LocallyMarkPrefixAsBad(bad_url, list_id);
+
   safe_browsing::FullHashInfo full_hash_info =
       GetFullHashInfoWithMetadata(bad_url, list_id, threat_metadata);
-  v4_db_factory_->MarkPrefixAsBad(list_id, full_hash_info.full_hash);
   v4_get_hash_factory_->AddToFullHashCache(full_hash_info);
 }
 
+void TestSafeBrowsingDatabaseHelper::LocallyMarkPrefixAsBad(
+    const GURL& url,
+    const safe_browsing::ListIdentifier& list_id) {
+  safe_browsing::FullHash full_hash = safe_browsing::GetFullHash(url);
+  v4_db_factory_->MarkPrefixAsBad(list_id, full_hash);
+}
+
 bool TestSafeBrowsingDatabaseHelper::HasListSynced(
     const safe_browsing::ListIdentifier& list_id) {
   return base::ContainsValue(v4_db_factory_->lists(), list_id);
diff --git a/chrome/browser/safe_browsing/test_safe_browsing_database_helper.h b/chrome/browser/safe_browsing/test_safe_browsing_database_helper.h
index aa6b8b5..7092ebb 100644
--- a/chrome/browser/safe_browsing/test_safe_browsing_database_helper.h
+++ b/chrome/browser/safe_browsing/test_safe_browsing_database_helper.h
@@ -21,30 +21,51 @@
 class GURL;
 
 // This class wraps a couple of safe browsing utilities that enable updating
-// underlying SafeBrowsing lists to match URLs. It optionally takes a list of
-// ListIdentifiers to add lists which are not normally enabled. This is used for
-// e.g. the SubresourceFilter list to allow browser tests to test the list
-// without building a chrome branded build.
+// underlying SafeBrowsing lists to match URLs.
 class TestSafeBrowsingDatabaseHelper {
  public:
-  TestSafeBrowsingDatabaseHelper();
+  // Use this constructor for more in-depth customization of the database
+  // helper. In particular, you can choose to:
+  // 1. Send a nullptr protocol manager factory, so that hash requests are not
+  //    mocked. Callers can consider mocking responses at the HTTP layer instead
+  //    using StartRedirectingV4RequestsForTesting in
+  //    v4_embedded_test_server_util.h.
+  //
+  // 2. Send a vector of additional lists to insert into the store map when
+  //    initializing the test database. This allows lists which need chrome
+  //    branding to function in non chrome branded tests (for developer
+  //    ergonomics).
   TestSafeBrowsingDatabaseHelper(
+      std::unique_ptr<safe_browsing::TestV4GetHashProtocolManagerFactory>
+          v4_get_hash_factory,
       std::vector<safe_browsing::ListIdentifier> lists_to_insert);
+  TestSafeBrowsingDatabaseHelper();
+
   ~TestSafeBrowsingDatabaseHelper();
 
-  void MarkUrlAsMatchingListIdWithMetadata(
+  // Only compatible with the kMock policy. Marks the hash prefix for the URL as
+  // bad in the local database and inserts it  into the full hash cache.
+  void AddFullHashToDbAndFullHashCache(
       const GURL& bad_url,
       const safe_browsing::ListIdentifier& list_id,
       const safe_browsing::ThreatMetadata& threat_metadata);
 
+  // Only marks the prefix as bad in the local database. Does not cache any full
+  // hash response.
+  void LocallyMarkPrefixAsBad(const GURL& url,
+                              const safe_browsing::ListIdentifier& list_id);
+
   bool HasListSynced(const safe_browsing::ListIdentifier& list_id);
 
  private:
   std::unique_ptr<safe_browsing::TestSafeBrowsingServiceFactory> sb_factory_;
   // Owned by the V4Database.
-  InsertingDatabaseFactory* v4_db_factory_;
-  // Owned by the V4GetHashProtocolManager.
-  safe_browsing::TestV4GetHashProtocolManagerFactory* v4_get_hash_factory_;
+  InsertingDatabaseFactory* v4_db_factory_ = nullptr;
+
+  // Owned by the V4GetHashProtocolManager. Will stay nullptr if the v4 hash
+  // factory is not being mocked.
+  safe_browsing::TestV4GetHashProtocolManagerFactory* v4_get_hash_factory_ =
+      nullptr;
 
   DISALLOW_COPY_AND_ASSIGN(TestSafeBrowsingDatabaseHelper);
 };
diff --git a/chrome/browser/safe_browsing/threat_details_unittest.cc b/chrome/browser/safe_browsing/threat_details_unittest.cc
index 65a7eb50..3298ced 100644
--- a/chrome/browser/safe_browsing/threat_details_unittest.cc
+++ b/chrome/browser/safe_browsing/threat_details_unittest.cc
@@ -27,6 +27,7 @@
 #include "content/public/browser/render_frame_host.h"
 #include "content/public/browser/render_process_host.h"
 #include "content/public/browser/web_contents.h"
+#include "content/public/test/navigation_simulator.h"
 #include "content/public/test/test_renderer_host.h"
 #include "content/public/test/web_contents_tester.h"
 #include "net/base/io_buffer.h"
@@ -398,14 +399,11 @@
 
 // Tests creating a simple threat report of a malware URL.
 TEST_F(ThreatDetailsTest, ThreatSubResource) {
-  // Commit a load.
-  content::WebContentsTester::For(web_contents())
-      ->TestDidNavigateWithReferrer(
-          web_contents()->GetMainFrame(), 0 /* nav_entry_id */,
-          true /* did_create_new_entry */, GURL(kLandingURL),
-          content::Referrer(GURL(kReferrerURL),
-                            blink::kWebReferrerPolicyDefault),
-          ui::PAGE_TRANSITION_TYPED);
+  auto navigation = content::NavigationSimulator::CreateBrowserInitiated(
+      GURL(kLandingURL), web_contents());
+  navigation->SetReferrer(
+      content::Referrer(GURL(kReferrerURL), blink::kWebReferrerPolicyDefault));
+  navigation->Commit();
 
   UnsafeResource resource;
   InitResource(SB_THREAT_TYPE_URL_MALWARE, ThreatSource::CLIENT_SIDE_DETECTION,
@@ -1176,13 +1174,11 @@
 
   // Load and commit an unrelated URL. The ThreatDetails should not use this
   // navigation entry.
-  content::WebContentsTester::For(web_contents())
-      ->TestDidNavigateWithReferrer(
-          web_contents()->GetMainFrame(), 0 /* nav_entry_id */,
-          true /* did_create_new_entry */, GURL(kUnrelatedURL),
-          content::Referrer(GURL(kUnrelatedReferrerURL),
-                            blink::kWebReferrerPolicyDefault),
-          ui::PAGE_TRANSITION_TYPED);
+  auto navigation = content::NavigationSimulator::CreateBrowserInitiated(
+      GURL(kUnrelatedURL), web_contents());
+  navigation->SetReferrer(content::Referrer(GURL(kUnrelatedReferrerURL),
+                                            blink::kWebReferrerPolicyDefault));
+  navigation->Commit();
 
   // Start a pending load with a referrer.
   controller().LoadURL(
@@ -1237,13 +1233,11 @@
   const char* kPendingURL = "http://www.pending.com/some/path";
 
   // Load and commit the landing URL with a referrer.
-  content::WebContentsTester::For(web_contents())
-      ->TestDidNavigateWithReferrer(
-          web_contents()->GetMainFrame(), 0 /* nav_entry_id */,
-          true /* did_create_new_entry */, GURL(kLandingURL),
-          content::Referrer(GURL(kReferrerURL),
-                            blink::kWebReferrerPolicyDefault),
-          ui::PAGE_TRANSITION_TYPED);
+  auto navigation = content::NavigationSimulator::CreateBrowserInitiated(
+      GURL(kLandingURL), web_contents());
+  navigation->SetReferrer(
+      content::Referrer(GURL(kReferrerURL), blink::kWebReferrerPolicyDefault));
+  navigation->Commit();
 
   // Create UnsafeResource for fake sub-resource of landing page.
   UnsafeResource resource;
diff --git a/chrome/browser/safe_browsing/v4_embedded_test_server_browsertest.cc b/chrome/browser/safe_browsing/v4_embedded_test_server_browsertest.cc
index cedfdd47..6d72167 100644
--- a/chrome/browser/safe_browsing/v4_embedded_test_server_browsertest.cc
+++ b/chrome/browser/safe_browsing/v4_embedded_test_server_browsertest.cc
@@ -6,7 +6,6 @@
 #include <utility>
 
 #include "base/macros.h"
-#include "base/memory/ptr_util.h"
 #include "chrome/browser/ui/browser.h"
 #include "chrome/browser/ui/tabs/tab_strip_model.h"
 #include "chrome/test/base/in_process_browser_test.h"
@@ -36,9 +35,9 @@
     // We only need to mock a local database. The tests will use a true real V4
     // protocol manager.
     V4Database::RegisterStoreFactoryForTest(
-        base::MakeUnique<TestV4StoreFactory>());
+        std::make_unique<TestV4StoreFactory>());
 
-    auto v4_db_factory = base::MakeUnique<TestV4DatabaseFactory>();
+    auto v4_db_factory = std::make_unique<TestV4DatabaseFactory>();
     v4_db_factory_ = v4_db_factory.get();
     V4Database::RegisterDatabaseFactoryForTest(std::move(v4_db_factory));
 
diff --git a/chrome/browser/search_provider_logos/logo_service_factory.cc b/chrome/browser/search_provider_logos/logo_service_factory.cc
index 7c62218..4cb937c 100644
--- a/chrome/browser/search_provider_logos/logo_service_factory.cc
+++ b/chrome/browser/search_provider_logos/logo_service_factory.cc
@@ -14,17 +14,9 @@
 #include "components/search_provider_logos/logo_service_impl.h"
 #include "net/url_request/url_request_context_getter.h"
 
-#if defined(OS_ANDROID)
-#include "chrome/browser/android/feature_utilities.h"
-#endif
-
 using search_provider_logos::LogoService;
 using search_provider_logos::LogoServiceImpl;
 
-#if defined(OS_ANDROID)
-using chrome::android::GetIsChromeHomeEnabled;
-#endif  // defined(OS_ANDROID)
-
 namespace {
 
 constexpr base::FilePath::CharType kCachedLogoDirectory[] =
@@ -57,7 +49,12 @@
   Profile* profile = static_cast<Profile*>(context);
   DCHECK(!profile->IsOffTheRecord());
 #if defined(OS_ANDROID)
-  bool use_gray_background = !GetIsChromeHomeEnabled();
+  // TODO(https://crbug.com/776725): Update LogoServiceImpl to request the
+  // latest value instead of caching it. Depending on the UI mode (ChromeHome
+  // enabled or not), the background where the logo is used changes from gray to
+  // white. This value can change at runtime, so we should stop using a value
+  // determined at factory instantiation time.
+  bool use_gray_background = true;
 #else
   bool use_gray_background = false;
 #endif
diff --git a/chrome/browser/shell_integration_linux.cc b/chrome/browser/shell_integration_linux.cc
index 78bc5d9c..2ab541b 100644
--- a/chrome/browser/shell_integration_linux.cc
+++ b/chrome/browser/shell_integration_linux.cc
@@ -56,6 +56,10 @@
 
 namespace shell_integration {
 
+// Allows LaunchXdgUtility to join a process.
+class LaunchXdgUtilityScopedAllowBaseSyncPrimitives
+    : public base::ScopedAllowBaseSyncPrimitives {};
+
 namespace {
 
 // Helper to launch xdg scripts. We don't want them to ask any questions on the
@@ -79,6 +83,7 @@
   close(devnull);
   if (!process.IsValid())
     return false;
+  LaunchXdgUtilityScopedAllowBaseSyncPrimitives allow_base_sync_primitives;
   return process.WaitForExit(exit_code);
 }
 
diff --git a/chrome/browser/signin/dice_browsertest.cc b/chrome/browser/signin/dice_browsertest.cc
index f0d52eb..47f79b7 100644
--- a/chrome/browser/signin/dice_browsertest.cc
+++ b/chrome/browser/signin/dice_browsertest.cc
@@ -378,6 +378,10 @@
     // stable state.
     reconcilor->AbortReconcile();
     reconcilor->AddObserver(this);
+
+    ASSERT_EQ(
+        account_consistency_method_ == signin::AccountConsistencyMethod::kDice,
+        signin::IsDiceEnabledForProfile(browser()->profile()->GetPrefs()));
   }
 
   void TearDownOnMainThread() override {
@@ -519,6 +523,12 @@
       : DiceBrowserTestBase(AccountConsistencyMethod::kDiceFixAuthErrors) {}
 };
 
+class DiceMigrationBrowserTest : public DiceBrowserTestBase {
+ public:
+  DiceMigrationBrowserTest()
+      : DiceBrowserTestBase(AccountConsistencyMethod::kDiceMigration) {}
+};
+
 // Checks that signin on Gaia triggers the fetch for a refresh token.
 IN_PROC_BROWSER_TEST_F(DiceBrowserTest, Signin) {
   EXPECT_EQ(0, reconcilor_started_count_);
@@ -772,3 +782,49 @@
   EXPECT_EQ(0, reconcilor_blocked_count_);
   WaitForReconcilorUnblockedCount(0);
 }
+
+// Checks that signin on Gaia triggers the fetch for a refresh token.
+IN_PROC_BROWSER_TEST_F(DiceMigrationBrowserTest, Signin) {
+  EXPECT_EQ(0, reconcilor_started_count_);
+
+  // Navigate to Gaia and sign in.
+  NavigateToURL(kSigninURL);
+
+  // Check that the Dice request header was sent, with no signout confirmation.
+  std::string client_id = GaiaUrls::GetInstance()->oauth2_chrome_client_id();
+  EXPECT_EQ(
+      base::StringPrintf("version=%s,client_id=%s,signin_mode=all_accounts,"
+                         "signout_mode=no_confirmation",
+                         signin::kDiceProtocolVersion, client_id.c_str()),
+      dice_request_header_);
+
+  // Check that the token was requested and added to the token service.
+  WaitForTokenReceived();
+  EXPECT_TRUE(GetTokenService()->RefreshTokenIsAvailable(GetMainAccountID()));
+  // Sync should not be enabled.
+  EXPECT_TRUE(GetSigninManager()->GetAuthenticatedAccountId().empty());
+
+  EXPECT_EQ(1, reconcilor_blocked_count_);
+  WaitForReconcilorUnblockedCount(1);
+  EXPECT_EQ(1, reconcilor_started_count_);
+}
+
+IN_PROC_BROWSER_TEST_F(DiceMigrationBrowserTest, Signout) {
+  // Start from a signed-in state.
+  SetupSignedInAccounts();
+
+  // Signout from main account on the web.
+  SignOutWithDice(kAllAccounts);
+
+  // Check that the user is still signed in Chrome on the main account, the
+  // token for the secondary token has been deleted.
+  EXPECT_EQ(GetMainAccountID(),
+            GetSigninManager()->GetAuthenticatedAccountId());
+  EXPECT_TRUE(GetTokenService()->RefreshTokenIsAvailable(GetMainAccountID()));
+  EXPECT_FALSE(
+      GetTokenService()->RefreshTokenIsAvailable(GetSecondaryAccountID()));
+  EXPECT_EQ(1, token_revoked_notification_count_);
+  EXPECT_EQ(1, token_revoked_count_);
+  EXPECT_EQ(1, reconcilor_blocked_count_);
+  WaitForReconcilorUnblockedCount(1);
+}
diff --git a/chrome/browser/signin/dice_response_handler_unittest.cc b/chrome/browser/signin/dice_response_handler_unittest.cc
index 96d7e960..25d90c0 100644
--- a/chrome/browser/signin/dice_response_handler_unittest.cc
+++ b/chrome/browser/signin/dice_response_handler_unittest.cc
@@ -4,8 +4,11 @@
 
 #include "chrome/browser/signin/dice_response_handler.h"
 
+#include <memory>
+
 #include "base/command_line.h"
 #include "base/macros.h"
+#include "base/memory/ptr_util.h"
 #include "base/memory/ref_counted.h"
 #include "base/message_loop/message_loop.h"
 #include "base/scoped_observer.h"
@@ -117,29 +120,27 @@
                         &token_service_,
                         &account_tracker_service_,
                         nullptr),
-        account_reconcilor_(&token_service_,
-                            &signin_manager_,
-                            &signin_client_,
-                            nullptr),
-        dice_response_handler_(&signin_client_,
-                               &signin_manager_,
-                               &token_service_,
-                               &account_tracker_service_,
-                               &account_reconcilor_),
         reconcilor_blocked_count_(0),
         reconcilor_unblocked_count_(0) {
     loop_.SetTaskRunner(task_runner_);
     DCHECK_EQ(task_runner_, base::ThreadTaskRunnerHandle::Get());
     signin_client_.SetURLRequestContext(request_context_getter_.get());
+    AccountReconcilor::RegisterProfilePrefs(pref_service_.registry());
     AccountTrackerService::RegisterPrefs(pref_service_.registry());
     SigninManager::RegisterProfilePrefs(pref_service_.registry());
     signin::RegisterAccountConsistencyProfilePrefs(pref_service_.registry());
+    account_reconcilor_ = base::MakeUnique<AccountReconcilor>(
+        &token_service_, &signin_manager_, &signin_client_, nullptr);
+    dice_response_handler_ = base::MakeUnique<DiceResponseHandler>(
+        &signin_client_, &signin_manager_, &token_service_,
+        &account_tracker_service_, account_reconcilor_.get());
+
     account_tracker_service_.Initialize(&signin_client_);
-    account_reconcilor_.AddObserver(this);
+    account_reconcilor_->AddObserver(this);
   }
 
   ~DiceResponseHandlerTest() override {
-    account_reconcilor_.RemoveObserver(this);
+    account_reconcilor_->RemoveObserver(this);
     task_runner_->ClearPendingTasks();
   }
 
@@ -171,8 +172,8 @@
   ProfileOAuth2TokenService token_service_;
   AccountTrackerService account_tracker_service_;
   FakeSigninManager signin_manager_;
-  AccountReconcilor account_reconcilor_;
-  DiceResponseHandler dice_response_handler_;
+  std::unique_ptr<AccountReconcilor> account_reconcilor_;
+  std::unique_ptr<DiceResponseHandler> dice_response_handler_;
   int reconcilor_blocked_count_;
   int reconcilor_unblocked_count_;
   std::string start_token_fetch_gaia_id_;
@@ -209,7 +210,7 @@
   std::string account_id = account_tracker_service_.PickAccountIdForAccount(
       dice_params.signin_info.gaia_id, dice_params.signin_info.email);
   ASSERT_FALSE(token_service_.RefreshTokenIsAvailable(account_id));
-  dice_response_handler_.ProcessDiceHeader(
+  dice_response_handler_->ProcessDiceHeader(
       dice_params, base::MakeUnique<TestProcessDiceHeaderObserver>(this));
   // Check that a GaiaAuthFetcher has been created.
   ASSERT_THAT(signin_client_.consumer_, testing::NotNull());
@@ -238,7 +239,7 @@
   std::string account_id = account_tracker_service_.PickAccountIdForAccount(
       dice_params.signin_info.gaia_id, dice_params.signin_info.email);
   ASSERT_FALSE(token_service_.RefreshTokenIsAvailable(account_id));
-  dice_response_handler_.ProcessDiceHeader(
+  dice_response_handler_->ProcessDiceHeader(
       dice_params, base::MakeUnique<TestProcessDiceHeaderObserver>(this));
   EXPECT_EQ(dice_params.signin_info.gaia_id, start_token_fetch_gaia_id_);
   EXPECT_EQ(dice_params.signin_info.email, start_token_fetch_email_);
@@ -247,12 +248,12 @@
   // Check that a GaiaAuthFetcher has been created.
   ASSERT_THAT(signin_client_.consumer_, testing::NotNull());
   EXPECT_EQ(
-      1u, dice_response_handler_.GetPendingDiceTokenFetchersCountForTesting());
+      1u, dice_response_handler_->GetPendingDiceTokenFetchersCountForTesting());
   // Simulate GaiaAuthFetcher failure.
   signin_client_.consumer_->OnClientOAuthFailure(
       GoogleServiceAuthError(GoogleServiceAuthError::SERVICE_UNAVAILABLE));
   EXPECT_EQ(
-      0u, dice_response_handler_.GetPendingDiceTokenFetchersCountForTesting());
+      0u, dice_response_handler_->GetPendingDiceTokenFetchersCountForTesting());
   // Check that the token has not been inserted in the token service.
   EXPECT_FALSE(token_service_.RefreshTokenIsAvailable(account_id));
   EXPECT_EQ("", finish_token_fetch_gaia_id_);
@@ -267,7 +268,7 @@
   std::string account_id = account_tracker_service_.PickAccountIdForAccount(
       dice_params.signin_info.gaia_id, dice_params.signin_info.email);
   ASSERT_FALSE(token_service_.RefreshTokenIsAvailable(account_id));
-  dice_response_handler_.ProcessDiceHeader(
+  dice_response_handler_->ProcessDiceHeader(
       dice_params, base::MakeUnique<TestProcessDiceHeaderObserver>(this));
   EXPECT_EQ(dice_params.signin_info.gaia_id, start_token_fetch_gaia_id_);
   EXPECT_EQ(dice_params.signin_info.email, start_token_fetch_email_);
@@ -276,7 +277,7 @@
   ASSERT_THAT(consumer, testing::NotNull());
   // Start a second request for the same account.
   signin_client_.consumer_ = nullptr;
-  dice_response_handler_.ProcessDiceHeader(
+  dice_response_handler_->ProcessDiceHeader(
       dice_params, base::MakeUnique<TestProcessDiceHeaderObserver>(this));
   // Check that there is no new request.
   ASSERT_THAT(signin_client_.consumer_, testing::IsNull());
@@ -303,7 +304,7 @@
   ASSERT_FALSE(token_service_.RefreshTokenIsAvailable(account_id_1));
   ASSERT_FALSE(token_service_.RefreshTokenIsAvailable(account_id_2));
   // Start first request.
-  dice_response_handler_.ProcessDiceHeader(
+  dice_response_handler_->ProcessDiceHeader(
       dice_params_1, base::MakeUnique<TestProcessDiceHeaderObserver>(this));
   // Check that a GaiaAuthFetcher has been created.
   GaiaAuthConsumer* consumer_1 = signin_client_.consumer_;
@@ -312,7 +313,7 @@
   EXPECT_EQ(0, reconcilor_unblocked_count_);
   // Start second request.
   signin_client_.consumer_ = nullptr;
-  dice_response_handler_.ProcessDiceHeader(
+  dice_response_handler_->ProcessDiceHeader(
       dice_params_2, base::MakeUnique<TestProcessDiceHeaderObserver>(this));
   GaiaAuthConsumer* consumer_2 = signin_client_.consumer_;
   ASSERT_THAT(consumer_2, testing::NotNull());
@@ -337,17 +338,17 @@
   std::string account_id = account_tracker_service_.PickAccountIdForAccount(
       dice_params.signin_info.gaia_id, dice_params.signin_info.email);
   ASSERT_FALSE(token_service_.RefreshTokenIsAvailable(account_id));
-  dice_response_handler_.ProcessDiceHeader(
+  dice_response_handler_->ProcessDiceHeader(
       dice_params, base::MakeUnique<TestProcessDiceHeaderObserver>(this));
   // Check that a GaiaAuthFetcher has been created.
   ASSERT_THAT(signin_client_.consumer_, testing::NotNull());
   EXPECT_EQ(
-      1u, dice_response_handler_.GetPendingDiceTokenFetchersCountForTesting());
+      1u, dice_response_handler_->GetPendingDiceTokenFetchersCountForTesting());
   // Force a timeout.
   task_runner_->FastForwardBy(
       base::TimeDelta::FromSeconds(kDiceTokenFetchTimeoutSeconds + 1));
   EXPECT_EQ(
-      0u, dice_response_handler_.GetPendingDiceTokenFetchersCountForTesting());
+      0u, dice_response_handler_->GetPendingDiceTokenFetchersCountForTesting());
   // Check that the token has not been inserted in the token service.
   EXPECT_FALSE(token_service_.RefreshTokenIsAvailable(account_id));
   // Check that the reconcilor was blocked and unblocked exactly once.
@@ -371,7 +372,7 @@
   EXPECT_TRUE(token_service_.RefreshTokenIsAvailable(kSecondaryGaiaID));
   EXPECT_TRUE(signin_manager_.IsAuthenticated());
   // Receive signout response for the main account.
-  dice_response_handler_.ProcessDiceHeader(
+  dice_response_handler_->ProcessDiceHeader(
       dice_params, base::MakeUnique<TestProcessDiceHeaderObserver>(this));
   EXPECT_EQ("", start_token_fetch_gaia_id_);
   EXPECT_EQ("", start_token_fetch_email_);
@@ -412,7 +413,7 @@
   EXPECT_TRUE(signin_manager_.IsAuthenticated());
 
   // Receive signout response for all accounts.
-  dice_response_handler_.ProcessDiceHeader(
+  dice_response_handler_->ProcessDiceHeader(
       dice_params, base::MakeUnique<TestProcessDiceHeaderObserver>(this));
   EXPECT_EQ("", start_token_fetch_gaia_id_);
   EXPECT_EQ("", start_token_fetch_email_);
@@ -446,7 +447,7 @@
   EXPECT_TRUE(token_service_.RefreshTokenIsAvailable(main_account_id));
   EXPECT_TRUE(signin_manager_.IsAuthenticated());
   // Receive signout response for the secondary account.
-  dice_response_handler_.ProcessDiceHeader(
+  dice_response_handler_->ProcessDiceHeader(
       dice_params, base::MakeUnique<TestProcessDiceHeaderObserver>(this));
   EXPECT_EQ("", start_token_fetch_gaia_id_);
   EXPECT_EQ("", start_token_fetch_email_);
@@ -474,7 +475,7 @@
   EXPECT_TRUE(token_service_.RefreshTokenIsAvailable(kSecondaryAccountID));
   EXPECT_FALSE(signin_manager_.IsAuthenticated());
   // Receive signout response.
-  dice_response_handler_.ProcessDiceHeader(
+  dice_response_handler_->ProcessDiceHeader(
       dice_params, base::MakeUnique<TestProcessDiceHeaderObserver>(this));
   // Only the token corresponding the the Dice parameter has been removed.
   EXPECT_FALSE(token_service_.RefreshTokenIsAvailable(account_id));
@@ -499,19 +500,19 @@
   dice_params_2.signin_info.gaia_id = "other_gaia_id";
   std::string account_id_2 = account_tracker_service_.PickAccountIdForAccount(
       dice_params_2.signin_info.gaia_id, dice_params_2.signin_info.email);
-  dice_response_handler_.ProcessDiceHeader(
+  dice_response_handler_->ProcessDiceHeader(
       dice_params_2, base::MakeUnique<TestProcessDiceHeaderObserver>(this));
   // Check that a GaiaAuthFetcher has been created and is pending.
   ASSERT_THAT(signin_client_.consumer_, testing::NotNull());
   EXPECT_EQ(
-      1u, dice_response_handler_.GetPendingDiceTokenFetchersCountForTesting());
+      1u, dice_response_handler_->GetPendingDiceTokenFetchersCountForTesting());
   ASSERT_FALSE(token_service_.RefreshTokenIsAvailable(account_id_2));
   // Signout from main account while signin for the other account is in flight.
-  dice_response_handler_.ProcessDiceHeader(
+  dice_response_handler_->ProcessDiceHeader(
       dice_params, base::MakeUnique<TestProcessDiceHeaderObserver>(this));
   // Check that the token fetcher has been canceled and all tokens erased.
   EXPECT_EQ(
-      0u, dice_response_handler_.GetPendingDiceTokenFetchersCountForTesting());
+      0u, dice_response_handler_->GetPendingDiceTokenFetchersCountForTesting());
   EXPECT_FALSE(token_service_.RefreshTokenIsAvailable(account_id));
   EXPECT_FALSE(token_service_.RefreshTokenIsAvailable(account_id_2));
 }
@@ -531,28 +532,28 @@
       signin_params_1.signin_info.gaia_id, signin_params_1.signin_info.email);
   std::string account_id_2 = account_tracker_service_.PickAccountIdForAccount(
       signin_params_2.signin_info.gaia_id, signin_params_2.signin_info.email);
-  dice_response_handler_.ProcessDiceHeader(
+  dice_response_handler_->ProcessDiceHeader(
       signin_params_1, base::MakeUnique<TestProcessDiceHeaderObserver>(this));
   ASSERT_THAT(signin_client_.consumer_, testing::NotNull());
   signin_client_.consumer_ = nullptr;
-  dice_response_handler_.ProcessDiceHeader(
+  dice_response_handler_->ProcessDiceHeader(
       signin_params_2, base::MakeUnique<TestProcessDiceHeaderObserver>(this));
   ASSERT_THAT(signin_client_.consumer_, testing::NotNull());
   EXPECT_EQ(
-      2u, dice_response_handler_.GetPendingDiceTokenFetchersCountForTesting());
+      2u, dice_response_handler_->GetPendingDiceTokenFetchersCountForTesting());
   ASSERT_FALSE(token_service_.RefreshTokenIsAvailable(account_id_1));
   ASSERT_FALSE(token_service_.RefreshTokenIsAvailable(account_id_2));
   // Signout from one of the accounts while signin is in flight.
-  dice_response_handler_.ProcessDiceHeader(
+  dice_response_handler_->ProcessDiceHeader(
       signout_params_1, base::MakeUnique<TestProcessDiceHeaderObserver>(this));
   // Check that one of the fetchers is cancelled.
   EXPECT_EQ(
-      1u, dice_response_handler_.GetPendingDiceTokenFetchersCountForTesting());
+      1u, dice_response_handler_->GetPendingDiceTokenFetchersCountForTesting());
   // Allow the remaining fetcher to complete.
   signin_client_.consumer_->OnClientOAuthSuccess(
       GaiaAuthConsumer::ClientOAuthResult("refresh_token", "access_token", 10));
   EXPECT_EQ(
-      0u, dice_response_handler_.GetPendingDiceTokenFetchersCountForTesting());
+      0u, dice_response_handler_->GetPendingDiceTokenFetchersCountForTesting());
   // Check that the right token is available.
   EXPECT_FALSE(token_service_.RefreshTokenIsAvailable(account_id_1));
   EXPECT_TRUE(token_service_.RefreshTokenIsAvailable(account_id_2));
@@ -565,7 +566,7 @@
   ASSERT_FALSE(token_service_.RefreshTokenIsAvailable(
       account_tracker_service_.PickAccountIdForAccount(
           dice_params.signin_info.gaia_id, dice_params.signin_info.email)));
-  dice_response_handler_.ProcessDiceHeader(
+  dice_response_handler_->ProcessDiceHeader(
       dice_params, base::MakeUnique<TestProcessDiceHeaderObserver>(this));
   // Check that a GaiaAuthFetcher has not been created.
   ASSERT_THAT(signin_client_.consumer_, testing::IsNull());
@@ -585,7 +586,7 @@
   EXPECT_TRUE(token_service_.RefreshTokenIsAvailable(account_id));
   EXPECT_TRUE(signin_manager_.IsAuthenticated());
   // Start re-authentication on the web.
-  dice_response_handler_.ProcessDiceHeader(
+  dice_response_handler_->ProcessDiceHeader(
       dice_params, base::MakeUnique<TestProcessDiceHeaderObserver>(this));
   // Check that a GaiaAuthFetcher has been created.
   ASSERT_THAT(signin_client_.consumer_, testing::NotNull());
@@ -611,7 +612,7 @@
   EXPECT_TRUE(token_service_.RefreshTokenIsAvailable(account_id));
   EXPECT_TRUE(signin_manager_.IsAuthenticated());
   // Start re-authentication on the web.
-  dice_response_handler_.ProcessDiceHeader(
+  dice_response_handler_->ProcessDiceHeader(
       dice_params, base::MakeUnique<TestProcessDiceHeaderObserver>(this));
   // Check that a GaiaAuthFetcher has been created.
   ASSERT_THAT(signin_client_.consumer_, testing::NotNull());
@@ -650,7 +651,7 @@
   EXPECT_TRUE(token_service_.RefreshTokenIsAvailable(account_id));
   EXPECT_TRUE(signin_manager_.IsAuthenticated());
   // Receive signout response for the main account.
-  dice_response_handler_.ProcessDiceHeader(
+  dice_response_handler_->ProcessDiceHeader(
       dice_params, base::MakeUnique<TestProcessDiceHeaderObserver>(this));
   // User is not signed out from Chrome.
   EXPECT_TRUE(token_service_.RefreshTokenIsAvailable(account_id));
diff --git a/chrome/browser/signin/easy_unlock_service.cc b/chrome/browser/signin/easy_unlock_service.cc
index 62aa970..6b904005 100644
--- a/chrome/browser/signin/easy_unlock_service.cc
+++ b/chrome/browser/signin/easy_unlock_service.cc
@@ -206,7 +206,9 @@
 
  private:
   // chromeos::PowerManagerClient::Observer:
-  void SuspendImminent() override { service_->PrepareForSuspend(); }
+  void SuspendImminent(power_manager::SuspendImminent::Reason reason) override {
+    service_->PrepareForSuspend();
+  }
 
   void SuspendDone(const base::TimeDelta& sleep_duration) override {
     waking_up_ = true;
diff --git a/chrome/browser/signin/easy_unlock_service_unittest_chromeos.cc b/chrome/browser/signin/easy_unlock_service_unittest_chromeos.cc
index a029e97a..d9cf821 100644
--- a/chrome/browser/signin/easy_unlock_service_unittest_chromeos.cc
+++ b/chrome/browser/signin/easy_unlock_service_unittest_chromeos.cc
@@ -26,6 +26,7 @@
 #include "chrome/test/base/testing_profile.h"
 #include "chromeos/dbus/dbus_thread_manager.h"
 #include "chromeos/dbus/fake_power_manager_client.h"
+#include "chromeos/dbus/power_manager/suspend.pb.h"
 #include "components/signin/core/account_id/account_id.h"
 #include "components/signin/core/browser/signin_manager_base.h"
 #include "components/sync_preferences/testing_pref_service_syncable.h"
@@ -360,7 +361,8 @@
   EXPECT_TRUE(
       EasyUnlockAppInState(profile_.get(), TestAppManager::STATE_LOADED));
 
-  power_manager_client()->SendSuspendImminent();
+  power_manager_client()->SendSuspendImminent(
+      power_manager::SuspendImminent_Reason_OTHER);
   EXPECT_TRUE(
       EasyUnlockAppInState(profile_.get(), TestAppManager::STATE_DISABLED));
 
diff --git a/chrome/browser/signin/signin_promo.cc b/chrome/browser/signin/signin_promo.cc
index 8d2e6c5..aec0739 100644
--- a/chrome/browser/signin/signin_promo.cc
+++ b/chrome/browser/signin/signin_promo.cc
@@ -22,6 +22,7 @@
 #include "chrome/browser/signin/signin_manager_factory.h"
 #include "chrome/browser/signin/signin_promo_util.h"
 #include "chrome/browser/ui/webui/theme_source.h"
+#include "chrome/common/chrome_features.h"
 #include "chrome/common/pref_names.h"
 #include "chrome/common/url_constants.h"
 #include "components/google/core/browser/google_util.h"
@@ -78,6 +79,48 @@
   return profile->GetPrefs()->GetBoolean(prefs::kSignInPromoUserSkipped);
 }
 
+// Returns the sign in promo URL with the given arguments in the query.
+// |access_point| indicates where the sign in is being initiated.
+// |reason| indicates the purpose of using this URL.
+// |auto_close| whether to close the sign in promo automatically when done.
+// |is_constrained| whether to load the URL in a constrained window, false
+// by default.
+GURL GetPromoURL(signin_metrics::AccessPoint access_point,
+                 signin_metrics::Reason reason,
+                 bool auto_close,
+                 bool is_constrained) {
+  CHECK_LT(static_cast<int>(access_point),
+           static_cast<int>(signin_metrics::AccessPoint::ACCESS_POINT_MAX));
+  CHECK_NE(static_cast<int>(access_point),
+           static_cast<int>(signin_metrics::AccessPoint::ACCESS_POINT_UNKNOWN));
+  CHECK_LT(static_cast<int>(reason),
+           static_cast<int>(signin_metrics::Reason::REASON_MAX));
+  CHECK_NE(static_cast<int>(reason),
+           static_cast<int>(signin_metrics::Reason::REASON_UNKNOWN_REASON));
+
+  std::string url(chrome::kChromeUIChromeSigninURL);
+  base::StringAppendF(&url, "?%s=%d", signin::kSignInPromoQueryKeyAccessPoint,
+                      static_cast<int>(access_point));
+  base::StringAppendF(&url, "&%s=%d", signin::kSignInPromoQueryKeyReason,
+                      static_cast<int>(reason));
+  if (auto_close)
+    base::StringAppendF(&url, "&%s=1", signin::kSignInPromoQueryKeyAutoClose);
+  if (is_constrained)
+    base::StringAppendF(&url, "&%s=1", signin::kSignInPromoQueryKeyConstrained);
+  return GURL(url);
+}
+
+GURL GetReauthURL(signin_metrics::AccessPoint access_point,
+                  signin_metrics::Reason reason,
+                  const std::string& email,
+                  bool auto_close,
+                  bool is_constrained) {
+  GURL url = GetPromoURL(access_point, reason, auto_close, is_constrained);
+  url = net::AppendQueryParameter(url, "email", email);
+  url = net::AppendQueryParameter(url, "validateEmail", "1");
+  return net::AppendQueryParameter(url, "readOnlyEmail", "1");
+}
+
 }  // namespace
 
 namespace signin {
@@ -167,56 +210,63 @@
   return GURL(url);
 }
 
-GURL GetPromoURL(signin_metrics::AccessPoint access_point,
-                 signin_metrics::Reason reason,
-                 bool auto_close) {
+GURL GetPromoURLForTab(signin_metrics::AccessPoint access_point,
+                       signin_metrics::Reason reason,
+                       bool auto_close) {
+  if (base::FeatureList::IsEnabled(
+          features::kRemoveUsageOfDeprecatedGaiaSigninEndpoint)) {
+    // The full-tab sign-in endpoint is deprecated. Use the constrained page for
+    // the full-tab URL as well.
+    return GetPromoURL(access_point, reason, auto_close,
+                       true /* is_constrained */);
+  }
+
   return GetPromoURL(access_point, reason, auto_close,
                      false /* is_constrained */);
 }
 
-GURL GetPromoURL(signin_metrics::AccessPoint access_point,
-                 signin_metrics::Reason reason,
-                 bool auto_close,
-                 bool is_constrained) {
-  CHECK_LT(static_cast<int>(access_point),
-           static_cast<int>(signin_metrics::AccessPoint::ACCESS_POINT_MAX));
-  CHECK_NE(static_cast<int>(access_point),
-           static_cast<int>(signin_metrics::AccessPoint::ACCESS_POINT_UNKNOWN));
-  CHECK_LT(static_cast<int>(reason),
-           static_cast<int>(signin_metrics::Reason::REASON_MAX));
-  CHECK_NE(static_cast<int>(reason),
-           static_cast<int>(signin_metrics::Reason::REASON_UNKNOWN_REASON));
-
-  std::string url(chrome::kChromeUIChromeSigninURL);
-  base::StringAppendF(&url, "?%s=%d", kSignInPromoQueryKeyAccessPoint,
-                      static_cast<int>(access_point));
-  base::StringAppendF(&url, "&%s=%d", kSignInPromoQueryKeyReason,
-                      static_cast<int>(reason));
-  if (auto_close)
-    base::StringAppendF(&url, "&%s=1", kSignInPromoQueryKeyAutoClose);
-  if (is_constrained)
-    base::StringAppendF(&url, "&%s=1", kSignInPromoQueryKeyConstrained);
-  return GURL(url);
+GURL GetPromoURLForDialog(signin_metrics::AccessPoint access_point,
+                          signin_metrics::Reason reason,
+                          bool auto_close) {
+  return GetPromoURL(access_point, reason, auto_close,
+                     true /* is_constrained */);
 }
 
-GURL GetReauthURL(signin_metrics::AccessPoint access_point,
-                  signin_metrics::Reason reason,
-                  Profile* profile,
-                  const std::string& account_id) {
+GURL GetReauthURLForDialog(signin_metrics::AccessPoint access_point,
+                           signin_metrics::Reason reason,
+                           Profile* profile,
+                           const std::string& account_id) {
   AccountInfo info = AccountTrackerServiceFactory::GetForProfile(profile)
                          ->GetAccountInfo(account_id);
-  return GetReauthURLWithEmail(access_point, reason, info.email);
+  return GetReauthURL(access_point, reason, info.email, true /* auto_close */,
+                      true /* is_constrained */);
 }
 
-GURL GetReauthURLWithEmail(signin_metrics::AccessPoint access_point,
-                           signin_metrics::Reason reason,
-                           const std::string& email) {
-  GURL url = signin::GetPromoURL(access_point, reason, true /* auto_close */,
-                                 true /* is_constrained */);
+GURL GetReauthURLForTab(signin_metrics::AccessPoint access_point,
+                        signin_metrics::Reason reason,
+                        Profile* profile,
+                        const std::string& account_id) {
+  AccountInfo info =
+      AccountTrackerServiceFactory::GetForProfile(profile)->GetAccountInfo(
+          account_id);
 
-  url = net::AppendQueryParameter(url, "email", email);
-  url = net::AppendQueryParameter(url, "validateEmail", "1");
-  return net::AppendQueryParameter(url, "readOnlyEmail", "1");
+  if (base::FeatureList::IsEnabled(
+          features::kRemoveUsageOfDeprecatedGaiaSigninEndpoint)) {
+    // The full-tab sign-in endpoint is deprecated. Use the constrained page for
+    // the full-tab URL as well.
+    return GetReauthURL(access_point, reason, info.email, true /* auto_close */,
+                        true /* is_constrained */);
+  }
+
+  return GetReauthURL(access_point, reason, info.email, true /* auto_close */,
+                      false /* is_constrained */);
+}
+
+GURL GetReauthURLWithEmailForDialog(signin_metrics::AccessPoint access_point,
+                                    signin_metrics::Reason reason,
+                                    const std::string& email) {
+  return GetReauthURL(access_point, reason, email, true /* auto_close */,
+                      true /* is_constrained */);
 }
 
 GURL GetNextPageURLForPromoURL(const GURL& url) {
@@ -239,23 +289,23 @@
                                     signin_metrics::AccessPoint access_point) {
   switch (mode) {
     case profiles::BUBBLE_VIEW_MODE_GAIA_SIGNIN:
-      return GetPromoURL(access_point,
-                         signin_metrics::Reason::REASON_SIGNIN_PRIMARY_ACCOUNT,
-                         false /* auto_close */, true /* is_constrained */);
+      return GetPromoURLForDialog(
+          access_point, signin_metrics::Reason::REASON_SIGNIN_PRIMARY_ACCOUNT,
+          false /* auto_close */);
       break;
     case profiles::BUBBLE_VIEW_MODE_GAIA_ADD_ACCOUNT:
-      return GetPromoURL(access_point,
-                         signin_metrics::Reason::REASON_ADD_SECONDARY_ACCOUNT,
-                         false /* auto_close */, true /* is_constrained */);
+      return GetPromoURLForDialog(
+          access_point, signin_metrics::Reason::REASON_ADD_SECONDARY_ACCOUNT,
+          false /* auto_close */);
       break;
     case profiles::BUBBLE_VIEW_MODE_GAIA_REAUTH: {
       const SigninErrorController* error_controller =
           SigninErrorControllerFactory::GetForProfile(profile);
       CHECK(error_controller);
       DCHECK(error_controller->HasError());
-      return GetReauthURL(access_point,
-                          signin_metrics::Reason::REASON_REAUTHENTICATION,
-                          profile, error_controller->error_account_id());
+      return GetReauthURLForDialog(
+          access_point, signin_metrics::Reason::REASON_REAUTHENTICATION,
+          profile, error_controller->error_account_id());
       break;
     }
     default:
diff --git a/chrome/browser/signin/signin_promo.h b/chrome/browser/signin/signin_promo.h
index 6526396..5d71fb3 100644
--- a/chrome/browser/signin/signin_promo.h
+++ b/chrome/browser/signin/signin_promo.h
@@ -43,30 +43,43 @@
 // Gets the sign in landing page URL.
 GURL GetLandingURL(signin_metrics::AccessPoint access_point);
 
-// Returns the sign in promo URL wth the given arguments in the query.
+// Returns the sign in promo URL that can be used in a full browser tab with
+// the given arguments in the query.
 // |access_point| indicates where the sign in is being initiated.
 // |reason| indicates the purpose of using this URL.
 // |auto_close| whether to close the sign in promo automatically when done.
-// |is_constrained} whether to load the URL in a constrained window, false
-// by default.
-GURL GetPromoURL(signin_metrics::AccessPoint access_point,
-                 signin_metrics::Reason reason,
-                 bool auto_close);
-GURL GetPromoURL(signin_metrics::AccessPoint access_point,
-                 signin_metrics::Reason reason,
-                 bool auto_close,
-                 bool is_constrained);
+GURL GetPromoURLForTab(signin_metrics::AccessPoint access_point,
+                       signin_metrics::Reason reason,
+                       bool auto_close);
 
-// Returns a sign in promo URL specifically for reauthenticating |account_id|.
-GURL GetReauthURL(signin_metrics::AccessPoint access_point,
-                  signin_metrics::Reason reason,
-                  Profile* profile,
-                  const std::string& account_id);
+// Returns the sign in promo URL that can be used in a modal dialog with
+// the given arguments in the query.
+// |access_point| indicates where the sign in is being initiated.
+// |reason| indicates the purpose of using this URL.
+// |auto_close| whether to close the sign in promo automatically when done.
+GURL GetPromoURLForDialog(signin_metrics::AccessPoint access_point,
+                          signin_metrics::Reason reason,
+                          bool auto_close);
 
-// Returns a sign in promo URL specifically for reauthenticating |email|.
-GURL GetReauthURLWithEmail(signin_metrics::AccessPoint access_point,
+// Returns a sign in promo URL specifically for reauthenticating |account_id|
+// that can be used in a full browser tab.
+GURL GetReauthURLForTab(signin_metrics::AccessPoint access_point,
+                        signin_metrics::Reason reason,
+                        Profile* profile,
+                        const std::string& account_id);
+
+// Returns a sign in promo URL specifically for reauthenticating |account_id|
+// that can be used in a modal dialog.
+GURL GetReauthURLForDialog(signin_metrics::AccessPoint access_point,
                            signin_metrics::Reason reason,
-                           const std::string& email);
+                           Profile* profile,
+                           const std::string& account_id);
+
+// Returns a sign in promo URL specifically for reauthenticating |email| that
+// can be used in a modal dialog.
+GURL GetReauthURLWithEmailForDialog(signin_metrics::AccessPoint access_point,
+                                    signin_metrics::Reason reason,
+                                    const std::string& email);
 
 // Gets the next page URL from the query portion of the sign in promo URL.
 GURL GetNextPageURLForPromoURL(const GURL& url);
diff --git a/chrome/browser/ssl/chrome_expect_ct_reporter.cc b/chrome/browser/ssl/chrome_expect_ct_reporter.cc
index 31ad8bc..68cff09 100644
--- a/chrome/browser/ssl/chrome_expect_ct_reporter.cc
+++ b/chrome/browser/ssl/chrome_expect_ct_reporter.cc
@@ -37,7 +37,7 @@
   std::string response_headers;
   request->GetResponseHeaderByName(header, &response_headers);
   const std::vector<std::string> response_values = base::SplitString(
-      response_headers, ",", base::KEEP_WHITESPACE, base::SPLIT_WANT_NONEMPTY);
+      response_headers, ",", base::TRIM_WHITESPACE, base::SPLIT_WANT_NONEMPTY);
   for (const auto& value : response_values) {
     for (const auto& allowed : allowed_values) {
       if (base::ToLowerASCII(allowed) == base::ToLowerASCII(value)) {
diff --git a/chrome/browser/ssl/chrome_expect_ct_reporter.h b/chrome/browser/ssl/chrome_expect_ct_reporter.h
index bb07a527..4a1c1a7 100644
--- a/chrome/browser/ssl/chrome_expect_ct_reporter.h
+++ b/chrome/browser/ssl/chrome_expect_ct_reporter.h
@@ -67,6 +67,8 @@
   FRIEND_TEST_ALL_PREFIXES(ChromeExpectCTReporterTest, EmptyReportURI);
   FRIEND_TEST_ALL_PREFIXES(ChromeExpectCTReporterTest, SendReport);
   FRIEND_TEST_ALL_PREFIXES(ChromeExpectCTReporterTest,
+                           PreflightContainsWhitespace);
+  FRIEND_TEST_ALL_PREFIXES(ChromeExpectCTReporterTest,
                            BadCORSPreflightResponseOrigin);
   FRIEND_TEST_ALL_PREFIXES(ChromeExpectCTReporterTest,
                            BadCORSPreflightResponseMethods);
diff --git a/chrome/browser/ssl/chrome_expect_ct_reporter_unittest.cc b/chrome/browser/ssl/chrome_expect_ct_reporter_unittest.cc
index 09fc12b..e9f8f3e 100644
--- a/chrome/browser/ssl/chrome_expect_ct_reporter_unittest.cc
+++ b/chrome/browser/ssl/chrome_expect_ct_reporter_unittest.cc
@@ -405,6 +405,10 @@
     EXPECT_EQ(successful_report_uri, sender->latest_report_uri());
   }
 
+  void SetCORSHeaderWithWhitespace() {
+    cors_headers_["Access-Control-Allow-Methods"] = "GET, POST";
+  }
+
  private:
   content::TestBrowserThreadBundle thread_bundle_;
   net::EmbeddedTestServer report_server_;
@@ -618,6 +622,37 @@
   histograms.ExpectBucketCount(kSendHistogramName, true, 1);
 }
 
+// Test that report preflight responses can contain whitespace.
+TEST_F(ChromeExpectCTReporterTest, PreflightContainsWhitespace) {
+  SetCORSHeaderWithWhitespace();
+
+  TestCertificateReportSender* sender = new TestCertificateReportSender();
+  net::TestURLRequestContext context;
+  ChromeExpectCTReporter reporter(&context);
+  reporter.report_sender_.reset(sender);
+  EXPECT_TRUE(sender->latest_report_uri().is_empty());
+  EXPECT_TRUE(sender->latest_serialized_report().empty());
+
+  net::SSLInfo ssl_info;
+  ssl_info.cert =
+      net::ImportCertFromFile(net::GetTestCertsDirectory(), "ok_cert.pem");
+  ssl_info.unverified_cert = net::ImportCertFromFile(
+      net::GetTestCertsDirectory(), "localhost_cert.pem");
+
+  const GURL report_uri = test_server().GetURL("/report");
+  reporter.OnExpectCTFailed(net::HostPortPair::FromURL(report_uri), report_uri,
+                            base::Time::Now(), ssl_info.cert.get(),
+                            ssl_info.unverified_cert.get(),
+                            ssl_info.signed_certificate_timestamps);
+
+  // A CORS preflight request should be sent before the actual report.
+  WaitForReportPreflight();
+  sender->WaitForReport(report_uri);
+
+  EXPECT_EQ(report_uri, sender->latest_report_uri());
+  EXPECT_FALSE(sender->latest_serialized_report().empty());
+}
+
 // Test that no report is sent when the CORS preflight returns an invalid
 // Access-Control-Allow-Origin.
 TEST_F(ChromeExpectCTReporterTest, BadCORSPreflightResponseOrigin) {
diff --git a/chrome/browser/ssl/ssl_browser_tests.cc b/chrome/browser/ssl/ssl_browser_tests.cc
index 9ffe798..564a39c 100644
--- a/chrome/browser/ssl/ssl_browser_tests.cc
+++ b/chrome/browser/ssl/ssl_browser_tests.cc
@@ -850,6 +850,13 @@
   }
 };
 
+class SSLUITestCommittedInterstitials : public SSLUITest {
+ protected:
+  void SetUpCommandLine(base::CommandLine* command_line) override {
+    command_line->AppendSwitch(switches::kCommittedInterstitials);
+  }
+};
+
 // Visits a regular page over http.
 IN_PROC_BROWSER_TEST_F(SSLUITest, TestHTTP) {
   ASSERT_TRUE(embedded_test_server()->Start());
@@ -5198,6 +5205,23 @@
                                SSLErrorHandler::OS_REPORTS_CAPTIVE_PORTAL, 0);
 }
 
+// Tests that the committed interstitial flag triggers the code path to show an
+// error PageType instead of an interstitial PageType.
+IN_PROC_BROWSER_TEST_F(SSLUITestCommittedInterstitials, ErrorPageType) {
+  ASSERT_TRUE(https_server_expired_.Start());
+  WebContents* tab = browser()->tab_strip_model()->GetActiveWebContents();
+  ui_test_utils::NavigateToURL(
+      browser(), https_server_expired_.GetURL("/ssl/google.html"));
+
+  // TODO(crbug.com/751951, crbug.com/752372): Get the correct cert error and
+  // security state showing in this test.
+  CheckSecurityState(tab, CertError::NONE, security_state::NONE,
+                     AuthState::SHOWING_ERROR);
+
+  NavigationEntry* entry = tab->GetController().GetVisibleEntry();
+  EXPECT_EQ(content::PAGE_TYPE_ERROR, entry->GetPageType());
+}
+
 namespace {
 
 // SPKI hash to captive-portal.badssl.com leaf certificate. This
diff --git a/chrome/browser/subresource_filter/subresource_filter_browser_test_harness.cc b/chrome/browser/subresource_filter/subresource_filter_browser_test_harness.cc
index 33c6def..e7762cd8e 100644
--- a/chrome/browser/subresource_filter/subresource_filter_browser_test_harness.cc
+++ b/chrome/browser/subresource_filter/subresource_filter_browser_test_harness.cc
@@ -10,7 +10,6 @@
 #include "base/files/file_path.h"
 #include "base/location.h"
 #include "base/logging.h"
-#include "base/memory/ptr_util.h"
 #include "base/path_service.h"
 #include "base/strings/string_piece.h"
 #include "base/strings/string_util.h"
@@ -23,6 +22,7 @@
 #include "chrome/browser/ui/tabs/tab_strip_model.h"
 #include "chrome/common/chrome_paths.h"
 #include "components/safe_browsing/db/v4_protocol_manager_util.h"
+#include "components/safe_browsing/db/v4_test_util.h"
 #include "components/safe_browsing/features.h"
 #include "components/subresource_filter/core/browser/subresource_filter_features.h"
 #include "content/public/browser/web_contents.h"
@@ -85,7 +85,7 @@
 
 std::unique_ptr<TestSafeBrowsingDatabaseHelper>
 SubresourceFilterBrowserTest::CreateTestDatabase() {
-  return base::MakeUnique<TestSafeBrowsingDatabaseHelper>();
+  return std::make_unique<TestSafeBrowsingDatabaseHelper>();
 }
 
 GURL SubresourceFilterBrowserTest::GetTestUrl(
@@ -95,14 +95,14 @@
 
 void SubresourceFilterBrowserTest::ConfigureAsPhishingURL(const GURL& url) {
   safe_browsing::ThreatMetadata metadata;
-  database_helper_->MarkUrlAsMatchingListIdWithMetadata(
+  database_helper_->AddFullHashToDbAndFullHashCache(
       url, safe_browsing::GetUrlSocEngId(), metadata);
 }
 
 void SubresourceFilterBrowserTest::ConfigureAsSubresourceFilterOnlyURL(
     const GURL& url) {
   safe_browsing::ThreatMetadata metadata;
-  database_helper_->MarkUrlAsMatchingListIdWithMetadata(
+  database_helper_->AddFullHashToDbAndFullHashCache(
       url, safe_browsing::GetUrlSubresourceFilterId(), metadata);
 }
 
@@ -115,7 +115,7 @@
     metadata.subresource_filter_match[type] =
         safe_browsing::SubresourceFilterLevel::WARN;
   }
-  database_helper_->MarkUrlAsMatchingListIdWithMetadata(
+  database_helper_->AddFullHashToDbAndFullHashCache(
       url, safe_browsing::GetUrlSubresourceFilterId(), metadata);
 }
 
@@ -243,7 +243,9 @@
 SubresourceFilterListInsertingBrowserTest::CreateTestDatabase() {
   std::vector<safe_browsing::ListIdentifier> list_ids = {
       safe_browsing::GetUrlSubresourceFilterId()};
-  return base::MakeUnique<TestSafeBrowsingDatabaseHelper>(std::move(list_ids));
+  return std::make_unique<TestSafeBrowsingDatabaseHelper>(
+      std::make_unique<safe_browsing::TestV4GetHashProtocolManagerFactory>(),
+      std::move(list_ids));
 }
 
 }  // namespace subresource_filter
diff --git a/chrome/browser/subresource_filter/subresource_filter_browsertest.cc b/chrome/browser/subresource_filter/subresource_filter_browsertest.cc
index 2ecbdbe..3bacfc8d 100644
--- a/chrome/browser/subresource_filter/subresource_filter_browsertest.cc
+++ b/chrome/browser/subresource_filter/subresource_filter_browsertest.cc
@@ -642,7 +642,7 @@
       g_browser_process->subresource_filter_ruleset_service();
   ASSERT_TRUE(service->ruleset_dealer());
   auto ruleset_handle =
-      base::MakeUnique<VerifiedRuleset::Handle>(service->ruleset_dealer());
+      std::make_unique<VerifiedRuleset::Handle>(service->ruleset_dealer());
   AsyncDocumentSubresourceFilter::InitializationParams params(
       GURL("https://example.com/"), ActivationLevel::ENABLED, false);
 
@@ -659,7 +659,7 @@
       g_browser_process->subresource_filter_ruleset_service();
   ASSERT_TRUE(service->ruleset_dealer());
   auto ruleset_handle =
-      base::MakeUnique<VerifiedRuleset::Handle>(service->ruleset_dealer());
+      std::make_unique<VerifiedRuleset::Handle>(service->ruleset_dealer());
   AsyncDocumentSubresourceFilter::InitializationParams params(
       GURL("https://example.com/"), ActivationLevel::ENABLED, false);
 
@@ -690,7 +690,7 @@
       testing::TestRuleset::Open(test_ruleset_pair.indexed));
 
   auto ruleset_handle =
-      base::MakeUnique<VerifiedRuleset::Handle>(service->ruleset_dealer());
+      std::make_unique<VerifiedRuleset::Handle>(service->ruleset_dealer());
   AsyncDocumentSubresourceFilter::InitializationParams params(
       GURL("https://example.com/"), ActivationLevel::ENABLED, false);
 
diff --git a/chrome/browser/subresource_filter/subresource_filter_intercepting_browsertest.cc b/chrome/browser/subresource_filter/subresource_filter_intercepting_browsertest.cc
new file mode 100644
index 0000000..027698a
--- /dev/null
+++ b/chrome/browser/subresource_filter/subresource_filter_intercepting_browsertest.cc
@@ -0,0 +1,128 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include <memory>
+#include <string>
+#include <utility>
+#include <vector>
+
+#include "base/macros.h"
+#include "chrome/browser/safe_browsing/test_safe_browsing_database_helper.h"
+#include "chrome/browser/subresource_filter/subresource_filter_browser_test_harness.h"
+#include "chrome/test/base/ui_test_utils.h"
+#include "components/safe_browsing/db/safebrowsing.pb.h"
+#include "components/safe_browsing/db/v4_embedded_test_server_util.h"
+#include "components/safe_browsing/db/v4_protocol_manager_util.h"
+#include "components/safe_browsing/db/v4_test_util.h"
+#include "components/subresource_filter/core/browser/subresource_filter_constants.h"
+#include "components/subresource_filter/core/browser/subresource_filter_features.h"
+#include "content/public/browser/web_contents.h"
+#include "content/public/test/browser_test_utils.h"
+#include "net/test/embedded_test_server/embedded_test_server.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "url/gurl.h"
+
+namespace subresource_filter {
+
+// This test harness intercepts URLRequests going to the SafeBrowsing V4 server.
+// It allows the tests to mock out proto responses.
+class SubresourceFilterInterceptingBrowserTest
+    : public SubresourceFilterBrowserTest {
+ public:
+  SubresourceFilterInterceptingBrowserTest()
+      : safe_browsing_test_server_(
+            std::make_unique<net::test_server::EmbeddedTestServer>()) {}
+  ~SubresourceFilterInterceptingBrowserTest() override {}
+
+  net::test_server::EmbeddedTestServer* safe_browsing_test_server() {
+    return safe_browsing_test_server_.get();
+  }
+
+  safe_browsing::ThreatMatch GetBetterAdsMatch(const GURL& url,
+                                               const std::string& bas_value) {
+    safe_browsing::ThreatMatch threat_match;
+    threat_match.set_threat_type(safe_browsing::SUBRESOURCE_FILTER);
+    threat_match.set_platform_type(
+        safe_browsing::GetUrlSubresourceFilterId().platform_type());
+    threat_match.set_threat_entry_type(safe_browsing::URL);
+
+    safe_browsing::FullHash enforce_full_hash = safe_browsing::GetFullHash(url);
+    threat_match.mutable_threat()->set_hash(enforce_full_hash);
+    threat_match.mutable_cache_duration()->set_seconds(300);
+
+    safe_browsing::ThreatEntryMetadata::MetadataEntry* threat_meta =
+        threat_match.mutable_threat_entry_metadata()->add_entries();
+    threat_meta->set_key("sf_bas");
+    threat_meta->set_value(bas_value);
+    return threat_match;
+  }
+
+ private:
+  // SubresourceFilterBrowserTest:
+  std::unique_ptr<TestSafeBrowsingDatabaseHelper> CreateTestDatabase()
+      override {
+    std::vector<safe_browsing::ListIdentifier> list_ids = {
+        safe_browsing::GetUrlSubresourceFilterId()};
+    return std::make_unique<TestSafeBrowsingDatabaseHelper>(
+        nullptr, std::move(list_ids));
+  }
+  void SetUp() override {
+    ASSERT_TRUE(safe_browsing_test_server()->InitializeAndListen());
+    SubresourceFilterBrowserTest::SetUp();
+  }
+
+  // This class needs some specific test server managing to intercept V4 hash
+  // requests, so just use another server for that rather than try to use the
+  // parent class' server.
+  std::unique_ptr<net::test_server::EmbeddedTestServer>
+      safe_browsing_test_server_;
+  DISALLOW_COPY_AND_ASSIGN(SubresourceFilterInterceptingBrowserTest);
+};
+
+IN_PROC_BROWSER_TEST_F(SubresourceFilterInterceptingBrowserTest,
+                       BetterAdsMetadata) {
+  ResetConfiguration(Configuration::MakePresetForLiveRunForBetterAds());
+  ASSERT_NO_FATAL_FAILURE(
+      SetRulesetToDisallowURLsWithPathSuffix("included_script.js"));
+
+  GURL enforce_url(embedded_test_server()->GetURL(
+      "enforce.example.com",
+      "/subresource_filter/frame_with_included_script.html"));
+  GURL warn_url(embedded_test_server()->GetURL(
+      "warn.example.com",
+      "/subresource_filter/frame_with_included_script.html"));
+
+  // Mark the prefixes as bad so that safe browsing will request full hashes
+  // from the v4 server.
+  database_helper()->LocallyMarkPrefixAsBad(
+      enforce_url, safe_browsing::GetUrlSubresourceFilterId());
+  database_helper()->LocallyMarkPrefixAsBad(
+      warn_url, safe_browsing::GetUrlSubresourceFilterId());
+
+  // Register the V4 server to handle full hash requests for the two URLs, with
+  // the given ThreatMatches, then start accepting connections on the v4 server.
+  std::map<GURL, safe_browsing::ThreatMatch> response_map{
+      {enforce_url, GetBetterAdsMatch(enforce_url, "enforce")},
+      {warn_url, GetBetterAdsMatch(warn_url, "warn")}};
+  safe_browsing::StartRedirectingV4RequestsForTesting(
+      response_map, safe_browsing_test_server());
+  safe_browsing_test_server()->StartAcceptingConnections();
+
+  content::ConsoleObserverDelegate enforce_console_observer(
+      web_contents(), kActivationConsoleMessage);
+  web_contents()->SetDelegate(&enforce_console_observer);
+  ui_test_utils::NavigateToURL(browser(), enforce_url);
+  EXPECT_FALSE(WasParsedScriptElementLoaded(web_contents()->GetMainFrame()));
+  EXPECT_EQ(enforce_console_observer.message(), kActivationConsoleMessage);
+
+  content::ConsoleObserverDelegate warn_console_observer(
+      web_contents(), kActivationWarningConsoleMessage);
+  web_contents()->SetDelegate(&warn_console_observer);
+  ui_test_utils::NavigateToURL(browser(), warn_url);
+  warn_console_observer.Wait();
+  EXPECT_TRUE(WasParsedScriptElementLoaded(web_contents()->GetMainFrame()));
+  EXPECT_EQ(warn_console_observer.message(), kActivationWarningConsoleMessage);
+}
+
+}  // namespace subresource_filter
diff --git a/chrome/browser/subresource_filter/subresource_filter_unittest.cc b/chrome/browser/subresource_filter/subresource_filter_unittest.cc
index 8b555a2..683d97da 100644
--- a/chrome/browser/subresource_filter/subresource_filter_unittest.cc
+++ b/chrome/browser/subresource_filter/subresource_filter_unittest.cc
@@ -325,3 +325,22 @@
                                                                   metadata));
   }
 }
+
+TEST_F(SubresourceFilterTest, WarningSite_NoMetadata) {
+  subresource_filter::Configuration config(
+      subresource_filter::ActivationLevel::ENABLED,
+      subresource_filter::ActivationScope::ACTIVATION_LIST,
+      subresource_filter::ActivationList::BETTER_ADS);
+  scoped_configuration().ResetConfiguration(std::move(config));
+  const GURL url("https://example.test/");
+  safe_browsing::ThreatMetadata metadata;
+  metadata.subresource_filter_match
+      [safe_browsing::SubresourceFilterType::BETTER_ADS] =
+      safe_browsing::SubresourceFilterLevel::WARN;
+  auto threat_type =
+      safe_browsing::SBThreatType::SB_THREAT_TYPE_SUBRESOURCE_FILTER;
+  fake_safe_browsing_database()->AddBlacklistedUrl(url, threat_type, metadata);
+
+  SimulateNavigateAndCommit(url, main_rfh());
+  EXPECT_EQ(nullptr, GetSettingsManager()->GetSiteMetadata(url));
+}
diff --git a/chrome/browser/sync/test/integration/sync_test.cc b/chrome/browser/sync/test/integration/sync_test.cc
index 1a5977c..49cd7fa 100644
--- a/chrome/browser/sync/test/integration/sync_test.cc
+++ b/chrome/browser/sync/test/integration/sync_test.cc
@@ -835,10 +835,8 @@
       net::HTTP_OK,
       net::URLRequestStatus::SUCCESS);
   fake_factory_->SetFakeResponse(
-      GaiaUrls::GetInstance()->client_login_to_oauth2_url(),
-      "some_response",
-      net::HTTP_OK,
-      net::URLRequestStatus::SUCCESS);
+      GaiaUrls::GetInstance()->deprecated_client_login_to_oauth2_url(),
+      "some_response", net::HTTP_OK, net::URLRequestStatus::SUCCESS);
   fake_factory_->SetFakeResponse(
       GaiaUrls::GetInstance()->oauth2_token_url(),
       "{"
diff --git a/chrome/browser/tab_contents/view_source_browsertest.cc b/chrome/browser/tab_contents/view_source_browsertest.cc
index 008a7fd1..a1274d0a 100644
--- a/chrome/browser/tab_contents/view_source_browsertest.cc
+++ b/chrome/browser/tab_contents/view_source_browsertest.cc
@@ -2,9 +2,11 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
+#include "base/macros.h"
 #include "base/strings/utf_string_conversions.h"
 #include "chrome/app/chrome_command_ids.h"
 #include "chrome/browser/chrome_notification_types.h"
+#include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/ui/browser.h"
 #include "chrome/browser/ui/browser_commands.h"
 #include "chrome/browser/ui/tabs/tab_strip_model.h"
@@ -14,17 +16,39 @@
 #include "content/public/browser/navigation_entry.h"
 #include "content/public/browser/notification_service.h"
 #include "content/public/browser/notification_types.h"
+#include "content/public/browser/render_frame_host.h"
+#include "content/public/browser/render_process_host.h"
 #include "content/public/browser/web_contents.h"
 #include "content/public/test/browser_test_utils.h"
+#include "content/public/test/test_navigation_observer.h"
+#include "content/public/test/test_utils.h"
+#include "net/dns/mock_host_resolver.h"
 #include "net/test/embedded_test_server/embedded_test_server.h"
+#include "testing/gmock/include/gmock/gmock.h"
+#include "testing/gtest/include/gtest/gtest.h"
 #include "url/gurl.h"
 
+using testing::HasSubstr;
+using testing::ContainsRegex;
+
 namespace {
 const char kTestHtml[] = "/viewsource/test.html";
 const char kTestMedia[] = "/media/pink_noise_140ms.wav";
 }
 
-typedef InProcessBrowserTest ViewSourceTest;
+class ViewSourceTest : public InProcessBrowserTest {
+ public:
+  ViewSourceTest() {}
+
+ protected:
+  void SetUpOnMainThread() override {
+    InProcessBrowserTest::SetUpOnMainThread();
+    host_resolver()->AddRule("*", "127.0.0.1");
+  }
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(ViewSourceTest);
+};
 
 // This test renders a page in view-source and then checks to see if the title
 // set in the html was set successfully (it shouldn't because we rendered the
@@ -183,3 +207,262 @@
   EXPECT_TRUE(result);
   EXPECT_FALSE(chrome::CanViewSource(browser()));
 }
+
+// Tests that view-source mode of b.com subframe won't commit in an a.com (main
+// frame) process.  This is a regresion test for https://crbug.com/770946.
+IN_PROC_BROWSER_TEST_F(ViewSourceTest, CrossSiteSubframe) {
+  // Navigate to a page with a cross-site frame.
+  content::SetupCrossSiteRedirector(embedded_test_server());
+  ASSERT_TRUE(embedded_test_server()->Start());
+  GURL main_url(
+      embedded_test_server()->GetURL("a.com", "/iframe_cross_site.html"));
+  ui_test_utils::NavigateToURL(browser(), main_url);
+
+  // Grab the original frames.
+  content::WebContents* original_contents =
+      browser()->tab_strip_model()->GetActiveWebContents();
+  content::RenderFrameHost* original_main_frame =
+      original_contents->GetMainFrame();
+  ASSERT_LE(2u, original_contents->GetAllFrames().size());
+  content::RenderFrameHost* original_child_frame =
+      original_contents->GetAllFrames()[1];
+
+  // Do a sanity check that in this particular test page the main frame and the
+  // subframe are cross-site.
+  EXPECT_FALSE(content::SiteInstance::IsSameWebSite(
+      browser()->profile(), original_main_frame->GetLastCommittedURL(),
+      original_child_frame->GetLastCommittedURL()));
+  if (content::AreAllSitesIsolatedForTesting()) {
+    EXPECT_NE(original_main_frame->GetProcess()->GetID(),
+              original_child_frame->GetProcess()->GetID());
+  }
+
+  // Open view-source mode tab for the subframe.  This tries to mimic the
+  // behavior of RenderViewContextMenu::ExecuteCommand when it handles
+  // IDC_CONTENT_CONTEXT_VIEWFRAMESOURCE.
+  content::WebContentsAddedObserver view_source_contents_observer;
+  original_child_frame->ViewSource();
+
+  // Grab the view-source frame and wait for load stop.
+  content::WebContents* view_source_contents =
+      view_source_contents_observer.GetWebContents();
+  content::RenderFrameHost* view_source_frame =
+      view_source_contents->GetMainFrame();
+  EXPECT_TRUE(WaitForLoadStop(view_source_contents));
+
+  // Verify that the last committed URL is the same in the original and the
+  // view-source frames.
+  EXPECT_EQ(original_child_frame->GetLastCommittedURL(),
+            view_source_frame->GetLastCommittedURL());
+
+  // Verify that the original main frame and the view-source subframe are in a
+  // different process (e.g. if the main frame was malicious and the subframe
+  // was an isolated origin, then the malicious frame shouldn't be able to see
+  // the contents of the isolated document).  See https://crbug.com/770946.
+  EXPECT_NE(original_main_frame->GetSiteInstance(),
+            view_source_frame->GetSiteInstance());
+
+  // Verify that the original subframe and the view-source subframe are in a
+  // different process - see https://crbug.com/699493.
+  EXPECT_NE(original_child_frame->GetSiteInstance(),
+            view_source_frame->GetSiteInstance());
+
+  // Verify the contents of the view-source tab (should match title1.html).
+  std::string source_text;
+  std::string view_source_extraction_script = R"(
+      output = "";
+      document.querySelectorAll(".line-content").forEach(function(elem) {
+          output += elem.innerText;
+      });
+      domAutomationController.send(output); )";
+  EXPECT_TRUE(content::ExecuteScriptAndExtractString(
+      view_source_contents, view_source_extraction_script, &source_text));
+  EXPECT_EQ("<html><head></head><body>This page has no title.</body></html>",
+            source_text);
+
+  // Verify the title is derived from the subframe URL.
+  GURL original_url = original_child_frame->GetLastCommittedURL();
+  std::string title = base::UTF16ToUTF8(view_source_contents->GetTitle());
+  EXPECT_THAT(title, HasSubstr(content::kViewSourceScheme));
+  EXPECT_THAT(title, HasSubstr(original_url.host()));
+  EXPECT_THAT(title, HasSubstr(original_url.port()));
+  EXPECT_THAT(title, HasSubstr(original_url.path()));
+}
+
+// Tests that "View Source" works fine for pages shown via HTTP POST.
+// This is a regression test for https://crbug.com/523.
+IN_PROC_BROWSER_TEST_F(ViewSourceTest, HttpPostInMainframe) {
+  // Navigate to a page with a form.
+  content::SetupCrossSiteRedirector(embedded_test_server());
+  ASSERT_TRUE(embedded_test_server()->Start());
+  GURL form_url(embedded_test_server()->GetURL(
+      "a.com", "/form_that_posts_to_echoall.html"));
+  ui_test_utils::NavigateToURL(browser(), form_url);
+  content::WebContents* original_contents =
+      browser()->tab_strip_model()->GetActiveWebContents();
+  content::RenderFrameHost* original_main_frame =
+      original_contents->GetMainFrame();
+
+  // Submit the form and verify that we arrived at the expected location.
+  content::TestNavigationObserver form_post_observer(original_contents, 1);
+  EXPECT_TRUE(ExecuteScript(original_main_frame,
+                            "document.getElementById('form').submit();"));
+  form_post_observer.Wait();
+  GURL target_url(embedded_test_server()->GetURL("a.com", "/echoall"));
+  EXPECT_EQ(target_url, original_main_frame->GetLastCommittedURL());
+
+  // Extract the response nonce.
+  std::string response_nonce;
+  std::string response_nonce_extraction_script = R"(
+      domAutomationController.send(
+          document.getElementById('response-nonce').innerText); )";
+  EXPECT_TRUE(ExecuteScriptAndExtractString(
+      original_main_frame, response_nonce_extraction_script, &response_nonce));
+
+  // Open view-source mode tab for the main frame.  This tries to mimic the
+  // behavior of RenderViewContextMenu::ExecuteCommand when it handles
+  // IDC_CONTENT_CONTEXT_VIEWFRAMESOURCE.
+  content::WebContentsAddedObserver view_source_contents_observer;
+  original_main_frame->ViewSource();
+  content::WebContents* view_source_contents =
+      view_source_contents_observer.GetWebContents();
+  EXPECT_TRUE(WaitForLoadStop(view_source_contents));
+
+  // Verify contents of the view-source tab.  In particular:
+  // 1) the sources should contain the POST data
+  // 2) the sources should contain the original response-nonce
+  //    (i.e. no new network request should be made - the data should be
+  //    retrieved from the cache)
+  std::string source_text;
+  std::string view_source_extraction_script = R"(
+      output = "";
+      document.querySelectorAll(".line-content").forEach(function(elem) {
+          output += elem.innerText;
+      });
+      domAutomationController.send(output); )";
+  EXPECT_TRUE(content::ExecuteScriptAndExtractString(
+      view_source_contents, view_source_extraction_script, &source_text));
+  EXPECT_THAT(source_text,
+              HasSubstr("<h1>Request Body:</h1><pre>text=value</pre>"));
+  EXPECT_THAT(source_text,
+              HasSubstr("<h1>Request Headers:</h1><pre>POST /echoall HTTP"));
+  EXPECT_THAT(source_text,
+              ContainsRegex("Request Headers:.*Referer: " + form_url.spec()));
+  EXPECT_THAT(
+      source_text,
+      ContainsRegex(
+          "Request Headers:.*Content-Type: application/x-www-form-urlencoded"));
+  EXPECT_THAT(source_text, HasSubstr("<h1>Response nonce:</h1>"
+                                     "<pre id='response-nonce'>" +
+                                     response_nonce + "</pre>"));
+  EXPECT_THAT(source_text,
+              HasSubstr("<title>EmbeddedTestServer - EchoAll</title>"));
+
+  // Verify that the original contents and the view-source contents are in a
+  // different process - see https://crbug.com/699493.
+  EXPECT_NE(original_main_frame->GetSiteInstance(),
+            view_source_contents->GetMainFrame()->GetSiteInstance());
+
+  // Verify the title of view-source is derived from the URL (not from the title
+  // of the original contents).
+  std::string title = base::UTF16ToUTF8(view_source_contents->GetTitle());
+  EXPECT_EQ("EmbeddedTestServer - EchoAll",
+            base::UTF16ToUTF8(original_contents->GetTitle()));
+  EXPECT_THAT(title, Not(HasSubstr("EmbeddedTestServer - EchoAll")));
+  GURL original_url = original_main_frame->GetLastCommittedURL();
+  EXPECT_THAT(title, HasSubstr(content::kViewSourceScheme));
+  EXPECT_THAT(title, HasSubstr(original_url.host()));
+  EXPECT_THAT(title, HasSubstr(original_url.port()));
+  EXPECT_THAT(title, HasSubstr(original_url.path()));
+}
+
+// Tests that "View Source" works fine for *subframes* shown via HTTP POST.
+// This is a regression test for https://crbug.com/774691.
+IN_PROC_BROWSER_TEST_F(ViewSourceTest, HttpPostInSubframe) {
+  // Navigate to a page with multiple frames.
+  content::SetupCrossSiteRedirector(embedded_test_server());
+  ASSERT_TRUE(embedded_test_server()->Start());
+  GURL main_url(
+      embedded_test_server()->GetURL("a.com", "/iframe_cross_site.html"));
+  ui_test_utils::NavigateToURL(browser(), main_url);
+  content::WebContents* original_contents =
+      browser()->tab_strip_model()->GetActiveWebContents();
+
+  // Navigate a child frame to a document with a form.
+  GURL form_url(embedded_test_server()->GetURL(
+      "b.com", "/form_that_posts_to_echoall.html"));
+  EXPECT_TRUE(
+      content::NavigateIframeToURL(original_contents, "frame1", form_url));
+  EXPECT_LE(2u, original_contents->GetAllFrames().size());
+  content::RenderFrameHost* original_child_frame =
+      original_contents->GetAllFrames()[1];
+
+  // Submit the form and verify that we arrived at the expected location.
+  content::TestNavigationObserver form_post_observer(original_contents, 1);
+  EXPECT_TRUE(ExecuteScript(original_child_frame,
+                            "document.getElementById('form').submit();"));
+  form_post_observer.Wait();
+  GURL target_url(embedded_test_server()->GetURL("b.com", "/echoall"));
+  EXPECT_EQ(target_url, original_child_frame->GetLastCommittedURL());
+
+  // Extract the response nonce.
+  std::string response_nonce;
+  std::string response_nonce_extraction_script = R"(
+      domAutomationController.send(
+          document.getElementById('response-nonce').innerText); )";
+  EXPECT_TRUE(ExecuteScriptAndExtractString(
+      original_child_frame, response_nonce_extraction_script, &response_nonce));
+
+  // Open view-source mode tab for the subframe.  This tries to mimic the
+  // behavior of RenderViewContextMenu::ExecuteCommand when it handles
+  // IDC_CONTENT_CONTEXT_VIEWFRAMESOURCE.
+  content::WebContentsAddedObserver view_source_contents_observer;
+  original_child_frame->ViewSource();
+  content::WebContents* view_source_contents =
+      view_source_contents_observer.GetWebContents();
+  EXPECT_TRUE(WaitForLoadStop(view_source_contents));
+
+  // Verify contents of the view-source tab.  In particular:
+  // 1) the sources should contain the POST data
+  // 2) the sources should contain the original response-nonce
+  //    (i.e. no new network request should be made - the data should be
+  //    retrieved from the cache)
+  std::string source_text;
+  std::string view_source_extraction_script = R"(
+      output = "";
+      document.querySelectorAll(".line-content").forEach(function(elem) {
+          output += elem.innerText;
+      });
+      domAutomationController.send(output); )";
+  EXPECT_TRUE(content::ExecuteScriptAndExtractString(
+      view_source_contents, view_source_extraction_script, &source_text));
+  EXPECT_THAT(source_text,
+              HasSubstr("<h1>Request Body:</h1><pre>text=value</pre>"));
+  EXPECT_THAT(source_text,
+              HasSubstr("<h1>Request Headers:</h1><pre>POST /echoall HTTP"));
+  EXPECT_THAT(source_text,
+              ContainsRegex("Request Headers:.*Referer: " + form_url.spec()));
+  EXPECT_THAT(
+      source_text,
+      ContainsRegex(
+          "Request Headers:.*Content-Type: application/x-www-form-urlencoded"));
+  EXPECT_THAT(source_text, HasSubstr("<h1>Response nonce:</h1>"
+                                     "<pre id='response-nonce'>" +
+                                     response_nonce + "</pre>"));
+  EXPECT_THAT(source_text,
+              HasSubstr("<title>EmbeddedTestServer - EchoAll</title>"));
+
+  // Verify that view-source opens in a new process - https://crbug.com/699493.
+  EXPECT_NE(original_child_frame->GetSiteInstance(),
+            view_source_contents->GetMainFrame()->GetSiteInstance());
+  EXPECT_NE(original_contents->GetSiteInstance(),
+            view_source_contents->GetMainFrame()->GetSiteInstance());
+
+  // Verify the title is derived from the URL.
+  GURL original_url = original_child_frame->GetLastCommittedURL();
+  std::string title = base::UTF16ToUTF8(view_source_contents->GetTitle());
+  EXPECT_THAT(title, HasSubstr(content::kViewSourceScheme));
+  EXPECT_THAT(title, HasSubstr(original_url.host()));
+  EXPECT_THAT(title, HasSubstr(original_url.port()));
+  EXPECT_THAT(title, HasSubstr(original_url.path()));
+}
diff --git a/chrome/browser/translate/chrome_translate_client.cc b/chrome/browser/translate/chrome_translate_client.cc
index 18fcc28..b92dbd99 100644
--- a/chrome/browser/translate/chrome_translate_client.cc
+++ b/chrome/browser/translate/chrome_translate_client.cc
@@ -122,11 +122,10 @@
           this,
           translate::TranslateRankerFactory::GetForBrowserContext(
               web_contents->GetBrowserContext()),
-          LanguageModelFactory::GetInstance()->GetForBrowserContext(
+          LanguageModelFactory::GetForBrowserContext(
               web_contents->GetBrowserContext()))),
-      language_histogram_(
-          UrlLanguageHistogramFactory::GetInstance()->GetForBrowserContext(
-              web_contents->GetBrowserContext())) {
+      language_histogram_(UrlLanguageHistogramFactory::GetForBrowserContext(
+          web_contents->GetBrowserContext())) {
   translate_driver_.AddObserver(this);
   translate_driver_.set_translate_manager(translate_manager_.get());
 }
diff --git a/chrome/browser/translate/translate_manager_browsertest.cc b/chrome/browser/translate/translate_manager_browsertest.cc
index 73d3e20..0d58296 100644
--- a/chrome/browser/translate/translate_manager_browsertest.cc
+++ b/chrome/browser/translate/translate_manager_browsertest.cc
@@ -289,6 +289,53 @@
             chrome_translate_client->GetLanguageState().original_language());
 }
 
+// Tests that the language detection / HTML attribute override works correctly.
+// For languages in the whitelist, the detected language should override the
+// HTML attribute. For all other languages, the HTML attribute should be used.
+IN_PROC_BROWSER_TEST_F(TranslateManagerBrowserTest,
+                       PageLanguageDetectionConflict) {
+  ASSERT_TRUE(embedded_test_server()->Start());
+
+  ChromeTranslateClient* chrome_translate_client = GetChromeTranslateClient();
+
+  // The InProcessBrowserTest opens a new tab, let's wait for that first.
+  // There is a possible race condition, when the language is not yet detected,
+  // so we check for that and wait if necessary.
+  if (chrome_translate_client->GetLanguageState().original_language().empty())
+    WaitUntilLanguageDetected();
+
+  EXPECT_EQ("und",
+            chrome_translate_client->GetLanguageState().original_language());
+
+  // Open a new tab with a page in French with incorrect HTML language
+  // attribute specified. The language attribute should be overridden by the
+  // language detection.
+  ResetObserver();
+  AddTabAtIndex(
+      0,
+      GURL(embedded_test_server()->GetURL("/french_page_lang_conflict.html")),
+      ui::PAGE_TRANSITION_TYPED);
+  chrome_translate_client = GetChromeTranslateClient();
+  WaitUntilLanguageDetected();
+
+  EXPECT_EQ("fr",
+            chrome_translate_client->GetLanguageState().original_language());
+
+  // Open a new tab with a page in Korean with incorrect HTML language
+  // attribute specified. The language attribute should not be overridden by the
+  // language detection.
+  ResetObserver();
+  AddTabAtIndex(
+      0,
+      GURL(embedded_test_server()->GetURL("/korean_page_lang_conflict.html")),
+      ui::PAGE_TRANSITION_TYPED);
+  chrome_translate_client = GetChromeTranslateClient();
+  WaitUntilLanguageDetected();
+
+  EXPECT_EQ("en",
+            chrome_translate_client->GetLanguageState().original_language());
+}
+
 // Test that the translation was successful.
 IN_PROC_BROWSER_TEST_F(TranslateManagerBrowserTest, PageTranslationSuccess) {
   ASSERT_TRUE(embedded_test_server()->Start());
diff --git a/chrome/browser/ui/BUILD.gn b/chrome/browser/ui/BUILD.gn
index 400cce0..02ef4b6 100644
--- a/chrome/browser/ui/BUILD.gn
+++ b/chrome/browser/ui/BUILD.gn
@@ -892,6 +892,8 @@
       "tabs/pinned_tab_service.h",
       "tabs/pinned_tab_service_factory.cc",
       "tabs/pinned_tab_service_factory.h",
+      "tabs/tab_features.cc",
+      "tabs/tab_features.h",
       "tabs/tab_menu_model.cc",
       "tabs/tab_menu_model.h",
       "tabs/tab_strip_model.cc",
@@ -2419,6 +2421,8 @@
       "network_profile_bubble.cc",
       "network_profile_bubble.h",
       "startup/default_browser_prompt_win.cc",
+      "tabs/tab_strip_model_experimental.cc",
+      "tabs/tab_strip_model_experimental.h",
       "views/certificate_viewer_win.cc",
       "views/chrome_cleaner_dialog_win.cc",
       "views/chrome_cleaner_dialog_win.h",
@@ -2909,6 +2913,8 @@
         "views/frame/contents_layout_manager.h",
         "views/frame/contents_web_view.cc",
         "views/frame/contents_web_view.h",
+        "views/frame/hosted_app_button_container.cc",
+        "views/frame/hosted_app_button_container.h",
         "views/frame/immersive_mode_controller.cc",
         "views/frame/immersive_mode_controller.h",
         "views/frame/immersive_mode_controller_factory_views.cc",
diff --git a/chrome/browser/ui/DEPS b/chrome/browser/ui/DEPS
index ccf7b24a..64b56e9 100644
--- a/chrome/browser/ui/DEPS
+++ b/chrome/browser/ui/DEPS
@@ -19,7 +19,7 @@
   ],
   "browser_commands_chromeos\.cc": [
     "+ash/accelerators/accelerator_controller_delegate_classic.h",
-    "+ash/mus/bridge/shell_port_mash.h",
+    "+ash/mus/shell_port_mus.h",
     # TODO(mash): Screenshot support. http://crbug.com/557397
     "+ash/screenshot_delegate.h",
     "+ash/shell_port_classic.h",
diff --git a/chrome/browser/ui/android/context_menu_helper.cc b/chrome/browser/ui/android/context_menu_helper.cc
index be70655..2263f86f 100644
--- a/chrome/browser/ui/android/context_menu_helper.cc
+++ b/chrome/browser/ui/android/context_menu_helper.cc
@@ -153,7 +153,8 @@
           ConvertUTF16ToJavaString(env, params.title_text),
           image_was_fetched_lo_fi,
           ConvertUTF8ToJavaString(env, sanitizedReferrer.spec()),
-          params.referrer_policy, can_save, params.x, params.y);
+          params.referrer_policy, can_save, params.x, params.y,
+          params.source_type);
 
   return jmenu_info;
 }
diff --git a/chrome/browser/ui/app_list/arc/arc_app_list_prefs.cc b/chrome/browser/ui/app_list/arc/arc_app_list_prefs.cc
index 1665e7d..c9fe76d 100644
--- a/chrome/browser/ui/app_list/arc/arc_app_list_prefs.cc
+++ b/chrome/browser/ui/app_list/arc/arc_app_list_prefs.cc
@@ -24,6 +24,7 @@
 #include "chrome/browser/ui/app_list/arc/arc_app_list_prefs_factory.h"
 #include "chrome/browser/ui/app_list/arc/arc_app_utils.h"
 #include "chrome/browser/ui/app_list/arc/arc_package_syncable_service.h"
+#include "chrome/browser/ui/app_list/arc/arc_pai_starter.h"
 #include "chrome/grit/generated_resources.h"
 #include "components/arc/arc_prefs.h"
 #include "components/arc/arc_service_manager.h"
@@ -58,7 +59,7 @@
 constexpr char kUninstalled[] = "uninstalled";
 
 constexpr base::TimeDelta kDetectDefaultAppAvailabilityTimeout =
-    base::TimeDelta::FromSeconds(15);
+    base::TimeDelta::FromMinutes(1);
 
 // Provider of write access to a dictionary storing ARC prefs.
 class ScopedArcPrefUpdate : public DictionaryPrefUpdate {
@@ -1073,8 +1074,19 @@
 
   if (!is_initialized_) {
     is_initialized_ = true;
-    MaybeSetDefaultAppLoadingTimeout();
+
     UMA_HISTOGRAM_COUNTS_1000("Arc.AppsInstalledAtStartup", ready_apps_.size());
+
+    arc::ArcPaiStarter* pai_starter =
+        arc::ArcSessionManager::Get()->pai_starter();
+
+    if (pai_starter) {
+      pai_starter->AddOnStartCallback(
+          base::BindOnce(&ArcAppListPrefs::MaybeSetDefaultAppLoadingTimeout,
+                         weak_ptr_factory_.GetWeakPtr()));
+    } else {
+      MaybeSetDefaultAppLoadingTimeout();
+    }
   }
 }
 
diff --git a/chrome/browser/ui/app_list/arc/arc_app_unittest.cc b/chrome/browser/ui/app_list/arc/arc_app_unittest.cc
index 23dc0f9..1ebe86d7 100644
--- a/chrome/browser/ui/app_list/arc/arc_app_unittest.cc
+++ b/chrome/browser/ui/app_list/arc/arc_app_unittest.cc
@@ -166,6 +166,10 @@
     ArcState::ARC_PERSISTENT_PLAY_STORE_UNMANAGED,
 };
 
+void OnPaiStartedCallback(bool* started_flag) {
+  *started_flag = true;
+}
+
 }  // namespace
 
 class ArcAppModelBuilderTest : public extensions::ExtensionServiceTestBase,
@@ -1258,12 +1262,18 @@
   ArcAppListPrefs* prefs = ArcAppListPrefs::Get(profile_.get());
   ASSERT_TRUE(prefs);
 
+  bool pai_started = false;
+
   arc::ArcPaiStarter starter1(profile_.get(), profile_->GetPrefs());
   arc::ArcPaiStarter starter2(profile_.get(), profile_->GetPrefs());
   EXPECT_FALSE(starter1.started());
   EXPECT_FALSE(starter2.started());
   EXPECT_EQ(app_instance()->start_pai_request_count(), 0);
 
+  starter1.AddOnStartCallback(
+      base::BindOnce(&OnPaiStartedCallback, &pai_started));
+  EXPECT_FALSE(pai_started);
+
   arc::ArcSessionManager* session_manager = arc::ArcSessionManager::Get();
   ASSERT_TRUE(session_manager);
 
@@ -1281,6 +1291,14 @@
   SendPlayStoreApp();
 
   EXPECT_TRUE(starter1.started());
+  EXPECT_TRUE(pai_started);
+
+  // Test that callback is called immediately in case PAI was already started.
+  pai_started = false;
+  starter1.AddOnStartCallback(
+      base::BindOnce(&OnPaiStartedCallback, &pai_started));
+  EXPECT_TRUE(pai_started);
+
   EXPECT_FALSE(starter2.started());
   EXPECT_TRUE(session_manager->pai_starter()->started());
   EXPECT_EQ(app_instance()->start_pai_request_count(), 2);
@@ -1954,12 +1972,46 @@
   app_instance()->RefreshAppList();
   app_instance()->SendRefreshAppList(empty_app_list);
 
-  ValidateHaveApps(fake_default_apps());
+  std::vector<arc::mojom::AppInfo> expected_apps(fake_default_apps());
+  ValidateHaveApps(expected_apps);
+
+  if (GetParam() == ArcState::ARC_PERSISTENT_WITHOUT_PLAY_STORE) {
+    prefs->SimulateDefaultAppAvailabilityTimeoutForTesting();
+    ValidateHaveApps(std::vector<arc::mojom::AppInfo>());
+    return;
+  }
+
+  // PAI was not started and we should not have any active timer for default
+  // apps.
+  prefs->SimulateDefaultAppAvailabilityTimeoutForTesting();
+  ValidateHaveApps(expected_apps);
+
+  arc::ArcSessionManager* arc_session_manager = arc::ArcSessionManager::Get();
+  ASSERT_TRUE(arc_session_manager);
+
+  arc::ArcPaiStarter* pai_starter = arc_session_manager->pai_starter();
+  ASSERT_TRUE(pai_starter);
+
+  EXPECT_FALSE(pai_starter->started());
+
+  // Play store app triggers PAI.
+  arc::mojom::AppInfo app;
+  app.name = "Play Store";
+  app.package_name = arc::kPlayStorePackage;
+  app.activity = arc::kPlayStoreActivity;
+  app_instance()->RefreshAppList();
+
+  std::vector<arc::mojom::AppInfo> only_play_store({app});
+  app_instance()->SendRefreshAppList(only_play_store);
+  expected_apps.push_back(app);
+
+  // Timer was set to detect not available default apps.
+  ValidateHaveApps(expected_apps);
 
   prefs->SimulateDefaultAppAvailabilityTimeoutForTesting();
 
   // No default app installation and already installed packages.
-  ValidateHaveApps(empty_app_list);
+  ValidateHaveApps(only_play_store);
 }
 
 TEST_P(ArcDefaulAppTest, DefaultAppsInstallation) {
diff --git a/chrome/browser/ui/app_list/arc/arc_pai_starter.cc b/chrome/browser/ui/app_list/arc/arc_pai_starter.cc
index 289aa521..7e2d617e 100644
--- a/chrome/browser/ui/app_list/arc/arc_pai_starter.cc
+++ b/chrome/browser/ui/app_list/arc/arc_pai_starter.cc
@@ -52,6 +52,15 @@
   MaybeStartPai();
 }
 
+void ArcPaiStarter::AddOnStartCallback(base::OnceClosure callback) {
+  if (started_) {
+    std::move(callback).Run();
+    return;
+  }
+
+  onstart_callbacks_.push_back(std::move(callback));
+}
+
 void ArcPaiStarter::MaybeStartPai() {
   if (started_ || locked_)
     return;
@@ -71,6 +80,15 @@
   pref_service_->SetBoolean(prefs::kArcPaiStarted, true);
 
   prefs->RemoveObserver(this);
+
+  for (auto& callback : onstart_callbacks_)
+    std::move(callback).Run();
+  onstart_callbacks_.clear();
+}
+
+void ArcPaiStarter::OnAppRegistered(const std::string& app_id,
+                                    const ArcAppListPrefs::AppInfo& app_info) {
+  OnAppReadyChanged(app_id, app_info.ready);
 }
 
 void ArcPaiStarter::OnAppReadyChanged(const std::string& app_id, bool ready) {
diff --git a/chrome/browser/ui/app_list/arc/arc_pai_starter.h b/chrome/browser/ui/app_list/arc/arc_pai_starter.h
index db4973d..b1689867 100644
--- a/chrome/browser/ui/app_list/arc/arc_pai_starter.h
+++ b/chrome/browser/ui/app_list/arc/arc_pai_starter.h
@@ -5,6 +5,9 @@
 #ifndef CHROME_BROWSER_UI_APP_LIST_ARC_ARC_PAI_STARTER_H_
 #define CHROME_BROWSER_UI_APP_LIST_ARC_ARC_PAI_STARTER_H_
 
+#include <vector>
+
+#include "base/callback.h"
 #include "base/macros.h"
 #include "chrome/browser/ui/app_list/arc/arc_app_list_prefs.h"
 
@@ -36,6 +39,10 @@
   // is ready at this moment then PAI is started immediately.
   void ReleaseLock();
 
+  // Registers callback that is called once PAI has been started. If PAI is
+  // started already then callback is called immediately.
+  void AddOnStartCallback(base::OnceClosure callback);
+
   // Returns true if lock was acquired.
   bool locked() const { return locked_; }
 
@@ -45,10 +52,13 @@
   void MaybeStartPai();
 
   // ArcAppListPrefs::Observer:
+  void OnAppRegistered(const std::string& app_id,
+                       const ArcAppListPrefs::AppInfo& app_info) override;
   void OnAppReadyChanged(const std::string& app_id, bool ready) override;
 
   content::BrowserContext* const context_;
   PrefService* const pref_service_;
+  std::vector<base::OnceClosure> onstart_callbacks_;
   bool locked_ = false;
   bool started_ = false;
 
diff --git a/chrome/browser/ui/ash/ash_init.cc b/chrome/browser/ui/ash/ash_init.cc
index 2b99983..cade4a8 100644
--- a/chrome/browser/ui/ash/ash_init.cc
+++ b/chrome/browser/ui/ash/ash_init.cc
@@ -9,7 +9,7 @@
 #include "ash/accessibility_types.h"
 #include "ash/high_contrast/high_contrast_controller.h"
 #include "ash/magnifier/magnification_controller.h"
-#include "ash/mus/bridge/shell_port_mash.h"
+#include "ash/mus/shell_port_mus.h"  // mash-ok
 #include "ash/mus/window_manager.h"
 #include "ash/public/cpp/config.h"
 #include "ash/shell.h"
@@ -104,7 +104,10 @@
         ash::ShellPortClassic::Get()->accelerator_controller_delegate();
   } else if (chromeos::GetAshConfig() == ash::Config::MUS) {
     accelerator_controller_delegate =
-        ash::mus::ShellPortMash::Get()->accelerator_controller_delegate_mus();
+        ash::mus::ShellPortMus::Get()->accelerator_controller_delegate();
+  } else {
+    // TODO(mash): Screenshot accelerator support. http://crbug.com/557397
+    NOTIMPLEMENTED();
   }
   if (accelerator_controller_delegate) {
     std::unique_ptr<ChromeScreenshotGrabber> screenshot_delegate =
diff --git a/chrome/browser/ui/ash/multi_user/multi_user_window_manager_chromeos.cc b/chrome/browser/ui/ash/multi_user/multi_user_window_manager_chromeos.cc
index a9a8c3f2..fb5e95a 100644
--- a/chrome/browser/ui/ash/multi_user/multi_user_window_manager_chromeos.cc
+++ b/chrome/browser/ui/ash/multi_user/multi_user_window_manager_chromeos.cc
@@ -514,8 +514,7 @@
       (owner == account_id && IsWindowOnDesktopOfUser(window, account_id)))
     return false;
 
-  bool minimized = window->GetProperty(aura::client::kShowStateKey) ==
-                   ui::SHOW_STATE_MINIMIZED;
+  bool minimized = wm::WindowStateIs(window, ui::SHOW_STATE_MINIMIZED);
   // Check that we are not trying to transfer ownership of a minimized window.
   if (account_id != owner && minimized)
     return false;
diff --git a/chrome/browser/ui/ash/multi_user/user_switch_animator_chromeos.cc b/chrome/browser/ui/ash/multi_user/user_switch_animator_chromeos.cc
index 0b296e6..0348314 100644
--- a/chrome/browser/ui/ash/multi_user/user_switch_animator_chromeos.cc
+++ b/chrome/browser/ui/ash/multi_user/user_switch_animator_chromeos.cc
@@ -94,18 +94,6 @@
   window_list->push_back(*it);
 }
 
-void Unminimize(aura::Window* window) {
-  window->SetProperty(
-      aura::client::kShowStateKey,
-      window->GetProperty(aura::client::kPreMinimizedShowStateKey));
-  window->ClearProperty(aura::client::kPreMinimizedShowStateKey);
-}
-
-bool IsMinimized(aura::Window* window) {
-  return window->GetProperty(aura::client::kShowStateKey) ==
-         ui::SHOW_STATE_MINIMIZED;
-}
-
 }  // namespace
 
 UserSwitchAnimatorChromeOS::UserSwitchAnimatorChromeOS(
@@ -143,10 +131,8 @@
   // Full screen covers the screen naturally. Since a normal window can have the
   // same size as the work area, we only compare the bounds against the work
   // area.
-  if (window->GetProperty(aura::client::kShowStateKey) ==
-      ui::SHOW_STATE_FULLSCREEN) {
+  if (wm::WindowStateIs(window, ui::SHOW_STATE_FULLSCREEN))
     return true;
-  }
   gfx::Rect bounds = window->GetBoundsInScreen();
   gfx::Rect work_area =
       display::Screen::GetScreen()->GetDisplayNearestWindow(window).work_area();
@@ -268,9 +254,9 @@
               owner_->window_to_entry().find(window);
           DCHECK(itr != owner_->window_to_entry().end());
           if (show_for_account_id != itr->second->owner() &&
-              IsMinimized(window)) {
+              wm::WindowStateIs(window, ui::SHOW_STATE_MINIMIZED)) {
             owner_->ShowWindowForUserIntern(window, itr->second->owner());
-            Unminimize(window);
+            wm::Unminimize(window);
             continue;
           }
 
@@ -324,7 +310,7 @@
       if (!mru_list.empty()) {
         aura::Window* window = mru_list[0];
         if (owner_->IsWindowOnDesktopOfUser(window, new_account_id_) &&
-            !IsMinimized(window)) {
+            !wm::WindowStateIs(window, ui::SHOW_STATE_MINIMIZED)) {
           // Several unit tests come here without an activation client.
           wm::ActivationClient* client =
               wm::GetActivationClient(window->GetRootWindow());
diff --git a/chrome/browser/ui/blocked_content/popup_blocker_browsertest.cc b/chrome/browser/ui/blocked_content/popup_blocker_browsertest.cc
index fd445ec..705b1fb 100644
--- a/chrome/browser/ui/blocked_content/popup_blocker_browsertest.cc
+++ b/chrome/browser/ui/blocked_content/popup_blocker_browsertest.cc
@@ -831,50 +831,6 @@
   ASSERT_EQ(popup_browser, chrome::FindLastActive());
 }
 
-IN_PROC_BROWSER_TEST_F(PopupBlockerBrowserTest, ModalPopUnderViaHTTPAuth) {
-  WebContents* tab = browser()->tab_strip_model()->GetActiveWebContents();
-  GURL url(
-      embedded_test_server()->GetURL("/popup_blocker/popup-window-open.html"));
-  HostContentSettingsMapFactory::GetForProfile(browser()->profile())
-      ->SetContentSettingDefaultScope(url, GURL(), CONTENT_SETTINGS_TYPE_POPUPS,
-                                      std::string(), CONTENT_SETTING_ALLOW);
-
-  NavigateAndCheckPopupShown(url, ExpectPopup);
-
-  Browser* popup_browser = chrome::FindLastActive();
-  ASSERT_NE(popup_browser, browser());
-
-  // Showing an http auth dialog will raise the tab over the popup.
-  LoginPromptBrowserTestObserver observer;
-  content::NavigationController* controller = &tab->GetController();
-  observer.Register(content::Source<content::NavigationController>(controller));
-  {
-#if !defined(OS_MACOSX)
-    // Mac doesn't activate the browser during modal dialogs, see
-    // https://crbug.com/687732 for details.
-    ui_test_utils::BrowserActivationWaiter raised_waiter(browser());
-#endif
-    WindowedAuthNeededObserver auth_needed_observer(controller);
-    tab->GetMainFrame()->ExecuteJavaScriptForTests(
-        base::UTF8ToUTF16("var f = document.createElement('iframe'); f.src = "
-                          "'/auth-basic'; document.body.appendChild(f);"));
-    auth_needed_observer.Wait();
-    ASSERT_FALSE(observer.handlers().empty());
-#if !defined(OS_MACOSX)
-    if (chrome::FindLastActive() != browser())
-      raised_waiter.WaitForActivation();
-#endif
-  }
-
-  {
-    ui_test_utils::BrowserActivationWaiter waiter(popup_browser);
-    LoginHandler* handler = *observer.handlers().begin();
-    handler->CancelAuth();
-    waiter.WaitForActivation();
-    ASSERT_EQ(popup_browser, chrome::FindLastActive());
-  }
-}
-
 // Tests that Ctrl+Enter/Cmd+Enter keys on a link open the backgournd tab.
 IN_PROC_BROWSER_TEST_F(PopupBlockerBrowserTest, CtrlEnterKey) {
   WebContents* tab = browser()->tab_strip_model()->GetActiveWebContents();
diff --git a/chrome/browser/ui/blocked_content/safe_browsing_triggered_popup_blocker_browsertest.cc b/chrome/browser/ui/blocked_content/safe_browsing_triggered_popup_blocker_browsertest.cc
index df57822..f9c9c53d 100644
--- a/chrome/browser/ui/blocked_content/safe_browsing_triggered_popup_blocker_browsertest.cc
+++ b/chrome/browser/ui/blocked_content/safe_browsing_triggered_popup_blocker_browsertest.cc
@@ -14,7 +14,6 @@
 #include "base/lazy_instance.h"
 #include "base/logging.h"
 #include "base/macros.h"
-#include "base/memory/ptr_util.h"
 #include "base/path_service.h"
 #include "base/test/histogram_tester.h"
 #include "chrome/browser/content_settings/host_content_settings_map_factory.h"
@@ -28,7 +27,9 @@
 #include "chrome/test/base/ui_test_utils.h"
 #include "components/content_settings/core/browser/host_content_settings_map.h"
 #include "components/content_settings/core/common/content_settings_types.h"
-#include "components/url_pattern_index/proto/rules.pb.h"
+#include "components/safe_browsing/db/safebrowsing.pb.h"
+#include "components/safe_browsing/db/v4_embedded_test_server_util.h"
+#include "components/safe_browsing/db/v4_test_util.h"
 #include "content/public/browser/web_contents.h"
 #include "content/public/test/browser_test.h"
 #include "content/public/test/browser_test_utils.h"
@@ -43,14 +44,17 @@
 
 namespace {
 
-base::LazyInstance<std::vector<std::string>>::Leaky error_messages_ =
+base::LazyInstance<std::vector<std::string>>::Leaky g_error_messages_ =
     LAZY_INSTANCE_INITIALIZER;
 
 class ScopedLoggingObserver {
  public:
-  ScopedLoggingObserver() {
+  ScopedLoggingObserver()
+      : old_log_handler_(logging::GetLogMessageHandler()),
+        error_index_(g_error_messages_.Get().size()) {
     logging::SetLogMessageHandler(&ScopedLoggingObserver::LogHandler);
   }
+  ~ScopedLoggingObserver() { logging::SetLogMessageHandler(old_log_handler_); }
 
   void RoundTripAndVerifyLogMessages(
       content::WebContents* web_contents,
@@ -62,7 +66,8 @@
     for (size_t i = 0; i < messages_expected.size(); i++)
       verify_messages_expected[i] = false;
 
-    for (const auto& message : error_messages_.Get()) {
+    for (size_t i = error_index_; i < g_error_messages_.Get().size(); ++i) {
+      const std::string& message = g_error_messages_.Get()[i];
       for (size_t i = 0; i < messages_expected.size(); i++) {
         verify_messages_expected[i] |=
             (message.find(messages_expected[i]) != std::string::npos);
@@ -85,9 +90,16 @@
                          size_t message_start,
                          const std::string& str) {
     if (file && std::string("CONSOLE") == file)
-      error_messages_.Get().push_back(str);
+      g_error_messages_.Get().push_back(str);
     return false;
   }
+
+  logging::LogMessageHandlerFunction old_log_handler_;
+
+  // The index into |g_error_messages| when this object was instantiated. Used
+  // for iterating through messages received since this object was created.
+  size_t error_index_;
+  DISALLOW_COPY_AND_ASSIGN(ScopedLoggingObserver);
 };
 
 }  // namespace
@@ -100,11 +112,7 @@
   ~SafeBrowsingTriggeredPopupBlockerBrowserTest() override {}
 
   void SetUp() override {
-    std::vector<safe_browsing::ListIdentifier> list_ids = {
-        safe_browsing::GetUrlSubresourceFilterId()};
-    database_helper_ =
-        base::MakeUnique<TestSafeBrowsingDatabaseHelper>(std::move(list_ids));
-
+    database_helper_ = CreateTestDatabase();
     InProcessBrowserTest::SetUp();
   }
   void SetUpCommandLine(base::CommandLine* command_line) override {
@@ -133,18 +141,26 @@
     return browser()->tab_strip_model()->GetActiveWebContents();
   }
 
+  virtual std::unique_ptr<TestSafeBrowsingDatabaseHelper> CreateTestDatabase() {
+    std::vector<safe_browsing::ListIdentifier> list_ids = {
+        safe_browsing::GetUrlSubresourceFilterId()};
+    return std::make_unique<TestSafeBrowsingDatabaseHelper>(
+        std::make_unique<safe_browsing::TestV4GetHashProtocolManagerFactory>(),
+        std::move(list_ids));
+  }
+
   void ConfigureAsAbusive(const GURL& url) {
     safe_browsing::ThreatMetadata metadata;
     metadata.subresource_filter_match = {
         {SubresourceFilterType::ABUSIVE, SubresourceFilterLevel::ENFORCE}};
-    database_helper_->MarkUrlAsMatchingListIdWithMetadata(
+    database_helper_->AddFullHashToDbAndFullHashCache(
         url, safe_browsing::GetUrlSubresourceFilterId(), metadata);
   }
   void ConfigureAsAbusiveWarn(const GURL& url) {
     safe_browsing::ThreatMetadata metadata;
     metadata.subresource_filter_match = {
         {SubresourceFilterType::ABUSIVE, SubresourceFilterLevel::WARN}};
-    database_helper()->MarkUrlAsMatchingListIdWithMetadata(
+    database_helper()->AddFullHashToDbAndFullHashCache(
         url, safe_browsing::GetUrlSubresourceFilterId(), metadata);
   }
 
@@ -159,10 +175,65 @@
   DISALLOW_COPY_AND_ASSIGN(SafeBrowsingTriggeredPopupBlockerBrowserTest);
 };
 
+// The boolean parameter is whether to ignore sublists.
 class SafeBrowsingTriggeredPopupBlockerParamBrowserTest
     : public SafeBrowsingTriggeredPopupBlockerBrowserTest,
       public testing::WithParamInterface<bool> {};
 
+// This test harness does not mock the safe browsing v4 hash protocol manager.
+// Instead, it mocks actual HTTP responses from the v4 server by redirecting
+// requests to a custom test server with a special full hash request handler.
+class SafeBrowsingTriggeredInterceptingBrowserTest
+    : public SafeBrowsingTriggeredPopupBlockerBrowserTest {
+ public:
+  SafeBrowsingTriggeredInterceptingBrowserTest()
+      : safe_browsing_server_(
+            std::make_unique<net::test_server::EmbeddedTestServer>()) {}
+  ~SafeBrowsingTriggeredInterceptingBrowserTest() override {}
+
+  // SafeBrowsingTriggeredPopupBlockerBrowserTest:
+  void SetUp() override {
+    ASSERT_TRUE(safe_browsing_server_->InitializeAndListen());
+    SafeBrowsingTriggeredPopupBlockerBrowserTest::SetUp();
+  }
+  std::unique_ptr<TestSafeBrowsingDatabaseHelper> CreateTestDatabase()
+      override {
+    std::vector<safe_browsing::ListIdentifier> list_ids = {
+        safe_browsing::GetUrlSubresourceFilterId()};
+    // Send a nullptr TestV4GetHashProtocolManager so full hash requests aren't
+    // mocked.
+    return std::make_unique<TestSafeBrowsingDatabaseHelper>(
+        nullptr, std::move(list_ids));
+  }
+
+  net::test_server::EmbeddedTestServer* safe_browsing_server() {
+    return safe_browsing_server_.get();
+  }
+
+  safe_browsing::ThreatMatch GetAbusiveMatch(const GURL& url,
+                                             const std::string& abusive_value) {
+    safe_browsing::ThreatMatch threat_match;
+    threat_match.set_threat_type(safe_browsing::SUBRESOURCE_FILTER);
+    threat_match.set_platform_type(
+        safe_browsing::GetUrlSubresourceFilterId().platform_type());
+    threat_match.set_threat_entry_type(safe_browsing::URL);
+
+    safe_browsing::FullHash enforce_full_hash = safe_browsing::GetFullHash(url);
+    threat_match.mutable_threat()->set_hash(enforce_full_hash);
+    threat_match.mutable_cache_duration()->set_seconds(300);
+
+    safe_browsing::ThreatEntryMetadata::MetadataEntry* threat_meta =
+        threat_match.mutable_threat_entry_metadata()->add_entries();
+    threat_meta->set_key("sf_absv");
+    threat_meta->set_value(abusive_value);
+    return threat_match;
+  }
+
+ private:
+  std::unique_ptr<net::test_server::EmbeddedTestServer> safe_browsing_server_;
+  DISALLOW_COPY_AND_ASSIGN(SafeBrowsingTriggeredInterceptingBrowserTest);
+};
+
 IN_PROC_BROWSER_TEST_F(SafeBrowsingTriggeredPopupBlockerBrowserTest,
                        NoFeature_AllowCreatingNewWindows) {
   // Disable Abusive enforcement.
@@ -226,7 +297,7 @@
 
   // Mark as matching social engineering, not subresource filter.
   safe_browsing::ThreatMetadata metadata;
-  database_helper()->MarkUrlAsMatchingListIdWithMetadata(
+  database_helper()->AddFullHashToDbAndFullHashCache(
       a_url, safe_browsing::GetUrlSocEngId(), metadata);
 
   // Navigate to a_url, should not trigger the popup blocker.
@@ -435,7 +506,7 @@
 
   // Do not set the ABUSIVE bit.
   safe_browsing::ThreatMetadata metadata;
-  database_helper()->MarkUrlAsMatchingListIdWithMetadata(
+  database_helper()->AddFullHashToDbAndFullHashCache(
       url, safe_browsing::GetUrlSubresourceFilterId(), metadata);
 
   // Navigate to url, should not trigger the popup blocker.
@@ -507,3 +578,66 @@
   log_observer.RoundTripAndVerifyLogMessages(
       web_contents(), {kAbusiveWarnMessage}, {kAbusiveEnforceMessage});
 }
+
+IN_PROC_BROWSER_TEST_F(SafeBrowsingTriggeredInterceptingBrowserTest,
+                       AbusiveMetadata) {
+  const char kWindowOpenPath[] = "/subresource_filter/window_open.html";
+  const GURL no_match_url(
+      embedded_test_server()->GetURL("no_match.com", kWindowOpenPath));
+  const GURL enforce_url(
+      embedded_test_server()->GetURL("enforce.com", kWindowOpenPath));
+  const GURL warn_url(
+      embedded_test_server()->GetURL("warn.com", kWindowOpenPath));
+
+  // Mark the prefixes as bad so that safe browsing will request full hashes
+  // from the v4 server. Even mark the no_match URL as bad just to test that the
+  // custom server handler is working properly.
+  database_helper()->LocallyMarkPrefixAsBad(
+      no_match_url, safe_browsing::GetUrlSubresourceFilterId());
+  database_helper()->LocallyMarkPrefixAsBad(
+      warn_url, safe_browsing::GetUrlSubresourceFilterId());
+  database_helper()->LocallyMarkPrefixAsBad(
+      enforce_url, safe_browsing::GetUrlSubresourceFilterId());
+
+  // Register the V4 server to handle full hash requests for the two URLs, with
+  // the given ThreatMatches, then start accepting connections on the v4 server.
+  // Then, start the server.
+  std::map<GURL, safe_browsing::ThreatMatch> response_map{
+      {enforce_url, GetAbusiveMatch(enforce_url, "enforce")},
+      {warn_url, GetAbusiveMatch(warn_url, "warn")}};
+  safe_browsing::StartRedirectingV4RequestsForTesting(response_map,
+                                                      safe_browsing_server());
+  safe_browsing_server()->StartAcceptingConnections();
+
+  // URL with no match should not trigger the blocker.
+  {
+    ScopedLoggingObserver log_observer;
+    ui_test_utils::NavigateToURL(browser(), no_match_url);
+    bool opened_window = false;
+    EXPECT_TRUE(content::ExecuteScriptAndExtractBool(
+        web_contents(), "openWindow()", &opened_window));
+    EXPECT_TRUE(opened_window);
+    log_observer.RoundTripAndVerifyLogMessages(
+        web_contents(), {}, {kAbusiveEnforceMessage, kAbusiveWarnMessage});
+  }
+  {
+    ScopedLoggingObserver log_observer;
+    ui_test_utils::NavigateToURL(browser(), enforce_url);
+    bool opened_window = false;
+    EXPECT_TRUE(content::ExecuteScriptAndExtractBool(
+        web_contents(), "openWindow()", &opened_window));
+    EXPECT_FALSE(opened_window);
+    log_observer.RoundTripAndVerifyLogMessages(
+        web_contents(), {kAbusiveEnforceMessage}, {kAbusiveWarnMessage});
+  }
+  {
+    ScopedLoggingObserver log_observer;
+    ui_test_utils::NavigateToURL(browser(), warn_url);
+    bool opened_window = false;
+    EXPECT_TRUE(content::ExecuteScriptAndExtractBool(
+        web_contents(), "openWindow()", &opened_window));
+    EXPECT_TRUE(opened_window);
+    log_observer.RoundTripAndVerifyLogMessages(
+        web_contents(), {kAbusiveWarnMessage}, {kAbusiveEnforceMessage});
+  }
+}
diff --git a/chrome/browser/ui/browser.cc b/chrome/browser/ui/browser.cc
index 538f7b7..036349ff 100644
--- a/chrome/browser/ui/browser.cc
+++ b/chrome/browser/ui/browser.cc
@@ -134,6 +134,7 @@
 #include "chrome/browser/ui/tab_dialogs.h"
 #include "chrome/browser/ui/tab_helpers.h"
 #include "chrome/browser/ui/tab_modal_confirm_dialog.h"
+#include "chrome/browser/ui/tabs/tab_features.h"
 #include "chrome/browser/ui/tabs/tab_menu_model.h"
 #include "chrome/browser/ui/tabs/tab_strip_model_impl.h"
 #include "chrome/browser/ui/tabs/tab_utils.h"
@@ -364,8 +365,8 @@
       profile_(params.profile),
       window_(NULL),
       tab_strip_model_delegate_(new chrome::BrowserTabStripModelDelegate(this)),
-      tab_strip_model_(new TabStripModelImpl(tab_strip_model_delegate_.get(),
-                                             params.profile)),
+      tab_strip_model_(
+          CreateTabStripModel(tab_strip_model_delegate_.get(), params.profile)),
       app_name_(params.app_name),
       is_trusted_source_(params.trusted_source),
       cancel_download_confirmation_state_(NOT_PROMPTED),
@@ -1612,18 +1613,6 @@
   return search::NavEntryIsInstantNTP(source, entry);
 }
 
-void Browser::ViewSourceForTab(WebContents* source, const GURL& page_url) {
-  DCHECK(source);
-  chrome::ViewSource(this, source);
-}
-
-void Browser::ViewSourceForFrame(WebContents* source,
-                                 const GURL& frame_url,
-                                 const content::PageState& frame_page_state) {
-  DCHECK(source);
-  chrome::ViewSource(this, source, frame_url, frame_page_state);
-}
-
 void Browser::ShowRepostFormWarningDialog(WebContents* source) {
   TabModalConfirmDialog::Create(new RepostFormWarningController(source),
                                 source);
diff --git a/chrome/browser/ui/browser.h b/chrome/browser/ui/browser.h
index cff50556..a5ba42e 100644
--- a/chrome/browser/ui/browser.h
+++ b/chrome/browser/ui/browser.h
@@ -81,7 +81,6 @@
 }
 
 namespace content {
-class PageState;
 class SessionStorageNamespace;
 }
 
@@ -597,11 +596,6 @@
                          bool proceed,
                          bool* proceed_to_fire_unload) override;
   bool ShouldFocusLocationBarByDefault(content::WebContents* source) override;
-  void ViewSourceForTab(content::WebContents* source,
-                        const GURL& page_url) override;
-  void ViewSourceForFrame(content::WebContents* source,
-                          const GURL& frame_url,
-                          const content::PageState& frame_page_state) override;
   void ShowRepostFormWarningDialog(content::WebContents* source) override;
   bool ShouldCreateWebContents(
       content::WebContents* web_contents,
diff --git a/chrome/browser/ui/browser_command_controller.cc b/chrome/browser/ui/browser_command_controller.cc
index 268ebf5..3372c99 100644
--- a/chrome/browser/ui/browser_command_controller.cc
+++ b/chrome/browser/ui/browser_command_controller.cc
@@ -48,6 +48,7 @@
 #include "content/public/browser/native_web_keyboard_event.h"
 #include "content/public/browser/navigation_controller.h"
 #include "content/public/browser/navigation_entry.h"
+#include "content/public/browser/render_frame_host.h"
 #include "content/public/browser/web_contents.h"
 #include "content/public/browser/web_contents_observer.h"
 #include "content/public/common/service_manager_connection.h"
@@ -437,7 +438,10 @@
       BookmarkAllTabs(browser_);
       break;
     case IDC_VIEW_SOURCE:
-      ViewSelectedSource(browser_);
+      browser_->tab_strip_model()
+          ->GetActiveWebContents()
+          ->GetMainFrame()
+          ->ViewSource();
       break;
     case IDC_EMAIL_PAGE_LOCATION:
       EmailPageLocation(browser_);
diff --git a/chrome/browser/ui/browser_commands.cc b/chrome/browser/ui/browser_commands.cc
index 82e27eb4..5f2b9dc 100644
--- a/chrome/browser/ui/browser_commands.cc
+++ b/chrome/browser/ui/browser_commands.cc
@@ -4,6 +4,8 @@
 
 #include "chrome/browser/ui/browser_commands.h"
 
+#include <vector>
+
 #include "base/command_line.h"
 #include "base/metrics/histogram_macros.h"
 #include "base/metrics/user_metrics.h"
@@ -1188,86 +1190,6 @@
       content::DevToolsAgentHost::IsDebuggerAttached(contents) : false;
 }
 
-void ViewSource(Browser* browser, WebContents* contents) {
-  DCHECK(contents);
-
-  // Use the last committed entry, since the pending entry hasn't loaded yet and
-  // won't be copied into the cloned tab.
-  NavigationEntry* entry = contents->GetController().GetLastCommittedEntry();
-  if (!entry)
-    return;
-
-  ViewSource(browser, contents, entry->GetURL(), entry->GetPageState());
-}
-
-void ViewSource(Browser* browser,
-                WebContents* contents,
-                const GURL& url,
-                const content::PageState& page_state) {
-  base::RecordAction(UserMetricsAction("ViewSource"));
-  DCHECK(contents);
-
-  WebContents* view_source_contents = contents->Clone();
-  DCHECK(view_source_contents->GetController().CanPruneAllButLastCommitted());
-  view_source_contents->GetController().PruneAllButLastCommitted();
-  NavigationEntry* last_committed_entry =
-      view_source_contents->GetController().GetLastCommittedEntry();
-  if (!last_committed_entry)
-    return;
-
-  GURL view_source_url =
-      GURL(content::kViewSourceScheme + std::string(":") + url.spec());
-  last_committed_entry->SetVirtualURL(view_source_url);
-  last_committed_entry->SetURL(url);
-
-  // Do not restore scroller position.
-  last_committed_entry->SetPageState(page_state.RemoveScrollOffset());
-
-  // Do not restore title, derive it from the url.
-  view_source_contents->UpdateTitleForEntry(last_committed_entry,
-                                            base::string16());
-
-  // Now show view-source entry.
-  if (browser->CanSupportWindowFeature(Browser::FEATURE_TABSTRIP)) {
-    // If this is a tabbed browser, just create a duplicate tab inside the same
-    // window next to the tab being duplicated.
-    int index = browser->tab_strip_model()->GetIndexOfWebContents(contents);
-    int add_types = TabStripModel::ADD_ACTIVE |
-        TabStripModel::ADD_INHERIT_GROUP;
-    browser->tab_strip_model()->InsertWebContentsAt(
-        index + 1,
-        view_source_contents,
-        add_types);
-  } else {
-    Browser* b = new Browser(
-        Browser::CreateParams(Browser::TYPE_TABBED, browser->profile(), true));
-
-    // Preserve the size of the original window. The new window has already
-    // been given an offset by the OS, so we shouldn't copy the old bounds.
-    BrowserWindow* new_window = b->window();
-    new_window->SetBounds(gfx::Rect(new_window->GetRestoredBounds().origin(),
-                          browser->window()->GetRestoredBounds().size()));
-
-    // We need to show the browser now. Otherwise ContainerWin assumes the
-    // WebContents is invisible and won't size it.
-    b->window()->Show();
-
-    // The page transition below is only for the purpose of inserting the tab.
-    b->tab_strip_model()->AddWebContents(view_source_contents, -1,
-                                         ui::PAGE_TRANSITION_LINK,
-                                         TabStripModel::ADD_ACTIVE);
-  }
-
-  SessionService* session_service =
-      SessionServiceFactory::GetForProfileIfExisting(browser->profile());
-  if (session_service)
-    session_service->TabRestored(view_source_contents, false);
-}
-
-void ViewSelectedSource(Browser* browser) {
-  ViewSource(browser, browser->tab_strip_model()->GetActiveWebContents());
-}
-
 bool CanViewSource(const Browser* browser) {
   return !browser->is_devtools() &&
       browser->tab_strip_model()->GetActiveWebContents()->GetController().
diff --git a/chrome/browser/ui/browser_commands.h b/chrome/browser/ui/browser_commands.h
index 104776e..d0f5ed8 100644
--- a/chrome/browser/ui/browser_commands.h
+++ b/chrome/browser/ui/browser_commands.h
@@ -27,7 +27,6 @@
 class Profile;
 
 namespace content {
-class PageState;
 class WebContents;
 }
 
@@ -158,16 +157,6 @@
 void SetIntentPickerViewVisibility(Browser* browser, bool visible);
 #endif  // defined(OS_CHROMEOS)
 
-// Opens a view-source tab for a given web contents.
-void ViewSource(Browser* browser, content::WebContents* tab);
-
-// Opens a view-source tab for any frame within a given web contents.
-void ViewSource(Browser* browser,
-                content::WebContents* tab,
-                const GURL& url,
-                const content::PageState& page_state);
-
-void ViewSelectedSource(Browser* browser);
 bool CanViewSource(const Browser* browser);
 
 void CreateBookmarkAppFromCurrentWebContents(Browser* browser);
diff --git a/chrome/browser/ui/browser_commands_chromeos.cc b/chrome/browser/ui/browser_commands_chromeos.cc
index 7c20de4..c93ddaab 100644
--- a/chrome/browser/ui/browser_commands_chromeos.cc
+++ b/chrome/browser/ui/browser_commands_chromeos.cc
@@ -5,7 +5,7 @@
 #include "chrome/browser/ui/browser_commands_chromeos.h"
 
 #include "ash/accelerators/accelerator_controller_delegate_classic.h"  // mash-ok
-#include "ash/mus/bridge/shell_port_mash.h"  // mash-ok
+#include "ash/mus/shell_port_mus.h"  // mash-ok
 #include "ash/public/cpp/config.h"
 #include "ash/screenshot_delegate.h"
 #include "ash/shell_port_classic.h"  // mash-ok
@@ -24,7 +24,7 @@
         ash::ShellPortClassic::Get()->accelerator_controller_delegate();
   } else if (chromeos::GetAshConfig() == ash::Config::MUS) {
     accelerator_controller_delegate =
-        ash::mus::ShellPortMash::Get()->accelerator_controller_delegate_mus();
+        ash::mus::ShellPortMus::Get()->accelerator_controller_delegate();
   } else {
     // TODO(mash): Screenshot support. http://crbug.com/557397
     NOTIMPLEMENTED();
diff --git a/chrome/browser/ui/chrome_pages.cc b/chrome/browser/ui/chrome_pages.cc
index e9924ff..8b038cf 100644
--- a/chrome/browser/ui/chrome_pages.cc
+++ b/chrome/browser/ui/chrome_pages.cc
@@ -395,7 +395,7 @@
   } else {
     NavigateToSingletonTab(
         browser,
-        signin::GetPromoURL(
+        signin::GetPromoURLForTab(
             access_point, signin_metrics::Reason::REASON_SIGNIN_PRIMARY_ACCOUNT,
             false));
     DCHECK_GT(browser->tab_strip_model()->count(), 0);
diff --git a/chrome/browser/ui/cocoa/chrome_style.cc b/chrome/browser/ui/cocoa/chrome_style.cc
index e134938..19d65b3 100644
--- a/chrome/browser/ui/cocoa/chrome_style.cc
+++ b/chrome/browser/ui/cocoa/chrome_style.cc
@@ -18,6 +18,11 @@
   return image->width();
 }
 
+SkColor GetBackgroundColor() {
+  return ThemeProperties::GetDefaultColor(
+      ThemeProperties::COLOR_CONTROL_BACKGROUND, false);
+}
+
 SkColor GetLinkColor() {
   return SkColorSetRGB(0x11, 0x55, 0xCC);
 }
diff --git a/chrome/browser/ui/cocoa/chrome_style.h b/chrome/browser/ui/cocoa/chrome_style.h
index 6757fc2..3e20b5c 100644
--- a/chrome/browser/ui/cocoa/chrome_style.h
+++ b/chrome/browser/ui/cocoa/chrome_style.h
@@ -18,6 +18,7 @@
 namespace chrome_style {
 
 int GetCloseButtonSize();  // Size of close button.
+SkColor GetBackgroundColor();  // Dialog background color.
 SkColor GetLinkColor();  // Dialog link color.
 
 const int kTitleTopPadding = 15; // Padding above the title.
diff --git a/chrome/browser/ui/cocoa/constrained_window/constrained_window_custom_window.mm b/chrome/browser/ui/cocoa/constrained_window/constrained_window_custom_window.mm
index a495711..b0af90f 100644
--- a/chrome/browser/ui/cocoa/constrained_window/constrained_window_custom_window.mm
+++ b/chrome/browser/ui/cocoa/constrained_window/constrained_window_custom_window.mm
@@ -46,7 +46,8 @@
     base::CommandLine* command_line = base::CommandLine::ForCurrentProcess();
     if (!command_line->HasSwitch(switches::kTestType))
       [self setHasShadow:YES];
-    [self setBackgroundColor:[NSColor windowBackgroundColor]];
+    [self setBackgroundColor:skia::SkColorToCalibratedNSColor(
+        chrome_style::GetBackgroundColor())];
     [self setOpaque:NO];
     [self setReleasedWhenClosed:NO];
   }
diff --git a/chrome/browser/ui/cocoa/download/download_danger_prompt_impl.cc b/chrome/browser/ui/cocoa/download/download_danger_prompt_impl.cc
index 9f548d9..8f10bb5 100644
--- a/chrome/browser/ui/cocoa/download/download_danger_prompt_impl.cc
+++ b/chrome/browser/ui/cocoa/download/download_danger_prompt_impl.cc
@@ -80,7 +80,6 @@
       download_(download),
       show_context_(show_context),
       done_(done) {
-  DCHECK(!done_.is_null());
   download_->AddObserver(this);
   RecordOpenedDangerousConfirmDialog(download_->GetDangerType());
 
diff --git a/chrome/browser/ui/cocoa/profiles/user_manager_mac.mm b/chrome/browser/ui/cocoa/profiles/user_manager_mac.mm
index 0116bd6..a589a987 100644
--- a/chrome/browser/ui/cocoa/profiles/user_manager_mac.mm
+++ b/chrome/browser/ui/cocoa/profiles/user_manager_mac.mm
@@ -488,7 +488,7 @@
   // This method should only be called if the user manager is already showing.
   if (!UserManager::IsShowing())
     return;
-  GURL url = signin::GetReauthURLWithEmail(
+  GURL url = signin::GetReauthURLWithEmailForDialog(
       signin_metrics::AccessPoint::ACCESS_POINT_USER_MANAGER, reason, email);
   instance_->ShowDialog(browser_context, email, url);
 }
@@ -500,9 +500,9 @@
   if (!UserManager::IsShowing())
     return;
   instance_->SetSigninProfilePath(profile_path);
-  GURL url = signin::GetPromoURL(
+  GURL url = signin::GetPromoURLForDialog(
       signin_metrics::AccessPoint::ACCESS_POINT_USER_MANAGER,
-      signin_metrics::Reason::REASON_SIGNIN_PRIMARY_ACCOUNT, true, true);
+      signin_metrics::Reason::REASON_SIGNIN_PRIMARY_ACCOUNT, true);
   instance_->ShowDialog(browser_context, std::string(), url);
 }
 
diff --git a/chrome/browser/ui/cocoa/share_menu_controller.mm b/chrome/browser/ui/cocoa/share_menu_controller.mm
index 1f50d10c..6c5a1f902 100644
--- a/chrome/browser/ui/cocoa/share_menu_controller.mm
+++ b/chrome/browser/ui/cocoa/share_menu_controller.mm
@@ -181,7 +181,10 @@
   if (@available(macOS 10.10, *)) {
     activity_.reset([[NSUserActivity alloc]
         initWithActivityType:NSUserActivityTypeBrowsingWeb]);
-    [activity_ setWebpageURL:url];
+    // webpageURL must be http or https or an exception is thrown.
+    if ([url.scheme hasPrefix:@"http"]) {
+      [activity_ setWebpageURL:url];
+    }
     [activity_ setTitle:title];
     [activity_ becomeCurrent];
   }
diff --git a/chrome/browser/ui/cocoa/tabs/tab_controller.mm b/chrome/browser/ui/cocoa/tabs/tab_controller.mm
index 3cea6f0e..1151fbf 100644
--- a/chrome/browser/ui/cocoa/tabs/tab_controller.mm
+++ b/chrome/browser/ui/cocoa/tabs/tab_controller.mm
@@ -212,6 +212,15 @@
 // the menu based off of the cross-platform model. Re-create the menu and
 // model every time to get the correct labels and enabling.
 - (NSMenu*)menu {
+  // If the menu is currently open, then this method is being called from
+  // the nested runloop of the menu. This can happen when an accessibility
+  // message is sent to retrieve the menu options. Do not delete the objects
+  // associated with a running menu, which could lead to a use-after-free,
+  // and instead just return the existing instance. https://crbug.com/778776
+  if ([contextMenuController_ isMenuOpen]) {
+    return [contextMenuController_ menu];
+  }
+
   contextMenuDelegate_.reset(new MenuDelegate(target_, self));
   contextMenuModel_.reset(
       [target_ contextMenuModelForController:self
diff --git a/chrome/browser/ui/cocoa/tabs/tab_controller_unittest.mm b/chrome/browser/ui/cocoa/tabs/tab_controller_unittest.mm
index 72d165a..c90e248f 100644
--- a/chrome/browser/ui/cocoa/tabs/tab_controller_unittest.mm
+++ b/chrome/browser/ui/cocoa/tabs/tab_controller_unittest.mm
@@ -15,11 +15,13 @@
 #import "chrome/browser/ui/cocoa/tabs/tab_strip_drag_controller.h"
 #import "chrome/browser/ui/cocoa/tabs/tab_view.h"
 #include "chrome/browser/ui/cocoa/test/cocoa_test_helper.h"
+#import "chrome/browser/ui/cocoa/test/menu_test_observer.h"
 #include "chrome/browser/ui/cocoa/test/scoped_force_rtl_mac.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #import "testing/gtest_mac.h"
 #include "testing/platform_test.h"
 #include "ui/base/resource/resource_bundle.h"
+#import "ui/events/test/cocoa_test_event_utils.h"
 #include "ui/resources/grit/ui_resources.h"
 
 // Implements the target interface for the tab, which gets sent messages when
@@ -520,6 +522,34 @@
   EXPECT_EQ(3, [menu numberOfItems]);
 }
 
+// Regression test for https://crbug.com/778776. An accessibility message can
+// cause -[TabController menu] to be called while the existing menu is open.
+// Test that this does not cause the running menu to be deleted.
+TEST_F(TabControllerTest, RecursiveMenu) {
+  base::scoped_nsobject<TabController> controller([[TabController alloc] init]);
+  base::scoped_nsobject<TabControllerTestTarget> target(
+      [[TabControllerTestTarget alloc] init]);
+  [controller setTarget:target];
+
+  NSMenu* menu = [controller menu];
+
+  base::scoped_nsobject<MenuTestObserver> menu_observer(
+      [[MenuTestObserver alloc] initWithMenu:menu]);
+  [menu_observer setCloseAfterOpening:YES];
+  [menu_observer setOpenCallback:^(MenuTestObserver*) {
+    NSMenu* open_menu = [controller menu];
+    EXPECT_TRUE(open_menu);
+    EXPECT_EQ(menu, open_menu);
+  }];
+
+  [NSMenu
+      popUpContextMenu:menu
+             withEvent:cocoa_test_event_utils::LeftMouseDownAtPoint(NSZeroPoint)
+               forView:[controller view]];
+
+  EXPECT_NE(menu, [controller menu]);
+}
+
 // Tests that the title field is correctly positioned and sized when the
 // view is resized.
 TEST_F(TabControllerTest, TitleViewLayout) {
diff --git a/chrome/browser/ui/cocoa/test/menu_test_observer.mm b/chrome/browser/ui/cocoa/test/menu_test_observer.mm
index 42851d5..56d55e1a 100644
--- a/chrome/browser/ui/cocoa/test/menu_test_observer.mm
+++ b/chrome/browser/ui/cocoa/test/menu_test_observer.mm
@@ -43,16 +43,13 @@
   isOpen_ = YES;
   didOpen_ = YES;
 
-  if (openCallback_)
-    openCallback_(self);
-
-  if (closeAfterOpening_) {
-    NSArray* modes = @[ NSEventTrackingRunLoopMode, NSDefaultRunLoopMode ];
-    [menu_ performSelector:@selector(cancelTracking)
-                withObject:nil
-                afterDelay:0
-                   inModes:modes];
-  }
+  // Post the callback to the runloop, since in this notification callback,
+  // the menu may not be fully in its tracking mode yet.
+  NSArray* modes = @[ NSEventTrackingRunLoopMode, NSDefaultRunLoopMode ];
+  [self performSelector:@selector(performOpenTasks)
+             withObject:nil
+             afterDelay:0
+                inModes:modes];
 }
 
 - (void)menuDidEndTracking:(NSNotification*)notif {
@@ -60,4 +57,14 @@
   isOpen_ = NO;
 }
 
+- (void)performOpenTasks {
+  DCHECK(isOpen_);
+
+  if (openCallback_)
+    openCallback_(self);
+
+  if (closeAfterOpening_)
+    [menu_ cancelTracking];
+}
+
 @end
diff --git a/chrome/browser/ui/cocoa/web_contents_modal_dialog_host_cocoa.h b/chrome/browser/ui/cocoa/web_contents_modal_dialog_host_cocoa.h
index 7a84b9a..9022d4830 100644
--- a/chrome/browser/ui/cocoa/web_contents_modal_dialog_host_cocoa.h
+++ b/chrome/browser/ui/cocoa/web_contents_modal_dialog_host_cocoa.h
@@ -22,6 +22,7 @@
   // web_modal::ModalDialogHost:
   gfx::NativeView GetHostView() const override;
   gfx::Point GetDialogPosition(const gfx::Size& size) override;
+  bool ShouldActivateDialog() const override;
   void AddObserver(web_modal::ModalDialogHostObserver* observer) override;
   void RemoveObserver(web_modal::ModalDialogHostObserver* observer) override;
 
diff --git a/chrome/browser/ui/cocoa/web_contents_modal_dialog_host_cocoa.mm b/chrome/browser/ui/cocoa/web_contents_modal_dialog_host_cocoa.mm
index 82fab3d..2522d1b 100644
--- a/chrome/browser/ui/cocoa/web_contents_modal_dialog_host_cocoa.mm
+++ b/chrome/browser/ui/cocoa/web_contents_modal_dialog_host_cocoa.mm
@@ -47,6 +47,10 @@
   return gfx::Point();
 }
 
+bool WebContentsModalDialogHostCocoa::ShouldActivateDialog() const {
+  return [[sheet_controller_ parentWindow] isMainWindow];
+}
+
 void WebContentsModalDialogHostCocoa::AddObserver(
     web_modal::ModalDialogHostObserver* observer) {
   NOTREACHED();
diff --git a/chrome/browser/ui/libgtkui/nav_button_layout_manager_gtk3.cc b/chrome/browser/ui/libgtkui/nav_button_layout_manager_gtk3.cc
index 5fdc45d3..cea0d1b 100644
--- a/chrome/browser/ui/libgtkui/nav_button_layout_manager_gtk3.cc
+++ b/chrome/browser/ui/libgtkui/nav_button_layout_manager_gtk3.cc
@@ -44,7 +44,7 @@
 }  // namespace
 
 NavButtonLayoutManagerGtk3::NavButtonLayoutManagerGtk3(GtkUi* delegate)
-    : delegate_(delegate), signal_id_(0) {
+    : delegate_(delegate), signal_id_(0), signal_id_middle_click_(0) {
   DCHECK(delegate_);
   GtkSettings* settings = gtk_settings_get_default();
   if (GtkVersionCheck(3, 14)) {
@@ -53,6 +53,12 @@
         G_CALLBACK(OnDecorationButtonLayoutChangedThunk), this);
     DCHECK(signal_id_);
     OnDecorationButtonLayoutChanged(settings, nullptr);
+
+    signal_id_middle_click_ =
+        g_signal_connect(settings, "notify::gtk-titlebar-middle-click",
+                         G_CALLBACK(OnMiddleClickActionChangedThunk), this);
+    DCHECK(signal_id_middle_click_);
+    OnMiddleClickActionChanged(settings, nullptr);
   } else if (GtkVersionCheck(3, 10, 3)) {
     signal_id_ = g_signal_connect_after(settings, "notify::gtk-theme-name",
                                         G_CALLBACK(OnThemeChangedThunk), this);
@@ -67,6 +73,9 @@
 NavButtonLayoutManagerGtk3::~NavButtonLayoutManagerGtk3() {
   if (signal_id_)
     g_signal_handler_disconnect(gtk_settings_get_default(), signal_id_);
+  if (signal_id_middle_click_)
+    g_signal_handler_disconnect(gtk_settings_get_default(),
+                                signal_id_middle_click_);
 }
 
 void NavButtonLayoutManagerGtk3::SetWindowButtonOrderingFromGtkLayout(
@@ -84,6 +93,28 @@
       GetGtkSettingsStringProperty(settings, "gtk-decoration-layout"));
 }
 
+void NavButtonLayoutManagerGtk3::OnMiddleClickActionChanged(
+    GtkSettings* settings,
+    GParamSpec* param) {
+  std::string value =
+      GetGtkSettingsStringProperty(settings, "gtk-titlebar-middle-click");
+  GtkUi::NonClientMiddleClickAction action;
+  if (value == "none") {
+    action = views::LinuxUI::MIDDLE_CLICK_ACTION_NONE;
+  } else if (value == "lower") {
+    action = views::LinuxUI::MIDDLE_CLICK_ACTION_LOWER;
+  } else if (value == "minimize") {
+    action = views::LinuxUI::MIDDLE_CLICK_ACTION_MINIMIZE;
+  } else if (value == "toggle-maximize") {
+    action = views::LinuxUI::MIDDLE_CLICK_ACTION_TOGGLE_MAXIMIZE;
+  } else {
+    // Default to no action if the user has explicitly
+    // chosen an action that we don't implement.
+    action = views::LinuxUI::MIDDLE_CLICK_ACTION_NONE;
+  }
+  delegate_->SetNonClientMiddleClickAction(action);
+}
+
 void NavButtonLayoutManagerGtk3::OnThemeChanged(GtkSettings* settings,
                                                 GParamSpec* param) {
   std::string layout = GetDecorationLayoutFromGtkWindow();
diff --git a/chrome/browser/ui/libgtkui/nav_button_layout_manager_gtk3.h b/chrome/browser/ui/libgtkui/nav_button_layout_manager_gtk3.h
index 938a084..dfbec32 100644
--- a/chrome/browser/ui/libgtkui/nav_button_layout_manager_gtk3.h
+++ b/chrome/browser/ui/libgtkui/nav_button_layout_manager_gtk3.h
@@ -34,6 +34,12 @@
 
   CHROMEG_CALLBACK_1(NavButtonLayoutManagerGtk3,
                      void,
+                     OnMiddleClickActionChanged,
+                     GtkSettings*,
+                     GParamSpec*);
+
+  CHROMEG_CALLBACK_1(NavButtonLayoutManagerGtk3,
+                     void,
                      OnThemeChanged,
                      GtkSettings*,
                      GParamSpec*);
@@ -42,6 +48,8 @@
 
   unsigned long signal_id_;
 
+  unsigned long signal_id_middle_click_;
+
   DISALLOW_COPY_AND_ASSIGN(NavButtonLayoutManagerGtk3);
 };
 
diff --git a/chrome/browser/ui/login/login_handler_browsertest.cc b/chrome/browser/ui/login/login_handler_browsertest.cc
index 7a66950..bc03040 100644
--- a/chrome/browser/ui/login/login_handler_browsertest.cc
+++ b/chrome/browser/ui/login/login_handler_browsertest.cc
@@ -754,6 +754,40 @@
   EXPECT_EQ(1, observer.auth_needed_count());
 }
 
+// Block same domain image resource if the top level frame is HTTPS and the
+// image resource is HTTP.
+// E.g. Top level: https://example.com, Image resource: http://example.com/image
+IN_PROC_BROWSER_TEST_F(LoginPromptBrowserTest,
+                       BlockCrossdomainPromptForSubresourcesMixedContent) {
+  ASSERT_TRUE(embedded_test_server()->Start());
+  net::EmbeddedTestServer https_server(net::EmbeddedTestServer::TYPE_HTTPS);
+  https_server.SetSSLConfig(net::EmbeddedTestServer::CERT_OK);
+  https_server.ServeFilesFromSourceDirectory("chrome/test/data");
+  ASSERT_TRUE(https_server.Start());
+
+  content::WebContents* contents =
+      browser()->tab_strip_model()->GetActiveWebContents();
+  NavigationController* controller = &contents->GetController();
+  LoginPromptBrowserTestObserver observer;
+  observer.Register(content::Source<NavigationController>(controller));
+
+  GURL image_url = embedded_test_server()->GetURL("/auth-basic/index.html");
+  GURL test_page = https_server.GetURL(
+      std::string("/login/load_img_from_same_domain_mixed_content.html?") +
+      image_url.spec());
+  GURL::Replacements replacements;
+  replacements.SetHostStr("a.com");
+  test_page = test_page.ReplaceComponents(replacements);
+  image_url = image_url.ReplaceComponents(replacements);
+
+  WindowedLoadStopObserver load_stop_waiter(controller, 1);
+  browser()->OpenURL(OpenURLParams(test_page, Referrer(),
+                                   WindowOpenDisposition::CURRENT_TAB,
+                                   ui::PAGE_TRANSITION_TYPED, false));
+  load_stop_waiter.Wait();
+  EXPECT_EQ(0, observer.auth_needed_count());
+}
+
 // Allow crossdomain iframe login prompting despite the above.
 IN_PROC_BROWSER_TEST_F(LoginPromptBrowserTest,
                        AllowCrossdomainPromptForSubframes) {
diff --git a/chrome/browser/ui/omnibox/chrome_omnibox_client.cc b/chrome/browser/ui/omnibox/chrome_omnibox_client.cc
index 07f1011..19802a6 100644
--- a/chrome/browser/ui/omnibox/chrome_omnibox_client.cc
+++ b/chrome/browser/ui/omnibox/chrome_omnibox_client.cc
@@ -340,7 +340,7 @@
 
 void ChromeOmniboxClient::OnTextChanged(const AutocompleteMatch& current_match,
                                         bool user_input_in_progress,
-                                        base::string16& user_text,
+                                        const base::string16& user_text,
                                         const AutocompleteResult& result,
                                         bool is_popup_open,
                                         bool has_focus) {
diff --git a/chrome/browser/ui/omnibox/chrome_omnibox_client.h b/chrome/browser/ui/omnibox/chrome_omnibox_client.h
index 5e70ab1..52361846 100644
--- a/chrome/browser/ui/omnibox/chrome_omnibox_client.h
+++ b/chrome/browser/ui/omnibox/chrome_omnibox_client.h
@@ -63,7 +63,7 @@
   void OnCurrentMatchChanged(const AutocompleteMatch& match) override;
   void OnTextChanged(const AutocompleteMatch& current_match,
                      bool user_input_in_progress,
-                     base::string16& user_text,
+                     const base::string16& user_text,
                      const AutocompleteResult& result,
                      bool is_popup_open,
                      bool has_focus) override;
diff --git a/chrome/browser/ui/page_info/permission_menu_model_unittest.cc b/chrome/browser/ui/page_info/permission_menu_model_unittest.cc
index b737ff7..2b678d2f 100644
--- a/chrome/browser/ui/page_info/permission_menu_model_unittest.cc
+++ b/chrome/browser/ui/page_info/permission_menu_model_unittest.cc
@@ -41,6 +41,7 @@
   permission.type = CONTENT_SETTINGS_TYPE_COOKIES;
   permission.setting = CONTENT_SETTING_ALLOW;
   permission.default_setting = CONTENT_SETTING_ALLOW;
+  permission.source = content_settings::SETTING_SOURCE_USER;
   permission.is_incognito = false;
   PermissionMenuModel model(profile(), GURL("http://www.google.com"),
                             permission, callback.callback());
@@ -56,6 +57,7 @@
     permission.type = type;
     permission.setting = CONTENT_SETTING_ALLOW;
     permission.default_setting = CONTENT_SETTING_ALLOW;
+    permission.source = content_settings::SETTING_SOURCE_USER;
     permission.is_incognito = false;
     PermissionMenuModel model(profile(), GURL("http://www.google.com"),
                               permission, callback.callback());
@@ -69,6 +71,7 @@
   permission.type = CONTENT_SETTINGS_TYPE_NOTIFICATIONS;
   permission.setting = CONTENT_SETTING_ASK;
   permission.default_setting = CONTENT_SETTING_ASK;
+  permission.source = content_settings::SETTING_SOURCE_USER;
 
   permission.is_incognito = false;
   PermissionMenuModel regular_model(profile(), GURL("https://www.google.com"),
@@ -87,6 +90,7 @@
   permission.type = CONTENT_SETTINGS_TYPE_ADS;
   permission.setting = CONTENT_SETTING_BLOCK;
   permission.default_setting = CONTENT_SETTING_BLOCK;
+  permission.source = content_settings::SETTING_SOURCE_USER;
   permission.is_incognito = false;
   PermissionMenuModel model(profile(), GURL("http://www.google.com"),
                             permission, callback.callback());
diff --git a/chrome/browser/ui/passwords/password_manager_porter.cc b/chrome/browser/ui/passwords/password_manager_porter.cc
index 688a858..cb8f2a9 100644
--- a/chrome/browser/ui/passwords/password_manager_porter.cc
+++ b/chrome/browser/ui/passwords/password_manager_porter.cc
@@ -87,7 +87,9 @@
 PasswordManagerPorter::~PasswordManagerPorter() {}
 
 void PasswordManagerPorter::Store() {
-  DCHECK(web_contents_);
+  // In unittests a null WebContents means: "Abort creating the file Selector."
+  if (!web_contents_)
+    return;
   PresentFileSelector(web_contents_,
                       PasswordManagerPorter::Type::PASSWORD_EXPORT);
 }
diff --git a/chrome/browser/ui/passwords/password_manager_presenter.cc b/chrome/browser/ui/passwords/password_manager_presenter.cc
index 21d4b9b..5c69768 100644
--- a/chrome/browser/ui/passwords/password_manager_presenter.cc
+++ b/chrome/browser/ui/passwords/password_manager_presenter.cc
@@ -44,12 +44,6 @@
 #include "net/base/registry_controlled_domains/registry_controlled_domain.h"
 #include "url/gurl.h"
 
-#if defined(OS_WIN)
-#include "chrome/browser/password_manager/password_manager_util_win.h"
-#elif defined(OS_MACOSX)
-#include "chrome/browser/password_manager/password_manager_util_mac.h"
-#endif
-
 #if !defined(OS_ANDROID)
 #include "chrome/browser/extensions/api/passwords_private/passwords_private_utils.h"
 #endif
@@ -215,11 +209,7 @@
     PasswordUIView* password_view)
     : populater_(this),
       exception_populater_(this),
-      password_view_(password_view),
-      password_manager_porter_(this),
-      password_access_authenticator_(
-          base::BindRepeating(&PasswordManagerPresenter::OsReauthCall,
-                              base::Unretained(this))) {
+      password_view_(password_view) {
   DCHECK(password_view_);
 }
 
@@ -313,10 +303,6 @@
     return;
   }
 
-  if (!password_access_authenticator_.EnsureUserIsAuthenticated()) {
-    return;
-  }
-
   syncer::SyncService* sync_service = nullptr;
   if (ProfileSyncServiceFactory::HasProfileSyncService(
           password_view_->GetProfile())) {
@@ -410,18 +396,6 @@
   }
 }
 
-void PasswordManagerPresenter::ImportPasswords(
-    content::WebContents* web_contents) {
-  password_manager_porter_.set_web_contents(web_contents);
-  password_manager_porter_.Load();
-}
-
-void PasswordManagerPresenter::ExportPasswords(
-    content::WebContents* web_contents) {
-  password_manager_porter_.set_web_contents(web_contents);
-  password_manager_porter_.Store();
-}
-
 void PasswordManagerPresenter::AddLogin(const autofill::PasswordForm& form) {
   PasswordStore* store = GetPasswordStore();
   if (!store)
@@ -442,26 +416,6 @@
   store->RemoveLogin(form);
 }
 
-void PasswordManagerPresenter::SetOsReauthCallForTesting(
-    base::RepeatingCallback<bool()> os_reauth_call) {
-  password_access_authenticator_.SetOsReauthCallForTesting(
-      std::move(os_reauth_call));
-}
-
-bool PasswordManagerPresenter::OsReauthCall() {
-#if defined(OS_ANDROID)
-  NOTREACHED();
-  return true;
-#elif defined(OS_WIN)
-  return password_manager_util_win::AuthenticateUser(
-      password_view_->GetNativeWindow());
-#elif defined(OS_MACOSX)
-  return password_manager_util_mac::AuthenticateUser();
-#else
-  return true;
-#endif
-}
-
 PasswordManagerPresenter::ListPopulater::ListPopulater(
     PasswordManagerPresenter* page) : page_(page) {
 }
diff --git a/chrome/browser/ui/passwords/password_manager_presenter.h b/chrome/browser/ui/passwords/password_manager_presenter.h
index c360113..e12aba35 100644
--- a/chrome/browser/ui/passwords/password_manager_presenter.h
+++ b/chrome/browser/ui/passwords/password_manager_presenter.h
@@ -13,8 +13,6 @@
 #include <vector>
 
 #include "base/macros.h"
-#include "chrome/browser/ui/passwords/password_access_authenticator.h"
-#include "chrome/browser/ui/passwords/password_manager_porter.h"
 #include "components/password_manager/core/browser/password_store.h"
 #include "components/password_manager/core/browser/password_store_consumer.h"
 #include "components/password_manager/core/browser/ui/credential_provider_interface.h"
@@ -79,14 +77,6 @@
   // |index| The index of the entry.
   void RequestShowPassword(size_t index);
 
-  // Trigger the password import procedure, allowing the user to load passwords
-  // from a file.
-  void ImportPasswords(content::WebContents* web_contents);
-
-  // Trigger the password export procedure, allowing the user to save all their
-  // passwords to a file.
-  void ExportPasswords(content::WebContents* web_contents);
-
   // Wrapper around |PasswordStore::AddLogin| that adds the corresponding undo
   // action to |undo_manager_|.
   void AddLogin(const autofill::PasswordForm& form);
@@ -95,17 +85,9 @@
   // undo action to |undo_manager_|.
   void RemoveLogin(const autofill::PasswordForm& form);
 
-  // Use this in tests to mock the OS-level reauthentication.
-  void SetOsReauthCallForTesting(
-      base::RepeatingCallback<bool()> os_reauth_call);
-
  private:
   friend class PasswordManagerPresenterTest;
 
-  // Triggers an OS-dependent UI to present OS account login challenge and
-  // returns true if the user is passed that challenge.
-  bool OsReauthCall();
-
   // Sets the password and exception list of the UI view.
   void SetPasswordList();
   void SetPasswordExceptionList();
@@ -180,10 +162,6 @@
   // UI view that owns this presenter.
   PasswordUIView* password_view_;
 
-  PasswordManagerPorter password_manager_porter_;
-
-  PasswordAccessAuthenticator password_access_authenticator_;
-
   DISALLOW_COPY_AND_ASSIGN(PasswordManagerPresenter);
 };
 
diff --git a/chrome/browser/ui/passwords/password_manager_presenter_unittest.cc b/chrome/browser/ui/passwords/password_manager_presenter_unittest.cc
index 198c712..4caaaa0 100644
--- a/chrome/browser/ui/passwords/password_manager_presenter_unittest.cc
+++ b/chrome/browser/ui/passwords/password_manager_presenter_unittest.cc
@@ -315,36 +315,4 @@
                         PasswordEntryType::SAVED);
 }
 
-#if !defined(OS_ANDROID)  // Reauthentication is handled differently on Android.
-enum class ReauthResult { PASS, FAIL };
-bool FakeOsReauthCall(bool* reauth_called, ReauthResult result) {
-  *reauth_called = true;
-  return result == ReauthResult::PASS;
-}
-
-TEST_F(PasswordManagerPresenterTest, TestPassedReauthOnView) {
-  bool reauth_called = false;
-  GetUIController()->GetPasswordManagerPresenter()->SetOsReauthCallForTesting(
-      base::BindRepeating(&FakeOsReauthCall, &reauth_called,
-                          ReauthResult::PASS));
-
-  AddPasswordEntry(GURL("http://abc1.com"), "test@gmail.com", "test");
-  EXPECT_CALL(*GetUIController(), ShowPassword(0, base::ASCIIToUTF16("test")));
-  GetUIController()->GetPasswordManagerPresenter()->RequestShowPassword(0);
-  EXPECT_TRUE(reauth_called);
-}
-
-TEST_F(PasswordManagerPresenterTest, TestFailedReauthOnView) {
-  bool reauth_called = false;
-  GetUIController()->GetPasswordManagerPresenter()->SetOsReauthCallForTesting(
-      base::BindRepeating(&FakeOsReauthCall, &reauth_called,
-                          ReauthResult::FAIL));
-
-  AddPasswordEntry(GURL("http://abc1.com"), "test@gmail.com", "test");
-  EXPECT_CALL(*GetUIController(), ShowPassword(_, _)).Times(0);
-  GetUIController()->GetPasswordManagerPresenter()->RequestShowPassword(0);
-  EXPECT_TRUE(reauth_called);
-}
-#endif  // !defined(OS_ANDROID)
-
 }  // namespace
diff --git a/chrome/browser/ui/sync/one_click_signin_sync_observer_unittest.cc b/chrome/browser/ui/sync/one_click_signin_sync_observer_unittest.cc
index 351a7d37..632bee8 100644
--- a/chrome/browser/ui/sync/one_click_signin_sync_observer_unittest.cc
+++ b/chrome/browser/ui/sync/one_click_signin_sync_observer_unittest.cc
@@ -271,7 +271,7 @@
 // triggered, since it would be redundant.
 TEST_F(OneClickSigninSyncObserverTest,
        OnSyncStateChanged_SyncConfiguredSuccessfully_SourceIsSettings) {
-  GURL continue_url = signin::GetPromoURL(
+  GURL continue_url = signin::GetPromoURLForTab(
       signin_metrics::AccessPoint::ACCESS_POINT_SETTINGS,
       signin_metrics::Reason::REASON_SIGNIN_PRIMARY_ACCOUNT, false);
   CreateSyncObserver(continue_url.spec());
diff --git a/chrome/browser/ui/tabs/tab_features.cc b/chrome/browser/ui/tabs/tab_features.cc
new file mode 100644
index 0000000..493eae43
--- /dev/null
+++ b/chrome/browser/ui/tabs/tab_features.cc
@@ -0,0 +1,30 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/ui/tabs/tab_features.h"
+
+#include "base/feature_list.h"
+#include "base/memory/ptr_util.h"
+#include "build/build_config.h"
+#include "chrome/browser/ui/tabs/tab_strip_model_impl.h"
+
+#if defined(OS_WIN)
+#include "chrome/browser/ui/tabs/tab_strip_model_experimental.h"
+#endif
+
+const base::Feature kExperimentalTabControllerFeature{
+    "ExperimentalTabController", base::FEATURE_DISABLED_BY_DEFAULT,
+};
+
+std::unique_ptr<TabStripModel> CreateTabStripModel(
+    TabStripModelDelegate* delegate,
+    Profile* profile) {
+  // The experimental controller currently just crashes so don't inflict it on
+  // people yet who may have accidentally triggered this feature.
+  // #if defined(OS_WIN)
+  // if (base::FeatureList::IsEnabled(kExperimentalTabControllerFeature))
+  //  return base::MakeUnique<TabStripModelExperimental>(delegate, profile);
+  // #endif
+  return base::MakeUnique<TabStripModelImpl>(delegate, profile);
+}
diff --git a/chrome/browser/ui/tabs/tab_features.h b/chrome/browser/ui/tabs/tab_features.h
new file mode 100644
index 0000000..dc5823d8
--- /dev/null
+++ b/chrome/browser/ui/tabs/tab_features.h
@@ -0,0 +1,24 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_UI_TABS_TAB_FEATURES_H_
+#define CHROME_BROWSER_UI_TABS_TAB_FEATURES_H_
+
+#include <memory>
+
+#include "base/feature_list.h"
+
+class TabStripModel;
+class TabStripModelDelegate;
+class Profile;
+
+// Enables the tab controller for experimenting with different behavior.
+extern const base::Feature kExperimentalTabControllerFeature;
+
+// Creates and returns the correct TabStripModel according to the feature flag.
+std::unique_ptr<TabStripModel> CreateTabStripModel(
+    TabStripModelDelegate* delegate,
+    Profile* profile);
+
+#endif  // CHROME_BROWSER_UI_TABS_TAB_FEATURES_H_
diff --git a/chrome/browser/ui/tabs/tab_strip_model.h b/chrome/browser/ui/tabs/tab_strip_model.h
index 5824efd..a336d74 100644
--- a/chrome/browser/ui/tabs/tab_strip_model.h
+++ b/chrome/browser/ui/tabs/tab_strip_model.h
@@ -19,7 +19,6 @@
 
 class Profile;
 class TabStripModelDelegate;
-class TabStripModelOrderController;
 
 namespace content {
 class WebContents;
@@ -144,9 +143,6 @@
   // avoid doing meaningless or unhelpful work.
   virtual bool closing_all() const = 0;
 
-  // Access the order controller. Exposed only for unit tests.
-  virtual TabStripModelOrderController* order_controller() const = 0;
-
   // Basic API /////////////////////////////////////////////////////////////////
 
   // Determines if the specified index is contained within the TabStripModel.
@@ -269,16 +265,6 @@
   virtual void SetOpenerOfWebContentsAt(int index,
                                         content::WebContents* opener) = 0;
 
-  // Returns the index of the next WebContents in the sequence of WebContentses
-  // spawned by the specified WebContents after |start_index|. If |use_group| is
-  // true, the group property of the tab is used instead of the opener to find
-  // the next tab. Under some circumstances the group relationship may exist but
-  // the opener may not.
-  virtual int GetIndexOfNextWebContentsOpenedBy(
-      const content::WebContents* opener,
-      int start_index,
-      bool use_group) const = 0;
-
   // Returns the index of the last WebContents in the model opened by the
   // specified opener, starting at |start_index|.
   virtual int GetIndexOfLastWebContentsOpenedBy(
@@ -292,25 +278,6 @@
   virtual void TabNavigating(content::WebContents* contents,
                              ui::PageTransition transition) = 0;
 
-  // Forget all Opener relationships that are stored (but _not_ group
-  // relationships!) This is to reduce unpredictable tab switching behavior
-  // in complex session states. The exact circumstances under which this method
-  // is called are left up to the implementation of the selected
-  // TabStripModelOrderController.
-  virtual void ForgetAllOpeners() = 0;
-
-  // Forgets the group affiliation of the specified WebContents. This
-  // should be called when a WebContents that is part of a logical group
-  // of tabs is moved to a new logical context by the user (e.g. by typing a new
-  // URL or selecting a bookmark). This also forgets the opener, which is
-  // considered a weaker relationship than group.
-  virtual void ForgetGroup(content::WebContents* contents) = 0;
-
-  // Returns true if the group/opener relationships present for |contents|
-  // should be reset when _any_ selection change occurs in the model.
-  virtual bool ShouldResetGroupOnSelect(
-      content::WebContents* contents) const = 0;
-
   // Changes the blocked state of the tab at |index|.
   virtual void SetTabBlocked(int index, bool blocked) = 0;
 
@@ -330,13 +297,6 @@
   // pinned tabs.
   virtual int IndexOfFirstNonPinnedTab() const = 0;
 
-  // Returns a valid index for inserting a new tab into this model. |index| is
-  // the proposed index and |pinned_tab| is true if inserting a tab will become
-  // pinned (pinned). If |pinned_tab| is true, the returned index is between 0
-  // and IndexOfFirstNonPinnedTab. If |pinned_tab| is false, the returned index
-  // is between IndexOfFirstNonPinnedTab and count().
-  virtual int ConstrainInsertionIndex(int index, bool pinned_tab) = 0;
-
   // Extends the selection from the anchor to |index|.
   virtual void ExtendSelectionTo(int index) = 0;
 
diff --git a/chrome/browser/ui/tabs/tab_strip_model_experimental.cc b/chrome/browser/ui/tabs/tab_strip_model_experimental.cc
new file mode 100644
index 0000000..f6b12ffa
--- /dev/null
+++ b/chrome/browser/ui/tabs/tab_strip_model_experimental.cc
@@ -0,0 +1,276 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/ui/tabs/tab_strip_model_experimental.h"
+
+#include "base/logging.h"
+
+TabStripModelExperimental::TabStripModelExperimental(
+    TabStripModelDelegate* delegate,
+    Profile* profile)
+    : delegate_(delegate), profile_(profile) {}
+
+TabStripModelExperimental::~TabStripModelExperimental() {}
+
+TabStripModelDelegate* TabStripModelExperimental::delegate() const {
+  return delegate_;
+}
+
+void TabStripModelExperimental::AddObserver(TabStripModelObserver* observer) {
+  observers_.AddObserver(observer);
+}
+
+void TabStripModelExperimental::RemoveObserver(
+    TabStripModelObserver* observer) {
+  observers_.RemoveObserver(observer);
+}
+
+int TabStripModelExperimental::count() const {
+  NOTIMPLEMENTED();
+  return 0;
+}
+
+bool TabStripModelExperimental::empty() const {
+  NOTIMPLEMENTED();
+  return true;
+}
+
+Profile* TabStripModelExperimental::profile() const {
+  return profile_;
+}
+
+int TabStripModelExperimental::active_index() const {
+  NOTIMPLEMENTED();
+  return kNoTab;
+}
+
+bool TabStripModelExperimental::closing_all() const {
+  NOTIMPLEMENTED();
+  return false;
+}
+
+bool TabStripModelExperimental::ContainsIndex(int index) const {
+  NOTIMPLEMENTED();
+  return false;
+}
+
+void TabStripModelExperimental::AppendWebContents(
+    content::WebContents* contents,
+    bool foreground) {
+  NOTIMPLEMENTED();
+}
+
+void TabStripModelExperimental::InsertWebContentsAt(
+    int index,
+    content::WebContents* contents,
+    int add_types) {
+  NOTIMPLEMENTED();
+}
+
+bool TabStripModelExperimental::CloseWebContentsAt(int index,
+                                                   uint32_t close_types) {
+  NOTIMPLEMENTED();
+  return true;
+}
+
+content::WebContents* TabStripModelExperimental::ReplaceWebContentsAt(
+    int index,
+    content::WebContents* new_contents) {
+  NOTIMPLEMENTED();
+  return nullptr;
+}
+
+content::WebContents* TabStripModelExperimental::DetachWebContentsAt(
+    int index) {
+  NOTIMPLEMENTED();
+  return nullptr;
+}
+
+void TabStripModelExperimental::ActivateTabAt(int index, bool user_gesture) {
+  NOTIMPLEMENTED();
+}
+
+void TabStripModelExperimental::AddTabAtToSelection(int index) {
+  NOTIMPLEMENTED();
+}
+
+void TabStripModelExperimental::MoveWebContentsAt(int index,
+                                                  int to_position,
+                                                  bool select_after_move) {
+  NOTIMPLEMENTED();
+}
+
+void TabStripModelExperimental::MoveSelectedTabsTo(int index) {
+  NOTIMPLEMENTED();
+}
+
+content::WebContents* TabStripModelExperimental::GetActiveWebContents() const {
+  NOTIMPLEMENTED();
+  return nullptr;
+}
+
+content::WebContents* TabStripModelExperimental::GetWebContentsAt(
+    int index) const {
+  NOTIMPLEMENTED();
+  return nullptr;
+}
+
+int TabStripModelExperimental::GetIndexOfWebContents(
+    const content::WebContents* contents) const {
+  NOTIMPLEMENTED();
+  return kNoTab;
+}
+
+void TabStripModelExperimental::UpdateWebContentsStateAt(
+    int index,
+    TabStripModelObserver::TabChangeType change_type) {
+  NOTIMPLEMENTED();
+}
+
+void TabStripModelExperimental::SetTabNeedsAttentionAt(int index,
+                                                       bool attention) {
+  NOTIMPLEMENTED();
+}
+
+void TabStripModelExperimental::CloseAllTabs() {
+  NOTIMPLEMENTED();
+}
+
+bool TabStripModelExperimental::TabsAreLoading() const {
+  NOTIMPLEMENTED();
+  return false;
+}
+
+content::WebContents* TabStripModelExperimental::GetOpenerOfWebContentsAt(
+    int index) {
+  NOTIMPLEMENTED();
+  return nullptr;
+}
+
+void TabStripModelExperimental::SetOpenerOfWebContentsAt(
+    int index,
+    content::WebContents* opener) {
+  NOTIMPLEMENTED();
+}
+
+void TabStripModelExperimental::TabNavigating(content::WebContents* contents,
+                                              ui::PageTransition transition) {
+  NOTIMPLEMENTED();
+}
+
+void TabStripModelExperimental::SetTabBlocked(int index, bool blocked) {
+  NOTIMPLEMENTED();
+}
+
+void TabStripModelExperimental::SetTabPinned(int index, bool pinned) {
+  NOTIMPLEMENTED();
+}
+
+bool TabStripModelExperimental::IsTabPinned(int index) const {
+  NOTIMPLEMENTED();
+  return false;
+}
+
+bool TabStripModelExperimental::IsTabBlocked(int index) const {
+  NOTIMPLEMENTED();
+  return false;
+}
+
+int TabStripModelExperimental::IndexOfFirstNonPinnedTab() const {
+  NOTIMPLEMENTED();
+  return 0;
+}
+
+void TabStripModelExperimental::ExtendSelectionTo(int index) {
+  NOTIMPLEMENTED();
+}
+
+void TabStripModelExperimental::ToggleSelectionAt(int index) {
+  NOTIMPLEMENTED();
+}
+
+void TabStripModelExperimental::AddSelectionFromAnchorTo(int index) {
+  NOTIMPLEMENTED();
+}
+
+bool TabStripModelExperimental::IsTabSelected(int index) const {
+  NOTIMPLEMENTED();
+  return false;
+}
+
+void TabStripModelExperimental::SetSelectionFromModel(
+    ui::ListSelectionModel source) {
+  NOTIMPLEMENTED();
+}
+
+const ui::ListSelectionModel& TabStripModelExperimental::selection_model()
+    const {
+  return selection_model_;
+}
+
+void TabStripModelExperimental::AddWebContents(content::WebContents* contents,
+                                               int index,
+                                               ui::PageTransition transition,
+                                               int add_types) {
+  NOTIMPLEMENTED();
+}
+
+void TabStripModelExperimental::CloseSelectedTabs() {
+  NOTIMPLEMENTED();
+}
+
+void TabStripModelExperimental::SelectNextTab() {
+  NOTIMPLEMENTED();
+}
+
+void TabStripModelExperimental::SelectPreviousTab() {
+  NOTIMPLEMENTED();
+}
+
+void TabStripModelExperimental::SelectLastTab() {
+  NOTIMPLEMENTED();
+}
+
+void TabStripModelExperimental::MoveTabNext() {
+  NOTIMPLEMENTED();
+}
+
+void TabStripModelExperimental::MoveTabPrevious() {
+  NOTIMPLEMENTED();
+}
+
+bool TabStripModelExperimental::IsContextMenuCommandEnabled(
+    int context_index,
+    ContextMenuCommand command_id) const {
+  NOTIMPLEMENTED();
+  return false;
+}
+
+void TabStripModelExperimental::ExecuteContextMenuCommand(
+    int context_index,
+    ContextMenuCommand command_id) {
+  NOTIMPLEMENTED();
+}
+
+std::vector<int> TabStripModelExperimental::GetIndicesClosedByCommand(
+    int index,
+    ContextMenuCommand id) const {
+  NOTIMPLEMENTED();
+  return std::vector<int>();
+}
+
+bool TabStripModelExperimental::WillContextMenuMute(int index) {
+  NOTIMPLEMENTED();
+  return false;
+}
+
+bool TabStripModelExperimental::WillContextMenuMuteSites(int index) {
+  NOTIMPLEMENTED();
+  return false;
+}
+
+bool TabStripModelExperimental::WillContextMenuPin(int index) {
+  NOTIMPLEMENTED();
+  return false;
+}
diff --git a/chrome/browser/ui/tabs/tab_strip_model_experimental.h b/chrome/browser/ui/tabs/tab_strip_model_experimental.h
new file mode 100644
index 0000000..07f99b9
--- /dev/null
+++ b/chrome/browser/ui/tabs/tab_strip_model_experimental.h
@@ -0,0 +1,104 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_UI_TABS_TAB_STRIP_MODEL_EXPERIMENTAL_H_
+#define CHROME_BROWSER_UI_TABS_TAB_STRIP_MODEL_EXPERIMENTAL_H_
+
+#include "base/macros.h"
+#include "base/observer_list.h"
+#include "chrome/browser/ui/tabs/tab_strip_model.h"
+#include "chrome/browser/ui/tabs/tab_strip_model_observer.h"
+#include "ui/base/models/list_selection_model.h"
+#include "ui/base/page_transition_types.h"
+
+class TabStripModelExperimental : public TabStripModel {
+ public:
+  TabStripModelExperimental(TabStripModelDelegate* delegate, Profile* profile);
+  ~TabStripModelExperimental() override;
+
+  // TabStripModel implementation.
+  TabStripModelDelegate* delegate() const override;
+  void AddObserver(TabStripModelObserver* observer) override;
+  void RemoveObserver(TabStripModelObserver* observer) override;
+  int count() const override;
+  bool empty() const override;
+  Profile* profile() const override;
+  int active_index() const override;
+  bool closing_all() const override;
+  bool ContainsIndex(int index) const override;
+  void AppendWebContents(content::WebContents* contents,
+                         bool foreground) override;
+  void InsertWebContentsAt(int index,
+                           content::WebContents* contents,
+                           int add_types) override;
+  bool CloseWebContentsAt(int index, uint32_t close_types) override;
+  content::WebContents* ReplaceWebContentsAt(
+      int index,
+      content::WebContents* new_contents) override;
+  content::WebContents* DetachWebContentsAt(int index) override;
+  void ActivateTabAt(int index, bool user_gesture) override;
+  void AddTabAtToSelection(int index) override;
+  void MoveWebContentsAt(int index,
+                         int to_position,
+                         bool select_after_move) override;
+  void MoveSelectedTabsTo(int index) override;
+  content::WebContents* GetActiveWebContents() const override;
+  content::WebContents* GetWebContentsAt(int index) const override;
+  int GetIndexOfWebContents(
+      const content::WebContents* contents) const override;
+  void UpdateWebContentsStateAt(
+      int index,
+      TabStripModelObserver::TabChangeType change_type) override;
+  void SetTabNeedsAttentionAt(int index, bool attention) override;
+  void CloseAllTabs() override;
+  bool TabsAreLoading() const override;
+  content::WebContents* GetOpenerOfWebContentsAt(int index) override;
+  void SetOpenerOfWebContentsAt(int index,
+                                content::WebContents* opener) override;
+  void TabNavigating(content::WebContents* contents,
+                     ui::PageTransition transition) override;
+  void SetTabBlocked(int index, bool blocked) override;
+  void SetTabPinned(int index, bool pinned) override;
+  bool IsTabPinned(int index) const override;
+  bool IsTabBlocked(int index) const override;
+  int IndexOfFirstNonPinnedTab() const override;
+  void ExtendSelectionTo(int index) override;
+  void ToggleSelectionAt(int index) override;
+  void AddSelectionFromAnchorTo(int index) override;
+  bool IsTabSelected(int index) const override;
+  void SetSelectionFromModel(ui::ListSelectionModel source) override;
+  const ui::ListSelectionModel& selection_model() const override;
+  void AddWebContents(content::WebContents* contents,
+                      int index,
+                      ui::PageTransition transition,
+                      int add_types) override;
+  void CloseSelectedTabs() override;
+  void SelectNextTab() override;
+  void SelectPreviousTab() override;
+  void SelectLastTab() override;
+  void MoveTabNext() override;
+  void MoveTabPrevious() override;
+  bool IsContextMenuCommandEnabled(
+      int context_index,
+      ContextMenuCommand command_id) const override;
+  void ExecuteContextMenuCommand(int context_index,
+                                 ContextMenuCommand command_id) override;
+  std::vector<int> GetIndicesClosedByCommand(int index, ContextMenuCommand id)
+      const override;
+  bool WillContextMenuMute(int index) override;
+  bool WillContextMenuMuteSites(int index) override;
+  bool WillContextMenuPin(int index) override;
+
+ private:
+  TabStripModelDelegate* delegate_;
+  Profile* profile_;
+
+  base::ObserverList<TabStripModelObserver> observers_;
+
+  ui::ListSelectionModel selection_model_;
+
+  DISALLOW_COPY_AND_ASSIGN(TabStripModelExperimental);
+};
+
+#endif  // CHROME_BROWSER_UI_TABS_TAB_STRIP_MODEL_EXPERIMENTAL_H_
diff --git a/chrome/browser/ui/tabs/tab_strip_model_impl.cc b/chrome/browser/ui/tabs/tab_strip_model_impl.cc
index f238b96..549e124 100644
--- a/chrome/browser/ui/tabs/tab_strip_model_impl.cc
+++ b/chrome/browser/ui/tabs/tab_strip_model_impl.cc
@@ -281,10 +281,6 @@
   return closing_all_;
 }
 
-TabStripModelOrderController* TabStripModelImpl::order_controller() const {
-  return order_controller_.get();
-}
-
 bool TabStripModelImpl::ContainsIndex(int index) const {
   return index >= 0 && index < count();
 }
@@ -580,26 +576,6 @@
   contents_data_[index]->set_opener(opener);
 }
 
-int TabStripModelImpl::GetIndexOfNextWebContentsOpenedBy(
-    const WebContents* opener,
-    int start_index,
-    bool use_group) const {
-  DCHECK(opener);
-  DCHECK(ContainsIndex(start_index));
-
-  // Check tabs after start_index first.
-  for (int i = start_index + 1; i < count(); ++i) {
-    if (OpenerMatches(contents_data_[i], opener, use_group))
-      return i;
-  }
-  // Then check tabs before start_index, iterating backwards.
-  for (int i = start_index - 1; i >= 0; --i) {
-    if (OpenerMatches(contents_data_[i], opener, use_group))
-      return i;
-  }
-  return kNoTab;
-}
-
 int TabStripModelImpl::GetIndexOfLastWebContentsOpenedBy(
     const WebContents* opener,
     int start_index) const {
@@ -647,26 +623,6 @@
   }
 }
 
-void TabStripModelImpl::ForgetAllOpeners() {
-  // Forget all opener memories so we don't do anything weird with tab
-  // re-selection ordering.
-  for (const auto& data : contents_data_)
-    data->set_opener(nullptr);
-}
-
-void TabStripModelImpl::ForgetGroup(WebContents* contents) {
-  int index = GetIndexOfWebContents(contents);
-  DCHECK(ContainsIndex(index));
-  contents_data_[index]->set_group(nullptr);
-  contents_data_[index]->set_opener(nullptr);
-}
-
-bool TabStripModelImpl::ShouldResetGroupOnSelect(WebContents* contents) const {
-  int index = GetIndexOfWebContents(contents);
-  DCHECK(ContainsIndex(index));
-  return contents_data_[index]->reset_group_on_select();
-}
-
 void TabStripModelImpl::SetTabBlocked(int index, bool blocked) {
   DCHECK(ContainsIndex(index));
   if (contents_data_[index]->blocked() == blocked)
@@ -716,12 +672,6 @@
   return count();
 }
 
-int TabStripModelImpl::ConstrainInsertionIndex(int index, bool pinned_tab) {
-  return pinned_tab
-             ? std::min(std::max(0, index), IndexOfFirstNonPinnedTab())
-             : std::min(count(), std::max(index, IndexOfFirstNonPinnedTab()));
-}
-
 void TabStripModelImpl::ExtendSelectionTo(int index) {
   DCHECK(ContainsIndex(index));
   ui::ListSelectionModel new_model = selection_model_;
@@ -1114,9 +1064,55 @@
   return !all_pinned;
 }
 
+int TabStripModelImpl::GetIndexOfNextWebContentsOpenedBy(
+    const WebContents* opener,
+    int start_index,
+    bool use_group) const {
+  DCHECK(opener);
+  DCHECK(ContainsIndex(start_index));
+
+  // Check tabs after start_index first.
+  for (int i = start_index + 1; i < count(); ++i) {
+    if (OpenerMatches(contents_data_[i], opener, use_group))
+      return i;
+  }
+  // Then check tabs before start_index, iterating backwards.
+  for (int i = start_index - 1; i >= 0; --i) {
+    if (OpenerMatches(contents_data_[i], opener, use_group))
+      return i;
+  }
+  return kNoTab;
+}
+
+void TabStripModelImpl::ForgetAllOpeners() {
+  // Forget all opener memories so we don't do anything weird with tab
+  // re-selection ordering.
+  for (const auto& data : contents_data_)
+    data->set_opener(nullptr);
+}
+
+void TabStripModelImpl::ForgetGroup(WebContents* contents) {
+  int index = GetIndexOfWebContents(contents);
+  DCHECK(ContainsIndex(index));
+  contents_data_[index]->set_group(nullptr);
+  contents_data_[index]->set_opener(nullptr);
+}
+
+bool TabStripModelImpl::ShouldResetGroupOnSelect(WebContents* contents) const {
+  int index = GetIndexOfWebContents(contents);
+  DCHECK(ContainsIndex(index));
+  return contents_data_[index]->reset_group_on_select();
+}
+
 ///////////////////////////////////////////////////////////////////////////////
 // TabStripModel, private:
 
+int TabStripModelImpl::ConstrainInsertionIndex(int index, bool pinned_tab) {
+  return pinned_tab
+             ? std::min(std::max(0, index), IndexOfFirstNonPinnedTab())
+             : std::min(count(), std::max(index, IndexOfFirstNonPinnedTab()));
+}
+
 std::vector<WebContents*> TabStripModelImpl::GetWebContentsFromIndices(
     const std::vector<int>& indices) const {
   std::vector<WebContents*> contents;
diff --git a/chrome/browser/ui/tabs/tab_strip_model_impl.h b/chrome/browser/ui/tabs/tab_strip_model_impl.h
index 104f154..31c1ea667 100644
--- a/chrome/browser/ui/tabs/tab_strip_model_impl.h
+++ b/chrome/browser/ui/tabs/tab_strip_model_impl.h
@@ -34,155 +34,92 @@
   TabStripModelImpl(TabStripModelDelegate* delegate, Profile* profile);
   ~TabStripModelImpl() override;
 
-  // Retrieves the TabStripModelDelegate associated with this TabStripModel.
+  // TabStripModel implementation.
   TabStripModelDelegate* delegate() const override;
-
-  // Add and remove observers to changes within this TabStripModel.
   void AddObserver(TabStripModelObserver* observer) override;
   void RemoveObserver(TabStripModelObserver* observer) override;
-
-  // Retrieve the number of WebContentses/emptiness of the TabStripModel.
   int count() const override;
   bool empty() const override;
-
-  // Retrieve the Profile associated with this TabStripModel.
   Profile* profile() const override;
-
-  // Retrieve the index of the currently active WebContents. This will be
-  // ui::ListSelectionModel::kUnselectedIndex if no tab is currently selected
-  // (this happens while the tab strip is being initialized or is empty).
   int active_index() const override;
-
-  // Returns true if the tabstrip is currently closing all open tabs (via a
-  // call to CloseAllTabs). As tabs close, the selection in the tabstrip
-  // changes which notifies observers, which can use this as an optimization to
-  // avoid doing meaningless or unhelpful work.
   bool closing_all() const override;
-
-  // Access the order controller. Exposed only for unit tests.
-  TabStripModelOrderController* order_controller() const override;
-
-  // Basic API /////////////////////////////////////////////////////////////////
-
-  // Determines if the specified index is contained within the TabStripModel.
   bool ContainsIndex(int index) const override;
-
-  // Adds the specified WebContents in the default location. Tabs opened
-  // in the foreground inherit the group of the previously active tab.
   void AppendWebContents(content::WebContents* contents,
                          bool foreground) override;
-
-  // Adds the specified WebContents at the specified location.
-  // |add_types| is a bitmask of AddTabTypes override; see it for details.
-  //
-  // All append/insert methods end up in this method.
-  //
-  // NOTE: adding a tab using this method does NOT query the order controller,
-  // as such the ADD_FORCE_INDEX AddTabTypes is meaningless here.  The only time
-  // the |index| is changed is if using the index would result in breaking the
-  // constraint that all pinned tabs occur before non-pinned tabs.
-  // See also AddWebContents.
   void InsertWebContentsAt(int index,
                            content::WebContents* contents,
                            int add_types) override;
-
-  // Closes the WebContents at the specified index. This causes the
-  // WebContents to be destroyed, but it may not happen immediately.
-  // |close_types| is a bitmask of CloseTypes. Returns true if the
-  // WebContents was closed immediately, false if it was not closed (we
-  // may be waiting for a response from an onunload handler, or waiting for the
-  // user to confirm closure).
   bool CloseWebContentsAt(int index, uint32_t close_types) override;
-
-  // Replaces the WebContents at |index| with |new_contents|. The
-  // WebContents that was at |index| is returned and its ownership returns
-  // to the caller.
   content::WebContents* ReplaceWebContentsAt(
       int index,
       content::WebContents* new_contents) override;
-
-  // Detaches the WebContents at the specified index from this strip. The
-  // WebContents is not destroyed, just removed from display. The caller
-  // is responsible for doing something with it (e.g. stuffing it into another
-  // strip). Returns the detached WebContents.
   content::WebContents* DetachWebContentsAt(int index) override;
-
-  // Makes the tab at the specified index the active tab. |user_gesture| is true
-  // if the user actually clicked on the tab or navigated to it using a keyboard
-  // command, false if the tab was activated as a by-product of some other
-  // action.
   void ActivateTabAt(int index, bool user_gesture) override;
-
-  // Adds tab at |index| to the currently selected tabs, without changing the
-  // active tab index.
   void AddTabAtToSelection(int index) override;
-
-  // Move the WebContents at the specified index to another index. This
-  // method does NOT send Detached/Attached notifications, rather it moves the
-  // WebContents inline and sends a Moved notification instead.
-  // If |select_after_move| is false, whatever tab was selected before the move
-  // will still be selected, but its index may have incremented or decremented
-  // one slot.
   void MoveWebContentsAt(int index,
                          int to_position,
                          bool select_after_move) override;
-
-  // Moves the selected tabs to |index|. |index| is treated as if the tab strip
-  // did not contain any of the selected tabs. For example, if the tabstrip
-  // contains [A b c D E f] (upper case selected) and this is invoked with 1 the
-  // result is [b A D E c f].
-  // This method maintains that all pinned tabs occur before non-pinned tabs.
-  // When pinned tabs are selected the move is processed in two chunks: first
-  // pinned tabs are moved, then non-pinned tabs are moved. If the index is
-  // after (pinned-tab-count - selected-pinned-tab-count), then the index the
-  // non-pinned selected tabs are moved to is (index +
-  // selected-pinned-tab-count). For example, if the model consists of
-  // [A b c D E f] (A b c are pinned) and this is invoked with 2, the result is
-  // [b c A D E f]. In this example nothing special happened because the target
-  // index was <= (pinned-tab-count - selected-pinned-tab-count). If the target
-  // index were 3, then the result would be [b c A f D F]. A, being pinned, can
-  // move no further than index 2. The non-pinned tabs are moved to the target
-  // index + selected-pinned tab-count (3 + 1).
   void MoveSelectedTabsTo(int index) override;
-
-  // Returns the currently active WebContents, or NULL if there is none.
   content::WebContents* GetActiveWebContents() const override;
-
-  // Returns the WebContents at the specified index, or NULL if there is
-  // none.
   content::WebContents* GetWebContentsAt(int index) const override;
-
-  // Returns the index of the specified WebContents, or TabStripModel::kNoTab
-  // if the WebContents is not in this TabStripModel.
   int GetIndexOfWebContents(
       const content::WebContents* contents) const override;
-
-  // Notify any observers that the WebContents at the specified index has
-  // changed in some way. See TabChangeType for details of |change_type|.
   void UpdateWebContentsStateAt(
       int index,
       TabStripModelObserver::TabChangeType change_type) override;
-
-  // Cause a tab to display a UI indication to the user that it needs their
-  // attention.
   void SetTabNeedsAttentionAt(int index, bool attention) override;
-
-  // Close all tabs at once. Code can use closing_all() above to defer
-  // operations that might otherwise by invoked by the flurry of detach/select
-  // notifications this method causes.
   void CloseAllTabs() override;
-
-  // Returns true if there are any WebContentses that are currently loading.
   bool TabsAreLoading() const override;
-
-  // Returns the WebContents that opened the WebContents at |index|, or NULL if
-  // there is no opener on record.
   content::WebContents* GetOpenerOfWebContentsAt(int index) override;
-
-  // Changes the |opener| of the WebContents at |index|.
-  // Note: |opener| must be in this tab strip.
   void SetOpenerOfWebContentsAt(int index,
                                 content::WebContents* opener) override;
+  int GetIndexOfLastWebContentsOpenedBy(const content::WebContents* opener,
+                                        int start_index) const override;
+  void TabNavigating(content::WebContents* contents,
+                     ui::PageTransition transition) override;
+  void SetTabBlocked(int index, bool blocked) override;
+  void SetTabPinned(int index, bool pinned) override;
+  bool IsTabPinned(int index) const override;
+  bool IsTabBlocked(int index) const override;
+  int IndexOfFirstNonPinnedTab() const override;
+  void ExtendSelectionTo(int index) override;
+  void ToggleSelectionAt(int index) override;
+  void AddSelectionFromAnchorTo(int index) override;
+  bool IsTabSelected(int index) const override;
+  void SetSelectionFromModel(ui::ListSelectionModel source) override;
+  const ui::ListSelectionModel& selection_model() const override;
+  void AddWebContents(content::WebContents* contents,
+                      int index,
+                      ui::PageTransition transition,
+                      int add_types) override;
+  void CloseSelectedTabs() override;
+  void SelectNextTab() override;
+  void SelectPreviousTab() override;
+  void SelectLastTab() override;
+  void MoveTabNext() override;
+  void MoveTabPrevious() override;
+  bool IsContextMenuCommandEnabled(
+      int context_index,
+      ContextMenuCommand command_id) const override;
+  void ExecuteContextMenuCommand(int context_index,
+                                 ContextMenuCommand command_id) override;
+  std::vector<int> GetIndicesClosedByCommand(int index, ContextMenuCommand id)
+      const override;
+  bool WillContextMenuMute(int index) override;
+  bool WillContextMenuMuteSites(int index) override;
+  bool WillContextMenuPin(int index) override;
+
+  //////////////////////////////////////////////////////////////////////////////
+  // Ordering API
+  //
+  // These functions are used only by the TabStripModelOrderController which
+  // goes with this class (not the abstract base-class) so these do not need
+  // to be exposed in the general TabStripModel interface.
+
+  // Access the order controller. Exposed only for unit tests.
+  TabStripModelOrderController* order_controller() const {
+    return order_controller_.get();
+  }
 
   // Returns the index of the next WebContents in the sequence of WebContentses
   // spawned by the specified WebContents after |start_index|. If |use_group| is
@@ -191,140 +128,25 @@
   // the opener may not.
   int GetIndexOfNextWebContentsOpenedBy(const content::WebContents* opener,
                                         int start_index,
-                                        bool use_group) const override;
-
-  // Returns the index of the last WebContents in the model opened by the
-  // specified opener, starting at |start_index|.
-  int GetIndexOfLastWebContentsOpenedBy(const content::WebContents* opener,
-                                        int start_index) const override;
-
-  // To be called when a navigation is about to occur in the specified
-  // WebContents. Depending on the tab, and the transition type of the
-  // navigation, the TabStripModel may adjust its selection and grouping
-  // behavior.
-  void TabNavigating(content::WebContents* contents,
-                     ui::PageTransition transition) override;
+                                        bool use_group) const;
 
   // Forget all Opener relationships that are stored (but _not_ group
   // relationships!) This is to reduce unpredictable tab switching behavior
   // in complex session states. The exact circumstances under which this method
   // is called are left up to the implementation of the selected
   // TabStripModelOrderController.
-  void ForgetAllOpeners() override;
+  void ForgetAllOpeners();
 
   // Forgets the group affiliation of the specified WebContents. This
   // should be called when a WebContents that is part of a logical group
   // of tabs is moved to a new logical context by the user (e.g. by typing a new
   // URL or selecting a bookmark). This also forgets the opener, which is
   // considered a weaker relationship than group.
-  void ForgetGroup(content::WebContents* contents) override;
+  void ForgetGroup(content::WebContents* contents);
 
   // Returns true if the group/opener relationships present for |contents|
   // should be reset when _any_ selection change occurs in the model.
-  bool ShouldResetGroupOnSelect(content::WebContents* contents) const override;
-
-  // Changes the blocked state of the tab at |index|.
-  void SetTabBlocked(int index, bool blocked) override;
-
-  // Changes the pinned state of the tab at |index|. See description above
-  // class for details on this.
-  void SetTabPinned(int index, bool pinned) override;
-
-  // Returns true if the tab at |index| is pinned.
-  // See description above class for details on pinned tabs.
-  bool IsTabPinned(int index) const override;
-
-  // Returns true if the tab at |index| is blocked by a tab modal dialog.
-  bool IsTabBlocked(int index) const override;
-
-  // Returns the index of the first tab that is not a pinned tab. This returns
-  // |count()| if all of the tabs are pinned tabs, and 0 if none of the tabs are
-  // pinned tabs.
-  int IndexOfFirstNonPinnedTab() const override;
-
-  // Returns a valid index for inserting a new tab into this model. |index| is
-  // the proposed index and |pinned_tab| is true if inserting a tab will become
-  // pinned (pinned). If |pinned_tab| is true, the returned index is between 0
-  // and IndexOfFirstNonPinnedTab. If |pinned_tab| is false, the returned index
-  // is between IndexOfFirstNonPinnedTab and count().
-  int ConstrainInsertionIndex(int index, bool pinned_tab) override;
-
-  // Extends the selection from the anchor to |index|.
-  void ExtendSelectionTo(int index) override;
-
-  // Toggles the selection at |index|. This does nothing if |index| is selected
-  // and there are no other selected tabs.
-  void ToggleSelectionAt(int index) override;
-
-  // Makes sure the tabs from the anchor to |index| are selected. This only
-  // adds to the selection.
-  void AddSelectionFromAnchorTo(int index) override;
-
-  // Returns true if the tab at |index| is selected.
-  bool IsTabSelected(int index) const override;
-
-  // Sets the selection to match that of |source|.
-  void SetSelectionFromModel(ui::ListSelectionModel source) override;
-
-  const ui::ListSelectionModel& selection_model() const override;
-
-  // Command level API /////////////////////////////////////////////////////////
-
-  // Adds a WebContents at the best position in the TabStripModel given
-  // the specified insertion index, transition, etc. |add_types| is a bitmask of
-  // AddTabTypes; see it for details. This method ends up calling into
-  // InsertWebContentsAt to do the actual insertion. Pass kNoTab for |index| to
-  // append the contents to the end of the tab strip.
-  void AddWebContents(content::WebContents* contents,
-                      int index,
-                      ui::PageTransition transition,
-                      int add_types) override;
-
-  // Closes the selected tabs.
-  void CloseSelectedTabs() override;
-
-  // Select adjacent tabs
-  void SelectNextTab() override;
-  void SelectPreviousTab() override;
-
-  // Selects the last tab in the tab strip.
-  void SelectLastTab() override;
-
-  // Swap adjacent tabs.
-  void MoveTabNext() override;
-  void MoveTabPrevious() override;
-
-  // View API //////////////////////////////////////////////////////////////////
-
-  // Returns true if the specified command is enabled. If |context_index| is
-  // selected the response applies to all selected tabs.
-  bool IsContextMenuCommandEnabled(
-      int context_index,
-      ContextMenuCommand command_id) const override;
-
-  // Performs the action associated with the specified command for the given
-  // TabStripModel index |context_index|.  If |context_index| is selected the
-  // command applies to all selected tabs.
-  void ExecuteContextMenuCommand(int context_index,
-                                 ContextMenuCommand command_id) override;
-
-  // Returns a vector of indices of the tabs that will close when executing the
-  // command |id| for the tab at |index|. The returned indices are sorted in
-  // descending order.
-  std::vector<int> GetIndicesClosedByCommand(int index, ContextMenuCommand id)
-      const override;
-
-  // Returns true if 'CommandToggleTabAudioMuted' will mute. |index| is the
-  // index supplied to |ExecuteContextMenuCommand|.
-  bool WillContextMenuMute(int index) override;
-
-  // Returns true if 'CommandToggleSiteMuted' will mute. |index| is the
-  // index supplied to |ExecuteContextMenuCommand|.
-  bool WillContextMenuMuteSites(int index) override;
-
-  // Returns true if 'CommandTogglePinned' will pin. |index| is the index
-  // supplied to |ExecuteContextMenuCommand|.
-  bool WillContextMenuPin(int index) override;
+  bool ShouldResetGroupOnSelect(content::WebContents* contents) const;
 
  private:
   class WebContentsData;
@@ -337,6 +159,8 @@
     NOTIFY_USER_GESTURE,
   };
 
+  int ConstrainInsertionIndex(int index, bool pinned_tab);
+
   // Convenience for converting a vector of indices into a vector of
   // WebContents.
   std::vector<content::WebContents*> GetWebContentsFromIndices(
diff --git a/chrome/browser/ui/tabs/tab_strip_model_impl_unittest.cc b/chrome/browser/ui/tabs/tab_strip_model_impl_unittest.cc
index 2946353..46119213 100644
--- a/chrome/browser/ui/tabs/tab_strip_model_impl_unittest.cc
+++ b/chrome/browser/ui/tabs/tab_strip_model_impl_unittest.cc
@@ -734,12 +734,12 @@
   EXPECT_TRUE(tabstrip.empty());
 }
 
-static int GetInsertionIndex(TabStripModel* tabstrip) {
+static int GetInsertionIndex(TabStripModelImpl* tabstrip) {
   return tabstrip->order_controller()->DetermineInsertionIndex(
       ui::PAGE_TRANSITION_LINK, false);
 }
 
-static void InsertWebContentses(TabStripModel* tabstrip,
+static void InsertWebContentses(TabStripModelImpl* tabstrip,
                                 WebContents* contents1,
                                 WebContents* contents2,
                                 WebContents* contents3) {
diff --git a/chrome/browser/ui/tabs/tab_strip_model_order_controller.cc b/chrome/browser/ui/tabs/tab_strip_model_order_controller.cc
index 4da7b98..2017f9a 100644
--- a/chrome/browser/ui/tabs/tab_strip_model_order_controller.cc
+++ b/chrome/browser/ui/tabs/tab_strip_model_order_controller.cc
@@ -4,13 +4,14 @@
 
 #include "chrome/browser/ui/tabs/tab_strip_model_order_controller.h"
 
+#include "chrome/browser/ui/tabs/tab_strip_model_impl.h"
 #include "content/public/browser/web_contents.h"
 
 ///////////////////////////////////////////////////////////////////////////////
 // TabStripModelOrderController, public:
 
 TabStripModelOrderController::TabStripModelOrderController(
-    TabStripModel* tabstrip)
+    TabStripModelImpl* tabstrip)
     : tabstrip_(tabstrip) {
   tabstrip_->AddObserver(this);
 }
diff --git a/chrome/browser/ui/tabs/tab_strip_model_order_controller.h b/chrome/browser/ui/tabs/tab_strip_model_order_controller.h
index 211a109..de59ee08 100644
--- a/chrome/browser/ui/tabs/tab_strip_model_order_controller.h
+++ b/chrome/browser/ui/tabs/tab_strip_model_order_controller.h
@@ -6,9 +6,11 @@
 #define CHROME_BROWSER_UI_TABS_TAB_STRIP_MODEL_ORDER_CONTROLLER_H_
 
 #include "base/macros.h"
-#include "chrome/browser/ui/tabs/tab_strip_model.h"
+#include "chrome/browser/ui/tabs/tab_strip_model_observer.h"
 #include "ui/base/page_transition_types.h"
 
+class TabStripModelImpl;
+
 ///////////////////////////////////////////////////////////////////////////////
 // TabStripModelOrderController
 //
@@ -17,7 +19,7 @@
 //
 class TabStripModelOrderController : public TabStripModelObserver {
  public:
-  explicit TabStripModelOrderController(TabStripModel* tabstrip);
+  explicit TabStripModelOrderController(TabStripModelImpl* tabstrip);
   ~TabStripModelOrderController() override;
 
   // Determine where to place a newly opened tab by using the supplied
@@ -40,7 +42,7 @@
   // reflect the fact that |removing_index| is going away.
   int GetValidIndex(int index, int removing_index) const;
 
-  TabStripModel* tabstrip_;
+  TabStripModelImpl* tabstrip_;
 
   DISALLOW_COPY_AND_ASSIGN(TabStripModelOrderController);
 };
diff --git a/chrome/browser/ui/views/content_setting_bubble_contents.cc b/chrome/browser/ui/views/content_setting_bubble_contents.cc
index eb7c6da..09d7f6f 100644
--- a/chrome/browser/ui/views/content_setting_bubble_contents.cc
+++ b/chrome/browser/ui/views/content_setting_bubble_contents.cc
@@ -357,7 +357,7 @@
 }
 
 bool ContentSettingBubbleContents::ShouldShowCloseButton() const {
-  return ChromeLayoutProvider::Get()->IsHarmonyMode();
+  return false;
 }
 
 void ContentSettingBubbleContents::Init() {
diff --git a/chrome/browser/ui/views/download/download_danger_prompt_views.cc b/chrome/browser/ui/views/download/download_danger_prompt_views.cc
index 01c7dd9..d004b1e 100644
--- a/chrome/browser/ui/views/download/download_danger_prompt_views.cc
+++ b/chrome/browser/ui/views/download/download_danger_prompt_views.cc
@@ -46,6 +46,7 @@
   DownloadDangerPromptViews(content::DownloadItem* item,
                             bool show_context,
                             const OnDone& done);
+  ~DownloadDangerPromptViews() override;
 
   // DownloadDangerPrompt:
   void InvokeActionForTesting(Action action) override;
@@ -91,7 +92,6 @@
       show_context_(show_context),
       done_(done),
       contents_view_(NULL) {
-  DCHECK(!done_.is_null());
   download_->AddObserver(this);
 
   contents_view_ = new views::View;
@@ -126,6 +126,11 @@
       chrome::DialogIdentifier::DOWNLOAD_DANGER_PROMPT);
 }
 
+DownloadDangerPromptViews::~DownloadDangerPromptViews() {
+  if (download_)
+    download_->RemoveObserver(this);
+}
+
 // DownloadDangerPrompt methods:
 void DownloadDangerPromptViews::InvokeActionForTesting(Action action) {
   switch (action) {
diff --git a/chrome/browser/ui/views/frame/browser_non_client_frame_view_ash.cc b/chrome/browser/ui/views/frame/browser_non_client_frame_view_ash.cc
index 51e1f3ae..5e332bf 100644
--- a/chrome/browser/ui/views/frame/browser_non_client_frame_view_ash.cc
+++ b/chrome/browser/ui/views/frame/browser_non_client_frame_view_ash.cc
@@ -26,6 +26,7 @@
 #include "chrome/browser/ui/views/frame/browser_frame.h"
 #include "chrome/browser/ui/views/frame/browser_header_painter_ash.h"
 #include "chrome/browser/ui/views/frame/browser_view.h"
+#include "chrome/browser/ui/views/frame/hosted_app_button_container.h"
 #include "chrome/browser/ui/views/frame/immersive_mode_controller.h"
 #include "chrome/browser/ui/views/profiles/profile_indicator_icon.h"
 #include "chrome/browser/ui/views/tab_icon_view.h"
@@ -73,7 +74,8 @@
     : BrowserNonClientFrameView(frame, browser_view),
       caption_button_container_(nullptr),
       back_button_(nullptr),
-      window_icon_(nullptr) {
+      window_icon_(nullptr),
+      hosted_app_button_container_(nullptr) {
   ash::wm::InstallResizeHandleWindowTargeterForWindow(frame->GetNativeWindow(),
                                                       nullptr);
   ash::Shell::Get()->AddShellObserver(this);
@@ -123,6 +125,13 @@
             SkColorSetA(theme_color.value(), SK_AlphaOPAQUE);
         header_painter->SetFrameColors(opaque_theme_color, opaque_theme_color);
       }
+      if (extensions::HostedAppBrowserController::
+              IsForExperimentalHostedAppBrowser(browser)) {
+        hosted_app_button_container_ = new HostedAppButtonContainer(
+            browser_view(), header_painter->ShouldUseLightImages());
+        caption_button_container_->AddChildViewAt(hosted_app_button_container_,
+                                                  0);
+      }
     } else if (!browser->is_app()) {
       // For non app (i.e. WebUI) windows (e.g. Settings) use MD frame color.
       header_painter->SetFrameColors(kMdWebUIFrameColor, kMdWebUIFrameColor);
@@ -226,6 +235,14 @@
 }
 
 int BrowserNonClientFrameViewAsh::NonClientHitTest(const gfx::Point& point) {
+  if (hosted_app_button_container_) {
+    gfx::Point client_point(point);
+    View::ConvertPointToTarget(this, hosted_app_button_container_,
+                               &client_point);
+    if (hosted_app_button_container_->HitTestPoint(client_point))
+      return HTCLIENT;
+  }
+
   const int hit_test = ash::FrameBorderNonClientHitTest(
       this, back_button_, caption_button_container_, point);
 
@@ -469,13 +486,12 @@
 }
 
 bool BrowserNonClientFrameViewAsh::ShouldPaint() const {
-  if (!frame()->IsFullscreen())
-    return true;
-
   // We need to paint when the top-of-window views are revealed in immersive
   // fullscreen.
   ImmersiveModeController* immersive_mode_controller =
       browser_view()->immersive_mode_controller();
-  return immersive_mode_controller->IsEnabled() &&
-         immersive_mode_controller->IsRevealed();
+  if (immersive_mode_controller->IsEnabled())
+    return immersive_mode_controller->IsRevealed();
+
+  return !frame()->IsFullscreen();
 }
diff --git a/chrome/browser/ui/views/frame/browser_non_client_frame_view_ash.h b/chrome/browser/ui/views/frame/browser_non_client_frame_view_ash.h
index 92e52e3..8ccfa7a0 100644
--- a/chrome/browser/ui/views/frame/browser_non_client_frame_view_ash.h
+++ b/chrome/browser/ui/views/frame/browser_non_client_frame_view_ash.h
@@ -14,6 +14,7 @@
 #include "chrome/browser/ui/views/frame/browser_non_client_frame_view.h"
 #include "chrome/browser/ui/views/tab_icon_view_model.h"
 
+class HostedAppButtonContainer;
 class TabIconView;
 
 namespace ash {
@@ -84,6 +85,7 @@
                            ToggleTabletModeRelayout);
   FRIEND_TEST_ALL_PREFIXES(BrowserNonClientFrameViewAshTest,
                            AvatarDisplayOnTeleportedWindow);
+  FRIEND_TEST_ALL_PREFIXES(HostedAppNonClientFrameViewAshTest, HostedAppFrame);
   FRIEND_TEST_ALL_PREFIXES(BrowserNonClientFrameViewAshBackButtonTest,
                            V1BackButton);
   FRIEND_TEST_ALL_PREFIXES(ImmersiveModeControllerAshHostedAppBrowserTest,
@@ -120,6 +122,10 @@
   // Helper class for painting the header.
   std::unique_ptr<ash::HeaderPainter> header_painter_;
 
+  // Container for extra frame buttons shown for hosted app windows.
+  // Owned by views hierarchy.
+  HostedAppButtonContainer* hosted_app_button_container_;
+
   DISALLOW_COPY_AND_ASSIGN(BrowserNonClientFrameViewAsh);
 };
 
diff --git a/chrome/browser/ui/views/frame/browser_non_client_frame_view_ash_browsertest.cc b/chrome/browser/ui/views/frame/browser_non_client_frame_view_ash_browsertest.cc
index 19ad1f24..dc6e31a 100644
--- a/chrome/browser/ui/views/frame/browser_non_client_frame_view_ash_browsertest.cc
+++ b/chrome/browser/ui/views/frame/browser_non_client_frame_view_ash_browsertest.cc
@@ -7,6 +7,7 @@
 #include "ash/ash_constants.h"
 #include "ash/frame/caption_buttons/frame_caption_button.h"
 #include "ash/frame/caption_buttons/frame_caption_button_container_view.h"
+#include "ash/frame/default_header_painter.h"
 #include "ash/frame/header_painter.h"
 #include "ash/public/cpp/ash_switches.h"
 #include "ash/public/cpp/immersive/immersive_fullscreen_controller_test_api.h"
@@ -15,9 +16,11 @@
 #include "base/command_line.h"
 #include "base/run_loop.h"
 #include "base/scoped_observer.h"
+#include "base/test/scoped_feature_list.h"
 #include "build/build_config.h"
 #include "chrome/app/chrome_command_ids.h"
 #include "chrome/browser/command_updater.h"
+#include "chrome/browser/extensions/extension_browsertest.h"
 #include "chrome/browser/profiles/profile_avatar_icon_util.h"
 #include "chrome/browser/ui/ash/multi_user/multi_user_util.h"
 #include "chrome/browser/ui/ash/multi_user/multi_user_window_manager_test.h"
@@ -30,21 +33,28 @@
 #include "chrome/browser/ui/tabs/tab_strip_model.h"
 #include "chrome/browser/ui/views/bookmarks/bookmark_bar_view.h"
 #include "chrome/browser/ui/views/frame/browser_view.h"
+#include "chrome/browser/ui/views/frame/hosted_app_button_container.h"
 #include "chrome/browser/ui/views/frame/immersive_mode_controller.h"
 #include "chrome/browser/ui/views/frame/immersive_mode_controller_ash.h"
 #include "chrome/browser/ui/views/profiles/profile_indicator_icon.h"
 #include "chrome/browser/ui/views/tabs/tab.h"
+#include "chrome/browser/ui/views/toolbar/app_menu.h"
+#include "chrome/common/chrome_features.h"
+#include "chrome/common/web_application_info.h"
 #include "chrome/test/base/in_process_browser_test.h"
 #include "components/signin/core/account_id/account_id.h"
 #include "ui/aura/client/aura_constants.h"
 #include "ui/aura/test/env_test_helper.h"
 #include "ui/base/hit_test.h"
 #include "ui/compositor/scoped_animation_duration_scale_mode.h"
+#include "ui/events/base_event_utils.h"
+#include "ui/events/event.h"
 #include "ui/views/widget/widget.h"
 
 using views::Widget;
 
-typedef InProcessBrowserTest BrowserNonClientFrameViewAshTest;
+using BrowserNonClientFrameViewAshTest = InProcessBrowserTest;
+using HostedAppNonClientFrameViewAshTest = ExtensionBrowserTest;
 
 IN_PROC_BROWSER_TEST_F(BrowserNonClientFrameViewAshTest, NonClientHitTest) {
   BrowserView* browser_view = BrowserView::GetBrowserViewForBrowser(browser());
@@ -443,6 +453,44 @@
     RunTest(datum.command, datum.expected_index);
 }
 
+// Creates a browser for a bookmark app and verifies the window frame is
+// correct.
+IN_PROC_BROWSER_TEST_F(HostedAppNonClientFrameViewAshTest, HostedAppFrame) {
+  base::test::ScopedFeatureList scoped_feature_list;
+  scoped_feature_list.InitAndEnableFeature(features::kDesktopPWAWindowing);
+
+  WebApplicationInfo web_app_info;
+  web_app_info.app_url = GURL("http://example.org/");
+  web_app_info.theme_color = SK_ColorBLUE;
+
+  const extensions::Extension* app = InstallBookmarkApp(web_app_info);
+  Browser* app_browser = LaunchAppBrowser(app);
+
+  BrowserView* browser_view =
+      BrowserView::GetBrowserViewForBrowser(app_browser);
+
+  BrowserNonClientFrameViewAsh* frame_view =
+      static_cast<BrowserNonClientFrameViewAsh*>(
+          browser_view->frame()->GetFrameView());
+
+  EXPECT_TRUE(frame_view->hosted_app_button_container_->visible());
+
+  // Ensure the theme color is set.
+  auto* header_painter = static_cast<ash::DefaultHeaderPainter*>(
+      frame_view->header_painter_.get());
+  EXPECT_EQ(SK_ColorBLUE, header_painter->GetActiveFrameColor());
+  EXPECT_EQ(SK_ColorBLUE, header_painter->GetInactiveFrameColor());
+
+  // Show the menu.
+  HostedAppButtonContainer::AppMenuButton* menu_button =
+      frame_view->hosted_app_button_container_->app_menu_button_;
+
+  ui::MouseEvent e(ui::ET_MOUSE_PRESSED, gfx::Point(), gfx::Point(),
+                   ui::EventTimeForNow(), ui::EF_LEFT_MOUSE_BUTTON, 0);
+  menu_button->OnMousePressed(e);
+  EXPECT_TRUE(menu_button->menu()->IsShowing());
+}
+
 namespace {
 
 class BrowserNonClientFrameViewAshBackButtonTest : public InProcessBrowserTest {
diff --git a/chrome/browser/ui/views/frame/browser_view_layout.cc b/chrome/browser/ui/views/frame/browser_view_layout.cc
index 0b8410c..2236892 100644
--- a/chrome/browser/ui/views/frame/browser_view_layout.cc
+++ b/chrome/browser/ui/views/frame/browser_view_layout.cc
@@ -83,6 +83,11 @@
     return gfx::Point(middle_x - size.width() / 2, top);
   }
 
+  bool ShouldActivateDialog() const override {
+    views::Widget* widget = browser_view_layout_->browser_view_->GetWidget();
+    return widget->IsActive();
+  }
+
   gfx::Size GetMaximumDialogSize() override {
     views::View* view = browser_view_layout_->contents_container_;
     gfx::Rect content_area = view->ConvertRectToWidget(view->GetLocalBounds());
diff --git a/chrome/browser/ui/views/frame/hosted_app_button_container.cc b/chrome/browser/ui/views/frame/hosted_app_button_container.cc
new file mode 100644
index 0000000..f5b3462c
--- /dev/null
+++ b/chrome/browser/ui/views/frame/hosted_app_button_container.cc
@@ -0,0 +1,53 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/ui/views/frame/hosted_app_button_container.h"
+
+#include "chrome/app/vector_icons/vector_icons.h"
+#include "chrome/browser/ui/toolbar/app_menu_model.h"
+#include "chrome/browser/ui/views/frame/browser_view.h"
+#include "chrome/browser/ui/views/toolbar/app_menu.h"
+#include "ui/gfx/color_palette.h"
+#include "ui/gfx/paint_vector_icon.h"
+#include "ui/views/layout/box_layout.h"
+
+HostedAppButtonContainer::AppMenuButton::AppMenuButton(
+    BrowserView* browser_view,
+    bool use_light)
+    : views::MenuButton(base::string16(), this, false),
+      browser_view_(browser_view) {
+  SetInkDropMode(InkDropMode::ON);
+  SkColor color = use_light ? SK_ColorWHITE : gfx::kChromeIconGrey;
+  SetImage(views::Button::STATE_NORMAL,
+           gfx::CreateVectorIcon(kBrowserToolsIcon, color));
+  set_ink_drop_base_color(color);
+}
+
+HostedAppButtonContainer::AppMenuButton::~AppMenuButton() {}
+
+void HostedAppButtonContainer::AppMenuButton::OnMenuButtonClicked(
+    views::MenuButton* source,
+    const gfx::Point& point,
+    const ui::Event* event) {
+  Browser* browser = browser_view_->browser();
+  menu_.reset(new AppMenu(browser, 0));
+  // TODO(calamity): Use custom menu model here.
+  menu_model_.reset(new AppMenuModel(browser_view_, browser));
+  menu_->Init(menu_model_.get());
+
+  menu_->RunMenu(this);
+}
+
+HostedAppButtonContainer::HostedAppButtonContainer(BrowserView* browser_view,
+                                                   bool use_light)
+    : app_menu_button_(new AppMenuButton(browser_view, use_light)) {
+  auto layout =
+      std::make_unique<views::BoxLayout>(views::BoxLayout::kHorizontal);
+  layout->set_cross_axis_alignment(
+      views::BoxLayout::CROSS_AXIS_ALIGNMENT_CENTER);
+  SetLayoutManager(layout.release());
+  AddChildView(app_menu_button_);
+}
+
+HostedAppButtonContainer::~HostedAppButtonContainer() {}
diff --git a/chrome/browser/ui/views/frame/hosted_app_button_container.h b/chrome/browser/ui/views/frame/hosted_app_button_container.h
new file mode 100644
index 0000000..fe13c87
--- /dev/null
+++ b/chrome/browser/ui/views/frame/hosted_app_button_container.h
@@ -0,0 +1,63 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_UI_VIEWS_FRAME_HOSTED_APP_BUTTON_CONTAINER_H_
+#define CHROME_BROWSER_UI_VIEWS_FRAME_HOSTED_APP_BUTTON_CONTAINER_H_
+
+#include <memory>
+
+#include "base/macros.h"
+#include "ui/views/controls/button/menu_button.h"
+#include "ui/views/controls/button/menu_button_listener.h"
+#include "ui/views/view.h"
+
+class AppMenu;
+class AppMenuModel;
+class BrowserView;
+
+// A container for hosted app buttons in the title bar.
+class HostedAppButtonContainer : public views::View {
+ public:
+  // |use_light| determines whether the buttons contained in the frame will use
+  // dark or light colors for drawing their button images.
+  HostedAppButtonContainer(BrowserView* browser_view, bool use_light);
+  ~HostedAppButtonContainer() override;
+
+ private:
+  FRIEND_TEST_ALL_PREFIXES(HostedAppNonClientFrameViewAshTest, HostedAppFrame);
+
+  // The 'app menu' button for the hosted app.
+  class AppMenuButton : public views::MenuButton,
+                        public views::MenuButtonListener {
+   public:
+    AppMenuButton(BrowserView* browser_view, bool use_light);
+    ~AppMenuButton() override;
+
+    // views::MenuButtonListener:
+    void OnMenuButtonClicked(views::MenuButton* source,
+                             const gfx::Point& point,
+                             const ui::Event* event) override;
+
+    AppMenu* menu() { return menu_.get(); }
+
+   private:
+    // The containing browser view.
+    BrowserView* browser_view_;
+
+    // App model and menu.
+    // Note that the menu should be destroyed before the model it uses, so the
+    // menu should be listed later.
+    std::unique_ptr<AppMenuModel> menu_model_;
+    std::unique_ptr<AppMenu> menu_;
+
+    DISALLOW_COPY_AND_ASSIGN(AppMenuButton);
+  };
+
+  // Owned by the views hierarchy.
+  AppMenuButton* app_menu_button_;
+
+  DISALLOW_COPY_AND_ASSIGN(HostedAppButtonContainer);
+};
+
+#endif  // CHROME_BROWSER_UI_VIEWS_FRAME_HOSTED_APP_BUTTON_CONTAINER_H_
diff --git a/chrome/browser/ui/views/frame/immersive_mode_controller_ash_browsertest.cc b/chrome/browser/ui/views/frame/immersive_mode_controller_ash_browsertest.cc
index 8646ac1..420a7a08 100644
--- a/chrome/browser/ui/views/frame/immersive_mode_controller_ash_browsertest.cc
+++ b/chrome/browser/ui/views/frame/immersive_mode_controller_ash_browsertest.cc
@@ -20,6 +20,7 @@
 #include "chrome/browser/ui/views/frame/top_container_view.h"
 #include "chrome/browser/ui/views/tabs/tab_strip.h"
 #include "chrome/browser/ui/views/toolbar/toolbar_view.h"
+#include "ui/aura/client/aura_constants.h"
 
 class ImmersiveModeControllerAshHostedAppBrowserTest
     : public InProcessBrowserTest {
@@ -148,12 +149,17 @@
                        ImmersiveModeStatusTabletMode) {
   ASSERT_FALSE(controller()->IsEnabled());
 
-  // Verify that after entering tablet mode, immersive mode is enabled.
+  aura::Window* window =
+      browser_view()->frame()->GetFrameView()->frame()->GetNativeWindow();
+  // Verify that after entering tablet mode, immersive mode is enabled, and the
+  // the associated window's top inset is 0 (the top of the window is not
+  // visible).
   ash::TabletModeController* tablet_mode_controller =
       ash::Shell::Get()->tablet_mode_controller();
   tablet_mode_controller->EnableTabletModeWindowManager(true);
   tablet_mode_controller->FlushForTesting();
   EXPECT_TRUE(controller()->IsEnabled());
+  EXPECT_EQ(0, window->GetProperty(aura::client::kTopViewInset));
 
   // Verify that after minimizing, immersive mode is disabled.
   browser()->window()->Minimize();
@@ -179,12 +185,14 @@
   EXPECT_TRUE(controller()->IsEnabled());
 
   // Verify that if the browser is not fullscreened, upon exiting tablet mode,
-  // immersive mode is not enabled.
+  // immersive mode is not enabled, and the associated window's top inset is
+  // greater than 0 (the top of the window is visible).
   ToggleFullscreen();
   EXPECT_TRUE(controller()->IsEnabled());
   tablet_mode_controller->EnableTabletModeWindowManager(false);
   tablet_mode_controller->FlushForTesting();
   EXPECT_FALSE(controller()->IsEnabled());
+  EXPECT_GT(window->GetProperty(aura::client::kTopViewInset), 0);
 }
 
 // Verify that the frame layout is as expected when using immersive mode in
diff --git a/chrome/browser/ui/views/global_error_bubble_view_unittest.cc b/chrome/browser/ui/views/global_error_bubble_view_unittest.cc
index 70dcb05..b33528f 100644
--- a/chrome/browser/ui/views/global_error_bubble_view_unittest.cc
+++ b/chrome/browser/ui/views/global_error_bubble_view_unittest.cc
@@ -121,7 +121,8 @@
       .WillOnce(Return(image));
   view_->GetWindowIcon();
 
-  EXPECT_TRUE(view_->ShouldShowWindowIcon());
+  EXPECT_EQ(ChromeLayoutProvider::Get()->ShouldShowWindowIcon(),
+            view_->ShouldShowWindowIcon());
 
   EXPECT_CALL(*mock_global_error_with_standard_bubble_,
               BubbleViewDidClose(nullptr));
diff --git a/chrome/browser/ui/views/page_info/page_info_bubble_view_browsertest.cc b/chrome/browser/ui/views/page_info/page_info_bubble_view_browsertest.cc
index 9369e6a..42ad3186 100644
--- a/chrome/browser/ui/views/page_info/page_info_bubble_view_browsertest.cc
+++ b/chrome/browser/ui/views/page_info/page_info_bubble_view_browsertest.cc
@@ -20,6 +20,7 @@
 #include "chrome/test/base/in_process_browser_test.h"
 #include "chrome/test/base/ui_test_utils.h"
 #include "components/safe_browsing/features.h"
+#include "content/public/browser/render_frame_host.h"
 #include "content/public/browser/web_contents.h"
 #include "content/public/test/browser_test_utils.h"
 #include "testing/gmock/include/gmock/gmock.h"
@@ -138,7 +139,11 @@
 
 IN_PROC_BROWSER_TEST_F(PageInfoBubbleViewBrowserTest, ViewSourceURL) {
   ui_test_utils::NavigateToURL(browser(), GURL(url::kAboutBlankURL));
-  chrome::ViewSelectedSource(browser());
+  browser()
+      ->tab_strip_model()
+      ->GetActiveWebContents()
+      ->GetMainFrame()
+      ->ViewSource();
   OpenPageInfoBubble(browser());
   EXPECT_EQ(PageInfoBubbleView::BUBBLE_INTERNAL_PAGE,
             PageInfoBubbleView::GetShownBubbleType());
diff --git a/chrome/browser/ui/views/profiles/user_manager_view.cc b/chrome/browser/ui/views/profiles/user_manager_view.cc
index 71c0d33..8b5d270 100644
--- a/chrome/browser/ui/views/profiles/user_manager_view.cc
+++ b/chrome/browser/ui/views/profiles/user_manager_view.cc
@@ -222,7 +222,7 @@
   // Load the re-auth URL, prepopulated with the user's email address.
   // Add the index of the profile to the URL so that the inline login page
   // knows which profile to load and update the credentials.
-  GURL url = signin::GetReauthURLWithEmail(
+  GURL url = signin::GetReauthURLWithEmailForDialog(
       signin_metrics::AccessPoint::ACCESS_POINT_USER_MANAGER, reason, email);
   instance_->ShowDialog(browser_context, email, url);
 }
@@ -234,9 +234,9 @@
   if (!UserManager::IsShowing())
     return;
   instance_->SetSigninProfilePath(profile_path);
-  GURL url = signin::GetPromoURL(
+  GURL url = signin::GetPromoURLForDialog(
       signin_metrics::AccessPoint::ACCESS_POINT_USER_MANAGER,
-      signin_metrics::Reason::REASON_SIGNIN_PRIMARY_ACCOUNT, true, true);
+      signin_metrics::Reason::REASON_SIGNIN_PRIMARY_ACCOUNT, true);
   instance_->ShowDialog(browser_context, std::string(), url);
 }
 
diff --git a/chrome/browser/ui/views/status_bubble_views.cc b/chrome/browser/ui/views/status_bubble_views.cc
index c3dd3cd7..4396cd4 100644
--- a/chrome/browser/ui/views/status_bubble_views.cc
+++ b/chrome/browser/ui/views/status_bubble_views.cc
@@ -40,12 +40,9 @@
 #include "url/gurl.h"
 
 #if defined(OS_CHROMEOS)
-#include "ash/shell.h"
-#include "ash/wm/window_state.h"
-#endif
-
-#if defined(USE_AURA)
-#include "services/ui/public/cpp/property_type_converters.h"  // nogncheck
+#include "ash/shell.h"                                           // mash-ok
+#include "ash/wm/window_state.h"                                 // mash-ok
+#include "services/ui/public/cpp/property_type_converters.h"     // nogncheck
 #include "services/ui/public/interfaces/window_manager.mojom.h"  // nogncheck
 #endif
 
@@ -657,7 +654,7 @@
     params.parent = frame->GetNativeView();
     params.context = frame->GetNativeWindow();
     params.name = "StatusBubble";
-#if defined(USE_AURA)
+#if defined(OS_CHROMEOS)
     params.mus_properties
         [ui::mojom::WindowManager::kWindowIgnoredByShelf_InitProperty] =
         mojo::ConvertTo<std::vector<uint8_t>>(true);
@@ -668,12 +665,10 @@
     popup_->SetOpacity(0.f);
     popup_->SetContentsView(view_);
 #if defined(OS_CHROMEOS)
+    // Mash is handled via mus_properties.
     if (ash::Shell::HasInstance()) {
       ash::wm::GetWindowState(popup_->GetNativeWindow())
           ->set_ignored_by_shelf(true);
-    } else {
-      // TODO: need mash implementation.
-      NOTIMPLEMENTED();
     }
 #endif
     RepositionPopup();
diff --git a/chrome/browser/ui/webui/chromeos/internet_config_dialog.cc b/chrome/browser/ui/webui/chromeos/internet_config_dialog.cc
index 75fdc38..f4cdfa9f 100644
--- a/chrome/browser/ui/webui/chromeos/internet_config_dialog.cc
+++ b/chrome/browser/ui/webui/chromeos/internet_config_dialog.cc
@@ -24,6 +24,10 @@
 
 namespace {
 
+// Width matches the internet config dialog in Settings UI (including margins).
+constexpr int kInternetConfigDialogWidth = 500;
+constexpr int kInternetConfigDialogHeight = 480;
+
 void AddInternetStrings(content::WebUIDataSource* html_source) {
   // Add default strings first.
   chromeos::network_element::AddLocalizedStrings(html_source);
@@ -35,6 +39,7 @@
     const char* name;
     int id;
   } localized_strings[] = {
+      {"internetJoinType", IDS_SETTINGS_INTERNET_JOIN_TYPE},
       {"networkButtonConnect", IDS_SETTINGS_INTERNET_BUTTON_CONNECT},
       {"cancel", IDS_CANCEL},
       {"save", IDS_SAVE},
@@ -72,6 +77,10 @@
 
 InternetConfigDialog::~InternetConfigDialog() {}
 
+void InternetConfigDialog::GetDialogSize(gfx::Size* size) const {
+  size->SetSize(kInternetConfigDialogWidth, kInternetConfigDialogHeight);
+}
+
 std::string InternetConfigDialog::GetDialogArgs() const {
   base::DictionaryValue args;
   args.SetKey("type", base::Value(network_type_));
diff --git a/chrome/browser/ui/webui/chromeos/internet_config_dialog.h b/chrome/browser/ui/webui/chromeos/internet_config_dialog.h
index 4a912381..8c3d0b8 100644
--- a/chrome/browser/ui/webui/chromeos/internet_config_dialog.h
+++ b/chrome/browser/ui/webui/chromeos/internet_config_dialog.h
@@ -29,6 +29,7 @@
   ~InternetConfigDialog() override;
 
   // ui::WebDialogDelegate
+  void GetDialogSize(gfx::Size* size) const override;
   std::string GetDialogArgs() const override;
 
  private:
diff --git a/chrome/browser/ui/webui/chromeos/network_element_localized_strings_provider.cc b/chrome/browser/ui/webui/chromeos/network_element_localized_strings_provider.cc
index bc5ffcc..86ac00c 100644
--- a/chrome/browser/ui/webui/chromeos/network_element_localized_strings_provider.cc
+++ b/chrome/browser/ui/webui/chromeos/network_element_localized_strings_provider.cc
@@ -200,6 +200,30 @@
       {"networkProxyTypePac", IDS_SETTINGS_INTERNET_NETWORK_PROXY_TYPE_PAC},
       {"networkProxyTypeWpad", IDS_SETTINGS_INTERNET_NETWORK_PROXY_TYPE_WPAD},
       {"networkProxyUseSame", IDS_SETTINGS_INTERNET_NETWORK_PROXY_USE_SAME},
+      {"networkSimCardLocked", IDS_SETTINGS_INTERNET_NETWORK_SIM_CARD_LOCKED},
+      {"networkSimCardMissing", IDS_SETTINGS_INTERNET_NETWORK_SIM_CARD_MISSING},
+      {"networkSimChange", IDS_SETTINGS_INTERNET_NETWORK_SIM_BUTTON_CHANGE},
+      {"networkSimChangePin", IDS_SETTINGS_INTERNET_NETWORK_SIM_CHANGE_PIN},
+      {"networkSimChangePinTitle",
+       IDS_SETTINGS_INTERNET_NETWORK_SIM_CHANGE_PIN_TITLE},
+      {"networkSimEnter", IDS_SETTINGS_INTERNET_NETWORK_SIM_BUTTON_ENTER},
+      {"networkSimEnterNewPin",
+       IDS_SETTINGS_INTERNET_NETWORK_SIM_ENTER_NEW_PIN},
+      {"networkSimEnterOldPin",
+       IDS_SETTINGS_INTERNET_NETWORK_SIM_ENTER_OLD_PIN},
+      {"networkSimEnterPin", IDS_SETTINGS_INTERNET_NETWORK_SIM_ENTER_PIN},
+      {"networkSimEnterPinTitle",
+       IDS_SETTINGS_INTERNET_NETWORK_SIM_ENTER_PIN_TITLE},
+      {"networkSimEnterPuk", IDS_SETTINGS_INTERNET_NETWORK_SIM_ENTER_PUK},
+      {"networkSimLockEnable", IDS_SETTINGS_INTERNET_NETWORK_SIM_LOCK_ENABLE},
+      {"networkSimLockedTitle", IDS_SETTINGS_INTERNET_NETWORK_SIM_LOCKED_TITLE},
+      {"networkSimLockedWarning",
+       IDS_SETTINGS_INTERNET_NETWORK_SIM_LOCKED_WARNING},
+      {"networkSimReEnterNewPin",
+       IDS_SETTINGS_INTERNET_NETWORK_SIM_RE_ENTER_NEW_PIN},
+      {"networkSimReEnterNewPin",
+       IDS_SETTINGS_INTERNET_NETWORK_SIM_RE_ENTER_NEW_PIN},
+      {"networkSimUnlock", IDS_SETTINGS_INTERNET_NETWORK_SIM_BUTTON_UNLOCK},
       {"networkAccessPoint", IDS_SETTINGS_INTERNET_NETWORK_ACCESS_POINT},
       {"networkChooseMobile", IDS_SETTINGS_INTERNET_NETWORK_CHOOSE_MOBILE},
       {"networkCellularScan", IDS_SETTINGS_INTERNET_NETWORK_CELLULAR_SCAN},
diff --git a/chrome/browser/ui/webui/chromeos/user_image_source.cc b/chrome/browser/ui/webui/chromeos/user_image_source.cc
index 5cf7577..8e6ac99b2 100644
--- a/chrome/browser/ui/webui/chromeos/user_image_source.cc
+++ b/chrome/browser/ui/webui/chromeos/user_image_source.cc
@@ -131,8 +131,16 @@
 
   if (user) {
     if (user->has_image_bytes()) {
-      return GetUserImageFrame(user->image_bytes(), user->image_format(),
-                               frame);
+      if (user->image_format() == user_manager::UserImage::FORMAT_PNG) {
+        return GetUserImageFrame(user->image_bytes(), user->image_format(),
+                                 frame);
+      } else {
+        scoped_refptr<base::RefCountedBytes> data(new base::RefCountedBytes);
+        gfx::PNGCodec::EncodeBGRASkBitmap(*user->GetImage().bitmap(),
+                                          false /* discard transparency */,
+                                          &data->data());
+        return data;
+      }
     }
     if (user->image_is_stub()) {
       return LoadUserImageFrameForScaleFactor(IDR_LOGIN_DEFAULT_USER, frame,
diff --git a/chrome/browser/ui/webui/extensions/extensions_ui.cc b/chrome/browser/ui/webui/extensions/extensions_ui.cc
index 11f6613..1a097d14 100644
--- a/chrome/browser/ui/webui/extensions/extensions_ui.cc
+++ b/chrome/browser/ui/webui/extensions/extensions_ui.cc
@@ -166,8 +166,13 @@
                              IDS_MD_EXTENSIONS_DEPENDENT_ENTRY);
   source->AddLocalizedString("itemDetails", IDS_MD_EXTENSIONS_ITEM_DETAILS);
   source->AddLocalizedString("itemErrors", IDS_MD_EXTENSIONS_ITEM_ERRORS);
+  source->AddLocalizedString("appIcon", IDS_MD_EXTENSIONS_APP_ICON);
+  source->AddLocalizedString("extensionIcon", IDS_MD_EXTENSIONS_EXTENSION_ICON);
   source->AddLocalizedString("itemIdHeading",
                              IDS_MD_EXTENSIONS_ITEM_ID_HEADING);
+  source->AddLocalizedString("extensionEnabled",
+                             IDS_MD_EXTENSIONS_EXTENSION_ENABLED);
+  source->AddLocalizedString("appEnabled", IDS_MD_EXTENSIONS_APP_ENABLED);
   source->AddLocalizedString("itemOff", IDS_MD_EXTENSIONS_ITEM_OFF);
   source->AddLocalizedString("itemOn", IDS_MD_EXTENSIONS_ITEM_ON);
   source->AddLocalizedString("itemOptions", IDS_MD_EXTENSIONS_ITEM_OPTIONS);
diff --git a/chrome/browser/ui/webui/settings/chromeos/cups_printers_handler.cc b/chrome/browser/ui/webui/settings/chromeos/cups_printers_handler.cc
index bf2a61c..de59cbdc 100644
--- a/chrome/browser/ui/webui/settings/chromeos/cups_printers_handler.cc
+++ b/chrome/browser/ui/webui/settings/chromeos/cups_printers_handler.cc
@@ -529,7 +529,8 @@
   CHECK(args->GetDictionary(0, &printer_dict));
 
   std::unique_ptr<Printer> printer = DictToPrinter(*printer_dict);
-  if (!printer) {
+  PrinterUri uri;
+  if (!printer || !ParseUri(printer->uri(), &uri)) {
     LOG(ERROR) << "Failed to parse printer";
     OnAddPrinterError(PrinterSetupResult::kFatalError);
     return;
diff --git a/chrome/browser/ui/webui/settings/chromeos/device_power_handler.cc b/chrome/browser/ui/webui/settings/chromeos/device_power_handler.cc
index be63133..3373a7cf 100644
--- a/chrome/browser/ui/webui/settings/chromeos/device_power_handler.cc
+++ b/chrome/browser/ui/webui/settings/chromeos/device_power_handler.cc
@@ -145,8 +145,9 @@
 }
 
 void PowerHandler::PowerManagerRestarted() {
-  DBusThreadManager::Get()->GetPowerManagerClient()->GetSwitchStates(base::Bind(
-      &PowerHandler::OnGotSwitchStates, weak_ptr_factory_.GetWeakPtr()));
+  DBusThreadManager::Get()->GetPowerManagerClient()->GetSwitchStates(
+      base::BindOnce(&PowerHandler::OnGotSwitchStates,
+                     weak_ptr_factory_.GetWeakPtr()));
 }
 
 void PowerHandler::LidEventReceived(PowerManagerClient::LidState state,
@@ -353,9 +354,10 @@
 }
 
 void PowerHandler::OnGotSwitchStates(
-    PowerManagerClient::LidState lid_state,
-    PowerManagerClient::TabletMode tablet_mode) {
-  lid_state_ = lid_state;
+    base::Optional<PowerManagerClient::SwitchStates> result) {
+  if (!result.has_value())
+    return;
+  lid_state_ = result->lid_state;
   SendPowerManagementSettings(false /* force */);
 }
 
diff --git a/chrome/browser/ui/webui/settings/chromeos/device_power_handler.h b/chrome/browser/ui/webui/settings/chromeos/device_power_handler.h
index 6839817..b30b3f2 100644
--- a/chrome/browser/ui/webui/settings/chromeos/device_power_handler.h
+++ b/chrome/browser/ui/webui/settings/chromeos/device_power_handler.h
@@ -10,6 +10,7 @@
 #include "ash/system/power/power_status.h"
 #include "base/macros.h"
 #include "base/memory/weak_ptr.h"
+#include "base/optional.h"
 #include "base/scoped_observer.h"
 #include "base/strings/string16.h"
 #include "chrome/browser/ui/webui/settings/settings_page_ui_handler.h"
@@ -109,8 +110,8 @@
   void SendPowerManagementSettings(bool force);
 
   // Callback used to receive switch states from PowerManagerClient.
-  void OnGotSwitchStates(PowerManagerClient::LidState lid_state,
-                         PowerManagerClient::TabletMode tablet_mode);
+  void OnGotSwitchStates(
+      base::Optional<PowerManagerClient::SwitchStates> result);
 
   PrefService* prefs_;              // Not owned.
   ash::PowerStatus* power_status_;  // Not owned.
diff --git a/chrome/browser/ui/webui/settings/md_settings_localized_strings_provider.cc b/chrome/browser/ui/webui/settings/md_settings_localized_strings_provider.cc
index ff5c699..e523aeb 100644
--- a/chrome/browser/ui/webui/settings/md_settings_localized_strings_provider.cc
+++ b/chrome/browser/ui/webui/settings/md_settings_localized_strings_provider.cc
@@ -898,10 +898,11 @@
       {"internetAddThirdPartyVPN", IDS_SETTINGS_INTERNET_ADD_THIRD_PARTY_VPN},
       {"internetAddVPN", IDS_SETTINGS_INTERNET_ADD_VPN},
       {"internetAddWiFi", IDS_SETTINGS_INTERNET_ADD_WIFI},
-      {"internetConfigTitle", IDS_SETTINGS_INTERNET_CONFIG},
+      {"internetConfigName", IDS_SETTINGS_INTERNET_CONFIG_NAME},
       {"internetDetailPageTitle", IDS_SETTINGS_INTERNET_DETAIL},
       {"internetDeviceEnabling", IDS_SETTINGS_INTERNET_DEVICE_ENABLING},
       {"internetDeviceInitializing", IDS_SETTINGS_INTERNET_DEVICE_INITIALIZING},
+      {"internetJoinType", IDS_SETTINGS_INTERNET_JOIN_TYPE},
       {"internetKnownNetworksPageTitle", IDS_SETTINGS_INTERNET_KNOWN_NETWORKS},
       {"internetMobileSearching", IDS_SETTINGS_INTERNET_MOBILE_SEARCH},
       {"internetNoNetworks", IDS_SETTINGS_INTERNET_NO_NETWORKS},
@@ -954,30 +955,6 @@
       {"networkSectionProxyExpandA11yLabel",
        IDS_SETTINGS_INTERNET_NETWORK_SECTION_PROXY_ACCESSIBILITY_LABEL},
       {"networkShared", IDS_SETTINGS_INTERNET_NETWORK_SHARED},
-      {"networkSimCardLocked", IDS_SETTINGS_INTERNET_NETWORK_SIM_CARD_LOCKED},
-      {"networkSimCardMissing", IDS_SETTINGS_INTERNET_NETWORK_SIM_CARD_MISSING},
-      {"networkSimChange", IDS_SETTINGS_INTERNET_NETWORK_SIM_BUTTON_CHANGE},
-      {"networkSimChangePin", IDS_SETTINGS_INTERNET_NETWORK_SIM_CHANGE_PIN},
-      {"networkSimChangePinTitle",
-       IDS_SETTINGS_INTERNET_NETWORK_SIM_CHANGE_PIN_TITLE},
-      {"networkSimEnter", IDS_SETTINGS_INTERNET_NETWORK_SIM_BUTTON_ENTER},
-      {"networkSimEnterNewPin",
-       IDS_SETTINGS_INTERNET_NETWORK_SIM_ENTER_NEW_PIN},
-      {"networkSimEnterOldPin",
-       IDS_SETTINGS_INTERNET_NETWORK_SIM_ENTER_OLD_PIN},
-      {"networkSimEnterPin", IDS_SETTINGS_INTERNET_NETWORK_SIM_ENTER_PIN},
-      {"networkSimEnterPinTitle",
-       IDS_SETTINGS_INTERNET_NETWORK_SIM_ENTER_PIN_TITLE},
-      {"networkSimEnterPuk", IDS_SETTINGS_INTERNET_NETWORK_SIM_ENTER_PUK},
-      {"networkSimLockEnable", IDS_SETTINGS_INTERNET_NETWORK_SIM_LOCK_ENABLE},
-      {"networkSimLockedTitle", IDS_SETTINGS_INTERNET_NETWORK_SIM_LOCKED_TITLE},
-      {"networkSimLockedWarning",
-       IDS_SETTINGS_INTERNET_NETWORK_SIM_LOCKED_WARNING},
-      {"networkSimReEnterNewPin",
-       IDS_SETTINGS_INTERNET_NETWORK_SIM_RE_ENTER_NEW_PIN},
-      {"networkSimReEnterNewPin",
-       IDS_SETTINGS_INTERNET_NETWORK_SIM_RE_ENTER_NEW_PIN},
-      {"networkSimUnlock", IDS_SETTINGS_INTERNET_NETWORK_SIM_BUTTON_UNLOCK},
       {"networkVpnBuiltin", IDS_NETWORK_TYPE_VPN_BUILTIN},
       {"tetherConnectionDialogTitle",
        IDS_SETTINGS_INTERNET_TETHER_CONNECTION_DIALOG_TITLE},
diff --git a/chrome/browser/ui/webui/settings/people_handler.cc b/chrome/browser/ui/webui/settings/people_handler.cc
index 75343088..0126d1c8 100644
--- a/chrome/browser/ui/webui/settings/people_handler.cc
+++ b/chrome/browser/ui/webui/settings/people_handler.cc
@@ -297,7 +297,7 @@
           BrowserWindow::AVATAR_BUBBLE_MODE_REAUTH,
           signin::ManageAccountsParams(), access_point, false);
     } else {
-      url = signin::GetReauthURL(
+      url = signin::GetReauthURLForTab(
           access_point, signin_metrics::Reason::REASON_REAUTHENTICATION,
           browser->profile(), error_controller->error_account_id());
     }
@@ -307,7 +307,7 @@
           BrowserWindow::AVATAR_BUBBLE_MODE_SIGNIN,
           signin::ManageAccountsParams(), access_point, false);
     } else {
-      url = signin::GetPromoURL(
+      url = signin::GetPromoURLForTab(
           access_point, signin_metrics::Reason::REASON_SIGNIN_PRIMARY_ACCOUNT,
           true);
     }
diff --git a/chrome/browser/ui/webui/signin/inline_login_handler_impl.cc b/chrome/browser/ui/webui/signin/inline_login_handler_impl.cc
index dea7116b..157556e 100644
--- a/chrome/browser/ui/webui/signin/inline_login_handler_impl.cc
+++ b/chrome/browser/ui/webui/signin/inline_login_handler_impl.cc
@@ -183,8 +183,9 @@
         auth_code, signin_scoped_device_id);
   } else {
     DCHECK(!session_index_.empty());
-    gaia_auth_fetcher_.StartCookieForOAuthLoginTokenExchangeWithDeviceId(
-        session_index_, signin_scoped_device_id);
+    gaia_auth_fetcher_
+        .DeprecatedStartCookieForOAuthLoginTokenExchangeWithDeviceId(
+            session_index_, signin_scoped_device_id);
   }
 }
 
@@ -565,6 +566,8 @@
 
   content::WebContentsObserver::Observe(contents);
   LogHistogramValue(signin_metrics::HISTOGRAM_SHOWN);
+  UMA_HISTOGRAM_BOOLEAN("Signin.UseDeprecatedGaiaSigninEndpoint",
+                        is_constrained == "1");
 }
 
 void InlineLoginHandlerImpl::CompleteLogin(const base::ListValue* args) {
diff --git a/chrome/browser/ui/webui/signin/inline_login_ui_browsertest.cc b/chrome/browser/ui/webui/signin/inline_login_ui_browsertest.cc
index 6395eff..af9d3bf 100644
--- a/chrome/browser/ui/webui/signin/inline_login_ui_browsertest.cc
+++ b/chrome/browser/ui/webui/signin/inline_login_ui_browsertest.cc
@@ -114,7 +114,7 @@
 }
 
 GURL GetSigninPromoURL() {
-  return signin::GetPromoURL(
+  return signin::GetPromoURLForTab(
       signin_metrics::AccessPoint::ACCESS_POINT_START_PAGE,
       signin_metrics::Reason::REASON_SIGNIN_PRIMARY_ACCOUNT, false);
 }
diff --git a/chrome/browser/ui/webui/signin/login_ui_test_utils.cc b/chrome/browser/ui/webui/signin/login_ui_test_utils.cc
index 2a10ba6..dc36720 100644
--- a/chrome/browser/ui/webui/signin/login_ui_test_utils.cc
+++ b/chrome/browser/ui/webui/signin/login_ui_test_utils.cc
@@ -254,7 +254,8 @@
       SigninTrackerFactory::CreateForProfile(browser->profile(),
                                              &signin_observer);
 
-  GURL signin_url = signin::GetPromoURL(access_point, signin_reason, false);
+  GURL signin_url =
+      signin::GetPromoURLForTab(access_point, signin_reason, false);
   DVLOG(1) << "Navigating to " << signin_url;
   // For some tests, the window is not shown yet and this might be the first tab
   // navigation, so GetActiveWebContents() for CURRENT_TAB is NULL. That's why
diff --git a/chrome/browser/ui/webui/webui_webview_browsertest.cc b/chrome/browser/ui/webui/webui_webview_browsertest.cc
index 9b7dc79a..ec4a4ee3 100644
--- a/chrome/browser/ui/webui/webui_webview_browsertest.cc
+++ b/chrome/browser/ui/webui/webui_webview_browsertest.cc
@@ -123,7 +123,7 @@
 #if defined(OS_CHROMEOS)
     return GURL(chrome::kChromeUIOobeURL).Resolve("/login");
 #else
-    return GURL(signin::GetPromoURL(
+    return GURL(signin::GetPromoURLForTab(
         signin_metrics::AccessPoint::ACCESS_POINT_START_PAGE,
         signin_metrics::Reason::REASON_SIGNIN_PRIMARY_ACCOUNT, false));
 #endif
diff --git a/chrome/browser/vr/elements/linear_layout.cc b/chrome/browser/vr/elements/linear_layout.cc
index 3aeee89..6a491532 100644
--- a/chrome/browser/vr/elements/linear_layout.cc
+++ b/chrome/browser/vr/elements/linear_layout.cc
@@ -8,10 +8,8 @@
 
 namespace {
 
-float GetExtent(const UiElement& element, LinearLayout::Direction direction) {
-  return (direction == LinearLayout::kLeft || direction == LinearLayout::kRight)
-             ? element.size().width()
-             : element.size().height();
+float GetExtent(const UiElement& element, bool horizontal) {
+  return horizontal ? element.size().width() : element.size().height();
 }
 
 }  // namespace
@@ -20,10 +18,16 @@
 LinearLayout::~LinearLayout() {}
 
 void LinearLayout::LayOutChildren() {
+  bool horizontal =
+      direction_ == LinearLayout::kLeft || direction_ == LinearLayout::kRight;
   float total_extent = -margin_;
+  float minor_extent = 0;
+
   for (auto& child : children()) {
-    if (child->requires_layout())
-      total_extent += GetExtent(*child, direction_) + margin_;
+    if (child->requires_layout()) {
+      total_extent += GetExtent(*child, horizontal) + margin_;
+      minor_extent = std::max(minor_extent, GetExtent(*child, !horizontal));
+    }
   }
 
   float x_factor = 0.f;
@@ -47,11 +51,14 @@
   for (auto& child : children()) {
     if (!child->requires_layout())
       continue;
-    float extent = GetExtent(*child, direction_);
+    float extent = GetExtent(*child, horizontal);
     float offset = cumulative_offset + 0.5 * extent;
     child->SetLayoutOffset(offset * x_factor, offset * y_factor);
     cumulative_offset += extent + margin_;
   }
+
+  SetSize(horizontal ? total_extent : minor_extent,
+          !horizontal ? total_extent : minor_extent);
 }
 
 }  // namespace vr
diff --git a/chrome/browser/vr/elements/linear_layout_unittest.cc b/chrome/browser/vr/elements/linear_layout_unittest.cc
index f9f6aca..2d3d9ec 100644
--- a/chrome/browser/vr/elements/linear_layout_unittest.cc
+++ b/chrome/browser/vr/elements/linear_layout_unittest.cc
@@ -5,10 +5,26 @@
 #include "chrome/browser/vr/elements/linear_layout.h"
 
 #include "base/memory/ptr_util.h"
+#include "chrome/browser/vr/test/animation_utils.h"
+#include "chrome/browser/vr/test/constants.h"
+#include "chrome/browser/vr/ui_scene.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
 namespace vr {
 
+namespace {
+
+// Helper class supplying convenient layout-related accessors.
+class TestElement : public UiElement {
+ public:
+  float x() const { return world_space_transform().To2dTranslation().x(); }
+  float y() const { return world_space_transform().To2dTranslation().y(); }
+  float local_x() const { return LocalTransform().To2dTranslation().x(); }
+  float local_y() const { return LocalTransform().To2dTranslation().y(); }
+};
+
+}  // namespace
+
 TEST(LinearLayout, HorizontalLayout) {
   LinearLayout layout(LinearLayout::kRight);
   layout.set_margin(10);
@@ -53,37 +69,83 @@
 TEST(LinearLayout, Orientations) {
   LinearLayout layout(LinearLayout::kUp);
 
+  TestElement* rect;
   for (int i = 0; i < 2; i++) {
-    auto element = base::MakeUnique<UiElement>();
+    auto element = base::MakeUnique<TestElement>();
+    rect = element.get();
     element->SetSize(10, 10);
     element->SetVisible(true);
     layout.AddChild(std::move(element));
   }
-  UiElement* rect = layout.children().back().get();
-  gfx::Vector2dF position;
 
   layout.set_direction(LinearLayout::kUp);
   layout.LayOutChildren();
-  position = rect->LocalTransform().To2dTranslation();
-  EXPECT_FLOAT_EQ(0.0f, position.x());
-  EXPECT_FLOAT_EQ(5.0f, position.y());
+  EXPECT_FLOAT_EQ(0.0f, rect->local_x());
+  EXPECT_FLOAT_EQ(5.0f, rect->local_y());
 
   layout.set_direction(LinearLayout::kDown);
   layout.LayOutChildren();
-  position = rect->LocalTransform().To2dTranslation();
-  EXPECT_FLOAT_EQ(0.0f, position.x());
-  EXPECT_FLOAT_EQ(-5.0f, position.y());
+  EXPECT_FLOAT_EQ(0.0f, rect->local_x());
+  EXPECT_FLOAT_EQ(-5.0f, rect->local_y());
 
   layout.set_direction(LinearLayout::kLeft);
   layout.LayOutChildren();
-  position = rect->LocalTransform().To2dTranslation();
-  EXPECT_FLOAT_EQ(-5.0f, position.x());
-  EXPECT_FLOAT_EQ(0.0f, position.y());
+  EXPECT_FLOAT_EQ(-5.0f, rect->local_x());
+  EXPECT_FLOAT_EQ(0.0f, rect->local_y());
 
   layout.set_direction(LinearLayout::kRight);
   layout.LayOutChildren();
-  position = rect->LocalTransform().To2dTranslation();
-  EXPECT_FLOAT_EQ(5.0f, position.x());
+  EXPECT_FLOAT_EQ(5.0f, rect->local_x());
+  EXPECT_FLOAT_EQ(0.0f, rect->local_y());
+}
+
+TEST(LinearLayout, NestedLayouts) {
+  // Build a tree of elements, including nested layouts:
+  //   parent_layout
+  //     child_layout
+  //       rect_a
+  //       rect_b
+  //     rect_c
+  auto parent_layout = base::MakeUnique<LinearLayout>(LinearLayout::kDown);
+  UiElement* p_parent_layout = parent_layout.get();
+  parent_layout->SetVisible(true);
+  auto child_layout = base::MakeUnique<LinearLayout>(LinearLayout::kDown);
+  UiElement* p_child_layout = child_layout.get();
+  child_layout->SetVisible(true);
+  auto rect_a = base::MakeUnique<TestElement>();
+  TestElement* p_rect_a = rect_a.get();
+  rect_a->SetVisible(true);
+  rect_a->SetSize(10, 10);
+  child_layout->AddChild(std::move(rect_a));
+  auto rect_b = base::MakeUnique<TestElement>();
+  TestElement* p_rect_b = rect_b.get();
+  rect_b->SetVisible(true);
+  rect_b->SetSize(10, 10);
+  child_layout->AddChild(std::move(rect_b));
+  auto rect_c = base::MakeUnique<TestElement>();
+  TestElement* p_rect_c = rect_c.get();
+  rect_c->SetVisible(true);
+  rect_c->SetSize(999, 10);
+  parent_layout->AddChild(std::move(child_layout));
+  parent_layout->AddChild(std::move(rect_c));
+
+  auto scene = base::MakeUnique<UiScene>();
+  scene->AddUiElement(kRoot, std::move(parent_layout));
+  scene->OnBeginFrame(MicrosecondsToTicks(1), kForwardVector);
+
+  // Ensure that layouts expand to include the cumulative size of children.
+  EXPECT_FLOAT_EQ(p_parent_layout->size().width(), 999.f);
+  EXPECT_FLOAT_EQ(p_parent_layout->size().height(), 30.f);
+  EXPECT_FLOAT_EQ(p_child_layout->size().width(), 10.f);
+  EXPECT_FLOAT_EQ(p_child_layout->size().height(), 20.f);
+
+  // Ensure that children are at correct positions.
+  EXPECT_FLOAT_EQ(p_rect_a->x(), 0);
+  EXPECT_FLOAT_EQ(p_rect_a->y(), 10);
+  EXPECT_FLOAT_EQ(p_rect_b->x(), 0);
+  EXPECT_FLOAT_EQ(p_rect_b->y(), 0);
+  EXPECT_FLOAT_EQ(p_rect_c->x(), 0);
+  EXPECT_FLOAT_EQ(p_rect_c->y(), -10);
 }
 
 }  // namespace vr
diff --git a/chrome/browser/vr/ui_scene.cc b/chrome/browser/vr/ui_scene.cc
index 082bf7a..674768d 100644
--- a/chrome/browser/vr/ui_scene.cc
+++ b/chrome/browser/vr/ui_scene.cc
@@ -7,6 +7,7 @@
 #include <string>
 #include <utility>
 
+#include "base/containers/adapters.h"
 #include "base/memory/ptr_util.h"
 #include "base/time/time.h"
 #include "base/trace_event/trace_event.h"
@@ -125,8 +126,11 @@
   {
     TRACE_EVENT0("gpu", "UiScene::OnBeginFrame.UpdateLayout");
 
-    // Update layout, which depends on size.
-    for (auto& element : *root_element_) {
+    // Update layout, which depends on size. Note that the layout phase changes
+    // the size of layout-type elements, as they adjust to fit the cumulative
+    // size of their children. This must be done in reverse order, such that
+    // children are correctly sized when laid out by their parent.
+    for (auto& element : base::Reversed(*root_element_)) {
       element.LayOutChildren();
       element.set_update_phase(UiElement::kUpdatedLayout);
     }
diff --git a/chrome/browser/vr/ui_scene_manager.cc b/chrome/browser/vr/ui_scene_manager.cc
index 943c2e18..ec4e622 100644
--- a/chrome/browser/vr/ui_scene_manager.cc
+++ b/chrome/browser/vr/ui_scene_manager.cc
@@ -914,8 +914,6 @@
         -kCloseButtonDistance);
     close_button_->SetSize(kCloseButtonWidth, kCloseButtonHeight);
   }
-  scene_->set_background_distance(kContentDistance *
-                                  kBackgroundDistanceMultiplier);
 
   scene_->root_element().SetMode(mode());
 
diff --git a/chrome/common/chrome_features.cc b/chrome/common/chrome_features.cc
index 2484b51..fa772d3 100644
--- a/chrome/common/chrome_features.cc
+++ b/chrome/common/chrome_features.cc
@@ -405,6 +405,12 @@
 const base::Feature kPwaMinimalUi{"PwaMinimalUi",
                                   base::FEATURE_ENABLED_BY_DEFAULT};
 
+#if !defined(OS_ANDROID)
+const base::Feature kRemoveUsageOfDeprecatedGaiaSigninEndpoint{
+    "RemoveUsageOfDeprecatedGaiaSigninEndpoint",
+    base::FEATURE_DISABLED_BY_DEFAULT};
+#endif
+
 #if defined(OS_CHROMEOS)
 // Runtime flag that indicates whether this leak detector should be enabled in
 // the current instance of Chrome.
diff --git a/chrome/common/chrome_features.h b/chrome/common/chrome_features.h
index f9b6150..67215c2 100644
--- a/chrome/common/chrome_features.h
+++ b/chrome/common/chrome_features.h
@@ -211,6 +211,10 @@
 
 extern const base::Feature kPwaMinimalUi;
 
+#if !defined(OS_ANDROID)
+extern const base::Feature kRemoveUsageOfDeprecatedGaiaSigninEndpoint;
+#endif
+
 #if defined(OS_CHROMEOS)
 extern const base::Feature kRuntimeMemoryLeakDetector;
 #endif  // defined(OS_CHROMEOS)
diff --git a/chrome/common/chrome_switches.cc b/chrome/common/chrome_switches.cc
index 3e02b16..498e5cd 100644
--- a/chrome/common/chrome_switches.cc
+++ b/chrome/common/chrome_switches.cc
@@ -128,6 +128,10 @@
 // service or register proxy for autostart.
 const char kCloudPrintSetupProxy[]          = "cloud-print-setup-proxy";
 
+// Enables committed error pages instead of transient navigation entries for
+// interstitial error pages (e.g. certificate errors).
+const char kCommittedInterstitials[] = "committed-interstitials";
+
 // Comma-separated list of BrowserThreads that cause browser process to crash
 // if the given browser thread is not responsive. UI,IO,DB,FILE,CACHE are the
 // list of BrowserThreads that are supported.
diff --git a/chrome/common/chrome_switches.h b/chrome/common/chrome_switches.h
index 2b95b746..f14eede9 100644
--- a/chrome/common/chrome_switches.h
+++ b/chrome/common/chrome_switches.h
@@ -58,6 +58,7 @@
 extern const char kCloudPrintPrintTicket[];
 extern const char kCloudPrintServiceProcess[];
 extern const char kCloudPrintSetupProxy[];
+extern const char kCommittedInterstitials[];
 extern const char kCrashOnHangThreads[];
 extern const char kCreateBrowserOnStartupForTests[];
 extern const char kCustomDevtoolsFrontend[];
diff --git a/chrome/common/extensions/docs/templates/articles/experimental_webRequest.html b/chrome/common/extensions/docs/templates/articles/experimental_webRequest.html
index 4439799..53bd46b6 100644
--- a/chrome/common/extensions/docs/templates/articles/experimental_webRequest.html
+++ b/chrome/common/extensions/docs/templates/articles/experimental_webRequest.html
@@ -8,8 +8,3 @@
 <blockquote>
 <a href="webRequest">chrome.webRequest</a>
 </blockquote>
-
-<p>
-What you see below are early outcomes of the plan to implement a declarative
-version of the WebRequest API. Please ignore this until we give notice.
-</p>
diff --git a/chrome/common/extensions/docs/templates/articles/match_patterns.html b/chrome/common/extensions/docs/templates/articles/match_patterns.html
index 6dcb1c68..b37b462 100644
--- a/chrome/common/extensions/docs/templates/articles/match_patterns.html
+++ b/chrome/common/extensions/docs/templates/articles/match_patterns.html
@@ -118,8 +118,8 @@
   </td>
 
   <td>
-    http://www.google.com/foo/baz/bar<br>
-    http://docs.google.com/foobar
+    https://www.google.com/foo/baz/bar<br>
+    https://docs.google.com/foobar
   </td>
 </tr>
 
diff --git a/chrome/common/media_router/media_route.cc b/chrome/common/media_router/media_route.cc
index 4013361..3a9449d 100644
--- a/chrome/common/media_router/media_route.cc
+++ b/chrome/common/media_router/media_route.cc
@@ -24,7 +24,7 @@
       custom_controller_path_(custom_controller_path),
       for_display_(for_display),
       is_incognito_(false),
-      is_offscreen_presentation_(false) {}
+      is_local_presentation_(false) {}
 
 MediaRoute::MediaRoute(const MediaRoute& other) = default;
 
diff --git a/chrome/common/media_router/media_route.h b/chrome/common/media_router/media_route.h
index 6439c0fe..0dfe2a11 100644
--- a/chrome/common/media_router/media_route.h
+++ b/chrome/common/media_router/media_route.h
@@ -101,10 +101,10 @@
   void set_incognito(bool is_incognito) { is_incognito_ = is_incognito; }
   bool is_incognito() const { return is_incognito_; }
 
-  void set_offscreen_presentation(bool is_offscreen_presentation) {
-    is_offscreen_presentation_ = is_offscreen_presentation;
+  void set_local_presentation(bool is_local_presentation) {
+    is_local_presentation_ = is_local_presentation;
   }
-  bool is_offscreen_presentation() const { return is_offscreen_presentation_; }
+  bool is_local_presentation() const { return is_local_presentation_; }
 
   bool Equals(const MediaRoute& other) const;
 
@@ -146,9 +146,9 @@
   // |true| if the route was created by an incognito profile.
   bool is_incognito_ = false;
 
-  // |true| if the presentation associated with this route is an offscreen
+  // |true| if the presentation associated with this route is a local
   // presentation.
-  bool is_offscreen_presentation_ = false;
+  bool is_local_presentation_ = false;
 };
 
 }  // namespace media_router
diff --git a/chrome/common/media_router/mojo/media_router.mojom b/chrome/common/media_router/mojo/media_router.mojom
index ab88a986..a5e58286 100644
--- a/chrome/common/media_router/mojo/media_router.mojom
+++ b/chrome/common/media_router/mojo/media_router.mojom
@@ -111,8 +111,8 @@
   bool for_display;
   // Set to true if this route was created by an incognito profile.
   bool is_incognito;
-  // Set to true if this route corresponds to an offscreen presentation.
-  bool is_offscreen_presentation;
+  // Set to true if this route corresponds to a local presentation.
+  bool is_local_presentation;
 };
 
 // Notifications or an actionable events to be shown to the user.
diff --git a/chrome/common/media_router/mojo/media_router_struct_traits.cc b/chrome/common/media_router/mojo/media_router_struct_traits.cc
index 73648b5f..3f7ef7f 100644
--- a/chrome/common/media_router/mojo/media_router_struct_traits.cc
+++ b/chrome/common/media_router/mojo/media_router_struct_traits.cc
@@ -214,7 +214,7 @@
       data.supports_media_route_controller());
   out->set_for_display(data.for_display());
   out->set_incognito(data.is_incognito());
-  out->set_offscreen_presentation(data.is_offscreen_presentation());
+  out->set_local_presentation(data.is_local_presentation());
 
   return true;
 }
diff --git a/chrome/common/media_router/mojo/media_router_struct_traits.h b/chrome/common/media_router/mojo/media_router_struct_traits.h
index 0bab31d2..6d8bc7f 100644
--- a/chrome/common/media_router/mojo/media_router_struct_traits.h
+++ b/chrome/common/media_router/mojo/media_router_struct_traits.h
@@ -434,8 +434,8 @@
     return route.is_incognito();
   }
 
-  static bool is_offscreen_presentation(const media_router::MediaRoute& route) {
-    return route.is_offscreen_presentation();
+  static bool is_local_presentation(const media_router::MediaRoute& route) {
+    return route.is_local_presentation();
   }
 };
 
diff --git a/chrome/common/profiling/profiling_client.h b/chrome/common/profiling/profiling_client.h
index ee7da6d..07d9e08c 100644
--- a/chrome/common/profiling/profiling_client.h
+++ b/chrome/common/profiling/profiling_client.h
@@ -17,9 +17,9 @@
 
 class MemlogSenderPipe;
 
-// The MemlogClient listens on the interface for a StartProfiling message. On
+// The ProfilingClient listens on the interface for a StartProfiling message. On
 // receiving the message, it begins profiling the current process.
-// It is also possible to use the MemlogClient to begin profiling the current
+// It is also possible to use the ProfilingClient to begin profiling the current
 // process without connecting to the service manager interface, if the caller
 // has a |sender_pipe| to pass to StartProfiling.
 class ProfilingClient : public mojom::ProfilingClient {
@@ -27,7 +27,7 @@
   ProfilingClient();
   ~ProfilingClient() override;
 
-  // mojom::MemlogClient overrides:
+  // mojom::ProfilingClient overrides:
   void StartProfiling(mojo::ScopedHandle memlog_sender_pipe) override;
   void FlushMemlogPipe(uint32_t barrier_id) override;
 
diff --git a/chrome/gpu/gpu_arc_video_encode_accelerator.cc b/chrome/gpu/gpu_arc_video_encode_accelerator.cc
index a1cf7056..90ae8b2d 100644
--- a/chrome/gpu/gpu_arc_video_encode_accelerator.cc
+++ b/chrome/gpu/gpu_arc_video_encode_accelerator.cc
@@ -225,6 +225,15 @@
   accelerator_->RequestEncodingParametersChange(bitrate, framerate);
 }
 
+void GpuArcVideoEncodeAccelerator::Flush(FlushCallback callback) {
+  DVLOGF(2);
+  if (!accelerator_) {
+    DLOG(ERROR) << "Accelerator is not initialized.";
+    return;
+  }
+  accelerator_->Flush(std::move(callback));
+}
+
 base::ScopedFD GpuArcVideoEncodeAccelerator::UnwrapFdFromMojoHandle(
     mojo::ScopedHandle handle) {
   DCHECK(client_);
diff --git a/chrome/gpu/gpu_arc_video_encode_accelerator.h b/chrome/gpu/gpu_arc_video_encode_accelerator.h
index c79e57c..6acf7f2 100644
--- a/chrome/gpu/gpu_arc_video_encode_accelerator.h
+++ b/chrome/gpu/gpu_arc_video_encode_accelerator.h
@@ -65,6 +65,7 @@
                           UseBitstreamBufferCallback callback) override;
   void RequestEncodingParametersChange(uint32_t bitrate,
                                        uint32_t framerate) override;
+  void Flush(FlushCallback callback) override;
 
   // Unwraps a file descriptor from the given mojo::ScopedHandle.
   // If an error is encountered, it returns an invalid base::ScopedFD and
diff --git a/chrome/installer/setup/setup_main.cc b/chrome/installer/setup/setup_main.cc
index ac097ec..be09f1a 100644
--- a/chrome/installer/setup/setup_main.cc
+++ b/chrome/installer/setup/setup_main.cc
@@ -1340,7 +1340,7 @@
 
   // Initialize COM for use later.
   base::win::ScopedCOMInitializer com_initializer;
-  if (!com_initializer.succeeded()) {
+  if (!com_initializer.Succeeded()) {
     installer_state.WriteInstallerResult(
         installer::OS_ERROR, IDS_INSTALL_OS_ERROR_BASE, NULL);
     return installer::OS_ERROR;
diff --git a/chrome/installer/util/run_all_unittests.cc b/chrome/installer/util/run_all_unittests.cc
index 9cfc94e..bd845bf 100644
--- a/chrome/installer/util/run_all_unittests.cc
+++ b/chrome/installer/util/run_all_unittests.cc
@@ -16,7 +16,7 @@
   chrome::RegisterPathProvider();
 
   base::win::ScopedCOMInitializer com_initializer;
-  if (!com_initializer.succeeded())
+  if (!com_initializer.Succeeded())
     return -1;
 
   install_static::ScopedInstallDetails scoped_install_details;
diff --git a/chrome/profiling/README.md b/chrome/profiling/README.md
index b108364a..7ce8ba4 100644
--- a/chrome/profiling/README.md
+++ b/chrome/profiling/README.md
@@ -51,8 +51,8 @@
 
 Code Locations
 --------------
-`//chrome/common/profiling` - Logic for MemlogClient.
+`//chrome/common/profiling` - Logic for ProfilingClient.
 `//chrome/browser/profiling_host` - Logic in browser process for starting
-profiling service, and connecting MemlogClients to the profiling service.
+profiling service, and connecting ProfilingClients to the profiling service.
 `//chrome/profiling` - Profiling service.
 
diff --git a/chrome/renderer/resources/extensions/media_router_bindings.js b/chrome/renderer/resources/extensions/media_router_bindings.js
index 8d55846..ed2aca18 100644
--- a/chrome/renderer/resources/extensions/media_router_bindings.js
+++ b/chrome/renderer/resources/extensions/media_router_bindings.js
@@ -93,7 +93,7 @@
       'custom_controller_path': route.customControllerPath,
       'for_display': route.forDisplay,
       'is_incognito': route.offTheRecord,
-      'is_offscreen_presentation': route.isOffscreenPresentation,
+      'is_local_presentation': route.isOffscreenPresentation,
       // Begin newly added properties, followed by the milestone they were
       // added.  The guard should be safe to remove N+2 milestones later.
       'supports_media_route_controller':
diff --git a/chrome/test/BUILD.gn b/chrome/test/BUILD.gn
index c6c1682e..4ce12bc 100644
--- a/chrome/test/BUILD.gn
+++ b/chrome/test/BUILD.gn
@@ -1441,6 +1441,7 @@
       "../browser/subresource_filter/subresource_filter_browser_test_harness.h",
       "../browser/subresource_filter/subresource_filter_browsertest.cc",
       "../browser/subresource_filter/subresource_filter_devtools_browsertest.cc",
+      "../browser/subresource_filter/subresource_filter_intercepting_browsertest.cc",
       "../browser/subresource_filter/subresource_filter_popup_browsertest.cc",
       "../browser/subresource_filter/subresource_filter_settings_browsertest.cc",
       "../browser/subresource_filter/subresource_filter_special_subframe_navigations_browsertest.cc",
@@ -3221,13 +3222,13 @@
     "../browser/media/midi_sysex_permission_context_unittest.cc",
     "../browser/media/router/browser_presentation_connection_proxy_unittest.cc",
     "../browser/media/router/issue_manager_unittest.cc",
+    "../browser/media/router/local_presentation_manager_factory_unittest.cc",
+    "../browser/media/router/local_presentation_manager_unittest.cc",
     "../browser/media/router/media_router_base_unittest.cc",
     "../browser/media/router/media_router_dialog_controller_unittest.cc",
     "../browser/media/router/media_router_factory_unittest.cc",
     "../browser/media/router/media_router_metrics_unittest.cc",
     "../browser/media/router/media_sinks_observer_unittest.cc",
-    "../browser/media/router/offscreen_presentation_manager_factory_unittest.cc",
-    "../browser/media/router/offscreen_presentation_manager_unittest.cc",
     "../browser/media/router/presentation_media_sinks_observer_unittest.cc",
     "../browser/media/router/presentation_service_delegate_impl_unittest.cc",
     "../browser/media/webrtc/media_stream_device_permission_context_unittest.cc",
@@ -3712,7 +3713,7 @@
       "../browser/media_galleries/media_galleries_preferences_unittest.cc",
       "../browser/media_galleries/win/mtp_device_delegate_impl_win_unittest.cc",
       "../browser/media_galleries/win/mtp_device_object_enumerator_unittest.cc",
-      "../browser/memory/swap_thrashing_monitor_win_unittest.cc",
+      "../browser/memory/swap_thrashing_monitor_delegate_win_unittest.cc",
       "../browser/page_load_metrics/observers/session_restore_page_load_metrics_observer_unittest.cc",
       "../browser/resource_coordinator/background_tab_navigation_throttle_unittest.cc",
       "../browser/resource_coordinator/tab_manager_delegate_chromeos_unittest.cc",
diff --git a/chrome/test/android/BUILD.gn b/chrome/test/android/BUILD.gn
index da3489b8..ab6c68aec 100644
--- a/chrome/test/android/BUILD.gn
+++ b/chrome/test/android/BUILD.gn
@@ -91,6 +91,7 @@
     "//testing/android/reporter:reporter_java",
     "//third_party/android_support_test_runner:rules_java",
     "//third_party/android_support_test_runner:runner_java",
+    "//third_party/android_tools:android_arch_lifecycle_common_java",
     "//third_party/android_tools:android_support_compat_java",
     "//third_party/android_tools:android_support_design_java",
     "//third_party/android_tools:android_support_transition_java",
diff --git a/chrome/test/android/OWNERS b/chrome/test/android/OWNERS
index 3098480..e62f3f88 100644
--- a/chrome/test/android/OWNERS
+++ b/chrome/test/android/OWNERS
@@ -1,5 +1,4 @@
 bauerb@chromium.org
-boliu@chromium.org
 dtrainor@chromium.org
 jbudorick@chromium.org
 mariakhomenko@chromium.org
diff --git a/chrome/test/chromedriver/test/run_py_tests.py b/chrome/test/chromedriver/test/run_py_tests.py
index de21d7a..57279a9 100755
--- a/chrome/test/chromedriver/test/run_py_tests.py
+++ b/chrome/test/chromedriver/test/run_py_tests.py
@@ -182,6 +182,8 @@
         'ChromeDriverTest.testHoverOverElement',
         # https://bugs.chromium.org/p/chromedriver/issues/detail?id=1478
         'ChromeDriverTest.testShouldHandleNewWindowLoadingProperly',
+        # https://bugs.chromium.org/p/chromedriver/issues/detail?id=2108
+        'ChromeLoggingCapabilityTest.testPerformanceLogger',
     ]
 )
 _ANDROID_NEGATIVE_FILTER['chromedriver_webview_shell'] = (
diff --git a/chrome/test/data/android/webvr_instrumentation/html/test_gamepad_button.html b/chrome/test/data/android/webvr_instrumentation/html/test_gamepad_button.html
index cfb0022..39acdae 100644
--- a/chrome/test/data/android/webvr_instrumentation/html/test_gamepad_button.html
+++ b/chrome/test/data/android/webvr_instrumentation/html/test_gamepad_button.html
@@ -1,8 +1,8 @@
 <!doctype html>
 <!--
-Tests that either screen taps are registered in VR when viewer is Cardboard
-or that controller clicks are registered as screen taps in VR when viewer is
-Daydream View.
+Tests that screen taps when using Cardboard are translated into controller
+input, and that Daydream controller input is registered when using Daydream
+View.
 -->
 <html>
   <head>
@@ -19,14 +19,16 @@
           () => {finishJavaScriptStep();}, false);
       var pressed = false;
       var index = -1;
+      var canStartTest = false;
       window.addEventListener("gamepadconnected", function(e) {
         t.step( () => {
           assert_equals(index, -1, "Should only receive gamepadconnected once");
-          index = e.gamepad.index;
         });
+        index = e.gamepad.index;
       });
       onAnimationFrameCallback = function() {
         if (index == -1) return;
+        if (!canStartTest) return;
         var gp = navigator.getGamepads()[index];
         if (!pressed && gp.buttons[0].pressed == true) {
           pressed = true;
diff --git a/chrome/test/data/extensions/api_test/serial/api/background.js b/chrome/test/data/extensions/api_test/serial/api/background.js
index ad82b71..560f03e 100644
--- a/chrome/test/data/extensions/api_test/serial/api/background.js
+++ b/chrome/test/data/extensions/api_test/serial/api/background.js
@@ -35,35 +35,46 @@
   var doNextOperation = function() {
     switch (operation++) {
       case 0:
-      serial.getDevices(onGetDevices);
-      break;
+        serial.getDevices(onGetDevices);
+        break;
       case 1:
-      var bitrate = 57600;
-      console.log('Connecting to serial device ' + serialPort + ' at ' +
-                  bitrate + ' bps.');
-      serial.connect(serialPort, {bitrate: bitrate}, onConnect);
-      break;
+        serial.getConnections(onGetConnectionsEmpty);
+        break;
       case 2:
-      serial.setControlSignals(connectionId, {dtr: true}, onSetControlSignals);
-      break;
+        var bitrate = 57600;
+        console.log(
+            'Connecting to serial device ' + serialPort + ' at ' + bitrate +
+            ' bps.');
+        serial.connect(serialPort, {bitrate: bitrate}, onConnect);
+        break;
       case 3:
-      serial.getControlSignals(connectionId,onGetControlSignals);
-      break;
+        serial.getConnections(onGetConnectionsOne);
+        break;
       case 4:
-      serial.onReceive.addListener(onReceive);
-      serial.onReceiveError.addListener(onReceiveError);
-      serial.send(connectionId, sendBuffer, onSend);
-      break;
-      case 50:  // GOTO 4 EVER
-      serial.disconnect(connectionId, onDisconnect);
-      break;
+        serial.setControlSignals(
+            connectionId, {dtr: true}, onSetControlSignals);
+        break;
+      case 5:
+        serial.getControlSignals(connectionId, onGetControlSignals);
+        break;
+      case 6:
+        serial.onReceive.addListener(onReceive);
+        serial.onReceiveError.addListener(onReceiveError);
+        serial.send(connectionId, sendBuffer, onSend);
+        break;
+      case 7:
+        serial.disconnect(connectionId, onDisconnect);
+        break;
+      case 8:
+        serial.getConnections(onGetConnectionsEmpty);
+        break;
       default:
-      // Beware! If you forget to assign a case for your next test, the whole
-      // test suite will appear to succeed!
-      chrome.test.succeed();
-      break;
+        // Beware! If you forget to assign a case for your next test, the whole
+        // test suite will appear to succeed!
+        chrome.test.succeed();
+        break;
     }
-  }
+  };
 
   var skipToTearDown = function() {
     operation = 50;
@@ -73,7 +84,18 @@
   var repeatOperation = function() {
     operation--;
     doNextOperation();
-  }
+  };
+
+  var onGetConnectionsEmpty = function(connectionInfos) {
+    chrome.test.assertEq(0, connectionInfos.length);
+    doNextOperation();
+  };
+
+  var onGetConnectionsOne = function(connectionInfos) {
+    chrome.test.assertEq(1, connectionInfos.length);
+    chrome.test.assertEq(connectionId, connectionInfos[0].connectionId);
+    doNextOperation();
+  };
 
   var onDisconnect = function(result) {
     chrome.test.assertTrue(result);
diff --git a/chrome/test/data/extensions/platform_apps/web_view/shim/main.js b/chrome/test/data/extensions/platform_apps/web_view/shim/main.js
index b6d6017..c9890e88 100644
--- a/chrome/test/data/extensions/platform_apps/web_view/shim/main.js
+++ b/chrome/test/data/extensions/platform_apps/web_view/shim/main.js
@@ -3119,6 +3119,39 @@
   webview.src = 'about:blank';
 };
 
+function testWebViewAndEmbedderInNewWindow() {
+  var webview = document.createElement('webview');
+  webview.addEventListener('newwindow', function(e) {
+    e.preventDefault();
+    var url = 'new_window_main.html';
+    chrome.app.window.create(url, {}, function (app_new_window) {
+      if (chrome.runtime.lastError) {
+        console.log('Error:' + chrome.runtime.lastError.message);
+        embedder.test.fail();
+        return;
+      }
+
+      var new_window = app_new_window.contentWindow;
+      new_window.onload = function(evt) {
+        var newwebview = new_window.document.createElement('webview');
+        // We could use e.targetUrl here I suppose, but it's about:blank so
+        // it doesn't seem to trigger a loadstop.
+        newwebview.setAttribute('src', embedder.emptyGuestURL);
+        newwebview.addEventListener('loadstop', function (evt2) {
+          // After this test exits, we'll still need to compare embedders in the
+          // C++ part of this test.
+          embedder.test.succeed();
+        });
+        // Be sure to do the attach before appending to document.
+        e.window.attach(newwebview);
+        new_window.document.body.appendChild(newwebview);
+      };
+    });
+  });
+  webview.setAttribute('src', embedder.windowOpenGuestURL);
+  document.body.appendChild(webview);
+}
+
 embedder.test.testList = {
   'testAllowTransparencyAttribute': testAllowTransparencyAttribute,
   'testAutosizeHeight': testAutosizeHeight,
@@ -3239,7 +3272,8 @@
   'testMailtoLink': testMailtoLink,
   'testRendererNavigationRedirectWhileUnattached':
        testRendererNavigationRedirectWhileUnattached,
-  'testBlobURL': testBlobURL
+  'testBlobURL': testBlobURL,
+  'testWebViewAndEmbedderInNewWindow': testWebViewAndEmbedderInNewWindow
 };
 
 onload = function() {
diff --git a/chrome/test/data/extensions/platform_apps/web_view/shim/new_window_main.html b/chrome/test/data/extensions/platform_apps/web_view/shim/new_window_main.html
new file mode 100644
index 0000000..d1d4117
--- /dev/null
+++ b/chrome/test/data/extensions/platform_apps/web_view/shim/new_window_main.html
@@ -0,0 +1,5 @@
+<!DOCTYPE html>
+<html>
+  <body>
+  </body>
+</html>
diff --git a/chrome/test/data/form_that_posts_to_echoall.html b/chrome/test/data/form_that_posts_to_echoall.html
new file mode 100644
index 0000000..0a1b160
--- /dev/null
+++ b/chrome/test/data/form_that_posts_to_echoall.html
@@ -0,0 +1,14 @@
+<!DOCTYPE html>
+<html>
+  <head></head>
+  <body>
+    <form id="form" method="POST" action="/echoall">
+      <input type="text" name="text" value="value">
+      <input type="submit">
+    </form>
+    <form id="form-multipart-form-data" method="POST" action="/echoall" enctype="multipart/form-data">
+      <input type="text" name="text" value="value">
+      <input type="submit">
+    </form>
+  </body>
+</html>
diff --git a/chrome/test/data/french_page_lang_conflict.html b/chrome/test/data/french_page_lang_conflict.html
new file mode 100644
index 0000000..5a03c20
--- /dev/null
+++ b/chrome/test/data/french_page_lang_conflict.html
@@ -0,0 +1,6 @@
+<html lang="en">
+<head><title>Cette page est en Français</title></head>
+<body>
+Cette page a été rédigée en français. Saviez-vous que le Français est la langue officielle des jeux olympiques? Ça vous en bouche un coin, pas vrai?
+</body>
+</html>
diff --git a/chrome/test/data/korean_page_lang_conflict.html b/chrome/test/data/korean_page_lang_conflict.html
new file mode 100644
index 0000000..28a981d
--- /dev/null
+++ b/chrome/test/data/korean_page_lang_conflict.html
@@ -0,0 +1,6 @@
+<html lang="en">
+<head><title>언어 탐지 테스트</title></head>
+<body>
+이것은 언어 감지를위한 한국어로 된 테스트 텍스트입니다. 이 테스트에서는 언어 특성이 검색된 언어로 덮어 쓰여지지 않는지 확인합니다.
+</body>
+</html>
diff --git a/chrome/test/data/login/load_img_from_same_domain_mixed_content.html b/chrome/test/data/login/load_img_from_same_domain_mixed_content.html
new file mode 100644
index 0000000..76d41d8
--- /dev/null
+++ b/chrome/test/data/login/load_img_from_same_domain_mixed_content.html
@@ -0,0 +1,9 @@
+<html>
+<body>
+<img id="i">
+<script>
+  var url = window.location.search.substring(1);
+  document.getElementById("i").src = url;
+</script>
+</body>
+</html>
diff --git a/chrome/test/data/printing/pdf_to_pwg_raster_test.pwg b/chrome/test/data/printing/pdf_to_pwg_raster_test.pwg
index f9c5b68..d61d334e 100644
--- a/chrome/test/data/printing/pdf_to_pwg_raster_test.pwg
+++ b/chrome/test/data/printing/pdf_to_pwg_raster_test.pwg
Binary files differ
diff --git a/chrome/test/data/printing/pdf_to_pwg_raster_test_32.pwg b/chrome/test/data/printing/pdf_to_pwg_raster_test_32.pwg
index cc3be9c5..13a399f1 100644
--- a/chrome/test/data/printing/pdf_to_pwg_raster_test_32.pwg
+++ b/chrome/test/data/printing/pdf_to_pwg_raster_test_32.pwg
Binary files differ
diff --git a/chrome/test/data/save_page/b.saved1.htm b/chrome/test/data/save_page/b.saved1.htm
index c296a2b33..2018f7a 100644
--- a/chrome/test/data/save_page/b.saved1.htm
+++ b/chrome/test/data/save_page/b.saved1.htm
@@ -1,5 +1,5 @@
 
-<!-- saved from url=(0032)http://mock.http/save_page/b.htm -->
+<!-- saved from url=(%04d)%s -->
 <html><head><meta http-equiv="Content-Type" content="text/html; charset=windows-1252">
     <title>
       Test page for saving page feature
diff --git a/chrome/test/data/save_page/b.saved2.htm b/chrome/test/data/save_page/b.saved2.htm
index 0d189bd..65fd0364 100644
--- a/chrome/test/data/save_page/b.saved2.htm
+++ b/chrome/test/data/save_page/b.saved2.htm
@@ -1,5 +1,5 @@
 
-<!-- saved from url=(0032)http://mock.http/save_page/b.htm -->
+<!-- saved from url=(%04d)%s -->
 <html><head><meta http-equiv="Content-Type" content="text/html; charset=windows-1252">
     <title>
       Test page for saving page feature
diff --git a/chrome/test/data/webui/extensions/cr_extensions_browsertest.js b/chrome/test/data/webui/extensions/cr_extensions_browsertest.js
index 879e235..affa92f 100644
--- a/chrome/test/data/webui/extensions/cr_extensions_browsertest.js
+++ b/chrome/test/data/webui/extensions/cr_extensions_browsertest.js
@@ -384,6 +384,7 @@
   /** @override */
   get extraLibraries() {
     return super.extraLibraries.concat([
+      '../test_browser_proxy.js',
       'extension_keyboard_shortcuts_test.js',
       'extension_shortcut_input_test.js',
     ]);
diff --git a/chrome/test/data/webui/extensions/extension_manager_test.js b/chrome/test/data/webui/extensions/extension_manager_test.js
index 31198fc..23c503a 100644
--- a/chrome/test/data/webui/extensions/extension_manager_test.js
+++ b/chrome/test/data/webui/extensions/extension_manager_test.js
@@ -22,8 +22,9 @@
     /** @type {extensions.Manager} */
     var manager;
 
-    function isActiveView(viewId) {
-      expectEquals(viewId, manager.$.viewManager.querySelector('.active').id);
+    /** @param {string} viewElement */
+    function assertViewActive(tagName) {
+      expectTrue(!!manager.$.viewManager.querySelector(`${tagName}.active`));
     }
 
     setup(function() {
@@ -122,34 +123,34 @@
       // We start on the item list.
       MockInteractions.tap(manager.$$('#sidebar').$['sections-extensions']);
       Polymer.dom.flush();
-      isActiveView(Page.LIST);
+      assertViewActive('extensions-item-list');
 
       // Switch: item list -> keyboard shortcuts.
       MockInteractions.tap(manager.$$('#sidebar').$['sections-shortcuts']);
       Polymer.dom.flush();
-      isActiveView(Page.SHORTCUTS);
+      assertViewActive('extensions-keyboard-shortcuts');
 
       // Switch: item list -> detail view.
       var item = manager.$['items-list'].$$('extensions-item');
       assert(item);
       item.onDetailsTap_();
       Polymer.dom.flush();
-      isActiveView(Page.DETAILS);
+      assertViewActive('extensions-detail-view');
 
       // Switch: detail view -> keyboard shortcuts.
       MockInteractions.tap(manager.$$('#sidebar').$['sections-shortcuts']);
       Polymer.dom.flush();
-      isActiveView(Page.SHORTCUTS);
+      assertViewActive('extensions-keyboard-shortcuts');
 
       // We get back on the item list.
       MockInteractions.tap(manager.$$('#sidebar').$['sections-extensions']);
       Polymer.dom.flush();
-      isActiveView(Page.LIST);
+      assertViewActive('extensions-item-list');
     });
 
     test(assert(TestNames.UrlNavigationToDetails), function() {
-      isActiveView(Page.DETAILS);
-      var detailsView = manager.$['details-view'];
+      assertViewActive('extensions-detail-view');
+      var detailsView = manager.$$('extensions-detail-view');
       expectEquals('ldnnhddmnhbkjipkidpdiheffobcpfmf', detailsView.data.id);
     });
 
@@ -165,11 +166,13 @@
       manager.addItem(extension);
       manager.addItem(secondExtension);
       var data = manager.extensions[0];
+      // The detail view is not present until navigation.
+      expectFalse(!!manager.$$('extensions-detail-view'));
       // TODO(scottchen): maybe testing too many things in a single unit test.
       extensions.navigation.navigateTo(
           {page: Page.DETAILS, extensionId: extension.id});
-      Polymer.dom.flush();
-      var detailsView = manager.$['details-view'];
+      var detailsView = manager.$$('extensions-detail-view');
+      expectTrue(!!detailsView);  // View should now be present.
       expectEquals(extension.id, detailsView.data.id);
       expectEquals(oldDescription, detailsView.data.description);
       expectEquals(
@@ -194,7 +197,6 @@
       expectEquals(
           newDescription,
           detailsView.$$('.section .section-content').textContent.trim());
-
     });
   });
 
diff --git a/chrome/test/data/webui/extensions/extension_shortcut_input_test.js b/chrome/test/data/webui/extensions/extension_shortcut_input_test.js
index 7c7362e..4a86e28 100644
--- a/chrome/test/data/webui/extensions/extension_shortcut_input_test.js
+++ b/chrome/test/data/webui/extensions/extension_shortcut_input_test.js
@@ -4,6 +4,27 @@
 
 /** @fileoverview Suite of tests for extension-keyboard-shortcuts. */
 cr.define('extension_shortcut_input_tests', function() {
+  class DelegateMock extends TestBrowserProxy {
+    constructor() {
+      super(['setShortcutHandlingSuspended', 'updateExtensionCommand']);
+    }
+
+    /** @param {boolean} enable */
+    setShortcutHandlingSuspended(enable) {
+      this.methodCalled('setShortcutHandlingSuspended', enable);
+    }
+
+    /**
+     * @param {string} item
+     * @param {string} commandName
+     * @param {string} keybinding
+     */
+    updateExtensionCommand(item, commandName, keybinding) {
+      this.methodCalled(
+          'updateExtensionCommand', [item, commandName, keybinding]);
+    }
+  }
+
   /** @enum {string} */
   var TestNames = {
     Basic: 'basic',
@@ -15,6 +36,7 @@
     setup(function() {
       PolymerTest.clearBody();
       input = new extensions.ShortcutInput();
+      input.delegate = new DelegateMock();
       input.commandName = 'Command';
       input.item = 'itemid';
       document.body.appendChild(input);
@@ -32,73 +54,65 @@
       expectFalse(isClearVisible());
 
       // Click the input. Capture should start.
-      {
-        let startCaptureListener = new extension_test_util.ListenerMock();
-        startCaptureListener.addListener(input, 'shortcut-capture-started');
-        MockInteractions.tap(field);
-        startCaptureListener.verify();
-      }
-      expectEquals('', fieldText());
-      expectTrue(input.capturing_);
-      expectFalse(isClearVisible());
-
-      // Press ctrl.
-      MockInteractions.keyDownOn(field, 17, ['ctrl']);
-      expectEquals('Ctrl', fieldText());
-      expectTrue(input.capturing_);
-      // Add shift.
-      MockInteractions.keyDownOn(field, 16, ['ctrl', 'shift']);
-      expectEquals('Ctrl + Shift', fieldText());
-      expectTrue(input.capturing_);
-      // Remove shift.
-      MockInteractions.keyUpOn(field, 16, ['ctrl']);
-      expectEquals('Ctrl', fieldText());
-      // Add alt (ctrl + alt is invalid).
-      MockInteractions.keyDownOn(field, 18, ['ctrl', 'alt']);
-      expectEquals('invalid', fieldText());
-      expectTrue(input.capturing_);
-      // Remove alt.
-      MockInteractions.keyUpOn(field, 18, ['ctrl']);
-      expectEquals('Ctrl', fieldText());
-      expectTrue(input.capturing_);
-      {
-        // Add 'A'. Once a valid shortcut is typed (like Ctrl + A), it is
-        // committed.
-        let updatedListener = new extension_test_util.ListenerMock();
-        updatedListener.addListener(
-            input, 'shortcut-updated',
-            {keybinding: 'Ctrl+A', item: 'itemid', commandName: 'Command'});
-        updatedListener.addListener(input, 'shortcut-capture-ended');
-        MockInteractions.keyDownOn(field, 65, ['ctrl']);
-        updatedListener.verify();
-      }
-      expectEquals('Ctrl + A', fieldText());
-      expectFalse(input.capturing_);
-      expectEquals('Ctrl+A', input.shortcut);
-      expectTrue(isClearVisible());
-
-      {
-        // Test clearing the shortcut.
-        let updatedListener = new extension_test_util.ListenerMock();
-        updatedListener.addListener(
-            input, 'shortcut-updated',
-            {keybinding: '', item: 'itemid', commandName: 'Command'});
-        MockInteractions.tap(input.$['clear']);
-        updatedListener.verify();
-      }
-      expectEquals('', input.shortcut);
-      expectFalse(isClearVisible());
-
       MockInteractions.tap(field);
-      {
-        // Test ending capture using the escape key.
-        expectTrue(input.capturing_);
-        let captureEndedListener = new extension_test_util.ListenerMock();
-        captureEndedListener.addListener(input, 'shortcut-capture-ended');
-        MockInteractions.keyDownOn(field, 27);  // Escape key.
-        expectFalse(input.capturing_);
-        captureEndedListener.verify();
-      }
+      return input.delegate.whenCalled('setShortcutHandlingSuspended')
+          .then((arg) => {
+            assertTrue(arg);
+            input.delegate.reset();
+
+            expectEquals('', fieldText());
+            expectFalse(isClearVisible());
+
+            // Press ctrl.
+            MockInteractions.keyDownOn(field, 17, ['ctrl']);
+            expectEquals('Ctrl', fieldText());
+            // Add shift.
+            MockInteractions.keyDownOn(field, 16, ['ctrl', 'shift']);
+            expectEquals('Ctrl + Shift', fieldText());
+            // Remove shift.
+            MockInteractions.keyUpOn(field, 16, ['ctrl']);
+            expectEquals('Ctrl', fieldText());
+            // Add alt (ctrl + alt is invalid).
+            MockInteractions.keyDownOn(field, 18, ['ctrl', 'alt']);
+            expectEquals('invalid', fieldText());
+            // Remove alt.
+            MockInteractions.keyUpOn(field, 18, ['ctrl']);
+            expectEquals('Ctrl', fieldText());
+
+            // Add 'A'. Once a valid shortcut is typed (like Ctrl + A), it is
+            // committed.
+            MockInteractions.keyDownOn(field, 65, ['ctrl']);
+            return input.delegate.whenCalled('updateExtensionCommand');
+          })
+          .then((arg) => {
+            input.delegate.reset();
+            expectDeepEquals(['itemid', 'Command', 'Ctrl+A'], arg);
+            expectEquals('Ctrl + A', fieldText());
+            expectEquals('Ctrl+A', input.shortcut);
+            expectTrue(isClearVisible());
+
+            // Test clearing the shortcut.
+            MockInteractions.tap(input.$['clear']);
+            return input.delegate.whenCalled('updateExtensionCommand');
+          })
+          .then((arg) => {
+            input.delegate.reset();
+            expectDeepEquals(['itemid', 'Command', ''], arg);
+            expectEquals('', input.shortcut);
+            expectFalse(isClearVisible());
+
+            MockInteractions.tap(field);
+            return input.delegate.whenCalled('setShortcutHandlingSuspended');
+          })
+          .then((arg) => {
+            input.delegate.reset();
+            expectTrue(arg);
+
+            // Test ending capture using the escape key.
+            MockInteractions.keyDownOn(field, 27);  // Escape key.
+            return input.delegate.whenCalled('setShortcutHandlingSuspended');
+          })
+          .then(expectFalse);
     });
   });
 
diff --git a/chrome/test/data/webui/extensions/extension_sidebar_test.js b/chrome/test/data/webui/extensions/extension_sidebar_test.js
index 2b98ba4..5f36a2b 100644
--- a/chrome/test/data/webui/extensions/extension_sidebar_test.js
+++ b/chrome/test/data/webui/extensions/extension_sidebar_test.js
@@ -21,7 +21,7 @@
     });
 
     test(assert(TestNames.SetSelected), function() {
-      const selector = 'paper-item.iron-selected';
+      const selector = '.section-item.iron-selected';
       expectFalse(!!sidebar.$$(selector));
 
       window.history.replaceState(undefined, '', '/shortcuts');
diff --git a/chrome/test/data/webui/test_api.js b/chrome/test/data/webui/test_api.js
index 8868a016..467786f 100644
--- a/chrome/test/data/webui/test_api.js
+++ b/chrome/test/data/webui/test_api.js
@@ -535,7 +535,7 @@
      *     time.
      * @param {...*} var_args Arguments to pass when running the
      *     |currentTestCase|.
-     * @return {function(): void} A function thatwill run this TestCase when
+     * @return {function(): void} A function that will run this TestCase when
      *     called.
      */
     deferRunTest: function(whenTestDone) {
@@ -956,7 +956,7 @@
    * Run an accessibility audit on the current page state.
    * @type {Function}
    * @param {Array} a11yResults
-   * @param {axs.AuditConfigutarion=} opt_config
+   * @param {axs.AuditConfiguration=} opt_config
    * @return {boolean} Whether there were any errors or warnings
    * @private
    */
@@ -1003,10 +1003,10 @@
   }
 
   /**
-   * Creates a function based upon a function that thows an exception on
+   * Creates a function based upon a function that throws an exception on
    * failure. The new function stuffs any errors into the |errors| array for
    * checking by runTest. This allows tests to continue running other checks,
-   * while failing the overall test if any errors occurrred.
+   * while failing the overall test if any errors occurred.
    * @param {Function} assertFunc The function which may throw an Error.
    * @return {function(...*):bool} A function that applies its arguments to
    *     |assertFunc| and returns true if |assertFunc| passes.
@@ -1099,7 +1099,12 @@
    */
   function createTestCase(testFixture, testName) {
     var fixtureConstructor = this[testFixture];
+    assertTrue(
+        !!fixtureConstructor,
+        `The testFixture \'${testFixture}\' was not found.`);
     var testBody = fixtureConstructor.testCaseBodies[testName];
+    assertTrue(
+        !!testBody, `Test \'${testName} was not found in \'${testFixture}\'.`);
     var fixture = new fixtureConstructor();
     fixture.name = testFixture;
     return new TestCase(testName, fixture, testBody);
@@ -1603,7 +1608,7 @@
 
   /**
    * Mock4JS matcher object that matches the actual argument and the expected
-   * value iff their JSON represenations are same.
+   * value iff their JSON representations are same.
    * @param {Object} expectedValue
    * @constructor
    */
@@ -1613,7 +1618,7 @@
 
   MatchJSON.prototype = {
     /**
-     * Checks that JSON represenation of the actual and expected arguments are
+     * Checks that JSON representation of the actual and expected arguments are
      * same.
      * @param {Object} actualArgument The argument to match.
      * @return {boolean} Result of the comparison.
diff --git a/chromecast/BUILD.gn b/chromecast/BUILD.gn
index 40d34b5..5526ce9f 100644
--- a/chromecast/BUILD.gn
+++ b/chromecast/BUILD.gn
@@ -37,6 +37,7 @@
   if (chromecast_branding != "public") {
     deps += [ "//chromecast/internal:all" ]
   }
+
   # No other targets should depend on this target, since it's just a convenience
   # target for the Chromecast internal build infrastructure.
   visibility = []
@@ -44,7 +45,7 @@
 }
 
 # A list of all public test() binaries. This is an organizational target that
-# cannot be depended upon or built directly. Build cast_group_test_list instead.
+# cannot be depended upon or built directly. Build cast_test_lists instead.
 cast_test_group("cast_tests") {
   filters = []
   tests = [
@@ -61,7 +62,6 @@
     "//media:media_unittests",
     "//media/midi:midi_unittests",
     "//net:net_unittests",
-    "//sandbox/linux:sandbox_linux_unittests",
     "//sql:sql_unittests",
     "//storage:storage_unittests",
     "//third_party/cacheinvalidation:cacheinvalidation_unittests",
@@ -77,7 +77,10 @@
   }
 
   if (is_linux) {
-    tests += [ "//chromecast/crash:cast_crash_unittests" ]
+    tests += [
+      "//chromecast/crash:cast_crash_unittests",
+      "//sandbox/linux:sandbox_linux_unittests",
+    ]
   }
 
   if (is_linux || is_fuchsia) {
@@ -89,10 +92,13 @@
       ":cast_shell_browsertests",
       ":cast_shell_unittests",
       "//ipc:ipc_tests",
-      "//jingle:jingle_unittests",
       "//url:url_unittests",
     ]
 
+    if (!is_fuchsia) {
+      tests += [ "//jingle:jingle_unittests" ]
+    }
+
     cast_media_unittests_filter = {
       test_name = "cast_media_unittests"
 
diff --git a/chromecast/browser/BUILD.gn b/chromecast/browser/BUILD.gn
index ac750bb..786e5349 100644
--- a/chromecast/browser/BUILD.gn
+++ b/chromecast/browser/BUILD.gn
@@ -94,6 +94,7 @@
     "//chromecast/graphics",
     "//chromecast/media",
     "//chromecast/media:libcast_media",
+    "//chromecast/media/base:video_plane_controller",
     "//chromecast/media/service",
     "//chromecast/net",
     "//chromecast/service",
diff --git a/chromecast/media/base/BUILD.gn b/chromecast/media/base/BUILD.gn
index 2e47da1..39894ac 100644
--- a/chromecast/media/base/BUILD.gn
+++ b/chromecast/media/base/BUILD.gn
@@ -38,8 +38,6 @@
     "supported_codec_profile_levels_memo.h",
     "video_mode_switcher.cc",
     "video_mode_switcher.h",
-    "video_plane_controller.cc",
-    "video_plane_controller.h",
   ]
 
   if (!is_android) {
@@ -94,3 +92,19 @@
     "//media",
   ]
 }
+
+source_set("video_plane_controller") {
+  sources = [
+    "video_plane_controller.cc",
+    "video_plane_controller.h",
+  ]
+
+  public_deps = [
+    "//chromecast/public",
+  ]
+
+  deps = [
+    "//base",
+    "//chromecast/media:libcast_media",
+  ]
+}
diff --git a/chromecast/media/cdm/cast_cdm_factory.cc b/chromecast/media/cdm/cast_cdm_factory.cc
index a8c0da97..452543b 100644
--- a/chromecast/media/cdm/cast_cdm_factory.cc
+++ b/chromecast/media/cdm/cast_cdm_factory.cc
@@ -60,7 +60,7 @@
   const int packed_cdm_config = (cdm_config.allow_distinctive_identifier << 2) |
                                 (cdm_config.allow_persistent_state << 1) |
                                 cdm_config.use_hw_secure_codecs;
-  metrics::CastMetricsHelper::GetInstance()->RecordEventWithValue(
+  metrics::CastMetricsHelper::GetInstance()->RecordApplicationEventWithValue(
       "Cast.Platform.CreateCdm." + key_system, packed_cdm_config);
 
   task_runner_->PostTask(
diff --git a/chromeos/BUILD.gn b/chromeos/BUILD.gn
index 3331a79..d8afdb0 100644
--- a/chromeos/BUILD.gn
+++ b/chromeos/BUILD.gn
@@ -662,6 +662,7 @@
     "dbus/fake_power_manager_client_unittest.cc",
     "dbus/gsm_sms_client_unittest.cc",
     "dbus/modem_messaging_client_unittest.cc",
+    "dbus/pipe_reader_unittest.cc",
     "dbus/power_manager_client_unittest.cc",
     "dbus/power_policy_controller_unittest.cc",
     "dbus/services/cros_dbus_service_unittest.cc",
@@ -743,6 +744,7 @@
 
 proto_library("power_manager_proto") {
   sources = [
+    "//third_party/cros_system_api/dbus/power_manager/idle.proto",
     "//third_party/cros_system_api/dbus/power_manager/input_event.proto",
     "//third_party/cros_system_api/dbus/power_manager/peripheral_battery_status.proto",
     "//third_party/cros_system_api/dbus/power_manager/policy.proto",
diff --git a/chromeos/audio/cras_audio_handler.cc b/chromeos/audio/cras_audio_handler.cc
index 4293b552..ac6bf44 100644
--- a/chromeos/audio/cras_audio_handler.cc
+++ b/chromeos/audio/cras_audio_handler.cc
@@ -520,6 +520,13 @@
   }
 }
 
+void CrasAudioHandler::SetOutputVolumePercentWithoutNotifyingObservers(
+    int volume_percent,
+    AutomatedVolumeChangeReason reason) {
+  automated_volume_change_reasons_.push_back(reason);
+  SetOutputVolumePercent(volume_percent);
+}
+
 // TODO: Rename the 'Percent' to something more meaningful.
 void CrasAudioHandler::SetInputGainPercent(int gain_percent) {
   // TODO(jennyz): Should we set all input devices' gain to the same level?
@@ -744,26 +751,36 @@
   output_volume_ = volume;
   audio_pref_handler_->SetVolumeGainValue(*device, volume);
 
-  if (initializing_audio_state_) {
-    // Do not notify the observers for volume changed event if CrasAudioHandler
-    // is initializing its state, i.e., the volume change event is in responding
-    // to SetOutputNodeVolume request from initializing audio state, not from
-    // user action, no need to notify UI to pop up the volume slider bar.
-    if (init_node_id_ == node_id && init_volume_ == volume) {
-      --init_volume_count_;
-      if (!init_volume_count_)
-        initializing_audio_state_ = false;
-      return;
+  bool should_notify = true;
+  if (!automated_volume_change_reasons_.empty()) {
+    AutomatedVolumeChangeReason reason =
+        automated_volume_change_reasons_.front();
+    if (reason == VOLUME_CHANGE_INITIALIZING_AUDIO_STATE &&
+        (init_node_id_ != node_id || init_volume_ != volume)) {
+      // A SetOutputNodeVolume request may be dropped if cras isn't ready
+      // during initialization. In this case, we clear the pending automated
+      // volume change reasons as they might also be dropped by cras.
+      LOG(WARNING) << "OutputNodeVolumeChanged signal dropped during the "
+                      "initialization.";
+      automated_volume_change_reasons_.clear();
+    } else {
+      // In other cases, sequential AutomatedVolumeChangeReason corresponds to
+      // sequential avoiding notifying observers.
+      should_notify = false;
+      automated_volume_change_reasons_.pop_front();
     }
-    // Reset the initializing_audio_state_ in case SetOutputNodeVolume request
-    // is lost by cras due to cras is not ready when CrasAudioHandler is being
-    // initialized.
-    initializing_audio_state_ = false;
-    init_volume_count_ = 0;
   }
 
-  for (auto& observer : observers_)
-    observer.OnOutputNodeVolumeChanged(node_id, volume);
+  if (std::find(automated_volume_change_reasons_.begin(),
+                automated_volume_change_reasons_.end(),
+                VOLUME_CHANGE_INITIALIZING_AUDIO_STATE) ==
+      automated_volume_change_reasons_.end())
+    initializing_audio_state_ = false;
+
+  if (should_notify) {
+    for (auto& observer : observers_)
+      observer.OnOutputNodeVolumeChanged(node_id, volume);
+  }
 }
 
 void CrasAudioHandler::ActiveOutputNodeChanged(uint64_t node_id) {
@@ -877,9 +894,10 @@
     // by CrasAudioHandler constructor, then by cras server restarting signal,
     // both sending SetOutputNodeVolume requests, and could lead to two
     // OutputNodeVolumeChanged signals.
-    ++init_volume_count_;
     init_node_id_ = active_output_node_id_;
     init_volume_ = output_volume_;
+    SetOutputVolumePercentWithoutNotifyingObservers(
+        output_volume_, VOLUME_CHANGE_INITIALIZING_AUDIO_STATE);
     return;
   }
   SetOutputNodeVolume(active_output_node_id_, output_volume_);
diff --git a/chromeos/audio/cras_audio_handler.h b/chromeos/audio/cras_audio_handler.h
index 9a244f80..9f47fd2 100644
--- a/chromeos/audio/cras_audio_handler.h
+++ b/chromeos/audio/cras_audio_handler.h
@@ -40,6 +40,13 @@
           AudioDevicePriorityQueue;
   typedef std::vector<uint64_t> NodeIdList;
 
+  // Volume change reasons that are not user-initiated.
+  // TODO(warx): remove AutomatedVolumeChangeReason enum.
+  enum AutomatedVolumeChangeReason {
+    // Indicates it is from initializing audio state.
+    VOLUME_CHANGE_INITIALIZING_AUDIO_STATE,
+  };
+
   class AudioObserver {
    public:
     // Called when an active output volume changed.
@@ -175,6 +182,12 @@
   // range is from 0-100%.
   void SetOutputVolumePercent(int volume_percent);
 
+  // Sets all active output devices' volume levels to |volume_percent|, whose
+  // range is from 0-100%, without notifying observers.
+  void SetOutputVolumePercentWithoutNotifyingObservers(
+      int volume_percent,
+      AutomatedVolumeChangeReason reason);
+
   // Sets all active input devices' gain level to |gain_percent|, whose range is
   // from 0-100%.
   void SetInputGainPercent(int gain_percent);
@@ -507,10 +520,16 @@
 
   bool cras_service_available_ = false;
 
+  // FIFO list of reasons passed to
+  // SetOutputVolumePercentWithoutNotifyingObservers() for which we're still
+  // waiting for OutputNodeVolumeChanged() calls. These are used to suppress
+  // notifications for those changes.
+  base::circular_deque<AutomatedVolumeChangeReason>
+      automated_volume_change_reasons_;
+
   bool initializing_audio_state_ = false;
   int init_volume_;
   uint64_t init_node_id_;
-  int init_volume_count_ = 0;
 
   bool front_camera_on_ = false;
   bool rear_camera_on_ = false;
diff --git a/chromeos/dbus/debug_daemon_client.cc b/chromeos/dbus/debug_daemon_client.cc
index 050c244..19de69a7 100644
--- a/chromeos/dbus/debug_daemon_client.cc
+++ b/chromeos/dbus/debug_daemon_client.cc
@@ -56,44 +56,54 @@
  public:
   explicit PipeReaderWrapper(const DebugDaemonClient::GetLogsCallback& callback)
       : pipe_reader_(base::CreateTaskRunnerWithTraits(
-                         {base::MayBlock(),
-                          base::TaskShutdownBehavior::CONTINUE_ON_SHUTDOWN}),
-                     base::Bind(&PipeReaderWrapper::OnIOComplete, AsWeakPtr())),
+            {base::MayBlock(),
+             base::TaskShutdownBehavior::CONTINUE_ON_SHUTDOWN})),
         callback_(callback) {}
 
-  base::ScopedFD Initialize() { return pipe_reader_.StartIO(); }
+  base::ScopedFD Initialize() {
+    return pipe_reader_.StartIO(
+        base::BindOnce(&PipeReaderWrapper::OnIOComplete, AsWeakPtr()));
+  }
 
-  void OnIOComplete() {
-    std::string pipe_data;
-    pipe_reader_.GetData(&pipe_data);
-    JSONStringValueDeserializer json_reader(pipe_data);
-
-    std::map<std::string, std::string> data;
-    const base::DictionaryValue* dictionary = nullptr;
-    std::unique_ptr<base::Value> logs_value =
-        json_reader.Deserialize(nullptr, nullptr);
-    if (!logs_value.get() || !logs_value->GetAsDictionary(&dictionary)) {
-      VLOG(1) << "Failed to deserialize the JSON logs.";
-      callback_.Run(false, data);
-      delete this;
+  void OnIOComplete(base::Optional<std::string> result) {
+    if (!result.has_value()) {
+      VLOG(1) << "Failed to read data.";
+      RunCallbackAndDestroy(base::nullopt);
       return;
     }
 
-    base::DictionaryValue::Iterator itr(*dictionary);
-    for (; !itr.IsAtEnd(); itr.Advance()) {
-      std::string value;
-      itr.value().GetAsString(&value);
-      data[itr.key()] = value;
+    JSONStringValueDeserializer json_reader(result.value());
+    std::unique_ptr<base::DictionaryValue> logs =
+        base::DictionaryValue::From(json_reader.Deserialize(nullptr, nullptr));
+    if (!logs.get()) {
+      VLOG(1) << "Failed to deserialize the JSON logs.";
+      RunCallbackAndDestroy(base::nullopt);
+      return;
     }
 
-    callback_.Run(true, data);
+    std::map<std::string, std::string> data;
+    for (const auto& entry : *logs)
+      data[entry.first] = entry.second->GetString();
+    RunCallbackAndDestroy(std::move(data));
+  }
+
+  void TerminateStream() {
+    VLOG(1) << "Terminated";
+    RunCallbackAndDestroy(base::nullopt);
+  }
+
+ private:
+  void RunCallbackAndDestroy(
+      base::Optional<std::map<std::string, std::string>> result) {
+    if (result.has_value()) {
+      callback_.Run(true, result.value());
+    } else {
+      callback_.Run(false, std::map<std::string, std::string>());
+    }
     delete this;
   }
 
-  void TerminateStream() { pipe_reader_.OnDataReady(-1); }
-
- private:
-  PipeReaderForString pipe_reader_;
+  PipeReader pipe_reader_;
   DebugDaemonClient::GetLogsCallback callback_;
 
   DISALLOW_COPY_AND_ASSIGN(PipeReaderWrapper);
@@ -306,12 +316,12 @@
       return;
     }
 
-    pipe_reader_.reset(
-        new PipeReaderForString(stop_agent_tracing_task_runner_,
-                                base::Bind(&DebugDaemonClientImpl::OnIOComplete,
-                                           weak_ptr_factory_.GetWeakPtr())));
+    pipe_reader_ =
+        std::make_unique<PipeReader>(stop_agent_tracing_task_runner_);
+    callback_ = callback;
+    base::ScopedFD pipe_write_end = pipe_reader_->StartIO(base::BindOnce(
+        &DebugDaemonClientImpl::OnIOComplete, weak_ptr_factory_.GetWeakPtr()));
 
-    base::ScopedFD pipe_write_end = pipe_reader_->StartIO();
     DCHECK(pipe_write_end.is_valid());
     // Issue the dbus request to stop system tracing
     dbus::MethodCall method_call(debugd::kDebugdInterface,
@@ -319,8 +329,6 @@
     dbus::MessageWriter writer(&method_call);
     writer.AppendFileDescriptor(pipe_write_end.get());
 
-    callback_ = callback;
-
     DVLOG(1) << "Requesting a systrace stop";
     debugdaemon_proxy_->CallMethod(
         &method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
@@ -691,8 +699,13 @@
       LOG(ERROR) << "Failed to request systrace stop";
       // If debugd crashes or completes I/O before this message is processed
       // then pipe_reader_ can be NULL, see OnIOComplete().
-      if (pipe_reader_.get())
-        pipe_reader_->OnDataReady(-1);  // terminate data stream
+      if (pipe_reader_.get()) {
+        pipe_reader_.reset();
+        base::ResetAndReturn(&callback_)
+            .Run(GetTracingAgentName(), GetTraceEventLabel(),
+                 scoped_refptr<base::RefCountedString>(
+                     new base::RefCountedString()));
+      }
     }
     // NB: requester is signaled when i/o completes
   }
@@ -706,12 +719,13 @@
   }
 
   // Called when pipe i/o completes; pass data on and delete the instance.
-  void OnIOComplete() {
-    std::string pipe_data;
-    pipe_reader_->GetData(&pipe_data);
-    callback_.Run(GetTracingAgentName(), GetTraceEventLabel(),
-                  base::RefCountedString::TakeString(&pipe_data));
+  void OnIOComplete(base::Optional<std::string> result) {
     pipe_reader_.reset();
+    std::string pipe_data =
+        result.has_value() ? std::move(result).value() : std::string();
+    base::ResetAndReturn(&callback_)
+        .Run(GetTracingAgentName(), GetTraceEventLabel(),
+             base::RefCountedString::TakeString(&pipe_data));
   }
 
   void OnSetOomScoreAdj(const SetOomScoreAdjCallback& callback,
@@ -747,7 +761,7 @@
   }
 
   dbus::ObjectProxy* debugdaemon_proxy_;
-  std::unique_ptr<PipeReaderForString> pipe_reader_;
+  std::unique_ptr<PipeReader> pipe_reader_;
   StopAgentTracingCallback callback_;
   scoped_refptr<base::TaskRunner> stop_agent_tracing_task_runner_;
   base::WeakPtrFactory<DebugDaemonClientImpl> weak_ptr_factory_;
diff --git a/chromeos/dbus/fake_power_manager_client.cc b/chromeos/dbus/fake_power_manager_client.cc
index 4490462a..14989a4 100644
--- a/chromeos/dbus/fake_power_manager_client.cc
+++ b/chromeos/dbus/fake_power_manager_client.cc
@@ -60,12 +60,10 @@
                                                         bool gradual) {}
 
 void FakePowerManagerClient::GetScreenBrightnessPercent(
-    const GetScreenBrightnessPercentCallback& callback) {
-  if (screen_brightness_percent_.has_value()) {
-    base::ThreadTaskRunnerHandle::Get()->PostTask(
-        FROM_HERE,
-        base::BindOnce(callback, screen_brightness_percent_.value()));
-  }
+    DBusMethodCallback<double> callback) {
+  base::ThreadTaskRunnerHandle::Get()->PostTask(
+      FROM_HERE,
+      base::BindOnce(std::move(callback), screen_brightness_percent_));
 }
 
 void FakePowerManagerClient::DecreaseKeyboardBrightness() {}
@@ -139,15 +137,16 @@
 }
 
 void FakePowerManagerClient::GetBacklightsForcedOff(
-    const GetBacklightsForcedOffCallback& callback) {
+    DBusMethodCallback<bool> callback) {
   base::ThreadTaskRunnerHandle::Get()->PostTask(
-      FROM_HERE, base::Bind(callback, backlights_forced_off_));
+      FROM_HERE, base::BindOnce(std::move(callback), backlights_forced_off_));
 }
 
 void FakePowerManagerClient::GetSwitchStates(
-    const GetSwitchStatesCallback& callback) {
+    DBusMethodCallback<SwitchStates> callback) {
   base::ThreadTaskRunnerHandle::Get()->PostTask(
-      FROM_HERE, base::Bind(callback, lid_state_, tablet_mode_));
+      FROM_HERE, base::BindOnce(std::move(callback),
+                                SwitchStates{lid_state_, tablet_mode_}));
 }
 
 base::Closure FakePowerManagerClient::GetSuspendReadinessCallback() {
@@ -168,9 +167,10 @@
   return fullscreen;
 }
 
-void FakePowerManagerClient::SendSuspendImminent() {
+void FakePowerManagerClient::SendSuspendImminent(
+    power_manager::SuspendImminent::Reason reason) {
   for (auto& observer : observers_)
-    observer.SuspendImminent();
+    observer.SuspendImminent(reason);
   if (render_process_manager_delegate_)
     render_process_manager_delegate_->SuspendImminent();
 }
diff --git a/chromeos/dbus/fake_power_manager_client.h b/chromeos/dbus/fake_power_manager_client.h
index 939214c..94244970 100644
--- a/chromeos/dbus/fake_power_manager_client.h
+++ b/chromeos/dbus/fake_power_manager_client.h
@@ -57,8 +57,7 @@
   void DecreaseScreenBrightness(bool allow_off) override;
   void IncreaseScreenBrightness() override;
   void SetScreenBrightnessPercent(double percent, bool gradual) override;
-  void GetScreenBrightnessPercent(
-      const GetScreenBrightnessPercentCallback& callback) override;
+  void GetScreenBrightnessPercent(DBusMethodCallback<double> callback) override;
   void DecreaseKeyboardBrightness() override;
   void IncreaseKeyboardBrightness() override;
   void RequestStatusUpdate() override;
@@ -73,9 +72,8 @@
   void SetIsProjecting(bool is_projecting) override;
   void SetPowerSource(const std::string& id) override;
   void SetBacklightsForcedOff(bool forced_off) override;
-  void GetBacklightsForcedOff(
-      const GetBacklightsForcedOffCallback& callback) override;
-  void GetSwitchStates(const GetSwitchStatesCallback& callback) override;
+  void GetBacklightsForcedOff(DBusMethodCallback<bool> callback) override;
+  void GetSwitchStates(DBusMethodCallback<SwitchStates> callback) override;
   base::Closure GetSuspendReadinessCallback() override;
   int GetNumPendingSuspendReadinessCallbacks() override;
 
@@ -85,7 +83,7 @@
 
   // Emulates the power manager announcing that the system is starting or
   // completing a suspend attempt.
-  void SendSuspendImminent();
+  void SendSuspendImminent(power_manager::SuspendImminent::Reason reason);
   void SendSuspendDone();
   void SendDarkSuspendImminent();
 
diff --git a/chromeos/dbus/fake_session_manager_client.cc b/chromeos/dbus/fake_session_manager_client.cc
index b36d1f1..2f2e190 100644
--- a/chromeos/dbus/fake_session_manager_client.cc
+++ b/chromeos/dbus/fake_session_manager_client.cc
@@ -263,9 +263,10 @@
     const std::vector<std::string>& flags) {}
 
 void FakeSessionManagerClient::GetServerBackedStateKeys(
-    const StateKeysCallback& callback) {
+    StateKeysCallback callback) {
   base::ThreadTaskRunnerHandle::Get()->PostTask(
-      FROM_HERE, base::Bind(callback, server_backed_state_keys_));
+      FROM_HERE,
+      base::BindOnce(std::move(callback), server_backed_state_keys_));
 }
 
 void FakeSessionManagerClient::StartArcInstance(
diff --git a/chromeos/dbus/fake_session_manager_client.h b/chromeos/dbus/fake_session_manager_client.h
index 275179e..a64f0c4 100644
--- a/chromeos/dbus/fake_session_manager_client.h
+++ b/chromeos/dbus/fake_session_manager_client.h
@@ -73,7 +73,7 @@
   bool SupportsRestartToApplyUserFlags() const override;
   void SetFlagsForUser(const cryptohome::Identification& cryptohome_id,
                        const std::vector<std::string>& flags) override;
-  void GetServerBackedStateKeys(const StateKeysCallback& callback) override;
+  void GetServerBackedStateKeys(StateKeysCallback callback) override;
 
   void StartArcInstance(ArcStartupMode startup_mode,
                         const cryptohome::Identification& cryptohome_id,
diff --git a/chromeos/dbus/lorgnette_manager_client.cc b/chromeos/dbus/lorgnette_manager_client.cc
index 40ab90b..34afc21 100644
--- a/chromeos/dbus/lorgnette_manager_client.cc
+++ b/chromeos/dbus/lorgnette_manager_client.cc
@@ -6,6 +6,7 @@
 
 #include <memory>
 #include <string>
+#include <utility>
 
 #include "base/bind.h"
 #include "base/bind_helpers.h"
@@ -102,36 +103,36 @@
     CompletionCallback Start(const ScanImageToStringCallback& callback,
                              base::ScopedFD* fd) {
       CHECK(!pipe_reader_.get());
-      pipe_reader_.reset(new chromeos::PipeReaderForString(
+      pipe_reader_ = std::make_unique<chromeos::PipeReader>(
           base::CreateTaskRunnerWithTraits(
               {base::MayBlock(),
-               base::TaskShutdownBehavior::CONTINUE_ON_SHUTDOWN}),
-          base::Bind(&ScanToStringCompletion::OnScanToStringDataCompleted,
-                     base::Unretained(this))));
-      *fd = pipe_reader_->StartIO();
+               base::TaskShutdownBehavior::CONTINUE_ON_SHUTDOWN}));
 
+      *fd = pipe_reader_->StartIO(
+          base::BindOnce(&ScanToStringCompletion::OnScanToStringDataCompleted,
+                         base::Unretained(this)));
       return base::Bind(&ScanToStringCompletion::OnScanToStringCompleted,
                         base::Owned(this), callback);
     }
 
    private:
     // Called when a |pipe_reader_| completes reading scan data to a string.
-    void OnScanToStringDataCompleted() {
-      pipe_reader_->GetData(&scanned_image_data_string_);
+    void OnScanToStringDataCompleted(base::Optional<std::string> result) {
+      scanned_image_data_string_ =
+          result.has_value() ? std::move(result).value() : std::string();
       pipe_reader_.reset();
     }
 
     // Called by LorgnetteManagerImpl when scan completes.
     void OnScanToStringCompleted(const ScanImageToStringCallback& callback,
                                  bool succeeded) {
-      if (pipe_reader_.get()) {
-        pipe_reader_->OnDataReady(-1);  // terminate data stream
-      }
+      if (pipe_reader_.get())
+        pipe_reader_.reset();
       callback.Run(succeeded, scanned_image_data_string_);
       scanned_image_data_string_.clear();
     }
 
-    std::unique_ptr<chromeos::PipeReaderForString> pipe_reader_;
+    std::unique_ptr<chromeos::PipeReader> pipe_reader_;
     std::string scanned_image_data_string_;
 
     DISALLOW_COPY_AND_ASSIGN(ScanToStringCompletion);
diff --git a/chromeos/dbus/pipe_reader.cc b/chromeos/dbus/pipe_reader.cc
index b1a096fd..bc81abc 100644
--- a/chromeos/dbus/pipe_reader.cc
+++ b/chromeos/dbus/pipe_reader.cc
@@ -4,7 +4,10 @@
 
 #include "chromeos/dbus/pipe_reader.h"
 
+#include <utility>
+
 #include "base/bind.h"
+#include "base/callback_helpers.h"
 #include "base/posix/eintr_wrapper.h"
 #include "base/task_runner.h"
 #include "net/base/file_stream.h"
@@ -13,17 +16,22 @@
 
 namespace chromeos {
 
-PipeReader::PipeReader(const scoped_refptr<base::TaskRunner>& task_runner,
-                       const IOCompleteCallback& callback)
+PipeReader::PipeReader(const scoped_refptr<base::TaskRunner>& task_runner)
     : io_buffer_(new net::IOBufferWithSize(4096)),
       task_runner_(task_runner),
-      callback_(callback),
       weak_ptr_factory_(this) {}
 
-PipeReader::~PipeReader() {
-}
+PipeReader::~PipeReader() = default;
 
-base::ScopedFD PipeReader::StartIO() {
+base::ScopedFD PipeReader::StartIO(CompletionCallback callback) {
+  DCHECK(!callback.is_null());
+  DCHECK(data_.empty());
+
+  if (!callback_.is_null()) {
+    LOG(ERROR) << "There already is in-flight operation.";
+    return base::ScopedFD();
+  }
+
   // Use a pipe to collect data
   int pipe_fds[2];
   const int status = HANDLE_EINTR(pipe(pipe_fds));
@@ -31,53 +39,55 @@
     PLOG(ERROR) << "pipe";
     return base::ScopedFD();
   }
+
   base::ScopedFD pipe_write_end(pipe_fds[1]);
   // Pass ownership of pipe_fds[0] to data_stream_, which will close it.
-  data_stream_.reset(new net::FileStream(
-      base::File(pipe_fds[0]), task_runner_));
+  data_stream_ =
+      std::make_unique<net::FileStream>(base::File(pipe_fds[0]), task_runner_);
 
   // Post an initial async read to setup data collection
-  int rv = data_stream_->Read(
-      io_buffer_.get(), io_buffer_->size(),
-      base::Bind(&PipeReader::OnDataReady, weak_ptr_factory_.GetWeakPtr()));
+  // Expect asynchronous operation.
+  int rv = RequestRead();
   if (rv != net::ERR_IO_PENDING) {
     LOG(ERROR) << "Unable to post initial read";
+    data_stream_.reset();
     return base::ScopedFD();
   }
+
+  // The operation is successfully started. Keep objects in the members,
+  // and returns the write-side of the pipe.
+  callback_ = std::move(callback);
   return pipe_write_end;
 }
 
-void PipeReader::OnDataReady(int byte_count) {
-  DVLOG(1) << "OnDataReady byte_count " << byte_count;
+int PipeReader::RequestRead() {
+  DCHECK(data_stream_.get());
+  return data_stream_->Read(
+      io_buffer_.get(), io_buffer_->size(),
+      base::Bind(&PipeReader::OnRead, weak_ptr_factory_.GetWeakPtr()));
+}
+
+void PipeReader::OnRead(int byte_count) {
+  DVLOG(1) << "OnRead byte_count: " << byte_count;
   if (byte_count <= 0) {
-    callback_.Run();  // signal creator to take data and delete us
+    // On EOF (= 0), or on error (< 0).
+    base::Optional<std::string> result =
+        byte_count < 0 ? base::nullopt : base::make_optional(std::move(data_));
+    // Clear members before calling the |callback|.
+    data_.clear();
+    data_stream_.reset();
+    base::ResetAndReturn(&callback_).Run(std::move(result));
     return;
   }
 
-  AcceptData(io_buffer_->data(), byte_count);
+  data_.append(io_buffer_->data(), byte_count);
 
-  // Post another read
-  int rv = data_stream_->Read(
-      io_buffer_.get(), io_buffer_->size(),
-      base::Bind(&PipeReader::OnDataReady, weak_ptr_factory_.GetWeakPtr()));
+  // Post another read.
+  int rv = RequestRead();
   if (rv != net::ERR_IO_PENDING) {
-    LOG(ERROR) << "Unable to post another read";
-    // TODO(sleffler) do something more intelligent?
+    // Calls OnRead() again with the error, which handles remaining clean up.
+    OnRead(rv > 0 ? net::ERR_FAILED : rv);
   }
 }
 
-PipeReaderForString::PipeReaderForString(
-    const scoped_refptr<base::TaskRunner>& task_runner,
-    const IOCompleteCallback& callback)
-    : PipeReader(task_runner, callback) {
-}
-
-void PipeReaderForString::AcceptData(const char *data, int byte_count) {
-  data_.append(data, byte_count);
-}
-
-void PipeReaderForString::GetData(std::string* data) {
-  data_.swap(*data);
-}
-
 }  // namespace chromeos
diff --git a/chromeos/dbus/pipe_reader.h b/chromeos/dbus/pipe_reader.h
index 3df73553..0787908 100644
--- a/chromeos/dbus/pipe_reader.h
+++ b/chromeos/dbus/pipe_reader.h
@@ -13,6 +13,7 @@
 #include "base/macros.h"
 #include "base/memory/ref_counted.h"
 #include "base/memory/weak_ptr.h"
+#include "base/optional.h"
 #include "chromeos/chromeos_export.h"
 
 namespace base {
@@ -36,32 +37,33 @@
 //     |callback|.
 class CHROMEOS_EXPORT PipeReader {
  public:
-  typedef base::Callback<void(void)> IOCompleteCallback;
+  using CompletionCallback =
+      base::OnceCallback<void(base::Optional<std::string> data)>;
 
-  PipeReader(const scoped_refptr<base::TaskRunner>& task_runner,
-             const IOCompleteCallback& callback);
-  virtual ~PipeReader();
+  explicit PipeReader(const scoped_refptr<base::TaskRunner>& task_runner);
+  ~PipeReader();
 
   // Starts data collection.
   // Returns the write end of the pipe if stream was setup correctly.
-  // On success data will automatically be accumulated into a string that
-  // can be retrieved with PipeReader::data().  To shutdown collection delete
-  // the instance and/or use PipeReader::OnDataReady(-1).
-  base::ScopedFD StartIO();
-
-  // Called when pipe data are available.  Can also be used to shutdown
-  // data collection by passing -1 for |byte_count|.
-  void OnDataReady(int byte_count);
-
-  // Virtual function that subclasses will override in order to deal
-  // with incoming data.
-  virtual void AcceptData(const char *data, int length) = 0;
+  // On completion, |callback| will be called with the read |data| in
+  // case of success, or with nullopt in case of an error.
+  // To shut down the collection delete the instance.
+  base::ScopedFD StartIO(CompletionCallback callback);
 
  private:
-  std::unique_ptr<net::FileStream> data_stream_;
+  // Posts a task to read the data from the pipe. Returns
+  // net::FileStream::Read()'s result.
+  int RequestRead();
+
+  // Called when |io_buffer_| is filled via |data_stream_.Read()|.
+  void OnRead(int byte_count);
+
   scoped_refptr<net::IOBufferWithSize> io_buffer_;
   scoped_refptr<base::TaskRunner> task_runner_;
-  IOCompleteCallback callback_;
+
+  CompletionCallback callback_;
+  std::unique_ptr<net::FileStream> data_stream_;
+  std::string data_;
 
   // Note: This should remain the last member so it'll be destroyed and
   // invalidate its weak pointers before any other members are destroyed.
@@ -70,23 +72,6 @@
   DISALLOW_COPY_AND_ASSIGN(PipeReader);
 };
 
-// PipeReader subclass which accepts incoming data to a string.
-class CHROMEOS_EXPORT PipeReaderForString : public PipeReader {
- public:
-  PipeReaderForString(const scoped_refptr<base::TaskRunner>& task_runner,
-                      const IOCompleteCallback& callback);
-
-  void AcceptData(const char* data, int length) override;
-
-  // Destructively returns collected data, by swapping |data_| with |data|.
-  void GetData(std::string* data);
-
- private:
-  std::string data_;
-
-  DISALLOW_COPY_AND_ASSIGN(PipeReaderForString);
-};
-
 }  // namespace chromeos
 
 #endif  // CHROMEOS_DBUS_PIPE_READER_H_
diff --git a/chromeos/dbus/pipe_reader_unittest.cc b/chromeos/dbus/pipe_reader_unittest.cc
new file mode 100644
index 0000000..9d9693c
--- /dev/null
+++ b/chromeos/dbus/pipe_reader_unittest.cc
@@ -0,0 +1,104 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chromeos/dbus/pipe_reader.h"
+
+#include <memory>
+#include <string>
+#include <utility>
+
+#include "base/bind.h"
+#include "base/bind_helpers.h"
+#include "base/files/file_util.h"
+#include "base/files/scoped_file.h"
+#include "base/location.h"
+#include "base/memory/ref_counted.h"
+#include "base/optional.h"
+#include "base/run_loop.h"
+#include "base/task_runner.h"
+#include "base/task_scheduler/post_task.h"
+#include "base/test/scoped_task_environment.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace chromeos {
+namespace {
+
+void CopyResult(base::RunLoop* run_loop,
+                base::Optional<std::string>* output,
+                base::Optional<std::string> result) {
+  run_loop->Quit();
+  *output = std::move(result);
+}
+
+// Writes the |data| to |fd|, then close |fd|.
+void WriteData(base::ScopedFD fd, const std::string& data) {
+  EXPECT_TRUE(base::WriteFileDescriptor(fd.get(), data.data(), data.size()));
+}
+
+}  // namespace
+
+class PipeReaderTest : public testing::Test {
+ public:
+  PipeReaderTest() = default;
+  ~PipeReaderTest() override = default;
+
+  scoped_refptr<base::TaskRunner> GetTaskRunner() {
+    return task_environment_.GetMainThreadTaskRunner();
+  }
+
+ private:
+  base::test::ScopedTaskEnvironment task_environment_;
+};
+
+TEST_F(PipeReaderTest, Empty) {
+  auto reader = std::make_unique<PipeReader>(GetTaskRunner());
+  base::RunLoop run_loop;
+  base::Optional<std::string> output;
+  base::ScopedFD write_fd =
+      reader->StartIO(base::BindOnce(&CopyResult, &run_loop, &output));
+  write_fd.reset();
+  run_loop.Run();
+  EXPECT_EQ(std::string(), output);
+}
+
+TEST_F(PipeReaderTest, SmallData) {
+  constexpr char kSmallData[] = "abcdefghijklmnopqrstuvwxyz";
+
+  auto reader = std::make_unique<PipeReader>(GetTaskRunner());
+  base::RunLoop run_loop;
+  base::Optional<std::string> output;
+  base::ScopedFD write_fd =
+      reader->StartIO(base::BindOnce(&CopyResult, &run_loop, &output));
+  base::PostTask(FROM_HERE,
+                 base::BindOnce(&WriteData, std::move(write_fd), kSmallData));
+  run_loop.Run();
+  EXPECT_EQ(std::string(kSmallData), output);
+}
+
+TEST_F(PipeReaderTest, LargeData) {
+  // Larger than internal buffer size (=4096 bytes).
+  const std::string large_data(8192, 'a');
+
+  auto reader = std::make_unique<PipeReader>(GetTaskRunner());
+  base::RunLoop run_loop;
+  base::Optional<std::string> output;
+  base::ScopedFD write_fd =
+      reader->StartIO(base::BindOnce(&CopyResult, &run_loop, &output));
+  base::PostTask(FROM_HERE,
+                 base::BindOnce(&WriteData, std::move(write_fd), large_data));
+  run_loop.Run();
+  EXPECT_EQ(large_data, output);
+}
+
+TEST_F(PipeReaderTest, Cancel) {
+  auto reader = std::make_unique<PipeReader>(GetTaskRunner());
+  base::RunLoop run_loop;
+  base::ScopedFD write_fd =
+      reader->StartIO(base::BindOnce([](base::Optional<std::string> result) {
+        FAIL();  // Unexpected to be called.
+      }));
+  reader.reset();  // Delete |reader| before closing |write_fd|.
+}
+
+}  // namespace chromeos
diff --git a/chromeos/dbus/power_manager_client.cc b/chromeos/dbus/power_manager_client.cc
index 5a1eef0..90e53cb9 100644
--- a/chromeos/dbus/power_manager_client.cc
+++ b/chromeos/dbus/power_manager_client.cc
@@ -25,11 +25,11 @@
 #include "base/timer/timer.h"
 #include "chromeos/chromeos_switches.h"
 #include "chromeos/dbus/fake_power_manager_client.h"
+#include "chromeos/dbus/power_manager/idle.pb.h"
 #include "chromeos/dbus/power_manager/input_event.pb.h"
 #include "chromeos/dbus/power_manager/peripheral_battery_status.pb.h"
 #include "chromeos/dbus/power_manager/policy.pb.h"
 #include "chromeos/dbus/power_manager/power_supply_properties.pb.h"
-#include "chromeos/dbus/power_manager/suspend.pb.h"
 #include "chromeos/dbus/power_manager/switch_states.pb.h"
 #include "chromeos/system/statistics_provider.h"
 #include "components/device_event_log/device_event_log.h"
@@ -176,14 +176,14 @@
   }
 
   void GetScreenBrightnessPercent(
-      const GetScreenBrightnessPercentCallback& callback) override {
+      DBusMethodCallback<double> callback) override {
     dbus::MethodCall method_call(
         power_manager::kPowerManagerInterface,
         power_manager::kGetScreenBrightnessPercentMethod);
     power_manager_proxy_->CallMethod(
         &method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
         base::BindOnce(&PowerManagerClientImpl::OnGetScreenBrightnessPercent,
-                       weak_ptr_factory_.GetWeakPtr(), callback));
+                       weak_ptr_factory_.GetWeakPtr(), std::move(callback)));
   }
 
   void RequestStatusUpdate() override {
@@ -307,23 +307,22 @@
         dbus::ObjectProxy::EmptyResponseCallback());
   }
 
-  void GetBacklightsForcedOff(
-      const GetBacklightsForcedOffCallback& callback) override {
+  void GetBacklightsForcedOff(DBusMethodCallback<bool> callback) override {
     dbus::MethodCall method_call(power_manager::kPowerManagerInterface,
                                  power_manager::kGetBacklightsForcedOffMethod);
     power_manager_proxy_->CallMethod(
         &method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
         base::BindOnce(&PowerManagerClientImpl::OnGetBacklightsForcedOff,
-                       weak_ptr_factory_.GetWeakPtr(), callback));
+                       weak_ptr_factory_.GetWeakPtr(), std::move(callback)));
   }
 
-  void GetSwitchStates(const GetSwitchStatesCallback& callback) override {
+  void GetSwitchStates(DBusMethodCallback<SwitchStates> callback) override {
     dbus::MethodCall method_call(power_manager::kPowerManagerInterface,
                                  power_manager::kGetSwitchStatesMethod);
     power_manager_proxy_->CallMethod(
         &method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
         base::BindOnce(&PowerManagerClientImpl::OnGetSwitchStates,
-                       weak_ptr_factory_.GetWeakPtr(), callback));
+                       weak_ptr_factory_.GetWeakPtr(), std::move(callback)));
   }
 
   base::Closure GetSuspendReadinessCallback() override {
@@ -370,6 +369,14 @@
 
     power_manager_proxy_->ConnectToSignal(
         power_manager::kPowerManagerInterface,
+        power_manager::kScreenIdleStateChangedSignal,
+        base::Bind(&PowerManagerClientImpl::ScreenIdleStateChangedReceived,
+                   weak_ptr_factory_.GetWeakPtr()),
+        base::Bind(&PowerManagerClientImpl::SignalConnected,
+                   weak_ptr_factory_.GetWeakPtr()));
+
+    power_manager_proxy_->ConnectToSignal(
+        power_manager::kPowerManagerInterface,
         power_manager::kPeripheralBatteryStatusSignal,
         base::Bind(&PowerManagerClientImpl::PeripheralBatteryStatusReceived,
                    weak_ptr_factory_.GetWeakPtr()),
@@ -513,6 +520,19 @@
       observer.KeyboardBrightnessChanged(brightness_level, user_initiated);
   }
 
+  void ScreenIdleStateChangedReceived(dbus::Signal* signal) {
+    dbus::MessageReader reader(signal);
+    power_manager::ScreenIdleState proto;
+    if (!reader.PopArrayOfBytesAsProto(&proto)) {
+      POWER_LOG(ERROR) << "Unable to decode protocol buffer from "
+                       << power_manager::kScreenIdleStateChangedSignal
+                       << " signal";
+      return;
+    }
+    for (auto& observer : observers_)
+      observer.ScreenIdleStateChanged(proto);
+  }
+
   void PeripheralBatteryStatusReceived(dbus::Signal* signal) {
     dbus::MessageReader reader(signal);
     power_manager::PeripheralBatteryStatus protobuf_status;
@@ -564,14 +584,14 @@
     }
   }
 
-  void OnGetScreenBrightnessPercent(
-      const GetScreenBrightnessPercentCallback& callback,
-      dbus::Response* response) {
+  void OnGetScreenBrightnessPercent(DBusMethodCallback<double> callback,
+                                    dbus::Response* response) {
     if (!response) {
       if (!system::StatisticsProvider::GetInstance()->IsRunningOnVm()) {
         POWER_LOG(ERROR) << "Error calling "
                          << power_manager::kGetScreenBrightnessPercentMethod;
       }
+      std::move(callback).Run(base::nullopt);
       return;
     }
     dbus::MessageReader reader(response);
@@ -579,15 +599,18 @@
     if (!reader.PopDouble(&percent)) {
       POWER_LOG(ERROR) << "Error reading response from powerd: "
                        << response->ToString();
+      std::move(callback).Run(base::nullopt);
+      return;
     }
-    callback.Run(percent);
+    std::move(callback).Run(percent);
   }
 
-  void OnGetBacklightsForcedOff(const GetBacklightsForcedOffCallback& callback,
+  void OnGetBacklightsForcedOff(DBusMethodCallback<bool> callback,
                                 dbus::Response* response) {
     if (!response) {
       POWER_LOG(ERROR) << "Error calling "
                        << power_manager::kGetBacklightsForcedOffMethod;
+      std::move(callback).Run(base::nullopt);
       return;
     }
     dbus::MessageReader reader(response);
@@ -595,25 +618,32 @@
     if (!reader.PopBool(&state)) {
       POWER_LOG(ERROR) << "Error reading response from powerd: "
                        << response->ToString();
+      std::move(callback).Run(base::nullopt);
+      return;
     }
-    callback.Run(state);
+    std::move(callback).Run(state);
   }
 
-  void OnGetSwitchStates(const GetSwitchStatesCallback& callback,
+  void OnGetSwitchStates(DBusMethodCallback<SwitchStates> callback,
                          dbus::Response* response) {
     if (!response) {
       POWER_LOG(ERROR) << "Error calling "
                        << power_manager::kGetSwitchStatesMethod;
+      std::move(callback).Run(base::nullopt);
       return;
     }
+
+    dbus::MessageReader reader(response);
     power_manager::SwitchStates proto;
-    if (!dbus::MessageReader(response).PopArrayOfBytesAsProto(&proto)) {
+    if (!reader.PopArrayOfBytesAsProto(&proto)) {
       POWER_LOG(ERROR) << "Error parsing response from "
                        << power_manager::kGetSwitchStatesMethod;
+      std::move(callback).Run(base::nullopt);
       return;
     }
-    callback.Run(GetLidStateFromProtoEnum(proto.lid_state()),
-                 GetTabletModeFromProtoEnum(proto.tablet_mode()));
+    std::move(callback).Run(
+        SwitchStates{GetLidStateFromProtoEnum(proto.lid_state()),
+                     GetTabletModeFromProtoEnum(proto.tablet_mode())});
   }
 
   void HandlePowerSupplyProperties(
@@ -693,12 +723,13 @@
     // GetSuspendReadinessCallback() and then runs the callback synchonously
     // instead of asynchronously.
     notifying_observers_about_suspend_imminent_ = true;
-    if (suspending_from_dark_resume_)
+    if (suspending_from_dark_resume_) {
       for (auto& observer : observers_)
         observer.DarkSuspendImminent();
-    else
+    } else {
       for (auto& observer : observers_)
-        observer.SuspendImminent();
+        observer.SuspendImminent(proto.reason());
+    }
     notifying_observers_about_suspend_imminent_ = false;
 
     base::PowerMonitorDeviceSource::HandleSystemSuspending();
diff --git a/chromeos/dbus/power_manager_client.h b/chromeos/dbus/power_manager_client.h
index cb74071..3b145ad 100644
--- a/chromeos/dbus/power_manager_client.h
+++ b/chromeos/dbus/power_manager_client.h
@@ -14,11 +14,14 @@
 #include "chromeos/chromeos_export.h"
 #include "chromeos/dbus/dbus_client.h"
 #include "chromeos/dbus/dbus_client_implementation_type.h"
+#include "chromeos/dbus/dbus_method_call_status.h"
+#include "chromeos/dbus/power_manager/suspend.pb.h"
 #include "third_party/cros_system_api/dbus/service_constants.h"
 
 namespace power_manager {
 class PowerManagementPolicy;
 class PowerSupplyProperties;
+class ScreenIdleState;
 }
 
 namespace chromeos {
@@ -38,15 +41,10 @@
     UNSUPPORTED,
   };
 
-  // Callback used for getting the current screen brightness. The param is in
-  // the range [0.0, 100.0].
-  typedef base::Callback<void(double)> GetScreenBrightnessPercentCallback;
-
-  // Callback passed to GetBacklightsForcedOff().
-  typedef base::Callback<void(bool forced_off)> GetBacklightsForcedOffCallback;
-
-  // Callback passed to GetSwitchStates().
-  typedef base::Callback<void(LidState, TabletMode)> GetSwitchStatesCallback;
+  struct SwitchStates {
+    LidState lid_state;
+    TabletMode tablet_mode;
+  };
 
   // Interface for observing changes from the power manager.
   class Observer {
@@ -66,6 +64,10 @@
     // |user_initiated| is true if the action is initiated by the user.
     virtual void KeyboardBrightnessChanged(int level, bool user_initiated) {}
 
+    // Called when screen-related inactivity timeouts are triggered or reset.
+    virtual void ScreenIdleStateChanged(
+        const power_manager::ScreenIdleState& proto) {}
+
     // Called when peripheral device battery status is received.
     // |path| is the sysfs path for the battery of the peripheral device.
     // |name| is the human readble name of the device.
@@ -88,7 +90,8 @@
     // PowerManagerClient::GetSuspendReadinessCallback() may be called from
     // within SuspendImminent().  The returned callback must be called once
     // the observer is ready for suspend.
-    virtual void SuspendImminent() {}
+    virtual void SuspendImminent(
+        power_manager::SuspendImminent::Reason reason) {}
 
     // Called when a suspend attempt (previously announced via
     // SuspendImminent()) has completed. The system may not have actually
@@ -165,10 +168,10 @@
   virtual void SetScreenBrightnessPercent(double percent, bool gradual) = 0;
 
   // Asynchronously gets the current screen brightness, in the range
-  // [0.0, 100.0]. On error (e.g. powerd not running), |callback| will not be
-  // run.
+  // [0.0, 100.0]. On error (e.g. powerd not running), |callback| will be run
+  // with nullopt.
   virtual void GetScreenBrightnessPercent(
-      const GetScreenBrightnessPercentCallback& callback) = 0;
+      DBusMethodCallback<double> callback) = 0;
 
   // Decreases the keyboard brightness.
   virtual void DecreaseKeyboardBrightness() = 0;
@@ -218,14 +221,13 @@
   virtual void SetBacklightsForcedOff(bool forced_off) = 0;
 
   // Gets the display and (if present) keyboard backlights' forced-off state. On
-  // error (e.g. powerd not running), |callback| will not be run.
-  virtual void GetBacklightsForcedOff(
-      const GetBacklightsForcedOffCallback& callback) = 0;
+  // error (e.g. powerd not running), |callback| will be called with nullopt.
+  virtual void GetBacklightsForcedOff(DBusMethodCallback<bool> callback) = 0;
 
   // Asynchronously fetches the current state of various hardware switches (e.g.
   // the lid switch and the tablet-mode switch). On error (e.g. powerd not
-  // running), |callback| will not be run.
-  virtual void GetSwitchStates(const GetSwitchStatesCallback& callback) = 0;
+  // running), |callback| will be called with nullopt.
+  virtual void GetSwitchStates(DBusMethodCallback<SwitchStates> callback) = 0;
 
   // Returns a callback that can be called by an observer to report
   // readiness for suspend.  See Observer::SuspendImminent().
diff --git a/chromeos/dbus/power_manager_client_unittest.cc b/chromeos/dbus/power_manager_client_unittest.cc
index b3ceb69..b2430c5 100644
--- a/chromeos/dbus/power_manager_client_unittest.cc
+++ b/chromeos/dbus/power_manager_client_unittest.cc
@@ -114,7 +114,7 @@
   }
 
   // PowerManagerClient::Observer:
-  void SuspendImminent() override {
+  void SuspendImminent(power_manager::SuspendImminent::Reason reason) override {
     num_suspend_imminent_++;
     if (take_suspend_readiness_callback_)
       suspend_readiness_callback_ = client_->GetSuspendReadinessCallback();
@@ -251,6 +251,7 @@
                                  int suspend_id) {
     power_manager::SuspendImminent proto;
     proto.set_suspend_id(suspend_id);
+    proto.set_reason(power_manager::SuspendImminent_Reason_OTHER);
     dbus::Signal signal(kInterface, signal_name);
     dbus::MessageWriter(&signal).AppendProtoAsArrayOfBytes(proto);
     EmitSignal(&signal);
diff --git a/chromeos/dbus/session_manager_client.cc b/chromeos/dbus/session_manager_client.cc
index 99fd5950..faca3f8 100644
--- a/chromeos/dbus/session_manager_client.cc
+++ b/chromeos/dbus/session_manager_client.cc
@@ -101,12 +101,6 @@
   return state_keys;
 }
 
-// Turn pass-by-value into pass-by-reference as expected by StateKeysCallback.
-void RunStateKeysCallbackStub(SessionManagerClient::StateKeysCallback callback,
-                              std::vector<std::string> state_keys) {
-  callback.Run(state_keys);
-}
-
 // Helper to notify the callback with SUCCESS, to be used by the stub.
 void NotifyOnRetrievePolicySuccess(
     SessionManagerClient::RetrievePolicyCallback callback,
@@ -396,7 +390,7 @@
         dbus::ObjectProxy::EmptyResponseCallback());
   }
 
-  void GetServerBackedStateKeys(const StateKeysCallback& callback) override {
+  void GetServerBackedStateKeys(StateKeysCallback callback) override {
     dbus::MethodCall method_call(
         login_manager::kSessionManagerInterface,
         login_manager::kSessionManagerGetServerBackedStateKeys);
@@ -410,7 +404,7 @@
     session_manager_proxy_->CallMethod(
         &method_call, dbus::ObjectProxy::TIMEOUT_INFINITE,
         base::BindOnce(&SessionManagerClientImpl::OnGetServerBackedStateKeys,
-                       weak_ptr_factory_.GetWeakPtr(), callback));
+                       weak_ptr_factory_.GetWeakPtr(), std::move(callback)));
   }
 
   void StartArcInstance(ArcStartupMode startup_mode,
@@ -763,7 +757,7 @@
   }
 
   // Called when kSessionManagerGetServerBackedStateKeys method is complete.
-  void OnGetServerBackedStateKeys(const StateKeysCallback& callback,
+  void OnGetServerBackedStateKeys(StateKeysCallback callback,
                                   dbus::Response* response) {
     std::vector<std::string> state_keys;
     if (response) {
@@ -786,8 +780,7 @@
       }
     }
 
-    if (!callback.is_null())
-      callback.Run(state_keys);
+    std::move(callback).Run(state_keys);
   }
 
   void OnGetArcStartTime(DBusMethodCallback<base::TimeTicks> callback,
@@ -1032,7 +1025,7 @@
   void SetFlagsForUser(const cryptohome::Identification& cryptohome_id,
                        const std::vector<std::string>& flags) override {}
 
-  void GetServerBackedStateKeys(const StateKeysCallback& callback) override {
+  void GetServerBackedStateKeys(StateKeysCallback callback) override {
     base::FilePath owner_key_path;
     CHECK(PathService::Get(chromeos::FILE_OWNER_KEY, &owner_key_path));
     const base::FilePath state_keys_path =
@@ -1040,8 +1033,8 @@
     base::PostTaskWithTraitsAndReplyWithResult(
         FROM_HERE,
         {base::MayBlock(), base::TaskShutdownBehavior::CONTINUE_ON_SHUTDOWN},
-        base::Bind(&ReadCreateStateKeysStub, state_keys_path),
-        base::Bind(&RunStateKeysCallbackStub, callback));
+        base::BindOnce(&ReadCreateStateKeysStub, state_keys_path),
+        std::move(callback));
   }
 
   void StartArcInstance(ArcStartupMode startup_mode,
diff --git a/chromeos/dbus/session_manager_client.h b/chromeos/dbus/session_manager_client.h
index 93d520c..6fd3662 100644
--- a/chromeos/dbus/session_manager_client.h
+++ b/chromeos/dbus/session_manager_client.h
@@ -258,7 +258,7 @@
                                const std::vector<std::string>& flags) = 0;
 
   using StateKeysCallback =
-      base::Callback<void(const std::vector<std::string>& state_keys)>;
+      base::OnceCallback<void(const std::vector<std::string>& state_keys)>;
 
   // Get the currently valid server-backed state keys for the device.
   // Server-backed state keys are opaque, device-unique, time-dependent,
@@ -268,7 +268,7 @@
   // The state keys are returned asynchronously via |callback|. The callback
   // is invoked with an empty state key vector in case of errors. If the time
   // sync fails or there's no network, the callback is never invoked.
-  virtual void GetServerBackedStateKeys(const StateKeysCallback& callback) = 0;
+  virtual void GetServerBackedStateKeys(StateKeysCallback callback) = 0;
 
   // Asynchronously starts the ARC instance for the user whose cryptohome is
   // located by |cryptohome_id|.  Flag |disable_boot_completed_broadcast|
diff --git a/chromeos/disks/suspend_unmount_manager.cc b/chromeos/disks/suspend_unmount_manager.cc
index 795ac9d..c966885 100644
--- a/chromeos/disks/suspend_unmount_manager.cc
+++ b/chromeos/disks/suspend_unmount_manager.cc
@@ -30,7 +30,8 @@
     suspend_readiness_callback_.Run();
 }
 
-void SuspendUnmountManager::SuspendImminent() {
+void SuspendUnmountManager::SuspendImminent(
+    power_manager::SuspendImminent::Reason reason) {
   DCHECK(unmounting_paths_.empty());
   if (!unmounting_paths_.empty())
     return;
diff --git a/chromeos/disks/suspend_unmount_manager.h b/chromeos/disks/suspend_unmount_manager.h
index e69dfb0c..bbcd637 100644
--- a/chromeos/disks/suspend_unmount_manager.h
+++ b/chromeos/disks/suspend_unmount_manager.h
@@ -32,7 +32,7 @@
                          chromeos::MountError error_code);
 
   // PowerManagerClient::Observer
-  void SuspendImminent() override;
+  void SuspendImminent(power_manager::SuspendImminent::Reason reason) override;
   void SuspendDone(const base::TimeDelta& sleep_duration) override;
 
   // Callback passed to DiskMountManager holds weak pointers of this.
diff --git a/chromeos/disks/suspend_unmount_manager_unittest.cc b/chromeos/disks/suspend_unmount_manager_unittest.cc
index c41e88c..2c3a9bf7 100644
--- a/chromeos/disks/suspend_unmount_manager_unittest.cc
+++ b/chromeos/disks/suspend_unmount_manager_unittest.cc
@@ -7,6 +7,7 @@
 #include <vector>
 
 #include "chromeos/dbus/fake_power_manager_client.h"
+#include "chromeos/dbus/power_manager/suspend.pb.h"
 #include "chromeos/disks/disk_mount_manager.h"
 #include "chromeos/disks/mock_disk_mount_manager.h"
 #include "chromeos/disks/suspend_unmount_manager.h"
@@ -86,7 +87,8 @@
       false /* on_boot_device */, true /* on_removable_device */,
       kFileSystemType);
   disk_mount_manager_.SetupDefaultReplies();
-  fake_power_client_.SendSuspendImminent();
+  fake_power_client_.SendSuspendImminent(
+      power_manager::SuspendImminent_Reason_OTHER);
 
   EXPECT_EQ(1, fake_power_client_.GetNumPendingSuspendReadinessCallbacks());
   EXPECT_EQ(2u, disk_mount_manager_.unmounting_mount_paths().size());
@@ -114,7 +116,8 @@
       false /* on_boot_device */, true /* on_removable_device */,
       kFileSystemType);
   disk_mount_manager_.SetupDefaultReplies();
-  fake_power_client_.SendSuspendImminent();
+  fake_power_client_.SendSuspendImminent(
+      power_manager::SuspendImminent_Reason_OTHER);
   EXPECT_EQ(1, fake_power_client_.GetNumPendingSuspendReadinessCallbacks());
   ASSERT_EQ(1u, disk_mount_manager_.unmounting_mount_paths().size());
   EXPECT_EQ(kDummyMountPath,
@@ -124,12 +127,13 @@
   fake_power_client_.SendSuspendDone();
 
   // Suspend again.
-  fake_power_client_.SendSuspendImminent();
+  fake_power_client_.SendSuspendImminent(
+      power_manager::SuspendImminent_Reason_OTHER);
   ASSERT_EQ(2u, disk_mount_manager_.unmounting_mount_paths().size());
   EXPECT_EQ(kDummyMountPath,
             disk_mount_manager_.unmounting_mount_paths().front());
 }
 
 }  // namespace
-}  // namespace chromeos
 }  // namespace disks
+}  // namespace chromeos
diff --git a/chromeos/network/device_state.cc b/chromeos/network/device_state.cc
index c04486a..d33c8ed 100644
--- a/chromeos/network/device_state.cc
+++ b/chromeos/network/device_state.cc
@@ -180,4 +180,11 @@
   return technology_family_ != shill::kTechnologyFamilyCdma && !sim_present_;
 }
 
+bool DeviceState::IsSimLocked() const {
+  if (technology_family_ == shill::kTechnologyFamilyCdma || !sim_present_)
+    return false;
+  return sim_lock_type_ == shill::kSIMLockPin ||
+         sim_lock_type_ == shill::kSIMLockPuk;
+}
+
 }  // namespace chromeos
diff --git a/chromeos/network/device_state.h b/chromeos/network/device_state.h
index 6eeb8d7..69a6bbf 100644
--- a/chromeos/network/device_state.h
+++ b/chromeos/network/device_state.h
@@ -72,8 +72,9 @@
   // Returns the IP Address for |type| if it exists or an empty string.
   std::string GetIpAddressByType(const std::string& type) const;
 
-  // Returns true if the technology family is GSM and sim_present_ is false.
+  // The following return false if the technology does not require a SIM.
   bool IsSimAbsent() const;
+  bool IsSimLocked() const;
 
  private:
   // Common Device Properties
diff --git a/chromeos/network/network_change_notifier_chromeos.cc b/chromeos/network/network_change_notifier_chromeos.cc
index 8a73fc1..ede81943 100644
--- a/chromeos/network/network_change_notifier_chromeos.cc
+++ b/chromeos/network/network_change_notifier_chromeos.cc
@@ -54,7 +54,7 @@
     : NetworkChangeNotifier(NetworkChangeCalculatorParamsChromeos()),
       connection_type_(CONNECTION_NONE),
       max_bandwidth_mbps_(
-          NetworkChangeNotifier::GetMaxBandwidthForConnectionSubtype(
+          NetworkChangeNotifier::GetMaxBandwidthMbpsForConnectionSubtype(
               SUBTYPE_NONE)),
       task_runner_(base::ThreadTaskRunnerHandle::Get()),
       weak_ptr_factory_(this) {
@@ -158,7 +158,8 @@
       *connection_type_changed = true;
       *max_bandwidth_changed = true;
       connection_type_ = CONNECTION_NONE;
-      max_bandwidth_mbps_ = GetMaxBandwidthForConnectionSubtype(SUBTYPE_NONE);
+      max_bandwidth_mbps_ =
+          GetMaxBandwidthMbpsForConnectionSubtype(SUBTYPE_NONE);
       service_path_.clear();
       ip_address_.clear();
       dns_servers_.clear();
@@ -220,7 +221,7 @@
   dns_servers_ = new_dns_servers;
   double old_max_bandwidth = max_bandwidth_mbps_;
   max_bandwidth_mbps_ =
-      GetMaxBandwidthForConnectionSubtype(GetConnectionSubtype(
+      GetMaxBandwidthMbpsForConnectionSubtype(GetConnectionSubtype(
           default_network->type(), default_network->network_technology()));
   if (max_bandwidth_mbps_ != old_max_bandwidth)
     *max_bandwidth_changed = true;
diff --git a/components/arc/BUILD.gn b/components/arc/BUILD.gn
index a90bed9..bdc15bb 100644
--- a/components/arc/BUILD.gn
+++ b/components/arc/BUILD.gn
@@ -79,6 +79,7 @@
     "//components/prefs",
     "//components/session_manager/core",
     "//components/signin/core/account_id",
+    "//components/url_formatter",
     "//components/user_manager",
     "//device/bluetooth",
     "//google_apis",
diff --git a/components/arc/bluetooth/bluetooth_type_converters_unittest.cc b/components/arc/bluetooth/bluetooth_type_converters_unittest.cc
index 9ed5d7e..213c8f0 100644
--- a/components/arc/bluetooth/bluetooth_type_converters_unittest.cc
+++ b/components/arc/bluetooth/bluetooth_type_converters_unittest.cc
@@ -58,15 +58,15 @@
 bluez::BluetoothServiceAttributeValueBlueZ CreateDeepBlueZSequenceAttribute(
     size_t depth) {
   if (depth > 0u) {
-    std::unique_ptr<bluez::BluetoothServiceAttributeValueBlueZ::Sequence>
-        sequence(new bluez::BluetoothServiceAttributeValueBlueZ::Sequence());
+    auto sequence = std::make_unique<
+        bluez::BluetoothServiceAttributeValueBlueZ::Sequence>();
     sequence->push_back(CreateDeepBlueZSequenceAttribute(depth - 1));
 
     return bluez::BluetoothServiceAttributeValueBlueZ(std::move(sequence));
   } else {
     return bluez::BluetoothServiceAttributeValueBlueZ(
         bluez::BluetoothServiceAttributeValueBlueZ::UINT, sizeof(uint16_t),
-        base::WrapUnique(new base::Value(3)));
+        std::make_unique<base::Value>(3));
   }
 }
 
@@ -81,420 +81,392 @@
   return depth;
 }
 
+std::string ValueToJson(const base::Value& value) {
+  std::string json;
+  base::JSONWriter::Write(value, &json);
+  return json;
+}
+
 }  // namespace
 
 namespace mojo {
 
-TEST(BluetoothTypeConvertorTest, ConvertMojoBluetoothAddressFromString) {
-  arc::mojom::BluetoothAddressPtr addressMojo =
+TEST(BluetoothTypeConverterTest, ConvertMojoBluetoothAddressFromString) {
+  arc::mojom::BluetoothAddressPtr address_mojo =
       arc::mojom::BluetoothAddress::From(std::string(kAddressStr));
-  EXPECT_EQ(kAddressSize, addressMojo->address.size());
-  for (size_t i = 0; i < kAddressSize; i++) {
-    EXPECT_EQ(kAddressArray[i], addressMojo->address[i]);
-  }
+  EXPECT_EQ(kAddressSize, address_mojo->address.size());
+  for (size_t i = 0; i < kAddressSize; i++)
+    EXPECT_EQ(kAddressArray[i], address_mojo->address[i]);
 }
 
-TEST(BluetoothTypeConvertorTest, ConvertMojoBluetoothAddressToString) {
-  arc::mojom::BluetoothAddressPtr addressMojo =
+TEST(BluetoothTypeConverterTest, ConvertMojoBluetoothAddressToString) {
+  arc::mojom::BluetoothAddressPtr address_mojo =
       arc::mojom::BluetoothAddress::New();
-  for (size_t i = 0; i < kAddressSize - 1; i++) {
-    addressMojo->address.push_back(kAddressArray[i]);
-  }
-  EXPECT_EQ(std::string(kInvalidAddressStr), addressMojo->To<std::string>());
+  // Test address is shorter than expected (invalid address).
+  for (size_t i = 0; i < kAddressSize - 1; i++)
+    address_mojo->address.push_back(kAddressArray[i]);
+  EXPECT_EQ(kInvalidAddressStr, address_mojo->To<std::string>());
 
-  addressMojo->address.push_back(kAddressArray[kAddressSize - 1]);
-  EXPECT_EQ(std::string(kAddressStr), addressMojo->To<std::string>());
+  // Test success case.
+  address_mojo->address.push_back(kAddressArray[kAddressSize - 1]);
+  EXPECT_EQ(kAddressStr, address_mojo->To<std::string>());
 
-  addressMojo->address.push_back(kFillerByte);
-
-  EXPECT_EQ(std::string(kInvalidAddressStr), addressMojo->To<std::string>());
+  // Test address is longer than expected (invalid address).
+  address_mojo->address.push_back(kFillerByte);
+  EXPECT_EQ(kInvalidAddressStr, address_mojo->To<std::string>());
 }
 
+TEST(BluetoothTypeConverterTest,
+     ConvertMojoValueAttributeToBlueZAttribute_NullType) {
+  auto mojo = arc::mojom::BluetoothSdpAttribute::New();
+  mojo->type = bluez::BluetoothServiceAttributeValueBlueZ::NULLTYPE;
+  mojo->type_size = 0;
 
-TEST(BluetoothTypeConvertorTest, ConvertMojoValueAttributeToBlueZAttribute) {
-  // Construct Mojo attribute with NULLTYPE value.
-  auto nulltypeAttributeMojo = arc::mojom::BluetoothSdpAttribute::New();
-  nulltypeAttributeMojo->type =
-      bluez::BluetoothServiceAttributeValueBlueZ::NULLTYPE;
-  nulltypeAttributeMojo->type_size = 0;
-
-  auto nulltypeAttributeBlueZ =
-      nulltypeAttributeMojo.To<bluez::BluetoothServiceAttributeValueBlueZ>();
+  auto blue_z = mojo.To<bluez::BluetoothServiceAttributeValueBlueZ>();
 
   EXPECT_EQ(bluez::BluetoothServiceAttributeValueBlueZ::NULLTYPE,
-            nulltypeAttributeBlueZ.type());
-  EXPECT_EQ(0u, nulltypeAttributeBlueZ.size());
-  EXPECT_EQ(base::Value::Type::NONE, nulltypeAttributeBlueZ.value().GetType());
+            blue_z.type());
+  EXPECT_EQ(0u, blue_z.size());
+  EXPECT_EQ(base::Value::Type::NONE, blue_z.value().type());
+}
 
-  // Construct Mojo attribute with TYPE_BOOLEAN value.
-  bool valueBool = true;
-  auto boolAttributeMojo = arc::mojom::BluetoothSdpAttribute::New();
-  boolAttributeMojo->type = bluez::BluetoothServiceAttributeValueBlueZ::BOOL;
-  boolAttributeMojo->type_size = static_cast<uint32_t>(sizeof(valueBool));
-  std::string json;
-  base::JSONWriter::Write(base::Value(valueBool), &json);
-  boolAttributeMojo->json_value = std::move(json);
-  auto boolAttributeBlueZ =
-      boolAttributeMojo.To<bluez::BluetoothServiceAttributeValueBlueZ>();
+TEST(BluetoothTypeConverterTest,
+     ConvertMojoValueAttributeToBlueZAttribute_BoolType) {
+  auto mojo = arc::mojom::BluetoothSdpAttribute::New();
+  mojo->type = bluez::BluetoothServiceAttributeValueBlueZ::BOOL;
+  mojo->type_size = static_cast<uint32_t>(sizeof(bool));
+  mojo->json_value = ValueToJson(base::Value(true));
 
-  EXPECT_EQ(bluez::BluetoothServiceAttributeValueBlueZ::BOOL,
-            boolAttributeBlueZ.type());
-  EXPECT_EQ(sizeof(valueBool), boolAttributeBlueZ.size());
-  EXPECT_EQ(base::Value::Type::BOOLEAN, boolAttributeBlueZ.value().GetType());
-  EXPECT_TRUE(boolAttributeBlueZ.value().GetAsBoolean(&valueBool));
-  EXPECT_TRUE(valueBool);
+  auto blue_z = mojo.To<bluez::BluetoothServiceAttributeValueBlueZ>();
 
-  // Construct Mojo attribute with TYPE_UINT value.
-  uint16_t valueUint16 = 10;
-  int valueUint16AsInt = 0;
-  auto uintAttributeMojo = arc::mojom::BluetoothSdpAttribute::New();
-  uintAttributeMojo->type = bluez::BluetoothServiceAttributeValueBlueZ::UINT;
-  uintAttributeMojo->type_size = static_cast<uint32_t>(sizeof(valueUint16));
-  json.clear();
-  base::JSONWriter::Write(base::Value(static_cast<int>(valueUint16)), &json);
-  uintAttributeMojo->json_value = std::move(json);
+  EXPECT_EQ(bluez::BluetoothServiceAttributeValueBlueZ::BOOL, blue_z.type());
+  EXPECT_EQ(sizeof(bool), blue_z.size());
+  ASSERT_EQ(base::Value::Type::BOOLEAN, blue_z.value().type());
+  EXPECT_TRUE(blue_z.value().GetBool());
+}
 
-  auto uintAttributeBlueZ =
-      uintAttributeMojo.To<bluez::BluetoothServiceAttributeValueBlueZ>();
+TEST(BluetoothTypeConverterTest,
+     ConvertMojoValueAttributeToBlueZAttribute_UintType) {
+  constexpr uint16_t kValue = 10;
+  auto mojo = arc::mojom::BluetoothSdpAttribute::New();
+  mojo->type = bluez::BluetoothServiceAttributeValueBlueZ::UINT;
+  mojo->type_size = static_cast<uint32_t>(sizeof(kValue));
+  mojo->json_value = ValueToJson(base::Value(static_cast<int>(kValue)));
 
-  EXPECT_EQ(bluez::BluetoothServiceAttributeValueBlueZ::UINT,
-            uintAttributeBlueZ.type());
-  EXPECT_EQ(sizeof(valueUint16), uintAttributeBlueZ.size());
-  EXPECT_EQ(base::Value::Type::INTEGER, uintAttributeBlueZ.value().GetType());
-  EXPECT_TRUE(uintAttributeBlueZ.value().GetAsInteger(&valueUint16AsInt));
-  EXPECT_EQ(valueUint16, static_cast<uint16_t>(valueUint16AsInt));
+  auto blue_z = mojo.To<bluez::BluetoothServiceAttributeValueBlueZ>();
 
-  // Construct Mojo attribute with TYPE_INT value.
-  int16_t valueInt16 = 20;
-  int valueInt16AsInt = 0;
-  auto intAttributeMojo = arc::mojom::BluetoothSdpAttribute::New();
-  intAttributeMojo->type = bluez::BluetoothServiceAttributeValueBlueZ::INT;
-  intAttributeMojo->type_size = static_cast<uint32_t>(sizeof(valueInt16));
-  json.clear();
-  base::JSONWriter::Write(base::Value(static_cast<int>(valueInt16)), &json);
-  intAttributeMojo->json_value = std::move(json);
+  EXPECT_EQ(bluez::BluetoothServiceAttributeValueBlueZ::UINT, blue_z.type());
+  EXPECT_EQ(sizeof(kValue), blue_z.size());
+  ASSERT_EQ(base::Value::Type::INTEGER, blue_z.value().type());
+  EXPECT_EQ(kValue, static_cast<uint16_t>(blue_z.value().GetInt()));
+}
 
-  auto intAttributeBlueZ =
-      intAttributeMojo.To<bluez::BluetoothServiceAttributeValueBlueZ>();
+TEST(BluetoothTypeConverterTest,
+     ConvertMojoValueAttributeToBlueZAttribute_IntType) {
+  constexpr int16_t kValue = 20;
+  auto mojo = arc::mojom::BluetoothSdpAttribute::New();
+  mojo->type = bluez::BluetoothServiceAttributeValueBlueZ::INT;
+  mojo->type_size = static_cast<uint32_t>(sizeof(kValue));
+  mojo->json_value = ValueToJson(base::Value(static_cast<int>(kValue)));
 
-  EXPECT_EQ(bluez::BluetoothServiceAttributeValueBlueZ::INT,
-            intAttributeBlueZ.type());
-  EXPECT_EQ(sizeof(valueInt16), intAttributeBlueZ.size());
-  EXPECT_EQ(base::Value::Type::INTEGER, intAttributeBlueZ.value().GetType());
-  EXPECT_TRUE(intAttributeBlueZ.value().GetAsInteger(&valueInt16AsInt));
-  EXPECT_EQ(valueInt16, static_cast<int16_t>(valueInt16AsInt));
+  auto blue_z = mojo.To<bluez::BluetoothServiceAttributeValueBlueZ>();
 
+  EXPECT_EQ(bluez::BluetoothServiceAttributeValueBlueZ::INT, blue_z.type());
+  EXPECT_EQ(sizeof(kValue), blue_z.size());
+  ASSERT_EQ(base::Value::Type::INTEGER, blue_z.value().type());
+  EXPECT_EQ(kValue, static_cast<int16_t>(blue_z.value().GetInt()));
+}
+
+TEST(BluetoothTypeConverterTest,
+     ConvertMojoValueAttributeToBlueZAttribute_UuidType) {
   // Construct Mojo attribute with TYPE_UUID.
-  std::string expectedUUID("00000000-0000-1000-8000-00805f9b34fb");
-  std::string actualUUID;
-  auto uuidAttributeMojo = arc::mojom::BluetoothSdpAttribute::New();
-  uuidAttributeMojo->type = bluez::BluetoothServiceAttributeValueBlueZ::UUID;
+  constexpr char kValue[] = "00000000-0000-1000-8000-00805f9b34fb";
+  auto mojo = arc::mojom::BluetoothSdpAttribute::New();
+  mojo->type = bluez::BluetoothServiceAttributeValueBlueZ::UUID;
   // UUIDs are all stored in string form, but it can be converted to one of
   // UUID16, UUID32 and UUID128.
-  uuidAttributeMojo->type_size = static_cast<uint32_t>(sizeof(uint16_t));
-  json.clear();
-  base::JSONWriter::Write(base::Value(expectedUUID), &json);
-  uuidAttributeMojo->json_value = std::move(json);
+  mojo->type_size = static_cast<uint32_t>(sizeof(uint16_t));
+  mojo->json_value = ValueToJson(base::Value(kValue));
 
-  auto uuidAttributeBlueZ =
-      uuidAttributeMojo.To<bluez::BluetoothServiceAttributeValueBlueZ>();
+  auto blue_z = mojo.To<bluez::BluetoothServiceAttributeValueBlueZ>();
 
-  EXPECT_EQ(bluez::BluetoothServiceAttributeValueBlueZ::UUID,
-            uuidAttributeBlueZ.type());
-  EXPECT_EQ(sizeof(uint16_t), uuidAttributeBlueZ.size());
-  EXPECT_EQ(base::Value::Type::STRING, uuidAttributeBlueZ.value().GetType());
-  EXPECT_TRUE(uuidAttributeBlueZ.value().GetAsString(&actualUUID));
-  EXPECT_EQ(expectedUUID, actualUUID);
+  EXPECT_EQ(bluez::BluetoothServiceAttributeValueBlueZ::UUID, blue_z.type());
+  EXPECT_EQ(sizeof(uint16_t), blue_z.size());
+  ASSERT_EQ(base::Value::Type::STRING, blue_z.value().type());
+  EXPECT_EQ(kValue, blue_z.value().GetString());
+}
 
+TEST(BluetoothTypeConverterTest,
+     ConvertMojoValueAttributeToBlueZAttribute_StringType) {
   // Construct Mojo attribute with TYPE_STRING. TYPE_URL is the same case as
   // TYPE_STRING.
-  std::string expectedString("Some SDP service");
-  std::string actualString;
-  auto stringAttributeMojo = arc::mojom::BluetoothSdpAttribute::New();
-  stringAttributeMojo->type =
-      bluez::BluetoothServiceAttributeValueBlueZ::STRING;
-  stringAttributeMojo->type_size =
-      static_cast<uint32_t>(expectedString.length());
-  json.clear();
-  base::JSONWriter::Write(base::Value(expectedString), &json);
-  stringAttributeMojo->json_value = std::move(json);
+  constexpr char kValue[] = "Some SDP service";
+  constexpr size_t kValueSize = sizeof(kValue) - 1;  // Subtract '\0' size.
+  auto mojo = arc::mojom::BluetoothSdpAttribute::New();
+  mojo->type = bluez::BluetoothServiceAttributeValueBlueZ::STRING;
+  // Subtract '\0'-terminate size.
+  mojo->type_size = static_cast<uint32_t>(kValueSize);
+  mojo->json_value = ValueToJson(base::Value(kValue));
 
-  auto stringAttributeBlueZ =
-      stringAttributeMojo.To<bluez::BluetoothServiceAttributeValueBlueZ>();
+  auto blue_z = mojo.To<bluez::BluetoothServiceAttributeValueBlueZ>();
 
-  EXPECT_EQ(bluez::BluetoothServiceAttributeValueBlueZ::STRING,
-            stringAttributeBlueZ.type());
-  EXPECT_EQ(expectedString.length(), stringAttributeBlueZ.size());
-  EXPECT_EQ(base::Value::Type::STRING, stringAttributeBlueZ.value().GetType());
-  EXPECT_TRUE(stringAttributeBlueZ.value().GetAsString(&actualString));
-  EXPECT_EQ(expectedString, actualString);
+  EXPECT_EQ(bluez::BluetoothServiceAttributeValueBlueZ::STRING, blue_z.type());
+  EXPECT_EQ(kValueSize, blue_z.size());
+  ASSERT_EQ(base::Value::Type::STRING, blue_z.value().type());
+  EXPECT_EQ(kValue, blue_z.value().GetString());
 }
 
-TEST(BluetoothTypeConvertorTest, ConvertMojoSequenceAttributeToBlueZAttribute) {
-  // Create an UUID value.
-  std::string l2capUUID("00000100-0000-1000-8000-00805f9b34fb");
-  auto valueUUID = arc::mojom::BluetoothSdpAttribute::New();
-  valueUUID->type = bluez::BluetoothServiceAttributeValueBlueZ::UUID;
-  valueUUID->type_size = static_cast<uint32_t>(sizeof(uint16_t));
-  std::string json;
-  base::JSONWriter::Write(base::Value(l2capUUID), &json);
-  valueUUID->json_value = std::move(json);
-
-  // Create an UINT value.
-  uint16_t l2capChannel = 3;
-  auto valueUint16 = arc::mojom::BluetoothSdpAttribute::New();
-  valueUint16->type = bluez::BluetoothServiceAttributeValueBlueZ::UINT;
-  valueUint16->type_size = static_cast<uint32_t>(sizeof(l2capChannel));
-  json.clear();
-  base::JSONWriter::Write(base::Value(static_cast<int>(l2capChannel)), &json);
-  valueUint16->json_value = std::move(json);
+TEST(BluetoothTypeConverterTest, ConvertMojoSequenceAttributeToBlueZAttribute) {
+  constexpr char kL2capUuid[] = "00000100-0000-1000-8000-00805f9b34fb";
+  constexpr uint16_t kL2capChannel = 3;
 
   // Create a sequence with the above two values.
-  auto sequenceMojo = arc::mojom::BluetoothSdpAttribute::New();
-  sequenceMojo->type = bluez::BluetoothServiceAttributeValueBlueZ::SEQUENCE;
-  sequenceMojo->sequence.push_back(std::move(valueUUID));
-  sequenceMojo->sequence.push_back(std::move(valueUint16));
-  sequenceMojo->type_size = sequenceMojo->sequence.size();
-  sequenceMojo->json_value = base::nullopt;
+  auto sequence_mojo = arc::mojom::BluetoothSdpAttribute::New();
+  sequence_mojo->type = bluez::BluetoothServiceAttributeValueBlueZ::SEQUENCE;
+  {
+    // Create an UUID value.
+    auto value_uuid = arc::mojom::BluetoothSdpAttribute::New();
+    value_uuid->type = bluez::BluetoothServiceAttributeValueBlueZ::UUID;
+    value_uuid->type_size = static_cast<uint32_t>(sizeof(uint16_t));
+    value_uuid->json_value = ValueToJson(base::Value(kL2capUuid));
+    sequence_mojo->sequence.push_back(std::move(value_uuid));
+  }
+  {
+    // Create an UINT value.
+    auto value_channel = arc::mojom::BluetoothSdpAttribute::New();
+    value_channel->type = bluez::BluetoothServiceAttributeValueBlueZ::UINT;
+    value_channel->type_size = static_cast<uint32_t>(sizeof(kL2capChannel));
+    value_channel->json_value =
+        ValueToJson(base::Value(static_cast<int>(kL2capChannel)));
+    sequence_mojo->sequence.push_back(std::move(value_channel));
+  }
+  sequence_mojo->type_size = sequence_mojo->sequence.size();
+  sequence_mojo->json_value = base::nullopt;
 
-  auto sequenceBlueZ =
-      sequenceMojo.To<bluez::BluetoothServiceAttributeValueBlueZ>();
+  auto sequence_blue_z =
+      sequence_mojo.To<bluez::BluetoothServiceAttributeValueBlueZ>();
 
   EXPECT_EQ(bluez::BluetoothServiceAttributeValueBlueZ::SEQUENCE,
-            sequenceBlueZ.type());
-  EXPECT_EQ(sequenceMojo->sequence.size(), sequenceBlueZ.sequence().size());
+            sequence_blue_z.type());
+  EXPECT_EQ(sequence_mojo->sequence.size(), sequence_blue_z.sequence().size());
 
-  const auto& sequence = sequenceBlueZ.sequence();
-  std::string uuid;
-  EXPECT_EQ(bluez::BluetoothServiceAttributeValueBlueZ::UUID,
-            sequence.at(0).type());
-  EXPECT_EQ(sizeof(uint16_t), sequence.at(0).size());
-  EXPECT_TRUE(sequence.at(0).value().GetAsString(&uuid));
-  EXPECT_EQ(l2capUUID, uuid);
+  const auto& sequence = sequence_blue_z.sequence();
+  ASSERT_EQ(2u, sequence.size());
+  {
+    const auto& blue_z = sequence[0];
+    EXPECT_EQ(bluez::BluetoothServiceAttributeValueBlueZ::UUID, blue_z.type());
+    EXPECT_EQ(sizeof(uint16_t), blue_z.size());
+    ASSERT_EQ(base::Value::Type::STRING, blue_z.value().type());
+    EXPECT_EQ(kL2capUuid, blue_z.value().GetString());
+  }
 
-  int channel;
-  EXPECT_EQ(bluez::BluetoothServiceAttributeValueBlueZ::UINT,
-            sequence.at(1).type());
-  EXPECT_EQ(sizeof(l2capChannel), sequence.at(1).size());
-  EXPECT_TRUE(sequence.at(1).value().GetAsInteger(&channel));
-  EXPECT_EQ(l2capChannel, static_cast<uint16_t>(channel));
+  {
+    const auto& blue_z = sequence[1];
+    EXPECT_EQ(bluez::BluetoothServiceAttributeValueBlueZ::UINT, blue_z.type());
+    EXPECT_EQ(sizeof(kL2capChannel), blue_z.size());
+    ASSERT_EQ(base::Value::Type::INTEGER, blue_z.value().type());
+    EXPECT_EQ(kL2capChannel, static_cast<uint16_t>(blue_z.value().GetInt()));
+  }
 }
 
-TEST(BluetoothTypeConvertorTest,
+TEST(BluetoothTypeConverterTest,
      ConvertInvalidMojoValueAttributeToBlueZAttribute) {
   // Create a Mojo attribute without value defined.
-  auto valueNoData = arc::mojom::BluetoothSdpAttribute::New();
-  valueNoData->type = bluez::BluetoothServiceAttributeValueBlueZ::UINT;
-  valueNoData->type_size = static_cast<uint32_t>(sizeof(uint32_t));
-  valueNoData->json_value = base::nullopt;
+  auto mojo = arc::mojom::BluetoothSdpAttribute::New();
+  mojo->type = bluez::BluetoothServiceAttributeValueBlueZ::UINT;
+  mojo->type_size = static_cast<uint32_t>(sizeof(uint32_t));
+  mojo->json_value = base::nullopt;
 
-  auto valueNoDataBlueZ =
-      valueNoData.To<bluez::BluetoothServiceAttributeValueBlueZ>();
+  auto blue_z = mojo.To<bluez::BluetoothServiceAttributeValueBlueZ>();
 
   EXPECT_EQ(bluez::BluetoothServiceAttributeValueBlueZ::NULLTYPE,
-            valueNoDataBlueZ.type());
-  EXPECT_EQ(0u, valueNoDataBlueZ.size());
-  EXPECT_EQ(base::Value::Type::NONE, valueNoDataBlueZ.value().GetType());
+            blue_z.type());
+  EXPECT_EQ(0u, blue_z.size());
+  EXPECT_EQ(base::Value::Type::NONE, blue_z.value().type());
 }
 
-TEST(BluetoothTypeConvertorTest,
-     ConvertInvalidMojoSequenceAttributeToBlueZAttribute) {
+TEST(BluetoothTypeConverterTest,
+     ConvertInvalidMojoSequenceAttributeToBlueZAttribute_NoData) {
   // Create a Mojo attribute with an empty sequence.
-  auto sequenceNoData = arc::mojom::BluetoothSdpAttribute::New();
-  sequenceNoData->type = bluez::BluetoothServiceAttributeValueBlueZ::SEQUENCE;
-  sequenceNoData->type_size = 0;
-  sequenceNoData->json_value = base::nullopt;
+  auto mojo = arc::mojom::BluetoothSdpAttribute::New();
+  mojo->type = bluez::BluetoothServiceAttributeValueBlueZ::SEQUENCE;
+  mojo->type_size = 0;
+  mojo->json_value = base::nullopt;
 
-  auto sequenceNoDataBlueZ =
-      sequenceNoData.To<bluez::BluetoothServiceAttributeValueBlueZ>();
+  auto blue_z = mojo.To<bluez::BluetoothServiceAttributeValueBlueZ>();
 
   EXPECT_EQ(bluez::BluetoothServiceAttributeValueBlueZ::NULLTYPE,
-            sequenceNoDataBlueZ.type());
-  EXPECT_EQ(0u, sequenceNoDataBlueZ.size());
-  EXPECT_EQ(base::Value::Type::NONE, sequenceNoDataBlueZ.value().GetType());
+            blue_z.type());
+  EXPECT_EQ(0u, blue_z.size());
+  EXPECT_EQ(base::Value::Type::NONE, blue_z.value().type());
+}
 
+TEST(BluetoothTypeConverterTest,
+     ConvertInvalidMojoSequenceAttributeToBlueZAttribute_TooDeep) {
   // Create a Mojo attribute with the depth = arc::kBluetoothSDPMaxDepth + 3.
-  auto sequenceTooDeepMojo =
-      CreateDeepMojoSequenceAttribute(arc::kBluetoothSDPMaxDepth + 3);
-  auto sequenceTooDeepBlueZ =
-      sequenceTooDeepMojo.To<bluez::BluetoothServiceAttributeValueBlueZ>();
+  auto mojo = CreateDeepMojoSequenceAttribute(arc::kBluetoothSDPMaxDepth + 3);
+
+  auto blue_z = mojo.To<bluez::BluetoothServiceAttributeValueBlueZ>();
 
   EXPECT_EQ(bluez::BluetoothServiceAttributeValueBlueZ::SEQUENCE,
-            sequenceTooDeepBlueZ.type());
-  EXPECT_EQ(1u, sequenceTooDeepBlueZ.size());
-  EXPECT_EQ(arc::kBluetoothSDPMaxDepth,
-            GetDepthOfBlueZAttribute(sequenceTooDeepBlueZ));
+            blue_z.type());
+  EXPECT_EQ(1u, blue_z.size());
+  EXPECT_EQ(arc::kBluetoothSDPMaxDepth, GetDepthOfBlueZAttribute(blue_z));
 }
 
-TEST(BluetoothTypeConvertorTest, ConvertBlueZValueAttributeToMojoAttribute) {
+TEST(BluetoothTypeConverterTest,
+     ConvertBlueZValueAttributeToMojoAttribute_NullType) {
   // Check NULL type.
-  auto nulltypeAttributeBlueZ = bluez::BluetoothServiceAttributeValueBlueZ();
+  auto blue_z = bluez::BluetoothServiceAttributeValueBlueZ();
 
-  auto nulltypeAttributeMojo =
-      ConvertTo<arc::mojom::BluetoothSdpAttributePtr>(nulltypeAttributeBlueZ);
+  auto mojo = ConvertTo<arc::mojom::BluetoothSdpAttributePtr>(blue_z);
 
-  EXPECT_EQ(bluez::BluetoothServiceAttributeValueBlueZ::NULLTYPE,
-            nulltypeAttributeMojo->type);
-  EXPECT_EQ(0u, nulltypeAttributeMojo->type_size);
-  {
-    ASSERT_TRUE(nulltypeAttributeMojo->json_value.has_value());
-    auto value =
-        base::JSONReader::Read(nulltypeAttributeMojo->json_value.value());
-    ASSERT_TRUE(value);
-    EXPECT_TRUE(value->is_none());
-  }
+  EXPECT_EQ(bluez::BluetoothServiceAttributeValueBlueZ::NULLTYPE, mojo->type);
+  EXPECT_EQ(0u, mojo->type_size);
 
-  // Check integer types (INT, UINT).
-  uint16_t valueUint16 = 10;
-  auto uintAttributeBlueZ = bluez::BluetoothServiceAttributeValueBlueZ(
-      bluez::BluetoothServiceAttributeValueBlueZ::UINT, sizeof(valueUint16),
-      std::make_unique<base::Value>(static_cast<int>(valueUint16)));
-
-  auto uintAttributeMojo =
-      ConvertTo<arc::mojom::BluetoothSdpAttributePtr>(uintAttributeBlueZ);
-
-  EXPECT_EQ(bluez::BluetoothServiceAttributeValueBlueZ::UINT,
-            uintAttributeMojo->type);
-  EXPECT_EQ(sizeof(valueUint16), uintAttributeMojo->type_size);
-  {
-    ASSERT_TRUE(uintAttributeMojo->json_value.has_value());
-    auto value = base::JSONReader::Read(uintAttributeMojo->json_value.value());
-    ASSERT_TRUE(value);
-    ASSERT_TRUE(value->is_int());
-    EXPECT_EQ(valueUint16, static_cast<uint16_t>(value->GetInt()));
-  }
-
-  // Check bool type.
-  bool valueBool = false;
-  auto boolAttributeBlueZ = bluez::BluetoothServiceAttributeValueBlueZ(
-      bluez::BluetoothServiceAttributeValueBlueZ::BOOL, sizeof(bool),
-      std::make_unique<base::Value>(valueBool));
-
-  auto boolAttributeMojo =
-      ConvertTo<arc::mojom::BluetoothSdpAttributePtr>(boolAttributeBlueZ);
-
-  EXPECT_EQ(bluez::BluetoothServiceAttributeValueBlueZ::BOOL,
-            boolAttributeMojo->type);
-  EXPECT_EQ(static_cast<uint32_t>(sizeof(valueBool)),
-            boolAttributeMojo->type_size);
-  {
-    ASSERT_TRUE(boolAttributeMojo->json_value.has_value());
-    auto value = base::JSONReader::Read(boolAttributeMojo->json_value.value());
-    ASSERT_TRUE(value);
-    ASSERT_TRUE(value->is_bool());
-    EXPECT_FALSE(value->GetBool());
-  }
-
-  // Check UUID type.
-  std::string valueUUID("00000100-0000-1000-8000-00805f9b34fb");
-  auto uuidAttributeBlueZ = bluez::BluetoothServiceAttributeValueBlueZ(
-      bluez::BluetoothServiceAttributeValueBlueZ::UUID, sizeof(uint16_t),
-      std::make_unique<base::Value>(valueUUID));
-
-  auto uuidAttributeMojo =
-      ConvertTo<arc::mojom::BluetoothSdpAttributePtr>(uuidAttributeBlueZ);
-
-  EXPECT_EQ(bluez::BluetoothServiceAttributeValueBlueZ::UUID,
-            uuidAttributeMojo->type);
-  EXPECT_EQ(static_cast<uint32_t>(sizeof(uint16_t)),
-            uuidAttributeMojo->type_size);
-  {
-    ASSERT_TRUE(uuidAttributeMojo->json_value.has_value());
-    auto value = base::JSONReader::Read(uuidAttributeMojo->json_value.value());
-    ASSERT_TRUE(value);
-    ASSERT_TRUE(value->is_string());
-    EXPECT_EQ(valueUUID, value->GetString());
-  }
-
-  // Check string types (STRING, URL).
-  std::string valueString("Some Service Name");
-  auto stringAttributeBlueZ = bluez::BluetoothServiceAttributeValueBlueZ(
-      bluez::BluetoothServiceAttributeValueBlueZ::STRING, valueString.length(),
-      std::make_unique<base::Value>(valueString));
-
-  auto stringAttributeMojo =
-      ConvertTo<arc::mojom::BluetoothSdpAttributePtr>(stringAttributeBlueZ);
-
-  EXPECT_EQ(bluez::BluetoothServiceAttributeValueBlueZ::STRING,
-            stringAttributeMojo->type);
-  EXPECT_EQ(static_cast<uint32_t>(valueString.length()),
-            stringAttributeMojo->type_size);
-  {
-    ASSERT_TRUE(stringAttributeMojo->json_value.has_value());
-    auto value =
-        base::JSONReader::Read(stringAttributeMojo->json_value.value());
-    ASSERT_TRUE(value);
-    ASSERT_TRUE(value->is_string());
-    EXPECT_EQ(valueString, value->GetString());
-  }
+  ASSERT_TRUE(mojo->json_value.has_value());
+  auto value = base::JSONReader::Read(mojo->json_value.value());
+  ASSERT_TRUE(value);
+  EXPECT_TRUE(value->is_none());
 }
 
-TEST(BluetoothTypeConvertorTest, ConvertBlueZSequenceAttributeToMojoAttribute) {
-  std::string l2capUUID("00000100-0000-1000-8000-00805f9b34fb");
-  uint16_t l2capChannel = 3;
+TEST(BluetoothTypeConverterTest,
+     ConvertBlueZValueAttributeToMojoAttribute_UintType) {
+  // Check integer types (INT, UINT).
+  constexpr uint16_t kValue = 10;
+  auto blue_z = bluez::BluetoothServiceAttributeValueBlueZ(
+      bluez::BluetoothServiceAttributeValueBlueZ::UINT, sizeof(kValue),
+      std::make_unique<base::Value>(static_cast<int>(kValue)));
 
-  std::unique_ptr<bluez::BluetoothServiceAttributeValueBlueZ::Sequence>
-      sequence(new bluez::BluetoothServiceAttributeValueBlueZ::Sequence());
+  auto mojo = ConvertTo<arc::mojom::BluetoothSdpAttributePtr>(blue_z);
+
+  EXPECT_EQ(bluez::BluetoothServiceAttributeValueBlueZ::UINT, mojo->type);
+  EXPECT_EQ(sizeof(kValue), mojo->type_size);
+
+  ASSERT_TRUE(mojo->json_value.has_value());
+  auto value = base::JSONReader::Read(mojo->json_value.value());
+  ASSERT_TRUE(value);
+  ASSERT_TRUE(value->is_int());
+  EXPECT_EQ(kValue, static_cast<uint16_t>(value->GetInt()));
+}
+
+TEST(BluetoothTypeConverterTest,
+     ConvertBlueZValueAttributeToMojoAttribute_BoolType) {
+  // Check bool type.
+  auto blue_z = bluez::BluetoothServiceAttributeValueBlueZ(
+      bluez::BluetoothServiceAttributeValueBlueZ::BOOL, sizeof(bool),
+      std::make_unique<base::Value>(false));
+
+  auto mojo = ConvertTo<arc::mojom::BluetoothSdpAttributePtr>(blue_z);
+
+  EXPECT_EQ(bluez::BluetoothServiceAttributeValueBlueZ::BOOL, mojo->type);
+  EXPECT_EQ(static_cast<uint32_t>(sizeof(bool)), mojo->type_size);
+
+  ASSERT_TRUE(mojo->json_value.has_value());
+  auto value = base::JSONReader::Read(mojo->json_value.value());
+  ASSERT_TRUE(value);
+  ASSERT_TRUE(value->is_bool());
+  EXPECT_FALSE(value->GetBool());
+}
+
+TEST(BluetoothTypeConverterTest,
+     ConvertBlueZValueAttributeToMojoAttribute_UuidType) {
+  // Check UUID type.
+  constexpr char kValue[] = "00000100-0000-1000-8000-00805f9b34fb";
+  auto blue_z = bluez::BluetoothServiceAttributeValueBlueZ(
+      bluez::BluetoothServiceAttributeValueBlueZ::UUID, sizeof(uint16_t),
+      std::make_unique<base::Value>(kValue));
+
+  auto mojo = ConvertTo<arc::mojom::BluetoothSdpAttributePtr>(blue_z);
+
+  EXPECT_EQ(bluez::BluetoothServiceAttributeValueBlueZ::UUID, mojo->type);
+  EXPECT_EQ(static_cast<uint32_t>(sizeof(uint16_t)), mojo->type_size);
+
+  ASSERT_TRUE(mojo->json_value.has_value());
+  auto value = base::JSONReader::Read(mojo->json_value.value());
+  ASSERT_TRUE(value);
+  ASSERT_TRUE(value->is_string());
+  EXPECT_EQ(kValue, value->GetString());
+}
+
+TEST(BluetoothTypeConverterTest,
+     ConvertBlueZValueAttributeToMojoAttribute_StringType) {
+  // Check string types (STRING, URL).
+  constexpr char kValue[] = "Some Service Name";
+  constexpr size_t kValueSize = sizeof(kValue) - 1;  // Subtract '\0' size.
+  auto blue_z = bluez::BluetoothServiceAttributeValueBlueZ(
+      bluez::BluetoothServiceAttributeValueBlueZ::STRING, kValueSize,
+      std::make_unique<base::Value>(kValue));
+
+  auto mojo = ConvertTo<arc::mojom::BluetoothSdpAttributePtr>(blue_z);
+
+  EXPECT_EQ(bluez::BluetoothServiceAttributeValueBlueZ::STRING, mojo->type);
+  EXPECT_EQ(static_cast<uint32_t>(kValueSize), mojo->type_size);
+
+  ASSERT_TRUE(mojo->json_value.has_value());
+  auto value = base::JSONReader::Read(mojo->json_value.value());
+  ASSERT_TRUE(value);
+  ASSERT_TRUE(value->is_string());
+  EXPECT_EQ(kValue, value->GetString());
+}
+
+TEST(BluetoothTypeConverterTest, ConvertBlueZSequenceAttributeToMojoAttribute) {
+  constexpr char kL2capUuid[] = "00000100-0000-1000-8000-00805f9b34fb";
+  constexpr uint16_t kL2capChannel = 3;
+
+  auto sequence =
+      std::make_unique<bluez::BluetoothServiceAttributeValueBlueZ::Sequence>();
   sequence->push_back(bluez::BluetoothServiceAttributeValueBlueZ(
       bluez::BluetoothServiceAttributeValueBlueZ::UUID, sizeof(uint16_t),
-      std::make_unique<base::Value>(l2capUUID)));
+      std::make_unique<base::Value>(kL2capUuid)));
   sequence->push_back(bluez::BluetoothServiceAttributeValueBlueZ(
       bluez::BluetoothServiceAttributeValueBlueZ::UINT, sizeof(uint16_t),
-      std::make_unique<base::Value>(l2capChannel)));
+      std::make_unique<base::Value>(kL2capChannel)));
 
-  auto sequenceBlueZ =
-      bluez::BluetoothServiceAttributeValueBlueZ(std::move(sequence));
+  auto blue_z = bluez::BluetoothServiceAttributeValueBlueZ(std::move(sequence));
+  ASSERT_EQ(2u, blue_z.sequence().size());
 
-  ASSERT_EQ(2u, sequenceBlueZ.sequence().size());
-
-  auto sequenceMojo =
-      ConvertTo<arc::mojom::BluetoothSdpAttributePtr>(sequenceBlueZ);
+  auto sequence_mojo = ConvertTo<arc::mojom::BluetoothSdpAttributePtr>(blue_z);
 
   EXPECT_EQ(bluez::BluetoothServiceAttributeValueBlueZ::SEQUENCE,
-            sequenceMojo->type);
-  EXPECT_EQ(static_cast<uint32_t>(sequenceBlueZ.size()),
-            sequenceMojo->type_size);
-  EXPECT_EQ(sequenceMojo->type_size, sequenceMojo->sequence.size());
+            sequence_mojo->type);
+  EXPECT_EQ(static_cast<uint32_t>(blue_z.size()), sequence_mojo->type_size);
+  EXPECT_EQ(sequence_mojo->type_size, sequence_mojo->sequence.size());
 
-  EXPECT_EQ(bluez::BluetoothServiceAttributeValueBlueZ::UUID,
-            sequenceMojo->sequence[0]->type);
-  EXPECT_EQ(static_cast<uint32_t>(sizeof(uint16_t)),
-            sequenceMojo->sequence[0]->type_size);
   {
-    ASSERT_TRUE(sequenceMojo->sequence[0]->json_value.has_value());
-    auto value =
-        base::JSONReader::Read(sequenceMojo->sequence[0]->json_value.value());
+    const auto& mojo = sequence_mojo->sequence[0];
+    EXPECT_EQ(bluez::BluetoothServiceAttributeValueBlueZ::UUID, mojo->type);
+    EXPECT_EQ(static_cast<uint32_t>(sizeof(uint16_t)), mojo->type_size);
+
+    ASSERT_TRUE(mojo->json_value.has_value());
+    auto value = base::JSONReader::Read(mojo->json_value.value());
     ASSERT_TRUE(value);
     ASSERT_TRUE(value->is_string());
-    EXPECT_EQ(l2capUUID, value->GetString());
+    EXPECT_EQ(kL2capUuid, value->GetString());
   }
 
-  EXPECT_EQ(bluez::BluetoothServiceAttributeValueBlueZ::UINT,
-            sequenceMojo->sequence[1]->type);
-  EXPECT_EQ(static_cast<uint32_t>(sizeof(uint16_t)),
-            sequenceMojo->sequence[1]->type_size);
   {
-    ASSERT_TRUE(sequenceMojo->sequence[1]->json_value.has_value());
-    auto value =
-        base::JSONReader::Read(sequenceMojo->sequence[1]->json_value.value());
+    const auto& mojo = sequence_mojo->sequence[1];
+    EXPECT_EQ(bluez::BluetoothServiceAttributeValueBlueZ::UINT, mojo->type);
+    EXPECT_EQ(static_cast<uint32_t>(sizeof(uint16_t)), mojo->type_size);
+    ASSERT_TRUE(mojo->json_value.has_value());
+    auto value = base::JSONReader::Read(mojo->json_value.value());
     ASSERT_TRUE(value);
     ASSERT_TRUE(value->is_int());
-    EXPECT_EQ(l2capChannel, static_cast<uint16_t>(value->GetInt()));
+    EXPECT_EQ(kL2capChannel, static_cast<uint16_t>(value->GetInt()));
   }
 }
 
-TEST(BluetoothTypeConvertorTest,
-     ConvertDeepBlueZSequenceAttributeToBlueZAttribute) {
-  bluez::BluetoothServiceAttributeValueBlueZ sequenceBlueZ =
+TEST(BluetoothTypeConverterTest,
+     ConvertInvalidBlueZSequenceAttributeToBlueZAttribute_TooDeep) {
+  bluez::BluetoothServiceAttributeValueBlueZ blue_z =
       CreateDeepBlueZSequenceAttribute(arc::kBluetoothSDPMaxDepth + 3);
 
-  auto sequenceMojo =
-      ConvertTo<arc::mojom::BluetoothSdpAttributePtr>(sequenceBlueZ);
+  auto mojo = ConvertTo<arc::mojom::BluetoothSdpAttributePtr>(blue_z);
 
-  EXPECT_EQ(bluez::BluetoothServiceAttributeValueBlueZ::SEQUENCE,
-            sequenceMojo->type);
-  EXPECT_EQ((uint32_t)1, sequenceMojo->type_size);
-  EXPECT_EQ(arc::kBluetoothSDPMaxDepth, GetDepthOfMojoAttribute(sequenceMojo));
+  EXPECT_EQ(bluez::BluetoothServiceAttributeValueBlueZ::SEQUENCE, mojo->type);
+  EXPECT_EQ(1u, mojo->type_size);
+  EXPECT_EQ(arc::kBluetoothSDPMaxDepth, GetDepthOfMojoAttribute(mojo));
 }
 
 }  // namespace mojo
diff --git a/components/arc/common/video_encode_accelerator.mojom b/components/arc/common/video_encode_accelerator.mojom
index 2aaf61e5..edba8d9 100644
--- a/components/arc/common/video_encode_accelerator.mojom
+++ b/components/arc/common/video_encode_accelerator.mojom
@@ -72,7 +72,7 @@
 
 // Video encoder IPC interface.
 // Next MinVersion: 1
-// Next Method ID: 5
+// Next Method ID: 6
 interface VideoEncodeAccelerator {
 
   // The input buffer storage type.
@@ -162,6 +162,14 @@
   //  |framerate| is the requested new framerate, in frames per second.
   RequestEncodingParametersChange@4(uint32 bitrate,
                                     uint32 framerate);
+
+  // Flushes the encoder: all pending inputs will be encoded and all bitstreams
+  // handed back to the client. The client should not invoke Flush() or
+  // Encode() before the previous Flush() is finished.
+  // Callback:
+  //  Called with |true| if Flush() is complete; with |false| if Flush() is
+  //  canceled.
+  Flush@5() => (bool flush_done);
 };
 
 // Interface for clients that use VideoEncodeAccelerator. These callbacks will
diff --git a/components/arc/intent_helper/DEPS b/components/arc/intent_helper/DEPS
index e2ab3722..71b1718 100644
--- a/components/arc/intent_helper/DEPS
+++ b/components/arc/intent_helper/DEPS
@@ -6,6 +6,7 @@
   "+ash/shell_delegate.h",
   "+ash/wallpaper/wallpaper_controller.h",
   "+components/google/core/browser",
+  "+components/url_formatter",
   "+ui/base",
   "+ui/gfx",
 ]
diff --git a/components/arc/intent_helper/arc_intent_helper_bridge.cc b/components/arc/intent_helper/arc_intent_helper_bridge.cc
index f470a46..60245bd 100644
--- a/components/arc/intent_helper/arc_intent_helper_bridge.cc
+++ b/components/arc/intent_helper/arc_intent_helper_bridge.cc
@@ -16,6 +16,7 @@
 #include "components/arc/arc_browser_context_keyed_service_factory_base.h"
 #include "components/arc/arc_service_manager.h"
 #include "components/arc/audio/arc_audio_bridge.h"
+#include "components/url_formatter/url_fixer.h"
 #include "ui/base/layout.h"
 #include "url/gurl.h"
 
@@ -124,9 +125,11 @@
 
 void ArcIntentHelperBridge::OnOpenUrl(const std::string& url) {
   DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
-  const GURL gurl(url);
+  // Converts |url| to a fixed-up one. This converts about: URIs to chrome://,
+  // for example.
+  const GURL gurl(url_formatter::FixupURL(url, std::string()));
   // Disallow opening chrome:// URLs.
-  if (gurl.SchemeIs(kChromeUIScheme))
+  if (!gurl.is_valid() || gurl.SchemeIs(kChromeUIScheme))
     return;
   open_url_delegate_->OpenUrl(gurl);
 }
diff --git a/components/arc/intent_helper/arc_intent_helper_bridge_unittest.cc b/components/arc/intent_helper/arc_intent_helper_bridge_unittest.cc
index e1ca752e..4e3d19a3 100644
--- a/components/arc/intent_helper/arc_intent_helper_bridge_unittest.cc
+++ b/components/arc/intent_helper/arc_intent_helper_bridge_unittest.cc
@@ -284,13 +284,20 @@
             test_open_url_delegate_->TakeLastOpenedUrl());
 }
 
-// Tests that OnOpenUrl does not open URLs with the 'chrome' scheme.
+// Tests that OnOpenUrl does not open URLs with the 'chrome://' and equivalent
+// schemes like 'about:'.
 TEST_F(ArcIntentHelperTest, TestOnOpenUrl_ChromeScheme) {
   instance_->OnOpenUrl("chrome://www.google.com");
   EXPECT_FALSE(test_open_url_delegate_->TakeLastOpenedUrl().is_valid());
 
   instance_->OnOpenUrl("chrome://settings");
   EXPECT_FALSE(test_open_url_delegate_->TakeLastOpenedUrl().is_valid());
+
+  instance_->OnOpenUrl("about:");
+  EXPECT_FALSE(test_open_url_delegate_->TakeLastOpenedUrl().is_valid());
+
+  instance_->OnOpenUrl("about:settings");
+  EXPECT_FALSE(test_open_url_delegate_->TakeLastOpenedUrl().is_valid());
 }
 
 // Tests that OnOpenChromeSettingsMultideviceUrl opens the multidevice settings
diff --git a/components/arc/power/arc_power_bridge.cc b/components/arc/power/arc_power_bridge.cc
index ef6a083..d488938 100644
--- a/components/arc/power/arc_power_bridge.cc
+++ b/components/arc/power/arc_power_bridge.cc
@@ -79,8 +79,8 @@
   chromeos::DBusThreadManager::Get()
       ->GetPowerManagerClient()
       ->GetScreenBrightnessPercent(
-          base::Bind(&ArcPowerBridge::UpdateAndroidScreenBrightness,
-                     weak_ptr_factory_.GetWeakPtr()));
+          base::BindOnce(&ArcPowerBridge::OnGetScreenBrightnessPercent,
+                         weak_ptr_factory_.GetWeakPtr()));
 }
 
 void ArcPowerBridge::OnInstanceClosed() {
@@ -92,7 +92,8 @@
   ReleaseAllDisplayWakeLocks();
 }
 
-void ArcPowerBridge::SuspendImminent() {
+void ArcPowerBridge::SuspendImminent(
+    power_manager::SuspendImminent::Reason reason) {
   mojom::PowerInstance* power_instance =
       ARC_GET_INSTANCE_FOR_METHOD(arc_bridge_service_->power(), Suspend);
   if (!power_instance)
@@ -214,6 +215,16 @@
   wake_locks_.clear();
 }
 
+void ArcPowerBridge::OnGetScreenBrightnessPercent(
+    base::Optional<double> percent) {
+  if (!percent.has_value()) {
+    LOG(ERROR)
+        << "PowerManagerClient::GetScreenBrightnessPercent reports an error";
+    return;
+  }
+  UpdateAndroidScreenBrightness(percent.value());
+}
+
 void ArcPowerBridge::UpdateAndroidScreenBrightness(double percent) {
   mojom::PowerInstance* power_instance = ARC_GET_INSTANCE_FOR_METHOD(
       arc_bridge_service_->power(), UpdateScreenBrightnessSettings);
diff --git a/components/arc/power/arc_power_bridge.h b/components/arc/power/arc_power_bridge.h
index 5aab165..3681440 100644
--- a/components/arc/power/arc_power_bridge.h
+++ b/components/arc/power/arc_power_bridge.h
@@ -8,6 +8,7 @@
 #include <map>
 
 #include "base/macros.h"
+#include "base/optional.h"
 #include "chromeos/dbus/power_manager_client.h"
 #include "components/arc/common/power.mojom.h"
 #include "components/arc/instance_holder.h"
@@ -44,7 +45,7 @@
   void OnInstanceClosed() override;
 
   // chromeos::PowerManagerClient::Observer overrides.
-  void SuspendImminent() override;
+  void SuspendImminent(power_manager::SuspendImminent::Reason reason) override;
   void SuspendDone(const base::TimeDelta& sleep_duration) override;
   void BrightnessChanged(int level, bool user_initiated) override;
 
@@ -58,6 +59,9 @@
   void OnScreenBrightnessUpdateRequest(double percent) override;
 
  private:
+  // Called on PowerManagerClient::GetScreenBrightnessPercent() completion.
+  void OnGetScreenBrightnessPercent(base::Optional<double> percent);
+
   void ReleaseAllDisplayWakeLocks();
   void UpdateAndroidScreenBrightness(double percent);
 
diff --git a/components/autofill/content/renderer/autofill_agent.cc b/components/autofill/content/renderer/autofill_agent.cc
index 5349ab0..515b9da 100644
--- a/components/autofill/content/renderer/autofill_agent.cc
+++ b/components/autofill/content/renderer/autofill_agent.cc
@@ -738,7 +738,7 @@
 void AutofillAgent::DoFillFieldWithValue(const base::string16& value,
                                          WebInputElement* node) {
   base::AutoReset<bool> auto_reset(&ignore_text_changes_, true);
-  node->SetEditingValue(
+  node->SetAutofillValue(
       blink::WebString::FromUTF16(value.substr(0, node->MaxLength())));
   password_autofill_agent_->UpdateStateForTextChange(*node);
 }
diff --git a/components/autofill/core/browser/credit_card_save_manager.cc b/components/autofill/core/browser/credit_card_save_manager.cc
index 905518ef..4daa56a9 100644
--- a/components/autofill/core/browser/credit_card_save_manager.cc
+++ b/components/autofill/core/browser/credit_card_save_manager.cc
@@ -407,43 +407,38 @@
 
 void CreditCardSaveManager::OnUserDidAcceptUpload() {
   user_did_accept_upload_prompt_ = true;
-  if (!upload_request_.risk_data.empty()) {
-    upload_request_.app_locale = app_locale_;
-    // If the upload request does not have card CVC, populate it with the
-    // value provided by the user:
-    if (upload_request_.cvc.empty()) {
-      DCHECK(client_->GetSaveCardBubbleController());
-      upload_request_.cvc =
-          client_->GetSaveCardBubbleController()->GetCvcEnteredByUser();
-    }
-    if (IsAutofillSendBillingCustomerNumberExperimentEnabled()) {
-      upload_request_.billing_customer_number =
-          static_cast<int64_t>(payments_client_->GetPrefService()->GetDouble(
-              prefs::kAutofillBillingCustomerNumber));
-    }
-    payments_client_->UploadCard(upload_request_);
-  }
+  // Populating risk data and offering upload occur asynchronously.
+  // If |risk_data| has already been loaded, send the upload card request.
+  // Otherwise, continue to wait and let OnDidGetUploadRiskData handle it.
+  if (!upload_request_.risk_data.empty())
+    SendUploadCardRequest();
 }
 
 void CreditCardSaveManager::OnDidGetUploadRiskData(
     const std::string& risk_data) {
   upload_request_.risk_data = risk_data;
-  if (user_did_accept_upload_prompt_) {
-    upload_request_.app_locale = app_locale_;
-    // If the upload request does not have card CVC, populate it with the
-    // value provided by the user:
-    if (upload_request_.cvc.empty()) {
-      DCHECK(client_->GetSaveCardBubbleController());
-      upload_request_.cvc =
-          client_->GetSaveCardBubbleController()->GetCvcEnteredByUser();
-    }
-    if (IsAutofillSendBillingCustomerNumberExperimentEnabled()) {
-      upload_request_.billing_customer_number =
-          static_cast<int64_t>(payments_client_->GetPrefService()->GetDouble(
-              prefs::kAutofillBillingCustomerNumber));
-    }
-    payments_client_->UploadCard(upload_request_);
+  // Populating risk data and offering upload occur asynchronously.
+  // If the dialog has already been accepted, send the upload card request.
+  // Otherwise, continue to wait for the user to accept the save dialog.
+  if (user_did_accept_upload_prompt_)
+    SendUploadCardRequest();
+}
+
+void CreditCardSaveManager::SendUploadCardRequest() {
+  upload_request_.app_locale = app_locale_;
+  // If the upload request does not have card CVC, populate it with the value
+  // provided by the user:
+  if (upload_request_.cvc.empty()) {
+    DCHECK(client_->GetSaveCardBubbleController());
+    upload_request_.cvc =
+        client_->GetSaveCardBubbleController()->GetCvcEnteredByUser();
   }
+  if (IsAutofillSendBillingCustomerNumberExperimentEnabled()) {
+    upload_request_.billing_customer_number =
+        static_cast<int64_t>(payments_client_->GetPrefService()->GetDouble(
+            prefs::kAutofillBillingCustomerNumber));
+  }
+  payments_client_->UploadCard(upload_request_);
 }
 
 AutofillMetrics::CardUploadDecisionMetric
diff --git a/components/autofill/core/browser/credit_card_save_manager.h b/components/autofill/core/browser/credit_card_save_manager.h
index 8a6f48c8..eda8e83 100644
--- a/components/autofill/core/browser/credit_card_save_manager.h
+++ b/components/autofill/core/browser/credit_card_save_manager.h
@@ -70,14 +70,17 @@
       const CreditCard& card,
       payments::PaymentsClient::UploadRequestDetails* upload_request) const;
 
-  // Sets |user_did_accept_upload_prompt_| and calls UploadCard if the risk data
-  // is available.
+  // Sets |user_did_accept_upload_prompt_| and calls SendUploadCardRequest if
+  // the risk data is available.
   void OnUserDidAcceptUpload();
 
-  // Saves risk data in |uploading_risk_data_| and calls UploadCard if the user
-  // has accepted the prompt.
+  // Saves risk data in |uploading_risk_data_| and calls SendUploadCardRequest
+  // if the user has accepted the prompt.
   void OnDidGetUploadRiskData(const std::string& risk_data);
 
+  // Finalizes the upload request and calls PaymentsClient::UploadCard().
+  void SendUploadCardRequest();
+
   // Returns metric relevant to the CVC field based on values in
   // |found_cvc_field_|, |found_value_in_cvc_field_| and
   // |found_cvc_value_in_non_cvc_field_|.
diff --git a/components/autofill/core/browser/form_data_importer.cc b/components/autofill/core/browser/form_data_importer.cc
index efe1ea09..f7b3650 100644
--- a/components/autofill/core/browser/form_data_importer.cc
+++ b/components/autofill/core/browser/form_data_importer.cc
@@ -122,16 +122,17 @@
 
   if (!credit_card_save_manager_->IsCreditCardUploadEnabled() ||
       imported_credit_card_matches_masked_server_credit_card) {
-    // This block will only be reached if we have observed a new card or a card
-    // whose |TypeAndLastFourDigits| matches a masked server card.
-    // |ImportFormData| will return false if the card matches a full card that
-    // we have already stored.
+    // Offer local save. This block will only be reached if we have observed a
+    // new card or a card whose |TypeAndLastFourDigits| matches a masked server
+    // card. |ImportFormData| will return false if the card matches a full card
+    // that we have already stored.
     credit_card_save_manager_->OfferCardLocalSave(*imported_credit_card);
   } else {
-    // Whereas, because we pass IsCreditCardUploadEnabled() to ImportFormData,
-    // this block can be reached on observing either a new card or one already
-    // stored locally and whose |TypeAndLastFourDigits| do not match a masked
-    // server card. We will offer to upload either kind.
+    // Attempt to offer upload save. Because we pass IsCreditCardUploadEnabled()
+    // to ImportFormData, this block can be reached on observing either a new
+    // card or one already stored locally and whose |TypeAndLastFourDigits| do
+    // not match a masked server card. We can offer to upload either kind, but
+    // note that they must pass address/name/CVC validation requirements first.
     credit_card_save_manager_->AttemptToOfferCardUploadSave(
         submitted_form, *imported_credit_card);
   }
diff --git a/components/autofill/core/browser/form_structure.cc b/components/autofill/core/browser/form_structure.cc
index 0c692a4d..2920a9b 100644
--- a/components/autofill/core/browser/form_structure.cc
+++ b/components/autofill/core/browser/form_structure.cc
@@ -303,6 +303,149 @@
   return true;
 }
 
+// Helper function that rationalizes phone numbers fields in the given
+// vector of fields. The vector of fields are expected to have all fields
+// for a certain section.
+void RationalizePhoneNumberFieldPredictionsInSection(
+    std::vector<AutofillField*>* fields_in_section) {
+  AutofillField* found_number_field = nullptr;
+  AutofillField* found_number_field_second = nullptr;
+  AutofillField* found_city_code_field = nullptr;
+  AutofillField* found_country_code_field = nullptr;
+  AutofillField* found_city_and_number_field = nullptr;
+  AutofillField* found_whole_number_field = nullptr;
+  bool phone_number_found = false;
+  bool phone_number_separate_fields = false;
+  // Iterate through all given fields. Iteration stops when it first finds a
+  // valid set of fields that can compose a whole number. The |found_*| pointers
+  // will be set to that set of fields when iteration finishes.
+  for (AutofillField* field : *fields_in_section) {
+    ServerFieldType current_field_type = field->Type().GetStorableType();
+    switch (current_field_type) {
+      case PHONE_HOME_NUMBER:
+      case PHONE_BILLING_NUMBER:
+        if (!found_number_field) {
+          found_number_field = field;
+          if (field->max_length < 5) {
+            phone_number_separate_fields = true;
+          } else {
+            phone_number_found = true;
+          }
+          break;
+        }
+        // If the form has phone number separated into exchange and subscriber
+        // number we mark both of them as number fields.
+        // TODO(wuandy): A less hacky solution to have dedicated enum for
+        // exchange and subscriber number.
+        DCHECK(phone_number_separate_fields);
+        DCHECK(!found_number_field_second);
+        found_number_field_second = field;
+        phone_number_found = true;
+        break;
+      case PHONE_HOME_CITY_CODE:
+      case PHONE_BILLING_CITY_CODE:
+        if (!found_city_code_field)
+          found_city_code_field = field;
+        break;
+      case PHONE_HOME_COUNTRY_CODE:
+      case PHONE_BILLING_COUNTRY_CODE:
+        if (!found_country_code_field)
+          found_country_code_field = field;
+        break;
+      case PHONE_HOME_CITY_AND_NUMBER:
+      case PHONE_BILLING_CITY_AND_NUMBER:
+        DCHECK(!phone_number_found && !found_city_and_number_field);
+        found_city_and_number_field = field;
+        phone_number_found = true;
+        break;
+      case PHONE_HOME_WHOLE_NUMBER:
+      case PHONE_BILLING_WHOLE_NUMBER:
+        DCHECK(!phone_number_found && !found_whole_number_field);
+        found_whole_number_field = field;
+        phone_number_found = true;
+        break;
+      default:
+        break;
+    }
+    if (phone_number_found)
+      break;
+  }
+
+  // The first number of found may be the whole number field, the
+  // city and number field, or neither. But it cannot be both.
+  DCHECK(!(found_whole_number_field && found_city_and_number_field));
+
+  // Prefer to fill the first complete phone number found. The whole number
+  // and city_and_number fields are only set if they represent the first
+  // complete number found; otherwise, a complete number is present as
+  // component input fields. These scenarios are mutually exclusive, so
+  // clean up any inconsistencies.
+  if (found_whole_number_field) {
+    found_number_field = nullptr;
+    found_number_field_second = nullptr;
+    found_city_code_field = nullptr;
+    found_country_code_field = nullptr;
+  } else if (found_city_and_number_field) {
+    found_number_field = nullptr;
+    found_number_field_second = nullptr;
+    found_city_code_field = nullptr;
+  }
+
+  // A second update pass.
+  // At this point, either |phone_number_found| is false and we should do a
+  // best-effort filling for the field whose types we have seen a first time.
+  // Or |phone_number_found| is true and the pointers to the fields that
+  // compose the first valid phone number are set to not-NULL, specifically:
+  // 1. |found_whole_number_field| is not NULL, other pointers set to NULL, or
+  // 2. |found_city_and_number_field| is not NULL, |found_country_code_field| is
+  //    probably not NULL, and other pointers set to NULL, or
+  // 3. |found_city_code_field| and |found_number_field| are not NULL,
+  //    |found_country_code_field| is probably not NULL, and other pointers are
+  //    NULL.
+  // 4. |found_city_code_field|, |found_number_field| and
+  // |found_number_field_second|
+  //    are not NULL, |found_country_code_field| is probably not NULL, and other
+  //    pointers are NULL.
+
+  // For all above cases, in the update pass, if one field is phone
+  // number related but not one of the found fields from first pass, set their
+  // |only_fill_when_focused| field to true.
+  for (auto it = fields_in_section->begin(); it != fields_in_section->end();
+       ++it) {
+    AutofillField* field = *it;
+    ServerFieldType current_field_type = field->Type().GetStorableType();
+    switch (current_field_type) {
+      case PHONE_HOME_NUMBER:
+      case PHONE_BILLING_NUMBER:
+        if (field != found_number_field && field != found_number_field_second)
+          field->set_only_fill_when_focused(true);
+        break;
+      case PHONE_HOME_CITY_CODE:
+      case PHONE_BILLING_CITY_CODE:
+        if (field != found_city_code_field)
+          field->set_only_fill_when_focused(true);
+        break;
+      case PHONE_HOME_COUNTRY_CODE:
+      case PHONE_BILLING_COUNTRY_CODE:
+        if (field != found_country_code_field)
+          field->set_only_fill_when_focused(true);
+        break;
+      case PHONE_HOME_CITY_AND_NUMBER:
+      case PHONE_BILLING_CITY_AND_NUMBER:
+        if (field != found_city_and_number_field)
+          field->set_only_fill_when_focused(true);
+        break;
+      case PHONE_HOME_WHOLE_NUMBER:
+      case PHONE_BILLING_WHOLE_NUMBER:
+        if (field != found_whole_number_field)
+          field->set_only_fill_when_focused(true);
+        break;
+      default:
+        break;
+    }
+  }
+}
+
 }  // namespace
 
 FormStructure::FormStructure(const FormData& form)
@@ -1201,141 +1344,13 @@
 }
 
 void FormStructure::RationalizePhoneNumberFieldPredictions() {
-  AutofillField* found_number_field = nullptr;
-  AutofillField* found_number_field_second = nullptr;
-  AutofillField* found_city_code_field = nullptr;
-  AutofillField* found_country_code_field = nullptr;
-  AutofillField* found_city_and_number_field = nullptr;
-  AutofillField* found_whole_number_field = nullptr;
-  bool phone_number_found = false;
-  bool phone_number_separate_fields = false;
-  // Iterate through all fields. Iteration stops when it first finds a valid
-  // set of fields that can compose a whole number. The |found_*| pointers
-  // will be set to that set of fields when iteration finishes.
+  auto section_to_fields_map =
+      std::map<std::string, std::vector<AutofillField*>>();
   for (const auto& field : fields_) {
-    ServerFieldType current_field_type = field->Type().GetStorableType();
-    switch (current_field_type) {
-      case PHONE_HOME_NUMBER:
-      case PHONE_BILLING_NUMBER:
-        if (!found_number_field) {
-          found_number_field = field.get();
-          if (field->max_length < 5) {
-            phone_number_separate_fields = true;
-          } else {
-            phone_number_found = true;
-          }
-          break;
-        }
-        // If the form has phone number separated into exchange and subscriber
-        // number we mark both of them as number fields.
-        // TODO(wuandy): A less hacky solution to have dedicated enum for
-        // exchange and subscriber number.
-        DCHECK(phone_number_separate_fields);
-        DCHECK(!found_number_field_second);
-        found_number_field_second = field.get();
-        phone_number_found = true;
-        break;
-      case PHONE_HOME_CITY_CODE:
-      case PHONE_BILLING_CITY_CODE:
-        if (!found_city_code_field)
-          found_city_code_field = field.get();
-        break;
-      case PHONE_HOME_COUNTRY_CODE:
-      case PHONE_BILLING_COUNTRY_CODE:
-        if (!found_country_code_field)
-          found_country_code_field = field.get();
-        break;
-      case PHONE_HOME_CITY_AND_NUMBER:
-      case PHONE_BILLING_CITY_AND_NUMBER:
-        DCHECK(!phone_number_found && !found_city_and_number_field);
-        found_city_and_number_field = field.get();
-        phone_number_found = true;
-        break;
-      case PHONE_HOME_WHOLE_NUMBER:
-      case PHONE_BILLING_WHOLE_NUMBER:
-        DCHECK(!phone_number_found && !found_whole_number_field);
-        found_whole_number_field = field.get();
-        phone_number_found = true;
-        break;
-      default:
-        break;
-    }
-    if (phone_number_found)
-      break;
+    section_to_fields_map[field->section()].push_back(field.get());
   }
-
-  // The first number of found may be the whole number field, the
-  // city and number field, or neither. But it cannot be both.
-  DCHECK(!(found_whole_number_field && found_city_and_number_field));
-
-  // Prefer to fill the first complete phone number found. The whole number
-  // and city_and_number fields are only set if they represent the first
-  // complete number found; otherwise, a complete number is present as
-  // component input fields. These scenarios are mutually exclusive, so
-  // clean up any inconsistencies.
-  if (found_whole_number_field) {
-    found_number_field = nullptr;
-    found_number_field_second = nullptr;
-    found_city_code_field = nullptr;
-    found_country_code_field = nullptr;
-  } else if (found_city_and_number_field) {
-    found_number_field = nullptr;
-    found_number_field_second = nullptr;
-    found_city_code_field = nullptr;
-  }
-
-  // A second update pass.
-  // At this point, either |phone_number_found| is false and we should do a
-  // best-effort filling for the field whose types we have seen a first time.
-  // Or |phone_number_found| is true and the pointers to the fields that
-  // compose the first valid phone number are set to not-NULL, specifically:
-  // 1. |found_whole_number_field| is not NULL, other pointers set to NULL, or
-  // 2. |found_city_and_number_field| is not NULL, |found_country_code_field| is
-  //    probably not NULL, and other pointers set to NULL, or
-  // 3. |found_city_code_field| and |found_number_field| are not NULL,
-  //    |found_country_code_field| is probably not NULL, and other pointers are
-  //    NULL.
-  // 4. |found_city_code_field|, |found_number_field| and
-  // |found_number_field_second|
-  //    are not NULL, |found_country_code_field| is probably not NULL, and other
-  //    pointers are NULL.
-
-  // For all above cases, in the update pass, if one field is phone
-  // number related but not one of the found fields from first pass, set their
-  // |only_fill_when_focused| field to true.
-  for (auto it = fields_.begin(); it != fields_.end(); ++it) {
-    auto& field = *it;
-    ServerFieldType current_field_type = field->Type().GetStorableType();
-    switch (current_field_type) {
-      case PHONE_HOME_NUMBER:
-      case PHONE_BILLING_NUMBER:
-        if (field.get() != found_number_field &&
-            field.get() != found_number_field_second)
-          field->set_only_fill_when_focused(true);
-        break;
-      case PHONE_HOME_CITY_CODE:
-      case PHONE_BILLING_CITY_CODE:
-        if (field.get() != found_city_code_field)
-          field->set_only_fill_when_focused(true);
-        break;
-      case PHONE_HOME_COUNTRY_CODE:
-      case PHONE_BILLING_COUNTRY_CODE:
-        if (field.get() != found_country_code_field)
-          field->set_only_fill_when_focused(true);
-        break;
-      case PHONE_HOME_CITY_AND_NUMBER:
-      case PHONE_BILLING_CITY_AND_NUMBER:
-        if (field.get() != found_city_and_number_field)
-          field->set_only_fill_when_focused(true);
-        break;
-      case PHONE_HOME_WHOLE_NUMBER:
-      case PHONE_BILLING_WHOLE_NUMBER:
-        if (field.get() != found_whole_number_field)
-          field->set_only_fill_when_focused(true);
-        break;
-      default:
-        break;
-    }
+  for (auto& it : section_to_fields_map) {
+    RationalizePhoneNumberFieldPredictionsInSection(&it.second);
   }
 }
 
diff --git a/components/autofill/core/browser/form_structure_unittest.cc b/components/autofill/core/browser/form_structure_unittest.cc
index 3813bd26..7e5a4e6 100644
--- a/components/autofill/core/browser/form_structure_unittest.cc
+++ b/components/autofill/core/browser/form_structure_unittest.cc
@@ -4747,6 +4747,150 @@
   }
 }
 
+TEST_F(FormStructureTest,
+       ParseQueryResponse_NumbersInDifferentSectionsShouldGetAutofilled) {
+  FormData form;
+  form.origin = GURL("http://foo.com");
+  FormFieldData field;
+  field.form_control_type = "text";
+  field.max_length = 10000;
+
+  field.label = ASCIIToUTF16("Full Name");
+  field.name = ASCIIToUTF16("fullName");
+  // Needed to force multiple section in the form as the section identifying
+  // logic only process fields with |is_focusable|=true.
+  field.is_focusable = true;
+  form.fields.push_back(field);
+
+  field.label = ASCIIToUTF16("Address");
+  field.name = ASCIIToUTF16("address");
+  form.fields.push_back(field);
+
+  field.label = ASCIIToUTF16("Country Code");
+  field.name = ASCIIToUTF16("countryCode");
+  form.fields.push_back(field);
+
+  field.label = ASCIIToUTF16("Number");
+  field.name = ASCIIToUTF16("phoneNumber");
+  form.fields.push_back(field);
+
+  field.label = ASCIIToUTF16("Full Name");
+  field.name = ASCIIToUTF16("fullName1");
+  // Needed to force multiple section in the form as the section identifying
+  // logic only process fields with |is_focusable|=true.
+  field.is_focusable = true;
+  form.fields.push_back(field);
+
+  field.label = ASCIIToUTF16("Billing Address");
+  field.name = ASCIIToUTF16("billingAddress");
+  form.fields.push_back(field);
+
+  field.label = ASCIIToUTF16("Phone Country Code");
+  field.name = ASCIIToUTF16("bCountryCode");
+  form.fields.push_back(field);
+
+  field.label = ASCIIToUTF16("PhoneNumber");
+  field.name = ASCIIToUTF16("bPhoneNumber");
+  form.fields.push_back(field);
+
+  AutofillQueryResponseContents response;
+  response.add_field()->set_overall_type_prediction(NAME_FULL);
+  response.add_field()->set_overall_type_prediction(
+      ADDRESS_HOME_STREET_ADDRESS);
+  response.add_field()->set_overall_type_prediction(PHONE_HOME_COUNTRY_CODE);
+  response.add_field()->set_overall_type_prediction(PHONE_HOME_CITY_AND_NUMBER);
+
+  response.add_field()->set_overall_type_prediction(NAME_FULL);
+  response.add_field()->set_overall_type_prediction(
+      ADDRESS_HOME_STREET_ADDRESS);
+  response.add_field()->set_overall_type_prediction(PHONE_HOME_COUNTRY_CODE);
+  response.add_field()->set_overall_type_prediction(PHONE_HOME_CITY_AND_NUMBER);
+
+  std::string response_string;
+  ASSERT_TRUE(response.SerializeToString(&response_string));
+
+  // Verify phone number in different section still gets autofilled.
+  {
+    base::test::ScopedFeatureList feature_list;
+    feature_list.InitAndEnableFeature(
+        autofill::kAutofillRationalizeFieldTypePredictions);
+
+    FormStructure form_structure(form);
+    std::vector<FormStructure*> forms;
+    forms.push_back(&form_structure);
+    FormStructure::ParseQueryResponse(response_string, forms);
+    ASSERT_EQ(1U, forms.size());
+    ASSERT_EQ(8U, forms[0]->field_count());
+    EXPECT_EQ(NAME_FULL, forms[0]->field(0)->overall_server_type());
+    EXPECT_EQ(ADDRESS_HOME_STREET_ADDRESS,
+              forms[0]->field(1)->overall_server_type());
+
+    EXPECT_EQ(PHONE_HOME_COUNTRY_CODE,
+              forms[0]->field(2)->overall_server_type());
+    EXPECT_FALSE(forms[0]->field(2)->only_fill_when_focused());
+
+    EXPECT_EQ(PHONE_HOME_CITY_AND_NUMBER,
+              forms[0]->field(3)->overall_server_type());
+    EXPECT_FALSE(forms[0]->field(3)->only_fill_when_focused());
+
+    EXPECT_EQ(NAME_FULL, forms[0]->field(4)->overall_server_type());
+    EXPECT_EQ(ADDRESS_HOME_STREET_ADDRESS,
+              forms[0]->field(5)->overall_server_type());
+
+    // Make sure numbers in different sections are treated independently.
+    EXPECT_NE(forms[0]->field(2)->section(), forms[0]->field(6)->section());
+    EXPECT_EQ(PHONE_HOME_COUNTRY_CODE,
+              forms[0]->field(6)->overall_server_type());
+    EXPECT_FALSE(forms[0]->field(6)->only_fill_when_focused());
+
+    EXPECT_NE(forms[0]->field(3)->section(), forms[0]->field(7)->section());
+    EXPECT_EQ(PHONE_HOME_CITY_AND_NUMBER,
+              forms[0]->field(7)->overall_server_type());
+    EXPECT_FALSE(forms[0]->field(7)->only_fill_when_focused());
+  }
+
+  // Sanity check that the enable/disabled works. Same output as when the
+  // feature is on.
+  {
+    base::test::ScopedFeatureList feature_list;
+    feature_list.InitAndDisableFeature(
+        autofill::kAutofillRationalizeFieldTypePredictions);
+
+    FormStructure form_structure(form);
+    std::vector<FormStructure*> forms;
+    forms.push_back(&form_structure);
+    FormStructure::ParseQueryResponse(response_string, forms);
+
+    ASSERT_EQ(1U, forms.size());
+    ASSERT_EQ(8U, forms[0]->field_count());
+    EXPECT_EQ(NAME_FULL, forms[0]->field(0)->overall_server_type());
+    EXPECT_EQ(ADDRESS_HOME_STREET_ADDRESS,
+              forms[0]->field(1)->overall_server_type());
+
+    EXPECT_EQ(PHONE_HOME_COUNTRY_CODE,
+              forms[0]->field(2)->overall_server_type());
+    EXPECT_FALSE(forms[0]->field(2)->only_fill_when_focused());
+
+    EXPECT_EQ(PHONE_HOME_CITY_AND_NUMBER,
+              forms[0]->field(3)->overall_server_type());
+    EXPECT_FALSE(forms[0]->field(3)->only_fill_when_focused());
+
+    EXPECT_EQ(NAME_FULL, forms[0]->field(4)->overall_server_type());
+    EXPECT_EQ(ADDRESS_HOME_STREET_ADDRESS,
+              forms[0]->field(5)->overall_server_type());
+
+    EXPECT_NE(forms[0]->field(2)->section(), forms[0]->field(6)->section());
+    EXPECT_EQ(PHONE_HOME_COUNTRY_CODE,
+              forms[0]->field(6)->overall_server_type());
+    EXPECT_FALSE(forms[0]->field(6)->only_fill_when_focused());
+
+    EXPECT_NE(forms[0]->field(3)->section(), forms[0]->field(7)->section());
+    EXPECT_EQ(PHONE_HOME_CITY_AND_NUMBER,
+              forms[0]->field(7)->overall_server_type());
+    EXPECT_FALSE(forms[0]->field(7)->only_fill_when_focused());
+  }
+}
+
 TEST_F(FormStructureTest, FindLongestCommonPrefix) {
   // Normal case: All strings are longer than threshold; some are common.
   std::vector<base::string16> strings;
diff --git a/components/constrained_window/native_web_contents_modal_dialog_manager_views.cc b/components/constrained_window/native_web_contents_modal_dialog_manager_views.cc
index 5a5a5c0..cf4b3274 100644
--- a/components/constrained_window/native_web_contents_modal_dialog_manager_views.cc
+++ b/components/constrained_window/native_web_contents_modal_dialog_manager_views.cc
@@ -48,10 +48,8 @@
   if (host_)
     host_->RemoveObserver(this);
 
-  for (std::set<views::Widget*>::iterator it = observed_widgets_.begin();
-       it != observed_widgets_.end(); ++it) {
-    (*it)->RemoveObserver(this);
-  }
+  for (auto* widget : observed_widgets_)
+    widget->RemoveObserver(this);
 }
 
 void NativeWebContentsModalDialogManagerViews::ManageDialog() {
@@ -99,7 +97,8 @@
   }
 #endif
   ShowWidget(widget);
-  Focus();
+  if (host_->ShouldActivateDialog())
+    Focus();
 
 #if defined(USE_AURA)
   // TODO(pkotwicz): Control the z-order of the constrained dialog via
@@ -142,10 +141,8 @@
 void NativeWebContentsModalDialogManagerViews::OnPositionRequiresUpdate() {
   DCHECK(host_);
 
-  for (std::set<views::Widget*>::iterator it = observed_widgets_.begin();
-       it != observed_widgets_.end(); ++it) {
-    constrained_window::UpdateWebContentsModalDialogPosition(*it, host_);
-  }
+  for (auto* widget : observed_widgets_)
+    constrained_window::UpdateWebContentsModalDialogPosition(widget, host_);
 }
 
 void NativeWebContentsModalDialogManagerViews::OnHostDestroying() {
@@ -177,9 +174,8 @@
   if (host_) {
     host_->AddObserver(this);
 
-    for (std::set<views::Widget*>::iterator it = observed_widgets_.begin();
-         it != observed_widgets_.end(); ++it) {
-      views::Widget::ReparentNativeView((*it)->GetNativeView(),
+    for (auto* widget : observed_widgets_) {
+      views::Widget::ReparentNativeView(widget->GetNativeView(),
                                         host_->GetHostView());
     }
 
diff --git a/components/cronet/OWNERS b/components/cronet/OWNERS
index fe8552d..c9838da 100644
--- a/components/cronet/OWNERS
+++ b/components/cronet/OWNERS
@@ -1,6 +1,5 @@
 kapishnikov@chromium.org
 mef@chromium.org
-mmenke@chromium.org
 mgersh@chromium.org
 pauljensen@chromium.org
 xunjieli@chromium.org
diff --git a/components/data_reduction_proxy/core/common/data_reduction_proxy_util.cc b/components/data_reduction_proxy/core/common/data_reduction_proxy_util.cc
index 51da15b5..788a033 100644
--- a/components/data_reduction_proxy/core/common/data_reduction_proxy_util.cc
+++ b/components/data_reduction_proxy/core/common/data_reduction_proxy_util.cc
@@ -183,6 +183,9 @@
 
 int64_t CalculateOCLFromOFCL(const net::URLRequest& request) {
   const net::HttpResponseHeaders* response_headers = request.response_headers();
+  if (!response_headers)
+    return request.received_response_content_length();
+
   int64_t original_content_length = GetDataReductionProxyOFCL(response_headers);
 
   if (response_headers->response_code() == net::HTTP_PARTIAL_CONTENT) {
diff --git a/components/data_reduction_proxy/core/common/data_reduction_proxy_util.h b/components/data_reduction_proxy/core/common/data_reduction_proxy_util.h
index 528d57c..a40f358 100644
--- a/components/data_reduction_proxy/core/common/data_reduction_proxy_util.h
+++ b/components/data_reduction_proxy/core/common/data_reduction_proxy_util.h
@@ -98,8 +98,8 @@
                                  net::ProxyInfo* data_reduction_proxy_info);
 
 // Calculates the original content length (OCL) of the |request|, from the OFCL
-// value in the Chrome-Proxy header. |request| must not be cached and response
-// headers must be valid. This does not account for partial failed responses.
+// value in the Chrome-Proxy header. |request| must not be cached. This does not
+// account for partial failed responses.
 int64_t CalculateOCLFromOFCL(const net::URLRequest& request);
 
 // Calculates the effective original content length of the |request|. For
diff --git a/components/exo/wayland/clients/client_base.cc b/components/exo/wayland/clients/client_base.cc
index 68cbcec..28b75a1c 100644
--- a/components/exo/wayland/clients/client_base.cc
+++ b/components/exo/wayland/clients/client_base.cc
@@ -767,6 +767,20 @@
   return buffer;
 }
 
+ClientBase::Buffer* ClientBase::DequeueBuffer() {
+  auto buffer_it =
+      std::find_if(buffers_.begin(), buffers_.end(),
+                   [](const std::unique_ptr<ClientBase::Buffer>& buffer) {
+                     return !buffer->busy;
+                   });
+  if (buffer_it == buffers_.end())
+    return nullptr;
+
+  Buffer* buffer = buffer_it->get();
+  buffer->busy = true;
+  return buffer;
+}
+
 }  // namespace clients
 }  // namespace wayland
 }  // namespace exo
diff --git a/components/exo/wayland/clients/client_base.h b/components/exo/wayland/clients/client_base.h
index 3e705bcc..3122ce5 100644
--- a/components/exo/wayland/clients/client_base.h
+++ b/components/exo/wayland/clients/client_base.h
@@ -43,7 +43,7 @@
     bool FromCommandLine(const base::CommandLine& command_line);
 
     std::string title = "Wayland Client";
-    size_t num_buffers = 8;
+    size_t num_buffers = 2;
     size_t width = 256;
     size_t height = 256;
     int scale = 1;
@@ -105,6 +105,7 @@
   std::unique_ptr<Buffer> CreateDrmBuffer(const gfx::Size& size,
                                           int32_t drm_format,
                                           int32_t bo_usage);
+  ClientBase::Buffer* DequeueBuffer();
 
   gfx::Size size_ = gfx::Size(256, 256);
   int scale_ = 1;
diff --git a/components/exo/wayland/clients/perftests.cc b/components/exo/wayland/clients/perftests.cc
index cec13cc..ff5b921 100644
--- a/components/exo/wayland/clients/perftests.cc
+++ b/components/exo/wayland/clients/perftests.cc
@@ -12,12 +12,14 @@
 
 using WaylandClientPerfTests = exo::WaylandClientTest;
 
+// Test simple double-buffered client performance.
 TEST_F(WaylandClientPerfTests, Simple) {
   const int kWarmUpFrames = 20;
   const int kTestFrames = 600;
 
   base::CommandLine* command_line = base::CommandLine::ForCurrentProcess();
   exo::wayland::clients::ClientBase::InitParams params;
+  params.num_buffers = 2;  // Double-buffering.
   EXPECT_TRUE(params.FromCommandLine(*command_line));
 
   exo::wayland::clients::Simple client;
diff --git a/components/exo/wayland/clients/rects.cc b/components/exo/wayland/clients/rects.cc
index 68aee89..307ad3a 100644
--- a/components/exo/wayland/clients/rects.cc
+++ b/components/exo/wayland/clients/rects.cc
@@ -282,16 +282,11 @@
                              ? pending_frames.size() < max_frames_pending
                              : pending_frames.empty();
     if (enqueue_frame) {
-      auto buffer_it =
-          std::find_if(buffers_.begin(), buffers_.end(),
-                       [](const std::unique_ptr<ClientBase::Buffer>& buffer) {
-                         return !buffer->busy;
-                       });
-      if (buffer_it == buffers_.end()) {
+      Buffer* buffer = DequeueBuffer();
+      if (!buffer) {
         LOG(ERROR) << "Can't find free buffer";
         return 1;
       }
-      auto* buffer = buffer_it->get();
 
       auto frame = std::make_unique<Frame>();
       frame->buffer = buffer;
@@ -402,8 +397,6 @@
         glFlush();
       }
 
-      buffer->busy = true;
-
       if (num_benchmark_runs) {
         frame->wall_time = base::TimeTicks::Now() - wall_time_start;
         frame->cpu_time = base::ThreadTicks::Now() - cpu_time_start;
@@ -486,6 +479,7 @@
   base::CommandLine* command_line = base::CommandLine::ForCurrentProcess();
 
   exo::wayland::clients::ClientBase::InitParams params;
+  params.num_buffers = 8;  // Allow up to 8 buffers by default.
   if (!params.FromCommandLine(*command_line))
     return 1;
 
diff --git a/components/exo/wayland/clients/simple.cc b/components/exo/wayland/clients/simple.cc
index fe34eaa..e2f9e9c 100644
--- a/components/exo/wayland/clients/simple.cc
+++ b/components/exo/wayland/clients/simple.cc
@@ -37,8 +37,11 @@
     if (frame_count == frames)
       break;
 
+    Buffer* buffer = DequeueBuffer();
+    if (!buffer)
+      continue;
+
     callback_pending = true;
-    Buffer* buffer = buffers_.front().get();
     SkCanvas* canvas = buffer->sk_surface->getCanvas();
 
     static const SkColor kColors[] = {SK_ColorRED, SK_ColorBLACK};
diff --git a/components/exo/wayland/clients/vulkan.cc b/components/exo/wayland/clients/vulkan.cc
index a712243..f87cd98e 100644
--- a/components/exo/wayland/clients/vulkan.cc
+++ b/components/exo/wayland/clients/vulkan.cc
@@ -129,7 +129,10 @@
     if (callback_pending)
       continue;
 
-    Buffer* buffer = buffers_.front().get();
+    Buffer* buffer = DequeueBuffer();
+    if (!buffer)
+      continue;
+
     {
       static const SkColor kColors[] = {SK_ColorRED, SK_ColorBLACK,
                                         SK_ColorGREEN};
diff --git a/components/exo/wayland/clients/yuv.cc b/components/exo/wayland/clients/yuv.cc
index 7e6ff196..ec8e634f 100644
--- a/components/exo/wayland/clients/yuv.cc
+++ b/components/exo/wayland/clients/yuv.cc
@@ -90,17 +90,11 @@
       continue;
     frame_number++;
 
-    auto buffer_it =
-        std::find_if(buffers_.begin(), buffers_.end(),
-                     [](const std::unique_ptr<ClientBase::Buffer>& buffer) {
-                       return !buffer->busy;
-                     });
-    if (buffer_it == buffers_.end()) {
+    Buffer* buffer = DequeueBuffer();
+    if (!buffer) {
       LOG(ERROR) << "Can't find free buffer";
       return;
     }
-    auto* buffer = buffer_it->get();
-    buffer->busy = true;
     const SkColor kColors[] = {SK_ColorBLUE,   SK_ColorGREEN, SK_ColorRED,
                                SK_ColorYELLOW, SK_ColorCYAN,  SK_ColorMAGENTA};
     if (!WriteSolidColor(buffer->bo.get(),
@@ -133,6 +127,7 @@
 
   exo::wayland::clients::ClientBase::InitParams params;
   params.use_drm = true;
+  params.num_buffers = 8;  // Allow up to 8 buffers by default.
   if (!params.FromCommandLine(*command_line))
     return 1;
 
diff --git a/components/flags_ui/resources/flags.css b/components/flags_ui/resources/flags.css
index f8976f0..8b095a39 100644
--- a/components/flags_ui/resources/flags.css
+++ b/components/flags_ui/resources/flags.css
@@ -128,7 +128,7 @@
   background: url(../../../ui/webui/resources/images/icon_cancel.svg) no-repeat;
   background-size: 20px;
   border: 0;
-  display: inline-block;
+  display: none;
   height: 20px;
   opacity: 0.5;
   position: absolute;
@@ -142,6 +142,10 @@
   outline: 0;
 }
 
+.searching .clear-search {
+  display: inline-block;
+}
+
 [dir='rtl'] .clear-search {
   left: 8px;
   right: initial;
@@ -220,13 +224,18 @@
 }
 
 .experiment-switched .experiment-name::before {
-  background: url(../../../ui/webui/resources/images/check_circle.svg) no-repeat;
-  color: var(--google-blue-700);
-  content: '';
+  color: var(--google-blue-500);
+  content: '•';
   display: inline-block;
-  height: 20px;
-  margin: 0 4px -6px 0;
-  width: 20px;
+  font-size: 40px;
+  line-height: 0;
+  margin: 0 4px 0 -20px;
+  vertical-align: middle;
+  width: 16px;
+}
+
+[dir='rtl'] .experiment-switched .experiment-name::before {
+  margin: 0 -20px 0 4px;
 }
 
 .match,
@@ -435,7 +444,7 @@
 @media (max-width: 360px) {
   #experiment-reset-all {
     font-size: 0.8em;
-    padding: 4px 8px;
+    padding: 2px 8px;
   }
 
   .experiment-restart-button {
@@ -521,6 +530,14 @@
 }
 
 @media (max-width: 732px) {
+  .experiment-switched .experiment-name::before {
+    margin-left: 0;
+  }
+
+  [dir='rtl'] .experiment-switched .experiment-name::before {
+    margin-right: 0;
+  }
+
   #flagsTemplate {
     padding: 8px 16px;
   }
diff --git a/components/flags_ui/resources/flags.html b/components/flags_ui/resources/flags.html
index 1b1c3a9a..3f7761e 100644
--- a/components/flags_ui/resources/flags.html
+++ b/components/flags_ui/resources/flags.html
@@ -3,10 +3,13 @@
 <head>
 <meta charset="utf-8">
 <meta name="viewport" content="width=device-width, initial-scale=1.0">
+<if expr="not is_ios">
 <link rel="stylesheet" href="chrome://resources/css/text_defaults_md.css">
+</if>
 <link rel="stylesheet" href="flags.css">
 
 <if expr="is_ios">
+<link rel="stylesheet" href="chrome://resources/css/text_defaults.css">
 <!-- TODO(crbug.com/487000): Remove this once injected by web. -->
 <script src="chrome://resources/js/ios/web_ui.js"></script>
 </if>
diff --git a/components/guest_view/browser/guest_view_base.cc b/components/guest_view/browser/guest_view_base.cc
index b88ed07d..4a128f8 100644
--- a/components/guest_view/browser/guest_view_base.cc
+++ b/components/guest_view/browser/guest_view_base.cc
@@ -871,14 +871,16 @@
 }
 
 void GuestViewBase::StopTrackingEmbedderZoomLevel() {
-  if (!attached() || !ZoomPropagatesFromEmbedderToGuest())
-    return;
+  // TODO(wjmaclean): Remove the observer any time the GuestWebView transitions
+  // from propagating to not-propagating the zoom from the embedder.
 
   auto* embedder_zoom_controller =
       zoom::ZoomController::FromWebContents(owner_web_contents());
   // Chrome Apps do not have a ZoomController.
   if (!embedder_zoom_controller)
     return;
+
+  // It is safe to remove an observer that was never registed.
   embedder_zoom_controller->RemoveObserver(this);
 }
 
diff --git a/components/guest_view/browser/guest_view_message_filter.cc b/components/guest_view/browser/guest_view_message_filter.cc
index e830b1e..d3e4d787 100644
--- a/components/guest_view/browser/guest_view_message_filter.cc
+++ b/components/guest_view/browser/guest_view_message_filter.cc
@@ -146,6 +146,11 @@
   DCHECK(owner_web_contents);
   auto* embedder_frame = RenderFrameHost::FromID(
       render_process_id_, embedder_local_render_frame_id);
+  // If we're creating a new guest through window.open /
+  // RenderViewImpl::CreateView, the embedder may not be the same as
+  // the original creator/owner, so update embedder_web_contents here.
+  content::WebContents* embedder_web_contents =
+      WebContents::FromRenderFrameHost(embedder_frame);
 
   // Update the guest manager about the attachment.
   // This sets up the embedder and guest pairing information inside
@@ -153,20 +158,20 @@
   manager->AttachGuest(render_process_id_, element_instance_id,
                        guest_instance_id, params);
 
-  owner_web_contents->GetMainFrame()->Send(
+  embedder_web_contents->GetMainFrame()->Send(
       new GuestViewMsg_AttachToEmbedderFrame_ACK(element_instance_id));
 
   guest->WillAttach(
-      owner_web_contents, element_instance_id, false,
+      embedder_web_contents, element_instance_id, false,
       base::Bind(&GuestViewBase::DidAttach,
                  guest->weak_ptr_factory_.GetWeakPtr(), MSG_ROUTING_NONE));
 
   // Attach this inner WebContents |guest_web_contents| to the outer
-  // WebContents |owner_web_contents|. The outer WebContents's
+  // WebContents |embedder_web_contents|. The outer WebContents's
   // frame |embedder_frame| hosts the inner WebContents.
   // NOTE: this must be called last, because it could unblock pending requests
   // which depend on the WebViewGuest being initialized which happens above.
-  guest_web_contents->AttachToOuterWebContentsFrame(owner_web_contents,
+  guest_web_contents->AttachToOuterWebContentsFrame(embedder_web_contents,
                                                     embedder_frame);
 }
 
diff --git a/components/omnibox/browser/autocomplete_controller.h b/components/omnibox/browser/autocomplete_controller.h
index 4cf270f..2cf23c5 100644
--- a/components/omnibox/browser/autocomplete_controller.h
+++ b/components/omnibox/browser/autocomplete_controller.h
@@ -6,6 +6,7 @@
 #define COMPONENTS_OMNIBOX_BROWSER_AUTOCOMPLETE_CONTROLLER_H_
 
 #include <memory>
+#include <vector>
 
 #include "base/compiler_specific.h"
 #include "base/gtest_prod_util.h"
diff --git a/components/omnibox/browser/autocomplete_input.cc b/components/omnibox/browser/autocomplete_input.cc
index 862da38..8c80cc1 100644
--- a/components/omnibox/browser/autocomplete_input.cc
+++ b/components/omnibox/browser/autocomplete_input.cc
@@ -4,6 +4,8 @@
 
 #include "components/omnibox/browser/autocomplete_input.h"
 
+#include <vector>
+
 #include "base/macros.h"
 #include "base/strings/string_split.h"
 #include "base/strings/string_util.h"
diff --git a/components/omnibox/browser/autocomplete_input.h b/components/omnibox/browser/autocomplete_input.h
index 37656f1..c1e1c7b8 100644
--- a/components/omnibox/browser/autocomplete_input.h
+++ b/components/omnibox/browser/autocomplete_input.h
@@ -8,6 +8,7 @@
 #include <stddef.h>
 
 #include <string>
+#include <vector>
 
 #include "base/strings/string16.h"
 #include "third_party/metrics_proto/omnibox_event.pb.h"
diff --git a/components/omnibox/browser/autocomplete_match.h b/components/omnibox/browser/autocomplete_match.h
index 751127c..8e4342f0 100644
--- a/components/omnibox/browser/autocomplete_match.h
+++ b/components/omnibox/browser/autocomplete_match.h
@@ -10,6 +10,7 @@
 #include <map>
 #include <memory>
 #include <string>
+#include <utility>
 #include <vector>
 
 #include "base/strings/utf_offset_string_conversions.h"
diff --git a/components/omnibox/browser/autocomplete_match_type.h b/components/omnibox/browser/autocomplete_match_type.h
index 9b16494..b484c73a 100644
--- a/components/omnibox/browser/autocomplete_match_type.h
+++ b/components/omnibox/browser/autocomplete_match_type.h
@@ -33,8 +33,8 @@
                                 // query that doesn't fall into one of the more
                                 // specific suggestion categories below.
     SEARCH_SUGGEST_ENTITY = 9,  // A suggested search for an entity.
-    SEARCH_SUGGEST_TAIL   = 10, // A suggested search to complete the
-                                // tail of the query.
+    SEARCH_SUGGEST_TAIL   = 10,        // A suggested search to complete the
+                                       // tail of the query.
     SEARCH_SUGGEST_PERSONALIZED = 11,  // A personalized suggested search.
     SEARCH_SUGGEST_PROFILE      = 12,  // A personalized suggested search for a
                                        // Google+ profile.
diff --git a/components/omnibox/browser/autocomplete_match_unittest.cc b/components/omnibox/browser/autocomplete_match_unittest.cc
index 2429084..e8831e5 100644
--- a/components/omnibox/browser/autocomplete_match_unittest.cc
+++ b/components/omnibox/browser/autocomplete_match_unittest.cc
@@ -6,6 +6,8 @@
 
 #include <stddef.h>
 
+#include <utility>
+
 #include "base/macros.h"
 #include "base/strings/utf_string_conversions.h"
 #include "base/test/scoped_feature_list.h"
@@ -268,7 +270,7 @@
                 url_formatter::FormatUrl(GURL(url), format_types,
                                          net::UnescapeRule::SPACES, nullptr,
                                          nullptr, nullptr));
-    };
+    }
   };
 
   FormatUrlTestData normal_cases[] = {
diff --git a/components/omnibox/browser/autocomplete_provider.cc b/components/omnibox/browser/autocomplete_provider.cc
index 0aa6466..211ed12 100644
--- a/components/omnibox/browser/autocomplete_provider.cc
+++ b/components/omnibox/browser/autocomplete_provider.cc
@@ -4,6 +4,9 @@
 
 #include "components/omnibox/browser/autocomplete_provider.h"
 
+#include <algorithm>
+#include <string>
+
 #include "base/logging.h"
 #include "base/strings/utf_string_conversions.h"
 #include "components/omnibox/browser/autocomplete_input.h"
diff --git a/components/omnibox/browser/autocomplete_provider.h b/components/omnibox/browser/autocomplete_provider.h
index 9073315..6f9c4c2 100644
--- a/components/omnibox/browser/autocomplete_provider.h
+++ b/components/omnibox/browser/autocomplete_provider.h
@@ -7,6 +7,9 @@
 
 #include <stddef.h>
 
+#include <utility>
+#include <vector>
+
 #include "base/gtest_prod_util.h"
 #include "base/macros.h"
 #include "base/memory/ref_counted.h"
diff --git a/components/omnibox/browser/autocomplete_provider_client.h b/components/omnibox/browser/autocomplete_provider_client.h
index 0bb3ddc..5098077 100644
--- a/components/omnibox/browser/autocomplete_provider_client.h
+++ b/components/omnibox/browser/autocomplete_provider_client.h
@@ -5,6 +5,8 @@
 #ifndef COMPONENTS_OMNIBOX_BROWSER_AUTOCOMPLETE_PROVIDER_CLIENT_H_
 #define COMPONENTS_OMNIBOX_BROWSER_AUTOCOMPLETE_PROVIDER_CLIENT_H_
 
+#include <memory>
+#include <string>
 #include <vector>
 
 #include "base/memory/ref_counted.h"
diff --git a/components/omnibox/browser/autocomplete_result.cc b/components/omnibox/browser/autocomplete_result.cc
index 98b9947..ee775a0 100644
--- a/components/omnibox/browser/autocomplete_result.cc
+++ b/components/omnibox/browser/autocomplete_result.cc
@@ -6,6 +6,7 @@
 
 #include <algorithm>
 #include <iterator>
+#include <string>
 
 #include "base/command_line.h"
 #include "base/logging.h"
diff --git a/components/omnibox/browser/autocomplete_result_unittest.cc b/components/omnibox/browser/autocomplete_result_unittest.cc
index 77607dd..5eab86ad 100644
--- a/components/omnibox/browser/autocomplete_result_unittest.cc
+++ b/components/omnibox/browser/autocomplete_result_unittest.cc
@@ -7,6 +7,7 @@
 #include <stddef.h>
 
 #include <memory>
+#include <string>
 #include <vector>
 
 #include "base/macros.h"
@@ -67,7 +68,7 @@
 // A simple AutocompleteProvider that does nothing.
 class MockAutocompleteProvider : public AutocompleteProvider {
  public:
-  MockAutocompleteProvider(Type type): AutocompleteProvider(type) {}
+  explicit MockAutocompleteProvider(Type type): AutocompleteProvider(type) {}
 
   void Start(const AutocompleteInput& input, bool minimal_changes) override {}
 
@@ -685,7 +686,7 @@
     std::vector<ACMatchClassification> before_contents_class;
     std::vector<ACMatchClassification> after_contents_class;
   } cases[] = {
-      // It should fix-up this match, since prefix matches.
+      // It should not touch this, since it's not a tail suggestion.
       {
           AutocompleteMatchType::SEARCH_WHAT_YOU_TYPED,
           "superman",
@@ -702,14 +703,7 @@
           {{0, ACMatchClassification::INVISIBLE},
            {5, ACMatchClassification::MATCH}},
       },
-      // It should not touch this one, since prefix doesn't match.
-      {
-          AutocompleteMatchType::SEARCH_SUGGEST,
-          "suppertime",
-          "suppertime",
-          {{0, ACMatchClassification::NONE}, {3, ACMatchClassification::MATCH}},
-          {{0, ACMatchClassification::NONE}, {3, ACMatchClassification::MATCH}},
-      }};
+  };
   ACMatches matches;
   for (const auto& test_case : cases) {
     AutocompleteMatch match;
diff --git a/components/omnibox/browser/base_search_provider.cc b/components/omnibox/browser/base_search_provider.cc
index be2d5d9..a43b5786 100644
--- a/components/omnibox/browser/base_search_provider.cc
+++ b/components/omnibox/browser/base_search_provider.cc
@@ -7,6 +7,8 @@
 #include <stddef.h>
 #include <stdint.h>
 
+#include <algorithm>
+
 #include "base/feature_list.h"
 #include "base/i18n/case_conversion.h"
 #include "base/macros.h"
diff --git a/components/omnibox/browser/base_search_provider_unittest.cc b/components/omnibox/browser/base_search_provider_unittest.cc
index 41b03c3d..b32062a9 100644
--- a/components/omnibox/browser/base_search_provider_unittest.cc
+++ b/components/omnibox/browser/base_search_provider_unittest.cc
@@ -4,6 +4,7 @@
 
 #include "components/omnibox/browser/base_search_provider.h"
 
+#include <algorithm>
 #include <utility>
 
 #include "base/macros.h"
diff --git a/components/omnibox/browser/builtin_provider.cc b/components/omnibox/browser/builtin_provider.cc
index 22c1c27..dfe5da6 100644
--- a/components/omnibox/browser/builtin_provider.cc
+++ b/components/omnibox/browser/builtin_provider.cc
@@ -7,6 +7,7 @@
 #include <stddef.h>
 
 #include <algorithm>
+#include <string>
 
 #include "base/strings/string_util.h"
 #include "base/strings/utf_string_conversions.h"
diff --git a/components/omnibox/browser/builtin_provider_unittest.cc b/components/omnibox/browser/builtin_provider_unittest.cc
index 12bdfe1a..9a43f42 100644
--- a/components/omnibox/browser/builtin_provider_unittest.cc
+++ b/components/omnibox/browser/builtin_provider_unittest.cc
@@ -6,6 +6,9 @@
 
 #include <stddef.h>
 
+#include <memory>
+#include <string>
+
 #include "base/format_macros.h"
 #include "base/macros.h"
 #include "base/strings/stringprintf.h"
@@ -341,7 +344,7 @@
     // Typing along "about://media" should not yield an inline autocompletion
     // until the completion is unique.  We don't bother checking every single
     // character before the first "m" is typed.
-    {kAbout.substr(0,2),                  base::string16()},
+    {kAbout.substr(0, 2),                 base::string16()},
     {kAbout,                              base::string16()},
     {kAbout + kSep,                       base::string16()},
     {kAbout + kSep + kHostM.substr(0, 1), base::string16()},
@@ -350,7 +353,7 @@
     {kAbout + kSep + kHostM.substr(0, 4), kHostM.substr(4)},
 
     // Ditto with "chrome://media".
-    {kEmbedder.substr(0,2),                  base::string16()},
+    {kEmbedder.substr(0, 2),                 base::string16()},
     {kEmbedder,                              base::string16()},
     {kEmbedder + kSep,                       base::string16()},
     {kEmbedder + kSep + kHostM.substr(0, 1), base::string16()},
diff --git a/components/omnibox/browser/contextual_suggestions_service.cc b/components/omnibox/browser/contextual_suggestions_service.cc
index 1b9ec343..7d6a9820 100644
--- a/components/omnibox/browser/contextual_suggestions_service.cc
+++ b/components/omnibox/browser/contextual_suggestions_service.cc
@@ -4,6 +4,8 @@
 
 #include "components/omnibox/browser/contextual_suggestions_service.h"
 
+#include <utility>
+
 #include "base/feature_list.h"
 #include "base/json/json_writer.h"
 #include "base/memory/ptr_util.h"
@@ -27,7 +29,7 @@
 const char kDefaultExperimentalServerAddress[] =
     "https://cuscochromeextension-pa.googleapis.com/v1/omniboxsuggestions";
 
-void AddVariationHeaders(std::unique_ptr<net::URLFetcher>& fetcher) {
+void AddVariationHeaders(const std::unique_ptr<net::URLFetcher>& fetcher) {
   net::HttpRequestHeaders headers;
   // Add Chrome experiment state to the request headers.
   // Note: It's OK to pass |is_signed_in| false if it's unknown, as it does
diff --git a/components/omnibox/browser/fake_autocomplete_provider_client.h b/components/omnibox/browser/fake_autocomplete_provider_client.h
index 7691a96..d574b21 100644
--- a/components/omnibox/browser/fake_autocomplete_provider_client.h
+++ b/components/omnibox/browser/fake_autocomplete_provider_client.h
@@ -2,7 +2,11 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
+#ifndef COMPONENTS_OMNIBOX_BROWSER_FAKE_AUTOCOMPLETE_PROVIDER_CLIENT_H_
+#define COMPONENTS_OMNIBOX_BROWSER_FAKE_AUTOCOMPLETE_PROVIDER_CLIENT_H_
+
 #include <memory>
+#include <utility>
 
 #include "base/files/scoped_temp_dir.h"
 #include "components/omnibox/browser/mock_autocomplete_provider_client.h"
@@ -44,3 +48,5 @@
 
   DISALLOW_COPY_AND_ASSIGN(FakeAutocompleteProviderClient);
 };
+
+#endif  // COMPONENTS_OMNIBOX_BROWSER_FAKE_AUTOCOMPLETE_PROVIDER_CLIENT_H_
diff --git a/components/omnibox/browser/history_quick_provider.cc b/components/omnibox/browser/history_quick_provider.cc
index 8caef2f..c2b167ab 100644
--- a/components/omnibox/browser/history_quick_provider.cc
+++ b/components/omnibox/browser/history_quick_provider.cc
@@ -6,6 +6,7 @@
 
 #include <stddef.h>
 
+#include <algorithm>
 #include <vector>
 
 #include "base/i18n/break_iterator.h"
diff --git a/components/omnibox/browser/history_url_provider.cc b/components/omnibox/browser/history_url_provider.cc
index 6c13e04e..33620fa 100644
--- a/components/omnibox/browser/history_url_provider.cc
+++ b/components/omnibox/browser/history_url_provider.cc
@@ -5,6 +5,8 @@
 #include "components/omnibox/browser/history_url_provider.h"
 
 #include <algorithm>
+#include <memory>
+#include <utility>
 
 #include "base/bind.h"
 #include "base/command_line.h"
diff --git a/components/omnibox/browser/history_url_provider.h b/components/omnibox/browser/history_url_provider.h
index 324dede..8498098 100644
--- a/components/omnibox/browser/history_url_provider.h
+++ b/components/omnibox/browser/history_url_provider.h
@@ -7,6 +7,7 @@
 
 #include <stddef.h>
 
+#include <memory>
 #include <string>
 #include <vector>
 
diff --git a/components/omnibox/browser/history_url_provider_unittest.cc b/components/omnibox/browser/history_url_provider_unittest.cc
index 9d4d160..b651e7f 100644
--- a/components/omnibox/browser/history_url_provider_unittest.cc
+++ b/components/omnibox/browser/history_url_provider_unittest.cc
@@ -8,6 +8,7 @@
 
 #include <algorithm>
 #include <memory>
+#include <utility>
 
 #include "base/files/scoped_temp_dir.h"
 #include "base/macros.h"
@@ -172,7 +173,7 @@
 
 class FakeAutocompleteProviderClient : public MockAutocompleteProviderClient {
  public:
-  FakeAutocompleteProviderClient(bool create_history_db) {
+  explicit FakeAutocompleteProviderClient(bool create_history_db) {
     set_template_url_service(base::MakeUnique<TemplateURLService>(nullptr, 0));
     if (history_dir_.CreateUniqueTempDir()) {
       history_service_ = history::CreateHistoryService(history_dir_.GetPath(),
diff --git a/components/omnibox/browser/in_memory_url_index.cc b/components/omnibox/browser/in_memory_url_index.cc
index 095e9f09..1d009ed 100644
--- a/components/omnibox/browser/in_memory_url_index.cc
+++ b/components/omnibox/browser/in_memory_url_index.cc
@@ -4,6 +4,8 @@
 
 #include "components/omnibox/browser/in_memory_url_index.h"
 
+#include <memory>
+
 #include "base/files/file_util.h"
 #include "base/strings/utf_string_conversions.h"
 #include "base/task_runner_util.h"
diff --git a/components/omnibox/browser/in_memory_url_index_unittest.cc b/components/omnibox/browser/in_memory_url_index_unittest.cc
index a7e02ae..e5850f5 100644
--- a/components/omnibox/browser/in_memory_url_index_unittest.cc
+++ b/components/omnibox/browser/in_memory_url_index_unittest.cc
@@ -7,7 +7,9 @@
 
 #include <algorithm>
 #include <fstream>
+#include <memory>
 #include <numeric>
+#include <utility>
 
 #include "base/auto_reset.h"
 #include "base/files/file_path.h"
diff --git a/components/omnibox/browser/keyword_provider_unittest.cc b/components/omnibox/browser/keyword_provider_unittest.cc
index 64cbf653..43c36be 100644
--- a/components/omnibox/browser/keyword_provider_unittest.cc
+++ b/components/omnibox/browser/keyword_provider_unittest.cc
@@ -5,6 +5,8 @@
 #include "components/omnibox/browser/keyword_provider.h"
 
 #include <stddef.h>
+
+#include <map>
 #include <utility>
 
 #include "base/command_line.h"
diff --git a/components/omnibox/browser/mock_autocomplete_provider_client.h b/components/omnibox/browser/mock_autocomplete_provider_client.h
index 0021e1bb..5a0a3d2 100644
--- a/components/omnibox/browser/mock_autocomplete_provider_client.h
+++ b/components/omnibox/browser/mock_autocomplete_provider_client.h
@@ -5,8 +5,10 @@
 #ifndef COMPONENTS_OMNIBOX_BROWSER_MOCK_AUTOCOMPLETE_PROVIDER_CLIENT_H_
 #define COMPONENTS_OMNIBOX_BROWSER_MOCK_AUTOCOMPLETE_PROVIDER_CLIENT_H_
 
+#include <memory>
 #include <string>
 #include <utility>
+#include <vector>
 
 #include "base/macros.h"
 #include "components/omnibox/browser/autocomplete_provider_client.h"
@@ -96,4 +98,4 @@
   DISALLOW_COPY_AND_ASSIGN(MockAutocompleteProviderClient);
 };
 
-#endif  // COMPONENTS_OMNIBOX_AUTOCOMPLETE_PROVIDER_CLIENT_H_
+#endif  // COMPONENTS_OMNIBOX_BROWSER_MOCK_AUTOCOMPLETE_PROVIDER_CLIENT_H_
diff --git a/components/omnibox/browser/omnibox_client.cc b/components/omnibox/browser/omnibox_client.cc
index 88f7312..a747c43 100644
--- a/components/omnibox/browser/omnibox_client.cc
+++ b/components/omnibox/browser/omnibox_client.cc
@@ -4,6 +4,8 @@
 
 #include "components/omnibox/browser/omnibox_client.h"
 
+#include <memory>
+
 #include "base/strings/string_util.h"
 #include "ui/gfx/image/image.h"
 
diff --git a/components/omnibox/browser/omnibox_client.h b/components/omnibox/browser/omnibox_client.h
index 6279159..c505f73 100644
--- a/components/omnibox/browser/omnibox_client.h
+++ b/components/omnibox/browser/omnibox_client.h
@@ -5,6 +5,8 @@
 #ifndef COMPONENTS_OMNIBOX_BROWSER_OMNIBOX_CLIENT_H_
 #define COMPONENTS_OMNIBOX_BROWSER_OMNIBOX_CLIENT_H_
 
+#include <memory>
+
 #include "components/omnibox/browser/autocomplete_provider_client.h"
 #include "components/omnibox/browser/omnibox_navigation_observer.h"
 #include "components/omnibox/common/omnibox_focus_state.h"
@@ -136,7 +138,7 @@
   // Called when the text may have changed in the edit.
   virtual void OnTextChanged(const AutocompleteMatch& current_match,
                              bool user_input_in_progress,
-                             base::string16& user_text,
+                             const base::string16& user_text,
                              const AutocompleteResult& result,
                              bool is_popup_open,
                              bool has_focus) {}
diff --git a/components/omnibox/browser/omnibox_field_trial.cc b/components/omnibox/browser/omnibox_field_trial.cc
index 9f4cefc..c85828c 100644
--- a/components/omnibox/browser/omnibox_field_trial.cc
+++ b/components/omnibox/browser/omnibox_field_trial.cc
@@ -4,7 +4,9 @@
 
 #include "components/omnibox/browser/omnibox_field_trial.h"
 
+#include <algorithm>
 #include <cmath>
+#include <functional>
 #include <string>
 
 #include "base/command_line.h"
diff --git a/components/omnibox/browser/omnibox_field_trial.h b/components/omnibox/browser/omnibox_field_trial.h
index 70b298be..4d17620 100644
--- a/components/omnibox/browser/omnibox_field_trial.h
+++ b/components/omnibox/browser/omnibox_field_trial.h
@@ -10,6 +10,7 @@
 
 #include <map>
 #include <string>
+#include <utility>
 #include <vector>
 
 #include "base/macros.h"
@@ -57,7 +58,7 @@
 #if defined(OS_IOS)
 extern const base::Feature kZeroSuggestProviderIOS;
 #endif
-}
+}  // namespace omnibox
 
 // The set of parameters customizing the HUP scoring.
 struct HUPScoringParams {
diff --git a/components/omnibox/browser/omnibox_field_trial_unittest.cc b/components/omnibox/browser/omnibox_field_trial_unittest.cc
index bd0cb03..f0bb4f0 100644
--- a/components/omnibox/browser/omnibox_field_trial_unittest.cc
+++ b/components/omnibox/browser/omnibox_field_trial_unittest.cc
@@ -5,6 +5,7 @@
 #include "components/omnibox/browser/omnibox_field_trial.h"
 
 #include <memory>
+#include <utility>
 
 #include "base/command_line.h"
 #include "base/macros.h"
diff --git a/components/omnibox/browser/omnibox_metrics_provider.h b/components/omnibox/browser/omnibox_metrics_provider.h
index ef5ce110..f069171 100644
--- a/components/omnibox/browser/omnibox_metrics_provider.h
+++ b/components/omnibox/browser/omnibox_metrics_provider.h
@@ -5,6 +5,8 @@
 #ifndef COMPONENTS_OMNIBOX_BROWSER_OMNIBOX_METRICS_PROVIDER_H_
 #define COMPONENTS_OMNIBOX_BROWSER_OMNIBOX_METRICS_PROVIDER_H_
 
+#include <memory>
+
 #include "base/macros.h"
 #include "components/metrics/metrics_provider.h"
 #include "components/omnibox/browser/omnibox_event_global_tracker.h"
diff --git a/components/omnibox/browser/omnibox_popup_model.cc b/components/omnibox/browser/omnibox_popup_model.cc
index c029b70..077688f 100644
--- a/components/omnibox/browser/omnibox_popup_model.cc
+++ b/components/omnibox/browser/omnibox_popup_model.cc
@@ -330,4 +330,4 @@
       view_->OnMatchIconUpdated(i);
     }
   }
-}
\ No newline at end of file
+}
diff --git a/components/omnibox/browser/omnibox_pref_names.h b/components/omnibox/browser/omnibox_pref_names.h
index 0e0745251..2f26309 100644
--- a/components/omnibox/browser/omnibox_pref_names.h
+++ b/components/omnibox/browser/omnibox_pref_names.h
@@ -13,6 +13,6 @@
 extern const char kZeroSuggestCachedResults[];
 extern const char kZeroSuggestChromeHomePersonalized[];
 
-}  // namespace metrics
+}  // namespace omnibox
 
 #endif  // COMPONENTS_OMNIBOX_BROWSER_OMNIBOX_PREF_NAMES_H_
diff --git a/components/omnibox/browser/physical_web_provider.cc b/components/omnibox/browser/physical_web_provider.cc
index a605b3c..ce8b0ee 100644
--- a/components/omnibox/browser/physical_web_provider.cc
+++ b/components/omnibox/browser/physical_web_provider.cc
@@ -4,6 +4,10 @@
 
 #include "components/omnibox/browser/physical_web_provider.h"
 
+#include <memory>
+#include <string>
+#include <utility>
+
 #include "base/feature_list.h"
 #include "base/memory/ptr_util.h"
 #include "base/metrics/histogram_macros.h"
@@ -36,7 +40,7 @@
 
 // The maximum number of Physical Web URLs to retrieve from the index.
 static const size_t kPhysicalWebIndexMaxMatches = 50;
-}
+}  // namespace
 
 // static
 const size_t PhysicalWebProvider::kPhysicalWebMaxMatches = 1;
diff --git a/components/omnibox/browser/physical_web_provider.h b/components/omnibox/browser/physical_web_provider.h
index f316c6e..2ddc3b4f 100644
--- a/components/omnibox/browser/physical_web_provider.h
+++ b/components/omnibox/browser/physical_web_provider.h
@@ -5,6 +5,7 @@
 #ifndef COMPONENTS_OMNIBOX_BROWSER_PHYSICAL_WEB_PROVIDER_H_
 #define COMPONENTS_OMNIBOX_BROWSER_PHYSICAL_WEB_PROVIDER_H_
 
+#include <memory>
 #include <vector>
 
 #include "base/macros.h"
diff --git a/components/omnibox/browser/physical_web_provider_unittest.cc b/components/omnibox/browser/physical_web_provider_unittest.cc
index 6f5d2c20..4f52662 100644
--- a/components/omnibox/browser/physical_web_provider_unittest.cc
+++ b/components/omnibox/browser/physical_web_provider_unittest.cc
@@ -4,8 +4,10 @@
 
 #include "components/omnibox/browser/physical_web_provider.h"
 
+#include <map>
 #include <memory>
 #include <string>
+#include <utility>
 
 #include "base/memory/ptr_util.h"
 #include "base/metrics/field_trial.h"
diff --git a/components/omnibox/browser/scored_history_match.cc b/components/omnibox/browser/scored_history_match.cc
index afcf569b..6ae1ab6 100644
--- a/components/omnibox/browser/scored_history_match.cc
+++ b/components/omnibox/browser/scored_history_match.cc
@@ -7,6 +7,7 @@
 #include <math.h>
 
 #include <algorithm>
+#include <utility>
 #include <vector>
 
 #include "base/logging.h"
@@ -655,7 +656,7 @@
       matches_to_specificity->begin(), matches_to_specificity->end(),
       std::pair<size_t, double>{num_matching_pages, -1});
   return (it != matches_to_specificity->end()) ? it->second : 1.0;
-};
+}
 
 // static
 float ScoredHistoryMatch::GetFinalRelevancyScore(float topicality_score,
diff --git a/components/omnibox/browser/scored_history_match.h b/components/omnibox/browser/scored_history_match.h
index f9c478a7..0020c94 100644
--- a/components/omnibox/browser/scored_history_match.h
+++ b/components/omnibox/browser/scored_history_match.h
@@ -8,6 +8,7 @@
 #include <stddef.h>
 
 #include <string>
+#include <utility>
 #include <vector>
 
 #include "base/gtest_prod_util.h"
diff --git a/components/omnibox/browser/scored_history_match_unittest.cc b/components/omnibox/browser/scored_history_match_unittest.cc
index da8e2db..2c978b9 100644
--- a/components/omnibox/browser/scored_history_match_unittest.cc
+++ b/components/omnibox/browser/scored_history_match_unittest.cc
@@ -6,6 +6,7 @@
 
 #include <algorithm>
 #include <memory>
+#include <utility>
 
 #include "base/auto_reset.h"
 #include "base/bind.h"
diff --git a/components/omnibox/browser/search_suggestion_parser.cc b/components/omnibox/browser/search_suggestion_parser.cc
index b4a899c..95a6031 100644
--- a/components/omnibox/browser/search_suggestion_parser.cc
+++ b/components/omnibox/browser/search_suggestion_parser.cc
@@ -5,7 +5,9 @@
 #include "components/omnibox/browser/search_suggestion_parser.h"
 
 #include <stddef.h>
+
 #include <algorithm>
+#include <memory>
 #include <utility>
 
 #include "base/i18n/icu_string_conversions.h"
diff --git a/components/omnibox/browser/search_suggestion_parser.h b/components/omnibox/browser/search_suggestion_parser.h
index 2cf5e103..5e5d3ec 100644
--- a/components/omnibox/browser/search_suggestion_parser.h
+++ b/components/omnibox/browser/search_suggestion_parser.h
@@ -5,6 +5,7 @@
 #ifndef COMPONENTS_OMNIBOX_BROWSER_SEARCH_SUGGESTION_PARSER_H_
 #define COMPONENTS_OMNIBOX_BROWSER_SEARCH_SUGGESTION_PARSER_H_
 
+#include <memory>
 #include <string>
 #include <vector>
 
diff --git a/components/omnibox/browser/shortcuts_backend.cc b/components/omnibox/browser/shortcuts_backend.cc
index 6f54aa5..03cc7f7 100644
--- a/components/omnibox/browser/shortcuts_backend.cc
+++ b/components/omnibox/browser/shortcuts_backend.cc
@@ -5,7 +5,9 @@
 #include "components/omnibox/browser/shortcuts_backend.h"
 
 #include <stddef.h>
+
 #include <map>
+#include <set>
 #include <string>
 #include <utility>
 #include <vector>
diff --git a/components/omnibox/browser/shortcuts_backend.h b/components/omnibox/browser/shortcuts_backend.h
index ce8536e..dd9673a5 100644
--- a/components/omnibox/browser/shortcuts_backend.h
+++ b/components/omnibox/browser/shortcuts_backend.h
@@ -7,6 +7,7 @@
 
 #include <map>
 #include <memory>
+#include <set>
 #include <string>
 #include <vector>
 
diff --git a/components/omnibox/browser/shortcuts_provider.cc b/components/omnibox/browser/shortcuts_provider.cc
index 671543e..a4121317 100644
--- a/components/omnibox/browser/shortcuts_provider.cc
+++ b/components/omnibox/browser/shortcuts_provider.cc
@@ -9,6 +9,7 @@
 #include <algorithm>
 #include <cmath>
 #include <map>
+#include <utility>
 #include <vector>
 
 #include "base/i18n/break_iterator.h"
diff --git a/components/omnibox/browser/shortcuts_provider_test_util.h b/components/omnibox/browser/shortcuts_provider_test_util.h
index 4ce8b04..adb0c8a 100644
--- a/components/omnibox/browser/shortcuts_provider_test_util.h
+++ b/components/omnibox/browser/shortcuts_provider_test_util.h
@@ -2,7 +2,11 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
+#ifndef COMPONENTS_OMNIBOX_BROWSER_SHORTCUTS_PROVIDER_TEST_UTIL_H_
+#define COMPONENTS_OMNIBOX_BROWSER_SHORTCUTS_PROVIDER_TEST_UTIL_H_
+
 #include <string>
+#include <utility>
 #include <vector>
 
 #include "base/memory/ref_counted.h"
@@ -63,3 +67,5 @@
     const std::vector<ExpectedURLAndAllowedToBeDefault>& expected_urls,
     std::string expected_top_result,
     base::string16 top_result_inline_autocompletion);
+
+#endif  // COMPONENTS_OMNIBOX_BROWSER_SHORTCUTS_PROVIDER_TEST_UTIL_H_
diff --git a/components/omnibox/browser/shortcuts_provider_unittest.cc b/components/omnibox/browser/shortcuts_provider_unittest.cc
index 8ebc37a9..9d0814f 100644
--- a/components/omnibox/browser/shortcuts_provider_unittest.cc
+++ b/components/omnibox/browser/shortcuts_provider_unittest.cc
@@ -9,6 +9,7 @@
 
 #include <algorithm>
 #include <functional>
+#include <memory>
 #include <set>
 #include <string>
 #include <vector>
diff --git a/components/omnibox/browser/suggestion_answer_unittest.cc b/components/omnibox/browser/suggestion_answer_unittest.cc
index ff8395f..d0a3553f 100644
--- a/components/omnibox/browser/suggestion_answer_unittest.cc
+++ b/components/omnibox/browser/suggestion_answer_unittest.cc
@@ -4,6 +4,8 @@
 
 #include "components/omnibox/browser/suggestion_answer.h"
 
+#include <algorithm>
+
 #include "base/json/json_reader.h"
 #include "base/memory/ptr_util.h"
 #include "base/strings/utf_string_conversions.h"
diff --git a/components/omnibox/browser/test_scheme_classifier.cc b/components/omnibox/browser/test_scheme_classifier.cc
index 40b98ee..3268364 100644
--- a/components/omnibox/browser/test_scheme_classifier.cc
+++ b/components/omnibox/browser/test_scheme_classifier.cc
@@ -4,6 +4,8 @@
 
 #include <stddef.h>
 
+#include <string>
+
 #include "base/macros.h"
 #include "components/omnibox/browser/test_scheme_classifier.h"
 #include "net/url_request/url_request.h"
diff --git a/components/omnibox/browser/test_scheme_classifier.h b/components/omnibox/browser/test_scheme_classifier.h
index 9334859..09b81e7a 100644
--- a/components/omnibox/browser/test_scheme_classifier.h
+++ b/components/omnibox/browser/test_scheme_classifier.h
@@ -5,6 +5,8 @@
 #ifndef COMPONENTS_OMNIBOX_BROWSER_TEST_SCHEME_CLASSIFIER_H_
 #define COMPONENTS_OMNIBOX_BROWSER_TEST_SCHEME_CLASSIFIER_H_
 
+#include <string>
+
 #include "base/macros.h"
 #include "components/omnibox/browser/autocomplete_scheme_classifier.h"
 
diff --git a/components/omnibox/browser/titled_url_match_utils.cc b/components/omnibox/browser/titled_url_match_utils.cc
index 7f758c35..08c6139 100644
--- a/components/omnibox/browser/titled_url_match_utils.cc
+++ b/components/omnibox/browser/titled_url_match_utils.cc
@@ -4,6 +4,8 @@
 
 #include "components/omnibox/browser/titled_url_match_utils.h"
 
+#include <vector>
+
 #include "base/strings/string_util.h"
 #include "base/strings/utf_string_conversions.h"
 #include "components/bookmarks/browser/titled_url_node.h"
diff --git a/components/omnibox/browser/titled_url_match_utils_unittest.cc b/components/omnibox/browser/titled_url_match_utils_unittest.cc
index e0749910..5085933 100644
--- a/components/omnibox/browser/titled_url_match_utils_unittest.cc
+++ b/components/omnibox/browser/titled_url_match_utils_unittest.cc
@@ -24,7 +24,7 @@
 // A simple AutocompleteProvider that does nothing.
 class MockAutocompleteProvider : public AutocompleteProvider {
  public:
-  MockAutocompleteProvider(Type type) : AutocompleteProvider(type) {}
+  explicit MockAutocompleteProvider(Type type) : AutocompleteProvider(type) {}
 
   void Start(const AutocompleteInput& input, bool minimal_changes) override {}
 
diff --git a/components/omnibox/browser/url_index_private_data.h b/components/omnibox/browser/url_index_private_data.h
index 7baab93..b8e0b8b7 100644
--- a/components/omnibox/browser/url_index_private_data.h
+++ b/components/omnibox/browser/url_index_private_data.h
@@ -7,6 +7,7 @@
 
 #include <stddef.h>
 
+#include <map>
 #include <set>
 #include <string>
 
diff --git a/components/omnibox/browser/zero_suggest_provider.cc b/components/omnibox/browser/zero_suggest_provider.cc
index 122739a1..4323f046 100644
--- a/components/omnibox/browser/zero_suggest_provider.cc
+++ b/components/omnibox/browser/zero_suggest_provider.cc
@@ -6,6 +6,9 @@
 
 #include <stddef.h>
 
+#include <string>
+#include <utility>
+
 #include "base/callback.h"
 #include "base/feature_list.h"
 #include "base/i18n/case_conversion.h"
diff --git a/components/omnibox/browser/zero_suggest_provider.h b/components/omnibox/browser/zero_suggest_provider.h
index c197101..d21e18e6 100644
--- a/components/omnibox/browser/zero_suggest_provider.h
+++ b/components/omnibox/browser/zero_suggest_provider.h
@@ -10,6 +10,7 @@
 #define COMPONENTS_OMNIBOX_BROWSER_ZERO_SUGGEST_PROVIDER_H_
 
 #include <memory>
+#include <string>
 
 #include "base/compiler_specific.h"
 #include "base/macros.h"
diff --git a/components/omnibox/browser/zero_suggest_provider_unittest.cc b/components/omnibox/browser/zero_suggest_provider_unittest.cc
index d914b68..daec7f8 100644
--- a/components/omnibox/browser/zero_suggest_provider_unittest.cc
+++ b/components/omnibox/browser/zero_suggest_provider_unittest.cc
@@ -4,6 +4,9 @@
 
 #include "components/omnibox/browser/zero_suggest_provider.h"
 
+#include <map>
+#include <string>
+
 #include "base/memory/ptr_util.h"
 #include "base/metrics/field_trial.h"
 #include "base/run_loop.h"
diff --git a/components/open_from_clipboard/OWNERS b/components/open_from_clipboard/OWNERS
index 48eb126..f566e77 100644
--- a/components/open_from_clipboard/OWNERS
+++ b/components/open_from_clipboard/OWNERS
@@ -1 +1 @@
-jif@chromium.org
\ No newline at end of file
+olivierrobin@chromium.org
\ No newline at end of file
diff --git a/components/safe_browsing/db/v4_test_util.cc b/components/safe_browsing/db/v4_test_util.cc
index d9fdf01b..6d973205 100644
--- a/components/safe_browsing/db/v4_test_util.cc
+++ b/components/safe_browsing/db/v4_test_util.cc
@@ -48,7 +48,7 @@
 }
 
 void TestV4Store::MarkPrefixAsBad(HashPrefix prefix) {
-  hash_prefix_map_[prefix.size()] = prefix;
+  hash_prefix_map_[prefix.size()] += prefix;
 }
 
 TestV4Database::TestV4Database(
diff --git a/components/signin/core/browser/account_reconcilor.cc b/components/signin/core/browser/account_reconcilor.cc
index db17e73..140a4d4 100644
--- a/components/signin/core/browser/account_reconcilor.cc
+++ b/components/signin/core/browser/account_reconcilor.cc
@@ -12,6 +12,7 @@
 #include "base/json/json_reader.h"
 #include "base/location.h"
 #include "base/logging.h"
+#include "base/metrics/histogram_macros.h"
 #include "base/single_thread_task_runner.h"
 #include "base/stl_util.h"
 #include "base/strings/string_number_conversions.h"
@@ -94,14 +95,16 @@
       account_reconcilor_lock_count_(0),
       reconcile_on_unblock_(false) {
   VLOG(1) << "AccountReconcilor::AccountReconcilor";
+  PrefService* prefs = client_->GetPrefs();
   if (ShouldMigrateToDiceOnStartup()) {
-    PrefService* prefs = client_->GetPrefs();
     DCHECK(prefs);
     if (!signin::IsDiceEnabledForProfile(prefs))
       VLOG(1) << "Profile is migrating to Dice";
     signin::MigrateProfileToDice(client->GetPrefs());
     DCHECK(signin::IsDiceEnabledForProfile(prefs));
   }
+  UMA_HISTOGRAM_BOOLEAN("Signin.DiceEnabledForProfile",
+                        signin::IsDiceEnabledForProfile(prefs));
 }
 
 AccountReconcilor::~AccountReconcilor() {
diff --git a/components/signin/ios/browser/account_consistency_service_unittest.mm b/components/signin/ios/browser/account_consistency_service_unittest.mm
index 5161ab0a..98f54de 100644
--- a/components/signin/ios/browser/account_consistency_service_unittest.mm
+++ b/components/signin/ios/browser/account_consistency_service_unittest.mm
@@ -8,6 +8,7 @@
 
 #include <memory>
 
+#include "base/memory/ptr_util.h"
 #include "components/signin/core/browser/account_reconcilor.h"
 #include "components/signin/core/browser/account_tracker_service.h"
 #include "components/signin/core/browser/fake_signin_manager.h"
@@ -76,8 +77,8 @@
 // Mock AccountReconcilor to catch call to OnReceivedManageAccountsResponse.
 class MockAccountReconcilor : public AccountReconcilor {
  public:
-  MockAccountReconcilor()
-      : AccountReconcilor(nullptr, nullptr, nullptr, nullptr) {}
+  MockAccountReconcilor(SigninClient* client)
+      : AccountReconcilor(nullptr, nullptr, client, nullptr) {}
   MOCK_METHOD1(OnReceivedManageAccountsResponse, void(signin::GAIAServiceType));
 };
 
@@ -148,6 +149,8 @@
         false /* store_last_modified */);
     cookie_settings_ =
         new content_settings::CookieSettings(settings_map_.get(), &prefs_, "");
+    account_reconcilor_ =
+        base::MakeUnique<MockAccountReconcilor>(signin_client_.get());
     ResetAccountConsistencyService();
   }
 
@@ -184,7 +187,7 @@
       account_consistency_service_->Shutdown();
     }
     account_consistency_service_.reset(new FakeAccountConsistencyService(
-        &browser_state_, &account_reconcilor_, cookie_settings_,
+        &browser_state_, account_reconcilor_.get(), cookie_settings_,
         gaia_cookie_manager_service_.get(), signin_client_.get(),
         signin_manager_.get()));
   }
@@ -237,7 +240,6 @@
   // Creates test threads, necessary for ActiveStateManager that needs a UI
   // thread.
   web::TestWebThreadBundle thread_bundle_;
-  MockAccountReconcilor account_reconcilor_;
   AccountTrackerService account_tracker_service_;
   web::TestBrowserState browser_state_;
   sync_preferences::TestingPrefServiceSyncable prefs_;
@@ -248,6 +250,7 @@
   std::unique_ptr<TestSigninClient> signin_client_;
   std::unique_ptr<FakeSigninManager> signin_manager_;
   std::unique_ptr<MockGaiaCookieManagerService> gaia_cookie_manager_service_;
+  std::unique_ptr<MockAccountReconcilor> account_reconcilor_;
   scoped_refptr<HostContentSettingsMap> settings_map_;
   scoped_refptr<content_settings::CookieSettings> cookie_settings_;
   bool remove_cookie_callback_called_;
@@ -388,8 +391,8 @@
        HTTPVersion:@"HTTP/1.1"
       headerFields:headers];
   account_consistency_service_->SetWebStateHandler(&web_state_, delegate);
-  EXPECT_CALL(account_reconcilor_, OnReceivedManageAccountsResponse(
-                                       signin::GAIA_SERVICE_TYPE_DEFAULT))
+  EXPECT_CALL(*account_reconcilor_, OnReceivedManageAccountsResponse(
+                                        signin::GAIA_SERVICE_TYPE_DEFAULT))
       .Times(1);
   EXPECT_FALSE(
       web_state_.ShouldAllowResponse(response, /* for_main_frame = */ true));
diff --git a/components/spellcheck/common/spellcheck_messages.h b/components/spellcheck/common/spellcheck_messages.h
index 616315c..c2952701 100644
--- a/components/spellcheck/common/spellcheck_messages.h
+++ b/components/spellcheck/common/spellcheck_messages.h
@@ -17,7 +17,7 @@
 
 #define IPC_MESSAGE_START SpellCheckMsgStart
 
-IPC_ENUM_TRAITS(SpellCheckResult::Decoration)
+IPC_ENUM_TRAITS_MAX_VALUE(SpellCheckResult::Decoration, SpellCheckResult::LAST)
 
 IPC_STRUCT_TRAITS_BEGIN(SpellCheckResult)
   IPC_STRUCT_TRAITS_MEMBER(decoration)
diff --git a/components/spellcheck/common/spellcheck_result.h b/components/spellcheck/common/spellcheck_result.h
index 1937a8f..5ee9cfdd 100644
--- a/components/spellcheck/common/spellcheck_result.h
+++ b/components/spellcheck/common/spellcheck_result.h
@@ -16,11 +16,12 @@
 struct SpellCheckResult {
   enum Decoration {
     // Red underline for misspelled words.
-    SPELLING = 1 << 1,
+    SPELLING,
 
     // Gray underline for correctly spelled words that are incorrectly used in
     // their context.
-    GRAMMAR = 1 << 2,
+    GRAMMAR,
+    LAST = GRAMMAR,
   };
 
   // Default values are so we have a default constructor for IPC::ReadParam()
diff --git a/components/subresource_filter/content/browser/subresource_filter_safe_browsing_activation_throttle.cc b/components/subresource_filter/content/browser/subresource_filter_safe_browsing_activation_throttle.cc
index ec881ff..b5e2b74 100644
--- a/components/subresource_filter/content/browser/subresource_filter_safe_browsing_activation_throttle.cc
+++ b/components/subresource_filter/content/browser/subresource_filter_safe_browsing_activation_throttle.cc
@@ -223,8 +223,8 @@
   // activation.
   bool whitelisted = client_->OnPageActivationComputed(
       navigation_handle(),
-      matched_configuration.activation_options.activation_level ==
-          ActivationLevel::ENABLED,
+      !warning && matched_configuration.activation_options.activation_level ==
+                      ActivationLevel::ENABLED,
       matched_configuration.activation_options.should_suppress_notifications);
 
   // Only reset the activation decision reason if we would have activated.
diff --git a/components/test/data/payments/render_tests/PaymentRequestFreeShippingTest.unmask.Nexus_5-19.png b/components/test/data/payments/render_tests/PaymentRequestFreeShippingTest.unmask.Nexus_5-19.png
index 8580453b..222fce0 100644
--- a/components/test/data/payments/render_tests/PaymentRequestFreeShippingTest.unmask.Nexus_5-19.png
+++ b/components/test/data/payments/render_tests/PaymentRequestFreeShippingTest.unmask.Nexus_5-19.png
Binary files differ
diff --git a/components/translate/core/language_detection/language_detection_util.cc b/components/translate/core/language_detection/language_detection_util.cc
index 5085df19..179c329 100644
--- a/components/translate/core/language_detection/language_detection_util.cc
+++ b/components/translate/core/language_detection/language_detection_util.cc
@@ -58,12 +58,12 @@
 }
 
 // Well-known languages which often have wrong server configuration of
-// Content-Language: en.
-// TODO(toyoshim): Remove these static tables and caller functions to
-// translate/common, and implement them as std::set<>.
-const char* kWellKnownCodesOnWrongConfiguration[] = {
-  "es", "pt", "ja", "ru", "de", "zh-CN", "zh-TW", "ar", "id", "fr", "it", "th"
-};
+// Content-Language: en. The list must be sorted alphabatically so
+// they can be binary searched.
+const char* const kWellKnownCodesOnWrongConfiguration[] = {
+    "ar", "da", "de", "el", "es", "fa", "fr",    "hi",
+    "hu", "id", "it", "ja", "ms", "nl", "pl",    "pt",
+    "ro", "ru", "sv", "th", "tr", "vi", "zh-CN", "zh-TW"};
 
 // Applies a series of language code modification in proper order.
 void ApplyLanguageCodeCorrection(std::string* code) {
@@ -431,6 +431,12 @@
   return match;
 }
 
+bool IsServerWrongConfigurationLanguage(const std::string& language_code) {
+  return binary_search(kWellKnownCodesOnWrongConfiguration,
+                       std::end(kWellKnownCodesOnWrongConfiguration),
+                       language_code);
+}
+
 bool MaybeServerWrongConfiguration(const std::string& page_language,
                                    const std::string& cld_language) {
   // If |page_language| is not "en-*", respect it and just return false here.
@@ -443,11 +449,7 @@
   // Let's trust |cld_language| if the determined language is not difficult to
   // distinguish from English, and the language is one of well-known languages
   // which often provide "en-*" meta information mistakenly.
-  for (size_t i = 0; i < arraysize(kWellKnownCodesOnWrongConfiguration); ++i) {
-    if (cld_language == kWellKnownCodesOnWrongConfiguration[i])
-      return true;
-  }
-  return false;
+  return IsServerWrongConfigurationLanguage(cld_language);
 }
 
 }  // namespace translate
diff --git a/components/translate/core/language_detection/language_detection_util.h b/components/translate/core/language_detection/language_detection_util.h
index aa3f0bc..8e4fb68 100644
--- a/components/translate/core/language_detection/language_detection_util.h
+++ b/components/translate/core/language_detection/language_detection_util.h
@@ -39,6 +39,10 @@
 bool MaybeServerWrongConfiguration(const std::string& page_language,
                                    const std::string& cld_language);
 
+// Returns true if the specified language often has the wrong server
+// configuration language, false otherwise.
+bool IsServerWrongConfigurationLanguage(const std::string& language);
+
 }  // namespace translate
 
 #endif  // COMPONENTS_TRANSLATE_CORE_LANGUAGE_DETECTION_LANGUAGE_DETECTION_UTIL_H_
diff --git a/components/translate/core/language_detection/language_detection_util_unittest.cc b/components/translate/core/language_detection/language_detection_util_unittest.cc
index 3103458..a931556 100644
--- a/components/translate/core/language_detection/language_detection_util_unittest.cc
+++ b/components/translate/core/language_detection/language_detection_util_unittest.cc
@@ -171,3 +171,25 @@
   EXPECT_EQ("en", cld_language);
   EXPECT_TRUE(is_cld_reliable);
 }
+
+// Tests that languages that often have the wrong server configuration are
+// correctly identified. All incorrect language codes should be checked to
+// make sure the binary_search is correct.
+TEST_F(LanguageDetectionUtilTest, IsServerWrongConfigurationLanguage) {
+  // These languages should all be identified as having the wrong server
+  // configuration.
+  const char* const wrong_languages[] = {
+      "ar", "da", "de", "el", "es", "fa", "fr",    "hi",
+      "hu", "id", "it", "ja", "ms", "nl", "pl",    "pt",
+      "ro", "ru", "sv", "th", "tr", "vi", "zh-CN", "zh-TW"};
+  for (const char* const language : wrong_languages) {
+    EXPECT_TRUE(translate::IsServerWrongConfigurationLanguage(language));
+  }
+  // These languages should all be identified as having the right server
+  // configuration.
+  const char* const right_languages[] = {"en", "en-AU", "en-US",
+                                         "xx", "gg",    "rr"};
+  for (const char* const language : right_languages) {
+    EXPECT_FALSE(translate::IsServerWrongConfigurationLanguage(language));
+  }
+}
diff --git a/components/viz/host/host_frame_sink_manager.cc b/components/viz/host/host_frame_sink_manager.cc
index 6c9f2b6..2de59528 100644
--- a/components/viz/host/host_frame_sink_manager.cc
+++ b/components/viz/host/host_frame_sink_manager.cc
@@ -133,10 +133,12 @@
                                                   child_frame_sink_id);
 
   FrameSinkData& child_data = frame_sink_data_map_[child_frame_sink_id];
+  DCHECK(child_data.IsFrameSinkRegistered());
   DCHECK(!base::ContainsValue(child_data.parents, parent_frame_sink_id));
   child_data.parents.push_back(parent_frame_sink_id);
 
   FrameSinkData& parent_data = frame_sink_data_map_[parent_frame_sink_id];
+  DCHECK(parent_data.IsFrameSinkRegistered());
   DCHECK(!base::ContainsValue(parent_data.children, child_frame_sink_id));
   parent_data.children.push_back(child_frame_sink_id);
 }
diff --git a/components/viz/host/host_frame_sink_manager.h b/components/viz/host/host_frame_sink_manager.h
index 6b1ed32..95cb735 100644
--- a/components/viz/host/host_frame_sink_manager.h
+++ b/components/viz/host/host_frame_sink_manager.h
@@ -101,7 +101,8 @@
                                  mojom::CompositorFrameSinkRequest request,
                                  mojom::CompositorFrameSinkClientPtr client);
 
-  // Registers frame sink hierarchy. A frame sink can have multiple parents.
+  // Registers frame sink hierarchy. Both parent and child FrameSinkIds must be
+  // registered before calling. A frame sink can have multiple parents.
   void RegisterFrameSinkHierarchy(const FrameSinkId& parent_frame_sink_id,
                                   const FrameSinkId& child_frame_sink_id);
 
diff --git a/components/viz/host/host_frame_sink_manager_unittest.cc b/components/viz/host/host_frame_sink_manager_unittest.cc
index a46fa8e1..edf8d8df 100644
--- a/components/viz/host/host_frame_sink_manager_unittest.cc
+++ b/components/viz/host/host_frame_sink_manager_unittest.cc
@@ -16,6 +16,7 @@
 #include "components/viz/service/frame_sinks/compositor_frame_sink_support.h"
 #include "components/viz/service/frame_sinks/frame_sink_manager_impl.h"
 #include "components/viz/service/surfaces/surface_manager.h"
+#include "components/viz/test/fake_host_frame_sink_client.h"
 #include "components/viz/test/mock_compositor_frame_sink_client.h"
 #include "services/viz/privileged/interfaces/compositing/frame_sink_manager.mojom.h"
 #include "testing/gmock/include/gmock/gmock.h"
@@ -46,19 +47,6 @@
   return SurfaceInfo(surface_id, 1.f, gfx::Size(1, 1));
 }
 
-// A fake (do-nothing) implementation of HostFrameSinkClient.
-class FakeHostFrameSinkClient : public HostFrameSinkClient {
- public:
-  FakeHostFrameSinkClient() = default;
-  ~FakeHostFrameSinkClient() override = default;
-
-  // HostFrameSinkClient implementation.
-  void OnFirstSurfaceActivation(const SurfaceInfo& surface_info) override {}
-
- private:
-  DISALLOW_COPY_AND_ASSIGN(FakeHostFrameSinkClient);
-};
-
 // A mock implementation of mojom::FrameSinkManager.
 class MockFrameSinkManagerImpl : public FrameSinkManagerImpl {
  public:
diff --git a/components/viz/service/display/gl_renderer.cc b/components/viz/service/display/gl_renderer.cc
index 8b21c43..a81bf62 100644
--- a/components/viz/service/display/gl_renderer.cc
+++ b/components/viz/service/display/gl_renderer.cc
@@ -3400,11 +3400,11 @@
   DCHECK(ca_layer_overlay->rpdq);
 
   if (!overlay_resource_pool_) {
-    overlay_resource_pool_ =
-        cc::ResourcePool::CreateForGpuMemoryBufferResources(
-            resource_provider_, base::ThreadTaskRunnerHandle::Get().get(),
-            gfx::BufferUsage::SCANOUT, base::TimeDelta::FromSeconds(3),
-            settings_->disallow_non_exact_resource_reuse);
+    overlay_resource_pool_ = cc::ResourcePool::Create(
+        resource_provider_, base::ThreadTaskRunnerHandle::Get().get(),
+        cc::ResourceProvider::TEXTURE_HINT_OVERLAY,
+        base::TimeDelta::FromSeconds(3),
+        settings_->disallow_non_exact_resource_reuse);
   }
 
   cc::Resource* resource = nullptr;
diff --git a/components/viz/service/display/gl_renderer_unittest.cc b/components/viz/service/display/gl_renderer_unittest.cc
index 31ebfbbf..51a0fa1 100644
--- a/components/viz/service/display/gl_renderer_unittest.cc
+++ b/components/viz/service/display/gl_renderer_unittest.cc
@@ -1973,7 +1973,11 @@
   std::vector<TransferableResource> list;
   child_resource_provider->PrepareSendToParent(resource_ids_to_transfer, &list);
   parent_resource_provider->ReceiveFromChild(child_id, list);
-  ResourceId parent_resource_id = list[0].id;
+
+  // In DisplayResourceProvider's namespace, use the mapped resource id.
+  cc::ResourceProvider::ResourceIdMap resource_map =
+      parent_resource_provider->GetChildToParentMap(child_id);
+  ResourceId parent_resource_id = resource_map[list[0].id];
 
   RendererSettings settings;
   FakeRendererGL renderer(&settings, output_surface.get(),
@@ -2165,7 +2169,11 @@
   std::vector<TransferableResource> list;
   child_resource_provider->PrepareSendToParent(resource_ids_to_transfer, &list);
   parent_resource_provider->ReceiveFromChild(child_id, list);
-  ResourceId parent_resource_id = list[0].id;
+
+  // In DisplayResourceProvider's namespace, use the mapped resource id.
+  cc::ResourceProvider::ResourceIdMap resource_map =
+      parent_resource_provider->GetChildToParentMap(child_id);
+  ResourceId parent_resource_id = resource_map[list[0].id];
 
   RendererSettings settings;
   FakeRendererGL renderer(&settings, output_surface.get(),
@@ -2403,7 +2411,10 @@
   std::vector<TransferableResource> list;
   child_resource_provider->PrepareSendToParent(resource_ids_to_transfer, &list);
   parent_resource_provider->ReceiveFromChild(child_id, list);
-  ResourceId parent_resource_id = list[0].id;
+  // In DisplayResourceProvider's namespace, use the mapped resource id.
+  cc::ResourceProvider::ResourceIdMap resource_map =
+      parent_resource_provider->GetChildToParentMap(child_id);
+  ResourceId parent_resource_id = resource_map[list[0].id];
 
   RendererSettings settings;
   settings.partial_swap_enabled = true;
diff --git a/components/viz/service/display/overlay_unittest.cc b/components/viz/service/display/overlay_unittest.cc
index aa44e779..a06fbb7 100644
--- a/components/viz/service/display/overlay_unittest.cc
+++ b/components/viz/service/display/overlay_unittest.cc
@@ -284,8 +284,11 @@
   std::vector<TransferableResource> list;
   child_resource_provider->PrepareSendToParent(resource_ids_to_transfer, &list);
   parent_resource_provider->ReceiveFromChild(child_id, list);
-  ResourceId parent_resource_id = list[0].id;
-  return parent_resource_id;
+
+  // In DisplayResourceProvider's namespace, use the mapped resource id.
+  cc::ResourceProvider::ResourceIdMap resource_map =
+      parent_resource_provider->GetChildToParentMap(child_id);
+  return resource_map[list[0].id];
 }
 
 SolidColorDrawQuad* CreateSolidColorQuadAt(
diff --git a/components/viz/service/display_embedder/buffer_queue.cc b/components/viz/service/display_embedder/buffer_queue.cc
index 11cbf2d..f2bfa394c 100644
--- a/components/viz/service/display_embedder/buffer_queue.cc
+++ b/components/viz/service/display_embedder/buffer_queue.cc
@@ -271,7 +271,7 @@
     DLOG(ERROR) << "Failed to allocate GPU memory buffer";
     return nullptr;
   }
-  buffer->SetColorSpaceForScanout(color_space_);
+  buffer->SetColorSpace(color_space_);
 
   uint32_t id =
       gl_->CreateImageCHROMIUM(buffer->AsClientBuffer(), size_.width(),
diff --git a/components/viz/service/display_embedder/buffer_queue_unittest.cc b/components/viz/service/display_embedder/buffer_queue_unittest.cc
index 8d940ead..7a2e1dd 100644
--- a/components/viz/service/display_embedder/buffer_queue_unittest.cc
+++ b/components/viz/service/display_embedder/buffer_queue_unittest.cc
@@ -46,7 +46,7 @@
   gfx::GpuMemoryBufferId GetId() const override {
     return gfx::GpuMemoryBufferId(0);
   }
-  void SetColorSpaceForScanout(const gfx::ColorSpace& color_space) override {
+  void SetColorSpace(const gfx::ColorSpace& color_space) override {
     *set_color_space_count_ += 1;
   }
   gfx::GpuMemoryBufferHandle GetHandle() const override {
diff --git a/components/viz/test/BUILD.gn b/components/viz/test/BUILD.gn
index baf86c8f..a5b3a22b 100644
--- a/components/viz/test/BUILD.gn
+++ b/components/viz/test/BUILD.gn
@@ -19,6 +19,8 @@
     "fake_delay_based_time_source.h",
     "fake_external_begin_frame_source.cc",
     "fake_external_begin_frame_source.h",
+    "fake_host_frame_sink_client.cc",
+    "fake_host_frame_sink_client.h",
     "fake_surface_observer.cc",
     "fake_surface_observer.h",
     "mock_compositor_frame_sink_client.cc",
@@ -41,6 +43,7 @@
     "//base",
     "//base/test:test_support",
     "//cc",
+    "//components/viz/host",
     "//components/viz/service",
     "//services/viz/privileged/interfaces/compositing",
     "//testing/gmock",
diff --git a/components/viz/test/fake_host_frame_sink_client.cc b/components/viz/test/fake_host_frame_sink_client.cc
new file mode 100644
index 0000000..e946e10
--- /dev/null
+++ b/components/viz/test/fake_host_frame_sink_client.cc
@@ -0,0 +1,13 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/viz/test/fake_host_frame_sink_client.h"
+
+namespace viz {
+
+FakeHostFrameSinkClient::FakeHostFrameSinkClient() = default;
+
+FakeHostFrameSinkClient::~FakeHostFrameSinkClient() = default;
+
+}  // namespace viz
diff --git a/components/viz/test/fake_host_frame_sink_client.h b/components/viz/test/fake_host_frame_sink_client.h
new file mode 100644
index 0000000..aec322fa
--- /dev/null
+++ b/components/viz/test/fake_host_frame_sink_client.h
@@ -0,0 +1,29 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef COMPONENTS_VIZ_TEST_FAKE_HOST_FRAME_SINK_CLIENT_H_
+#define COMPONENTS_VIZ_TEST_FAKE_HOST_FRAME_SINK_CLIENT_H_
+
+#include "base/macros.h"
+#include "components/viz/common/surfaces/surface_info.h"
+#include "components/viz/host/host_frame_sink_client.h"
+
+namespace viz {
+
+// HostFrameSinkClient implementation that does nothing.
+class FakeHostFrameSinkClient : public HostFrameSinkClient {
+ public:
+  FakeHostFrameSinkClient();
+  ~FakeHostFrameSinkClient() override;
+
+  // HostFrameSinkClient implementation.
+  void OnFirstSurfaceActivation(const SurfaceInfo& surface_info) override {}
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(FakeHostFrameSinkClient);
+};
+
+}  // namespace viz
+
+#endif  // COMPONENTS_VIZ_TEST_FAKE_HOST_FRAME_SINK_CLIENT_H_
diff --git a/components/web_modal/modal_dialog_host.cc b/components/web_modal/modal_dialog_host.cc
index 61ddbc29..6e237d3 100644
--- a/components/web_modal/modal_dialog_host.cc
+++ b/components/web_modal/modal_dialog_host.cc
@@ -12,4 +12,8 @@
 ModalDialogHost::~ModalDialogHost() {
 }
 
+bool ModalDialogHost::ShouldActivateDialog() const {
+  return true;
+}
+
 }  // namespace web_modal
diff --git a/components/web_modal/modal_dialog_host.h b/components/web_modal/modal_dialog_host.h
index c7842b3d..56d8fe3 100644
--- a/components/web_modal/modal_dialog_host.h
+++ b/components/web_modal/modal_dialog_host.h
@@ -33,6 +33,8 @@
   virtual gfx::NativeView GetHostView() const = 0;
   // Gets the position for the dialog in coordinates relative to the host view.
   virtual gfx::Point GetDialogPosition(const gfx::Size& size) = 0;
+  // Returns whether a dialog currently about to be shown should be activated.
+  virtual bool ShouldActivateDialog() const;
 
   // Add/remove observer.
   virtual void AddObserver(ModalDialogHostObserver* observer) = 0;
diff --git a/content/app/strings/content_strings.grd b/content/app/strings/content_strings.grd
index 2dedd1a..c4b7d8d 100644
--- a/content/app/strings/content_strings.grd
+++ b/content/app/strings/content_strings.grd
@@ -782,6 +782,9 @@
       <message name="IDS_MEDIA_OVERFLOW_MENU_CLOSED_CAPTIONS" desc="Media controls overflow menu item label for a closed captions button. The text for this overflow menu should be short.">
         Captions
       </message>
+      <message name="IDS_MEDIA_OVERFLOW_MENU_CLOSED_CAPTIONS_SUBMENU_TITLE" desc="Media controls overflow menu title for the closed captions submenu. The text for this overflow menu should be short.">
+        Options
+      </message>
       <message name="IDS_MEDIA_OVERFLOW_MENU_CAST" desc="Media controls overflow menu item label for a cast button.">
         Cast
       </message>
diff --git a/content/browser/BUILD.gn b/content/browser/BUILD.gn
index 6dff5df37..2fe1a9b48 100644
--- a/content/browser/BUILD.gn
+++ b/content/browser/BUILD.gn
@@ -250,8 +250,6 @@
     "accessibility/accessibility_tree_formatter_win.cc",
     "accessibility/accessibility_ui.cc",
     "accessibility/accessibility_ui.h",
-    "accessibility/ax_platform_position.cc",
-    "accessibility/ax_platform_position.h",
     "accessibility/browser_accessibility.cc",
     "accessibility/browser_accessibility.h",
     "accessibility/browser_accessibility_cocoa.h",
@@ -266,6 +264,8 @@
     "accessibility/browser_accessibility_manager_mac.mm",
     "accessibility/browser_accessibility_manager_win.cc",
     "accessibility/browser_accessibility_manager_win.h",
+    "accessibility/browser_accessibility_position.cc",
+    "accessibility/browser_accessibility_position.h",
     "accessibility/browser_accessibility_state_impl.cc",
     "accessibility/browser_accessibility_state_impl.h",
     "accessibility/browser_accessibility_state_impl_mac.mm",
@@ -727,8 +727,6 @@
     "fileapi/browser_file_system_helper.h",
     "fileapi/fileapi_message_filter.cc",
     "fileapi/fileapi_message_filter.h",
-    "fileapi/upload_file_system_file_element_reader.cc",
-    "fileapi/upload_file_system_file_element_reader.h",
     "find_request_manager.cc",
     "find_request_manager.h",
     "font_list_async.cc",
@@ -1922,6 +1920,8 @@
 
   if (enable_library_cdms) {
     sources += [
+      "media/cdm_file_impl.cc",
+      "media/cdm_file_impl.h",
       "media/cdm_storage_impl.cc",
       "media/cdm_storage_impl.h",
     ]
diff --git a/content/browser/accessibility/ax_platform_position.cc b/content/browser/accessibility/ax_platform_position.cc
deleted file mode 100644
index 47caacda..0000000
--- a/content/browser/accessibility/ax_platform_position.cc
+++ /dev/null
@@ -1,169 +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 "content/browser/accessibility/ax_platform_position.h"
-
-#include "content/browser/accessibility/accessibility_flags.h"
-#include "content/browser/accessibility/browser_accessibility.h"
-#include "content/browser/accessibility/browser_accessibility_manager.h"
-#include "ui/accessibility/ax_enums.h"
-
-namespace content {
-
-AXPlatformPosition::AXPlatformPosition() {}
-
-AXPlatformPosition::~AXPlatformPosition() {}
-
-AXPlatformPosition::AXPositionInstance AXPlatformPosition::Clone() const {
-  return AXPositionInstance(new AXPlatformPosition(*this));
-}
-
-base::string16 AXPlatformPosition::GetInnerText() const {
-  if (IsNullPosition())
-    return base::string16();
-  DCHECK(GetAnchor());
-  return GetAnchor()->GetText();
-}
-
-void AXPlatformPosition::AnchorChild(int child_index,
-                                     AXTreeID* tree_id,
-                                     int32_t* child_id) const {
-  DCHECK(tree_id);
-  DCHECK(child_id);
-
-  if (!GetAnchor() || child_index < 0 || child_index >= AnchorChildCount()) {
-    *tree_id = INVALID_TREE_ID;
-    *child_id = INVALID_ANCHOR_ID;
-    return;
-  }
-
-  BrowserAccessibility* child = nullptr;
-  if (GetAnchor()->PlatformIsLeaf()) {
-    child = GetAnchor()->InternalGetChild(child_index);
-  } else {
-    child = GetAnchor()->PlatformGetChild(child_index);
-  }
-  DCHECK(child);
-  *tree_id = child->manager()->ax_tree_id();
-  *child_id = child->GetId();
-}
-
-int AXPlatformPosition::AnchorChildCount() const {
-  if (!GetAnchor())
-    return 0;
-
-  if (GetAnchor()->PlatformIsLeaf()) {
-    return static_cast<int>(GetAnchor()->InternalChildCount());
-  } else {
-    return static_cast<int>(GetAnchor()->PlatformChildCount());
-  }
-}
-
-int AXPlatformPosition::AnchorIndexInParent() const {
-  return GetAnchor() ? static_cast<int>(GetAnchor()->GetIndexInParent())
-                     : AXPosition::INVALID_INDEX;
-}
-
-void AXPlatformPosition::AnchorParent(AXTreeID* tree_id,
-                                      int32_t* parent_id) const {
-  DCHECK(tree_id);
-  DCHECK(parent_id);
-
-  if (!GetAnchor() || !GetAnchor()->PlatformGetParent()) {
-    *tree_id = AXPosition::INVALID_TREE_ID;
-    *parent_id = AXPosition::INVALID_ANCHOR_ID;
-    return;
-  }
-
-  BrowserAccessibility* parent = GetAnchor()->PlatformGetParent();
-  *tree_id = parent->manager()->ax_tree_id();
-  *parent_id = parent->GetId();
-}
-
-BrowserAccessibility* AXPlatformPosition::GetNodeInTree(AXTreeID tree_id,
-                                                        int32_t node_id) const {
-  if (tree_id == AXPosition::INVALID_TREE_ID ||
-      node_id == AXPosition::INVALID_ANCHOR_ID) {
-    return nullptr;
-  }
-
-  auto* manager = BrowserAccessibilityManager::FromID(tree_id);
-  if (!manager)
-    return nullptr;
-  return manager->GetFromID(node_id);
-}
-
-int AXPlatformPosition::MaxTextOffset() const {
-  if (IsNullPosition())
-    return INVALID_OFFSET;
-  return static_cast<int>(GetInnerText().length());
-}
-
-// On some platforms, most objects are represented in the text of their parents
-// with a special (embedded object) character and not with their actual text
-// contents.
-int AXPlatformPosition::MaxTextOffsetInParent() const {
-#if defined(OS_WIN) || BUILDFLAG(USE_ATK)
-  if (IsNullPosition())
-    return INVALID_OFFSET;
-  if (GetAnchor()->IsTextOnlyObject())
-    return MaxTextOffset();
-  // Not all objects in the internal accessibility tree are exposed to platform
-  // APIs.
-  if (GetAnchor()->PlatformIsChildOfLeaf())
-    return MaxTextOffset();
-  return 1;
-#else
-  return MaxTextOffset();
-#endif
-}
-
-bool AXPlatformPosition::IsInLineBreak() const {
-  if (IsNullPosition())
-    return false;
-
-  DCHECK(GetAnchor());
-  return GetAnchor()->IsLineBreakObject();
-}
-
-std::vector<int32_t> AXPlatformPosition::GetWordStartOffsets() const {
-  if (IsNullPosition())
-    return std::vector<int32_t>();
-  DCHECK(GetAnchor());
-  return GetAnchor()->GetIntListAttribute(ui::AX_ATTR_WORD_STARTS);
-}
-
-std::vector<int32_t> AXPlatformPosition::GetWordEndOffsets() const {
-  if (IsNullPosition())
-    return std::vector<int32_t>();
-  DCHECK(GetAnchor());
-  return GetAnchor()->GetIntListAttribute(ui::AX_ATTR_WORD_ENDS);
-}
-
-int32_t AXPlatformPosition::GetNextOnLineID(int32_t node_id) const {
-  if (IsNullPosition())
-    return INVALID_ANCHOR_ID;
-  BrowserAccessibility* node = GetNodeInTree(tree_id(), node_id);
-  int next_on_line_id;
-  if (!node ||
-      !node->GetIntAttribute(ui::AX_ATTR_NEXT_ON_LINE_ID, &next_on_line_id)) {
-    return INVALID_ANCHOR_ID;
-  }
-  return static_cast<int32_t>(next_on_line_id);
-}
-
-int32_t AXPlatformPosition::GetPreviousOnLineID(int32_t node_id) const {
-  if (IsNullPosition())
-    return INVALID_ANCHOR_ID;
-  BrowserAccessibility* node = GetNodeInTree(tree_id(), node_id);
-  int previous_on_line_id;
-  if (!node ||
-      !node->GetIntAttribute(ui::AX_ATTR_PREVIOUS_ON_LINE_ID,
-                             &previous_on_line_id)) {
-    return INVALID_ANCHOR_ID;
-  }
-  return static_cast<int32_t>(previous_on_line_id);
-}
-
-}  // namespace content
diff --git a/content/browser/accessibility/ax_platform_position.h b/content/browser/accessibility/ax_platform_position.h
deleted file mode 100644
index 186c02b..0000000
--- a/content/browser/accessibility/ax_platform_position.h
+++ /dev/null
@@ -1,53 +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 CONTENT_BROWSER_ACCESSIBILITY_AX_PLATFORM_POSITION_H_
-#define CONTENT_BROWSER_ACCESSIBILITY_AX_PLATFORM_POSITION_H_
-
-#include <stdint.h>
-
-#include <vector>
-
-#include "base/strings/string16.h"
-#include "ui/accessibility/ax_position.h"
-#include "ui/accessibility/ax_tree_id_registry.h"
-
-namespace content {
-
-class BrowserAccessibility;
-
-using AXTreeID = ui::AXTreeIDRegistry::AXTreeID;
-
-class AXPlatformPosition
-    : public ui::AXPosition<AXPlatformPosition, BrowserAccessibility> {
- public:
-  AXPlatformPosition();
-  ~AXPlatformPosition() override;
-
-  AXPositionInstance Clone() const override;
-
-  base::string16 GetInnerText() const override;
-
- protected:
-  AXPlatformPosition(const AXPlatformPosition& other) = default;
-  void AnchorChild(int child_index,
-                   AXTreeID* tree_id,
-                   int32_t* child_id) const override;
-  int AnchorChildCount() const override;
-  int AnchorIndexInParent() const override;
-  void AnchorParent(AXTreeID* tree_id, int32_t* parent_id) const override;
-  BrowserAccessibility* GetNodeInTree(AXTreeID tree_id,
-                                      int32_t node_id) const override;
-  int MaxTextOffset() const override;
-  int MaxTextOffsetInParent() const override;
-  bool IsInLineBreak() const override;
-  std::vector<int32_t> GetWordStartOffsets() const override;
-  std::vector<int32_t> GetWordEndOffsets() const override;
-  int32_t GetNextOnLineID(int32_t node_id) const override;
-  int32_t GetPreviousOnLineID(int32_t node_id) const override;
-};
-
-}  // namespace content
-
-#endif  // CONTENT_BROWSER_ACCESSIBILITY_AX_PLATFORM_POSITION_H_
diff --git a/content/browser/accessibility/browser_accessibility.cc b/content/browser/accessibility/browser_accessibility.cc
index b074d07..1e697ee 100644
--- a/content/browser/accessibility/browser_accessibility.cc
+++ b/content/browser/accessibility/browser_accessibility.cc
@@ -829,12 +829,12 @@
   return node()->GetOrComputeLineStartOffsets();
 }
 
-BrowserAccessibility::AXPlatformPositionInstance
+BrowserAccessibilityPosition::AXPositionInstance
 BrowserAccessibility::CreatePositionAt(int offset,
                                        ui::AXTextAffinity affinity) const {
   DCHECK(manager_);
-  return AXPlatformPosition::CreateTextPosition(manager_->ax_tree_id(), GetId(),
-                                                offset, affinity);
+  return BrowserAccessibilityPosition::CreateTextPosition(
+      manager_->ax_tree_id(), GetId(), offset, affinity);
 }
 
 base::string16 BrowserAccessibility::GetInnerText() const {
diff --git a/content/browser/accessibility/browser_accessibility.h b/content/browser/accessibility/browser_accessibility.h
index f94f3f9..1ef30c7a 100644
--- a/content/browser/accessibility/browser_accessibility.h
+++ b/content/browser/accessibility/browser_accessibility.h
@@ -16,7 +16,7 @@
 #include "base/strings/string_split.h"
 #include "build/build_config.h"
 #include "content/browser/accessibility/accessibility_flags.h"
-#include "content/browser/accessibility/ax_platform_position.h"
+#include "content/browser/accessibility/browser_accessibility_position.h"
 #include "content/common/content_export.h"
 #include "third_party/WebKit/public/web/WebAXEnums.h"
 #include "ui/accessibility/ax_node.h"
@@ -321,7 +321,7 @@
   std::string ComputeAccessibleNameFromDescendants() const;
 
   // Creates a text position rooted at this object.
-  AXPlatformPosition::AXPositionInstance CreatePositionAt(
+  BrowserAccessibilityPosition::AXPositionInstance CreatePositionAt(
       int offset,
       ui::AXTextAffinity affinity = ui::AX_TEXT_AFFINITY_DOWNSTREAM) const;
 
@@ -348,8 +348,10 @@
   bool IsOffscreen() const override;
 
  protected:
-  using AXPlatformPositionInstance = AXPlatformPosition::AXPositionInstance;
-  using AXPlatformRange = ui::AXRange<AXPlatformPositionInstance::element_type>;
+  using BrowserAccessibilityPositionInstance =
+      BrowserAccessibilityPosition::AXPositionInstance;
+  using AXPlatformRange =
+      ui::AXRange<BrowserAccessibilityPositionInstance::element_type>;
 
   BrowserAccessibility();
 
diff --git a/content/browser/accessibility/browser_accessibility_cocoa.h b/content/browser/accessibility/browser_accessibility_cocoa.h
index e774370..599882f 100644
--- a/content/browser/accessibility/browser_accessibility_cocoa.h
+++ b/content/browser/accessibility/browser_accessibility_cocoa.h
@@ -83,6 +83,9 @@
 - (NSString*)valueForRange:(NSRange)range;
 - (NSAttributedString*)attributedValueForRange:(NSRange)range;
 
+- (BOOL)isRowHeaderForCurrentCell:(content::BrowserAccessibility*)header;
+- (BOOL)isColumnHeaderForCurrentCell:(content::BrowserAccessibility*)header;
+
 // Internally-used property.
 @property(nonatomic, readonly) NSPoint origin;
 
diff --git a/content/browser/accessibility/browser_accessibility_cocoa.mm b/content/browser/accessibility/browser_accessibility_cocoa.mm
index 2e01e7c..abaff714 100644
--- a/content/browser/accessibility/browser_accessibility_cocoa.mm
+++ b/content/browser/accessibility/browser_accessibility_cocoa.mm
@@ -20,10 +20,10 @@
 #include "base/strings/sys_string_conversions.h"
 #include "base/strings/utf_string_conversions.h"
 #include "content/app/strings/grit/content_strings.h"
-#include "content/browser/accessibility/ax_platform_position.h"
 #include "content/browser/accessibility/browser_accessibility_mac.h"
 #include "content/browser/accessibility/browser_accessibility_manager.h"
 #include "content/browser/accessibility/browser_accessibility_manager_mac.h"
+#include "content/browser/accessibility/browser_accessibility_position.h"
 #include "content/browser/accessibility/one_shot_accessibility_tree_search.h"
 #include "content/public/common/content_client.h"
 #include "third_party/skia/include/core/SkColor.h"
@@ -32,13 +32,14 @@
 
 #import "ui/accessibility/platform/ax_platform_node_mac.h"
 
-using AXPlatformPositionInstance =
-    content::AXPlatformPosition::AXPositionInstance;
-using AXPlatformRange = ui::AXRange<AXPlatformPositionInstance::element_type>;
+using BrowserAccessibilityPositionInstance =
+    content::BrowserAccessibilityPosition::AXPositionInstance;
+using AXPlatformRange =
+    ui::AXRange<BrowserAccessibilityPositionInstance::element_type>;
 using AXTextMarkerRangeRef = CFTypeRef;
 using AXTextMarkerRef = CFTypeRef;
 using StringAttribute = ui::AXStringAttribute;
-using content::AXPlatformPosition;
+using content::BrowserAccessibilityPosition;
 using content::AccessibilityMatchPredicate;
 using content::BrowserAccessibility;
 using content::BrowserAccessibilityDelegate;
@@ -148,10 +149,10 @@
 }  // extern "C"
 
 // AXTextMarkerCreate copies from data buffer given to it.
-id CreateTextMarker(AXPlatformPositionInstance position) {
+id CreateTextMarker(BrowserAccessibilityPositionInstance position) {
   AXTextMarkerRef text_marker = AXTextMarkerCreate(
       kCFAllocatorDefault, reinterpret_cast<const UInt8*>(position.get()),
-      sizeof(AXPlatformPosition));
+      sizeof(BrowserAccessibilityPosition));
   return static_cast<id>(
       base::mac::CFTypeRefToNSObjectAutorelease(text_marker));
 }
@@ -161,31 +162,34 @@
 id CreateTextMarkerRange(const AXPlatformRange range) {
   base::ScopedCFTypeRef<AXTextMarkerRef> start_marker(AXTextMarkerCreate(
       kCFAllocatorDefault, reinterpret_cast<const UInt8*>(range.anchor()),
-      sizeof(AXPlatformPosition)));
+      sizeof(BrowserAccessibilityPosition)));
   base::ScopedCFTypeRef<AXTextMarkerRef> end_marker(AXTextMarkerCreate(
       kCFAllocatorDefault, reinterpret_cast<const UInt8*>(range.focus()),
-      sizeof(AXPlatformPosition)));
+      sizeof(BrowserAccessibilityPosition)));
   AXTextMarkerRangeRef marker_range =
       AXTextMarkerRangeCreate(kCFAllocatorDefault, start_marker, end_marker);
   return static_cast<id>(
       base::mac::CFTypeRefToNSObjectAutorelease(marker_range));
 }
 
-AXPlatformPositionInstance CreatePositionFromTextMarker(
+BrowserAccessibilityPositionInstance CreatePositionFromTextMarker(
     AXTextMarkerRef text_marker) {
   DCHECK(text_marker);
-  if (AXTextMarkerGetLength(text_marker) != sizeof(AXPlatformPosition))
-    return AXPlatformPosition::CreateNullPosition();
+  if (AXTextMarkerGetLength(text_marker) !=
+      sizeof(BrowserAccessibilityPosition))
+    return BrowserAccessibilityPosition::CreateNullPosition();
   const UInt8* source_buffer = AXTextMarkerGetBytePtr(text_marker);
   if (!source_buffer)
-    return AXPlatformPosition::CreateNullPosition();
-  UInt8* destination_buffer = new UInt8[sizeof(AXPlatformPosition)];
-  std::memcpy(destination_buffer, source_buffer, sizeof(AXPlatformPosition));
-  AXPlatformPosition::AXPositionInstance position(
-      reinterpret_cast<AXPlatformPosition::AXPositionInstance::pointer>(
+    return BrowserAccessibilityPosition::CreateNullPosition();
+  UInt8* destination_buffer = new UInt8[sizeof(BrowserAccessibilityPosition)];
+  std::memcpy(destination_buffer, source_buffer,
+              sizeof(BrowserAccessibilityPosition));
+  BrowserAccessibilityPosition::AXPositionInstance position(
+      reinterpret_cast<
+          BrowserAccessibilityPosition::AXPositionInstance::pointer>(
           destination_buffer));
   if (!position)
-    return AXPlatformPosition::CreateNullPosition();
+    return BrowserAccessibilityPosition::CreateNullPosition();
   return position;
 }
 
@@ -199,24 +203,24 @@
   if (!start_marker.get() || !end_marker.get())
     return AXPlatformRange();
 
-  AXPlatformPositionInstance anchor =
+  BrowserAccessibilityPositionInstance anchor =
       CreatePositionFromTextMarker(start_marker.get());
-  AXPlatformPositionInstance focus =
+  BrowserAccessibilityPositionInstance focus =
       CreatePositionFromTextMarker(end_marker.get());
   // |AXPlatformRange| takes ownership of its anchor and focus.
   return AXPlatformRange(std::move(anchor), std::move(focus));
 }
 
-AXPlatformPositionInstance CreateTextPosition(
+BrowserAccessibilityPositionInstance CreateTextPosition(
     const BrowserAccessibility& object,
     int offset,
     ui::AXTextAffinity affinity) {
   if (!object.instance_active())
-    return AXPlatformPosition::CreateNullPosition();
+    return BrowserAccessibilityPosition::CreateNullPosition();
 
   const BrowserAccessibilityManager* manager = object.manager();
   DCHECK(manager);
-  return AXPlatformPosition::CreateTextPosition(
+  return BrowserAccessibilityPosition::CreateTextPosition(
       manager->ax_tree_id(), object.GetId(), offset, affinity);
 }
 
@@ -226,9 +230,9 @@
                                 const BrowserAccessibility& end_object,
                                 int end_offset,
                                 ui::AXTextAffinity end_affinity) {
-  AXPlatformPositionInstance anchor =
+  BrowserAccessibilityPositionInstance anchor =
       CreateTextPosition(start_object, start_offset, start_affinity);
-  AXPlatformPositionInstance focus =
+  BrowserAccessibilityPositionInstance focus =
       CreateTextPosition(end_object, end_offset, end_affinity);
   // |AXPlatformRange| takes ownership of its anchor and focus.
   return AXPlatformRange(std::move(anchor), std::move(focus));
@@ -801,13 +805,55 @@
   }
 }
 
+- (BOOL)isColumnHeaderForCurrentCell:(BrowserAccessibility*)header {
+  int cell_first_col = -1;
+  int cell_colspan = -1;
+  browserAccessibility_->GetIntAttribute(ui::AX_ATTR_ARIA_CELL_COLUMN_INDEX,
+                                         &cell_first_col);
+  if (cell_first_col < 0) {
+    browserAccessibility_->GetIntAttribute(ui::AX_ATTR_TABLE_CELL_COLUMN_INDEX,
+                                           &cell_first_col);
+  }
+  if (cell_first_col < 0)
+    return false;
+  browserAccessibility_->GetIntAttribute(ui::AX_ATTR_TABLE_CELL_COLUMN_SPAN,
+                                         &cell_colspan);
+  if (cell_colspan <= 0)
+    cell_colspan = 1;
+  int cell_last_col = cell_first_col + cell_colspan - 1;
+
+  int header_first_col = -1;
+  int header_colspan = -1;
+  header->GetIntAttribute(ui::AX_ATTR_ARIA_CELL_COLUMN_INDEX,
+                          &header_first_col);
+  if (header_first_col < 0) {
+    header->GetIntAttribute(ui::AX_ATTR_TABLE_CELL_COLUMN_INDEX,
+                            &header_first_col);
+  }
+  if (header_first_col < 0)
+    return false;
+
+  header->GetIntAttribute(ui::AX_ATTR_TABLE_CELL_COLUMN_SPAN, &header_colspan);
+  if (header_colspan <= 0)
+    header_colspan = 1;
+  int header_last_col = header_first_col + header_colspan - 1;
+
+  int topmost_col_of_either = std::max(cell_first_col, header_first_col);
+  int bottommost_col_of_either = std::min(cell_last_col, header_last_col);
+  bool has_col_intersection = topmost_col_of_either <= bottommost_col_of_either;
+
+  return has_col_intersection;
+}
+
 - (NSArray*)columnHeaders {
   if (![self instanceActive])
     return nil;
-  if (!ui::IsTableLikeRole(browserAccessibility_->GetRole()) &&
-      !ui::IsCellOrTableHeaderRole(browserAccessibility_->GetRole())) {
+
+  bool is_cell_or_table_header =
+      ui::IsCellOrTableHeaderRole(browserAccessibility_->GetRole());
+  bool is_table_like = ui::IsTableLikeRole(browserAccessibility_->GetRole());
+  if (!is_table_like && !is_cell_or_table_header)
     return nil;
-  }
   BrowserAccessibility* table = [self containingTable];
   if (!table)
     return nil;
@@ -819,10 +865,14 @@
     int id = uniqueCellIds[i];
     BrowserAccessibility* cell =
         browserAccessibility_->manager()->GetFromID(id);
-    if (cell && cell->GetRole() == ui::AX_ROLE_COLUMN_HEADER)
-      [ret addObject:ToBrowserAccessibilityCocoa(cell)];
+    if (cell && cell->GetRole() == ui::AX_ROLE_COLUMN_HEADER) {
+      // Expose all column headers on table object.
+      // Expose only relevant column headers on cell object.
+      if (is_table_like || [self isColumnHeaderForCurrentCell:cell])
+        [ret addObject:ToBrowserAccessibilityCocoa(cell)];
+    }
   }
-  return ret;
+  return [ret count] ? ret : nil;
 }
 
 - (NSValue*)columnIndexRange {
@@ -1024,7 +1074,7 @@
   if (!root)
     return nil;
 
-  AXPlatformPositionInstance position = root->CreatePositionAt(0);
+  BrowserAccessibilityPositionInstance position = root->CreatePositionAt(0);
   return CreateTextMarker(position->CreatePositionAtEndOfAnchor());
 }
 
@@ -1613,13 +1663,56 @@
   return NSAccessibilityRoleDescription(role, nil);
 }
 
+- (BOOL)isRowHeaderForCurrentCell:(BrowserAccessibility*)header {
+  int cell_first_row = -1;
+  int cell_rowspan = -1;
+  browserAccessibility_->GetIntAttribute(ui::AX_ATTR_ARIA_CELL_ROW_INDEX,
+                                         &cell_first_row);
+  if (cell_first_row < 0) {
+    browserAccessibility_->GetIntAttribute(ui::AX_ATTR_TABLE_CELL_ROW_INDEX,
+                                           &cell_first_row);
+  }
+  if (cell_first_row < 0)
+    return false;
+
+  browserAccessibility_->GetIntAttribute(ui::AX_ATTR_TABLE_CELL_ROW_SPAN,
+                                         &cell_rowspan);
+  if (cell_rowspan <= 0)
+    cell_rowspan = 1;
+
+  int cell_last_row = cell_first_row + cell_rowspan - 1;
+
+  int header_first_row = -1;
+  int header_rowspan = -1;
+  header->GetIntAttribute(ui::AX_ATTR_ARIA_CELL_ROW_INDEX, &header_first_row);
+  if (header_first_row < 0) {
+    header->GetIntAttribute(ui::AX_ATTR_TABLE_CELL_ROW_INDEX,
+                            &header_first_row);
+  }
+  if (header_first_row < 0)
+    return false;
+
+  header->GetIntAttribute(ui::AX_ATTR_TABLE_CELL_ROW_SPAN, &header_rowspan);
+  if (header_rowspan <= 0)
+    header_rowspan = 1;
+
+  int header_last_row = header_first_row + header_rowspan - 1;
+
+  int topmost_row_of_either = std::max(cell_first_row, header_first_row);
+  int bottommost_row_of_either = std::min(cell_last_row, header_last_row);
+  bool has_row_intersection = topmost_row_of_either <= bottommost_row_of_either;
+
+  return has_row_intersection;
+}
+
 - (NSArray*)rowHeaders {
   if (![self instanceActive])
     return nil;
-  if (!ui::IsTableLikeRole(browserAccessibility_->GetRole()) &&
-      !ui::IsCellOrTableHeaderRole(browserAccessibility_->GetRole())) {
+  bool is_cell_or_table_header =
+      ui::IsCellOrTableHeaderRole(browserAccessibility_->GetRole());
+  bool is_table_like = ui::IsTableLikeRole(browserAccessibility_->GetRole());
+  if (!is_table_like && !is_cell_or_table_header)
     return nil;
-  }
   BrowserAccessibility* table = [self containingTable];
   if (!table)
     return nil;
@@ -1631,10 +1724,12 @@
     int id = uniqueCellIds[i];
     BrowserAccessibility* cell =
         browserAccessibility_->manager()->GetFromID(id);
-    if (cell && cell->GetRole() == ui::AX_ROLE_ROW_HEADER)
-      [ret addObject:ToBrowserAccessibilityCocoa(cell)];
+    if (cell && cell->GetRole() == ui::AX_ROLE_ROW_HEADER) {
+      if (is_table_like || [self isRowHeaderForCurrentCell:cell])
+        [ret addObject:ToBrowserAccessibilityCocoa(cell)];
+    }
   }
-  return ret;
+  return [ret count] ? ret : nil;
 }
 
 - (NSValue*)rowIndexRange {
@@ -1852,7 +1947,7 @@
   if (!root)
     return nil;
 
-  AXPlatformPositionInstance position = root->CreatePositionAt(0);
+  BrowserAccessibilityPositionInstance position = root->CreatePositionAt(0);
   return CreateTextMarker(position->CreatePositionAtStartOfAnchor());
 }
 
@@ -2050,17 +2145,7 @@
 - (NSArray*)visibleChildren {
   if (![self instanceActive])
     return nil;
-  NSMutableArray* ret = [[[NSMutableArray alloc] init] autorelease];
-  uint32_t childCount = browserAccessibility_->PlatformChildCount();
-  for (uint32_t index = 0; index < childCount; ++index) {
-    BrowserAccessibilityCocoa* child = ToBrowserAccessibilityCocoa(
-        browserAccessibility_->PlatformGetChild(index));
-    if ([child isIgnored])
-      [ret addObjectsFromArray:[child visibleChildren]];
-    else
-      [ret addObject:child];
-  }
-  return ret;
+  return [self children];
 }
 
 - (NSArray*)visibleColumns {
@@ -2255,7 +2340,7 @@
   }
 
   if ([attribute isEqualToString:@"AXUIElementForTextMarker"]) {
-    AXPlatformPositionInstance position =
+    BrowserAccessibilityPositionInstance position =
         CreatePositionFromTextMarker(parameter);
     if (!position->IsNullPosition())
       return ToBrowserAccessibilityCocoa(position->GetAnchor());
@@ -2264,9 +2349,9 @@
   }
 
   if ([attribute isEqualToString:@"AXTextMarkerRangeForUIElement"]) {
-    AXPlatformPositionInstance startPosition =
+    BrowserAccessibilityPositionInstance startPosition =
         browserAccessibility_->CreatePositionAt(0);
-    AXPlatformPositionInstance endPosition =
+    BrowserAccessibilityPositionInstance endPosition =
         startPosition->CreatePositionAtEndOfAnchor();
     AXPlatformRange range =
         AXPlatformRange(std::move(startPosition), std::move(endPosition));
@@ -2280,7 +2365,7 @@
     return GetAttributedTextForTextMarkerRange(parameter);
 
   if ([attribute isEqualToString:@"AXNextTextMarkerForTextMarker"]) {
-    AXPlatformPositionInstance position =
+    BrowserAccessibilityPositionInstance position =
         CreatePositionFromTextMarker(parameter);
     if (position->IsNullPosition())
       return nil;
@@ -2289,7 +2374,7 @@
   }
 
   if ([attribute isEqualToString:@"AXPreviousTextMarkerForTextMarker"]) {
-    AXPlatformPositionInstance position =
+    BrowserAccessibilityPositionInstance position =
         CreatePositionFromTextMarker(parameter);
     if (position->IsNullPosition())
       return nil;
@@ -2298,18 +2383,18 @@
   }
 
   if ([attribute isEqualToString:@"AXLeftWordTextMarkerRangeForTextMarker"]) {
-    AXPlatformPositionInstance endPosition =
+    BrowserAccessibilityPositionInstance endPosition =
         CreatePositionFromTextMarker(parameter);
     if (endPosition->IsNullPosition())
       return nil;
 
-    AXPlatformPositionInstance startWordPosition =
+    BrowserAccessibilityPositionInstance startWordPosition =
         endPosition->CreatePreviousWordStartPosition(
             ui::AXBoundaryBehavior::StopAtAnchorBoundary);
-    AXPlatformPositionInstance endWordPosition =
+    BrowserAccessibilityPositionInstance endWordPosition =
         endPosition->CreatePreviousWordEndPosition(
             ui::AXBoundaryBehavior::StopAtAnchorBoundary);
-    AXPlatformPositionInstance startPosition =
+    BrowserAccessibilityPositionInstance startPosition =
         *startWordPosition <= *endWordPosition ? std::move(endWordPosition)
                                                : std::move(startWordPosition);
     AXPlatformRange range(std::move(startPosition), std::move(endPosition));
@@ -2317,18 +2402,18 @@
   }
 
   if ([attribute isEqualToString:@"AXRightWordTextMarkerRangeForTextMarker"]) {
-    AXPlatformPositionInstance startPosition =
+    BrowserAccessibilityPositionInstance startPosition =
         CreatePositionFromTextMarker(parameter);
     if (startPosition->IsNullPosition())
       return nil;
 
-    AXPlatformPositionInstance endWordPosition =
+    BrowserAccessibilityPositionInstance endWordPosition =
         startPosition->CreateNextWordEndPosition(
             ui::AXBoundaryBehavior::StopAtAnchorBoundary);
-    AXPlatformPositionInstance startWordPosition =
+    BrowserAccessibilityPositionInstance startWordPosition =
         startPosition->CreateNextWordStartPosition(
             ui::AXBoundaryBehavior::StopAtAnchorBoundary);
-    AXPlatformPositionInstance endPosition =
+    BrowserAccessibilityPositionInstance endPosition =
         *startWordPosition <= *endWordPosition ? std::move(startWordPosition)
                                                : std::move(endWordPosition);
     AXPlatformRange range(std::move(startPosition), std::move(endPosition));
@@ -2336,7 +2421,7 @@
   }
 
   if ([attribute isEqualToString:@"AXNextWordEndTextMarkerForTextMarker"]) {
-    AXPlatformPositionInstance position =
+    BrowserAccessibilityPositionInstance position =
         CreatePositionFromTextMarker(parameter);
     if (position->IsNullPosition())
       return nil;
@@ -2346,7 +2431,7 @@
 
   if ([attribute
           isEqualToString:@"AXPreviousWordStartTextMarkerForTextMarker"]) {
-    AXPlatformPositionInstance position =
+    BrowserAccessibilityPositionInstance position =
         CreatePositionFromTextMarker(parameter);
     if (position->IsNullPosition())
       return nil;
@@ -2355,15 +2440,15 @@
   }
 
   if ([attribute isEqualToString:@"AXTextMarkerRangeForLine"]) {
-    AXPlatformPositionInstance position =
+    BrowserAccessibilityPositionInstance position =
         CreatePositionFromTextMarker(parameter);
     if (position->IsNullPosition())
       return nil;
 
-    AXPlatformPositionInstance startPosition =
+    BrowserAccessibilityPositionInstance startPosition =
         position->CreatePreviousLineStartPosition(
             ui::AXBoundaryBehavior::StopIfAlreadyAtBoundary);
-    AXPlatformPositionInstance endPosition =
+    BrowserAccessibilityPositionInstance endPosition =
         position->CreateNextLineEndPosition(
             ui::AXBoundaryBehavior::StopIfAlreadyAtBoundary);
     AXPlatformRange range(std::move(startPosition), std::move(endPosition));
@@ -2371,18 +2456,18 @@
   }
 
   if ([attribute isEqualToString:@"AXLeftLineTextMarkerRangeForTextMarker"]) {
-    AXPlatformPositionInstance endPosition =
+    BrowserAccessibilityPositionInstance endPosition =
         CreatePositionFromTextMarker(parameter);
     if (endPosition->IsNullPosition())
       return nil;
 
-    AXPlatformPositionInstance startLinePosition =
+    BrowserAccessibilityPositionInstance startLinePosition =
         endPosition->CreatePreviousLineStartPosition(
             ui::AXBoundaryBehavior::CrossBoundary);
-    AXPlatformPositionInstance endLinePosition =
+    BrowserAccessibilityPositionInstance endLinePosition =
         endPosition->CreatePreviousLineEndPosition(
             ui::AXBoundaryBehavior::CrossBoundary);
-    AXPlatformPositionInstance startPosition =
+    BrowserAccessibilityPositionInstance startPosition =
         *startLinePosition <= *endLinePosition ? std::move(endLinePosition)
                                                : std::move(startLinePosition);
     AXPlatformRange range(std::move(startPosition), std::move(endPosition));
@@ -2390,18 +2475,18 @@
   }
 
   if ([attribute isEqualToString:@"AXRightLineTextMarkerRangeForTextMarker"]) {
-    AXPlatformPositionInstance startPosition =
+    BrowserAccessibilityPositionInstance startPosition =
         CreatePositionFromTextMarker(parameter);
     if (startPosition->IsNullPosition())
       return nil;
 
-    AXPlatformPositionInstance startLinePosition =
+    BrowserAccessibilityPositionInstance startLinePosition =
         startPosition->CreateNextLineStartPosition(
             ui::AXBoundaryBehavior::CrossBoundary);
-    AXPlatformPositionInstance endLinePosition =
+    BrowserAccessibilityPositionInstance endLinePosition =
         startPosition->CreateNextLineEndPosition(
             ui::AXBoundaryBehavior::CrossBoundary);
-    AXPlatformPositionInstance endPosition =
+    BrowserAccessibilityPositionInstance endPosition =
         *startLinePosition <= *endLinePosition ? std::move(startLinePosition)
                                                : std::move(endLinePosition);
     AXPlatformRange range(std::move(startPosition), std::move(endPosition));
@@ -2409,7 +2494,7 @@
   }
 
   if ([attribute isEqualToString:@"AXNextLineEndTextMarkerForTextMarker"]) {
-    AXPlatformPositionInstance position =
+    BrowserAccessibilityPositionInstance position =
         CreatePositionFromTextMarker(parameter);
     if (position->IsNullPosition())
       return nil;
@@ -2419,7 +2504,7 @@
 
   if ([attribute
           isEqualToString:@"AXPreviousLineStartTextMarkerForTextMarker"]) {
-    AXPlatformPositionInstance position =
+    BrowserAccessibilityPositionInstance position =
         CreatePositionFromTextMarker(parameter);
     if (position->IsNullPosition())
       return nil;
@@ -2470,7 +2555,7 @@
 
   if ([attribute isEqualToString:
            NSAccessibilityLineTextMarkerRangeForTextMarkerParameterizedAttribute]) {
-    AXPlatformPositionInstance position =
+    BrowserAccessibilityPositionInstance position =
         CreatePositionFromTextMarker(parameter);
     if (position->IsNullPosition())
       return nil;
@@ -2518,9 +2603,9 @@
     if ([text_marker_array count] != 2)
       return nil;
 
-    AXPlatformPositionInstance startPosition =
+    BrowserAccessibilityPositionInstance startPosition =
         CreatePositionFromTextMarker([text_marker_array objectAtIndex:0]);
-    AXPlatformPositionInstance endPosition =
+    BrowserAccessibilityPositionInstance endPosition =
         CreatePositionFromTextMarker([text_marker_array objectAtIndex:1]);
     if (*startPosition <= *endPosition) {
       return CreateTextMarkerRange(
@@ -2749,12 +2834,20 @@
     [ret addObjectsFromArray:@[
       NSAccessibilityColumnIndexRangeAttribute,
       NSAccessibilityRowIndexRangeAttribute,
-      NSAccessibilityColumnHeaderUIElementsAttribute,
-      NSAccessibilityRowHeaderUIElementsAttribute,
       NSAccessibilityARIAColumnIndexAttribute,
       NSAccessibilityARIARowIndexAttribute,
       @"AXSortDirection",
     ]];
+    if ([self internalRole] != ui::AX_ROLE_COLUMN_HEADER) {
+      [ret addObjectsFromArray:@[
+        NSAccessibilityColumnHeaderUIElementsAttribute,
+      ]];
+    }
+    if ([self internalRole] != ui::AX_ROLE_ROW_HEADER) {
+      [ret addObjectsFromArray:@[
+        NSAccessibilityRowHeaderUIElementsAttribute,
+      ]];
+    }
   } else if ([role isEqualToString:@"AXWebArea"]) {
     [ret addObjectsFromArray:@[
       @"AXLoaded", NSAccessibilityLoadingProgressAttribute
diff --git a/content/browser/accessibility/browser_accessibility_com_win.cc b/content/browser/accessibility/browser_accessibility_com_win.cc
index cff284e..94332b4 100644
--- a/content/browser/accessibility/browser_accessibility_com_win.cc
+++ b/content/browser/accessibility/browser_accessibility_com_win.cc
@@ -38,8 +38,10 @@
 
 namespace content {
 
-using AXPlatformPositionInstance = AXPlatformPosition::AXPositionInstance;
-using AXPlatformRange = ui::AXRange<AXPlatformPositionInstance::element_type>;
+using BrowserAccessibilityPositionInstance =
+    BrowserAccessibilityPosition::AXPositionInstance;
+using AXPlatformRange =
+    ui::AXRange<BrowserAccessibilityPositionInstance::element_type>;
 
 // These nonstandard GUIDs are taken directly from the Mozilla sources
 // (accessible/src/msaa/nsAccessNodeWrap.cpp); some documentation is here:
@@ -1760,9 +1762,9 @@
 // tree positions.
 // TODO(nektar): Remove this function once selection fixes in Blink are
 // thoroughly tested and convert to tree positions.
-AXPlatformPosition::AXPositionInstance
+BrowserAccessibilityPosition::AXPositionInstance
 BrowserAccessibilityComWin::CreatePositionForSelectionAt(int offset) const {
-  AXPlatformPositionInstance position =
+  BrowserAccessibilityPositionInstance position =
       owner()->CreatePositionAt(offset)->AsLeafTextPosition();
   if (position->GetAnchor() &&
       position->GetAnchor()->GetRole() == ui::AX_ROLE_INLINE_TEXT_BOX) {
@@ -2247,9 +2249,9 @@
                                                           LONG end_offset) {
   HandleSpecialTextOffset(&start_offset);
   HandleSpecialTextOffset(&end_offset);
-  AXPlatformPositionInstance start_position =
+  BrowserAccessibilityPositionInstance start_position =
       CreatePositionForSelectionAt(static_cast<int>(start_offset));
-  AXPlatformPositionInstance end_position =
+  BrowserAccessibilityPositionInstance end_position =
       CreatePositionForSelectionAt(static_cast<int>(end_offset));
   Manager()->SetSelection(
       AXPlatformRange(std::move(start_position), std::move(end_position)));
@@ -2270,17 +2272,17 @@
   if (ia2_boundary == IA2_TEXT_BOUNDARY_WORD) {
     switch (direction) {
       case ui::FORWARDS_DIRECTION: {
-        AXPlatformPositionInstance position =
+        BrowserAccessibilityPositionInstance position =
             owner()->CreatePositionAt(static_cast<int>(start_offset), affinity);
-        AXPlatformPositionInstance next_word =
+        BrowserAccessibilityPositionInstance next_word =
             position->CreateNextWordStartPosition(
                 ui::AXBoundaryBehavior::StopAtAnchorBoundary);
         return next_word->text_offset();
       }
       case ui::BACKWARDS_DIRECTION: {
-        AXPlatformPositionInstance position =
+        BrowserAccessibilityPositionInstance position =
             owner()->CreatePositionAt(static_cast<int>(start_offset), affinity);
-        AXPlatformPositionInstance previous_word =
+        BrowserAccessibilityPositionInstance previous_word =
             position->CreatePreviousWordStartPosition(
                 ui::AXBoundaryBehavior::StopIfAlreadyAtBoundary);
         return previous_word->text_offset();
@@ -2291,17 +2293,17 @@
   if (ia2_boundary == IA2_TEXT_BOUNDARY_LINE) {
     switch (direction) {
       case ui::FORWARDS_DIRECTION: {
-        AXPlatformPositionInstance position =
+        BrowserAccessibilityPositionInstance position =
             owner()->CreatePositionAt(static_cast<int>(start_offset), affinity);
-        AXPlatformPositionInstance next_line =
+        BrowserAccessibilityPositionInstance next_line =
             position->CreateNextLineStartPosition(
                 ui::AXBoundaryBehavior::StopAtAnchorBoundary);
         return next_line->text_offset();
       }
       case ui::BACKWARDS_DIRECTION: {
-        AXPlatformPositionInstance position =
+        BrowserAccessibilityPositionInstance position =
             owner()->CreatePositionAt(static_cast<int>(start_offset), affinity);
-        AXPlatformPositionInstance previous_line =
+        BrowserAccessibilityPositionInstance previous_line =
             position->CreatePreviousLineStartPosition(
                 ui::AXBoundaryBehavior::StopIfAlreadyAtBoundary);
         return previous_line->text_offset();
diff --git a/content/browser/accessibility/browser_accessibility_com_win.h b/content/browser/accessibility/browser_accessibility_com_win.h
index acb3f90..d601a64 100644
--- a/content/browser/accessibility/browser_accessibility_com_win.h
+++ b/content/browser/accessibility/browser_accessibility_com_win.h
@@ -413,7 +413,7 @@
 
   // |offset| could either be a text character or a child index in case of
   // non-text objects.
-  AXPlatformPosition::AXPositionInstance CreatePositionForSelectionAt(
+  BrowserAccessibilityPosition::AXPositionInstance CreatePositionForSelectionAt(
       int offset) const;
 
   // Public accessors (these do not have COM accessible accessors)
diff --git a/content/browser/accessibility/browser_accessibility_manager.h b/content/browser/accessibility/browser_accessibility_manager.h
index 50d66f7..697c8f2 100644
--- a/content/browser/accessibility/browser_accessibility_manager.h
+++ b/content/browser/accessibility/browser_accessibility_manager.h
@@ -15,7 +15,7 @@
 #include "base/macros.h"
 #include "build/build_config.h"
 #include "content/browser/accessibility/accessibility_flags.h"
-#include "content/browser/accessibility/ax_platform_position.h"
+#include "content/browser/accessibility/browser_accessibility_position.h"
 #include "content/common/content_export.h"
 #include "content/public/browser/ax_event_notification_details.h"
 #include "third_party/WebKit/public/web/WebAXEnums.h"
@@ -209,7 +209,9 @@
   void SetValue(
       const BrowserAccessibility& node, const base::string16& value);
   void SetSelection(
-      ui::AXRange<AXPlatformPosition::AXPositionInstance::element_type> range);
+      ui::AXRange<
+          BrowserAccessibilityPosition::AXPositionInstance::element_type>
+          range);
   void ShowContextMenu(const BrowserAccessibility& node);
 
   // Retrieve the bounds of the parent View in screen coordinates.
@@ -381,8 +383,10 @@
   void CacheHitTestResult(BrowserAccessibility* hit_test_result);
 
  protected:
-  using AXPlatformPositionInstance = AXPlatformPosition::AXPositionInstance;
-  using AXPlatformRange = ui::AXRange<AXPlatformPositionInstance::element_type>;
+  using BrowserAccessibilityPositionInstance =
+      BrowserAccessibilityPosition::AXPositionInstance;
+  using AXPlatformRange =
+      ui::AXRange<BrowserAccessibilityPositionInstance::element_type>;
 
   BrowserAccessibilityManager(
       BrowserAccessibilityDelegate* delegate,
diff --git a/content/browser/accessibility/browser_accessibility_position.cc b/content/browser/accessibility/browser_accessibility_position.cc
new file mode 100644
index 0000000..7864a4c
--- /dev/null
+++ b/content/browser/accessibility/browser_accessibility_position.cc
@@ -0,0 +1,172 @@
+// 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 "content/browser/accessibility/browser_accessibility_position.h"
+
+#include "build/build_config.h"
+#include "content/browser/accessibility/accessibility_flags.h"
+#include "content/browser/accessibility/browser_accessibility.h"
+#include "content/browser/accessibility/browser_accessibility_manager.h"
+#include "ui/accessibility/ax_enums.h"
+
+namespace content {
+
+BrowserAccessibilityPosition::BrowserAccessibilityPosition() {}
+
+BrowserAccessibilityPosition::~BrowserAccessibilityPosition() {}
+
+BrowserAccessibilityPosition::AXPositionInstance
+BrowserAccessibilityPosition::Clone() const {
+  return AXPositionInstance(new BrowserAccessibilityPosition(*this));
+}
+
+base::string16 BrowserAccessibilityPosition::GetInnerText() const {
+  if (IsNullPosition())
+    return base::string16();
+  DCHECK(GetAnchor());
+  return GetAnchor()->GetText();
+}
+
+void BrowserAccessibilityPosition::AnchorChild(int child_index,
+                                               AXTreeID* tree_id,
+                                               int32_t* child_id) const {
+  DCHECK(tree_id);
+  DCHECK(child_id);
+
+  if (!GetAnchor() || child_index < 0 || child_index >= AnchorChildCount()) {
+    *tree_id = INVALID_TREE_ID;
+    *child_id = INVALID_ANCHOR_ID;
+    return;
+  }
+
+  BrowserAccessibility* child = nullptr;
+  if (GetAnchor()->PlatformIsLeaf()) {
+    child = GetAnchor()->InternalGetChild(child_index);
+  } else {
+    child = GetAnchor()->PlatformGetChild(child_index);
+  }
+  DCHECK(child);
+  *tree_id = child->manager()->ax_tree_id();
+  *child_id = child->GetId();
+}
+
+int BrowserAccessibilityPosition::AnchorChildCount() const {
+  if (!GetAnchor())
+    return 0;
+
+  if (GetAnchor()->PlatformIsLeaf()) {
+    return static_cast<int>(GetAnchor()->InternalChildCount());
+  } else {
+    return static_cast<int>(GetAnchor()->PlatformChildCount());
+  }
+}
+
+int BrowserAccessibilityPosition::AnchorIndexInParent() const {
+  return GetAnchor() ? static_cast<int>(GetAnchor()->GetIndexInParent())
+                     : AXPosition::INVALID_INDEX;
+}
+
+void BrowserAccessibilityPosition::AnchorParent(AXTreeID* tree_id,
+                                                int32_t* parent_id) const {
+  DCHECK(tree_id);
+  DCHECK(parent_id);
+
+  if (!GetAnchor() || !GetAnchor()->PlatformGetParent()) {
+    *tree_id = AXPosition::INVALID_TREE_ID;
+    *parent_id = AXPosition::INVALID_ANCHOR_ID;
+    return;
+  }
+
+  BrowserAccessibility* parent = GetAnchor()->PlatformGetParent();
+  *tree_id = parent->manager()->ax_tree_id();
+  *parent_id = parent->GetId();
+}
+
+BrowserAccessibility* BrowserAccessibilityPosition::GetNodeInTree(
+    AXTreeID tree_id,
+    int32_t node_id) const {
+  if (tree_id == AXPosition::INVALID_TREE_ID ||
+      node_id == AXPosition::INVALID_ANCHOR_ID) {
+    return nullptr;
+  }
+
+  auto* manager = BrowserAccessibilityManager::FromID(tree_id);
+  if (!manager)
+    return nullptr;
+  return manager->GetFromID(node_id);
+}
+
+int BrowserAccessibilityPosition::MaxTextOffset() const {
+  if (IsNullPosition())
+    return INVALID_OFFSET;
+  return static_cast<int>(GetInnerText().length());
+}
+
+// On some platforms, most objects are represented in the text of their parents
+// with a special (embedded object) character and not with their actual text
+// contents.
+int BrowserAccessibilityPosition::MaxTextOffsetInParent() const {
+#if defined(OS_WIN) || BUILDFLAG(USE_ATK)
+  if (IsNullPosition())
+    return INVALID_OFFSET;
+  if (GetAnchor()->IsTextOnlyObject())
+    return MaxTextOffset();
+  // Not all objects in the internal accessibility tree are exposed to platform
+  // APIs.
+  if (GetAnchor()->PlatformIsChildOfLeaf())
+    return MaxTextOffset();
+  return 1;
+#else
+  return MaxTextOffset();
+#endif
+}
+
+bool BrowserAccessibilityPosition::IsInLineBreak() const {
+  if (IsNullPosition())
+    return false;
+
+  DCHECK(GetAnchor());
+  return GetAnchor()->IsLineBreakObject();
+}
+
+std::vector<int32_t> BrowserAccessibilityPosition::GetWordStartOffsets() const {
+  if (IsNullPosition())
+    return std::vector<int32_t>();
+  DCHECK(GetAnchor());
+  return GetAnchor()->GetIntListAttribute(ui::AX_ATTR_WORD_STARTS);
+}
+
+std::vector<int32_t> BrowserAccessibilityPosition::GetWordEndOffsets() const {
+  if (IsNullPosition())
+    return std::vector<int32_t>();
+  DCHECK(GetAnchor());
+  return GetAnchor()->GetIntListAttribute(ui::AX_ATTR_WORD_ENDS);
+}
+
+int32_t BrowserAccessibilityPosition::GetNextOnLineID(int32_t node_id) const {
+  if (IsNullPosition())
+    return INVALID_ANCHOR_ID;
+  BrowserAccessibility* node = GetNodeInTree(tree_id(), node_id);
+  int next_on_line_id;
+  if (!node ||
+      !node->GetIntAttribute(ui::AX_ATTR_NEXT_ON_LINE_ID, &next_on_line_id)) {
+    return INVALID_ANCHOR_ID;
+  }
+  return static_cast<int32_t>(next_on_line_id);
+}
+
+int32_t BrowserAccessibilityPosition::GetPreviousOnLineID(
+    int32_t node_id) const {
+  if (IsNullPosition())
+    return INVALID_ANCHOR_ID;
+  BrowserAccessibility* node = GetNodeInTree(tree_id(), node_id);
+  int previous_on_line_id;
+  if (!node || !node->GetIntAttribute(ui::AX_ATTR_PREVIOUS_ON_LINE_ID,
+                                      &previous_on_line_id)) {
+    return INVALID_ANCHOR_ID;
+  }
+  return static_cast<int32_t>(previous_on_line_id);
+}
+
+}  // namespace content
diff --git a/content/browser/accessibility/browser_accessibility_position.h b/content/browser/accessibility/browser_accessibility_position.h
new file mode 100644
index 0000000..c829251e
--- /dev/null
+++ b/content/browser/accessibility/browser_accessibility_position.h
@@ -0,0 +1,55 @@
+// 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_ACCESSIBILITY_BROWSER_ACCESSIBILITY_POSITION_H_
+#define CONTENT_BROWSER_ACCESSIBILITY_BROWSER_ACCESSIBILITY_POSITION_H_
+
+#include <stdint.h>
+
+#include <vector>
+
+#include "base/strings/string16.h"
+#include "ui/accessibility/ax_position.h"
+#include "ui/accessibility/ax_tree_id_registry.h"
+
+namespace content {
+
+class BrowserAccessibility;
+
+using AXTreeID = ui::AXTreeIDRegistry::AXTreeID;
+
+class BrowserAccessibilityPosition
+    : public ui::AXPosition<BrowserAccessibilityPosition,
+                            BrowserAccessibility> {
+ public:
+  BrowserAccessibilityPosition();
+  ~BrowserAccessibilityPosition() override;
+
+  AXPositionInstance Clone() const override;
+
+  base::string16 GetInnerText() const override;
+
+ protected:
+  BrowserAccessibilityPosition(const BrowserAccessibilityPosition& other) =
+      default;
+  void AnchorChild(int child_index,
+                   AXTreeID* tree_id,
+                   int32_t* child_id) const override;
+  int AnchorChildCount() const override;
+  int AnchorIndexInParent() const override;
+  void AnchorParent(AXTreeID* tree_id, int32_t* parent_id) const override;
+  BrowserAccessibility* GetNodeInTree(AXTreeID tree_id,
+                                      int32_t node_id) const override;
+  int MaxTextOffset() const override;
+  int MaxTextOffsetInParent() const override;
+  bool IsInLineBreak() const override;
+  std::vector<int32_t> GetWordStartOffsets() const override;
+  std::vector<int32_t> GetWordEndOffsets() const override;
+  int32_t GetNextOnLineID(int32_t node_id) const override;
+  int32_t GetPreviousOnLineID(int32_t node_id) const override;
+};
+
+}  // namespace content
+
+#endif  // CONTENT_BROWSER_ACCESSIBILITY_BROWSER_ACCESSIBILITY_POSITION_H_
diff --git a/content/browser/accessibility/web_contents_accessibility_android.cc b/content/browser/accessibility/web_contents_accessibility_android.cc
index 6f4979a..8879cd60 100644
--- a/content/browser/accessibility/web_contents_accessibility_android.cc
+++ b/content/browser/accessibility/web_contents_accessibility_android.cc
@@ -866,7 +866,8 @@
     jint unique_id,
     jint start,
     jint end) {
-  using AXPlatformPositionInstance = AXPlatformPosition::AXPositionInstance;
+  using AXPlatformPositionInstance =
+      BrowserAccessibilityPosition::AXPositionInstance;
   using AXPlatformRange = ui::AXRange<AXPlatformPositionInstance::element_type>;
 
   BrowserAccessibilityAndroid* node = GetAXFromUniqueID(unique_id);
diff --git a/content/browser/appcache/appcache_request_handler.cc b/content/browser/appcache/appcache_request_handler.cc
index a3710cc..9c8cb77 100644
--- a/content/browser/appcache/appcache_request_handler.cc
+++ b/content/browser/appcache/appcache_request_handler.cc
@@ -19,6 +19,7 @@
 #include "content/browser/appcache/appcache_url_loader_request.h"
 #include "content/browser/appcache/appcache_url_request_job.h"
 #include "content/browser/service_worker/service_worker_request_handler.h"
+#include "content/common/navigation_subresource_loader_params.h"
 #include "content/public/common/content_features.h"
 #include "net/url_request/url_request.h"
 #include "net/url_request/url_request_job.h"
@@ -610,13 +611,16 @@
   return true;
 }
 
-mojom::URLLoaderFactoryPtr
-AppCacheRequestHandler::MaybeCreateSubresourceFactory() {
+base::Optional<SubresourceLoaderParams>
+AppCacheRequestHandler::MaybeCreateSubresourceLoaderParams() {
   // The factory is destroyed when the renderer drops the connection.
   mojom::URLLoaderFactoryPtr factory_ptr;
   AppCacheSubresourceURLFactory::CreateURLLoaderFactory(
       network_url_loader_factory_getter_.get(), appcache_host_, &factory_ptr);
-  return factory_ptr;
+
+  SubresourceLoaderParams params;
+  params.loader_factory_info = factory_ptr.PassInterface();
+  return params;
 }
 
 void AppCacheRequestHandler::MaybeCreateSubresourceLoader(
diff --git a/content/browser/appcache/appcache_request_handler.h b/content/browser/appcache/appcache_request_handler.h
index 2fccdf3..5da57db 100644
--- a/content/browser/appcache/appcache_request_handler.h
+++ b/content/browser/appcache/appcache_request_handler.h
@@ -90,7 +90,8 @@
       const ResourceResponseHead& response,
       mojom::URLLoaderPtr* loader,
       mojom::URLLoaderClientRequest* client_request) override;
-  mojom::URLLoaderFactoryPtr MaybeCreateSubresourceFactory() override;
+  base::Optional<SubresourceLoaderParams> MaybeCreateSubresourceLoaderParams()
+      override;
 
   // These methods are used for subresource loading by the
   // AppCacheSubresourceURLFactory::SubresourceLoader class.
diff --git a/content/browser/background_fetch/background_fetch_context.cc b/content/browser/background_fetch/background_fetch_context.cc
index 9b8e7a88..2013efc 100644
--- a/content/browser/background_fetch/background_fetch_context.cc
+++ b/content/browser/background_fetch/background_fetch_context.cc
@@ -64,10 +64,6 @@
     blink::mojom::BackgroundFetchService::FetchCallback callback) {
   DCHECK_CURRENTLY_ON(BrowserThread::IO);
 
-  delegate_proxy_.CreateDownloadJob(registration_id.unique_id(), options.title,
-                                    registration_id.origin(), 0,
-                                    requests.size(), {});
-
   data_manager_.CreateRegistration(
       registration_id, requests, options,
       base::BindOnce(&BackgroundFetchContext::DidCreateRegistration,
diff --git a/content/browser/background_fetch/background_fetch_data_manager.cc b/content/browser/background_fetch/background_fetch_data_manager.cc
index e0c032a..9d6ac2ee 100644
--- a/content/browser/background_fetch/background_fetch_data_manager.cc
+++ b/content/browser/background_fetch/background_fetch_data_manager.cc
@@ -5,6 +5,7 @@
 #include "content/browser/background_fetch/background_fetch_data_manager.h"
 
 #include <algorithm>
+#include <utility>
 
 #include "base/command_line.h"
 #include "base/containers/flat_set.h"
@@ -122,7 +123,7 @@
          base::IntToString(request_index);
 }
 
-void IgnoreError(blink::mojom::BackgroundFetchError) {}
+void EmptyErrorHandler(blink::mojom::BackgroundFetchError) {}
 
 enum class DatabaseStatus { kOk, kFailed, kNotFound };
 
@@ -653,7 +654,7 @@
             // DeleteRegistrationTask for the actual deletion logic.
             AddDatabaseTask(std::make_unique<DeleteRegistrationTask>(
                 data_manager(), service_worker_registration_id, unique_id,
-                base::BindOnce(&IgnoreError)));
+                base::BindOnce(&EmptyErrorHandler)));
           }
         }
       }
@@ -700,6 +701,8 @@
     auto request = pending_requests_.front();
     pending_requests_.pop();
 
+    request->InitializeDownloadGuid();
+
     // The |request| is considered to be active now.
     active_requests_.push_back(request);
 
@@ -762,6 +765,11 @@
            (controller ? controller->GetInProgressDownloadedBytes() : 0);
   }
 
+  int GetTotalNumberOfRequests() const {
+    return pending_requests_.size() + active_requests_.size() +
+           completed_requests_.size();
+  }
+
  private:
   BackgroundFetchRegistrationId registration_id_;
   BackgroundFetchOptions options_;
@@ -819,6 +827,14 @@
   if (controller) {
     DCHECK_EQ(0u, controllers_.count(registration_id.unique_id()));
     controllers_.emplace(registration_id.unique_id(), controller);
+
+    // TODO(delphick): This assumes that fetches are always started afresh in
+    // each browser session. We need to initialize the number of downloads using
+    // information loaded from the database.
+    controller->InitializeRequestStatus(
+        0, /* completed_downloads*/
+        registrations_[registration_id.unique_id()]->GetTotalNumberOfRequests(),
+        std::vector<std::string>() /* outstanding download GUIDs */);
   } else {
     DCHECK_EQ(1u, controllers_.count(registration_id.unique_id()));
     controllers_.erase(registration_id.unique_id());
diff --git a/content/browser/background_fetch/background_fetch_data_manager.h b/content/browser/background_fetch/background_fetch_data_manager.h
index a01169e..57b8949 100644
--- a/content/browser/background_fetch/background_fetch_data_manager.h
+++ b/content/browser/background_fetch/background_fetch_data_manager.h
@@ -9,6 +9,7 @@
 #include <memory>
 #include <string>
 #include <tuple>
+#include <vector>
 
 #include "base/callback_forward.h"
 #include "base/containers/flat_map.h"
@@ -62,6 +63,13 @@
    public:
     virtual ~Controller() {}
 
+    // Called once the status of the active and completed downloads has been
+    // loaded from the database.
+    virtual void InitializeRequestStatus(
+        int completed_downloads,
+        int total_downloads,
+        const std::vector<std::string>& outstanding_guids) = 0;
+
     // Called once UpdateRegistrationUI has been persisted to the database.
     virtual void UpdateUI(const std::string& title) = 0;
 
diff --git a/content/browser/background_fetch/background_fetch_delegate_proxy.cc b/content/browser/background_fetch/background_fetch_delegate_proxy.cc
index 4982e53..b9a26b2 100644
--- a/content/browser/background_fetch/background_fetch_delegate_proxy.cc
+++ b/content/browser/background_fetch/background_fetch_delegate_proxy.cc
@@ -6,7 +6,6 @@
 
 #include <utility>
 
-#include "base/guid.h"
 #include "base/memory/ptr_util.h"
 #include "content/browser/background_fetch/background_fetch_job_controller.h"
 #include "content/public/browser/background_fetch_delegate.h"
@@ -55,7 +54,6 @@
   }
 
   void StartRequest(const std::string& job_unique_id,
-                    const std::string& guid,
                     const url::Origin& origin,
                     scoped_refptr<BackgroundFetchRequestInfo> request) {
     DCHECK_CURRENTLY_ON(BrowserThread::UI);
@@ -114,8 +112,9 @@
       headers.SetHeader("Origin", origin.Serialize());
     }
 
-    delegate_->DownloadUrl(job_unique_id, guid, fetch_request.method,
-                           fetch_request.url, traffic_annotation, headers);
+    delegate_->DownloadUrl(job_unique_id, request->download_guid(),
+                           fetch_request.method, fetch_request.url,
+                           traffic_annotation, headers);
   }
 
   void Abort(const std::string& job_unique_id) {
@@ -126,12 +125,16 @@
   }
 
   // BackgroundFetchDelegate::Client implementation:
-  void OnDownloadUpdated(const std::string& guid,
+  void OnJobCancelled(const std::string& job_unique_id) override;
+  void OnDownloadUpdated(const std::string& job_unique_id,
+                         const std::string& guid,
                          uint64_t bytes_downloaded) override;
   void OnDownloadComplete(
+      const std::string& job_unique_id,
       const std::string& guid,
       std::unique_ptr<BackgroundFetchResult> result) override;
   void OnDownloadStarted(
+      const std::string& job_unique_id,
       const std::string& guid,
       std::unique_ptr<content::BackgroundFetchResponse> response) override;
   void OnDelegateShutdown() override;
@@ -149,27 +152,39 @@
   DISALLOW_COPY_AND_ASSIGN(Core);
 };
 
+void BackgroundFetchDelegateProxy::Core::OnJobCancelled(
+    const std::string& job_unique_id) {
+  DCHECK_CURRENTLY_ON(BrowserThread::UI);
+  BrowserThread::PostTask(
+      BrowserThread::IO, FROM_HERE,
+      base::BindOnce(&BackgroundFetchDelegateProxy::OnJobCancelled, io_parent_,
+                     job_unique_id));
+}
+
 void BackgroundFetchDelegateProxy::Core::OnDownloadUpdated(
+    const std::string& job_unique_id,
     const std::string& guid,
     uint64_t bytes_downloaded) {
   DCHECK_CURRENTLY_ON(BrowserThread::UI);
   BrowserThread::PostTask(
       BrowserThread::IO, FROM_HERE,
       base::BindOnce(&BackgroundFetchDelegateProxy::OnDownloadUpdated,
-                     io_parent_, guid, bytes_downloaded));
+                     io_parent_, job_unique_id, guid, bytes_downloaded));
 }
 
 void BackgroundFetchDelegateProxy::Core::OnDownloadComplete(
+    const std::string& job_unique_id,
     const std::string& guid,
     std::unique_ptr<BackgroundFetchResult> result) {
   DCHECK_CURRENTLY_ON(BrowserThread::UI);
   BrowserThread::PostTask(
       BrowserThread::IO, FROM_HERE,
       base::BindOnce(&BackgroundFetchDelegateProxy::OnDownloadComplete,
-                     io_parent_, guid, std::move(result)));
+                     io_parent_, job_unique_id, guid, std::move(result)));
 }
 
 void BackgroundFetchDelegateProxy::Core::OnDownloadStarted(
+    const std::string& job_unique_id,
     const std::string& guid,
     std::unique_ptr<content::BackgroundFetchResponse> response) {
   DCHECK_CURRENTLY_ON(BrowserThread::UI);
@@ -177,13 +192,22 @@
   BrowserThread::PostTask(
       BrowserThread::IO, FROM_HERE,
       base::BindOnce(&BackgroundFetchDelegateProxy::DidStartRequest, io_parent_,
-                     guid, std::move(response)));
+                     job_unique_id, guid, std::move(response)));
 }
 
 void BackgroundFetchDelegateProxy::Core::OnDelegateShutdown() {
   delegate_ = nullptr;
 }
 
+BackgroundFetchDelegateProxy::JobDetails::JobDetails(
+    base::WeakPtr<Controller> controller)
+    : controller(controller) {}
+
+BackgroundFetchDelegateProxy::JobDetails::JobDetails(JobDetails&& details) =
+    default;
+
+BackgroundFetchDelegateProxy::JobDetails::~JobDetails() = default;
+
 BackgroundFetchDelegateProxy::BackgroundFetchDelegateProxy(
     BackgroundFetchDelegate* delegate)
     : weak_ptr_factory_(this) {
@@ -207,11 +231,15 @@
     const std::string& job_unique_id,
     const std::string& title,
     const url::Origin& origin,
+    base::WeakPtr<Controller> controller,
     int completed_parts,
     int total_parts,
     const std::vector<std::string>& current_guids) {
   DCHECK_CURRENTLY_ON(BrowserThread::IO);
 
+  DCHECK(!job_details_map_.count(job_unique_id));
+  job_details_map_.emplace(job_unique_id, JobDetails(controller));
+
   BrowserThread::PostTask(
       BrowserThread::UI, FROM_HERE,
       base::BindOnce(&Core::CreateDownloadJob, ui_core_ptr_, job_unique_id,
@@ -221,20 +249,22 @@
 
 void BackgroundFetchDelegateProxy::StartRequest(
     const std::string& job_unique_id,
-    base::WeakPtr<Controller> job_controller,
     const url::Origin& origin,
     scoped_refptr<BackgroundFetchRequestInfo> request) {
   DCHECK_CURRENTLY_ON(BrowserThread::IO);
-  DCHECK(job_controller);
 
-  std::string download_guid(base::GenerateGUID());
+  DCHECK(job_details_map_.count(job_unique_id));
+  JobDetails& job_details = job_details_map_.find(job_unique_id)->second;
+  DCHECK(job_details.controller);
 
-  controller_map_[download_guid] = std::make_pair(request, job_controller);
+  std::string download_guid = request->download_guid();
+  DCHECK(!download_guid.empty());
 
-  BrowserThread::PostTask(
-      BrowserThread::UI, FROM_HERE,
-      base::BindOnce(&Core::StartRequest, ui_core_ptr_, job_unique_id,
-                     download_guid, origin, request));
+  job_details.current_request_map[download_guid] = request;
+
+  BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
+                          base::BindOnce(&Core::StartRequest, ui_core_ptr_,
+                                         job_unique_id, origin, request));
 }
 
 void BackgroundFetchDelegateProxy::UpdateUI(const std::string& job_unique_id,
@@ -250,65 +280,89 @@
   BrowserThread::PostTask(
       BrowserThread::UI, FROM_HERE,
       base::BindOnce(&Core::Abort, ui_core_ptr_, job_unique_id));
+
+  job_details_map_.erase(job_details_map_.find(job_unique_id));
+}
+
+void BackgroundFetchDelegateProxy::OnJobCancelled(
+    const std::string& job_unique_id) {
+  DCHECK_CURRENTLY_ON(BrowserThread::IO);
+
+  // TODO(delphick): The controller may not exist as persistence is not yet
+  // implemented.
+  auto job_details_iter = job_details_map_.find(job_unique_id);
+  if (job_details_iter == job_details_map_.end())
+    return;
+
+  JobDetails& job_details = job_details_iter->second;
+  if (job_details.controller)
+    job_details.controller->AbortFromUser();
 }
 
 void BackgroundFetchDelegateProxy::DidStartRequest(
+    const std::string& job_unique_id,
     const std::string& guid,
     std::unique_ptr<BackgroundFetchResponse> response) {
   DCHECK_CURRENTLY_ON(BrowserThread::IO);
 
   // TODO(delphick): The controller may not exist as persistence is not yet
   // implemented.
-  if (!controller_map_.count(guid))
+  auto job_details_iter = job_details_map_.find(job_unique_id);
+  if (job_details_iter == job_details_map_.end())
     return;
 
+  JobDetails& job_details = job_details_iter->second;
+
   const scoped_refptr<BackgroundFetchRequestInfo>& request_info =
-      controller_map_[guid].first;
-  base::WeakPtr<Controller> job_controller = controller_map_[guid].second;
+      job_details.current_request_map[guid];
 
   request_info->PopulateWithResponse(std::move(response));
 
-  if (job_controller)
-    job_controller->DidStartRequest(request_info, guid);
+  if (job_details.controller)
+    job_details.controller->DidStartRequest(request_info, guid);
 }
 
 void BackgroundFetchDelegateProxy::OnDownloadUpdated(
+    const std::string& job_unique_id,
     const std::string& guid,
     uint64_t bytes_downloaded) {
   DCHECK_CURRENTLY_ON(BrowserThread::IO);
 
   // TODO(delphick): The controller may not exist as persistence is not yet
   // implemented.
-  if (!controller_map_.count(guid))
+  auto job_details_iter = job_details_map_.find(job_unique_id);
+  if (job_details_iter == job_details_map_.end())
     return;
 
-  const scoped_refptr<BackgroundFetchRequestInfo>& request_info =
-      controller_map_[guid].first;
-  base::WeakPtr<Controller> job_controller = controller_map_[guid].second;
+  JobDetails& job_details = job_details_iter->second;
 
   // TODO(peter): Should we update the |request_info| with the progress?
-  if (job_controller)
-    job_controller->DidUpdateRequest(request_info, guid, bytes_downloaded);
+  if (job_details.controller) {
+    job_details.controller->DidUpdateRequest(
+        job_details.current_request_map[guid], guid, bytes_downloaded);
+  }
 }
 
 void BackgroundFetchDelegateProxy::OnDownloadComplete(
+    const std::string& job_unique_id,
     const std::string& guid,
     std::unique_ptr<BackgroundFetchResult> result) {
   DCHECK_CURRENTLY_ON(BrowserThread::IO);
 
   // TODO(delphick): The controller may not exist as persistence is not yet
   // implemented.
-  if (!controller_map_.count(guid))
+  auto job_details_iter = job_details_map_.find(job_unique_id);
+  if (job_details_iter == job_details_map_.end())
     return;
 
-  const scoped_refptr<BackgroundFetchRequestInfo>& request_info =
-      controller_map_[guid].first;
-  base::WeakPtr<Controller> job_controller = controller_map_[guid].second;
+  JobDetails& job_details = job_details_iter->second;
 
+  const scoped_refptr<BackgroundFetchRequestInfo>& request_info =
+      job_details.current_request_map[guid];
   request_info->SetResult(std::move(result));
 
-  if (job_controller)
-    job_controller->DidCompleteRequest(request_info, guid);
+  if (job_details.controller)
+    job_details.controller->DidCompleteRequest(request_info, guid);
 }
 
 }  // namespace content
diff --git a/content/browser/background_fetch/background_fetch_delegate_proxy.h b/content/browser/background_fetch/background_fetch_delegate_proxy.h
index 69b2cdef..22f1d10 100644
--- a/content/browser/background_fetch/background_fetch_delegate_proxy.h
+++ b/content/browser/background_fetch/background_fetch_delegate_proxy.h
@@ -69,6 +69,7 @@
   void CreateDownloadJob(const std::string& job_unique_id,
                          const std::string& title,
                          const url::Origin& origin,
+                         base::WeakPtr<Controller> controller,
                          int completed_parts,
                          int total_parts,
                          const std::vector<std::string>& current_guids);
@@ -77,7 +78,6 @@
   // Should only be called from the Controller (on the IO
   // thread).
   void StartRequest(const std::string& job_unique_id,
-                    base::WeakPtr<Controller> job_controller,
                     const url::Origin& origin,
                     scoped_refptr<BackgroundFetchRequestInfo> request);
 
@@ -93,28 +93,48 @@
  private:
   class Core;
 
+  // Called when the job identified by |job_unique|id| was cancelled by the
+  // delegate. Should only be called on the IO thread.
+  void OnJobCancelled(const std::string& job_unique_id);
+
   // Called when the download identified by |guid| has succeeded/failed/aborted.
   // Should only be called on the IO thread.
-  void OnDownloadComplete(const std::string& guid,
+  void OnDownloadComplete(const std::string& job_unique_id,
+                          const std::string& guid,
                           std::unique_ptr<BackgroundFetchResult> result);
 
   // Called when progress has been made for the download identified by |guid|.
   // Should only be called on the IO thread.
-  void OnDownloadUpdated(const std::string& guid, uint64_t bytes_downloaded);
+  void OnDownloadUpdated(const std::string& job_unique_id,
+                         const std::string& guid,
+                         uint64_t bytes_downloaded);
 
   // Should only be called from the BackgroundFetchDelegate (on the IO thread).
-  void DidStartRequest(const std::string& guid,
+  void DidStartRequest(const std::string& job_unique_id,
+                       const std::string& guid,
                        std::unique_ptr<BackgroundFetchResponse> response);
 
   std::unique_ptr<Core, BrowserThread::DeleteOnUIThread> ui_core_;
   base::WeakPtr<Core> ui_core_ptr_;
 
-  // Map from DownloadService GUIDs to the RequestInfo and the JobController
-  // that started the download.
-  std::map<std::string,
-           std::pair<scoped_refptr<BackgroundFetchRequestInfo>,
-                     base::WeakPtr<Controller>>>
-      controller_map_;
+  struct JobDetails {
+    explicit JobDetails(base::WeakPtr<Controller> controller);
+    JobDetails(JobDetails&& details);
+    ~JobDetails();
+
+    base::WeakPtr<Controller> controller;
+
+    // Map from DownloadService GUIDs to their corresponding request.
+    base::flat_map<std::string, scoped_refptr<BackgroundFetchRequestInfo>>
+        current_request_map;
+
+   private:
+    DISALLOW_COPY_AND_ASSIGN(JobDetails);
+  };
+
+  // Map from unique job ids to a JobDetails containing the outstanding download
+  // GUIDs and the controller that started the download.
+  std::map<std::string, JobDetails> job_details_map_;
 
   base::WeakPtrFactory<BackgroundFetchDelegateProxy> weak_ptr_factory_;
 
diff --git a/content/browser/background_fetch/background_fetch_delegate_proxy_unittest.cc b/content/browser/background_fetch/background_fetch_delegate_proxy_unittest.cc
index c800ddf..057ae5d5 100644
--- a/content/browser/background_fetch/background_fetch_delegate_proxy_unittest.cc
+++ b/content/browser/background_fetch/background_fetch_delegate_proxy_unittest.cc
@@ -19,6 +19,7 @@
 namespace {
 
 const char kExampleUniqueId[] = "7e57ab1e-c0de-a150-ca75-1e75f005ba11";
+const char kExampleUniqueId2[] = "17467386-60b4-4c5b-b66c-aabf793fd39b";
 
 class FakeBackgroundFetchDelegate : public BackgroundFetchDelegate {
  public:
@@ -47,12 +48,12 @@
         std::vector<GURL>({url}),
         base::MakeRefCounted<net::HttpResponseHeaders>("200 OK"));
 
-    client()->OnDownloadStarted(guid, std::move(response));
+    client()->OnDownloadStarted(job_unique_id, guid, std::move(response));
     if (complete_downloads_) {
       BrowserThread::PostTask(
           BrowserThread::IO, FROM_HERE,
           base::BindOnce(&FakeBackgroundFetchDelegate::CompleteDownload,
-                         base::Unretained(this), guid));
+                         base::Unretained(this), job_unique_id, guid));
     }
   }
   void Abort(const std::string& job_unique_id) override {
@@ -64,16 +65,17 @@
   }
 
  private:
-  void CompleteDownload(const std::string& guid) {
+  void CompleteDownload(const std::string& job_unique_id,
+                        const std::string& guid) {
     if (!client())
       return;
 
     if (aborted_jobs_.count(download_guid_to_job_id_map_[guid]))
       return;
 
-    client()->OnDownloadComplete(
-        guid, std::make_unique<BackgroundFetchResult>(base::Time::Now(),
-                                                      base::FilePath(), 10u));
+    client()->OnDownloadComplete(job_unique_id, guid,
+                                 std::make_unique<BackgroundFetchResult>(
+                                     base::Time::Now(), base::FilePath(), 10u));
   }
 
   std::set<std::string> aborted_jobs_;
@@ -117,6 +119,15 @@
   BackgroundFetchDelegateProxy delegate_proxy_;
 };
 
+scoped_refptr<BackgroundFetchRequestInfo> CreateRequestInfo(
+    int request_index,
+    const ServiceWorkerFetchRequest& fetch_request) {
+  auto request = base::MakeRefCounted<BackgroundFetchRequestInfo>(
+      request_index, fetch_request);
+  request->InitializeDownloadGuid();
+  return request;
+}
+
 }  // namespace
 
 TEST_F(BackgroundFetchDelegateProxyTest, SetDelegate) {
@@ -126,15 +137,16 @@
 TEST_F(BackgroundFetchDelegateProxyTest, StartRequest) {
   FakeController controller;
   ServiceWorkerFetchRequest fetch_request;
-  auto request = base::MakeRefCounted<BackgroundFetchRequestInfo>(
-      0 /* request_index */, fetch_request);
+  auto request = CreateRequestInfo(0 /* request_index */, fetch_request);
 
   EXPECT_FALSE(controller.request_started_);
   EXPECT_FALSE(controller.request_completed_);
 
-  delegate_proxy_.StartRequest(kExampleUniqueId,
-                               controller.weak_ptr_factory_.GetWeakPtr(),
-                               url::Origin(), request);
+  delegate_proxy_.CreateDownloadJob(kExampleUniqueId, "Job 1", url::Origin(),
+                                    controller.weak_ptr_factory_.GetWeakPtr(),
+                                    0, 1, {});
+
+  delegate_proxy_.StartRequest(kExampleUniqueId, url::Origin(), request);
   base::RunLoop().RunUntilIdle();
 
   EXPECT_TRUE(controller.request_started_);
@@ -144,16 +156,17 @@
 TEST_F(BackgroundFetchDelegateProxyTest, StartRequest_NotCompleted) {
   FakeController controller;
   ServiceWorkerFetchRequest fetch_request;
-  auto request = base::MakeRefCounted<BackgroundFetchRequestInfo>(
-      0 /* request_index */, fetch_request);
+  auto request = CreateRequestInfo(0 /* request_index */, fetch_request);
 
   EXPECT_FALSE(controller.request_started_);
   EXPECT_FALSE(controller.request_completed_);
 
   delegate_.set_complete_downloads(false);
-  delegate_proxy_.StartRequest(kExampleUniqueId,
-                               controller.weak_ptr_factory_.GetWeakPtr(),
-                               url::Origin(), request);
+  delegate_proxy_.CreateDownloadJob(kExampleUniqueId, "Job 1", url::Origin(),
+                                    controller.weak_ptr_factory_.GetWeakPtr(),
+                                    0, 1, {});
+
+  delegate_proxy_.StartRequest(kExampleUniqueId, url::Origin(), request);
   base::RunLoop().RunUntilIdle();
 
   EXPECT_TRUE(controller.request_started_);
@@ -165,28 +178,30 @@
   FakeController controller2;
   ServiceWorkerFetchRequest fetch_request;
   ServiceWorkerFetchRequest fetch_request2;
-  auto request = base::MakeRefCounted<BackgroundFetchRequestInfo>(
-      0 /* request_index */, fetch_request);
-  auto request2 = base::MakeRefCounted<BackgroundFetchRequestInfo>(
-      1 /* request_index */, fetch_request2);
+  auto request = CreateRequestInfo(0 /* request_index */, fetch_request);
+  auto request2 = CreateRequestInfo(1 /* request_index */, fetch_request2);
 
   EXPECT_FALSE(controller.request_started_);
   EXPECT_FALSE(controller.request_completed_);
   EXPECT_FALSE(controller2.request_started_);
   EXPECT_FALSE(controller2.request_completed_);
 
-  delegate_proxy_.StartRequest("jobid1",
-                               controller.weak_ptr_factory_.GetWeakPtr(),
-                               url::Origin(), request);
-  delegate_proxy_.StartRequest("jobid2",
-                               controller2.weak_ptr_factory_.GetWeakPtr(),
-                               url::Origin(), request2);
-  delegate_proxy_.Abort("jobid1");
+  delegate_proxy_.CreateDownloadJob(kExampleUniqueId, "Job 1", url::Origin(),
+                                    controller.weak_ptr_factory_.GetWeakPtr(),
+                                    0, 1, {});
+
+  delegate_proxy_.CreateDownloadJob(kExampleUniqueId2, "Job 2", url::Origin(),
+                                    controller2.weak_ptr_factory_.GetWeakPtr(),
+                                    0, 1, {});
+
+  delegate_proxy_.StartRequest(kExampleUniqueId, url::Origin(), request);
+  delegate_proxy_.StartRequest(kExampleUniqueId2, url::Origin(), request2);
+  delegate_proxy_.Abort(kExampleUniqueId);
   base::RunLoop().RunUntilIdle();
 
-  EXPECT_TRUE(controller.request_started_);
+  EXPECT_FALSE(controller.request_started_) << "Aborted job started";
   EXPECT_FALSE(controller.request_completed_) << "Aborted job completed";
-  EXPECT_TRUE(controller2.request_started_);
+  EXPECT_TRUE(controller2.request_started_) << "Normal job did not start";
   EXPECT_TRUE(controller2.request_completed_) << "Normal job did not complete";
 }
 
diff --git a/content/browser/background_fetch/background_fetch_job_controller.cc b/content/browser/background_fetch/background_fetch_job_controller.cc
index 9c757c9..0a7f0016 100644
--- a/content/browser/background_fetch/background_fetch_job_controller.cc
+++ b/content/browser/background_fetch/background_fetch_job_controller.cc
@@ -31,6 +31,17 @@
   data_manager_->SetController(registration_id, this);
 }
 
+void BackgroundFetchJobController::InitializeRequestStatus(
+    int completed_downloads,
+    int total_downloads,
+    const std::vector<std::string>& outstanding_guids) {
+  DCHECK_CURRENTLY_ON(BrowserThread::IO);
+
+  delegate_proxy_->CreateDownloadJob(
+      registration_id_.unique_id(), options_.title, registration_id_.origin(),
+      GetWeakPtr(), completed_downloads, total_downloads, outstanding_guids);
+}
+
 BackgroundFetchJobController::~BackgroundFetchJobController() {
   DCHECK_CURRENTLY_ON(BrowserThread::IO);
   data_manager_->SetController(registration_id_, nullptr);
@@ -61,7 +72,6 @@
   }
 
   delegate_proxy_->StartRequest(registration_id_.unique_id(),
-                                weak_ptr_factory_.GetWeakPtr(),
                                 registration_id_.origin(), request);
 }
 
diff --git a/content/browser/background_fetch/background_fetch_job_controller.h b/content/browser/background_fetch/background_fetch_job_controller.h
index a121d12..db80870 100644
--- a/content/browser/background_fetch/background_fetch_job_controller.h
+++ b/content/browser/background_fetch/background_fetch_job_controller.h
@@ -8,7 +8,7 @@
 #include <stdint.h>
 #include <memory>
 #include <string>
-#include <unordered_map>
+#include <vector>
 
 #include "base/callback.h"
 #include "base/macros.h"
@@ -58,6 +58,10 @@
   void Start();
 
   // BackgroundFetchDataManager::Controller implementation:
+  void InitializeRequestStatus(
+      int completed_downloads,
+      int total_downloads,
+      const std::vector<std::string>& outstanding_guids) override;
   void UpdateUI(const std::string& title) override;
   uint64_t GetInProgressDownloadedBytes() override;
   void Abort() override;
diff --git a/content/browser/background_fetch/background_fetch_job_controller_unittest.cc b/content/browser/background_fetch/background_fetch_job_controller_unittest.cc
index a849a9a..aab4e60 100644
--- a/content/browser/background_fetch/background_fetch_job_controller_unittest.cc
+++ b/content/browser/background_fetch/background_fetch_job_controller_unittest.cc
@@ -95,7 +95,8 @@
 
   // Creates a new BackgroundFetchJobController instance.
   std::unique_ptr<BackgroundFetchJobController> CreateJobController(
-      const BackgroundFetchRegistrationId& registration_id) {
+      const BackgroundFetchRegistrationId& registration_id,
+      int total_downloads = 1) {
     delegate_ = browser_context()->GetBackgroundFetchDelegate();
     DCHECK(delegate_);
     delegate_proxy_ = std::make_unique<BackgroundFetchDelegateProxy>(delegate_);
diff --git a/content/browser/background_fetch/background_fetch_request_info.cc b/content/browser/background_fetch/background_fetch_request_info.cc
index 05d56e1..fbd7db3 100644
--- a/content/browser/background_fetch/background_fetch_request_info.cc
+++ b/content/browser/background_fetch/background_fetch_request_info.cc
@@ -6,6 +6,7 @@
 
 #include <utility>
 
+#include "base/guid.h"
 #include "base/strings/string_util.h"
 #include "base/threading/sequenced_task_runner_handle.h"
 #include "content/public/browser/background_fetch_response.h"
@@ -27,6 +28,20 @@
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
 }
 
+void BackgroundFetchRequestInfo::InitializeDownloadGuid() {
+  DCHECK(download_guid_.empty());
+
+  download_guid_ = base::GenerateGUID();
+}
+
+void BackgroundFetchRequestInfo::SetDownloadGuid(
+    const std::string& download_guid) {
+  DCHECK(!download_guid.empty());
+  DCHECK(download_guid_.empty());
+
+  download_guid_ = download_guid;
+}
+
 void BackgroundFetchRequestInfo::PopulateWithResponse(
     std::unique_ptr<BackgroundFetchResponse> response) {
   DCHECK_CURRENTLY_ON(BrowserThread::IO);
diff --git a/content/browser/background_fetch/background_fetch_request_info.h b/content/browser/background_fetch/background_fetch_request_info.h
index 01132c1..a446f8f 100644
--- a/content/browser/background_fetch/background_fetch_request_info.h
+++ b/content/browser/background_fetch/background_fetch_request_info.h
@@ -35,6 +35,14 @@
   BackgroundFetchRequestInfo(int request_index,
                              const ServiceWorkerFetchRequest& fetch_request);
 
+  // Sets the download GUID to a newly generated value. Can only be used if no
+  // GUID is already set.
+  void InitializeDownloadGuid();
+
+  // Sets the download GUID to a given value (to be used when requests are
+  // retrieved from storage). Can only be used if no GUID is already set.
+  void SetDownloadGuid(const std::string& download_guid);
+
   // Populates the cached state for the in-progress download.
   void PopulateWithResponse(std::unique_ptr<BackgroundFetchResponse> response);
 
@@ -43,6 +51,10 @@
   // Returns the index of this request within a Background Fetch registration.
   int request_index() const { return request_index_; }
 
+  // Returns the GUID used to identify this download. (Empty before the download
+  // becomes active).
+  const std::string& download_guid() const { return download_guid_; }
+
   // Returns the Fetch API Request object that details the developer's request.
   const ServiceWorkerFetchRequest& fetch_request() const {
     return fetch_request_;
@@ -80,7 +92,6 @@
   ~BackgroundFetchRequestInfo();
 
   // ---- Data associated with the request -------------------------------------
-
   int request_index_ = kInvalidBackgroundFetchRequestIndex;
   ServiceWorkerFetchRequest fetch_request_;
 
diff --git a/content/browser/background_fetch/mock_background_fetch_delegate.cc b/content/browser/background_fetch/mock_background_fetch_delegate.cc
index 1971ff9..4ac18a4 100644
--- a/content/browser/background_fetch/mock_background_fetch_delegate.cc
+++ b/content/browser/background_fetch/mock_background_fetch_delegate.cc
@@ -93,20 +93,22 @@
   PostAbortCheckingTask(
       job_unique_id,
       base::BindOnce(&BackgroundFetchDelegate::Client::OnDownloadStarted,
-                     client(), guid, std::move(response)));
+                     client(), job_unique_id, guid, std::move(response)));
 
   if (test_response->data.size()) {
     // Report progress at 50% complete.
     PostAbortCheckingTask(
         job_unique_id,
         base::BindOnce(&BackgroundFetchDelegate::Client::OnDownloadUpdated,
-                       client(), guid, test_response->data.size() / 2));
+                       client(), job_unique_id, guid,
+                       test_response->data.size() / 2));
 
     // Report progress at 100% complete.
     PostAbortCheckingTask(
         job_unique_id,
         base::BindOnce(&BackgroundFetchDelegate::Client::OnDownloadUpdated,
-                       client(), guid, test_response->data.size()));
+                       client(), job_unique_id, guid,
+                       test_response->data.size()));
   }
 
   if (test_response->succeeded_) {
@@ -127,14 +129,14 @@
         job_unique_id,
         base::BindOnce(
             &BackgroundFetchDelegate::Client::OnDownloadComplete, client(),
-            guid,
+            job_unique_id, guid,
             std::make_unique<BackgroundFetchResult>(
                 base::Time::Now(), response_path, test_response->data.size())));
   } else {
     PostAbortCheckingTask(
         job_unique_id,
         base::BindOnce(&BackgroundFetchDelegate::Client::OnDownloadComplete,
-                       client(), guid,
+                       client(), job_unique_id, guid,
                        std::make_unique<BackgroundFetchResult>(
                            base::Time::Now(),
                            BackgroundFetchResult::FailureReason::UNKNOWN)));
diff --git a/content/browser/browser_context.cc b/content/browser/browser_context.cc
index 5932fec..0e4d5ff 100644
--- a/content/browser/browser_context.cc
+++ b/content/browser/browser_context.cc
@@ -15,6 +15,7 @@
 
 #include "base/base64.h"
 #include "base/command_line.h"
+#include "base/files/file_path.h"
 #include "base/guid.h"
 #include "base/lazy_instance.h"
 #include "base/logging.h"
@@ -41,6 +42,8 @@
 #include "content/public/common/content_switches.h"
 #include "content/public/common/service_manager_connection.h"
 #include "content/public/common/service_names.mojom.h"
+#include "media/mojo/services/video_decode_perf_history.h"
+#include "media/mojo/services/video_decode_stats_db_impl.h"
 #include "net/cookies/cookie_store.h"
 #include "net/ssl/channel_id_service.h"
 #include "net/ssl/channel_id_store.h"
@@ -84,6 +87,7 @@
 const char kServiceManagerConnection[] = "service-manager-connection";
 const char kServiceUserId[] = "service-user-id";
 const char kStoragePartitionMapKeyName[] = "content_storage_partition_map";
+const char kVideoDecodePerfHistoryId[] = "video-decode-perf-history";
 
 #if defined(OS_CHROMEOS)
 const char kMountPointsKey[] = "mount_points";
@@ -204,9 +208,7 @@
     BrowserContext* context) {
   DCHECK_CURRENTLY_ON(BrowserThread::UI);
   if (!context->GetUserData(kDownloadManagerKeyName)) {
-    DownloadManager* download_manager =
-        new DownloadManagerImpl(
-            GetContentClient()->browser()->GetNetLog(), context);
+    DownloadManager* download_manager = new DownloadManagerImpl(context);
 
     SetDownloadManager(context, base::WrapUnique(download_manager));
     download_manager->SetDelegate(context->GetDownloadManagerDelegate());
@@ -582,4 +584,22 @@
   return salt;
 }
 
+media::VideoDecodePerfHistory* BrowserContext::GetVideoDecodePerfHistory() {
+  media::VideoDecodePerfHistory* decode_history =
+      static_cast<media::VideoDecodePerfHistory*>(
+          GetUserData(kVideoDecodePerfHistoryId));
+
+  // Lazily created. Note, this does not trigger loading the DB from disk. That
+  // occurs later upon first VideoDecodePerfHistory API request that requires DB
+  // access. DB operations will not block the UI thread.
+  if (!decode_history) {
+    auto db_factory = std::make_unique<media::VideoDecodeStatsDBImplFactory>(
+        GetPath().Append(FILE_PATH_LITERAL("VideoDecodeStats")));
+    decode_history = new media::VideoDecodePerfHistory(std::move(db_factory));
+    SetUserData(kVideoDecodePerfHistoryId, base::WrapUnique(decode_history));
+  }
+
+  return decode_history;
+}
+
 }  // namespace content
diff --git a/content/browser/devtools/protocol/system_info_handler.cc b/content/browser/devtools/protocol/system_info_handler.cc
index 490e97c..2606838 100644
--- a/content/browser/devtools/protocol/system_info_handler.cc
+++ b/content/browser/devtools/protocol/system_info_handler.cc
@@ -13,7 +13,7 @@
 #include "base/memory/ptr_util.h"
 #include "base/strings/utf_string_conversions.h"
 #include "content/browser/gpu/compositor_util.h"
-#include "content/browser/gpu/gpu_data_manager_impl.h"
+#include "content/public/browser/gpu_data_manager.h"
 #include "gpu/config/gpu_feature_type.h"
 #include "gpu/config/gpu_info.h"
 #include "gpu/config/gpu_switches.h"
@@ -97,7 +97,7 @@
 }
 
 void SendGetInfoResponse(std::unique_ptr<GetInfoCallback> callback) {
-  gpu::GPUInfo gpu_info = GpuDataManagerImpl::GetInstance()->GetGPUInfo();
+  gpu::GPUInfo gpu_info = GpuDataManager::GetInstance()->GetGPUInfo();
   std::unique_ptr<protocol::Array<GPUDevice>> devices =
       protocol::Array<GPUDevice>::create();
   devices->addItem(GPUDeviceToProtocol(gpu_info.gpu));
@@ -153,12 +153,13 @@
                        weak_factory_.GetWeakPtr()),
         base::TimeDelta::FromMilliseconds(kGPUInfoWatchdogTimeoutMs));
 
-    GpuDataManagerImpl::GetInstance()->AddObserver(this);
+    GpuDataManager::GetInstance()->AddObserver(this);
+    // There's no other method available to request just essential GPU info.
+    GpuDataManager::GetInstance()->RequestCompleteGpuInfoIfNeeded();
   }
 
   void OnGpuInfoUpdate() override {
-    if (GpuDataManagerImpl::GetInstance()->IsGpuFeatureInfoAvailable())
-      UnregisterAndSendResponse();
+    UnregisterAndSendResponse();
   }
 
   void OnGpuProcessCrashed(base::TerminationStatus exit_code) override {
@@ -171,7 +172,7 @@
   }
 
   void UnregisterAndSendResponse() {
-    GpuDataManagerImpl::GetInstance()->RemoveObserver(this);
+    GpuDataManager::GetInstance()->RemoveObserver(this);
     SendGetInfoResponse(std::move(callback_));
     delete this;
   }
@@ -195,8 +196,8 @@
 void SystemInfoHandler::GetInfo(
     std::unique_ptr<GetInfoCallback> callback) {
   std::string reason;
-  if (!GpuDataManagerImpl::GetInstance()->GpuAccessAllowed(&reason) ||
-      GpuDataManagerImpl::GetInstance()->IsGpuFeatureInfoAvailable() ||
+  if (!GpuDataManager::GetInstance()->GpuAccessAllowed(&reason) ||
+      GpuDataManager::GetInstance()->IsEssentialGpuInfoAvailable() ||
       base::CommandLine::ForCurrentProcess()->HasSwitch(
           switches::kGpuTestingNoCompleteInfoCollection)) {
     // The GpuDataManager already has all of the information needed to make
diff --git a/content/browser/dom_storage/local_storage_context_mojo_unittest.cc b/content/browser/dom_storage/local_storage_context_mojo_unittest.cc
index 654dba48..fb1ab2d 100644
--- a/content/browser/dom_storage/local_storage_context_mojo_unittest.cc
+++ b/content/browser/dom_storage/local_storage_context_mojo_unittest.cc
@@ -933,8 +933,7 @@
 class LocalStorageContextMojoTestWithService
     : public service_manager::test::ServiceTest {
  public:
-  LocalStorageContextMojoTestWithService()
-      : ServiceTest("content_unittests", false) {}
+  LocalStorageContextMojoTestWithService() : ServiceTest("content_unittests") {}
   ~LocalStorageContextMojoTestWithService() override {}
 
  protected:
diff --git a/content/browser/download/download_manager_impl.cc b/content/browser/download/download_manager_impl.cc
index cd82ef85..474e2b2 100644
--- a/content/browser/download/download_manager_impl.cc
+++ b/content/browser/download/download_manager_impl.cc
@@ -284,15 +284,14 @@
 
 }  // namespace
 
-DownloadManagerImpl::DownloadManagerImpl(net::NetLog* net_log,
-                                         BrowserContext* browser_context)
+DownloadManagerImpl::DownloadManagerImpl(BrowserContext* browser_context)
     : item_factory_(new DownloadItemFactoryImpl()),
       file_factory_(new DownloadFileFactory()),
       shutdown_needed_(true),
       initialized_(false),
       browser_context_(browser_context),
       delegate_(nullptr),
-      net_log_(net_log),
+      net_log_(nullptr),
       weak_factory_(this) {
   DCHECK(browser_context);
 }
diff --git a/content/browser/download/download_manager_impl.h b/content/browser/download/download_manager_impl.h
index 6b0b6a4c..ead13aa 100644
--- a/content/browser/download/download_manager_impl.h
+++ b/content/browser/download/download_manager_impl.h
@@ -51,7 +51,7 @@
 
   // Caller guarantees that |net_log| will remain valid
   // for the lifetime of DownloadManagerImpl (until Shutdown() is called).
-  DownloadManagerImpl(net::NetLog* net_log, BrowserContext* browser_context);
+  explicit DownloadManagerImpl(BrowserContext* browser_context);
   ~DownloadManagerImpl() override;
 
   // Implementation functions (not part of the DownloadManager interface).
diff --git a/content/browser/download/download_manager_impl_unittest.cc b/content/browser/download/download_manager_impl_unittest.cc
index 19c8d86..c2b0de35a 100644
--- a/content/browser/download/download_manager_impl_unittest.cc
+++ b/content/browser/download/download_manager_impl_unittest.cc
@@ -410,8 +410,8 @@
     EXPECT_CALL(*mock_browser_context_.get(), IsOffTheRecord())
         .WillRepeatedly(Return(false));
 
-    download_manager_.reset(new DownloadManagerImpl(
-                                NULL, mock_browser_context_.get()));
+    download_manager_.reset(
+        new DownloadManagerImpl(mock_browser_context_.get()));
     download_manager_->SetDownloadItemFactoryForTesting(
         std::unique_ptr<DownloadItemFactory>(
             mock_download_item_factory_.get()));
diff --git a/content/browser/download/download_stats.cc b/content/browser/download/download_stats.cc
index 588fb486..dbb9a18 100644
--- a/content/browser/download/download_stats.cc
+++ b/content/browser/download/download_stats.cc
@@ -208,7 +208,33 @@
     FILE_PATH_LITERAL(".imgpart"),     FILE_PATH_LITERAL(".ndif"),
     FILE_PATH_LITERAL(".smi"),         FILE_PATH_LITERAL(".sparsebundle"),
     FILE_PATH_LITERAL(".sparseimage"), FILE_PATH_LITERAL(".toast"),
-    FILE_PATH_LITERAL(".udif"),
+    FILE_PATH_LITERAL(".udif"),        FILE_PATH_LITERAL(".run"),        // 262
+    FILE_PATH_LITERAL(".mpkg"),        FILE_PATH_LITERAL(".as"),         // 264
+    FILE_PATH_LITERAL(".cpgz"),        FILE_PATH_LITERAL(".pax"),        // 266
+    FILE_PATH_LITERAL(".xip"),         FILE_PATH_LITERAL(".docx"),       // 268
+    FILE_PATH_LITERAL(".docm"),        FILE_PATH_LITERAL(".dott"),       // 270
+    FILE_PATH_LITERAL(".dotm"),        FILE_PATH_LITERAL(".docb"),       // 272
+    FILE_PATH_LITERAL(".xlsx"),        FILE_PATH_LITERAL(".xlsm"),       // 274
+    FILE_PATH_LITERAL(".xltx"),        FILE_PATH_LITERAL(".xltm"),       // 276
+    FILE_PATH_LITERAL(".pptx"),        FILE_PATH_LITERAL(".pptm"),       // 278
+    FILE_PATH_LITERAL(".potx"),        FILE_PATH_LITERAL(".ppam"),       // 280
+    FILE_PATH_LITERAL(".ppsx"),        FILE_PATH_LITERAL(".sldx"),       // 282
+    FILE_PATH_LITERAL(".sldm"),        FILE_PATH_LITERAL(".htm"),        // 284
+    FILE_PATH_LITERAL(".html"),        FILE_PATH_LITERAL(".xht"),        // 286
+    FILE_PATH_LITERAL(".xhtm"),        FILE_PATH_LITERAL(".xhtml"),      // 288
+    FILE_PATH_LITERAL(".vdx"),         FILE_PATH_LITERAL(".vsx"),        // 290
+    FILE_PATH_LITERAL(".vtx"),         FILE_PATH_LITERAL(".vsdx"),       // 292
+    FILE_PATH_LITERAL(".vssx"),        FILE_PATH_LITERAL(".vstx"),       // 294
+    FILE_PATH_LITERAL(".vsdm"),        FILE_PATH_LITERAL(".vssm"),       // 296
+    FILE_PATH_LITERAL(".vstm"),        FILE_PATH_LITERAL(".btapp"),      // 298
+    FILE_PATH_LITERAL(".btbtskin"),    FILE_PATH_LITERAL(".btinstall"),  // 300
+    FILE_PATH_LITERAL(".btkey"),       FILE_PATH_LITERAL(".btsearch"),   // 302
+    FILE_PATH_LITERAL(".dhtml"),       FILE_PATH_LITERAL(".dhtm"),       // 304
+    FILE_PATH_LITERAL(".dht"),         FILE_PATH_LITERAL(".shtml"),      // 306
+    FILE_PATH_LITERAL(".shtm"),        FILE_PATH_LITERAL(".sht"),        // 308
+    // NOTE! When you add a type here, please add the UMA value as a comment.
+    // These must all match DownloadItem.DangerousFileType in enums.xml.
+    // From 263 onward, they should also match SBClientDownloadExtensions.
 };
 
 // The maximum size in KB for the file size metric, file size larger than this
diff --git a/content/browser/fileapi/upload_file_system_file_element_reader.cc b/content/browser/fileapi/upload_file_system_file_element_reader.cc
deleted file mode 100644
index 1951b94..0000000
--- a/content/browser/fileapi/upload_file_system_file_element_reader.cc
+++ /dev/null
@@ -1,118 +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/fileapi/upload_file_system_file_element_reader.h"
-
-#include <algorithm>
-#include <limits>
-
-#include "base/bind.h"
-#include "base/numerics/safe_conversions.h"
-#include "net/base/net_errors.h"
-#include "storage/browser/fileapi/file_stream_reader.h"
-#include "storage/browser/fileapi/file_system_context.h"
-#include "storage/browser/fileapi/file_system_url.h"
-
-namespace content {
-
-UploadFileSystemFileElementReader::UploadFileSystemFileElementReader(
-    storage::FileSystemContext* file_system_context,
-    const GURL& url,
-    uint64_t range_offset,
-    uint64_t range_length,
-    const base::Time& expected_modification_time)
-    : file_system_context_(file_system_context),
-      url_(url),
-      range_offset_(range_offset),
-      range_length_(range_length),
-      expected_modification_time_(expected_modification_time),
-      stream_length_(0),
-      position_(0),
-      weak_ptr_factory_(this) {}
-
-UploadFileSystemFileElementReader::~UploadFileSystemFileElementReader() {
-}
-
-int UploadFileSystemFileElementReader::Init(
-    const net::CompletionCallback& callback) {
-  // Reset states.
-  weak_ptr_factory_.InvalidateWeakPtrs();
-  stream_length_ = 0;
-  position_ = 0;
-
-  // Initialize the stream reader and the length.
-  stream_reader_ = file_system_context_->CreateFileStreamReader(
-      file_system_context_->CrackURL(url_), range_offset_,
-      range_length_ == std::numeric_limits<uint64_t>::max()
-          ? storage::kMaximumLength
-          : base::checked_cast<int64_t>(range_length_),
-      expected_modification_time_);
-  DCHECK(stream_reader_);
-
-  const int64_t result = stream_reader_->GetLength(
-      base::Bind(&UploadFileSystemFileElementReader::OnGetLength,
-                 weak_ptr_factory_.GetWeakPtr(), callback));
-  if (result >= 0) {
-    stream_length_ = result;
-    return net::OK;
-  }
-
-  // The error code can be casted to int.
-  return static_cast<int>(result);
-}
-
-uint64_t UploadFileSystemFileElementReader::GetContentLength() const {
-  return std::min(stream_length_, range_length_);
-}
-
-uint64_t UploadFileSystemFileElementReader::BytesRemaining() const {
-  return GetContentLength() - position_;
-}
-
-int UploadFileSystemFileElementReader::Read(
-    net::IOBuffer* buf,
-    int buf_length,
-    const net::CompletionCallback& callback) {
-  DCHECK_LT(0, buf_length);
-  DCHECK(stream_reader_);
-
-  const uint64_t num_bytes_to_read =
-      std::min(BytesRemaining(), static_cast<uint64_t>(buf_length));
-
-  if (num_bytes_to_read == 0)
-    return 0;
-
-  const int result = stream_reader_->Read(
-      buf, num_bytes_to_read,
-      base::Bind(&UploadFileSystemFileElementReader::OnRead,
-                 weak_ptr_factory_.GetWeakPtr(),
-                 callback));
-  if (result >= 0)
-    OnRead(net::CompletionCallback(), result);
-  return result;
-}
-
-void UploadFileSystemFileElementReader::OnGetLength(
-    const net::CompletionCallback& callback,
-    int64_t result) {
-  if (result >= 0) {
-    stream_length_ = result;
-    callback.Run(net::OK);
-    return;
-  }
-  callback.Run(result);
-}
-
-void UploadFileSystemFileElementReader::OnRead(
-    const net::CompletionCallback& callback,
-    int result) {
-  if (result > 0) {
-    position_ += result;
-    DCHECK_LE(position_, GetContentLength());
-  }
-  if (!callback.is_null())
-    callback.Run(result);
-}
-
-}  // namespace content
diff --git a/content/browser/fileapi/upload_file_system_file_element_reader.h b/content/browser/fileapi/upload_file_system_file_element_reader.h
deleted file mode 100644
index be6e313..0000000
--- a/content/browser/fileapi/upload_file_system_file_element_reader.h
+++ /dev/null
@@ -1,71 +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_FILEAPI_UPLOAD_FILE_SYSTEM_FILE_ELEMENT_READER_H_
-#define CONTENT_BROWSER_FILEAPI_UPLOAD_FILE_SYSTEM_FILE_ELEMENT_READER_H_
-
-#include <stdint.h>
-
-#include <memory>
-
-#include "base/macros.h"
-#include "base/memory/weak_ptr.h"
-#include "base/time/time.h"
-#include "content/common/content_export.h"
-#include "net/base/upload_element_reader.h"
-#include "url/gurl.h"
-
-namespace storage {
-class FileStreamReader;
-}
-
-namespace storage {
-class FileSystemContext;
-}
-
-namespace content {
-
-// An UploadElementReader implementation for filesystem file.
-class CONTENT_EXPORT UploadFileSystemFileElementReader
-    : public net::UploadElementReader {
- public:
-  UploadFileSystemFileElementReader(
-      storage::FileSystemContext* file_system_context,
-      const GURL& url,
-      uint64_t range_offset,
-      uint64_t range_length,
-      const base::Time& expected_modification_time);
-  ~UploadFileSystemFileElementReader() override;
-
-  // UploadElementReader overrides:
-  int Init(const net::CompletionCallback& callback) override;
-  uint64_t GetContentLength() const override;
-  uint64_t BytesRemaining() const override;
-  int Read(net::IOBuffer* buf,
-           int buf_length,
-           const net::CompletionCallback& callback) override;
-
- private:
-  void OnGetLength(const net::CompletionCallback& callback, int64_t result);
-  void OnRead(const net::CompletionCallback& callback, int result);
-
-  scoped_refptr<storage::FileSystemContext> file_system_context_;
-  const GURL url_;
-  const uint64_t range_offset_;
-  const uint64_t range_length_;
-  const base::Time expected_modification_time_;
-
-  std::unique_ptr<storage::FileStreamReader> stream_reader_;
-
-  uint64_t stream_length_;
-  uint64_t position_;
-
-  base::WeakPtrFactory<UploadFileSystemFileElementReader> weak_ptr_factory_;
-
-  DISALLOW_COPY_AND_ASSIGN(UploadFileSystemFileElementReader);
-};
-
-}  // namespace content
-
-#endif  // CONTENT_BROWSER_FILEAPI_UPLOAD_FILE_SYSTEM_FILE_ELEMENT_READER_H_
diff --git a/content/browser/fileapi/upload_file_system_file_element_reader_unittest.cc b/content/browser/fileapi/upload_file_system_file_element_reader_unittest.cc
deleted file mode 100644
index d248c03..0000000
--- a/content/browser/fileapi/upload_file_system_file_element_reader_unittest.cc
+++ /dev/null
@@ -1,283 +0,0 @@
-// 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.
-
-#include "content/browser/fileapi/upload_file_system_file_element_reader.h"
-
-#include <stddef.h>
-#include <stdint.h>
-
-#include <limits>
-
-#include "base/files/scoped_temp_dir.h"
-#include "base/macros.h"
-#include "base/message_loop/message_loop.h"
-#include "base/run_loop.h"
-#include "net/base/io_buffer.h"
-#include "net/base/test_completion_callback.h"
-#include "storage/browser/fileapi/file_system_backend.h"
-#include "storage/browser/fileapi/file_system_context.h"
-#include "storage/browser/fileapi/file_system_operation_context.h"
-#include "storage/browser/fileapi/file_system_url.h"
-#include "storage/browser/test/async_file_test_helper.h"
-#include "storage/browser/test/test_file_system_context.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-using content::AsyncFileTestHelper;
-using storage::FileSystemContext;
-using storage::FileSystemType;
-using storage::FileSystemURL;
-
-namespace content {
-
-namespace {
-
-const char kFileSystemURLOrigin[] = "http://remote";
-const storage::FileSystemType kFileSystemType =
-    storage::kFileSystemTypeTemporary;
-
-}  // namespace
-
-class UploadFileSystemFileElementReaderTest : public testing::Test {
- public:
-  UploadFileSystemFileElementReaderTest() {}
-
-  void SetUp() override {
-    ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());
-
-    file_system_context_ =
-        CreateFileSystemContextForTesting(NULL, temp_dir_.GetPath());
-
-    file_system_context_->OpenFileSystem(
-        GURL(kFileSystemURLOrigin), kFileSystemType,
-        storage::OPEN_FILE_SYSTEM_CREATE_IF_NONEXISTENT,
-        base::BindOnce(&UploadFileSystemFileElementReaderTest::OnOpenFileSystem,
-                       base::Unretained(this)));
-    base::RunLoop().RunUntilIdle();
-    ASSERT_TRUE(file_system_root_url_.is_valid());
-
-    // Prepare a file on file system.
-    const char kTestData[] = "abcdefghijklmnop0123456789";
-    file_data_.assign(kTestData, kTestData + arraysize(kTestData) - 1);
-    const char kFilename[] = "File.dat";
-    file_url_ = GetFileSystemURL(kFilename);
-    WriteFileSystemFile(kFilename, &file_data_[0], file_data_.size(),
-                        &file_modification_time_);
-
-    // Create and initialize a reader.
-    reader_.reset(new UploadFileSystemFileElementReader(
-        file_system_context_.get(), file_url_, 0,
-        std::numeric_limits<uint64_t>::max(), file_modification_time_));
-    net::TestCompletionCallback callback;
-    ASSERT_EQ(net::ERR_IO_PENDING, reader_->Init(callback.callback()));
-    EXPECT_EQ(net::OK, callback.WaitForResult());
-    EXPECT_EQ(file_data_.size(), reader_->GetContentLength());
-    EXPECT_EQ(file_data_.size(), reader_->BytesRemaining());
-    EXPECT_FALSE(reader_->IsInMemory());
-  }
-
-  void TearDown() override {
-    reader_.reset();
-    base::RunLoop().RunUntilIdle();
- }
-
- protected:
-  GURL GetFileSystemURL(const std::string& filename) {
-    return GURL(file_system_root_url_.spec() + filename);
-  }
-
-  void WriteFileSystemFile(const std::string& filename,
-                           const char* buf,
-                           int buf_size,
-                           base::Time* modification_time) {
-    storage::FileSystemURL url =
-        file_system_context_->CreateCrackedFileSystemURL(
-            GURL(kFileSystemURLOrigin),
-            kFileSystemType,
-            base::FilePath().AppendASCII(filename));
-
-    ASSERT_EQ(base::File::FILE_OK,
-              AsyncFileTestHelper::CreateFileWithData(
-                  file_system_context_.get(), url, buf, buf_size));
-
-    base::File::Info file_info;
-    ASSERT_EQ(base::File::FILE_OK,
-              AsyncFileTestHelper::GetMetadata(
-                  file_system_context_.get(), url, &file_info));
-    *modification_time = file_info.last_modified;
-  }
-
-  void OnOpenFileSystem(const GURL& root,
-                        const std::string& name,
-                        base::File::Error result) {
-    ASSERT_EQ(base::File::FILE_OK, result);
-    ASSERT_TRUE(root.is_valid());
-    file_system_root_url_ = root;
-  }
-
-  base::MessageLoopForIO message_loop_;
-  base::ScopedTempDir temp_dir_;
-  scoped_refptr<FileSystemContext> file_system_context_;
-  GURL file_system_root_url_;
-  std::vector<char> file_data_;
-  GURL file_url_;
-  base::Time file_modification_time_;
-  std::unique_ptr<UploadFileSystemFileElementReader> reader_;
-};
-
-TEST_F(UploadFileSystemFileElementReaderTest, ReadAll) {
-  scoped_refptr<net::IOBufferWithSize> buf =
-      new net::IOBufferWithSize(file_data_.size());
-  net::TestCompletionCallback read_callback;
-  ASSERT_EQ(net::ERR_IO_PENDING,
-            reader_->Read(buf.get(), buf->size(), read_callback.callback()));
-  EXPECT_EQ(buf->size(), read_callback.WaitForResult());
-  EXPECT_EQ(0U, reader_->BytesRemaining());
-  EXPECT_TRUE(std::equal(file_data_.begin(), file_data_.end(), buf->data()));
-  // Try to read again.
-  EXPECT_EQ(0, reader_->Read(buf.get(), buf->size(), read_callback.callback()));
-}
-
-TEST_F(UploadFileSystemFileElementReaderTest, ReadPartially) {
-  const size_t kHalfSize = file_data_.size() / 2;
-  ASSERT_EQ(file_data_.size(), kHalfSize * 2);
-
-  scoped_refptr<net::IOBufferWithSize> buf =
-      new net::IOBufferWithSize(kHalfSize);
-
-  net::TestCompletionCallback read_callback1;
-  ASSERT_EQ(net::ERR_IO_PENDING,
-            reader_->Read(buf.get(), buf->size(), read_callback1.callback()));
-  EXPECT_EQ(buf->size(), read_callback1.WaitForResult());
-  EXPECT_EQ(file_data_.size() - buf->size(), reader_->BytesRemaining());
-  EXPECT_TRUE(std::equal(file_data_.begin(), file_data_.begin() + kHalfSize,
-                         buf->data()));
-
-  net::TestCompletionCallback read_callback2;
-  EXPECT_EQ(net::ERR_IO_PENDING,
-            reader_->Read(buf.get(), buf->size(), read_callback2.callback()));
-  EXPECT_EQ(buf->size(), read_callback2.WaitForResult());
-  EXPECT_EQ(0U, reader_->BytesRemaining());
-  EXPECT_TRUE(std::equal(file_data_.begin() + kHalfSize, file_data_.end(),
-                         buf->data()));
-}
-
-TEST_F(UploadFileSystemFileElementReaderTest, ReadTooMuch) {
-  const size_t kTooLargeSize = file_data_.size() * 2;
-  scoped_refptr<net::IOBufferWithSize> buf =
-      new net::IOBufferWithSize(kTooLargeSize);
-  net::TestCompletionCallback read_callback;
-  ASSERT_EQ(net::ERR_IO_PENDING,
-            reader_->Read(buf.get(), buf->size(), read_callback.callback()));
-  EXPECT_EQ(static_cast<int>(file_data_.size()), read_callback.WaitForResult());
-  EXPECT_EQ(0U, reader_->BytesRemaining());
-  EXPECT_TRUE(std::equal(file_data_.begin(), file_data_.end(), buf->data()));
-}
-
-TEST_F(UploadFileSystemFileElementReaderTest, MultipleInit) {
-  scoped_refptr<net::IOBufferWithSize> buf =
-      new net::IOBufferWithSize(file_data_.size());
-
-  // Read all.
-  net::TestCompletionCallback read_callback1;
-  ASSERT_EQ(net::ERR_IO_PENDING,
-            reader_->Read(buf.get(), buf->size(), read_callback1.callback()));
-  EXPECT_EQ(buf->size(), read_callback1.WaitForResult());
-  EXPECT_EQ(0U, reader_->BytesRemaining());
-  EXPECT_TRUE(std::equal(file_data_.begin(), file_data_.end(), buf->data()));
-
-  // Call Init() again to reset the state.
-  net::TestCompletionCallback init_callback;
-  ASSERT_EQ(net::ERR_IO_PENDING, reader_->Init(init_callback.callback()));
-  EXPECT_EQ(net::OK, init_callback.WaitForResult());
-  EXPECT_EQ(file_data_.size(), reader_->GetContentLength());
-  EXPECT_EQ(file_data_.size(), reader_->BytesRemaining());
-
-  // Read again.
-  net::TestCompletionCallback read_callback2;
-  ASSERT_EQ(net::ERR_IO_PENDING,
-            reader_->Read(buf.get(), buf->size(), read_callback2.callback()));
-  EXPECT_EQ(buf->size(), read_callback2.WaitForResult());
-  EXPECT_EQ(0U, reader_->BytesRemaining());
-  EXPECT_TRUE(std::equal(file_data_.begin(), file_data_.end(), buf->data()));
-}
-
-TEST_F(UploadFileSystemFileElementReaderTest, InitDuringAsyncOperation) {
-  scoped_refptr<net::IOBufferWithSize> buf =
-      new net::IOBufferWithSize(file_data_.size());
-
-  // Start reading all.
-  net::TestCompletionCallback read_callback1;
-  EXPECT_EQ(net::ERR_IO_PENDING,
-            reader_->Read(buf.get(), buf->size(), read_callback1.callback()));
-
-  // Call Init to cancel the previous read.
-  net::TestCompletionCallback init_callback1;
-  EXPECT_EQ(net::ERR_IO_PENDING, reader_->Init(init_callback1.callback()));
-
-  // Call Init again to cancel the previous init.
-  net::TestCompletionCallback init_callback2;
-  EXPECT_EQ(net::ERR_IO_PENDING, reader_->Init(init_callback2.callback()));
-  EXPECT_EQ(net::OK, init_callback2.WaitForResult());
-  EXPECT_EQ(file_data_.size(), reader_->GetContentLength());
-  EXPECT_EQ(file_data_.size(), reader_->BytesRemaining());
-
-  // Read half.
-  scoped_refptr<net::IOBufferWithSize> buf2 =
-      new net::IOBufferWithSize(file_data_.size() / 2);
-  net::TestCompletionCallback read_callback2;
-  EXPECT_EQ(net::ERR_IO_PENDING,
-            reader_->Read(buf2.get(), buf2->size(), read_callback2.callback()));
-  EXPECT_EQ(buf2->size(), read_callback2.WaitForResult());
-  EXPECT_EQ(file_data_.size() - buf2->size(), reader_->BytesRemaining());
-  EXPECT_TRUE(std::equal(file_data_.begin(), file_data_.begin() + buf2->size(),
-                         buf2->data()));
-
-  // Make sure callbacks are not called for cancelled operations.
-  EXPECT_FALSE(read_callback1.have_result());
-  EXPECT_FALSE(init_callback1.have_result());
-}
-
-TEST_F(UploadFileSystemFileElementReaderTest, Range) {
-  const int kOffset = 2;
-  const int kLength = file_data_.size() - kOffset * 3;
-  reader_.reset(new UploadFileSystemFileElementReader(
-      file_system_context_.get(), file_url_, kOffset, kLength, base::Time()));
-  net::TestCompletionCallback init_callback;
-  ASSERT_EQ(net::ERR_IO_PENDING, reader_->Init(init_callback.callback()));
-  EXPECT_EQ(net::OK, init_callback.WaitForResult());
-  EXPECT_EQ(static_cast<uint64_t>(kLength), reader_->GetContentLength());
-  EXPECT_EQ(static_cast<uint64_t>(kLength), reader_->BytesRemaining());
-  scoped_refptr<net::IOBufferWithSize> buf = new net::IOBufferWithSize(kLength);
-  net::TestCompletionCallback read_callback;
-  ASSERT_EQ(net::ERR_IO_PENDING,
-            reader_->Read(buf.get(), buf->size(), read_callback.callback()));
-  EXPECT_EQ(kLength, read_callback.WaitForResult());
-  EXPECT_TRUE(std::equal(file_data_.begin() + kOffset,
-                         file_data_.begin() + kOffset + kLength,
-                         buf->data()));
-}
-
-TEST_F(UploadFileSystemFileElementReaderTest, FileChanged) {
-  // Expect one second before the actual modification time to simulate change.
-  const base::Time expected_modification_time =
-      file_modification_time_ - base::TimeDelta::FromSeconds(1);
-  reader_.reset(new UploadFileSystemFileElementReader(
-      file_system_context_.get(), file_url_, 0,
-      std::numeric_limits<uint64_t>::max(), expected_modification_time));
-  net::TestCompletionCallback init_callback;
-  ASSERT_EQ(net::ERR_IO_PENDING, reader_->Init(init_callback.callback()));
-  EXPECT_EQ(net::ERR_UPLOAD_FILE_CHANGED, init_callback.WaitForResult());
-}
-
-TEST_F(UploadFileSystemFileElementReaderTest, WrongURL) {
-  const GURL wrong_url = GetFileSystemURL("wrong_file_name.dat");
-  reader_.reset(new UploadFileSystemFileElementReader(
-      file_system_context_.get(), wrong_url, 0,
-      std::numeric_limits<uint64_t>::max(), base::Time()));
-  net::TestCompletionCallback init_callback;
-  ASSERT_EQ(net::ERR_IO_PENDING, reader_->Init(init_callback.callback()));
-  EXPECT_EQ(net::ERR_FILE_NOT_FOUND, init_callback.WaitForResult());
-}
-
-}  // namespace content
diff --git a/content/browser/frame_host/frame_tree.cc b/content/browser/frame_host/frame_tree.cc
index 55c3e9e7..cec7510 100644
--- a/content/browser/frame_host/frame_tree.cc
+++ b/content/browser/frame_host/frame_tree.cc
@@ -171,15 +171,17 @@
   return NodeRange(root_, node);
 }
 
-bool FrameTree::AddFrame(FrameTreeNode* parent,
-                         int process_id,
-                         int new_routing_id,
-                         blink::WebTreeScopeType scope,
-                         const std::string& frame_name,
-                         const std::string& frame_unique_name,
-                         const base::UnguessableToken& devtools_frame_token,
-                         const FramePolicy& frame_policy,
-                         const FrameOwnerProperties& frame_owner_properties) {
+bool FrameTree::AddFrame(
+    FrameTreeNode* parent,
+    int process_id,
+    int new_routing_id,
+    service_manager::mojom::InterfaceProviderRequest interface_provider_request,
+    blink::WebTreeScopeType scope,
+    const std::string& frame_name,
+    const std::string& frame_unique_name,
+    const base::UnguessableToken& devtools_frame_token,
+    const FramePolicy& frame_policy,
+    const FrameOwnerProperties& frame_owner_properties) {
   CHECK_NE(new_routing_id, MSG_ROUTING_NONE);
 
   // A child frame always starts with an initial empty document, which means
@@ -206,6 +208,10 @@
   FrameTreeNode* added_node =
       parent->AddChild(std::move(new_node), process_id, new_routing_id);
 
+  DCHECK(interface_provider_request.is_pending());
+  added_node->current_frame_host()->BindInterfaceProviderRequest(
+      std::move(interface_provider_request));
+
   // The last committed NavigationEntry may have a FrameNavigationEntry with the
   // same |frame_unique_name|, since we don't remove FrameNavigationEntries if
   // their frames are deleted.  If there is a stale one, remove it to avoid
diff --git a/content/browser/frame_host/frame_tree.h b/content/browser/frame_host/frame_tree.h
index f3915e3..36ec863 100644
--- a/content/browser/frame_host/frame_tree.h
+++ b/content/browser/frame_host/frame_tree.h
@@ -17,6 +17,7 @@
 #include "base/macros.h"
 #include "content/browser/frame_host/frame_tree_node.h"
 #include "content/common/content_export.h"
+#include "services/service_manager/public/interfaces/interface_provider.mojom.h"
 
 namespace content {
 
@@ -122,9 +123,15 @@
   // Adds a new child frame to the frame tree. |process_id| is required to
   // disambiguate |new_routing_id|, and it must match the process of the
   // |parent| node. Otherwise no child is added and this method returns false.
+  // |interface_provider_request| is the request end of the InterfaceProvider
+  // interface through which the child RenderFrame can access Mojo services
+  // exposed by the corresponding RenderFrameHost. The caller takes care of
+  // sending the client end of the interface down to the RenderFrame.
   bool AddFrame(FrameTreeNode* parent,
                 int process_id,
                 int new_routing_id,
+                service_manager::mojom::InterfaceProviderRequest
+                    interface_provider_request,
                 blink::WebTreeScopeType scope,
                 const std::string& frame_name,
                 const std::string& frame_unique_name,
diff --git a/content/browser/frame_host/frame_tree_node_blame_context_unittest.cc b/content/browser/frame_host/frame_tree_node_blame_context_unittest.cc
index 47db159..2e731ab 100644
--- a/content/browser/frame_host/frame_tree_node_blame_context_unittest.cc
+++ b/content/browser/frame_host/frame_tree_node_blame_context_unittest.cc
@@ -131,11 +131,13 @@
     int consumption = 0;
     for (int child_num = 1; shape[consumption++] == '('; ++child_num) {
       int child_id = self_id * 10 + child_num;
-      tree()->AddFrame(node, process_id(), child_id,
-                       blink::WebTreeScopeType::kDocument, std::string(),
-                       base::StringPrintf("uniqueName%d", child_id),
-                       base::UnguessableToken::Create(), FramePolicy(),
-                       FrameOwnerProperties());
+      tree()->AddFrame(
+          node, process_id(), child_id,
+          TestRenderFrameHost::CreateStubInterfaceProviderRequest(),
+          blink::WebTreeScopeType::kDocument, std::string(),
+          base::StringPrintf("uniqueName%d", child_id),
+          base::UnguessableToken::Create(), FramePolicy(),
+          FrameOwnerProperties());
       FrameTreeNode* child = node->child_at(child_num - 1);
       consumption += CreateSubframes(child, child_id, shape + consumption);
     }
diff --git a/content/browser/frame_host/frame_tree_unittest.cc b/content/browser/frame_host/frame_tree_unittest.cc
index dea82c6..7d885eab 100644
--- a/content/browser/frame_host/frame_tree_unittest.cc
+++ b/content/browser/frame_host/frame_tree_unittest.cc
@@ -52,6 +52,11 @@
   result->append("]");
 }
 
+service_manager::mojom::InterfaceProviderRequest
+CreateStubInterfaceProviderRequest() {
+  return TestRenderFrameHost::CreateStubInterfaceProviderRequest();
+}
+
 // Logs calls to WebContentsObserver along with the state of the frame tree,
 // for later use in EXPECT_EQ().
 class TreeWalkingWebContentsLogger : public WebContentsObserver {
@@ -157,30 +162,30 @@
   EXPECT_EQ("2: []", GetTreeState(frame_tree));
 
   // Simulate attaching a series of frames to build the frame tree.
-  frame_tree->AddFrame(root, process_id, 14, blink::WebTreeScopeType::kDocument,
-                       std::string(), "uniqueName0",
-                       base::UnguessableToken::Create(), FramePolicy(),
-                       FrameOwnerProperties());
-  frame_tree->AddFrame(root, process_id, 15, blink::WebTreeScopeType::kDocument,
-                       std::string(), "uniqueName1",
-                       base::UnguessableToken::Create(), FramePolicy(),
-                       FrameOwnerProperties());
-  frame_tree->AddFrame(root, process_id, 16, blink::WebTreeScopeType::kDocument,
-                       std::string(), "uniqueName2",
-                       base::UnguessableToken::Create(), FramePolicy(),
-                       FrameOwnerProperties());
-  frame_tree->AddFrame(root->child_at(0), process_id, 244,
-                       blink::WebTreeScopeType::kDocument, std::string(),
-                       "uniqueName3", base::UnguessableToken::Create(),
-                       FramePolicy(), FrameOwnerProperties());
-  frame_tree->AddFrame(root->child_at(1), process_id, 255,
-                       blink::WebTreeScopeType::kDocument, no_children_node,
-                       "uniqueName4", base::UnguessableToken::Create(),
-                       FramePolicy(), FrameOwnerProperties());
-  frame_tree->AddFrame(root->child_at(0), process_id, 245,
-                       blink::WebTreeScopeType::kDocument, std::string(),
-                       "uniqueName5", base::UnguessableToken::Create(),
-                       FramePolicy(), FrameOwnerProperties());
+  frame_tree->AddFrame(
+      root, process_id, 14, CreateStubInterfaceProviderRequest(),
+      blink::WebTreeScopeType::kDocument, std::string(), "uniqueName0",
+      base::UnguessableToken::Create(), FramePolicy(), FrameOwnerProperties());
+  frame_tree->AddFrame(
+      root, process_id, 15, CreateStubInterfaceProviderRequest(),
+      blink::WebTreeScopeType::kDocument, std::string(), "uniqueName1",
+      base::UnguessableToken::Create(), FramePolicy(), FrameOwnerProperties());
+  frame_tree->AddFrame(
+      root, process_id, 16, CreateStubInterfaceProviderRequest(),
+      blink::WebTreeScopeType::kDocument, std::string(), "uniqueName2",
+      base::UnguessableToken::Create(), FramePolicy(), FrameOwnerProperties());
+  frame_tree->AddFrame(
+      root->child_at(0), process_id, 244, CreateStubInterfaceProviderRequest(),
+      blink::WebTreeScopeType::kDocument, std::string(), "uniqueName3",
+      base::UnguessableToken::Create(), FramePolicy(), FrameOwnerProperties());
+  frame_tree->AddFrame(
+      root->child_at(1), process_id, 255, CreateStubInterfaceProviderRequest(),
+      blink::WebTreeScopeType::kDocument, no_children_node, "uniqueName4",
+      base::UnguessableToken::Create(), FramePolicy(), FrameOwnerProperties());
+  frame_tree->AddFrame(
+      root->child_at(0), process_id, 245, CreateStubInterfaceProviderRequest(),
+      blink::WebTreeScopeType::kDocument, std::string(), "uniqueName5",
+      base::UnguessableToken::Create(), FramePolicy(), FrameOwnerProperties());
 
   EXPECT_EQ(
       "2: [14: [244: [], 245: []], "
@@ -189,44 +194,47 @@
       GetTreeState(frame_tree));
 
   FrameTreeNode* child_16 = root->child_at(2);
-  frame_tree->AddFrame(child_16, process_id, 264,
-                       blink::WebTreeScopeType::kDocument, std::string(),
-                       "uniqueName6", base::UnguessableToken::Create(),
-                       FramePolicy(), FrameOwnerProperties());
-  frame_tree->AddFrame(child_16, process_id, 265,
-                       blink::WebTreeScopeType::kDocument, std::string(),
-                       "uniqueName7", base::UnguessableToken::Create(),
-                       FramePolicy(), FrameOwnerProperties());
-  frame_tree->AddFrame(child_16, process_id, 266,
-                       blink::WebTreeScopeType::kDocument, std::string(),
-                       "uniqueName8", base::UnguessableToken::Create(),
-                       FramePolicy(), FrameOwnerProperties());
-  frame_tree->AddFrame(child_16, process_id, 267,
-                       blink::WebTreeScopeType::kDocument, deep_subtree,
-                       "uniqueName9", base::UnguessableToken::Create(),
-                       FramePolicy(), FrameOwnerProperties());
-  frame_tree->AddFrame(child_16, process_id, 268,
-                       blink::WebTreeScopeType::kDocument, std::string(),
-                       "uniqueName10", base::UnguessableToken::Create(),
-                       FramePolicy(), FrameOwnerProperties());
+  frame_tree->AddFrame(
+      child_16, process_id, 264, CreateStubInterfaceProviderRequest(),
+      blink::WebTreeScopeType::kDocument, std::string(), "uniqueName6",
+      base::UnguessableToken::Create(), FramePolicy(), FrameOwnerProperties());
+  frame_tree->AddFrame(
+      child_16, process_id, 265, CreateStubInterfaceProviderRequest(),
+      blink::WebTreeScopeType::kDocument, std::string(), "uniqueName7",
+      base::UnguessableToken::Create(), FramePolicy(), FrameOwnerProperties());
+  frame_tree->AddFrame(
+      child_16, process_id, 266, CreateStubInterfaceProviderRequest(),
+      blink::WebTreeScopeType::kDocument, std::string(), "uniqueName8",
+      base::UnguessableToken::Create(), FramePolicy(), FrameOwnerProperties());
+  frame_tree->AddFrame(
+      child_16, process_id, 267, CreateStubInterfaceProviderRequest(),
+      blink::WebTreeScopeType::kDocument, deep_subtree, "uniqueName9",
+      base::UnguessableToken::Create(), FramePolicy(), FrameOwnerProperties());
+  frame_tree->AddFrame(
+      child_16, process_id, 268, CreateStubInterfaceProviderRequest(),
+      blink::WebTreeScopeType::kDocument, std::string(), "uniqueName10",
+      base::UnguessableToken::Create(), FramePolicy(), FrameOwnerProperties());
 
   FrameTreeNode* child_267 = child_16->child_at(3);
-  frame_tree->AddFrame(child_267, process_id, 365,
-                       blink::WebTreeScopeType::kDocument, std::string(),
-                       "uniqueName11", base::UnguessableToken::Create(),
-                       FramePolicy(), FrameOwnerProperties());
+  frame_tree->AddFrame(
+      child_267, process_id, 365, CreateStubInterfaceProviderRequest(),
+      blink::WebTreeScopeType::kDocument, std::string(), "uniqueName11",
+      base::UnguessableToken::Create(), FramePolicy(), FrameOwnerProperties());
   frame_tree->AddFrame(child_267->child_at(0), process_id, 455,
+                       CreateStubInterfaceProviderRequest(),
                        blink::WebTreeScopeType::kDocument, std::string(),
                        "uniqueName12", base::UnguessableToken::Create(),
                        FramePolicy(), FrameOwnerProperties());
   frame_tree->AddFrame(child_267->child_at(0)->child_at(0), process_id, 555,
+                       CreateStubInterfaceProviderRequest(),
                        blink::WebTreeScopeType::kDocument, std::string(),
                        "uniqueName13", base::UnguessableToken::Create(),
                        FramePolicy(), FrameOwnerProperties());
-  frame_tree->AddFrame(
-      child_267->child_at(0)->child_at(0)->child_at(0), process_id, 655,
-      blink::WebTreeScopeType::kDocument, std::string(), "uniqueName14",
-      base::UnguessableToken::Create(), FramePolicy(), FrameOwnerProperties());
+  frame_tree->AddFrame(child_267->child_at(0)->child_at(0)->child_at(0),
+                       process_id, 655, CreateStubInterfaceProviderRequest(),
+                       blink::WebTreeScopeType::kDocument, std::string(),
+                       "uniqueName14", base::UnguessableToken::Create(),
+                       FramePolicy(), FrameOwnerProperties());
 
   // Now that's it's fully built, verify the tree structure is as expected.
   EXPECT_EQ(
@@ -298,13 +306,16 @@
   FrameTreeNode* root = frame_tree->root();
 
   main_test_rfh()->OnCreateChildFrame(
-      22, blink::WebTreeScopeType::kDocument, "child0", "uniqueName0",
+      22, CreateStubInterfaceProviderRequest(),
+      blink::WebTreeScopeType::kDocument, "child0", "uniqueName0",
       base::UnguessableToken::Create(), FramePolicy(), FrameOwnerProperties());
   main_test_rfh()->OnCreateChildFrame(
-      23, blink::WebTreeScopeType::kDocument, "child1", "uniqueName1",
+      23, CreateStubInterfaceProviderRequest(),
+      blink::WebTreeScopeType::kDocument, "child1", "uniqueName1",
       base::UnguessableToken::Create(), FramePolicy(), FrameOwnerProperties());
   main_test_rfh()->OnCreateChildFrame(
-      24, blink::WebTreeScopeType::kDocument, std::string(), "uniqueName2",
+      24, CreateStubInterfaceProviderRequest(),
+      blink::WebTreeScopeType::kDocument, std::string(), "uniqueName2",
       base::UnguessableToken::Create(), FramePolicy(), FrameOwnerProperties());
   FrameTreeNode* child0 = root->child_at(0);
   FrameTreeNode* child1 = root->child_at(1);
@@ -312,7 +323,8 @@
 
   // Add one grandchild frame.
   child1->current_frame_host()->OnCreateChildFrame(
-      33, blink::WebTreeScopeType::kDocument, "grandchild", "uniqueName3",
+      33, CreateStubInterfaceProviderRequest(),
+      blink::WebTreeScopeType::kDocument, "grandchild", "uniqueName3",
       base::UnguessableToken::Create(), FramePolicy(), FrameOwnerProperties());
   FrameTreeNode* grandchild = child1->child_at(0);
 
@@ -350,13 +362,16 @@
   FrameTree* frame_tree = contents()->GetFrameTree();
   FrameTreeNode* root = frame_tree->root();
   main_test_rfh()->OnCreateChildFrame(
-      22, blink::WebTreeScopeType::kDocument, "child0", "uniqueName0",
+      22, CreateStubInterfaceProviderRequest(),
+      blink::WebTreeScopeType::kDocument, "child0", "uniqueName0",
       base::UnguessableToken::Create(), FramePolicy(), FrameOwnerProperties());
   main_test_rfh()->OnCreateChildFrame(
-      23, blink::WebTreeScopeType::kDocument, "child1", "uniqueName1",
+      23, CreateStubInterfaceProviderRequest(),
+      blink::WebTreeScopeType::kDocument, "child1", "uniqueName1",
       base::UnguessableToken::Create(), FramePolicy(), FrameOwnerProperties());
   main_test_rfh()->OnCreateChildFrame(
-      24, blink::WebTreeScopeType::kDocument, "child2", "uniqueName2",
+      24, CreateStubInterfaceProviderRequest(),
+      blink::WebTreeScopeType::kDocument, "child2", "uniqueName2",
       base::UnguessableToken::Create(), FramePolicy(), FrameOwnerProperties());
   FrameTreeNode* child0 = root->child_at(0);
   FrameTreeNode* child1 = root->child_at(1);
@@ -364,7 +379,8 @@
 
   // Add one grandchild frame.
   child1->current_frame_host()->OnCreateChildFrame(
-      33, blink::WebTreeScopeType::kDocument, "grandchild", "uniqueName3",
+      33, CreateStubInterfaceProviderRequest(),
+      blink::WebTreeScopeType::kDocument, "grandchild", "uniqueName3",
       base::UnguessableToken::Create(), FramePolicy(), FrameOwnerProperties());
   FrameTreeNode* grandchild = child1->child_at(0);
 
@@ -395,14 +411,16 @@
 
   // Simulate attaching a series of frames to build the frame tree.
   main_test_rfh()->OnCreateChildFrame(
-      14, blink::WebTreeScopeType::kDocument, std::string(), "uniqueName0",
+      14, CreateStubInterfaceProviderRequest(),
+      blink::WebTreeScopeType::kDocument, std::string(), "uniqueName0",
       base::UnguessableToken::Create(), FramePolicy(), FrameOwnerProperties());
   EXPECT_EQ(
       "RenderFrameHostChanged(new)(14) -> 2: []\n"
       "RenderFrameCreated(14) -> 2: [14: []]",
       activity.GetLog());
   main_test_rfh()->OnCreateChildFrame(
-      18, blink::WebTreeScopeType::kDocument, std::string(), "uniqueName1",
+      18, CreateStubInterfaceProviderRequest(),
+      blink::WebTreeScopeType::kDocument, std::string(), "uniqueName1",
       base::UnguessableToken::Create(), FramePolicy(), FrameOwnerProperties());
   EXPECT_EQ(
       "RenderFrameHostChanged(new)(18) -> 2: [14: []]\n"
@@ -422,14 +440,16 @@
   EXPECT_EQ("RenderFrameCreated(2) -> 2: []", activity.GetLog());
 
   main_test_rfh()->OnCreateChildFrame(
-      22, blink::WebTreeScopeType::kDocument, std::string(), "uniqueName0",
+      22, CreateStubInterfaceProviderRequest(),
+      blink::WebTreeScopeType::kDocument, std::string(), "uniqueName0",
       base::UnguessableToken::Create(), FramePolicy(), FrameOwnerProperties());
   EXPECT_EQ(
       "RenderFrameHostChanged(new)(22) -> 2: []\n"
       "RenderFrameCreated(22) -> 2: [22: []]",
       activity.GetLog());
   main_test_rfh()->OnCreateChildFrame(
-      23, blink::WebTreeScopeType::kDocument, std::string(), "uniqueName1",
+      23, CreateStubInterfaceProviderRequest(),
+      blink::WebTreeScopeType::kDocument, std::string(), "uniqueName1",
       base::UnguessableToken::Create(), FramePolicy(), FrameOwnerProperties());
   EXPECT_EQ(
       "RenderFrameHostChanged(new)(23) -> 2: [22: []]\n"
@@ -458,9 +478,9 @@
 
   // Simulate attaching a frame from mismatched process id.
   ASSERT_FALSE(frame_tree->AddFrame(
-      root, process_id + 1, 1, blink::WebTreeScopeType::kDocument,
-      std::string(), "uniqueName0", base::UnguessableToken::Create(),
-      FramePolicy(), FrameOwnerProperties()));
+      root, process_id + 1, 1, CreateStubInterfaceProviderRequest(),
+      blink::WebTreeScopeType::kDocument, std::string(), "uniqueName0",
+      base::UnguessableToken::Create(), FramePolicy(), FrameOwnerProperties()));
   ASSERT_EQ("2: []", GetTreeState(frame_tree));
 }
 
@@ -473,16 +493,19 @@
   FrameTreeNode* root = contents()->GetFrameTree()->root();
 
   main_test_rfh()->OnCreateChildFrame(
-      22, blink::WebTreeScopeType::kDocument, std::string(), "uniqueName0",
+      22, CreateStubInterfaceProviderRequest(),
+      blink::WebTreeScopeType::kDocument, std::string(), "uniqueName0",
       base::UnguessableToken::Create(), FramePolicy(), FrameOwnerProperties());
   main_test_rfh()->OnCreateChildFrame(
-      23, blink::WebTreeScopeType::kDocument, std::string(), "uniqueName1",
+      23, CreateStubInterfaceProviderRequest(),
+      blink::WebTreeScopeType::kDocument, std::string(), "uniqueName1",
       base::UnguessableToken::Create(), FramePolicy(), FrameOwnerProperties());
 
   // Add one grandchild frame.
   RenderFrameHostImpl* child1_rfh = root->child_at(0)->current_frame_host();
   child1_rfh->OnCreateChildFrame(
-      33, blink::WebTreeScopeType::kDocument, std::string(), "uniqueName2",
+      33, CreateStubInterfaceProviderRequest(),
+      blink::WebTreeScopeType::kDocument, std::string(), "uniqueName2",
       base::UnguessableToken::Create(), FramePolicy(), FrameOwnerProperties());
 
   // Ensure they can be found by id.
diff --git a/content/browser/frame_host/navigation_controller_impl_unittest.cc b/content/browser/frame_host/navigation_controller_impl_unittest.cc
index b217943a..aea5a4e 100644
--- a/content/browser/frame_host/navigation_controller_impl_unittest.cc
+++ b/content/browser/frame_host/navigation_controller_impl_unittest.cc
@@ -2221,9 +2221,10 @@
   // Prereq: add a subframe with an initial auto-subframe navigation.
   std::string unique_name("uniqueName0");
   main_test_rfh()->OnCreateChildFrame(
-      process()->GetNextRoutingID(), blink::WebTreeScopeType::kDocument,
-      std::string(), unique_name, base::UnguessableToken::Create(),
-      FramePolicy(), FrameOwnerProperties());
+      process()->GetNextRoutingID(),
+      TestRenderFrameHost::CreateStubInterfaceProviderRequest(),
+      blink::WebTreeScopeType::kDocument, std::string(), unique_name,
+      base::UnguessableToken::Create(), FramePolicy(), FrameOwnerProperties());
   TestRenderFrameHost* subframe = static_cast<TestRenderFrameHost*>(
       contents()->GetFrameTree()->root()->child_at(0)->current_frame_host());
   const GURL subframe_url("http://foo1/subframe");
@@ -2297,9 +2298,10 @@
   // Add a subframe and navigate it.
   std::string unique_name0("uniqueName0");
   main_test_rfh()->OnCreateChildFrame(
-      process()->GetNextRoutingID(), blink::WebTreeScopeType::kDocument,
-      std::string(), unique_name0, base::UnguessableToken::Create(),
-      FramePolicy(), FrameOwnerProperties());
+      process()->GetNextRoutingID(),
+      TestRenderFrameHost::CreateStubInterfaceProviderRequest(),
+      blink::WebTreeScopeType::kDocument, std::string(), unique_name0,
+      base::UnguessableToken::Create(), FramePolicy(), FrameOwnerProperties());
   TestRenderFrameHost* subframe = static_cast<TestRenderFrameHost*>(
       contents()->GetFrameTree()->root()->child_at(0)->current_frame_host());
   const GURL url2("http://foo/2");
@@ -2341,9 +2343,10 @@
   // Add a second subframe and navigate.
   std::string unique_name1("uniqueName1");
   main_test_rfh()->OnCreateChildFrame(
-      process()->GetNextRoutingID(), blink::WebTreeScopeType::kDocument,
-      std::string(), unique_name1, base::UnguessableToken::Create(),
-      FramePolicy(), FrameOwnerProperties());
+      process()->GetNextRoutingID(),
+      TestRenderFrameHost::CreateStubInterfaceProviderRequest(),
+      blink::WebTreeScopeType::kDocument, std::string(), unique_name1,
+      base::UnguessableToken::Create(), FramePolicy(), FrameOwnerProperties());
   TestRenderFrameHost* subframe2 = static_cast<TestRenderFrameHost*>(
       contents()->GetFrameTree()->root()->child_at(1)->current_frame_host());
   const GURL url3("http://foo/3");
@@ -2385,9 +2388,10 @@
   // Add a nested subframe and navigate.
   std::string unique_name2("uniqueName2");
   subframe->OnCreateChildFrame(
-      process()->GetNextRoutingID(), blink::WebTreeScopeType::kDocument,
-      std::string(), unique_name2, base::UnguessableToken::Create(),
-      FramePolicy(), FrameOwnerProperties());
+      process()->GetNextRoutingID(),
+      TestRenderFrameHost::CreateStubInterfaceProviderRequest(),
+      blink::WebTreeScopeType::kDocument, std::string(), unique_name2,
+      base::UnguessableToken::Create(), FramePolicy(), FrameOwnerProperties());
   TestRenderFrameHost* subframe3 =
       static_cast<TestRenderFrameHost*>(contents()
                                             ->GetFrameTree()
@@ -2447,9 +2451,10 @@
   // Prereq: add a subframe with an initial auto-subframe navigation.
   std::string unique_name("uniqueName0");
   main_test_rfh()->OnCreateChildFrame(
-      process()->GetNextRoutingID(), blink::WebTreeScopeType::kDocument,
-      std::string(), unique_name, base::UnguessableToken::Create(),
-      FramePolicy(), FrameOwnerProperties());
+      process()->GetNextRoutingID(),
+      TestRenderFrameHost::CreateStubInterfaceProviderRequest(),
+      blink::WebTreeScopeType::kDocument, std::string(), unique_name,
+      base::UnguessableToken::Create(), FramePolicy(), FrameOwnerProperties());
   TestRenderFrameHost* subframe = static_cast<TestRenderFrameHost*>(
       contents()->GetFrameTree()->root()->child_at(0)->current_frame_host());
   const GURL subframe_url("http://foo1/subframe");
@@ -3850,9 +3855,10 @@
   // Add and navigate a subframe that would normally count as in-page.
   std::string unique_name("uniqueName0");
   main_test_rfh()->OnCreateChildFrame(
-      process()->GetNextRoutingID(), blink::WebTreeScopeType::kDocument,
-      std::string(), unique_name, base::UnguessableToken::Create(),
-      FramePolicy(), FrameOwnerProperties());
+      process()->GetNextRoutingID(),
+      TestRenderFrameHost::CreateStubInterfaceProviderRequest(),
+      blink::WebTreeScopeType::kDocument, std::string(), unique_name,
+      base::UnguessableToken::Create(), FramePolicy(), FrameOwnerProperties());
   TestRenderFrameHost* subframe = static_cast<TestRenderFrameHost*>(
       contents()->GetFrameTree()->root()->child_at(0)->current_frame_host());
   const GURL subframe_url("http://www.google.com/#");
@@ -4024,9 +4030,10 @@
   // automatically loaded. Auto subframes don't increment the page ID.
   std::string unique_name("uniqueName0");
   main_test_rfh()->OnCreateChildFrame(
-      process()->GetNextRoutingID(), blink::WebTreeScopeType::kDocument,
-      std::string(), unique_name, base::UnguessableToken::Create(),
-      FramePolicy(), FrameOwnerProperties());
+      process()->GetNextRoutingID(),
+      TestRenderFrameHost::CreateStubInterfaceProviderRequest(),
+      blink::WebTreeScopeType::kDocument, std::string(), unique_name,
+      base::UnguessableToken::Create(), FramePolicy(), FrameOwnerProperties());
   TestRenderFrameHost* subframe = static_cast<TestRenderFrameHost*>(
       contents()->GetFrameTree()->root()->child_at(0)->current_frame_host());
   const GURL url1_sub("http://foo/subframe");
@@ -4532,7 +4539,8 @@
   EXPECT_EQ(0, controller.GetPendingEntryIndex());
   // The actual cross-navigation is suspended until the current RVH tells us
   // it unloaded, simulate that.
-  contents()->ProceedWithCrossSiteNavigation();
+  if (!IsBrowserSideNavigationEnabled())
+    contents()->GetMainFrame()->PrepareForCommitIfNecessary();
   // Also make sure we told the page to navigate.
   GURL nav_url = GetLastNavigationURL();
   EXPECT_EQ(url1, nav_url);
@@ -4544,7 +4552,8 @@
   EXPECT_EQ(2, controller.GetPendingEntryIndex());
   // The actual cross-navigation is suspended until the current RVH tells us
   // it unloaded, simulate that.
-  contents()->ProceedWithCrossSiteNavigation();
+  if (!IsBrowserSideNavigationEnabled())
+    contents()->GetMainFrame()->PrepareForCommitIfNecessary();
   nav_url = GetLastNavigationURL();
   EXPECT_EQ(url3, nav_url);
   contents()->CommitPendingNavigation();
diff --git a/content/browser/frame_host/navigation_request.cc b/content/browser/frame_host/navigation_request.cc
index cae9cd32..747475c 100644
--- a/content/browser/frame_host/navigation_request.cc
+++ b/content/browser/frame_host/navigation_request.cc
@@ -727,7 +727,7 @@
     const GlobalRequestID& request_id,
     bool is_download,
     bool is_stream,
-    mojom::URLLoaderFactoryPtrInfo subresource_loader_factory_info) {
+    base::Optional<SubresourceLoaderParams> subresource_loader_params) {
   DCHECK(state_ == STARTED);
   DCHECK(response);
   TRACE_EVENT_ASYNC_STEP_INTO0("navigation", "NavigationRequest", this,
@@ -802,7 +802,7 @@
   ssl_status_ = ssl_status;
   is_download_ = is_download;
 
-  subresource_loader_factory_info_ = std::move(subresource_loader_factory_info);
+  subresource_loader_params_ = std::move(subresource_loader_params);
 
   // Since we've made the final pick for the RenderFrameHost above, the picked
   // RenderFrameHost's process should be considered "tainted" for future
@@ -1191,8 +1191,7 @@
 
   render_frame_host->CommitNavigation(
       response_.get(), std::move(body_), std::move(handle_), common_params_,
-      request_params_, is_view_source_,
-      std::move(subresource_loader_factory_info_));
+      request_params_, is_view_source_, std::move(subresource_loader_params_));
 
   frame_tree_node_->ResetNavigationRequest(true, true);
 }
diff --git a/content/browser/frame_host/navigation_request.h b/content/browser/frame_host/navigation_request.h
index 99679615..367a9de 100644
--- a/content/browser/frame_host/navigation_request.h
+++ b/content/browser/frame_host/navigation_request.h
@@ -11,11 +11,13 @@
 #include "base/macros.h"
 #include "base/memory/ref_counted.h"
 #include "base/memory/weak_ptr.h"
+#include "base/optional.h"
 #include "content/browser/frame_host/navigation_entry_impl.h"
 #include "content/browser/loader/navigation_url_loader_delegate.h"
 #include "content/common/content_export.h"
 #include "content/common/frame_message_enums.h"
 #include "content/common/navigation_params.h"
+#include "content/common/navigation_subresource_loader_params.h"
 #include "content/public/browser/navigation_throttle.h"
 #include "content/public/common/previews_state.h"
 #include "mojo/public/cpp/system/data_pipe.h"
@@ -31,6 +33,7 @@
 class ResourceRequestBody;
 class SiteInstanceImpl;
 class StreamHandle;
+struct SubresourceLoaderParams;
 
 // PlzNavigate
 // A UI thread object that owns a navigation request until it commits. It
@@ -208,8 +211,8 @@
                          const GlobalRequestID& request_id,
                          bool is_download,
                          bool is_stream,
-                         mojom::URLLoaderFactoryPtrInfo
-                             subresource_url_loader_factory_info) override;
+                         base::Optional<SubresourceLoaderParams>
+                             subresource_loader_params) override;
   void OnRequestFailed(bool has_stale_copy_in_cache,
                        int net_error,
                        const base::Optional<net::SSLInfo>& ssl_info,
@@ -340,9 +343,9 @@
 
   base::Closure on_start_checks_complete_closure_;
 
-  // Used in the network service world to pass the subressource loader factory
-  // to the renderer. Currently only used by AppCache.
-  mojom::URLLoaderFactoryPtrInfo subresource_loader_factory_info_;
+  // Used in the network service world to pass the subressource loader params
+  // to the renderer. Used by AppCache and ServiceWorker.
+  base::Optional<SubresourceLoaderParams> subresource_loader_params_;
 
   base::WeakPtrFactory<NavigationRequest> weak_factory_;
 
diff --git a/content/browser/frame_host/navigator_impl.cc b/content/browser/frame_host/navigator_impl.cc
index a3719a6..c32872c 100644
--- a/content/browser/frame_host/navigator_impl.cc
+++ b/content/browser/frame_host/navigator_impl.cc
@@ -1185,7 +1185,7 @@
         nullptr,  // body
         mojo::ScopedDataPipeConsumerHandle(), scoped_request->common_params(),
         scoped_request->request_params(), scoped_request->is_view_source(),
-        mojom::URLLoaderFactoryPtrInfo());
+        base::nullopt);
     return;
   }
 
diff --git a/content/browser/frame_host/render_frame_host_delegate.h b/content/browser/frame_host/render_frame_host_delegate.h
index cf2fc73..e29b84f 100644
--- a/content/browser/frame_host/render_frame_host_delegate.h
+++ b/content/browser/frame_host/render_frame_host_delegate.h
@@ -325,6 +325,9 @@
                                                  const url::Origin& origin,
                                                  const GURL& resource_url);
 
+  // Opens a new view-source tab for the last committed document in |frame|.
+  virtual void ViewSource(RenderFrameHostImpl* frame) {}
+
 #if defined(OS_ANDROID)
   virtual base::android::ScopedJavaLocalRef<jobject>
   GetJavaRenderFrameHostDelegate();
diff --git a/content/browser/frame_host/render_frame_host_impl.cc b/content/browser/frame_host/render_frame_host_impl.cc
index a97660da..fd86463 100644
--- a/content/browser/frame_host/render_frame_host_impl.cc
+++ b/content/browser/frame_host/render_frame_host_impl.cc
@@ -90,10 +90,12 @@
 #include "content/common/input_messages.h"
 #include "content/common/inter_process_time_ticks_converter.h"
 #include "content/common/navigation_params.h"
+#include "content/common/navigation_subresource_loader_params.h"
 #include "content/common/render_message_filter.mojom.h"
 #include "content/common/renderer.mojom.h"
 #include "content/common/site_isolation_policy.h"
 #include "content/common/swapped_out_messages.h"
+#include "content/common/url_loader_factory_bundle.mojom.h"
 #include "content/common/widget.mojom.h"
 #include "content/network/restricted_cookie_manager_impl.h"
 #include "content/public/browser/ax_event_notification_details.h"
@@ -153,6 +155,7 @@
 #include "ui/gfx/geometry/quad_f.h"
 #include "url/gurl.h"
 #include "url/origin.h"
+#include "url/url_constants.h"
 
 #if defined(OS_ANDROID)
 #include "content/browser/android/java_interfaces_impl.h"
@@ -502,10 +505,10 @@
       has_selection_(false),
       is_audible_(false),
       last_navigation_previews_state_(PREVIEWS_UNSPECIFIED),
-      frame_host_interface_broker_binding_(this),
       frame_host_associated_binding_(this),
       waiting_for_init_(renderer_initiated_creation),
       has_focused_editable_element_(false),
+      interface_provider_binding_(this),
       weak_ptr_factory_(this) {
   frame_tree_->AddRenderViewHostRef(render_view_host_);
   GetProcess()->AddRoute(routing_id_, this);
@@ -531,6 +534,7 @@
   }
 
   SetUpMojoIfNeeded();
+
   swapout_event_monitor_timeout_.reset(new TimeoutMonitor(base::Bind(
       &RenderFrameHostImpl::OnSwappedOut, weak_ptr_factory_.GetWeakPtr())));
   beforeunload_timeout_.reset(
@@ -1152,7 +1156,11 @@
 
   DCHECK(GetProcess()->HasConnection());
 
+  service_manager::mojom::InterfaceProviderPtr interface_provider;
+  BindInterfaceProviderRequest(mojo::MakeRequest(&interface_provider));
+
   mojom::CreateFrameParamsPtr params = mojom::CreateFrameParams::New();
+  params->interface_provider = std::move(interface_provider);
   params->routing_id = routing_id_;
   params->proxy_routing_id = proxy_routing_id;
   params->opener_routing_id = opener_routing_id;
@@ -1318,6 +1326,8 @@
 
 void RenderFrameHostImpl::OnCreateChildFrame(
     int new_routing_id,
+    service_manager::mojom::InterfaceProviderRequest
+        new_interface_provider_provider_request,
     blink::WebTreeScopeType scope,
     const std::string& frame_name,
     const std::string& frame_unique_name,
@@ -1326,6 +1336,7 @@
     const FrameOwnerProperties& frame_owner_properties) {
   // TODO(lukasza): Call ReceivedBadMessage when |frame_unique_name| is empty.
   DCHECK(!frame_unique_name.empty());
+  DCHECK(new_interface_provider_provider_request.is_pending());
 
   // The RenderFrame corresponding to this host sent an IPC message to create a
   // child, but by the time we get here, it's possible for the host to have been
@@ -1334,9 +1345,11 @@
   if (!is_active() || !IsCurrent() || !render_frame_created_)
     return;
 
-  // |new_routing_id| and |devtools_frame_token| were generated on the browser's
-  // IO thread and not taken from the renderer process.
+  // |new_routing_id|, |new_interface_provider_provider_request|, and
+  // |devtools_frame_token| were generated on the browser's IO thread and not
+  // taken from the renderer process.
   frame_tree_->AddFrame(frame_tree_node_, GetProcess()->GetID(), new_routing_id,
+                        std::move(new_interface_provider_provider_request),
                         scope, frame_name, frame_unique_name,
                         devtools_frame_token, frame_policy,
                         frame_owner_properties);
@@ -1506,8 +1519,7 @@
   // navigating already and sent it before hearing the FrameMsg_Stop message.
   // Treat this as an implicit beforeunload ack to allow the pending navigation
   // to continue.
-  if (is_waiting_for_beforeunload_ack_ &&
-      unload_ack_is_for_navigation_ &&
+  if (is_waiting_for_beforeunload_ack_ && unload_ack_is_for_navigation_ &&
       !GetParent()) {
     base::TimeTicks approx_renderer_start_time = send_before_unload_start_time_;
     OnBeforeUnloadACK(true, approx_renderer_start_time, base::TimeTicks::Now());
@@ -1845,6 +1857,7 @@
   // reset.
   SetRenderFrameCreated(false);
   InvalidateMojoConnection();
+  interface_provider_binding_.Close();
 
   // Execute any pending AX tree snapshot callbacks with an empty response,
   // since we're never going to get a response from this renderer.
@@ -2166,6 +2179,10 @@
                                 feature, GetLastCommittedOrigin());
 }
 
+void RenderFrameHostImpl::ViewSource() {
+  delegate_->ViewSource(this);
+}
+
 void RenderFrameHostImpl::OnDidAccessInitialDocument() {
   delegate_->DidAccessInitialDocument();
 }
@@ -2747,6 +2764,16 @@
                                            *overlay_routing_token_));
 }
 
+void RenderFrameHostImpl::BindInterfaceProviderRequest(
+    service_manager::mojom::InterfaceProviderRequest
+        interface_provider_request) {
+  DCHECK(!interface_provider_binding_.is_bound());
+  DCHECK(interface_provider_request.is_pending());
+  interface_provider_binding_.Bind(FilterRendererExposedInterfaces(
+      mojom::kNavigation_FrameSpec, GetProcess()->GetID(),
+      std::move(interface_provider_request)));
+}
+
 void RenderFrameHostImpl::OnShowCreatedWindow(int pending_widget_routing_id,
                                               WindowOpenDisposition disposition,
                                               const gfx::Rect& initial_rect,
@@ -2863,12 +2890,18 @@
 
   // The view, widget, and frame should all be routable now.
   DCHECK(RenderViewHost::FromID(render_process_id, render_view_route_id));
-  RenderFrameHost* rfh =
-      RenderFrameHost::FromID(GetProcess()->GetID(), main_frame_route_id);
+  RenderFrameHostImpl* rfh =
+      RenderFrameHostImpl::FromID(GetProcess()->GetID(), main_frame_route_id);
   DCHECK(rfh);
+
+  service_manager::mojom::InterfaceProviderPtr main_frame_interface_provider;
+  rfh->BindInterfaceProviderRequest(
+      mojo::MakeRequest(&main_frame_interface_provider));
+
   mojom::CreateNewWindowReplyPtr reply = mojom::CreateNewWindowReply::New(
       render_view_route_id, main_frame_route_id, main_frame_widget_route_id,
-      cloned_namespace->id(), rfh->GetDevToolsFrameToken());
+      std::move(main_frame_interface_provider), cloned_namespace->id(),
+      rfh->GetDevToolsFrameToken());
   std::move(callback).Run(mojom::CreateNewWindowStatus::kSuccess,
                           std::move(reply));
 }
@@ -3074,10 +3107,16 @@
         base::Bind(&InputInjectorImpl::Create, weak_ptr_factory_.GetWeakPtr()));
   }
 
-  registry_->AddInterface(base::Bind(&media::VideoDecodeStatsRecorder::Create));
-
   registry_->AddInterface(
       base::BindRepeating(GetRestrictedCookieManager, base::Unretained(this)));
+
+  // Only save decode stats when on-the-record.
+  if (!GetSiteInstance()->GetBrowserContext()->IsOffTheRecord()) {
+    media::VideoDecodePerfHistory* video_perf_history =
+        GetSiteInstance()->GetBrowserContext()->GetVideoDecodePerfHistory();
+    registry_->AddInterface(base::BindRepeating(
+        &media::VideoDecodeStatsRecorder::Create, video_perf_history));
+  }
 }
 
 void RenderFrameHostImpl::ResetWaitingState() {
@@ -3188,7 +3227,7 @@
   if (IsBrowserSideNavigationEnabled()) {
     CommitNavigation(nullptr, nullptr, mojo::ScopedDataPipeConsumerHandle(),
                      common_params, RequestNavigationParams(), false,
-                     mojom::URLLoaderFactoryPtrInfo());
+                     base::nullopt);
   } else {
     Navigate(common_params, StartNavigationParams(), RequestNavigationParams());
   }
@@ -3339,7 +3378,7 @@
     const CommonNavigationParams& common_params,
     const RequestNavigationParams& request_params,
     bool is_view_source,
-    mojom::URLLoaderFactoryPtrInfo subresource_url_loader_factory_info) {
+    base::Optional<SubresourceLoaderParams> subresource_loader_params) {
   TRACE_EVENT2("navigation", "RenderFrameHostImpl::CommitNavigation",
                "frame_tree_node", frame_tree_node_->frame_tree_node_id(), "url",
                common_params.url.possibly_invalid_spec());
@@ -3358,7 +3397,7 @@
     GetNavigationControl()->CommitNavigation(
         ResourceResponseHead(), GURL(), common_params, request_params,
         mojo::ScopedDataPipeConsumerHandle(),
-        /*default_subresource_url_loader_factory=*/nullptr);
+        /*subresource_loader_factories=*/base::nullopt);
     return;
   }
 
@@ -3378,24 +3417,49 @@
   const GURL body_url = body.get() ? body->GetURL() : GURL();
   const ResourceResponseHead head = response ?
       response->head : ResourceResponseHead();
-  mojom::URLLoaderFactoryPtr default_subresource_url_loader_factory;
+  const bool is_same_document =
+      FrameMsg_Navigate_Type::IsSameDocument(common_params.navigation_type);
+
   // TODO(scottmg): Pass a factory for SW, etc. once we have one.
-  if (base::FeatureList::IsEnabled(features::kNetworkService)) {
-    if (!subresource_url_loader_factory_info.is_valid()) {
-      const auto& schemes = URLDataManagerBackend::GetWebUISchemes();
-      if (std::find(schemes.begin(), schemes.end(),
-                    common_params.url.scheme()) != schemes.end()) {
-        default_subresource_url_loader_factory =
-            CreateWebUIURLLoader(frame_tree_node_);
-      }
+  base::Optional<URLLoaderFactoryBundle> subresource_loader_factories;
+  if (base::FeatureList::IsEnabled(features::kNetworkService) &&
+      !is_same_document) {
+    // NOTE: On Network Service navigations, we want to ensure that a frame is
+    // given everything it will need to load any accessible subresources. We
+    // however only do this for cross-document navigations, because the
+    // alternative would be redundant effort.
+    mojom::URLLoaderFactoryPtr default_factory;
+    StoragePartitionImpl* storage_partition =
+        static_cast<StoragePartitionImpl*>(BrowserContext::GetStoragePartition(
+            GetSiteInstance()->GetBrowserContext(), GetSiteInstance()));
+    if (subresource_loader_params &&
+        subresource_loader_params->loader_factory_info.is_valid()) {
+      // If the caller has supplied a default URLLoaderFactory override (for
+      // e.g. appcache, Service Worker, etc.), use that.
+      default_factory.Bind(
+          std::move(subresource_loader_params->loader_factory_info));
     } else {
-      default_subresource_url_loader_factory.Bind(
-          std::move(subresource_url_loader_factory_info));
+      // Otherwise default to a Network Service-backed loader from the
+      // appropriate NetworkContext.
+      storage_partition->GetNetworkContext()->CreateURLLoaderFactory(
+          mojo::MakeRequest(&default_factory), GetProcess()->GetID());
     }
+
+    DCHECK(default_factory.is_bound());
+    subresource_loader_factories.emplace();
+    subresource_loader_factories->SetDefaultFactory(std::move(default_factory));
+
+    // Everyone gets a blob loader.
+    mojom::URLLoaderFactoryPtr blob_factory;
+    storage_partition->GetBlobURLLoaderFactory()->HandleRequest(
+        mojo::MakeRequest(&blob_factory));
+    subresource_loader_factories->RegisterFactory(url::kBlobScheme,
+                                                  std::move(blob_factory));
   }
+
   GetNavigationControl()->CommitNavigation(
       head, body_url, common_params, request_params, std::move(handle),
-      std::move(default_subresource_url_loader_factory));
+      std::move(subresource_loader_factories));
 
   // If a network request was made, update the Previews state.
   if (IsURLHandledByNetworkStack(common_params.url) &&
@@ -3409,7 +3473,7 @@
   // same-document navigation would not load any new ones for replacement.
   // The user would finish with a half loaded document.
   // See https://crbug.com/769645.
-  if (!FrameMsg_Navigate_Type::IsSameDocument(common_params.navigation_type)) {
+  if (!is_same_document) {
     // Released in OnStreamHandleConsumed().
     stream_handle_ = std::move(body);
   }
@@ -3472,11 +3536,7 @@
   RegisterMojoInterfaces();
   mojom::FrameFactoryPtr frame_factory;
   BindInterface(GetProcess(), &frame_factory);
-
-  mojom::FrameHostInterfaceBrokerPtr broker_proxy;
-  frame_host_interface_broker_binding_.Bind(mojo::MakeRequest(&broker_proxy));
-  frame_factory->CreateFrame(routing_id_, MakeRequest(&frame_),
-                             std::move(broker_proxy));
+  frame_factory->CreateFrame(routing_id_, MakeRequest(&frame_));
 
   service_manager::mojom::InterfaceProviderPtr remote_interfaces;
   frame_->GetInterfaceProvider(mojo::MakeRequest(&remote_interfaces));
@@ -3494,8 +3554,8 @@
   registry_.reset();
 
   frame_.reset();
-  frame_host_interface_broker_binding_.Close();
   frame_bindings_control_.reset();
+  frame_host_associated_binding_.Close();
   navigation_control_.reset();
 
   // Disconnect with ImageDownloader Mojo service in RenderFrame.
@@ -3806,14 +3866,6 @@
   return has_selection_;
 }
 
-void RenderFrameHostImpl::GetInterfaceProvider(
-    service_manager::mojom::InterfaceProviderRequest interfaces) {
-  interface_provider_bindings_.AddBinding(
-      this, FilterRendererExposedInterfaces(mojom::kNavigation_FrameSpec,
-                                            GetProcess()->GetID(),
-                                            std::move(interfaces)));
-}
-
 #if BUILDFLAG(USE_EXTERNAL_POPUP_MENU)
 #if defined(OS_MACOSX)
 
diff --git a/content/browser/frame_host/render_frame_host_impl.h b/content/browser/frame_host/render_frame_host_impl.h
index c03001ae..b323c3c 100644
--- a/content/browser/frame_host/render_frame_host_impl.h
+++ b/content/browser/frame_host/render_frame_host_impl.h
@@ -46,13 +46,13 @@
 #include "content/public/browser/render_frame_host.h"
 #include "content/public/common/javascript_dialog_type.h"
 #include "content/public/common/previews_state.h"
-#include "content/public/common/url_loader_factory.mojom.h"
 #include "media/mojo/interfaces/interface_factory.mojom.h"
 #include "mojo/public/cpp/bindings/binding_set.h"
 #include "mojo/public/cpp/system/data_pipe.h"
 #include "net/http/http_response_headers.h"
 #include "services/device/public/interfaces/wake_lock_context.mojom.h"
 #include "services/service_manager/public/cpp/binder_registry.h"
+#include "services/service_manager/public/interfaces/interface_provider.mojom.h"
 #include "third_party/WebKit/public/platform/WebFocusType.h"
 #include "third_party/WebKit/public/platform/WebInsecureRequestPolicy.h"
 #include "third_party/WebKit/public/platform/WebSuddenTerminationDisablerType.h"
@@ -126,12 +126,12 @@
 struct FramePolicy;
 struct FileChooserParams;
 struct ResourceResponse;
+struct SubresourceLoaderParams;
 
 class CONTENT_EXPORT RenderFrameHostImpl
     : public RenderFrameHost,
       public base::SupportsUserData,
       public mojom::FrameHost,
-      public mojom::FrameHostInterfaceBroker,
       public BrowserAccessibilityDelegate,
       public SiteInstanceImpl::Observer,
       public service_manager::mojom::InterfaceProvider,
@@ -210,12 +210,8 @@
   bool IsBeforeUnloadHangMonitorDisabledForTesting() override;
   bool GetSuddenTerminationDisablerState(
       blink::WebSuddenTerminationDisablerType disabler_type) override;
-
   bool IsFeatureEnabled(blink::WebFeaturePolicyFeature feature) override;
-
-  // mojom::FrameHostInterfaceBroker
-  void GetInterfaceProvider(
-      service_manager::mojom::InterfaceProviderRequest interfaces) override;
+  void ViewSource() override;
 
   // IPC::Sender
   bool Send(IPC::Message* msg) override;
@@ -277,7 +273,13 @@
   // that was partially handled on the IO thread (to allocate |new_routing_id|
   // and |devtools_frame_token|), and is forwarded here. The renderer has
   // already been told to create a RenderFrame with the specified ID values.
+  // |interface_provider_request| is the request end of the InterfaceProvider
+  // interface that the RenderFrameHost corresponding to the child frame should
+  // bind to expose services to the renderer process. The caller takes care of
+  // sending down the client end of the pipe to the child RenderFrame to use.
   void OnCreateChildFrame(int new_routing_id,
+                          service_manager::mojom::InterfaceProviderRequest
+                              interface_provider_request,
                           blink::WebTreeScopeType scope,
                           const std::string& frame_name,
                           const std::string& frame_unique_name,
@@ -545,9 +547,9 @@
 
   // PlzNavigate: Indicates that a navigation is ready to commit and can be
   // handled by this RenderFrame.
-  // |subresource_url_loader_factory_info| is used in network service land to
-  // allow factories interested in handling subresource requests to the
-  // renderer. E.g. AppCache.
+  // |subresource_loader_params| is used in network service land to pass
+  // the parameters to create a custom subresource loader in the renderer
+  // process, e.g. by AppCache etc.
   void CommitNavigation(
       ResourceResponse* response,
       std::unique_ptr<StreamHandle> body,
@@ -555,7 +557,7 @@
       const CommonNavigationParams& common_params,
       const RequestNavigationParams& request_params,
       bool is_view_source,
-      mojom::URLLoaderFactoryPtrInfo subresource_url_loader_factory_info);
+      base::Optional<SubresourceLoaderParams> subresource_loader_params);
 
   // PlzNavigate
   // Indicates that a navigation failed and that this RenderFrame should display
@@ -661,6 +663,14 @@
   // sending a mojo overlay factory.
   const base::UnguessableToken& GetOverlayRoutingToken();
 
+  // Binds the request end of the InterfaceProvider interface through which
+  // services provided by this RenderFrameHost are exposed to the correponding
+  // RenderFrame. The caller is responsible for plumbing the client end to the
+  // the renderer process.
+  void BindInterfaceProviderRequest(
+      service_manager::mojom::InterfaceProviderRequest
+          interface_provider_request);
+
   const StreamHandle* stream_handle_for_testing() const {
     return stream_handle_.get();
   }
@@ -842,7 +852,7 @@
                            const gfx::Rect& initial_rect,
                            bool user_gesture);
 
-  // mojom::FrameHost
+  // mojom::FrameHost:
   void CreateNewWindow(mojom::CreateNewWindowParamsPtr params,
                        CreateNewWindowCallback callback) override;
   void IssueKeepAliveHandle(mojom::KeepAliveHandleRequest request) override;
@@ -1250,8 +1260,6 @@
   // same Previews status as the top-level frame.
   PreviewsState last_navigation_previews_state_;
 
-  mojo::Binding<mojom::FrameHostInterfaceBroker>
-      frame_host_interface_broker_binding_;
   mojo::AssociatedBinding<mojom::FrameHost> frame_host_associated_binding_;
   mojom::FramePtr frame_;
   mojom::FrameBindingsControlAssociatedPtr frame_bindings_control_;
@@ -1309,8 +1317,17 @@
   std::unique_ptr<JavaInterfaceProvider> java_interface_registry_;
 #endif
 
-  mojo::BindingSet<service_manager::mojom::InterfaceProvider>
-      interface_provider_bindings_;
+  // Binding for the InterfaceProvider through which this RFHI exposes Mojo
+  // services to the corresonding RenderFrame.
+  //
+  // Normally, whoever creates this RFHI, is responsible for creating a message
+  // pipe, then supplying the request end to BindInterfaceProviderRequest(), and
+  // plumbing the client end to the RenderFrame in the renderer process.
+  //
+  // Currently the only exception to this rule are out-of-process iframes, where
+  // the child RFHI takes care of this internally in CreateRenderFrame().
+  mojo::Binding<service_manager::mojom::InterfaceProvider>
+      interface_provider_binding_;
 
   // IPC-friendly token that represents this host for AndroidOverlays, if we
   // have created one yet.
diff --git a/content/browser/frame_host/render_frame_host_manager_unittest.cc b/content/browser/frame_host/render_frame_host_manager_unittest.cc
index a74afc4..d0364932 100644
--- a/content/browser/frame_host/render_frame_host_manager_unittest.cc
+++ b/content/browser/frame_host/render_frame_host_manager_unittest.cc
@@ -1949,10 +1949,12 @@
   contents()->NavigateAndCommit(kUrlA);
   contents()->GetMainFrame()->OnCreateChildFrame(
       contents()->GetMainFrame()->GetProcess()->GetNextRoutingID(),
+      TestRenderFrameHost::CreateStubInterfaceProviderRequest(),
       blink::WebTreeScopeType::kDocument, "frame_name", "uniqueName1",
       base::UnguessableToken::Create(), FramePolicy(), FrameOwnerProperties());
   contents()->GetMainFrame()->OnCreateChildFrame(
       contents()->GetMainFrame()->GetProcess()->GetNextRoutingID(),
+      TestRenderFrameHost::CreateStubInterfaceProviderRequest(),
       blink::WebTreeScopeType::kDocument, "frame_name", "uniqueName2",
       base::UnguessableToken::Create(), FramePolicy(), FrameOwnerProperties());
   RenderFrameHostManager* root_manager =
@@ -2088,6 +2090,7 @@
   // |contents1| creates an out of process iframe.
   contents1->GetMainFrame()->OnCreateChildFrame(
       contents1->GetMainFrame()->GetProcess()->GetNextRoutingID(),
+      TestRenderFrameHost::CreateStubInterfaceProviderRequest(),
       blink::WebTreeScopeType::kDocument, "frame_name", "uniqueName1",
       base::UnguessableToken::Create(), FramePolicy(), FrameOwnerProperties());
   RenderFrameHostManager* iframe =
@@ -2137,6 +2140,7 @@
   EXPECT_TRUE(main_rfh->IsRenderFrameLive());
   main_rfh->OnCreateChildFrame(
       main_rfh->GetProcess()->GetNextRoutingID(),
+      TestRenderFrameHost::CreateStubInterfaceProviderRequest(),
       blink::WebTreeScopeType::kDocument, std::string(), "uniqueName1",
       base::UnguessableToken::Create(), FramePolicy(), FrameOwnerProperties());
   RenderFrameHostManager* subframe_rfhm =
@@ -2294,14 +2298,16 @@
   FrameTree* tree1 = contents()->GetFrameTree();
   FrameTreeNode* root1 = tree1->root();
   int process_id = root1->current_frame_host()->GetProcess()->GetID();
-  tree1->AddFrame(root1, process_id, 12, blink::WebTreeScopeType::kDocument,
-                  std::string(), "uniqueName0",
-                  base::UnguessableToken::Create(), FramePolicy(),
-                  FrameOwnerProperties());
-  tree1->AddFrame(root1, process_id, 13, blink::WebTreeScopeType::kDocument,
-                  std::string(), "uniqueName1",
-                  base::UnguessableToken::Create(), FramePolicy(),
-                  FrameOwnerProperties());
+  tree1->AddFrame(root1, process_id, 12,
+                  TestRenderFrameHost::CreateStubInterfaceProviderRequest(),
+                  blink::WebTreeScopeType::kDocument, std::string(),
+                  "uniqueName0", base::UnguessableToken::Create(),
+                  FramePolicy(), FrameOwnerProperties());
+  tree1->AddFrame(root1, process_id, 13,
+                  TestRenderFrameHost::CreateStubInterfaceProviderRequest(),
+                  blink::WebTreeScopeType::kDocument, std::string(),
+                  "uniqueName1", base::UnguessableToken::Create(),
+                  FramePolicy(), FrameOwnerProperties());
 
   std::unique_ptr<TestWebContents> tab2(
       TestWebContents::Create(browser_context(), nullptr));
@@ -2309,14 +2315,16 @@
   FrameTree* tree2 = tab2->GetFrameTree();
   FrameTreeNode* root2 = tree2->root();
   process_id = root2->current_frame_host()->GetProcess()->GetID();
-  tree2->AddFrame(root2, process_id, 22, blink::WebTreeScopeType::kDocument,
-                  std::string(), "uniqueName2",
-                  base::UnguessableToken::Create(), FramePolicy(),
-                  FrameOwnerProperties());
-  tree2->AddFrame(root2, process_id, 23, blink::WebTreeScopeType::kDocument,
-                  std::string(), "uniqueName3",
-                  base::UnguessableToken::Create(), FramePolicy(),
-                  FrameOwnerProperties());
+  tree2->AddFrame(root2, process_id, 22,
+                  TestRenderFrameHost::CreateStubInterfaceProviderRequest(),
+                  blink::WebTreeScopeType::kDocument, std::string(),
+                  "uniqueName2", base::UnguessableToken::Create(),
+                  FramePolicy(), FrameOwnerProperties());
+  tree2->AddFrame(root2, process_id, 23,
+                  TestRenderFrameHost::CreateStubInterfaceProviderRequest(),
+                  blink::WebTreeScopeType::kDocument, std::string(),
+                  "uniqueName3", base::UnguessableToken::Create(),
+                  FramePolicy(), FrameOwnerProperties());
 
   std::unique_ptr<TestWebContents> tab3(
       TestWebContents::Create(browser_context(), nullptr));
@@ -2329,10 +2337,11 @@
   FrameTree* tree4 = tab4->GetFrameTree();
   FrameTreeNode* root4 = tree4->root();
   process_id = root4->current_frame_host()->GetProcess()->GetID();
-  tree4->AddFrame(root4, process_id, 42, blink::WebTreeScopeType::kDocument,
-                  std::string(), "uniqueName4",
-                  base::UnguessableToken::Create(), FramePolicy(),
-                  FrameOwnerProperties());
+  tree4->AddFrame(root4, process_id, 42,
+                  TestRenderFrameHost::CreateStubInterfaceProviderRequest(),
+                  blink::WebTreeScopeType::kDocument, std::string(),
+                  "uniqueName4", base::UnguessableToken::Create(),
+                  FramePolicy(), FrameOwnerProperties());
 
   root1->child_at(1)->SetOpener(root1->child_at(1));
   root1->SetOpener(root2->child_at(1));
@@ -2380,14 +2389,17 @@
   contents()->NavigateAndCommit(kUrlA);
   main_test_rfh()->OnCreateChildFrame(
       main_test_rfh()->GetProcess()->GetNextRoutingID(),
+      TestRenderFrameHost::CreateStubInterfaceProviderRequest(),
       blink::WebTreeScopeType::kDocument, "frame1", "uniqueName1",
       base::UnguessableToken::Create(), FramePolicy(), FrameOwnerProperties());
   main_test_rfh()->OnCreateChildFrame(
       main_test_rfh()->GetProcess()->GetNextRoutingID(),
+      TestRenderFrameHost::CreateStubInterfaceProviderRequest(),
       blink::WebTreeScopeType::kDocument, "frame2", "uniqueName2",
       base::UnguessableToken::Create(), FramePolicy(), FrameOwnerProperties());
   main_test_rfh()->OnCreateChildFrame(
       main_test_rfh()->GetProcess()->GetNextRoutingID(),
+      TestRenderFrameHost::CreateStubInterfaceProviderRequest(),
       blink::WebTreeScopeType::kDocument, "frame3", "uniqueName3",
       base::UnguessableToken::Create(), FramePolicy(), FrameOwnerProperties());
 
@@ -2478,6 +2490,7 @@
   contents()->NavigateAndCommit(kUrlA);
   main_test_rfh()->OnCreateChildFrame(
       main_test_rfh()->GetProcess()->GetNextRoutingID(),
+      TestRenderFrameHost::CreateStubInterfaceProviderRequest(),
       blink::WebTreeScopeType::kDocument, "frame1", "uniqueName1",
       base::UnguessableToken::Create(), FramePolicy(), FrameOwnerProperties());
 
@@ -3022,6 +3035,7 @@
   // Create a child frame and navigate it cross-site.
   main_test_rfh()->OnCreateChildFrame(
       main_test_rfh()->GetProcess()->GetNextRoutingID(),
+      TestRenderFrameHost::CreateStubInterfaceProviderRequest(),
       blink::WebTreeScopeType::kDocument, "frame1", "uniqueName1",
       base::UnguessableToken::Create(), FramePolicy(), FrameOwnerProperties());
 
diff --git a/content/browser/frame_host/render_frame_message_filter.cc b/content/browser/frame_host/render_frame_message_filter.cc
index 9ee3ffc..9e9a5e7 100644
--- a/content/browser/frame_host/render_frame_message_filter.cc
+++ b/content/browser/frame_host/render_frame_message_filter.cc
@@ -31,6 +31,7 @@
 #include "content/public/common/content_constants.h"
 #include "content/public/common/content_features.h"
 #include "gpu/GLES2/gl2extchromium.h"
+#include "mojo/public/cpp/system/message_pipe.h"
 #include "net/base/registry_controlled_domains/registry_controlled_domain.h"
 #include "net/cookies/cookie_options.h"
 #include "net/cookies/cookie_store.h"
@@ -38,6 +39,7 @@
 #include "net/url_request/url_request_context.h"
 #include "net/url_request/url_request_context_getter.h"
 #include "ppapi/features/features.h"
+#include "services/service_manager/public/interfaces/interface_provider.mojom.h"
 #include "storage/browser/blob/blob_storage_context.h"
 #include "url/gurl.h"
 #include "url/origin.h"
@@ -61,15 +63,17 @@
 const int kPluginsRefreshThresholdInSeconds = 3;
 #endif
 
-void CreateChildFrameOnUI(int process_id,
-                          int parent_routing_id,
-                          blink::WebTreeScopeType scope,
-                          const std::string& frame_name,
-                          const std::string& frame_unique_name,
-                          const base::UnguessableToken& devtools_frame_token,
-                          const FramePolicy& frame_policy,
-                          const FrameOwnerProperties& frame_owner_properties,
-                          int new_routing_id) {
+void CreateChildFrameOnUI(
+    int process_id,
+    int parent_routing_id,
+    blink::WebTreeScopeType scope,
+    const std::string& frame_name,
+    const std::string& frame_unique_name,
+    const base::UnguessableToken& devtools_frame_token,
+    const FramePolicy& frame_policy,
+    const FrameOwnerProperties& frame_owner_properties,
+    int new_routing_id,
+    mojo::ScopedMessagePipeHandle interface_provider_request_handle) {
   DCHECK_CURRENTLY_ON(BrowserThread::UI);
   RenderFrameHostImpl* render_frame_host =
       RenderFrameHostImpl::FromID(process_id, parent_routing_id);
@@ -77,8 +81,11 @@
   // processing a subframe creation message.
   if (render_frame_host) {
     render_frame_host->OnCreateChildFrame(
-        new_routing_id, scope, frame_name, frame_unique_name,
-        devtools_frame_token, frame_policy, frame_owner_properties);
+        new_routing_id,
+        service_manager::mojom::InterfaceProviderRequest(
+            std::move(interface_provider_request_handle)),
+        scope, frame_name, frame_unique_name, devtools_frame_token,
+        frame_policy, frame_owner_properties);
   }
 }
 
@@ -341,16 +348,25 @@
 void RenderFrameMessageFilter::OnCreateChildFrame(
     const FrameHostMsg_CreateChildFrame_Params& params,
     int* new_routing_id,
+    mojo::MessagePipeHandle* new_interface_provider,
     base::UnguessableToken* devtools_frame_token) {
   *new_routing_id = render_widget_helper_->GetNextRoutingID();
+
+  service_manager::mojom::InterfaceProviderPtr interface_provider;
+  auto interface_provider_request(mojo::MakeRequest(&interface_provider));
+  *new_interface_provider =
+      interface_provider.PassInterface().PassHandle().release();
+
   *devtools_frame_token = base::UnguessableToken::Create();
+
   BrowserThread::PostTask(
       BrowserThread::UI, FROM_HERE,
       base::BindOnce(&CreateChildFrameOnUI, render_process_id_,
                      params.parent_routing_id, params.scope, params.frame_name,
                      params.frame_unique_name, *devtools_frame_token,
                      params.frame_policy, params.frame_owner_properties,
-                     *new_routing_id));
+                     *new_routing_id,
+                     interface_provider_request.PassMessagePipe()));
 }
 
 void RenderFrameMessageFilter::OnCookiesEnabled(int render_frame_id,
diff --git a/content/browser/frame_host/render_frame_message_filter.h b/content/browser/frame_host/render_frame_message_filter.h
index 1826101..95a8c39 100644
--- a/content/browser/frame_host/render_frame_message_filter.h
+++ b/content/browser/frame_host/render_frame_message_filter.h
@@ -27,6 +27,10 @@
 struct FrameHostMsg_DownloadUrl_Params;
 class GURL;
 
+namespace mojo {
+class MessagePipeHandle;
+}
+
 namespace net {
 class URLRequestContext;
 class URLRequestContextGetter;
@@ -92,6 +96,7 @@
   // Browser process defines them for the renderer process.
   void OnCreateChildFrame(const FrameHostMsg_CreateChildFrame_Params& params,
                           int* new_render_frame_id,
+                          mojo::MessagePipeHandle* new_interface_provider,
                           base::UnguessableToken* devtools_frame_token);
   void OnCookiesEnabled(int render_frame_id,
                         const GURL& url,
diff --git a/content/browser/gpu/browser_gpu_channel_host_factory.cc b/content/browser/gpu/browser_gpu_channel_host_factory.cc
index 9555552..cdf4622 100644
--- a/content/browser/gpu/browser_gpu_channel_host_factory.cc
+++ b/content/browser/gpu/browser_gpu_channel_host_factory.cc
@@ -11,6 +11,7 @@
 #include "base/synchronization/waitable_event.h"
 #include "base/threading/thread_restrictions.h"
 #include "base/threading/thread_task_runner_handle.h"
+#include "base/timer/timer.h"
 #include "base/trace_event/memory_dump_manager.h"
 #include "base/trace_event/trace_event.h"
 #include "build/build_config.h"
@@ -23,6 +24,7 @@
 #include "content/public/browser/content_browser_client.h"
 #include "content/public/browser/gpu_data_manager.h"
 #include "content/public/common/content_client.h"
+#include "content/public/common/content_switches.h"
 #include "gpu/command_buffer/service/gpu_switches.h"
 #include "gpu/ipc/common/gpu_messages.h"
 #include "ipc/ipc_channel_handle.h"
@@ -36,6 +38,12 @@
 
 namespace content {
 
+namespace {
+void TimedOut() {
+  LOG(FATAL) << "Timed out waiting for GPU channel.";
+}
+}  // namespace
+
 BrowserGpuChannelHostFactory* BrowserGpuChannelHostFactory::instance_ = NULL;
 
 class BrowserGpuChannelHostFactory::EstablishRequest
@@ -54,8 +62,9 @@
 
  private:
   friend class base::RefCountedThreadSafe<EstablishRequest>;
-  explicit EstablishRequest(int gpu_client_id, uint64_t gpu_client_tracing_id);
+  EstablishRequest(int gpu_client_id, uint64_t gpu_client_tracing_id);
   ~EstablishRequest() {}
+  void RestartTimeout();
   void EstablishOnIO();
   void OnEstablishedOnIO(const IPC::ChannelHandle& channel_handle,
                          const gpu::GPUInfo& gpu_info,
@@ -101,6 +110,12 @@
       finished_(false),
       main_task_runner_(base::ThreadTaskRunnerHandle::Get()) {}
 
+void BrowserGpuChannelHostFactory::EstablishRequest::RestartTimeout() {
+  BrowserGpuChannelHostFactory* factory =
+      BrowserGpuChannelHostFactory::instance();
+  factory->RestartTimeout();
+}
+
 void BrowserGpuChannelHostFactory::EstablishRequest::EstablishOnIO() {
   GpuProcessHost* host = GpuProcessHost::Get();
   if (!host) {
@@ -129,6 +144,11 @@
       status == GpuProcessHost::EstablishChannelStatus::GPU_HOST_INVALID) {
     DVLOG(1) << "Failed to create channel on existing GPU process. Trying to "
                 "restart GPU process.";
+    main_task_runner_->PostTask(
+        FROM_HERE,
+        base::BindOnce(
+            &BrowserGpuChannelHostFactory::EstablishRequest::RestartTimeout,
+            this));
     EstablishOnIO();
     return;
   }
@@ -267,6 +287,7 @@
     // We should only get here if the context was lost.
     pending_request_ =
         EstablishRequest::Create(gpu_client_id_, gpu_client_tracing_id_);
+    RestartTimeout();
   }
 
   if (!callback.is_null()) {
@@ -320,6 +341,7 @@
         gpu_memory_buffer_manager_.get());
   }
   pending_request_ = NULL;
+  timeout_.Stop();
 
   std::vector<gpu::GpuChannelEstablishedCallback> established_callbacks;
   established_callbacks_.swap(established_callbacks);
@@ -327,6 +349,35 @@
     callback.Run(gpu_channel_);
 }
 
+void BrowserGpuChannelHostFactory::RestartTimeout() {
+  DCHECK(IsMainThread());
+#if defined(OS_ANDROID)
+  if (base::CommandLine::ForCurrentProcess()->HasSwitch(
+          switches::kDisableTimeoutsForProfiling)) {
+    return;
+  }
+#else
+  // Only implement timeout on Android, which does not have a software fallback.
+  return;
+#endif
+
+  if (!pending_request_)
+    return;
+
+#if defined(ADDRESS_SANITIZER) || defined(THREAD_SANITIZER) || \
+    defined(SYZYASAN) || defined(CYGPROFILE_INSTRUMENTATION)
+  constexpr int64_t kGpuChannelTimeoutInSeconds = 40;
+#else
+  // The GPU watchdog timeout is 15 seconds (1.5x the kGpuTimeout value due to
+  // logic in GpuWatchdogThread). Make this slightly longer to give the GPU a
+  // chance to crash itself before crashing the browser.
+  constexpr int64_t kGpuChannelTimeoutInSeconds = 20;
+#endif
+  timeout_.Start(FROM_HERE,
+                 base::TimeDelta::FromSeconds(kGpuChannelTimeoutInSeconds),
+                 base::Bind(&TimedOut));
+}
+
 // static
 void BrowserGpuChannelHostFactory::InitializeShaderDiskCacheOnIO(
     int gpu_client_id,
diff --git a/content/browser/gpu/browser_gpu_channel_host_factory.h b/content/browser/gpu/browser_gpu_channel_host_factory.h
index a2ba4d1..1bbbe530 100644
--- a/content/browser/gpu/browser_gpu_channel_host_factory.h
+++ b/content/browser/gpu/browser_gpu_channel_host_factory.h
@@ -60,6 +60,7 @@
   ~BrowserGpuChannelHostFactory() override;
 
   void GpuChannelEstablished();
+  void RestartTimeout();
 
   static void InitializeShaderDiskCacheOnIO(int gpu_client_id,
                                             const base::FilePath& cache_dir);
@@ -72,6 +73,8 @@
   scoped_refptr<EstablishRequest> pending_request_;
   std::vector<gpu::GpuChannelEstablishedCallback> established_callbacks_;
 
+  base::OneShotTimer timeout_;
+
   static BrowserGpuChannelHostFactory* instance_;
 
   DISALLOW_COPY_AND_ASSIGN(BrowserGpuChannelHostFactory);
diff --git a/content/browser/gpu/compositor_util.cc b/content/browser/gpu/compositor_util.cc
index 937c9af..7ab507c1 100644
--- a/content/browser/gpu/compositor_util.cc
+++ b/content/browser/gpu/compositor_util.cc
@@ -24,7 +24,6 @@
 #include "content/public/common/content_switches.h"
 #include "gpu/config/gpu_feature_type.h"
 #include "gpu/config/gpu_finch_features.h"
-#include "gpu/config/gpu_switches.h"
 #include "gpu/ipc/host/gpu_memory_buffer_support.h"
 #include "media/media_features.h"
 #include "ui/gl/gl_switches.h"
@@ -33,6 +32,12 @@
 
 namespace {
 
+static bool IsGpuRasterizationBlacklisted() {
+  GpuDataManagerImpl* manager = GpuDataManagerImpl::GetInstance();
+  return manager->IsFeatureBlacklisted(
+        gpu::GPU_FEATURE_TYPE_GPU_RASTERIZATION);
+}
+
 const char kGpuCompositingFeatureName[] = "gpu_compositing";
 const char kWebGLFeatureName[] = "webgl";
 const char kRasterizationFeatureName[] = "rasterization";
@@ -46,101 +51,106 @@
 
 const int kMinMSAASampleCount = 0;
 
-struct GpuFeatureData {
+struct GpuFeatureInfo {
   std::string name;
-  gpu::GpuFeatureStatus status;
+  bool blocked;
   bool disabled;
   std::string disabled_description;
   bool fallback_to_software;
 };
 
-bool IsForceGpuRasterizationEnabled() {
-  base::CommandLine* command_line = base::CommandLine::ForCurrentProcess();
-  return command_line->HasSwitch(switches::kForceGpuRasterization);
-}
-
-const GpuFeatureData GetGpuFeatureData(size_t index, bool* eof) {
+const GpuFeatureInfo GetGpuFeatureInfo(size_t index, bool* eof) {
   const base::CommandLine& command_line =
       *base::CommandLine::ForCurrentProcess();
   GpuDataManagerImpl* manager = GpuDataManagerImpl::GetInstance();
 
-  const GpuFeatureData kGpuFeatureData[] = {
+  const GpuFeatureInfo kGpuFeatureInfo[] = {
     {"2d_canvas",
-     manager->GetFeatureStatus(gpu::GPU_FEATURE_TYPE_ACCELERATED_2D_CANVAS),
+     manager->IsFeatureBlacklisted(gpu::GPU_FEATURE_TYPE_ACCELERATED_2D_CANVAS),
      command_line.HasSwitch(switches::kDisableAccelerated2dCanvas),
      "Accelerated 2D canvas is unavailable: either disabled via blacklist or"
      " the command line.",
      true},
     {kGpuCompositingFeatureName,
-     manager->GetFeatureStatus(gpu::GPU_FEATURE_TYPE_GPU_COMPOSITING),
+     manager->IsFeatureBlacklisted(gpu::GPU_FEATURE_TYPE_GPU_COMPOSITING),
      command_line.HasSwitch(switches::kDisableGpuCompositing),
      "Gpu compositing has been disabled, either via blacklist, about:flags"
      " or the command line. The browser will fall back to software compositing"
      " and hardware acceleration will be unavailable.",
      true},
-    {kWebGLFeatureName,
-     manager->GetFeatureStatus(gpu::GPU_FEATURE_TYPE_ACCELERATED_WEBGL),
+    {kWebGLFeatureName, !manager->IsWebGLEnabled(),
      command_line.HasSwitch(switches::kDisableWebGL),
      "WebGL has been disabled via blacklist or the command line.", false},
-    {"flash_3d", manager->GetFeatureStatus(gpu::GPU_FEATURE_TYPE_FLASH3D),
+    {"flash_3d", manager->IsFeatureBlacklisted(gpu::GPU_FEATURE_TYPE_FLASH3D),
      command_line.HasSwitch(switches::kDisableFlash3d),
      "Using 3d in flash has been disabled, either via blacklist, about:flags or"
      " the command line.",
      true},
     {"flash_stage3d",
-     manager->GetFeatureStatus(gpu::GPU_FEATURE_TYPE_FLASH_STAGE3D),
+     manager->IsFeatureBlacklisted(gpu::GPU_FEATURE_TYPE_FLASH_STAGE3D),
      command_line.HasSwitch(switches::kDisableFlashStage3d),
      "Using Stage3d in Flash has been disabled, either via blacklist,"
      " about:flags or the command line.",
      true},
     {"flash_stage3d_baseline",
-     manager->GetFeatureStatus(gpu::GPU_FEATURE_TYPE_FLASH_STAGE3D_BASELINE),
+     manager->IsFeatureBlacklisted(
+         gpu::GPU_FEATURE_TYPE_FLASH_STAGE3D_BASELINE) ||
+         manager->IsFeatureBlacklisted(gpu::GPU_FEATURE_TYPE_FLASH_STAGE3D),
      command_line.HasSwitch(switches::kDisableFlashStage3d),
      "Using Stage3d Baseline profile in Flash has been disabled, either"
      " via blacklist, about:flags or the command line.",
      true},
     {"video_decode",
-     manager->GetFeatureStatus(gpu::GPU_FEATURE_TYPE_ACCELERATED_VIDEO_DECODE),
+     manager->IsFeatureBlacklisted(
+         gpu::GPU_FEATURE_TYPE_ACCELERATED_VIDEO_DECODE),
      command_line.HasSwitch(switches::kDisableAcceleratedVideoDecode),
      "Accelerated video decode has been disabled, either via blacklist,"
      " about:flags or the command line.",
      true},
+#if BUILDFLAG(ENABLE_WEBRTC)
+    {"video_encode",
+     manager->IsFeatureBlacklisted(
+         gpu::GPU_FEATURE_TYPE_ACCELERATED_VIDEO_ENCODE),
+     command_line.HasSwitch(switches::kDisableWebRtcHWEncoding),
+     "Accelerated video encode has been disabled, either via blacklist,"
+     " about:flags or the command line.",
+     true},
+#endif
 #if defined(OS_CHROMEOS)
     {"panel_fitting",
-     manager->GetFeatureStatus(gpu::GPU_FEATURE_TYPE_PANEL_FITTING),
+     manager->IsFeatureBlacklisted(gpu::GPU_FEATURE_TYPE_PANEL_FITTING),
      command_line.HasSwitch(switches::kDisablePanelFitting),
      "Panel fitting has been disabled, either via blacklist, about:flags or"
      " the command line.",
      false},
 #endif
     {kRasterizationFeatureName,
-     manager->GetFeatureStatus(gpu::GPU_FEATURE_TYPE_GPU_RASTERIZATION),
-     (command_line.HasSwitch(switches::kDisableGpuRasterization) &&
-      !IsForceGpuRasterizationEnabled()),
+     IsGpuRasterizationBlacklisted() && !IsGpuRasterizationEnabled() &&
+         !IsForceGpuRasterizationEnabled(),
+     !IsGpuRasterizationEnabled() && !IsForceGpuRasterizationEnabled() &&
+         !IsGpuRasterizationBlacklisted(),
      "Accelerated rasterization has been disabled, either via blacklist,"
      " about:flags or the command line.",
      true},
-    {kMultipleRasterThreadsFeatureName, gpu::kGpuFeatureStatusEnabled,
+    {kMultipleRasterThreadsFeatureName, false,
      NumberOfRendererRasterThreads() == 1, "Raster is using a single thread.",
      false},
-    {kNativeGpuMemoryBuffersFeatureName, gpu::kGpuFeatureStatusEnabled,
+    {kNativeGpuMemoryBuffersFeatureName, false,
      !gpu::AreNativeGpuMemoryBuffersEnabled(),
      "Native GpuMemoryBuffers have been disabled, either via about:flags"
      " or command line.",
      true},
-    {kWebGL2FeatureName,
-     manager->GetFeatureStatus(gpu::GPU_FEATURE_TYPE_ACCELERATED_WEBGL2),
-     (command_line.HasSwitch(switches::kDisableWebGL) ||
-      command_line.HasSwitch(switches::kDisableWebGL2)),
+    {kWebGL2FeatureName, !manager->IsWebGL2Enabled(),
+     command_line.HasSwitch(switches::kDisableWebGL) ||
+         command_line.HasSwitch(switches::kDisableWebGL2),
      "WebGL2 has been disabled via blacklist or the command line.", false},
-    {kCheckerImagingFeatureName, gpu::kGpuFeatureStatusEnabled,
-     !IsCheckerImagingEnabled(),
+    {kCheckerImagingFeatureName, false, !IsCheckerImagingEnabled(),
      "Checker-imaging has been disabled via finch trial or the command line.",
      false},
   };
-  DCHECK(index < arraysize(kGpuFeatureData));
-  *eof = (index == arraysize(kGpuFeatureData) - 1);
-  return kGpuFeatureData[index];
+  DCHECK(index < arraysize(kGpuFeatureInfo));
+  *eof = (index == arraysize(kGpuFeatureInfo) - 1);
+  return kGpuFeatureInfo[index];
 }
 
 }  // namespace
@@ -219,6 +229,17 @@
 #endif
 }
 
+bool IsGpuRasterizationEnabled() {
+  GpuDataManagerImpl* manager = GpuDataManagerImpl::GetInstance();
+  return manager->IsFeatureEnabled(gpu::GPU_FEATURE_TYPE_GPU_RASTERIZATION);
+}
+
+bool IsForceGpuRasterizationEnabled() {
+  const base::CommandLine& command_line =
+      *base::CommandLine::ForCurrentProcess();
+  return command_line.HasSwitch(switches::kForceGpuRasterization);
+}
+
 int GpuRasterizationMSAASampleCount() {
   const base::CommandLine& command_line =
       *base::CommandLine::ForCurrentProcess();
@@ -299,39 +320,40 @@
 
   bool eof = false;
   for (size_t i = 0; !eof; ++i) {
-    const GpuFeatureData gpu_feature_data = GetGpuFeatureData(i, &eof);
+    const GpuFeatureInfo gpu_feature_info = GetGpuFeatureInfo(i, &eof);
     std::string status;
-    if (gpu_feature_data.disabled || gpu_access_blocked) {
+    if (gpu_feature_info.disabled) {
       status = "disabled";
-      if (gpu_feature_data.fallback_to_software)
+      if (gpu_feature_info.fallback_to_software)
         status += "_software";
       else
         status += "_off";
-    } else if (gpu_feature_data.status == gpu::kGpuFeatureStatusBlacklisted) {
-      status = "unavailable_off";
-    } else if (gpu_feature_data.status == gpu::kGpuFeatureStatusSoftware) {
-      status = "unavailable_software";
+    } else if (gpu_feature_info.blocked ||
+               gpu_access_blocked) {
+      status = "unavailable";
+      if (gpu_feature_info.fallback_to_software)
+        status += "_software";
+      else
+        status += "_off";
     } else {
       status = "enabled";
-      if ((gpu_feature_data.name == kWebGLFeatureName ||
-           gpu_feature_data.name == kWebGL2FeatureName) &&
-          (manager->GetFeatureStatus(gpu::GPU_FEATURE_TYPE_GPU_COMPOSITING) !=
-           gpu::kGpuFeatureStatusEnabled)) {
+      if ((gpu_feature_info.name == kWebGLFeatureName ||
+           gpu_feature_info.name == kWebGL2FeatureName) &&
+          manager->IsFeatureBlacklisted(gpu::GPU_FEATURE_TYPE_GPU_COMPOSITING))
         status += "_readback";
-      }
-      if (gpu_feature_data.name == kRasterizationFeatureName) {
+      if (gpu_feature_info.name == kRasterizationFeatureName) {
         if (IsForceGpuRasterizationEnabled())
           status += "_force";
       }
-      if (gpu_feature_data.name == kMultipleRasterThreadsFeatureName) {
+      if (gpu_feature_info.name == kMultipleRasterThreadsFeatureName) {
         const base::CommandLine& command_line =
             *base::CommandLine::ForCurrentProcess();
         if (command_line.HasSwitch(switches::kNumRasterThreads))
           status += "_force";
       }
-      if (gpu_feature_data.name == kMultipleRasterThreadsFeatureName)
+      if (gpu_feature_info.name == kMultipleRasterThreadsFeatureName)
         status += "_on";
-      if (gpu_feature_data.name == kCheckerImagingFeatureName) {
+      if (gpu_feature_info.name == kCheckerImagingFeatureName) {
         const base::CommandLine& command_line =
             *base::CommandLine::ForCurrentProcess();
         if (command_line.HasSwitch(cc::switches::kEnableCheckerImaging))
@@ -339,7 +361,14 @@
         status += "_on";
       }
     }
-    feature_status_dict->SetString(gpu_feature_data.name, status);
+    if ((gpu_feature_info.name == kWebGLFeatureName ||
+         gpu_feature_info.name == kWebGL2FeatureName) &&
+        (gpu_feature_info.blocked || gpu_access_blocked) &&
+        manager->ShouldUseSwiftShader()) {
+      status = "unavailable_software";
+    }
+
+    feature_status_dict->SetString(gpu_feature_info.name, status);
   }
   return feature_status_dict;
 }
@@ -367,13 +396,14 @@
 
   bool eof = false;
   for (size_t i = 0; !eof; ++i) {
-    const GpuFeatureData gpu_feature_data = GetGpuFeatureData(i, &eof);
-    if (gpu_feature_data.disabled) {
-      auto problem = std::make_unique<base::DictionaryValue>();
-      problem->SetString("description", gpu_feature_data.disabled_description);
-      problem->Set("crBugs", std::make_unique<base::ListValue>());
-      auto disabled_features = std::make_unique<base::ListValue>();
-      disabled_features->AppendString(gpu_feature_data.name);
+    const GpuFeatureInfo gpu_feature_info = GetGpuFeatureInfo(i, &eof);
+    if (gpu_feature_info.disabled) {
+      auto problem = base::MakeUnique<base::DictionaryValue>();
+      problem->SetString(
+          "description", gpu_feature_info.disabled_description);
+      problem->Set("crBugs", base::MakeUnique<base::ListValue>());
+      auto disabled_features = base::MakeUnique<base::ListValue>();
+      disabled_features->AppendString(gpu_feature_info.name);
       problem->Set("affectedGpuSettings", std::move(disabled_features));
       problem->SetString("tag", "disabledFeatures");
       problem_list->Append(std::move(problem));
diff --git a/content/browser/gpu/compositor_util.h b/content/browser/gpu/compositor_util.h
index 01fc8bc..139a9d7e 100644
--- a/content/browser/gpu/compositor_util.h
+++ b/content/browser/gpu/compositor_util.h
@@ -26,10 +26,16 @@
 // Returns true if all compositor resources should use GPU memory buffers.
 CONTENT_EXPORT bool IsGpuMemoryBufferCompositorResourcesEnabled();
 
+// Returns true if gpu rasterization is on (via flags) for the renderer.
+CONTENT_EXPORT bool IsGpuRasterizationEnabled();
+
 // Returns the number of multisample antialiasing samples (via flags) for
 // GPU rasterization.
 CONTENT_EXPORT int GpuRasterizationMSAASampleCount();
 
+// Returns true if force-gpu-rasterization is on (via flags) for the renderer.
+CONTENT_EXPORT bool IsForceGpuRasterizationEnabled();
+
 // Returns the number of raster threads to use for compositing.
 CONTENT_EXPORT int NumberOfRendererRasterThreads();
 
diff --git a/content/browser/gpu/gpu_data_manager_impl.cc b/content/browser/gpu/gpu_data_manager_impl.cc
index 2cd8402..5a3d62c 100644
--- a/content/browser/gpu/gpu_data_manager_impl.cc
+++ b/content/browser/gpu/gpu_data_manager_impl.cc
@@ -20,11 +20,43 @@
 }
 
 void GpuDataManagerImpl::BlacklistWebGLForTesting() {
+  // Manually generate the following data instead of going through
+  // gpu/config/process_json.py because this is just one simple instance.
+  static const int kFeatureListForEntry0[1] = {
+      gpu::GPU_FEATURE_TYPE_ACCELERATED_WEBGL};
+  static const gpu::GpuControlList::Entry kEntry = {
+      1,  // id
+      "ExtensionWebstoreGetWebGLStatusTest.Blocked",
+      arraysize(kFeatureListForEntry0),  // features size
+      kFeatureListForEntry0,             // features
+      0,                                 // DisabledExtensions size
+      nullptr,                           // DisabledExtensions
+      0,                                 // CrBugs size
+      nullptr,                           // CrBugs
+      {
+          gpu::GpuControlList::kOsAny,  // os_type
+          {gpu::GpuControlList::kUnknown,
+           gpu::GpuControlList::kVersionStyleNumerical, nullptr,
+           nullptr},                                   // os_version
+          0x00,                                        // vendor_id
+          0,                                           // DeviceIDs size
+          nullptr,                                     // DeviceIDs
+          gpu::GpuControlList::kMultiGpuCategoryNone,  // multi_gpu_category
+          gpu::GpuControlList::kMultiGpuStyleNone,     // multi_gpu_style
+          nullptr,                                     // driver info
+          nullptr,                                     // GL strings
+          nullptr,                                     // machine model info
+          nullptr,                                     // more conditions
+      },
+      0,        // exceptions count
+      nullptr,  // exceptions
+  };
+  static const gpu::GpuControlListData kData(1, &kEntry);
+
+  gpu::GPUInfo gpu_info;
+
   base::AutoLock auto_lock(lock_);
-  gpu::GpuFeatureInfo gpu_feature_info;
-  gpu_feature_info.status_values[gpu::GPU_FEATURE_TYPE_ACCELERATED_WEBGL] =
-      gpu::kGpuFeatureStatusBlacklisted;
-  private_->UpdateGpuFeatureInfo(gpu_feature_info);
+  private_->InitializeForTesting(kData, gpu_info);
 }
 
 void GpuDataManagerImpl::InitializeForTesting(
@@ -39,6 +71,21 @@
   return private_->IsFeatureBlacklisted(feature);
 }
 
+bool GpuDataManagerImpl::IsFeatureEnabled(int feature) const {
+  base::AutoLock auto_lock(lock_);
+  return private_->IsFeatureEnabled(feature);
+}
+
+bool GpuDataManagerImpl::IsWebGLEnabled() const {
+  base::AutoLock auto_lock(lock_);
+  return private_->IsWebGLEnabled();
+}
+
+bool GpuDataManagerImpl::IsWebGL2Enabled() const {
+  base::AutoLock auto_lock(lock_);
+  return private_->IsWebGL2Enabled();
+}
+
 gpu::GPUInfo GpuDataManagerImpl::GetGPUInfo() const {
   base::AutoLock auto_lock(lock_);
   return private_->GetGPUInfo();
@@ -59,6 +106,11 @@
   return private_->IsEssentialGpuInfoAvailable();
 }
 
+bool GpuDataManagerImpl::IsCompleteGpuInfoAvailable() const {
+  base::AutoLock auto_lock(lock_);
+  return private_->IsCompleteGpuInfoAvailable();
+}
+
 void GpuDataManagerImpl::RequestVideoMemoryUsageStatsUpdate(
     const base::Callback<void(const gpu::VideoMemoryUsageStats& stats)>&
         callback) const {
@@ -150,17 +202,6 @@
   return private_->GetGpuFeatureInfo();
 }
 
-gpu::GpuFeatureStatus GpuDataManagerImpl::GetFeatureStatus(
-    gpu::GpuFeatureType feature) const {
-  base::AutoLock auto_lock(lock_);
-  return private_->GetFeatureStatus(feature);
-}
-
-bool GpuDataManagerImpl::IsGpuFeatureInfoAvailable() const {
-  base::AutoLock auto_lock(lock_);
-  return private_->IsGpuFeatureInfoAvailable();
-}
-
 void GpuDataManagerImpl::AppendRendererCommandLine(
     base::CommandLine* command_line) const {
   base::AutoLock auto_lock(lock_);
diff --git a/content/browser/gpu/gpu_data_manager_impl.h b/content/browser/gpu/gpu_data_manager_impl.h
index 1b6dc1e..ebaf2b9 100644
--- a/content/browser/gpu/gpu_data_manager_impl.h
+++ b/content/browser/gpu/gpu_data_manager_impl.h
@@ -22,6 +22,7 @@
 #include "content/public/browser/gpu_data_manager.h"
 #include "content/public/common/three_d_api_types.h"
 #include "gpu/config/gpu_control_list.h"
+#include "gpu/config/gpu_feature_info.h"
 #include "gpu/config/gpu_info.h"
 
 class GURL;
@@ -66,12 +67,14 @@
   // GpuDataManager implementation.
   void BlacklistWebGLForTesting() override;
   bool IsFeatureBlacklisted(int feature) const override;
-  gpu::GpuFeatureStatus GetFeatureStatus(
-      gpu::GpuFeatureType feature) const override;
+  bool IsFeatureEnabled(int feature) const override;
+  bool IsWebGLEnabled() const override;
+  bool IsWebGL2Enabled() const override;
   gpu::GPUInfo GetGPUInfo() const override;
   bool GpuAccessAllowed(std::string* reason) const override;
   void RequestCompleteGpuInfoIfNeeded() override;
   bool IsEssentialGpuInfoAvailable() const override;
+  bool IsCompleteGpuInfoAvailable() const override;
   void RequestVideoMemoryUsageStatsUpdate(
       const base::Callback<void(const gpu::VideoMemoryUsageStats& stats)>&
           callback) const override;
@@ -113,7 +116,6 @@
   void UpdateGpuFeatureInfo(const gpu::GpuFeatureInfo& gpu_feature_info);
 
   gpu::GpuFeatureInfo GetGpuFeatureInfo() const;
-  bool IsGpuFeatureInfoAvailable() const;
 
   // Insert disable-feature switches corresponding to preliminary gpu feature
   // flags into the renderer process command line.
diff --git a/content/browser/gpu/gpu_data_manager_impl_private.cc b/content/browser/gpu/gpu_data_manager_impl_private.cc
index 3bdfd595..f9f6543 100644
--- a/content/browser/gpu/gpu_data_manager_impl_private.cc
+++ b/content/browser/gpu/gpu_data_manager_impl_private.cc
@@ -349,6 +349,23 @@
   return use_swiftshader_ || (blacklisted_features_.count(feature) == 1);
 }
 
+bool GpuDataManagerImplPrivate::IsFeatureEnabled(int feature) const {
+  DCHECK_EQ(feature, gpu::GPU_FEATURE_TYPE_GPU_RASTERIZATION);
+  return gpu_feature_info_
+             .status_values[gpu::GPU_FEATURE_TYPE_GPU_RASTERIZATION] ==
+         gpu::kGpuFeatureStatusEnabled;
+}
+
+bool GpuDataManagerImplPrivate::IsWebGLEnabled() const {
+  return use_swiftshader_ ||
+         !blacklisted_features_.count(gpu::GPU_FEATURE_TYPE_ACCELERATED_WEBGL);
+}
+
+bool GpuDataManagerImplPrivate::IsWebGL2Enabled() const {
+  return /*use_swiftshader_ ||*/ // Uncomment to enable WebGL 2 with SwiftShader
+         !blacklisted_features_.count(gpu::GPU_FEATURE_TYPE_ACCELERATED_WEBGL2);
+}
+
 size_t GpuDataManagerImplPrivate::GetBlacklistedFeatureCount() const {
   // SwiftShader blacklists all features
   return use_swiftshader_ ? gpu::NUMBER_OF_GPU_FEATURE_TYPES
@@ -684,21 +701,17 @@
 
 void GpuDataManagerImplPrivate::UpdateGpuFeatureInfo(
     const gpu::GpuFeatureInfo& gpu_feature_info) {
-  gpu_feature_info_ = gpu_feature_info;
-  gpu_feature_info_available_ = true;
-  UpdateDriverBugListStats(gpu_feature_info);
+  if (!use_swiftshader_) {
+    gpu_feature_info_ = gpu_feature_info;
+    UpdateDriverBugListStats(gpu_feature_info);
+    NotifyGpuInfoUpdate();
+  }
 }
 
 gpu::GpuFeatureInfo GpuDataManagerImplPrivate::GetGpuFeatureInfo() const {
   return gpu_feature_info_;
 }
 
-gpu::GpuFeatureStatus GpuDataManagerImplPrivate::GetFeatureStatus(
-    gpu::GpuFeatureType feature) const {
-  DCHECK(feature >= 0 && feature < gpu::NUMBER_OF_GPU_FEATURE_TYPES);
-  return gpu_feature_info_.status_values[feature];
-}
-
 void GpuDataManagerImplPrivate::AppendRendererCommandLine(
     base::CommandLine* command_line) const {
   DCHECK(command_line);
diff --git a/content/browser/gpu/gpu_data_manager_impl_private.h b/content/browser/gpu/gpu_data_manager_impl_private.h
index 830e070..8862506d 100644
--- a/content/browser/gpu/gpu_data_manager_impl_private.h
+++ b/content/browser/gpu/gpu_data_manager_impl_private.h
@@ -43,12 +43,14 @@
   void InitializeForTesting(const gpu::GpuControlListData& gpu_blacklist_data,
                             const gpu::GPUInfo& gpu_info);
   bool IsFeatureBlacklisted(int feature) const;
+  bool IsFeatureEnabled(int feature) const;
+  bool IsWebGLEnabled() const;
+  bool IsWebGL2Enabled() const;
   gpu::GPUInfo GetGPUInfo() const;
   bool GpuAccessAllowed(std::string* reason) const;
   void RequestCompleteGpuInfoIfNeeded();
   bool IsEssentialGpuInfoAvailable() const;
   bool IsCompleteGpuInfoAvailable() const;
-  bool IsGpuFeatureInfoAvailable() const { return gpu_feature_info_available_; }
   void RequestVideoMemoryUsageStatsUpdate(
       const base::Callback<void(const gpu::VideoMemoryUsageStats& stats)>&
           callback) const;
@@ -70,7 +72,6 @@
   void UpdateGpuInfo(const gpu::GPUInfo& gpu_info);
   void UpdateGpuFeatureInfo(const gpu::GpuFeatureInfo& gpu_feature_info);
   gpu::GpuFeatureInfo GetGpuFeatureInfo() const;
-  gpu::GpuFeatureStatus GetFeatureStatus(gpu::GpuFeatureType feature) const;
 
   void AppendRendererCommandLine(base::CommandLine* command_line) const;
 
@@ -227,7 +228,6 @@
 
   // Eventually |blacklisted_features_| should be folded in to this.
   gpu::GpuFeatureInfo gpu_feature_info_;
-  bool gpu_feature_info_available_ = false;
 
   gpu::GPUInfo gpu_info_;
 
diff --git a/content/browser/gpu/gpu_data_manager_testing_arrays_and_structs_autogen.h b/content/browser/gpu/gpu_data_manager_testing_arrays_and_structs_autogen.h
index ed7833c..eae84643 100644
--- a/content/browser/gpu/gpu_data_manager_testing_arrays_and_structs_autogen.h
+++ b/content/browser/gpu/gpu_data_manager_testing_arrays_and_structs_autogen.h
@@ -94,7 +94,7 @@
      nullptr},  // driver_date
 };
 
-const int kFeatureListForEntry9[10] = {
+const int kFeatureListForEntry9[11] = {
     GPU_FEATURE_TYPE_FLASH_STAGE3D,
     GPU_FEATURE_TYPE_GPU_COMPOSITING,
     GPU_FEATURE_TYPE_PANEL_FITTING,
@@ -105,6 +105,7 @@
     GPU_FEATURE_TYPE_ACCELERATED_WEBGL2,
     GPU_FEATURE_TYPE_ACCELERATED_WEBGL,
     GPU_FEATURE_TYPE_FLASH_STAGE3D_BASELINE,
+    GPU_FEATURE_TYPE_ACCELERATED_VIDEO_ENCODE,
 };
 
 const int kFeatureListForEntry10[1] = {
diff --git a/content/browser/gpu/gpu_feature_checker_impl.cc b/content/browser/gpu/gpu_feature_checker_impl.cc
index e7664a1..1e3f5c3 100644
--- a/content/browser/gpu/gpu_feature_checker_impl.cc
+++ b/content/browser/gpu/gpu_feature_checker_impl.cc
@@ -6,8 +6,8 @@
 
 #include "base/logging.h"
 #include "build/build_config.h"
-#include "content/browser/gpu/gpu_data_manager_impl.h"
 #include "content/public/browser/browser_thread.h"
+#include "content/public/browser/gpu_data_manager.h"
 
 namespace content {
 
@@ -15,13 +15,9 @@
 
 // A false return value is always valid, but a true one is only valid if full
 // GPU info has been collected in a GPU process.
-bool IsFeatureAllowed(GpuDataManagerImpl* manager,
-                      gpu::GpuFeatureType feature) {
-  // This is mostly for WebStore checking WebGL status, therefore, don't return
-  // yes if WebGL is rendering on software, because user experience on the app
-  // won't be good in most cases.
-  return (manager->GpuAccessAllowed(nullptr) &&
-          manager->GetFeatureStatus(feature) == gpu::kGpuFeatureStatusEnabled);
+bool IsFeatureAllowed(GpuDataManager* manager, gpu::GpuFeatureType feature) {
+  return (manager->GpuAccessAllowed(NULL) &&
+          !manager->IsFeatureBlacklisted(feature));
 }
 
 }  // namespace
@@ -42,27 +38,41 @@
 void GpuFeatureCheckerImpl::CheckGpuFeatureAvailability() {
   CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
 
-  GpuDataManagerImpl* manager = GpuDataManagerImpl::GetInstance();
-  if (!manager->IsGpuFeatureInfoAvailable()) {
-    AddRef();
-    manager->AddObserver(this);
-    return;
-  }
+  bool finalized = true;
+#if defined(OS_LINUX)
+  // On Windows and Mac, so far we can always make the final WebGL blacklisting
+  // decision based on partial GPU info; on Linux, we need to launch the GPU
+  // process to collect full GPU info and make the final decision.
+  finalized = false;
+#endif
+
+  GpuDataManager* manager = GpuDataManager::GetInstance();
+  if (manager->IsEssentialGpuInfoAvailable())
+    finalized = true;
 
   bool feature_allowed = IsFeatureAllowed(manager, feature_);
-  callback_.Run(feature_allowed);
+  if (!feature_allowed)
+    finalized = true;
+
+  if (finalized) {
+    callback_.Run(feature_allowed);
+  } else {
+    // Matched with a Release in OnGpuInfoUpdate.
+    AddRef();
+
+    manager->AddObserver(this);
+    manager->RequestCompleteGpuInfoIfNeeded();
+  }
 }
 
 void GpuFeatureCheckerImpl::OnGpuInfoUpdate() {
-  GpuDataManagerImpl* manager = GpuDataManagerImpl::GetInstance();
-  if (manager->IsGpuFeatureInfoAvailable()) {
-    manager->RemoveObserver(this);
-    bool feature_allowed = IsFeatureAllowed(manager, feature_);
-    callback_.Run(feature_allowed);
+  GpuDataManager* manager = GpuDataManager::GetInstance();
+  manager->RemoveObserver(this);
+  bool feature_allowed = IsFeatureAllowed(manager, feature_);
+  callback_.Run(feature_allowed);
 
-    // Matches the AddRef in CheckGpuFeatureAvailability().
-    Release();
-  }
+  // Matches the AddRef in CheckGpuFeatureAvailability().
+  Release();
 }
 
 }  // namespace content
diff --git a/content/browser/gpu/gpu_process_host.cc b/content/browser/gpu/gpu_process_host.cc
index 1dc7eca7..d960e56 100644
--- a/content/browser/gpu/gpu_process_host.cc
+++ b/content/browser/gpu/gpu_process_host.cc
@@ -867,10 +867,8 @@
 
   GpuDataManagerImpl* gpu_data_manager = GpuDataManagerImpl::GetInstance();
   if (!gpu_data_manager->ShouldUseSwiftShader()) {
-    // UpdateGpuFeatureInfo() needs to be called before UpdateGpuInfo() because
-    // the latter will trigger registered callbacks waiting for the update.
-    gpu_data_manager->UpdateGpuFeatureInfo(gpu_feature_info);
     gpu_data_manager->UpdateGpuInfo(gpu_info);
+    gpu_data_manager->UpdateGpuFeatureInfo(gpu_feature_info);
   }
   RunRequestGPUInfoCallbacks(gpu_data_manager->GetGPUInfo());
 }
diff --git a/content/browser/loader/navigation_url_loader_delegate.h b/content/browser/loader/navigation_url_loader_delegate.h
index 2dbb64f..4173383 100644
--- a/content/browser/loader/navigation_url_loader_delegate.h
+++ b/content/browser/loader/navigation_url_loader_delegate.h
@@ -9,8 +9,8 @@
 
 #include "base/macros.h"
 #include "base/memory/ref_counted.h"
+#include "base/optional.h"
 #include "content/common/content_export.h"
-#include "content/public/common/url_loader_factory.mojom.h"
 #include "mojo/public/cpp/system/data_pipe.h"
 
 namespace net {
@@ -25,6 +25,7 @@
 struct GlobalRequestID;
 struct ResourceResponse;
 struct SSLStatus;
+struct SubresourceLoaderParams;
 
 // PlzNavigate: The delegate interface to NavigationURLLoader.
 class CONTENT_EXPORT NavigationURLLoaderDelegate {
@@ -40,9 +41,10 @@
   // |body_stream|. |navigation_data| is passed to the NavigationHandle.
   // If --enable-network-service, then |consumer_handle| will be used,
   // otherwise |body_stream|. Only one of these will ever be non-null.
-  // |subresource_url_loader_factory_info| is used in the network service only
-  // for passing factories which are interested in handling subresource
-  // requests like AppCache.
+  // |subresource_loader_params| is used in the network service only
+  // for passing necessary info to create a custom subresource loader in
+  // the renderer process if the navigated context is controlled by a request
+  // interceptor like AppCache or ServiceWorker.
   virtual void OnResponseStarted(
       const scoped_refptr<ResourceResponse>& response,
       std::unique_ptr<StreamHandle> body_stream,
@@ -52,7 +54,7 @@
       const GlobalRequestID& request_id,
       bool is_download,
       bool is_stream,
-      mojom::URLLoaderFactoryPtrInfo subresource_url_loader_factory_info) = 0;
+      base::Optional<SubresourceLoaderParams> subresource_loader_params) = 0;
 
   // Called if the request fails before receving a response. |net_error| is a
   // network error code for the failure. |has_stale_copy_in_cache| is true if
diff --git a/content/browser/loader/navigation_url_loader_impl.cc b/content/browser/loader/navigation_url_loader_impl.cc
index 801d3104..33e67ad 100644
--- a/content/browser/loader/navigation_url_loader_impl.cc
+++ b/content/browser/loader/navigation_url_loader_impl.cc
@@ -16,6 +16,7 @@
 #include "content/browser/loader/navigation_url_loader_delegate.h"
 #include "content/browser/loader/navigation_url_loader_impl_core.h"
 #include "content/browser/service_worker/service_worker_navigation_handle.h"
+#include "content/common/navigation_subresource_loader_params.h"
 #include "content/public/browser/browser_context.h"
 #include "content/public/browser/browser_thread.h"
 #include "content/public/browser/global_request_id.h"
@@ -107,10 +108,10 @@
     bool is_stream) {
   DCHECK_CURRENTLY_ON(BrowserThread::UI);
 
-  delegate_->OnResponseStarted(
-      response, std::move(body), mojo::ScopedDataPipeConsumerHandle(),
-      ssl_status, std::move(navigation_data), request_id, is_download,
-      is_stream, mojom::URLLoaderFactoryPtrInfo());
+  delegate_->OnResponseStarted(response, std::move(body),
+                               mojo::ScopedDataPipeConsumerHandle(), ssl_status,
+                               std::move(navigation_data), request_id,
+                               is_download, is_stream, base::nullopt);
 }
 void NavigationURLLoaderImpl::NotifyRequestFailed(
     bool in_cache,
diff --git a/content/browser/loader/navigation_url_loader_network_service.cc b/content/browser/loader/navigation_url_loader_network_service.cc
index eca0771..fdcc1073 100644
--- a/content/browser/loader/navigation_url_loader_network_service.cc
+++ b/content/browser/loader/navigation_url_loader_network_service.cc
@@ -26,6 +26,7 @@
 #include "content/browser/web_contents/web_contents_impl.h"
 #include "content/browser/webui/url_data_manager_backend.h"
 #include "content/browser/webui/web_ui_url_loader_factory.h"
+#include "content/common/navigation_subresource_loader_params.h"
 #include "content/common/throttling_url_loader.h"
 #include "content/public/browser/browser_context.h"
 #include "content/public/browser/browser_thread.h"
@@ -138,6 +139,7 @@
       AppCacheNavigationHandleCore* appcache_handle_core,
       std::unique_ptr<NavigationRequestInfo> request_info,
       mojom::URLLoaderFactoryPtrInfo factory_for_webui,
+      mojom::URLLoaderFactoryPtrInfo subresource_factory_for_webui,
       const base::Callback<WebContents*(void)>& web_contents_getter,
       std::unique_ptr<service_manager::Connector> connector) {
     DCHECK_CURRENTLY_ON(BrowserThread::IO);
@@ -163,6 +165,9 @@
               web_contents_getter_),
           0 /* routing_id? */, 0 /* request_id? */, mojom::kURLLoadOptionNone,
           *resource_request_, this, kTrafficAnnotation);
+      SubresourceLoaderParams params;
+      params.loader_factory_info = std::move(subresource_factory_for_webui);
+      subresource_loader_params_ = std::move(params);
       return;
     }
 
@@ -208,11 +213,18 @@
       url_loader_.reset();
     handler_index_ = 0;
     received_response_ = false;
-    MaybeStartLoader(StartLoaderCallback());
+    MaybeStartLoader(nullptr /* handler */, StartLoaderCallback());
   }
 
-  void MaybeStartLoader(StartLoaderCallback start_loader_callback) {
+  // |handler| is the one who called this method (as a LoaderCallback), nullptr
+  // if this method is not called by a handler.
+  // |start_loader_callback| is the callback given by the |handler|, non-null
+  // if the |handler| wants to handle the request.
+  void MaybeStartLoader(URLLoaderRequestHandler* handler,
+                        StartLoaderCallback start_loader_callback) {
     if (start_loader_callback) {
+      // |handler| wants to handle the request.
+      DCHECK(handler);
       default_loader_used_ = false;
       url_loader_ = ThrottlingURLLoader::CreateLoaderAndStart(
           std::move(start_loader_callback),
@@ -220,22 +232,18 @@
               web_contents_getter_),
           *resource_request_, this, kTrafficAnnotation);
 
-      DCHECK_GT(handler_index_, 0U);
-
-      mojom::URLLoaderFactoryPtr subresource_loader_factory =
-          handlers_[handler_index_ - 1]->MaybeCreateSubresourceFactory();
-      if (subresource_loader_factory.get()) {
-        subresource_url_loader_factory_ptr_info_ =
-            subresource_loader_factory.PassInterface();
-      }
+      subresource_loader_params_ =
+          handler->MaybeCreateSubresourceLoaderParams();
       return;
     }
 
+    // See if the next handler wants to handle the request.
     if (handler_index_ < handlers_.size()) {
-      handlers_[handler_index_++]->MaybeCreateLoader(
+      auto* next_handler = handlers_[handler_index_++].get();
+      next_handler->MaybeCreateLoader(
           *resource_request_, resource_context_,
           base::BindOnce(&URLLoaderRequestController::MaybeStartLoader,
-                         base::Unretained(this)));
+                         base::Unretained(this), next_handler));
       return;
     }
 
@@ -312,10 +320,8 @@
                             std::move(completion_status_));
   }
 
-  // Ownership of the URLLoaderFactoryPtrInfo instance is transferred to the
-  // caller.
-  mojom::URLLoaderFactoryPtrInfo GetSubresourceURLLoaderFactory() {
-    return std::move(subresource_url_loader_factory_ptr_info_);
+  base::Optional<SubresourceLoaderParams> TakeSubresourceLoaderParams() {
+    return std::move(subresource_loader_params_);
   }
 
  private:
@@ -439,7 +445,7 @@
 
   // Currently used by the AppCache loader to pass its factory to the
   // renderer which enables it to handle subresources.
-  mojom::URLLoaderFactoryPtrInfo subresource_url_loader_factory_ptr_info_;
+  base::Optional<SubresourceLoaderParams> subresource_loader_params_;
 
   // This is referenced only on the UI thread.
   base::WeakPtr<NavigationURLLoaderNetworkService> owner_;
@@ -531,12 +537,15 @@
 
   // Check if a web UI scheme wants to handle this request.
   mojom::URLLoaderFactoryPtrInfo factory_for_webui;
+  mojom::URLLoaderFactoryPtrInfo subresource_factory_for_webui;
   const auto& schemes = URLDataManagerBackend::GetWebUISchemes();
   if (std::find(schemes.begin(), schemes.end(), new_request->url.scheme()) !=
       schemes.end()) {
     FrameTreeNode* frame_tree_node =
         FrameTreeNode::GloballyFindByID(frame_tree_node_id);
     factory_for_webui = CreateWebUIURLLoader(frame_tree_node).PassInterface();
+    subresource_factory_for_webui =
+        CreateWebUIURLLoader(frame_tree_node).PassInterface();
   }
 
   g_next_request_id--;
@@ -558,6 +567,7 @@
           appcache_handle ? appcache_handle->core() : nullptr,
           base::Passed(std::move(request_info)),
           base::Passed(std::move(factory_for_webui)),
+          base::Passed(std::move(subresource_factory_for_webui)),
           base::Bind(&GetWebContentsFromFrameTreeNodeID, frame_tree_node_id),
           base::Passed(ServiceManagerConnection::GetForProcess()
                            ->GetConnector()
@@ -622,7 +632,7 @@
       response_, nullptr, std::move(body), ssl_status_,
       std::unique_ptr<NavigationData>(), GlobalRequestID(-1, g_next_request_id),
       IsDownload(), false /* is_stream */,
-      request_controller_->GetSubresourceURLLoaderFactory());
+      request_controller_->TakeSubresourceLoaderParams());
 }
 
 void NavigationURLLoaderNetworkService::OnComplete(
diff --git a/content/browser/loader/navigation_url_loader_network_service_unittest.cc b/content/browser/loader/navigation_url_loader_network_service_unittest.cc
index 0bc50e01..380bade 100644
--- a/content/browser/loader/navigation_url_loader_network_service_unittest.cc
+++ b/content/browser/loader/navigation_url_loader_network_service_unittest.cc
@@ -57,10 +57,6 @@
                       std::move(client), TRAFFIC_ANNOTATION_FOR_TESTS);
   }
 
-  mojom::URLLoaderFactoryPtr MaybeCreateSubresourceFactory() override {
-    return nullptr;
-  }
-
   bool MaybeCreateLoaderForResponse(
       const ResourceResponseHead& response,
       mojom::URLLoaderPtr* loader,
diff --git a/content/browser/loader/resource_dispatcher_host_impl.cc b/content/browser/loader/resource_dispatcher_host_impl.cc
index 4136bb58..0966299 100644
--- a/content/browser/loader/resource_dispatcher_host_impl.cc
+++ b/content/browser/loader/resource_dispatcher_host_impl.cc
@@ -88,6 +88,7 @@
 #include "content/public/browser/stream_info.h"
 #include "content/public/common/browser_side_navigation_policy.h"
 #include "content/public/common/content_features.h"
+#include "content/public/common/origin_util.h"
 #include "content/public/common/resource_request.h"
 #include "content/public/common/resource_request_body.h"
 #include "content/public/common/resource_request_completion_status.h"
@@ -2583,8 +2584,15 @@
 
   if (net::registry_controlled_domains::SameDomainOrHost(
           first_party, request_url,
-          net::registry_controlled_domains::INCLUDE_PRIVATE_REGISTRIES))
+          net::registry_controlled_domains::INCLUDE_PRIVATE_REGISTRIES)) {
+    // If the first party is secure but the subresource is not, this is
+    // mixed-content. Do not allow the image.
+    if (!allow_cross_origin_auth_prompt() && IsOriginSecure(first_party) &&
+        !IsOriginSecure(request_url)) {
+      return HTTP_AUTH_RELATION_BLOCKED_CROSS;
+    }
     return HTTP_AUTH_RELATION_SAME_DOMAIN;
+  }
 
   if (allow_cross_origin_auth_prompt())
     return HTTP_AUTH_RELATION_ALLOWED_CROSS;
diff --git a/content/browser/loader/upload_data_stream_builder.cc b/content/browser/loader/upload_data_stream_builder.cc
index 1d91917..fc446eb 100644
--- a/content/browser/loader/upload_data_stream_builder.cc
+++ b/content/browser/loader/upload_data_stream_builder.cc
@@ -15,7 +15,6 @@
 #include "base/memory/ptr_util.h"
 #include "base/memory/ref_counted.h"
 #include "base/single_thread_task_runner.h"
-#include "content/browser/fileapi/upload_file_system_file_element_reader.h"
 #include "content/public/common/resource_request_body.h"
 #include "net/base/elements_upload_data_stream.h"
 #include "net/base/upload_bytes_element_reader.h"
@@ -99,15 +98,6 @@
         element_readers.push_back(std::make_unique<FileElementReader>(
             body, file_task_runner, element));
         break;
-      case ResourceRequestBody::Element::TYPE_FILE_FILESYSTEM:
-        // If |body| contains any filesystem URLs, the caller should have
-        // supplied a FileSystemContext.
-        DCHECK(file_system_context);
-        element_readers.push_back(
-            std::make_unique<content::UploadFileSystemFileElementReader>(
-                file_system_context, element.filesystem_url(), element.offset(),
-                element.length(), element.expected_modification_time()));
-        break;
       case ResourceRequestBody::Element::TYPE_BLOB: {
         DCHECK_EQ(std::numeric_limits<uint64_t>::max(), element.length());
         DCHECK_EQ(0ul, element.offset());
@@ -118,6 +108,9 @@
                 std::move(handle), file_system_context));
         break;
       }
+      case ResourceRequestBody::Element::TYPE_FILE_FILESYSTEM:
+        CHECK(false) << "Should never be reached";
+        break;
       case ResourceRequestBody::Element::TYPE_DISK_CACHE_ENTRY:
       case ResourceRequestBody::Element::TYPE_BYTES_DESCRIPTION:
       case ResourceRequestBody::Element::TYPE_DATA_PIPE:
diff --git a/content/browser/loader/url_loader_request_handler.cc b/content/browser/loader/url_loader_request_handler.cc
index 731e9de..bb41972 100644
--- a/content/browser/loader/url_loader_request_handler.cc
+++ b/content/browser/loader/url_loader_request_handler.cc
@@ -4,11 +4,13 @@
 
 #include "content/browser/loader/url_loader_request_handler.h"
 
+#include "content/common/navigation_subresource_loader_params.h"
+
 namespace content {
 
-mojom::URLLoaderFactoryPtr
-URLLoaderRequestHandler::MaybeCreateSubresourceFactory() {
-  return nullptr;
+base::Optional<SubresourceLoaderParams>
+URLLoaderRequestHandler::MaybeCreateSubresourceLoaderParams() {
+  return base::nullopt;
 }
 
 bool URLLoaderRequestHandler::MaybeCreateLoaderForResponse(
@@ -18,4 +20,4 @@
   return false;
 }
 
-}  // namespace content
\ No newline at end of file
+}  // namespace content
diff --git a/content/browser/loader/url_loader_request_handler.h b/content/browser/loader/url_loader_request_handler.h
index b736618..da24d52 100644
--- a/content/browser/loader/url_loader_request_handler.h
+++ b/content/browser/loader/url_loader_request_handler.h
@@ -8,6 +8,7 @@
 #include <memory>
 #include "base/callback_forward.h"
 #include "base/macros.h"
+#include "base/optional.h"
 #include "content/public/common/url_loader.mojom.h"
 #include "content/public/common/url_loader_factory.mojom.h"
 #include "net/url_request/redirect_info.h"
@@ -16,6 +17,7 @@
 
 class ResourceContext;
 struct ResourceRequest;
+struct SubresourceLoaderParams;
 
 using StartLoaderCallback =
     base::OnceCallback<void(mojom::URLLoaderRequest request,
@@ -36,10 +38,12 @@
                                  ResourceContext* resource_context,
                                  LoaderCallback callback) = 0;
 
-  // Returns the URLLoaderFactory if any to be used for subsequent URL requests
-  // going forward. Subclasses who want to handle subresource requests etc may
-  // want to override this to return a custom factory.
-  virtual mojom::URLLoaderFactoryPtr MaybeCreateSubresourceFactory();
+  // Returns a SubresourceLoaderParams if any to be used for subsequent URL
+  // requests going forward. Subclasses who want to set-up custom loader for
+  // subresource requests may want to override this.
+  // Called only when MaybeCreateLoader has returned a non-null LoaderCallback.
+  virtual base::Optional<SubresourceLoaderParams>
+  MaybeCreateSubresourceLoaderParams();
 
   // Returns true if the handler creates a loader for the |response| passed.
   // An example of where this is used is AppCache, where the handler returns
diff --git a/content/browser/media/cdm_file_impl.cc b/content/browser/media/cdm_file_impl.cc
new file mode 100644
index 0000000..e42469e
--- /dev/null
+++ b/content/browser/media/cdm_file_impl.cc
@@ -0,0 +1,405 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/browser/media/cdm_file_impl.h"
+
+#include <set>
+#include <utility>
+
+#include "base/callback.h"
+#include "base/logging.h"
+#include "base/strings/string_util.h"
+#include "base/task_scheduler/post_task.h"
+#include "storage/browser/fileapi/file_system_context.h"
+#include "storage/browser/fileapi/file_system_operation_context.h"
+#include "storage/browser/fileapi/file_system_url.h"
+#include "storage/browser/quota/quota_manager.h"
+#include "storage/common/fileapi/file_system_types.h"
+
+namespace content {
+
+namespace {
+
+// The CDM interface has a restriction that file names can not begin with _,
+// so use it to prefix temporary files.
+const char kTemporaryFilePrefix[] = "_";
+
+std::string GetTempFileName(const std::string& file_name) {
+  DCHECK(!base::StartsWith(file_name, kTemporaryFilePrefix,
+                           base::CompareCase::SENSITIVE));
+  return kTemporaryFilePrefix + file_name;
+}
+
+// The file system is different for each CDM and each origin. So track files
+// in use based on (file system ID, origin, file name).
+struct FileLockKey {
+  FileLockKey(const std::string& file_system_id,
+              const url::Origin& origin,
+              const std::string& file_name)
+      : file_system_id(file_system_id), origin(origin), file_name(file_name) {}
+  ~FileLockKey() = default;
+
+  // Allow use as a key in std::set.
+  bool operator<(const FileLockKey& other) const {
+    return std::tie(file_system_id, origin, file_name) <
+           std::tie(other.file_system_id, other.origin, other.file_name);
+  }
+
+  std::string file_system_id;
+  url::Origin origin;
+  std::string file_name;
+};
+
+// File map shared by all CdmFileImpl objects to prevent read/write race.
+// A lock must be acquired before opening a file to ensure that the file is not
+// currently in use. The lock must be held until the file is closed.
+class FileLockMap {
+ public:
+  FileLockMap() = default;
+  ~FileLockMap() = default;
+
+  // Acquire a lock on the file represented by |key|. Returns true if |key|
+  // is not currently in use, false otherwise.
+  bool AcquireFileLock(const FileLockKey& key) {
+    DVLOG(3) << __func__ << " file: " << key.file_name;
+    DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
+
+    // Add a new entry. If |key| already has an entry, insert() tells so
+    // with the second piece of the returned value and does not modify
+    // the original.
+    return file_lock_map_.insert(key).second;
+  }
+
+  // Tests whether a lock is held on |key| or not. Returns true if |key|
+  // is currently locked, false otherwise.
+  bool IsFileLockHeld(const FileLockKey& key) {
+    DVLOG(3) << __func__ << " file: " << key.file_name;
+    DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
+
+    // Lock is held if there is an entry for |key|.
+    return file_lock_map_.count(key) > 0;
+  }
+
+  // Release the lock held on the file represented by |key|. If
+  // |on_close_callback| has been set, run it before releasing the lock.
+  void ReleaseFileLock(const FileLockKey& key) {
+    DVLOG(3) << __func__ << " file: " << key.file_name;
+    DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
+
+    auto entry = file_lock_map_.find(key);
+    if (entry == file_lock_map_.end()) {
+      NOTREACHED() << "Unable to release lock on file " << key.file_name;
+      return;
+    }
+
+    file_lock_map_.erase(entry);
+  }
+
+ private:
+  // Note that this map is never deleted. As entries are removed when a file
+  // is closed, it should never get too large.
+  std::set<FileLockKey> file_lock_map_;
+
+  THREAD_CHECKER(thread_checker_);
+  DISALLOW_COPY_AND_ASSIGN(FileLockMap);
+};
+
+// The FileLockMap is a global lock map shared by all CdmFileImpl instances.
+FileLockMap* GetFileLockMap() {
+  static auto* file_lock_map = new FileLockMap();
+  return file_lock_map;
+}
+
+// Takes ownership of the file and closes it. Used only in OnFileOpened().
+void CloseFile(base::File file, const base::Closure& on_close_callback) {
+  DVLOG(3) << __func__;
+
+  if (file.IsValid())
+    file.Close();
+
+  if (on_close_callback)
+    on_close_callback.Run();
+}
+
+// Called when storage::AsyncFileUtil::CreateOrOpen() completes. As the
+// CdmFileImpl may have been destroyed in the meantime, check if it has
+// happened and respond appropriately. http://crbug.com/778839
+void OnFileOpened(base::WeakPtr<CdmFileImpl> weak_ptr,
+                  storage::AsyncFileUtil::CreateOrOpenCallback callback,
+                  base::File file,
+                  const base::Closure& on_close_callback) {
+  DVLOG(3) << __func__ << (weak_ptr ? " callback" : " post_task");
+
+  if (weak_ptr) {
+    // CdmFileImpl still alive, so run |callback| and we're done.
+    std::move(callback).Run(std::move(file), on_close_callback);
+    return;
+  }
+
+  // CdmFileImpl not around anymore, so free |file| and |on_close_callback|
+  // if necessary.
+  if (file.IsValid()) {
+    constexpr base::TaskTraits traits = {base::MayBlock()};
+    base::PostTaskWithTraits(
+        FROM_HERE, traits,
+        base::BindOnce(&CloseFile, std::move(file), on_close_callback));
+  } else {
+    DCHECK(!on_close_callback);
+  }
+}
+
+}  // namespace
+
+CdmFileImpl::CdmFileImpl(
+    const std::string& file_name,
+    const url::Origin& origin,
+    const std::string& file_system_id,
+    const std::string& file_system_root_uri,
+    scoped_refptr<storage::FileSystemContext> file_system_context)
+    : file_name_(file_name),
+      temp_file_name_(GetTempFileName(file_name_)),
+      origin_(origin),
+      file_system_id_(file_system_id),
+      file_system_root_uri_(file_system_root_uri),
+      file_system_context_(file_system_context),
+      weak_factory_(this) {
+  DVLOG(3) << __func__ << " " << file_name_;
+}
+
+CdmFileImpl::~CdmFileImpl() {
+  DVLOG(3) << __func__ << " " << file_name_;
+  DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
+
+  // If a file open was started but hasn't completed by now, run the callback
+  // and report an error.
+  if (pending_open_callback_) {
+    std::move(pending_open_callback_)
+        .Run(base::File(base::File::FILE_ERROR_ABORT));
+  }
+
+  if (lock_state_ == LockState::kFileAndTempFileLocked) {
+    // Temporary file is open, so close and release it.
+    if (temporary_file_on_close_callback_)
+      std::move(temporary_file_on_close_callback_).Run();
+    ReleaseFileLock(temp_file_name_);
+  }
+  if (lock_state_ != LockState::kNone) {
+    // Original file is open, so close and release it.
+    if (on_close_callback_)
+      std::move(on_close_callback_).Run();
+    ReleaseFileLock(file_name_);
+  }
+}
+
+void CdmFileImpl::Initialize(OpenFileCallback callback) {
+  DVLOG(3) << __func__ << " file: " << file_name_;
+  DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
+  DCHECK_EQ(LockState::kNone, lock_state_);
+  DCHECK(!pending_open_callback_);
+
+  // Grab the lock on |file_name_|. The lock will be held until this object is
+  // destructed.
+  if (!AcquireFileLock(file_name_)) {
+    DVLOG(3) << "File " << file_name_ << " is already in use.";
+    std::move(callback).Run(base::File(base::File::FILE_ERROR_IN_USE));
+    return;
+  }
+
+  // We have the lock on |file_name_|. Now open the file for reading. Since
+  // we don't know if this file exists or not, provide FLAG_OPEN_ALWAYS to
+  // create the file if it doesn't exist.
+  lock_state_ = LockState::kFileLocked;
+  pending_open_callback_ = std::move(callback);
+  OpenFile(file_name_, base::File::FLAG_OPEN_ALWAYS | base::File::FLAG_READ,
+           base::Bind(&CdmFileImpl::OnFileOpenedForReading,
+                      weak_factory_.GetWeakPtr()));
+}
+
+void CdmFileImpl::OpenFile(const std::string& file_name,
+                           uint32_t file_flags,
+                           CreateOrOpenCallback callback) {
+  DVLOG(3) << __func__ << " file: " << file_name << ", flags: " << file_flags;
+  DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
+  DCHECK_NE(LockState::kNone, lock_state_);
+  DCHECK(IsFileLockHeld(file_name));
+  DCHECK(pending_open_callback_);
+
+  storage::FileSystemURL file_url = CreateFileSystemURL(file_name);
+  storage::AsyncFileUtil* file_util = file_system_context_->GetAsyncFileUtil(
+      storage::kFileSystemTypePluginPrivate);
+  auto operation_context =
+      std::make_unique<storage::FileSystemOperationContext>(
+          file_system_context_.get());
+  operation_context->set_allowed_bytes_growth(storage::QuotaManager::kNoLimit);
+  DVLOG(3) << "Opening " << file_url.DebugString();
+
+  // As |this| may go away while the CreateOrOpen() is being processed, use
+  // the static method OnFileOpened() to handle the response. If |this| has
+  // been destroyed, it will clean up the base::File returned properly.
+  file_util->CreateOrOpen(std::move(operation_context), file_url, file_flags,
+                          base::Bind(&OnFileOpened, weak_factory_.GetWeakPtr(),
+                                     std::move(callback)));
+}
+
+void CdmFileImpl::OnFileOpenedForReading(
+    base::File file,
+    const base::Closure& on_close_callback) {
+  DVLOG(3) << __func__ << " file: " << file_name_;
+  DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
+  DCHECK_EQ(LockState::kFileLocked, lock_state_);
+  DCHECK(pending_open_callback_);
+
+  if (!file.IsValid()) {
+    // File is invalid. Note that the lock on |file_name_| is kept until this
+    // object is destructed.
+    DLOG(WARNING) << "Unable to open file " << file_name_ << ", error: "
+                  << base::File::ErrorToString(file.error_details());
+    std::move(pending_open_callback_).Run(std::move(file));
+    return;
+  }
+
+  // When the file is closed, |on_close_callback| will be run.
+  on_close_callback_ = std::move(on_close_callback);
+  std::move(pending_open_callback_).Run(std::move(file));
+}
+
+void CdmFileImpl::OpenFileForWriting(OpenFileForWritingCallback callback) {
+  DVLOG(3) << __func__ << " " << file_name_;
+
+  // Fail if this is called out of order. We must have opened the original
+  // file, and there should be no call in progress.
+  if (lock_state_ != LockState::kFileLocked || pending_open_callback_) {
+    std::move(callback).Run(
+        base::File(base::File::FILE_ERROR_INVALID_OPERATION));
+    return;
+  }
+
+  // Grab a lock on the temporary file. The lock will be held until this
+  // new file is renamed in CommitWrite() (or this object is
+  // destructed).
+  if (!AcquireFileLock(temp_file_name_)) {
+    DVLOG(3) << "File " << temp_file_name_ << " is already in use.";
+    std::move(callback).Run(base::File(base::File::FILE_ERROR_IN_USE));
+    return;
+  }
+
+  // We now have locks on both |file_name_| and |temp_file_name_|. Open the
+  // temporary file for writing. Specifying FLAG_CREATE_ALWAYS which will
+  // overwrite any existing file.
+  lock_state_ = LockState::kFileAndTempFileLocked;
+  pending_open_callback_ = std::move(callback);
+  OpenFile(temp_file_name_,
+           base::File::FLAG_CREATE_ALWAYS | base::File::FLAG_WRITE,
+           base::Bind(&CdmFileImpl::OnTempFileOpenedForWriting,
+                      weak_factory_.GetWeakPtr()));
+}
+
+void CdmFileImpl::OnTempFileOpenedForWriting(
+    base::File file,
+    const base::Closure& on_close_callback) {
+  DVLOG(3) << __func__ << " file: " << file_name_;
+  DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
+  DCHECK_EQ(LockState::kFileAndTempFileLocked, lock_state_);
+  DCHECK(pending_open_callback_);
+
+  if (!file.IsValid()) {
+    DLOG(WARNING) << "Unable to open file " << temp_file_name_ << ", error: "
+                  << base::File::ErrorToString(file.error_details());
+    lock_state_ = LockState::kFileLocked;
+    ReleaseFileLock(temp_file_name_);
+    std::move(pending_open_callback_).Run(std::move(file));
+    return;
+  }
+
+  temporary_file_on_close_callback_ = std::move(on_close_callback);
+  std::move(pending_open_callback_).Run(std::move(file));
+}
+
+void CdmFileImpl::CommitWrite(CommitWriteCallback callback) {
+  DVLOG(3) << __func__ << " " << temp_file_name_ << " to " << file_name_;
+  DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
+  DCHECK_EQ(LockState::kFileAndTempFileLocked, lock_state_);
+  DCHECK(IsFileLockHeld(file_name_));
+  DCHECK(IsFileLockHeld(temp_file_name_));
+
+  // TODO(jrummell): Verify that the written file does not exceed the file
+  // size limit of 32MB. If it does simply delete the written file and fail.
+
+  // Fail if this is called out of order. We must have opened both the original
+  // and the temporary file, and there should be no call in progress.
+  if (lock_state_ != LockState::kFileAndTempFileLocked ||
+      pending_open_callback_) {
+    std::move(callback).Run(
+        base::File(base::File::FILE_ERROR_INVALID_OPERATION));
+    return;
+  }
+
+  if (on_close_callback_)
+    std::move(on_close_callback_).Run();
+  if (temporary_file_on_close_callback_)
+    std::move(temporary_file_on_close_callback_).Run();
+
+  // OpenFile() will be called after the file is renamed, so save |callback|.
+  pending_open_callback_ = std::move(callback);
+
+  storage::FileSystemURL src_file_url = CreateFileSystemURL(temp_file_name_);
+  storage::FileSystemURL dest_file_url = CreateFileSystemURL(file_name_);
+  storage::AsyncFileUtil* file_util = file_system_context_->GetAsyncFileUtil(
+      storage::kFileSystemTypePluginPrivate);
+  auto operation_context =
+      std::make_unique<storage::FileSystemOperationContext>(
+          file_system_context_.get());
+  DVLOG(3) << "Renaming " << src_file_url.DebugString() << " to "
+           << dest_file_url.DebugString();
+  file_util->MoveFileLocal(
+      std::move(operation_context), src_file_url, dest_file_url,
+      storage::FileSystemOperation::OPTION_NONE,
+      base::Bind(&CdmFileImpl::OnFileRenamed, weak_factory_.GetWeakPtr()));
+}
+
+void CdmFileImpl::OnFileRenamed(base::File::Error move_result) {
+  DVLOG(3) << __func__;
+  DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
+  DCHECK_EQ(LockState::kFileAndTempFileLocked, lock_state_);
+  DCHECK(pending_open_callback_);
+
+  // Temporary file has been renamed, so we can release the lock on it.
+  ReleaseFileLock(temp_file_name_);
+  lock_state_ = LockState::kFileLocked;
+
+  // Was the rename successful?
+  if (move_result != base::File::FILE_OK) {
+    std::move(pending_open_callback_).Run(base::File(move_result));
+    return;
+  }
+
+  // Reopen the original file for reading. Specifying FLAG_OPEN as the file
+  // has to exist or something's wrong.
+  OpenFile(file_name_, base::File::FLAG_OPEN | base::File::FLAG_READ,
+           base::Bind(&CdmFileImpl::OnFileOpenedForReading,
+                      weak_factory_.GetWeakPtr()));
+}
+
+storage::FileSystemURL CdmFileImpl::CreateFileSystemURL(
+    const std::string& file_name) {
+  return file_system_context_->CrackURL(
+      GURL(file_system_root_uri_ + file_name));
+}
+
+bool CdmFileImpl::AcquireFileLock(const std::string& file_name) {
+  FileLockKey file_lock_key(file_system_id_, origin_, file_name);
+  return GetFileLockMap()->AcquireFileLock(file_lock_key);
+}
+
+bool CdmFileImpl::IsFileLockHeld(const std::string& file_name) {
+  FileLockKey file_lock_key(file_system_id_, origin_, file_name);
+  return GetFileLockMap()->IsFileLockHeld(file_lock_key);
+}
+
+void CdmFileImpl::ReleaseFileLock(const std::string& file_name) {
+  FileLockKey file_lock_key(file_system_id_, origin_, file_name);
+  GetFileLockMap()->ReleaseFileLock(file_lock_key);
+}
+
+}  // namespace content
diff --git a/content/browser/media/cdm_file_impl.h b/content/browser/media/cdm_file_impl.h
new file mode 100644
index 0000000..bbf3c9a
--- /dev/null
+++ b/content/browser/media/cdm_file_impl.h
@@ -0,0 +1,123 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CONTENT_BROWSER_MEDIA_CDM_FILE_IMPL_H_
+#define CONTENT_BROWSER_MEDIA_CDM_FILE_IMPL_H_
+
+#include <string>
+
+#include "base/callback_forward.h"
+#include "base/files/file.h"
+#include "base/macros.h"
+#include "base/memory/ref_counted.h"
+#include "base/memory/weak_ptr.h"
+#include "base/threading/thread_checker.h"
+#include "media/mojo/interfaces/cdm_storage.mojom.h"
+#include "storage/browser/fileapi/async_file_util.h"
+#include "url/origin.h"
+
+namespace storage {
+class FileSystemContext;
+class FileSystemURL;
+}  // namespace storage
+
+namespace content {
+
+// This class implements the media::mojom::CdmFile interface. It uses the same
+// mojo pipe as CdmStorageImpl, to enforce message dispatch order.
+class CdmFileImpl final : public media::mojom::CdmFile {
+ public:
+  CdmFileImpl(const std::string& file_name,
+              const url::Origin& origin,
+              const std::string& file_system_id,
+              const std::string& file_system_root_uri,
+              scoped_refptr<storage::FileSystemContext> file_system_context);
+  ~CdmFileImpl() final;
+
+  // Called to open the file for read initially. Will create a file with
+  // |file_name_| if it does not exist. |file_opened_callback| will be called
+  // with the opened file descriptor on success. |file|.error_details()
+  // = base::File::FILE_ERROR_IN_USE if the file is in use by other CDMs
+  // or by the system. Note that |file_opened_callback| may destroy |this|
+  // (especially if the file can not be opened).
+  // Note that |this| should not be used anymore if Initialize() fails.
+  using OpenFileCallback = base::OnceCallback<void(base::File file)>;
+  void Initialize(OpenFileCallback file_opened_callback);
+
+  // media::mojom::CdmFile implementation. |callback| will be called with the
+  // file descriptor on success. Otherwise the file descriptor will not be
+  // valid, and error_details() provides the reason.
+  void OpenFileForWriting(OpenFileForWritingCallback callback) final;
+  void CommitWrite(CommitWriteCallback callback) final;
+
+ private:
+  using CreateOrOpenCallback = storage::AsyncFileUtil::CreateOrOpenCallback;
+
+  // Keep track of which files are locked.
+  //   kFileLocked: Only the original file |file_name_| is locked.
+  //   kFileAndTempFileLocked: Both |file_name_| and |temp_file_name_| are
+  //                           locked.
+  // Initialize() can only be called if kNone, results in kFileLocked (on
+  // success). OpenFileForWriting() can only be called if kFileLocked, results
+  // in kFileAndTempFileLocked. CommitWrite() can only be called if
+  // kFileAndTempFileLocked, results in kFileLocked (temp file closed and then
+  // renamed to replace the original).
+  enum class LockState { kNone, kFileLocked, kFileAndTempFileLocked };
+
+  // Open the file |file_name| using the flags provided in |file_flags|.
+  // |callback| is called with the result.
+  void OpenFile(const std::string& file_name,
+                uint32_t file_flags,
+                CreateOrOpenCallback callback);
+
+  void OnFileOpenedForReading(base::File file,
+                              const base::Closure& on_close_callback);
+  void OnTempFileOpenedForWriting(base::File file,
+                                  const base::Closure& on_close_callback);
+  void OnFileRenamed(base::File::Error move_result);
+
+  // Returns the FileSystemURL for the specified |file_name|.
+  storage::FileSystemURL CreateFileSystemURL(const std::string& file_name);
+
+  // Helper methods to lock and unlock a file.
+  bool AcquireFileLock(const std::string& file_name);
+  bool IsFileLockHeld(const std::string& file_name);
+  void ReleaseFileLock(const std::string& file_name);
+
+  // Names of the files this class represents.
+  const std::string file_name_;
+  const std::string temp_file_name_;
+
+  // Files are stored in the PluginPrivateFileSystem. The following are needed
+  // to access files.
+  const url::Origin origin_;
+  const std::string file_system_id_;
+  const std::string file_system_root_uri_;
+  scoped_refptr<storage::FileSystemContext> file_system_context_;
+
+  // Keep track of which files are opened.
+  LockState lock_state_ = LockState::kNone;
+
+  // As only one open operation is allowed at a time, |pending_open_callback_|
+  // keeps track of the callback to be called when the file is opened. This
+  // ensures the callback is always called if we are destroyed while the open
+  // operation is running.
+  OpenFileCallback pending_open_callback_;
+
+  // Callbacks required to close the file when it's no longer needed.
+  // storage::AsyncFileUtil::CreateOrOpen() returns this callback on a
+  // successful open along with the base::File object, which should be
+  // called when the file is closed.
+  base::Closure on_close_callback_;
+  base::Closure temporary_file_on_close_callback_;
+
+  THREAD_CHECKER(thread_checker_);
+  base::WeakPtrFactory<CdmFileImpl> weak_factory_;
+
+  DISALLOW_COPY_AND_ASSIGN(CdmFileImpl);
+};
+
+}  // namespace content
+
+#endif  // CONTENT_BROWSER_MEDIA_CDM_FILE_IMPL_H_
diff --git a/content/browser/media/cdm_storage_impl.cc b/content/browser/media/cdm_storage_impl.cc
index d788910..5b4be43 100644
--- a/content/browser/media/cdm_storage_impl.cc
+++ b/content/browser/media/cdm_storage_impl.cc
@@ -11,17 +11,17 @@
 
 #include "base/callback.h"
 #include "base/logging.h"
+#include "content/browser/media/cdm_file_impl.h"
 #include "content/public/browser/child_process_security_policy.h"
 #include "content/public/browser/render_frame_host.h"
 #include "content/public/browser/render_process_host.h"
 #include "content/public/browser/storage_partition.h"
-#include "mojo/public/cpp/bindings/strong_associated_binding.h"
 #include "ppapi/shared_impl/ppapi_constants.h"
-#include "storage/browser/fileapi/async_file_util.h"
 #include "storage/browser/fileapi/file_system_context.h"
 #include "storage/browser/fileapi/file_system_operation_context.h"
 #include "storage/browser/fileapi/isolated_context.h"
-#include "storage/browser/quota/quota_manager.h"
+#include "storage/common/fileapi/file_system_types.h"
+#include "storage/common/fileapi/file_system_util.h"
 #include "url/origin.h"
 
 // Currently this uses the PluginPrivateFileSystem as the previous CDMs ran
@@ -31,112 +31,6 @@
 
 namespace content {
 
-namespace {
-
-// File map shared by all CdmStorageImpl objects to prevent read/write race.
-// A lock must be acquired before opening a file to ensure that the file is not
-// currently in use. Once the file is opened the file map must be updated to
-// include the callback used to close the file. The lock must be held until
-// the file is closed.
-class FileLockMap {
- public:
-  using Key = CdmStorageImpl::FileLockKey;
-
-  FileLockMap() = default;
-  ~FileLockMap() = default;
-
-  // Acquire a lock on the file represented by |key|. Returns true if |key|
-  // is not currently in use, false otherwise.
-  bool AcquireFileLock(const Key& key) {
-    DVLOG(3) << __func__ << " file: " << key.file_name;
-    DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
-
-    // Add a new entry. If |key| already has an entry, emplace() tells so
-    // with the second piece of the returned value and does not modify
-    // the original.
-    return file_lock_map_.emplace(key, base::Closure()).second;
-  }
-
-  // Update the entry for the file represented by |key| so that
-  // |on_close_callback| will be called when the lock is released.
-  void SetOnCloseCallback(const Key& key, base::Closure on_close_callback) {
-    DVLOG(3) << __func__ << " file: " << key.file_name;
-    DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
-
-    DCHECK(!file_lock_map_.empty());
-    auto entry = file_lock_map_.find(key);
-    DCHECK(entry != file_lock_map_.end());
-    entry->second = std::move(on_close_callback);
-  }
-
-  // Release the lock held on the file represented by |key|. If
-  // |on_close_callback| has been set, run it before releasing the lock.
-  void ReleaseFileLock(const Key& key) {
-    DVLOG(3) << __func__ << " file: " << key.file_name;
-    DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
-
-    auto entry = file_lock_map_.find(key);
-    if (entry == file_lock_map_.end()) {
-      NOTREACHED() << "Unable to relase lock on file " << key.file_name;
-      return;
-    }
-
-    if (entry->second)
-      entry->second.Run();
-    file_lock_map_.erase(entry);
-  }
-
- private:
-  // Note that this map is never deleted. As entries are removed when a file
-  // is closed, it should never get too large.
-  std::map<Key, base::Closure> file_lock_map_;
-
-  THREAD_CHECKER(thread_checker_);
-  DISALLOW_COPY_AND_ASSIGN(FileLockMap);
-};
-
-FileLockMap* GetFileLockMap() {
-  static auto* file_lock_map = new FileLockMap();
-  return file_lock_map;
-}
-
-// mojom::CdmStorage::Open() returns a mojom::CdmFileReleaser reference to keep
-// track of the file being used. This object is created when the file is being
-// passed to the client. When the client is done using the file, the connection
-// should be broken and this will release the lock held on the file.
-class CdmFileReleaserImpl final : public media::mojom::CdmFileReleaser {
- public:
-  using Key = CdmStorageImpl::FileLockKey;
-
-  explicit CdmFileReleaserImpl(const Key& key) : key_(key) {
-    DVLOG(1) << __func__;
-  }
-
-  ~CdmFileReleaserImpl() override {
-    DVLOG(1) << __func__;
-    GetFileLockMap()->ReleaseFileLock(key_);
-  }
-
- private:
-  Key key_;
-
-  DISALLOW_COPY_AND_ASSIGN(CdmFileReleaserImpl);
-};
-
-}  // namespace
-
-CdmStorageImpl::FileLockKey::FileLockKey(const std::string& cdm_file_system_id,
-                                         const url::Origin& origin,
-                                         const std::string& file_name)
-    : cdm_file_system_id(cdm_file_system_id),
-      origin(origin),
-      file_name(file_name) {}
-
-bool CdmStorageImpl::FileLockKey::operator<(const FileLockKey& other) const {
-  return std::tie(cdm_file_system_id, origin, file_name) <
-         std::tie(other.cdm_file_system_id, other.origin, other.file_name);
-}
-
 // static
 void CdmStorageImpl::Create(RenderFrameHost* render_frame_host,
                             const std::string& cdm_file_system_id,
@@ -187,11 +81,6 @@
 
 CdmStorageImpl::~CdmStorageImpl() {
   DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
-
-  // If any file locks were taken in Open() and never made it to OnFileOpened(),
-  // release them now as OnFileOpened() will never run.
-  for (const auto& file_lock_key : pending_open_)
-    GetFileLockMap()->ReleaseFileLock(file_lock_key);
 }
 
 void CdmStorageImpl::Open(const std::string& file_name, OpenCallback callback) {
@@ -210,109 +99,119 @@
     return;
   }
 
-  FileLockKey file_lock_key(cdm_file_system_id_, origin(), file_name);
-  if (!GetFileLockMap()->AcquireFileLock(file_lock_key)) {
-    DVLOG(1) << "File " << file_name << " is already in use.";
-    std::move(callback).Run(Status::kInUse, base::File(), nullptr);
+  // The file system should only be opened once. If it has been attempted and
+  // failed, we can't create the CdmFile objects.
+  if (file_system_state_ == FileSystemState::kError) {
+    std::move(callback).Run(Status::kFailure, base::File(), nullptr);
     return;
   }
 
+  // If the file system is already open, create and initialize the CdmFileImpl
+  // object.
+  if (file_system_state_ == FileSystemState::kOpened) {
+    CreateCdmFile(file_name, std::move(callback));
+    return;
+  }
+
+  // Save a file name and callback for when the file system is open. If the
+  // open is already in progress, nothing more to do until the existing
+  // OpenPluginPrivateFileSystem() call completes.
+  pending_open_calls_.emplace(pending_open_calls_.end(), file_name,
+                              std::move(callback));
+  if (file_system_state_ == FileSystemState::kOpening)
+    return;
+
+  DCHECK_EQ(FileSystemState::kUnopened, file_system_state_);
+  file_system_state_ = FileSystemState::kOpening;
+
   std::string fsid =
       storage::IsolatedContext::GetInstance()->RegisterFileSystemForVirtualPath(
           storage::kFileSystemTypePluginPrivate, ppapi::kPluginPrivateRootName,
           base::FilePath());
   if (!storage::ValidateIsolatedFileSystemId(fsid)) {
     DVLOG(1) << "Invalid file system ID.";
-    GetFileLockMap()->ReleaseFileLock(file_lock_key);
-    std::move(callback).Run(Status::kFailure, base::File(), nullptr);
+    OnFileSystemOpened(base::File::FILE_ERROR_NOT_FOUND);
     return;
   }
 
-  // In case this object gets destroyed before OpenPluginPrivateFileSystem()
-  // completes, keep track of |file_lock_key| so that it can be released if
-  // OnFileSystemOpened() or OnFileOpened() never get called.
-  pending_open_.insert(file_lock_key);
-
   // Grant full access of isolated file system to child process.
   ChildProcessSecurityPolicy::GetInstance()->GrantCreateReadWriteFileSystem(
       child_process_id_, fsid);
 
+  // Keep track of the URI for this instance of the PluginPrivateFileSystem.
+  file_system_root_uri_ = storage::GetIsolatedFileSystemRootURIString(
+      origin().GetURL(), fsid, ppapi::kPluginPrivateRootName);
+
   file_system_context_->OpenPluginPrivateFileSystem(
       origin().GetURL(), storage::kFileSystemTypePluginPrivate, fsid,
       cdm_file_system_id_, storage::OPEN_FILE_SYSTEM_CREATE_IF_NONEXISTENT,
       base::Bind(&CdmStorageImpl::OnFileSystemOpened,
-                 weak_factory_.GetWeakPtr(), file_lock_key, fsid,
-                 base::Passed(&callback)));
+                 weak_factory_.GetWeakPtr()));
 }
 
-void CdmStorageImpl::OnFileSystemOpened(const FileLockKey& file_lock_key,
-                                        const std::string& fsid,
-                                        OpenCallback callback,
-                                        base::File::Error error) {
+void CdmStorageImpl::OnFileSystemOpened(base::File::Error error) {
   DVLOG(3) << __func__;
   DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
+  DCHECK_EQ(FileSystemState::kOpening, file_system_state_);
 
   if (error != base::File::FILE_OK) {
-    DVLOG(1) << "Unable to access the file system.";
-    pending_open_.erase(file_lock_key);
-    GetFileLockMap()->ReleaseFileLock(file_lock_key);
-    std::move(callback).Run(Status::kFailure, base::File(), nullptr);
+    file_system_state_ = FileSystemState::kError;
+    // All pending calls will fail.
+    for (auto& pending : pending_open_calls_) {
+      std::move(pending.second).Run(Status::kFailure, base::File(), nullptr);
+    }
+    pending_open_calls_.clear();
     return;
   }
 
-  std::string root = storage::GetIsolatedFileSystemRootURIString(
-                         origin().GetURL(), fsid, ppapi::kPluginPrivateRootName)
-                         .append(file_lock_key.file_name);
-  storage::FileSystemURL file_url = file_system_context_->CrackURL(GURL(root));
-  storage::AsyncFileUtil* file_util = file_system_context_->GetAsyncFileUtil(
-      storage::kFileSystemTypePluginPrivate);
-  auto operation_context =
-      std::make_unique<storage::FileSystemOperationContext>(
-          file_system_context_.get());
-  operation_context->set_allowed_bytes_growth(storage::QuotaManager::kNoLimit);
-  int flags = base::File::FLAG_OPEN_ALWAYS | base::File::FLAG_READ |
-              base::File::FLAG_WRITE;
-  DVLOG(1) << "Opening " << file_url.DebugString();
-  file_util->CreateOrOpen(
-      std::move(operation_context), file_url, flags,
-      base::Bind(&CdmStorageImpl::OnFileOpened, weak_factory_.GetWeakPtr(),
-                 file_lock_key, base::Passed(&callback)));
+  // File system successfully opened, so create the CdmFileImpl object for
+  // all pending Open() calls.
+  file_system_state_ = FileSystemState::kOpened;
+  for (auto& pending : pending_open_calls_) {
+    CreateCdmFile(pending.first, std::move(pending.second));
+  }
+  pending_open_calls_.clear();
 }
 
-void CdmStorageImpl::OnFileOpened(const FileLockKey& file_lock_key,
-                                  OpenCallback callback,
-                                  base::File file,
-                                  const base::Closure& on_close_callback) {
-  // |on_close_callback| should be called after the |file| is closed in the
-  // child process. See AsyncFileUtil for details.
+void CdmStorageImpl::CreateCdmFile(const std::string& file_name,
+                                   OpenCallback callback) {
+  DVLOG(3) << __func__ << " file: " << file_name;
+  DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
+  DCHECK_EQ(FileSystemState::kOpened, file_system_state_);
+
+  // File system opened successfully, so create an CdmFileImpl object and
+  // initialize it (which actually opens the file for reading).
+  auto cdm_file_impl = std::make_unique<CdmFileImpl>(
+      file_name, origin(), cdm_file_system_id_, file_system_root_uri_,
+      file_system_context_);
+  auto* cdm_file_ptr = cdm_file_impl.get();
+  cdm_file_ptr->Initialize(base::BindOnce(
+      &CdmStorageImpl::OnCdmFileInitialized, weak_factory_.GetWeakPtr(),
+      std::move(cdm_file_impl), std::move(callback)));
+}
+
+void CdmStorageImpl::OnCdmFileInitialized(
+    std::unique_ptr<CdmFileImpl> cdm_file_impl,
+    OpenCallback callback,
+    base::File file) {
   DVLOG(3) << __func__;
   DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
 
-  // |file_lock_key| will either be used by CdmFileReleaserImpl on a successful
-  // open or released if |file| is not valid, so the open is no longer pending.
-  pending_open_.erase(file_lock_key);
-
   if (!file.IsValid()) {
-    DLOG(WARNING) << "Unable to open file " << file_lock_key.file_name
-                  << ", error: "
-                  << base::File::ErrorToString(file.error_details());
-    GetFileLockMap()->ReleaseFileLock(file_lock_key);
-    std::move(callback).Run(Status::kFailure, base::File(), nullptr);
+    // Unable to open the file requested. Return an appropriate error.
+    Status status = (file.error_details() == base::File::FILE_ERROR_IN_USE)
+                        ? Status::kInUse
+                        : Status::kFailure;
+    std::move(callback).Run(status, base::File(), nullptr);
     return;
   }
 
-  GetFileLockMap()->SetOnCloseCallback(file_lock_key,
-                                       std::move(on_close_callback));
-
-  // When the connection to |releaser| is closed, ReleaseFileLock() will be
-  // called. This will release the lock on the file and cause
-  // |on_close_callback| to be run.
-  media::mojom::CdmFileReleaserAssociatedPtrInfo releaser;
-  mojo::MakeStrongAssociatedBinding(
-      std::make_unique<CdmFileReleaserImpl>(file_lock_key),
-      mojo::MakeRequest(&releaser));
+  // File was opened successfully, so create the binding and return success.
+  media::mojom::CdmFileAssociatedPtrInfo cdm_file;
+  cdm_file_bindings_.AddBinding(std::move(cdm_file_impl),
+                                mojo::MakeRequest(&cdm_file));
   std::move(callback).Run(Status::kSuccess, std::move(file),
-                          std::move(releaser));
+                          std::move(cdm_file));
 }
 
 }  // namespace content
diff --git a/content/browser/media/cdm_storage_impl.h b/content/browser/media/cdm_storage_impl.h
index a90d5e4..331d2b9c 100644
--- a/content/browser/media/cdm_storage_impl.h
+++ b/content/browser/media/cdm_storage_impl.h
@@ -16,16 +16,14 @@
 #include "content/common/content_export.h"
 #include "content/public/browser/frame_service_base.h"
 #include "media/mojo/interfaces/cdm_storage.mojom.h"
+#include "mojo/public/cpp/bindings/strong_associated_binding_set.h"
 
 namespace storage {
 class FileSystemContext;
 }
 
-namespace url {
-class Origin;
-}
-
 namespace content {
+class CdmFileImpl;
 class RenderFrameHost;
 
 // This class implements the media::mojom::CdmStorage using the
@@ -34,21 +32,6 @@
 class CONTENT_EXPORT CdmStorageImpl final
     : public content::FrameServiceBase<media::mojom::CdmStorage> {
  public:
-  // The file system is different for each CDM and each origin. So track files
-  // in use based on the tuple CDM file system ID, origin, and file name.
-  struct FileLockKey {
-    FileLockKey(const std::string& cdm_file_system_id,
-                const url::Origin& origin,
-                const std::string& file_name);
-    ~FileLockKey() = default;
-
-    // Allow use as a key in std::set.
-    bool operator<(const FileLockKey& other) const;
-
-    std::string cdm_file_system_id;
-    url::Origin origin;
-    std::string file_name;
-  };
 
   // Check if |cdm_file_system_id| is valid.
   static bool IsValidCdmFileSystemId(const std::string& cdm_file_system_id);
@@ -63,39 +46,54 @@
   void Open(const std::string& file_name, OpenCallback callback) final;
 
  private:
+  // File system should only be opened once, so keep track if it has already
+  // been opened (or is in the process of opening). State is kError if an error
+  // happens while opening the file system.
+  enum class FileSystemState { kUnopened, kOpening, kOpened, kError };
+
   CdmStorageImpl(RenderFrameHost* render_frame_host,
                  const std::string& cdm_file_system_id,
                  scoped_refptr<storage::FileSystemContext> file_system_context,
                  media::mojom::CdmStorageRequest request);
   ~CdmStorageImpl() final;
 
-  // Called when the file system has been opened (OpenPluginPrivateFileSystem
-  // is asynchronous).
-  void OnFileSystemOpened(const FileLockKey& key,
-                          const std::string& fsid,
-                          OpenCallback callback,
-                          base::File::Error error);
+  // Called when the file system is opened.
+  void OnFileSystemOpened(base::File::Error error);
 
-  // Called when the requested file has been opened.
-  void OnFileOpened(const FileLockKey& key,
-                    OpenCallback callback,
-                    base::File file,
-                    const base::Closure& on_close_callback);
+  // After the file system is opened, called to create a CdmFile object.
+  void CreateCdmFile(const std::string& file_name, OpenCallback callback);
+
+  // Called after the CdmFileImpl object has opened the file for reading.
+  void OnCdmFileInitialized(std::unique_ptr<CdmFileImpl> cdm_file_impl,
+                            OpenCallback callback,
+                            base::File file);
 
   // Files are stored in the PluginPrivateFileSystem, so keep track of the
   // CDM file system ID in order to open the files in the correct context.
   const std::string cdm_file_system_id_;
   scoped_refptr<storage::FileSystemContext> file_system_context_;
 
+  // The PluginPrivateFileSystem only needs to be opened once.
+  FileSystemState file_system_state_ = FileSystemState::kUnopened;
+
+  // As multiple calls to Open() could happen while the file system is being
+  // opened asynchronously, keep track of the requests so they can be
+  // processed once the file system is open.
+  using PendingOpenData = std::pair<std::string, OpenCallback>;
+  std::vector<PendingOpenData> pending_open_calls_;
+
+  // Once the PluginPrivateFileSystem is opened, keep track of the URI that
+  // refers to it.
+  std::string file_system_root_uri_;
+
   // This is the child process that will actually read and write the file(s)
-  // returned, and it needs permission to access the file when it's opened.
+  // returned, and it needs permission to access the file(s).
   const int child_process_id_;
 
-  // As a lock is taken on a file when Open() is called, it needs to be
-  // released if the async operations to open the file haven't completed
-  // by the time |this| is destroyed. So keep track of FileLockKey for files
-  // that have a lock on them but failed to finish.
-  std::set<FileLockKey> pending_open_;
+  // Keep track of all media::mojom::CdmFile bindings, as each CdmFileImpl
+  // object keeps a reference to |this|. If |this| goes away unexpectedly,
+  // all remaining CdmFile bindings will be closed.
+  mojo::StrongAssociatedBindingSet<media::mojom::CdmFile> cdm_file_bindings_;
 
   base::WeakPtrFactory<CdmStorageImpl> weak_factory_;
 
diff --git a/content/browser/media/cdm_storage_impl_unittest.cc b/content/browser/media/cdm_storage_impl_unittest.cc
index 06cc8f3..cc7b845 100644
--- a/content/browser/media/cdm_storage_impl_unittest.cc
+++ b/content/browser/media/cdm_storage_impl_unittest.cc
@@ -18,7 +18,11 @@
 #include "url/gurl.h"
 #include "url/origin.h"
 
+using media::mojom::CdmFile;
+using media::mojom::CdmFileAssociatedPtr;
+using media::mojom::CdmFileAssociatedPtrInfo;
 using media::mojom::CdmStorage;
+using media::mojom::CdmStoragePtr;
 
 namespace content {
 
@@ -63,40 +67,67 @@
   }
 
   // Open the file |name|. Returns true if the file returned is valid, false
-  // otherwise. Updates |status|, |file|, and |releaser| with the values
+  // otherwise. Updates |status|, |file|, and |cdm_file| with the values
   // returned by CdmStorage. If |status| = kSuccess, |file| should be valid to
-  // access, and |releaser| should be reset when the file is closed.
+  // access, and |cdm_file| should be reset when the file is closed.
   bool Open(const std::string& name,
             CdmStorage::Status* status,
             base::File* file,
-            media::mojom::CdmFileReleaserAssociatedPtr* releaser) {
+            CdmFileAssociatedPtr* cdm_file) {
     DVLOG(3) << __func__;
 
     cdm_storage_->Open(
         name, base::Bind(&CdmStorageTest::OpenDone, base::Unretained(this),
-                         status, file, releaser));
+                         status, file, cdm_file));
     RunAndWaitForResult();
     return file->IsValid();
   }
 
+  bool Write(CdmFile* cdm_file,
+             const std::vector<uint8_t>& data,
+             base::File* file) {
+    bool status;
+    cdm_file->OpenFileForWriting(base::Bind(&CdmStorageTest::FileOpenedForWrite,
+                                            base::Unretained(this), cdm_file,
+                                            data, file, &status));
+    RunAndWaitForResult();
+    return status;
+  }
+
  private:
-  void OpenDone(
-      CdmStorage::Status* status,
-      base::File* file,
-      media::mojom::CdmFileReleaserAssociatedPtr* releaser,
-      CdmStorage::Status actual_status,
-      base::File actual_file,
-      media::mojom::CdmFileReleaserAssociatedPtrInfo actual_releaser) {
+  void OpenDone(CdmStorage::Status* status,
+                base::File* file,
+                CdmFileAssociatedPtr* cdm_file,
+                CdmStorage::Status actual_status,
+                base::File actual_file,
+                CdmFileAssociatedPtrInfo actual_cdm_file) {
     DVLOG(3) << __func__;
     *status = actual_status;
     *file = std::move(actual_file);
 
-    // Open() returns a CdmFileReleaserAssociatedPtrInfo, so bind it to the
-    // CdmFileReleaserAssociatedPtr provided.
-    media::mojom::CdmFileReleaserAssociatedPtr releaser_ptr;
-    releaser_ptr.Bind(std::move(actual_releaser));
-    *releaser = std::move(releaser_ptr);
+    // Open() returns a CdmFileAssociatedPtrInfo, so bind it to the
+    // CdmFileAssociatedPtr provided.
+    CdmFileAssociatedPtr cdm_file_ptr;
+    cdm_file_ptr.Bind(std::move(actual_cdm_file));
+    *cdm_file = std::move(cdm_file_ptr);
+    run_loop_->Quit();
+  }
 
+  void FileOpenedForWrite(CdmFile* cdm_file,
+                          const std::vector<uint8_t>& data,
+                          base::File* file,
+                          bool* status,
+                          base::File file_to_write) {
+    int bytes_to_write = base::checked_cast<int>(data.size());
+    int bytes_written = file_to_write.Write(
+        0, reinterpret_cast<const char*>(data.data()), bytes_to_write);
+    *status = bytes_to_write == bytes_written;
+    cdm_file->CommitWrite(
+        base::Bind(&CdmStorageTest::WriteDone, base::Unretained(this), file));
+  }
+
+  void WriteDone(base::File* file, base::File new_file_for_reading) {
+    *file = std::move(new_file_for_reading);
     run_loop_->Quit();
   }
 
@@ -107,7 +138,7 @@
   }
 
   RenderFrameHost* rfh_ = nullptr;
-  media::mojom::CdmStoragePtr cdm_storage_;
+  CdmStoragePtr cdm_storage_;
   std::unique_ptr<base::RunLoop> run_loop_;
 };
 
@@ -117,11 +148,11 @@
   const char kFileName[] = "valid_file_name";
   CdmStorage::Status status;
   base::File file;
-  media::mojom::CdmFileReleaserAssociatedPtr releaser;
-  EXPECT_FALSE(Open(kFileName, &status, &file, &releaser));
+  CdmFileAssociatedPtr cdm_file;
+  EXPECT_FALSE(Open(kFileName, &status, &file, &cdm_file));
   EXPECT_EQ(status, CdmStorage::Status::kFailure);
   EXPECT_FALSE(file.IsValid());
-  EXPECT_FALSE(releaser.is_bound());
+  EXPECT_FALSE(cdm_file.is_bound());
 }
 
 TEST_F(CdmStorageTest, InvalidFileSystemIdWithBackSlash) {
@@ -130,11 +161,11 @@
   const char kFileName[] = "valid_file_name";
   CdmStorage::Status status;
   base::File file;
-  media::mojom::CdmFileReleaserAssociatedPtr releaser;
-  EXPECT_FALSE(Open(kFileName, &status, &file, &releaser));
+  CdmFileAssociatedPtr cdm_file;
+  EXPECT_FALSE(Open(kFileName, &status, &file, &cdm_file));
   EXPECT_EQ(status, CdmStorage::Status::kFailure);
   EXPECT_FALSE(file.IsValid());
-  EXPECT_FALSE(releaser.is_bound());
+  EXPECT_FALSE(cdm_file.is_bound());
 }
 
 TEST_F(CdmStorageTest, InvalidFileSystemIdEmpty) {
@@ -143,11 +174,11 @@
   const char kFileName[] = "valid_file_name";
   CdmStorage::Status status;
   base::File file;
-  media::mojom::CdmFileReleaserAssociatedPtr releaser;
-  EXPECT_FALSE(Open(kFileName, &status, &file, &releaser));
+  CdmFileAssociatedPtr cdm_file;
+  EXPECT_FALSE(Open(kFileName, &status, &file, &cdm_file));
   EXPECT_EQ(status, CdmStorage::Status::kFailure);
   EXPECT_FALSE(file.IsValid());
-  EXPECT_FALSE(releaser.is_bound());
+  EXPECT_FALSE(cdm_file.is_bound());
 }
 
 TEST_F(CdmStorageTest, InvalidFileNameEmpty) {
@@ -156,11 +187,11 @@
   const char kFileName[] = "";
   CdmStorage::Status status;
   base::File file;
-  media::mojom::CdmFileReleaserAssociatedPtr releaser;
-  EXPECT_FALSE(Open(kFileName, &status, &file, &releaser));
+  CdmFileAssociatedPtr cdm_file;
+  EXPECT_FALSE(Open(kFileName, &status, &file, &cdm_file));
   EXPECT_EQ(status, CdmStorage::Status::kFailure);
   EXPECT_FALSE(file.IsValid());
-  EXPECT_FALSE(releaser.is_bound());
+  EXPECT_FALSE(cdm_file.is_bound());
 }
 
 TEST_F(CdmStorageTest, OpenFile) {
@@ -169,11 +200,11 @@
   const char kFileName[] = "test_file_name";
   CdmStorage::Status status;
   base::File file;
-  media::mojom::CdmFileReleaserAssociatedPtr releaser;
-  EXPECT_TRUE(Open(kFileName, &status, &file, &releaser));
+  CdmFileAssociatedPtr cdm_file;
+  EXPECT_TRUE(Open(kFileName, &status, &file, &cdm_file));
   EXPECT_EQ(status, CdmStorage::Status::kSuccess);
   EXPECT_TRUE(file.IsValid());
-  EXPECT_TRUE(releaser.is_bound());
+  EXPECT_TRUE(cdm_file.is_bound());
 }
 
 TEST_F(CdmStorageTest, OpenFileLocked) {
@@ -182,30 +213,30 @@
   const char kFileName[] = "test_file_name";
   CdmStorage::Status status;
   base::File file1;
-  media::mojom::CdmFileReleaserAssociatedPtr releaser1;
-  EXPECT_TRUE(Open(kFileName, &status, &file1, &releaser1));
+  CdmFileAssociatedPtr cdm_file1;
+  EXPECT_TRUE(Open(kFileName, &status, &file1, &cdm_file1));
   EXPECT_EQ(status, CdmStorage::Status::kSuccess);
   EXPECT_TRUE(file1.IsValid());
-  EXPECT_TRUE(releaser1.is_bound());
+  EXPECT_TRUE(cdm_file1.is_bound());
 
   // Second attempt on the same file should fail as the file is locked.
   base::File file2;
-  media::mojom::CdmFileReleaserAssociatedPtr releaser2;
-  EXPECT_FALSE(Open(kFileName, &status, &file2, &releaser2));
+  CdmFileAssociatedPtr cdm_file2;
+  EXPECT_FALSE(Open(kFileName, &status, &file2, &cdm_file2));
   EXPECT_EQ(status, CdmStorage::Status::kInUse);
   EXPECT_FALSE(file2.IsValid());
-  EXPECT_FALSE(releaser2.is_bound());
+  EXPECT_FALSE(cdm_file2.is_bound());
 
   // Now close the first file and try again. It should be free now.
   file1.Close();
-  releaser1.reset();
+  cdm_file1.reset();
 
   base::File file3;
-  media::mojom::CdmFileReleaserAssociatedPtr releaser3;
-  EXPECT_TRUE(Open(kFileName, &status, &file3, &releaser3));
+  CdmFileAssociatedPtr cdm_file3;
+  EXPECT_TRUE(Open(kFileName, &status, &file3, &cdm_file3));
   EXPECT_EQ(status, CdmStorage::Status::kSuccess);
   EXPECT_TRUE(file3.IsValid());
-  EXPECT_TRUE(releaser3.is_bound());
+  EXPECT_TRUE(cdm_file3.is_bound());
 }
 
 TEST_F(CdmStorageTest, MultipleFiles) {
@@ -214,52 +245,83 @@
   const char kFileName1[] = "file1";
   CdmStorage::Status status;
   base::File file1;
-  media::mojom::CdmFileReleaserAssociatedPtr releaser1;
-  EXPECT_TRUE(Open(kFileName1, &status, &file1, &releaser1));
+  CdmFileAssociatedPtr cdm_file1;
+  EXPECT_TRUE(Open(kFileName1, &status, &file1, &cdm_file1));
   EXPECT_EQ(status, CdmStorage::Status::kSuccess);
   EXPECT_TRUE(file1.IsValid());
-  EXPECT_TRUE(releaser1.is_bound());
+  EXPECT_TRUE(cdm_file1.is_bound());
 
   const char kFileName2[] = "file2";
   base::File file2;
-  media::mojom::CdmFileReleaserAssociatedPtr releaser2;
-  EXPECT_TRUE(Open(kFileName2, &status, &file2, &releaser2));
+  CdmFileAssociatedPtr cdm_file2;
+  EXPECT_TRUE(Open(kFileName2, &status, &file2, &cdm_file2));
   EXPECT_EQ(status, CdmStorage::Status::kSuccess);
   EXPECT_TRUE(file2.IsValid());
-  EXPECT_TRUE(releaser2.is_bound());
+  EXPECT_TRUE(cdm_file2.is_bound());
 
   const char kFileName3[] = "file3";
   base::File file3;
-  media::mojom::CdmFileReleaserAssociatedPtr releaser3;
-  EXPECT_TRUE(Open(kFileName3, &status, &file3, &releaser3));
+  CdmFileAssociatedPtr cdm_file3;
+  EXPECT_TRUE(Open(kFileName3, &status, &file3, &cdm_file3));
   EXPECT_EQ(status, CdmStorage::Status::kSuccess);
   EXPECT_TRUE(file3.IsValid());
-  EXPECT_TRUE(releaser3.is_bound());
+  EXPECT_TRUE(cdm_file3.is_bound());
 }
 
-TEST_F(CdmStorageTest, ReadWriteFile) {
+TEST_F(CdmStorageTest, WriteThenReadFile) {
   Initialize(kTestFileSystemId);
 
   const char kFileName[] = "test_file_name";
   CdmStorage::Status status;
   base::File file;
-  media::mojom::CdmFileReleaserAssociatedPtr releaser;
-  EXPECT_TRUE(Open(kFileName, &status, &file, &releaser));
+  CdmFileAssociatedPtr cdm_file;
+  EXPECT_TRUE(Open(kFileName, &status, &file, &cdm_file));
   EXPECT_EQ(status, CdmStorage::Status::kSuccess);
   EXPECT_TRUE(file.IsValid());
-  EXPECT_TRUE(releaser.is_bound());
+  EXPECT_TRUE(cdm_file.is_bound());
 
   // Write several bytes and read them back.
-  const char kTestData[] = "random string";
+  const uint8_t kTestData[] = "random string";
   const int kTestDataSize = sizeof(kTestData);
-  EXPECT_EQ(kTestDataSize, file.Write(0, kTestData, kTestDataSize));
+  EXPECT_TRUE(Write(cdm_file.get(),
+                    std::vector<uint8_t>(kTestData, kTestData + kTestDataSize),
+                    &file));
+  EXPECT_TRUE(file.IsValid());
 
-  char data_read[32];
+  uint8_t data_read[32];
   const int kTestDataReadSize = sizeof(data_read);
   EXPECT_GT(kTestDataReadSize, kTestDataSize);
-  EXPECT_EQ(kTestDataSize, file.Read(0, data_read, kTestDataReadSize));
+  EXPECT_EQ(kTestDataSize, file.Read(0, reinterpret_cast<char*>(data_read),
+                                     kTestDataReadSize));
   for (size_t i = 0; i < kTestDataSize; i++)
     EXPECT_EQ(kTestData[i], data_read[i]);
 }
 
+TEST_F(CdmStorageTest, ReadThenWriteEmptyFile) {
+  Initialize(kTestFileSystemId);
+
+  const char kFileName[] = "empty_file_name";
+  CdmStorage::Status status;
+  base::File file;
+  CdmFileAssociatedPtr cdm_file;
+  EXPECT_TRUE(Open(kFileName, &status, &file, &cdm_file));
+  EXPECT_EQ(status, CdmStorage::Status::kSuccess);
+  EXPECT_TRUE(file.IsValid());
+  EXPECT_TRUE(cdm_file.is_bound());
+
+  // New file should be empty.
+  uint8_t data_read[32];
+  const int kTestDataReadSize = sizeof(data_read);
+  EXPECT_EQ(
+      0, file.Read(0, reinterpret_cast<char*>(data_read), kTestDataReadSize));
+
+  // Write nothing.
+  EXPECT_TRUE(Write(cdm_file.get(), std::vector<uint8_t>(), &file));
+  EXPECT_TRUE(file.IsValid());
+
+  // Should still be empty.
+  EXPECT_EQ(
+      0, file.Read(0, reinterpret_cast<char*>(data_read), kTestDataReadSize));
+}
+
 }  // namespace content
diff --git a/content/browser/net_info_browsertest.cc b/content/browser/net_info_browsertest.cc
index 5b5ffa72..769136a 100644
--- a/content/browser/net_info_browsertest.cc
+++ b/content/browser/net_info_browsertest.cc
@@ -116,7 +116,7 @@
       net::NetworkChangeNotifier::ConnectionType type,
       net::NetworkChangeNotifier::ConnectionSubtype subtype) {
     net::NetworkChangeNotifier::NotifyObserversOfMaxBandwidthChangeForTests(
-        net::NetworkChangeNotifier::GetMaxBandwidthForConnectionSubtype(
+        net::NetworkChangeNotifier::GetMaxBandwidthMbpsForConnectionSubtype(
             subtype),
         type);
     base::RunLoop().RunUntilIdle();
@@ -154,7 +154,7 @@
   NavigateToURL(shell(), content::GetTestUrl("", "net_info.html"));
   EXPECT_TRUE(RunScriptExtractBool("getOnLine()"));
   EXPECT_EQ("ethernet", RunScriptExtractString("getType()"));
-  EXPECT_EQ(net::NetworkChangeNotifier::GetMaxBandwidthForConnectionSubtype(
+  EXPECT_EQ(net::NetworkChangeNotifier::GetMaxBandwidthMbpsForConnectionSubtype(
                 net::NetworkChangeNotifier::SUBTYPE_GIGABIT_ETHERNET),
             RunScriptExtractDouble("getDownlinkMax()"));
 }
@@ -166,14 +166,14 @@
   SetConnectionType(net::NetworkChangeNotifier::CONNECTION_WIFI,
                     net::NetworkChangeNotifier::SUBTYPE_WIFI_N);
   EXPECT_EQ("wifi", RunScriptExtractString("getType()"));
-  EXPECT_EQ(net::NetworkChangeNotifier::GetMaxBandwidthForConnectionSubtype(
+  EXPECT_EQ(net::NetworkChangeNotifier::GetMaxBandwidthMbpsForConnectionSubtype(
                 net::NetworkChangeNotifier::SUBTYPE_WIFI_N),
             RunScriptExtractDouble("getDownlinkMax()"));
 
   SetConnectionType(net::NetworkChangeNotifier::CONNECTION_ETHERNET,
                     net::NetworkChangeNotifier::SUBTYPE_GIGABIT_ETHERNET);
   EXPECT_EQ("ethernet", RunScriptExtractString("getType()"));
-  EXPECT_EQ(net::NetworkChangeNotifier::GetMaxBandwidthForConnectionSubtype(
+  EXPECT_EQ(net::NetworkChangeNotifier::GetMaxBandwidthMbpsForConnectionSubtype(
                 net::NetworkChangeNotifier::SUBTYPE_GIGABIT_ETHERNET),
             RunScriptExtractDouble("getDownlinkMax()"));
 }
diff --git a/content/browser/notifications/notification_event_dispatcher_impl.cc b/content/browser/notifications/notification_event_dispatcher_impl.cc
index 69acf7f..a83d41a 100644
--- a/content/browser/notifications/notification_event_dispatcher_impl.cc
+++ b/content/browser/notifications/notification_event_dispatcher_impl.cc
@@ -455,12 +455,9 @@
   // closed.
   if (!sender)
     return;
+
   sender->Send(new PlatformNotificationMsg_DidClose(
       non_persistent_ids_[notification_id]));
-
-  static_cast<RenderProcessHostImpl*>(sender)
-      ->notification_message_filter()
-      ->DidCloseNotification(notification_id);
 }
 
 void NotificationEventDispatcherImpl::RendererGone(int renderer_id) {
diff --git a/content/browser/notifications/notification_message_filter.cc b/content/browser/notifications/notification_message_filter.cc
index d56ece3..2b9578b1 100644
--- a/content/browser/notifications/notification_message_filter.cc
+++ b/content/browser/notifications/notification_message_filter.cc
@@ -98,12 +98,6 @@
 
 NotificationMessageFilter::~NotificationMessageFilter() = default;
 
-void NotificationMessageFilter::DidCloseNotification(
-    const std::string& notification_id) {
-  DCHECK_CURRENTLY_ON(BrowserThread::UI);
-  close_closures_.erase(notification_id);
-}
-
 void NotificationMessageFilter::OnDestruct() const {
   if (non_persistent__notification_shown_) {
     NotificationEventDispatcherImpl* event_dispatcher =
@@ -172,13 +166,9 @@
   event_dispatcher->RegisterNonPersistentNotification(
       notification_id, process_id_, non_persistent_notification_id);
 
-  base::Closure close_closure;
   service->DisplayNotification(browser_context_, notification_id, origin,
                                SanitizeNotificationData(notification_data),
-                               notification_resources, &close_closure);
-
-  if (!close_closure.is_null())
-    close_closures_[notification_id] = close_closure;
+                               notification_resources);
 }
 
 void NotificationMessageFilter::OnShowPersistentNotification(
@@ -328,11 +318,11 @@
       GetNotificationIdGenerator()->GenerateForNonPersistentNotification(
           origin, tag, non_persistent_notification_id, process_id_);
 
-  if (!close_closures_.count(notification_id))
-    return;
+  PlatformNotificationService* service =
+      GetContentClient()->browser()->GetPlatformNotificationService();
+  DCHECK(service);
 
-  close_closures_[notification_id].Run();
-  close_closures_.erase(notification_id);
+  service->CloseNotification(browser_context_, notification_id);
 }
 
 void NotificationMessageFilter::OnClosePersistentNotification(
diff --git a/content/browser/notifications/notification_message_filter.h b/content/browser/notifications/notification_message_filter.h
index e3d67c5b..c471053 100644
--- a/content/browser/notifications/notification_message_filter.h
+++ b/content/browser/notifications/notification_message_filter.h
@@ -7,10 +7,8 @@
 
 #include <stdint.h>
 
-#include <map>
 #include <vector>
 
-#include "base/callback_forward.h"
 #include "base/macros.h"
 #include "base/memory/weak_ptr.h"
 #include "content/common/service_worker/service_worker_status_code.h"
@@ -41,10 +39,6 @@
       const scoped_refptr<ServiceWorkerContextWrapper>& service_worker_context,
       BrowserContext* browser_context);
 
-  // To be called by non-persistent notification delegates when they are closed,
-  // so that the close closure associated with that notification can be removed.
-  void DidCloseNotification(const std::string& notification_id);
-
   // BrowserMessageFilter implementation. Called on the UI thread.
   void OnDestruct() const override;
   bool OnMessageReceived(const IPC::Message& message) override;
@@ -140,10 +134,6 @@
   scoped_refptr<ServiceWorkerContextWrapper> service_worker_context_;
   BrowserContext* browser_context_;
 
-  // Map mapping notification IDs associated with non-persistent notifications
-  // to the closures that may be used for programmatically closing them.
-  std::unordered_map<std::string, base::Closure> close_closures_;
-
   base::WeakPtrFactory<NotificationMessageFilter> weak_factory_io_;
 
   DISALLOW_COPY_AND_ASSIGN(NotificationMessageFilter);
diff --git a/content/browser/notifications/platform_notification_context_unittest.cc b/content/browser/notifications/platform_notification_context_unittest.cc
index 64616d96..6a451a2 100644
--- a/content/browser/notifications/platform_notification_context_unittest.cc
+++ b/content/browser/notifications/platform_notification_context_unittest.cc
@@ -32,7 +32,8 @@
 class NotificationBrowserClient : public TestContentBrowserClient {
  public:
   NotificationBrowserClient()
-      : platform_notification_service_(new MockPlatformNotificationService()) {}
+      : platform_notification_service_(
+            std::make_unique<MockPlatformNotificationService>()) {}
 
   PlatformNotificationService* GetPlatformNotificationService() override {
     return platform_notification_service_.get();
diff --git a/content/browser/presentation/presentation_service_impl.h b/content/browser/presentation/presentation_service_impl.h
index a5f783a33..c16c5647 100644
--- a/content/browser/presentation/presentation_service_impl.h
+++ b/content/browser/presentation/presentation_service_impl.h
@@ -215,7 +215,7 @@
       const content::PresentationInfo& presentation_info,
       std::vector<content::PresentationConnectionMessage> messages);
 
-  // A callback registered to OffscreenPresentationManager when
+  // A callback registered to LocalPresentationManager when
   // the PresentationServiceImpl for the presentation receiver is initialized.
   // Calls |client_| to create a new PresentationConnection on receiver page.
   void OnReceiverConnectionAvailable(
diff --git a/content/browser/presentation/presentation_service_impl_unittest.cc b/content/browser/presentation/presentation_service_impl_unittest.cc
index e72f236..52e87590 100644
--- a/content/browser/presentation/presentation_service_impl_unittest.cc
+++ b/content/browser/presentation/presentation_service_impl_unittest.cc
@@ -169,12 +169,12 @@
       const PresentationInfo& presentation_info,
       PresentationConnectionPtr controller_conn_ptr,
       PresentationConnectionRequest receiver_conn_request) override {
-    RegisterOffscreenPresentationConnectionRaw(
-        render_process_id, render_frame_id, presentation_info,
-        controller_conn_ptr.get());
+    RegisterLocalPresentationConnectionRaw(render_process_id, render_frame_id,
+                                           presentation_info,
+                                           controller_conn_ptr.get());
   }
 
-  MOCK_METHOD4(RegisterOffscreenPresentationConnectionRaw,
+  MOCK_METHOD4(RegisterLocalPresentationConnectionRaw,
                void(int render_process_id,
                     int render_frame_id,
                     const PresentationInfo& presentation_info,
@@ -619,7 +619,7 @@
   auto request = mojo::MakeRequest(&receiver_connection);
 
   PresentationInfo expected(presentation_url1_, kPresentationId);
-  EXPECT_CALL(mock_delegate_, RegisterOffscreenPresentationConnectionRaw(
+  EXPECT_CALL(mock_delegate_, RegisterLocalPresentationConnectionRaw(
                                   _, _, InfoEquals(expected), _));
 
   service_impl_->SetPresentationConnection(
diff --git a/content/browser/renderer_host/compositor_impl_android.cc b/content/browser/renderer_host/compositor_impl_android.cc
index 2b1c63d..e63a6fd 100644
--- a/content/browser/renderer_host/compositor_impl_android.cc
+++ b/content/browser/renderer_host/compositor_impl_android.cc
@@ -61,7 +61,6 @@
 #include "content/public/browser/android/compositor.h"
 #include "content/public/browser/android/compositor_client.h"
 #include "content/public/browser/browser_thread.h"
-#include "content/public/common/content_switches.h"
 #include "gpu/command_buffer/client/context_support.h"
 #include "gpu/command_buffer/client/gles2_interface.h"
 #include "gpu/ipc/client/command_buffer_proxy_impl.h"
@@ -690,25 +689,6 @@
     return;
 #endif
 
-  if (!base::CommandLine::ForCurrentProcess()->HasSwitch(
-          switches::kDisableTimeoutsForProfiling)) {
-#if defined(ADDRESS_SANITIZER) || defined(THREAD_SANITIZER) || \
-    defined(SYZYASAN) || defined(CYGPROFILE_INSTRUMENTATION)
-    const int64_t kGpuChannelTimeoutInSeconds = 40;
-#else
-    // The GPU watchdog timeout is 15 seconds (1.5x the kGpuTimeout value due to
-    // logic in GpuWatchdogThread). Make this slightly longer to give the GPU a
-    // chance to crash itself before crashing the browser.
-    const int64_t kGpuChannelTimeoutInSeconds = 20;
-#endif
-
-    // Start the timer first, if the result comes synchronously, we want it to
-    // stop in the callback.
-    establish_gpu_channel_timeout_.Start(
-        FROM_HERE, base::TimeDelta::FromSeconds(kGpuChannelTimeoutInSeconds),
-        this, &CompositorImpl::OnGpuChannelTimeout);
-  }
-
   DCHECK(surface_handle_ != gpu::kNullSurfaceHandle);
   BrowserMainLoop::GetInstance()
       ->gpu_channel_establish_factory()
@@ -716,10 +696,6 @@
                                        weak_factory_.GetWeakPtr()));
 }
 
-void CompositorImpl::OnGpuChannelTimeout() {
-  LOG(FATAL) << "Timed out waiting for GPU channel.";
-}
-
 #if BUILDFLAG(ENABLE_VULKAN)
 void CompositorImpl::CreateVulkanOutputSurface() {
   if (!base::CommandLine::ForCurrentProcess()->HasSwitch(
@@ -744,8 +720,6 @@
 
 void CompositorImpl::OnGpuChannelEstablished(
     scoped_refptr<gpu::GpuChannelHost> gpu_channel_host) {
-  establish_gpu_channel_timeout_.Stop();
-
   // We might end up queing multiple GpuChannel requests for the same
   // LayerTreeFrameSink request as the visibility of the compositor changes, so
   // the LayerTreeFrameSink request could have been handled already.
diff --git a/content/browser/renderer_host/compositor_impl_android.h b/content/browser/renderer_host/compositor_impl_android.h
index 735a43b2..fe0f857 100644
--- a/content/browser/renderer_host/compositor_impl_android.h
+++ b/content/browser/renderer_host/compositor_impl_android.h
@@ -14,7 +14,6 @@
 #include "base/macros.h"
 #include "base/memory/weak_ptr.h"
 #include "base/observer_list.h"
-#include "base/timer/timer.h"
 #include "cc/trees/layer_tree_host_client.h"
 #include "cc/trees/layer_tree_host_single_thread_client.h"
 #include "components/viz/common/surfaces/frame_sink_id.h"
@@ -136,7 +135,6 @@
 #endif
   void OnGpuChannelEstablished(
       scoped_refptr<gpu::GpuChannelHost> gpu_channel_host);
-  void OnGpuChannelTimeout();
   void InitializeDisplay(
       std::unique_ptr<viz::OutputSurface> display_output_surface,
       scoped_refptr<viz::VulkanContextProvider> vulkan_context_provider,
@@ -181,8 +179,6 @@
   // the GPU thread.
   unsigned int pending_frames_;
 
-  base::OneShotTimer establish_gpu_channel_timeout_;
-
   // Whether there is a LayerTreeFrameSink request pending from the current
   // |host_|. Becomes |true| if RequestNewLayerTreeFrameSink is called, and
   // |false| if |host_| is deleted or we succeed in creating *and* initializing
diff --git a/content/browser/renderer_host/input/touch_selection_controller_client_aura_browsertest.cc b/content/browser/renderer_host/input/touch_selection_controller_client_aura_browsertest.cc
index e532066..854405d 100644
--- a/content/browser/renderer_host/input/touch_selection_controller_client_aura_browsertest.cc
+++ b/content/browser/renderer_host/input/touch_selection_controller_client_aura_browsertest.cc
@@ -848,7 +848,7 @@
 
   const int window_width = rwhva->GetNativeView()->bounds().width();
   const float overscroll_threshold =
-      GetOverscrollConfig(OVERSCROLL_CONFIG_HORIZ_THRESHOLD_START_TOUCHSCREEN);
+      GetOverscrollConfig(OverscrollConfig::THRESHOLD_START_TOUCHSCREEN);
   const float scroll_amount = window_width * overscroll_threshold + 1;
   event_x += scroll_amount;
   ui::GestureEventDetails scroll_update_details(ui::ET_GESTURE_SCROLL_UPDATE,
diff --git a/content/browser/renderer_host/offscreen_canvas_provider_impl_unittest.cc b/content/browser/renderer_host/offscreen_canvas_provider_impl_unittest.cc
index 872b58b..fdc8db6 100644
--- a/content/browser/renderer_host/offscreen_canvas_provider_impl_unittest.cc
+++ b/content/browser/renderer_host/offscreen_canvas_provider_impl_unittest.cc
@@ -12,9 +12,11 @@
 #include "base/message_loop/message_loop.h"
 #include "base/run_loop.h"
 #include "components/viz/common/quads/compositor_frame.h"
+#include "components/viz/host/host_frame_sink_manager.h"
+#include "components/viz/service/frame_sinks/frame_sink_manager_impl.h"
+#include "components/viz/test/fake_host_frame_sink_client.h"
 #include "components/viz/test/mock_compositor_frame_sink_client.h"
 #include "content/browser/compositor/surface_utils.h"
-#include "content/browser/compositor/test/no_transport_image_transport_factory.h"
 #include "content/browser/renderer_host/offscreen_canvas_surface_impl.h"
 #include "services/viz/public/interfaces/compositing/compositor_frame_sink.mojom.h"
 #include "testing/gmock/include/gmock/gmock.h"
@@ -120,10 +122,6 @@
 
  protected:
   void SetUp() override {
-#if !defined(OS_ANDROID)
-    ImageTransportFactory::SetFactory(
-        std::make_unique<NoTransportImageTransportFactory>());
-#endif
     host_frame_sink_manager_ = std::make_unique<viz::HostFrameSinkManager>();
 
     // The FrameSinkManagerImpl implementation is in-process here for tests.
@@ -133,20 +131,21 @@
 
     provider_ = std::make_unique<OffscreenCanvasProviderImpl>(
         host_frame_sink_manager_.get(), kRendererClientId);
+
+    host_frame_sink_manager_->RegisterFrameSinkId(kFrameSinkParent,
+                                                  &host_frame_sink_client_);
   }
   void TearDown() override {
     provider_.reset();
     frame_sink_manager_.reset();
     host_frame_sink_manager_.reset();
-#if !defined(OS_ANDROID)
-    ImageTransportFactory::Terminate();
-#endif
   }
 
  private:
   // A MessageLoop is required for mojo bindings which are used to
   // connect to graphics services.
   base::MessageLoop message_loop_;
+  viz::FakeHostFrameSinkClient host_frame_sink_client_;
   std::unique_ptr<viz::HostFrameSinkManager> host_frame_sink_manager_;
   std::unique_ptr<viz::FrameSinkManagerImpl> frame_sink_manager_;
   std::unique_ptr<OffscreenCanvasProviderImpl> provider_;
diff --git a/content/browser/renderer_host/overscroll_configuration.cc b/content/browser/renderer_host/overscroll_configuration.cc
index 80f975b..b7544655 100644
--- a/content/browser/renderer_host/overscroll_configuration.cc
+++ b/content/browser/renderer_host/overscroll_configuration.cc
@@ -11,26 +11,25 @@
 
 namespace {
 
-const float kHorizThresholdComplete = 0.25f;
-const float kVertThresholdComplete = 0.20f;
+const float kThresholdCompleteTouchpad = 0.3f;
+const float kThresholdCompleteTouchscreen = 0.25f;
 
-const float kHorizThresholdStartTouchscreen = 50.f;
-const float kHorizThresholdStartTouchpad = 50.f;
-const float kVertThresholdStart = 50.f;
+const float kThresholdStartTouchpad = 60.f;
+const float kThresholdStartTouchscreen = 50.f;
 
-float GetHorizontalStartThresholdMultiplier() {
+float GetStartThresholdMultiplier() {
   base::CommandLine* cmd = base::CommandLine::ForCurrentProcess();
   if (!cmd->HasSwitch(switches::kOverscrollStartThreshold))
     return 1.f;
+
   std::string string_value =
       cmd->GetSwitchValueASCII(switches::kOverscrollStartThreshold);
   int percentage;
-  if (base::StringToInt(string_value, &percentage) && percentage > 0) {
+  if (base::StringToInt(string_value, &percentage) && percentage > 0)
     return percentage / 100.f;
-  }
 
   DLOG(WARNING) << "Failed to parse switch "
-               << switches::kOverscrollStartThreshold << ": " << string_value;
+                << switches::kOverscrollStartThreshold << ": " << string_value;
   return 1.f;
 }
 
@@ -40,31 +39,24 @@
 
 float GetOverscrollConfig(OverscrollConfig config) {
   switch (config) {
-    case OVERSCROLL_CONFIG_HORIZ_THRESHOLD_COMPLETE:
-      return kHorizThresholdComplete;
+    case OverscrollConfig::THRESHOLD_COMPLETE_TOUCHPAD:
+      return kThresholdCompleteTouchpad;
 
-    case OVERSCROLL_CONFIG_VERT_THRESHOLD_COMPLETE:
-      return kVertThresholdComplete;
+    case OverscrollConfig::THRESHOLD_COMPLETE_TOUCHSCREEN:
+      return kThresholdCompleteTouchscreen;
 
-    case OVERSCROLL_CONFIG_HORIZ_THRESHOLD_START_TOUCHSCREEN:
-      static const float horiz_threshold_start_touchscreen =
-          GetHorizontalStartThresholdMultiplier() *
-          kHorizThresholdStartTouchscreen;
-      return horiz_threshold_start_touchscreen;
+    case OverscrollConfig::THRESHOLD_START_TOUCHPAD:
+      static const float threshold_start_touchpad =
+          GetStartThresholdMultiplier() * kThresholdStartTouchpad;
+      return threshold_start_touchpad;
 
-    case OVERSCROLL_CONFIG_HORIZ_THRESHOLD_START_TOUCHPAD:
-      static const float horiz_threshold_start_touchpad =
-          GetHorizontalStartThresholdMultiplier() *
-          kHorizThresholdStartTouchpad;
-      return horiz_threshold_start_touchpad;
-
-    case OVERSCROLL_CONFIG_VERT_THRESHOLD_START:
-      return kVertThresholdStart;
-
-    case OVERSCROLL_CONFIG_NONE:
-      NOTREACHED();
+    case OverscrollConfig::THRESHOLD_START_TOUCHSCREEN:
+      static const float threshold_start_touchscreen =
+          GetStartThresholdMultiplier() * kThresholdStartTouchscreen;
+      return threshold_start_touchscreen;
   }
 
+  NOTREACHED();
   return -1.f;
 }
 
diff --git a/content/browser/renderer_host/overscroll_controller.cc b/content/browser/renderer_host/overscroll_controller.cc
index ba933016..3d9b66f0 100644
--- a/content/browser/renderer_host/overscroll_controller.cc
+++ b/content/browser/renderer_host/overscroll_controller.cc
@@ -12,8 +12,6 @@
 #include "content/public/browser/overscroll_configuration.h"
 #include "content/public/common/content_switches.h"
 
-using blink::WebInputEvent;
-
 namespace content {
 
 namespace {
@@ -185,6 +183,7 @@
     const blink::WebInputEvent& event) const {
   if (overscroll_mode_ == OVERSCROLL_NONE)
     return false;
+  DCHECK_NE(OverscrollSource::NONE, overscroll_source_);
 
   // Complete the overscroll gesture if there was a mouse move or a scroll-end
   // after the threshold.
@@ -197,7 +196,8 @@
   // from the touchpad since it is sent based on a timeout not
   // when the user has stopped interacting.
   if (event.GetType() == blink::WebInputEvent::kGestureScrollEnd &&
-      IsGestureEventFromTouchpad(event)) {
+      overscroll_source_ == OverscrollSource::TOUCHPAD) {
+    DCHECK(IsGestureEventFromTouchpad(event));
     return false;
   }
 
@@ -234,16 +234,15 @@
   if (size.IsEmpty())
     return false;
 
-  float ratio, threshold;
-  if (overscroll_mode_ == OVERSCROLL_WEST ||
-      overscroll_mode_ == OVERSCROLL_EAST) {
-    ratio = fabs(overscroll_delta_x_) / size.width();
-    threshold = GetOverscrollConfig(OVERSCROLL_CONFIG_HORIZ_THRESHOLD_COMPLETE);
-  } else {
-    ratio = fabs(overscroll_delta_y_) / size.height();
-    threshold = GetOverscrollConfig(OVERSCROLL_CONFIG_VERT_THRESHOLD_COMPLETE);
-  }
-
+  const float delta =
+      overscroll_mode_ == OVERSCROLL_WEST || overscroll_mode_ == OVERSCROLL_EAST
+          ? overscroll_delta_x_
+          : overscroll_delta_y_;
+  const float ratio = fabs(delta) / std::max(size.width(), size.height());
+  const float threshold = GetOverscrollConfig(
+      overscroll_source_ == OverscrollSource::TOUCHPAD
+          ? OverscrollConfig::THRESHOLD_COMPLETE_TOUCHPAD
+          : OverscrollConfig::THRESHOLD_COMPLETE_TOUCHSCREEN);
   return ratio >= threshold;
 }
 
@@ -352,13 +351,11 @@
     overscroll_delta_y_ += delta_y;
   }
 
-  const float horiz_threshold = GetOverscrollConfig(
-      is_touchpad ? OVERSCROLL_CONFIG_HORIZ_THRESHOLD_START_TOUCHPAD
-                  : OVERSCROLL_CONFIG_HORIZ_THRESHOLD_START_TOUCHSCREEN);
-  const float vert_threshold =
-      GetOverscrollConfig(OVERSCROLL_CONFIG_VERT_THRESHOLD_START);
-  if (fabs(overscroll_delta_x_) <= horiz_threshold &&
-      fabs(overscroll_delta_y_) <= vert_threshold) {
+  const float start_threshold = GetOverscrollConfig(
+      is_touchpad ? OverscrollConfig::THRESHOLD_START_TOUCHPAD
+                  : OverscrollConfig::THRESHOLD_START_TOUCHSCREEN);
+  if (fabs(overscroll_delta_x_) <= start_threshold &&
+      fabs(overscroll_delta_y_) <= start_threshold) {
     SetOverscrollMode(OVERSCROLL_NONE, OverscrollSource::NONE);
     return true;
   }
@@ -371,12 +368,12 @@
         case OVERSCROLL_WEST:
         case OVERSCROLL_EAST:
           overscroll_delta_x_ = ClampAbsoluteValue(
-              overscroll_delta_x_, cap.value() + horiz_threshold);
+              overscroll_delta_x_, cap.value() + start_threshold);
           break;
         case OVERSCROLL_NORTH:
         case OVERSCROLL_SOUTH:
           overscroll_delta_y_ = ClampAbsoluteValue(
-              overscroll_delta_y_, cap.value() + vert_threshold);
+              overscroll_delta_y_, cap.value() + start_threshold);
           break;
         case OVERSCROLL_NONE:
           break;
@@ -389,10 +386,10 @@
   // to make sure that subsequent scroll events go through to the page first.
   OverscrollMode new_mode = OVERSCROLL_NONE;
   const float kMinRatio = 2.5;
-  if (fabs(overscroll_delta_x_) > horiz_threshold &&
+  if (fabs(overscroll_delta_x_) > start_threshold &&
       fabs(overscroll_delta_x_) > fabs(overscroll_delta_y_) * kMinRatio)
     new_mode = overscroll_delta_x_ > 0.f ? OVERSCROLL_EAST : OVERSCROLL_WEST;
-  else if (fabs(overscroll_delta_y_) > vert_threshold &&
+  else if (fabs(overscroll_delta_y_) > start_threshold &&
            fabs(overscroll_delta_y_) > fabs(overscroll_delta_x_) * kMinRatio)
     new_mode = overscroll_delta_y_ > 0.f ? OVERSCROLL_SOUTH : OVERSCROLL_NORTH;
 
@@ -418,21 +415,21 @@
     // Do not include the threshold amount when sending the deltas to the
     // delegate.
     float delegate_delta_x = overscroll_delta_x_;
-    if (fabs(delegate_delta_x) > horiz_threshold) {
+    if (fabs(delegate_delta_x) > start_threshold) {
       if (delegate_delta_x < 0)
-        delegate_delta_x += horiz_threshold;
+        delegate_delta_x += start_threshold;
       else
-        delegate_delta_x -= horiz_threshold;
+        delegate_delta_x -= start_threshold;
     } else {
       delegate_delta_x = 0.f;
     }
 
     float delegate_delta_y = overscroll_delta_y_;
-    if (fabs(delegate_delta_y) > vert_threshold) {
+    if (fabs(delegate_delta_y) > start_threshold) {
       if (delegate_delta_y < 0)
-        delegate_delta_y += vert_threshold;
+        delegate_delta_y += start_threshold;
       else
-        delegate_delta_y -= vert_threshold;
+        delegate_delta_y -= start_threshold;
     } else {
       delegate_delta_y = 0.f;
     }
diff --git a/content/browser/renderer_host/render_process_host_impl.cc b/content/browser/renderer_host/render_process_host_impl.cc
index bfd6f1e..b05b834 100644
--- a/content/browser/renderer_host/render_process_host_impl.cc
+++ b/content/browser/renderer_host/render_process_host_impl.cc
@@ -141,6 +141,7 @@
 #include "content/common/content_switches_internal.h"
 #include "content/common/frame_messages.h"
 #include "content/common/in_process_child_thread_params.h"
+#include "content/common/navigation_subresource_loader_params.h"
 #include "content/common/render_process_messages.h"
 #include "content/common/resource_messages.h"
 #include "content/common/service_manager/child_connection.h"
@@ -172,6 +173,7 @@
 #include "content/public/common/sandboxed_process_launcher_delegate.h"
 #include "content/public/common/service_names.mojom.h"
 #include "content/public/common/url_constants.h"
+#include "device/gamepad/gamepad_haptics_manager.h"
 #include "device/gamepad/gamepad_monitor.h"
 #include "gpu/GLES2/gl2extchromium.h"
 #include "gpu/command_buffer/client/gpu_switches.h"
@@ -1856,6 +1858,13 @@
                                     base::Unretained(this)));
   }
 
+  media::VideoDecodePerfHistory* video_perf_history =
+      GetBrowserContext()->GetVideoDecodePerfHistory();
+  AddUIThreadInterface(
+      registry.get(),
+      base::BindRepeating(&media::VideoDecodePerfHistory::BindRequest,
+                          base::Unretained(video_perf_history)));
+
   registry->AddInterface(
       base::Bind(&MimeRegistryImpl::Create),
       base::CreateSequencedTaskRunnerWithTraits(
@@ -1866,6 +1875,8 @@
                          hyphenation::HyphenationImpl::GetTaskRunner());
 #endif
 
+  registry->AddInterface(base::Bind(&device::GamepadHapticsManager::Create));
+
   registry->AddInterface(base::Bind(&device::GamepadMonitor::Create));
 
   registry->AddInterface(
@@ -1941,9 +1952,6 @@
                    storage_partition_impl_->GetBlobRegistry(), GetID()));
   }
 
-  registry->AddInterface(
-      base::Bind(&media::VideoDecodePerfHistory::BindRequest));
-
   ServiceManagerConnection* service_manager_connection =
       BrowserContext::GetServiceManagerConnectionFor(browser_context_);
   std::unique_ptr<ConnectionFilterImpl> connection_filter(
diff --git a/content/browser/renderer_host/render_process_host_unittest.cc b/content/browser/renderer_host/render_process_host_unittest.cc
index fbbba99..9b80395e 100644
--- a/content/browser/renderer_host/render_process_host_unittest.cc
+++ b/content/browser/renderer_host/render_process_host_unittest.cc
@@ -78,7 +78,7 @@
 #endif
 
 #if defined(OS_ANDROID) || defined(OS_CHROMEOS)
-TEST_F(RenderProcessHostUnitTest, NoRendererProcessLimitOnAndroid) {
+TEST_F(RenderProcessHostUnitTest, NoRendererProcessLimitOnAndroidOrChromeOS) {
   // Disable any overrides.
   RenderProcessHostImpl::SetMaxRendererProcessCount(0);
 
@@ -130,9 +130,10 @@
   // return the process of the subframe RFH.
   std::string unique_name("uniqueName0");
   main_test_rfh()->OnCreateChildFrame(
-      process()->GetNextRoutingID(), blink::WebTreeScopeType::kDocument,
-      std::string(), unique_name, base::UnguessableToken::Create(),
-      FramePolicy(), FrameOwnerProperties());
+      process()->GetNextRoutingID(),
+      TestRenderFrameHost::CreateStubInterfaceProviderRequest(),
+      blink::WebTreeScopeType::kDocument, std::string(), unique_name,
+      base::UnguessableToken::Create(), FramePolicy(), FrameOwnerProperties());
   TestRenderFrameHost* subframe = static_cast<TestRenderFrameHost*>(
       contents()->GetFrameTree()->root()->child_at(0)->current_frame_host());
   subframe = static_cast<TestRenderFrameHost*>(
diff --git a/content/browser/renderer_host/render_view_host_impl.cc b/content/browser/renderer_host/render_view_host_impl.cc
index 75003ac..1d8f28d 100644
--- a/content/browser/renderer_host/render_view_host_impl.cc
+++ b/content/browser/renderer_host/render_view_host_impl.cc
@@ -308,6 +308,8 @@
     RenderFrameHostImpl* main_rfh = RenderFrameHostImpl::FromID(
         GetProcess()->GetID(), main_frame_routing_id_);
     DCHECK(main_rfh);
+    main_rfh->BindInterfaceProviderRequest(
+        mojo::MakeRequest(&params->main_frame_interface_provider));
     RenderWidgetHostImpl* main_rwh = main_rfh->GetRenderWidgetHost();
     params->main_frame_widget_routing_id = main_rwh->GetRoutingID();
   }
diff --git a/content/browser/renderer_host/render_widget_host_view_aura.cc b/content/browser/renderer_host/render_widget_host_view_aura.cc
index b119ec4..e9b0ec5 100644
--- a/content/browser/renderer_host/render_widget_host_view_aura.cc
+++ b/content/browser/renderer_host/render_widget_host_view_aura.cc
@@ -930,6 +930,14 @@
   UpdateBackgroundColorFromRenderer(frame.metadata.root_background_color);
 
   last_scroll_offset_ = frame.metadata.root_scroll_offset;
+  if (IsUseZoomForDSFEnabled()) {
+    // With zoom-for-DSF Blink pixel coordinates are used and zoom is used to
+    // adjusts for the device scale factor. That's why last_scroll_offset_
+    // needs to be scaled to view coordinates.
+    // Without zoom-for-DSF the values are already in view coordinates.
+    last_scroll_offset_.Scale(1.0f / current_device_scale_factor_);
+  }
+
   if (delegated_frame_host_) {
     delegated_frame_host_->SubmitCompositorFrame(local_surface_id,
                                                  std::move(frame));
@@ -1701,6 +1709,10 @@
 void RenderWidgetHostViewAura::FocusedNodeChanged(
     bool editable,
     const gfx::Rect& node_bounds_in_screen) {
+  if (GetInputMethod())
+    GetInputMethod()->CancelComposition(this);
+  has_composition_text_ = false;
+
 #if defined(OS_WIN)
   if (!editable && virtual_keyboard_requested_) {
     virtual_keyboard_requested_ = false;
diff --git a/content/browser/renderer_host/render_widget_host_view_aura.h b/content/browser/renderer_host/render_widget_host_view_aura.h
index e60bd3f..a387836 100644
--- a/content/browser/renderer_host/render_widget_host_view_aura.h
+++ b/content/browser/renderer_host/render_widget_host_view_aura.h
@@ -365,6 +365,7 @@
   FRIEND_TEST_ALL_PREFIXES(RenderWidgetHostViewAuraTest,
                            PopupRetainsCaptureAfterMouseRelease);
   FRIEND_TEST_ALL_PREFIXES(RenderWidgetHostViewAuraTest, SetCompositionText);
+  FRIEND_TEST_ALL_PREFIXES(RenderWidgetHostViewAuraTest, FocusedNodeChanged);
   FRIEND_TEST_ALL_PREFIXES(RenderWidgetHostViewAuraTest, TouchEventState);
   FRIEND_TEST_ALL_PREFIXES(RenderWidgetHostViewAuraTest,
                            TouchEventPositionsArentRounded);
diff --git a/content/browser/renderer_host/render_widget_host_view_aura_unittest.cc b/content/browser/renderer_host/render_widget_host_view_aura_unittest.cc
index 17b6658..4826e33 100644
--- a/content/browser/renderer_host/render_widget_host_view_aura_unittest.cc
+++ b/content/browser/renderer_host/render_widget_host_view_aura_unittest.cc
@@ -86,6 +86,7 @@
 #include "ui/aura/window_event_dispatcher.h"
 #include "ui/aura/window_observer.h"
 #include "ui/base/clipboard/clipboard.h"
+#include "ui/base/ime/input_method.h"
 #include "ui/base/ui_base_switches.h"
 #include "ui/base/ui_base_types.h"
 #include "ui/compositor/compositor.h"
@@ -1629,6 +1630,22 @@
   EXPECT_FALSE(view_->has_composition_text_);
 }
 
+// Checks that we reset has_composition_text_ to false upon when the focused
+// node is changed.
+TEST_F(RenderWidgetHostViewAuraTest, FocusedNodeChanged) {
+  view_->InitAsChild(nullptr);
+  view_->Show();
+  ActivateViewForTextInputManager(view_, ui::TEXT_INPUT_TYPE_TEXT);
+
+  ui::CompositionText composition_text;
+  composition_text.text = base::ASCIIToUTF16("hello");
+  view_->SetCompositionText(composition_text);
+  EXPECT_TRUE(view_->has_composition_text_);
+
+  view_->FocusedNodeChanged(true, gfx::Rect());
+  EXPECT_FALSE(view_->has_composition_text_);
+}
+
 // Checks that sequence of IME-composition-event and mouse-event when mouse
 // clicking to cancel the composition.
 TEST_F(RenderWidgetHostViewAuraTest, FinishCompositionByMouse) {
@@ -3860,11 +3877,12 @@
 void RenderWidgetHostViewAuraOverscrollTest::WheelNotPreciseScrollEvent() {
   SetUpOverscrollEnvironment();
 
-  // Simulate wheel events.
+  // Simulate wheel event. Does not cross start threshold.
   SimulateWheelEventPossiblyIncludingPhase(
       -5, 0, 0, false, WebMouseWheelEvent::kPhaseBegan);  // sent directly
+  // Simulate wheel event. Crosses start threshold.
   SimulateWheelEventPossiblyIncludingPhase(
-      -60, 1, 0, false, WebMouseWheelEvent::kPhaseChanged);  // enqueued
+      -70, 1, 0, false, WebMouseWheelEvent::kPhaseChanged);  // enqueued
   EXPECT_EQ(OVERSCROLL_NONE, overscroll_mode());
   EXPECT_EQ(OverscrollSource::NONE, overscroll_source());
   MockWidgetInputHandler::MessageVector events =
@@ -3920,17 +3938,18 @@
 void RenderWidgetHostViewAuraOverscrollTest::WheelScrollEventOverscrolls() {
   SetUpOverscrollEnvironment();
 
-  // Simulate wheel events.
+  // Simulate wheel events. Do not cross start threshold.
   SimulateWheelEventPossiblyIncludingPhase(
       -5, 0, 0, true, WebMouseWheelEvent::kPhaseBegan);  // sent directly
   SimulateWheelEventPossiblyIncludingPhase(
-      -1, 1, 0, true, WebMouseWheelEvent::kPhaseChanged);  // enqueued
+      -10, 1, 0, true, WebMouseWheelEvent::kPhaseChanged);  // enqueued
   SimulateWheelEventPossiblyIncludingPhase(
       -10, -3, 0, true,
       WebMouseWheelEvent::kPhaseChanged);  // coalesced into previous event
   SimulateWheelEventPossiblyIncludingPhase(
       -15, -1, 0, true,
       WebMouseWheelEvent::kPhaseChanged);  // coalesced into previous event
+  // Simulate wheel events. Cross start threshold.
   SimulateWheelEventPossiblyIncludingPhase(
       -30, -3, 0, true,
       WebMouseWheelEvent::kPhaseChanged);  // coalesced into previous event
@@ -3971,8 +3990,8 @@
   EXPECT_EQ(OVERSCROLL_WEST, overscroll_mode());
   EXPECT_EQ(OverscrollSource::TOUCHPAD, overscroll_source());
   EXPECT_EQ(OVERSCROLL_WEST, overscroll_delegate()->current_mode());
-  EXPECT_EQ(-81.f, overscroll_delta_x());
-  EXPECT_EQ(-31.f, overscroll_delegate()->delta_x());
+  EXPECT_EQ(-90.f, overscroll_delta_x());
+  EXPECT_EQ(-30.f, overscroll_delegate()->delta_x());
   EXPECT_EQ(0.f, overscroll_delegate()->delta_y());
   events = GetAndResetDispatchedMessages();
   EXPECT_EQ(0U, events.size());
@@ -4003,17 +4022,18 @@
     WheelScrollConsumedDoNotHorizOverscroll() {
   SetUpOverscrollEnvironment();
 
-  // Simulate wheel events.
+  // Simulate wheel events. Do not cross start threshold.
   SimulateWheelEventPossiblyIncludingPhase(
       -5, 0, 0, true, WebMouseWheelEvent::kPhaseBegan);  // sent directly
   SimulateWheelEventPossiblyIncludingPhase(
-      -1, -1, 0, true, WebMouseWheelEvent::kPhaseChanged);  // enqueued
+      -10, -1, 0, true, WebMouseWheelEvent::kPhaseChanged);  // enqueued
   SimulateWheelEventPossiblyIncludingPhase(
       -10, -3, 0, true,
       WebMouseWheelEvent::kPhaseChanged);  // coalesced into previous event
   SimulateWheelEventPossiblyIncludingPhase(
       -15, -1, 0, true,
       WebMouseWheelEvent::kPhaseChanged);  // coalesced into previous event
+  // Simulate wheel events. Cross start threshold.
   SimulateWheelEventPossiblyIncludingPhase(
       -30, -3, 0, true,
       WebMouseWheelEvent::kPhaseChanged);  // coalesced into previous event
@@ -4133,7 +4153,7 @@
   EXPECT_EQ(OVERSCROLL_NONE, overscroll_delegate()->current_mode());
 
   // Scroll some more to initiate an overscroll.
-  SimulateWheelEventPossiblyIncludingPhase(40, 0, 0, true,
+  SimulateWheelEventPossiblyIncludingPhase(50, 0, 0, true,
                                            WebMouseWheelEvent::kPhaseChanged);
   if (wheel_scrolling_mode_ == kAsyncWheelEvents) {
     events = ExpectGestureScrollUpdateAfterNonBlockingMouseWheelACK(false);
@@ -4150,7 +4170,7 @@
   EXPECT_EQ(OVERSCROLL_EAST, overscroll_mode());
   EXPECT_EQ(OverscrollSource::TOUCHPAD, overscroll_source());
   EXPECT_EQ(OVERSCROLL_EAST, overscroll_delegate()->current_mode());
-  EXPECT_EQ(60.f, overscroll_delta_x());
+  EXPECT_EQ(70.f, overscroll_delta_x());
   EXPECT_EQ(10.f, overscroll_delegate()->delta_x());
   EXPECT_EQ(0.f, overscroll_delegate()->delta_y());
 
@@ -4185,7 +4205,7 @@
   // Continue to scroll in the reverse direction enough to initiate overscroll
   // in that direction. However, overscroll should not be initiated as the
   // overscroll mode is locked to east mode.
-  SimulateWheelEventPossiblyIncludingPhase(-55, 0, 0, true,
+  SimulateWheelEventPossiblyIncludingPhase(-65, 0, 0, true,
                                            WebMouseWheelEvent::kPhaseChanged);
   events = GetAndResetDispatchedMessages();
   EXPECT_EQ("MouseWheel", GetMessageNames(events));
@@ -4210,7 +4230,7 @@
   EXPECT_EQ(OVERSCROLL_NONE, overscroll_mode());
   EXPECT_EQ(OverscrollSource::NONE, overscroll_source());
   EXPECT_EQ(OVERSCROLL_NONE, overscroll_delegate()->current_mode());
-  EXPECT_EQ(-95.f, overscroll_delta_x());
+  EXPECT_EQ(-105.f, overscroll_delta_x());
   EXPECT_EQ(0.f, overscroll_delegate()->delta_x());
   EXPECT_EQ(0.f, overscroll_delegate()->delta_y());
 }
@@ -4264,7 +4284,7 @@
   EXPECT_EQ(OVERSCROLL_NONE, overscroll_delegate()->current_mode());
 
   // Scroll some more to initiate an overscroll.
-  SimulateWheelEventPossiblyIncludingPhase(30, 0, 0, true,
+  SimulateWheelEventPossiblyIncludingPhase(40, 0, 0, true,
                                            WebMouseWheelEvent::kPhaseChanged);
   if (wheel_scrolling_mode_ == kAsyncWheelEvents) {
     ExpectGestureScrollUpdateAfterNonBlockingMouseWheelACK(false);
@@ -4281,7 +4301,7 @@
   EXPECT_EQ(OverscrollSource::TOUCHPAD, overscroll_source());
   EXPECT_EQ(OVERSCROLL_EAST, overscroll_delegate()->current_mode());
 
-  EXPECT_EQ(60.f, overscroll_delta_x());
+  EXPECT_EQ(70.f, overscroll_delta_x());
   EXPECT_EQ(10.f, overscroll_delegate()->delta_x());
   EXPECT_EQ(0.f, overscroll_delegate()->delta_y());
   events = GetAndResetDispatchedMessages();
@@ -4358,7 +4378,7 @@
   EXPECT_EQ(OVERSCROLL_NONE, overscroll_delegate()->current_mode());
 
   // Scroll some more to initiate an overscroll.
-  SimulateWheelEventPossiblyIncludingPhase(30, 0, 0, true,
+  SimulateWheelEventPossiblyIncludingPhase(40, 0, 0, true,
                                            WebMouseWheelEvent::kPhaseChanged);
   if (wheel_scrolling_mode_ == kAsyncWheelEvents) {
     ExpectGestureScrollUpdateAfterNonBlockingMouseWheelACK(false);
@@ -4376,7 +4396,7 @@
   EXPECT_EQ(OverscrollSource::TOUCHPAD, overscroll_source());
   EXPECT_EQ(OVERSCROLL_EAST, overscroll_delegate()->current_mode());
 
-  EXPECT_EQ(60.f, overscroll_delta_x());
+  EXPECT_EQ(70.f, overscroll_delta_x());
   EXPECT_EQ(10.f, overscroll_delegate()->delta_x());
   EXPECT_EQ(0.f, overscroll_delegate()->delta_y());
   events = GetAndResetDispatchedMessages();
@@ -5154,9 +5174,9 @@
   SetUpOverscrollEnvironment();
 
   SimulateWheelEventPossiblyIncludingPhase(
-      5, 0, 0, true, WebMouseWheelEvent::kPhaseBegan);  // sent directly
+      -5, 0, 0, true, WebMouseWheelEvent::kPhaseBegan);  // sent directly
   SimulateWheelEventPossiblyIncludingPhase(
-      -1, 0, 0, true, WebMouseWheelEvent::kPhaseChanged);  // enqueued
+      -10, 0, 0, true, WebMouseWheelEvent::kPhaseChanged);  // enqueued
   SimulateWheelEventPossiblyIncludingPhase(
       -10, -3, 0, true,
       WebMouseWheelEvent::kPhaseChanged);  // coalesced into previous event
@@ -6439,4 +6459,17 @@
   }
 }
 
+// This test verifies that when the focused node is changed,
+// RenderWidgetHostViewAura will tell InputMethodAuraLinux to cancel the current
+// composition.
+TEST_F(InputMethodStateAuraTest, ImeFocusedNodeChanged) {
+  ActivateViewForTextInputManager(tab_view(), ui::TEXT_INPUT_TYPE_TEXT);
+  // There is no composition in the beginning.
+  EXPECT_FALSE(has_composition_text());
+  SetHasCompositionTextToTrue();
+  tab_view()->FocusedNodeChanged(true, gfx::Rect());
+  // The composition must have been canceled.
+  EXPECT_FALSE(has_composition_text());
+}
+
 }  // namespace content
diff --git a/content/browser/renderer_host/render_widget_host_view_browsertest.cc b/content/browser/renderer_host/render_widget_host_view_browsertest.cc
index 729f62db..743ad09 100644
--- a/content/browser/renderer_host/render_widget_host_view_browsertest.cc
+++ b/content/browser/renderer_host/render_widget_host_view_browsertest.cc
@@ -988,6 +988,80 @@
                                 video_frame);
 }
 
+class CompositingRenderWidgetHostViewBrowserTestHiDPI
+    : public CompositingRenderWidgetHostViewBrowserTest {
+ public:
+  CompositingRenderWidgetHostViewBrowserTestHiDPI() {}
+
+ protected:
+  void SetUpCommandLine(base::CommandLine* cmd) override {
+    CompositingRenderWidgetHostViewBrowserTest::SetUpCommandLine(cmd);
+    cmd->AppendSwitchASCII(switches::kForceDeviceScaleFactor,
+                           base::StringPrintf("%f", scale()));
+  }
+
+  GURL TestUrl() override { return GURL(test_url_); }
+
+  void SetTestUrl(const std::string& url) { test_url_ = url; }
+
+  bool ShouldContinueAfterTestURLLoad() {
+    // Short-circuit a pass for platforms where setting up high-DPI fails.
+    const float actual_scale_factor =
+        GetScaleFactorForView(GetRenderWidgetHostView());
+    if (actual_scale_factor != scale()) {
+      LOG(WARNING) << "Blindly passing this test; unable to force device scale "
+                   << "factor: seems to be " << actual_scale_factor
+                   << " but expected " << scale();
+      return false;
+    }
+    VLOG(1)
+        << ("Successfully forced device scale factor.  Moving forward with "
+            "this test!  :-)");
+    return true;
+  }
+
+  static float scale() { return 2.0f; }
+
+ private:
+  std::string test_url_;
+
+  DISALLOW_COPY_AND_ASSIGN(CompositingRenderWidgetHostViewBrowserTestHiDPI);
+};
+
+IN_PROC_BROWSER_TEST_P(CompositingRenderWidgetHostViewBrowserTestHiDPI,
+                       ScrollOffset) {
+  const int kContentHeight = 2000;
+  const int kScrollAmount = 100;
+
+  SetTestUrl(
+      base::StringPrintf("data:text/html,<!doctype html>"
+                         "<div class='box'></div>"
+                         "<style>"
+                         "body { padding: 0; margin: 0; }"
+                         ".box { position: absolute;"
+                         "        background: #0ff;"
+                         "        width: 100%%;"
+                         "        height: %dpx;"
+                         "}"
+                         "</style>"
+                         "<script>"
+                         "  addEventListener(\"scroll\", function() {"
+                         "      domAutomationController.send(\"DONE\"); });"
+                         "  window.scrollTo(0, %d);"
+                         "</script>",
+                         kContentHeight, kScrollAmount));
+
+  SET_UP_SURFACE_OR_PASS_TEST("\"DONE\"");
+  if (!ShouldContinueAfterTestURLLoad())
+    return;
+
+  RenderWidgetHostViewBase* rwhv = GetRenderWidgetHostView();
+  gfx::Vector2dF scroll_offset = rwhv->GetLastScrollOffset();
+
+  EXPECT_EQ(scroll_offset.x(), 0);
+  EXPECT_EQ(scroll_offset.y(), kScrollAmount);
+}
+
 #if defined(OS_CHROMEOS)
 // On ChromeOS there is no software compositing.
 static const auto kTestCompositingModes = testing::Values(GL_COMPOSITING);
@@ -1006,6 +1080,9 @@
     GLAndSoftwareCompositing,
     CompositingRenderWidgetHostViewBrowserTestTabCaptureHighDPI,
     kTestCompositingModes);
+INSTANTIATE_TEST_CASE_P(GLAndSoftwareCompositing,
+                        CompositingRenderWidgetHostViewBrowserTestHiDPI,
+                        kTestCompositingModes);
 
 #endif  // !defined(OS_ANDROID)
 
diff --git a/content/browser/renderer_host/render_widget_host_view_mac.mm b/content/browser/renderer_host/render_widget_host_view_mac.mm
index 80f1e3fd..f90e495 100644
--- a/content/browser/renderer_host/render_widget_host_view_mac.mm
+++ b/content/browser/renderer_host/render_widget_host_view_mac.mm
@@ -1421,6 +1421,8 @@
 void RenderWidgetHostViewMac::FocusedNodeChanged(
     bool is_editable_node,
     const gfx::Rect& node_bounds_in_screen) {
+  [cocoa_view_ cancelComposition];
+
   // If the Mac Zoom feature is enabled, update it with the bounds of the
   // current focused node so that it can ensure that it's scrolled into view.
   // Don't do anything if it's an editable node, as this will be handled by
diff --git a/content/browser/renderer_host/render_widget_host_view_mac_unittest.mm b/content/browser/renderer_host/render_widget_host_view_mac_unittest.mm
index 9869018..3121ad0 100644
--- a/content/browser/renderer_host/render_widget_host_view_mac_unittest.mm
+++ b/content/browser/renderer_host/render_widget_host_view_mac_unittest.mm
@@ -2060,6 +2060,23 @@
   EXPECT_FALSE([rwhv_cocoa_ hasMarkedText]);
 }
 
+// This test verifies that calling FocusedNodeChanged() on
+// RenderWidgetHostViewMac calls cancelComposition on the Cocoa view.
+TEST_F(InputMethodMacTest, FocusedNodeChanged) {
+  // Some values for the call to setMarkedText.
+  base::scoped_nsobject<NSString> text(
+      [[NSString alloc] initWithString:@"sample text"]);
+  NSRange selectedRange = NSMakeRange(0, 1);
+  NSRange replacementRange = NSMakeRange(0, 1);
+
+  [rwhv_cocoa_ setMarkedText:text
+               selectedRange:selectedRange
+            replacementRange:replacementRange];
+  EXPECT_TRUE([rwhv_cocoa_ hasMarkedText]);
+  rwhv_mac_->FocusedNodeChanged(true, gfx::Rect());
+  EXPECT_FALSE([rwhv_cocoa_ hasMarkedText]);
+}
+
 // This test verifies that when a RenderWidgetHostView changes its
 // TextInputState to NONE we send the IPC to stop monitor composition info and,
 // conversely, when its state is set to non-NONE, we start monitoring the
diff --git a/content/browser/resources/gpu/info_view.js b/content/browser/resources/gpu/info_view.js
index c67cdbd..dedd9a5 100644
--- a/content/browser/resources/gpu/info_view.js
+++ b/content/browser/resources/gpu/info_view.js
@@ -93,6 +93,7 @@
         'flash_stage3d_baseline': 'Flash Stage3D Baseline profile',
         'texture_sharing': 'Texture Sharing',
         'video_decode': 'Video Decode',
+        'video_encode': 'Video Encode',
         'panel_fitting': 'Panel Fitting',
         'rasterization': 'Rasterization',
         'multiple_raster_threads': 'Multiple Raster Threads',
diff --git a/content/browser/service_manager/service_manager_context.cc b/content/browser/service_manager/service_manager_context.cc
index 21957a3..18a268d 100644
--- a/content/browser/service_manager/service_manager_context.cc
+++ b/content/browser/service_manager/service_manager_context.cc
@@ -101,7 +101,7 @@
   UtilityProcessHostImpl* process_host =
       new UtilityProcessHostImpl(nullptr, nullptr);
 #if defined(OS_WIN)
-  if (sandbox_type == service_manager::SANDBOX_TYPE_PPAPI)
+  if (sandbox_type == service_manager::SANDBOX_TYPE_PDF_COMPOSITOR)
     process_host->AddFilter(new DWriteFontProxyMessageFilter());
 #endif
   process_host->SetName(process_name);
diff --git a/content/browser/site_per_process_browsertest.cc b/content/browser/site_per_process_browsertest.cc
index 4b33175..fe833c7 100644
--- a/content/browser/site_per_process_browsertest.cc
+++ b/content/browser/site_per_process_browsertest.cc
@@ -1814,7 +1814,7 @@
 
 #if defined(USE_AURA)
   const float overscroll_threshold =
-      GetOverscrollConfig(OVERSCROLL_CONFIG_HORIZ_THRESHOLD_START_TOUCHSCREEN);
+      GetOverscrollConfig(OverscrollConfig::THRESHOLD_START_TOUCHSCREEN);
 #elif defined(OS_ANDROID)
   const float overscroll_threshold = 0.f;
 #endif
@@ -7592,6 +7592,7 @@
   {
     mojom::CreateFrameParamsPtr params = mojom::CreateFrameParams::New();
     params->routing_id = frame_routing_id;
+    mojo::MakeRequest(&params->interface_provider);
     params->proxy_routing_id = proxy_routing_id;
     params->opener_routing_id = IPC::mojom::kRoutingIdNone;
     params->parent_routing_id =
@@ -7659,6 +7660,7 @@
   {
     mojom::CreateFrameParamsPtr params = mojom::CreateFrameParams::New();
     params->routing_id = frame_routing_id;
+    mojo::MakeRequest(&params->interface_provider);
     params->proxy_routing_id = IPC::mojom::kRoutingIdNone;
     params->opener_routing_id = IPC::mojom::kRoutingIdNone;
     params->parent_routing_id = parent_routing_id;
diff --git a/content/browser/web_contents/aura/gesture_nav_simple.cc b/content/browser/web_contents/aura/gesture_nav_simple.cc
index 184563fc..3b7ccbb 100644
--- a/content/browser/web_contents/aura/gesture_nav_simple.cc
+++ b/content/browser/web_contents/aura/gesture_nav_simple.cc
@@ -627,22 +627,21 @@
       GetUmaNavigationType(GetDirectionFromMode(mode_), source_),
       UmaNavigationType::NAVIGATION_TYPE_COUNT);
 
-  bool is_vertical = mode_ == OVERSCROLL_SOUTH;
+  const bool is_touchpad = source == OverscrollSource::TOUCHPAD;
   const float start_threshold = GetOverscrollConfig(
-      is_vertical ? OVERSCROLL_CONFIG_VERT_THRESHOLD_START
-                  : source == OverscrollSource::TOUCHPAD
-                        ? OVERSCROLL_CONFIG_HORIZ_THRESHOLD_START_TOUCHPAD
-                        : OVERSCROLL_CONFIG_HORIZ_THRESHOLD_START_TOUCHSCREEN);
-  const int size =
-      is_vertical ? GetDisplaySize().height() : GetDisplaySize().width();
+      is_touchpad ? OverscrollConfig::THRESHOLD_START_TOUCHPAD
+                  : OverscrollConfig::THRESHOLD_START_TOUCHSCREEN);
+  const gfx::Size size = GetDisplaySize();
+  const int max_size = std::max(size.width(), size.height());
   completion_threshold_ =
-      size * GetOverscrollConfig(
-                 is_vertical ? OVERSCROLL_CONFIG_VERT_THRESHOLD_COMPLETE
-                             : OVERSCROLL_CONFIG_HORIZ_THRESHOLD_COMPLETE) -
+      max_size * GetOverscrollConfig(
+                     is_touchpad
+                         ? OverscrollConfig::THRESHOLD_COMPLETE_TOUCHPAD
+                         : OverscrollConfig::THRESHOLD_COMPLETE_TOUCHSCREEN) -
       start_threshold;
   DCHECK_LE(0, completion_threshold_);
 
-  max_delta_ = size - start_threshold;
+  max_delta_ = max_size - start_threshold;
   DCHECK_LE(0, max_delta_);
 
   aura::Window* window = web_contents_->GetNativeView();
diff --git a/content/browser/web_contents/aura/overscroll_navigation_overlay_unittest.cc b/content/browser/web_contents/aura/overscroll_navigation_overlay_unittest.cc
index 33306b7..044e129 100644
--- a/content/browser/web_contents/aura/overscroll_navigation_overlay_unittest.cc
+++ b/content/browser/web_contents/aura/overscroll_navigation_overlay_unittest.cc
@@ -496,9 +496,10 @@
   int overscroll_complete_distance =
       root_window()->bounds().size().width() *
           content::GetOverscrollConfig(
-              content::OVERSCROLL_CONFIG_HORIZ_THRESHOLD_COMPLETE) +
+              content::OverscrollConfig::THRESHOLD_COMPLETE_TOUCHSCREEN) +
       ui::GestureConfiguration::GetInstance()
-          ->max_touch_move_in_pixels_for_click() + 1;
+          ->max_touch_move_in_pixels_for_click() +
+      1;
 
   // Start and complete a back navigation via a gesture.
   ui::test::EventGenerator generator(root_window());
diff --git a/content/browser/web_contents/aura/overscroll_window_delegate.cc b/content/browser/web_contents/aura/overscroll_window_delegate.cc
index 5f910bc..075d966 100644
--- a/content/browser/web_contents/aura/overscroll_window_delegate.cc
+++ b/content/browser/web_contents/aura/overscroll_window_delegate.cc
@@ -21,12 +21,15 @@
     : delegate_(delegate),
       overscroll_mode_(OVERSCROLL_NONE),
       delta_x_(0.f),
-      complete_threshold_ratio_(content::GetOverscrollConfig(
-          content::OVERSCROLL_CONFIG_HORIZ_THRESHOLD_COMPLETE)),
+      complete_threshold_ratio_touchscreen_(content::GetOverscrollConfig(
+          content::OverscrollConfig::THRESHOLD_COMPLETE_TOUCHSCREEN)),
+      complete_threshold_ratio_touchpad_(content::GetOverscrollConfig(
+          content::OverscrollConfig::THRESHOLD_COMPLETE_TOUCHPAD)),
+      active_complete_threshold_ratio_(0.f),
       start_threshold_touchscreen_(content::GetOverscrollConfig(
-          content::OVERSCROLL_CONFIG_HORIZ_THRESHOLD_START_TOUCHSCREEN)),
+          content::OverscrollConfig::THRESHOLD_START_TOUCHSCREEN)),
       start_threshold_touchpad_(content::GetOverscrollConfig(
-          content::OVERSCROLL_CONFIG_HORIZ_THRESHOLD_START_TOUCHPAD)),
+          content::OverscrollConfig::THRESHOLD_START_TOUCHPAD)),
       active_start_threshold_(0.f) {
   SetImage(image);
 }
@@ -55,8 +58,10 @@
 void OverscrollWindowDelegate::CompleteOrResetOverscroll() {
   if (overscroll_mode_ == OVERSCROLL_NONE)
     return;
-  float ratio = (fabs(delta_x_)) / delegate_->GetDisplaySize().width();
-  if (ratio < complete_threshold_ratio_) {
+  gfx::Size display_size = delegate_->GetDisplaySize();
+  int max_size = std::max(display_size.width(), display_size.height());
+  float ratio = (fabs(delta_x_)) / max_size;
+  if (ratio < active_complete_threshold_ratio_) {
     ResetOverscroll();
     return;
   }
@@ -94,6 +99,7 @@
 
 void OverscrollWindowDelegate::OnScrollEvent(ui::ScrollEvent* event) {
   active_start_threshold_ = start_threshold_touchpad_;
+  active_complete_threshold_ratio_ = complete_threshold_ratio_touchpad_;
   if (event->type() == ui::ET_SCROLL)
     UpdateOverscroll(event->x_offset_ordinal(), OverscrollSource::TOUCHPAD);
   else if (event->type() == ui::ET_SCROLL_FLING_START)
@@ -105,6 +111,7 @@
 
 void OverscrollWindowDelegate::OnGestureEvent(ui::GestureEvent* event) {
   active_start_threshold_ = start_threshold_touchscreen_;
+  active_complete_threshold_ratio_ = complete_threshold_ratio_touchscreen_;
   switch (event->type()) {
     case ui::ET_GESTURE_SCROLL_UPDATE:
       UpdateOverscroll(event->details().scroll_x(),
diff --git a/content/browser/web_contents/aura/overscroll_window_delegate.h b/content/browser/web_contents/aura/overscroll_window_delegate.h
index f267b85..7c8ca3333 100644
--- a/content/browser/web_contents/aura/overscroll_window_delegate.h
+++ b/content/browser/web_contents/aura/overscroll_window_delegate.h
@@ -55,8 +55,14 @@
   // The latest delta_x scroll update.
   float delta_x_;
 
-  // The ratio of overscroll at which we consider the overscroll completed.
-  const float complete_threshold_ratio_;
+  // The ratio of overscroll at which we consider the overscroll completed, for
+  // touchscreen or touchpad.
+  const float complete_threshold_ratio_touchscreen_;
+  const float complete_threshold_ratio_touchpad_;
+
+  // The ratio of overscroll at which we consider the overscroll completed for
+  // the current touch input.
+  float active_complete_threshold_ratio_;
 
   // The threshold for starting the overscroll gesture, for touchscreen or
   // touchpads.
diff --git a/content/browser/web_contents/aura/overscroll_window_delegate_unittest.cc b/content/browser/web_contents/aura/overscroll_window_delegate_unittest.cc
index 683a6cb1..6058a7cd 100644
--- a/content/browser/web_contents/aura/overscroll_window_delegate_unittest.cc
+++ b/content/browser/web_contents/aura/overscroll_window_delegate_unittest.cc
@@ -30,9 +30,9 @@
         mode_changed_(false),
         current_mode_(OVERSCROLL_NONE),
         touch_start_threshold_(content::GetOverscrollConfig(
-            content::OVERSCROLL_CONFIG_HORIZ_THRESHOLD_START_TOUCHSCREEN)),
+            OverscrollConfig::THRESHOLD_START_TOUCHSCREEN)),
         touch_complete_threshold_(content::GetOverscrollConfig(
-            content::OVERSCROLL_CONFIG_HORIZ_THRESHOLD_COMPLETE)) {}
+            OverscrollConfig::THRESHOLD_COMPLETE_TOUCHSCREEN)) {}
 
   ~OverscrollWindowDelegateTest() override {}
 
diff --git a/content/browser/web_contents/web_contents_impl.cc b/content/browser/web_contents/web_contents_impl.cc
index 8a788f6..219ad19 100644
--- a/content/browser/web_contents/web_contents_impl.cc
+++ b/content/browser/web_contents/web_contents_impl.cc
@@ -105,6 +105,7 @@
 #include "content/public/browser/notification_types.h"
 #include "content/public/browser/render_widget_host_iterator.h"
 #include "content/public/browser/resource_request_details.h"
+#include "content/public/browser/restore_type.h"
 #include "content/public/browser/security_style_explanations.h"
 #include "content/public/browser/ssl_status.h"
 #include "content/public/browser/storage_partition.h"
@@ -116,6 +117,7 @@
 #include "content/public/common/child_process_host.h"
 #include "content/public/common/content_constants.h"
 #include "content/public/common/content_switches.h"
+#include "content/public/common/page_state.h"
 #include "content/public/common/page_zoom.h"
 #include "content/public/common/result_codes.h"
 #include "content/public/common/url_utils.h"
@@ -2339,7 +2341,7 @@
   create_params.renderer_initiated_creation =
       main_frame_route_id != MSG_ROUTING_NONE;
 
-  WebContentsImpl* new_contents = NULL;
+  WebContentsImpl* new_contents = nullptr;
   if (!is_guest) {
     create_params.context = view_->GetNativeView();
     create_params.initial_size = GetContainerBounds().size();
@@ -3455,25 +3457,6 @@
   return closed_by_user_gesture_;
 }
 
-void WebContentsImpl::ViewSource() {
-  if (!delegate_)
-    return;
-
-  NavigationEntry* entry = GetController().GetLastCommittedEntry();
-  if (!entry)
-    return;
-
-  delegate_->ViewSourceForTab(this, entry->GetURL());
-}
-
-void WebContentsImpl::ViewFrameSource(const GURL& url,
-                                      const PageState& page_state) {
-  if (!delegate_)
-    return;
-
-  delegate_->ViewSourceForFrame(this, url, page_state);
-}
-
 int WebContentsImpl::GetMinimumZoomPercent() const {
   return minimum_zoom_percent_;
 }
@@ -3923,6 +3906,83 @@
       web_contents, allowed_per_prefs, origin, resource_url);
 }
 
+void WebContentsImpl::ViewSource(RenderFrameHostImpl* frame) {
+  DCHECK_EQ(this, WebContents::FromRenderFrameHost(frame));
+
+  // Don't do anything if there is no |delegate_| that could accept and show the
+  // new WebContents containing the view-source.
+  if (!delegate_)
+    return;
+
+  // Use the last committed entry, since the pending entry hasn't loaded yet and
+  // won't be copied into the cloned tab.
+  NavigationEntryImpl* last_committed_entry =
+      static_cast<NavigationEntryImpl*>(frame->frame_tree_node()
+                                            ->navigator()
+                                            ->GetController()
+                                            ->GetLastCommittedEntry());
+  if (!last_committed_entry)
+    return;
+
+  FrameNavigationEntry* frame_entry =
+      last_committed_entry->GetFrameEntry(frame->frame_tree_node());
+  if (!frame_entry)
+    return;
+
+  // Any new WebContents opened while this WebContents is in fullscreen can be
+  // used to confuse the user, so drop fullscreen.
+  if (IsFullscreenForCurrentTab())
+    ExitFullscreen(true);
+
+  // We intentionally don't share the SiteInstance with the original frame so
+  // that view source has a consistent process model and always ends up in a new
+  // process (https://crbug.com/699493).
+  scoped_refptr<SiteInstanceImpl> site_instance_for_view_source = nullptr;
+  // Referrer is not important, because view-source should not hit the network,
+  // but should be served from the cache instead.
+  Referrer referrer_for_view_source;
+  // Do not restore title, derive it from the url.
+  base::string16 title_for_view_source;
+  auto navigation_entry = std::make_unique<NavigationEntryImpl>(
+      site_instance_for_view_source, frame_entry->url(),
+      referrer_for_view_source, title_for_view_source, ui::PAGE_TRANSITION_LINK,
+      /* is_renderer_initiated = */ false);
+  navigation_entry->SetVirtualURL(GURL(content::kViewSourceScheme +
+                                       std::string(":") +
+                                       frame_entry->url().spec()));
+
+  // Do not restore scroller position.
+  // TODO(creis, lukasza, arthursonzogni): Do not reuse the original PageState,
+  // but start from a new one and only copy the needed data.
+  const PageState& new_page_state =
+      frame_entry->page_state().RemoveScrollOffset();
+
+  scoped_refptr<FrameNavigationEntry> new_frame_entry =
+      navigation_entry->root_node()->frame_entry;
+  new_frame_entry->set_method(frame_entry->method());
+  new_frame_entry->SetPageState(new_page_state);
+
+  // Create a new WebContents, which is used to display the source code.
+  WebContentsImpl* view_source_contents =
+      static_cast<WebContentsImpl*>(Create(CreateParams(GetBrowserContext())));
+
+  // Restore the previously created NavigationEntry.
+  std::vector<std::unique_ptr<NavigationEntry>> navigation_entries;
+  navigation_entries.push_back(std::move(navigation_entry));
+  view_source_contents->GetController().Restore(0, RestoreType::CURRENT_SESSION,
+                                                &navigation_entries);
+
+  // Add |view_source_contents| as a new tab.
+  gfx::Rect initial_rect;
+  constexpr bool kUserGesture = true;
+  bool ignored_was_blocked;
+  delegate_->AddNewContents(this, view_source_contents,
+                            WindowOpenDisposition::NEW_FOREGROUND_TAB,
+                            initial_rect, kUserGesture, &ignored_was_blocked);
+  // Note that the |delegate_| could have deleted |view_source_contents| during
+  // AddNewContents method call.
+}
+
 #if defined(OS_ANDROID)
 base::android::ScopedJavaLocalRef<jobject>
 WebContentsImpl::GetJavaRenderFrameHostDelegate() {
diff --git a/content/browser/web_contents/web_contents_impl.h b/content/browser/web_contents/web_contents_impl.h
index 23bc4344..7b639c1 100644
--- a/content/browser/web_contents/web_contents_impl.h
+++ b/content/browser/web_contents/web_contents_impl.h
@@ -426,8 +426,6 @@
   void UserGestureDone() override;
   void SetClosedByUserGesture(bool value) override;
   bool GetClosedByUserGesture() const override;
-  void ViewSource() override;
-  void ViewFrameSource(const GURL& url, const PageState& page_state) override;
   int GetMinimumZoomPercent() const override;
   int GetMaximumZoomPercent() const override;
   void SetPageScale(float page_scale_factor) override;
@@ -564,6 +562,7 @@
                                          bool allowed_per_prefs,
                                          const url::Origin& origin,
                                          const GURL& resource_url) override;
+  void ViewSource(RenderFrameHostImpl* frame) override;
 #if defined(OS_ANDROID)
   base::android::ScopedJavaLocalRef<jobject> GetJavaRenderFrameHostDelegate()
       override;
diff --git a/content/browser/web_contents/web_contents_view_aura_browsertest.cc b/content/browser/web_contents/web_contents_view_aura_browsertest.cc
index 14e5782..3a9a79a 100644
--- a/content/browser/web_contents/web_contents_view_aura_browsertest.cc
+++ b/content/browser/web_contents/web_contents_view_aura_browsertest.cc
@@ -473,9 +473,9 @@
   gesture_scroll_update.data.scroll_update.delta_units =
       blink::WebGestureEvent::ScrollUnits::kPrecisePixels;
   gesture_scroll_update.data.scroll_update.delta_y = 0.f;
-  float horiz_threshold =
-      GetOverscrollConfig(OVERSCROLL_CONFIG_HORIZ_THRESHOLD_START_TOUCHSCREEN);
-  gesture_scroll_update.data.scroll_update.delta_x = horiz_threshold + 1;
+  float start_threshold =
+      GetOverscrollConfig(OverscrollConfig::THRESHOLD_START_TOUCHSCREEN);
+  gesture_scroll_update.data.scroll_update.delta_x = start_threshold + 1;
   GetRenderWidgetHost()->ForwardGestureEvent(gesture_scroll_update);
 
   // Wait for the overscroll gesture to start and then allow some time for the
diff --git a/content/child/blink_platform_impl.cc b/content/child/blink_platform_impl.cc
index 7459cf1..83334a0 100644
--- a/content/child/blink_platform_impl.cc
+++ b/content/child/blink_platform_impl.cc
@@ -196,6 +196,8 @@
       return IDS_FORM_OTHER_WEEK_LABEL;
     case WebLocalizedString::kOverflowMenuCaptions:
       return IDS_MEDIA_OVERFLOW_MENU_CLOSED_CAPTIONS;
+    case WebLocalizedString::kOverflowMenuCaptionsSubmenuTitle:
+      return IDS_MEDIA_OVERFLOW_MENU_CLOSED_CAPTIONS_SUBMENU_TITLE;
     case WebLocalizedString::kOverflowMenuCast:
       return IDS_MEDIA_OVERFLOW_MENU_CAST;
     case WebLocalizedString::kOverflowMenuEnterFullscreen:
diff --git a/content/common/BUILD.gn b/content/common/BUILD.gn
index 05e186c4..0013627 100644
--- a/content/common/BUILD.gn
+++ b/content/common/BUILD.gn
@@ -236,6 +236,8 @@
     "navigation_gesture.h",
     "navigation_params.cc",
     "navigation_params.h",
+    "navigation_subresource_loader_params.cc",
+    "navigation_subresource_loader_params.h",
     "net/url_fetcher.cc",
     "net/url_request_service_worker_data.cc",
     "net/url_request_service_worker_data.h",
@@ -315,6 +317,8 @@
     "throttling_url_loader.h",
     "unique_name_helper.cc",
     "unique_name_helper.h",
+    "url_loader_factory_bundle.cc",
+    "url_loader_factory_bundle.h",
     "url_request_struct_traits.cc",
     "url_request_struct_traits.h",
     "url_schemes.cc",
@@ -589,6 +593,7 @@
     "media/renderer_audio_output_stream_factory.mojom",
     "memory_coordinator.mojom",
     "native_types.mojom",
+    "page_state.mojom",
     "push_messaging.mojom",
     "render_frame_message_filter.mojom",
     "render_message_filter.mojom",
@@ -611,6 +616,7 @@
     "shared_worker/shared_worker_host.mojom",
     "shared_worker/shared_worker_info.mojom",
     "storage_partition_service.mojom",
+    "url_loader_factory_bundle.mojom",
     "video_capture.mojom",
     "web_database.mojom",
     "widget.mojom",
diff --git a/content/common/frame.mojom b/content/common/frame.mojom
index c402b91..cde8296e 100644
--- a/content/common/frame.mojom
+++ b/content/common/frame.mojom
@@ -4,8 +4,8 @@
 
 module content.mojom;
 
+import "content/common/url_loader_factory_bundle.mojom";
 import "content/public/common/url_loader.mojom";
-import "content/public/common/url_loader_factory.mojom";
 import "content/public/common/window_container_type.mojom";
 import "mojo/common/unguessable_token.mojom";
 import "services/service_manager/public/interfaces/interface_provider.mojom";
@@ -38,14 +38,15 @@
   // should request |body_url| to get access to the stream containing the body
   // of the response. When the Network Service is enabled, |body_url| is not
   // used and instead the data is passed to the renderer via |body_data|. In
-  // that case |default_subresource_url_loader_factory| may also be provided by
-  // the browser as a means for the renderer to load subresources.
+  // that case |subresource_loader_factories| may also be provided by the
+  // browser as a a means for the renderer to load subresources where
+  // applicable.
   CommitNavigation(URLResponseHead head,
                    url.mojom.Url body_url,
                    CommonNavigationParams common_params,
                    RequestNavigationParams request_params,
                    handle<data_pipe_consumer>? body_data,
-                   URLLoaderFactory? default_subresource_url_loader_factory);
+                   URLLoaderFactoryBundle? subresource_loader_factories);
 };
 
 // Implemented by the frame (e.g. renderer processes).
@@ -58,15 +59,10 @@
   AllowBindings(int32 enabled_bindings_flags);
 };
 
-// Implemented by the frame server (i.e. the browser process).
-interface FrameHostInterfaceBroker {
-  GetInterfaceProvider(service_manager.mojom.InterfaceProvider& interfaces);
-};
-
 // Implemented by a service that provides implementations of the Frame
 // interface. (e.g. renderer processes).
 interface FrameFactory {
-  CreateFrame(int32 frame_routing_id, Frame& frame, FrameHostInterfaceBroker host);
+  CreateFrame(int32 frame_routing_id, Frame& frame);
 };
 
 struct CreateNewWindowParams {
@@ -124,6 +120,10 @@
   // The ID of the widget for the main frame.
   int32 main_frame_widget_route_id;
 
+  // The InterfaceProvider through which the main RenderFrame can access
+  // services exposed by its RenderFrameHost.
+  service_manager.mojom.InterfaceProvider main_frame_interface_provider;
+
   // Duplicated from CreateNewWindowParams because legacy code.
   int64 cloned_session_storage_namespace_id;
 
diff --git a/content/common/frame_messages.h b/content/common/frame_messages.h
index 8536588..76e574be 100644
--- a/content/common/frame_messages.h
+++ b/content/common/frame_messages.h
@@ -168,7 +168,6 @@
   IPC_STRUCT_TRAITS_MEMBER(page_url)
   IPC_STRUCT_TRAITS_MEMBER(keyword_url)
   IPC_STRUCT_TRAITS_MEMBER(frame_url)
-  IPC_STRUCT_TRAITS_MEMBER(frame_page_state)
   IPC_STRUCT_TRAITS_MEMBER(media_flags)
   IPC_STRUCT_TRAITS_MEMBER(selection_text)
   IPC_STRUCT_TRAITS_MEMBER(title_text)
@@ -1108,12 +1107,15 @@
 //
 // Each of these messages will have a corresponding FrameHostMsg_Detach message
 // sent when the frame is detached from the DOM.
-// Note that |new_render_frame_id| and |devtools_frame_token| are out
-// parameters. Browser process defines them for the renderer process.
-IPC_SYNC_MESSAGE_CONTROL1_2(FrameHostMsg_CreateChildFrame,
-                            FrameHostMsg_CreateChildFrame_Params,
-                            int32_t /* new_routing_id */,
-                            base::UnguessableToken /* devtools_frame_token */)
+// Note that |new_render_frame_id|, |new_interface_provider|, and
+// |devtools_frame_token| are out parameters. Browser process defines them for
+// the renderer process.
+IPC_SYNC_MESSAGE_CONTROL1_3(
+    FrameHostMsg_CreateChildFrame,
+    FrameHostMsg_CreateChildFrame_Params,
+    int32_t,                 /* new_routing_id */
+    mojo::MessagePipeHandle, /* new_interface_provider */
+    base::UnguessableToken /* devtools_frame_token */)
 
 // Sent by the renderer to the parent RenderFrameHost when a child frame is
 // detached from the DOM.
diff --git a/content/common/navigation_subresource_loader_params.cc b/content/common/navigation_subresource_loader_params.cc
new file mode 100644
index 0000000..8bf57eb
--- /dev/null
+++ b/content/common/navigation_subresource_loader_params.cc
@@ -0,0 +1,23 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/common/navigation_subresource_loader_params.h"
+
+namespace content {
+
+SubresourceLoaderParams::SubresourceLoaderParams() = default;
+SubresourceLoaderParams::~SubresourceLoaderParams() = default;
+
+SubresourceLoaderParams::SubresourceLoaderParams(
+    SubresourceLoaderParams&& other) {
+  loader_factory_info = std::move(other.loader_factory_info);
+}
+
+SubresourceLoaderParams& SubresourceLoaderParams::operator=(
+    SubresourceLoaderParams&& other) {
+  loader_factory_info = std::move(other.loader_factory_info);
+  return *this;
+}
+
+}  // namespace content
diff --git a/content/common/navigation_subresource_loader_params.h b/content/common/navigation_subresource_loader_params.h
new file mode 100644
index 0000000..ad4cb84
--- /dev/null
+++ b/content/common/navigation_subresource_loader_params.h
@@ -0,0 +1,34 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CONTENT_COMMON_NAVIGATION_SUBRESOURCE_LOADER_PARAMS_H_
+#define CONTENT_COMMON_NAVIGATION_SUBRESOURCE_LOADER_PARAMS_H_
+
+#include "content/common/service_worker/controller_service_worker.mojom.h"
+#include "content/public/common/url_loader_factory.mojom.h"
+
+namespace content {
+
+// For NetworkService glues:
+// Navigation parameters that are necessary to set-up a subresource loader
+// for the frame that is going to be created by the navigation.
+// Passed from the browser to the renderer when the navigation commits when
+// NetworkService or its glue code for relevant features is enabled.
+struct CONTENT_EXPORT SubresourceLoaderParams {
+  SubresourceLoaderParams();
+  ~SubresourceLoaderParams();
+
+  SubresourceLoaderParams(SubresourceLoaderParams&& other);
+  SubresourceLoaderParams& operator=(SubresourceLoaderParams&& other);
+
+  // The subresource loader factory info that is to be used to create a
+  // subresource loader in the renderer. Used by AppCache and WebUI.
+  mojom::URLLoaderFactoryPtrInfo loader_factory_info;
+
+  // TODO(kinuko): Add the controller interface ptr for the service worker.
+};
+
+}  // namespace content
+
+#endif  // CONTENT_COMMON_NAVIGATION_SUBRESOURCE_LOADER_PARAMS_H_
diff --git a/content/common/page_state.mojom b/content/common/page_state.mojom
new file mode 100644
index 0000000..e6afdb43
--- /dev/null
+++ b/content/common/page_state.mojom
@@ -0,0 +1,107 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+module content.history.mojom;
+
+import "mojo/common/string16.mojom";
+import "mojo/common/time.mojom";
+import "third_party/WebKit/public/platform/referrer.mojom";
+import "url/mojo/url.mojom";
+import "ui/gfx/geometry/mojo/geometry.mojom";
+
+// This file contains the mojo IDL definitions for PageState and its constituent
+// parts. The resultant generated code is used to serialize and deserialize
+// PageState for the purpose of history restore.
+// When adding fields, assign your new field an explicity ordinal(@n) and
+// prefer to add fields to the end of the struct to simplify finding the
+// latest ordinal.
+// For backwards compatibility purposes, new fields must be tagged with a
+// [MinVersion=x] attribute; x is specified at the bottom of this comment
+// block.
+// You'll also need to read/write the new field's value when decoding and
+// encoding PageState, update PageStateSerializationTest to check that
+// your new field is preserved across serialization, and add a BackwardsCompat
+// test with associated serialized_vxx.dat file. Look for
+// DumpExpectedPageStateForBackwardsCompat in page_state_serialization_unittest
+// for how to do this.
+// Don't remove, or change the type of fields; this will break
+// compatibility. If re-ordering fields, make sure to retain the original
+// ordinal value.
+// Update the below value if your change introduces fields using it.
+// Next MinVersion: 1
+
+// Next Ordinal: 4
+struct FileSystemFile {
+  url.mojom.Url filesystem_url@0;
+  uint64 offset@1;
+  uint64 length@2;
+  mojo.common.mojom.Time modification_time@3;
+};
+
+// Next Ordinal: 4
+struct File {
+  mojo.common.mojom.String16 path@0;
+  uint64 offset@1;
+  uint64 length@2;
+  mojo.common.mojom.Time modification_time@3;
+};
+
+// Next Ordinal: 4
+union Element {
+  string blob_uuid@0;
+  array<uint8> bytes@1;
+  File file@2;
+  FileSystemFile file_system_file@3;
+};
+
+// Next Ordinal: 3
+struct RequestBody {
+  array<Element> elements@0;
+  int64 identifier@1;
+  bool contains_sensitive_info@2;
+};
+
+// Next Ordinal: 3
+struct HttpBody {
+  mojo.common.mojom.String16? http_content_type@0;
+  RequestBody? request_body@1;
+  bool contains_passwords@2 = false;
+};
+
+// This enum's values must match blink::WebHistoryScrollRestorationType. This
+// is enforced with static asserts in page_state_serialization.cc.
+[Extensible]
+enum ScrollRestorationType {
+  kAuto = 0,
+  kManual = 1
+};
+
+// Next Ordinal: 3
+struct ViewState {
+  gfx.mojom.PointF visual_viewport_scroll_offset@0;
+  gfx.mojom.Point scroll_offset@1;
+  double page_scale_factor@2;
+};
+
+// Next Ordinal: 12
+struct FrameState {
+  mojo.common.mojom.String16? url_string@0;
+  mojo.common.mojom.String16? referrer@1;
+  mojo.common.mojom.String16? target@2;
+  mojo.common.mojom.String16? state_object@3;
+  array<mojo.common.mojom.String16?> document_state@4;
+  ScrollRestorationType scroll_restoration_type@5;
+  ViewState? view_state@6;
+  int64 item_sequence_number@7;
+  int64 document_sequence_number@8;
+  blink.mojom.ReferrerPolicy referrer_policy@9;
+  HttpBody http_body@10;
+  array<FrameState> children@11;
+};
+
+// Next Ordinal: 2
+struct PageState {
+  array<mojo.common.mojom.String16?> referenced_files@0;
+  FrameState top@1;
+};
diff --git a/content/common/page_state_serialization.cc b/content/common/page_state_serialization.cc
index a379477..d685314 100644
--- a/content/common/page_state_serialization.cc
+++ b/content/common/page_state_serialization.cc
@@ -14,12 +14,32 @@
 #include "base/strings/string_util.h"
 #include "base/strings/utf_string_conversions.h"
 #include "build/build_config.h"
+#include "content/common/page_state.mojom.h"
 #include "content/common/unique_name_helper.h"
+#include "content/public/common/referrer_struct_traits.h"
 #include "content/public/common/resource_request_body.h"
+#include "ipc/ipc_message_utils.h"
+#include "mojo/common/common_custom_types_struct_traits.h"
+#include "mojo/common/time_struct_traits.h"
+#include "third_party/WebKit/public/platform/WebHistoryScrollRestorationType.h"
 #include "ui/display/display.h"
 #include "ui/display/screen.h"
+#include "ui/gfx/geometry/mojo/geometry_struct_traits.h"
+#include "url/mojo/url_gurl_struct_traits.h"
+
+namespace mojom = content::history::mojom;
 
 namespace content {
+
+#define STATIC_ASSERT_ENUM(a, b)                            \
+  static_assert(static_cast<int>(a) == static_cast<int>(b), \
+                "mismatching enums: " #a)
+
+STATIC_ASSERT_ENUM(mojom::ScrollRestorationType::kAuto,
+                   blink::kWebHistoryScrollRestorationAuto);
+STATIC_ASSERT_ENUM(mojom::ScrollRestorationType::kManual,
+                   blink::kWebHistoryScrollRestorationManual);
+
 namespace {
 
 #if defined(OS_ANDROID)
@@ -40,12 +60,12 @@
     const base::Optional<base::string16>& file_path,
     int file_start,
     int file_length,
-    double file_modification_time) {
+    base::Time file_modification_time) {
   request_body->AppendFileRange(
       file_path ? base::FilePath::FromUTF16Unsafe(*file_path)
                 : base::FilePath(),
       static_cast<uint64_t>(file_start), static_cast<uint64_t>(file_length),
-      base::Time::FromDoubleT(file_modification_time));
+      file_modification_time);
 }
 
 void AppendURLRangeToRequestBody(
@@ -53,11 +73,10 @@
     const GURL& url,
     int file_start,
     int file_length,
-    double file_modification_time) {
+    base::Time file_modification_time) {
   request_body->AppendFileSystemFileRange(
       url, static_cast<uint64_t>(file_start),
-      static_cast<uint64_t>(file_length),
-      base::Time::FromDoubleT(file_modification_time));
+      static_cast<uint64_t>(file_length), file_modification_time);
 }
 
 void AppendBlobToRequestBody(
@@ -200,6 +219,7 @@
 // 23: Remove frame sequence number, there are easier ways.
 // 24: Add did save scroll or scale state.
 // 25: Limit the length of unique names: https://crbug.com/626202
+// 26: Switch to mojo-based serialization.
 //
 // NOTE: If the version is -1, then the pickle contains only a URL string.
 // See ReadPageState.
@@ -208,11 +228,14 @@
 // NOTE: When changing the version, please add a backwards compatibility test.
 // See PageStateSerializationTest.DumpExpectedPageStateForBackwardsCompat for
 // instructions on how to generate the new test case.
-const int kCurrentVersion = 25;
+const int kCurrentVersion = 26;
 
-// A bunch of convenience functions to read/write to SerializeObjects.  The
+// A bunch of convenience functions to write to/read from SerializeObjects.  The
 // de-serializers assume the input data will be in the correct format and fall
-// back to returning safe defaults when not.
+// back to returning safe defaults when not. These are mostly used by
+// legacy(pre-mojo) serialization methods. If you're making changes to the
+// PageState serialization format you almost certainly want to add/remove fields
+// in page_state.mojom rather than using these methods.
 
 void WriteData(const void* data, int length, SerializeObject* obj) {
   obj->pickle.WriteData(static_cast<const char*>(data), length);
@@ -461,15 +484,17 @@
       int64_t file_start = ReadInteger64(obj);
       int64_t file_length = ReadInteger64(obj);
       double file_modification_time = ReadReal(obj);
-      AppendFileRangeToRequestBody(request_body, file_path, file_start,
-                                   file_length, file_modification_time);
+      AppendFileRangeToRequestBody(
+          request_body, file_path, file_start, file_length,
+          base::Time::FromDoubleT(file_modification_time));
     } else if (type == blink::WebHTTPBody::Element::kTypeFileSystemURL) {
       GURL url = ReadGURL(obj);
       int64_t file_start = ReadInteger64(obj);
       int64_t file_length = ReadInteger64(obj);
       double file_modification_time = ReadReal(obj);
-      AppendURLRangeToRequestBody(request_body, url, file_start, file_length,
-                                  file_modification_time);
+      AppendURLRangeToRequestBody(
+          request_body, url, file_start, file_length,
+          base::Time::FromDoubleT(file_modification_time));
     } else if (type == blink::WebHTTPBody::Element::kTypeBlob) {
       if (obj->version >= 16) {
         std::string blob_uuid = ReadStdString(obj);
@@ -482,17 +507,6 @@
   request_body->set_identifier(ReadInteger64(obj));
 }
 
-// Writes an ExplodedHttpBody object into a SerializeObject for serialization.
-void WriteHttpBody(const ExplodedHttpBody& http_body, SerializeObject* obj) {
-  bool is_null = http_body.request_body == nullptr;
-  WriteBoolean(!is_null, obj);
-  if (is_null)
-    return;
-
-  WriteResourceRequestBody(*http_body.request_body, obj);
-  WriteBoolean(http_body.contains_passwords, obj);
-}
-
 void ReadHttpBody(SerializeObject* obj, ExplodedHttpBody* http_body) {
   // An initial boolean indicates if we have an HTTP body.
   if (!ReadBoolean(obj))
@@ -505,60 +519,14 @@
     http_body->contains_passwords = ReadBoolean(obj);
 }
 
-// Writes the ExplodedFrameState data into the SerializeObject object for
-// serialization.
-void WriteFrameState(
-    const ExplodedFrameState& state, SerializeObject* obj, bool is_top) {
-  // WARNING: This data may be persisted for later use. As such, care must be
-  // taken when changing the serialized format. If a new field needs to be
-  // written, only adding at the end will make it easier to deal with loading
-  // older versions. Similarly, this should NOT save fields with sensitive
-  // data, such as password fields.
+void WriteHttpBody(const ExplodedHttpBody& http_body, SerializeObject* obj) {
+  bool is_null = http_body.request_body == nullptr;
+  WriteBoolean(!is_null, obj);
+  if (is_null)
+    return;
 
-  WriteString(state.url_string, obj);
-  WriteString(state.target, obj);
-  WriteBoolean(state.did_save_scroll_or_scale_state, obj);
-
-  if (state.did_save_scroll_or_scale_state) {
-    WriteInteger(state.scroll_offset.x(), obj);
-    WriteInteger(state.scroll_offset.y(), obj);
-  }
-
-  WriteString(state.referrer, obj);
-
-  WriteStringVector(state.document_state, obj);
-
-  if (state.did_save_scroll_or_scale_state)
-    WriteReal(state.page_scale_factor, obj);
-
-  WriteInteger64(state.item_sequence_number, obj);
-  WriteInteger64(state.document_sequence_number, obj);
-  WriteInteger(static_cast<int>(state.referrer_policy), obj);
-
-  if (state.did_save_scroll_or_scale_state) {
-    WriteReal(state.visual_viewport_scroll_offset.x(), obj);
-    WriteReal(state.visual_viewport_scroll_offset.y(), obj);
-  }
-
-  WriteInteger(state.scroll_restoration_type, obj);
-
-  bool has_state_object = state.state_object.has_value();
-  WriteBoolean(has_state_object, obj);
-  if (has_state_object)
-    WriteString(*state.state_object, obj);
-
-  WriteHttpBody(state.http_body, obj);
-
-  // NOTE: It is a quirk of the format that we still have to write the
-  // http_content_type field when the HTTP body is null.  That's why this code
-  // is here instead of inside WriteHttpBody.
-  WriteString(state.http_body.http_content_type, obj);
-
-  // Subitems
-  const std::vector<ExplodedFrameState>& children = state.children;
-  WriteAndValidateVectorSize(children, obj);
-  for (size_t i = 0; i < children.size(); ++i)
-    WriteFrameState(children[i], obj, false);
+  WriteResourceRequestBody(*http_body.request_body, obj);
+  WriteBoolean(http_body.contains_passwords, obj);
 }
 
 void ReadFrameState(
@@ -681,12 +649,287 @@
     ReadFrameState(obj, false, unique_name_replacements, &state->children[i]);
 }
 
+// Writes the ExplodedFrameState data into the SerializeObject object for
+// serialization. This uses the custom, legacy format, and its implementation
+// should remain frozen in order to preserve this format.
+// TODO(pnoland, dcheng) Move the legacy write methods into a test-only helper.
+void WriteFrameState(const ExplodedFrameState& state,
+                     SerializeObject* obj,
+                     bool is_top) {
+  // WARNING: This data may be persisted for later use. As such, care must be
+  // taken when changing the serialized format. If a new field needs to be
+  // written, only adding at the end will make it easier to deal with loading
+  // older versions. Similarly, this should NOT save fields with sensitive
+  // data, such as password fields.
+
+  WriteString(state.url_string, obj);
+  WriteString(state.target, obj);
+  WriteBoolean(state.did_save_scroll_or_scale_state, obj);
+
+  if (state.did_save_scroll_or_scale_state) {
+    WriteInteger(state.scroll_offset.x(), obj);
+    WriteInteger(state.scroll_offset.y(), obj);
+  }
+
+  WriteString(state.referrer, obj);
+
+  WriteStringVector(state.document_state, obj);
+
+  if (state.did_save_scroll_or_scale_state)
+    WriteReal(state.page_scale_factor, obj);
+
+  WriteInteger64(state.item_sequence_number, obj);
+  WriteInteger64(state.document_sequence_number, obj);
+  WriteInteger(static_cast<int>(state.referrer_policy), obj);
+
+  if (state.did_save_scroll_or_scale_state) {
+    WriteReal(state.visual_viewport_scroll_offset.x(), obj);
+    WriteReal(state.visual_viewport_scroll_offset.y(), obj);
+  }
+
+  WriteInteger(state.scroll_restoration_type, obj);
+
+  bool has_state_object = state.state_object.has_value();
+  WriteBoolean(has_state_object, obj);
+  if (has_state_object)
+    WriteString(*state.state_object, obj);
+
+  WriteHttpBody(state.http_body, obj);
+
+  // NOTE: It is a quirk of the format that we still have to write the
+  // http_content_type field when the HTTP body is null.  That's why this code
+  // is here instead of inside WriteHttpBody.
+  WriteString(state.http_body.http_content_type, obj);
+
+  // Subitems
+  const std::vector<ExplodedFrameState>& children = state.children;
+  WriteAndValidateVectorSize(children, obj);
+  for (size_t i = 0; i < children.size(); ++i)
+    WriteFrameState(children[i], obj, false);
+}
+
 void WritePageState(const ExplodedPageState& state, SerializeObject* obj) {
   WriteInteger(obj->version, obj);
   WriteStringVector(state.referenced_files, obj);
   WriteFrameState(state.top, obj, true);
 }
 
+// Legacy read/write functions above this line. Don't change these.
+//-----------------------------------------------------------------------------
+// "Modern" read/write functions start here. These are probably what you want.
+
+void WriteResourceRequestBody(const ResourceRequestBody& request_body,
+                              mojom::RequestBody* mojo_body) {
+  for (const auto& element : *request_body.elements()) {
+    mojom::ElementPtr data_element = mojom::Element::New();
+    switch (element.type()) {
+      case ResourceRequestBody::Element::TYPE_BYTES: {
+        data_element->set_bytes(std::vector<unsigned char>(
+            reinterpret_cast<const char*>(element.bytes()),
+            element.bytes() + element.length()));
+        break;
+      }
+      case ResourceRequestBody::Element::TYPE_FILE: {
+        mojom::FilePtr file = mojom::File::New(
+            element.path().AsUTF16Unsafe(), element.offset(), element.length(),
+            element.expected_modification_time());
+        data_element->set_file(std::move(file));
+        break;
+      }
+      case ResourceRequestBody::Element::TYPE_FILE_FILESYSTEM: {
+        mojom::FileSystemFilePtr file_system = mojom::FileSystemFile::New(
+            element.filesystem_url(), element.offset(), element.length(),
+            element.expected_modification_time());
+        data_element->set_file_system_file(std::move(file_system));
+        break;
+      }
+      case ResourceRequestBody::Element::TYPE_BLOB:
+        data_element->set_blob_uuid(element.blob_uuid());
+        break;
+      case ResourceRequestBody::Element::TYPE_BYTES_DESCRIPTION:
+      case ResourceRequestBody::Element::TYPE_DISK_CACHE_ENTRY:
+      case ResourceRequestBody::Element::TYPE_DATA_PIPE:
+      case ResourceRequestBody::Element::TYPE_UNKNOWN:
+        NOTREACHED();
+        continue;
+    }
+    mojo_body->elements.push_back(std::move(data_element));
+  }
+  mojo_body->identifier = request_body.identifier();
+}
+
+void ReadResourceRequestBody(
+    mojom::RequestBody* mojo_body,
+    const scoped_refptr<ResourceRequestBody>& request_body) {
+  for (const auto& element : mojo_body->elements) {
+    mojom::Element::Tag tag = element->which();
+    switch (tag) {
+      case mojom::Element::Tag::BYTES:
+        AppendDataToRequestBody(
+            request_body,
+            reinterpret_cast<const char*>(element->get_bytes().data()),
+            element->get_bytes().size());
+        break;
+      case mojom::Element::Tag::FILE: {
+        mojom::File* file = element->get_file().get();
+        AppendFileRangeToRequestBody(request_body, file->path, file->offset,
+                                     file->length, file->modification_time);
+        break;
+      }
+      case mojom::Element::Tag::FILE_SYSTEM_FILE: {
+        mojom::FileSystemFile* file_system =
+            element->get_file_system_file().get();
+        AppendURLRangeToRequestBody(request_body, file_system->filesystem_url,
+                                    file_system->offset, file_system->length,
+                                    file_system->modification_time);
+        break;
+      }
+      case mojom::Element::Tag::BLOB_UUID:
+        AppendBlobToRequestBody(request_body, element->get_blob_uuid());
+        break;
+    }
+  }
+  request_body->set_identifier(mojo_body->identifier);
+}
+
+void WriteHttpBody(const ExplodedHttpBody& http_body,
+                   mojom::HttpBody* mojo_body) {
+  if (http_body.request_body != nullptr) {
+    mojo_body->request_body = mojom::RequestBody::New();
+    mojo_body->contains_passwords = http_body.contains_passwords;
+    mojo_body->http_content_type = http_body.http_content_type;
+    WriteResourceRequestBody(*http_body.request_body,
+                             mojo_body->request_body.get());
+  }
+}
+
+void ReadHttpBody(mojom::HttpBody* mojo_body, ExplodedHttpBody* http_body) {
+  http_body->contains_passwords = mojo_body->contains_passwords;
+  http_body->http_content_type = mojo_body->http_content_type;
+  if (mojo_body->request_body) {
+    http_body->request_body = base::MakeRefCounted<ResourceRequestBody>();
+    ReadResourceRequestBody(mojo_body->request_body.get(),
+                            http_body->request_body);
+  }
+}
+
+void WriteFrameState(const ExplodedFrameState& state,
+                     mojom::FrameState* frame) {
+  frame->url_string = state.url_string;
+  frame->referrer = state.referrer;
+  frame->target = state.target;
+  frame->state_object = state.state_object;
+
+  for (const auto& s : state.document_state) {
+    frame->document_state.push_back(s);
+  }
+
+  frame->scroll_restoration_type =
+      static_cast<mojom::ScrollRestorationType>(state.scroll_restoration_type);
+
+  if (state.did_save_scroll_or_scale_state) {
+    frame->view_state = mojom::ViewState::New();
+    frame->view_state->scroll_offset = state.scroll_offset;
+    frame->view_state->visual_viewport_scroll_offset =
+        state.visual_viewport_scroll_offset;
+    frame->view_state->page_scale_factor = state.page_scale_factor;
+  }
+
+  frame->item_sequence_number = state.item_sequence_number;
+  frame->document_sequence_number = state.document_sequence_number;
+
+  frame->referrer_policy = state.referrer_policy;
+
+  frame->http_body = mojom::HttpBody::New();
+  WriteHttpBody(state.http_body, frame->http_body.get());
+
+  // Subitems
+  const std::vector<ExplodedFrameState>& children = state.children;
+  for (const auto& child : children) {
+    mojom::FrameStatePtr child_frame = mojom::FrameState::New();
+    WriteFrameState(child, child_frame.get());
+    frame->children.push_back(std::move(child_frame));
+  }
+}
+
+void ReadFrameState(mojom::FrameState* frame, ExplodedFrameState* state) {
+  state->url_string = frame->url_string;
+  state->referrer = frame->referrer;
+  state->target = frame->target;
+  state->state_object = frame->state_object;
+
+  for (const auto& s : frame->document_state) {
+    state->document_state.push_back(s);
+  }
+
+  state->scroll_restoration_type =
+      static_cast<blink::WebHistoryScrollRestorationType>(
+          frame->scroll_restoration_type);
+
+  if (frame->view_state) {
+    state->did_save_scroll_or_scale_state = true;
+    state->visual_viewport_scroll_offset =
+        frame->view_state->visual_viewport_scroll_offset;
+    state->scroll_offset = frame->view_state->scroll_offset;
+    state->page_scale_factor = frame->view_state->page_scale_factor;
+  }
+
+  state->item_sequence_number = frame->item_sequence_number;
+  state->document_sequence_number = frame->document_sequence_number;
+
+  state->referrer_policy = frame->referrer_policy;
+  if (frame->http_body) {
+    ReadHttpBody(frame->http_body.get(), &state->http_body);
+  } else {
+    state->http_body.request_body = nullptr;
+  }
+
+  state->children.resize(frame->children.size());
+  int i = 0;
+  for (const auto& child : frame->children)
+    ReadFrameState(child.get(), &state->children[i++]);
+}
+
+void ReadMojoPageState(SerializeObject* obj, ExplodedPageState* state) {
+  const void* tmp = nullptr;
+  int length = 0;
+  ReadData(obj, &tmp, &length);
+  DCHECK_GT(length, 0);
+  if (obj->parse_error)
+    return;
+
+  mojom::PageStatePtr page;
+  obj->parse_error = !(mojom::PageState::Deserialize(tmp, length, &page));
+  if (obj->parse_error)
+    return;
+
+  for (const auto& referenced_file : page->referenced_files) {
+    state->referenced_files.push_back(referenced_file);
+  }
+
+  ReadFrameState(page->top.get(), &state->top);
+
+  state->referenced_files.erase(std::unique(state->referenced_files.begin(),
+                                            state->referenced_files.end()),
+                                state->referenced_files.end());
+}
+
+void WriteMojoPageState(const ExplodedPageState& state, SerializeObject* obj) {
+  WriteInteger(obj->version, obj);
+
+  mojom::PageStatePtr page = mojom::PageState::New();
+  for (const auto& referenced_file : state.referenced_files) {
+    page->referenced_files.push_back(referenced_file.value());
+  }
+
+  page->top = mojom::FrameState::New();
+  WriteFrameState(state.top, page->top.get());
+
+  std::vector<uint8_t> page_bytes = mojom::PageState::Serialize(&page);
+  obj->pickle.WriteData(reinterpret_cast<char*>(page_bytes.data()),
+                        page_bytes.size());
+}
+
 void ReadPageState(SerializeObject* obj, ExplodedPageState* state) {
   obj->version = ReadInteger(obj);
 
@@ -702,6 +945,11 @@
     return;
   }
 
+  if (obj->version >= 26) {
+    ReadMojoPageState(obj, state);
+    return;
+  }
+
   if (obj->version >= 14)
     ReadStringVector(obj, &state->referenced_files);
 
@@ -790,25 +1038,22 @@
   return DecodePageStateInternal(encoded, exploded);
 }
 
-static void EncodePageStateInternal(const ExplodedPageState& exploded,
-                                    int version,
-                                    std::string* encoded) {
+void EncodePageState(const ExplodedPageState& exploded, std::string* encoded) {
+  SerializeObject obj;
+  obj.version = kCurrentVersion;
+  WriteMojoPageState(exploded, &obj);
+  *encoded = obj.GetAsString();
+}
+
+void LegacyEncodePageStateForTesting(const ExplodedPageState& exploded,
+                                     int version,
+                                     std::string* encoded) {
   SerializeObject obj;
   obj.version = version;
   WritePageState(exploded, &obj);
   *encoded = obj.GetAsString();
 }
 
-void EncodePageState(const ExplodedPageState& exploded, std::string* encoded) {
-  EncodePageStateInternal(exploded, kCurrentVersion, encoded);
-}
-
-void EncodePageStateForTesting(const ExplodedPageState& exploded,
-                               int version,
-                               std::string* encoded) {
-  EncodePageStateInternal(exploded, version, encoded);
-}
-
 #if defined(OS_ANDROID)
 bool DecodePageStateWithDeviceScaleFactorForTesting(
     const std::string& encoded,
@@ -835,7 +1080,7 @@
 std::string EncodeResourceRequestBody(
     const ResourceRequestBody& resource_request_body) {
   SerializeObject obj;
-  obj.version = kCurrentVersion;
+  obj.version = 25;
   WriteResourceRequestBody(resource_request_body, &obj);
   // EncodeResourceRequestBody() is different from WriteResourceRequestBody()
   // because it covers additional data (e.g.|contains_sensitive_info|) which
diff --git a/content/common/page_state_serialization.h b/content/common/page_state_serialization.h
index a04764f..8f68584 100644
--- a/content/common/page_state_serialization.h
+++ b/content/common/page_state_serialization.h
@@ -79,9 +79,10 @@
                                              ExplodedPageState* exploded);
 CONTENT_EXPORT void EncodePageState(const ExplodedPageState& exploded,
                                     std::string* encoded);
-CONTENT_EXPORT void EncodePageStateForTesting(const ExplodedPageState& exploded,
-                                              int version,
-                                              std::string* encoded);
+CONTENT_EXPORT void LegacyEncodePageStateForTesting(
+    const ExplodedPageState& exploded,
+    int version,
+    std::string* encoded);
 
 #if defined(OS_ANDROID)
 CONTENT_EXPORT bool DecodePageStateWithDeviceScaleFactorForTesting(
diff --git a/content/common/page_state_serialization_unittest.cc b/content/common/page_state_serialization_unittest.cc
index 725d52c..2ec8199 100644
--- a/content/common/page_state_serialization_unittest.cc
+++ b/content/common/page_state_serialization_unittest.cc
@@ -24,68 +24,76 @@
 //-----------------------------------------------------------------------------
 
 template <typename T>
-void ExpectEquality(const T& a, const T& b) {
-  EXPECT_EQ(a, b);
+void ExpectEquality(const T& expected, const T& actual) {
+  EXPECT_EQ(expected, actual);
 }
 
 template <typename T>
-void ExpectEquality(const std::vector<T>& a, const std::vector<T>& b) {
-  EXPECT_EQ(a.size(), b.size());
-  for (size_t i = 0; i < std::min(a.size(), b.size()); ++i)
-    ExpectEquality(a[i], b[i]);
+void ExpectEquality(const std::vector<T>& expected,
+                    const std::vector<T>& actual) {
+  EXPECT_EQ(expected.size(), actual.size());
+  for (size_t i = 0; i < std::min(expected.size(), actual.size()); ++i)
+    ExpectEquality(expected[i], actual[i]);
 }
 
 template <>
-void ExpectEquality(const ResourceRequestBody::Element& a,
-                    const ResourceRequestBody::Element& b) {
-  EXPECT_EQ(a.type(), b.type());
-  if (a.type() == ResourceRequestBody::Element::TYPE_BYTES &&
-      b.type() == ResourceRequestBody::Element::TYPE_BYTES) {
-    EXPECT_EQ(std::string(a.bytes(), a.length()),
-              std::string(b.bytes(), b.length()));
+void ExpectEquality(const ResourceRequestBody::Element& expected,
+                    const ResourceRequestBody::Element& actual) {
+  EXPECT_EQ(expected.type(), actual.type());
+  if (expected.type() == ResourceRequestBody::Element::TYPE_BYTES &&
+      actual.type() == ResourceRequestBody::Element::TYPE_BYTES) {
+    EXPECT_EQ(std::string(expected.bytes(), expected.length()),
+              std::string(actual.bytes(), actual.length()));
   }
-  EXPECT_EQ(a.path(), b.path());
-  EXPECT_EQ(a.filesystem_url(), b.filesystem_url());
-  EXPECT_EQ(a.offset(), b.offset());
-  EXPECT_EQ(a.length(), b.length());
-  EXPECT_EQ(a.expected_modification_time(), b.expected_modification_time());
-  EXPECT_EQ(a.blob_uuid(), b.blob_uuid());
+  EXPECT_EQ(expected.path(), actual.path());
+  EXPECT_EQ(expected.filesystem_url(), actual.filesystem_url());
+  EXPECT_EQ(expected.offset(), actual.offset());
+  EXPECT_EQ(expected.length(), actual.length());
+  EXPECT_EQ(expected.expected_modification_time(),
+            actual.expected_modification_time());
+  EXPECT_EQ(expected.blob_uuid(), actual.blob_uuid());
 }
 
 template <>
-void ExpectEquality(const ExplodedHttpBody& a, const ExplodedHttpBody& b) {
-  EXPECT_EQ(a.http_content_type, b.http_content_type);
-  EXPECT_EQ(a.contains_passwords, b.contains_passwords);
-  if (a.request_body == nullptr || b.request_body == nullptr) {
-    EXPECT_EQ(nullptr, a.request_body);
-    EXPECT_EQ(nullptr, b.request_body);
+void ExpectEquality(const ExplodedHttpBody& expected,
+                    const ExplodedHttpBody& actual) {
+  EXPECT_EQ(expected.http_content_type, actual.http_content_type);
+  EXPECT_EQ(expected.contains_passwords, actual.contains_passwords);
+  if (expected.request_body == nullptr || actual.request_body == nullptr) {
+    EXPECT_EQ(nullptr, expected.request_body);
+    EXPECT_EQ(nullptr, actual.request_body);
   } else {
-    EXPECT_EQ(a.request_body->identifier(), b.request_body->identifier());
-    ExpectEquality(*a.request_body->elements(), *b.request_body->elements());
+    EXPECT_EQ(expected.request_body->identifier(),
+              actual.request_body->identifier());
+    ExpectEquality(*expected.request_body->elements(),
+                   *actual.request_body->elements());
   }
 }
 
 template <>
-void ExpectEquality(const ExplodedFrameState& a, const ExplodedFrameState& b) {
-  EXPECT_EQ(a.url_string, b.url_string);
-  EXPECT_EQ(a.referrer, b.referrer);
-  EXPECT_EQ(a.referrer_policy, b.referrer_policy);
-  EXPECT_EQ(a.target, b.target);
-  EXPECT_EQ(a.state_object, b.state_object);
-  ExpectEquality(a.document_state, b.document_state);
-  EXPECT_EQ(a.scroll_restoration_type, b.scroll_restoration_type);
-  EXPECT_EQ(a.visual_viewport_scroll_offset, b.visual_viewport_scroll_offset);
-  EXPECT_EQ(a.scroll_offset, b.scroll_offset);
-  EXPECT_EQ(a.item_sequence_number, b.item_sequence_number);
-  EXPECT_EQ(a.document_sequence_number, b.document_sequence_number);
-  EXPECT_EQ(a.page_scale_factor, b.page_scale_factor);
-  ExpectEquality(a.http_body, b.http_body);
-  ExpectEquality(a.children, b.children);
+void ExpectEquality(const ExplodedFrameState& expected,
+                    const ExplodedFrameState& actual) {
+  EXPECT_EQ(expected.url_string, actual.url_string);
+  EXPECT_EQ(expected.referrer, actual.referrer);
+  EXPECT_EQ(expected.referrer_policy, actual.referrer_policy);
+  EXPECT_EQ(expected.target, actual.target);
+  EXPECT_EQ(expected.state_object, actual.state_object);
+  ExpectEquality(expected.document_state, actual.document_state);
+  EXPECT_EQ(expected.scroll_restoration_type, actual.scroll_restoration_type);
+  EXPECT_EQ(expected.visual_viewport_scroll_offset,
+            actual.visual_viewport_scroll_offset);
+  EXPECT_EQ(expected.scroll_offset, actual.scroll_offset);
+  EXPECT_EQ(expected.item_sequence_number, actual.item_sequence_number);
+  EXPECT_EQ(expected.document_sequence_number, actual.document_sequence_number);
+  EXPECT_EQ(expected.page_scale_factor, actual.page_scale_factor);
+  ExpectEquality(expected.http_body, actual.http_body);
+  ExpectEquality(expected.children, actual.children);
 }
 
-void ExpectEquality(const ExplodedPageState& a, const ExplodedPageState& b) {
-  ExpectEquality(a.referenced_files, b.referenced_files);
-  ExpectEquality(a.top, b.top);
+void ExpectEquality(const ExplodedPageState& expected,
+                    const ExplodedPageState& actual) {
+  ExpectEquality(expected.referenced_files, actual.referenced_files);
+  ExpectEquality(expected.top, actual.top);
 }
 
 //-----------------------------------------------------------------------------
@@ -186,20 +194,14 @@
     PopulateFrameStateForBackwardsCompatTest(&page_state->top, false);
   }
 
-  void TestBackwardsCompat(int version) {
-    const char* suffix = "";
-
-#if defined(OS_ANDROID)
-    // Unfortunately, the format of version 11 is different on Android, so we
-    // need to use a special reference file.
-    if (version == 11)
-      suffix = "_android";
-#endif
-
+  void ReadBackwardsCompatPageState(const std::string& suffix,
+                                    int version,
+                                    ExplodedPageState* page_state) {
     base::FilePath path;
     PathService::Get(content::DIR_TEST_DATA, &path);
-    path = path.AppendASCII("page_state").AppendASCII(
-        base::StringPrintf("serialized_v%d%s.dat", version, suffix));
+    path = path.AppendASCII("page_state")
+               .AppendASCII(
+                   base::StringPrintf("serialized_%s.dat", suffix.c_str()));
 
     std::string file_contents;
     if (!base::ReadFileToString(path, &file_contents)) {
@@ -207,30 +209,47 @@
       return;
     }
 
-    std::string trimmed_contents;
-    EXPECT_TRUE(base::RemoveChars(file_contents, "\r\n", &trimmed_contents));
+    std::string trimmed_file_contents;
+    EXPECT_TRUE(
+        base::RemoveChars(file_contents, "\r\n", &trimmed_file_contents));
 
-    std::string encoded;
-    EXPECT_TRUE(base::Base64Decode(trimmed_contents, &encoded));
+    std::string saved_encoded_state;
+    // PageState is encoded twice; once via EncodePageState, and again
+    // via Base64Decode, so we need to Base64Decode to get the original
+    // encoded PageState.
+    EXPECT_TRUE(
+        base::Base64Decode(trimmed_file_contents, &saved_encoded_state));
 
-    ExplodedPageState output;
 #if defined(OS_ANDROID)
     // Because version 11 of the file format unfortunately bakes in the device
     // scale factor on Android, perform this test by assuming a preset device
     // scale factor, ignoring the device scale factor of the current device.
     const float kPresetDeviceScaleFactor = 2.0f;
     EXPECT_TRUE(DecodePageStateWithDeviceScaleFactorForTesting(
-        encoded,
-        kPresetDeviceScaleFactor,
-        &output));
+        saved_encoded_state, kPresetDeviceScaleFactor, page_state));
 #else
-    EXPECT_EQ(version, DecodePageStateForTesting(encoded, &output));
+    EXPECT_EQ(version,
+              DecodePageStateForTesting(saved_encoded_state, page_state));
+#endif
+  }
+
+  void TestBackwardsCompat(int version) {
+    std::string suffix = base::StringPrintf("v%d", version);
+
+#if defined(OS_ANDROID)
+    // Unfortunately, the format of version 11 is different on Android, so we
+    // need to use a special reference file.
+    if (version == 11) {
+      suffix = std::string("v11_android");
+    }
 #endif
 
-    ExplodedPageState expected;
-    PopulatePageStateForBackwardsCompatTest(&expected);
+    ExplodedPageState decoded_state;
+    ExplodedPageState expected_state;
+    PopulatePageStateForBackwardsCompatTest(&expected_state);
+    ReadBackwardsCompatPageState(suffix, version, &decoded_state);
 
-    ExpectEquality(expected, output);
+    ExpectEquality(expected_state, decoded_state);
   }
 };
 
@@ -360,11 +379,45 @@
   EXPECT_FALSE(DecodePageState(s, &output));
 }
 
+// Tests that LegacyEncodePageState, which uses the pre-mojo serialization
+// format, produces the exact same blob as it did when the test was written.
+// This ensures that the implementation is frozen, which is needed to correctly
+// test compatibility and migration.
+TEST_F(PageStateSerializationTest, LegacyEncodePageStateFrozen) {
+  ExplodedPageState actual_state;
+  PopulatePageStateForBackwardsCompatTest(&actual_state);
+
+  std::string actual_encoded_state;
+  LegacyEncodePageStateForTesting(actual_state, 25, &actual_encoded_state);
+
+  base::FilePath path;
+  PathService::Get(content::DIR_TEST_DATA, &path);
+  path = path.AppendASCII("page_state").AppendASCII("serialized_v25.dat");
+
+  std::string file_contents;
+  ASSERT_TRUE(base::ReadFileToString(path, &file_contents))
+      << "File not found: " << path.value();
+
+  std::string trimmed_file_contents;
+  EXPECT_TRUE(base::RemoveChars(file_contents, "\n", &trimmed_file_contents));
+
+  std::string expected_encoded_state;
+  EXPECT_TRUE(
+      base::Base64Decode(trimmed_file_contents, &expected_encoded_state));
+
+  ExpectEquality(actual_encoded_state, expected_encoded_state);
+}
+
 // Change to #if 1 to enable this code. Run this test to generate data, based on
 // the current serialization format, for the BackwardsCompat_vXX tests. This
 // will generate an expected.dat in the temp directory, which should be moved
 // //content/test/data/page_state/serialization_vXX.dat. A corresponding test
-// case for that version should also then be added below.
+// case for that version should also then be added below. You need to add such
+// a test for any addition/change to the schema of serialized page state.
+// If you're adding a field whose type is defined externally of
+// page_state.mojom, add an backwards compat test for that field specifically
+// by dumping a state object with only that field populated. See, e.g.,
+// BackwardsCompat_UrlString as an example.
 //
 // IMPORTANT: this code dumps the serialization as the *current* version, so if
 // generating a backwards compat test for v23, the tree must be synced to a
@@ -451,5 +504,140 @@
   TestBackwardsCompat(24);
 }
 
+TEST_F(PageStateSerializationTest, BackwardsCompat_v25) {
+  TestBackwardsCompat(25);
+}
+
+TEST_F(PageStateSerializationTest, BackwardsCompat_v26) {
+  TestBackwardsCompat(26);
+}
+
+// If any of the below tests fail, you likely made a backwards incompatible
+// change to a definition that page_state.mojom relies on. Ideally you should
+// find a way to avoid making this change; if that's not possible, contact the
+// page state serialization owners to figure out a resolution.
+TEST_F(PageStateSerializationTest, BackwardsCompat_ReferencedFiles) {
+  ExplodedPageState state;
+  state.referenced_files.push_back(base::UTF8ToUTF16("file.txt"));
+
+  ExplodedPageState saved_state;
+  ReadBackwardsCompatPageState("referenced_files", 26, &saved_state);
+  ExpectEquality(state, saved_state);
+}
+
+TEST_F(PageStateSerializationTest, BackwardsCompat_UrlString) {
+  ExplodedPageState state;
+  state.top.url_string = base::ASCIIToUTF16("http://chromium.org");
+
+  ExplodedPageState saved_state;
+  ReadBackwardsCompatPageState("url_string", 26, &saved_state);
+  ExpectEquality(state, saved_state);
+}
+
+TEST_F(PageStateSerializationTest, BackwardsCompat_Referrer) {
+  ExplodedPageState state;
+  state.top.referrer = base::ASCIIToUTF16("http://www.google.com");
+
+  ExplodedPageState saved_state;
+  ReadBackwardsCompatPageState("referrer", 26, &saved_state);
+  ExpectEquality(state, saved_state);
+}
+
+TEST_F(PageStateSerializationTest, BackwardsCompat_Target) {
+  ExplodedPageState state;
+  state.top.target = base::ASCIIToUTF16("http://www.google.com");
+
+  ExplodedPageState saved_state;
+  ReadBackwardsCompatPageState("target", 26, &saved_state);
+  ExpectEquality(state, saved_state);
+}
+
+TEST_F(PageStateSerializationTest, BackwardsCompat_StateObject) {
+  ExplodedPageState state;
+  state.top.state_object = base::ASCIIToUTF16("state");
+
+  ExplodedPageState saved_state;
+  ReadBackwardsCompatPageState("state_object", 26, &saved_state);
+  ExpectEquality(state, saved_state);
+}
+
+TEST_F(PageStateSerializationTest, BackwardsCompat_DocumentState) {
+  ExplodedPageState state;
+  state.top.document_state.push_back(base::ASCIIToUTF16(
+      "\n\r?% WebKit serialized form state version 8 \n\r=&"));
+
+  ExplodedPageState saved_state;
+  ReadBackwardsCompatPageState("document_state", 26, &saved_state);
+  ExpectEquality(state, saved_state);
+}
+
+TEST_F(PageStateSerializationTest, BackwardsCompat_ScrollRestorationType) {
+  ExplodedPageState state;
+  state.top.scroll_restoration_type = blink::kWebHistoryScrollRestorationManual;
+
+  ExplodedPageState saved_state;
+  ReadBackwardsCompatPageState("scroll_restoration_type", 26, &saved_state);
+  ExpectEquality(state, saved_state);
+}
+
+TEST_F(PageStateSerializationTest, BackwardsCompat_VisualViewportScrollOffset) {
+  ExplodedPageState state;
+  state.top.visual_viewport_scroll_offset = gfx::PointF(42.2, -42.2);
+
+  ExplodedPageState saved_state;
+  ReadBackwardsCompatPageState("visual_viewport_scroll_offset", 26,
+                               &saved_state);
+  ExpectEquality(state, saved_state);
+}
+
+TEST_F(PageStateSerializationTest, BackwardsCompat_ScrollOffset) {
+  ExplodedPageState state;
+  state.top.scroll_offset = gfx::Point(1, -1);
+
+  ExplodedPageState saved_state;
+  ReadBackwardsCompatPageState("scroll_offset", 26, &saved_state);
+  ExpectEquality(state, saved_state);
+}
+
+TEST_F(PageStateSerializationTest, BackwardsCompat_ReferrerPolicy) {
+  ExplodedPageState state;
+  state.top.referrer_policy = blink::kWebReferrerPolicyAlways;
+
+  ExplodedPageState saved_state;
+  ReadBackwardsCompatPageState("referrer_policy", 26, &saved_state);
+  ExpectEquality(state, saved_state);
+}
+
+TEST_F(PageStateSerializationTest, BackwardsCompat_HttpBody) {
+  ExplodedPageState state;
+  ExplodedHttpBody& http_body = state.top.http_body;
+
+  http_body.request_body = new ResourceRequestBody();
+  http_body.request_body->set_identifier(12345);
+  http_body.contains_passwords = false;
+  http_body.http_content_type = base::UTF8ToUTF16("text/foo");
+
+  std::string test_body("foo");
+  http_body.request_body->AppendBytes(test_body.data(), test_body.size());
+
+  http_body.request_body->AppendBlob("some_uuid");
+
+  base::FilePath path(FILE_PATH_LITERAL("file.txt"));
+  http_body.request_body->AppendFileRange(base::FilePath(path), 100, 1024,
+                                          base::Time::FromDoubleT(9999.0));
+
+  http_body.request_body->AppendFileSystemFileRange(
+      GURL("file://some_file.txt"), 100, 1024, base::Time::FromDoubleT(9999.0));
+
+  ExplodedPageState saved_state;
+  ReadBackwardsCompatPageState("http_body", 26, &saved_state);
+  ExpectEquality(state, saved_state);
+}
+
+// Add your new backwards compat test for future versions/fields here.
+// Any field additions require a new version and backcompat test; only fields
+// with external type definitions require their own dedicated test.
+// See DumpExpectedPageStateForBackwardsCompat for more details.
+
 }  // namespace
 }  // namespace content
diff --git a/content/common/renderer.mojom b/content/common/renderer.mojom
index 86ad9e7b..ad8c015e5 100644
--- a/content/common/renderer.mojom
+++ b/content/common/renderer.mojom
@@ -9,6 +9,7 @@
 import "ipc/constants.mojom";
 import "mojo/common/time.mojom";
 import "mojo/common/unguessable_token.mojom";
+import "services/service_manager/public/interfaces/interface_provider.mojom";
 import "ui/gfx/geometry/mojo/geometry.mojom";
 import "ui/gfx/mojo/icc_profile.mojom";
 
@@ -22,9 +23,17 @@
   // The ID of the view to be created.
   int32 view_id = IPC.mojom.kRoutingIdNone;
 
-  // The ID of the main frame hosted in the view.
+  // The ID of the main frame hosted in the view, or None if creating a view to
+  // host a main frame proxy.
   int32 main_frame_routing_id = IPC.mojom.kRoutingIdNone;
 
+  // The InterfaceProvider through which the main RenderFrame can access
+  // services exposed by its RenderFrameHost.
+  //
+  // This is null precisely when |main_frame_routing_id| is MSG_ROUTING_NONE,
+  // that is, when creating a RenderView for a remote main frame.
+  service_manager.mojom.InterfaceProvider? main_frame_interface_provider;
+
   // The ID of the widget for the main frame.
   int32 main_frame_widget_routing_id = IPC.mojom.kRoutingIdNone;
 
@@ -114,6 +123,10 @@
   // parent frame, in front of any other children.
   int32 previous_sibling_routing_id;
 
+  // The InterfaceProvider through which the RenderFrame can access services
+  // exposed by its RenderFrameHost.
+  service_manager.mojom.InterfaceProvider interface_provider;
+
   // When the new frame has a parent, |replication_state| holds the new frame's
   // properties replicated from the process rendering the parent frame, such as
   // the new frame's sandbox flags.
@@ -187,7 +200,7 @@
   // The downstream throughput is computed in kilobits per second. If an
   // estimate of the HTTP or transport RTT is unavailable, it will be set to
   // net::nqe::internal::InvalidRTT(). If the throughput estimate is
-  // unavailable, it will be set to net::nqe::internal::kInvalidThroughput.
+  // unavailable, it will be set to net::nqe::internal::INVALID_RTT_THROUGHPUT.
   OnNetworkQualityChanged(EffectiveConnectionType effective_connection_type,
                           mojo.common.mojom.TimeDelta http_rtt,
                           mojo.common.mojom.TimeDelta transport_rtt,
diff --git a/content/common/typemaps.gni b/content/common/typemaps.gni
index 3daaa86..ab0d08b3 100644
--- a/content/common/typemaps.gni
+++ b/content/common/typemaps.gni
@@ -15,6 +15,7 @@
   "//content/common/service_worker/service_worker_fetch_request.typemap",
   "//content/common/service_worker/service_worker_provider.typemap",
   "//content/common/service_worker/service_worker_types.typemap",
+  "//content/common/url_loader_factory_bundle.typemap",
   "//content/common/web_preferences.typemap",
   "//content/common/media/media_session.typemap",
 ]
diff --git a/content/common/unique_name_helper_unittest.cc b/content/common/unique_name_helper_unittest.cc
index 12932e4..1bf2e5b 100644
--- a/content/common/unique_name_helper_unittest.cc
+++ b/content/common/unique_name_helper_unittest.cc
@@ -163,7 +163,7 @@
 
   // Version 24 is the last version with unlimited size unique names.
   std::string encoded_state;
-  EncodePageStateForTesting(in_state, 24, &encoded_state);
+  LegacyEncodePageStateForTesting(in_state, 24, &encoded_state);
 
   ExplodedPageState out_state;
   DecodePageState(encoded_state, &out_state);
diff --git a/content/common/url_loader_factory_bundle.cc b/content/common/url_loader_factory_bundle.cc
new file mode 100644
index 0000000..a0128c84
--- /dev/null
+++ b/content/common/url_loader_factory_bundle.cc
@@ -0,0 +1,94 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/common/url_loader_factory_bundle.h"
+
+#include <map>
+#include <string>
+
+#include "base/macros.h"
+#include "content/public/common/url_loader_factory.mojom.h"
+#include "url/gurl.h"
+
+class GURL;
+
+namespace content {
+
+URLLoaderFactoryBundleInfo::URLLoaderFactoryBundleInfo(
+    URLLoaderFactoryBundleInfo&&) = default;
+
+URLLoaderFactoryBundleInfo::URLLoaderFactoryBundleInfo(
+    mojom::URLLoaderFactoryPtrInfo default_factory_info,
+    std::map<std::string, mojom::URLLoaderFactoryPtrInfo> factories_info)
+    : default_factory_info(std::move(default_factory_info)),
+      factories_info(std::move(factories_info)) {}
+
+URLLoaderFactoryBundleInfo::~URLLoaderFactoryBundleInfo() = default;
+
+URLLoaderFactoryBundle::URLLoaderFactoryBundle() = default;
+
+URLLoaderFactoryBundle::URLLoaderFactoryBundle(URLLoaderFactoryBundle&&) =
+    default;
+
+URLLoaderFactoryBundle::URLLoaderFactoryBundle(
+    URLLoaderFactoryBundleInfo info) {
+  default_factory_.Bind(std::move(info.default_factory_info));
+  for (auto& factory_info : info.factories_info)
+    factories_[factory_info.first].Bind(std::move(factory_info.second));
+}
+
+URLLoaderFactoryBundle::~URLLoaderFactoryBundle() = default;
+
+URLLoaderFactoryBundle& URLLoaderFactoryBundle::operator=(
+    URLLoaderFactoryBundle&&) = default;
+
+void URLLoaderFactoryBundle::SetDefaultFactory(
+    mojom::URLLoaderFactoryPtr factory) {
+  default_factory_ = std::move(factory);
+}
+
+void URLLoaderFactoryBundle::RegisterFactory(
+    const base::StringPiece& scheme,
+    mojom::URLLoaderFactoryPtr factory) {
+  DCHECK(factory.is_bound());
+  auto result = factories_.emplace(std::string(scheme), std::move(factory));
+  DCHECK(result.second);
+}
+
+mojom::URLLoaderFactory* URLLoaderFactoryBundle::GetFactoryForRequest(
+    const GURL& url) {
+  auto it = factories_.find(url.scheme());
+  if (it == factories_.end()) {
+    DCHECK(default_factory_.is_bound());
+    return default_factory_.get();
+  }
+  return it->second.get();
+}
+
+URLLoaderFactoryBundleInfo URLLoaderFactoryBundle::PassInfo() {
+  std::map<std::string, mojom::URLLoaderFactoryPtrInfo> factories_info;
+  for (auto& factory : factories_)
+    factories_info.emplace(factory.first, factory.second.PassInterface());
+  DCHECK(default_factory_.is_bound());
+  return URLLoaderFactoryBundleInfo(default_factory_.PassInterface(),
+                                    std::move(factories_info));
+}
+
+URLLoaderFactoryBundle URLLoaderFactoryBundle::Clone() {
+  DCHECK(default_factory_.is_bound());
+  mojom::URLLoaderFactoryPtr cloned_default_factory;
+  default_factory_->Clone(mojo::MakeRequest(&cloned_default_factory));
+
+  URLLoaderFactoryBundle new_bundle;
+  new_bundle.SetDefaultFactory(std::move(cloned_default_factory));
+  for (auto& factory : factories_) {
+    mojom::URLLoaderFactoryPtr cloned_factory;
+    factory.second->Clone(mojo::MakeRequest(&cloned_factory));
+    new_bundle.RegisterFactory(factory.first, std::move(cloned_factory));
+  }
+
+  return new_bundle;
+}
+
+}  // namespace content
diff --git a/content/common/url_loader_factory_bundle.h b/content/common/url_loader_factory_bundle.h
new file mode 100644
index 0000000..0147254
--- /dev/null
+++ b/content/common/url_loader_factory_bundle.h
@@ -0,0 +1,87 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CONTENT_COMMON_URL_LOADER_FACTORY_BUNDLE_H_
+#define CONTENT_COMMON_URL_LOADER_FACTORY_BUNDLE_H_
+
+#include <map>
+#include <string>
+
+#include "base/macros.h"
+#include "content/common/content_export.h"
+#include "content/public/common/url_loader_factory.mojom.h"
+
+class GURL;
+
+namespace mojo {
+template <typename, typename>
+struct StructTraits;
+}
+
+namespace content {
+
+namespace mojom {
+class URLLoaderFactoryBundleDataView;
+}
+
+// Holds the internal state of a URLLoaderFactoryBundle in a form that is safe
+// to pass across sequences.
+struct CONTENT_EXPORT URLLoaderFactoryBundleInfo {
+  URLLoaderFactoryBundleInfo(URLLoaderFactoryBundleInfo&&);
+  URLLoaderFactoryBundleInfo(
+      mojom::URLLoaderFactoryPtrInfo default_factory_info,
+      std::map<std::string, mojom::URLLoaderFactoryPtrInfo> factories_info);
+  ~URLLoaderFactoryBundleInfo();
+
+  mojom::URLLoaderFactoryPtrInfo default_factory_info;
+  std::map<std::string, mojom::URLLoaderFactoryPtrInfo> factories_info;
+};
+
+// Encapsulates a collection of URLLoaderFactoryPtrs which can be usd to acquire
+// loaders for various types of resource requests.
+class CONTENT_EXPORT URLLoaderFactoryBundle {
+ public:
+  URLLoaderFactoryBundle();
+  URLLoaderFactoryBundle(URLLoaderFactoryBundle&&);
+  explicit URLLoaderFactoryBundle(URLLoaderFactoryBundleInfo info);
+  ~URLLoaderFactoryBundle();
+
+  URLLoaderFactoryBundle& operator=(URLLoaderFactoryBundle&&);
+
+  // Sets the default factory to use when no registered factories match a given
+  // |url|.
+  void SetDefaultFactory(mojom::URLLoaderFactoryPtr factory);
+
+  // Registers a new factory to handle requests matching scheme |scheme|.
+  void RegisterFactory(const base::StringPiece& scheme,
+                       mojom::URLLoaderFactoryPtr factory);
+
+  // Returns a factory which can be used to acquire a loader for |url|. If no
+  // registered factory matches |url|'s scheme, the default factory is used. It
+  // is undefined behavior to call this when no default factory is set.
+  mojom::URLLoaderFactory* GetFactoryForRequest(const GURL& url);
+
+  // Passes out a structure which captures the internal state of this bundle in
+  // a form that is safe to pass across sequences. Effectively resets |this|
+  // to have no registered factories.
+  URLLoaderFactoryBundleInfo PassInfo();
+
+  // Creates a clone of this bundle which can be passed to and owned by another
+  // consumer. The clone operates identically to but independent from the
+  // original (this) bundle.
+  URLLoaderFactoryBundle Clone();
+
+ private:
+  friend struct mojo::StructTraits<mojom::URLLoaderFactoryBundleDataView,
+                                   URLLoaderFactoryBundle>;
+
+  mojom::URLLoaderFactoryPtr default_factory_;
+  std::map<std::string, mojom::URLLoaderFactoryPtr> factories_;
+
+  DISALLOW_COPY_AND_ASSIGN(URLLoaderFactoryBundle);
+};
+
+}  // namespace content
+
+#endif  // CONTENT_COMMON_URL_LOADER_FACTORY_BUNDLE_H_
diff --git a/content/common/url_loader_factory_bundle.mojom b/content/common/url_loader_factory_bundle.mojom
new file mode 100644
index 0000000..1f0f9e2b
--- /dev/null
+++ b/content/common/url_loader_factory_bundle.mojom
@@ -0,0 +1,16 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+module content.mojom;
+
+import "content/public/common/url_loader_factory.mojom";
+
+// Serializes a collection of URLLoaderFactory interfaces.
+struct URLLoaderFactoryBundle {
+  // The default factory to be used when no others apply.
+  URLLoaderFactory default_factory;
+
+  // A mapping from URL scheme to factory interface.
+  map<string, URLLoaderFactory> factories;
+};
diff --git a/content/common/url_loader_factory_bundle.typemap b/content/common/url_loader_factory_bundle.typemap
new file mode 100644
index 0000000..066c04c
--- /dev/null
+++ b/content/common/url_loader_factory_bundle.typemap
@@ -0,0 +1,13 @@
+# Copyright 2017 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+mojom = "//content/common/url_loader_factory_bundle.mojom"
+public_headers = [ "//content/common/url_loader_factory_bundle.h" ]
+traits_headers =
+    [ "//content/common/url_loader_factory_bundle_struct_traits.h" ]
+sources = [
+  "//content/common/url_loader_factory_bundle_struct_traits.cc",
+]
+
+type_mappings = [ "content.mojom.URLLoaderFactoryBundle=content::URLLoaderFactoryBundle[move_only]" ]
diff --git a/content/common/url_loader_factory_bundle_struct_traits.cc b/content/common/url_loader_factory_bundle_struct_traits.cc
new file mode 100644
index 0000000..917d12a
--- /dev/null
+++ b/content/common/url_loader_factory_bundle_struct_traits.cc
@@ -0,0 +1,34 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/common/url_loader_factory_bundle_struct_traits.h"
+
+namespace mojo {
+
+using Traits = StructTraits<content::mojom::URLLoaderFactoryBundleDataView,
+                            content::URLLoaderFactoryBundle>;
+
+// static
+content::mojom::URLLoaderFactoryPtr Traits::default_factory(
+    content::URLLoaderFactoryBundle& bundle) {
+  return std::move(bundle.default_factory_);
+}
+
+// static
+std::map<std::string, content::mojom::URLLoaderFactoryPtr> Traits::factories(
+    content::URLLoaderFactoryBundle& bundle) {
+  return std::move(bundle.factories_);
+}
+
+// static
+bool Traits::Read(content::mojom::URLLoaderFactoryBundleDataView data,
+                  content::URLLoaderFactoryBundle* out_bundle) {
+  out_bundle->SetDefaultFactory(
+      data.TakeDefaultFactory<content::mojom::URLLoaderFactoryPtr>());
+  if (!data.ReadFactories(&out_bundle->factories_))
+    return false;
+  return true;
+}
+
+}  // namespace mojo
diff --git a/content/common/url_loader_factory_bundle_struct_traits.h b/content/common/url_loader_factory_bundle_struct_traits.h
new file mode 100644
index 0000000..f263049
--- /dev/null
+++ b/content/common/url_loader_factory_bundle_struct_traits.h
@@ -0,0 +1,29 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CONTENT_COMMON_URL_LOADER_FACTORY_BUNDLE_STRUCT_TRAITS_H_
+#define CONTENT_COMMON_URL_LOADER_FACTORY_BUNDLE_STRUCT_TRAITS_H_
+
+#include "content/common/url_loader_factory_bundle.h"
+#include "content/common/url_loader_factory_bundle.mojom-shared.h"
+#include "mojo/public/cpp/bindings/struct_traits.h"
+
+namespace mojo {
+
+template <>
+struct StructTraits<content::mojom::URLLoaderFactoryBundleDataView,
+                    content::URLLoaderFactoryBundle> {
+  static content::mojom::URLLoaderFactoryPtr default_factory(
+      content::URLLoaderFactoryBundle& bundle);
+
+  static std::map<std::string, content::mojom::URLLoaderFactoryPtr> factories(
+      content::URLLoaderFactoryBundle& bundle);
+
+  static bool Read(content::mojom::URLLoaderFactoryBundleDataView data,
+                   content::URLLoaderFactoryBundle* out_bundle);
+};
+
+}  // namespace mojo
+
+#endif  // CONTENT_COMMON_URL_LOADER_FACTORY_BUNDLE_STRUCT_TRAITS_H_
diff --git a/content/network/network_service_unittest.cc b/content/network/network_service_unittest.cc
index fd736fa5..e779364 100644
--- a/content/network/network_service_unittest.cc
+++ b/content/network/network_service_unittest.cc
@@ -122,7 +122,6 @@
  public:
   NetworkServiceTestWithService()
       : ServiceTest("content_unittests",
-                    false,
                     base::test::ScopedTaskEnvironment::MainThreadType::IO) {}
   ~NetworkServiceTestWithService() override {}
 
@@ -379,7 +378,6 @@
  public:
   NetworkServiceNetworkChangeTest()
       : ServiceTest("content_unittests",
-                    false,
                     base::test::ScopedTaskEnvironment::MainThreadType::IO) {}
   ~NetworkServiceNetworkChangeTest() override {}
 
diff --git a/content/network/url_loader_impl.cc b/content/network/url_loader_impl.cc
index 28fca4a..acabd23 100644
--- a/content/network/url_loader_impl.cc
+++ b/content/network/url_loader_impl.cc
@@ -233,10 +233,10 @@
             body, file_task_runner, element));
         break;
       case ResourceRequestBody::Element::TYPE_FILE_FILESYSTEM:
-        NOTIMPLEMENTED();
+        CHECK(false) << "Should never be reached";
         break;
       case ResourceRequestBody::Element::TYPE_BLOB: {
-        NOTREACHED();
+        CHECK(false) << "Network service always uses DATA_PIPE for blobs.";
         break;
       }
       case ResourceRequestBody::Element::TYPE_DATA_PIPE: {
diff --git a/content/public/app/mojo/content_browser_manifest.json b/content/public/app/mojo/content_browser_manifest.json
index bfdc3ec5..ed92140 100644
--- a/content/public/app/mojo/content_browser_manifest.json
+++ b/content/public/app/mojo/content_browser_manifest.json
@@ -43,6 +43,7 @@
           "content::mojom::WebDatabaseHost",
           "content::mojom::WorkerURLLoaderFactoryProvider",
           "device::mojom::BatteryMonitor",
+          "device::mojom::GamepadHapticsManager",
           "device::mojom::GamepadMonitor",
           "discardable_memory::mojom::DiscardableSharedMemoryManager",
           "media::mojom::VideoDecodePerfHistory",
diff --git a/content/public/browser/background_fetch_delegate.h b/content/public/browser/background_fetch_delegate.h
index 826243b..8b66700 100644
--- a/content/public/browser/background_fetch_delegate.h
+++ b/content/public/browser/background_fetch_delegate.h
@@ -41,21 +41,28 @@
    public:
     virtual ~Client() {}
 
+    // Called when the entire download job has been cancelled by the delegate,
+    // e.g. because the user clicked cancel on a notification.
+    virtual void OnJobCancelled(const std::string& job_unique_id) = 0;
+
     // Called after the download has started with the initial response
     // (including headers and URL chain). Always called on the UI thread.
     virtual void OnDownloadStarted(
-        const std::string& guid,
+        const std::string& job_unique_id,
+        const std::string& download_guid,
         std::unique_ptr<content::BackgroundFetchResponse> response) = 0;
 
     // Called during the download to indicate the current progress. Always
     // called on the UI thread.
-    virtual void OnDownloadUpdated(const std::string& guid,
+    virtual void OnDownloadUpdated(const std::string& job_unique_id,
+                                   const std::string& download_guid,
                                    uint64_t bytes_downloaded) = 0;
 
     // Called after the download has completed giving the result including the
     // path to the downloaded file and its size. Always called on the UI thread.
     virtual void OnDownloadComplete(
-        const std::string& guid,
+        const std::string& job_unique_id,
+        const std::string& download_guid,
         std::unique_ptr<BackgroundFetchResult> result) = 0;
 
     // Called by the delegate when it's shutting down to signal that the
@@ -81,11 +88,11 @@
       int total_parts,
       const std::vector<std::string>& current_guids) = 0;
 
-  // Creates a new download identified by |guid| in the download job identified
-  // by |job_unique_id|.
+  // Creates a new download identified by |download_guid| in the download job
+  // identified by |job_unique_id|.
   virtual void DownloadUrl(
       const std::string& job_unique_id,
-      const std::string& guid,
+      const std::string& download_guid,
       const std::string& method,
       const GURL& url,
       const net::NetworkTrafficAnnotationTag& traffic_annotation,
diff --git a/content/public/browser/browser_context.h b/content/public/browser/browser_context.h
index 261c2a1..f75be61 100644
--- a/content/public/browser/browser_context.h
+++ b/content/public/browser/browser_context.h
@@ -41,6 +41,10 @@
 class ExternalMountPoints;
 }
 
+namespace media {
+class VideoDecodePerfHistory;
+}
+
 namespace net {
 class URLRequestContextGetter;
 }
@@ -300,6 +304,12 @@
   // 2) The embedder saves its salt across restarts.
   static std::string CreateRandomMediaDeviceIDSalt();
 
+  // Media service for storing/retrieving video decoding performance stats.
+  // Exposed here rather than StoragePartition because all SiteInstances should
+  // have similar decode performance and stats are not exposed to the web
+  // directly, so privacy is not compromised.
+  virtual media::VideoDecodePerfHistory* GetVideoDecodePerfHistory();
+
  private:
   const std::string media_device_id_salt_;
 };
diff --git a/content/public/browser/gpu_data_manager.h b/content/public/browser/gpu_data_manager.h
index be661ff5..06758fb 100644
--- a/content/public/browser/gpu_data_manager.h
+++ b/content/public/browser/gpu_data_manager.h
@@ -11,7 +11,6 @@
 #include "base/callback_forward.h"
 #include "base/process/process.h"
 #include "content/common/content_export.h"
-#include "gpu/config/gpu_feature_info.h"
 
 class GURL;
 
@@ -34,9 +33,9 @@
   virtual void BlacklistWebGLForTesting() = 0;
 
   virtual bool IsFeatureBlacklisted(int feature) const = 0;
-
-  virtual gpu::GpuFeatureStatus GetFeatureStatus(
-      gpu::GpuFeatureType feature) const = 0;
+  virtual bool IsFeatureEnabled(int feature) const = 0;
+  virtual bool IsWebGLEnabled() const = 0;
+  virtual bool IsWebGL2Enabled() const = 0;
 
   virtual gpu::GPUInfo GetGPUInfo() const = 0;
 
@@ -56,6 +55,11 @@
   // Check if basic and context GPU info have been collected.
   virtual bool IsEssentialGpuInfoAvailable() const = 0;
 
+  // On Windows, besides basic and context GPU info, it also checks if
+  // DxDiagnostics have been collected.
+  // On other platforms, it's the same as IsEsentialGpuInfoAvailable().
+  virtual bool IsCompleteGpuInfoAvailable() const = 0;
+
   // Requests that the GPU process report its current video memory usage stats.
   virtual void RequestVideoMemoryUsageStatsUpdate(
       const base::Callback<void(const gpu::VideoMemoryUsageStats& stats)>&
diff --git a/content/public/browser/overscroll_configuration.h b/content/public/browser/overscroll_configuration.h
index 369ae7d..d3db2a2 100644
--- a/content/public/browser/overscroll_configuration.h
+++ b/content/public/browser/overscroll_configuration.h
@@ -10,27 +10,20 @@
 namespace content {
 
 // Sets and retrieves various overscroll related configuration values.
-enum OverscrollConfig {
-  OVERSCROLL_CONFIG_NONE,
+enum class OverscrollConfig {
+  // Threshold to complete touchpad overscroll, in terms of the percentage of
+  // the display size.
+  THRESHOLD_COMPLETE_TOUCHPAD,
 
-  // Threshold to complete horizontal overscroll. For touchpad, it represents
-  // the percentage of the display width. For touchscreen, it represents the
-  // percentage of the window width.
-  OVERSCROLL_CONFIG_HORIZ_THRESHOLD_COMPLETE,
+  // Threshold to complete touchscreen overscroll, in terms of the percentage of
+  // the display size.
+  THRESHOLD_COMPLETE_TOUCHSCREEN,
 
-  // Threshold to complete vertical overscroll. For touchpad, it represents the
-  // percentage of the display width. For touchscreen, it represents the
-  // percentage of the window width.
-  OVERSCROLL_CONFIG_VERT_THRESHOLD_COMPLETE,
+  // Threshold to start touchpad overscroll, in DIPs.
+  THRESHOLD_START_TOUCHPAD,
 
-  // Threshold to start horizontal touchpad overscroll, in DIPs.
-  OVERSCROLL_CONFIG_HORIZ_THRESHOLD_START_TOUCHPAD,
-
-  // Threshold to start horizontal touchscreen overscroll, in DIPs.
-  OVERSCROLL_CONFIG_HORIZ_THRESHOLD_START_TOUCHSCREEN,
-
-  // Threshold to start vertical overscroll, in DIPs.
-  OVERSCROLL_CONFIG_VERT_THRESHOLD_START,
+  // Threshold to start touchscreen overscroll, in DIPs.
+  THRESHOLD_START_TOUCHSCREEN,
 };
 
 CONTENT_EXPORT float GetOverscrollConfig(OverscrollConfig config);
diff --git a/content/public/browser/platform_notification_service.h b/content/public/browser/platform_notification_service.h
index a8dcc86..71b8f2d 100644
--- a/content/public/browser/platform_notification_service.h
+++ b/content/public/browser/platform_notification_service.h
@@ -53,16 +53,14 @@
       const GURL& origin,
       int render_process_id) = 0;
 
-  // Displays the notification described in |notification_data| to the user. A
-  // closure through which the notification can be closed will be stored in the
-  // |cancel_callback| argument. This method must be called on the UI thread.
+  // Displays the notification described in |notification_data| to the user.
+  // This method must be called on the UI thread.
   virtual void DisplayNotification(
       BrowserContext* browser_context,
       const std::string& notification_id,
       const GURL& origin,
       const PlatformNotificationData& notification_data,
-      const NotificationResources& notification_resources,
-      base::Closure* cancel_callback) = 0;
+      const NotificationResources& notification_resources) = 0;
 
   // Displays the persistent notification described in |notification_data| to
   // the user. This method must be called on the UI thread.
@@ -74,8 +72,13 @@
       const PlatformNotificationData& notification_data,
       const NotificationResources& notification_resources) = 0;
 
-  // Closes the persistent notification identified by
-  // |persistent_notification_id|. This method must be called on the UI thread.
+  // Closes the notification identified by |notification_id|. This method must
+  // be called on the UI thread.
+  virtual void CloseNotification(BrowserContext* browser_context,
+                                 const std::string& notification_id) = 0;
+
+  // Closes the persistent notification identified by |notification_id|. This
+  // method must be called on the UI thread.
   virtual void ClosePersistentNotification(
       BrowserContext* browser_context,
       const std::string& notification_id) = 0;
diff --git a/content/public/browser/presentation_service_delegate.h b/content/public/browser/presentation_service_delegate.h
index 83f2f8313..7072c26 100644
--- a/content/public/browser/presentation_service_delegate.h
+++ b/content/public/browser/presentation_service_delegate.h
@@ -181,10 +181,10 @@
       const PresentationConnectionStateChangedCallback& state_changed_cb) = 0;
 
   // Connect |controller_connection| owned by the controlling frame to the
-  // offscreen presentation represented by |presentation_info|.
+  // local presentation represented by |presentation_info|.
   // |render_process_id|, |render_frame_id|: ID of originating frame.
   // |controller_connection|: Pointer to controller's presentation connection,
-  // ownership passed from controlling frame to the offscreen presentation.
+  // ownership passed from controlling frame to the local presentation.
   // |receiver_connection_request|: Mojo InterfaceRequest to be bind to receiver
   // page's presentation connection.
   virtual void ConnectToPresentation(
@@ -203,7 +203,7 @@
   // Registers a callback from the embedder when an offscreeen presentation has
   // been successfully started.
   // |receiver_available_callback|: Invoked when successfully starting a
-  // offscreen presentation.
+  // local presentation.
   virtual void RegisterReceiverConnectionAvailableCallback(
       const content::ReceiverConnectionAvailableCallback&
           receiver_available_callback) = 0;
diff --git a/content/public/browser/render_frame_host.h b/content/public/browser/render_frame_host.h
index 644b1dd..711c457 100644
--- a/content/public/browser/render_frame_host.h
+++ b/content/public/browser/render_frame_host.h
@@ -6,6 +6,7 @@
 #define CONTENT_PUBLIC_BROWSER_RENDER_FRAME_HOST_H_
 
 #include <string>
+#include <vector>
 
 #include "base/callback_forward.h"
 #include "build/build_config.h"
@@ -299,6 +300,10 @@
   // process to determine whether access to a feature is allowed.
   virtual bool IsFeatureEnabled(blink::WebFeaturePolicyFeature feature) = 0;
 
+  // Opens view-source tab for the document last committed in this
+  // RenderFrameHost.
+  virtual void ViewSource() = 0;
+
  private:
   // This interface should only be implemented inside content.
   friend class RenderFrameHostImpl;
diff --git a/content/public/browser/web_contents.h b/content/public/browser/web_contents.h
index ff551bf..561f6ae 100644
--- a/content/public/browser/web_contents.h
+++ b/content/public/browser/web_contents.h
@@ -66,7 +66,6 @@
 class BrowserContext;
 class BrowserPluginGuestDelegate;
 class InterstitialPage;
-class PageState;
 class RenderFrameHost;
 class RenderViewHost;
 class RenderWidgetHost;
@@ -643,12 +642,6 @@
   virtual void SetClosedByUserGesture(bool value) = 0;
   virtual bool GetClosedByUserGesture() const = 0;
 
-  // Opens view-source tab for this contents.
-  virtual void ViewSource() = 0;
-
-  virtual void ViewFrameSource(const GURL& url,
-                               const PageState& page_state) = 0;
-
   // Gets the minimum/maximum zoom percent.
   virtual int GetMinimumZoomPercent() const = 0;
   virtual int GetMaximumZoomPercent() const = 0;
diff --git a/content/public/browser/web_contents_delegate.cc b/content/public/browser/web_contents_delegate.cc
index 959fe72..1071aca 100644
--- a/content/public/browser/web_contents_delegate.cc
+++ b/content/public/browser/web_contents_delegate.cc
@@ -4,6 +4,8 @@
 
 #include "content/public/browser/web_contents_delegate.h"
 
+#include <memory>
+
 #include "base/compiler_specific.h"
 #include "base/logging.h"
 #include "base/memory/singleton.h"
@@ -88,29 +90,6 @@
   return false;
 }
 
-void WebContentsDelegate::ViewSourceForTab(WebContents* source,
-                                           const GURL& page_url) {
-  // Fall back implementation based entirely on the view-source scheme.
-  // It suffers from http://crbug.com/523 and that is why browser overrides
-  // it with proper implementation.
-  GURL url = GURL(kViewSourceScheme + std::string(":") + page_url.spec());
-  OpenURLFromTab(
-      source,
-      OpenURLParams(url, Referrer(), WindowOpenDisposition::NEW_FOREGROUND_TAB,
-                    ui::PAGE_TRANSITION_LINK, false));
-}
-
-void WebContentsDelegate::ViewSourceForFrame(WebContents* source,
-                                             const GURL& frame_url,
-                                             const PageState& page_state) {
-  // Same as ViewSourceForTab, but for given subframe.
-  GURL url = GURL(kViewSourceScheme + std::string(":") + frame_url.spec());
-  OpenURLFromTab(
-      source,
-      OpenURLParams(url, Referrer(), WindowOpenDisposition::NEW_FOREGROUND_TAB,
-                    ui::PAGE_TRANSITION_LINK, false));
-}
-
 KeyboardEventProcessingResult WebContentsDelegate::PreHandleKeyboardEvent(
     WebContents* source,
     const NativeWebKeyboardEvent& event) {
@@ -247,7 +226,7 @@
 }
 
 gfx::Size WebContentsDelegate::GetSizeForNewRenderView(
-   WebContents* web_contents) const {
+    WebContents* web_contents) const {
   return gfx::Size();
 }
 
diff --git a/content/public/browser/web_contents_delegate.h b/content/public/browser/web_contents_delegate.h
index d0f141c..a36505c6 100644
--- a/content/public/browser/web_contents_delegate.h
+++ b/content/public/browser/web_contents_delegate.h
@@ -42,7 +42,6 @@
 namespace content {
 class ColorChooser;
 class JavaScriptDialogManager;
-class PageState;
 class RenderFrameHost;
 class RenderWidgetHost;
 class SessionStorageNamespace;
@@ -239,15 +238,6 @@
   // Returns true if the context menu operation was handled by the delegate.
   virtual bool HandleContextMenu(const content::ContextMenuParams& params);
 
-  // Opens source view for given WebContents that is navigated to the given
-  // page url.
-  virtual void ViewSourceForTab(WebContents* source, const GURL& page_url);
-
-  // Opens source view for the given subframe.
-  virtual void ViewSourceForFrame(WebContents* source,
-                                  const GURL& url,
-                                  const PageState& page_state);
-
   // Allows delegates to handle keyboard events before sending to the renderer.
   // See enum for description of return values.
   virtual KeyboardEventProcessingResult PreHandleKeyboardEvent(
diff --git a/content/public/common/common_param_traits_macros.h b/content/public/common/common_param_traits_macros.h
index 90951a5d..1fae466 100644
--- a/content/public/common/common_param_traits_macros.h
+++ b/content/public/common/common_param_traits_macros.h
@@ -18,6 +18,7 @@
 #include "net/base/request_priority.h"
 #include "net/http/http_request_headers.h"
 #include "net/nqe/effective_connection_type.h"
+#include "third_party/WebKit/public/platform/WebHistoryScrollRestorationType.h"
 #include "third_party/WebKit/public/platform/WebPoint.h"
 #include "third_party/WebKit/public/platform/WebRect.h"
 #include "third_party/WebKit/public/platform/WebReferrerPolicy.h"
@@ -53,6 +54,8 @@
                           blink::WebFrameSerializerCacheControlPolicy::kLast)
 IPC_ENUM_TRAITS_MAX_VALUE(blink::WebReferrerPolicy,
                           blink::kWebReferrerPolicyLast)
+IPC_ENUM_TRAITS_MAX_VALUE(blink::WebHistoryScrollRestorationType,
+                          blink::kWebHistoryScrollRestorationManual)
 IPC_ENUM_TRAITS_MAX_VALUE(blink::WebSecurityStyle, blink::kWebSecurityStyleLast)
 IPC_ENUM_TRAITS_MAX_VALUE(blink::mojom::PermissionStatus,
                           blink::mojom::PermissionStatus::LAST)
diff --git a/content/public/common/content_client.cc b/content/public/common/content_client.cc
index 790b4fcdd..765322bf 100644
--- a/content/public/common/content_client.cc
+++ b/content/public/common/content_client.cc
@@ -38,11 +38,6 @@
 
 void SetContentClient(ContentClient* client) {
   g_client = client;
-
-  // TODO(jam): find out which static on Windows is causing this to have to be
-  // called on startup.
-  if (client)
-    client->GetUserAgent();
 }
 
 ContentClient* GetContentClient() {
diff --git a/content/public/common/context_menu_params.h b/content/public/common/context_menu_params.h
index 0abff18..3b853985 100644
--- a/content/public/common/context_menu_params.h
+++ b/content/public/common/context_menu_params.h
@@ -15,7 +15,6 @@
 #include "build/build_config.h"
 #include "content/common/content_export.h"
 #include "content/public/common/menu_item.h"
-#include "content/public/common/page_state.h"
 #include "third_party/WebKit/public/platform/WebReferrerPolicy.h"
 #include "third_party/WebKit/public/web/WebContextMenuData.h"
 #include "ui/base/ui_base_types.h"
@@ -94,9 +93,6 @@
   // This is the URL of the subframe that the context menu was invoked on.
   GURL frame_url;
 
-  // This is the page state of the frame on which the context menu was invoked.
-  PageState frame_page_state;
-
   // These are the parameters for the media element that the context menu
   // was invoked on.
   int media_flags;
diff --git a/content/public/common/referrer_struct_traits.cc b/content/public/common/referrer_struct_traits.cc
index 6fc851b..33dafc0 100644
--- a/content/public/common/referrer_struct_traits.cc
+++ b/content/public/common/referrer_struct_traits.cc
@@ -4,7 +4,6 @@
 
 #include "content/public/common/referrer_struct_traits.h"
 
-#include "third_party/WebKit/public/platform/ReferrerPolicyEnumTraits.h"
 #include "url/mojo/url_gurl_struct_traits.h"
 
 namespace mojo {
diff --git a/content/public/common/referrer_struct_traits.h b/content/public/common/referrer_struct_traits.h
index f7a7b02..142aaee 100644
--- a/content/public/common/referrer_struct_traits.h
+++ b/content/public/common/referrer_struct_traits.h
@@ -7,6 +7,7 @@
 
 #include "content/common/content_export.h"
 #include "content/public/common/referrer.h"
+#include "third_party/WebKit/public/platform/ReferrerPolicyEnumTraits.h"
 #include "third_party/WebKit/public/platform/referrer.mojom.h"
 
 namespace mojo {
diff --git a/content/public/test/browser_test_utils.cc b/content/public/test/browser_test_utils.cc
index 63127b3..08d9922 100644
--- a/content/public/test/browser_test_utils.cc
+++ b/content/public/test/browser_test_utils.cc
@@ -2305,4 +2305,9 @@
   message_loop_runner_->Quit();
 }
 
+WebContents* GetEmbedderForGuest(content::WebContents* guest) {
+  CHECK(guest);
+  return static_cast<content::WebContentsImpl*>(guest)->GetOuterWebContents();
+}
+
 }  // namespace content
diff --git a/content/public/test/browser_test_utils.h b/content/public/test/browser_test_utils.h
index a02a1ab..7fc6f245 100644
--- a/content/public/test/browser_test_utils.h
+++ b/content/public/test/browser_test_utils.h
@@ -994,6 +994,8 @@
   DISALLOW_COPY_AND_ASSIGN(ContextMenuFilter);
 };
 
+WebContents* GetEmbedderForGuest(content::WebContents* guest);
+
 }  // namespace content
 
 #endif  // CONTENT_PUBLIC_TEST_BROWSER_TEST_UTILS_H_
diff --git a/content/public/test/mock_render_thread.cc b/content/public/test/mock_render_thread.cc
index 6eab25c88..6d7cfd07 100644
--- a/content/public/test/mock_render_thread.cc
+++ b/content/public/test/mock_render_thread.cc
@@ -66,6 +66,14 @@
   MockRenderThread* const thread_;
 };
 
+// Returns an InterfaceProvider that is safe to call into, but will not actually
+// service any interface requests.
+service_manager::mojom::InterfaceProviderPtr CreateStubInterfaceProvider() {
+  ::service_manager::mojom::InterfaceProviderPtr stub_interface_provider_proxy;
+  mojo::MakeRequest(&stub_interface_provider_proxy);
+  return stub_interface_provider_proxy;
+}
+
 }  // namespace
 
 MockRenderThread::MockRenderThread()
@@ -269,8 +277,11 @@
 void MockRenderThread::OnCreateChildFrame(
     const FrameHostMsg_CreateChildFrame_Params& params,
     int* new_render_frame_id,
+    mojo::MessagePipeHandle* new_interface_provider,
     base::UnguessableToken* devtools_frame_token) {
   *new_render_frame_id = new_frame_routing_id_++;
+  *new_interface_provider =
+      CreateStubInterfaceProvider().PassInterface().PassHandle().release();
   *devtools_frame_token = base::UnguessableToken::Create();
 }
 
@@ -310,6 +321,7 @@
     mojom::CreateNewWindowReply* reply) {
   reply->route_id = new_window_routing_id_;
   reply->main_frame_route_id = new_window_main_frame_routing_id_;
+  reply->main_frame_interface_provider = CreateStubInterfaceProvider();
   reply->main_frame_widget_route_id = new_window_main_frame_widget_routing_id_;
   reply->cloned_session_storage_namespace_id = 0;
 }
diff --git a/content/public/test/mock_render_thread.h b/content/public/test/mock_render_thread.h
index 075e89e..2a5fdf1 100644
--- a/content/public/test/mock_render_thread.h
+++ b/content/public/test/mock_render_thread.h
@@ -136,6 +136,7 @@
   // The Frame expects to be returned a valid route_id different from its own.
   void OnCreateChildFrame(const FrameHostMsg_CreateChildFrame_Params& params,
                           int* new_render_frame_id,
+                          mojo::MessagePipeHandle* new_interface_provider,
                           base::UnguessableToken* devtools_frame_token);
 
 #if defined(OS_WIN)
diff --git a/content/public/test/navigation_simulator.cc b/content/public/test/navigation_simulator.cc
index 15029b26f..b3d6aad 100644
--- a/content/public/test/navigation_simulator.cc
+++ b/content/public/test/navigation_simulator.cc
@@ -422,6 +422,7 @@
   params.nav_entry_id = handle_->pending_nav_entry_id();
   params.url = navigation_url_;
   params.origin = url::Origin::Create(navigation_url_);
+  params.referrer = referrer_;
   params.transition = transition_;
   params.should_update_history = true;
   params.did_create_new_entry =
@@ -548,6 +549,7 @@
                                     ui::PAGE_TRANSITION_AUTO_SUBFRAME) &&
       reload_type_ == ReloadType::NONE;
   params.url = navigation_url_;
+  params.referrer = referrer_;
   params.transition = transition_;
   params.was_within_same_document = false;
   params.url_is_unreachable = true;
@@ -592,6 +594,7 @@
   params.nav_entry_id = 0;
   params.url = navigation_url_;
   params.origin = url::Origin::Create(navigation_url_);
+  params.referrer = referrer_;
   params.transition = transition_;
   params.should_update_history = true;
   params.did_create_new_entry = false;
diff --git a/content/public/test/render_view_test.cc b/content/public/test/render_view_test.cc
index 76fa56d..0909ca9 100644
--- a/content/public/test/render_view_test.cc
+++ b/content/public/test/render_view_test.cc
@@ -111,6 +111,14 @@
   }
 }
 
+// Returns an InterfaceProvider that is safe to call into, but will not actually
+// service any interface requests.
+service_manager::mojom::InterfaceProviderPtr CreateStubInterfaceProvider() {
+  ::service_manager::mojom::InterfaceProviderPtr stub_interface_provider_proxy;
+  mojo::MakeRequest(&stub_interface_provider_proxy);
+  return stub_interface_provider_proxy;
+}
+
 }  // namespace
 
 namespace content {
@@ -299,28 +307,30 @@
   compositor_deps_.reset(new FakeCompositorDependencies);
   mock_process_.reset(new MockRenderProcess);
 
-  mojom::CreateViewParams view_params;
-  view_params.opener_frame_route_id = MSG_ROUTING_NONE;
-  view_params.window_was_created_with_opener = false;
-  view_params.renderer_preferences = RendererPreferences();
-  view_params.web_preferences = WebPreferences();
-  view_params.view_id = kRouteId;
-  view_params.main_frame_routing_id = kMainFrameRouteId;
-  view_params.main_frame_widget_routing_id = kMainFrameWidgetRouteId;
-  view_params.session_storage_namespace_id = kInvalidSessionStorageNamespaceId;
-  view_params.swapped_out = false;
-  view_params.replicated_frame_state = FrameReplicationState();
-  view_params.proxy_routing_id = MSG_ROUTING_NONE;
-  view_params.hidden = false;
-  view_params.never_visible = false;
-  view_params.initial_size = *InitialSizeParams();
-  view_params.enable_auto_resize = false;
-  view_params.min_size = gfx::Size();
-  view_params.max_size = gfx::Size();
+  mojom::CreateViewParamsPtr view_params = mojom::CreateViewParams::New();
+  view_params->opener_frame_route_id = MSG_ROUTING_NONE;
+  view_params->window_was_created_with_opener = false;
+  view_params->renderer_preferences = RendererPreferences();
+  view_params->web_preferences = WebPreferences();
+  view_params->view_id = kRouteId;
+  view_params->main_frame_routing_id = kMainFrameRouteId;
+  view_params->main_frame_interface_provider = CreateStubInterfaceProvider();
+  view_params->main_frame_widget_routing_id = kMainFrameWidgetRouteId;
+  view_params->session_storage_namespace_id = kInvalidSessionStorageNamespaceId;
+  view_params->swapped_out = false;
+  view_params->replicated_frame_state = FrameReplicationState();
+  view_params->proxy_routing_id = MSG_ROUTING_NONE;
+  view_params->hidden = false;
+  view_params->never_visible = false;
+  view_params->initial_size = *InitialSizeParams();
+  view_params->enable_auto_resize = false;
+  view_params->min_size = gfx::Size();
+  view_params->max_size = gfx::Size();
 
   // This needs to pass the mock render thread to the view.
-  RenderViewImpl* view = RenderViewImpl::Create(
-      compositor_deps_.get(), view_params, RenderWidget::ShowCallback());
+  RenderViewImpl* view =
+      RenderViewImpl::Create(compositor_deps_.get(), std::move(view_params),
+                             RenderWidget::ShowCallback());
   view_ = view;
 }
 
diff --git a/content/public/test/test_browser_thread_bundle.cc b/content/public/test/test_browser_thread_bundle.cc
index b981f6f..d39888c 100644
--- a/content/public/test/test_browser_thread_bundle.cc
+++ b/content/public/test/test_browser_thread_bundle.cc
@@ -95,7 +95,7 @@
   // this thread as we don't call Start() for the UI TestBrowserThread; it's
   // already started!
   com_initializer_ = std::make_unique<base::win::ScopedCOMInitializer>();
-  CHECK(com_initializer_->succeeded());
+  CHECK(com_initializer_->Succeeded());
 #endif
 
   // Create the ScopedTaskEnvironment if it doesn't already exist. A
diff --git a/content/public/test/web_contents_tester.h b/content/public/test/web_contents_tester.h
index 4bf8f8c..2247509 100644
--- a/content/public/test/web_contents_tester.h
+++ b/content/public/test/web_contents_tester.h
@@ -29,7 +29,6 @@
 class NavigationHandle;
 class RenderFrameHost;
 class WebContents;
-struct Referrer;
 
 // This interface allows embedders of content/ to write tests that depend on a
 // test version of WebContents.  This interface can be retrieved from any
@@ -80,11 +79,6 @@
   // Sets the loading state to the given value.
   virtual void TestSetIsLoading(bool value) = 0;
 
-  // Simulates the current RVH notifying that it has unloaded so that the
-  // pending RVH navigation can proceed.
-  // Does nothing if no cross-navigation is pending.
-  virtual void ProceedWithCrossSiteNavigation() = 0;
-
   // Simulates a navigation with the given information.
   //
   // Guidance for calling these:
@@ -99,12 +93,6 @@
                                bool did_create_new_entry,
                                const GURL& url,
                                ui::PageTransition transition) = 0;
-  virtual void TestDidNavigateWithReferrer(RenderFrameHost* render_frame_host,
-                                           int nav_entry_id,
-                                           bool did_create_new_entry,
-                                           const GURL& url,
-                                           const Referrer& referrer,
-                                           ui::PageTransition transition) = 0;
 
   // Sets NavgationData on |navigation_handle|.
   virtual void SetNavigationData(
diff --git a/content/renderer/accessibility/blink_ax_tree_source.cc b/content/renderer/accessibility/blink_ax_tree_source.cc
index 7eb04af..2f4de50 100644
--- a/content/renderer/accessibility/blink_ax_tree_source.cc
+++ b/content/renderer/accessibility/blink_ax_tree_source.cc
@@ -905,15 +905,15 @@
   // parent is the row, the row adds it as a child, and the column adds it
   // as an indirect child.
   int child_count = src.ChildCount();
+  std::vector<int32_t> indirect_child_ids;
   for (int i = 0; i < child_count; ++i) {
     WebAXObject child = src.ChildAt(i);
-    std::vector<int32_t> indirect_child_ids;
     if (!is_iframe && !child.IsDetached() && !IsParentUnignoredOf(src, child))
       indirect_child_ids.push_back(child.AxID());
-    if (indirect_child_ids.size() > 0) {
-      dst->AddIntListAttribute(
-          ui::AX_ATTR_INDIRECT_CHILD_IDS, indirect_child_ids);
-    }
+  }
+  if (indirect_child_ids.size() > 0) {
+    dst->AddIntListAttribute(ui::AX_ATTR_INDIRECT_CHILD_IDS,
+                             indirect_child_ids);
   }
 
   if (src.IsScrollableContainer()) {
diff --git a/content/renderer/context_menu_params_builder.cc b/content/renderer/context_menu_params_builder.cc
index 61eb893..844e25a 100644
--- a/content/renderer/context_menu_params_builder.cc
+++ b/content/renderer/context_menu_params_builder.cc
@@ -55,11 +55,6 @@
   for (size_t i = 0; i < data.custom_items.size(); ++i)
     params.custom_items.push_back(MenuItemBuilder::Build(data.custom_items[i]));
 
-  if (!data.frame_history_item.IsNull()) {
-    params.frame_page_state =
-        SingleHistoryItemToPageState(data.frame_history_item);
-  }
-
   params.link_text = data.link_text.Utf16();
   params.source_type = static_cast<ui::MenuSourceType>(data.source_type);
 
diff --git a/content/renderer/gpu/compositor_dependencies.h b/content/renderer/gpu/compositor_dependencies.h
index 712e2cb..91f629e 100644
--- a/content/renderer/gpu/compositor_dependencies.h
+++ b/content/renderer/gpu/compositor_dependencies.h
@@ -17,6 +17,7 @@
 
 namespace cc {
 class TaskGraphRunner;
+class UkmRecorderFactory;
 }
 
 namespace blink {
@@ -50,6 +51,8 @@
   virtual cc::TaskGraphRunner* GetTaskGraphRunner() = 0;
   virtual bool IsThreadedAnimationEnabled() = 0;
   virtual bool IsScrollAnimatorEnabled() = 0;
+  virtual std::unique_ptr<cc::UkmRecorderFactory>
+  CreateUkmRecorderFactory() = 0;
 
   virtual ~CompositorDependencies() {}
 };
diff --git a/content/renderer/gpu/render_widget_compositor.cc b/content/renderer/gpu/render_widget_compositor.cc
index e376ae8d..0642ab0 100644
--- a/content/renderer/gpu/render_widget_compositor.cc
+++ b/content/renderer/gpu/render_widget_compositor.cc
@@ -43,6 +43,7 @@
 #include "cc/trees/layer_tree_host.h"
 #include "cc/trees/layer_tree_mutator.h"
 #include "cc/trees/swap_promise.h"
+#include "cc/trees/ukm_manager.h"
 #include "components/viz/common/frame_sinks/begin_frame_args.h"
 #include "components/viz/common/frame_sinks/begin_frame_source.h"
 #include "components/viz/common/frame_sinks/copy_output_request.h"
@@ -320,6 +321,7 @@
   params.task_graph_runner = deps->GetTaskGraphRunner();
   params.main_task_runner = deps->GetCompositorMainThreadTaskRunner();
   params.mutator_host = mutator_host;
+  params.ukm_recorder_factory = deps->CreateUkmRecorderFactory();
   if (base::TaskScheduler::GetInstance()) {
     // The image worker thread needs to allow waiting since it makes discardable
     // shared memory allocations which need to make synchronous calls to the
@@ -1312,4 +1314,8 @@
   layer_tree_host_->RequestBeginMainFrameNotExpected(new_state);
 }
 
+void RenderWidgetCompositor::SetURLForUkm(const GURL& url) {
+  layer_tree_host_->SetURLForUkm(url);
+}
+
 }  // namespace content
diff --git a/content/renderer/gpu/render_widget_compositor.h b/content/renderer/gpu/render_widget_compositor.h
index 375541d..f15dc000 100644
--- a/content/renderer/gpu/render_widget_compositor.h
+++ b/content/renderer/gpu/render_widget_compositor.h
@@ -20,6 +20,7 @@
 #include "cc/trees/swap_promise_monitor.h"
 #include "content/common/content_export.h"
 #include "content/renderer/gpu/compositor_dependencies.h"
+#include "services/metrics/public/cpp/ukm_recorder.h"
 #include "third_party/WebKit/public/platform/WebLayerTreeView.h"
 #include "ui/gfx/geometry/rect.h"
 
@@ -124,6 +125,7 @@
   void SetContentSourceId(uint32_t source_id);
   void SetViewportSize(const gfx::Size& device_viewport_size,
                        const viz::LocalSurfaceId& local_surface_id);
+  void SetURLForUkm(const GURL& url);
 
   // WebLayerTreeView implementation.
   viz::FrameSinkId GetFrameSinkId() override;
diff --git a/content/renderer/render_frame_impl.cc b/content/renderer/render_frame_impl.cc
index 01f954ee..0c5e05c 100644
--- a/content/renderer/render_frame_impl.cc
+++ b/content/renderer/render_frame_impl.cc
@@ -103,6 +103,7 @@
 #include "content/renderer/external_popup_menu.h"
 #include "content/renderer/frame_owner_properties.h"
 #include "content/renderer/gpu/gpu_benchmarking_extension.h"
+#include "content/renderer/gpu/render_widget_compositor.h"
 #include "content/renderer/history_entry.h"
 #include "content/renderer/history_serialization.h"
 #include "content/renderer/image_downloader/image_downloader_impl.h"
@@ -169,6 +170,7 @@
 #include "ppapi/features/features.h"
 #include "services/service_manager/public/cpp/connector.h"
 #include "services/service_manager/public/cpp/interface_provider.h"
+#include "services/service_manager/public/interfaces/interface_provider.mojom.h"
 #include "services/ui/public/cpp/gpu/context_provider_command_buffer.h"
 #include "storage/common/data_element.h"
 #include "third_party/WebKit/public/platform/FilePathConversion.h"
@@ -741,9 +743,14 @@
     DCHECK(frame_);
     frame_->UpdatePeakMemoryStats();
 
-    mojom::URLLoaderFactory* factory =
-        frame_->GetDefaultURLLoaderFactoryGetter()->GetFactoryForURL(
-            request.Url(), frame_->custom_url_loader_factory());
+    mojom::URLLoaderFactory* factory;
+    if (base::FeatureList::IsEnabled(features::kNetworkService)) {
+      factory = frame_->GetSubresourceLoaderFactories().GetFactoryForRequest(
+          request.Url());
+    } else {
+      factory = frame_->GetDefaultURLLoaderFactoryGetter()->GetFactoryForURL(
+          request.Url(), frame_->custom_url_loader_factory());
+    }
     DCHECK(factory);
 
     mojom::KeepAliveHandlePtr keep_alive_handle;
@@ -1007,14 +1014,16 @@
 RenderFrameImpl* RenderFrameImpl::Create(
     RenderViewImpl* render_view,
     int32_t routing_id,
+    service_manager::mojom::InterfaceProviderPtr interface_provider,
     const base::UnguessableToken& devtools_frame_token) {
   DCHECK(routing_id != MSG_ROUTING_NONE);
-  CreateParams params(render_view, routing_id, devtools_frame_token);
+  CreateParams params(render_view, routing_id, std::move(interface_provider),
+                      devtools_frame_token);
 
   if (g_create_render_frame_impl)
-    return g_create_render_frame_impl(params);
+    return g_create_render_frame_impl(std::move(params));
   else
-    return new RenderFrameImpl(params);
+    return new RenderFrameImpl(std::move(params));
 }
 
 // static
@@ -1035,6 +1044,7 @@
 RenderFrameImpl* RenderFrameImpl::CreateMainFrame(
     RenderViewImpl* render_view,
     int32_t routing_id,
+    service_manager::mojom::InterfaceProviderPtr interface_provider,
     int32_t widget_routing_id,
     bool hidden,
     const ScreenInfo& screen_info,
@@ -1045,8 +1055,9 @@
   // A main frame RenderFrame must have a RenderWidget.
   DCHECK_NE(MSG_ROUTING_NONE, widget_routing_id);
 
-  RenderFrameImpl* render_frame =
-      RenderFrameImpl::Create(render_view, routing_id, devtools_frame_token);
+  RenderFrameImpl* render_frame = RenderFrameImpl::Create(
+      render_view, routing_id, std::move(interface_provider),
+      devtools_frame_token);
   render_frame->InitializeBlameContext(nullptr);
   WebLocalFrame* web_frame = WebLocalFrame::CreateMainFrame(
       render_view->webview(), render_frame,
@@ -1068,6 +1079,7 @@
 // static
 void RenderFrameImpl::CreateFrame(
     int routing_id,
+    service_manager::mojom::InterfaceProviderPtr interface_provider,
     int proxy_routing_id,
     int opener_routing_id,
     int parent_routing_id,
@@ -1101,8 +1113,9 @@
       previous_sibling_web_frame = previous_sibling_proxy->web_frame();
 
     // Create the RenderFrame and WebLocalFrame, linking the two.
-    render_frame = RenderFrameImpl::Create(parent_proxy->render_view(),
-                                           routing_id, devtools_frame_token);
+    render_frame = RenderFrameImpl::Create(
+        parent_proxy->render_view(), routing_id, std::move(interface_provider),
+        devtools_frame_token);
     render_frame->InitializeBlameContext(FromRoutingID(parent_routing_id));
     render_frame->unique_name_helper_.set_propagated_name(
         replicated_state.unique_name);
@@ -1131,6 +1144,7 @@
       return;
 
     render_frame = RenderFrameImpl::Create(proxy->render_view(), routing_id,
+                                           std::move(interface_provider),
                                            devtools_frame_token);
     render_frame->InitializeBlameContext(nullptr);
     render_frame->proxy_routing_id_ = proxy_routing_id;
@@ -1222,8 +1236,24 @@
   return GetContentClient()->renderer()->OverrideFlashEmbedWithHTML(url);
 }
 
+// RenderFrameImpl::CreateParams --------------------------------------------
+
+RenderFrameImpl::CreateParams::CreateParams(
+    RenderViewImpl* render_view,
+    int32_t routing_id,
+    service_manager::mojom::InterfaceProviderPtr interface_provider,
+    const base::UnguessableToken& devtools_frame_token)
+    : render_view(render_view),
+      routing_id(routing_id),
+      interface_provider(std::move(interface_provider)),
+      devtools_frame_token(devtools_frame_token) {}
+RenderFrameImpl::CreateParams::~CreateParams() = default;
+RenderFrameImpl::CreateParams::CreateParams(CreateParams&&) = default;
+RenderFrameImpl::CreateParams& RenderFrameImpl::CreateParams::operator=(
+    CreateParams&&) = default;
+
 // RenderFrameImpl ----------------------------------------------------------
-RenderFrameImpl::RenderFrameImpl(const CreateParams& params)
+RenderFrameImpl::RenderFrameImpl(CreateParams params)
     : frame_(NULL),
       is_main_frame_(true),
       unique_name_frame_adapter_(this),
@@ -1271,10 +1301,10 @@
       devtools_frame_token_(
           blink::WebString::FromUTF8(params.devtools_frame_token.ToString())),
       weak_factory_(this) {
-  service_manager::mojom::InterfaceProviderPtr remote_interfaces;
-  pending_remote_interface_provider_request_ = MakeRequest(&remote_interfaces);
-  remote_interfaces_.reset(new service_manager::InterfaceProvider);
-  remote_interfaces_->Bind(std::move(remote_interfaces));
+  // The InterfaceProvider to access Mojo services exposed by the RFHI must be
+  // provided at construction time. See: https://crbug.com/729021/.
+  CHECK(params.interface_provider.is_bound());
+  remote_interfaces_.Bind(std::move(params.interface_provider));
   blink_interface_registry_.reset(
       new BlinkInterfaceRegistryImpl(registry_.GetWeakPtr()));
 
@@ -1791,7 +1821,8 @@
   TRACE_EVENT2("navigation,rail", "RenderFrameImpl::OnNavigate", "id",
                routing_id_, "url", common_params.url.possibly_invalid_spec());
   NavigateInternal(common_params, start_params, request_params,
-                   std::unique_ptr<StreamOverrideParameters>());
+                   std::unique_ptr<StreamOverrideParameters>(),
+                   /*subresource_loader_factories=*/base::nullopt);
 }
 
 void RenderFrameImpl::BindEngagement(
@@ -1806,13 +1837,9 @@
 
 void RenderFrameImpl::BindFrame(
     const service_manager::BindSourceInfo& browser_info,
-    mojom::FrameRequest request,
-    mojom::FrameHostInterfaceBrokerPtr frame_host_interface_broker) {
+    mojom::FrameRequest request) {
   browser_info_ = browser_info;
   frame_binding_.Bind(std::move(request));
-  frame_host_interface_broker_ = std::move(frame_host_interface_broker);
-  frame_host_interface_broker_->GetInterfaceProvider(
-      std::move(pending_remote_interface_provider_request_));
 }
 
 void RenderFrameImpl::BindFrameBindingsControl(
@@ -2774,7 +2801,7 @@
 }
 
 service_manager::InterfaceProvider* RenderFrameImpl::GetRemoteInterfaces() {
-  return remote_interfaces_.get();
+  return &remote_interfaces_;
 }
 
 AssociatedInterfaceRegistry*
@@ -2874,8 +2901,7 @@
                              mojo::edk::js::Support::GetModule(isolate));
   registry->AddBuiltinModule(
       isolate, InterfaceProviderJsWrapper::kPerFrameModuleName,
-      InterfaceProviderJsWrapper::Create(
-          isolate, context, remote_interfaces_.get())
+      InterfaceProviderJsWrapper::Create(isolate, context, &remote_interfaces_)
           .ToV8());
   registry->AddBuiltinModule(
       isolate, InterfaceProviderJsWrapper::kPerProcessModuleName,
@@ -2991,7 +3017,7 @@
     const CommonNavigationParams& common_params,
     const RequestNavigationParams& request_params,
     mojo::ScopedDataPipeConsumerHandle body_data,
-    mojom::URLLoaderFactoryPtr default_subresource_url_loader_factory) {
+    base::Optional<URLLoaderFactoryBundle> subresource_loader_factories) {
   CHECK(IsBrowserSideNavigationEnabled());
   // If this was a renderer-initiated navigation (nav_entry_id == 0) from this
   // frame, but it was aborted, then ignore it.
@@ -3026,8 +3052,6 @@
       },
       weak_factory_.GetWeakPtr());
 
-  SetCustomURLLoaderFactory(std::move(default_subresource_url_loader_factory));
-
   // If the request was initiated in the context of a user gesture then make
   // sure that the navigation also executes in the context of a user gesture.
   std::unique_ptr<blink::WebScopedUserGesture> gesture(
@@ -3038,7 +3062,8 @@
   browser_side_navigation_pending_url_ = GURL();
 
   NavigateInternal(common_params, StartNavigationParams(), request_params,
-                   std::move(stream_override));
+                   std::move(stream_override),
+                   std::move(subresource_loader_factories));
 
   // Don't add code after this since NavigateInternal may have destroyed this
   // RenderFrameImpl.
@@ -3240,8 +3265,7 @@
 }
 
 service_manager::InterfaceProvider* RenderFrameImpl::GetInterfaceProvider() {
-  DCHECK(remote_interfaces_);
-  return remote_interfaces_.get();
+  return &remote_interfaces_;
 }
 
 void RenderFrameImpl::DidAccessInitialDocument() {
@@ -3279,6 +3303,7 @@
   // Synchronously notify the browser of a child frame creation to get the
   // routing_id for the RenderFrame.
   int child_routing_id = MSG_ROUTING_NONE;
+  mojo::MessagePipeHandle child_interface_provider_handle;
   base::UnguessableToken devtools_frame_token;
   FrameHostMsg_CreateChildFrame_Params params;
   params.parent_routing_id = routing_id_;
@@ -3306,6 +3331,7 @@
       ConvertWebFrameOwnerPropertiesToFrameOwnerProperties(
           frame_owner_properties);
   Send(new FrameHostMsg_CreateChildFrame(params, &child_routing_id,
+                                         &child_interface_provider_handle,
                                          &devtools_frame_token));
 
   // Allocation of routing id failed, so we can't create a child frame. This can
@@ -3315,6 +3341,12 @@
   if (child_routing_id == MSG_ROUTING_NONE)
     return nullptr;
 
+  CHECK(child_interface_provider_handle.is_valid());
+  service_manager::mojom::InterfaceProviderPtr child_interface_provider;
+  child_interface_provider.Bind(
+      service_manager::mojom::InterfaceProviderPtrInfo(
+          mojo::ScopedMessagePipeHandle(child_interface_provider_handle), 0u));
+
   // This method is always called by local frames, never remote frames.
 
   // Tracing analysis uses this to find main frames when this value is
@@ -3325,7 +3357,8 @@
 
   // Create the RenderFrame and WebLocalFrame, linking the two.
   RenderFrameImpl* child_render_frame = RenderFrameImpl::Create(
-      render_view_, child_routing_id, devtools_frame_token);
+      render_view_, child_routing_id, std::move(child_interface_provider),
+      devtools_frame_token);
   child_render_frame->unique_name_helper_.set_propagated_name(
       params.frame_unique_name);
   child_render_frame->InitializeBlameContext(this);
@@ -3862,9 +3895,18 @@
   // Navigations that change the document represent a new content source.  Keep
   // track of that on the widget to help the browser process detect when stale
   // compositor frames are being shown after a commit.
-  if (is_main_frame_ && !navigation_state->WasWithinSameDocument())
+  if (is_main_frame_ && !navigation_state->WasWithinSameDocument()) {
     GetRenderWidget()->IncrementContentSourceId();
 
+    // Update the URL used to key Ukm metrics in the compositor if the
+    // navigation is not in the same document, which represents a new source
+    // URL.
+    // Note that this is only done for the main frame since the metrics for all
+    // frames are keyed to the main frame's URL.
+    if (GetRenderWidget()->compositor())
+      GetRenderWidget()->compositor()->SetURLForUkm(GetLoadingUrl());
+  }
+
   // When we perform a new navigation, we need to update the last committed
   // session history entry with state for the page we are leaving. Do this
   // before updating the current history item.
@@ -6132,7 +6174,8 @@
     const CommonNavigationParams& common_params,
     const StartNavigationParams& start_params,
     const RequestNavigationParams& request_params,
-    std::unique_ptr<StreamOverrideParameters> stream_params) {
+    std::unique_ptr<StreamOverrideParameters> stream_params,
+    base::Optional<URLLoaderFactoryBundle> subresource_loader_factories) {
   bool browser_side_navigation = IsBrowserSideNavigationEnabled();
 
   // PlzNavigate
@@ -6196,6 +6239,15 @@
       IsBrowserSideNavigationEnabled() &&
       FrameMsg_Navigate_Type::IsSameDocument(common_params.navigation_type);
 
+  // The browser only provides new subresource loader factories on
+  // cross-document navigations. In other cases we are free to keep reusing the
+  // ones we have.
+  if (!is_same_document &&
+      base::FeatureList::IsEnabled(features::kNetworkService)) {
+    DCHECK(subresource_loader_factories);
+    subresource_loader_factories_ = std::move(subresource_loader_factories);
+  }
+
   WebURLRequest request = CreateURLRequestForNavigation(
       common_params, request_params, std::move(stream_params),
       frame_->IsViewSourceModeEnabled(), is_same_document);
@@ -6402,6 +6454,18 @@
   }
 }
 
+URLLoaderFactoryBundle& RenderFrameImpl::GetSubresourceLoaderFactories() {
+  DCHECK(base::FeatureList::IsEnabled(features::kNetworkService));
+  if (!subresource_loader_factories_) {
+    RenderFrameImpl* creator = RenderFrameImpl::FromWebFrame(
+        frame_->Parent() ? frame_->Parent() : frame_->Opener());
+    DCHECK(creator);
+    subresource_loader_factories_ =
+        creator->GetSubresourceLoaderFactories().Clone();
+  }
+  return *subresource_loader_factories_;
+}
+
 void RenderFrameImpl::UpdateEncoding(WebFrame* frame,
                                      const std::string& encoding_name) {
   // Only update main frame's encoding_name.
@@ -6470,7 +6534,14 @@
 
 void RenderFrameImpl::SetCustomURLLoaderFactory(
     mojom::URLLoaderFactoryPtr factory) {
-  custom_url_loader_factory_ = std::move(factory);
+  if (base::FeatureList::IsEnabled(features::kNetworkService)) {
+    // When the network service is enabled, all subresource loads go through
+    // a factory from |subresource_loader_factories|. In this case we simply
+    // replace the existing default factory within the bundle.
+    GetSubresourceLoaderFactories().SetDefaultFactory(std::move(factory));
+  } else {
+    custom_url_loader_factory_ = std::move(factory);
+  }
 }
 
 void RenderFrameImpl::InitializeUserMediaClient() {
diff --git a/content/renderer/render_frame_impl.h b/content/renderer/render_frame_impl.h
index 63f16eea..640d8026 100644
--- a/content/renderer/render_frame_impl.h
+++ b/content/renderer/render_frame_impl.h
@@ -12,6 +12,7 @@
 #include <memory>
 #include <set>
 #include <string>
+#include <utility>
 #include <vector>
 
 #include "base/callback.h"
@@ -37,6 +38,7 @@
 #include "content/common/possibly_associated_interface_ptr.h"
 #include "content/common/renderer.mojom.h"
 #include "content/common/unique_name_helper.h"
+#include "content/common/url_loader_factory_bundle.h"
 #include "content/common/widget.mojom.h"
 #include "content/public/common/console_message_level.h"
 #include "content/public/common/javascript_dialog_type.h"
@@ -61,6 +63,7 @@
 #include "ppapi/features/features.h"
 #include "services/service_manager/public/cpp/bind_source_info.h"
 #include "services/service_manager/public/cpp/binder_registry.h"
+#include "services/service_manager/public/cpp/interface_provider.h"
 #include "services/service_manager/public/interfaces/connector.mojom.h"
 #include "services/service_manager/public/interfaces/interface_provider.mojom.h"
 #include "third_party/WebKit/public/platform/WebEffectiveConnectionType.h"
@@ -189,6 +192,7 @@
   static RenderFrameImpl* CreateMainFrame(
       RenderViewImpl* render_view,
       int32_t routing_id,
+      service_manager::mojom::InterfaceProviderPtr interface_provider,
       int32_t widget_routing_id,
       bool hidden,
       const ScreenInfo& screen_info,
@@ -216,16 +220,18 @@
   // Note: This is called only when RenderFrame is being created in response
   // to IPC message from the browser process. All other frame creation is driven
   // through Blink and Create.
-  static void CreateFrame(int routing_id,
-                          int proxy_routing_id,
-                          int opener_routing_id,
-                          int parent_routing_id,
-                          int previous_sibling_routing_id,
-                          const base::UnguessableToken& devtools_frame_token,
-                          const FrameReplicationState& replicated_state,
-                          CompositorDependencies* compositor_deps,
-                          const mojom::CreateFrameWidgetParams& params,
-                          const FrameOwnerProperties& frame_owner_properties);
+  static void CreateFrame(
+      int routing_id,
+      service_manager::mojom::InterfaceProviderPtr interface_provider,
+      int proxy_routing_id,
+      int opener_routing_id,
+      int parent_routing_id,
+      int previous_sibling_routing_id,
+      const base::UnguessableToken& devtools_frame_token,
+      const FrameReplicationState& replicated_state,
+      CompositorDependencies* compositor_deps,
+      const mojom::CreateFrameWidgetParams& params,
+      const FrameOwnerProperties& frame_owner_properties);
 
   // Returns the RenderFrameImpl for the given routing ID.
   static RenderFrameImpl* FromRoutingID(int routing_id);
@@ -235,22 +241,24 @@
 
   // Used by content_layouttest_support to hook into the creation of
   // RenderFrameImpls.
-  struct CreateParams {
-    CreateParams(RenderViewImpl* render_view,
-                 int32_t routing_id,
-                 const base::UnguessableToken& devtools_frame_token)
-        : render_view(render_view),
-          routing_id(routing_id),
-          devtools_frame_token(devtools_frame_token) {}
-    ~CreateParams() {}
+  struct CONTENT_EXPORT CreateParams {
+    CreateParams(
+        RenderViewImpl* render_view,
+        int32_t routing_id,
+        service_manager::mojom::InterfaceProviderPtr interface_provider,
+        const base::UnguessableToken& devtools_frame_token);
+    ~CreateParams();
+
+    CreateParams(CreateParams&&);
+    CreateParams& operator=(CreateParams&&);
 
     RenderViewImpl* render_view;
     int32_t routing_id;
+    service_manager::mojom::InterfaceProviderPtr interface_provider;
     base::UnguessableToken devtools_frame_token;
   };
 
-  using CreateRenderFrameImplFunction =
-      RenderFrameImpl* (*)(const CreateParams&);
+  using CreateRenderFrameImplFunction = RenderFrameImpl* (*)(CreateParams);
   static void InstallCreateHook(
       CreateRenderFrameImplFunction create_render_frame_impl);
 
@@ -510,14 +518,14 @@
   // mojom::FrameBindingsControl implementation:
   void AllowBindings(int32_t enabled_bindings_flags) override;
 
-  // mojom::FrameNavigationControl implemenentation:
-  void CommitNavigation(const ResourceResponseHead& head,
-                        const GURL& body_url,
-                        const CommonNavigationParams& common_params,
-                        const RequestNavigationParams& request_params,
-                        mojo::ScopedDataPipeConsumerHandle body_data,
-                        mojom::URLLoaderFactoryPtr
-                            default_subresource_url_loader_factory) override;
+  // mojom::FrameNavigationControl implementation:
+  void CommitNavigation(
+      const ResourceResponseHead& head,
+      const GURL& body_url,
+      const CommonNavigationParams& common_params,
+      const RequestNavigationParams& request_params,
+      mojo::ScopedDataPipeConsumerHandle body_data,
+      base::Optional<URLLoaderFactoryBundle> subresource_loaders) override;
 
   // mojom::HostZoom implementation:
   void SetHostZoomLevel(const GURL& url, double zoom_level) override;
@@ -743,8 +751,7 @@
 
   // Binds to the FrameHost in the browser.
   void BindFrame(const service_manager::BindSourceInfo& browser_info,
-                 mojom::FrameRequest request,
-                 mojom::FrameHostInterfaceBrokerPtr frame_host);
+                 mojom::FrameRequest request);
 
   // Virtual so that a TestRenderFrame can mock out the interface.
   virtual mojom::FrameHost* GetFrameHost();
@@ -831,7 +838,7 @@
   void SetCustomURLLoaderFactory(mojom::URLLoaderFactoryPtr factory);
 
  protected:
-  explicit RenderFrameImpl(const CreateParams& params);
+  explicit RenderFrameImpl(CreateParams params);
 
  private:
   friend class RenderFrameImplTest;
@@ -906,10 +913,12 @@
       EngagementOriginAndLevel;
 
   // Creates a new RenderFrame. |render_view| is the RenderView object that this
-  // frame belongs to.
+  // frame belongs to, and |interface_provider| is the RenderFrameHost's
+  // InterfaceProvider through which services are exposed to the RenderFrame.
   static RenderFrameImpl* Create(
       RenderViewImpl* render_view,
       int32_t routing_id,
+      service_manager::mojom::InterfaceProviderPtr interface_provider,
       const base::UnguessableToken& devtools_frame_token);
 
   // Functions to add and remove observers for this object.
@@ -1077,7 +1086,16 @@
       const CommonNavigationParams& common_params,
       const StartNavigationParams& start_params,
       const RequestNavigationParams& request_params,
-      std::unique_ptr<StreamOverrideParameters> stream_params);
+      std::unique_ptr<StreamOverrideParameters> stream_params,
+      base::Optional<URLLoaderFactoryBundle> subresource_loader_factories);
+
+  // Returns a URLLoaderFactoryBundle which can be used to request subresources
+  // for this frame. Only valid to call when the Network Service is enabled.
+  // For frames with committed navigations, this bundle is provided by the
+  // browser at navigation time. For any other frames (i.e. frames on the
+  // initial about:blank Document), the bundle returned here is lazily cloned
+  // from the parent or opener's own bundle.
+  URLLoaderFactoryBundle& GetSubresourceLoaderFactories();
 
   // Update current main frame's encoding and send it to browser window.
   // Since we want to let users see the right encoding info from menu
@@ -1378,10 +1396,8 @@
   PushMessagingClient* push_messaging_client_;
 
   service_manager::BinderRegistry registry_;
-  std::unique_ptr<service_manager::InterfaceProvider> remote_interfaces_;
+  service_manager::InterfaceProvider remote_interfaces_;
   std::unique_ptr<BlinkInterfaceRegistryImpl> blink_interface_registry_;
-  service_manager::mojom::InterfaceProviderRequest
-      pending_remote_interface_provider_request_;
 
   service_manager::BindSourceInfo local_info_;
   service_manager::BindSourceInfo remote_info_;
@@ -1470,7 +1486,6 @@
       frame_bindings_control_binding_;
   mojo::AssociatedBinding<mojom::FrameNavigationControl>
       frame_navigation_control_binding_;
-  mojom::FrameHostInterfaceBrokerPtr frame_host_interface_broker_;
 
   // Indicates whether |didAccessInitialDocument| was called.
   bool has_accessed_initial_document_;
@@ -1481,6 +1496,7 @@
   AssociatedInterfaceRegistryImpl associated_interfaces_;
   std::unique_ptr<AssociatedInterfaceProviderImpl>
       remote_associated_interfaces_;
+  mojom::FrameHostAssociatedPtr frame_host_;
 
   // TODO(dcheng): Remove these members.
   bool committed_first_load_ = false;
@@ -1530,6 +1546,10 @@
 
   scoped_refptr<ChildURLLoaderFactoryGetter> url_loader_factory_getter_;
 
+  // URLLoaderFactory instances used for subresource loading when the Network
+  // Service is enabled.
+  base::Optional<URLLoaderFactoryBundle> subresource_loader_factories_;
+
   // AndroidOverlay routing token from the browser, if we have one yet.
   base::Optional<base::UnguessableToken> overlay_routing_token_;
 
diff --git a/content/renderer/render_frame_impl_browsertest.cc b/content/renderer/render_frame_impl_browsertest.cc
index 5a660ff..f206d66 100644
--- a/content/renderer/render_frame_impl_browsertest.cc
+++ b/content/renderer/render_frame_impl_browsertest.cc
@@ -74,11 +74,13 @@
         view_->GetMainRenderFrame()->GetWebFrame()->FirstChild())
         ->OnSwapOut(kFrameProxyRouteId, false, frame_replication_state);
 
+    service_manager::mojom::InterfaceProviderPtr stub_interface_provider;
+    mojo::MakeRequest(&stub_interface_provider);
     RenderFrameImpl::CreateFrame(
-        kSubframeRouteId, MSG_ROUTING_NONE, MSG_ROUTING_NONE,
-        kFrameProxyRouteId, MSG_ROUTING_NONE, base::UnguessableToken::Create(),
-        frame_replication_state, &compositor_deps_, widget_params,
-        FrameOwnerProperties());
+        kSubframeRouteId, std::move(stub_interface_provider), MSG_ROUTING_NONE,
+        MSG_ROUTING_NONE, kFrameProxyRouteId, MSG_ROUTING_NONE,
+        base::UnguessableToken::Create(), frame_replication_state,
+        &compositor_deps_, widget_params, FrameOwnerProperties());
 
     frame_ = RenderFrameImpl::FromRoutingID(kSubframeRouteId);
     EXPECT_FALSE(frame_->is_main_frame_);
@@ -359,7 +361,7 @@
   GetMainRenderFrame()->SetHostZoomLevel(common_params.url, kMinZoomLevel);
   GetMainRenderFrame()->NavigateInternal(
       common_params, StartNavigationParams(), RequestNavigationParams(),
-      std::unique_ptr<StreamOverrideParameters>());
+      std::unique_ptr<StreamOverrideParameters>(), base::nullopt);
   base::RunLoop().RunUntilIdle();
   EXPECT_DOUBLE_EQ(kMinZoomLevel, view_->GetWebView()->ZoomLevel());
 
@@ -370,7 +372,7 @@
   GetMainRenderFrame()->SetHostZoomLevel(common_params.url, kMaxZoomLevel);
   GetMainRenderFrame()->NavigateInternal(
       common_params, StartNavigationParams(), RequestNavigationParams(),
-      std::unique_ptr<StreamOverrideParameters>());
+      std::unique_ptr<StreamOverrideParameters>(), base::nullopt);
   base::RunLoop().RunUntilIdle();
   EXPECT_DOUBLE_EQ(kMaxZoomLevel, view_->GetWebView()->ZoomLevel());
 }
diff --git a/content/renderer/render_thread_impl.cc b/content/renderer/render_thread_impl.cc
index 8c939879..997e8c0 100644
--- a/content/renderer/render_thread_impl.cc
+++ b/content/renderer/render_thread_impl.cc
@@ -161,6 +161,7 @@
 #include "net/base/registry_controlled_domains/registry_controlled_domain.h"
 #include "net/base/url_util.h"
 #include "ppapi/features/features.h"
+#include "services/metrics/public/cpp/mojo_ukm_recorder.h"
 #include "services/service_manager/public/cpp/binder_registry.h"
 #include "services/service_manager/public/cpp/connector.h"
 #include "services/service_manager/public/cpp/interface_provider.h"
@@ -339,10 +340,8 @@
 
  private:
   // mojom::FrameFactory:
-  void CreateFrame(
-      int32_t frame_routing_id,
-      mojom::FrameRequest frame_request,
-      mojom::FrameHostInterfaceBrokerPtr frame_host_interface_broker) override {
+  void CreateFrame(int32_t frame_routing_id,
+                   mojom::FrameRequest frame_request) override {
     // TODO(morrita): This is for investigating http://crbug.com/415059 and
     // should be removed once it is fixed.
     CHECK_LT(routing_id_highmark_, frame_routing_id);
@@ -355,13 +354,11 @@
     // we want.
     if (!frame) {
       RenderThreadImpl::current()->RegisterPendingFrameCreate(
-          source_info_, frame_routing_id, std::move(frame_request),
-          std::move(frame_host_interface_broker));
+          source_info_, frame_routing_id, std::move(frame_request));
       return;
     }
 
-    frame->BindFrame(source_info_, std::move(frame_request),
-                     std::move(frame_host_interface_broker));
+    frame->BindFrame(source_info_, std::move(frame_request));
   }
 
  private:
@@ -445,6 +442,28 @@
   RenderWidgetSurfaceProperties surface_properties_;
 };
 
+// This factory is used to defer binding of the InterfacePtr to the compositor
+// thread.
+class UkmRecorderFactoryImpl : public cc::UkmRecorderFactory {
+ public:
+  UkmRecorderFactoryImpl(ukm::mojom::UkmRecorderInterfacePtrInfo info)
+      : info_(std::move(info)) {
+    DCHECK(info_.is_valid());
+  }
+  ~UkmRecorderFactoryImpl() override = default;
+
+  std::unique_ptr<ukm::UkmRecorder> CreateRecorder() override {
+    DCHECK(info_.is_valid());
+
+    ukm::mojom::UkmRecorderInterfacePtr recorder;
+    recorder.Bind(std::move(info_));
+    return std::make_unique<ukm::MojoUkmRecorder>(std::move(recorder));
+  }
+
+ private:
+  ukm::mojom::UkmRecorderInterfacePtrInfo info_;
+};
+
 }  // namespace
 
 RenderThreadImpl::HistogramCustomizer::HistogramCustomizer() {
@@ -1081,8 +1100,7 @@
     return;
 
   scoped_refptr<PendingFrameCreate> create(it->second);
-  frame->BindFrame(it->second->browser_info(), it->second->TakeFrameRequest(),
-                   it->second->TakeInterfaceBroker());
+  frame->BindFrame(it->second->browser_info(), it->second->TakeFrameRequest());
   pending_frame_creates_.erase(it);
 }
 
@@ -1110,13 +1128,11 @@
 void RenderThreadImpl::RegisterPendingFrameCreate(
     const service_manager::BindSourceInfo& browser_info,
     int routing_id,
-    mojom::FrameRequest frame_request,
-    mojom::FrameHostInterfaceBrokerPtr frame_host_interface_broker) {
+    mojom::FrameRequest frame_request) {
   std::pair<PendingFrameCreateMap::iterator, bool> result =
       pending_frame_creates_.insert(std::make_pair(
           routing_id, base::MakeRefCounted<PendingFrameCreate>(
-                          browser_info, routing_id, std::move(frame_request),
-                          std::move(frame_host_interface_broker))));
+                          browser_info, routing_id, std::move(frame_request))));
   CHECK(result.second) << "Inserting a duplicate item.";
 }
 
@@ -1701,6 +1717,13 @@
   return is_scroll_animator_enabled_;
 }
 
+std::unique_ptr<cc::UkmRecorderFactory>
+RenderThreadImpl::CreateUkmRecorderFactory() {
+  ukm::mojom::UkmRecorderInterfacePtrInfo info;
+  mojo::MakeRequest(&info);
+  return std::make_unique<UkmRecorderFactoryImpl>(std::move(info));
+}
+
 void RenderThreadImpl::OnRAILModeChanged(v8::RAILMode rail_mode) {
   blink::MainThreadIsolate()->SetRAILMode(rail_mode);
   blink::SetRAILModeOnWorkerThreadIsolates(rail_mode);
@@ -2195,7 +2218,7 @@
   CompositorDependencies* compositor_deps = this;
   is_scroll_animator_enabled_ = params->web_preferences.enable_scroll_animator;
   // When bringing in render_view, also bring in webkit's glue and jsbindings.
-  RenderViewImpl::Create(compositor_deps, *params,
+  RenderViewImpl::Create(compositor_deps, std::move(params),
                          RenderWidget::ShowCallback());
 }
 
@@ -2218,7 +2241,8 @@
                                 params->replication_state.origin.Serialize());
   CompositorDependencies* compositor_deps = this;
   RenderFrameImpl::CreateFrame(
-      params->routing_id, params->proxy_routing_id, params->opener_routing_id,
+      params->routing_id, std::move(params->interface_provider),
+      params->proxy_routing_id, params->opener_routing_id,
       params->parent_routing_id, params->previous_sibling_routing_id,
       params->devtools_frame_token, params->replication_state, compositor_deps,
       *params->widget_params, params->frame_owner_properties);
@@ -2516,19 +2540,10 @@
 RenderThreadImpl::PendingFrameCreate::PendingFrameCreate(
     const service_manager::BindSourceInfo& browser_info,
     int routing_id,
-    mojom::FrameRequest frame_request,
-    mojom::FrameHostInterfaceBrokerPtr frame_host_interface_broker)
+    mojom::FrameRequest frame_request)
     : browser_info_(browser_info),
       routing_id_(routing_id),
-      frame_request_(std::move(frame_request)),
-      frame_host_interface_broker_(std::move(frame_host_interface_broker)) {
-  // The RenderFrame may be deleted before the CreateFrame message is received.
-  // In that case, the RenderFrameHost should cancel the create, which is
-  // detected by setting an error handler on |frame_host_interface_broker_|.
-  frame_host_interface_broker_.set_connection_error_handler(
-      base::BindOnce(&RenderThreadImpl::PendingFrameCreate::OnConnectionError,
-                     base::Unretained(this)));
-}
+      frame_request_(std::move(frame_request)) {}
 
 RenderThreadImpl::PendingFrameCreate::~PendingFrameCreate() {
 }
diff --git a/content/renderer/render_thread_impl.h b/content/renderer/render_thread_impl.h
index 8968106..a2487d4 100644
--- a/content/renderer/render_thread_impl.h
+++ b/content/renderer/render_thread_impl.h
@@ -261,6 +261,7 @@
   cc::TaskGraphRunner* GetTaskGraphRunner() override;
   bool IsThreadedAnimationEnabled() override;
   bool IsScrollAnimatorEnabled() override;
+  std::unique_ptr<cc::UkmRecorderFactory> CreateUkmRecorderFactory() override;
 
   // blink::scheduler::RendererScheduler::RAILModeObserver implementation.
   void OnRAILModeChanged(v8::RAILMode rail_mode) override;
@@ -514,8 +515,7 @@
   void RegisterPendingFrameCreate(
       const service_manager::BindSourceInfo& source_info,
       int routing_id,
-      mojom::FrameRequest frame,
-      mojom::FrameHostInterfaceBrokerPtr host);
+      mojom::FrameRequest frame);
 
   mojom::StoragePartitionService* GetStoragePartitionService();
   mojom::RendererHost* GetRendererHost();
@@ -781,21 +781,14 @@
 
   class PendingFrameCreate : public base::RefCounted<PendingFrameCreate> {
    public:
-    PendingFrameCreate(
-        const service_manager::BindSourceInfo& source_info,
-        int routing_id,
-        mojom::FrameRequest frame_request,
-        mojom::FrameHostInterfaceBrokerPtr frame_host_interface_broker);
+    PendingFrameCreate(const service_manager::BindSourceInfo& source_info,
+                       int routing_id,
+                       mojom::FrameRequest frame_request);
 
     const service_manager::BindSourceInfo& browser_info() const {
       return browser_info_;
     }
     mojom::FrameRequest TakeFrameRequest() { return std::move(frame_request_); }
-    mojom::FrameHostInterfaceBrokerPtr TakeInterfaceBroker() {
-      frame_host_interface_broker_.set_connection_error_handler(
-          base::Closure());
-      return std::move(frame_host_interface_broker_);
-    }
 
    private:
     friend class base::RefCounted<PendingFrameCreate>;
@@ -808,7 +801,6 @@
     service_manager::BindSourceInfo browser_info_;
     int routing_id_;
     mojom::FrameRequest frame_request_;
-    mojom::FrameHostInterfaceBrokerPtr frame_host_interface_broker_;
   };
 
   using PendingFrameCreateMap =
diff --git a/content/renderer/render_view_browsertest.cc b/content/renderer/render_view_browsertest.cc
index 9ff8c1e..7ac5929 100644
--- a/content/renderer/render_view_browsertest.cc
+++ b/content/renderer/render_view_browsertest.cc
@@ -875,13 +875,16 @@
   // Do the remote-to-local transition for the proxy, which is to create a
   // provisional local frame.
   int routing_id = kProxyRoutingId + 1;
+  service_manager::mojom::InterfaceProviderPtr stub_interface_provider;
+  mojo::MakeRequest(&stub_interface_provider);
   mojom::CreateFrameWidgetParams widget_params;
   widget_params.routing_id = view()->GetRoutingID();
   widget_params.hidden = false;
   RenderFrameImpl::CreateFrame(
-      routing_id, kProxyRoutingId, MSG_ROUTING_NONE, MSG_ROUTING_NONE,
-      MSG_ROUTING_NONE, base::UnguessableToken::Create(), replication_state,
-      nullptr, widget_params, FrameOwnerProperties());
+      routing_id, std::move(stub_interface_provider), kProxyRoutingId,
+      MSG_ROUTING_NONE, MSG_ROUTING_NONE, MSG_ROUTING_NONE,
+      base::UnguessableToken::Create(), replication_state, nullptr,
+      widget_params, FrameOwnerProperties());
   TestRenderFrame* provisional_frame =
       static_cast<TestRenderFrame*>(RenderFrameImpl::FromRoutingID(routing_id));
   EXPECT_TRUE(provisional_frame);
@@ -923,13 +926,16 @@
   // Do the first step of a remote-to-local transition for the child proxy,
   // which is to create a provisional local frame.
   int routing_id = kProxyRoutingId + 1;
+  service_manager::mojom::InterfaceProviderPtr stub_interface_provider;
+  mojo::MakeRequest(&stub_interface_provider);
   mojom::CreateFrameWidgetParams widget_params;
   widget_params.routing_id = MSG_ROUTING_NONE;
   widget_params.hidden = false;
   RenderFrameImpl::CreateFrame(
-      routing_id, kProxyRoutingId, MSG_ROUTING_NONE, frame()->GetRoutingID(),
-      MSG_ROUTING_NONE, base::UnguessableToken::Create(), replication_state,
-      nullptr, widget_params, FrameOwnerProperties());
+      routing_id, std::move(stub_interface_provider), kProxyRoutingId,
+      MSG_ROUTING_NONE, frame()->GetRoutingID(), MSG_ROUTING_NONE,
+      base::UnguessableToken::Create(), replication_state, nullptr,
+      widget_params, FrameOwnerProperties());
   {
     TestRenderFrame* provisional_frame = static_cast<TestRenderFrame*>(
         RenderFrameImpl::FromRoutingID(routing_id));
diff --git a/content/renderer/render_view_impl.cc b/content/renderer/render_view_impl.cc
index 39c758c..da65bb40 100644
--- a/content/renderer/render_view_impl.cc
+++ b/content/renderer/render_view_impl.cc
@@ -556,7 +556,7 @@
 }
 
 void RenderViewImpl::Initialize(
-    const mojom::CreateViewParams& params,
+    mojom::CreateViewParamsPtr params,
     const RenderWidget::ShowCallback& show_callback) {
   bool was_created_by_renderer = !show_callback.is_null();
 #if defined(OS_ANDROID)
@@ -564,7 +564,7 @@
   // HandleNavigation codepath.
   was_created_by_renderer_ = was_created_by_renderer;
 #endif
-  display_mode_ = params.initial_size.display_mode;
+  display_mode_ = params->initial_size.display_mode;
 
   webview_ = WebView::Create(this, is_hidden()
                                        ? blink::kWebPageVisibilityStateHidden
@@ -620,23 +620,26 @@
   ApplyBlinkSettings(command_line, webview()->GetSettings());
 
   WebFrame* opener_frame =
-      RenderFrameImpl::ResolveOpener(params.opener_frame_route_id);
+      RenderFrameImpl::ResolveOpener(params->opener_frame_route_id);
 
-  if (params.main_frame_routing_id != MSG_ROUTING_NONE) {
+  if (params->main_frame_routing_id != MSG_ROUTING_NONE) {
+    CHECK(params->main_frame_interface_provider.is_bound());
     main_render_frame_ = RenderFrameImpl::CreateMainFrame(
-        this, params.main_frame_routing_id, params.main_frame_widget_routing_id,
-        params.hidden, screen_info(), compositor_deps_, opener_frame,
-        params.devtools_main_frame_token, params.replicated_frame_state);
+        this, params->main_frame_routing_id,
+        std::move(params->main_frame_interface_provider),
+        params->main_frame_widget_routing_id, params->hidden, screen_info(),
+        compositor_deps_, opener_frame, params->devtools_main_frame_token,
+        params->replicated_frame_state);
   }
 
   // TODO(dcheng): Shouldn't these be mutually exclusive at this point? See
   // https://crbug.com/720116 where the browser is apparently sending both
   // routing IDs...
-  if (params.proxy_routing_id != MSG_ROUTING_NONE) {
-    CHECK(params.swapped_out);
-    RenderFrameProxy::CreateFrameProxy(params.proxy_routing_id, GetRoutingID(),
+  if (params->proxy_routing_id != MSG_ROUTING_NONE) {
+    CHECK(params->swapped_out);
+    RenderFrameProxy::CreateFrameProxy(params->proxy_routing_id, GetRoutingID(),
                                        opener_frame, MSG_ROUTING_NONE,
-                                       params.replicated_frame_state);
+                                       params->replicated_frame_state);
   }
 
   if (main_render_frame_)
@@ -650,23 +653,23 @@
     did_show_ = true;
 
   // TODO(davidben): Move this state from Blink into content.
-  if (params.window_was_created_with_opener)
+  if (params->window_was_created_with_opener)
     webview()->SetOpenedByDOM();
 
   UpdateWebViewWithDeviceScaleFactor();
-  OnSetRendererPrefs(params.renderer_preferences);
+  OnSetRendererPrefs(params->renderer_preferences);
 
-  if (!params.enable_auto_resize) {
-    OnResize(params.initial_size);
+  if (!params->enable_auto_resize) {
+    OnResize(params->initial_size);
   } else {
-    OnEnableAutoResize(params.min_size, params.max_size);
+    OnEnableAutoResize(params->min_size, params->max_size);
   }
 
   idle_user_detector_.reset(new IdleUserDetector(this));
 
   GetContentClient()->renderer()->RenderViewCreated(this);
 
-  page_zoom_level_ = params.page_zoom_level;
+  page_zoom_level_ = params->page_zoom_level;
 }
 
 RenderViewImpl::~RenderViewImpl() {
@@ -1032,16 +1035,16 @@
 /*static*/
 RenderViewImpl* RenderViewImpl::Create(
     CompositorDependencies* compositor_deps,
-    const mojom::CreateViewParams& params,
+    mojom::CreateViewParamsPtr params,
     const RenderWidget::ShowCallback& show_callback) {
-  DCHECK(params.view_id != MSG_ROUTING_NONE);
+  DCHECK(params->view_id != MSG_ROUTING_NONE);
   RenderViewImpl* render_view;
   if (g_create_render_view_impl)
-    render_view = g_create_render_view_impl(compositor_deps, params);
+    render_view = g_create_render_view_impl(compositor_deps, *params);
   else
-    render_view = new RenderViewImpl(compositor_deps, params);
+    render_view = new RenderViewImpl(compositor_deps, *params);
 
-  render_view->Initialize(params, show_callback);
+  render_view->Initialize(std::move(params), show_callback);
   return render_view;
 }
 
@@ -1386,32 +1389,35 @@
   // return from this call synchronously, we just have to make our best guess
   // and rely on the browser sending a WasHidden / WasShown message if it
   // disagrees.
-  mojom::CreateViewParams view_params;
+  mojom::CreateViewParamsPtr view_params = mojom::CreateViewParams::New();
 
-  view_params.opener_frame_route_id = creator_frame->GetRoutingID();
+  view_params->opener_frame_route_id = creator_frame->GetRoutingID();
   DCHECK_EQ(GetRoutingID(), creator_frame->render_view()->GetRoutingID());
 
-  view_params.window_was_created_with_opener = true;
-  view_params.renderer_preferences = renderer_preferences_;
-  view_params.web_preferences = webkit_preferences_;
-  view_params.view_id = reply->route_id;
-  view_params.main_frame_routing_id = reply->main_frame_route_id;
-  view_params.main_frame_widget_routing_id = reply->main_frame_widget_route_id;
-  view_params.session_storage_namespace_id =
+  view_params->window_was_created_with_opener = true;
+  view_params->renderer_preferences = renderer_preferences_;
+  view_params->web_preferences = webkit_preferences_;
+  view_params->view_id = reply->route_id;
+  view_params->main_frame_routing_id = reply->main_frame_route_id;
+  view_params->main_frame_interface_provider =
+      std::move(reply->main_frame_interface_provider);
+  view_params->main_frame_widget_routing_id = reply->main_frame_widget_route_id;
+  view_params->session_storage_namespace_id =
       reply->cloned_session_storage_namespace_id;
-  view_params.swapped_out = false;
-  view_params.replicated_frame_state.frame_policy.sandbox_flags = sandbox_flags;
-  view_params.replicated_frame_state.name = frame_name_utf8;
-  view_params.devtools_main_frame_token = reply->devtools_main_frame_token;
+  view_params->swapped_out = false;
+  view_params->replicated_frame_state.frame_policy.sandbox_flags =
+      sandbox_flags;
+  view_params->replicated_frame_state.name = frame_name_utf8;
+  view_params->devtools_main_frame_token = reply->devtools_main_frame_token;
   // Even if the main frame has a name, the main frame's unique name is always
   // the empty string.
-  view_params.hidden = is_background_tab;
-  view_params.never_visible = never_visible;
-  view_params.initial_size = initial_size;
-  view_params.enable_auto_resize = false;
-  view_params.min_size = gfx::Size();
-  view_params.max_size = gfx::Size();
-  view_params.page_zoom_level = page_zoom_level_;
+  view_params->hidden = is_background_tab;
+  view_params->never_visible = never_visible;
+  view_params->initial_size = initial_size;
+  view_params->enable_auto_resize = false;
+  view_params->min_size = gfx::Size();
+  view_params->max_size = gfx::Size();
+  view_params->page_zoom_level = page_zoom_level_;
 
   // Unretained() is safe here because our calling function will also call
   // show().
@@ -1419,8 +1425,8 @@
       base::Bind(&RenderFrameImpl::ShowCreatedWindow,
                  base::Unretained(creator_frame), opened_by_user_gesture);
 
-  RenderViewImpl* view =
-      RenderViewImpl::Create(compositor_deps_, view_params, show_callback);
+  RenderViewImpl* view = RenderViewImpl::Create(
+      compositor_deps_, std::move(view_params), show_callback);
 
   return view->webview();
 }
diff --git a/content/renderer/render_view_impl.h b/content/renderer/render_view_impl.h
index de8e3a3..c060595 100644
--- a/content/renderer/render_view_impl.h
+++ b/content/renderer/render_view_impl.h
@@ -123,7 +123,7 @@
   // send an additional IPC to finish making this view visible.
   static RenderViewImpl* Create(
       CompositorDependencies* compositor_deps,
-      const mojom::CreateViewParams& params,
+      mojom::CreateViewParamsPtr params,
       const RenderWidget::ShowCallback& show_callback);
 
   // Used by content_layouttest_support to hook into the creation of
@@ -387,7 +387,7 @@
   RenderViewImpl(CompositorDependencies* compositor_deps,
                  const mojom::CreateViewParams& params);
 
-  void Initialize(const mojom::CreateViewParams& params,
+  void Initialize(mojom::CreateViewParamsPtr params,
                   const RenderWidget::ShowCallback& show_callback);
   void SetScreenMetricsEmulationParameters(
       bool enabled,
diff --git a/content/renderer/render_widget.cc b/content/renderer/render_widget.cc
index 992233b..6bd8444 100644
--- a/content/renderer/render_widget.cc
+++ b/content/renderer/render_widget.cc
@@ -42,6 +42,7 @@
 #include "content/public/common/content_switches.h"
 #include "content/public/common/context_menu_params.h"
 #include "content/public/common/drop_data.h"
+#include "content/public/common/service_names.mojom.h"
 #include "content/public/renderer/content_renderer_client.h"
 #include "content/renderer/browser_plugin/browser_plugin_manager.h"
 #include "content/renderer/cursor_utils.h"
@@ -1430,6 +1431,8 @@
     }
   }
 
+  UpdateURLForCompositorUkm();
+
   return compositor_.get();
 }
 
@@ -2510,6 +2513,20 @@
   need_update_rect_for_auto_resize_ = false;
 }
 
+void RenderWidget::UpdateURLForCompositorUkm() {
+  DCHECK(compositor_);
+
+  if (!GetWebWidget() || !GetWebWidget()->IsWebFrameWidget())
+    return;
+
+  auto* render_frame = RenderFrameImpl::FromWebFrame(
+      static_cast<blink::WebFrameWidget*>(GetWebWidget())->LocalRoot());
+  if (!render_frame->IsMainFrame())
+    return;
+
+  compositor_->SetURLForUkm(render_frame->GetWebFrame()->GetDocument().Url());
+}
+
 #if BUILDFLAG(ENABLE_PLUGINS)
 PepperPluginInstanceImpl* RenderWidget::GetFocusedPepperPluginInsideWidget() {
   if (!GetWebWidget() || !GetWebWidget()->IsWebFrameWidget())
diff --git a/content/renderer/render_widget.h b/content/renderer/render_widget.h
index b2eb5258..f3bf93f 100644
--- a/content/renderer/render_widget.h
+++ b/content/renderer/render_widget.h
@@ -867,6 +867,12 @@
 #endif
   void RecordTimeToFirstActivePaint();
 
+  // Updates the URL used by the compositor for keying UKM metrics.
+  // Note that this uses the main frame's URL and only if its available in the
+  // current process. In the case where it is not available, no metrics will be
+  // recorded.
+  void UpdateURLForCompositorUkm();
+
   // Indicates whether this widget has focus.
   bool has_focus_;
 
diff --git a/content/renderer/service_worker/service_worker_subresource_loader.cc b/content/renderer/service_worker/service_worker_subresource_loader.cc
index e2e7f37..3ac919d 100644
--- a/content/renderer/service_worker/service_worker_subresource_loader.cc
+++ b/content/renderer/service_worker/service_worker_subresource_loader.cc
@@ -187,7 +187,7 @@
 void ServiceWorkerSubresourceLoader::StartRequest(
     const ResourceRequest& resource_request) {
   // TODO(kinuko): Implement request.request_body handling.
-  DCHECK(!resource_request.request_body);
+  DCHECK(!resource_request_.request_body);
   DCHECK(!inflight_fetch_request_);
   inflight_fetch_request_ =
       ServiceWorkerLoaderHelpers::CreateFetchRequest(resource_request);
diff --git a/content/shell/app/shell_main_delegate.cc b/content/shell/app/shell_main_delegate.cc
index 092694f3..64e1c0a7 100644
--- a/content/shell/app/shell_main_delegate.cc
+++ b/content/shell/app/shell_main_delegate.cc
@@ -263,7 +263,7 @@
 #endif
 
 // Disable platform crash handling & initialize Breakpad, if requested.
-// TODO(753619): Implement crash reporter integration for Fuchsia.
+// TODO(crbug.com/753619): Implement crash reporter integration for Fuchsia.
 #if !defined(OS_FUCHSIA)
   if (base::CommandLine::ForCurrentProcess()->HasSwitch(
           switches::kEnableCrashReporter)) {
diff --git a/content/shell/test_runner/web_frame_test_proxy.h b/content/shell/test_runner/web_frame_test_proxy.h
index c6f3cfc..575e255 100644
--- a/content/shell/test_runner/web_frame_test_proxy.h
+++ b/content/shell/test_runner/web_frame_test_proxy.h
@@ -54,7 +54,7 @@
 template <class Base, typename P>
 class WebFrameTestProxy : public Base, public WebFrameTestProxyBase {
  public:
-  explicit WebFrameTestProxy(P p) : Base(p) {}
+  explicit WebFrameTestProxy(P p) : Base(std::move(p)) {}
 
   virtual ~WebFrameTestProxy() {}
 
diff --git a/content/test/BUILD.gn b/content/test/BUILD.gn
index 70b5156..8df031ae 100644
--- a/content/test/BUILD.gn
+++ b/content/test/BUILD.gn
@@ -1213,7 +1213,6 @@
     "../browser/fileapi/browser_file_system_helper_unittest.cc",
     "../browser/fileapi/file_system_operation_runner_unittest.cc",
     "../browser/fileapi/fileapi_message_filter_unittest.cc",
-    "../browser/fileapi/upload_file_system_file_element_reader_unittest.cc",
     "../browser/frame_host/ancestor_throttle_unittest.cc",
     "../browser/frame_host/frame_service_base_unittest.cc",
     "../browser/frame_host/frame_tree_node_blame_context_unittest.cc",
diff --git a/content/test/data/accessibility/aria/aria-columnheader-expected-mac.txt b/content/test/data/accessibility/aria/aria-columnheader-expected-mac.txt
index 5b65b528..7f26dff 100644
--- a/content/test/data/accessibility/aria/aria-columnheader-expected-mac.txt
+++ b/content/test/data/accessibility/aria/aria-columnheader-expected-mac.txt
@@ -1,20 +1,20 @@
 AXWebArea
-++AXTable AXColumnHeaderUIElements=["AXCell Browser","AXCell Rendering Engine"] AXHeader='AXGroup' AXRowHeaderUIElements=[]
+++AXTable AXColumnHeaderUIElements=["AXCell Browser","AXCell Rendering Engine"] AXHeader='AXGroup'
 ++++AXRow AXIndex='0'
-++++++AXCell AXTitle='Browser' AXColumnHeaderUIElements=["AXCell Browser","AXCell Rendering Engine"] AXColumnIndexRange={"len":1,"loc":0} AXRowHeaderUIElements=[] AXRowIndexRange={"len":1,"loc":0}
+++++++AXCell AXTitle='Browser' AXColumnIndexRange={"len":1,"loc":0} AXRowIndexRange={"len":1,"loc":0}
 ++++++++AXStaticText AXValue='Browser'
-++++++AXCell AXTitle='Rendering Engine' AXColumnHeaderUIElements=["AXCell Browser","AXCell Rendering Engine"] AXColumnIndexRange={"len":1,"loc":1} AXRowHeaderUIElements=[] AXRowIndexRange={"len":1,"loc":0}
+++++++AXCell AXTitle='Rendering Engine' AXColumnIndexRange={"len":1,"loc":1} AXRowIndexRange={"len":1,"loc":0}
 ++++++++AXStaticText AXValue='Rendering Engine'
 ++++AXRow AXIndex='1'
-++++++AXCell AXTitle='Chrome' AXColumnHeaderUIElements=["AXCell Browser","AXCell Rendering Engine"] AXColumnIndexRange={"len":1,"loc":0} AXRowHeaderUIElements=[] AXRowIndexRange={"len":1,"loc":1}
+++++++AXCell AXTitle='Chrome' AXColumnHeaderUIElements=["AXCell Browser"] AXColumnIndexRange={"len":1,"loc":0} AXRowIndexRange={"len":1,"loc":1}
 ++++++++AXStaticText AXValue='Chrome'
-++++++AXCell AXTitle='Blink' AXColumnHeaderUIElements=["AXCell Browser","AXCell Rendering Engine"] AXColumnIndexRange={"len":1,"loc":1} AXRowHeaderUIElements=[] AXRowIndexRange={"len":1,"loc":1}
+++++++AXCell AXTitle='Blink' AXColumnHeaderUIElements=["AXCell Rendering Engine"] AXColumnIndexRange={"len":1,"loc":1} AXRowIndexRange={"len":1,"loc":1}
 ++++++++AXStaticText AXValue='Blink'
 ++++AXRow AXIndex='2'
-++++++AXCell AXTitle='Safari' AXColumnHeaderUIElements=["AXCell Browser","AXCell Rendering Engine"] AXColumnIndexRange={"len":1,"loc":0} AXRowHeaderUIElements=[] AXRowIndexRange={"len":1,"loc":2}
+++++++AXCell AXTitle='Safari' AXColumnHeaderUIElements=["AXCell Browser"] AXColumnIndexRange={"len":1,"loc":0} AXRowIndexRange={"len":1,"loc":2}
 ++++++++AXStaticText AXValue='Safari'
-++++++AXCell AXTitle='WebKit' AXColumnHeaderUIElements=["AXCell Browser","AXCell Rendering Engine"] AXColumnIndexRange={"len":1,"loc":1} AXRowHeaderUIElements=[] AXRowIndexRange={"len":1,"loc":2}
+++++++AXCell AXTitle='WebKit' AXColumnHeaderUIElements=["AXCell Rendering Engine"] AXColumnIndexRange={"len":1,"loc":1} AXRowIndexRange={"len":1,"loc":2}
 ++++++++AXStaticText AXValue='WebKit'
 ++++AXColumn AXHeader='AXCell Browser' AXIndex='0'
 ++++AXColumn AXHeader='AXCell Rendering Engine' AXIndex='1'
-++++AXGroup
\ No newline at end of file
+++++AXGroup
diff --git a/content/test/data/accessibility/aria/aria-rowheader-expected-mac.txt b/content/test/data/accessibility/aria/aria-rowheader-expected-mac.txt
index 5bd8a539..abfd94f 100644
--- a/content/test/data/accessibility/aria/aria-rowheader-expected-mac.txt
+++ b/content/test/data/accessibility/aria/aria-rowheader-expected-mac.txt
@@ -1,20 +1,20 @@
 AXWebArea
-++AXTable AXColumnHeaderUIElements=[] AXHeader='AXGroup' AXRowHeaderUIElements=["AXCell Browser","AXCell Rendering Engine"]
+++AXTable AXHeader='AXGroup' AXRowHeaderUIElements=["AXCell Browser","AXCell Rendering Engine"]
 ++++AXRow AXIndex='0'
-++++++AXCell AXTitle='Browser' AXColumnHeaderUIElements=[] AXColumnIndexRange={"len":1,"loc":0} AXRowHeaderUIElements=["AXCell Browser","AXCell Rendering Engine"] AXRowIndexRange={"len":1,"loc":0}
+++++++AXCell AXTitle='Browser' AXColumnIndexRange={"len":1,"loc":0} AXRowIndexRange={"len":1,"loc":0}
 ++++++++AXStaticText AXValue='Browser'
-++++++AXCell AXTitle='Chrome' AXColumnHeaderUIElements=[] AXColumnIndexRange={"len":1,"loc":1} AXRowHeaderUIElements=["AXCell Browser","AXCell Rendering Engine"] AXRowIndexRange={"len":1,"loc":0}
+++++++AXCell AXTitle='Chrome' AXColumnIndexRange={"len":1,"loc":1} AXRowHeaderUIElements=["AXCell Browser"] AXRowIndexRange={"len":1,"loc":0}
 ++++++++AXStaticText AXValue='Chrome'
-++++++AXCell AXTitle='Safari' AXColumnHeaderUIElements=[] AXColumnIndexRange={"len":1,"loc":2} AXRowHeaderUIElements=["AXCell Browser","AXCell Rendering Engine"] AXRowIndexRange={"len":1,"loc":0}
+++++++AXCell AXTitle='Safari' AXColumnIndexRange={"len":1,"loc":2} AXRowHeaderUIElements=["AXCell Browser"] AXRowIndexRange={"len":1,"loc":0}
 ++++++++AXStaticText AXValue='Safari'
 ++++AXRow AXIndex='1'
-++++++AXCell AXTitle='Rendering Engine' AXColumnHeaderUIElements=[] AXColumnIndexRange={"len":1,"loc":0} AXRowHeaderUIElements=["AXCell Browser","AXCell Rendering Engine"] AXRowIndexRange={"len":1,"loc":1}
+++++++AXCell AXTitle='Rendering Engine' AXColumnIndexRange={"len":1,"loc":0} AXRowIndexRange={"len":1,"loc":1}
 ++++++++AXStaticText AXValue='Rendering Engine'
-++++++AXCell AXTitle='Blink' AXColumnHeaderUIElements=[] AXColumnIndexRange={"len":1,"loc":1} AXRowHeaderUIElements=["AXCell Browser","AXCell Rendering Engine"] AXRowIndexRange={"len":1,"loc":1}
+++++++AXCell AXTitle='Blink' AXColumnIndexRange={"len":1,"loc":1} AXRowHeaderUIElements=["AXCell Rendering Engine"] AXRowIndexRange={"len":1,"loc":1}
 ++++++++AXStaticText AXValue='Blink'
-++++++AXCell AXTitle='WebKit' AXColumnHeaderUIElements=[] AXColumnIndexRange={"len":1,"loc":2} AXRowHeaderUIElements=["AXCell Browser","AXCell Rendering Engine"] AXRowIndexRange={"len":1,"loc":1}
+++++++AXCell AXTitle='WebKit' AXColumnIndexRange={"len":1,"loc":2} AXRowHeaderUIElements=["AXCell Rendering Engine"] AXRowIndexRange={"len":1,"loc":1}
 ++++++++AXStaticText AXValue='WebKit'
 ++++AXColumn AXIndex='0'
 ++++AXColumn AXIndex='1'
 ++++AXColumn AXIndex='2'
-++++AXGroup
\ No newline at end of file
+++++AXGroup
diff --git a/content/test/data/accessibility/html/table-th-colheader-expected-mac.txt b/content/test/data/accessibility/html/table-th-colheader-expected-mac.txt
index 0891396a..34c121c 100644
--- a/content/test/data/accessibility/html/table-th-colheader-expected-mac.txt
+++ b/content/test/data/accessibility/html/table-th-colheader-expected-mac.txt
@@ -1,15 +1,15 @@
 AXWebArea
-++AXTable AXColumnHeaderUIElements=["AXCell Firstname","AXCell Lastname"] AXHeader='AXGroup' AXRowHeaderUIElements=[]
+++AXTable AXColumnHeaderUIElements=["AXCell Firstname","AXCell Lastname"] AXHeader='AXGroup'
 ++++AXRow AXIndex='0'
-++++++AXCell AXTitle='Firstname' AXColumnHeaderUIElements=["AXCell Firstname","AXCell Lastname"] AXColumnIndexRange={"len":1,"loc":0} AXRowHeaderUIElements=[] AXRowIndexRange={"len":1,"loc":0}
+++++++AXCell AXTitle='Firstname' AXColumnIndexRange={"len":1,"loc":0} AXRowIndexRange={"len":1,"loc":0}
 ++++++++AXStaticText AXValue='Firstname'
-++++++AXCell AXTitle='Lastname' AXColumnHeaderUIElements=["AXCell Firstname","AXCell Lastname"] AXColumnIndexRange={"len":1,"loc":1} AXRowHeaderUIElements=[] AXRowIndexRange={"len":1,"loc":0}
+++++++AXCell AXTitle='Lastname' AXColumnIndexRange={"len":1,"loc":1} AXRowIndexRange={"len":1,"loc":0}
 ++++++++AXStaticText AXValue='Lastname'
 ++++AXRow AXIndex='1'
-++++++AXCell AXTitle='Jill' AXColumnHeaderUIElements=["AXCell Firstname","AXCell Lastname"] AXColumnIndexRange={"len":1,"loc":0} AXRowHeaderUIElements=[] AXRowIndexRange={"len":1,"loc":1}
+++++++AXCell AXTitle='Jill' AXColumnHeaderUIElements=["AXCell Firstname"] AXColumnIndexRange={"len":1,"loc":0} AXRowIndexRange={"len":1,"loc":1}
 ++++++++AXStaticText AXValue='Jill'
-++++++AXCell AXTitle='Smith' AXColumnHeaderUIElements=["AXCell Firstname","AXCell Lastname"] AXColumnIndexRange={"len":1,"loc":1} AXRowHeaderUIElements=[] AXRowIndexRange={"len":1,"loc":1}
+++++++AXCell AXTitle='Smith' AXColumnHeaderUIElements=["AXCell Lastname"] AXColumnIndexRange={"len":1,"loc":1} AXRowIndexRange={"len":1,"loc":1}
 ++++++++AXStaticText AXValue='Smith'
 ++++AXColumn AXHeader='AXCell Firstname' AXIndex='0'
 ++++AXColumn AXHeader='AXCell Lastname' AXIndex='1'
-++++AXGroup
\ No newline at end of file
+++++AXGroup
diff --git a/content/test/data/accessibility/html/table-th-rowheader-expected-mac.txt b/content/test/data/accessibility/html/table-th-rowheader-expected-mac.txt
index e33f9b33..0876a9af 100644
--- a/content/test/data/accessibility/html/table-th-rowheader-expected-mac.txt
+++ b/content/test/data/accessibility/html/table-th-rowheader-expected-mac.txt
@@ -1,15 +1,15 @@
 AXWebArea AXTitle='Table example - th rowheader'
-++AXTable AXColumnHeaderUIElements=[] AXHeader='AXGroup' AXRowHeaderUIElements=["AXCell Firstname","AXCell Lastname"]
+++AXTable AXHeader='AXGroup' AXRowHeaderUIElements=["AXCell Firstname","AXCell Lastname"]
 ++++AXRow AXIndex='0'
-++++++AXCell AXTitle='Firstname' AXColumnHeaderUIElements=[] AXColumnIndexRange={"len":1,"loc":0} AXRowHeaderUIElements=["AXCell Firstname","AXCell Lastname"] AXRowIndexRange={"len":1,"loc":0}
+++++++AXCell AXTitle='Firstname' AXColumnIndexRange={"len":1,"loc":0} AXRowIndexRange={"len":1,"loc":0}
 ++++++++AXStaticText AXValue='Firstname'
-++++++AXCell AXTitle='Jill' AXColumnHeaderUIElements=[] AXColumnIndexRange={"len":1,"loc":1} AXRowHeaderUIElements=["AXCell Firstname","AXCell Lastname"] AXRowIndexRange={"len":1,"loc":0}
+++++++AXCell AXTitle='Jill' AXColumnIndexRange={"len":1,"loc":1} AXRowHeaderUIElements=["AXCell Firstname"] AXRowIndexRange={"len":1,"loc":0}
 ++++++++AXStaticText AXValue='Jill'
 ++++AXRow AXIndex='1'
-++++++AXCell AXTitle='Lastname' AXColumnHeaderUIElements=[] AXColumnIndexRange={"len":1,"loc":0} AXRowHeaderUIElements=["AXCell Firstname","AXCell Lastname"] AXRowIndexRange={"len":1,"loc":1}
+++++++AXCell AXTitle='Lastname' AXColumnIndexRange={"len":1,"loc":0} AXRowIndexRange={"len":1,"loc":1}
 ++++++++AXStaticText AXValue='Lastname'
-++++++AXCell AXTitle='Smith' AXColumnHeaderUIElements=[] AXColumnIndexRange={"len":1,"loc":1} AXRowHeaderUIElements=["AXCell Firstname","AXCell Lastname"] AXRowIndexRange={"len":1,"loc":1}
+++++++AXCell AXTitle='Smith' AXColumnIndexRange={"len":1,"loc":1} AXRowHeaderUIElements=["AXCell Lastname"] AXRowIndexRange={"len":1,"loc":1}
 ++++++++AXStaticText AXValue='Smith'
 ++++AXColumn AXIndex='0'
 ++++AXColumn AXIndex='1'
-++++AXGroup
\ No newline at end of file
+++++AXGroup
diff --git a/content/test/data/page_state/serialized_document_state.dat b/content/test/data/page_state/serialized_document_state.dat
new file mode 100644
index 0000000..f21cba4
--- /dev/null
+++ b/content/test/data/page_state/serialized_document_state.dat
@@ -0,0 +1,7 @@
+eAEAABoAAABwAQAAGAAAAAAAAAAQAAAAAAAAABAAAAAAAAAACAAAAAAAAABgAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAOAAAAAAAAAAAAAAAAQAAALAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAANgAAAAAAAAA8AAAAAAAAAAQAAAAAQAAAAgAAAAAAAAAEAAAAAAAAAAIAAAAAAAA
+AGgAAAAwAAAACgANAD8AJQAgAFcAZQBiAEsAaQB0ACAAcwBlAHIAaQBhAGwAaQB6AGUAZAAgAGYA
+bwByAG0AIABzAHQAYQB0AGUAIAB2AGUAcgBzAGkAbwBuACAAOAAgAAoADQA9ACYAIAAAAAAAAAAY
+AAAAAAAAACAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAACAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACAAAAAAAAAA=
diff --git a/content/test/data/page_state/serialized_http_body.dat b/content/test/data/page_state/serialized_http_body.dat
new file mode 100644
index 0000000..3cf8372
--- /dev/null
+++ b/content/test/data/page_state/serialized_http_body.dat
@@ -0,0 +1,12 @@
+eAIAABoAAABwAgAAGAAAAAAAAAAQAAAAAAAAABAAAAAAAAAACAAAAAAAAABgAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAOAAAAAAAAAAAAAAAAQAAADAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAFgAAAAAAAAA8AEAAAAAAAAIAAAAAAAAACAAAAAAAAAAGAAAAAAAAAAgAAAAAAAA
+AAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAgAAAAAAAAABgAAAAAAAAA
+OAAAAAAAAAAAAAAAAAAAABAAAAAAAAAACAAAAAAAAAAYAAAACAAAAHQAZQB4AHQALwBmAG8AbwAg
+AAAAAAAAABgAAAAAAAAAOTAAAAAAAAAAAAAAAAAAAEgAAAAEAAAAEAAAAAEAAAA4AAAAAAAAABAA
+AAAAAAAAOAAAAAAAAAAQAAAAAgAAAEAAAAAAAAAAEAAAAAMAAACQAAAAAAAAAAsAAAADAAAAZm9v
+AAAAAAARAAAACQAAAHNvbWVfdXVpZAAAAAAAAAAoAAAAAAAAACAAAAAAAAAAZAAAAAAAAAAABAAA
+AAAAADAAAAAAAAAAEAAAAAAAAAAIAAAAAAAAABgAAAAIAAAAZgBpAGwAZQAuAHQAeAB0ABAAAAAA
+AAAAwOGCnJheKQAoAAAAAAAAACAAAAAAAAAAZAAAAAAAAAAABAAAAAAAADgAAAAAAAAAEAAAAAAA
+AAAIAAAAAAAAAB0AAAAVAAAAZmlsZTovL3NvbWVfZmlsZS50eHQvAAAAEAAAAAAAAADA4YKcmF4p
+AAgAAAAAAAAA
diff --git a/content/test/data/page_state/serialized_referenced_files.dat b/content/test/data/page_state/serialized_referenced_files.dat
new file mode 100644
index 0000000..d6536d2
--- /dev/null
+++ b/content/test/data/page_state/serialized_referenced_files.dat
@@ -0,0 +1,6 @@
+KAEAABoAAAAgAQAAGAAAAAAAAAAQAAAAAAAAAEAAAAAAAAAAEAAAAAEAAAAIAAAAAAAAABAAAAAA
+AAAACAAAAAAAAAAYAAAACAAAAGYAaQBsAGUALgB0AHgAdABgAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAOAAAAAAAAAAAAAAAAQAAADAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AFgAAAAAAAAAcAAAAAAAAAAIAAAAAAAAACAAAAAAAAAAGAAAAAAAAAAgAAAAAAAAAAAAAAAAAAAA
+EAAAAAAAAAAAAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAgAAAAAAAAA
diff --git a/content/test/data/page_state/serialized_referrer.dat b/content/test/data/page_state/serialized_referrer.dat
new file mode 100644
index 0000000..98d8fad
--- /dev/null
+++ b/content/test/data/page_state/serialized_referrer.dat
@@ -0,0 +1,6 @@
+QAEAABoAAAA4AQAAGAAAAAAAAAAQAAAAAAAAABAAAAAAAAAACAAAAAAAAABgAAAAAAAAAAAAAAAA
+AAAAUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgAAAAAAAAAAAAAAAAQAAAHgAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAKAAAAAAAAAAuAAAAAAAAAAQAAAAAAAAAAgAAAAAAAAAMgAAABUAAABoAHQAdABw
+ADoALwAvAHcAdwB3AC4AZwBvAG8AZwBsAGUALgBjAG8AbQAAAAAAAAAIAAAAAAAAACAAAAAAAAAA
+GAAAAAAAAAAgAAAAAAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAg
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgAAAAAAAAA
diff --git a/content/test/data/page_state/serialized_referrer_policy.dat b/content/test/data/page_state/serialized_referrer_policy.dat
new file mode 100644
index 0000000..38e2981
--- /dev/null
+++ b/content/test/data/page_state/serialized_referrer_policy.dat
@@ -0,0 +1,5 @@
++AAAABoAAADwAAAAGAAAAAAAAAAQAAAAAAAAABAAAAAAAAAACAAAAAAAAABgAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAOAAAAAAAAAAAAAAAAAAAADAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAFgAAAAAAAAAcAAAAAAAAAAIAAAAAAAAACAAAAAAAAAAGAAAAAAAAAAgAAAAAAAA
+AAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAgAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAgAAAAAAAAA
diff --git a/content/test/data/page_state/serialized_scroll_offset.dat b/content/test/data/page_state/serialized_scroll_offset.dat
new file mode 100644
index 0000000..f078ed94
--- /dev/null
+++ b/content/test/data/page_state/serialized_scroll_offset.dat
@@ -0,0 +1,5 @@
++AAAABoAAADwAAAAGAAAAAAAAAAQAAAAAAAAABAAAAAAAAAACAAAAAAAAABgAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAOAAAAAAAAAAAAAAAAQAAADAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAFgAAAAAAAAAcAAAAAAAAAAIAAAAAAAAACAAAAAAAAAAGAAAAAAAAAAgAAAAAAAA
+AAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAABAAAAAAAAAAAQAAAP////8gAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAgAAAAAAAAA
diff --git a/content/test/data/page_state/serialized_scroll_restoration_type.dat b/content/test/data/page_state/serialized_scroll_restoration_type.dat
new file mode 100644
index 0000000..21adc12
--- /dev/null
+++ b/content/test/data/page_state/serialized_scroll_restoration_type.dat
@@ -0,0 +1,5 @@
++AAAABoAAADwAAAAGAAAAAAAAAAQAAAAAAAAABAAAAAAAAAACAAAAAAAAABgAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAOAAAAAAAAAABAAAAAQAAADAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAFgAAAAAAAAAcAAAAAAAAAAIAAAAAAAAACAAAAAAAAAAGAAAAAAAAAAgAAAAAAAA
+AAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAgAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAgAAAAAAAAA
diff --git a/content/test/data/page_state/serialized_state_object.dat b/content/test/data/page_state/serialized_state_object.dat
new file mode 100644
index 0000000..59db11d7
--- /dev/null
+++ b/content/test/data/page_state/serialized_state_object.dat
@@ -0,0 +1,6 @@
+IAEAABoAAAAYAQAAGAAAAAAAAAAQAAAAAAAAABAAAAAAAAAACAAAAAAAAABgAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAEAAAAAAAAAAYAAAAAAAAAAAAAAAAQAAAFgAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAIAAAAAAAAAAmAAAAAAAAAAQAAAAAAAAAAgAAAAAAAAAEgAAAAUAAABzAHQAYQB0
+AGUAAAAAAAAACAAAAAAAAAAgAAAAAAAAABgAAAAAAAAAIAAAAAAAAAAAAAAAAAAAABAAAAAAAAAA
+AAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAI
+AAAAAAAAAA==
diff --git a/content/test/data/page_state/serialized_target.dat b/content/test/data/page_state/serialized_target.dat
new file mode 100644
index 0000000..991d6aff
--- /dev/null
+++ b/content/test/data/page_state/serialized_target.dat
@@ -0,0 +1,6 @@
+QAEAABoAAAA4AQAAGAAAAAAAAAAQAAAAAAAAABAAAAAAAAAACAAAAAAAAABgAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAABIAAAAAAAAAAAAAAAAAAAAgAAAAAAAAAAAAAAAAQAAAHgAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAKAAAAAAAAAAuAAAAAAAAAAQAAAAAAAAAAgAAAAAAAAAMgAAABUAAABoAHQAdABw
+ADoALwAvAHcAdwB3AC4AZwBvAG8AZwBsAGUALgBjAG8AbQAAAAAAAAAIAAAAAAAAACAAAAAAAAAA
+GAAAAAAAAAAgAAAAAAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAg
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgAAAAAAAAA
diff --git a/content/test/data/page_state/serialized_url_string.dat b/content/test/data/page_state/serialized_url_string.dat
new file mode 100644
index 0000000..b3f0f92
--- /dev/null
+++ b/content/test/data/page_state/serialized_url_string.dat
@@ -0,0 +1,6 @@
+OAEAABoAAAAwAQAAGAAAAAAAAAAQAAAAAAAAABAAAAAAAAAACAAAAAAAAABgAAAAAAAAAFgAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAeAAAAAAAAAAAAAAAAQAAAHAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAJgAAAAAAAAAsAAAAAAAAAAQAAAAAAAAAAgAAAAAAAAALgAAABMAAABoAHQAdABw
+ADoALwAvAGMAaAByAG8AbQBpAHUAbQAuAG8AcgBnAAAACAAAAAAAAAAgAAAAAAAAABgAAAAAAAAA
+IAAAAAAAAAAAAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAIAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIAAAAAAAAAA==
diff --git a/content/test/data/page_state/serialized_v25.dat b/content/test/data/page_state/serialized_v25.dat
new file mode 100644
index 0000000..d170a3f
--- /dev/null
+++ b/content/test/data/page_state/serialized_v25.dat
@@ -0,0 +1,17 @@
+tAMAABkAAAABAAAAEAAAAGYAaQBsAGUALgB0AHgAdAAoAAAAaAB0AHQAcAA6AC8ALwBjAGgAcgBv
+AG0AaQB1AG0ALgBvAHIAZwAvAAwAAAB0AGEAcgBnAGUAdAABAAAAKgAAANb///8kAAAAaAB0AHQA
+cAA6AC8ALwBnAG8AbwBnAGwAZQAuAGMAbwBtAC8ACAAAAGAAAAAKAA0APwAlACAAVwBlAGIASwBp
+AHQAIABzAGUAcgBpAGEAbABpAHoAZQBkACAAZgBvAHIAbQAgAHMAdABhAHQAZQAgAHYAZQByAHMA
+aQBvAG4AIAA4ACAACgANAD0AJgAQAAAAZgBvAHIAbQAgAGsAZQB5AAIAAAAxAAAABgAAAGYAbwBv
+AAAACAAAAGYAaQBsAGUAAgAAADIAAAAQAAAAZgBpAGwAZQAuAHQAeAB0ABYAAABkAGkAcwBwAGwA
+YQB5AE4AYQBtAGUAAAAIAAAAAAAAAAAAAEB7AAAAAAAAAMgBAAAAAAAAAQAAAAgAAAAAAAAAAADw
+vwgAAAAAAAAAAADwvwAAAAAAAAAAAQAAAAMAAAAAAAAAEAAAAGZpcnN0IGRhdGEgYmxvY2sBAAAA
+EAAAAGYAaQBsAGUALgB0AHgAdAAAAAAAAAAAAP//////////CAAAAAAAAAAAAAAAAAAAAA8AAABk
+YXRhIHRoZSBzZWNvbmQAFQMAAAAAAAAAAAAADgAAAGYAbwBvAC8AYgBhAHIAAAABAAAAKAAAAGgA
+dAB0AHAAOgAvAC8AYwBoAHIAbwBtAGkAdQBtAC4AbwByAGcALwD/////AQAAACoAAADW////JAAA
+AGgAdAB0AHAAOgAvAC8AZwBvAG8AZwBsAGUALgBjAG8AbQAvAAgAAABgAAAACgANAD8AJQAgAFcA
+ZQBiAEsAaQB0ACAAcwBlAHIAaQBhAGwAaQB6AGUAZAAgAGYAbwByAG0AIABzAHQAYQB0AGUAIAB2
+AGUAcgBzAGkAbwBuACAAOAAgAAoADQA9ACYAEAAAAGYAbwByAG0AIABrAGUAeQACAAAAMQAAAAYA
+AABmAG8AbwAAAAgAAABmAGkAbABlAAIAAAAyAAAAEAAAAGYAaQBsAGUALgB0AHgAdAAWAAAAZABp
+AHMAcABsAGEAeQBOAGEAbQBlAAAACAAAAAAAAAAAAABAewAAAAAAAADIAQAAAAAAAAEAAAAIAAAA
+AAAAAAAA8L8IAAAAAAAAAAAA8L8AAAAAAAAAAAAAAAD/////AAAAAA==
diff --git a/content/test/data/page_state/serialized_v26.dat b/content/test/data/page_state/serialized_v26.dat
new file mode 100644
index 0000000..fcbd5159
--- /dev/null
+++ b/content/test/data/page_state/serialized_v26.dat
@@ -0,0 +1,35 @@
+qAcAABoAAACgBwAAGAAAAAAAAAAQAAAAAAAAAEAAAAAAAAAAEAAAAAEAAAAIAAAAAAAAABAAAAAA
+AAAACAAAAAAAAAAYAAAACAAAAGYAaQBsAGUALgB0AHgAdABgAAAAAAAAAFgAAAAAAAAAkAAAAAAA
+AADIAAAAAAAAAAAAAAAAAAAA4AAAAAAAAAAAAAAAAQAAAJACAAAAAAAAewAAAAAAAADIAQAAAAAA
+ALgCAAAAAAAA4AMAAAAAAAAQAAAAAAAAAAgAAAAAAAAAMAAAABQAAABoAHQAdABwADoALwAvAGMA
+aAByAG8AbQBpAHUAbQAuAG8AcgBnAC8AEAAAAAAAAAAIAAAAAAAAACwAAAASAAAAaAB0AHQAcAA6
+AC8ALwBnAG8AbwBnAGwAZQAuAGMAbwBtAC8AAAAAABAAAAAAAAAACAAAAAAAAAAUAAAABgAAAHQA
+YQByAGcAZQB0AAAAAABIAAAACAAAAEAAAAAAAAAAsAAAAAAAAADQAAAAAAAAAOgAAAAAAAAAAAEA
+AAAAAAAYAQAAAAAAADABAAAAAAAAUAEAAAAAAAAQAAAAAAAAAAgAAAAAAAAAaAAAADAAAAAKAA0A
+PwAlACAAVwBlAGIASwBpAHQAIABzAGUAcgBpAGEAbABpAHoAZQBkACAAZgBvAHIAbQAgAHMAdABh
+AHQAZQAgAHYAZQByAHMAaQBvAG4AIAA4ACAACgANAD0AJgAQAAAAAAAAAAgAAAAAAAAAGAAAAAgA
+AABmAG8AcgBtACAAawBlAHkAEAAAAAAAAAAIAAAAAAAAAAoAAAABAAAAMQAAAAAAAAAQAAAAAAAA
+AAgAAAAAAAAADgAAAAMAAABmAG8AbwAAABAAAAAAAAAACAAAAAAAAAAQAAAABAAAAGYAaQBsAGUA
+EAAAAAAAAAAIAAAAAAAAAAoAAAABAAAAMgAAAAAAAAAQAAAAAAAAAAgAAAAAAAAAGAAAAAgAAABm
+AGkAbABlAC4AdAB4AHQAEAAAAAAAAAAIAAAAAAAAAB4AAAALAAAAZABpAHMAcABsAGEAeQBOAGEA
+bQBlAAAAIAAAAAAAAAAYAAAAAAAAACAAAAAAAAAAAAAAAAAAAEAQAAAAAAAAAAAAgL8AAIC/EAAA
+AAAAAAAqAAAA1v///yAAAAAAAAAAGAAAAAAAAAA4AAAAAAAAAAAAAAAAAAAAEAAAAAAAAAAIAAAA
+AAAAABYAAAAHAAAAZgBvAG8ALwBiAGEAcgAAACAAAAAAAAAAGAAAAAAAAAAVAwAAAAAAAAAAAAAA
+AAAAOAAAAAMAAAAQAAAAAQAAACgAAAAAAAAAEAAAAAIAAAAwAAAAAAAAABAAAAABAAAAgAAAAAAA
+AAAYAAAAEAAAAGZpcnN0IGRhdGEgYmxvY2soAAAAAAAAACAAAAAAAAAAAAAAAAAAAAD/////////
+/zAAAAAAAAAAEAAAAAAAAAAIAAAAAAAAABgAAAAIAAAAZgBpAGwAZQAuAHQAeAB0ABAAAAAAAAAA
+AAAAAAAAAAAXAAAADwAAAGRhdGEgdGhlIHNlY29uZAAQAAAAAQAAAAgAAAAAAAAAYAAAAAAAAABY
+AAAAAAAAAJAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALgAAAAAAAAAAAAAAAEAAABoAgAAAAAAAHsA
+AAAAAAAAyAEAAAAAAACQAgAAAAAAAKgCAAAAAAAAEAAAAAAAAAAIAAAAAAAAADAAAAAUAAAAaAB0
+AHQAcAA6AC8ALwBjAGgAcgBvAG0AaQB1AG0ALgBvAHIAZwAvABAAAAAAAAAACAAAAAAAAAAsAAAA
+EgAAAGgAdAB0AHAAOgAvAC8AZwBvAG8AZwBsAGUALgBjAG8AbQAvAAAAAABIAAAACAAAAEAAAAAA
+AAAAsAAAAAAAAADQAAAAAAAAAOgAAAAAAAAAAAEAAAAAAAAYAQAAAAAAADABAAAAAAAAUAEAAAAA
+AAAQAAAAAAAAAAgAAAAAAAAAaAAAADAAAAAKAA0APwAlACAAVwBlAGIASwBpAHQAIABzAGUAcgBp
+AGEAbABpAHoAZQBkACAAZgBvAHIAbQAgAHMAdABhAHQAZQAgAHYAZQByAHMAaQBvAG4AIAA4ACAA
+CgANAD0AJgAQAAAAAAAAAAgAAAAAAAAAGAAAAAgAAABmAG8AcgBtACAAawBlAHkAEAAAAAAAAAAI
+AAAAAAAAAAoAAAABAAAAMQAAAAAAAAAQAAAAAAAAAAgAAAAAAAAADgAAAAMAAABmAG8AbwAAABAA
+AAAAAAAACAAAAAAAAAAQAAAABAAAAGYAaQBsAGUAEAAAAAAAAAAIAAAAAAAAAAoAAAABAAAAMgAA
+AAAAAAAQAAAAAAAAAAgAAAAAAAAAGAAAAAgAAABmAGkAbABlAC4AdAB4AHQAEAAAAAAAAAAIAAAA
+AAAAAB4AAAALAAAAZABpAHMAcABsAGEAeQBOAGEAbQBlAAAAIAAAAAAAAAAYAAAAAAAAACAAAAAA
+AAAAAAAAAAAAAEAQAAAAAAAAAAAAgL8AAIC/EAAAAAAAAAAqAAAA1v///yAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAACAAAAAAAAAA=
diff --git a/content/test/data/page_state/serialized_visual_viewport_scroll_offset.dat b/content/test/data/page_state/serialized_visual_viewport_scroll_offset.dat
new file mode 100644
index 0000000..6c1524e
--- /dev/null
+++ b/content/test/data/page_state/serialized_visual_viewport_scroll_offset.dat
@@ -0,0 +1,5 @@
++AAAABoAAADwAAAAGAAAAAAAAAAQAAAAAAAAABAAAAAAAAAACAAAAAAAAABgAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAOAAAAAAAAAAAAAAAAQAAADAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAFgAAAAAAAAAcAAAAAAAAAAIAAAAAAAAACAAAAAAAAAAGAAAAAAAAAAgAAAAAAAA
+AAAAAAAAAAAAEAAAAAAAAADNzChCzcwowhAAAAAAAAAAAAAAAAAAAAAgAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAgAAAAAAAAA
diff --git a/content/test/fake_compositor_dependencies.cc b/content/test/fake_compositor_dependencies.cc
index 4187c49d..ad987db 100644
--- a/content/test/fake_compositor_dependencies.cc
+++ b/content/test/fake_compositor_dependencies.cc
@@ -9,6 +9,7 @@
 #include "base/memory/ptr_util.h"
 #include "base/single_thread_task_runner.h"
 #include "base/threading/thread_task_runner_handle.h"
+#include "cc/test/test_ukm_recorder_factory.h"
 #include "third_party/khronos/GLES2/gl2.h"
 #include "ui/gfx/buffer_types.h"
 
@@ -88,4 +89,9 @@
   return false;
 }
 
+std::unique_ptr<cc::UkmRecorderFactory>
+FakeCompositorDependencies::CreateUkmRecorderFactory() {
+  return std::make_unique<cc::TestUkmRecorderFactory>();
+}
+
 }  // namespace content
diff --git a/content/test/fake_compositor_dependencies.h b/content/test/fake_compositor_dependencies.h
index 23483de..f22d4db 100644
--- a/content/test/fake_compositor_dependencies.h
+++ b/content/test/fake_compositor_dependencies.h
@@ -38,6 +38,7 @@
   cc::TaskGraphRunner* GetTaskGraphRunner() override;
   bool IsThreadedAnimationEnabled() override;
   bool IsScrollAnimatorEnabled() override;
+  std::unique_ptr<cc::UkmRecorderFactory> CreateUkmRecorderFactory() override;
 
  private:
   cc::TestTaskGraphRunner task_graph_runner_;
diff --git a/content/test/gpu/gpu_tests/gpu_process_expectations.py b/content/test/gpu/gpu_tests/gpu_process_expectations.py
index fa4c262..fa3778e 100644
--- a/content/test/gpu/gpu_tests/gpu_process_expectations.py
+++ b/content/test/gpu/gpu_tests/gpu_process_expectations.py
@@ -39,7 +39,3 @@
 
     # Seems to have become flaky on Windows recently.
     self.Flaky('GpuProcess_only_one_workaround', ['win'], bug=700522)
-
-    # Seems to trigger SwiftShader, so the test becomes invalid.
-    # Will re-enable this test once we move SwiftShader decision to GPU process.
-    self.Skip('GpuProcess_readback_webgl_gpu_process', ['linux'], bug=732623)
diff --git a/content/test/gpu/gpu_tests/gpu_process_integration_test.py b/content/test/gpu/gpu_tests/gpu_process_integration_test.py
index 9feed23..3ef1a259 100644
--- a/content/test/gpu/gpu_tests/gpu_process_integration_test.py
+++ b/content/test/gpu/gpu_tests/gpu_process_integration_test.py
@@ -73,6 +73,7 @@
              ('GpuProcess_gpu_info_complete', 'gpu/functional_3d_css.html'),
              ('GpuProcess_no_gpu_process', 'about:blank'),
              ('GpuProcess_driver_bug_workarounds_in_gpu_process', 'chrome:gpu'),
+             ('GpuProcess_readback_webgl_gpu_process', 'chrome:gpu'),
              ('GpuProcess_driver_bug_workarounds_upon_gl_renderer',
               'chrome:gpu'),
              ('GpuProcess_only_one_workaround', 'chrome:gpu'),
@@ -251,10 +252,7 @@
       self.fail('Browser must support GPU aux attributes')
     if not 'gl_renderer' in system_info.gpu.aux_attributes:
       self.fail('Browser must have gl_renderer in aux attribs')
-    if (len(system_info.gpu.aux_attributes['gl_renderer']) <= 0 and
-        sys.platform != 'darwin'):
-      # We don't create a GL context and collect GL strings on GPU process
-      # startup on MacOSX because it's too slow.
+    if len(system_info.gpu.aux_attributes['gl_renderer']) <= 0:
       self.fail('Must have a non-empty gl_renderer string')
 
   def _GpuProcess_no_gpu_process(self, test_path):
@@ -297,6 +295,39 @@
     self._ValidateDriverBugWorkarounds(
       'use_gpu_driver_workaround_for_testing', None)
 
+  def _GpuProcess_readback_webgl_gpu_process(self, test_path):
+    # This test was designed to only run on desktop Linux.
+    options = self.__class__._original_finder_options.browser_options
+    is_platform_android = options.browser_type.startswith('android')
+    if sys.platform.startswith('linux') and not is_platform_android:
+      # Hit id 110 from kSoftwareRenderingListEntries.
+      self.RestartBrowserIfNecessaryWithArgs([
+        '--gpu-testing-vendor-id=0x10de',
+        '--gpu-testing-device-id=0x0de1',
+        '--gpu-testing-gl-vendor=VMware',
+        '--gpu-testing-gl-renderer=Gallium 0.4 ' \
+        'on llvmpipe (LLVM 3.4, 256 bits)',
+        '--gpu-testing-gl-version="3.0 Mesa 11.2"'])
+      self._Navigate(test_path)
+      feature_status_list = self.tab.EvaluateJavaScript(
+          'browserBridge.gpuInfo.featureStatus.featureStatus')
+      result = True
+      for name, status in feature_status_list.items():
+        if name == 'multiple_raster_threads':
+          result = result and status == 'enabled_on'
+        elif name == 'native_gpu_memory_buffers':
+          result = result and status == 'disabled_software'
+        elif name == 'webgl':
+          result = result and status == 'enabled_readback'
+        elif name == 'webgl2':
+          result = result and status == 'unavailable_software'
+        elif name == 'checker_imaging':
+          pass
+        else:
+          result = result and status == 'unavailable_software'
+      if not result:
+        self.fail('WebGL readback setup failed: %s' % feature_status_list)
+
   def _GpuProcess_driver_bug_workarounds_upon_gl_renderer(self, test_path):
     is_platform_android = self._RunningOnAndroid()
     if is_platform_android:
diff --git a/content/test/gpu/gpu_tests/pixel_expectations.py b/content/test/gpu/gpu_tests/pixel_expectations.py
index 474c8a2..ef75abb 100644
--- a/content/test/gpu/gpu_tests/pixel_expectations.py
+++ b/content/test/gpu/gpu_tests/pixel_expectations.py
@@ -28,8 +28,8 @@
     self.Fail('Pixel_ScissorTestWithPreserveDrawingBuffer',
         ['android'], bug=521588)
 
-    # TODO(ccameron) fix these on Mac Retina
-    self.Fail('Pixel_CSS3DBlueBox', ['mac'], bug=533690)
+    # TODO(ccameron) fix these on Mac Retina, commented for
+    # self.Fail('Pixel_CSS3DBlueBox', ['mac'], bug=533690)
 
     # TODO(vmiura) check / generate reference images for Android devices
     self.Fail('Pixel_SolidColorBackground', ['mac', 'android'], bug=624256)
@@ -66,11 +66,8 @@
     self.Skip('Pixel_WebGL2_ClearBufferfv_Result_Displayed',
         ['android', ('qualcomm', 'Adreno (TM) 330')], bug=773293)
 
-    # Failing on Nexus 5 and 5X
-    self.Fail('Pixel_CSS3DBlueBox',
-        ['android', ('qualcomm', 'Adreno (TM) 330')], bug=774354)
-    self.Fail('Pixel_CSS3DBlueBox',
-        ['android', ('qualcomm', 'Adreno (TM) 418')], bug=774354)
+    # Rebaseline Pixel_CSS3DBlueBox
+    self.Fail('Pixel_CSS3DBlueBox', bug=774354)
 
     # Failing on Mac Intel HighSierra
     self.Fail('Pixel_Video_MP4',
diff --git a/content/test/gpu/gpu_tests/pixel_test_pages.py b/content/test/gpu/gpu_tests/pixel_test_pages.py
index bc31b70..7d5c1a0 100644
--- a/content/test/gpu/gpu_tests/pixel_test_pages.py
+++ b/content/test/gpu/gpu_tests/pixel_test_pages.py
@@ -64,7 +64,7 @@
       'pixel_css3d.html',
       base_name + '_CSS3DBlueBox',
       test_rect=[0, 0, 300, 300],
-      revision=16),
+      revision=17),
 
     PixelTestPage(
       'pixel_webgl_aa_alpha.html',
diff --git a/content/test/layouttest_support.cc b/content/test/layouttest_support.cc
index 30c9b172..a56bd05 100644
--- a/content/test/layouttest_support.cc
+++ b/content/test/layouttest_support.cc
@@ -101,7 +101,7 @@
                                     bool>;
 using WebFrameTestProxyType =
     test_runner::WebFrameTestProxy<RenderFrameImpl,
-                                   const RenderFrameImpl::CreateParams&>;
+                                   RenderFrameImpl::CreateParams>;
 
 RenderViewImpl* CreateWebViewTestProxy(CompositorDependencies* compositor_deps,
                                        const mojom::CreateViewParams& params) {
@@ -135,9 +135,9 @@
   }
 }
 
-RenderFrameImpl* CreateWebFrameTestProxy(
-    const RenderFrameImpl::CreateParams& params) {
-  WebFrameTestProxyType* render_frame_proxy = new WebFrameTestProxyType(params);
+RenderFrameImpl* CreateWebFrameTestProxy(RenderFrameImpl::CreateParams params) {
+  WebFrameTestProxyType* render_frame_proxy =
+      new WebFrameTestProxyType(std::move(params));
   if (g_frame_test_proxy_callback == 0)
     return render_frame_proxy;
   g_frame_test_proxy_callback.Get().Run(render_frame_proxy, render_frame_proxy);
diff --git a/content/test/mock_platform_notification_service.cc b/content/test/mock_platform_notification_service.cc
index cb14254..17c22a31 100644
--- a/content/test/mock_platform_notification_service.cc
+++ b/content/test/mock_platform_notification_service.cc
@@ -22,23 +22,17 @@
 
 }  // namespace
 
-MockPlatformNotificationService::MockPlatformNotificationService()
-    : weak_factory_(this) {}
+MockPlatformNotificationService::MockPlatformNotificationService() = default;
 
-MockPlatformNotificationService::~MockPlatformNotificationService() {}
+MockPlatformNotificationService::~MockPlatformNotificationService() = default;
 
 void MockPlatformNotificationService::DisplayNotification(
     BrowserContext* browser_context,
     const std::string& notification_id,
     const GURL& origin,
     const PlatformNotificationData& notification_data,
-    const NotificationResources& notification_resources,
-    base::Closure* cancel_callback) {
+    const NotificationResources& notification_resources) {
   DCHECK_CURRENTLY_ON(BrowserThread::UI);
-  DCHECK(cancel_callback);
-
-  *cancel_callback = base::Bind(&MockPlatformNotificationService::Close,
-                                weak_factory_.GetWeakPtr(), notification_id);
 
   ReplaceNotificationIfNeeded(notification_id);
   non_persistent_notifications_.insert(notification_id);
@@ -70,6 +64,22 @@
       notification_id;
 }
 
+void MockPlatformNotificationService::CloseNotification(
+    BrowserContext* browser_context,
+    const std::string& notification_id) {
+  DCHECK_CURRENTLY_ON(BrowserThread::UI);
+
+  const auto non_persistent_iter =
+      non_persistent_notifications_.find(notification_id);
+  if (non_persistent_iter == non_persistent_notifications_.end())
+    return;
+
+  NotificationEventDispatcher::GetInstance()->DispatchNonPersistentCloseEvent(
+      notification_id);
+
+  non_persistent_notifications_.erase(non_persistent_iter);
+}
+
 void MockPlatformNotificationService::ClosePersistentNotification(
     BrowserContext* browser_context,
     const std::string& notification_id) {
@@ -162,18 +172,6 @@
   return CheckPermission(origin);
 }
 
-void MockPlatformNotificationService::Close(
-    const std::string& notification_id) {
-  DCHECK_CURRENTLY_ON(BrowserThread::UI);
-  const auto non_persistent_iter =
-      non_persistent_notifications_.find(notification_id);
-  if (non_persistent_iter == non_persistent_notifications_.end()) {
-    NotificationEventDispatcher::GetInstance()->DispatchNonPersistentCloseEvent(
-        notification_id);
-    non_persistent_notifications_.erase(non_persistent_iter);
-  }
-}
-
 void MockPlatformNotificationService::ReplaceNotificationIfNeeded(
     const std::string& notification_id) {
   persistent_notifications_.erase(notification_id);
diff --git a/content/test/mock_platform_notification_service.h b/content/test/mock_platform_notification_service.h
index 466166b..c64267a 100644
--- a/content/test/mock_platform_notification_service.h
+++ b/content/test/mock_platform_notification_service.h
@@ -12,7 +12,6 @@
 
 #include "base/callback.h"
 #include "base/macros.h"
-#include "base/memory/weak_ptr.h"
 #include "base/optional.h"
 #include "base/strings/string16.h"
 #include "content/public/browser/platform_notification_service.h"
@@ -56,8 +55,7 @@
       const std::string& notification_id,
       const GURL& origin,
       const PlatformNotificationData& notification_data,
-      const NotificationResources& notification_resources,
-      base::Closure* cancel_callback) override;
+      const NotificationResources& notification_resources) override;
   void DisplayPersistentNotification(
       BrowserContext* browser_context,
       const std::string& notification_id,
@@ -65,6 +63,8 @@
       const GURL& origin,
       const PlatformNotificationData& notification_data,
       const NotificationResources& notification_resources) override;
+  void CloseNotification(BrowserContext* browser_context,
+                         const std::string& notification_id) override;
   void ClosePersistentNotification(BrowserContext* browser_context,
                                    const std::string& notification_id) override;
   void GetDisplayedNotifications(
@@ -83,9 +83,6 @@
     GURL origin;
   };
 
-  // Closes the notification titled |title|. Must be called on the UI thread.
-  void Close(const std::string& title);
-
   // Fakes replacing the notification identified by |notification_id|. Both
   // persistent and non-persistent notifications will be considered for this.
   void ReplaceNotificationIfNeeded(const std::string& notification_id);
@@ -97,8 +94,6 @@
   // Mapping of titles to notification ids giving test a usable identifier.
   std::unordered_map<std::string, std::string> notification_id_map_;
 
-  base::WeakPtrFactory<MockPlatformNotificationService> weak_factory_;
-
   DISALLOW_COPY_AND_ASSIGN(MockPlatformNotificationService);
 };
 
diff --git a/content/test/test_navigation_url_loader.cc b/content/test/test_navigation_url_loader.cc
index 4e6d54d..74405ba 100644
--- a/content/test/test_navigation_url_loader.cc
+++ b/content/test/test_navigation_url_loader.cc
@@ -7,6 +7,7 @@
 #include <utility>
 
 #include "content/browser/loader/navigation_url_loader_delegate.h"
+#include "content/common/navigation_subresource_loader_params.h"
 #include "content/public/browser/global_request_id.h"
 #include "content/public/browser/navigation_data.h"
 #include "content/public/browser/render_frame_host.h"
@@ -75,10 +76,10 @@
           ->GetProcess()
           ->GetID();
   GlobalRequestID global_id(child_id, ++request_id);
-  delegate_->OnResponseStarted(
-      response, std::move(body), mojo::ScopedDataPipeConsumerHandle(),
-      SSLStatus(), std::move(navigation_data), global_id, false, false,
-      mojom::URLLoaderFactoryPtrInfo());
+  delegate_->OnResponseStarted(response, std::move(body),
+                               mojo::ScopedDataPipeConsumerHandle(),
+                               SSLStatus(), std::move(navigation_data),
+                               global_id, false, false, base::nullopt);
 }
 
 TestNavigationURLLoader::~TestNavigationURLLoader() {}
diff --git a/content/test/test_navigation_url_loader_delegate.cc b/content/test/test_navigation_url_loader_delegate.cc
index 5b8a47f2..c3b2c2c2 100644
--- a/content/test/test_navigation_url_loader_delegate.cc
+++ b/content/test/test_navigation_url_loader_delegate.cc
@@ -5,6 +5,7 @@
 #include "content/test/test_navigation_url_loader_delegate.h"
 
 #include "base/run_loop.h"
+#include "content/common/navigation_subresource_loader_params.h"
 #include "content/public/browser/global_request_id.h"
 #include "content/public/browser/navigation_data.h"
 #include "content/public/browser/stream_handle.h"
@@ -65,7 +66,7 @@
     const GlobalRequestID& request_id,
     bool is_download,
     bool is_stream,
-    mojom::URLLoaderFactoryPtrInfo loader_factory_ptr_info) {
+    base::Optional<SubresourceLoaderParams> subresource_loader_params) {
   response_ = response;
   body_ = std::move(body);
   handle_ = std::move(consumer_handle);
diff --git a/content/test/test_navigation_url_loader_delegate.h b/content/test/test_navigation_url_loader_delegate.h
index d26bf0a..8de8383 100644
--- a/content/test/test_navigation_url_loader_delegate.h
+++ b/content/test/test_navigation_url_loader_delegate.h
@@ -61,16 +61,16 @@
   void OnRequestRedirected(
       const net::RedirectInfo& redirect_info,
       const scoped_refptr<ResourceResponse>& response) override;
-  void OnResponseStarted(
-      const scoped_refptr<ResourceResponse>& response,
-      std::unique_ptr<StreamHandle> body,
-      mojo::ScopedDataPipeConsumerHandle consumer_handle,
-      const SSLStatus& ssl_status,
-      std::unique_ptr<NavigationData> navigation_data,
-      const GlobalRequestID& request_id,
-      bool is_download,
-      bool is_stream,
-      mojom::URLLoaderFactoryPtrInfo loader_factory_ptr_info) override;
+  void OnResponseStarted(const scoped_refptr<ResourceResponse>& response,
+                         std::unique_ptr<StreamHandle> body,
+                         mojo::ScopedDataPipeConsumerHandle consumer_handle,
+                         const SSLStatus& ssl_status,
+                         std::unique_ptr<NavigationData> navigation_data,
+                         const GlobalRequestID& request_id,
+                         bool is_download,
+                         bool is_stream,
+                         base::Optional<SubresourceLoaderParams>
+                             subresource_loader_params) override;
   void OnRequestFailed(bool in_cache,
                        int net_error,
                        const base::Optional<net::SSLInfo>& ssl_info,
diff --git a/content/test/test_render_frame.cc b/content/test/test_render_frame.cc
index 6704dfe..95001684 100644
--- a/content/test/test_render_frame.cc
+++ b/content/test/test_render_frame.cc
@@ -62,12 +62,12 @@
 
 // static
 RenderFrameImpl* TestRenderFrame::CreateTestRenderFrame(
-    const RenderFrameImpl::CreateParams& params) {
-  return new TestRenderFrame(params);
+    RenderFrameImpl::CreateParams params) {
+  return new TestRenderFrame(std::move(params));
 }
 
-TestRenderFrame::TestRenderFrame(const RenderFrameImpl::CreateParams& params)
-    : RenderFrameImpl(params),
+TestRenderFrame::TestRenderFrame(RenderFrameImpl::CreateParams params)
+    : RenderFrameImpl(std::move(params)),
       mock_frame_host_(std::make_unique<MockFrameHost>()) {}
 
 TestRenderFrame::~TestRenderFrame() {}
@@ -79,7 +79,7 @@
   if (IsBrowserSideNavigationEnabled()) {
     CommitNavigation(ResourceResponseHead(), GURL(), common_params,
                      request_params, mojo::ScopedDataPipeConsumerHandle(),
-                     nullptr);
+                     base::nullopt);
   } else {
     OnNavigate(common_params, start_params, request_params);
   }
diff --git a/content/test/test_render_frame.h b/content/test/test_render_frame.h
index 854f2578..1a263529 100644
--- a/content/test/test_render_frame.h
+++ b/content/test/test_render_frame.h
@@ -27,7 +27,7 @@
 class TestRenderFrame : public RenderFrameImpl {
  public:
   static RenderFrameImpl* CreateTestRenderFrame(
-      const RenderFrameImpl::CreateParams& params);
+      RenderFrameImpl::CreateParams params);
   ~TestRenderFrame() override;
 
   const blink::WebHistoryItem& current_history_item() {
@@ -58,7 +58,7 @@
   TakeLastCommitParams();
 
  private:
-  explicit TestRenderFrame(const RenderFrameImpl::CreateParams& params);
+  explicit TestRenderFrame(RenderFrameImpl::CreateParams params);
 
   mojom::FrameHost* GetFrameHost() override;
 
diff --git a/content/test/test_render_frame_host.cc b/content/test/test_render_frame_host.cc
index b5dc056..a26889e 100644
--- a/content/test/test_render_frame_host.cc
+++ b/content/test/test_render_frame_host.cc
@@ -61,12 +61,12 @@
                         const CommonNavigationParams& common_params,
                         const RequestNavigationParams& request_params,
                         mojo::ScopedDataPipeConsumerHandle body_data,
-                        mojom::URLLoaderFactoryPtr
-                            default_subresource_url_loader_factory) override {
+                        base::Optional<URLLoaderFactoryBundle>
+                            subresource_loader_factories) override {
     frame_host_->GetProcess()->set_did_frame_commit_navigation(true);
     frame_host_->GetInternalNavigationControl()->CommitNavigation(
         head, body_url, common_params, request_params, std::move(body_data),
-        std::move(default_subresource_url_loader_factory));
+        std::move(subresource_loader_factories));
   }
 
  private:
@@ -122,10 +122,10 @@
 TestRenderFrameHost* TestRenderFrameHost::AppendChild(
     const std::string& frame_name) {
   std::string frame_unique_name = base::GenerateGUID();
-  OnCreateChildFrame(GetProcess()->GetNextRoutingID(),
-                     blink::WebTreeScopeType::kDocument, frame_name,
-                     frame_unique_name, base::UnguessableToken::Create(),
-                     FramePolicy(), FrameOwnerProperties());
+  OnCreateChildFrame(
+      GetProcess()->GetNextRoutingID(), CreateStubInterfaceProviderRequest(),
+      blink::WebTreeScopeType::kDocument, frame_name, frame_unique_name,
+      base::UnguessableToken::Create(), FramePolicy(), FrameOwnerProperties());
   return static_cast<TestRenderFrameHost*>(
       child_creation_observer_.last_created_frame());
 }
@@ -567,4 +567,11 @@
   return RenderFrameHostImpl::GetNavigationControl();
 }
 
+// static
+service_manager::mojom::InterfaceProviderRequest
+TestRenderFrameHost::CreateStubInterfaceProviderRequest() {
+  ::service_manager::mojom::InterfaceProviderPtr dead_interface_provider_proxy;
+  return mojo::MakeRequest(&dead_interface_provider_proxy);
+}
+
 }  // namespace content
diff --git a/content/test/test_render_frame_host.h b/content/test/test_render_frame_host.h
index d28bbd9b..a81f0675 100644
--- a/content/test/test_render_frame_host.h
+++ b/content/test/test_render_frame_host.h
@@ -160,6 +160,11 @@
     return last_commit_was_error_page_;
   }
 
+  // Returns a pending InterfaceProvider request that is safe to bind to an
+  // implementation, but will never receive any interface requests.
+  static service_manager::mojom::InterfaceProviderRequest
+  CreateStubInterfaceProviderRequest();
+
  private:
   class NavigationInterceptor;
 
diff --git a/content/test/test_render_view_host.cc b/content/test/test_render_view_host.cc
index 7c0f59e..bd0a262 100644
--- a/content/test/test_render_view_host.cc
+++ b/content/test/test_render_view_host.cc
@@ -276,9 +276,15 @@
   GetWidget()->set_renderer_initialized(true);
   DCHECK(IsRenderViewLive());
   opener_frame_route_id_ = opener_frame_route_id;
-  RenderFrameHost* main_frame = GetMainFrame();
-  if (main_frame)
-    static_cast<RenderFrameHostImpl*>(main_frame)->SetRenderFrameCreated(true);
+  RenderFrameHostImpl* main_frame =
+      static_cast<RenderFrameHostImpl*>(GetMainFrame());
+  if (main_frame && is_active()) {
+    service_manager::mojom::InterfaceProviderPtr
+        stub_interface_provider_request;
+    main_frame->BindInterfaceProviderRequest(
+        mojo::MakeRequest(&stub_interface_provider_request));
+    main_frame->SetRenderFrameCreated(true);
+  }
 
   return true;
 }
diff --git a/content/test/test_web_contents.cc b/content/test/test_web_contents.cc
index f31eaa4..ace913a 100644
--- a/content/test/test_web_contents.cc
+++ b/content/test/test_web_contents.cc
@@ -91,23 +91,8 @@
                                       bool did_create_new_entry,
                                       const GURL& url,
                                       ui::PageTransition transition) {
-  TestDidNavigateWithReferrer(render_frame_host,
-                              nav_entry_id,
-                              did_create_new_entry,
-                              url,
-                              Referrer(),
-                              transition);
-}
-
-void TestWebContents::TestDidNavigateWithReferrer(
-    RenderFrameHost* render_frame_host,
-    int nav_entry_id,
-    bool did_create_new_entry,
-    const GURL& url,
-    const Referrer& referrer,
-    ui::PageTransition transition) {
   TestDidNavigateWithSequenceNumber(render_frame_host, nav_entry_id,
-                                    did_create_new_entry, url, referrer,
+                                    did_create_new_entry, url, Referrer(),
                                     transition, false, -1, -1);
 }
 
@@ -299,12 +284,6 @@
     old_rfh->OnSwappedOut();
 }
 
-void TestWebContents::ProceedWithCrossSiteNavigation() {
-  if (!GetPendingMainFrame())
-    return;
-  GetMainFrame()->SendBeforeUnloadACK(true);
-}
-
 RenderViewHostDelegateView* TestWebContents::GetDelegateView() {
   if (delegate_view_override_)
     return delegate_view_override_;
diff --git a/content/test/test_web_contents.h b/content/test/test_web_contents.h
index 255b754..50256bf 100644
--- a/content/test/test_web_contents.h
+++ b/content/test/test_web_contents.h
@@ -63,18 +63,11 @@
   TestRenderFrameHost* GetPendingMainFrame() override;
   void NavigateAndCommit(const GURL& url) override;
   void TestSetIsLoading(bool value) override;
-  void ProceedWithCrossSiteNavigation() override;
   void TestDidNavigate(RenderFrameHost* render_frame_host,
                        int nav_entry_id,
                        bool did_create_new_entry,
                        const GURL& url,
                        ui::PageTransition transition) override;
-  void TestDidNavigateWithReferrer(RenderFrameHost* render_frame_host,
-                                   int nav_entry_id,
-                                   bool did_create_new_entry,
-                                   const GURL& url,
-                                   const Referrer& referrer,
-                                   ui::PageTransition transition) override;
   void TestDidNavigateWithSequenceNumber(RenderFrameHost* render_frame_host,
                                          int nav_entry_id,
                                          bool did_create_new_entry,
diff --git a/device/BUILD.gn b/device/BUILD.gn
index d366ab9..587ab9e8 100644
--- a/device/BUILD.gn
+++ b/device/BUILD.gn
@@ -158,7 +158,6 @@
       "usb/public/cpp/filter_utils_unittest.cc",
       "usb/usb_descriptors_unittest.cc",
       "usb/usb_device_handle_unittest.cc",
-      "usb/usb_ids_unittest.cc",
       "usb/usb_service_unittest.cc",
       "usb/webusb_descriptors_unittest.cc",
     ]
@@ -174,6 +173,7 @@
     ]
 
     if (!is_android) {
+      sources += [ "usb/usb_ids_unittest.cc" ]
       deps += [ "//device/hid" ]
     }
   }
diff --git a/device/gamepad/BUILD.gn b/device/gamepad/BUILD.gn
index e39da45f..93e07709 100644
--- a/device/gamepad/BUILD.gn
+++ b/device/gamepad/BUILD.gn
@@ -22,6 +22,8 @@
     "gamepad_data_fetcher_manager.cc",
     "gamepad_data_fetcher_manager.h",
     "gamepad_export.h",
+    "gamepad_haptics_manager.cc",
+    "gamepad_haptics_manager.h",
     "gamepad_monitor.cc",
     "gamepad_monitor.h",
     "gamepad_pad_state_provider.cc",
diff --git a/device/gamepad/gamepad_haptics_manager.cc b/device/gamepad/gamepad_haptics_manager.cc
new file mode 100644
index 0000000..3056c0f
--- /dev/null
+++ b/device/gamepad/gamepad_haptics_manager.cc
@@ -0,0 +1,39 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "device/gamepad/gamepad_haptics_manager.h"
+
+#include <utility>
+
+#include "base/memory/ptr_util.h"
+#include "mojo/public/cpp/bindings/strong_binding.h"
+
+namespace device {
+
+GamepadHapticsManager::GamepadHapticsManager() = default;
+
+GamepadHapticsManager::~GamepadHapticsManager() = default;
+
+// static
+void GamepadHapticsManager::Create(
+    mojom::GamepadHapticsManagerRequest request) {
+  mojo::MakeStrongBinding(base::MakeUnique<GamepadHapticsManager>(),
+                          std::move(request));
+}
+
+void GamepadHapticsManager::PlayVibrationEffectOnce(
+    int pad_index,
+    mojom::GamepadHapticEffectType type,
+    mojom::GamepadEffectParametersPtr params,
+    PlayVibrationEffectOnceCallback callback) {
+  NOTIMPLEMENTED();
+}
+
+void GamepadHapticsManager::ResetVibrationActuator(
+    int pad_index,
+    ResetVibrationActuatorCallback callback) {
+  NOTIMPLEMENTED();
+}
+
+}  // namespace device
diff --git a/device/gamepad/gamepad_haptics_manager.h b/device/gamepad/gamepad_haptics_manager.h
new file mode 100644
index 0000000..ef07c6a
--- /dev/null
+++ b/device/gamepad/gamepad_haptics_manager.h
@@ -0,0 +1,36 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef DEVICE_GAMEPAD_GAMEPAD_HAPTICS_MANAGER_H_
+#define DEVICE_GAMEPAD_GAMEPAD_HAPTICS_MANAGER_H_
+
+#include "base/macros.h"
+#include "device/gamepad/gamepad_export.h"
+#include "device/gamepad/public/interfaces/gamepad.mojom.h"
+
+namespace device {
+
+class DEVICE_GAMEPAD_EXPORT GamepadHapticsManager
+    : public mojom::GamepadHapticsManager {
+ public:
+  GamepadHapticsManager();
+  ~GamepadHapticsManager() override;
+
+  static void Create(mojom::GamepadHapticsManagerRequest request);
+
+  // mojom::GamepadHapticsManager implementation.
+  void PlayVibrationEffectOnce(int pad_index,
+                               mojom::GamepadHapticEffectType,
+                               mojom::GamepadEffectParametersPtr,
+                               PlayVibrationEffectOnceCallback) override;
+  void ResetVibrationActuator(int pad_index,
+                              ResetVibrationActuatorCallback) override;
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(GamepadHapticsManager);
+};
+
+}  // namespace device
+
+#endif  // DEVICE_GAMEPAD_GAMEPAD_HAPTICS_MANAGER_H_
diff --git a/device/gamepad/public/cpp/gamepad.h b/device/gamepad/public/cpp/gamepad.h
index c8a7e8bd..4d6a630 100644
--- a/device/gamepad/public/cpp/gamepad.h
+++ b/device/gamepad/public/cpp/gamepad.h
@@ -21,6 +21,34 @@
   double value;
 };
 
+enum class GamepadHapticActuatorType { kVibration = 0, kDualRumble = 1 };
+
+enum class GamepadHapticEffectType { kDualRumble = 0 };
+
+enum class GamepadHapticsResult {
+  kError = 0,
+  kComplete = 1,
+  kPreempted = 2,
+  kInvalidParameter = 3,
+  kNotSupported = 4
+};
+
+class GamepadHapticActuator {
+ public:
+  GamepadHapticActuator() : not_null(false) {}
+
+  bool not_null;
+  GamepadHapticActuatorType type;
+};
+
+class GamepadEffectParameters {
+ public:
+  double duration;
+  double start_delay;
+  double strong_magnitude;
+  double weak_magnitude;
+};
+
 class GamepadVector {
  public:
   GamepadVector() : not_null(false) {}
@@ -98,6 +126,8 @@
   // Button states
   GamepadButton buttons[kButtonsLengthCap];
 
+  GamepadHapticActuator vibration_actuator;
+
   // Mapping type (for example "standard")
   UChar mapping[kMappingLengthCap];
 
diff --git a/device/gamepad/public/interfaces/gamepad.mojom b/device/gamepad/public/interfaces/gamepad.mojom
index 1c670d5..465fb10 100644
--- a/device/gamepad/public/interfaces/gamepad.mojom
+++ b/device/gamepad/public/interfaces/gamepad.mojom
@@ -38,12 +38,26 @@
   GamepadHandRight = 2
 };
 
+enum GamepadHapticActuatorType {
+  GamepadHapticActuatorTypeVibration = 0,
+  GamepadHapticActuatorTypeDualRumble = 1
+};
+
+enum GamepadHapticEffectType {
+  GamepadHapticEffectTypeDualRumble = 0
+};
+
+struct GamepadHapticActuator {
+  GamepadHapticActuatorType type;
+};
+
 struct Gamepad {
   bool connected;
   array<uint16> id;
   uint64 timestamp;
   array<double> axes;
   array<GamepadButton> buttons;
+  GamepadHapticActuator? vibration_actuator;
   array<uint16> mapping;
   GamepadPose? pose;
   GamepadHand hand;
@@ -68,3 +82,26 @@
 
   SetObserver(GamepadObserver gamepad_observer);
 };
+
+struct GamepadEffectParameters {
+  double duration;
+  double start_delay;
+  double strong_magnitude;
+  double weak_magnitude;
+};
+
+enum GamepadHapticsResult {
+  GamepadHapticsResultError = 0,
+  GamepadHapticsResultComplete = 1,
+  GamepadHapticsResultPreempted = 2,
+  GamepadHapticsResultInvalidParameter = 3,
+  GamepadHapticsResultNotSupported = 4
+};
+
+interface GamepadHapticsManager {
+  PlayVibrationEffectOnce(int32 pad_index,
+                          GamepadHapticEffectType type,
+                          GamepadEffectParameters params)
+      => (GamepadHapticsResult result);
+  ResetVibrationActuator(int32 pad_index) => (GamepadHapticsResult result);
+};
diff --git a/device/gamepad/public/interfaces/gamepad.typemap b/device/gamepad/public/interfaces/gamepad.typemap
index 81850d6..43b3c0f 100644
--- a/device/gamepad/public/interfaces/gamepad.typemap
+++ b/device/gamepad/public/interfaces/gamepad.typemap
@@ -14,10 +14,15 @@
   "//third_party/WebKit/public:blink_headers",
 ]
 
+# Use typemaps for device::Gamepad and its member types. Gamepad data is
+# intentionally POD and fixed size so that it can be stored in shared memory
+# between hardware polling threads and the rest of the browser.
 type_mappings = [
   "device.mojom.Gamepad=device::Gamepad",
   "device.mojom.GamepadButton=device::GamepadButton",
   "device.mojom.GamepadHand=device::GamepadHand",
+  "device.mojom.GamepadHapticActuator=device::GamepadHapticActuator[nullable_is_same_type]",
+  "device.mojom.GamepadHapticActuatorType=device::GamepadHapticActuatorType",
   "device.mojom.GamepadPose=device::GamepadPose[nullable_is_same_type]",
   "device.mojom.GamepadQuaternion=device::GamepadQuaternion[nullable_is_same_type]",
   "device.mojom.GamepadVector=device::GamepadVector[nullable_is_same_type]",
diff --git a/device/gamepad/public/interfaces/gamepad_struct_traits.cc b/device/gamepad/public/interfaces/gamepad_struct_traits.cc
index 56e77b7..0765eae4 100644
--- a/device/gamepad/public/interfaces/gamepad_struct_traits.cc
+++ b/device/gamepad/public/interfaces/gamepad_struct_traits.cc
@@ -59,6 +59,63 @@
 }
 
 // static
+device::mojom::GamepadHapticActuatorType
+EnumTraits<device::mojom::GamepadHapticActuatorType,
+           device::GamepadHapticActuatorType>::
+    ToMojom(device::GamepadHapticActuatorType input) {
+  switch (input) {
+    case device::GamepadHapticActuatorType::kVibration:
+      return device::mojom::GamepadHapticActuatorType::
+          GamepadHapticActuatorTypeVibration;
+    case device::GamepadHapticActuatorType::kDualRumble:
+      return device::mojom::GamepadHapticActuatorType::
+          GamepadHapticActuatorTypeDualRumble;
+  }
+
+  NOTREACHED();
+  return device::mojom::GamepadHapticActuatorType::
+      GamepadHapticActuatorTypeVibration;
+}
+
+// static
+bool EnumTraits<device::mojom::GamepadHapticActuatorType,
+                device::GamepadHapticActuatorType>::
+    FromMojom(device::mojom::GamepadHapticActuatorType input,
+              device::GamepadHapticActuatorType* output) {
+  switch (input) {
+    case device::mojom::GamepadHapticActuatorType::
+        GamepadHapticActuatorTypeVibration:
+      *output = device::GamepadHapticActuatorType::kVibration;
+      return true;
+    case device::mojom::GamepadHapticActuatorType::
+        GamepadHapticActuatorTypeDualRumble:
+      *output = device::GamepadHapticActuatorType::kDualRumble;
+      return true;
+  }
+
+  NOTREACHED();
+  return false;
+}
+
+// static
+void StructTraits<device::mojom::GamepadHapticActuatorDataView,
+                  device::GamepadHapticActuator>::
+    SetToNull(device::GamepadHapticActuator* out) {
+  memset(out, 0, sizeof(device::GamepadHapticActuator));
+  out->not_null = false;
+}
+
+// static
+bool StructTraits<device::mojom::GamepadHapticActuatorDataView,
+                  device::GamepadHapticActuator>::
+    Read(device::mojom::GamepadHapticActuatorDataView data,
+         device::GamepadHapticActuator* out) {
+  if (!data.ReadType(&out->type))
+    return false;
+  return true;
+}
+
+// static
 void StructTraits<device::mojom::GamepadPoseDataView,
                   device::GamepadPose>::SetToNull(device::GamepadPose* out) {
   memset(out, 0, sizeof(device::GamepadPose));
@@ -184,6 +241,9 @@
   // static_cast is safe when "data.ReadButtons(&buttons)" above returns true.
   out->buttons_length = static_cast<unsigned>(buttons.size());
 
+  if (!data.ReadVibrationActuator(&out->vibration_actuator))
+    return false;
+
   memset(out->mapping, 0, sizeof(out->mapping));
   base::span<uint16_t> mapping(reinterpret_cast<uint16_t*>(out->mapping),
                                device::Gamepad::kMappingLengthCap);
diff --git a/device/gamepad/public/interfaces/gamepad_struct_traits.h b/device/gamepad/public/interfaces/gamepad_struct_traits.h
index e175270..07c4904 100644
--- a/device/gamepad/public/interfaces/gamepad_struct_traits.h
+++ b/device/gamepad/public/interfaces/gamepad_struct_traits.h
@@ -51,6 +51,30 @@
 };
 
 template <>
+struct EnumTraits<device::mojom::GamepadHapticActuatorType,
+                  device::GamepadHapticActuatorType> {
+  static device::mojom::GamepadHapticActuatorType ToMojom(
+      device::GamepadHapticActuatorType input);
+  static bool FromMojom(device::mojom::GamepadHapticActuatorType input,
+                        device::GamepadHapticActuatorType* output);
+};
+
+template <>
+struct StructTraits<device::mojom::GamepadHapticActuatorDataView,
+                    device::GamepadHapticActuator> {
+  static bool IsNull(const device::GamepadHapticActuator& r) {
+    return !r.not_null;
+  }
+  static void SetToNull(device::GamepadHapticActuator* out);
+  static const device::GamepadHapticActuatorType& type(
+      const device::GamepadHapticActuator& r) {
+    return r.type;
+  }
+  static bool Read(device::mojom::GamepadHapticActuatorDataView data,
+                   device::GamepadHapticActuator* out);
+};
+
+template <>
 struct StructTraits<device::mojom::GamepadPoseDataView, device::GamepadPose> {
   static bool IsNull(const device::GamepadPose& r) { return !r.not_null; }
   static void SetToNull(device::GamepadPose* out);
@@ -99,6 +123,10 @@
       const device::Gamepad& r) {
     return base::make_span(r.buttons, r.buttons_length);
   }
+  static const device::GamepadHapticActuator& vibration_actuator(
+      const device::Gamepad& r) {
+    return r.vibration_actuator;
+  }
   static const device::GamepadPose& pose(const device::Gamepad& r) {
     return r.pose;
   }
diff --git a/device/usb/BUILD.gn b/device/usb/BUILD.gn
index 260e83b..22f6f26 100644
--- a/device/usb/BUILD.gn
+++ b/device/usb/BUILD.gn
@@ -36,8 +36,6 @@
     "usb_device_win.h",
     "usb_endpoint_android.cc",
     "usb_endpoint_android.h",
-    "usb_ids.cc",
-    "usb_ids.h",
     "usb_interface_android.cc",
     "usb_interface_android.h",
     "usb_service.cc",
@@ -48,11 +46,9 @@
     "usb_service_win.h",
     "webusb_descriptors.cc",
     "webusb_descriptors.h",
-    generated_ids,
   ]
 
   deps = [
-    ":usb_device_ids",
     "//base/third_party/dynamic_annotations",
     "//components/device_event_log",
     "//device/base",
@@ -75,6 +71,13 @@
 
   if (is_android) {
     deps += [ ":jni_headers" ]
+  } else {
+    deps += [ ":usb_device_ids" ]
+    sources += [
+      "usb_ids.cc",
+      "usb_ids.h",
+      generated_ids,
+    ]
   }
 
   if (is_win || is_mac) {
diff --git a/device/vr/BUILD.gn b/device/vr/BUILD.gn
index 18758f9..0c7f599 100644
--- a/device/vr/BUILD.gn
+++ b/device/vr/BUILD.gn
@@ -37,7 +37,7 @@
       "//ui/gfx",
     ]
 
-    if (enable_daydream) {
+    if (enable_gvr_services) {
       sources += [
         "android/gvr/cardboard_gamepad_data_fetcher.cc",
         "android/gvr/cardboard_gamepad_data_fetcher.h",
@@ -120,7 +120,7 @@
   }
 }
 
-if (enable_daydream) {
+if (enable_gvr_services) {
   java_sources_needing_jni =
       [ "android/java/src/org/chromium/device/vr/NonPresentingGvrContext.java" ]
 
diff --git a/device/vr/features/features.gni b/device/vr/features/features.gni
index fcf90c5..2e3c76a7 100644
--- a/device/vr/features/features.gni
+++ b/device/vr/features/features.gni
@@ -5,13 +5,17 @@
 import("//build/config/chromecast_build.gni")
 
 declare_args() {
-  # Enable VR device support by default on Android and Windows
   # TODO(733935): Enable for other Android architectures too. Currently we only
   # support arm and arm64.
-  enable_vr = (is_android && (current_cpu == "arm" || current_cpu == "arm64") &&
-               !is_chromecast) || is_win
+  enable_gvr_services = is_android && !is_chromecast &&
+                        (current_cpu == "arm" || current_cpu == "arm64")
   enable_openvr = false
-  enable_daydream = is_android && (current_cpu == "arm" || current_cpu == "arm64")
+}
+
+declare_args() {
+  # Enable VR device support whenever VR device SDK(s) are supported and
+  # on Windows for testing.
+  enable_vr = enable_gvr_services || enable_openvr || is_win
 
   # Whether to include VR extras like test APKs in non-VR-specific targets
   include_vr_data = false
diff --git a/docs/fuchsia_sdk_updates.md b/docs/fuchsia_sdk_updates.md
index 5c61e55..8d3ca2d 100644
--- a/docs/fuchsia_sdk_updates.md
+++ b/docs/fuchsia_sdk_updates.md
@@ -16,3 +16,10 @@
 In order to sync a Fuchsia tree to the state matching an SDK hash, you can use:
 
 `jiri update https://storage.googleapis.com/fuchsia/jiri/snapshots/SDK_HASH_HERE`
+
+If you are waiting for a Zircon CL to roll into the SDK, you can check the
+status of the [Zircon
+roller](https://luci-scheduler.appspot.com/jobs/fuchsia/zircon-roller).
+Checking the bot's [list of
+CLs](https://fuchsia-review.googlesource.com/q/owner:zircon-roller%40fuchsia-infra.iam.gserviceaccount.com)
+might be useful too.
diff --git a/docs/security/OWNERS b/docs/security/OWNERS
index 9c57fff..e722c66d 100644
--- a/docs/security/OWNERS
+++ b/docs/security/OWNERS
@@ -1,4 +1,5 @@
 awhalley@chromium.org
+dcheng@chromium.org
 elawrence@chromium.org
 estark@chromium.org
 felt@chromium.org
diff --git a/docs/security/apf-right-a-wrong.png b/docs/security/apf-right-a-wrong.png
new file mode 100644
index 0000000..5981711
--- /dev/null
+++ b/docs/security/apf-right-a-wrong.png
Binary files differ
diff --git a/docs/security/life-of-a-security-issue.png b/docs/security/life-of-a-security-issue.png
new file mode 100644
index 0000000..7d6ab098
--- /dev/null
+++ b/docs/security/life-of-a-security-issue.png
Binary files differ
diff --git a/docs/security/mojo.md b/docs/security/mojo.md
new file mode 100644
index 0000000..785a0ed
--- /dev/null
+++ b/docs/security/mojo.md
@@ -0,0 +1,523 @@
+# Mojo "Style" Guide
+
+Mojo is Chrome's new IPC system and provides lots of useful abstractions. These
+abstractions can make it easier to write code that makes interprocess calls,
+but can also add significant complexity. Below are some recommendation from
+Mojo and IPC reviewers for best practices.
+
+For questions, concerns, or suggestions, reach out to <mojo@chromium.org>.
+
+> For legacy IPC, please see [security tips for IPC][security-tips-for-ipc].
+
+[TOC]
+
+
+## Simplicity
+
+Strive to write simple interfaces. Minimize the amount of cross-process state
+that needs to be maintained in sync.
+
+**_Good_**
+
+```c++
+interface FrameFactory {
+  CreateFrame(NavigationHost, MediaHost, PrintingHost) => (Frame);
+};
+interface Frame {
+  // ...
+};
+```
+
+**_Bad_**
+
+```c++
+interface Frame {
+  // Bad: comments will need to explicitly call out that these must be called
+  // to set the host objects before using any other interface methods.
+  //
+  // If untrustworthy processes can talk to trustworthy processes, the Frame
+  // implementation will also need to handle the case where the host objects are
+  // not yet bound. Double bad!
+  BindNavigationHost(NavigationHost);
+  BindMediaHost(MediaHost);
+  BindPrintingHost(PrintingHost);
+};
+```
+
+Similarly, strive to make methods focused. Do not overuse optional types.
+
+**_Good_**
+
+```c++
+interface Panel {
+  UpdateTitle(string);
+  UpdateIcon(skia.mojom.Bitmap);
+  UpdateText(string);
+};
+```
+
+**_Bad_**
+
+```c++
+interface Panel {
+  // Updates window attributes.
+  // Bad: it's unclear what combination of arguments is valid.
+  Update(string? title, skia.mojom.Bitmap? icon, string? text);
+};
+```
+
+
+## Documentation
+
+Mojo structs, interfaces, and methods should all have comments. Make sure the
+comments cover the "how" and the "why" of using an interface and its methods,
+and not just the "what". Document preconditions, postconditions, and trust: if
+an interface is implemented in the browser process and handles requests from
+the renderer process, this should be mentioned in the comments. Complex features
+should also have an external `README.md` that covers the high-level flow of
+information through interfaces and how they interact to implement the feature.
+
+**_Good_**
+
+```c++
+// Interface for controlling a goat teleporter from any process. Before
+// teleporting a goat, both the entrance and the exit must be bound to a
+// location.
+interface GoatTeleporter {
+  // Binds the entrance and exit, respectively. The entrance and exit
+  // may not be bound to the same location.
+  BindEntrance(LocationID) => ();
+  BindExit(LocationID) => ();
+  // Goats can be teleported from any process.
+  Teleport(Goat) => 0;
+};
+```
+
+**_Bad_**
+
+```c++
+interface GoatTeleporter {
+  BindEntrance(LocationID) => ();
+  BindExit(LocationID) => ();
+  Teleport(Goat) => 0;
+};
+```
+
+
+## Security
+
+Policy should be controlled solely by the browser process. "Policy" can mean
+any number of things, such as sizes, addresses, permissions, URLs, origins,
+etc. In an ideal world:
+
+1.  Unprivileged process asks for a capability from the privileged process that
+    owns the resource.
+1.  Privileged process applies policy to find an implementation for the
+    capability.
+1.  Unprivileged process performs operations on the capability, constrained in
+    scope.
+
+The privileged process must own the capability lifecycle.
+
+
+### Do not trust less privileged processes
+
+This is the overriding principle for all guidelines in this section. When
+receiving data from a less trusted process, treat the data as if it were
+generated by a malicious adversary. Message handlers cannot assume that offsets
+are valid, calculations won't overflow, et cetera.
+
+In general:
+
+*   the browser process is the most privileged process type and therefore, must
+    be maximally suspicious of its IPC inputs
+*   the renderer and the ARC++ processes are the least privileged and least
+    trustworthy process types
+*   other process types, such as GPU and plugin, fall in between
+
+When passing objects up a privilege gradient (from less → more privileged), the
+callee must validate the inputs before acting on them. When passing objects
+down a privilege gradient, such as from browser → renderer, it is OK for the
+callee to trust the caller.
+
+> See also: [Do not Handle Impossible Situations](#Do-not-handle-impossible-situations)
+
+
+### Do not send unnecessary or privilege-presuming data
+
+> Note: there is currently work in progress to associate origins with the
+> `InterfaceProvider`s for frames and workers: <https://crbug.com/734210> and
+> <https://crbug.com/775792/>.
+
+For example, the browser process must not (fully) trust the renderer's claims
+about origins. The browser process should already know what origin the renderer
+is evaluating, and thus should already have this data (for example, see
+`RenderFrameHost::GetLastCommittedOrigin()`). Thus, a method that requires
+passing an origin from the renderer to the browser process has a conceptual
+error, and quite possibly, a vulnerability.
+
+> Note: there are currently subtle races when using `GetLastCommittedOrigin()`
+> that will be resolved by fixing <https://crbug.com/729021>.
+
+Similarly, the browser process must not trust the renderer's claims about file
+pathnames. It would be unsafe for the browser process to save a downloaded file
+to `~/.bashrc` just because the renderer asked. Instead, it would be better for
+the browser process to:
+
+1.  Kill the renderer if `basename(pathname) != pathname`, since the renderer is
+    obviously compromised if it makes this mistake.
+1.  Defang the basename, by removing leading dots, et cetera. Note that the
+    definition of proper defanging varies per platform.
+1.  Prepend its own parent directory to the basename, e.g. ~/Downloads.
+
+> TODO(https://crbug.com/779196): Even better would be to implement a C++ type
+> performs the appropriate sanitizations and recommend its usage directly here.
+
+
+### Do not define things that are not used
+
+Platform-specific functionality should only be defined on the platforms where
+it is used.
+
+> The work to make this possible is in progress: <https://crbug.com/676224>
+
+For enums, avoid the pattern of defining a `LAST` or `MAX` value. The `LAST`
+value is typically used in conjunction with legacy IPC macros to validate enums;
+this is not needed with Mojo enums, which automatically validated.
+
+The `MAX` value is typically used as an invalid sentinel value for UMA
+histograms: unfortunately, simply defining a `MAX` value in a Mojo enum will
+cause Mojo to treat it as valid. This forces all IPC handling to do manual
+checks that the semantically invalid `MAX` value isn't accidentally or
+maliciously passed around.
+
+> Improving UMA logging is tracked in <https://crbug.com/742517>.
+
+
+### Use structured types
+
+Where possible, use structured types: this allows the type system to help
+enforce that the input data is valid. Common ones to watch out for:
+
+*   Files: use `mojo.common.mojom.File`, not raw descriptor types like `HANDLE`
+    and `int`.
+*   File paths: use `mojo.common.mojom.FilePath`, not `string`.
+*   JSON: use `mojo.common.mojom.Value`, not `string`.
+*   Mojo interfaces: use `Interface` or `Interface&`, not `handle` or
+    `handle<message_pipe>`.
+*   Nonces: use `mojo.common.mojom.UnguessableToken`, not `string`.
+*   Origins: use `url.mojom.Origin`, not `url.mojom.Url` and certainly not
+    `string`.
+*   Time types: use `mojo.common.mojom.TimeDelta` /
+    `mojo.common.mojom.TimeTicks` / `mojo.common.mojom.Time`, not `int64` /
+    `uint64` / `double` / et cetera.
+*   URLs: use `url.mojom.Url`, not `string`.
+
+**_Good_**
+
+```c++
+interface ReportingService {
+  ReportDeprecation(mojo.common.mojom.TimeTicks time,
+                    url.mojom.Url resource,
+                    uint32 line_number);
+};
+```
+
+**_Bad_**
+
+```c++
+interface ReportingService {
+  // Bad: unclear what units |time| is or what |data| contains.
+  ReportDeprecation(double time, mojo.common.mojom.Value data);
+};
+```
+
+Another anti-pattern to avoid is parallel arrays of data: this requires the
+receiver to validate that all the arrays have the same length. Instead, prefer
+to pass the data so that it is impossible to have a mismatch.
+
+**_Good_**
+
+```c++
+struct Pixel {
+  int8 reds;
+  int8 greens;
+  int8 blues;
+  int8 alphas;
+};
+
+struct Bitmap {
+  // Good: it is impossible for there to be mismatched data.
+  array<Pixel> pixels;
+};
+```
+
+**_Bad_**
+
+```c++
+// Bad: code using this struct will need to validate that all the arrays have
+// matching sizes.
+struct Bitmap {
+  array<int8> reds;
+  array<int8> greens;
+  array<int8> blues;
+  array<int8> alphas;
+};
+```
+
+
+### Beware of arithmetic overflow
+
+> TODO(dcheng): Import the guidance from the legacy IPC doc.
+
+Signed overflow is undefined in C++. If unsure about whether or not something
+will overflow, use the safe numeric helpers from `//base/numerics`!
+
+**_Good_**
+
+```c++
+base::CheckedNumeric<int32_t> size = mojo_rect->width();
+size *= mojo_rect.height();
+if (!size.IsValid()) {
+  mojo::ReportBadMessage("Bad size from renderer!");
+}
+```
+
+**_Bad_**
+
+```c++
+// Bad: Signed overflow is undefined in C++!
+int32_t size = mojo_rect->width() * mojo_rect.height();
+```
+
+Note that even if the types have defined overflow semantics, it is almost always
+a good idea to check for overflow.
+
+**_Good_**
+
+```c++
+uint32_t alloc_size;
+if (!CheckMul(request->elements(), request->element_size())
+         .AssignIfValid(&alloc_size)) {
+  // Safe: avoids allocating with a bogus size that overflowed to a smaller than
+  // expected value.
+  mojo::ReportBadMessge("Invalid allocation size");
+}
+
+Element* array = CreateArray(alloc_size);
+for (size_t i = 0; i < request->element_size(); ++i) {
+  array[i] = PopulateArray(i);
+}
+```
+
+**_Bad_**
+
+```c++
+uint32_t alloc_size = request->elements() * request->element_size();
+
+// Dangerous: alloc_size can overflow so that CreateArray allocates too little
+// memory. Subsequent assignments will turn into an out-of-bound write!
+Element* array = CreateArray(alloc_size);
+for (size_t i = 0; i < request->element_size(); ++i) {
+  array[i] = PopulateArray(i);
+}
+```
+
+
+## C++ Best Practices
+
+
+### Use StructTraits
+
+Creating a typemap and defining a `StructTraits` specialization moves the
+complexity of serialization, deserialization, and validation into a central
+location. We universally recommend this over defining `TypeConverter`
+specializations: when a value fails deserialization, the receiver method will
+never even be invoked. As a bonus, it also reduces the number of copies during
+serialization and deserialization. 😄
+
+**_Good_**
+
+```c++
+// In url_gurl_struct_traits.h:
+template <>
+struct StructTraits<url::mojom::UrlDataView, GURL> {
+  static base::StringPiece url(const GURL& r);
+
+  // If Read() returns false, Mojo will discard the message.
+  static bool Read(url::mojom::UrlDataView data, GURL* out);
+};
+
+// In url_gurl_struct_traits.cc:
+// Note that methods that aren't simple getters should be defined
+// out-of-line to avoid code bloat.
+base::StringPiece StructTraits<url::mojom::UrlDataView, GURL>::url(
+    const GURL& r) {
+  if (r.possibly_invalid_spec().length() > url::kMaxURLChars ||
+      !r.is_valid()) {
+    return base::StringPiece();
+  }
+  return base::StringPiece(r.possibly_invalid_spec().c_str(),
+                           r.possibly_invalid_spec().length());
+}
+
+bool StructTraits<url::mojom::UrlDataView, GURL>::Read(
+    url::mojom::UrlDataView data, GURL* out) {
+  base::StringPiece url_string;
+  if (!data.ReadUrl(&url_string))
+    return false;
+  if (url_string.length() > url::kMaxURLChars)
+    return false;
+  *out = GURL(url_string);
+  return !url_string.empty() && out->is_valid();
+}
+```
+
+**_Bad_**
+
+```c++
+template <>
+struct TypeConverter<url::mojom::UrlPtr, GURL> {
+  // Inefficient: this copies data once off the wire to create a
+  // url.mojom.Url object, then copies it again to create a GURL.
+  static GURL Convert(const url::mojom::UrlPtr url) {
+    if (url.url.is_empty()) return GURL();
+    // Not good: no way to signal errors, so any code that converts the
+    // Mojo struct to a GURL will somehow need to check for errors…
+    // but it can't even be distinguished from the empty URL case!
+    if (url.url.size() > url::kMaxURLChars) return GURL();
+    return GURL(url.url);
+  }
+};
+```
+
+There are also corresponding `EnumTraits` and `UnionTraits` specializations for
+mojo enums and unions respectively.
+
+
+### StructTraits getters should be simple
+
+Where possible, `StructTraits` should be returning const references or simple
+read-only views of the data. Having to create temporary data structures during
+serialization should be rare, and it should be even rarer to mutate the input
+argument.
+
+
+### Out-of-line complex serialization/deserialization logic
+
+A `StructTraits` specialization is almost always fully specialized. Only define
+`StructTraits` methods inline in the header if the method is a simple getter
+that returns a reference, pointer, or other simple POD. Define all other
+methods out-of-line to avoid code bloat.
+
+
+### Do not write one-off functions to convert to/from Mojo types
+
+There are some instances where it is simply not possible to define a
+`StructTraits` for type mapping: this commonly occurs with Blink IDL and Oilpan
+types. In these instances, add a `TypeConverter` specialization rather than
+defining a one-off conversion function. This makes it easier to search for and
+audit code that does potentially risky type conversions.
+
+> The use of `TypeConverter` should be limited as much as possible: ideally,
+> only use it in renderers.
+
+**_Good_**
+
+```c++
+template <>
+struct TypeConverter<IDLDictionary, mojom::blink::DictionaryPtr> {
+  static IDLDictionary* Convert(const mojom::blink::DictionaryPtr& in) {
+    // Note that unlike StructTraits, there is no out-of-band way to signal
+    // failure.
+    IDLDictionary* out = new IDLDictionary;
+    out->int_value = in->int_value;
+    out->str_value = in->str_value;
+    return out;
+  }
+};
+```
+
+**_Bad_**
+
+```c++
+// Using a custom one-off function makes this hard to discover in security
+// audits.
+IDLDictionary* FromMojo(const mojom::blink::DictionaryPtr& in) {
+  IDLDictionary* out = new IDLDictionary;
+  out->int_value = in->int_value;
+  out->str_value = in->str_value;
+  return out;
+}
+```
+
+
+### Use the proper abstractions
+
+`mojo::BindingSet` implies multiple clients may connect. If this actually isn't
+the case, please do not use it. For example, if an interface can be rebound,
+then use the singular `mojo::Binding` and simply `Close()` the existing binding
+before reusing it.
+
+
+## Java Best Practices
+
+Unfortunately, there are no strongly established conventions here. Most code
+tends to write manual conversion helpers and throw an exception on conversion
+failure. See [NfcTypeConverter.java] as one example of how to write conversion
+code.
+
+
+## General Code Health
+
+
+### Naming Conventions
+
+Place mojo types in `<top-level namespace>.mojom`. Directories for Mojo traits
+should be named `mojom` (preferable) or `ipc`. Legacy names that are also
+encountered are `public/interfaces`, `interfaces`, or just `mojo`.
+
+`mojom` is preferred for consistency between the directory name and the nested
+namespace name.
+
+
+### Do not handle impossible situations
+
+Do not clutter the code by handling impossible situations. Omitting it makes
+the invariants clear. This takes two different forms:
+
+*   A less trustworthy process can be compromised by an adversary and send
+    arbitrary data. When processing data from a less trustworthy process, do
+    not attempt to handle this invalid data: just call
+    `mojo::ReportBadMessage()`. When invoked in the context of processing an
+    IPC from the renderer, this will kill the renderer process.
+*   A more trustworthy process must be trusted, by definition. Do not write
+    code to handle impossible situations "just in case" there's a bug. For
+    example, the renderer class `content::RenderFrameImpl` must always be
+    connected to certain control interfaces in the browser. It does not makes
+    sense to handle a Mojo connection error and try to reconnect: a connection
+    error signals that the browser process is in the process of deleting the
+    frame, and any attempt at reconnecting will never succeed.
+
+
+### Using mojo enums directly when possible
+
+`EnumTraits` generally do not add much value: incoming Mojo enum values are
+already validated before typemapping, so it is guaranteed that the input value
+to `EnumTraits<T>::FromMojom()` is already a valid enum value, so the method
+itself is just a bunch of boilerplate to map between two very similarly named,
+yet slightly different, enums.
+
+To avoid this, prefer to use the Mojo enum directly when possible.
+
+
+### Consider the cost of setting up message pipes
+
+Message pipes are fairly inexpensive, but they are not free either: it takes 6
+control messages to establish a message pipe. Keep this in mind: if the
+interface is used relatively frequently, connecting once and reusing the
+interface pointer is probably a good idea.
+
+
+[security-tips-for-ipc]: https://www.chromium.org/Home/chromium-security/education/security-tips-for-ipc
+[NfcTypeConverter.java]: https://chromium.googlesource.com/chromium/src/+/e97442ee6e8c4cf6bcf7f5623c6fb2cc8cce92ac/services/device/nfc/android/java/src/org/chromium/device/nfc/NfcTypeConverter.java
diff --git a/docs/security/security-labels.md b/docs/security/security-labels.md
new file mode 100644
index 0000000..d099a7b
--- /dev/null
+++ b/docs/security/security-labels.md
@@ -0,0 +1,101 @@
+# Security Labels And Components
+
+[TOC]
+
+Bug database labels are used very heavily for security bugs. We rely on the
+labels being correct for a variety of reasons, including driving fixing efforts,
+driving release management efforts (merges and release notes) and also
+historical queries and data mining.
+
+Because of the extent to which we rely on labels, it is an important part of the
+Security Sheriff duty to ensure that all security bugs are correctly tagged and
+managed. But even if you are not the Sheriff, please fix any labeling errors you
+happen upon.
+
+Any issue that relates to security should have one of the following:
+
+* **Security** component: Features that are related to security.
+* **Type-Bug-Security**: Designates a security vulnerability that impacts users.
+This label should not be used for new features that relate to security, or
+general remediation/refactoring ideas. (Use the **Security** component for
+that.)
+
+## Labels Relevant For Any **Type-Bug-Security**
+
+* **Security_Severity-**{**Critical**, **High**, **Medium**, **Low**,
+**None**}: Designates the severity of a vulnerability according to our
+[severity guidelines](severity-guidelines.md).
+* **Pri-#**: Priority should generally match Severity:
+  * **Security_Severity-Critical**: **Pri-0**.
+  * **High** and **Medium**: **Pri-1**.
+  * **Low**: **Pri-2**.
+* **Security_Impact-**{**Head**, **Beta**, **Stable**, **None**}: Designates
+which branch(es) were impacted by the bug. Only apply the label corresponding
+with the earliest affected branch. **None** means that a security bug is in a
+disabled feature, or otherwise doesn't impact Chrome.
+* **Restrict-View-SecurityTeam** or **Restrict-View-SecurityNotify**: Labels
+that restrict access to the bug for members of security@chromium.org or
+security-notify@chromium.org, respectively. Should a bug ever contain
+confidential information, or if the reporter wishes to remain anonymous, we add
+**Restrict-View-Google** and/or **Restrict-View-SecurityEmbargo**.
+* **reward-**{**topanel**, **unpaid**, **na**, **inprocess**, _#_}: Labels used
+in tracking bugs nominated for our [Vulnerability Reward
+Program](https://www.chromium.org/Home/chromium-security/vulnerability-rewards-program).
+* **M-#**: Target milestone for the fix.
+* Component: For bugs filed as **Type-Bug-Security**, we also want to track
+which component(s) the bug is in.
+* **ReleaseBlock-Stable**: When we find a security bug regression that has not
+yet shipped to stable, we use this label to try and prevent the security
+regression from ever affecting users of the Stable channel.
+* **OS-**{**Chrome**, **Linux**, **Windows**, ...}: Denotes which operating
+systems are affected.
+* **Merge-**{**Request-?**, **Approved-?**, **Merged-?**}: Security fixes
+are frequently merged to earlier release branches.
+* **Release-#-M##**: Denotes which exact patch a security fix made it into.
+This is more fine-grained than the **M-** label. **Release-0-M50** denotes the
+initial release of a M50 to Stable.
+* **CVE-####-####**: For security bugs that get assigned a CVE, we tag the
+appropriate bug(s) with the label for easy searching.
+
+## An Example
+
+Given the importance and volume of labels, an example might be useful.
+
+1. An external researcher files a security bug, with a repro that demonstrates
+memory corruption against the latest (e.g.) M29 dev channel. The labels
+**Restrict-View-SecurityTeam** and **Type-Bug-Security** will be applied.
+1. The sheriff jumps right on it and uses ClusterFuzz to confirm that the bug is
+a novel and nasty-looking buffer overflow in the renderer process. ClusterFuzz
+also confirms that all current releases are affected. Since M27 is the current
+Stable release, and M28 is in Beta, we add the labels of the earliest affected
+release: **M-27**, **Security_Impact-Stable**. The severity of a buffer overflow
+in a renderer implies **Security_Severity-High** and **Pri-1**. Any external
+report for a confirmed vulnerability needs **reward-topanel**. Sheriffbot will
+usually add it automatically. The stack trace provided by ClusterFuzz suggests
+that the bug is in the component **Blink>DOM**, and such bugs should be labeled
+as applying to all OSs except iOS (where Blink is not used): **OS-**{**Linux**,
+**Windows**, **Android**, **Chrome**, **Fuchsia**}.
+1. Within a day or two, the sheriff was able to get the bug assigned and — oh
+joy! — fixed very quickly. When the bug's status changes to **Fixed**,
+Sheriffbot will add the **Merge-Requested** label, and will change
+**Restrict-View-SecurityTeam** to **Restrict-View-SecurityNotify**.
+1. Later that week, the Chrome Security manager does a sweep of all
+**reward-topanel** bugs. This one gets rewarded, so that one reward label is
+replaced with two: **reward-1000** and **reward-unpaid**. Later,
+**reward-unpaid** becomes **reward-inprocess** and is later still removed when
+all is done. Of course, **reward-1000** remains forever. (We use it to track
+total payout!)
+1. The next week, a Chrome TPM states that the first Chrome M27 stable patch is
+going on and asks if we want to include security fixes. We do, of course.
+Having had this particular fix "bake" in another M29 Dev channel, the Chrome
+Security release manager decides to merge it. **Merge-Approved-M##** is
+replaced with **Merge-Merged-M##**. (IMPORTANT: This transition only occurs
+after the fix is merged to ALL applicable branches, i.e. M28 as well as M27 in
+this case.) We now know that users of Chrome Stable will get the fix in the
+first M27 Stable patch, so the following labels are changed/applied: **M-27**,
+**Release-1**. Since the bug was externally reported, it definitely gets its
+own CVE, and a label is eventually added: **CVE-2013-31337**.
+1. 14 weeks after the bug is marked **Fixed**, Sheriffbot removes the
+**Restrict-View-SecurityNotify** label and other **Restrict-View-?** labels,
+making the bug public. There is one crucial exception: Sheriffbot will not
+remove **Restrict-View-SecurityEmbargo**.
diff --git a/docs/security/sheriff.md b/docs/security/sheriff.md
new file mode 100644
index 0000000..ba5a34c
--- /dev/null
+++ b/docs/security/sheriff.md
@@ -0,0 +1,303 @@
+# Security Sheriff
+
+[TOC]
+
+## Important Links
+
+[Chrome Open Security Bugs dashboard,
+go/chrome-security-bugs](http://go/chrome-security-bugs).
+
+[Vulnerability Severity Guidelines](severity-guidelines.md).
+
+[Security Labels](security-labels.md).
+
+[Sheriff Handoff Log](http://go/chrome-security-sheriff-handoff) (Googlers
+only).
+
+You might also like the [HOWTO: Be A Security Sheriff
+deck](https://docs.google.com/presentation/d/1eISJXxyv7dUCGUKk_rvUI9t9s2xb98QY4d_-dZSa7Wg/edit#slide=id.p).
+
+## What Is A Security Sheriff?
+
+A security sheriff is a member of a rotation that occurs in 1-week time slots,
+starting on Tuesdays and ending the following Monday. [Here is the rotation
+schedule](https://docs.google.com/spreadsheets/d/10sLYZbi6QfLcXrhO-j5eSc82uc7NKnBz_o1pR9y8h7U/edit#gid=0).
+
+Sheriffs ensure that all incoming security issues are triaged quickly and
+correctly. We aim to have get every bug triaged and assigned within 48 hours
+(preferably 24). This includes weekends, so it's good for sheriffs to check in
+once on a weekend and see if there are any emergencies.
+
+Sheriffing is not an on-call rotation, however. Sheriffs don't have to work
+nights or to do more than a few minutes' work on weekends.
+
+## I'm The Security Sheriff. What Do I Do?
+
+Each week has a primary and secondary sheriff, and during their rotation both
+have various important and overlapping responsibilities:
+
+### Primary Sheriff
+
+* Look at every incoming security bug report on the
+[dashboard](http://go/chrome-security-bugs). Ensure each is accurately triaged,
+and actively progressing towards getting fixed.
+* Keep the [Sheriff Handoff Log](http://go/chrome-security-sheriff-handoff) up
+to date.
+* Shout for help if the incoming bug rate is too high ([suggested vocal
+exercises](https://youtu.be/5y_SbnPx_cE?t=37s)). The first person to ask is
+the secondary sheriff.
+* Stay sharp, keep in shape ([hand-stand
+pushups](https://www.youtube.com/watch?v=jZ1ZDlLImF8#t=50) are standard for the
+primary sheriff), and remember you may be [called upon during
+emergencies](https://www.youtube.com/watch?v=buHaKYL9Jhg).
+
+### Secondary Sheriff
+
+* Ensure that all incoming queries to the
+[security@chromium.org](https://groups.google.com/a/chromium.org/forum/#!forum/security)
+and
+[chrome-security@google.com](https://groups.google.com/a/google.com/forum/#!forum/chrome-security)
+lists get a reply (by someone; not necessarily the sheriffs themselves).
+  * Note: external emails will always come in on security@chromium.org as
+chrome-security@google.com is a google-only list, but both need to be triaged.
+* Ensure [accurate label management](security-labels.md) on bugs, for example
+applying the correct **Merge-?** and **Restrict-View-?** labels when a bug
+transitions to **Fixed**.
+* Change bugs status to **Fixed** for those that the developer forgets to
+close. Make sure to read bug comments where developer might point out that it
+needs more CLs, et c. Wait 24 hours before closing ClusterFuzz bugs, to give
+ClusterFuzz a chance to close it automatically.
+* Look at open security bug reports and check that progress is occurring.
+* Generally keep an eye on all bug traffic in case anything needs action or
+replying to.
+* Stay sharp, keep in shape ([finger
+exercises](https://youtu.be/20elMaVZ9lg?t=47s) are standard for the secondary
+sheriff), and remember you may be called upon during emergencies.
+
+## Life Of A Security Bug
+
+Do as much as you can for the week to triage, shepherd, and wrap up open
+security bugs. What follows are the details of what that entails, but it
+practically means turning all the red cells in the dashboard to green. **If
+you're ever stuck or in doubt, ask for help on #chrome-security!**
+
+![alt text](apf-right-a-wrong.png "felt: a lot of Chrome vuln reports come from
+well-meaning people who clearly went out of their way to try to right a wrong.
+i like that.")
+
+[link](https://twitter.com/__apf__/status/728776130564526080)
+
+### Diagnose The Issue
+
+![alt text](life-of-a-security-issue.png "Life of a security issue.")
+
+* **If the report is invalid**, remove the **Restrict-View-SecurityTeam** label
+and mark it **WontFix**.
+* **If the report is a duplicate**, mark it **Duplicate**. If the issue this is
+a duplicate of is public, remove the **Restrict-View-SecurityTeam** label.
+* **If the report is primarily a privacy issue**, send it to the privacy team:
+  * Add the **Privacy** component so that it enters their triage queue
+  * CC any security team members, including yourself, who may be interested in
+  the privacy issue
+	* Change the **Restrict-View-SecurityTeam** label to
+  **Restrict-View-ChromePrivacy**
+    * Note that security team members don't automatically have privacy bug
+    access, so this will probably make the issue inaccessible to you.
+* **If the report is asking about why something is or is not on the Safe
+Browsing list:**
+  * Assign it to zbutler@, who will triage it for the Safe Browsing team
+	* Remove the **Restrict-View-SecurityTeam** label and add the
+  **Restrict-View-Google** label
+  * Change **Type-Bug-Security** label to **Type-Bug**
+  * Add the **Security** component
+* **If the report is a potentially valid bug but is not a security vulnerability:**
+  * remove the **Restrict-View-SecurityTeam** label. If necessary, add one of the
+  other **Restrict-View-?** labels:
+    * **Restrict-View-Google** if this is a crash report
+    * **Restrict-View-EditIssue** if the bug can be abused (e.g. denial of service)
+	* Change **Type-Bug-Security** label to **Type-Bug** (or whatever **Type-?**
+  is appropriate)
+  * Add appropriate component or CCs to ensure it does get triaged
+  * Add the **Security** component or the **Team-Security-UX** label if the security
+team should still track the issue (e.g. security features).
+* **If the report doesn't have enough information**, ask the reporter for more
+information, add the **Needs-Feedback** label and wait for 24 hours for a response.
+* **If the report smells like a vulnerability, keep going.**
+
+### Verify And Label The Bug
+
+#### Step 1. Reproduce legitimate-sounding issues.
+
+If you can't reproduce the issue, ask for help on IRC (#chrome-security), or
+find an area owner to help.
+
+Tips for reproducing bugs:
+
+* [https://clusterfuzz.com/v2/upload-testcase](https://clusterfuzz.com/v2/upload-testcase)
+allows you to upload files to reproduce crashes on various platforms and will
+identify revision ranges when the regression was introduced. If a test case
+requires multiple files, they can be uploaded together in a zip or tar archive.
+* When you can't just build from a specific branch locally, check out
+[https://dev.chromium.org/getting-involved/dev-channel](https://dev.chromium.org/getting-involved/dev-channel)
+or
+[https://commondatastorage.googleapis.com/chromium-browser-asan/index.html](https://commondatastorage.googleapis.com/chromium-browser-asan/index.html)
+for latest release of a specific version.
+* There are many tools available to help you reproduce various memory issues
+reliably. If you aren't already familiar with them, check out
+[AddressSanitizer](https://www.chromium.org/developers/testing/addresssanitizer),
+[MemorySanitizer](https://www.chromium.org/developers/testing/memorysanitizer),
+[ThreadSanitizer](https://www.chromium.org/developers/testing/threadsanitizer-tsan-v2),
+and
+[UndefinedBehaviorSanitizer](https://www.chromium.org/developers/testing/undefinedbehaviorsanitizer).
+* If you run into issues with a reproducible ClusterFuzz test case (like
+missing symbols, or if anything else seems off), try uploading the test case
+again using a different job type with a more mature tool (e.g. ASan on Linux).
+It may give more complete information.
+
+#### Step 2. Assess the severity.
+
+[See the severity guidelines](severity-guidelines.md). If it's a critical
+vulnerability, act quick! We aim to get users patched in < 30 days. Remember
+that if something requires an unusual configuration or complicated user
+interaction, the severity rating should be lowered.
+
+Bug chains are typically composed of several individual security bugs and
+should be split into a new bug for each potential fix required, so this allows
+each team to work on fixing their part of the chain. In cases like this, leave
+the main bug as the severity/priority of the full chain, and mark child bugs as
+being blockers of the parent bug each with their own separate severity. Each
+child bug can have its own priority. Examples of this in action are [issue
+352369](https://crbug.com/352369) and [issue 453937](https://crbug.com/453937).
+
+#### Step 3. [Label, label, label](security-labels.md).
+
+Much of Chrome's development and release process depends on bugs having the
+right labels and components. Labels and components are vitally important for
+our metrics, the visiblity of bugs, and tracking our progress over time.
+
+Labels to **double-check** (that should already be there if the bug was filed
+using the Security template):
+
+* **Restrict-View-SecurityTeam**
+* **Type-Bug-Security**
+* **If the reporter wants to remain anonymous or if the bug description or
+comments contain PII**, add **Restrict-View-SecurityEmbargo**.
+
+Generally, see [the Security Labels document](security-labels.md).
+
+**Ensure the comment adequately explains any status changes.** Severity,
+milestone, and priority assignment generally require explanatory text.
+
+* Report suspected malicious URLs to SafeBrowsing.
+  * Public URL:
+  [https://www.google.com/safebrowsing/report_badware/](https://www.google.com/safebrowsing/report_badware/)
+  * Googlers: see instructions at [go/report-safe-browsing](go/report-safe-browsing)
+* Report suspected malicious file attachments to SafeBrowsing and VirusTotal.
+* Make sure the report is properly forwarded when the vulnerability is in an
+upstream project, the OS, or some other dependency.
+* For vulnerabilities in services Chrome uses (e.g. Omaha, Chrome Web Store,
+SafeBrowsing), make sure the affected team is informed and has access to the
+necessary bugs.
+
+### Find An Owner To Fix The Bug
+
+That owner can be you! Otherwise, this is one of the more grey areas of
+sheriffing. With experience, you'll figure out good goto people for certain
+areas. Until then, here are some tips.
+
+**Determine the correct component before continuing.** It's not enough on its
+own, but it's a good starting point. Many components will automatically apply
+some CCs who may be able to help you out. If it's a crash bug, see if
+ClusterFuzz is able to provide one (will appear in the same card as the culprit
+CL). You can also use `git hyper-blame` and check OWNERS files to see who might
+own the relevant code.
+
+**For crashes, check to see if ClusterFuzz provides a culprit CL.** Before you
+assign a bug based on this, do a quick sanity check to ensure the CL could have
+caused the bug. If the result seems wrong, apply the Test-Predator-Wrong label
+to the bug and keep going.
+
+If you're able to narrow this to a specific regression range, usually from
+ClusterFuzz for crash bugs, do a quick pass over the git log to see if any CLs
+stand out. If you aren't sure, don't be afraid to add CCs to the bug and ask!
+
+At this point, you'll probably need to dive in and attempt to root cause the
+bug, which is another complicated grey area that you'll figure out with
+experience. Try not to spend too much time for this on any given bug, as some
+cases will simply be too difficult without a deep understanding of certain
+portions of the codebase.
+
+* If you can narrow the bug to a specific file or block of code, or if
+something stands out as suspicious, try to assign an owner based on `git
+hyper-blame` or add some CCs based on OWNERS files
+* If not, consider searching in the issue tracker for people that fixed
+similar bugs or bugs in similar areas of the code base, such as issues with the
+same components, recently. For example, let's say you were trying to figure out
+a good person to assign a Content>Fonts issue. Look for "status=fixed,
+verified" and query by when the issues were closed after (i.e. w/ in the last
+30 days == closed>today-30).
+
+A few components have their own triage processes or points of contact who can
+help.
+
+* V8 bugs? Look for V8 rolls within the regression range, then look within the
+CLs of those rolls to find possible culprits. If you are unable to find the
+culprit CL, assign to the [V8 ClusterFuzz
+Sheriff](https://rotation.googleplex.com/status?id=5714662985302016) for
+triage. Note that V8 CHECK failure crashes can have security implications, so
+don't triage it yourself and instead assign it to V8 ClusterFuzz Sheriff. He or
+she can make an informed decision on whether it is a security vulnerability or
+not and whether it is safe to strip the security tags (**Type=Bug-Security**,
+**Restrict-View-SecurityTeam**).
+* Skia bugs? If you made it this far and still aren't sure, assign them to
+hcm@chromium.org. Be careful while triaging these! The place where we're
+crashing isn't necessarily the place where the bug was introduced, so blame may
+be misleading.
+* URL spoofing issues, especially related to RTL or IDNs? See
+[go/url-spoofs](go/url-spoofs) for a guide to triaging these.
+
+Still stuck? Ask #chrome-security or someone from
+[go/chrome-security-secondary-sheriffs](https://goto.google.com/chrome-security-secondary-sheriffs)
+for help! That's why we're here. Don't be afraid to do this!
+
+Make sure that the person you assign to handle a bug is not OOO. And,
+generally, explicitly CC more than 1 person on the bug, if possible, and
+preferably people from more than 1 geographic region. (See the OWNERS file(s)
+that affect(s) the relevant area of code.)
+
+**Sometimes, finding an owner isn't enough to ensure that a bug will get
+fixed.** Check the stale bug list on the security dashboard and try resolve
+some of the problems that might be blocking these issues. If you get in touch
+with a bug owner off of the issue tracker, be sure to have them update the bug
+so that future sheriffs are aware of the status.
+
+> Q: Why isn’t setting the component alone good enough?
+>
+> A: CCs are critical because just assigning to a component is ineffective
+> because the component’s team cannot see the issues unless they have the
+> Security View permissions.
+
+### Using The Permission API Kill Switch
+
+If you find a vulnerability in a Permission API and need to use the Global
+Permissions Kill Switch, then follow [the
+instructions](https://docs.google.com/document/d/17JeYt3c1GgghYoxy4NKJnlxrteAX8F4x-MAzTeXqP4U)
+
+### Wrap Up The Fixed Issue
+
+1. For any **Security_Severity-**{**Critical**, **High**, **Medium**} bugs that
+**Security_Impact-**{**Beta**, **Stable**}, add **Merge-Requested** so that the
+fix gets merged into the next release. Exercise discretion according to
+security severity and risk associated with the bug fix; you can ask the patch
+author whether any risky code paths are affected. The actual merging and
+drafting of release notes is taken care of by the [security release management
+role](https://www.chromium.org/Home/chromium-security/security-release-management).
+1. Chrome's [Vulnerability Rewards
+Program](https://www.google.com/about/appsecurity/chrome-rewards/index.html)
+TPM adds the **reward-topanel** label by mass modification, but **do** label any
+bugs reported by a @chromium.org email that should be rewarded (e.g. "I'm
+filing this on behalf of" or the like).
+
+## End Of Rotation
+
+Update the [Sheriff Handoff Log](http://go/chrome-security-sheriff-handoff).
diff --git a/docs/win_cross.md b/docs/win_cross.md
index 77c15682..8f0aa00 100644
--- a/docs/win_cross.md
+++ b/docs/win_cross.md
@@ -64,6 +64,7 @@
         -S https://chromium-swarm.appspot.com \
         -I https://isolateserver.appspot.com \
         -d os Windows -d pool Chrome -s <hash printed by previous command>
+        [ -- <flag to target process, for example --gtest_filter>... ]
 
 Most tests that build should pass.  However, the cross build uses
 the lld linker, and a couple of tests fail when using lld. You can look at
diff --git a/extensions/browser/api/serial/serial_api.cc b/extensions/browser/api/serial/serial_api.cc
index cb59058..f05ef42 100644
--- a/extensions/browser/api/serial/serial_api.cc
+++ b/extensions/browser/api/serial/serial_api.cc
@@ -394,9 +394,11 @@
             &SerialGetConnectionsFunction::OnGotOne, this, connection_id));
       }
     }
-  } else {
-    OnGotAll();
   }
+  if (count_ > 0)
+    return;
+
+  OnGotAll();
 }
 
 void SerialGetConnectionsFunction::OnGotOne(
diff --git a/google_apis/gaia/fake_gaia.cc b/google_apis/gaia/fake_gaia.cc
index 8221da8..5c130de 100644
--- a/google_apis/gaia/fake_gaia.cc
+++ b/google_apis/gaia/fake_gaia.cc
@@ -234,8 +234,8 @@
       gaia_urls->merge_session_url(), HandleMergeSession);
 
   // Handles /o/oauth2/programmatic_auth GAIA call.
-  REGISTER_RESPONSE_HANDLER(
-      gaia_urls->client_login_to_oauth2_url(), HandleProgramaticAuth);
+  REGISTER_RESPONSE_HANDLER(gaia_urls->deprecated_client_login_to_oauth2_url(),
+                            HandleProgramaticAuth);
 
   // Handles /ServiceLogin GAIA call.
   REGISTER_RESPONSE_HANDLER(
diff --git a/google_apis/gaia/gaia_auth_fetcher.cc b/google_apis/gaia/gaia_auth_fetcher.cc
index 0e698d8e..5816ed2 100644
--- a/google_apis/gaia/gaia_auth_fetcher.cc
+++ b/google_apis/gaia/gaia_auth_fetcher.cc
@@ -11,6 +11,8 @@
 #include "base/json/json_reader.h"
 #include "base/json/json_writer.h"
 #include "base/macros.h"
+#include "base/metrics/user_metrics.h"
+#include "base/metrics/user_metrics_action.h"
 #include "base/strings/string_split.h"
 #include "base/strings/string_util.h"
 #include "base/strings/stringprintf.h"
@@ -195,9 +197,8 @@
       get_check_connection_info_url_(
           GaiaUrls::GetInstance()->GetCheckConnectionInfoURLWithSource(source)),
       oauth2_iframe_url_(GaiaUrls::GetInstance()->oauth2_iframe_url()),
-      client_login_to_oauth2_gurl_(
-          GaiaUrls::GetInstance()->client_login_to_oauth2_url()) {
-}
+      deprecated_client_login_to_oauth2_gurl_(
+          GaiaUrls::GetInstance()->deprecated_client_login_to_oauth2_url()) {}
 
 GaiaAuthFetcher::~GaiaAuthFetcher() {}
 
@@ -541,23 +542,22 @@
                             kLoadFlagsIgnoreCookies, traffic_annotation);
 }
 
-void GaiaAuthFetcher::StartCookieForOAuthLoginTokenExchange(
+void GaiaAuthFetcher::DeprecatedStartCookieForOAuthLoginTokenExchange(
     const std::string& session_index) {
-  StartCookieForOAuthLoginTokenExchangeWithDeviceId(session_index,
-                                                    std::string());
+  DeprecatedStartCookieForOAuthLoginTokenExchangeWithDeviceId(session_index,
+                                                              std::string());
 }
 
-void GaiaAuthFetcher::StartCookieForOAuthLoginTokenExchangeWithDeviceId(
-    const std::string& session_index,
-    const std::string& device_id) {
-  StartCookieForOAuthLoginTokenExchange(
-      true,
-      session_index,
-      GaiaUrls::GetInstance()->oauth2_chrome_client_id(),
+void GaiaAuthFetcher::
+    DeprecatedStartCookieForOAuthLoginTokenExchangeWithDeviceId(
+        const std::string& session_index,
+        const std::string& device_id) {
+  DeprecatedStartCookieForOAuthLoginTokenExchange(
+      true, session_index, GaiaUrls::GetInstance()->oauth2_chrome_client_id(),
       device_id);
 }
 
-void GaiaAuthFetcher::StartCookieForOAuthLoginTokenExchange(
+void GaiaAuthFetcher::DeprecatedStartCookieForOAuthLoginTokenExchange(
     bool fetch_token_from_auth_code,
     const std::string& session_index,
     const std::string& client_id,
@@ -613,9 +613,13 @@
             }
           }
         })");
-  CreateAndStartGaiaFetcher(std::string(), device_id_header,
-                            client_login_to_oauth2_gurl_.Resolve(query_string),
-                            net::LOAD_NORMAL, traffic_annotation);
+
+  base::RecordAction(base::UserMetricsAction(
+      "Signin_UseDeprecatedCookieToOAuth2TokenEndpoint"));
+  CreateAndStartGaiaFetcher(
+      std::string(), device_id_header,
+      deprecated_client_login_to_oauth2_gurl_.Resolve(query_string),
+      net::LOAD_NORMAL, traffic_annotation);
 }
 
 void GaiaAuthFetcher::StartAuthCodeForOAuth2TokenExchange(
@@ -1214,7 +1218,7 @@
   if (url == issue_auth_token_gurl_) {
     OnIssueAuthTokenFetched(data, status, response_code);
   } else if (base::StartsWith(url.spec(),
-                              client_login_to_oauth2_gurl_.spec(),
+                              deprecated_client_login_to_oauth2_gurl_.spec(),
                               base::CompareCase::SENSITIVE)) {
     OnClientLoginToOAuth2Fetched(data, cookies, status, response_code);
   } else if (url == oauth2_token_gurl_) {
diff --git a/google_apis/gaia/gaia_auth_fetcher.h b/google_apis/gaia/gaia_auth_fetcher.h
index a53eb822..097267e 100644
--- a/google_apis/gaia/gaia_auth_fetcher.h
+++ b/google_apis/gaia/gaia_auth_fetcher.h
@@ -81,7 +81,8 @@
   //
   // Either OnClientOAuthSuccess or OnClientOAuthFailure will be
   // called on the consumer on the original thread.
-  void StartCookieForOAuthLoginTokenExchange(const std::string& session_index);
+  void DeprecatedStartCookieForOAuthLoginTokenExchange(
+      const std::string& session_index);
 
   // Start a request to exchange the cookies of a signed-in user session
   // for an OAuthLogin-scoped oauth2 token. In the case of a session with
@@ -92,7 +93,7 @@
   //
   // Either OnClientOAuthSuccess or OnClientOAuthFailure will be
   // called on the consumer on the original thread.
-  void StartCookieForOAuthLoginTokenExchangeWithDeviceId(
+  void DeprecatedStartCookieForOAuthLoginTokenExchangeWithDeviceId(
       const std::string& session_index,
       const std::string& device_id);
 
@@ -108,7 +109,7 @@
   //
   // Either OnClientOAuthCode or ClientOAuthSuccess or OnClientOAuthFailure
   // will be called on the consumer on the original thread.
-  void StartCookieForOAuthLoginTokenExchange(
+  void DeprecatedStartCookieForOAuthLoginTokenExchange(
       bool fetch_token_from_auth_code,
       const std::string& session_index,
       const std::string& client_id,
@@ -429,7 +430,7 @@
 
   // While a fetch is going on:
   std::unique_ptr<net::URLFetcher> fetcher_;
-  GURL client_login_to_oauth2_gurl_;
+  GURL deprecated_client_login_to_oauth2_gurl_;
   std::string request_body_;
   std::string requested_service_;
   bool fetch_pending_ = false;
diff --git a/google_apis/gaia/gaia_auth_fetcher_unittest.cc b/google_apis/gaia/gaia_auth_fetcher_unittest.cc
index 2311cc3..2777399 100644
--- a/google_apis/gaia/gaia_auth_fetcher_unittest.cc
+++ b/google_apis/gaia/gaia_auth_fetcher_unittest.cc
@@ -96,16 +96,16 @@
 class GaiaAuthFetcherTest : public testing::Test {
  protected:
   GaiaAuthFetcherTest()
-      : issue_auth_token_source_(GaiaUrls::GetInstance()
-                                     ->issue_auth_token_url()),
-        client_login_to_oauth2_source_(GaiaUrls::GetInstance()
-                                           ->client_login_to_oauth2_url()),
+      : issue_auth_token_source_(
+            GaiaUrls::GetInstance()->issue_auth_token_url()),
+        client_login_to_oauth2_source_(
+            GaiaUrls::GetInstance()->deprecated_client_login_to_oauth2_url()),
         oauth2_token_source_(GaiaUrls::GetInstance()->oauth2_token_url()),
         token_auth_source_(GaiaUrls::GetInstance()->token_auth_url()),
         merge_session_source_(GaiaUrls::GetInstance()->merge_session_url()),
-        uberauth_token_source_(GaiaUrls::GetInstance()
-                                   ->oauth1_login_url()
-                                   .Resolve("?source=&issueuberauth=1")),
+        uberauth_token_source_(
+            GaiaUrls::GetInstance()->oauth1_login_url().Resolve(
+                "?source=&issueuberauth=1")),
         oauth_login_gurl_(GaiaUrls::GetInstance()->oauth1_login_url()) {}
 
   void RunParsingTest(const std::string& data,
@@ -362,7 +362,7 @@
 
   net::TestURLFetcherFactory factory;
   GaiaAuthFetcher auth(&consumer, std::string(), GetRequestContext());
-  auth.StartCookieForOAuthLoginTokenExchange("0");
+  auth.DeprecatedStartCookieForOAuthLoginTokenExchange("0");
   net::TestURLFetcher* fetcher = factory.GetFetcherByID(0);
   EXPECT_TRUE(NULL != fetcher);
   EXPECT_EQ(net::LOAD_NORMAL, fetcher->GetLoadFlags());
@@ -399,8 +399,8 @@
 
   net::TestURLFetcherFactory factory;
   GaiaAuthFetcher auth(&consumer, std::string(), GetRequestContext());
-  auth.StartCookieForOAuthLoginTokenExchange(
-      false, "0", "ABCDE_12345", "");
+  auth.DeprecatedStartCookieForOAuthLoginTokenExchange(false, "0",
+                                                       "ABCDE_12345", "");
   net::TestURLFetcher* fetcher = factory.GetFetcherByID(0);
   EXPECT_TRUE(NULL != fetcher);
   EXPECT_EQ(net::LOAD_NORMAL, fetcher->GetLoadFlags());
@@ -428,8 +428,8 @@
   net::TestURLFetcherFactory factory;
   std::string expected_device_id("ABCDE-12345");
   GaiaAuthFetcher auth(&consumer, std::string(), GetRequestContext());
-  auth.StartCookieForOAuthLoginTokenExchangeWithDeviceId("0",
-                                                         expected_device_id);
+  auth.DeprecatedStartCookieForOAuthLoginTokenExchangeWithDeviceId(
+      "0", expected_device_id);
   net::TestURLFetcher* fetcher = factory.GetFetcherByID(0);
   EXPECT_TRUE(NULL != fetcher);
   EXPECT_EQ(net::LOAD_NORMAL, fetcher->GetLoadFlags());
@@ -449,7 +449,7 @@
 
   net::TestURLFetcherFactory factory;
   GaiaAuthFetcher auth(&consumer, std::string(), GetRequestContext());
-  auth.StartCookieForOAuthLoginTokenExchange(std::string());
+  auth.DeprecatedStartCookieForOAuthLoginTokenExchange(std::string());
 
   EXPECT_TRUE(auth.HasPendingFetch());
   MockFetcher mock_fetcher(
@@ -470,7 +470,7 @@
 
   net::TestURLFetcherFactory factory;
   GaiaAuthFetcher auth(&consumer, std::string(), GetRequestContext());
-  auth.StartCookieForOAuthLoginTokenExchange(std::string());
+  auth.DeprecatedStartCookieForOAuthLoginTokenExchange(std::string());
 
   scoped_refptr<net::HttpResponseHeaders> reponse_headers =
       new net::HttpResponseHeaders("");
diff --git a/google_apis/gaia/gaia_urls.cc b/google_apis/gaia/gaia_urls.cc
index e314a10..c76928a97 100644
--- a/google_apis/gaia/gaia_urls.cc
+++ b/google_apis/gaia/gaia_urls.cc
@@ -39,7 +39,8 @@
 
 // API calls from accounts.google.com (LSO)
 const char kGetOAuthTokenUrlSuffix[] = "o/oauth/GetOAuthToken/";
-const char kClientLoginToOAuth2UrlSuffix[] = "o/oauth2/programmatic_auth";
+const char kDeprecatedClientLoginToOAuth2UrlSuffix[] =
+    "o/oauth2/programmatic_auth";
 const char kOAuth2AuthUrlSuffix[] = "o/oauth2/auth";
 const char kOAuth2RevokeUrlSuffix[] = "o/oauth2/revoke";
 const char kOAuth2IFrameUrlSuffix[] = "o/oauth2/iframerpc";
@@ -121,8 +122,8 @@
 
   // URLs from accounts.google.com (LSO).
   get_oauth_token_url_ = lso_origin_url_.Resolve(kGetOAuthTokenUrlSuffix);
-  client_login_to_oauth2_url_ =
-      lso_origin_url_.Resolve(kClientLoginToOAuth2UrlSuffix);
+  deprecated_client_login_to_oauth2_url_ =
+      lso_origin_url_.Resolve(kDeprecatedClientLoginToOAuth2UrlSuffix);
   oauth2_auth_url_ = lso_origin_url_.Resolve(kOAuth2AuthUrlSuffix);
   oauth2_revoke_url_ = lso_origin_url_.Resolve(kOAuth2RevokeUrlSuffix);
   oauth2_iframe_url_ =
@@ -241,8 +242,8 @@
   return oauth2_chrome_client_secret_;
 }
 
-const GURL& GaiaUrls::client_login_to_oauth2_url() const {
-  return client_login_to_oauth2_url_;
+const GURL& GaiaUrls::deprecated_client_login_to_oauth2_url() const {
+  return deprecated_client_login_to_oauth2_url_;
 }
 
 const GURL& GaiaUrls::oauth2_auth_url() const {
diff --git a/google_apis/gaia/gaia_urls.h b/google_apis/gaia/gaia_urls.h
index b4951d4..42f6516 100644
--- a/google_apis/gaia/gaia_urls.h
+++ b/google_apis/gaia/gaia_urls.h
@@ -40,7 +40,7 @@
 
   const std::string& oauth2_chrome_client_id() const;
   const std::string& oauth2_chrome_client_secret() const;
-  const GURL& client_login_to_oauth2_url() const;
+  const GURL& deprecated_client_login_to_oauth2_url() const;
   const GURL& oauth2_auth_url() const;
   const GURL& oauth2_token_url() const;
   const GURL& oauth2_issue_token_url() const;
@@ -94,7 +94,7 @@
   std::string oauth2_chrome_client_id_;
   std::string oauth2_chrome_client_secret_;
 
-  GURL client_login_to_oauth2_url_;
+  GURL deprecated_client_login_to_oauth2_url_;
   GURL oauth2_auth_url_;
   GURL oauth2_token_url_;
   GURL oauth2_issue_token_url_;
diff --git a/gpu/BUILD.gn b/gpu/BUILD.gn
index d890292..c3f8843 100644
--- a/gpu/BUILD.gn
+++ b/gpu/BUILD.gn
@@ -357,6 +357,7 @@
   if ((is_win || (is_linux && !use_ozone)) && !is_asan) {
     sources += [
       "command_buffer/service/gles2_cmd_decoder_passthrough_unittest_buffers.cc",
+      "command_buffer/service/gles2_cmd_decoder_passthrough_unittest_commands.cc",
       "command_buffer/service/gles2_cmd_decoder_passthrough_unittest_drawing.cc",
       "command_buffer/service/gles2_cmd_decoder_passthrough_unittest_framebuffers.cc",
     ]
diff --git a/gpu/command_buffer/build_gles2_cmd_buffer.py b/gpu/command_buffer/build_gles2_cmd_buffer.py
index f313b7c..c8a0a2c 100755
--- a/gpu/command_buffer/build_gles2_cmd_buffer.py
+++ b/gpu/command_buffer/build_gles2_cmd_buffer.py
@@ -5038,6 +5038,10 @@
     f.write("""error::Error GLES2DecoderPassthroughImpl::Handle%(name)s(
         uint32_t immediate_data_size, const volatile void* cmd_data) {
       """ % {'name': func.name})
+    if func.IsES3():
+      f.write("""if (!feature_info_->IsWebGL2OrES3Context())
+          return error::kUnknownCommand;
+        """)
     if func.GetCmdArgs():
       f.write("""const volatile gles2::cmds::%(name)s& c =
             *static_cast<const volatile gles2::cmds::%(name)s*>(cmd_data);
@@ -5054,6 +5058,7 @@
   def WritePassthroughServiceImplementation(self, func, f):
     """Writes the service implementation for a command."""
     self.WritePassthroughServiceFunctionHeader(func, f)
+    self.WriteHandlerExtensionCheck(func, f)
     self.WriteServiceHandlerArgGetCode(func, f)
     func.WritePassthroughHandlerValidation(f)
     self.WritePassthroughServiceFunctionDoerCall(func, f)
@@ -5064,6 +5069,7 @@
   def WritePassthroughImmediateServiceImplementation(self, func, f):
     """Writes the service implementation for a command."""
     self.WritePassthroughServiceFunctionHeader(func, f)
+    self.WriteHandlerExtensionCheck(func, f)
     self.WriteImmediateServiceHandlerArgGetCode(func, f)
     func.WritePassthroughHandlerValidation(f)
     self.WritePassthroughServiceFunctionDoerCall(func, f)
@@ -5074,6 +5080,7 @@
   def WritePassthroughBucketServiceImplementation(self, func, f):
     """Writes the service implementation for a command."""
     self.WritePassthroughServiceFunctionHeader(func, f)
+    self.WriteHandlerExtensionCheck(func, f)
     self.WriteBucketServiceHandlerArgGetCode(func, f)
     func.WritePassthroughHandlerValidation(f)
     self.WritePassthroughServiceFunctionDoerCall(func, f)
@@ -8234,6 +8241,7 @@
   def WritePassthroughServiceImplementation(self, func, f):
     """Overrriden from TypeHandler."""
     self.WritePassthroughServiceFunctionHeader(func, f)
+    self.WriteHandlerExtensionCheck(func, f)
     self.WriteServiceHandlerArgGetCode(func, f)
 
     code = """  typedef cmds::%(func_name)s::Result Result;
@@ -9941,7 +9949,9 @@
 class GLGenerator(object):
   """A class to generate GL command buffers."""
 
-  _function_re = re.compile(r'GL_APICALL(.*?)GL_APIENTRY (.*?) \((.*?)\);')
+  _whitespace_re = re.compile(r'^\w*$')
+  _comment_re = re.compile(r'^//.*$')
+  _function_re = re.compile(r'^GL_APICALL(.*?)GL_APIENTRY (.*?) \((.*?)\);$')
 
   def __init__(self, verbose):
     self.original_functions = []
@@ -9988,6 +9998,8 @@
     with open(filename, "r") as f:
       functions = f.read()
     for line in functions.splitlines():
+      if self._whitespace_re.match(line) or self._comment_re.match(line):
+        continue
       match = self._function_re.match(line)
       if match:
         func_name = match.group(2)[2:]
@@ -10025,6 +10037,9 @@
               self.AddFunction(f)
           else:
             self.AddFunction(f)
+      else:
+        self.Error("Could not parse function: %s using regex: %s" %
+                   (line, self._function_re.pattern))
 
     self.Log("Auto Generated Functions    : %d" %
              len([f for f in self.functions if f.can_auto_generate or
diff --git a/gpu/command_buffer/service/context_group.cc b/gpu/command_buffer/service/context_group.cc
index 7453d71..e510684 100644
--- a/gpu/command_buffer/service/context_group.cc
+++ b/gpu/command_buffer/service/context_group.cc
@@ -582,7 +582,9 @@
   }
 
   if (texture_manager_ != NULL) {
-    texture_manager_->Destroy(have_context);
+    if (!have_context)
+      texture_manager_->MarkContextLost();
+    texture_manager_->Destroy();
     texture_manager_.reset();
     ReportProgress();
   }
diff --git a/gpu/command_buffer/service/feature_info.cc b/gpu/command_buffer/service/feature_info.cc
index cb9f614..d24e73c9 100644
--- a/gpu/command_buffer/service/feature_info.cc
+++ b/gpu/command_buffer/service/feature_info.cc
@@ -328,6 +328,8 @@
 }
 
 void FeatureInfo::EnableEXTColorBufferHalfFloat() {
+  if (!ext_color_buffer_half_float_available_)
+    return;
   AddExtensionString("GL_EXT_color_buffer_half_float");
   validators_.render_buffer_format.AddValue(GL_R16F);
   validators_.render_buffer_format.AddValue(GL_RG16F);
@@ -1619,9 +1621,10 @@
   }
 
   // Enable GL_EXT_color_buffer_half_float if we have found the capability.
-  if (enable_ext_color_buffer_half_float &&
-      !disallowed_features_.ext_color_buffer_half_float) {
-    EnableEXTColorBufferHalfFloat();
+  if (enable_ext_color_buffer_half_float) {
+    ext_color_buffer_half_float_available_ = true;
+    if (!disallowed_features_.ext_color_buffer_half_float)
+      EnableEXTColorBufferHalfFloat();
   }
 
   if (enable_texture_float) {
diff --git a/gpu/command_buffer/service/feature_info.h b/gpu/command_buffer/service/feature_info.h
index 578ec82..d9fbdad 100644
--- a/gpu/command_buffer/service/feature_info.h
+++ b/gpu/command_buffer/service/feature_info.h
@@ -187,6 +187,10 @@
     return ext_color_buffer_float_available_;
   }
 
+  bool ext_color_buffer_half_float_available() const {
+    return ext_color_buffer_half_float_available_;
+  }
+
   bool oes_texture_float_linear_available() const {
     return oes_texture_float_linear_available_;
   }
@@ -218,6 +222,7 @@
   const GpuDriverBugWorkarounds workarounds_;
 
   bool ext_color_buffer_float_available_ = false;
+  bool ext_color_buffer_half_float_available_ = false;
   bool oes_texture_float_linear_available_ = false;
   bool oes_texture_half_float_linear_available_ = false;
 
diff --git a/gpu/command_buffer/service/framebuffer_manager_unittest.cc b/gpu/command_buffer/service/framebuffer_manager_unittest.cc
index 6a96d4c..01551f9 100644
--- a/gpu/command_buffer/service/framebuffer_manager_unittest.cc
+++ b/gpu/command_buffer/service/framebuffer_manager_unittest.cc
@@ -55,7 +55,8 @@
   }
   ~FramebufferManagerTest() override {
     manager_.Destroy(false);
-    texture_manager_->Destroy(false);
+    texture_manager_->MarkContextLost();
+    texture_manager_->Destroy();
     renderbuffer_manager_->Destroy(false);
   }
 
@@ -133,7 +134,8 @@
   }
   ~FramebufferInfoTestBase() override {
     manager_.Destroy(false);
-    texture_manager_->Destroy(false);
+    texture_manager_->MarkContextLost();
+    texture_manager_->Destroy();
     renderbuffer_manager_->Destroy(false);
   }
 
diff --git a/gpu/command_buffer/service/gles2_cmd_decoder.cc b/gpu/command_buffer/service/gles2_cmd_decoder.cc
index cc4a8d0..a080d53 100644
--- a/gpu/command_buffer/service/gles2_cmd_decoder.cc
+++ b/gpu/command_buffer/service/gles2_cmd_decoder.cc
@@ -4952,6 +4952,9 @@
     for (auto& fence : deschedule_until_finished_fences_) {
       fence->Invalidate();
     }
+
+    if (group_->texture_manager())
+      group_->texture_manager()->MarkContextLost();
   }
   deschedule_until_finished_fences_.clear();
 
@@ -16147,6 +16150,10 @@
   if (feature_str.find("GL_EXT_color_buffer_float ") != std::string::npos) {
     feature_info_->EnableEXTColorBufferFloat();
   }
+  if (feature_str.find("GL_EXT_color_buffer_half_float ") !=
+      std::string::npos) {
+    feature_info_->EnableEXTColorBufferHalfFloat();
+  }
   if (feature_str.find("GL_OES_texture_float_linear ") != std::string::npos) {
     feature_info_->EnableOESTextureFloatLinear();
   }
@@ -16371,6 +16378,8 @@
 error::Error GLES2DecoderImpl::HandleDescheduleUntilFinishedCHROMIUM(
     uint32_t immediate_data_size,
     const volatile void* cmd_data) {
+  if (!gl::GLFence::IsSupported())
+    return error::kNoError;
   std::unique_ptr<gl::GLFence> fence(gl::GLFence::Create());
   deschedule_until_finished_fences_.push_back(std::move(fence));
 
@@ -16705,6 +16714,15 @@
     }
     query =
         query_manager_->CreateQuery(target, client_id, std::move(buffer), sync);
+  } else {
+    if (query->target() != target) {
+      LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, "glQueryCounterEXT",
+                         "target does not match");
+      return error::kNoError;
+    } else if (query->sync() != sync) {
+      DLOG(ERROR) << "Shared memory used by query not the same as before";
+      return error::kInvalidArguments;
+    }
   }
   query_manager_->QueryCounter(query, submit_count);
 
diff --git a/gpu/command_buffer/service/gles2_cmd_decoder_passthrough.cc b/gpu/command_buffer/service/gles2_cmd_decoder_passthrough.cc
index 93a96c1..5661067 100644
--- a/gpu/command_buffer/service/gles2_cmd_decoder_passthrough.cc
+++ b/gpu/command_buffer/service/gles2_cmd_decoder_passthrough.cc
@@ -857,7 +857,9 @@
   if (!have_context) {
     for (const auto& bound_texture_type : bound_textures_) {
       for (const auto& bound_texture : bound_texture_type.second) {
-        bound_texture.texture->MarkContextLost();
+        if (bound_texture.texture) {
+          bound_texture.texture->MarkContextLost();
+        }
       }
     }
   }
diff --git a/gpu/command_buffer/service/gles2_cmd_decoder_passthrough.h b/gpu/command_buffer/service/gles2_cmd_decoder_passthrough.h
index 6603f67..56958e6 100644
--- a/gpu/command_buffer/service/gles2_cmd_decoder_passthrough.h
+++ b/gpu/command_buffer/service/gles2_cmd_decoder_passthrough.h
@@ -381,6 +381,10 @@
 
   bool IsEmulatedFramebufferBound(GLenum target) const;
 
+  const FeatureInfo::FeatureFlags& features() const {
+    return feature_info_->feature_flags();
+  }
+
   GLES2DecoderClient* client_;
 
   int commands_to_process_;
diff --git a/gpu/command_buffer/service/gles2_cmd_decoder_passthrough_doers.cc b/gpu/command_buffer/service/gles2_cmd_decoder_passthrough_doers.cc
index 36c9593..fd4801d 100644
--- a/gpu/command_buffer/service/gles2_cmd_decoder_passthrough_doers.cc
+++ b/gpu/command_buffer/service/gles2_cmd_decoder_passthrough_doers.cc
@@ -2822,10 +2822,6 @@
     GLenum internalformat,
     GLsizei width,
     GLsizei height) {
-  if (!feature_info_->feature_flags().chromium_framebuffer_multisample) {
-    return error::kUnknownCommand;
-  }
-
   if (feature_info_->feature_flags().angle_framebuffer_multisample) {
     api()->glRenderbufferStorageMultisampleANGLEFn(
         target, samples, internalformat, width, height);
@@ -2843,10 +2839,6 @@
     GLenum internalformat,
     GLsizei width,
     GLsizei height) {
-  if (!feature_info_->feature_flags().chromium_framebuffer_multisample) {
-    return error::kUnknownCommand;
-  }
-
   if (feature_info_->feature_flags().angle_framebuffer_multisample) {
     api()->glRenderbufferStorageMultisampleANGLEFn(
         target, samples, internalformat, width, height);
@@ -2865,10 +2857,6 @@
     GLuint texture,
     GLint level,
     GLsizei samples) {
-  if (!feature_info_->feature_flags().multisampled_render_to_texture) {
-    return error::kUnknownCommand;
-  }
-
   if (IsEmulatedFramebufferBound(target)) {
     InsertError(GL_INVALID_OPERATION,
                 "Cannot change the attachments of the default framebuffer.");
@@ -2954,10 +2942,6 @@
     int32_t sync_shm_id,
     uint32_t sync_shm_offset,
     uint32_t submit_count) {
-  if (!feature_info_->feature_flags().ext_disjoint_timer_query) {
-    return error::kUnknownCommand;
-  }
-
   scoped_refptr<gpu::Buffer> buffer = GetSharedMemoryBuffer(sync_shm_id);
   if (!buffer)
     return error::kInvalidArguments;
@@ -3116,10 +3100,6 @@
 error::Error GLES2DecoderPassthroughImpl::DoInsertEventMarkerEXT(
     GLsizei length,
     const char* marker) {
-  if (!feature_info_->feature_flags().ext_debug_marker) {
-    return error::kUnknownCommand;
-  }
-
   api()->glInsertEventMarkerEXTFn(length, marker);
   return error::kNoError;
 }
@@ -3127,19 +3107,11 @@
 error::Error GLES2DecoderPassthroughImpl::DoPushGroupMarkerEXT(
     GLsizei length,
     const char* marker) {
-  if (!feature_info_->feature_flags().ext_debug_marker) {
-    return error::kUnknownCommand;
-  }
-
   api()->glPushGroupMarkerEXTFn(length, marker);
   return error::kNoError;
 }
 
 error::Error GLES2DecoderPassthroughImpl::DoPopGroupMarkerEXT() {
-  if (!feature_info_->feature_flags().ext_debug_marker) {
-    return error::kUnknownCommand;
-  }
-
   api()->glPopGroupMarkerEXTFn();
   return error::kNoError;
 }
@@ -3848,10 +3820,6 @@
     GLboolean unpack_flip_y,
     GLboolean unpack_premultiply_alpha,
     GLboolean unpack_unmultiply_alpha) {
-  if (!feature_info_->feature_flags().chromium_copy_texture) {
-    return error::kUnknownCommand;
-  }
-
   api()->glCopyTextureCHROMIUMFn(
       GetTextureServiceID(api(), source_id, resources_, false), source_level,
       dest_target, GetTextureServiceID(api(), dest_id, resources_, false),
@@ -3875,10 +3843,6 @@
     GLboolean unpack_flip_y,
     GLboolean unpack_premultiply_alpha,
     GLboolean unpack_unmultiply_alpha) {
-  if (!feature_info_->feature_flags().chromium_copy_texture) {
-    return error::kUnknownCommand;
-  }
-
   api()->glCopySubTextureCHROMIUMFn(
       GetTextureServiceID(api(), source_id, resources_, false), source_level,
       dest_target, GetTextureServiceID(api(), dest_id, resources_, false),
@@ -3890,10 +3854,6 @@
 error::Error GLES2DecoderPassthroughImpl::DoCompressedCopyTextureCHROMIUM(
     GLuint source_id,
     GLuint dest_id) {
-  if (!feature_info_->feature_flags().chromium_copy_compressed_texture) {
-    return error::kUnknownCommand;
-  }
-
   api()->glCompressedCopyTextureCHROMIUMFn(
       GetTextureServiceID(api(), source_id, resources_, false),
       GetTextureServiceID(api(), dest_id, resources_, false));
@@ -3905,9 +3865,6 @@
     GLint first,
     GLsizei count,
     GLsizei primcount) {
-  if (!feature_info_->feature_flags().angle_instanced_arrays) {
-    return error::kUnknownCommand;
-  }
   api()->glDrawArraysInstancedANGLEFn(mode, first, count, primcount);
   return error::kNoError;
 }
@@ -3918,9 +3875,6 @@
     GLenum type,
     const void* indices,
     GLsizei primcount) {
-  if (!feature_info_->feature_flags().angle_instanced_arrays) {
-    return error::kUnknownCommand;
-  }
   api()->glDrawElementsInstancedANGLEFn(mode, count, type, indices, primcount);
   return error::kNoError;
 }
@@ -3928,9 +3882,6 @@
 error::Error GLES2DecoderPassthroughImpl::DoVertexAttribDivisorANGLE(
     GLuint index,
     GLuint divisor) {
-  if (!feature_info_->feature_flags().angle_instanced_arrays) {
-    return error::kUnknownCommand;
-  }
   api()->glVertexAttribDivisorANGLEFn(index, divisor);
   return error::kNoError;
 }
@@ -4092,10 +4043,6 @@
     GLenum target,
     GLsizei count,
     const volatile GLenum* attachments) {
-  if (!feature_info_->feature_flags().ext_discard_framebuffer) {
-    return error::kUnknownCommand;
-  }
-
   // Validate that count is non-negative before allocating a vector
   if (count < 0) {
     InsertError(GL_INVALID_VALUE, "count cannot be negative.");
diff --git a/gpu/command_buffer/service/gles2_cmd_decoder_passthrough_handlers.cc b/gpu/command_buffer/service/gles2_cmd_decoder_passthrough_handlers.cc
index 7e698dc..ae09c237 100644
--- a/gpu/command_buffer/service/gles2_cmd_decoder_passthrough_handlers.cc
+++ b/gpu/command_buffer/service/gles2_cmd_decoder_passthrough_handlers.cc
@@ -53,6 +53,9 @@
 error::Error GLES2DecoderPassthroughImpl::HandleClientWaitSync(
     uint32_t immediate_data_size,
     const volatile void* cmd_data) {
+  if (!feature_info_->IsWebGL2OrES3Context()) {
+    return error::kUnknownCommand;
+  }
   const volatile gles2::cmds::ClientWaitSync& c =
       *static_cast<const volatile gles2::cmds::ClientWaitSync*>(cmd_data);
   const GLuint sync = static_cast<GLuint>(c.sync);
@@ -94,6 +97,9 @@
 error::Error GLES2DecoderPassthroughImpl::HandleFenceSync(
     uint32_t immediate_data_size,
     const volatile void* cmd_data) {
+  if (!feature_info_->IsWebGL2OrES3Context()) {
+    return error::kUnknownCommand;
+  }
   const volatile gles2::cmds::FenceSync& c =
       *static_cast<const volatile gles2::cmds::FenceSync*>(cmd_data);
   GLenum condition = static_cast<GLenum>(c.condition);
@@ -202,6 +208,9 @@
 error::Error GLES2DecoderPassthroughImpl::HandleGetActiveUniformBlockiv(
     uint32_t immediate_data_size,
     const volatile void* cmd_data) {
+  if (!feature_info_->IsWebGL2OrES3Context()) {
+    return error::kUnknownCommand;
+  }
   const volatile gles2::cmds::GetActiveUniformBlockiv& c =
       *static_cast<const volatile gles2::cmds::GetActiveUniformBlockiv*>(
           cmd_data);
@@ -236,6 +245,9 @@
 error::Error GLES2DecoderPassthroughImpl::HandleGetActiveUniformBlockName(
     uint32_t immediate_data_size,
     const volatile void* cmd_data) {
+  if (!feature_info_->IsWebGL2OrES3Context()) {
+    return error::kUnknownCommand;
+  }
   const volatile gles2::cmds::GetActiveUniformBlockName& c =
       *static_cast<const volatile gles2::cmds::GetActiveUniformBlockName*>(
           cmd_data);
@@ -272,6 +284,9 @@
 error::Error GLES2DecoderPassthroughImpl::HandleGetActiveUniformsiv(
     uint32_t immediate_data_size,
     const volatile void* cmd_data) {
+  if (!feature_info_->IsWebGL2OrES3Context()) {
+    return error::kUnknownCommand;
+  }
   const volatile gles2::cmds::GetActiveUniformsiv& c =
       *static_cast<const volatile gles2::cmds::GetActiveUniformsiv*>(cmd_data);
   GLuint program = static_cast<GLuint>(c.program);
@@ -372,6 +387,9 @@
 error::Error GLES2DecoderPassthroughImpl::HandleGetBufferSubDataAsyncCHROMIUM(
     uint32_t immediate_data_size,
     const volatile void* cmd_data) {
+  if (!feature_info_->IsWebGL2OrES3Context()) {
+    return error::kUnknownCommand;
+  }
   const volatile gles2::cmds::GetBufferSubDataAsyncCHROMIUM& c =
       *static_cast<const volatile gles2::cmds::GetBufferSubDataAsyncCHROMIUM*>(
           cmd_data);
@@ -394,6 +412,9 @@
 error::Error GLES2DecoderPassthroughImpl::HandleGetFragDataLocation(
     uint32_t immediate_data_size,
     const volatile void* cmd_data) {
+  if (!feature_info_->IsWebGL2OrES3Context()) {
+    return error::kUnknownCommand;
+  }
   const volatile gles2::cmds::GetFragDataLocation& c =
       *static_cast<const volatile gles2::cmds::GetFragDataLocation*>(cmd_data);
   GLuint program = static_cast<GLuint>(c.program);
@@ -423,6 +444,9 @@
 error::Error GLES2DecoderPassthroughImpl::HandleGetInternalformativ(
     uint32_t immediate_data_size,
     const volatile void* cmd_data) {
+  if (!feature_info_->IsWebGL2OrES3Context()) {
+    return error::kUnknownCommand;
+  }
   const volatile gles2::cmds::GetInternalformativ& c =
       *static_cast<const volatile gles2::cmds::GetInternalformativ*>(cmd_data);
   GLenum target = static_cast<GLenum>(c.target);
@@ -574,6 +598,9 @@
 error::Error GLES2DecoderPassthroughImpl::HandleGetTransformFeedbackVarying(
     uint32_t immediate_data_size,
     const volatile void* cmd_data) {
+  if (!feature_info_->IsWebGL2OrES3Context()) {
+    return error::kUnknownCommand;
+  }
   const volatile gles2::cmds::GetTransformFeedbackVarying& c =
       *static_cast<const volatile gles2::cmds::GetTransformFeedbackVarying*>(
           cmd_data);
@@ -614,6 +641,9 @@
 error::Error GLES2DecoderPassthroughImpl::HandleGetUniformBlockIndex(
     uint32_t immediate_data_size,
     const volatile void* cmd_data) {
+  if (!feature_info_->IsWebGL2OrES3Context()) {
+    return error::kUnknownCommand;
+  }
   const volatile gles2::cmds::GetUniformBlockIndex& c =
       *static_cast<const volatile gles2::cmds::GetUniformBlockIndex*>(cmd_data);
   GLuint program = static_cast<GLuint>(c.program);
@@ -707,6 +737,9 @@
 error::Error GLES2DecoderPassthroughImpl::HandleGetUniformuiv(
     uint32_t immediate_data_size,
     const volatile void* cmd_data) {
+  if (!feature_info_->IsWebGL2OrES3Context()) {
+    return error::kUnknownCommand;
+  }
   const volatile gles2::cmds::GetUniformuiv& c =
       *static_cast<const volatile gles2::cmds::GetUniformuiv*>(cmd_data);
   GLuint program = static_cast<GLuint>(c.program);
@@ -739,6 +772,9 @@
 error::Error GLES2DecoderPassthroughImpl::HandleGetUniformIndices(
     uint32_t immediate_data_size,
     const volatile void* cmd_data) {
+  if (!feature_info_->IsWebGL2OrES3Context()) {
+    return error::kUnknownCommand;
+  }
   const volatile gles2::cmds::GetUniformIndices& c =
       *static_cast<const volatile gles2::cmds::GetUniformIndices*>(cmd_data);
   GLuint program = static_cast<GLuint>(c.program);
@@ -994,6 +1030,9 @@
 error::Error GLES2DecoderPassthroughImpl::HandleTexImage3D(
     uint32_t immediate_data_size,
     const volatile void* cmd_data) {
+  if (!feature_info_->IsWebGL2OrES3Context()) {
+    return error::kUnknownCommand;
+  }
   const volatile gles2::cmds::TexImage3D& c =
       *static_cast<const volatile gles2::cmds::TexImage3D*>(cmd_data);
   GLenum target = static_cast<GLenum>(c.target);
@@ -1063,6 +1102,9 @@
 error::Error GLES2DecoderPassthroughImpl::HandleTexSubImage3D(
     uint32_t immediate_data_size,
     const volatile void* cmd_data) {
+  if (!feature_info_->IsWebGL2OrES3Context()) {
+    return error::kUnknownCommand;
+  }
   const volatile gles2::cmds::TexSubImage3D& c =
       *static_cast<const volatile gles2::cmds::TexSubImage3D*>(cmd_data);
   GLenum target = static_cast<GLenum>(c.target);
@@ -1099,6 +1141,9 @@
 error::Error GLES2DecoderPassthroughImpl::HandleUniformBlockBinding(
     uint32_t immediate_data_size,
     const volatile void* cmd_data) {
+  if (!feature_info_->IsWebGL2OrES3Context()) {
+    return error::kUnknownCommand;
+  }
   const volatile gles2::cmds::UniformBlockBinding& c =
       *static_cast<const volatile gles2::cmds::UniformBlockBinding*>(cmd_data);
   GLuint program = static_cast<GLuint>(c.program);
@@ -1111,6 +1156,9 @@
 error::Error GLES2DecoderPassthroughImpl::HandleVertexAttribIPointer(
     uint32_t immediate_data_size,
     const volatile void* cmd_data) {
+  if (!feature_info_->IsWebGL2OrES3Context()) {
+    return error::kUnknownCommand;
+  }
   const volatile gles2::cmds::VertexAttribIPointer& c =
       *static_cast<const volatile gles2::cmds::VertexAttribIPointer*>(cmd_data);
   GLuint index = static_cast<GLuint>(c.indx);
@@ -1142,6 +1190,8 @@
 error::Error GLES2DecoderPassthroughImpl::HandleWaitSync(
     uint32_t immediate_data_size,
     const volatile void* cmd_data) {
+  if (!feature_info_->IsWebGL2OrES3Context())
+    return error::kUnknownCommand;
   const volatile gles2::cmds::WaitSync& c =
       *static_cast<const volatile gles2::cmds::WaitSync*>(cmd_data);
   const GLuint sync = static_cast<GLuint>(c.sync);
@@ -1154,6 +1204,9 @@
 error::Error GLES2DecoderPassthroughImpl::HandleQueryCounterEXT(
     uint32_t immediate_data_size,
     const volatile void* cmd_data) {
+  if (!features().ext_disjoint_timer_query) {
+    return error::kUnknownCommand;
+  }
   const volatile gles2::cmds::QueryCounterEXT& c =
       *static_cast<const volatile gles2::cmds::QueryCounterEXT*>(cmd_data);
   GLuint id = static_cast<GLuint>(c.id);
@@ -1210,6 +1263,9 @@
 error::Error GLES2DecoderPassthroughImpl::HandleInsertEventMarkerEXT(
     uint32_t immediate_data_size,
     const volatile void* cmd_data) {
+  if (!features().ext_debug_marker) {
+    return error::kUnknownCommand;
+  }
   const volatile gles2::cmds::InsertEventMarkerEXT& c =
       *static_cast<const volatile gles2::cmds::InsertEventMarkerEXT*>(cmd_data);
   uint32_t bucket_id = c.bucket_id;
@@ -1228,6 +1284,9 @@
 error::Error GLES2DecoderPassthroughImpl::HandlePushGroupMarkerEXT(
     uint32_t immediate_data_size,
     const volatile void* cmd_data) {
+  if (!features().ext_debug_marker) {
+    return error::kUnknownCommand;
+  }
   const volatile gles2::cmds::PushGroupMarkerEXT& c =
       *static_cast<const volatile gles2::cmds::PushGroupMarkerEXT*>(cmd_data);
   uint32_t bucket_id = c.bucket_id;
@@ -1283,6 +1342,9 @@
 error::Error GLES2DecoderPassthroughImpl::HandleMapBufferRange(
     uint32_t immediate_data_size,
     const volatile void* cmd_data) {
+  if (!feature_info_->IsWebGL2OrES3Context()) {
+    return error::kUnknownCommand;
+  }
   const volatile gles2::cmds::MapBufferRange& c =
       *static_cast<const volatile gles2::cmds::MapBufferRange*>(cmd_data);
   GLenum target = static_cast<GLenum>(c.target);
@@ -1319,6 +1381,9 @@
 error::Error GLES2DecoderPassthroughImpl::HandleUnmapBuffer(
     uint32_t immediate_data_size,
     const volatile void* cmd_data) {
+  if (!feature_info_->IsWebGL2OrES3Context()) {
+    return error::kUnknownCommand;
+  }
   const volatile gles2::cmds::UnmapBuffer& c =
       *static_cast<const volatile gles2::cmds::UnmapBuffer*>(cmd_data);
   GLenum target = static_cast<GLenum>(c.target);
@@ -1344,6 +1409,9 @@
 GLES2DecoderPassthroughImpl::HandleGetRequestableExtensionsCHROMIUM(
     uint32_t immediate_data_size,
     const volatile void* cmd_data) {
+  if (!features().angle_request_extension) {
+    return error::kUnknownCommand;
+  }
   const volatile gles2::cmds::GetRequestableExtensionsCHROMIUM& c =
       *static_cast<
           const volatile gles2::cmds::GetRequestableExtensionsCHROMIUM*>(
@@ -1367,6 +1435,9 @@
 error::Error GLES2DecoderPassthroughImpl::HandleRequestExtensionCHROMIUM(
     uint32_t immediate_data_size,
     const volatile void* cmd_data) {
+  if (!features().angle_request_extension) {
+    return error::kUnknownCommand;
+  }
   const volatile gles2::cmds::RequestExtensionCHROMIUM& c =
       *static_cast<const volatile gles2::cmds::RequestExtensionCHROMIUM*>(
           cmd_data);
@@ -1410,6 +1481,9 @@
 error::Error GLES2DecoderPassthroughImpl::HandleGetUniformBlocksCHROMIUM(
     uint32_t immediate_data_size,
     const volatile void* cmd_data) {
+  if (!feature_info_->IsWebGL2OrES3Context()) {
+    return error::kUnknownCommand;
+  }
   const volatile gles2::cmds::GetUniformBlocksCHROMIUM& c =
       *static_cast<const volatile gles2::cmds::GetUniformBlocksCHROMIUM*>(
           cmd_data);
@@ -1435,6 +1509,9 @@
 GLES2DecoderPassthroughImpl::HandleGetTransformFeedbackVaryingsCHROMIUM(
     uint32_t immediate_data_size,
     const volatile void* cmd_data) {
+  if (!feature_info_->IsWebGL2OrES3Context()) {
+    return error::kUnknownCommand;
+  }
   const volatile gles2::cmds::GetTransformFeedbackVaryingsCHROMIUM& c =
       *static_cast<
           const volatile gles2::cmds::GetTransformFeedbackVaryingsCHROMIUM*>(
@@ -1460,6 +1537,9 @@
 error::Error GLES2DecoderPassthroughImpl::HandleGetUniformsES3CHROMIUM(
     uint32_t immediate_data_size,
     const volatile void* cmd_data) {
+  if (!feature_info_->IsWebGL2OrES3Context()) {
+    return error::kUnknownCommand;
+  }
   const volatile gles2::cmds::GetUniformsES3CHROMIUM& c =
       *static_cast<const volatile gles2::cmds::GetUniformsES3CHROMIUM*>(
           cmd_data);
@@ -1484,6 +1564,9 @@
 error::Error GLES2DecoderPassthroughImpl::HandleGetTranslatedShaderSourceANGLE(
     uint32_t immediate_data_size,
     const volatile void* cmd_data) {
+  if (!features().angle_translated_shader_source) {
+    return error::kUnknownCommand;
+  }
   const volatile gles2::cmds::GetTranslatedShaderSourceANGLE& c =
       *static_cast<const volatile gles2::cmds::GetTranslatedShaderSourceANGLE*>(
           cmd_data);
@@ -1519,6 +1602,9 @@
 error::Error GLES2DecoderPassthroughImpl::HandleDrawArraysInstancedANGLE(
     uint32_t immediate_data_size,
     const volatile void* cmd_data) {
+  if (!features().angle_instanced_arrays) {
+    return error::kUnknownCommand;
+  }
   const volatile gles2::cmds::DrawArraysInstancedANGLE& c =
       *static_cast<const volatile gles2::cmds::DrawArraysInstancedANGLE*>(
           cmd_data);
@@ -1533,6 +1619,9 @@
 error::Error GLES2DecoderPassthroughImpl::HandleDrawElementsInstancedANGLE(
     uint32_t immediate_data_size,
     const volatile void* cmd_data) {
+  if (!features().angle_instanced_arrays) {
+    return error::kUnknownCommand;
+  }
   const volatile gles2::cmds::DrawElementsInstancedANGLE& c =
       *static_cast<const volatile gles2::cmds::DrawElementsInstancedANGLE*>(
           cmd_data);
@@ -1549,6 +1638,9 @@
 error::Error GLES2DecoderPassthroughImpl::HandleVertexAttribDivisorANGLE(
     uint32_t immediate_data_size,
     const volatile void* cmd_data) {
+  if (!features().angle_instanced_arrays) {
+    return error::kUnknownCommand;
+  }
   const volatile gles2::cmds::VertexAttribDivisorANGLE& c =
       *static_cast<const volatile gles2::cmds::VertexAttribDivisorANGLE*>(
           cmd_data);
@@ -1792,6 +1884,9 @@
 error::Error GLES2DecoderPassthroughImpl::HandleGenPathsCHROMIUM(
     uint32_t immediate_data_size,
     const volatile void* cmd_data) {
+  if (!features().chromium_path_rendering) {
+    return error::kUnknownCommand;
+  }
   const volatile gles2::cmds::GenPathsCHROMIUM& c =
       *static_cast<const volatile gles2::cmds::GenPathsCHROMIUM*>(cmd_data);
   GLuint path = static_cast<GLuint>(c.first_client_id);
@@ -1803,6 +1898,9 @@
 error::Error GLES2DecoderPassthroughImpl::HandleDeletePathsCHROMIUM(
     uint32_t immediate_data_size,
     const volatile void* cmd_data) {
+  if (!features().chromium_path_rendering) {
+    return error::kUnknownCommand;
+  }
   const volatile gles2::cmds::DeletePathsCHROMIUM& c =
       *static_cast<const volatile gles2::cmds::DeletePathsCHROMIUM*>(cmd_data);
   GLuint path = static_cast<GLuint>(c.first_client_id);
@@ -1814,6 +1912,9 @@
 error::Error GLES2DecoderPassthroughImpl::HandlePathCommandsCHROMIUM(
     uint32_t immediate_data_size,
     const volatile void* cmd_data) {
+  if (!features().chromium_path_rendering) {
+    return error::kUnknownCommand;
+  }
   const volatile gles2::cmds::PathCommandsCHROMIUM& c =
       *static_cast<const volatile gles2::cmds::PathCommandsCHROMIUM*>(cmd_data);
   GLuint path = static_cast<GLuint>(c.path);
@@ -1857,6 +1958,9 @@
 error::Error GLES2DecoderPassthroughImpl::HandlePathParameterfCHROMIUM(
     uint32_t immediate_data_size,
     const volatile void* cmd_data) {
+  if (!features().chromium_path_rendering) {
+    return error::kUnknownCommand;
+  }
   const volatile gles2::cmds::PathParameterfCHROMIUM& c =
       *static_cast<const volatile gles2::cmds::PathParameterfCHROMIUM*>(
           cmd_data);
@@ -1870,6 +1974,9 @@
 error::Error GLES2DecoderPassthroughImpl::HandlePathParameteriCHROMIUM(
     uint32_t immediate_data_size,
     const volatile void* cmd_data) {
+  if (!features().chromium_path_rendering) {
+    return error::kUnknownCommand;
+  }
   const volatile gles2::cmds::PathParameteriCHROMIUM& c =
       *static_cast<const volatile gles2::cmds::PathParameteriCHROMIUM*>(
           cmd_data);
@@ -1883,6 +1990,8 @@
 error::Error GLES2DecoderPassthroughImpl::HandleStencilFillPathCHROMIUM(
     uint32_t immediate_data_size,
     const volatile void* cmd_data) {
+  if (!features().chromium_path_rendering)
+    return error::kUnknownCommand;
   const volatile gles2::cmds::StencilFillPathCHROMIUM& c =
       *static_cast<const volatile gles2::cmds::StencilFillPathCHROMIUM*>(
           cmd_data);
@@ -1896,6 +2005,9 @@
 error::Error GLES2DecoderPassthroughImpl::HandleStencilStrokePathCHROMIUM(
     uint32_t immediate_data_size,
     const volatile void* cmd_data) {
+  if (!features().chromium_path_rendering) {
+    return error::kUnknownCommand;
+  }
   const volatile gles2::cmds::StencilStrokePathCHROMIUM& c =
       *static_cast<const volatile gles2::cmds::StencilStrokePathCHROMIUM*>(
           cmd_data);
@@ -1909,6 +2021,8 @@
 error::Error GLES2DecoderPassthroughImpl::HandleCoverFillPathCHROMIUM(
     uint32_t immediate_data_size,
     const volatile void* cmd_data) {
+  if (!features().chromium_path_rendering)
+    return error::kUnknownCommand;
   const volatile gles2::cmds::CoverFillPathCHROMIUM& c =
       *static_cast<const volatile gles2::cmds::CoverFillPathCHROMIUM*>(
           cmd_data);
@@ -1921,6 +2035,9 @@
 error::Error GLES2DecoderPassthroughImpl::HandleCoverStrokePathCHROMIUM(
     uint32_t immediate_data_size,
     const volatile void* cmd_data) {
+  if (!features().chromium_path_rendering) {
+    return error::kUnknownCommand;
+  }
   const volatile gles2::cmds::CoverStrokePathCHROMIUM& c =
       *static_cast<const volatile gles2::cmds::CoverStrokePathCHROMIUM*>(
           cmd_data);
@@ -1934,6 +2051,8 @@
 GLES2DecoderPassthroughImpl::HandleStencilThenCoverFillPathCHROMIUM(
     uint32_t immediate_data_size,
     const volatile void* cmd_data) {
+  if (!features().chromium_path_rendering)
+    return error::kUnknownCommand;
   const volatile gles2::cmds::StencilThenCoverFillPathCHROMIUM& c =
       *static_cast<
           const volatile gles2::cmds::StencilThenCoverFillPathCHROMIUM*>(
@@ -1950,6 +2069,9 @@
 GLES2DecoderPassthroughImpl::HandleStencilThenCoverStrokePathCHROMIUM(
     uint32_t immediate_data_size,
     const volatile void* cmd_data) {
+  if (!features().chromium_path_rendering) {
+    return error::kUnknownCommand;
+  }
   const volatile gles2::cmds::StencilThenCoverStrokePathCHROMIUM& c =
       *static_cast<
           const volatile gles2::cmds::StencilThenCoverStrokePathCHROMIUM*>(
@@ -1967,6 +2089,9 @@
 GLES2DecoderPassthroughImpl::HandleStencilFillPathInstancedCHROMIUM(
     uint32_t immediate_data_size,
     const volatile void* cmd_data) {
+  if (!features().chromium_path_rendering) {
+    return error::kUnknownCommand;
+  }
   const volatile gles2::cmds::StencilFillPathInstancedCHROMIUM& c =
       *static_cast<
           const volatile gles2::cmds::StencilFillPathInstancedCHROMIUM*>(
@@ -2017,6 +2142,9 @@
 GLES2DecoderPassthroughImpl::HandleStencilStrokePathInstancedCHROMIUM(
     uint32_t immediate_data_size,
     const volatile void* cmd_data) {
+  if (!features().chromium_path_rendering) {
+    return error::kUnknownCommand;
+  }
   const volatile gles2::cmds::StencilStrokePathInstancedCHROMIUM& c =
       *static_cast<
           const volatile gles2::cmds::StencilStrokePathInstancedCHROMIUM*>(
@@ -2066,6 +2194,9 @@
 error::Error GLES2DecoderPassthroughImpl::HandleCoverFillPathInstancedCHROMIUM(
     uint32_t immediate_data_size,
     const volatile void* cmd_data) {
+  if (!features().chromium_path_rendering) {
+    return error::kUnknownCommand;
+  }
   const volatile gles2::cmds::CoverFillPathInstancedCHROMIUM& c =
       *static_cast<const volatile gles2::cmds::CoverFillPathInstancedCHROMIUM*>(
           cmd_data);
@@ -2114,6 +2245,9 @@
 GLES2DecoderPassthroughImpl::HandleCoverStrokePathInstancedCHROMIUM(
     uint32_t immediate_data_size,
     const volatile void* cmd_data) {
+  if (!features().chromium_path_rendering) {
+    return error::kUnknownCommand;
+  }
   const volatile gles2::cmds::CoverStrokePathInstancedCHROMIUM& c =
       *static_cast<
           const volatile gles2::cmds::CoverStrokePathInstancedCHROMIUM*>(
@@ -2163,6 +2297,9 @@
 GLES2DecoderPassthroughImpl::HandleStencilThenCoverFillPathInstancedCHROMIUM(
     uint32_t immediate_data_size,
     const volatile void* cmd_data) {
+  if (!features().chromium_path_rendering) {
+    return error::kUnknownCommand;
+  }
   const volatile gles2::cmds::StencilThenCoverFillPathInstancedCHROMIUM& c =
       *static_cast<const volatile gles2::cmds::
                        StencilThenCoverFillPathInstancedCHROMIUM*>(cmd_data);
@@ -2214,6 +2351,9 @@
 GLES2DecoderPassthroughImpl::HandleStencilThenCoverStrokePathInstancedCHROMIUM(
     uint32_t immediate_data_size,
     const volatile void* cmd_data) {
+  if (!features().chromium_path_rendering) {
+    return error::kUnknownCommand;
+  }
   const volatile gles2::cmds::StencilThenCoverStrokePathInstancedCHROMIUM& c =
       *static_cast<const volatile gles2::cmds::
                        StencilThenCoverStrokePathInstancedCHROMIUM*>(cmd_data);
@@ -2265,6 +2405,9 @@
 GLES2DecoderPassthroughImpl::HandleBindFragmentInputLocationCHROMIUMBucket(
     uint32_t immediate_data_size,
     const volatile void* cmd_data) {
+  if (!features().chromium_path_rendering) {
+    return error::kUnknownCommand;
+  }
   const volatile gles2::cmds::BindFragmentInputLocationCHROMIUMBucket& c =
       *static_cast<
           const volatile gles2::cmds::BindFragmentInputLocationCHROMIUMBucket*>(
@@ -2289,6 +2432,9 @@
 GLES2DecoderPassthroughImpl::HandleProgramPathFragmentInputGenCHROMIUM(
     uint32_t immediate_data_size,
     const volatile void* cmd_data) {
+  if (!features().chromium_path_rendering) {
+    return error::kUnknownCommand;
+  }
   const volatile gles2::cmds::ProgramPathFragmentInputGenCHROMIUM& c =
       *static_cast<
           const volatile gles2::cmds::ProgramPathFragmentInputGenCHROMIUM*>(
@@ -2319,6 +2465,9 @@
 GLES2DecoderPassthroughImpl::HandleBindFragDataLocationIndexedEXTBucket(
     uint32_t immediate_data_size,
     const volatile void* cmd_data) {
+  if (!features().ext_blend_func_extended) {
+    return error::kUnknownCommand;
+  }
   const volatile gles2::cmds::BindFragDataLocationIndexedEXTBucket& c =
       *static_cast<
           const volatile gles2::cmds::BindFragDataLocationIndexedEXTBucket*>(
@@ -2343,6 +2492,9 @@
 error::Error GLES2DecoderPassthroughImpl::HandleBindFragDataLocationEXTBucket(
     uint32_t immediate_data_size,
     const volatile void* cmd_data) {
+  if (!features().ext_blend_func_extended) {
+    return error::kUnknownCommand;
+  }
   const volatile gles2::cmds::BindFragDataLocationEXTBucket& c =
       *static_cast<const volatile gles2::cmds::BindFragDataLocationEXTBucket*>(
           cmd_data);
@@ -2364,6 +2516,9 @@
 error::Error GLES2DecoderPassthroughImpl::HandleGetFragDataIndexEXT(
     uint32_t immediate_data_size,
     const volatile void* cmd_data) {
+  if (!features().ext_blend_func_extended) {
+    return error::kUnknownCommand;
+  }
   const volatile gles2::cmds::GetFragDataIndexEXT& c =
       *static_cast<const volatile gles2::cmds::GetFragDataIndexEXT*>(cmd_data);
   GLuint program = static_cast<GLuint>(c.program);
@@ -2507,6 +2662,9 @@
 
 error::Error GLES2DecoderPassthroughImpl::HandleCompressedTexImage3DBucket(
     uint32_t immediate_data_size, const volatile void* cmd_data) {
+  if (!feature_info_->IsWebGL2OrES3Context()) {
+    return error::kUnknownCommand;
+  }
   const volatile gles2::cmds::CompressedTexImage3DBucket& c =
       *static_cast<const volatile gles2::cmds::CompressedTexImage3DBucket*>(
           cmd_data);
@@ -2532,6 +2690,9 @@
 
 error::Error GLES2DecoderPassthroughImpl::HandleCompressedTexImage3D(
     uint32_t immediate_data_size, const volatile void* cmd_data) {
+  if (!feature_info_->IsWebGL2OrES3Context()) {
+    return error::kUnknownCommand;
+  }
   const volatile gles2::cmds::CompressedTexImage3D& c =
       *static_cast<const volatile gles2::cmds::CompressedTexImage3D*>(cmd_data);
   GLenum target = static_cast<GLenum>(c.target);
@@ -2564,6 +2725,9 @@
 
 error::Error GLES2DecoderPassthroughImpl::HandleCompressedTexSubImage3DBucket(
     uint32_t immediate_data_size, const volatile void* cmd_data) {
+  if (!feature_info_->IsWebGL2OrES3Context()) {
+    return error::kUnknownCommand;
+  }
   const volatile gles2::cmds::CompressedTexSubImage3DBucket& c =
       *static_cast<const volatile gles2::cmds::CompressedTexSubImage3DBucket*>(
           cmd_data);
@@ -2592,6 +2756,9 @@
 
 error::Error GLES2DecoderPassthroughImpl::HandleCompressedTexSubImage3D(
     uint32_t immediate_data_size, const volatile void* cmd_data) {
+  if (!feature_info_->IsWebGL2OrES3Context()) {
+    return error::kUnknownCommand;
+  }
   const volatile gles2::cmds::CompressedTexSubImage3D& c =
       *static_cast<const volatile gles2::cmds::CompressedTexSubImage3D*>(
           cmd_data);
diff --git a/gpu/command_buffer/service/gles2_cmd_decoder_passthrough_handlers_autogen.cc b/gpu/command_buffer/service/gles2_cmd_decoder_passthrough_handlers_autogen.cc
index 8d3736f..a0eff99 100644
--- a/gpu/command_buffer/service/gles2_cmd_decoder_passthrough_handlers_autogen.cc
+++ b/gpu/command_buffer/service/gles2_cmd_decoder_passthrough_handlers_autogen.cc
@@ -57,6 +57,8 @@
 error::Error GLES2DecoderPassthroughImpl::HandleBindBufferBase(
     uint32_t immediate_data_size,
     const volatile void* cmd_data) {
+  if (!feature_info_->IsWebGL2OrES3Context())
+    return error::kUnknownCommand;
   const volatile gles2::cmds::BindBufferBase& c =
       *static_cast<const volatile gles2::cmds::BindBufferBase*>(cmd_data);
   GLenum target = static_cast<GLenum>(c.target);
@@ -72,6 +74,8 @@
 error::Error GLES2DecoderPassthroughImpl::HandleBindBufferRange(
     uint32_t immediate_data_size,
     const volatile void* cmd_data) {
+  if (!feature_info_->IsWebGL2OrES3Context())
+    return error::kUnknownCommand;
   const volatile gles2::cmds::BindBufferRange& c =
       *static_cast<const volatile gles2::cmds::BindBufferRange*>(cmd_data);
   GLenum target = static_cast<GLenum>(c.target);
@@ -117,6 +121,8 @@
 error::Error GLES2DecoderPassthroughImpl::HandleBindSampler(
     uint32_t immediate_data_size,
     const volatile void* cmd_data) {
+  if (!feature_info_->IsWebGL2OrES3Context())
+    return error::kUnknownCommand;
   const volatile gles2::cmds::BindSampler& c =
       *static_cast<const volatile gles2::cmds::BindSampler*>(cmd_data);
   GLuint unit = static_cast<GLuint>(c.unit);
@@ -145,6 +151,8 @@
 error::Error GLES2DecoderPassthroughImpl::HandleBindTransformFeedback(
     uint32_t immediate_data_size,
     const volatile void* cmd_data) {
+  if (!feature_info_->IsWebGL2OrES3Context())
+    return error::kUnknownCommand;
   const volatile gles2::cmds::BindTransformFeedback& c =
       *static_cast<const volatile gles2::cmds::BindTransformFeedback*>(
           cmd_data);
@@ -285,6 +293,8 @@
 error::Error GLES2DecoderPassthroughImpl::HandleClearBufferfi(
     uint32_t immediate_data_size,
     const volatile void* cmd_data) {
+  if (!feature_info_->IsWebGL2OrES3Context())
+    return error::kUnknownCommand;
   const volatile gles2::cmds::ClearBufferfi& c =
       *static_cast<const volatile gles2::cmds::ClearBufferfi*>(cmd_data);
   GLenum buffer = static_cast<GLenum>(c.buffer);
@@ -301,6 +311,8 @@
 error::Error GLES2DecoderPassthroughImpl::HandleClearBufferfvImmediate(
     uint32_t immediate_data_size,
     const volatile void* cmd_data) {
+  if (!feature_info_->IsWebGL2OrES3Context())
+    return error::kUnknownCommand;
   const volatile gles2::cmds::ClearBufferfvImmediate& c =
       *static_cast<const volatile gles2::cmds::ClearBufferfvImmediate*>(
           cmd_data);
@@ -328,6 +340,8 @@
 error::Error GLES2DecoderPassthroughImpl::HandleClearBufferivImmediate(
     uint32_t immediate_data_size,
     const volatile void* cmd_data) {
+  if (!feature_info_->IsWebGL2OrES3Context())
+    return error::kUnknownCommand;
   const volatile gles2::cmds::ClearBufferivImmediate& c =
       *static_cast<const volatile gles2::cmds::ClearBufferivImmediate*>(
           cmd_data);
@@ -355,6 +369,8 @@
 error::Error GLES2DecoderPassthroughImpl::HandleClearBufferuivImmediate(
     uint32_t immediate_data_size,
     const volatile void* cmd_data) {
+  if (!feature_info_->IsWebGL2OrES3Context())
+    return error::kUnknownCommand;
   const volatile gles2::cmds::ClearBufferuivImmediate& c =
       *static_cast<const volatile gles2::cmds::ClearBufferuivImmediate*>(
           cmd_data);
@@ -453,6 +469,8 @@
 error::Error GLES2DecoderPassthroughImpl::HandleCopyBufferSubData(
     uint32_t immediate_data_size,
     const volatile void* cmd_data) {
+  if (!feature_info_->IsWebGL2OrES3Context())
+    return error::kUnknownCommand;
   const volatile gles2::cmds::CopyBufferSubData& c =
       *static_cast<const volatile gles2::cmds::CopyBufferSubData*>(cmd_data);
   GLenum readtarget = static_cast<GLenum>(c.readtarget);
@@ -513,6 +531,8 @@
 error::Error GLES2DecoderPassthroughImpl::HandleCopyTexSubImage3D(
     uint32_t immediate_data_size,
     const volatile void* cmd_data) {
+  if (!feature_info_->IsWebGL2OrES3Context())
+    return error::kUnknownCommand;
   const volatile gles2::cmds::CopyTexSubImage3D& c =
       *static_cast<const volatile gles2::cmds::CopyTexSubImage3D*>(cmd_data);
   GLenum target = static_cast<GLenum>(c.target);
@@ -632,6 +652,8 @@
 error::Error GLES2DecoderPassthroughImpl::HandleDeleteSamplersImmediate(
     uint32_t immediate_data_size,
     const volatile void* cmd_data) {
+  if (!feature_info_->IsWebGL2OrES3Context())
+    return error::kUnknownCommand;
   const volatile gles2::cmds::DeleteSamplersImmediate& c =
       *static_cast<const volatile gles2::cmds::DeleteSamplersImmediate*>(
           cmd_data);
@@ -655,6 +677,8 @@
 error::Error GLES2DecoderPassthroughImpl::HandleDeleteSync(
     uint32_t immediate_data_size,
     const volatile void* cmd_data) {
+  if (!feature_info_->IsWebGL2OrES3Context())
+    return error::kUnknownCommand;
   const volatile gles2::cmds::DeleteSync& c =
       *static_cast<const volatile gles2::cmds::DeleteSync*>(cmd_data);
   GLuint sync = c.sync;
@@ -705,6 +729,8 @@
 GLES2DecoderPassthroughImpl::HandleDeleteTransformFeedbacksImmediate(
     uint32_t immediate_data_size,
     const volatile void* cmd_data) {
+  if (!feature_info_->IsWebGL2OrES3Context())
+    return error::kUnknownCommand;
   const volatile gles2::cmds::DeleteTransformFeedbacksImmediate& c =
       *static_cast<
           const volatile gles2::cmds::DeleteTransformFeedbacksImmediate*>(
@@ -893,6 +919,8 @@
 error::Error GLES2DecoderPassthroughImpl::HandleFramebufferTextureLayer(
     uint32_t immediate_data_size,
     const volatile void* cmd_data) {
+  if (!feature_info_->IsWebGL2OrES3Context())
+    return error::kUnknownCommand;
   const volatile gles2::cmds::FramebufferTextureLayer& c =
       *static_cast<const volatile gles2::cmds::FramebufferTextureLayer*>(
           cmd_data);
@@ -1006,6 +1034,8 @@
 error::Error GLES2DecoderPassthroughImpl::HandleGenSamplersImmediate(
     uint32_t immediate_data_size,
     const volatile void* cmd_data) {
+  if (!feature_info_->IsWebGL2OrES3Context())
+    return error::kUnknownCommand;
   const volatile gles2::cmds::GenSamplersImmediate& c =
       *static_cast<const volatile gles2::cmds::GenSamplersImmediate*>(cmd_data);
   GLsizei n = static_cast<GLsizei>(c.n);
@@ -1050,6 +1080,8 @@
 error::Error GLES2DecoderPassthroughImpl::HandleGenTransformFeedbacksImmediate(
     uint32_t immediate_data_size,
     const volatile void* cmd_data) {
+  if (!feature_info_->IsWebGL2OrES3Context())
+    return error::kUnknownCommand;
   const volatile gles2::cmds::GenTransformFeedbacksImmediate& c =
       *static_cast<const volatile gles2::cmds::GenTransformFeedbacksImmediate*>(
           cmd_data);
@@ -1101,6 +1133,8 @@
 error::Error GLES2DecoderPassthroughImpl::HandleGetBufferParameteri64v(
     uint32_t immediate_data_size,
     const volatile void* cmd_data) {
+  if (!feature_info_->IsWebGL2OrES3Context())
+    return error::kUnknownCommand;
   const volatile gles2::cmds::GetBufferParameteri64v& c =
       *static_cast<const volatile gles2::cmds::GetBufferParameteri64v*>(
           cmd_data);
@@ -1242,6 +1276,8 @@
 error::Error GLES2DecoderPassthroughImpl::HandleGetInteger64v(
     uint32_t immediate_data_size,
     const volatile void* cmd_data) {
+  if (!feature_info_->IsWebGL2OrES3Context())
+    return error::kUnknownCommand;
   const volatile gles2::cmds::GetInteger64v& c =
       *static_cast<const volatile gles2::cmds::GetInteger64v*>(cmd_data);
   GLenum pname = static_cast<GLenum>(c.pname);
@@ -1270,6 +1306,8 @@
 error::Error GLES2DecoderPassthroughImpl::HandleGetIntegeri_v(
     uint32_t immediate_data_size,
     const volatile void* cmd_data) {
+  if (!feature_info_->IsWebGL2OrES3Context())
+    return error::kUnknownCommand;
   const volatile gles2::cmds::GetIntegeri_v& c =
       *static_cast<const volatile gles2::cmds::GetIntegeri_v*>(cmd_data);
   GLenum pname = static_cast<GLenum>(c.pname);
@@ -1299,6 +1337,8 @@
 error::Error GLES2DecoderPassthroughImpl::HandleGetInteger64i_v(
     uint32_t immediate_data_size,
     const volatile void* cmd_data) {
+  if (!feature_info_->IsWebGL2OrES3Context())
+    return error::kUnknownCommand;
   const volatile gles2::cmds::GetInteger64i_v& c =
       *static_cast<const volatile gles2::cmds::GetInteger64i_v*>(cmd_data);
   GLenum pname = static_cast<GLenum>(c.pname);
@@ -1416,6 +1456,8 @@
 error::Error GLES2DecoderPassthroughImpl::HandleGetSamplerParameterfv(
     uint32_t immediate_data_size,
     const volatile void* cmd_data) {
+  if (!feature_info_->IsWebGL2OrES3Context())
+    return error::kUnknownCommand;
   const volatile gles2::cmds::GetSamplerParameterfv& c =
       *static_cast<const volatile gles2::cmds::GetSamplerParameterfv*>(
           cmd_data);
@@ -1447,6 +1489,8 @@
 error::Error GLES2DecoderPassthroughImpl::HandleGetSamplerParameteriv(
     uint32_t immediate_data_size,
     const volatile void* cmd_data) {
+  if (!feature_info_->IsWebGL2OrES3Context())
+    return error::kUnknownCommand;
   const volatile gles2::cmds::GetSamplerParameteriv& c =
       *static_cast<const volatile gles2::cmds::GetSamplerParameteriv*>(
           cmd_data);
@@ -1507,6 +1551,8 @@
 error::Error GLES2DecoderPassthroughImpl::HandleGetSynciv(
     uint32_t immediate_data_size,
     const volatile void* cmd_data) {
+  if (!feature_info_->IsWebGL2OrES3Context())
+    return error::kUnknownCommand;
   const volatile gles2::cmds::GetSynciv& c =
       *static_cast<const volatile gles2::cmds::GetSynciv*>(cmd_data);
   GLuint sync = static_cast<GLuint>(c.sync);
@@ -1656,6 +1702,8 @@
 error::Error GLES2DecoderPassthroughImpl::HandleGetVertexAttribIiv(
     uint32_t immediate_data_size,
     const volatile void* cmd_data) {
+  if (!feature_info_->IsWebGL2OrES3Context())
+    return error::kUnknownCommand;
   const volatile gles2::cmds::GetVertexAttribIiv& c =
       *static_cast<const volatile gles2::cmds::GetVertexAttribIiv*>(cmd_data);
   GLuint index = static_cast<GLuint>(c.index);
@@ -1686,6 +1734,8 @@
 error::Error GLES2DecoderPassthroughImpl::HandleGetVertexAttribIuiv(
     uint32_t immediate_data_size,
     const volatile void* cmd_data) {
+  if (!feature_info_->IsWebGL2OrES3Context())
+    return error::kUnknownCommand;
   const volatile gles2::cmds::GetVertexAttribIuiv& c =
       *static_cast<const volatile gles2::cmds::GetVertexAttribIuiv*>(cmd_data);
   GLuint index = static_cast<GLuint>(c.index);
@@ -1730,6 +1780,8 @@
 error::Error GLES2DecoderPassthroughImpl::HandleInvalidateFramebufferImmediate(
     uint32_t immediate_data_size,
     const volatile void* cmd_data) {
+  if (!feature_info_->IsWebGL2OrES3Context())
+    return error::kUnknownCommand;
   const volatile gles2::cmds::InvalidateFramebufferImmediate& c =
       *static_cast<const volatile gles2::cmds::InvalidateFramebufferImmediate*>(
           cmd_data);
@@ -1759,6 +1811,8 @@
 GLES2DecoderPassthroughImpl::HandleInvalidateSubFramebufferImmediate(
     uint32_t immediate_data_size,
     const volatile void* cmd_data) {
+  if (!feature_info_->IsWebGL2OrES3Context())
+    return error::kUnknownCommand;
   const volatile gles2::cmds::InvalidateSubFramebufferImmediate& c =
       *static_cast<
           const volatile gles2::cmds::InvalidateSubFramebufferImmediate*>(
@@ -1888,6 +1942,8 @@
 error::Error GLES2DecoderPassthroughImpl::HandleIsSampler(
     uint32_t immediate_data_size,
     const volatile void* cmd_data) {
+  if (!feature_info_->IsWebGL2OrES3Context())
+    return error::kUnknownCommand;
   const volatile gles2::cmds::IsSampler& c =
       *static_cast<const volatile gles2::cmds::IsSampler*>(cmd_data);
   GLuint sampler = c.sampler;
@@ -1926,6 +1982,8 @@
 error::Error GLES2DecoderPassthroughImpl::HandleIsSync(
     uint32_t immediate_data_size,
     const volatile void* cmd_data) {
+  if (!feature_info_->IsWebGL2OrES3Context())
+    return error::kUnknownCommand;
   const volatile gles2::cmds::IsSync& c =
       *static_cast<const volatile gles2::cmds::IsSync*>(cmd_data);
   GLuint sync = c.sync;
@@ -1964,6 +2022,8 @@
 error::Error GLES2DecoderPassthroughImpl::HandleIsTransformFeedback(
     uint32_t immediate_data_size,
     const volatile void* cmd_data) {
+  if (!feature_info_->IsWebGL2OrES3Context())
+    return error::kUnknownCommand;
   const volatile gles2::cmds::IsTransformFeedback& c =
       *static_cast<const volatile gles2::cmds::IsTransformFeedback*>(cmd_data);
   GLuint transformfeedback = c.transformfeedback;
@@ -2009,6 +2069,8 @@
 error::Error GLES2DecoderPassthroughImpl::HandlePauseTransformFeedback(
     uint32_t immediate_data_size,
     const volatile void* cmd_data) {
+  if (!feature_info_->IsWebGL2OrES3Context())
+    return error::kUnknownCommand;
   error::Error error = DoPauseTransformFeedback();
   if (error != error::kNoError) {
     return error;
@@ -2033,6 +2095,8 @@
 error::Error GLES2DecoderPassthroughImpl::HandleReadBuffer(
     uint32_t immediate_data_size,
     const volatile void* cmd_data) {
+  if (!feature_info_->IsWebGL2OrES3Context())
+    return error::kUnknownCommand;
   const volatile gles2::cmds::ReadBuffer& c =
       *static_cast<const volatile gles2::cmds::ReadBuffer*>(cmd_data);
   GLenum src = static_cast<GLenum>(c.src);
@@ -2073,6 +2137,8 @@
 error::Error GLES2DecoderPassthroughImpl::HandleResumeTransformFeedback(
     uint32_t immediate_data_size,
     const volatile void* cmd_data) {
+  if (!feature_info_->IsWebGL2OrES3Context())
+    return error::kUnknownCommand;
   error::Error error = DoResumeTransformFeedback();
   if (error != error::kNoError) {
     return error;
@@ -2097,6 +2163,8 @@
 error::Error GLES2DecoderPassthroughImpl::HandleSamplerParameterf(
     uint32_t immediate_data_size,
     const volatile void* cmd_data) {
+  if (!feature_info_->IsWebGL2OrES3Context())
+    return error::kUnknownCommand;
   const volatile gles2::cmds::SamplerParameterf& c =
       *static_cast<const volatile gles2::cmds::SamplerParameterf*>(cmd_data);
   GLuint sampler = c.sampler;
@@ -2112,6 +2180,8 @@
 error::Error GLES2DecoderPassthroughImpl::HandleSamplerParameterfvImmediate(
     uint32_t immediate_data_size,
     const volatile void* cmd_data) {
+  if (!feature_info_->IsWebGL2OrES3Context())
+    return error::kUnknownCommand;
   const volatile gles2::cmds::SamplerParameterfvImmediate& c =
       *static_cast<const volatile gles2::cmds::SamplerParameterfvImmediate*>(
           cmd_data);
@@ -2139,6 +2209,8 @@
 error::Error GLES2DecoderPassthroughImpl::HandleSamplerParameteri(
     uint32_t immediate_data_size,
     const volatile void* cmd_data) {
+  if (!feature_info_->IsWebGL2OrES3Context())
+    return error::kUnknownCommand;
   const volatile gles2::cmds::SamplerParameteri& c =
       *static_cast<const volatile gles2::cmds::SamplerParameteri*>(cmd_data);
   GLuint sampler = c.sampler;
@@ -2154,6 +2226,8 @@
 error::Error GLES2DecoderPassthroughImpl::HandleSamplerParameterivImmediate(
     uint32_t immediate_data_size,
     const volatile void* cmd_data) {
+  if (!feature_info_->IsWebGL2OrES3Context())
+    return error::kUnknownCommand;
   const volatile gles2::cmds::SamplerParameterivImmediate& c =
       *static_cast<const volatile gles2::cmds::SamplerParameterivImmediate*>(
           cmd_data);
@@ -2399,6 +2473,8 @@
 error::Error GLES2DecoderPassthroughImpl::HandleTexStorage3D(
     uint32_t immediate_data_size,
     const volatile void* cmd_data) {
+  if (!feature_info_->IsWebGL2OrES3Context())
+    return error::kUnknownCommand;
   const volatile gles2::cmds::TexStorage3D& c =
       *static_cast<const volatile gles2::cmds::TexStorage3D*>(cmd_data);
   GLenum target = static_cast<GLenum>(c.target);
@@ -2418,6 +2494,8 @@
 error::Error GLES2DecoderPassthroughImpl::HandleTransformFeedbackVaryingsBucket(
     uint32_t immediate_data_size,
     const volatile void* cmd_data) {
+  if (!feature_info_->IsWebGL2OrES3Context())
+    return error::kUnknownCommand;
   const volatile gles2::cmds::TransformFeedbackVaryingsBucket& c = *static_cast<
       const volatile gles2::cmds::TransformFeedbackVaryingsBucket*>(cmd_data);
   GLuint program = static_cast<GLuint>(c.program);
@@ -2530,6 +2608,8 @@
 error::Error GLES2DecoderPassthroughImpl::HandleUniform1ui(
     uint32_t immediate_data_size,
     const volatile void* cmd_data) {
+  if (!feature_info_->IsWebGL2OrES3Context())
+    return error::kUnknownCommand;
   const volatile gles2::cmds::Uniform1ui& c =
       *static_cast<const volatile gles2::cmds::Uniform1ui*>(cmd_data);
   GLint location = static_cast<GLint>(c.location);
@@ -2544,6 +2624,8 @@
 error::Error GLES2DecoderPassthroughImpl::HandleUniform1uivImmediate(
     uint32_t immediate_data_size,
     const volatile void* cmd_data) {
+  if (!feature_info_->IsWebGL2OrES3Context())
+    return error::kUnknownCommand;
   const volatile gles2::cmds::Uniform1uivImmediate& c =
       *static_cast<const volatile gles2::cmds::Uniform1uivImmediate*>(cmd_data);
   GLint location = static_cast<GLint>(c.location);
@@ -2653,6 +2735,8 @@
 error::Error GLES2DecoderPassthroughImpl::HandleUniform2ui(
     uint32_t immediate_data_size,
     const volatile void* cmd_data) {
+  if (!feature_info_->IsWebGL2OrES3Context())
+    return error::kUnknownCommand;
   const volatile gles2::cmds::Uniform2ui& c =
       *static_cast<const volatile gles2::cmds::Uniform2ui*>(cmd_data);
   GLint location = static_cast<GLint>(c.location);
@@ -2668,6 +2752,8 @@
 error::Error GLES2DecoderPassthroughImpl::HandleUniform2uivImmediate(
     uint32_t immediate_data_size,
     const volatile void* cmd_data) {
+  if (!feature_info_->IsWebGL2OrES3Context())
+    return error::kUnknownCommand;
   const volatile gles2::cmds::Uniform2uivImmediate& c =
       *static_cast<const volatile gles2::cmds::Uniform2uivImmediate*>(cmd_data);
   GLint location = static_cast<GLint>(c.location);
@@ -2779,6 +2865,8 @@
 error::Error GLES2DecoderPassthroughImpl::HandleUniform3ui(
     uint32_t immediate_data_size,
     const volatile void* cmd_data) {
+  if (!feature_info_->IsWebGL2OrES3Context())
+    return error::kUnknownCommand;
   const volatile gles2::cmds::Uniform3ui& c =
       *static_cast<const volatile gles2::cmds::Uniform3ui*>(cmd_data);
   GLint location = static_cast<GLint>(c.location);
@@ -2795,6 +2883,8 @@
 error::Error GLES2DecoderPassthroughImpl::HandleUniform3uivImmediate(
     uint32_t immediate_data_size,
     const volatile void* cmd_data) {
+  if (!feature_info_->IsWebGL2OrES3Context())
+    return error::kUnknownCommand;
   const volatile gles2::cmds::Uniform3uivImmediate& c =
       *static_cast<const volatile gles2::cmds::Uniform3uivImmediate*>(cmd_data);
   GLint location = static_cast<GLint>(c.location);
@@ -2908,6 +2998,8 @@
 error::Error GLES2DecoderPassthroughImpl::HandleUniform4ui(
     uint32_t immediate_data_size,
     const volatile void* cmd_data) {
+  if (!feature_info_->IsWebGL2OrES3Context())
+    return error::kUnknownCommand;
   const volatile gles2::cmds::Uniform4ui& c =
       *static_cast<const volatile gles2::cmds::Uniform4ui*>(cmd_data);
   GLint location = static_cast<GLint>(c.location);
@@ -2925,6 +3017,8 @@
 error::Error GLES2DecoderPassthroughImpl::HandleUniform4uivImmediate(
     uint32_t immediate_data_size,
     const volatile void* cmd_data) {
+  if (!feature_info_->IsWebGL2OrES3Context())
+    return error::kUnknownCommand;
   const volatile gles2::cmds::Uniform4uivImmediate& c =
       *static_cast<const volatile gles2::cmds::Uniform4uivImmediate*>(cmd_data);
   GLint location = static_cast<GLint>(c.location);
@@ -2980,6 +3074,8 @@
 error::Error GLES2DecoderPassthroughImpl::HandleUniformMatrix2x3fvImmediate(
     uint32_t immediate_data_size,
     const volatile void* cmd_data) {
+  if (!feature_info_->IsWebGL2OrES3Context())
+    return error::kUnknownCommand;
   const volatile gles2::cmds::UniformMatrix2x3fvImmediate& c =
       *static_cast<const volatile gles2::cmds::UniformMatrix2x3fvImmediate*>(
           cmd_data);
@@ -3009,6 +3105,8 @@
 error::Error GLES2DecoderPassthroughImpl::HandleUniformMatrix2x4fvImmediate(
     uint32_t immediate_data_size,
     const volatile void* cmd_data) {
+  if (!feature_info_->IsWebGL2OrES3Context())
+    return error::kUnknownCommand;
   const volatile gles2::cmds::UniformMatrix2x4fvImmediate& c =
       *static_cast<const volatile gles2::cmds::UniformMatrix2x4fvImmediate*>(
           cmd_data);
@@ -3067,6 +3165,8 @@
 error::Error GLES2DecoderPassthroughImpl::HandleUniformMatrix3x2fvImmediate(
     uint32_t immediate_data_size,
     const volatile void* cmd_data) {
+  if (!feature_info_->IsWebGL2OrES3Context())
+    return error::kUnknownCommand;
   const volatile gles2::cmds::UniformMatrix3x2fvImmediate& c =
       *static_cast<const volatile gles2::cmds::UniformMatrix3x2fvImmediate*>(
           cmd_data);
@@ -3096,6 +3196,8 @@
 error::Error GLES2DecoderPassthroughImpl::HandleUniformMatrix3x4fvImmediate(
     uint32_t immediate_data_size,
     const volatile void* cmd_data) {
+  if (!feature_info_->IsWebGL2OrES3Context())
+    return error::kUnknownCommand;
   const volatile gles2::cmds::UniformMatrix3x4fvImmediate& c =
       *static_cast<const volatile gles2::cmds::UniformMatrix3x4fvImmediate*>(
           cmd_data);
@@ -3154,6 +3256,8 @@
 error::Error GLES2DecoderPassthroughImpl::HandleUniformMatrix4x2fvImmediate(
     uint32_t immediate_data_size,
     const volatile void* cmd_data) {
+  if (!feature_info_->IsWebGL2OrES3Context())
+    return error::kUnknownCommand;
   const volatile gles2::cmds::UniformMatrix4x2fvImmediate& c =
       *static_cast<const volatile gles2::cmds::UniformMatrix4x2fvImmediate*>(
           cmd_data);
@@ -3183,6 +3287,8 @@
 error::Error GLES2DecoderPassthroughImpl::HandleUniformMatrix4x3fvImmediate(
     uint32_t immediate_data_size,
     const volatile void* cmd_data) {
+  if (!feature_info_->IsWebGL2OrES3Context())
+    return error::kUnknownCommand;
   const volatile gles2::cmds::UniformMatrix4x3fvImmediate& c =
       *static_cast<const volatile gles2::cmds::UniformMatrix4x3fvImmediate*>(
           cmd_data);
@@ -3404,6 +3510,8 @@
 error::Error GLES2DecoderPassthroughImpl::HandleVertexAttribI4i(
     uint32_t immediate_data_size,
     const volatile void* cmd_data) {
+  if (!feature_info_->IsWebGL2OrES3Context())
+    return error::kUnknownCommand;
   const volatile gles2::cmds::VertexAttribI4i& c =
       *static_cast<const volatile gles2::cmds::VertexAttribI4i*>(cmd_data);
   GLuint indx = static_cast<GLuint>(c.indx);
@@ -3421,6 +3529,8 @@
 error::Error GLES2DecoderPassthroughImpl::HandleVertexAttribI4ivImmediate(
     uint32_t immediate_data_size,
     const volatile void* cmd_data) {
+  if (!feature_info_->IsWebGL2OrES3Context())
+    return error::kUnknownCommand;
   const volatile gles2::cmds::VertexAttribI4ivImmediate& c =
       *static_cast<const volatile gles2::cmds::VertexAttribI4ivImmediate*>(
           cmd_data);
@@ -3447,6 +3557,8 @@
 error::Error GLES2DecoderPassthroughImpl::HandleVertexAttribI4ui(
     uint32_t immediate_data_size,
     const volatile void* cmd_data) {
+  if (!feature_info_->IsWebGL2OrES3Context())
+    return error::kUnknownCommand;
   const volatile gles2::cmds::VertexAttribI4ui& c =
       *static_cast<const volatile gles2::cmds::VertexAttribI4ui*>(cmd_data);
   GLuint indx = static_cast<GLuint>(c.indx);
@@ -3464,6 +3576,8 @@
 error::Error GLES2DecoderPassthroughImpl::HandleVertexAttribI4uivImmediate(
     uint32_t immediate_data_size,
     const volatile void* cmd_data) {
+  if (!feature_info_->IsWebGL2OrES3Context())
+    return error::kUnknownCommand;
   const volatile gles2::cmds::VertexAttribI4uivImmediate& c =
       *static_cast<const volatile gles2::cmds::VertexAttribI4uivImmediate*>(
           cmd_data);
@@ -3509,6 +3623,10 @@
   const volatile gles2::cmds::BlitFramebufferCHROMIUM& c =
       *static_cast<const volatile gles2::cmds::BlitFramebufferCHROMIUM*>(
           cmd_data);
+  if (!features().chromium_framebuffer_multisample) {
+    return error::kUnknownCommand;
+  }
+
   GLint srcX0 = static_cast<GLint>(c.srcX0);
   GLint srcY0 = static_cast<GLint>(c.srcY0);
   GLint srcX1 = static_cast<GLint>(c.srcX1);
@@ -3535,6 +3653,10 @@
       *static_cast<
           const volatile gles2::cmds::RenderbufferStorageMultisampleCHROMIUM*>(
           cmd_data);
+  if (!features().chromium_framebuffer_multisample) {
+    return error::kUnknownCommand;
+  }
+
   GLenum target = static_cast<GLenum>(c.target);
   GLsizei samples = static_cast<GLsizei>(c.samples);
   GLenum internalformat = static_cast<GLenum>(c.internalformat);
@@ -3556,6 +3678,10 @@
       *static_cast<
           const volatile gles2::cmds::RenderbufferStorageMultisampleEXT*>(
           cmd_data);
+  if (!features().multisampled_render_to_texture) {
+    return error::kUnknownCommand;
+  }
+
   GLenum target = static_cast<GLenum>(c.target);
   GLsizei samples = static_cast<GLsizei>(c.samples);
   GLenum internalformat = static_cast<GLenum>(c.internalformat);
@@ -3577,6 +3703,10 @@
       *static_cast<
           const volatile gles2::cmds::FramebufferTexture2DMultisampleEXT*>(
           cmd_data);
+  if (!features().multisampled_render_to_texture) {
+    return error::kUnknownCommand;
+  }
+
   GLenum target = static_cast<GLenum>(c.target);
   GLenum attachment = static_cast<GLenum>(c.attachment);
   GLenum textarget = static_cast<GLenum>(c.textarget);
@@ -3596,6 +3726,10 @@
     const volatile void* cmd_data) {
   const volatile gles2::cmds::TexStorage2DEXT& c =
       *static_cast<const volatile gles2::cmds::TexStorage2DEXT*>(cmd_data);
+  if (!features().ext_texture_storage) {
+    return error::kUnknownCommand;
+  }
+
   GLenum target = static_cast<GLenum>(c.target);
   GLsizei levels = static_cast<GLsizei>(c.levels);
   GLenum internalFormat = static_cast<GLenum>(c.internalFormat);
@@ -3658,6 +3792,8 @@
 error::Error GLES2DecoderPassthroughImpl::HandleBeginTransformFeedback(
     uint32_t immediate_data_size,
     const volatile void* cmd_data) {
+  if (!feature_info_->IsWebGL2OrES3Context())
+    return error::kUnknownCommand;
   const volatile gles2::cmds::BeginTransformFeedback& c =
       *static_cast<const volatile gles2::cmds::BeginTransformFeedback*>(
           cmd_data);
@@ -3672,6 +3808,8 @@
 error::Error GLES2DecoderPassthroughImpl::HandleEndTransformFeedback(
     uint32_t immediate_data_size,
     const volatile void* cmd_data) {
+  if (!feature_info_->IsWebGL2OrES3Context())
+    return error::kUnknownCommand;
   error::Error error = DoEndTransformFeedback();
   if (error != error::kNoError) {
     return error;
@@ -3804,6 +3942,8 @@
 error::Error GLES2DecoderPassthroughImpl::HandleFlushMappedBufferRange(
     uint32_t immediate_data_size,
     const volatile void* cmd_data) {
+  if (!feature_info_->IsWebGL2OrES3Context())
+    return error::kUnknownCommand;
   const volatile gles2::cmds::FlushMappedBufferRange& c =
       *static_cast<const volatile gles2::cmds::FlushMappedBufferRange*>(
           cmd_data);
@@ -4038,6 +4178,10 @@
   const volatile gles2::cmds::DiscardFramebufferEXTImmediate& c =
       *static_cast<const volatile gles2::cmds::DiscardFramebufferEXTImmediate*>(
           cmd_data);
+  if (!features().ext_discard_framebuffer) {
+    return error::kUnknownCommand;
+  }
+
   GLenum target = static_cast<GLenum>(c.target);
   GLsizei count = static_cast<GLsizei>(c.count);
   uint32_t data_size = 0;
@@ -4166,6 +4310,10 @@
   const volatile gles2::cmds::MatrixLoadfCHROMIUMImmediate& c =
       *static_cast<const volatile gles2::cmds::MatrixLoadfCHROMIUMImmediate*>(
           cmd_data);
+  if (!features().chromium_path_rendering) {
+    return error::kUnknownCommand;
+  }
+
   GLenum matrixMode = static_cast<GLenum>(c.matrixMode);
   uint32_t data_size;
   if (!GLES2Util::ComputeDataSize<GLfloat, 16>(1, &data_size)) {
@@ -4192,6 +4340,10 @@
   const volatile gles2::cmds::MatrixLoadIdentityCHROMIUM& c =
       *static_cast<const volatile gles2::cmds::MatrixLoadIdentityCHROMIUM*>(
           cmd_data);
+  if (!features().chromium_path_rendering) {
+    return error::kUnknownCommand;
+  }
+
   GLenum matrixMode = static_cast<GLenum>(c.matrixMode);
   error::Error error = DoMatrixLoadIdentityCHROMIUM(matrixMode);
   if (error != error::kNoError) {
@@ -4205,6 +4357,10 @@
     const volatile void* cmd_data) {
   const volatile gles2::cmds::IsPathCHROMIUM& c =
       *static_cast<const volatile gles2::cmds::IsPathCHROMIUM*>(cmd_data);
+  if (!features().chromium_path_rendering) {
+    return error::kUnknownCommand;
+  }
+
   GLuint path = c.path;
   typedef cmds::IsPathCHROMIUM::Result Result;
   Result* result = GetSharedMemoryAs<Result*>(
@@ -4225,6 +4381,10 @@
   const volatile gles2::cmds::PathStencilFuncCHROMIUM& c =
       *static_cast<const volatile gles2::cmds::PathStencilFuncCHROMIUM*>(
           cmd_data);
+  if (!features().chromium_path_rendering) {
+    return error::kUnknownCommand;
+  }
+
   GLenum func = static_cast<GLenum>(c.func);
   GLint ref = static_cast<GLint>(c.ref);
   GLuint mask = static_cast<GLuint>(c.mask);
@@ -4241,6 +4401,10 @@
   const volatile gles2::cmds::CoverageModulationCHROMIUM& c =
       *static_cast<const volatile gles2::cmds::CoverageModulationCHROMIUM*>(
           cmd_data);
+  if (!features().chromium_framebuffer_mixed_samples) {
+    return error::kUnknownCommand;
+  }
+
   GLenum components = static_cast<GLenum>(c.components);
   error::Error error = DoCoverageModulationCHROMIUM(components);
   if (error != error::kNoError) {
@@ -4252,6 +4416,10 @@
 error::Error GLES2DecoderPassthroughImpl::HandleBlendBarrierKHR(
     uint32_t immediate_data_size,
     const volatile void* cmd_data) {
+  if (!features().blend_equation_advanced) {
+    return error::kUnknownCommand;
+  }
+
   error::Error error = DoBlendBarrierKHR();
   if (error != error::kNoError) {
     return error;
@@ -4263,6 +4431,10 @@
 GLES2DecoderPassthroughImpl::HandleApplyScreenSpaceAntialiasingCHROMIUM(
     uint32_t immediate_data_size,
     const volatile void* cmd_data) {
+  if (!features().chromium_screen_space_antialiasing) {
+    return error::kUnknownCommand;
+  }
+
   error::Error error = DoApplyScreenSpaceAntialiasingCHROMIUM();
   if (error != error::kNoError) {
     return error;
@@ -4386,6 +4558,10 @@
     const volatile void* cmd_data) {
   const volatile gles2::cmds::BeginRasterCHROMIUM& c =
       *static_cast<const volatile gles2::cmds::BeginRasterCHROMIUM*>(cmd_data);
+  if (!features().chromium_raster_transport) {
+    return error::kUnknownCommand;
+  }
+
   GLuint texture_id = static_cast<GLuint>(c.texture_id);
   GLuint sk_color = static_cast<GLuint>(c.sk_color);
   GLuint msaa_sample_count = static_cast<GLuint>(c.msaa_sample_count);
@@ -4405,6 +4581,10 @@
 error::Error GLES2DecoderPassthroughImpl::HandleEndRasterCHROMIUM(
     uint32_t immediate_data_size,
     const volatile void* cmd_data) {
+  if (!features().chromium_raster_transport) {
+    return error::kUnknownCommand;
+  }
+
   error::Error error = DoEndRasterCHROMIUM();
   if (error != error::kNoError) {
     return error;
@@ -4418,6 +4598,10 @@
   const volatile gles2::cmds::TexStorage2DImageCHROMIUM& c =
       *static_cast<const volatile gles2::cmds::TexStorage2DImageCHROMIUM*>(
           cmd_data);
+  if (!features().chromium_texture_storage_image) {
+    return error::kUnknownCommand;
+  }
+
   GLenum target = static_cast<GLenum>(c.target);
   GLenum internalFormat = static_cast<GLenum>(c.internalFormat);
   GLenum bufferUsage = static_cast<GLenum>(c.bufferUsage);
diff --git a/gpu/command_buffer/service/gles2_cmd_decoder_passthrough_unittest_commands.cc b/gpu/command_buffer/service/gles2_cmd_decoder_passthrough_unittest_commands.cc
new file mode 100644
index 0000000..8cc4498
--- /dev/null
+++ b/gpu/command_buffer/service/gles2_cmd_decoder_passthrough_unittest_commands.cc
@@ -0,0 +1,162 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.

+// Use of this source code is governed by a BSD-style license that can be

+// found in the LICENSE file.

+

+#include <stdint.h>

+

+#include "gpu/command_buffer/service/gles2_cmd_decoder.h"

+#include "gpu/command_buffer/service/gles2_cmd_decoder_unittest.h"

+

+namespace gpu {

+namespace gles2 {

+

+using namespace cmds;

+

+template <typename T>

+class GLES2DecoderPassthroughFixedCommandTest

+    : public GLES2DecoderPassthroughTest {};

+TYPED_TEST_CASE_P(GLES2DecoderPassthroughFixedCommandTest);

+

+TYPED_TEST_P(GLES2DecoderPassthroughFixedCommandTest, InvalidCommand) {

+  TypeParam cmd;

+  cmd.SetHeader();

+  EXPECT_EQ(error::kUnknownCommand, this->ExecuteCmd(cmd));

+}

+REGISTER_TYPED_TEST_CASE_P(GLES2DecoderPassthroughFixedCommandTest,

+                           InvalidCommand);

+

+template <typename T>

+class GLES2DecoderPassthroughImmediateNoArgCommandTest

+    : public GLES2DecoderPassthroughTest {};

+TYPED_TEST_CASE_P(GLES2DecoderPassthroughImmediateNoArgCommandTest);

+

+TYPED_TEST_P(GLES2DecoderPassthroughImmediateNoArgCommandTest, InvalidCommand) {

+  TypeParam& cmd = *(this->template GetImmediateAs<TypeParam>());

+  cmd.SetHeader();

+  EXPECT_EQ(error::kUnknownCommand, this->ExecuteImmediateCmd(cmd, 64));

+}

+REGISTER_TYPED_TEST_CASE_P(GLES2DecoderPassthroughImmediateNoArgCommandTest,

+                           InvalidCommand);

+

+template <typename T>

+class GLES2DecoderPassthroughImmediateSizeArgCommandTest

+    : public GLES2DecoderPassthroughTest {};

+TYPED_TEST_CASE_P(GLES2DecoderPassthroughImmediateSizeArgCommandTest);

+

+TYPED_TEST_P(GLES2DecoderPassthroughImmediateSizeArgCommandTest,

+             InvalidCommand) {

+  TypeParam& cmd = *(this->template GetImmediateAs<TypeParam>());

+  cmd.SetHeader(0);

+  EXPECT_EQ(error::kUnknownCommand, this->ExecuteImmediateCmd(cmd, 0));

+}

+REGISTER_TYPED_TEST_CASE_P(GLES2DecoderPassthroughImmediateSizeArgCommandTest,

+                           InvalidCommand);

+

+using ES3FixedCommandTypes0 =

+    ::testing::Types<BindBufferBase,

+                     BindBufferRange,

+                     BindSampler,

+                     BindTransformFeedback,

+                     ClearBufferfi,

+                     ClientWaitSync,

+                     CopyBufferSubData,

+                     CompressedTexImage3D,

+                     CompressedTexImage3DBucket,

+                     CompressedTexSubImage3D,

+                     CompressedTexSubImage3DBucket,

+                     CopyTexSubImage3D,

+                     DeleteSync,

+                     FenceSync,

+                     FlushMappedBufferRange,

+                     FramebufferTextureLayer,

+                     GetActiveUniformBlockiv,

+                     GetActiveUniformBlockName,

+                     GetActiveUniformsiv,

+                     GetBufferSubDataAsyncCHROMIUM,

+                     GetFragDataLocation,

+                     GetBufferParameteri64v,

+                     GetInteger64v,

+                     GetInteger64i_v,

+                     GetIntegeri_v,

+                     GetInternalformativ,

+                     GetSamplerParameterfv,

+                     GetSamplerParameteriv,

+                     GetSynciv,

+                     GetUniformBlockIndex,

+                     GetUniformBlocksCHROMIUM,

+                     GetUniformsES3CHROMIUM,

+                     GetTransformFeedbackVarying,

+                     GetTransformFeedbackVaryingsCHROMIUM,

+                     GetUniformuiv,

+                     GetUniformIndices,

+                     GetVertexAttribIiv,

+                     GetVertexAttribIuiv,

+                     IsSampler,

+                     IsSync,

+                     IsTransformFeedback,

+                     MapBufferRange,

+                     PauseTransformFeedback,

+                     ReadBuffer,

+                     ResumeTransformFeedback,

+                     SamplerParameterf,

+                     SamplerParameteri,

+                     TexImage3D,

+                     TexStorage3D,

+                     TexSubImage3D>;

+

+using ES3FixedCommandTypes1 = ::testing::Types<TransformFeedbackVaryingsBucket,

+                                               Uniform1ui,

+                                               Uniform2ui,

+                                               Uniform3ui,

+                                               Uniform4ui,

+                                               UniformBlockBinding,

+                                               UnmapBuffer,

+                                               VertexAttribI4i,

+                                               VertexAttribI4ui,

+                                               VertexAttribIPointer,

+                                               WaitSync,

+                                               BeginTransformFeedback,

+                                               EndTransformFeedback>;

+

+using ES3ImmediateNoArgCommandTypes0 =

+    ::testing::Types<ClearBufferivImmediate,

+                     ClearBufferuivImmediate,

+                     ClearBufferfvImmediate,

+                     SamplerParameterfvImmediate,

+                     SamplerParameterfvImmediate,

+                     VertexAttribI4ivImmediate,

+                     VertexAttribI4uivImmediate>;

+

+using ES3ImmediateSizeArgCommandTypes0 =

+    ::testing::Types<DeleteSamplersImmediate,

+                     DeleteTransformFeedbacksImmediate,

+                     GenTransformFeedbacksImmediate,

+                     InvalidateFramebufferImmediate,

+                     InvalidateSubFramebufferImmediate,

+                     Uniform1uivImmediate,

+                     Uniform2uivImmediate,

+                     Uniform3uivImmediate,

+                     Uniform4uivImmediate,

+                     UniformMatrix2x3fvImmediate,

+                     UniformMatrix2x4fvImmediate,

+                     UniformMatrix3x2fvImmediate,

+                     UniformMatrix3x4fvImmediate,

+                     UniformMatrix4x2fvImmediate,

+                     UniformMatrix4x3fvImmediate>;

+

+INSTANTIATE_TYPED_TEST_CASE_P(0,

+                              GLES2DecoderPassthroughFixedCommandTest,

+                              ES3FixedCommandTypes0);

+INSTANTIATE_TYPED_TEST_CASE_P(1,

+                              GLES2DecoderPassthroughFixedCommandTest,

+                              ES3FixedCommandTypes1);

+INSTANTIATE_TYPED_TEST_CASE_P(0,

+                              GLES2DecoderPassthroughImmediateNoArgCommandTest,

+                              ES3ImmediateNoArgCommandTypes0);

+INSTANTIATE_TYPED_TEST_CASE_P(

+    0,

+    GLES2DecoderPassthroughImmediateSizeArgCommandTest,

+    ES3ImmediateSizeArgCommandTypes0);

+

+}  // namespace gles2

+}  // namespace gpu

diff --git a/gpu/command_buffer/service/gles2_cmd_decoder_unittest.cc b/gpu/command_buffer/service/gles2_cmd_decoder_unittest.cc
index d48fa540..a8292947 100644
--- a/gpu/command_buffer/service/gles2_cmd_decoder_unittest.cc
+++ b/gpu/command_buffer/service/gles2_cmd_decoder_unittest.cc
@@ -533,6 +533,31 @@
   EXPECT_EQ(GL_NO_ERROR, GetGLError());
   EXPECT_TRUE(query->IsPending());
 
+  // Begin should fail if using a different target
+  begin_cmd.Init(GL_ANY_SAMPLES_PASSED_CONSERVATIVE_EXT, kNewClientId,
+                 shared_memory_id_, kSharedMemoryOffset);
+  EXPECT_EQ(error::kNoError, ExecuteCmd(begin_cmd));
+  EXPECT_EQ(GL_INVALID_OPERATION, GetGLError());
+
+  // Begin should fail if using a different sync
+  begin_cmd.Init(GL_ANY_SAMPLES_PASSED_CONSERVATIVE_EXT, kNewClientId,
+                 shared_memory_id_, kSharedMemoryOffset + sizeof(QuerySync));
+  EXPECT_EQ(error::kNoError, ExecuteCmd(begin_cmd));
+  EXPECT_EQ(GL_INVALID_OPERATION, GetGLError());
+
+  // QueryCounter should fail if using a different target
+  QueryCounterEXT query_counter_cmd;
+  query_counter_cmd.Init(kNewClientId, GL_TIMESTAMP, shared_memory_id_,
+                         kSharedMemoryOffset, 1);
+  EXPECT_EQ(error::kNoError, ExecuteCmd(query_counter_cmd));
+  EXPECT_EQ(GL_INVALID_OPERATION, GetGLError());
+
+  // QueryCounter should fail if using a different sync
+  query_counter_cmd.Init(kNewClientId, GL_TIMESTAMP, shared_memory_id_,
+                         kSharedMemoryOffset + sizeof(QuerySync), 1);
+  EXPECT_EQ(error::kNoError, ExecuteCmd(query_counter_cmd));
+  EXPECT_EQ(GL_INVALID_OPERATION, GetGLError());
+
   EXPECT_CALL(*gl_, DeleteQueries(1, _)).Times(1).RetiresOnSaturation();
 }
 
diff --git a/gpu/command_buffer/service/gles2_cmd_decoder_unittest_context_lost.cc b/gpu/command_buffer/service/gles2_cmd_decoder_unittest_context_lost.cc
index 2b882079..de10d51c 100644
--- a/gpu/command_buffer/service/gles2_cmd_decoder_unittest_context_lost.cc
+++ b/gpu/command_buffer/service/gles2_cmd_decoder_unittest_context_lost.cc
@@ -190,6 +190,44 @@
   ClearCurrentDecoderError();
 }
 
+TEST_P(GLES2DecoderLostContextTest, TextureDestroyAfterLostFromMakeCurrent) {
+  Init(true);
+  // Create a texture and framebuffer, and attach the texture to the
+  // framebuffer.
+  const GLuint kClientTextureId = 4100;
+  const GLuint kServiceTextureId = 4101;
+  EXPECT_CALL(*gl_, GenTextures(_, _))
+      .WillOnce(SetArgPointee<1>(kServiceTextureId))
+      .RetiresOnSaturation();
+  GenHelper<GenTexturesImmediate>(kClientTextureId);
+  DoBindTexture(GL_TEXTURE_2D, kClientTextureId, kServiceTextureId);
+  DoTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 5, 6, 0, GL_RGBA, GL_UNSIGNED_BYTE,
+               shared_memory_id_, kSharedMemoryOffset);
+  DoBindFramebuffer(GL_FRAMEBUFFER, client_framebuffer_id_,
+                    kServiceFramebufferId);
+  DoFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D,
+                         kClientTextureId, kServiceTextureId, 0, GL_NO_ERROR);
+
+  // The texture should never be deleted at the GL level.
+  EXPECT_CALL(*gl_, DeleteTextures(1, Pointee(kServiceTextureId)))
+      .Times(0)
+      .RetiresOnSaturation();
+
+  DoBindFramebuffer(GL_FRAMEBUFFER, 0, 0);
+  EXPECT_CALL(*gl_, BindTexture(_, 0)).Times(testing::AnyNumber());
+  GenHelper<cmds::DeleteTexturesImmediate>(kClientTextureId);
+
+  // Force context lost for MakeCurrent().
+  EXPECT_CALL(*context_, MakeCurrent(surface_.get())).WillOnce(Return(false));
+  // Expect the group to be lost.
+  EXPECT_CALL(*mock_decoder_, MarkContextLost(error::kUnknown)).Times(1);
+
+  decoder_->MakeCurrent();
+  EXPECT_TRUE(decoder_->WasContextLost());
+  EXPECT_EQ(error::kMakeCurrentFailed, GetContextLostReason());
+  ClearCurrentDecoderError();
+}
+
 TEST_P(GLES2DecoderLostContextTest, LostFromResetAfterMakeCurrent) {
   Init(true); // with robustness
   InSequence seq;
diff --git a/gpu/command_buffer/service/texture_manager.cc b/gpu/command_buffer/service/texture_manager.cc
index c1b4475..b5f8ae4 100644
--- a/gpu/command_buffer/service/texture_manager.cc
+++ b/gpu/command_buffer/service/texture_manager.cc
@@ -443,9 +443,11 @@
       this);
 }
 
-void TextureManager::Destroy(bool have_context) {
-  have_context_ = have_context;
+void TextureManager::MarkContextLost() {
+  have_context_ = false;
+}
 
+void TextureManager::Destroy() {
   // Retreive any outstanding unlocked textures from the discardable manager so
   // we can clean them up here.
   discardable_manager_->OnTextureManagerDestruction(this);
@@ -461,7 +463,7 @@
       progress_reporter_->ReportProgress();
   }
 
-  if (have_context) {
+  if (have_context_) {
     glDeleteTextures(arraysize(black_texture_ids_), black_texture_ids_);
   }
 
diff --git a/gpu/command_buffer/service/texture_manager.h b/gpu/command_buffer/service/texture_manager.h
index 776d528..574b32e 100644
--- a/gpu/command_buffer/service/texture_manager.h
+++ b/gpu/command_buffer/service/texture_manager.h
@@ -773,8 +773,10 @@
   // Init the texture manager.
   void Initialize();
 
+  void MarkContextLost();
+
   // Must call before destruction.
-  void Destroy(bool have_context);
+  void Destroy();
 
   // Returns the maximum number of levels.
   GLint MaxLevelsForTarget(GLenum target) const {
diff --git a/gpu/command_buffer/service/texture_manager_unittest.cc b/gpu/command_buffer/service/texture_manager_unittest.cc
index 90fc64e..6e4157c 100644
--- a/gpu/command_buffer/service/texture_manager_unittest.cc
+++ b/gpu/command_buffer/service/texture_manager_unittest.cc
@@ -92,7 +92,8 @@
   }
 
   void TearDown() override {
-    manager_->Destroy(false);
+    manager_->MarkContextLost();
+    manager_->Destroy();
     manager_.reset();
     GpuServiceTest::TearDown();
   }
@@ -263,7 +264,8 @@
 
   // TODO(vmiura): Test GL_TEXTURE_EXTERNAL_OES & GL_TEXTURE_RECTANGLE_ARB.
 
-  manager.Destroy(false);
+  manager.MarkContextLost();
+  manager.Destroy();
 }
 
 TEST_F(TextureManagerTest, UseDefaultTexturesFalse) {
@@ -282,7 +284,8 @@
 
   // TODO(vmiura): Test GL_TEXTURE_EXTERNAL_OES & GL_TEXTURE_RECTANGLE_ARB.
 
-  manager.Destroy(false);
+  manager.MarkContextLost();
+  manager.Destroy();
 }
 
 TEST_F(TextureManagerTest, UseDefaultTexturesTrueES3) {
@@ -299,7 +302,8 @@
   EXPECT_TRUE(manager.GetDefaultTextureInfo(GL_TEXTURE_3D) != NULL);
   EXPECT_TRUE(manager.GetDefaultTextureInfo(GL_TEXTURE_2D_ARRAY) != NULL);
 
-  manager.Destroy(false);
+  manager.MarkContextLost();
+  manager.Destroy();
 }
 
 TEST_F(TextureManagerTest, UseDefaultTexturesFalseES3) {
@@ -316,7 +320,8 @@
   EXPECT_TRUE(manager.GetDefaultTextureInfo(GL_TEXTURE_3D) == NULL);
   EXPECT_TRUE(manager.GetDefaultTextureInfo(GL_TEXTURE_2D_ARRAY) == NULL);
 
-  manager.Destroy(false);
+  manager.MarkContextLost();
+  manager.Destroy();
 }
 
 TEST_F(TextureManagerTest, TextureUsageExt) {
@@ -340,7 +345,8 @@
       GL_TEXTURE_USAGE_ANGLE, GL_FRAMEBUFFER_ATTACHMENT_ANGLE, GL_NO_ERROR);
   EXPECT_EQ(static_cast<GLenum>(GL_FRAMEBUFFER_ATTACHMENT_ANGLE),
             texture_ref->texture()->usage());
-  manager.Destroy(false);
+  manager.MarkContextLost();
+  manager.Destroy();
 }
 
 TEST_F(TextureManagerTest, Destroy) {
@@ -363,7 +369,7 @@
       .RetiresOnSaturation();
   TestHelper::SetupTextureManagerDestructionExpectations(
       gl_.get(), false, false, {}, kUseDefaultTextures);
-  manager.Destroy(true);
+  manager.Destroy();
   // Check that resources got freed.
   texture = manager.GetTexture(kClient1Id);
   ASSERT_TRUE(texture == NULL);
@@ -515,7 +521,8 @@
   EXPECT_TRUE(manager.ValidForTarget(GL_TEXTURE_2D, 1, 5, 2, 1));
   // Check NPOT height on level 1
   EXPECT_TRUE(manager.ValidForTarget(GL_TEXTURE_2D, 1, 2, 5, 1));
-  manager.Destroy(false);
+  manager.MarkContextLost();
+  manager.Destroy();
 }
 
 TEST_F(TextureManagerTest, AlphaLuminanceCompatibilityProfile) {
@@ -707,7 +714,8 @@
       }
       texture_ref_ = NULL;
     }
-    manager_->Destroy(false);
+    manager_->MarkContextLost();
+    manager_->Destroy();
     manager_.reset();
     GpuServiceTest::TearDown();
   }
@@ -1037,7 +1045,8 @@
   manager.MarkMipmapsGenerated(texture_ref);
   EXPECT_TRUE(TextureTestHelper::IsTextureComplete(texture));
   EXPECT_TRUE(manager.CanRender(texture_ref));
-  manager.Destroy(false);
+  manager.MarkContextLost();
+  manager.Destroy();
 }
 
 TEST_F(TextureTest, POTCubeMap) {
@@ -1335,7 +1344,8 @@
       gl_.get(), error_state_.get(), &manager, texture_ref,
       GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_NEAREST, GL_NO_ERROR);
   EXPECT_TRUE(manager.CanRender(texture_ref));
-  manager.Destroy(false);
+  manager.MarkContextLost();
+  manager.Destroy();
 }
 
 TEST_F(TextureTest, FloatLinear) {
@@ -1356,7 +1366,8 @@
   manager.SetLevelInfo(texture_ref, GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 1, 0,
                        GL_RGBA, GL_FLOAT, gfx::Rect(1, 1));
   EXPECT_TRUE(manager.CanRender(texture_ref));
-  manager.Destroy(false);
+  manager.MarkContextLost();
+  manager.Destroy();
 }
 
 TEST_F(TextureTest, HalfFloatNotLinear) {
@@ -1385,7 +1396,8 @@
       gl_.get(), error_state_.get(), &manager, texture_ref,
       GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_NEAREST, GL_NO_ERROR);
   EXPECT_TRUE(manager.CanRender(texture_ref));
-  manager.Destroy(false);
+  manager.MarkContextLost();
+  manager.Destroy();
 }
 
 TEST_F(TextureTest, HalfFloatLinear) {
@@ -1406,7 +1418,8 @@
   manager.SetLevelInfo(texture_ref, GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 1, 0,
                        GL_RGBA, GL_HALF_FLOAT_OES, gfx::Rect(1, 1));
   EXPECT_TRUE(manager.CanRender(texture_ref));
-  manager.Destroy(false);
+  manager.MarkContextLost();
+  manager.Destroy();
 }
 
 TEST_F(TextureTest, EGLImageExternal) {
@@ -1425,7 +1438,8 @@
   Texture* texture = texture_ref->texture();
   EXPECT_EQ(static_cast<GLenum>(GL_TEXTURE_EXTERNAL_OES), texture->target());
   EXPECT_FALSE(manager.CanGenerateMipmaps(texture_ref));
-  manager.Destroy(false);
+  manager.MarkContextLost();
+  manager.Destroy();
 }
 
 TEST_F(TextureTest, DepthTexture) {
@@ -1444,7 +1458,8 @@
   manager.SetLevelInfo(texture_ref, GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT, 4, 4,
                        1, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, gfx::Rect());
   EXPECT_FALSE(manager.CanGenerateMipmaps(texture_ref));
-  manager.Destroy(false);
+  manager.MarkContextLost();
+  manager.Destroy();
 }
 
 TEST_F(TextureTest, SafeUnsafe) {
@@ -2232,9 +2247,11 @@
   }
 
   void TearDown() override {
-    texture_manager2_->Destroy(false);
+    texture_manager2_->MarkContextLost();
+    texture_manager2_->Destroy();
     texture_manager2_.reset();
-    texture_manager1_->Destroy(false);
+    texture_manager1_->MarkContextLost();
+    texture_manager1_->Destroy();
     texture_manager1_.reset();
     GpuServiceTest::TearDown();
   }
diff --git a/gpu/command_buffer/tests/fuzzer_main.cc b/gpu/command_buffer/tests/fuzzer_main.cc
index db663f5..7084c62 100644
--- a/gpu/command_buffer/tests/fuzzer_main.cc
+++ b/gpu/command_buffer/tests/fuzzer_main.cc
@@ -13,6 +13,8 @@
 #include "base/logging.h"
 #include "base/memory/ptr_util.h"
 #include "base/memory/ref_counted.h"
+#include "base/strings/string_piece.h"
+#include "base/strings/string_util.h"
 #include "build/build_config.h"
 #include "gpu/command_buffer/common/constants.h"
 #include "gpu/command_buffer/common/gles2_cmd_utils.h"
@@ -54,43 +56,212 @@
 #define GPU_FUZZER_USE_STUB
 #endif
 
+constexpr const char* kExtensions[] = {
+    "GL_AMD_compressed_ATC_texture",
+    "GL_ANGLE_client_arrays",
+    "GL_ANGLE_depth_texture",
+    "GL_ANGLE_framebuffer_multisample",
+    "GL_ANGLE_instanced_arrays",
+    "GL_ANGLE_request_extension",
+    "GL_ANGLE_robust_client_memory",
+    "GL_ANGLE_robust_resource_initialization",
+    "GL_ANGLE_texture_compression_dxt3",
+    "GL_ANGLE_texture_compression_dxt5",
+    "GL_ANGLE_texture_rectangle",
+    "GL_ANGLE_texture_usage",
+    "GL_ANGLE_translated_shader_source",
+    "GL_ANGLE_webgl_compatibility",
+    "GL_APPLE_texture_format_BGRA8888",
+    "GL_APPLE_vertex_array_object",
+    "GL_APPLE_ycbcr_422",
+    "GL_ARB_blend_func_extended",
+    "GL_ARB_depth_texture",
+    "GL_ARB_draw_buffers",
+    "GL_ARB_draw_instanced",
+    "GL_ARB_ES3_compatibility",
+    "GL_ARB_explicit_attrib_location",
+    "GL_ARB_explicit_uniform_location",
+    "GL_ARB_framebuffer_sRGB",
+    "GL_ARB_instanced_arrays",
+    "GL_ARB_map_buffer_range",
+    "GL_ARB_occlusion_query",
+    "GL_ARB_occlusion_query2",
+    "GL_ARB_pixel_buffer_object",
+    "GL_ARB_program_interface_query",
+    "GL_ARB_robustness",
+    "GL_ARB_sampler_objects",
+    "GL_ARB_shader_image_load_store",
+    "GL_ARB_shading_language_420pack",
+    "GL_ARB_texture_float",
+    "GL_ARB_texture_gather",
+    "GL_ARB_texture_non_power_of_two",
+    "GL_ARB_texture_rectangle",
+    "GL_ARB_texture_rg",
+    "GL_ARB_texture_storage",
+    "GL_ARB_timer_query",
+    "GL_ARB_vertex_array_object",
+    "GL_ATI_texture_compression_atitc",
+    "GL_CHROMIUM_bind_generates_resource",
+    "GL_CHROMIUM_color_buffer_float_rgb",
+    "GL_CHROMIUM_color_buffer_float_rgba",
+    "GL_CHROMIUM_copy_compressed_texture",
+    "GL_CHROMIUM_copy_texture",
+    "GL_CHROMIUM_texture_filtering_hint",
+    "GL_EXT_blend_func_extended",
+    "GL_EXT_blend_minmax",
+    "GL_EXT_color_buffer_float",
+    "GL_EXT_color_buffer_half_float",
+    "GL_EXT_debug_marker",
+    "GL_EXT_direct_state_access",
+    "GL_EXT_discard_framebuffer",
+    "GL_EXT_disjoint_timer_query",
+    "GL_EXT_draw_buffers",
+    "GL_EXT_frag_depth",
+    "GL_EXT_framebuffer_multisample",
+    "GL_EXT_framebuffer_sRGB",
+    "GL_EXT_map_buffer_range",
+    "GL_EXT_multisample_compatibility",
+    "GL_EXT_multisampled_render_to_texture",
+    "GL_EXT_occlusion_query_boolean",
+    "GL_EXT_packed_depth_stencil",
+    "GL_EXT_read_format_bgra",
+    "GL_EXT_robustness",
+    "GL_EXT_shader_texture_lod",
+    "GL_EXT_sRGB",
+    "GL_EXT_sRGB_write_control",
+    "GL_EXT_texture_compression_dxt1",
+    "GL_EXT_texture_compression_s3tc",
+    "GL_EXT_texture_compression_s3tc_srgb",
+    "GL_EXT_texture_filter_anisotropic",
+    "GL_EXT_texture_format_BGRA8888",
+    "GL_EXT_texture_norm16",
+    "GL_EXT_texture_rg",
+    "GL_EXT_texture_sRGB",
+    "GL_EXT_texture_sRGB_decode",
+    "GL_EXT_texture_storage",
+    "GL_EXT_timer_query",
+    "GL_IMG_multisampled_render_to_texture",
+    "GL_IMG_texture_compression_pvrtc",
+    "GL_INTEL_framebuffer_CMAA",
+    "GL_KHR_blend_equation_advanced",
+    "GL_KHR_blend_equation_advanced_coherent",
+    "GL_KHR_debug",
+    "GL_KHR_robustness",
+    "GL_KHR_texture_compression_astc_ldr",
+    "GL_NV_blend_equation_advanced",
+    "GL_NV_blend_equation_advanced_coherent",
+    "GL_NV_draw_buffers",
+    "GL_NV_EGL_stream_consumer_external",
+    "GL_NV_fence",
+    "GL_NV_framebuffer_mixed_samples",
+    "GL_NV_path_rendering",
+    "GL_NV_pixel_buffer_object",
+    "GL_NV_sRGB_formats",
+    "GL_OES_compressed_ETC1_RGB8_texture",
+    "GL_OES_depth24",
+    "GL_OES_depth_texture",
+    "GL_OES_EGL_image_external",
+    "GL_OES_element_index_uint",
+    "GL_OES_packed_depth_stencil",
+    "GL_OES_rgb8_rgba8",
+    "GL_OES_standard_derivatives",
+    "GL_OES_texture_float",
+    "GL_OES_texture_float_linear",
+    "GL_OES_texture_half_float",
+    "GL_OES_texture_half_float_linear",
+    "GL_OES_texture_npot",
+    "GL_OES_vertex_array_object"};
+constexpr size_t kExtensionCount = arraysize(kExtensions);
+
 #if defined(GPU_FUZZER_USE_STUB)
-static const char kExtensions[] =
-    "GL_AMD_compressed_ATC_texture "
-    "GL_ANGLE_texture_compression_dxt3 "
-    "GL_ANGLE_texture_compression_dxt5 "
-    "GL_ANGLE_texture_usage "
-    "GL_APPLE_ycbcr_422 "
-    "GL_ARB_texture_rectangle "
-    "GL_EXT_blend_func_extended "
-    "GL_EXT_color_buffer_float "
-    "GL_EXT_disjoint_timer_query "
-    "GL_EXT_draw_buffers "
-    "GL_EXT_frag_depth "
-    "GL_EXT_multisample_compatibility "
-    "GL_EXT_multisampled_render_to_texture "
-    "GL_EXT_occlusion_query_boolean "
-    "GL_EXT_read_format_bgra "
-    "GL_EXT_shader_texture_lod "
-    "GL_EXT_texture_compression_s3tc "
-    "GL_EXT_texture_filter_anisotropic "
-    "GL_IMG_texture_compression_pvrtc "
-    "GL_KHR_blend_equation_advanced "
-    "GL_KHR_blend_equation_advanced_coherent "
-    "GL_KHR_texture_compression_astc_ldr "
-    "GL_NV_EGL_stream_consumer_external "
-    "GL_NV_framebuffer_mixed_samples "
-    "GL_NV_path_rendering "
-    "GL_OES_compressed_ETC1_RGB8_texture "
-    "GL_OES_depth24 "
-    "GL_OES_EGL_image_external "
-    "GL_OES_rgb8_rgba8 "
-    "GL_OES_texture_float "
-    "GL_OES_texture_float_linear "
-    "GL_OES_texture_half_float "
-    "GL_OES_texture_half_float_linear";
+constexpr const char* kDriverVersions[] = {"OpenGL ES 2.0", "OpenGL ES 3.1",
+                                           "2.0", "4.5.0"};
 #endif
 
+class BitIterator {
+ public:
+  BitIterator(const uint8_t* data, size_t size) : data_(data), size_(size) {}
+
+  bool GetBit() {
+    if (offset_ == size_)
+      return false;
+    bool value = !!(data_[offset_] & (1u << bit_));
+    if (++bit_ == 8) {
+      bit_ = 0;
+      ++offset_;
+    }
+    return value;
+  }
+
+  void Advance(size_t bits) {
+    bit_ += bits;
+    offset_ += bit_ / 8;
+    if (offset_ >= size_) {
+      offset_ = size_;
+      bit_ = 0;
+    } else {
+      bit_ = bit_ % 8;
+    }
+  }
+
+  size_t consumed_bytes() const { return offset_ + (bit_ + 7) / 8; }
+
+ private:
+  const uint8_t* data_;
+  size_t size_;
+  size_t offset_ = 0;
+  size_t bit_ = 0;
+};
+
+struct Config {
+  size_t MakeFromBits(const uint8_t* bits, size_t size) {
+    BitIterator it(bits, size);
+    attrib_helper.red_size = 8;
+    attrib_helper.green_size = 8;
+    attrib_helper.blue_size = 8;
+    attrib_helper.alpha_size = it.GetBit() ? 8 : 0;
+    attrib_helper.depth_size = it.GetBit() ? 24 : 0;
+    attrib_helper.stencil_size = it.GetBit() ? 8 : 0;
+    attrib_helper.buffer_preserved = it.GetBit();
+    attrib_helper.bind_generates_resource = it.GetBit();
+    attrib_helper.single_buffer = it.GetBit();
+    bool es3 = it.GetBit();
+    attrib_helper.context_type =
+        es3 ? gles2::CONTEXT_TYPE_OPENGLES3 : gles2::CONTEXT_TYPE_OPENGLES2;
+
+#if defined(GPU_FUZZER_USE_STUB)
+    std::vector<base::StringPiece> enabled_extensions;
+    enabled_extensions.reserve(kExtensionCount);
+    for (const char* extension : kExtensions) {
+      if (it.GetBit())
+        enabled_extensions.push_back(extension);
+    }
+    extensions = base::JoinString(enabled_extensions, " ");
+
+    bool desktop_driver = it.GetBit();
+    size_t version_index = (desktop_driver ? 2 : 0) + (es3 ? 1 : 0);
+    version = kDriverVersions[version_index];
+#else
+    // We consume bits even if we don't use them, so that the same inputs can be
+    // used for every fuzzer variation
+    it.Advance(kExtensionCount + 1);
+#endif
+
+#define GPU_OP(type, name) workarounds.name = it.GetBit();
+    GPU_DRIVER_BUG_WORKAROUNDS(GPU_OP)
+#undef GPU_OP
+
+    return it.consumed_bytes();
+  };
+
+  GpuDriverBugWorkarounds workarounds;
+  gles2::ContextCreationAttribHelper attrib_helper;
+#if defined(GPU_FUZZER_USE_STUB)
+  const char* version;
+  std::string extensions;
+#endif
+};
+
 GpuPreferences GetGpuPreferences() {
   GpuPreferences preferences;
 #if defined(GPU_FUZZER_USE_PASSTHROUGH_CMD_DECODER)
@@ -124,34 +295,37 @@
                                     gl::kGLImplementationSwiftShaderName);
     CHECK(gl::init::InitializeGLOneOffImplementation(
         gl::kGLImplementationSwiftShaderGL, false, false, false, true));
+#elif defined(GPU_FUZZER_USE_STUB)
+    gl::GLSurfaceTestSupport::InitializeOneOffWithStubBindings();
+    // Because the context depends on configuration bits, we want to recreate
+    // it every time.
+    recreate_context_ = true;
+#else
+#error invalid configuration
 #endif
     discardable_manager_ = std::make_unique<ServiceDiscardableManager>();
 
-#if !defined(GPU_FUZZER_USE_STUB)
-    surface_ = new gl::PbufferGLSurfaceEGL(gfx::Size());
-    surface_->Initialize();
+    if (gpu_preferences_.use_passthrough_cmd_decoder)
+      recreate_context_ = true;
+
+    surface_ = gl::init::CreateOffscreenGLSurface(gfx::Size());
     if (!recreate_context_) {
       InitContext();
     }
-#else   // defined(GPU_FUZZER_USE_STUB)
-    surface_ = new gl::GLSurfaceStub;
-    InitContext();
-    gl::GLSurfaceTestSupport::InitializeOneOffWithMockBindings();
-#endif  // defined(GPU_FUZZER_USE_STUB)
   }
 
-  void InitDecoder() {
+  bool InitDecoder() {
     if (recreate_context_) {
       InitContext();
     }
 
     context_->MakeCurrent(surface_.get());
     scoped_refptr<gles2::FeatureInfo> feature_info =
-        new gles2::FeatureInfo();
+        new gles2::FeatureInfo(config_.workarounds);
     scoped_refptr<gles2::ContextGroup> context_group = new gles2::ContextGroup(
         gpu_preferences_, true, &mailbox_manager_, nullptr /* memory_tracker */,
         &translator_cache_, &completeness_cache_, feature_info,
-        true /* bind_generates_resource */, &image_manager_,
+        config_.attrib_helper.bind_generates_resource, &image_manager_,
         nullptr /* image_factory */, nullptr /* progress_reporter */,
         GpuFeatureInfo(), discardable_manager_.get());
     command_buffer_.reset(new CommandBufferDirect(
@@ -160,36 +334,26 @@
     decoder_.reset(gles2::GLES2Decoder::Create(
         command_buffer_.get(), command_buffer_->service(), &outputter_,
         context_group.get()));
-    command_buffer_->set_handler(decoder_.get());
-
-    InitializeInitialCommandBuffer();
 
     decoder_->GetLogger()->set_log_synthesized_gl_errors(false);
 
-    gles2::ContextCreationAttribHelper attrib_helper;
-    attrib_helper.offscreen_framebuffer_size = gfx::Size(16, 16);
-    attrib_helper.red_size = 8;
-    attrib_helper.green_size = 8;
-    attrib_helper.blue_size = 8;
-    attrib_helper.alpha_size = 8;
-    attrib_helper.depth_size = 0;
-    attrib_helper.stencil_size = 0;
-    attrib_helper.context_type = gles2::CONTEXT_TYPE_OPENGLES3;
+    auto result = decoder_->Initialize(surface_.get(), context_.get(), true,
+                                       gles2::DisallowedFeatures(),
+                                       config_.attrib_helper);
+    if (result != gpu::ContextResult::kSuccess)
+      return false;
 
-    auto result =
-        decoder_->Initialize(surface_.get(), context_.get(), true,
-                             gles2::DisallowedFeatures(), attrib_helper);
-    CHECK_EQ(result, gpu::ContextResult::kSuccess);
+    command_buffer_->set_handler(decoder_.get());
+    InitializeInitialCommandBuffer();
+
     decoder_->set_max_bucket_size(8 << 20);
     context_group->buffer_manager()->set_max_buffer_size(8 << 20);
-    if (!vertex_translator_) {
-      // Keep a reference to the translators, which keeps them in the cache even
-      // after the decoder is reset. They are expensive to initialize, but they
-      // don't keep state.
-      vertex_translator_ = decoder_->GetTranslator(GL_VERTEX_SHADER);
-      fragment_translator_ = decoder_->GetTranslator(GL_FRAGMENT_SHADER);
-    }
-    decoder_->MakeCurrent();
+    // Keep a reference to the translators, which keeps them in the cache even
+    // after the decoder is reset. They are expensive to initialize, but they
+    // don't keep state.
+    decoder_->GetTranslator(GL_VERTEX_SHADER)->AddRef();
+    decoder_->GetTranslator(GL_FRAGMENT_SHADER)->AddRef();
+    return decoder_->MakeCurrent();
   }
 
   void ResetDecoder() {
@@ -203,6 +367,12 @@
   }
 
   void RunCommandBuffer(const uint8_t* data, size_t size) {
+    size_t consumed = config_.MakeFromBits(data, size);
+    consumed = (consumed + 3) & ~3;
+    if (consumed > size)
+      return;
+    data += consumed;
+    size -= consumed;
     // The commands are flushed at a uint32_t granularity. If the data is not
     // a full command, we zero-pad it.
     size_t padded_size = (size + 3) & ~3;
@@ -211,7 +381,9 @@
     if (padded_size > kCommandBufferSize)
       return;
 
-    InitDecoder();
+    if (!InitDecoder())
+      return;
+
     size_t buffer_size = buffer_->size();
     CHECK_LE(padded_size, buffer_size);
     command_buffer_->SetGetBuffer(buffer_id_);
@@ -251,8 +423,8 @@
 #else
     scoped_refptr<gl::GLContextStub> context_stub =
         new gl::GLContextStub(share_group_.get());
-    context_stub->SetGLVersionString("OpenGL ES 3.1");
-    context_stub->SetExtensionsString(kExtensions);
+    context_stub->SetGLVersionString(config_.version);
+    context_stub->SetExtensionsString(config_.extensions.c_str());
     context_stub->SetUseStubApi(true);
     context_ = context_stub;
 #endif
@@ -262,6 +434,8 @@
 
   GpuPreferences gpu_preferences_;
 
+  Config config_;
+
   gles2::MailboxManagerImpl mailbox_manager_;
   gles2::TraceOutputter outputter_;
   scoped_refptr<gl::GLShareGroup> share_group_;
@@ -280,9 +454,6 @@
 
   std::unique_ptr<gles2::GLES2Decoder> decoder_;
 
-  scoped_refptr<gles2::ShaderTranslatorInterface> vertex_translator_;
-  scoped_refptr<gles2::ShaderTranslatorInterface> fragment_translator_;
-
   scoped_refptr<Buffer> buffer_;
   int32_t buffer_id_ = 0;
 };
diff --git a/gpu/config/gpu_blacklist.cc b/gpu/config/gpu_blacklist.cc
index 177607f..3787197 100644
--- a/gpu/config/gpu_blacklist.cc
+++ b/gpu/config/gpu_blacklist.cc
@@ -38,6 +38,8 @@
                             GPU_FEATURE_TYPE_FLASH_STAGE3D_BASELINE);
   list->AddSupportedFeature("accelerated_video_decode",
                             GPU_FEATURE_TYPE_ACCELERATED_VIDEO_DECODE);
+  list->AddSupportedFeature("accelerated_video_encode",
+                            GPU_FEATURE_TYPE_ACCELERATED_VIDEO_ENCODE);
   list->AddSupportedFeature("panel_fitting", GPU_FEATURE_TYPE_PANEL_FITTING);
   list->AddSupportedFeature("gpu_rasterization",
                             GPU_FEATURE_TYPE_GPU_RASTERIZATION);
diff --git a/gpu/config/gpu_blacklist_unittest.cc b/gpu/config/gpu_blacklist_unittest.cc
index fcbd3ac..3906d18 100644
--- a/gpu/config/gpu_blacklist_unittest.cc
+++ b/gpu/config/gpu_blacklist_unittest.cc
@@ -95,6 +95,9 @@
 GPU_BLACKLIST_FEATURE_TEST(AcceleratedVideoDecode,
                            GPU_FEATURE_TYPE_ACCELERATED_VIDEO_DECODE)
 
+GPU_BLACKLIST_FEATURE_TEST(AcceleratedVideoEncode,
+                           GPU_FEATURE_TYPE_ACCELERATED_VIDEO_ENCODE)
+
 GPU_BLACKLIST_FEATURE_TEST(PanelFitting,
                            GPU_FEATURE_TYPE_PANEL_FITTING)
 
diff --git a/gpu/config/gpu_driver_bug_list.json b/gpu/config/gpu_driver_bug_list.json
index b9f17790..3d9ef51d 100644
--- a/gpu/config/gpu_driver_bug_list.json
+++ b/gpu/config/gpu_driver_bug_list.json
@@ -2640,9 +2640,19 @@
       "features": [
         "dont_initialize_uninitialized_locals"
       ]
+    },
+    {
+      "id": 243,
+      "description": "Program binaries don't contain transform feedback varyings on Mali GPUs",
+      "cr_bugs": [778871],
+      "os": {
+        "type": "chromeos"
+      },
+      "gl_vendor": "ARM.*",
+      "gl_renderer": "Mali.*",
+      "features": [
+        "disable_program_caching_for_transform_feedback"
+      ]
     }
-  ],
-  "comment": [
-    "Please update the version number on top whenever you change this file"
   ]
 }
diff --git a/gpu/config/gpu_feature_type.h b/gpu/config/gpu_feature_type.h
index 4cfe8fc..fb50143 100644
--- a/gpu/config/gpu_feature_type.h
+++ b/gpu/config/gpu_feature_type.h
@@ -17,6 +17,7 @@
   GPU_FEATURE_TYPE_FLASH3D,
   GPU_FEATURE_TYPE_FLASH_STAGE3D,
   GPU_FEATURE_TYPE_ACCELERATED_VIDEO_DECODE,
+  GPU_FEATURE_TYPE_ACCELERATED_VIDEO_ENCODE,
   GPU_FEATURE_TYPE_PANEL_FITTING,
   GPU_FEATURE_TYPE_FLASH_STAGE3D_BASELINE,
   GPU_FEATURE_TYPE_GPU_RASTERIZATION,
diff --git a/gpu/config/gpu_util.cc b/gpu/config/gpu_util.cc
index d22c80c..e2558666 100644
--- a/gpu/config/gpu_util.cc
+++ b/gpu/config/gpu_util.cc
@@ -166,37 +166,6 @@
   return kGpuFeatureStatusEnabled;
 }
 
-GpuFeatureStatus GetPanelFittingFeatureStatus(
-    const std::set<int>& blacklisted_features,
-    bool use_swift_shader,
-    bool use_swift_shader_for_webgl) {
-#if defined(OS_CHROMEOS)
-  if (use_swift_shader || use_swift_shader_for_webgl)
-    return kGpuFeatureStatusDisabled;
-  if (blacklisted_features.count(GPU_FEATURE_TYPE_PANEL_FITTING))
-    return kGpuFeatureStatusBlacklisted;
-  return kGpuFeatureStatusEnabled;
-#else
-  return kGpuFeatureStatusDisabled;
-#endif
-}
-
-GpuFeatureStatus GetGpuCompositingFeatureStatus(
-    const std::set<int>& blacklisted_features,
-    bool use_swift_shader,
-    bool use_swift_shader_for_webgl) {
-  if (use_swift_shader) {
-    // This is for testing only. Chrome should exercise the GPU accelerated
-    // path on top of SwiftShader driver.
-    return kGpuFeatureStatusEnabled;
-  }
-  if (use_swift_shader_for_webgl)
-    return kGpuFeatureStatusDisabled;
-  if (blacklisted_features.count(GPU_FEATURE_TYPE_GPU_COMPOSITING))
-    return kGpuFeatureStatusBlacklisted;
-  return kGpuFeatureStatusEnabled;
-}
-
 void AppendWorkaroundsToCommandLine(const GpuFeatureInfo& gpu_feature_info,
                                     base::CommandLine* command_line) {
   if (gpu_feature_info.IsWorkaroundEnabled(DISABLE_D3D11)) {
@@ -358,17 +327,6 @@
   gpu_feature_info.status_values[GPU_FEATURE_TYPE_ACCELERATED_VIDEO_DECODE] =
       GetAcceleratedVideoDecodeFeatureStatus(
           blacklisted_features, use_swift_shader, use_swift_shader_for_webgl);
-  gpu_feature_info.status_values[GPU_FEATURE_TYPE_PANEL_FITTING] =
-      GetPanelFittingFeatureStatus(blacklisted_features, use_swift_shader,
-                                   use_swift_shader_for_webgl);
-  gpu_feature_info.status_values[GPU_FEATURE_TYPE_GPU_COMPOSITING] =
-      GetGpuCompositingFeatureStatus(blacklisted_features, use_swift_shader,
-                                     use_swift_shader_for_webgl);
-#if DCHECK_IS_ON()
-  for (int ii = 0; ii < NUMBER_OF_GPU_FEATURE_TYPES; ++ii) {
-    DCHECK_NE(kGpuFeatureStatusUndefined, gpu_feature_info.status_values[ii]);
-  }
-#endif
 
   std::set<base::StringPiece> all_disabled_extensions;
   std::string disabled_gl_extensions_value =
diff --git a/gpu/config/software_rendering_list.json b/gpu/config/software_rendering_list.json
index 61c62c7..5381783 100644
--- a/gpu/config/software_rendering_list.json
+++ b/gpu/config/software_rendering_list.json
@@ -1383,6 +1383,16 @@
       ]
     },
     {
+      "id": 138,
+      "description": "Accelerated video encode is unavailable on Linux",
+      "os": {
+        "type": "linux"
+      },
+      "features": [
+        "accelerated_video_encode"
+      ]
+    },
+    {
       "id": 139,
       "description": "GPU Rasterization is disabled on pre-GCN AMD cards",
       "cr_bugs": [643850],
@@ -1563,8 +1573,5 @@
         "gpu_rasterization"
       ]
     }
-  ],
-  "comment": [
-    "Please update the version number on top whenever you change this file"
   ]
 }
diff --git a/gpu/ipc/client/gpu_memory_buffer_impl_io_surface.cc b/gpu/ipc/client/gpu_memory_buffer_impl_io_surface.cc
index 15706d41..40e592b 100644
--- a/gpu/ipc/client/gpu_memory_buffer_impl_io_surface.cc
+++ b/gpu/ipc/client/gpu_memory_buffer_impl_io_surface.cc
@@ -113,7 +113,7 @@
   return IOSurfaceGetBytesPerRowOfPlane(io_surface_, plane);
 }
 
-void GpuMemoryBufferImplIOSurface::SetColorSpaceForScanout(
+void GpuMemoryBufferImplIOSurface::SetColorSpace(
     const gfx::ColorSpace& color_space) {
   if (color_space == color_space_)
     return;
diff --git a/gpu/ipc/client/gpu_memory_buffer_impl_io_surface.h b/gpu/ipc/client/gpu_memory_buffer_impl_io_surface.h
index 810cf65..4dc00e2 100644
--- a/gpu/ipc/client/gpu_memory_buffer_impl_io_surface.h
+++ b/gpu/ipc/client/gpu_memory_buffer_impl_io_surface.h
@@ -44,7 +44,7 @@
   void* memory(size_t plane) override;
   void Unmap() override;
   int stride(size_t plane) const override;
-  void SetColorSpaceForScanout(const gfx::ColorSpace& color_space) override;
+  void SetColorSpace(const gfx::ColorSpace& color_space) override;
   gfx::GpuMemoryBufferHandle GetHandle() const override;
 
  private:
diff --git a/headless/lib/browser/headless_browser_context_impl.cc b/headless/lib/browser/headless_browser_context_impl.cc
index b5ada78..f92a385c 100644
--- a/headless/lib/browser/headless_browser_context_impl.cc
+++ b/headless/lib/browser/headless_browser_context_impl.cc
@@ -201,7 +201,8 @@
 
 void HeadlessBrowserContextImpl::InitWhileIOAllowed() {
   if (!context_options_->user_data_dir().empty()) {
-    path_ = context_options_->user_data_dir();
+    path_ =
+        context_options_->user_data_dir().Append(FILE_PATH_LITERAL("Default"));
   } else {
     PathService::Get(base::DIR_EXE, &path_);
   }
diff --git a/headless/lib/browser/headless_url_request_context_getter.cc b/headless/lib/browser/headless_url_request_context_getter.cc
index 73871d9b..826f2b6 100644
--- a/headless/lib/browser/headless_url_request_context_getter.cc
+++ b/headless/lib/browser/headless_url_request_context_getter.cc
@@ -79,26 +79,29 @@
   if (!url_request_context_) {
     net::URLRequestContextBuilder builder;
 
-    // Don't store cookies in incognito mode or if no user-data-dir was
-    // specified
-    // TODO: Enable this always once saving/restoring sessions is implemented
-    // (https://crbug.com/617931)
-    if (headless_browser_context_ &&
-        !headless_browser_context_->IsOffTheRecord() &&
-        !headless_browser_context_->options()->user_data_dir().empty()) {
-      content::CookieStoreConfig cookie_config(
-          headless_browser_context_->GetPath().Append(
-              FILE_PATH_LITERAL("Cookies")),
-          content::CookieStoreConfig::PERSISTANT_SESSION_COOKIES, NULL);
-      std::unique_ptr<net::CookieStore> cookie_store =
-          CreateCookieStore(cookie_config);
-      std::unique_ptr<net::ChannelIDService> channel_id_service =
-          base::MakeUnique<net::ChannelIDService>(
-              new net::DefaultChannelIDStore(nullptr));
+    {
+      base::AutoLock lock(lock_);
+      // Don't store cookies in incognito mode or if no user-data-dir was
+      // specified
+      // TODO: Enable this always once saving/restoring sessions is implemented
+      // (https://crbug.com/617931)
+      if (headless_browser_context_ &&
+          !headless_browser_context_->IsOffTheRecord() &&
+          !headless_browser_context_->options()->user_data_dir().empty()) {
+        content::CookieStoreConfig cookie_config(
+            headless_browser_context_->GetPath().Append(
+                FILE_PATH_LITERAL("Cookies")),
+            content::CookieStoreConfig::PERSISTANT_SESSION_COOKIES, NULL);
+        std::unique_ptr<net::CookieStore> cookie_store =
+            CreateCookieStore(cookie_config);
+        std::unique_ptr<net::ChannelIDService> channel_id_service =
+            base::MakeUnique<net::ChannelIDService>(
+                new net::DefaultChannelIDStore(nullptr));
 
-      cookie_store->SetChannelIDServiceID(channel_id_service->GetUniqueID());
-      builder.SetCookieAndChannelIdStores(std::move(cookie_store),
-                                          std::move(channel_id_service));
+        cookie_store->SetChannelIDServiceID(channel_id_service->GetUniqueID());
+        builder.SetCookieAndChannelIdStores(std::move(cookie_store),
+                                            std::move(channel_id_service));
+      }
     }
 
     builder.set_accept_language(
diff --git a/headless/lib/virtual_time_browsertest.cc b/headless/lib/virtual_time_browsertest.cc
index 6944b02d..1261ff2 100644
--- a/headless/lib/virtual_time_browsertest.cc
+++ b/headless/lib/virtual_time_browsertest.cc
@@ -279,4 +279,21 @@
 HEADLESS_ASYNC_DEVTOOLED_TEST_F(
     FrameDetatchWithPendingResourceLoadVirtualTimeTest);
 
+class DeferredLoadDoesntBlockVirtualTimeTest : public VirtualTimeBrowserTest {
+ public:
+  DeferredLoadDoesntBlockVirtualTimeTest() {
+    EXPECT_TRUE(embedded_test_server()->Start());
+    SetInitialURL(embedded_test_server()->GetURL("/video.html").spec());
+  }
+
+  // emulation::Observer implementation:
+  void OnVirtualTimeBudgetExpired(
+      const emulation::VirtualTimeBudgetExpiredParams& params) override {
+    // The video should not block virtual time.
+    FinishAsynchronousTest();
+  }
+};
+
+HEADLESS_ASYNC_DEVTOOLED_TEST_F(DeferredLoadDoesntBlockVirtualTimeTest);
+
 }  // namespace headless
diff --git a/headless/test/data/tulip2.webm b/headless/test/data/tulip2.webm
new file mode 100644
index 0000000..a2774f6
--- /dev/null
+++ b/headless/test/data/tulip2.webm
Binary files differ
diff --git a/ios/chrome/app/BUILD.gn b/ios/chrome/app/BUILD.gn
index effe124..a1820394 100644
--- a/ios/chrome/app/BUILD.gn
+++ b/ios/chrome/app/BUILD.gn
@@ -187,8 +187,10 @@
     "//ios/chrome/browser/ui/downloads",
     "//ios/chrome/browser/ui/first_run",
     "//ios/chrome/browser/ui/fullscreen",
+    "//ios/chrome/browser/ui/fullscreen:legacy_fullscreen",
     "//ios/chrome/browser/ui/history",
     "//ios/chrome/browser/ui/main",
+    "//ios/chrome/browser/ui/main:feature_flags",
     "//ios/chrome/browser/ui/promos",
     "//ios/chrome/browser/ui/settings",
     "//ios/chrome/browser/ui/signin_interaction",
diff --git a/ios/chrome/app/main_controller.mm b/ios/chrome/app/main_controller.mm
index 709277f..e5d657ef 100644
--- a/ios/chrome/app/main_controller.mm
+++ b/ios/chrome/app/main_controller.mm
@@ -121,6 +121,7 @@
 #import "ios/chrome/browser/ui/history/history_panel_view_controller.h"
 #import "ios/chrome/browser/ui/main/browser_view_wrangler.h"
 #import "ios/chrome/browser/ui/main/main_coordinator.h"
+#import "ios/chrome/browser/ui/main/main_feature_flags.h"
 #import "ios/chrome/browser/ui/main/view_controller_swapping.h"
 #import "ios/chrome/browser/ui/orientation_limiting_navigation_controller.h"
 #import "ios/chrome/browser/ui/promos/signin_promo_view_controller.h"
@@ -1506,22 +1507,28 @@
 
 #pragma mark - ApplicationSettingsCommands
 
-- (void)showAccountsSettings {
+// TODO(crbug.com/779791) : Remove show settings from MainController.
+- (void)showAccountsSettingsFromViewController:
+    (UIViewController*)baseViewController {
+  if (!baseViewController) {
+    DCHECK_EQ(self.currentBVC, self.mainViewController.activeViewController);
+    baseViewController = self.currentBVC;
+  }
+  DCHECK(![baseViewController presentedViewController]);
   if ([self currentBrowserState]->IsOffTheRecord()) {
     NOTREACHED();
     return;
   }
   if (_settingsNavigationController) {
-    [_settingsNavigationController showAccountsSettings];
+    [_settingsNavigationController showAccountsSettingsFromViewController:nil];
     return;
   }
   _settingsNavigationController = [SettingsNavigationController
       newAccountsController:self.currentBrowserState
                    delegate:self];
-  [[self topPresentedViewController]
-      presentViewController:_settingsNavigationController
-                   animated:YES
-                 completion:nil];
+  [baseViewController presentViewController:_settingsNavigationController
+                                   animated:YES
+                                 completion:nil];
 }
 
 - (void)showSyncSettings {
@@ -1909,11 +1916,32 @@
   BrowserViewController* targetBVC =
       (tabModel == self.mainTabModel) ? self.mainBVC : self.otrBVC;
   self.currentBVC = targetBVC;
+
+  // The call to set currentBVC above does not actually display the BVC, because
+  // _dismissingStackView is YES.  When the presentation experiment is enabled,
+  // force the BVC transition to start.
+  if (TabSwitcherPresentsBVCEnabled()) {
+    [self displayCurrentBVC];
+  }
 }
 
 - (void)finishDismissingStackView {
-  DCHECK_EQ(self.mainViewController.activeViewController,
-            _tabSwitcherController);
+  // The tab switcher presentation experiment modifies the app's VC hierarchy.
+  // As a result, the "active" VC when the animation completes differs based on
+  // the experiment state.
+  if (TabSwitcherPresentsBVCEnabled()) {
+    // When the experiment is enabled, the tab switcher dismissal animation runs
+    // as part of the BVC presentation process.  The BVC is presented before the
+    // animations begin, so it is the current active VC at this point.
+    DCHECK_EQ(self.mainViewController.activeViewController, self.currentBVC);
+  } else {
+    // Without the experiment, the BVC is added as a child and made visible in
+    // the call to |displayCurrentBVC| below, after the tab switcher dismissal
+    // animation is complete.  At this point in the process, the tab switcher is
+    // still the active VC.
+    DCHECK_EQ(self.mainViewController.activeViewController,
+              _tabSwitcherController);
+  }
 
   if (_modeToDisplayOnStackViewDismissal == StackViewDismissalMode::NORMAL) {
     self.currentBVC = self.mainBVC;
@@ -1924,7 +1952,9 @@
 
   _modeToDisplayOnStackViewDismissal = StackViewDismissalMode::NONE;
 
-  // Displaying the current BVC dismisses the stack view.
+  // Displaying the current BVC dismisses the stack view.  When the tabswitcher
+  // presentation experiment is enabled, this call does nothing because the BVC
+  // is already presented.
   [self displayCurrentBVC];
 
   ProceduralBlock action = [self completionBlockForTriggeringAction:
diff --git a/ios/chrome/app/strings/ios_strings.grd b/ios/chrome/app/strings/ios_strings.grd
index 620bcbec..36778c4 100644
--- a/ios/chrome/app/strings/ios_strings.grd
+++ b/ios/chrome/app/strings/ios_strings.grd
@@ -1538,18 +1538,9 @@
       <message name="IDS_IOS_COMPOSE_EMAIL_SETTING" desc="Title for the view and option to select a handler for mailto: URLs. [Length: 20em]">
         Compose Email
       </message>
-      <message name="IDS_IOS_CHOOSE_EMAIL_CLIENT_APP" desc="Title for action sheet to select an email client app when user taps on an URL that has a mailto: URL scheme. [Length: 50em]">
-        Create email with:
-      </message>
-      <message name="IDS_IOS_CHOOSE_DEFAULT_EMAIL_CLIENT_APP" desc="Title for action sheet to select an email client app when user taps on an URL that has a mailto: URL scheme. [Length: 50em]">
-        Choose Default Email App
-      </message>
       <message name="IDS_IOS_CHOOSE_EMAIL_APP" desc="Title for bottom sheet to choose an email client app when user taps on an URL that has a mailto: URL scheme. [Length 40em]">
         Choose Email App
       </message>
-      <message name="IDS_IOS_CHOOSE_EMAIL_APP_HOW_TO_CHANGE" desc="Subtitle for action sheet to choose mailto:// handler with instructions on how to change the preference in the future. [Length: 80]">
-        You can change this preference any time in Chrome settings
-      </message>
       <message name="IDS_IOS_CHOOSE_EMAIL_ASK_TOGGLE" desc="Title for toggle switch to set whether to ask user which Mail client app to use every time a mailto:// URL is tapped. [Length: 50]">
         Ask me which app to use every time
       </message>
diff --git a/ios/chrome/browser/BUILD.gn b/ios/chrome/browser/BUILD.gn
index fa6015c..0a8eda60 100644
--- a/ios/chrome/browser/BUILD.gn
+++ b/ios/chrome/browser/BUILD.gn
@@ -126,8 +126,7 @@
     "//ios/chrome/browser/ui/external_search:features",
     "//ios/chrome/browser/ui/history:history_base_feature",
     "//ios/chrome/browser/ui/main:feature_flags",
-    "//ios/chrome/browser/ui/toolbar:toolbar_base_feature",
-    "//ios/chrome/browser/web:features",
+    "//ios/chrome/browser/ui/toolbar/public:toolbar_base_feature",
     "//ios/chrome/common",
     "//ios/components/io_thread",
     "//ios/net",
diff --git a/ios/chrome/browser/about_flags.mm b/ios/chrome/browser/about_flags.mm
index 2d401a8..64661cb 100644
--- a/ios/chrome/browser/about_flags.mm
+++ b/ios/chrome/browser/about_flags.mm
@@ -42,10 +42,10 @@
 #include "ios/chrome/browser/ui/external_search/features.h"
 #import "ios/chrome/browser/ui/history/history_base_feature.h"
 #include "ios/chrome/browser/ui/main/main_feature_flags.h"
-#import "ios/chrome/browser/ui/toolbar/toolbar_controller_base_feature.h"
-#include "ios/chrome/browser/web/features.h"
+#import "ios/chrome/browser/ui/toolbar/public/toolbar_controller_base_feature.h"
 #include "ios/chrome/grit/ios_strings.h"
 #include "ios/public/provider/chrome/browser/chrome_browser_provider.h"
+#include "ios/web/public/features.h"
 #include "ios/web/public/user_agent.h"
 #include "ios/web/public/web_view_creation_util.h"
 
@@ -170,10 +170,6 @@
     {"bookmark-new-generation", flag_descriptions::kBookmarkNewGenerationName,
      flag_descriptions::kBookmarkNewGenerationDescription, flags_ui::kOsIos,
      FEATURE_VALUE_TYPE(kBookmarkNewGeneration)},
-    {"mailto-prompt-for-user-choice",
-     flag_descriptions::kMailtoPromptForUserChoiceName,
-     flag_descriptions::kMailtoPromptForUserChoiceDescription, flags_ui::kOsIos,
-     FEATURE_VALUE_TYPE(kMailtoPromptForUserChoice)},
 #if defined(__IPHONE_11_0) && (__IPHONE_OS_VERSION_MAX_ALLOWED >= __IPHONE_11_0)
     {"drag_and_drop", flag_descriptions::kDragAndDropName,
      flag_descriptions::kDragAndDropDescription, flags_ui::kOsIos,
@@ -194,6 +190,9 @@
      flag_descriptions::kHistoryBatchUpdatesFilterName,
      flag_descriptions::kHistoryBatchUpdatesFilterDescription, flags_ui::kOsIos,
      FEATURE_VALUE_TYPE(kHistoryBatchUpdatesFilter)},
+    {"slim-navigation-manager", flag_descriptions::kSlimNavigationManagerName,
+     flag_descriptions::kSlimNavigationManagerDescription, flags_ui::kOsIos,
+     FEATURE_VALUE_TYPE(web::features::kSlimNavigationManager)},
 };
 
 // Add all switches from experimental flags to |command_line|.
@@ -247,16 +246,6 @@
         ntp_tiles::switches::kDisableNtpMostLikelyFaviconsFromServer);
   }
 
-  // Populate command line flag for the native to WKBackForwardList based
-  // navigation manager experiment.
-  NSString* enableSlimNavigationManager =
-      [defaults stringForKey:@"EnableSlimNavigationManager"];
-  if ([enableSlimNavigationManager isEqualToString:@"Enabled"]) {
-    command_line->AppendSwitch(switches::kEnableSlimNavigationManager);
-  } else if ([enableSlimNavigationManager isEqualToString:@"Disabled"]) {
-    command_line->AppendSwitch(switches::kDisableSlimNavigationManager);
-  }
-
   // Freeform commandline flags.  These are added last, so that any flags added
   // earlier in this function take precedence.
   if ([defaults boolForKey:@"EnableFreeformCommandLineFlags"]) {
diff --git a/ios/chrome/browser/chrome_switches.cc b/ios/chrome/browser/chrome_switches.cc
index 499dd11..725ccd52b 100644
--- a/ios/chrome/browser/chrome_switches.cc
+++ b/ios/chrome/browser/chrome_switches.cc
@@ -27,9 +27,6 @@
 // Disables the Suggestions UI
 const char kDisableSuggestionsUI[] = "disable-suggestions-ui";
 
-// Disables the WKBackForwardList based navigation manager experiment.
-const char kDisableSlimNavigationManager[] = "disable-slim-navigation-manager";
-
 // Disables the 3rd party keyboard omnibox workaround.
 const char kDisableThirdPartyKeyboardWorkaround[] =
     "disable-third-party-keyboard-workaround";
@@ -52,9 +49,6 @@
 // Enables the Suggestions UI
 const char kEnableSuggestionsUI[] = "enable-suggestions-ui";
 
-// Enables the WKBackForwardList based navigation manager experiment.
-const char kEnableSlimNavigationManager[] = "enable-slim-navigation-manager";
-
 // Enables the 3rd party keyboard omnibox workaround.
 const char kEnableThirdPartyKeyboardWorkaround[] =
     "enable-third-party-keyboard-workaround";
diff --git a/ios/chrome/browser/chrome_switches.h b/ios/chrome/browser/chrome_switches.h
index 8e9f403..9822af9 100644
--- a/ios/chrome/browser/chrome_switches.h
+++ b/ios/chrome/browser/chrome_switches.h
@@ -14,7 +14,6 @@
 extern const char kDisableIOSPasswordSuggestions[];
 extern const char kDisableNTPFavicons[];
 extern const char kDisableSuggestionsUI[];
-extern const char kDisableSlimNavigationManager[];
 extern const char kDisableThirdPartyKeyboardWorkaround[];
 
 extern const char kEnableContextualSearch[];
@@ -23,7 +22,6 @@
 extern const char kEnableNTPFavicons[];
 extern const char kEnableSpotlightActions[];
 extern const char kEnableSuggestionsUI[];
-extern const char kEnableSlimNavigationManager[];
 extern const char kEnableThirdPartyKeyboardWorkaround[];
 
 extern const char kIOSForceVariationIds[];
diff --git a/ios/chrome/browser/drag_and_drop/OWNERS b/ios/chrome/browser/drag_and_drop/OWNERS
index d2e1add..0fb09d6 100644
--- a/ios/chrome/browser/drag_and_drop/OWNERS
+++ b/ios/chrome/browser/drag_and_drop/OWNERS
@@ -1 +1 @@
-jif@chromium.org
+stk@chromium.org
diff --git a/ios/chrome/browser/experimental_flags.h b/ios/chrome/browser/experimental_flags.h
index d3559f4..f5bb674b 100644
--- a/ios/chrome/browser/experimental_flags.h
+++ b/ios/chrome/browser/experimental_flags.h
@@ -69,9 +69,6 @@
 // Whether a new version of FeedbackKit is the preferred feedback UI provider.
 bool IsNewFeedbackKitEnabled();
 
-// Whether the WKBackForwardList based navigation manager is enabled.
-bool IsSlimNavigationManagerEnabled();
-
 // Whether the 3rd party keyboard omnibox workaround is enabled.
 bool IsThirdPartyKeyboardWorkaroundEnabled();
 
diff --git a/ios/chrome/browser/experimental_flags.mm b/ios/chrome/browser/experimental_flags.mm
index f55de515..44d785f 100644
--- a/ios/chrome/browser/experimental_flags.mm
+++ b/ios/chrome/browser/experimental_flags.mm
@@ -38,8 +38,6 @@
 NSString* const kOriginServerHost = @"AlternateOriginServerHost";
 NSString* const kWhatsNewPromoStatus = @"WhatsNewPromoStatus";
 NSString* const kClearApplicationGroup = @"ClearApplicationGroup";
-const base::Feature kEnableSlimNavigationManager{
-    "EnableSlimNavigationManager", base::FEATURE_DISABLED_BY_DEFAULT};
 const base::Feature kEnableThirdPartyKeyboardWorkaround{
     "EnableThirdPartyKeyboardWorkaround", base::FEATURE_ENABLED_BY_DEFAULT};
 const base::Feature kIOSNTPSuggestions{"IOSNTPSuggestions",
@@ -170,19 +168,6 @@
       boolForKey:@"NewFeedbackKitEnabled"];
 }
 
-bool IsSlimNavigationManagerEnabled() {
-  // Check if the experimental flag is forced on or off.
-  base::CommandLine* command_line = base::CommandLine::ForCurrentProcess();
-  if (command_line->HasSwitch(switches::kEnableSlimNavigationManager)) {
-    return true;
-  } else if (command_line->HasSwitch(switches::kDisableSlimNavigationManager)) {
-    return false;
-  }
-
-  // Check if the Finch experiment is turned on.
-  return base::FeatureList::IsEnabled(kEnableSlimNavigationManager);
-}
-
 bool IsThirdPartyKeyboardWorkaroundEnabled() {
   // Check if the experimental flag is forced on or off.
   base::CommandLine* command_line = base::CommandLine::ForCurrentProcess();
diff --git a/ios/chrome/browser/infobars/OWNERS b/ios/chrome/browser/infobars/OWNERS
index c85e66a..b127701 100644
--- a/ios/chrome/browser/infobars/OWNERS
+++ b/ios/chrome/browser/infobars/OWNERS
@@ -1,4 +1,4 @@
-jif@chromium.org
+rohitrao@chromium.org
 
 # TEAM: ios-directory-owners@chromium.org
 # OS: iOS
diff --git a/ios/chrome/browser/ios_chrome_flag_descriptions.cc b/ios/chrome/browser/ios_chrome_flag_descriptions.cc
index 8e21a083f..e0cc9a193 100644
--- a/ios/chrome/browser/ios_chrome_flag_descriptions.cc
+++ b/ios/chrome/browser/ios_chrome_flag_descriptions.cc
@@ -51,12 +51,6 @@
 const char kMarkHttpAsDescription[] = "Change the UI treatment for HTTP pages";
 const char kMarkHttpAsDangerous[] = "Always mark HTTP as actively dangerous";
 
-const char kMailtoPromptForUserChoiceName[] =
-    "Mailto Handler Prompt for User Choice";
-const char kMailtoPromptForUserChoiceDescription[] =
-    "Enable prompt for user to choose a mail client app when user taps on a "
-    "mailto:// URL link.";
-
 const char kOmniboxUIElideSuggestionUrlAfterHostName[] =
     "Hide the path, query, and ref of omnibox suggestions";
 const char kOmniboxUIElideSuggestionUrlAfterHostDescription[] =
@@ -84,6 +78,11 @@
 extern const char kSafeAreaCompatibleToolbarDescription[] =
     "When enabled, the toolbar resizes itself when the safe area changes.";
 
+const char kSlimNavigationManagerName[] = "Use Slim Navigation Manager";
+const char kSlimNavigationManagerDescription[] =
+    "When enabled, uses the experimental slim navigation manager that provides "
+    "better compatibility with HTML navigation spec.";
+
 const char kTabSwitcherPresentsBVCName[] = "TabSwitcher Presents BVC";
 const char kTabSwitcherPresentsBVCDescription[] =
     "When enabled, the tab switcher will present the BVC, so that when the "
diff --git a/ios/chrome/browser/ios_chrome_flag_descriptions.h b/ios/chrome/browser/ios_chrome_flag_descriptions.h
index 055e36e..47ebdac 100644
--- a/ios/chrome/browser/ios_chrome_flag_descriptions.h
+++ b/ios/chrome/browser/ios_chrome_flag_descriptions.h
@@ -47,11 +47,6 @@
 extern const char kMarkHttpAsDescription[];
 extern const char kMarkHttpAsDangerous[];
 
-// Title and descript for the flag to enable a prompt asking user to choose
-// which mail client app to use to handle mailto:// URLs.
-extern const char kMailtoPromptForUserChoiceName[];
-extern const char kMailtoPromptForUserChoiceDescription[];
-
 // Title and description for the flag to enable elision of the URL path, query,
 // and ref in omnibox URL suggestions.
 extern const char kOmniboxUIElideSuggestionUrlAfterHostName[];
@@ -75,6 +70,11 @@
 extern const char kSafeAreaCompatibleToolbarName[];
 extern const char kSafeAreaCompatibleToolbarDescription[];
 
+// Title and description for the flag to enable WKBackForwardList based
+// navigation manager.
+extern const char kSlimNavigationManagerName[];
+extern const char kSlimNavigationManagerDescription[];
+
 // Title and description for the flag to enable the TabSwitcher to present the
 // BVC.
 extern const char kTabSwitcherPresentsBVCName[];
diff --git a/ios/chrome/browser/metrics/tab_usage_recorder.h b/ios/chrome/browser/metrics/tab_usage_recorder.h
index 8bef4bd..75cb753 100644
--- a/ios/chrome/browser/metrics/tab_usage_recorder.h
+++ b/ios/chrome/browser/metrics/tab_usage_recorder.h
@@ -13,6 +13,7 @@
 #include "base/macros.h"
 #include "base/time/time.h"
 #import "ios/chrome/browser/web_state_list/web_state_list_observer.h"
+#import "ios/web/public/web_state/web_state_observer.h"
 
 class PrerenderService;
 class WebStateList;
@@ -75,7 +76,8 @@
 extern const int kSecondsBeforeRendererTermination;
 
 // Reports usage about the lifecycle of a single TabModel's tabs.
-class TabUsageRecorder : public WebStateListObserver {
+class TabUsageRecorder : public web::WebStateObserver,
+                         public WebStateListObserver {
  public:
   enum TabStateWhenSelected {
     IN_MEMORY = 0,
@@ -181,11 +183,6 @@
   // to depends on injecting values in |termination_timestamps_|.
   friend class TabUsageRecorderTest;
 
-  // Sub-class of web::WebStateObserver to allow track events from multiple
-  // web::WebState (needs to be forward-declared here because the destructor
-  // of web::WebStateObserver is protected).
-  class WebStateObserver;
-
   // Clear out all state regarding a current evicted tab.
   void ResetEvictedTab();
 
@@ -205,15 +202,20 @@
   // Returns the number of WebState that are still alive (in-memory).
   int GetLiveWebStatesCount() const;
 
-  // Called after a WebState is added to the WebStateList; will create the
-  // observer used to track the WebState's events.
-  void OnWebStateInserted(web::WebState* web_state);
-
   // Called before one of the tracked WebState is destroyed. The WebState is
   // still valid but will become invalid afterwards, so any reference to it
   // should be removed.
   void OnWebStateDestroyed(web::WebState* web_state);
 
+  // web::WebStateObserver implementation.
+  void DidStartNavigation(web::WebState* web_state,
+                          web::NavigationContext* navigation_context) override;
+  void PageLoaded(
+      web::WebState* web_state,
+      web::PageLoadCompletionStatus load_completion_status) override;
+  void RenderProcessGone(web::WebState* web_state) override;
+  void WebStateDestroyed(web::WebState* web_state) override;
+
   // WebStateListObserver implementation.
   void WebStateInsertedAt(WebStateList* web_state_list,
                           web::WebState* web_state,
@@ -266,10 +268,6 @@
   // Keep track of the tabs that have a known eviction cause.
   std::map<web::WebState*, TabStateWhenSelected> evicted_web_states_;
 
-  // Maps WebStates to the WebStateObserver used to track its events.
-  std::map<web::WebState*, std::unique_ptr<WebStateObserver>>
-      web_state_observers_;
-
   // The WebStateList containing all the monitored tabs.
   WebStateList* web_state_list_;  // weak
 
diff --git a/ios/chrome/browser/metrics/tab_usage_recorder.mm b/ios/chrome/browser/metrics/tab_usage_recorder.mm
index f34c041..073624a 100644
--- a/ios/chrome/browser/metrics/tab_usage_recorder.mm
+++ b/ios/chrome/browser/metrics/tab_usage_recorder.mm
@@ -15,7 +15,6 @@
 #import "ios/web/public/navigation_manager.h"
 #import "ios/web/public/web_state/navigation_context.h"
 #import "ios/web/public/web_state/web_state.h"
-#import "ios/web/public/web_state/web_state_observer.h"
 #include "ui/base/page_transition_types.h"
 
 #if !defined(__has_feature) || !__has_feature(objc_arc)
@@ -73,67 +72,18 @@
 // specifies x.
 const int kSecondsBeforeRendererTermination = 2;
 
-class TabUsageRecorder::WebStateObserver : public web::WebStateObserver {
- public:
-  WebStateObserver(web::WebState* web_state,
-                   TabUsageRecorder* tab_usage_recorder);
-  ~WebStateObserver() override;
-
- private:
-  // web::WebStateObserver implementation.
-  void DidStartNavigation(web::WebState* web_state,
-                          web::NavigationContext* navigation_context) override;
-  void PageLoaded(
-      web::WebState* web_state,
-      web::PageLoadCompletionStatus load_completion_status) override;
-  void RenderProcessGone(web::WebState* web_state) override;
-
-  TabUsageRecorder* tab_usage_recorder_;
-
-  DISALLOW_COPY_AND_ASSIGN(WebStateObserver);
-};
-
-TabUsageRecorder::WebStateObserver::WebStateObserver(
-    web::WebState* web_state,
-    TabUsageRecorder* tab_usage_recorder)
-    : web::WebStateObserver(web_state),
-      tab_usage_recorder_(tab_usage_recorder) {
-  DCHECK(tab_usage_recorder_);
-}
-
-TabUsageRecorder::WebStateObserver::~WebStateObserver() = default;
-
-void TabUsageRecorder::WebStateObserver::DidStartNavigation(
-    web::WebState* web_state,
-    web::NavigationContext* navigation_context) {
-  if (PageTransitionCoreTypeIs(navigation_context->GetPageTransition(),
-                               ui::PAGE_TRANSITION_RELOAD)) {
-    tab_usage_recorder_->RecordReload(web_state);
-  }
-}
-
-void TabUsageRecorder::WebStateObserver::PageLoaded(
-    web::WebState* web_state,
-    web::PageLoadCompletionStatus load_completion_status) {
-  tab_usage_recorder_->RecordPageLoadDone(
-      web_state,
-      load_completion_status == web::PageLoadCompletionStatus::SUCCESS);
-}
-
-void TabUsageRecorder::WebStateObserver::RenderProcessGone(
-    web::WebState* web_state) {
-  tab_usage_recorder_->RendererTerminated(
-      web_state, web_state->IsVisible(),
-      [UIApplication sharedApplication].applicationState);
-}
-
 TabUsageRecorder::TabUsageRecorder(WebStateList* web_state_list,
                                    PrerenderService* prerender_service)
     : restore_start_time_(base::TimeTicks::Now()),
       web_state_list_(web_state_list),
       prerender_service_(prerender_service) {
   DCHECK(web_state_list_);
+
   web_state_list_->AddObserver(this);
+  for (int index = 0; index < web_state_list_->count(); ++index) {
+    web::WebState* web_state = web_state_list_->GetWebStateAt(index);
+    web_state->AddObserver(this);
+  }
 
   // Register for backgrounding and foregrounding notifications. It is safe for
   // the block to capture a pointer to |this| as they are unregistered in the
@@ -156,6 +106,12 @@
 }
 
 TabUsageRecorder::~TabUsageRecorder() {
+  DCHECK(web_state_list_);
+
+  for (int index = 0; index < web_state_list_->count(); ++index) {
+    web::WebState* web_state = web_state_list_->GetWebStateAt(index);
+    web_state->RemoveObserver(this);
+  }
   web_state_list_->RemoveObserver(this);
 
   if (application_backgrounding_observer_) {
@@ -461,13 +417,6 @@
   return count;
 }
 
-void TabUsageRecorder::OnWebStateInserted(web::WebState* web_state) {
-  DCHECK(web_state_observers_.find(web_state) == web_state_observers_.end());
-  web_state_observers_.insert(std::make_pair(
-      web_state,
-      std::make_unique<TabUsageRecorder::WebStateObserver>(web_state, this)));
-}
-
 void TabUsageRecorder::OnWebStateDestroyed(web::WebState* web_state) {
   if (web_state == web_state_created_selected_)
     web_state_created_selected_ = nullptr;
@@ -482,9 +431,37 @@
   if (evicted_web_states_iter != evicted_web_states_.end())
     evicted_web_states_.erase(evicted_web_states_iter);
 
-  auto web_state_observers_iter = web_state_observers_.find(web_state);
-  if (web_state_observers_iter != web_state_observers_.end())
-    web_state_observers_.erase(web_state_observers_iter);
+  web_state->RemoveObserver(this);
+}
+
+void TabUsageRecorder::DidStartNavigation(
+    web::WebState* web_state,
+    web::NavigationContext* navigation_context) {
+  if (PageTransitionCoreTypeIs(navigation_context->GetPageTransition(),
+                               ui::PAGE_TRANSITION_RELOAD)) {
+    RecordReload(web_state);
+  }
+}
+
+void TabUsageRecorder::PageLoaded(
+    web::WebState* web_state,
+    web::PageLoadCompletionStatus load_completion_status) {
+  RecordPageLoadDone(web_state, load_completion_status ==
+                                    web::PageLoadCompletionStatus::SUCCESS);
+}
+
+void TabUsageRecorder::RenderProcessGone(web::WebState* web_state) {
+  RendererTerminated(web_state, web_state->IsVisible(),
+                     [UIApplication sharedApplication].applicationState);
+}
+
+void TabUsageRecorder::WebStateDestroyed(web::WebState* web_state) {
+  // TabUsageRecorder only watches WebState inserted in a WebStateList. The
+  // WebStateList owns the WebStates it manages. TabUsageRecorder removes
+  // itself from WebStates' WebStateObservers when notified by WebStateList
+  // that a WebState is removed, so it should never notice WebStateDestroyed
+  // event. Thus the implementation enforces this with NOTREACHED().
+  NOTREACHED();
 }
 
 void TabUsageRecorder::WebStateInsertedAt(WebStateList* web_state_list,
@@ -494,7 +471,7 @@
   if (activating)
     web_state_created_selected_ = web_state;
 
-  OnWebStateInserted(web_state);
+  web_state->AddObserver(this);
 }
 
 void TabUsageRecorder::WebStateReplacedAt(WebStateList* web_state_list,
@@ -502,7 +479,9 @@
                                           web::WebState* new_web_state,
                                           int index) {
   OnWebStateDestroyed(old_web_state);
-  OnWebStateInserted(new_web_state);
+
+  if (new_web_state)
+    new_web_state->AddObserver(this);
 }
 
 void TabUsageRecorder::WebStateDetachedAt(WebStateList* web_state_list,
diff --git a/ios/chrome/browser/payments/payment_request.mm b/ios/chrome/browser/payments/payment_request.mm
index 0ac1e5f..28ab8e0 100644
--- a/ios/chrome/browser/payments/payment_request.mm
+++ b/ios/chrome/browser/payments/payment_request.mm
@@ -133,17 +133,6 @@
     }
   }
 
-  // Kickoff the process of loading the rules (which is asynchronous) for each
-  // profile's country, to get faster address normalization later.
-  for (const autofill::AutofillProfile* profile :
-       personal_data_manager_->GetProfilesToSuggest()) {
-    std::string countryCode =
-        base::UTF16ToUTF8(profile->GetRawInfo(autofill::ADDRESS_HOME_COUNTRY));
-    if (autofill::data_util::IsValidCountryCode(countryCode)) {
-      address_normalizer_.LoadRulesForRegion(countryCode);
-    }
-  }
-
   RecordNumberOfSuggestionsShown();
   RecordRequestedInformation();
 }
diff --git a/ios/chrome/browser/snapshots/OWNERS b/ios/chrome/browser/snapshots/OWNERS
index f4823b16..867f7564 100644
--- a/ios/chrome/browser/snapshots/OWNERS
+++ b/ios/chrome/browser/snapshots/OWNERS
@@ -1,4 +1,3 @@
-jif@chromium.org
 justincohen@chromium.org
 
 # TEAM: ios-directory-owners@chromium.org
diff --git a/ios/chrome/browser/store_kit/OWNERS b/ios/chrome/browser/store_kit/OWNERS
index c85e66a..241c424 100644
--- a/ios/chrome/browser/store_kit/OWNERS
+++ b/ios/chrome/browser/store_kit/OWNERS
@@ -1,4 +1,4 @@
-jif@chromium.org
+pkl@chromium.org
 
 # TEAM: ios-directory-owners@chromium.org
 # OS: iOS
diff --git a/ios/chrome/browser/tabs/BUILD.gn b/ios/chrome/browser/tabs/BUILD.gn
index 149e06d..08c5e1e8 100644
--- a/ios/chrome/browser/tabs/BUILD.gn
+++ b/ios/chrome/browser/tabs/BUILD.gn
@@ -116,6 +116,7 @@
     "//ios/chrome/browser/ui/commands",
     "//ios/chrome/browser/ui/downloads",
     "//ios/chrome/browser/ui/fullscreen",
+    "//ios/chrome/browser/ui/fullscreen:legacy_fullscreen",
     "//ios/chrome/browser/ui/overscroll_actions",
     "//ios/chrome/browser/ui/toolbar",
     "//ios/chrome/browser/ui/util",
diff --git a/ios/chrome/browser/tabs/tab.h b/ios/chrome/browser/tabs/tab.h
index 57fca91..0f38e21 100644
--- a/ios/chrome/browser/tabs/tab.h
+++ b/ios/chrome/browser/tabs/tab.h
@@ -116,8 +116,13 @@
 
 @property(nonatomic, weak) id<IOSCaptivePortalBlockingPageDelegate>
     iOSCaptivePortalBlockingPageDelegate;
+
+// The delegate to use for the legacy fullscreen controller.  It should not be
+// set if the new fullscreen is enabled.
+// TODO(crbug.com/778823): Remove this property.
 @property(nonatomic, weak) id<FullScreenControllerDelegate>
     fullScreenControllerDelegate;
+
 @property(nonatomic, readonly)
     OverscrollActionsController* overscrollActionsController;
 @property(nonatomic, weak) id<OverscrollActionsControllerDelegate>
@@ -188,6 +193,7 @@
 - (void)reloadWithUserAgentType:(web::UserAgentType)userAgentType;
 
 // Ensures the toolbar visibility matches |visible|.
+// TODO(crbug.com/778823): Remove this code.
 - (void)updateFullscreenWithToolbarVisible:(BOOL)visible;
 
 // Returns a snapshot of the current page, backed by disk so it can be purged
diff --git a/ios/chrome/browser/tabs/tab.mm b/ios/chrome/browser/tabs/tab.mm
index 64935b2..1c0e9cd 100644
--- a/ios/chrome/browser/tabs/tab.mm
+++ b/ios/chrome/browser/tabs/tab.mm
@@ -11,6 +11,7 @@
 #include <vector>
 
 #include "base/bind.h"
+#include "base/feature_list.h"
 #include "base/ios/block_types.h"
 #include "base/json/string_escape.h"
 #include "base/logging.h"
@@ -78,6 +79,7 @@
 #import "ios/chrome/browser/ui/commands/show_signin_command.h"
 #import "ios/chrome/browser/ui/downloads/download_manager_controller.h"
 #import "ios/chrome/browser/ui/fullscreen/fullscreen_controller.h"
+#import "ios/chrome/browser/ui/fullscreen/fullscreen_features.h"
 #import "ios/chrome/browser/ui/open_in_controller.h"
 #import "ios/chrome/browser/ui/overscroll_actions/overscroll_actions_controller.h"
 #include "ios/chrome/browser/ui/ui_util.h"
@@ -422,7 +424,9 @@
   if (_isPrerenderTab)
     return;
 
-  [_fullScreenController moveContentBelowHeader];
+  if (!base::FeatureList::IsEnabled(features::kNewFullscreen)) {
+    [_fullScreenController moveContentBelowHeader];
+  }
 
   // If the page has finished loading, take a snapshot.  If the page is still
   // loading, do nothing, as CRWWebController will automatically take a
@@ -438,6 +442,7 @@
 
 - (void)setFullScreenControllerDelegate:
     (id<FullScreenControllerDelegate>)fullScreenControllerDelegate {
+  DCHECK(!base::FeatureList::IsEnabled(features::kNewFullscreen));
   if (fullScreenControllerDelegate == fullScreenControllerDelegate_)
     return;
   // Lazily create a FullScreenController.
@@ -517,7 +522,6 @@
 
 - (void)webStateDestroyed:(web::WebState*)webState {
   DCHECK_EQ(_webStateImpl, webState);
-  self.fullScreenControllerDelegate = nil;
   self.overscrollActionsControllerDelegate = nil;
   self.passKitDialogProvider = nil;
   self.snapshotOverlayProvider = nil;
@@ -526,15 +530,20 @@
 
   [_openInController detachFromWebController];
   _openInController = nil;
-  if (_fullScreenController)
-    [self.webController removeObserver:_fullScreenController];
-  [_fullScreenController invalidate];
-  _fullScreenController = nil;
   if (_overscrollActionsController)
     [self.webController removeObserver:_overscrollActionsController];
   [_overscrollActionsController invalidate];
   _overscrollActionsController = nil;
 
+  // Clean up legacy fullscreen.
+  if (!base::FeatureList::IsEnabled(features::kNewFullscreen)) {
+    self.fullScreenControllerDelegate = nil;
+    if (_fullScreenController)
+      [self.webController removeObserver:_fullScreenController];
+    [_fullScreenController invalidate];
+    _fullScreenController = nil;
+  }
+
   // Cancel any queued dialogs.
   [self.dialogDelegate cancelDialogForTab:self];
 
@@ -771,15 +780,18 @@
 #pragma mark FindInPageControllerDelegate
 
 - (void)willAdjustScrollPosition {
-  // Skip the next attempt to correct the scroll offset for the toolbar height.
-  // Used when programatically scrolling down the y offset.
-  [_fullScreenController shouldSkipNextScrollOffsetForHeader];
+  if (!base::FeatureList::IsEnabled(features::kNewFullscreen)) {
+    // Skip the next attempt to correct the scroll offset for the toolbar
+    // height.  Used when programatically scrolling down the y offset.
+    [_fullScreenController shouldSkipNextScrollOffsetForHeader];
+  }
 }
 
 #pragma mark -
 #pragma mark FullScreen
 
 - (void)updateFullscreenWithToolbarVisible:(BOOL)visible {
+  DCHECK(!base::FeatureList::IsEnabled(features::kNewFullscreen));
   [_fullScreenController moveHeaderToRestingPosition:visible];
 }
 
@@ -871,7 +883,8 @@
 
 - (void)webState:(web::WebState*)webState
     didStartNavigation:(web::NavigationContext*)navigation {
-  if (!navigation->IsSameDocument()) {
+  if (!navigation->IsSameDocument() &&
+      !base::FeatureList::IsEnabled(features::kNewFullscreen)) {
     // Move the toolbar to visible during page load.
     [_fullScreenController disableFullScreen];
   }
@@ -893,10 +906,12 @@
 - (void)webState:(web::WebState*)webState
     didCommitNavigationWithDetails:(const web::LoadCommittedDetails&)details {
   DCHECK([self navigationManager]);
-  // |webWillAddPendingURL:transition:| is not called for native page loads.
-  // TODO(crbug.com/381201): Move this call there once that bug is fixed so that
-  // |disableFullScreen| is called only from one place.
-  [_fullScreenController disableFullScreen];
+  if (!base::FeatureList::IsEnabled(features::kNewFullscreen)) {
+    // |webWillAddPendingURL:transition:| is not called for native page loads.
+    // TODO(crbug.com/381201): Move this call there once that bug is fixed so
+    // that |disableFullScreen| is called only from one place.
+    [_fullScreenController disableFullScreen];
+  }
   GURL lastCommittedURL = webState->GetLastCommittedURL();
 
   if (_parentTabModel) {
@@ -953,7 +968,7 @@
     lastCommittedURL = lastCommittedItem->GetVirtualURL();
   }
   [_webControllerSnapshotHelper setSnapshotCoalescingEnabled:YES];
-  if (!loadSuccess)
+  if (!base::FeatureList::IsEnabled(features::kNewFullscreen) && !loadSuccess)
     [_fullScreenController disableFullScreen];
   [self recordInterfaceOrientation];
   navigation_metrics::RecordMainFrameNavigation(
@@ -1003,9 +1018,11 @@
 }
 
 - (void)webStateDidStopLoading:(web::WebState*)webState {
-  // This is the maximum that a page will ever load and it is safe to allow
-  // fullscreen mode.
-  [_fullScreenController enableFullScreen];
+  if (!base::FeatureList::IsEnabled(features::kNewFullscreen)) {
+    // This is the maximum that a page will ever load and it is safe to allow
+    // fullscreen mode.
+    [_fullScreenController enableFullScreen];
+  }
   [_parentTabModel notifyTabChanged:self];
 }
 
@@ -1155,12 +1172,14 @@
 }
 
 - (void)webStateDidChangeVisibleSecurityState:(web::WebState*)webState {
-  // Disable fullscreen if SSL cert is invalid.
-  web::NavigationItem* item = [self navigationManager]->GetTransientItem();
-  if (item) {
-    web::SecurityStyle securityStyle = item->GetSSL().security_style;
-    if (securityStyle == web::SECURITY_STYLE_AUTHENTICATION_BROKEN) {
-      [_fullScreenController disableFullScreen];
+  if (!base::FeatureList::IsEnabled(features::kNewFullscreen)) {
+    // Disable fullscreen if SSL cert is invalid.
+    web::NavigationItem* item = [self navigationManager]->GetTransientItem();
+    if (item) {
+      web::SecurityStyle securityStyle = item->GetSSL().security_style;
+      if (securityStyle == web::SECURITY_STYLE_AUTHENTICATION_BROKEN) {
+        [_fullScreenController disableFullScreen];
+      }
     }
   }
 
@@ -1170,9 +1189,12 @@
 
 - (void)renderProcessGoneForWebState:(web::WebState*)webState {
   DCHECK(webState == _webStateImpl);
-  UIApplicationState state = [UIApplication sharedApplication].applicationState;
-  if (webState->IsVisible() && state == UIApplicationStateActive) {
-    [_fullScreenController disableFullScreen];
+  if (!base::FeatureList::IsEnabled(features::kNewFullscreen)) {
+    UIApplicationState state =
+        [UIApplication sharedApplication].applicationState;
+    if (webState->IsVisible() && state == UIApplicationStateActive) {
+      [_fullScreenController disableFullScreen];
+    }
   }
   [self.dialogDelegate cancelDialogForTab:self];
 }
diff --git a/ios/chrome/browser/translate/chrome_ios_translate_client.mm b/ios/chrome/browser/translate/chrome_ios_translate_client.mm
index ff4509a..fe1fe73 100644
--- a/ios/chrome/browser/translate/chrome_ios_translate_client.mm
+++ b/ios/chrome/browser/translate/chrome_ios_translate_client.mm
@@ -60,7 +60,7 @@
           translate::TranslateRankerFactory::GetForBrowserState(
               ios::ChromeBrowserState::FromBrowserState(
                   web_state->GetBrowserState())),
-          LanguageModelFactory::GetInstance()->GetForBrowserState(
+          LanguageModelFactory::GetForBrowserState(
               ios::ChromeBrowserState::FromBrowserState(
                   web_state->GetBrowserState())))),
       translate_driver_(web_state,
diff --git a/ios/chrome/browser/ui/BUILD.gn b/ios/chrome/browser/ui/BUILD.gn
index d5fc3245..b9ae08e 100644
--- a/ios/chrome/browser/ui/BUILD.gn
+++ b/ios/chrome/browser/ui/BUILD.gn
@@ -60,7 +60,7 @@
     "//base",
     "//base:i18n",
     "//ios/chrome/browser",
-    "//ios/chrome/browser/ui/toolbar:toolbar_base_feature",
+    "//ios/chrome/browser/ui/toolbar/public:toolbar_base_feature",
     "//ios/web",
     "//ui/base",
     "//ui/gfx",
@@ -310,10 +310,12 @@
     "//ios/chrome/browser/ui/find_bar",
     "//ios/chrome/browser/ui/first_run",
     "//ios/chrome/browser/ui/fullscreen",
+    "//ios/chrome/browser/ui/fullscreen:legacy_fullscreen",
     "//ios/chrome/browser/ui/history",
     "//ios/chrome/browser/ui/history_popup:coordinator",
     "//ios/chrome/browser/ui/history_popup/requirements",
     "//ios/chrome/browser/ui/keyboard",
+    "//ios/chrome/browser/ui/main:feature_flags",
     "//ios/chrome/browser/ui/ntp",
     "//ios/chrome/browser/ui/ntp:ntp_controller",
     "//ios/chrome/browser/ui/ntp:ntp_internal",
@@ -335,7 +337,7 @@
     "//ios/chrome/browser/ui/tab_switcher",
     "//ios/chrome/browser/ui/tabs:coordinator",
     "//ios/chrome/browser/ui/tabs/requirements",
-    "//ios/chrome/browser/ui/toolbar:toolbar_base_feature",
+    "//ios/chrome/browser/ui/toolbar/public:toolbar_base_feature",
     "//ios/chrome/browser/ui/tools_menu",
     "//ios/chrome/browser/ui/tools_menu:configuration",
     "//ios/chrome/browser/ui/util",
diff --git a/ios/chrome/browser/ui/DEPS b/ios/chrome/browser/ui/DEPS
index 08f0755..b91362ad 100644
--- a/ios/chrome/browser/ui/DEPS
+++ b/ios/chrome/browser/ui/DEPS
@@ -14,23 +14,6 @@
     "+ios/web/web_state/web_state_impl.h",
   ],
 
-  # TODO(crbug.com/620139): Remove this exception.
-  "^fullscreen_controller\.mm$": [
-    "+ios/web/web_state/ui/crw_web_controller.h",
-  ],
-
-  # TODO(crbug.com/620143): Remove these exceptions.
-  "^fullscreen_controller_unittest\.mm$": [
-    "+ios/web/web_state/ui/crw_web_view_proxy_impl.h",
-    "+ios/web/web_state/ui/crw_web_controller.h",
-  ],
-
-  # TODO(crbug.com/620139): Remove these exceptions.
-  "^fullscreen_controller_unittest\.mm$": [
-    "+ios/web/web_state/ui/crw_web_view_proxy_impl.h",
-    "+ios/web/web_state/ui/crw_web_controller.h",
-  ],
-
   # TODO(crbug.com/620147): Remove these exceptions.
   "^open_in_controller\.mm$": [
     "+ios/web/web_state/ui/crw_web_controller.h",
diff --git a/ios/chrome/browser/ui/activity_services/OWNERS b/ios/chrome/browser/ui/activity_services/OWNERS
index c85e66a..241c424 100644
--- a/ios/chrome/browser/ui/activity_services/OWNERS
+++ b/ios/chrome/browser/ui/activity_services/OWNERS
@@ -1,4 +1,4 @@
-jif@chromium.org
+pkl@chromium.org
 
 # TEAM: ios-directory-owners@chromium.org
 # OS: iOS
diff --git a/ios/chrome/browser/ui/authentication/signed_in_accounts_view_controller.mm b/ios/chrome/browser/ui/authentication/signed_in_accounts_view_controller.mm
index 4d7095a..298b57b 100644
--- a/ios/chrome/browser/ui/authentication/signed_in_accounts_view_controller.mm
+++ b/ios/chrome/browser/ui/authentication/signed_in_accounts_view_controller.mm
@@ -379,7 +379,8 @@
 
 - (void)onSecondaryButtonPressed:(id)sender {
   [self dismiss];
-  [self.dispatcher showAccountsSettings];
+  [self.dispatcher
+      showAccountsSettingsFromViewController:self.presentingViewController];
 }
 
 #pragma mark OAuth2TokenServiceObserverBridgeDelegate
diff --git a/ios/chrome/browser/ui/bookmarks/BUILD.gn b/ios/chrome/browser/ui/bookmarks/BUILD.gn
index 6b13e4f6..aea3e2a 100644
--- a/ios/chrome/browser/ui/bookmarks/BUILD.gn
+++ b/ios/chrome/browser/ui/bookmarks/BUILD.gn
@@ -200,7 +200,7 @@
     "//ios/chrome/browser/ui/authentication:eg_test_support",
     "//ios/chrome/browser/ui/bookmarks:bookmarks",
     "//ios/chrome/browser/ui/commands",
-    "//ios/chrome/browser/ui/toolbar",
+    "//ios/chrome/browser/ui/toolbar/public",
     "//ios/chrome/browser/ui/tools_menu",
     "//ios/chrome/test/app:test_support",
     "//ios/chrome/test/earl_grey:test_support",
diff --git a/ios/chrome/browser/ui/bookmarks/bookmarks_egtest.mm b/ios/chrome/browser/ui/bookmarks/bookmarks_egtest.mm
index f35a9f80..6a7a1cd 100644
--- a/ios/chrome/browser/ui/bookmarks/bookmarks_egtest.mm
+++ b/ios/chrome/browser/ui/bookmarks/bookmarks_egtest.mm
@@ -21,7 +21,7 @@
 #include "ios/chrome/browser/pref_names.h"
 #import "ios/chrome/browser/ui/authentication/signin_earlgrey_utils.h"
 #import "ios/chrome/browser/ui/authentication/signin_promo_view.h"
-#import "ios/chrome/browser/ui/toolbar/toolbar_controller_constants.h"
+#import "ios/chrome/browser/ui/toolbar/public/toolbar_controller_constants.h"
 #include "ios/chrome/browser/ui/tools_menu/tools_menu_constants.h"
 #import "ios/chrome/browser/ui/uikit_ui_util.h"
 #include "ios/chrome/grit/ios_strings.h"
diff --git a/ios/chrome/browser/ui/bookmarks/cells/bookmark_table_cell.mm b/ios/chrome/browser/ui/bookmarks/cells/bookmark_table_cell.mm
index ea9afe1c..ad5f6df1 100644
--- a/ios/chrome/browser/ui/bookmarks/cells/bookmark_table_cell.mm
+++ b/ios/chrome/browser/ui/bookmarks/cells/bookmark_table_cell.mm
@@ -200,6 +200,22 @@
   [super prepareForReuse];
 }
 
+#pragma mark - Persist placeholder background color
+
+- (void)setHighlighted:(BOOL)highlighted animated:(BOOL)animated {
+  // Prevent placeholderLabel's background color from being cleared.
+  UIColor* backgroundColor = self.placeholderLabel.backgroundColor;
+  [super setHighlighted:highlighted animated:animated];
+  self.placeholderLabel.backgroundColor = backgroundColor;
+}
+
+- (void)setSelected:(BOOL)selected animated:(BOOL)animated {
+  // Prevent placeholderLabel's background color from being cleared.
+  UIColor* backgroundColor = self.placeholderLabel.backgroundColor;
+  [super setSelected:selected animated:animated];
+  self.placeholderLabel.backgroundColor = backgroundColor;
+}
+
 #pragma mark - UITextFieldDelegate
 
 // This method hides the keyboard when the return key is pressed.
diff --git a/ios/chrome/browser/ui/browser_view_controller.h b/ios/chrome/browser/ui/browser_view_controller.h
index de84d23..cfccd32 100644
--- a/ios/chrome/browser/ui/browser_view_controller.h
+++ b/ios/chrome/browser/ui/browser_view_controller.h
@@ -26,6 +26,7 @@
 @class Tab;
 @class TabModel;
 @protocol TabStripFoldAnimation;
+@protocol ToolbarSnapshotProviding;
 
 namespace ios {
 class ChromeBrowserState;
@@ -33,8 +34,7 @@
 
 // The top-level view controller for the browser UI. Manages other controllers
 // which implement the interface.
-@interface BrowserViewController : UIViewController<SideSwipeControllerDelegate,
-                                                    ToolbarOwner,
+@interface BrowserViewController : UIViewController<ToolbarOwner,
                                                     UrlLoader,
                                                     VoiceSearchPresenter,
                                                     WebToolbarDelegate>
@@ -84,6 +84,9 @@
 // Returns the ios::ChromeBrowserState passed to the initializer.
 @property(nonatomic, assign, readonly) ios::ChromeBrowserState* browserState;
 
+@property(nonatomic, strong, readonly) id<ToolbarSnapshotProviding>
+    toolbarSnapshotProvider;
+
 // Whether the receiver is currently the primary BVC.
 - (void)setPrimary:(BOOL)primary;
 
diff --git a/ios/chrome/browser/ui/browser_view_controller.mm b/ios/chrome/browser/ui/browser_view_controller.mm
index f58c486..257b863 100644
--- a/ios/chrome/browser/ui/browser_view_controller.mm
+++ b/ios/chrome/browser/ui/browser_view_controller.mm
@@ -136,10 +136,12 @@
 #import "ios/chrome/browser/ui/find_bar/find_bar_controller_ios.h"
 #import "ios/chrome/browser/ui/first_run/welcome_to_chrome_view_controller.h"
 #import "ios/chrome/browser/ui/fullscreen/fullscreen_controller.h"
+#import "ios/chrome/browser/ui/fullscreen/fullscreen_features.h"
 #import "ios/chrome/browser/ui/history_popup/requirements/tab_history_presentation.h"
 #import "ios/chrome/browser/ui/history_popup/tab_history_legacy_coordinator.h"
 #import "ios/chrome/browser/ui/key_commands_provider.h"
 #import "ios/chrome/browser/ui/location_bar_notification_names.h"
+#import "ios/chrome/browser/ui/main/main_feature_flags.h"
 #import "ios/chrome/browser/ui/ntp/modal_ntp.h"
 #import "ios/chrome/browser/ui/ntp/new_tab_page_controller.h"
 #import "ios/chrome/browser/ui/ntp/recent_tabs/recent_tabs_handset_coordinator.h"
@@ -166,10 +168,11 @@
 #import "ios/chrome/browser/ui/tabs/requirements/tab_strip_constants.h"
 #import "ios/chrome/browser/ui/tabs/requirements/tab_strip_presentation.h"
 #import "ios/chrome/browser/ui/tabs/tab_strip_legacy_coordinator.h"
-#import "ios/chrome/browser/ui/toolbar/toolbar_controller_base_feature.h"
+#import "ios/chrome/browser/ui/toolbar/public/toolbar_controller_base_feature.h"
 #include "ios/chrome/browser/ui/toolbar/toolbar_coordinator.h"
 #include "ios/chrome/browser/ui/toolbar/toolbar_model_delegate_ios.h"
 #include "ios/chrome/browser/ui/toolbar/toolbar_model_ios.h"
+#import "ios/chrome/browser/ui/toolbar/toolbar_snapshot_providing.h"
 #import "ios/chrome/browser/ui/toolbar/web_toolbar_controller.h"
 #import "ios/chrome/browser/ui/tools_menu/tools_menu_configuration.h"
 #import "ios/chrome/browser/ui/tools_menu/tools_menu_view_item.h"
@@ -386,6 +389,7 @@
                                     PreloadControllerDelegate,
                                     QRScannerPresenting,
                                     RepostFormTabHelperDelegate,
+                                    SideSwipeControllerDelegate,
                                     SKStoreProductViewControllerDelegate,
                                     SnapshotOverlayProvider,
                                     StoreKitLauncher,
@@ -1089,6 +1093,10 @@
       _dispatcher);
 }
 
+- (id<ToolbarSnapshotProviding>)toolbarSnapshotProvider {
+  return _toolbarCoordinator;
+}
+
 - (void)setActive:(BOOL)active {
   if (_active == active) {
     return;
@@ -1162,6 +1170,7 @@
         [[SideSwipeController alloc] initWithTabModel:_model
                                          browserState:_browserState];
     [_sideSwipeController setSnapshotDelegate:self];
+    _sideSwipeController.toolbarInteractionHandler = _toolbarCoordinator;
     [_sideSwipeController setSwipeDelegate:self];
     [_sideSwipeController setTabStripDelegate:self.tabStripCoordinator];
   }
@@ -1351,9 +1360,17 @@
 - (void)viewWillAppear:(BOOL)animated {
   [super viewWillAppear:animated];
 
-  // Reparent the toolbar if it's been relinquished.
-  if (_isToolbarControllerRelinquished)
-    [self reparentToolbarController];
+  // Reparent the toolbar if it's been relinquished.  If the tab switcher
+  // presentation experiment is enabled, only do this if the parent VC is not
+  // currently being presented.  Otherwise, reparenting here would remove the
+  // toolbar from the tab switcher while the switcher is in the process of
+  // animating.
+  if (_isToolbarControllerRelinquished) {
+    if (!TabSwitcherPresentsBVCEnabled() ||
+        (!self.beingPresented && !self.parentViewController.beingPresented)) {
+      [self reparentToolbarController];
+    }
+  }
 
   self.visible = YES;
 
@@ -1882,6 +1899,7 @@
       newToolbarModelIOSWithDelegate:_toolbarModelDelegate.get()]);
   _toolbarCoordinator =
       [[LegacyToolbarCoordinator alloc] initWithBaseViewController:self];
+  _sideSwipeController.toolbarInteractionHandler = _toolbarCoordinator;
   _toolbarCoordinator.tabModel = _model;
   [_toolbarCoordinator
       setWebToolbar:[_dependencyFactory
@@ -2465,7 +2483,9 @@
   tab.dialogDelegate = self;
   tab.snapshotOverlayProvider = self;
   tab.passKitDialogProvider = self;
-  tab.fullScreenControllerDelegate = self;
+  if (!base::FeatureList::IsEnabled(features::kNewFullscreen)) {
+    tab.fullScreenControllerDelegate = self;
+  }
   if (!IsIPadIdiom()) {
     tab.overscrollActionsControllerDelegate = self;
   }
@@ -2507,7 +2527,9 @@
   tab.dialogDelegate = nil;
   tab.snapshotOverlayProvider = nil;
   tab.passKitDialogProvider = nil;
-  tab.fullScreenControllerDelegate = nil;
+  if (!base::FeatureList::IsEnabled(features::kNewFullscreen)) {
+    tab.fullScreenControllerDelegate = nil;
+  }
   if (!IsIPadIdiom()) {
     tab.overscrollActionsControllerDelegate = nil;
   }
@@ -4984,10 +5006,6 @@
   return _contentArea;
 }
 
-- (WebToolbarController*)toolbarController {
-  return _toolbarCoordinator.webToolbarController;
-}
-
 - (BOOL)preventSideSwipe {
   if ([_toolbarCoordinator toolsPopupController])
     return YES;
@@ -5303,7 +5321,7 @@
   signin_metrics::LogAccountReconcilorStateOnGaiaResponse(
       ios::AccountReconcilorFactory::GetForBrowserState(self.browserState)
           ->GetState());
-  [self.dispatcher showAccountsSettings];
+  [self.dispatcher showAccountsSettingsFromViewController:self];
 }
 
 - (void)onAddAccount {
diff --git a/ios/chrome/browser/ui/commands/application_commands.h b/ios/chrome/browser/ui/commands/application_commands.h
index 4c8717b..c2e44ff 100644
--- a/ios/chrome/browser/ui/commands/application_commands.h
+++ b/ios/chrome/browser/ui/commands/application_commands.h
@@ -17,8 +17,9 @@
 // may also be forwarded directly to a settings navigation controller.
 @protocol ApplicationSettingsCommands
 
-// Shows the accounts settings.
-- (void)showAccountsSettings;
+// Shows the accounts settings UI, presenting from |baseViewController|.
+- (void)showAccountsSettingsFromViewController:
+    (UIViewController*)baseViewController;
 
 // Shows the sync settings UI.
 - (void)showSyncSettings;
@@ -40,6 +41,7 @@
 // Dismisses all modal dialogs.
 - (void)dismissModalDialogs;
 
+// TODO(crbug.com/779791) : Do not pass baseViewController through dispatcher.
 // Shows the Settings UI, presenting from |baseViewController|.
 - (void)showSettingsFromViewController:(UIViewController*)baseViewController;
 
diff --git a/ios/chrome/browser/ui/content_suggestions/BUILD.gn b/ios/chrome/browser/ui/content_suggestions/BUILD.gn
index 4ca9efc..711bfc83 100644
--- a/ios/chrome/browser/ui/content_suggestions/BUILD.gn
+++ b/ios/chrome/browser/ui/content_suggestions/BUILD.gn
@@ -72,7 +72,7 @@
     "//ios/chrome/browser/ui/commands",
     "//ios/chrome/browser/ui/content_suggestions/cells:cells_ui",
     "//ios/chrome/browser/ui/ntp",
-    "//ios/chrome/browser/ui/toolbar",
+    "//ios/chrome/browser/ui/toolbar/public",
     "//ios/third_party/material_components_ios",
     "//mojo/common:common_custom_types",
     "//ui/base",
diff --git a/ios/chrome/browser/ui/content_suggestions/content_suggestions_collection_utils.mm b/ios/chrome/browser/ui/content_suggestions/content_suggestions_collection_utils.mm
index 9d52b05d..1a95893 100644
--- a/ios/chrome/browser/ui/content_suggestions/content_suggestions_collection_utils.mm
+++ b/ios/chrome/browser/ui/content_suggestions/content_suggestions_collection_utils.mm
@@ -9,7 +9,7 @@
 #include "components/strings/grit/components_strings.h"
 #import "ios/chrome/browser/ui/content_suggestions/cells/content_suggestions_most_visited_cell.h"
 #import "ios/chrome/browser/ui/ntp/new_tab_page_header_constants.h"
-#import "ios/chrome/browser/ui/toolbar/web_toolbar_controller_constants.h"
+#import "ios/chrome/browser/ui/toolbar/public/web_toolbar_controller_constants.h"
 #include "ios/chrome/browser/ui/ui_util.h"
 #include "ios/chrome/grit/ios_strings.h"
 #import "ios/third_party/material_components_ios/src/components/Typography/src/MaterialTypography.h"
diff --git a/ios/chrome/browser/ui/content_suggestions/ntp_home_egtest.mm b/ios/chrome/browser/ui/content_suggestions/ntp_home_egtest.mm
index b70cc01..48cfe68 100644
--- a/ios/chrome/browser/ui/content_suggestions/ntp_home_egtest.mm
+++ b/ios/chrome/browser/ui/content_suggestions/ntp_home_egtest.mm
@@ -22,6 +22,7 @@
 #import "ios/chrome/browser/ui/content_suggestions/ntp_home_provider_test_singleton.h"
 #import "ios/chrome/browser/ui/content_suggestions/ntp_home_test_utils.h"
 #include "ios/chrome/browser/ui/ui_util.h"
+#import "ios/chrome/browser/ui/uikit_ui_util.h"
 #include "ios/chrome/grit/ios_strings.h"
 #import "ios/chrome/test/app/chrome_test_util.h"
 #import "ios/chrome/test/app/history_test_util.h"
@@ -178,7 +179,9 @@
     EARL_GREY_TEST_DISABLED(@"Disabled for iPad due to device rotation bug.");
   }
   [[GREYUIThreadExecutor sharedInstance] drainUntilIdle];
-  CGFloat collectionWidth = CollectionView().bounds.size.width;
+  UIEdgeInsets safeArea = SafeAreaInsetsForView(CollectionView());
+  CGFloat collectionWidth =
+      CGRectGetWidth(UIEdgeInsetsInsetRect(CollectionView().bounds, safeArea));
   GREYAssertTrue(collectionWidth > 0, @"The collection width is nil.");
   CGFloat fakeOmniboxWidth = searchFieldWidth(collectionWidth);
 
@@ -190,7 +193,9 @@
                            errorOrNil:nil];
   [[GREYUIThreadExecutor sharedInstance] drainUntilIdle];
 
-  CGFloat collectionWidthAfterRotation = CollectionView().bounds.size.width;
+  safeArea = SafeAreaInsetsForView(CollectionView());
+  CGFloat collectionWidthAfterRotation =
+      CGRectGetWidth(UIEdgeInsetsInsetRect(CollectionView().bounds, safeArea));
   GREYAssertNotEqual(collectionWidth, collectionWidthAfterRotation,
                      @"The collection width has not changed.");
   fakeOmniboxWidth = searchFieldWidth(collectionWidthAfterRotation);
@@ -209,7 +214,9 @@
     EARL_GREY_TEST_DISABLED(@"Disabled for iPad due to device rotation bug.");
   }
   [[GREYUIThreadExecutor sharedInstance] drainUntilIdle];
-  CGFloat collectionWidth = CollectionView().bounds.size.width;
+  UIEdgeInsets safeArea = SafeAreaInsetsForView(CollectionView());
+  CGFloat collectionWidth =
+      CGRectGetWidth(UIEdgeInsetsInsetRect(CollectionView().bounds, safeArea));
   GREYAssertTrue(collectionWidth > 0, @"The collection width is nil.");
   CGFloat fakeOmniboxWidth = searchFieldWidth(collectionWidth);
 
@@ -228,7 +235,9 @@
                                    IDS_IOS_NAVIGATION_BAR_DONE_BUTTON)]
       performAction:grey_tap()];
 
-  CGFloat collectionWidthAfterRotation = CollectionView().bounds.size.width;
+  safeArea = SafeAreaInsetsForView(CollectionView());
+  CGFloat collectionWidthAfterRotation =
+      CGRectGetWidth(UIEdgeInsetsInsetRect(CollectionView().bounds, safeArea));
   GREYAssertNotEqual(collectionWidth, collectionWidthAfterRotation,
                      @"The collection width has not changed.");
   fakeOmniboxWidth = searchFieldWidth(collectionWidthAfterRotation);
diff --git a/ios/chrome/browser/ui/first_run/first_run_chrome_signin_view_controller.mm b/ios/chrome/browser/ui/first_run/first_run_chrome_signin_view_controller.mm
index 4940534..0639221 100644
--- a/ios/chrome/browser/ui/first_run/first_run_chrome_signin_view_controller.mm
+++ b/ios/chrome/browser/ui/first_run/first_run_chrome_signin_view_controller.mm
@@ -4,6 +4,7 @@
 
 #import "ios/chrome/browser/ui/first_run/first_run_chrome_signin_view_controller.h"
 
+#import "base/ios/block_types.h"
 #include "base/metrics/user_metrics.h"
 #include "components/signin/core/browser/signin_metrics.h"
 #include "ios/chrome/browser/browser_state/chrome_browser_state.h"
@@ -95,13 +96,15 @@
   return IsIPadIdiom() ? [super shouldAutorotate] : NO;
 }
 
-- (void)finishFirstRunAndDismiss {
+- (void)finishFirstRunAndDismissWithCompletion:(ProceduralBlock)completion {
   DCHECK(self.presentingViewController);
   FinishFirstRun(self.browserState, [_tabModel currentTab], _firstRunConfig,
                  self.dispatcher);
   [self.presentingViewController dismissViewControllerAnimated:YES
                                                     completion:^{
                                                       FirstRunDismissed();
+                                                      if (completion)
+                                                        completion();
                                                     }];
 }
 
@@ -121,7 +124,7 @@
 - (void)didSkipSignIn:(ChromeSigninViewController*)controller {
   DCHECK_EQ(self, controller);
   // User is done with First Run after explicit skip.
-  [self finishFirstRunAndDismiss];
+  [self finishFirstRunAndDismissWithCompletion:nil];
 }
 
 - (void)didFailSignIn:(ChromeSigninViewController*)controller {
@@ -157,10 +160,16 @@
   DCHECK_EQ(self, controller);
 
   // User is done with First Run after explicit sign-in accept.
-  [self finishFirstRunAndDismiss];
-  if (showAccountsSettings) {
-    [self.dispatcher showAccountsSettings];
-  }
+  // Save a reference to the presentingViewController since this view controller
+  // will be dismissed.
+  __weak UIViewController* baseViewController = self.presentingViewController;
+  __weak id<ApplicationCommands> weakDispatcher = self.dispatcher;
+  [self finishFirstRunAndDismissWithCompletion:^{
+    if (showAccountsSettings) {
+      [weakDispatcher
+          showAccountsSettingsFromViewController:baseViewController];
+    }
+  }];
 }
 
 #pragma mark ChromeSigninViewController
diff --git a/ios/chrome/browser/ui/fullscreen/BUILD.gn b/ios/chrome/browser/ui/fullscreen/BUILD.gn
index b906837..6aeee92 100644
--- a/ios/chrome/browser/ui/fullscreen/BUILD.gn
+++ b/ios/chrome/browser/ui/fullscreen/BUILD.gn
@@ -4,6 +4,19 @@
 
 source_set("fullscreen") {
   sources = [
+    "fullscreen_features.h",
+    "fullscreen_features.mm",
+  ]
+
+  configs += [ "//build/config/compiler:enable_arc" ]
+
+  deps = [
+    "//base",
+  ]
+}
+
+source_set("legacy_fullscreen") {
+  sources = [
     "fullscreen_controller.h",
     "fullscreen_controller.mm",
   ]
@@ -18,13 +31,13 @@
     "//ios/chrome/browser/ui/page_info:coordinator",
     "//ios/chrome/browser/ui/side_swipe",
     "//ios/chrome/browser/ui/tabs/requirements",
-    "//ios/chrome/browser/ui/toolbar",
+    "//ios/chrome/browser/ui/toolbar/public",
     "//ios/chrome/browser/ui/voice",
     "//ios/web",
   ]
 }
 
-source_set("unit_tests") {
+source_set("legacy_unit_tests") {
   testonly = true
   sources = [
     "fullscreen_controller_unittest.mm",
@@ -33,7 +46,7 @@
   configs += [ "//build/config/compiler:enable_arc" ]
 
   deps = [
-    ":fullscreen",
+    ":legacy_fullscreen",
     "//ios/web",
     "//ios/web/public",
     "//ios/web/public/test/fakes",
diff --git a/ios/chrome/browser/ui/fullscreen/DEPS b/ios/chrome/browser/ui/fullscreen/DEPS
new file mode 100644
index 0000000..de3f308
--- /dev/null
+++ b/ios/chrome/browser/ui/fullscreen/DEPS
@@ -0,0 +1,18 @@
+specific_include_rules = {
+  # TODO(crbug.com/620139): Remove this exception.
+  "^fullscreen_controller\.mm$": [
+    "+ios/web/web_state/ui/crw_web_controller.h",
+  ],
+
+  # TODO(crbug.com/620143): Remove these exceptions.
+  "^fullscreen_controller_unittest\.mm$": [
+    "+ios/web/web_state/ui/crw_web_view_proxy_impl.h",
+    "+ios/web/web_state/ui/crw_web_controller.h",
+  ],
+
+  # TODO(crbug.com/620139): Remove these exceptions.
+  "^fullscreen_controller_unittest\.mm$": [
+    "+ios/web/web_state/ui/crw_web_view_proxy_impl.h",
+    "+ios/web/web_state/ui/crw_web_controller.h",
+  ],
+}
diff --git a/ios/chrome/browser/ui/fullscreen/fullscreen_controller.mm b/ios/chrome/browser/ui/fullscreen/fullscreen_controller.mm
index 8e7f215..711dab3 100644
--- a/ios/chrome/browser/ui/fullscreen/fullscreen_controller.mm
+++ b/ios/chrome/browser/ui/fullscreen/fullscreen_controller.mm
@@ -14,7 +14,7 @@
 #import "ios/chrome/browser/ui/page_info/page_info_legacy_coordinator.h"
 #import "ios/chrome/browser/ui/side_swipe/side_swipe_controller.h"
 #import "ios/chrome/browser/ui/tabs/requirements/tab_strip_constants.h"
-#import "ios/chrome/browser/ui/toolbar/toolbar_controller_constants.h"
+#import "ios/chrome/browser/ui/toolbar/public/toolbar_controller_constants.h"
 #import "ios/chrome/browser/ui/voice/voice_search_notification_names.h"
 #include "ios/web/public/navigation_item.h"
 #import "ios/web/public/navigation_manager.h"
diff --git a/ios/chrome/browser/ui/fullscreen/fullscreen_features.h b/ios/chrome/browser/ui/fullscreen/fullscreen_features.h
new file mode 100644
index 0000000..6e5640a
--- /dev/null
+++ b/ios/chrome/browser/ui/fullscreen/fullscreen_features.h
@@ -0,0 +1,17 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef IOS_CHROME_BROWSER_UI_FULLSCREEN_FULLSCREEN_FEATURES_H_
+#define IOS_CHROME_BROWSER_UI_FULLSCREEN_FULLSCREEN_FEATURES_H_
+
+#include "base/feature_list.h"
+
+namespace features {
+
+// Used to control whether the new fullscreen implementation should be used.
+extern const base::Feature kNewFullscreen;
+
+}  // namespace features
+
+#endif  // IOS_CHROME_BROWSER_UI_FULLSCREEN_FULLSCREEN_FEATURES_H_
diff --git a/ios/chrome/browser/ui/fullscreen/fullscreen_features.mm b/ios/chrome/browser/ui/fullscreen/fullscreen_features.mm
new file mode 100644
index 0000000..f599f9b
--- /dev/null
+++ b/ios/chrome/browser/ui/fullscreen/fullscreen_features.mm
@@ -0,0 +1,16 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#import "ios/chrome/browser/ui/fullscreen/fullscreen_features.h"
+
+#if !defined(__has_feature) || !__has_feature(objc_arc)
+#error "This file requires ARC support."
+#endif
+
+namespace features {
+
+const base::Feature kNewFullscreen{"NewFullscreen",
+                                   base::FEATURE_DISABLED_BY_DEFAULT};
+
+}  // namespace features
diff --git a/ios/chrome/browser/ui/infobars/OWNERS b/ios/chrome/browser/ui/infobars/OWNERS
index c85e66a..b127701 100644
--- a/ios/chrome/browser/ui/infobars/OWNERS
+++ b/ios/chrome/browser/ui/infobars/OWNERS
@@ -1,4 +1,4 @@
-jif@chromium.org
+rohitrao@chromium.org
 
 # TEAM: ios-directory-owners@chromium.org
 # OS: iOS
diff --git a/ios/chrome/browser/ui/main/main_presenting_view_controller.h b/ios/chrome/browser/ui/main/main_presenting_view_controller.h
index 3c739dc..23310ae 100644
--- a/ios/chrome/browser/ui/main/main_presenting_view_controller.h
+++ b/ios/chrome/browser/ui/main/main_presenting_view_controller.h
@@ -18,6 +18,11 @@
 
 @property(nonatomic, readonly, weak) UIViewController<TabSwitcher>* tabSwitcher;
 
+// If this property is YES, calls to |showTabSwitcher:completion:| and
+// |showTabViewController:completion:| will present the given view controllers
+// without animation.  This should only be used by unittests.
+@property(nonatomic, readwrite, assign) BOOL animationsDisabledForTesting;
+
 @end
 
 #endif  // IOS_CHROME_BROWSER_UI_MAIN_MAIN_PRESENTING_VIEW_CONTROLLER_H_
diff --git a/ios/chrome/browser/ui/main/main_presenting_view_controller.mm b/ios/chrome/browser/ui/main/main_presenting_view_controller.mm
index d396b008..bada2705 100644
--- a/ios/chrome/browser/ui/main/main_presenting_view_controller.mm
+++ b/ios/chrome/browser/ui/main/main_presenting_view_controller.mm
@@ -6,6 +6,7 @@
 
 #import "base/logging.h"
 #import "ios/chrome/browser/ui/main/transitions/bvc_container_to_tab_switcher_animator.h"
+#import "ios/chrome/browser/ui/main/transitions/tab_switcher_to_bvc_container_animator.h"
 
 #if !defined(__has_feature) || !__has_feature(objc_arc)
 #error "This file requires ARC support."
@@ -79,6 +80,7 @@
 @end
 
 @implementation MainPresentingViewController
+@synthesize animationsDisabledForTesting = _animationsDisabledForTesting;
 @synthesize tabSwitcher = _tabSwitcher;
 @synthesize bvcContainer = _bvcContainer;
 
@@ -121,7 +123,8 @@
   if (self.bvcContainer) {
     self.bvcContainer.transitioningDelegate = self;
     self.bvcContainer = nil;
-    [super dismissViewControllerAnimated:YES completion:completion];
+    BOOL animated = !self.animationsDisabledForTesting;
+    [super dismissViewControllerAnimated:animated completion:completion];
   } else {
     if (completion) {
       completion();
@@ -145,8 +148,10 @@
 
   self.bvcContainer = [[BVCContainerViewController alloc] init];
   self.bvcContainer.currentBVC = viewController;
+  self.bvcContainer.transitioningDelegate = self;
+  BOOL animated = !self.animationsDisabledForTesting && self.tabSwitcher != nil;
   [super presentViewController:self.bvcContainer
-                      animated:(self.tabSwitcher != nil)
+                      animated:animated
                     completion:completion];
 }
 
@@ -189,6 +194,16 @@
 #pragma mark - Transitioning Delegate
 
 - (id<UIViewControllerAnimatedTransitioning>)
+animationControllerForPresentedController:(UIViewController*)presented
+                     presentingController:(UIViewController*)presenting
+                         sourceController:(UIViewController*)source {
+  TabSwitcherToBVCContainerAnimator* animator =
+      [[TabSwitcherToBVCContainerAnimator alloc] init];
+  animator.tabSwitcher = self.tabSwitcher;
+  return animator;
+}
+
+- (id<UIViewControllerAnimatedTransitioning>)
 animationControllerForDismissedController:(UIViewController*)dismissed {
   // Verify that the presenting and dismissed view controllers are of the
   // expected types.
diff --git a/ios/chrome/browser/ui/main/main_presenting_view_controller_unittest.mm b/ios/chrome/browser/ui/main/main_presenting_view_controller_unittest.mm
index f65ca671..c7a563a 100644
--- a/ios/chrome/browser/ui/main/main_presenting_view_controller_unittest.mm
+++ b/ios/chrome/browser/ui/main/main_presenting_view_controller_unittest.mm
@@ -22,6 +22,8 @@
  public:
   MainPresentingViewControllerTest() {
     main_view_controller_ = [[MainPresentingViewController alloc] init];
+    main_view_controller_.animationsDisabledForTesting = YES;
+
     SetRootViewController(main_view_controller_);
     CGRect windowRect = CGRectMake(0, 0, 200, 200);
     main_view_controller_.view.frame = windowRect;
diff --git a/ios/chrome/browser/ui/main/transitions/BUILD.gn b/ios/chrome/browser/ui/main/transitions/BUILD.gn
index 418a95c..9b3184a8 100644
--- a/ios/chrome/browser/ui/main/transitions/BUILD.gn
+++ b/ios/chrome/browser/ui/main/transitions/BUILD.gn
@@ -7,6 +7,8 @@
   sources = [
     "bvc_container_to_tab_switcher_animator.h",
     "bvc_container_to_tab_switcher_animator.mm",
+    "tab_switcher_to_bvc_container_animator.h",
+    "tab_switcher_to_bvc_container_animator.mm",
   ]
   deps = [
     "//base",
diff --git a/ios/chrome/browser/ui/main/transitions/bvc_container_to_tab_switcher_animator.mm b/ios/chrome/browser/ui/main/transitions/bvc_container_to_tab_switcher_animator.mm
index e6fac68..0e68776 100644
--- a/ios/chrome/browser/ui/main/transitions/bvc_container_to_tab_switcher_animator.mm
+++ b/ios/chrome/browser/ui/main/transitions/bvc_container_to_tab_switcher_animator.mm
@@ -66,8 +66,9 @@
 #pragma mark - TabSwitcherAnimationDelegate
 
 - (void)tabSwitcherPresentationAnimationDidEnd:(id<TabSwitcher>)tabSwitcher {
-  // Calling |completeTransition:| seems to deallocate |self|, so save any
-  // needed variables here.
+  // Calling |completeTransition:| seems to deallocate |self|, so make any
+  // necessary changes to |self| here, and be sure not to access |self| after
+  // the call to |completeTransition:|.
   id<UIViewControllerContextTransitioning> transitionContext =
       self.transitionContext;
   self.tabSwitcher = nil;
@@ -78,4 +79,10 @@
   [transitionContext completeTransition:!wasCancelled];
 }
 
+- (void)tabSwitcherDismissalAnimationDidEnd:(id<TabSwitcher>)tabSwitcher {
+  // This animator does not expect to participate in dismissal animations, so it
+  // is an error if this method ever gets called.
+  NOTREACHED();
+}
+
 @end
diff --git a/ios/chrome/browser/ui/main/transitions/tab_switcher_to_bvc_container_animator.h b/ios/chrome/browser/ui/main/transitions/tab_switcher_to_bvc_container_animator.h
new file mode 100644
index 0000000..4f351ca
--- /dev/null
+++ b/ios/chrome/browser/ui/main/transitions/tab_switcher_to_bvc_container_animator.h
@@ -0,0 +1,23 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef IOS_CHROME_BROWSER_UI_MAIN_TRANSITIONS_TAB_SWITCHER_TO_BVC_CONTAINER_ANIMATOR_H_
+#define IOS_CHROME_BROWSER_UI_MAIN_TRANSITIONS_TAB_SWITCHER_TO_BVC_CONTAINER_ANIMATOR_H_
+
+#import <UIKit/UIKit.h>
+
+@protocol TabSwitcher;
+
+// This class provides an animator that can animate the transition from the tab
+// switcher to the BVC container.
+@interface TabSwitcherToBVCContainerAnimator
+    : NSObject<UIViewControllerAnimatedTransitioning>
+
+// The TabSwitcher to animate.
+@property(nonatomic, readwrite, weak)
+    UIViewController<TabSwitcher>* tabSwitcher;
+
+@end
+
+#endif  // IOS_CHROME_BROWSER_UI_MAIN_TRANSITIONS_TAB_SWITCHER_TO_BVC_CONTAINER_ANIMATOR_H_
diff --git a/ios/chrome/browser/ui/main/transitions/tab_switcher_to_bvc_container_animator.mm b/ios/chrome/browser/ui/main/transitions/tab_switcher_to_bvc_container_animator.mm
new file mode 100644
index 0000000..5977983
--- /dev/null
+++ b/ios/chrome/browser/ui/main/transitions/tab_switcher_to_bvc_container_animator.mm
@@ -0,0 +1,92 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#import "ios/chrome/browser/ui/main/transitions/tab_switcher_to_bvc_container_animator.h"
+
+#import "base/mac/foundation_util.h"
+#import "ios/chrome/browser/ui/tab_switcher/tab_switcher.h"
+
+#if !defined(__has_feature) || !__has_feature(objc_arc)
+#error "This file requires ARC support."
+#endif
+
+@interface TabSwitcherToBVCContainerAnimator ()<TabSwitcherAnimationDelegate>
+
+@property(nonatomic, readwrite, weak) id<UIViewControllerContextTransitioning>
+    transitionContext;
+
+@end
+
+@implementation TabSwitcherToBVCContainerAnimator
+
+@synthesize tabSwitcher = _tabSwitcher;
+@synthesize transitionContext = _transitionContext;
+
+- (NSTimeInterval)transitionDuration:
+    (id<UIViewControllerContextTransitioning>)transitionContext {
+  // This value is arbitrary, chosen to roughly match the visual length of the
+  // stack view animations.  The returned value does not appear to be used
+  // anywhere.  The actual transition does not complete until
+  // |tabSwitcherDismissalAnimationDidEnd:| is called, which happens as a
+  // result of a CoreAnimation completion block.
+  return 0.25;
+}
+
+// Tab switcher dismissal animations are currently driven by the tab switcher
+// itself.  MainController and this animator object are notified of progress
+// through delegate callbacks, but they do not directly participate in the
+// animation.  As a result, this animator is largely along for the ride.  It
+// does not initiate or control any animations, and its main responsibility is
+// to call |completeTransition| when the tab switcher is finished animating.
+- (void)animateTransition:
+    (id<UIViewControllerContextTransitioning>)transitionContext {
+  UIViewController* fromViewController = [transitionContext
+      viewControllerForKey:UITransitionContextFromViewControllerKey];
+  UIViewController* toViewController = [transitionContext
+      viewControllerForKey:UITransitionContextToViewControllerKey];
+
+  UIView* containerView = transitionContext.containerView;
+  UIView* fromView =
+      [transitionContext viewForKey:UITransitionContextFromViewKey];
+  UIView* toView = [transitionContext viewForKey:UITransitionContextToViewKey];
+  fromView.frame =
+      [transitionContext initialFrameForViewController:fromViewController];
+  toView.frame =
+      [transitionContext finalFrameForViewController:toViewController];
+
+  // This animator is responsible for adding the incoming view to the
+  // containerView for the presentation/dismissal.  Since the animations run in
+  // the tab switcher's view, order the subviews to ensure that the tab
+  // switcher's view remains on top.
+  [containerView addSubview:toView];
+  [containerView sendSubviewToBack:toView];
+
+  DCHECK_EQ(fromViewController, self.tabSwitcher.parentViewController);
+  self.tabSwitcher.animationDelegate = self;
+  self.transitionContext = transitionContext;
+}
+
+#pragma mark - TabSwitcherAnimationDelegate
+
+- (void)tabSwitcherPresentationAnimationDidEnd:(id<TabSwitcher>)tabSwitcher {
+  // This animator does not expect to participate in presentation animations, so
+  // it is an error if this method ever gets called.
+  NOTREACHED();
+}
+
+- (void)tabSwitcherDismissalAnimationDidEnd:(id<TabSwitcher>)tabSwitcher {
+  // Calling |completeTransition:| seems to deallocate |self|, so make any
+  // necessary changes to |self| here, and be sure not to access |self| after
+  // the call to |completeTransition:|.
+  id<UIViewControllerContextTransitioning> transitionContext =
+      self.transitionContext;
+  self.tabSwitcher = nil;
+  self.transitionContext = nil;
+
+  tabSwitcher.animationDelegate = nil;
+  BOOL wasCancelled = [transitionContext transitionWasCancelled];
+  [transitionContext completeTransition:!wasCancelled];
+}
+
+@end
diff --git a/ios/chrome/browser/ui/ntp/BUILD.gn b/ios/chrome/browser/ui/ntp/BUILD.gn
index 0b0da5e..884afb7b 100644
--- a/ios/chrome/browser/ui/ntp/BUILD.gn
+++ b/ios/chrome/browser/ui/ntp/BUILD.gn
@@ -35,7 +35,8 @@
     "//ios/chrome/browser/ui/favicon:favicon_ui",
     "//ios/chrome/browser/ui/toolbar",
     "//ios/chrome/browser/ui/toolbar:resource_macros",
-    "//ios/chrome/browser/ui/toolbar:toolbar_base_feature",
+    "//ios/chrome/browser/ui/toolbar/public",
+    "//ios/chrome/browser/ui/toolbar/public:toolbar_base_feature",
     "//ios/chrome/common",
     "//ui/base",
   ]
diff --git a/ios/chrome/browser/ui/ntp/new_tab_page_header_view.mm b/ios/chrome/browser/ui/ntp/new_tab_page_header_view.mm
index 43d27a83..e6efdaf 100644
--- a/ios/chrome/browser/ui/ntp/new_tab_page_header_view.mm
+++ b/ios/chrome/browser/ui/ntp/new_tab_page_header_view.mm
@@ -12,8 +12,8 @@
 #import "ios/chrome/browser/ui/ntp/google_landing_data_source.h"
 #import "ios/chrome/browser/ui/ntp/new_tab_page_header_constants.h"
 #import "ios/chrome/browser/ui/ntp/new_tab_page_toolbar_controller.h"
-#import "ios/chrome/browser/ui/toolbar/toolbar_controller_base_feature.h"
-#import "ios/chrome/browser/ui/toolbar/toolbar_utils.h"
+#import "ios/chrome/browser/ui/toolbar/public/toolbar_controller_base_feature.h"
+#import "ios/chrome/browser/ui/toolbar/public/toolbar_utils.h"
 #import "ios/chrome/browser/ui/uikit_ui_util.h"
 #import "ios/chrome/common/material_timing.h"
 #include "ios/chrome/grit/ios_theme_resources.h"
@@ -148,8 +148,8 @@
                      forOffset:(CGFloat)offset
                    screenWidth:(CGFloat)screenWidth
                 safeAreaInsets:(UIEdgeInsets)safeAreaInsets {
-  CGFloat contentWidth =
-      MAX(0, screenWidth - safeAreaInsets.left - safeAreaInsets.right);
+  CGFloat contentWidth = std::max<CGFloat>(
+      0, screenWidth - safeAreaInsets.left - safeAreaInsets.right);
   // The scroll offset at which point searchField's frame should stop growing.
   CGFloat maxScaleOffset =
       self.frame.size.height - ntp_header::kMinHeaderHeight;
diff --git a/ios/chrome/browser/ui/ntp/new_tab_page_toolbar_controller.mm b/ios/chrome/browser/ui/ntp/new_tab_page_toolbar_controller.mm
index dbc0a3a..d17080b 100644
--- a/ios/chrome/browser/ui/ntp/new_tab_page_toolbar_controller.mm
+++ b/ios/chrome/browser/ui/ntp/new_tab_page_toolbar_controller.mm
@@ -14,8 +14,8 @@
 #import "ios/chrome/browser/ui/ntp/google_landing_data_source.h"
 #import "ios/chrome/browser/ui/rtl_geometry.h"
 #import "ios/chrome/browser/ui/toolbar/omnibox_focuser.h"
+#import "ios/chrome/browser/ui/toolbar/public/toolbar_controller_constants.h"
 #import "ios/chrome/browser/ui/toolbar/toolbar_controller+protected.h"
-#import "ios/chrome/browser/ui/toolbar/toolbar_controller_constants.h"
 #include "ios/chrome/browser/ui/toolbar/toolbar_resource_macros.h"
 #import "ios/chrome/browser/ui/toolbar/web_toolbar_delegate.h"
 #import "ios/chrome/browser/ui/uikit_ui_util.h"
diff --git a/ios/chrome/browser/ui/ntp/recent_tabs/OWNERS b/ios/chrome/browser/ui/ntp/recent_tabs/OWNERS
index c85e66a..f192143 100644
--- a/ios/chrome/browser/ui/ntp/recent_tabs/OWNERS
+++ b/ios/chrome/browser/ui/ntp/recent_tabs/OWNERS
@@ -1,4 +1,4 @@
-jif@chromium.org
+gambard@chromium.org
 
 # TEAM: ios-directory-owners@chromium.org
 # OS: iOS
diff --git a/ios/chrome/browser/ui/omnibox/chrome_omnibox_client_ios.h b/ios/chrome/browser/ui/omnibox/chrome_omnibox_client_ios.h
index 5a24eb6..a5e3f17 100644
--- a/ios/chrome/browser/ui/omnibox/chrome_omnibox_client_ios.h
+++ b/ios/chrome/browser/ui/omnibox/chrome_omnibox_client_ios.h
@@ -64,7 +64,7 @@
   gfx::Image GetFavicon() const override;
   void OnTextChanged(const AutocompleteMatch& current_match,
                      bool user_input_in_progress,
-                     base::string16& user_text,
+                     const base::string16& user_text,
                      const AutocompleteResult& result,
                      bool is_popup_open,
                      bool has_focus) override;
diff --git a/ios/chrome/browser/ui/omnibox/chrome_omnibox_client_ios.mm b/ios/chrome/browser/ui/omnibox/chrome_omnibox_client_ios.mm
index 6a716b4..b4fa58d 100644
--- a/ios/chrome/browser/ui/omnibox/chrome_omnibox_client_ios.mm
+++ b/ios/chrome/browser/ui/omnibox/chrome_omnibox_client_ios.mm
@@ -216,7 +216,7 @@
 void ChromeOmniboxClientIOS::OnTextChanged(
     const AutocompleteMatch& current_match,
     bool user_input_in_progress,
-    base::string16& user_text,
+    const base::string16& user_text,
     const AutocompleteResult& result,
     bool is_popup_open,
     bool has_focus) {}
diff --git a/ios/chrome/browser/ui/overscroll_actions/BUILD.gn b/ios/chrome/browser/ui/overscroll_actions/BUILD.gn
index dee9b42..0ffb5f9 100644
--- a/ios/chrome/browser/ui/overscroll_actions/BUILD.gn
+++ b/ios/chrome/browser/ui/overscroll_actions/BUILD.gn
@@ -26,10 +26,11 @@
     "//ios/chrome/browser/ui/history_popup/requirements",
     "//ios/chrome/browser/ui/page_info:coordinator",
     "//ios/chrome/browser/ui/static_content",
-    "//ios/chrome/browser/ui/toolbar",
+    "//ios/chrome/browser/ui/toolbar/public",
     "//ios/chrome/browser/ui/util",
     "//ios/chrome/browser/ui/voice",
     "//ios/web",
+    "//ui/gfx",
   ]
   allow_circular_includes_from = [ "//ios/chrome/browser/ui/static_content" ]
   libs = [
diff --git a/ios/chrome/browser/ui/overscroll_actions/OWNERS b/ios/chrome/browser/ui/overscroll_actions/OWNERS
index c85e66a..bd85dcf2 100644
--- a/ios/chrome/browser/ui/overscroll_actions/OWNERS
+++ b/ios/chrome/browser/ui/overscroll_actions/OWNERS
@@ -1,4 +1,4 @@
-jif@chromium.org
+kkhorimoto@chromium.org
 
 # TEAM: ios-directory-owners@chromium.org
 # OS: iOS
diff --git a/ios/chrome/browser/ui/overscroll_actions/overscroll_actions_controller.mm b/ios/chrome/browser/ui/overscroll_actions/overscroll_actions_controller.mm
index a428993..019d19b 100644
--- a/ios/chrome/browser/ui/overscroll_actions/overscroll_actions_controller.mm
+++ b/ios/chrome/browser/ui/overscroll_actions/overscroll_actions_controller.mm
@@ -16,7 +16,7 @@
 #import "ios/chrome/browser/ui/overscroll_actions/overscroll_actions_view.h"
 #import "ios/chrome/browser/ui/page_info/page_info_legacy_coordinator.h"
 #include "ios/chrome/browser/ui/rtl_geometry.h"
-#import "ios/chrome/browser/ui/toolbar/toolbar_controller_constants.h"
+#import "ios/chrome/browser/ui/toolbar/public/toolbar_controller_constants.h"
 #include "ios/chrome/browser/ui/uikit_ui_util.h"
 #import "ios/chrome/browser/ui/voice/voice_search_notification_names.h"
 #import "ios/web/public/web_state/ui/crw_web_view_proxy.h"
diff --git a/ios/chrome/browser/ui/payments/BUILD.gn b/ios/chrome/browser/ui/payments/BUILD.gn
index 9cef1fe..955eb1d 100644
--- a/ios/chrome/browser/ui/payments/BUILD.gn
+++ b/ios/chrome/browser/ui/payments/BUILD.gn
@@ -110,6 +110,7 @@
     "payment_request_edit_view_controller.mm",
     "payment_request_edit_view_controller_actions.h",
     "payment_request_edit_view_controller_data_source.h",
+    "payment_request_edit_view_controller_validator.h",
     "payment_request_editor_field.h",
     "payment_request_editor_field.mm",
     "payment_request_error_view_controller.h",
diff --git a/ios/chrome/browser/ui/payments/address_edit_coordinator.h b/ios/chrome/browser/ui/payments/address_edit_coordinator.h
index ea73359..f1be088e 100644
--- a/ios/chrome/browser/ui/payments/address_edit_coordinator.h
+++ b/ios/chrome/browser/ui/payments/address_edit_coordinator.h
@@ -40,7 +40,6 @@
 // provided in the initializer.
 @interface AddressEditCoordinator
     : ChromeCoordinator<PaymentRequestEditViewControllerDelegate,
-                        PaymentRequestEditViewControllerValidator,
                         CountrySelectionCoordinatorDelegate>
 
 // The address to be edited, if any. This pointer is not owned by this class
diff --git a/ios/chrome/browser/ui/payments/address_edit_coordinator.mm b/ios/chrome/browser/ui/payments/address_edit_coordinator.mm
index 1157b90..c35db56 100644
--- a/ios/chrome/browser/ui/payments/address_edit_coordinator.mm
+++ b/ios/chrome/browser/ui/payments/address_edit_coordinator.mm
@@ -11,10 +11,8 @@
 #include "components/autofill/core/browser/autofill_profile.h"
 #include "components/autofill/core/browser/autofill_type.h"
 #include "components/autofill/core/browser/personal_data_manager.h"
-#include "components/autofill/core/browser/validation.h"
 #include "components/autofill/core/common/autofill_constants.h"
 #include "components/payments/core/payments_profile_comparator.h"
-#include "components/strings/grit/components_strings.h"
 #include "ios/chrome/browser/payments/payment_request.h"
 #import "ios/chrome/browser/ui/autofill/autofill_ui_type_util.h"
 #import "ios/chrome/browser/ui/payments/address_edit_mediator.h"
@@ -58,12 +56,12 @@
 - (void)start {
   self.editViewController = [[PaymentRequestEditViewController alloc] init];
   [self.editViewController setDelegate:self];
-  [self.editViewController setValidatorDelegate:self];
   self.mediator =
       [[AddressEditMediator alloc] initWithPaymentRequest:self.paymentRequest
                                                   address:self.address];
   [self.mediator setConsumer:self.editViewController];
   [self.editViewController setDataSource:self.mediator];
+  [self.editViewController setValidatorDelegate:self.mediator];
   [self.editViewController loadModel];
 
   self.viewController = [[PaymentRequestNavigationController alloc]
@@ -88,33 +86,6 @@
   self.viewController = nil;
 }
 
-#pragma mark - PaymentRequestEditViewControllerValidator
-
-- (NSString*)paymentRequestEditViewController:
-                 (PaymentRequestEditViewController*)controller
-                                validateField:(EditorField*)field {
-  if (field.value.length) {
-    switch (field.autofillUIType) {
-      case AutofillUITypeProfileHomePhoneWholeNumber: {
-        const std::string selectedCountryCode =
-            base::SysNSStringToUTF8(self.mediator.selectedCountryCode);
-        if (!autofill::IsValidPhoneNumber(base::SysNSStringToUTF16(field.value),
-                                          selectedCountryCode)) {
-          return l10n_util::GetNSString(
-              IDS_PAYMENTS_PHONE_INVALID_VALIDATION_MESSAGE);
-        }
-        break;
-      }
-      default:
-        break;
-    }
-  } else if (field.isRequired) {
-    return l10n_util::GetNSString(
-        IDS_PAYMENTS_FIELD_REQUIRED_VALIDATION_MESSAGE);
-  }
-  return nil;
-}
-
 #pragma mark - PaymentRequestEditViewControllerDelegate
 
 - (void)paymentRequestEditViewController:
diff --git a/ios/chrome/browser/ui/payments/address_edit_mediator.h b/ios/chrome/browser/ui/payments/address_edit_mediator.h
index 8ec1f82..4d61f89 100644
--- a/ios/chrome/browser/ui/payments/address_edit_mediator.h
+++ b/ios/chrome/browser/ui/payments/address_edit_mediator.h
@@ -6,6 +6,7 @@
 #define IOS_CHROME_BROWSER_UI_PAYMENTS_ADDRESS_EDIT_MEDIATOR_H_
 
 #import "ios/chrome/browser/ui/payments/payment_request_edit_view_controller_data_source.h"
+#import "ios/chrome/browser/ui/payments/payment_request_edit_view_controller_validator.h"
 #import "ios/chrome/browser/ui/payments/region_data_loader.h"
 
 @protocol PaymentRequestEditConsumer;
@@ -21,6 +22,7 @@
 // Serves as data source for AddressEditViewController.
 @interface AddressEditMediator
     : NSObject<PaymentRequestEditViewControllerDataSource,
+               PaymentRequestEditViewControllerValidator,
                RegionDataLoaderConsumer>
 
 // The consumer for this object. This can change during the lifetime of this
diff --git a/ios/chrome/browser/ui/payments/address_edit_mediator.mm b/ios/chrome/browser/ui/payments/address_edit_mediator.mm
index 5be2963..1b178f2c 100644
--- a/ios/chrome/browser/ui/payments/address_edit_mediator.mm
+++ b/ios/chrome/browser/ui/payments/address_edit_mediator.mm
@@ -23,6 +23,7 @@
 #include "components/autofill/core/browser/field_types.h"
 #include "components/autofill/core/browser/personal_data_manager.h"
 #include "components/autofill/core/browser/phone_number_i18n.h"
+#include "components/autofill/core/browser/validation.h"
 #include "components/payments/core/payment_request_data_util.h"
 #include "components/strings/grit/components_strings.h"
 #include "ios/chrome/browser/payments/payment_request.h"
@@ -181,6 +182,33 @@
   return nil;
 }
 
+#pragma mark - PaymentRequestEditViewControllerValidator
+
+- (NSString*)paymentRequestEditViewController:
+                 (PaymentRequestEditViewController*)controller
+                                validateField:(EditorField*)field {
+  if (field.value.length) {
+    switch (field.autofillUIType) {
+      case AutofillUITypeProfileHomePhoneWholeNumber: {
+        const std::string selectedCountryCode =
+            base::SysNSStringToUTF8(self.selectedCountryCode);
+        if (!autofill::IsValidPhoneNumber(base::SysNSStringToUTF16(field.value),
+                                          selectedCountryCode)) {
+          return l10n_util::GetNSString(
+              IDS_PAYMENTS_PHONE_INVALID_VALIDATION_MESSAGE);
+        }
+        break;
+      }
+      default:
+        break;
+    }
+  } else if (field.isRequired) {
+    return l10n_util::GetNSString(
+        IDS_PAYMENTS_FIELD_REQUIRED_VALIDATION_MESSAGE);
+  }
+  return nil;
+}
+
 #pragma mark - RegionDataLoaderConsumer
 
 - (void)regionDataLoaderDidSucceedWithRegions:(NSArray<RegionData*>*)regions {
diff --git a/ios/chrome/browser/ui/payments/address_edit_mediator_unittest.mm b/ios/chrome/browser/ui/payments/address_edit_mediator_unittest.mm
index f2f46c38..9ddf965 100644
--- a/ios/chrome/browser/ui/payments/address_edit_mediator_unittest.mm
+++ b/ios/chrome/browser/ui/payments/address_edit_mediator_unittest.mm
@@ -8,6 +8,8 @@
 #include "components/autofill/core/browser/autofill_test_utils.h"
 #include "components/strings/grit/components_strings.h"
 #import "ios/chrome/browser/payments/payment_request_unittest_base.h"
+#import "ios/chrome/browser/ui/autofill/autofill_ui_type.h"
+#import "ios/chrome/browser/ui/payments/payment_request_editor_field.h"
 #include "testing/platform_test.h"
 #include "third_party/ocmock/gtest_support.h"
 #include "ui/base/l10n/l10n_util.h"
@@ -28,6 +30,67 @@
   void TearDown() override { PaymentRequestUnitTestBase::TearDown(); }
 };
 
+// Tests that no validation error should be expected if validating an empty
+// field that is not required.
+TEST_F(PaymentRequestAddressEditMediatorTest, ValidateEmptyField) {
+  AddressEditMediator* mediator =
+      [[AddressEditMediator alloc] initWithPaymentRequest:payment_request()
+                                                  address:nil];
+
+  EditorField* field = [[EditorField alloc]
+      initWithAutofillUIType:AutofillUITypeProfileHomePhoneWholeNumber
+                   fieldType:EditorFieldTypeTextField
+                       label:@""
+                       value:@""
+                    required:NO];
+  NSString* validationError =
+      [mediator paymentRequestEditViewController:nil
+                                   validateField:(EditorField*)field];
+  EXPECT_TRUE(!validationError);
+}
+
+// Tests that the appropriate validation error should be expected if validating
+// an empty field that is required.
+TEST_F(PaymentRequestAddressEditMediatorTest, ValidateEmptyRequiredField) {
+  AddressEditMediator* mediator =
+      [[AddressEditMediator alloc] initWithPaymentRequest:payment_request()
+                                                  address:nil];
+
+  EditorField* field = [[EditorField alloc]
+      initWithAutofillUIType:AutofillUITypeProfileHomePhoneWholeNumber
+                   fieldType:EditorFieldTypeTextField
+                       label:@""
+                       value:@""
+                    required:YES];
+  NSString* validationError =
+      [mediator paymentRequestEditViewController:nil
+                                   validateField:(EditorField*)field];
+  EXPECT_TRUE([validationError
+      isEqualToString:l10n_util::GetNSString(
+                          IDS_PAYMENTS_FIELD_REQUIRED_VALIDATION_MESSAGE)]);
+}
+
+// Tests that the appropriate validation error should be expected if validating
+// a field with an invalid value.
+TEST_F(PaymentRequestAddressEditMediatorTest, ValidateFieldInvalidValue) {
+  AddressEditMediator* mediator =
+      [[AddressEditMediator alloc] initWithPaymentRequest:payment_request()
+                                                  address:nil];
+
+  EditorField* field = [[EditorField alloc]
+      initWithAutofillUIType:AutofillUITypeProfileHomePhoneWholeNumber
+                   fieldType:EditorFieldTypeTextField
+                       label:@""
+                       value:@"1506853121"  // Missing one last digit.
+                    required:YES];
+  NSString* validationError =
+      [mediator paymentRequestEditViewController:nil
+                                   validateField:(EditorField*)field];
+  EXPECT_TRUE([validationError
+      isEqualToString:l10n_util::GetNSString(
+                          IDS_PAYMENTS_PHONE_INVALID_VALIDATION_MESSAGE)]);
+}
+
 // Tests that the editor's title is correct in various situations.
 TEST_F(PaymentRequestAddressEditMediatorTest, Title) {
   // No address, so the title should ask to add an address.
diff --git a/ios/chrome/browser/ui/payments/contact_info_edit_coordinator.h b/ios/chrome/browser/ui/payments/contact_info_edit_coordinator.h
index 97af0ad6..5983ceb 100644
--- a/ios/chrome/browser/ui/payments/contact_info_edit_coordinator.h
+++ b/ios/chrome/browser/ui/payments/contact_info_edit_coordinator.h
@@ -39,8 +39,7 @@
 // controller. This view controller will be presented by the view controller
 // provided in the initializer.
 @interface ContactInfoEditCoordinator
-    : ChromeCoordinator<PaymentRequestEditViewControllerDelegate,
-                        PaymentRequestEditViewControllerValidator>
+    : ChromeCoordinator<PaymentRequestEditViewControllerDelegate>
 
 // The profile to be edited, if any. This pointer is not owned by this class
 // and should outlive it.
diff --git a/ios/chrome/browser/ui/payments/contact_info_edit_coordinator.mm b/ios/chrome/browser/ui/payments/contact_info_edit_coordinator.mm
index 495c0ae..3b86f9bc 100644
--- a/ios/chrome/browser/ui/payments/contact_info_edit_coordinator.mm
+++ b/ios/chrome/browser/ui/payments/contact_info_edit_coordinator.mm
@@ -14,7 +14,6 @@
 #include "components/autofill/core/browser/validation.h"
 #include "components/autofill/core/common/autofill_constants.h"
 #include "components/payments/core/payments_profile_comparator.h"
-#include "components/strings/grit/components_strings.h"
 #include "ios/chrome/browser/payments/payment_request.h"
 #import "ios/chrome/browser/ui/autofill/autofill_ui_type_util.h"
 #import "ios/chrome/browser/ui/payments/contact_info_edit_mediator.h"
@@ -53,12 +52,12 @@
 - (void)start {
   self.editViewController = [[PaymentRequestEditViewController alloc] init];
   [self.editViewController setDelegate:self];
-  [self.editViewController setValidatorDelegate:self];
   self.mediator = [[ContactInfoEditMediator alloc]
       initWithPaymentRequest:self.paymentRequest
                      profile:self.profile];
   [self.mediator setConsumer:self.editViewController];
   [self.editViewController setDataSource:self.mediator];
+  [self.editViewController setValidatorDelegate:self.mediator];
   [self.editViewController loadModel];
 
   self.viewController = [[PaymentRequestNavigationController alloc]
@@ -81,42 +80,6 @@
   self.viewController = nil;
 }
 
-#pragma mark - PaymentRequestEditViewControllerValidator
-
-- (NSString*)paymentRequestEditViewController:
-                 (PaymentRequestEditViewController*)controller
-                                validateField:(EditorField*)field {
-  if (field.value.length) {
-    switch (field.autofillUIType) {
-      case AutofillUITypeProfileHomePhoneWholeNumber: {
-        const std::string countryCode =
-            autofill::AutofillCountry::CountryCodeForLocale(
-                self.paymentRequest->GetApplicationLocale());
-        if (!autofill::IsValidPhoneNumber(base::SysNSStringToUTF16(field.value),
-                                          countryCode)) {
-          return l10n_util::GetNSString(
-              IDS_PAYMENTS_PHONE_INVALID_VALIDATION_MESSAGE);
-        }
-        break;
-      }
-      case AutofillUITypeProfileEmailAddress: {
-        if (!autofill::IsValidEmailAddress(
-                base::SysNSStringToUTF16(field.value))) {
-          return l10n_util::GetNSString(
-              IDS_PAYMENTS_EMAIL_INVALID_VALIDATION_MESSAGE);
-        }
-        break;
-      }
-      default:
-        break;
-    }
-  } else if (field.isRequired) {
-    return l10n_util::GetNSString(
-        IDS_PAYMENTS_FIELD_REQUIRED_VALIDATION_MESSAGE);
-  }
-  return nil;
-}
-
 #pragma mark - PaymentRequestEditViewControllerDelegate
 
 - (void)paymentRequestEditViewController:
diff --git a/ios/chrome/browser/ui/payments/contact_info_edit_mediator.h b/ios/chrome/browser/ui/payments/contact_info_edit_mediator.h
index 7c6c892d..0a8bd2d 100644
--- a/ios/chrome/browser/ui/payments/contact_info_edit_mediator.h
+++ b/ios/chrome/browser/ui/payments/contact_info_edit_mediator.h
@@ -8,6 +8,7 @@
 #import <Foundation/Foundation.h>
 
 #import "ios/chrome/browser/ui/payments/payment_request_edit_view_controller_data_source.h"
+#import "ios/chrome/browser/ui/payments/payment_request_edit_view_controller_validator.h"
 
 @protocol PaymentRequestEditConsumer;
 
@@ -21,7 +22,8 @@
 
 // Serves as data source for AddressEditViewController.
 @interface ContactInfoEditMediator
-    : NSObject<PaymentRequestEditViewControllerDataSource>
+    : NSObject<PaymentRequestEditViewControllerDataSource,
+               PaymentRequestEditViewControllerValidator>
 
 // The consumer for this object. This can change during the lifetime of this
 // object and may be nil.
diff --git a/ios/chrome/browser/ui/payments/contact_info_edit_mediator.mm b/ios/chrome/browser/ui/payments/contact_info_edit_mediator.mm
index 0429ff5dd..6874804 100644
--- a/ios/chrome/browser/ui/payments/contact_info_edit_mediator.mm
+++ b/ios/chrome/browser/ui/payments/contact_info_edit_mediator.mm
@@ -11,6 +11,7 @@
 #include "components/autofill/core/browser/autofill_type.h"
 #include "components/autofill/core/browser/field_types.h"
 #include "components/autofill/core/browser/phone_number_i18n.h"
+#include "components/autofill/core/browser/validation.h"
 #include "components/payments/core/payment_request_data_util.h"
 #include "components/strings/grit/components_strings.h"
 #include "ios/chrome/browser/payments/payment_request.h"
@@ -104,6 +105,42 @@
   return nil;
 }
 
+#pragma mark - PaymentRequestEditViewControllerValidator
+
+- (NSString*)paymentRequestEditViewController:
+                 (PaymentRequestEditViewController*)controller
+                                validateField:(EditorField*)field {
+  if (field.value.length) {
+    switch (field.autofillUIType) {
+      case AutofillUITypeProfileHomePhoneWholeNumber: {
+        const std::string countryCode =
+            autofill::AutofillCountry::CountryCodeForLocale(
+                self.paymentRequest->GetApplicationLocale());
+        if (!autofill::IsValidPhoneNumber(base::SysNSStringToUTF16(field.value),
+                                          countryCode)) {
+          return l10n_util::GetNSString(
+              IDS_PAYMENTS_PHONE_INVALID_VALIDATION_MESSAGE);
+        }
+        break;
+      }
+      case AutofillUITypeProfileEmailAddress: {
+        if (!autofill::IsValidEmailAddress(
+                base::SysNSStringToUTF16(field.value))) {
+          return l10n_util::GetNSString(
+              IDS_PAYMENTS_EMAIL_INVALID_VALIDATION_MESSAGE);
+        }
+        break;
+      }
+      default:
+        break;
+    }
+  } else if (field.isRequired) {
+    return l10n_util::GetNSString(
+        IDS_PAYMENTS_FIELD_REQUIRED_VALIDATION_MESSAGE);
+  }
+  return nil;
+}
+
 #pragma mark - Helper methods
 
 // Creates and returns an array of editor fields.
diff --git a/ios/chrome/browser/ui/payments/contact_info_edit_mediator_unittest.mm b/ios/chrome/browser/ui/payments/contact_info_edit_mediator_unittest.mm
index 9b8de1d9a..d02c51b 100644
--- a/ios/chrome/browser/ui/payments/contact_info_edit_mediator_unittest.mm
+++ b/ios/chrome/browser/ui/payments/contact_info_edit_mediator_unittest.mm
@@ -10,6 +10,7 @@
 #include "components/strings/grit/components_strings.h"
 #include "ios/chrome/browser/payments/payment_request_test_util.h"
 #import "ios/chrome/browser/payments/payment_request_unittest_base.h"
+#import "ios/chrome/browser/ui/autofill/autofill_ui_type.h"
 #import "ios/chrome/browser/ui/autofill/autofill_ui_type_util.h"
 #import "ios/chrome/browser/ui/payments/payment_request_edit_consumer.h"
 #import "ios/chrome/browser/ui/payments/payment_request_editor_field.h"
@@ -197,6 +198,80 @@
   EXPECT_OCMOCK_VERIFY(consumer);
 }
 
+// Tests that no validation error should be expected if validating an empty
+// field that is not required.
+TEST_F(PaymentRequestContactInfoEditMediatorTest, ValidateEmptyField) {
+  ContactInfoEditMediator* mediator =
+      [[ContactInfoEditMediator alloc] initWithPaymentRequest:payment_request()
+                                                      profile:nil];
+
+  EditorField* field = [[EditorField alloc]
+      initWithAutofillUIType:AutofillUITypeProfileHomePhoneWholeNumber
+                   fieldType:EditorFieldTypeTextField
+                       label:@""
+                       value:@""
+                    required:NO];
+  NSString* validationError =
+      [mediator paymentRequestEditViewController:nil
+                                   validateField:(EditorField*)field];
+  EXPECT_TRUE(!validationError);
+}
+
+// Tests that the appropriate validation error should be expected if validating
+// an empty field that is required.
+TEST_F(PaymentRequestContactInfoEditMediatorTest, ValidateEmptyRequiredField) {
+  ContactInfoEditMediator* mediator =
+      [[ContactInfoEditMediator alloc] initWithPaymentRequest:payment_request()
+                                                      profile:nil];
+
+  EditorField* field = [[EditorField alloc]
+      initWithAutofillUIType:AutofillUITypeProfileHomePhoneWholeNumber
+                   fieldType:EditorFieldTypeTextField
+                       label:@""
+                       value:@""
+                    required:YES];
+  NSString* validationError =
+      [mediator paymentRequestEditViewController:nil
+                                   validateField:(EditorField*)field];
+  EXPECT_TRUE([validationError
+      isEqualToString:l10n_util::GetNSString(
+                          IDS_PAYMENTS_FIELD_REQUIRED_VALIDATION_MESSAGE)]);
+}
+
+// Tests that the appropriate validation error should be expected if validating
+// a field with an invalid value.
+TEST_F(PaymentRequestContactInfoEditMediatorTest, ValidateFieldInvalidValue) {
+  ContactInfoEditMediator* mediator =
+      [[ContactInfoEditMediator alloc] initWithPaymentRequest:payment_request()
+                                                      profile:nil];
+
+  EditorField* field = [[EditorField alloc]
+      initWithAutofillUIType:AutofillUITypeProfileHomePhoneWholeNumber
+                   fieldType:EditorFieldTypeTextField
+                       label:@""
+                       value:@"1506853121"  // Missing one last digit.
+                    required:YES];
+  NSString* validationError =
+      [mediator paymentRequestEditViewController:nil
+                                   validateField:(EditorField*)field];
+  EXPECT_TRUE([validationError
+      isEqualToString:l10n_util::GetNSString(
+                          IDS_PAYMENTS_PHONE_INVALID_VALIDATION_MESSAGE)]);
+
+  field = [[EditorField alloc]
+      initWithAutofillUIType:AutofillUITypeProfileEmailAddress
+                   fieldType:EditorFieldTypeTextField
+                       label:@""
+                       value:@"example.com"  // Invalid email address.
+                    required:YES];
+  validationError =
+      [mediator paymentRequestEditViewController:nil
+                                   validateField:(EditorField*)field];
+  EXPECT_TRUE([validationError
+      isEqualToString:l10n_util::GetNSString(
+                          IDS_PAYMENTS_EMAIL_INVALID_VALIDATION_MESSAGE)]);
+}
+
 // Tests that the editor's title is correct in various situations.
 TEST_F(PaymentRequestContactInfoEditMediatorTest, Title) {
   // No profile, so the title should ask to add contact details.
diff --git a/ios/chrome/browser/ui/payments/credit_card_edit_coordinator.h b/ios/chrome/browser/ui/payments/credit_card_edit_coordinator.h
index aa14107..4933c75 100644
--- a/ios/chrome/browser/ui/payments/credit_card_edit_coordinator.h
+++ b/ios/chrome/browser/ui/payments/credit_card_edit_coordinator.h
@@ -44,8 +44,7 @@
 @interface CreditCardEditCoordinator
     : ChromeCoordinator<AddressEditCoordinatorDelegate,
                         BillingAddressSelectionCoordinatorDelegate,
-                        PaymentRequestEditViewControllerDelegate,
-                        PaymentRequestEditViewControllerValidator>
+                        PaymentRequestEditViewControllerDelegate>
 
 // The payment method to be edited, if any. This pointer is not owned by this
 // class and should outlive it.
diff --git a/ios/chrome/browser/ui/payments/credit_card_edit_coordinator.mm b/ios/chrome/browser/ui/payments/credit_card_edit_coordinator.mm
index 7b5b17f..0563b75a 100644
--- a/ios/chrome/browser/ui/payments/credit_card_edit_coordinator.mm
+++ b/ios/chrome/browser/ui/payments/credit_card_edit_coordinator.mm
@@ -11,13 +11,10 @@
 #include "components/autofill/core/browser/autofill_type.h"
 #include "components/autofill/core/browser/credit_card.h"
 #include "components/autofill/core/browser/personal_data_manager.h"
-#include "components/autofill/core/browser/validation.h"
-#include "components/autofill/core/common/autofill_clock.h"
 #include "components/autofill/core/common/autofill_constants.h"
 #import "components/autofill/ios/browser/credit_card_util.h"
 #include "components/payments/core/autofill_payment_instrument.h"
 #include "components/payments/core/payment_instrument.h"
-#include "components/strings/grit/components_strings.h"
 #include "ios/chrome/browser/payments/payment_request.h"
 #import "ios/chrome/browser/ui/autofill/autofill_ui_type_util.h"
 #import "ios/chrome/browser/ui/payments/credit_card_edit_mediator.h"
@@ -29,46 +26,6 @@
 #error "This file requires ARC support."
 #endif
 
-namespace {
-using ::AutofillUITypeFromAutofillType;
-using ::AutofillTypeFromAutofillUIType;
-
-// Returns true if |card_number| is a supported card type and a valid credit
-// card number and no other credit card with the same number exists.
-// |error_message| can't be null and will be filled with the appropriate error
-// message iff the return value is false.
-bool IsValidCreditCardNumber(const base::string16& card_number,
-                             payments::PaymentRequest* payment_request,
-                             const autofill::CreditCard* credit_card_to_edit,
-                             base::string16* error_message) {
-  std::set<std::string> supported_card_networks(
-      payment_request->supported_card_networks().begin(),
-      payment_request->supported_card_networks().end());
-  if (!::autofill::IsValidCreditCardNumberForBasicCardNetworks(
-          card_number, supported_card_networks, error_message)) {
-    return false;
-  }
-
-  // Check if another credit card has already been created with this number.
-  // TODO(crbug.com/725604): the UI should offer to load / update the existing
-  // credit card info.
-  autofill::CreditCard* existing_card =
-      payment_request->GetPersonalDataManager()->GetCreditCardByNumber(
-          base::UTF16ToASCII(card_number));
-  // If a card exists, it could be the one currently being edited.
-  if (!existing_card || (credit_card_to_edit && credit_card_to_edit->guid() ==
-                                                    existing_card->guid())) {
-    return true;
-  }
-  if (error_message) {
-    *error_message = l10n_util::GetStringUTF16(
-        IDS_PAYMENTS_VALIDATION_ALREADY_USED_CREDIT_CARD_NUMBER);
-  }
-  return false;
-}
-
-}  // namespace
-
 @interface CreditCardEditCoordinator ()
 
 @property(nonatomic, assign) autofill::CreditCard* creditCard;
@@ -105,12 +62,12 @@
 
   _editViewController = [[PaymentRequestEditViewController alloc] init];
   [_editViewController setDelegate:self];
-  [_editViewController setValidatorDelegate:self];
   _mediator = [[CreditCardEditViewControllerMediator alloc]
       initWithPaymentRequest:_paymentRequest
                   creditCard:_creditCard];
   [_mediator setConsumer:_editViewController];
   [_editViewController setDataSource:_mediator];
+  [_editViewController setValidatorDelegate:_mediator];
   [_editViewController loadModel];
 
   self.viewController = [[PaymentRequestNavigationController alloc]
@@ -137,41 +94,6 @@
   self.viewController = nil;
 }
 
-#pragma mark - PaymentRequestEditViewControllerValidator
-
-- (NSString*)paymentRequestEditViewController:
-                 (PaymentRequestEditViewController*)controller
-                                validateField:(EditorField*)field {
-  if (field.value.length) {
-    base::string16 errorMessage;
-    base::string16 valueString = base::SysNSStringToUTF16(field.value);
-    if (field.autofillUIType == AutofillUITypeCreditCardNumber) {
-      ::IsValidCreditCardNumber(valueString, _paymentRequest, _creditCard,
-                                &errorMessage);
-    } else if (field.autofillUIType == AutofillUITypeCreditCardExpDate) {
-      NSArray<NSString*>* fieldComponents =
-          [field.value componentsSeparatedByString:@" / "];
-      int expMonth = [fieldComponents[0] intValue];
-      int expYear = [fieldComponents[1] intValue];
-      if (!autofill::IsValidCreditCardExpirationDate(
-              expYear, expMonth, autofill::AutofillClock::Now())) {
-        errorMessage = l10n_util::GetStringUTF16(
-            IDS_PAYMENTS_VALIDATION_INVALID_CREDIT_CARD_EXPIRED);
-      }
-    } else if (field.autofillUIType != AutofillUITypeCreditCardBillingAddress &&
-               field.autofillUIType != AutofillUITypeCreditCardSaveToChrome) {
-      autofill::IsValidForType(
-          valueString, AutofillTypeFromAutofillUIType(field.autofillUIType),
-          &errorMessage);
-    }
-    return !errorMessage.empty() ? base::SysUTF16ToNSString(errorMessage) : nil;
-  } else if (field.isRequired) {
-    return l10n_util::GetNSString(
-        IDS_PAYMENTS_FIELD_REQUIRED_VALIDATION_MESSAGE);
-  }
-  return nil;
-}
-
 #pragma mark - PaymentRequestEditViewControllerDelegate
 
 - (void)paymentRequestEditViewController:
diff --git a/ios/chrome/browser/ui/payments/credit_card_edit_mediator.h b/ios/chrome/browser/ui/payments/credit_card_edit_mediator.h
index b55574e..7b4ddcd 100644
--- a/ios/chrome/browser/ui/payments/credit_card_edit_mediator.h
+++ b/ios/chrome/browser/ui/payments/credit_card_edit_mediator.h
@@ -6,6 +6,7 @@
 #define IOS_CHROME_BROWSER_UI_PAYMENTS_CREDIT_CARD_EDIT_MEDIATOR_H_
 
 #import "ios/chrome/browser/ui/payments/payment_request_edit_view_controller_data_source.h"
+#import "ios/chrome/browser/ui/payments/payment_request_edit_view_controller_validator.h"
 
 @protocol PaymentRequestEditConsumer;
 
@@ -20,7 +21,8 @@
 
 // Serves as data source for CreditCardEditViewController.
 @interface CreditCardEditViewControllerMediator
-    : NSObject<PaymentRequestEditViewControllerDataSource>
+    : NSObject<PaymentRequestEditViewControllerDataSource,
+               PaymentRequestEditViewControllerValidator>
 
 // The consumer for this object. This can change during the lifetime of this
 // object and may be nil.
diff --git a/ios/chrome/browser/ui/payments/credit_card_edit_mediator.mm b/ios/chrome/browser/ui/payments/credit_card_edit_mediator.mm
index 01c33867..88206f8 100644
--- a/ios/chrome/browser/ui/payments/credit_card_edit_mediator.mm
+++ b/ios/chrome/browser/ui/payments/credit_card_edit_mediator.mm
@@ -5,11 +5,13 @@
 #import "ios/chrome/browser/ui/payments/credit_card_edit_mediator.h"
 
 #include "base/strings/sys_string_conversions.h"
+#include "base/strings/utf_string_conversions.h"
 #include "components/autofill/core/browser/autofill_data_util.h"
 #include "components/autofill/core/browser/autofill_profile.h"
 #include "components/autofill/core/browser/credit_card.h"
 #include "components/autofill/core/browser/personal_data_manager.h"
 #include "components/autofill/core/browser/validation.h"
+#include "components/autofill/core/common/autofill_clock.h"
 #import "components/autofill/ios/browser/credit_card_util.h"
 #include "components/payments/core/payment_request_data_util.h"
 #include "components/payments/core/strings_util.h"
@@ -17,6 +19,7 @@
 #include "ios/chrome/browser/payments/payment_request.h"
 #import "ios/chrome/browser/payments/payment_request_util.h"
 #import "ios/chrome/browser/ui/autofill/autofill_ui_type.h"
+#import "ios/chrome/browser/ui/autofill/autofill_ui_type_util.h"
 #import "ios/chrome/browser/ui/payments/cells/accepted_payment_methods_item.h"
 #import "ios/chrome/browser/ui/payments/cells/payment_method_item.h"
 #import "ios/chrome/browser/ui/payments/payment_request_edit_consumer.h"
@@ -32,6 +35,41 @@
 using ::autofill::data_util::GetIssuerNetworkForBasicCardIssuerNetwork;
 using ::autofill::data_util::GetPaymentRequestData;
 using ::payment_request_util::GetBillingAddressLabelFromAutofillProfile;
+
+// Returns true if |card_number| is a supported card type and a valid credit
+// card number and no other credit card with the same number exists.
+// |error_message| can't be null and will be filled with the appropriate error
+// message iff the return value is false.
+bool IsValidCreditCardNumber(const base::string16& card_number,
+                             payments::PaymentRequest* payment_request,
+                             const autofill::CreditCard* credit_card_to_edit,
+                             base::string16* error_message) {
+  std::set<std::string> supported_card_networks(
+      payment_request->supported_card_networks().begin(),
+      payment_request->supported_card_networks().end());
+  if (!::autofill::IsValidCreditCardNumberForBasicCardNetworks(
+          card_number, supported_card_networks, error_message)) {
+    return false;
+  }
+
+  // Check if another credit card has already been created with this number.
+  // TODO(crbug.com/725604): the UI should offer to load / update the existing
+  // credit card info.
+  autofill::CreditCard* existing_card =
+      payment_request->GetPersonalDataManager()->GetCreditCardByNumber(
+          base::UTF16ToASCII(card_number));
+  // If a card exists, it could be the one currently being edited.
+  if (!existing_card || (credit_card_to_edit && credit_card_to_edit->guid() ==
+                                                    existing_card->guid())) {
+    return true;
+  }
+  if (error_message) {
+    *error_message = l10n_util::GetStringUTF16(
+        IDS_PAYMENTS_VALIDATION_ALREADY_USED_CREDIT_CARD_NUMBER);
+  }
+  return false;
+}
+
 }  // namespace
 
 @interface CreditCardEditViewControllerMediator ()
@@ -186,6 +224,41 @@
   return NativeImage(resourceID);
 }
 
+#pragma mark - PaymentRequestEditViewControllerValidator
+
+- (NSString*)paymentRequestEditViewController:
+                 (PaymentRequestEditViewController*)controller
+                                validateField:(EditorField*)field {
+  if (field.value.length) {
+    base::string16 errorMessage;
+    base::string16 valueString = base::SysNSStringToUTF16(field.value);
+    if (field.autofillUIType == AutofillUITypeCreditCardNumber) {
+      ::IsValidCreditCardNumber(valueString, _paymentRequest, _creditCard,
+                                &errorMessage);
+    } else if (field.autofillUIType == AutofillUITypeCreditCardExpDate) {
+      NSArray<NSString*>* fieldComponents =
+          [field.value componentsSeparatedByString:@" / "];
+      int expMonth = [fieldComponents[0] intValue];
+      int expYear = [fieldComponents[1] intValue];
+      if (!autofill::IsValidCreditCardExpirationDate(
+              expYear, expMonth, autofill::AutofillClock::Now())) {
+        errorMessage = l10n_util::GetStringUTF16(
+            IDS_PAYMENTS_VALIDATION_INVALID_CREDIT_CARD_EXPIRED);
+      }
+    } else if (field.autofillUIType != AutofillUITypeCreditCardBillingAddress &&
+               field.autofillUIType != AutofillUITypeCreditCardSaveToChrome) {
+      autofill::IsValidForType(
+          valueString, ::AutofillTypeFromAutofillUIType(field.autofillUIType),
+          &errorMessage);
+    }
+    return !errorMessage.empty() ? base::SysUTF16ToNSString(errorMessage) : nil;
+  } else if (field.isRequired) {
+    return l10n_util::GetNSString(
+        IDS_PAYMENTS_FIELD_REQUIRED_VALIDATION_MESSAGE);
+  }
+  return nil;
+}
+
 #pragma mark - Helper methods
 
 // Queries the month and year numbers and informs the consumer.
diff --git a/ios/chrome/browser/ui/payments/credit_card_edit_mediator_unittest.mm b/ios/chrome/browser/ui/payments/credit_card_edit_mediator_unittest.mm
index 9b0d9a5..f6d3ad7 100644
--- a/ios/chrome/browser/ui/payments/credit_card_edit_mediator_unittest.mm
+++ b/ios/chrome/browser/ui/payments/credit_card_edit_mediator_unittest.mm
@@ -4,9 +4,12 @@
 
 #import "ios/chrome/browser/ui/payments/credit_card_edit_mediator.h"
 
+#include "base/time/time.h"
 #include "components/autofill/core/browser/autofill_test_utils.h"
+#include "components/autofill/core/browser/test_autofill_clock.h"
 #include "components/strings/grit/components_strings.h"
 #import "ios/chrome/browser/payments/payment_request_unittest_base.h"
+#import "ios/chrome/browser/ui/payments/payment_request_editor_field.h"
 #include "testing/platform_test.h"
 #include "third_party/ocmock/gtest_support.h"
 #include "ui/base/l10n/l10n_util.h"
@@ -15,12 +18,19 @@
 #error "This file requires ARC support."
 #endif
 
+namespace {
+
+const base::Time kOct2017 = base::Time::FromDoubleT(1509050356);
+
+}  // namespace
+
 class PaymentRequestCreditCardEditMediatorTest
     : public PaymentRequestUnitTestBase,
       public PlatformTest {
  protected:
   void SetUp() override {
     PaymentRequestUnitTestBase::SetUp();
+
     AddAutofillProfile(autofill::test::GetFullProfile());
     CreateTestPaymentRequest();
   }
@@ -28,6 +38,88 @@
   void TearDown() override { PaymentRequestUnitTestBase::TearDown(); }
 };
 
+// Tests that no validation error should be expected if validating an empty
+// field that is not required.
+TEST_F(PaymentRequestCreditCardEditMediatorTest, ValidateEmptyField) {
+  CreditCardEditViewControllerMediator* mediator =
+      [[CreditCardEditViewControllerMediator alloc]
+          initWithPaymentRequest:payment_request()
+                      creditCard:nil];
+
+  EditorField* field = [[EditorField alloc]
+      initWithAutofillUIType:AutofillUITypeProfileHomePhoneWholeNumber
+                   fieldType:EditorFieldTypeTextField
+                       label:@""
+                       value:@""
+                    required:NO];
+  NSString* validationError =
+      [mediator paymentRequestEditViewController:nil
+                                   validateField:(EditorField*)field];
+  EXPECT_TRUE(!validationError);
+}
+
+// Tests that the appropriate validation error should be expected if validating
+// an empty field that is required.
+TEST_F(PaymentRequestCreditCardEditMediatorTest, ValidateEmptyRequiredField) {
+  CreditCardEditViewControllerMediator* mediator =
+      [[CreditCardEditViewControllerMediator alloc]
+          initWithPaymentRequest:payment_request()
+                      creditCard:nil];
+
+  EditorField* field = [[EditorField alloc]
+      initWithAutofillUIType:AutofillUITypeProfileHomePhoneWholeNumber
+                   fieldType:EditorFieldTypeTextField
+                       label:@""
+                       value:@""
+                    required:YES];
+  NSString* validationError =
+      [mediator paymentRequestEditViewController:nil
+                                   validateField:(EditorField*)field];
+  EXPECT_TRUE([validationError
+      isEqualToString:l10n_util::GetNSString(
+                          IDS_PAYMENTS_FIELD_REQUIRED_VALIDATION_MESSAGE)]);
+}
+
+// Tests that the appropriate validation error should be expected if validating
+// a field with an invalid value.
+TEST_F(PaymentRequestCreditCardEditMediatorTest, ValidateFieldInvalidValue) {
+  CreditCardEditViewControllerMediator* mediator =
+      [[CreditCardEditViewControllerMediator alloc]
+          initWithPaymentRequest:payment_request()
+                      creditCard:nil];
+
+  EditorField* field = [[EditorField alloc]
+      initWithAutofillUIType:AutofillUITypeCreditCardNumber
+                   fieldType:EditorFieldTypeTextField
+                       label:@""
+                       value:@"411111111111111"  // Missing one last digit.
+                    required:YES];
+  NSString* validationError =
+      [mediator paymentRequestEditViewController:nil
+                                   validateField:(EditorField*)field];
+  EXPECT_TRUE([validationError
+      isEqualToString:
+          l10n_util::GetNSString(
+              IDS_PAYMENTS_CARD_NUMBER_INVALID_VALIDATION_MESSAGE)]);
+
+  autofill::TestAutofillClock test_clock;
+  test_clock.SetNow(kOct2017);
+
+  field = [[EditorField alloc]
+      initWithAutofillUIType:AutofillUITypeCreditCardExpDate
+                   fieldType:EditorFieldTypeTextField
+                       label:@""
+                       value:@"09 / 17"  // September 2017.
+                    required:YES];
+  validationError =
+      [mediator paymentRequestEditViewController:nil
+                                   validateField:(EditorField*)field];
+  EXPECT_TRUE([validationError
+      isEqualToString:
+          l10n_util::GetNSString(
+              IDS_PAYMENTS_VALIDATION_INVALID_CREDIT_CARD_EXPIRED)]);
+}
+
 // Tests that the editor's title is correct in various situations.
 TEST_F(PaymentRequestCreditCardEditMediatorTest, Title) {
   // No card, so the title should ask to add a card.
diff --git a/ios/chrome/browser/ui/payments/payment_request_edit_view_controller.h b/ios/chrome/browser/ui/payments/payment_request_edit_view_controller.h
index 8aea55d..f763ec0b 100644
--- a/ios/chrome/browser/ui/payments/payment_request_edit_view_controller.h
+++ b/ios/chrome/browser/ui/payments/payment_request_edit_view_controller.h
@@ -12,6 +12,7 @@
 #import "ios/chrome/browser/ui/collection_view/collection_view_controller.h"
 #import "ios/chrome/browser/ui/payments/payment_request_edit_consumer.h"
 #import "ios/chrome/browser/ui/payments/payment_request_edit_view_controller_data_source.h"
+#import "ios/chrome/browser/ui/payments/payment_request_edit_view_controller_validator.h"
 
 extern NSString* const kWarningMessageAccessibilityID;
 
@@ -40,17 +41,6 @@
 
 @end
 
-// Validator protocol for PaymentRequestEditViewController.
-@protocol PaymentRequestEditViewControllerValidator<NSObject>
-
-// Returns the validation error string for |field|. Returns nil if there are no
-// validation errors.
-- (NSString*)paymentRequestEditViewController:
-                 (PaymentRequestEditViewController*)controller
-                                validateField:(EditorField*)field;
-
-@end
-
 // The collection view controller for a generic Payment Request edit screen. It
 // features sections for every EditorField supplied to the initializer. Each
 // section has a text field as well as an error message item which is visible
diff --git a/ios/chrome/browser/ui/payments/payment_request_edit_view_controller_validator.h b/ios/chrome/browser/ui/payments/payment_request_edit_view_controller_validator.h
new file mode 100644
index 0000000..5b1a127
--- /dev/null
+++ b/ios/chrome/browser/ui/payments/payment_request_edit_view_controller_validator.h
@@ -0,0 +1,24 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef IOS_CHROME_BROWSER_UI_PAYMENTS_PAYMENT_REQUEST_EDIT_VIEW_CONTROLLER_VALIDATOR_H_
+#define IOS_CHROME_BROWSER_UI_PAYMENTS_PAYMENT_REQUEST_EDIT_VIEW_CONTROLLER_VALIDATOR_H_
+
+#import <Foundation/Foundation.h>
+
+@class PaymentRequestEditViewController;
+@class EditorField;
+
+// Validator protocol for PaymentRequestEditViewController.
+@protocol PaymentRequestEditViewControllerValidator<NSObject>
+
+// Returns the validation error string for |field|. Returns nil if there are no
+// validation errors.
+- (NSString*)paymentRequestEditViewController:
+                 (PaymentRequestEditViewController*)controller
+                                validateField:(EditorField*)field;
+
+@end
+
+#endif  // IOS_CHROME_BROWSER_UI_PAYMENTS_PAYMENT_REQUEST_EDIT_VIEW_CONTROLLER_VALIDATOR_H_
diff --git a/ios/chrome/browser/ui/promos/signin_promo_view_controller.mm b/ios/chrome/browser/ui/promos/signin_promo_view_controller.mm
index 454c47b7a..791f312 100644
--- a/ios/chrome/browser/ui/promos/signin_promo_view_controller.mm
+++ b/ios/chrome/browser/ui/promos/signin_promo_view_controller.mm
@@ -93,12 +93,16 @@
 - (void)dismissWithSignedIn:(BOOL)signedIn
        showAccountsSettings:(BOOL)showAccountsSettings {
   DCHECK(self.presentingViewController);
-  UIViewController* presentingViewController = self.presentingViewController;
+  __weak UIViewController* presentingViewController =
+      self.presentingViewController;
+  __weak id<ApplicationCommands> weakDispatcher = self.dispatcher;
   [presentingViewController
       dismissViewControllerAnimated:YES
                          completion:^{
                            if (showAccountsSettings) {
-                             [self.dispatcher showAccountsSettings];
+                             [weakDispatcher
+                                 showAccountsSettingsFromViewController:
+                                     presentingViewController];
                            }
                          }];
 }
diff --git a/ios/chrome/browser/ui/qr_scanner/OWNERS b/ios/chrome/browser/ui/qr_scanner/OWNERS
index c85e66a..56360bb 100644
--- a/ios/chrome/browser/ui/qr_scanner/OWNERS
+++ b/ios/chrome/browser/ui/qr_scanner/OWNERS
@@ -1,4 +1,4 @@
-jif@chromium.org
+olivierrobin@chromium.org
 
 # TEAM: ios-directory-owners@chromium.org
 # OS: iOS
diff --git a/ios/chrome/browser/ui/settings/BUILD.gn b/ios/chrome/browser/ui/settings/BUILD.gn
index 47bfc93c..c731175 100644
--- a/ios/chrome/browser/ui/settings/BUILD.gn
+++ b/ios/chrome/browser/ui/settings/BUILD.gn
@@ -152,7 +152,6 @@
     "//ios/chrome/browser/ui/settings/utils",
     "//ios/chrome/browser/ui/signin_interaction",
     "//ios/chrome/browser/voice",
-    "//ios/chrome/browser/web:features",
     "//ios/chrome/browser/web:web",
     "//ios/chrome/common",
     "//ios/public/provider/chrome/browser",
@@ -292,7 +291,6 @@
     "//ios/chrome/browser/ui/settings/sync_utils",
     "//ios/chrome/browser/voice",
     "//ios/chrome/browser/web",
-    "//ios/chrome/browser/web:features",
     "//ios/chrome/browser/web:test_support",
     "//ios/chrome/common",
     "//ios/chrome/test:test_support",
diff --git a/ios/chrome/browser/ui/settings/compose_email_handler_collection_view_controller.mm b/ios/chrome/browser/ui/settings/compose_email_handler_collection_view_controller.mm
index eee2b6a..57962364 100644
--- a/ios/chrome/browser/ui/settings/compose_email_handler_collection_view_controller.mm
+++ b/ios/chrome/browser/ui/settings/compose_email_handler_collection_view_controller.mm
@@ -7,7 +7,6 @@
 #include "base/mac/foundation_util.h"
 #import "ios/chrome/browser/ui/collection_view/cells/collection_view_switch_item.h"
 #import "ios/chrome/browser/ui/collection_view/cells/collection_view_text_item.h"
-#import "ios/chrome/browser/web/features.h"
 #import "ios/chrome/browser/web/mailto_handler.h"
 #import "ios/chrome/browser/web/mailto_url_rewriter.h"
 #include "ios/chrome/grit/ios_strings.h"
@@ -91,20 +90,16 @@
   NSString* currentHandlerID = [_rewriter defaultHandlerID];
 
   // Populates the toggle "Always Ask" toggle switch row first because the
-  // state of of the Mail client apps selection list is dependent of the value
-  // of the toggle switch.
-  if (base::FeatureList::IsEnabled(kMailtoPromptInMdcStyle)) {
-    // The second section, if it exists, is the toggle switch to always prompt
-    // for selection of Mail client app.
-    [model addSectionWithIdentifier:SectionIdentifierAlwaysAsk];
-    _alwaysAskItem =
-        [[CollectionViewSwitchItem alloc] initWithType:ItemTypeAlwaysAskSwitch];
-    _alwaysAskItem.text =
-        l10n_util::GetNSString(IDS_IOS_CHOOSE_EMAIL_ASK_TOGGLE);
-    _alwaysAskItem.on = currentHandlerID == nil;
-    [model addItem:_alwaysAskItem
-        toSectionWithIdentifier:SectionIdentifierAlwaysAsk];
-  }
+  // state of of the Mail client apps selection list is dependent on the value
+  // of the toggle switch. The second section is the toggle switch to always
+  // prompt for selection of Mail client app.
+  [model addSectionWithIdentifier:SectionIdentifierAlwaysAsk];
+  _alwaysAskItem =
+      [[CollectionViewSwitchItem alloc] initWithType:ItemTypeAlwaysAskSwitch];
+  _alwaysAskItem.text = l10n_util::GetNSString(IDS_IOS_CHOOSE_EMAIL_ASK_TOGGLE);
+  _alwaysAskItem.on = currentHandlerID == nil;
+  [model addItem:_alwaysAskItem
+      toSectionWithIdentifier:SectionIdentifierAlwaysAsk];
 
   // Lists all the Mail client apps known.
   for (MailtoHandler* handler in handlers) {
diff --git a/ios/chrome/browser/ui/settings/compose_email_handler_collection_view_controller_unittest.mm b/ios/chrome/browser/ui/settings/compose_email_handler_collection_view_controller_unittest.mm
index 3b65e2e..e1ec1c3 100644
--- a/ios/chrome/browser/ui/settings/compose_email_handler_collection_view_controller_unittest.mm
+++ b/ios/chrome/browser/ui/settings/compose_email_handler_collection_view_controller_unittest.mm
@@ -9,8 +9,6 @@
 #import "ios/chrome/browser/ui/collection_view/cells/collection_view_text_item.h"
 #import "ios/chrome/browser/ui/collection_view/collection_view_controller_test.h"
 #import "ios/chrome/browser/web/fake_mailto_handler_helpers.h"
-#include "ios/chrome/browser/web/features.h"
-#import "ios/chrome/browser/web/legacy_mailto_url_rewriter.h"
 #import "ios/chrome/browser/web/mailto_handler_system_mail.h"
 #import "ios/chrome/browser/web/nullable_mailto_url_rewriter.h"
 #include "ios/chrome/grit/ios_strings.h"
@@ -34,9 +32,7 @@
   // CollectionViewController.
   CollectionViewController* InstantiateController() override {
     rewriter_ =
-        base::FeatureList::IsEnabled(kMailtoPromptForUserChoice)
-            ? [NullableMailtoURLRewriter mailtoURLRewriterWithStandardHandlers]
-            : [[LegacyMailtoURLRewriter alloc] init];
+        [NullableMailtoURLRewriter mailtoURLRewriterWithStandardHandlers];
     // Clears the state so unit tests start from a known state.
     [[NSUserDefaults standardUserDefaults]
         removeObjectForKey:[[rewriter_ class] userDefaultsKey]];
@@ -55,7 +51,6 @@
 };
 
 TEST_F(ComposeEmailHandlerCollectionViewControllerTest, TestConstructor) {
-  bool use_mdc_style = base::FeatureList::IsEnabled(kMailtoPromptInMdcStyle);
   handlers_ = @[
     [[MailtoHandlerSystemMail alloc] init],
     [[FakeMailtoHandlerGmailInstalled alloc] init],
@@ -65,10 +60,9 @@
   CheckController();
   CheckTitleWithId(IDS_IOS_COMPOSE_EMAIL_SETTING);
 
-  // Checks that there is one section with all the available MailtoHandler
-  // objects listed.
-  NSInteger expected_sections = use_mdc_style ? 2 : 1;
-  ASSERT_EQ(expected_sections, NumberOfSections());
+  // Checks that there are two sections: one with all the available
+  // MailtoHandler objects listed and a second one with the "Always Ask" toggle.
+  ASSERT_EQ(2, NumberOfSections());
   // Array returned by -defaultHandlers is sorted by the name of the Mail app
   // and may not be in the same order as |handlers_|.
   NSArray<MailtoHandler*>* handlers = [rewriter_ defaultHandlers];
@@ -80,14 +74,14 @@
     // Checks that the title displayed is the name of the MailtoHandler.
     EXPECT_NSEQ([handler appName], item.text);
     EXPECT_FALSE(item.detailText);
-    // The enable/disable state of the Mail client apps depends on whether
-    // the "Always Ask" toggle is available. All rows should be disabled
-    // if user has not selected a default Mail client app.
-    BOOL is_disabled = use_mdc_style && [rewriter_ defaultHandlerID] == nil;
+    // The enable/disable state of each Mail client app depends on the state
+    // of the "Always Ask" toggle. All rows should be disabled if user has
+    // not selected a default Mail client app.
+    BOOL is_enabled = [rewriter_ defaultHandlerID] != nil;
     // Checks that text cells are displayed differently depending on the
     // availability of the handlers.
     UIColor* darkest_tint = [[MDCPalette greyPalette] tint900];
-    if (!is_disabled && [handler isAvailable]) {
+    if (is_enabled && [handler isAvailable]) {
       EXPECT_EQ(darkest_tint, item.textColor);
       EXPECT_NE(UIAccessibilityTraitNotEnabled, item.accessibilityTraits);
     } else {
@@ -95,11 +89,9 @@
       EXPECT_EQ(UIAccessibilityTraitNotEnabled, item.accessibilityTraits);
     }
   }
-  if (use_mdc_style) {
     bool is_on = [rewriter_ defaultHandlerID] == nil;
     CheckSwitchCellStateAndTitleWithId(is_on, IDS_IOS_CHOOSE_EMAIL_ASK_TOGGLE,
                                        1, 0);
-  }
 }
 
 TEST_F(ComposeEmailHandlerCollectionViewControllerTest, TestSelection) {
@@ -144,12 +136,8 @@
 }
 
 // Tests the state of the mailto:// handler apps and as the "Always ask"
-// switch is toggled. This test is relevant only if MDC Style is enabled
-// because the switch exists only in MDC style.
+// switch is toggled.
 TEST_F(ComposeEmailHandlerCollectionViewControllerTest, TestSwitchChanged) {
-  if (!base::FeatureList::IsEnabled(kMailtoPromptInMdcStyle))
-    return;
-
   handlers_ = @[
     [[MailtoHandlerSystemMail alloc] init],
     [[FakeMailtoHandlerGmailInstalled alloc] init]
diff --git a/ios/chrome/browser/ui/settings/content_settings_collection_view_controller.mm b/ios/chrome/browser/ui/settings/content_settings_collection_view_controller.mm
index 92048a5..707cecf 100644
--- a/ios/chrome/browser/ui/settings/content_settings_collection_view_controller.mm
+++ b/ios/chrome/browser/ui/settings/content_settings_collection_view_controller.mm
@@ -23,8 +23,6 @@
 #import "ios/chrome/browser/ui/settings/settings_navigation_controller.h"
 #import "ios/chrome/browser/ui/settings/translate_collection_view_controller.h"
 #import "ios/chrome/browser/ui/settings/utils/content_setting_backed_boolean.h"
-#include "ios/chrome/browser/web/features.h"
-#import "ios/chrome/browser/web/legacy_mailto_url_rewriter.h"
 #import "ios/chrome/browser/web/nullable_mailto_url_rewriter.h"
 #include "ios/chrome/grit/ios_strings.h"
 #import "ios/third_party/material_components_ios/src/components/CollectionCells/src/MaterialCollectionCells.h"
@@ -109,9 +107,7 @@
     [_disablePopupsSetting setObserver:self];
 
     _mailtoURLRewriter =
-        base::FeatureList::IsEnabled(kMailtoPromptForUserChoice)
-            ? [NullableMailtoURLRewriter mailtoURLRewriterWithStandardHandlers]
-            : [LegacyMailtoURLRewriter mailtoURLRewriterWithStandardHandlers];
+        [NullableMailtoURLRewriter mailtoURLRewriterWithStandardHandlers];
     [_mailtoURLRewriter setObserver:self];
 
     // TODO(crbug.com/764578): -loadModel should not be called from
@@ -139,11 +135,8 @@
       toSectionWithIdentifier:SectionIdentifierSettings];
   [model addItem:[self translateItem]
       toSectionWithIdentifier:SectionIdentifierSettings];
-  // Show Compose Email setting if mailto: URL rewriting feature is enabled.
-  if (base::FeatureList::IsEnabled(kMailtoUrlRewriting)) {
-    [model addItem:[self composeEmailItem]
-        toSectionWithIdentifier:SectionIdentifierSettings];
-  }
+  [model addItem:[self composeEmailItem]
+      toSectionWithIdentifier:SectionIdentifierSettings];
 }
 
 - (CollectionViewItem*)blockPopupsItem {
diff --git a/ios/chrome/browser/ui/settings/content_settings_collection_view_controller_unittest.mm b/ios/chrome/browser/ui/settings/content_settings_collection_view_controller_unittest.mm
index f266b00..4ce23d1 100644
--- a/ios/chrome/browser/ui/settings/content_settings_collection_view_controller_unittest.mm
+++ b/ios/chrome/browser/ui/settings/content_settings_collection_view_controller_unittest.mm
@@ -4,11 +4,9 @@
 
 #import "ios/chrome/browser/ui/settings/content_settings_collection_view_controller.h"
 
-#include "base/test/scoped_feature_list.h"
 #include "ios/chrome/browser/browser_state/test_chrome_browser_state.h"
 #import "ios/chrome/browser/ui/collection_view/cells/collection_view_detail_item.h"
 #import "ios/chrome/browser/ui/collection_view/collection_view_controller_test.h"
-#include "ios/chrome/browser/web/features.h"
 #include "ios/chrome/grit/ios_strings.h"
 #include "ios/web/public/test/test_web_thread_bundle.h"
 #include "testing/gtest_mac.h"
@@ -43,9 +41,6 @@
 // rewriting feature is enabled.
 TEST_F(ContentSettingsCollectionViewControllerTest,
        TestModelWithMailToUrlRewriting) {
-  base::test::ScopedFeatureList feature_list;
-  feature_list.InitAndEnableFeature(kMailtoUrlRewriting);
-
   CreateController();
   CheckController();
   CheckTitleWithId(IDS_IOS_CONTENT_SETTINGS_TITLE);
@@ -59,22 +54,4 @@
   EXPECT_NSEQ(l10n_util::GetNSString(IDS_IOS_COMPOSE_EMAIL_SETTING), item.text);
 }
 
-// Tests that there are only 2 sections in Content Settings if mailto: URL
-// rewriting feature is disabled.
-TEST_F(ContentSettingsCollectionViewControllerTest,
-       TestModelWithoutMailToUrlRewriting) {
-  base::test::ScopedFeatureList feature_list;
-  feature_list.InitAndDisableFeature(kMailtoUrlRewriting);
-
-  CreateController();
-  CheckController();
-  CheckTitleWithId(IDS_IOS_CONTENT_SETTINGS_TITLE);
-
-  ASSERT_EQ(1, NumberOfSections());
-  ASSERT_EQ(2, NumberOfItemsInSection(0));
-  CheckDetailItemTextWithIds(IDS_IOS_BLOCK_POPUPS, IDS_IOS_SETTING_ON, 0, 0);
-  CheckDetailItemTextWithIds(IDS_IOS_TRANSLATE_SETTING, IDS_IOS_SETTING_ON, 0,
-                             1);
-}
-
 }  // namespace
diff --git a/ios/chrome/browser/ui/settings/settings_navigation_controller.mm b/ios/chrome/browser/ui/settings/settings_navigation_controller.mm
index 9002ab25..e3882fe 100644
--- a/ios/chrome/browser/ui/settings/settings_navigation_controller.mm
+++ b/ios/chrome/browser/ui/settings/settings_navigation_controller.mm
@@ -502,7 +502,10 @@
 
 #pragma mark - ApplicationSettingsCommands
 
-- (void)showAccountsSettings {
+- (void)showAccountsSettingsFromViewController:
+    (UIViewController*)baseViewController {
+  // |baseViewController| is intentionally unused because
+  // this navigation controller is already presented.
   AccountsCollectionViewController* controller =
       [[AccountsCollectionViewController alloc]
                initWithBrowserState:mainBrowserState_
diff --git a/ios/chrome/browser/ui/side_swipe/BUILD.gn b/ios/chrome/browser/ui/side_swipe/BUILD.gn
index 379b721..753a5329 100644
--- a/ios/chrome/browser/ui/side_swipe/BUILD.gn
+++ b/ios/chrome/browser/ui/side_swipe/BUILD.gn
@@ -13,6 +13,7 @@
     "side_swipe_controller.mm",
     "side_swipe_navigation_view.h",
     "side_swipe_navigation_view.mm",
+    "side_swipe_toolbar_interacting.h",
     "side_swipe_util.h",
     "side_swipe_util.mm",
   ]
@@ -28,6 +29,7 @@
     "//ios/chrome/browser/snapshots",
     "//ios/chrome/browser/tabs",
     "//ios/chrome/browser/ui",
+    "//ios/chrome/browser/ui/fullscreen",
     "//ios/chrome/browser/ui/ntp",
     "//ios/chrome/browser/ui/tabs/requirements",
     "//ios/chrome/browser/web",
diff --git a/ios/chrome/browser/ui/side_swipe/card_side_swipe_view.h b/ios/chrome/browser/ui/side_swipe/card_side_swipe_view.h
index d3493b7..e3fce97f 100644
--- a/ios/chrome/browser/ui/side_swipe/card_side_swipe_view.h
+++ b/ios/chrome/browser/ui/side_swipe/card_side_swipe_view.h
@@ -11,8 +11,8 @@
 #import "ios/chrome/browser/ui/side_swipe/side_swipe_controller.h"
 
 @class SideSwipeGestureRecognizer;
+@protocol SideSwipeToolbarInteracting;
 @class TabModel;
-@class WebToolbarController;
 
 @interface SwipeView : UIView {
   base::scoped_nsobject<UIImageView> image_;
@@ -43,13 +43,14 @@
 }
 
 @property(nonatomic, weak) id<SideSwipeControllerDelegate> delegate;
+@property(nonatomic, weak) id<SideSwipeToolbarInteracting>
+    toolbarInteractionHandler;
 @property(nonatomic, assign) CGFloat topMargin;
 
 - (id)initWithFrame:(CGRect)frame
           topMargin:(CGFloat)margin
               model:(TabModel*)model;
-- (void)updateViewsForDirection:(UISwipeGestureRecognizerDirection)direction
-                    withToolbar:(WebToolbarController*)toolbarController;
+- (void)updateViewsForDirection:(UISwipeGestureRecognizerDirection)direction;
 - (void)handleHorizontalPan:(SideSwipeGestureRecognizer*)gesture;
 
 @end
diff --git a/ios/chrome/browser/ui/side_swipe/card_side_swipe_view.mm b/ios/chrome/browser/ui/side_swipe/card_side_swipe_view.mm
index 66104fd6..a5762fd 100644
--- a/ios/chrome/browser/ui/side_swipe/card_side_swipe_view.mm
+++ b/ios/chrome/browser/ui/side_swipe/card_side_swipe_view.mm
@@ -16,9 +16,9 @@
 #import "ios/chrome/browser/ui/background_generator.h"
 #import "ios/chrome/browser/ui/ntp/new_tab_page_panel_protocol.h"
 #include "ios/chrome/browser/ui/rtl_geometry.h"
+#include "ios/chrome/browser/ui/side_swipe/side_swipe_toolbar_interacting.h"
 #import "ios/chrome/browser/ui/side_swipe/side_swipe_util.h"
 #import "ios/chrome/browser/ui/side_swipe_gesture_recognizer.h"
-#import "ios/chrome/browser/ui/toolbar/web_toolbar_controller.h"
 #include "ios/chrome/browser/ui/ui_util.h"
 #import "ios/chrome/browser/ui/uikit_ui_util.h"
 #import "ios/chrome/browser/ui/util/constraints_ui_util.h"
@@ -129,9 +129,7 @@
 // Is the current card is an edge card based on swipe direction.
 - (BOOL)isEdgeSwipe;
 // Initialize card based on model_ index.
-- (void)setupCard:(SwipeView*)card
-        withIndex:(NSInteger)index
-      withToolbar:(WebToolbarController*)toolbarController;
+- (void)setupCard:(SwipeView*)card withIndex:(NSInteger)index;
 // Build a |kResizeFactor| sized greyscaled version of |image|.
 - (UIImage*)smallGreyImage:(UIImage*)image;
 @end
@@ -139,6 +137,7 @@
 @implementation CardSideSwipeView
 
 @synthesize delegate = delegate_;
+@synthesize toolbarInteractionHandler = toolbarInteractionHandler_;
 @synthesize topMargin = topMargin_;
 
 - (id)initWithFrame:(CGRect)frame
@@ -184,26 +183,24 @@
 
 // Set up left and right card views depending on current tab and swipe
 // direction.
-- (void)updateViewsForDirection:(UISwipeGestureRecognizerDirection)direction
-                    withToolbar:(WebToolbarController*)tbc {
+- (void)updateViewsForDirection:(UISwipeGestureRecognizerDirection)direction {
   direction_ = direction;
   CGRect cardFrame = [self cardFrame];
   NSUInteger currentIndex = [model_ indexOfTab:model_.currentTab];
   CGFloat offset = UseRTLLayout() ? -1 : 1;
   if (direction_ == UISwipeGestureRecognizerDirectionRight) {
-    [self setupCard:rightCard_ withIndex:currentIndex withToolbar:tbc];
+    [self setupCard:rightCard_ withIndex:currentIndex];
     [rightCard_ setFrame:cardFrame];
-    [self setupCard:leftCard_ withIndex:currentIndex - offset withToolbar:tbc];
+    [self setupCard:leftCard_ withIndex:currentIndex - offset];
     cardFrame.origin.x -= cardFrame.size.width + kCardHorizontalSpacing;
     [leftCard_ setFrame:cardFrame];
   } else {
-    [self setupCard:leftCard_ withIndex:currentIndex withToolbar:tbc];
+    [self setupCard:leftCard_ withIndex:currentIndex];
     [leftCard_ setFrame:cardFrame];
-    [self setupCard:rightCard_ withIndex:currentIndex + offset withToolbar:tbc];
+    [self setupCard:rightCard_ withIndex:currentIndex + offset];
     cardFrame.origin.x += cardFrame.size.width + kCardHorizontalSpacing;
     [rightCard_ setFrame:cardFrame];
   }
-  [tbc resetToolbarAfterSideSwipeSnapshot];
 }
 
 - (UIImage*)smallGreyImage:(UIImage*)image {
@@ -219,9 +216,7 @@
 }
 
 // Create card view based on TabModel index.
-- (void)setupCard:(SwipeView*)card
-        withIndex:(NSInteger)index
-      withToolbar:(WebToolbarController*)toolbarController {
+- (void)setupCard:(SwipeView*)card withIndex:(NSInteger)index {
   if (index < 0 || index >= (NSInteger)[model_ count]) {
     [card setHidden:YES];
     return;
@@ -231,10 +226,8 @@
   Tab* tab = [model_ tabAtIndex:index];
   BOOL isNTP =
       tab.webState->GetLastCommittedURL().host_piece() == kChromeUINewTabHost;
-  [toolbarController updateToolbarForSideSwipeSnapshot:tab];
-  UIImage* toolbarView = CaptureViewWithOption([toolbarController view],
-                                               [[UIScreen mainScreen] scale],
-                                               kClientSideRendering);
+  UIImage* toolbarView =
+      [self.toolbarInteractionHandler toolbarSideSwipeSnapshotForTab:tab];
   [card setToolbarImage:toolbarView isNewTabPage:isNTP];
 
   // Converting snapshotted images to grey takes too much time for single core
diff --git a/ios/chrome/browser/ui/side_swipe/side_swipe_controller.h b/ios/chrome/browser/ui/side_swipe/side_swipe_controller.h
index 9a28ecd..44981ff 100644
--- a/ios/chrome/browser/ui/side_swipe/side_swipe_controller.h
+++ b/ios/chrome/browser/ui/side_swipe/side_swipe_controller.h
@@ -14,8 +14,8 @@
 
 @class CardSideSwipeView;
 @class SideSwipeGestureRecognizer;
+@protocol SideSwipeToolbarInteracting;
 @protocol TabStripHighlighting;
-@class WebToolbarController;
 
 // Notification sent when the user starts a side swipe (on tablet).
 extern NSString* const kSideSwipeWillStartNotification;
@@ -46,8 +46,6 @@
 - (void)sideSwipeViewDismissAnimationDidEnd:(UIView*)sideSwipeView;
 // Returns the main content view.
 - (UIView*)contentView;
-// Returns the toolbar controller.
-- (WebToolbarController*)toolbarController;
 // Makes |tab| the currently visible tab, displaying its view.  Calls
 // -selectedTabChanged on the toolbar only if |newSelection| is YES.
 - (void)displayTab:(Tab*)tab isNewSelection:(BOOL)newSelection;
@@ -75,6 +73,8 @@
 
 @property(nonatomic, assign) BOOL inSwipe;
 @property(nonatomic, weak) id<SideSwipeControllerDelegate> swipeDelegate;
+@property(nonatomic, weak) id<SideSwipeToolbarInteracting>
+    toolbarInteractionHandler;
 @property(nonatomic, weak) id<TabSnapshottingDelegate> snapshotDelegate;
 @property(nonatomic, weak) id<TabStripHighlighting> tabStripDelegate;
 
diff --git a/ios/chrome/browser/ui/side_swipe/side_swipe_controller.mm b/ios/chrome/browser/ui/side_swipe/side_swipe_controller.mm
index f45667f..a0d4b61d 100644
--- a/ios/chrome/browser/ui/side_swipe/side_swipe_controller.mm
+++ b/ios/chrome/browser/ui/side_swipe/side_swipe_controller.mm
@@ -6,6 +6,7 @@
 
 #include <memory>
 
+#include "base/feature_list.h"
 #include "components/reading_list/core/reading_list_model.h"
 #import "ios/chrome/browser/browser_state/chrome_browser_state.h"
 #import "ios/chrome/browser/infobars/infobar_container_view.h"
@@ -15,14 +16,15 @@
 #import "ios/chrome/browser/tabs/tab.h"
 #import "ios/chrome/browser/tabs/tab_model_observer.h"
 #import "ios/chrome/browser/tabs/tab_private.h"
+#import "ios/chrome/browser/ui/fullscreen/fullscreen_features.h"
 #import "ios/chrome/browser/ui/reading_list/reading_list_side_swipe_provider.h"
 #import "ios/chrome/browser/ui/side_swipe/card_side_swipe_view.h"
 #import "ios/chrome/browser/ui/side_swipe/history_side_swipe_provider.h"
 #import "ios/chrome/browser/ui/side_swipe/side_swipe_navigation_view.h"
+#include "ios/chrome/browser/ui/side_swipe/side_swipe_toolbar_interacting.h"
 #import "ios/chrome/browser/ui/side_swipe/side_swipe_util.h"
 #import "ios/chrome/browser/ui/side_swipe_gesture_recognizer.h"
 #import "ios/chrome/browser/ui/tabs/requirements/tab_strip_highlighting.h"
-#import "ios/chrome/browser/ui/toolbar/web_toolbar_controller.h"
 #include "ios/chrome/browser/ui/ui_util.h"
 #import "ios/chrome/browser/web/page_placeholder_tab_helper.h"
 #import "ios/web/public/web_state/web_state_observer_bridge.h"
@@ -118,6 +120,7 @@
 
 @synthesize inSwipe = inSwipe_;
 @synthesize swipeDelegate = swipeDelegate_;
+@synthesize toolbarInteractionHandler = _toolbarInteractionHandler;
 @synthesize snapshotDelegate = snapshotDelegate_;
 @synthesize tabStripDelegate = tabStripDelegate_;
 
@@ -213,17 +216,13 @@
   // Since the toolbar and the contentView can overlap, check the toolbar frame
   // first, and confirm the right gesture recognizer is firing.
   CGRect toolbarFrame =
-      CGRectInset([[[swipeDelegate_ toolbarController] view] frame], -1, -1);
+      CGRectInset([self.toolbarInteractionHandler toolbarView].frame, -1, -1);
   if (CGRectContainsPoint(toolbarFrame, location)) {
     if (![gesture isEqual:panGestureRecognizer_]) {
       return NO;
     }
 
-    if ([[swipeDelegate_ toolbarController] isOmniboxFirstResponder] ||
-        [[swipeDelegate_ toolbarController] showingOmniboxPopup]) {
-      return NO;
-    }
-    return YES;
+    return [self.toolbarInteractionHandler canBeginToolbarSwipe];
   }
 
   // Otherwise, only allow contentView touches with |swipeGestureRecognizer_|.
@@ -307,7 +306,9 @@
 
   if (gesture.state == UIGestureRecognizerStateBegan) {
     // If the toolbar is hidden, move it to visible.
-    [[model_ currentTab] updateFullscreenWithToolbarVisible:YES];
+    if (!base::FeatureList::IsEnabled(features::kNewFullscreen)) {
+      [[model_ currentTab] updateFullscreenWithToolbarVisible:YES];
+    }
     [[model_ currentTab] updateSnapshotWithOverlay:YES visibleFrameOnly:YES];
     [[NSNotificationCenter defaultCenter]
         postNotificationName:kSideSwipeWillStartNotification
@@ -390,8 +391,10 @@
 // Show swipe to navigate.
 - (void)handleSwipeToNavigate:(SideSwipeGestureRecognizer*)gesture {
   if (gesture.state == UIGestureRecognizerStateBegan) {
-    // If the toolbar is hidden, move it to visible.
-    [[model_ currentTab] updateFullscreenWithToolbarVisible:YES];
+    if (!base::FeatureList::IsEnabled(features::kNewFullscreen)) {
+      // If the toolbar is hidden, move it to visible.
+      [[model_ currentTab] updateFullscreenWithToolbarVisible:YES];
+    }
 
     inSwipe_ = YES;
     [swipeDelegate_ updateAccessoryViewsForSideSwipeWithVisibility:NO];
@@ -417,7 +420,7 @@
     [pageSideSwipeView_ setTargetView:[swipeDelegate_ contentView]];
 
     [gesture.view insertSubview:pageSideSwipeView_
-                   belowSubview:[[swipeDelegate_ toolbarController] view]];
+                   belowSubview:[self.toolbarInteractionHandler toolbarView]];
   }
 
   __weak Tab* weakCurrentTab = [model_ currentTab];
@@ -451,8 +454,10 @@
 // Show horizontal swipe stack view for iPhone.
 - (void)handleiPhoneTabSwipe:(SideSwipeGestureRecognizer*)gesture {
   if (gesture.state == UIGestureRecognizerStateBegan) {
-    // If the toolbar is hidden, move it to visible.
-    [[model_ currentTab] updateFullscreenWithToolbarVisible:YES];
+    if (!base::FeatureList::IsEnabled(features::kNewFullscreen)) {
+      // If the toolbar is hidden, move it to visible.
+      [[model_ currentTab] updateFullscreenWithToolbarVisible:YES];
+    }
 
     inSwipe_ = YES;
 
@@ -469,6 +474,8 @@
       tabSideSwipeView_ = [[CardSideSwipeView alloc] initWithFrame:frame
                                                          topMargin:headerHeight
                                                              model:model_];
+      tabSideSwipeView_.toolbarInteractionHandler =
+          self.toolbarInteractionHandler;
       [tabSideSwipeView_ setAutoresizingMask:UIViewAutoresizingFlexibleWidth |
                                              UIViewAutoresizingFlexibleHeight];
       [tabSideSwipeView_ setDelegate:swipeDelegate_];
@@ -482,9 +489,7 @@
     [swipeDelegate_ updateAccessoryViewsForSideSwipeWithVisibility:NO];
 
     // Layout tabs with new snapshots in the current orientation.
-    [tabSideSwipeView_
-        updateViewsForDirection:gesture.direction
-                    withToolbar:[swipeDelegate_ toolbarController]];
+    [tabSideSwipeView_ updateViewsForDirection:gesture.direction];
 
     // Insert behind infobar container (which is below toolbar)
     // so card border doesn't look janky during animation.
diff --git a/ios/chrome/browser/ui/side_swipe/side_swipe_toolbar_interacting.h b/ios/chrome/browser/ui/side_swipe/side_swipe_toolbar_interacting.h
new file mode 100644
index 0000000..51b1394b
--- /dev/null
+++ b/ios/chrome/browser/ui/side_swipe/side_swipe_toolbar_interacting.h
@@ -0,0 +1,25 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef IOS_CHROME_BROWSER_UI_SIDE_SWIPE_SIDE_SWIPE_TOOLBAR_INTERACTING_H_
+#define IOS_CHROME_BROWSER_UI_SIDE_SWIPE_SIDE_SWIPE_TOOLBAR_INTERACTING_H_
+
+#import <UIKit/UIKit.h>
+
+@class Tab;
+
+// Protocol used by SideSwipe to interact with the toolbar.
+@protocol SideSwipeToolbarInteracting
+
+// Returns the toolbar view.
+- (UIView*)toolbarView;
+// Returns whether a swipe on the toolbar can start.
+- (BOOL)canBeginToolbarSwipe;
+// Returns a snapshot of the toolbar with the controls visibility adapted to
+// |tab|.
+- (UIImage*)toolbarSideSwipeSnapshotForTab:(Tab*)tab;
+
+@end
+
+#endif  // IOS_CHROME_BROWSER_UI_SIDE_SWIPE_SIDE_SWIPE_TOOLBAR_INTERACTING_H_
diff --git a/ios/chrome/browser/ui/signin_interaction/signin_interaction_controller.mm b/ios/chrome/browser/ui/signin_interaction/signin_interaction_controller.mm
index f9557fd..f2870297 100644
--- a/ios/chrome/browser/ui/signin_interaction/signin_interaction_controller.mm
+++ b/ios/chrome/browser/ui/signin_interaction/signin_interaction_controller.mm
@@ -16,7 +16,6 @@
 #import "ios/chrome/browser/signin/signin_util.h"
 #import "ios/chrome/browser/ui/authentication/authentication_ui_util.h"
 #import "ios/chrome/browser/ui/authentication/chrome_signin_view_controller.h"
-#import "ios/chrome/browser/ui/commands/application_commands.h"
 #import "ios/chrome/browser/ui/signin_interaction/signin_interaction_presenting.h"
 #import "ios/public/provider/chrome/browser/chrome_browser_provider.h"
 #import "ios/public/provider/chrome/browser/signin/chrome_identity.h"
@@ -370,6 +369,11 @@
     [self dismissPresentedViewControllersAnimated:YES completion:nil];
   }
 
+  if (showAccountsSettings) {
+    [self.presenter showAccountsSettings];
+  }
+
+  // Cleaning up and calling the |completionCallback_| should be done last.
   identityInteractionManager_ = nil;
   signinViewController_ = nil;
   // Ensure self is not destroyed in the callbacks.
@@ -379,9 +383,6 @@
     completionCallback_ = nil;
   }
   strongSelf = nil;
-  if (showAccountsSettings) {
-    [self.dispatcher showAccountsSettings];
-  }
 }
 
 @end
diff --git a/ios/chrome/browser/ui/signin_interaction/signin_interaction_coordinator.mm b/ios/chrome/browser/ui/signin_interaction/signin_interaction_coordinator.mm
index 1ff4ca9..90235bc9 100644
--- a/ios/chrome/browser/ui/signin_interaction/signin_interaction_coordinator.mm
+++ b/ios/chrome/browser/ui/signin_interaction/signin_interaction_coordinator.mm
@@ -8,6 +8,7 @@
 #include "base/logging.h"
 #import "ios/chrome/browser/ui/alert_coordinator/alert_coordinator.h"
 #import "ios/chrome/browser/ui/authentication/authentication_ui_util.h"
+#import "ios/chrome/browser/ui/commands/application_commands.h"
 #import "ios/chrome/browser/ui/signin_interaction/signin_interaction_controller.h"
 #import "ios/chrome/browser/ui/signin_interaction/signin_interaction_presenting.h"
 #import "ios/chrome/browser/ui/util/top_view_controller.h"
@@ -164,6 +165,11 @@
   self.alertCoordinator = nil;
 }
 
+- (void)showAccountsSettings {
+  [self.dispatcher
+      showAccountsSettingsFromViewController:self.presentingViewController];
+}
+
 - (BOOL)isPresenting {
   return self.presentingViewController.presentedViewController != nil;
 }
diff --git a/ios/chrome/browser/ui/signin_interaction/signin_interaction_presenting.h b/ios/chrome/browser/ui/signin_interaction/signin_interaction_presenting.h
index 4110761..378dbc48 100644
--- a/ios/chrome/browser/ui/signin_interaction/signin_interaction_presenting.h
+++ b/ios/chrome/browser/ui/signin_interaction/signin_interaction_presenting.h
@@ -36,6 +36,9 @@
 // Dismisses the error dialog.
 - (void)dismissError;
 
+// Shows the accounts settings UI.
+- (void)showAccountsSettings;
+
 // Indicates whether the object is currently presenting.
 @property(nonatomic, assign, readonly, getter=isPresenting) BOOL presenting;
 
diff --git a/ios/chrome/browser/ui/stack_view/BUILD.gn b/ios/chrome/browser/ui/stack_view/BUILD.gn
index 66e737e..0e65a2d8 100644
--- a/ios/chrome/browser/ui/stack_view/BUILD.gn
+++ b/ios/chrome/browser/ui/stack_view/BUILD.gn
@@ -56,7 +56,8 @@
     "//ios/chrome/browser/ui/ntp:ntp_internal",
     "//ios/chrome/browser/ui/tab_switcher",
     "//ios/chrome/browser/ui/toolbar",
-    "//ios/chrome/browser/ui/toolbar:toolbar_base_feature",
+    "//ios/chrome/browser/ui/toolbar/public",
+    "//ios/chrome/browser/ui/toolbar/public:toolbar_base_feature",
     "//ios/chrome/browser/ui/tools_menu",
     "//ios/chrome/browser/ui/tools_menu:configuration",
     "//ios/chrome/common",
@@ -109,6 +110,7 @@
     "//ios/chrome/browser/browser_state",
     "//ios/chrome/browser/tabs",
     "//ios/chrome/browser/ui:ui_internal",
+    "//ios/chrome/browser/ui/toolbar/public",
     "//ios/chrome/browser/ui/tools_menu",
     "//ios/chrome/test/app:test_support",
     "//ios/chrome/test/earl_grey:test_support",
@@ -135,6 +137,7 @@
     "//ios/chrome/browser/ui",
     "//ios/chrome/browser/ui:ui_internal",
     "//ios/chrome/browser/ui/fullscreen",
+    "//ios/chrome/browser/ui/fullscreen:legacy_fullscreen",
     "//ios/web",
     "//net",
   ]
diff --git a/ios/chrome/browser/ui/stack_view/stack_view_controller.mm b/ios/chrome/browser/ui/stack_view/stack_view_controller.mm
index 4923d92..3b16e8a 100644
--- a/ios/chrome/browser/ui/stack_view/stack_view_controller.mm
+++ b/ios/chrome/browser/ui/stack_view/stack_view_controller.mm
@@ -49,10 +49,10 @@
 #import "ios/chrome/browser/ui/stack_view/stack_view_toolbar_controller.h"
 #import "ios/chrome/browser/ui/stack_view/title_label.h"
 #import "ios/chrome/browser/ui/toolbar/new_tab_button.h"
-#import "ios/chrome/browser/ui/toolbar/toolbar_controller_base_feature.h"
-#import "ios/chrome/browser/ui/toolbar/toolbar_controller_constants.h"
+#import "ios/chrome/browser/ui/toolbar/public/toolbar_controller_base_feature.h"
+#import "ios/chrome/browser/ui/toolbar/public/toolbar_controller_constants.h"
+#import "ios/chrome/browser/ui/toolbar/public/toolbar_utils.h"
 #import "ios/chrome/browser/ui/toolbar/toolbar_owner.h"
-#import "ios/chrome/browser/ui/toolbar/toolbar_utils.h"
 #import "ios/chrome/browser/ui/tools_menu/tools_menu_configuration.h"
 #import "ios/chrome/browser/ui/tools_menu/tools_menu_view_item.h"
 #import "ios/chrome/browser/ui/ui_util.h"
@@ -1628,6 +1628,7 @@
     [_animationDelegate tabSwitcherPresentationAnimationDidEnd:self];
     [_delegate tabSwitcherPresentationTransitionDidEnd:self];
   } else {
+    [_animationDelegate tabSwitcherDismissalAnimationDidEnd:self];
     [_delegate tabSwitcherDismissTransitionDidEnd:self];
   }
 }
@@ -2151,6 +2152,7 @@
   void (^completionBlock)(void) = ^{
     [newCard removeFromSuperview];
     [[_scrollView layer] setShouldRasterize:NO];
+    [_animationDelegate tabSwitcherDismissalAnimationDidEnd:self];
     [_delegate tabSwitcherDismissTransitionDidEnd:self];
     double duration = [NSDate timeIntervalSinceReferenceDate] - startTime;
     if (_activeCardSet.tabModel.isOffTheRecord) {
diff --git a/ios/chrome/browser/ui/stack_view/stack_view_egtest.mm b/ios/chrome/browser/ui/stack_view/stack_view_egtest.mm
index 6e5dff2..60d4ec7 100644
--- a/ios/chrome/browser/ui/stack_view/stack_view_egtest.mm
+++ b/ios/chrome/browser/ui/stack_view/stack_view_egtest.mm
@@ -16,7 +16,7 @@
 #import "ios/chrome/browser/ui/stack_view/card_view.h"
 #import "ios/chrome/browser/ui/stack_view/stack_view_controller.h"
 #import "ios/chrome/browser/ui/stack_view/stack_view_controller_private.h"
-#import "ios/chrome/browser/ui/toolbar/toolbar_controller_constants.h"
+#import "ios/chrome/browser/ui/toolbar/public/toolbar_controller_constants.h"
 #include "ios/chrome/browser/ui/tools_menu/tools_menu_constants.h"
 #include "ios/chrome/test/app/chrome_test_util.h"
 #import "ios/chrome/test/app/stack_view_test_util.h"
diff --git a/ios/chrome/browser/ui/stack_view/stack_view_toolbar_controller.mm b/ios/chrome/browser/ui/stack_view/stack_view_toolbar_controller.mm
index 8b1bb6a..2be9abf 100644
--- a/ios/chrome/browser/ui/stack_view/stack_view_toolbar_controller.mm
+++ b/ios/chrome/browser/ui/stack_view/stack_view_toolbar_controller.mm
@@ -13,8 +13,8 @@
 #import "ios/chrome/browser/ui/image_util.h"
 #import "ios/chrome/browser/ui/rtl_geometry.h"
 #import "ios/chrome/browser/ui/toolbar/new_tab_button.h"
+#import "ios/chrome/browser/ui/toolbar/public/toolbar_controller_constants.h"
 #import "ios/chrome/browser/ui/toolbar/toolbar_controller+protected.h"
-#import "ios/chrome/browser/ui/toolbar/toolbar_controller_constants.h"
 #import "ios/chrome/browser/ui/uikit_ui_util.h"
 
 #if !defined(__has_feature) || !__has_feature(objc_arc)
diff --git a/ios/chrome/browser/ui/tab_switcher/BUILD.gn b/ios/chrome/browser/ui/tab_switcher/BUILD.gn
index 03801fea..93e63ea6 100644
--- a/ios/chrome/browser/ui/tab_switcher/BUILD.gn
+++ b/ios/chrome/browser/ui/tab_switcher/BUILD.gn
@@ -85,6 +85,7 @@
     "//ios/chrome/browser/ui/settings/sync_utils",
     "//ios/chrome/browser/ui/tabs/requirements",
     "//ios/chrome/browser/ui/toolbar",
+    "//ios/chrome/browser/ui/toolbar",
     "//ios/chrome/browser/web_state_list",
     "//ios/chrome/common:ios_app_bundle_id_prefix_header",
     "//ios/public/provider/chrome/browser",
diff --git a/ios/chrome/browser/ui/tab_switcher/tab_switcher.h b/ios/chrome/browser/ui/tab_switcher/tab_switcher.h
index e7d04632..398f80b 100644
--- a/ios/chrome/browser/ui/tab_switcher/tab_switcher.h
+++ b/ios/chrome/browser/ui/tab_switcher/tab_switcher.h
@@ -49,6 +49,9 @@
 // Informs the delegate that a TabSwitcher presentation animation has completed.
 - (void)tabSwitcherPresentationAnimationDidEnd:(id<TabSwitcher>)tabSwitcher;
 
+// Informs the delegate that a TabSwitcher dismissal animation has completed.
+- (void)tabSwitcherDismissalAnimationDidEnd:(id<TabSwitcher>)tabSwitcher;
+
 @end
 
 // This protocol describes the common interface between the two implementations
diff --git a/ios/chrome/browser/ui/tab_switcher/tab_switcher_controller.mm b/ios/chrome/browser/ui/tab_switcher/tab_switcher_controller.mm
index de55b81..cd4869e 100644
--- a/ios/chrome/browser/ui/tab_switcher/tab_switcher_controller.mm
+++ b/ios/chrome/browser/ui/tab_switcher/tab_switcher_controller.mm
@@ -813,6 +813,8 @@
                            withModel:model
                             animated:animated
                       withCompletion:^{
+                        [self.animationDelegate
+                            tabSwitcherDismissalAnimationDidEnd:self];
                         [self.delegate tabSwitcherDismissTransitionDidEnd:self];
                       }];
 }
diff --git a/ios/chrome/browser/ui/tab_switcher/tab_switcher_transition_context.mm b/ios/chrome/browser/ui/tab_switcher/tab_switcher_transition_context.mm
index 5c29838..241a1021 100644
--- a/ios/chrome/browser/ui/tab_switcher/tab_switcher_transition_context.mm
+++ b/ios/chrome/browser/ui/tab_switcher/tab_switcher_transition_context.mm
@@ -7,6 +7,7 @@
 #import "ios/chrome/browser/tabs/tab.h"
 #import "ios/chrome/browser/ui/browser_view_controller.h"
 #include "ios/chrome/browser/ui/tab_switcher/tab_switcher_transition_context.h"
+#import "ios/chrome/browser/ui/toolbar/toolbar_snapshot_providing.h"
 #import "ios/chrome/browser/ui/toolbar/web_toolbar_controller.h"
 #import "ios/chrome/browser/ui/uikit_ui_util.h"
 
@@ -38,15 +39,8 @@
     [bvc.view setFrame:[[UIScreen mainScreen] bounds]];
   }
 
-  UIView* toolbarView = [[bvc toolbarController] view];
-  UIView* toolbarSnapshotView;
-  if ([toolbarView window]) {
-    toolbarSnapshotView = [toolbarView snapshotViewAfterScreenUpdates:NO];
-  } else {
-    toolbarSnapshotView = [[UIView alloc] initWithFrame:toolbarView.frame];
-    [toolbarSnapshotView layer].contents = static_cast<id>(
-        CaptureViewWithOption(toolbarView, 1, kClientSideRendering).CGImage);
-  }
+  UIView* toolbarSnapshotView =
+      [bvc.toolbarSnapshotProvider snapshotForTabSwitcher];
   transitionContextContent.toolbarSnapshotView = toolbarSnapshotView;
   transitionContextContent->_bvc = bvc;
   return transitionContextContent;
diff --git a/ios/chrome/browser/ui/toolbar/BUILD.gn b/ios/chrome/browser/ui/toolbar/BUILD.gn
index 2bc89c3..4adf3a6 100644
--- a/ios/chrome/browser/ui/toolbar/BUILD.gn
+++ b/ios/chrome/browser/ui/toolbar/BUILD.gn
@@ -13,8 +13,6 @@
     "toolbar_controller+protected.h",
     "toolbar_controller.h",
     "toolbar_controller.mm",
-    "toolbar_controller_constants.h",
-    "toolbar_controller_constants.mm",
     "toolbar_coordinator.h",
     "toolbar_coordinator.mm",
     "toolbar_frame_delegate.h",
@@ -24,23 +22,21 @@
     "toolbar_model_impl_ios.mm",
     "toolbar_model_ios.h",
     "toolbar_owner.h",
+    "toolbar_snapshot_providing.h",
     "toolbar_tools_menu_button.h",
     "toolbar_tools_menu_button.mm",
-    "toolbar_utils.h",
-    "toolbar_utils.mm",
     "toolbar_view.h",
     "toolbar_view.mm",
     "tools_menu_button_observer_bridge.h",
     "tools_menu_button_observer_bridge.mm",
     "web_toolbar_controller.h",
     "web_toolbar_controller.mm",
-    "web_toolbar_controller_constants.h",
-    "web_toolbar_controller_constants.mm",
     "web_toolbar_delegate.h",
   ]
   deps = [
     ":resource_macros",
-    ":toolbar_base_feature",
+    "public",
+    "public:toolbar_base_feature",
     "resources:collapse",
     "resources:collapse_incognito",
     "resources:collapse_pressed",
@@ -100,7 +96,6 @@
     "//ios/web",
     "//net",
     "//ui/base",
-    "//ui/gfx",
 
     # Fake dependencies to break cycles
     "//ios/chrome/browser/ui/ntp",
@@ -128,16 +123,6 @@
   ]
 }
 
-source_set("toolbar_base_feature") {
-  sources = [
-    "toolbar_controller_base_feature.h",
-    "toolbar_controller_base_feature.mm",
-  ]
-  deps = [
-    "//base",
-  ]
-}
-
 source_set("test_support") {
   configs += [ "//build/config/compiler:enable_arc" ]
   testonly = true
diff --git a/ios/chrome/browser/ui/toolbar/keyboard_assist/OWNERS b/ios/chrome/browser/ui/toolbar/keyboard_assist/OWNERS
index c85e66a..3f33d7b 100644
--- a/ios/chrome/browser/ui/toolbar/keyboard_assist/OWNERS
+++ b/ios/chrome/browser/ui/toolbar/keyboard_assist/OWNERS
@@ -1,4 +1,4 @@
-jif@chromium.org
+lod@chromium.org
 
 # TEAM: ios-directory-owners@chromium.org
 # OS: iOS
diff --git a/ios/chrome/browser/ui/toolbar/public/BUILD.gn b/ios/chrome/browser/ui/toolbar/public/BUILD.gn
new file mode 100644
index 0000000..4d5aae0
--- /dev/null
+++ b/ios/chrome/browser/ui/toolbar/public/BUILD.gn
@@ -0,0 +1,30 @@
+# Copyright 2017 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+source_set("public") {
+  configs += [ "//build/config/compiler:enable_arc" ]
+  sources = [
+    "toolbar_controller_constants.h",
+    "toolbar_controller_constants.mm",
+    "toolbar_utils.h",
+    "toolbar_utils.mm",
+    "web_toolbar_controller_constants.h",
+    "web_toolbar_controller_constants.mm",
+  ]
+  deps = [
+    ":toolbar_base_feature",
+    "//base",
+    "//ios/chrome/browser/ui",
+  ]
+}
+
+source_set("toolbar_base_feature") {
+  sources = [
+    "toolbar_controller_base_feature.h",
+    "toolbar_controller_base_feature.mm",
+  ]
+  deps = [
+    "//base",
+  ]
+}
diff --git a/ios/chrome/browser/ui/toolbar/toolbar_controller_base_feature.h b/ios/chrome/browser/ui/toolbar/public/toolbar_controller_base_feature.h
similarity index 100%
rename from ios/chrome/browser/ui/toolbar/toolbar_controller_base_feature.h
rename to ios/chrome/browser/ui/toolbar/public/toolbar_controller_base_feature.h
diff --git a/ios/chrome/browser/ui/toolbar/public/toolbar_controller_base_feature.mm b/ios/chrome/browser/ui/toolbar/public/toolbar_controller_base_feature.mm
new file mode 100644
index 0000000..3cf69e8
--- /dev/null
+++ b/ios/chrome/browser/ui/toolbar/public/toolbar_controller_base_feature.mm
@@ -0,0 +1,8 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#import "ios/chrome/browser/ui/toolbar/public/toolbar_controller_base_feature.h"
+
+const base::Feature kSafeAreaCompatibleToolbar{
+    "SafeAreaCompatibleToolbar", base::FEATURE_DISABLED_BY_DEFAULT};
diff --git a/ios/chrome/browser/ui/toolbar/toolbar_controller_constants.h b/ios/chrome/browser/ui/toolbar/public/toolbar_controller_constants.h
similarity index 100%
rename from ios/chrome/browser/ui/toolbar/toolbar_controller_constants.h
rename to ios/chrome/browser/ui/toolbar/public/toolbar_controller_constants.h
diff --git a/ios/chrome/browser/ui/toolbar/public/toolbar_controller_constants.mm b/ios/chrome/browser/ui/toolbar/public/toolbar_controller_constants.mm
new file mode 100644
index 0000000..35a2eb9
--- /dev/null
+++ b/ios/chrome/browser/ui/toolbar/public/toolbar_controller_constants.mm
@@ -0,0 +1,73 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#import "ios/chrome/browser/ui/toolbar/public/toolbar_controller_constants.h"
+
+#if !defined(__has_feature) || !__has_feature(objc_arc)
+#error "This file requires ARC support."
+#endif
+
+const int64_t kNonInitialImageAdditionDelayNanosec = 500000LL;
+
+NSString* const kMenuWillShowNotification = @"kMenuWillShowNotification";
+NSString* const kMenuWillHideNotification = @"kMenuWillHideNotification";
+
+NSString* const kToolbarIdentifier = @"kToolbarIdentifier";
+NSString* const kIncognitoToolbarIdentifier = @"kIncognitoToolbarIdentifier";
+NSString* const kToolbarToolsMenuButtonIdentifier =
+    @"kToolbarToolsMenuButtonIdentifier";
+NSString* const kToolbarStackButtonIdentifier =
+    @"kToolbarStackButtonIdentifier";
+NSString* const kToolbarShareButtonIdentifier =
+    @"kToolbarShareButtonIdentifier";
+
+const NSInteger kStackButtonMaxTabCount = 99;
+
+NSString* const kToolbarTransitionAnimationKey = @"ToolbarTransitionAnimation";
+
+const NSInteger kFontSizeFewerThanTenTabs = 11;
+const NSInteger kFontSizeTenTabsOrMore = 9;
+
+const NSUInteger kTransitionLayerCapacity = 11;
+
+// Macros for creating CGRects of height H, origin (0,0), with the portrait
+// width of phone/pad devices.
+// clang-format off
+#define IPHONE_FRAME(H) { { 0, 0 }, { kPortraitWidth[IPHONE_IDIOM], H } }
+#define IPAD_FRAME(H)   { { 0, 0 }, { kPortraitWidth[IPAD_IDIOM],   H } }
+// Makes a two-element C array of CGRects as described above, one for each
+// device idiom.
+#define FRAME_PAIR(H) { IPHONE_FRAME(H), IPAD_FRAME(H) }
+// clang-format on
+
+const CGRect kToolbarFrame[INTERFACE_IDIOM_COUNT] = FRAME_PAIR(56);
+const CGRect kBackgroundViewFrame[INTERFACE_IDIOM_COUNT] = FRAME_PAIR(56);
+const CGRect kShadowViewFrame[INTERFACE_IDIOM_COUNT] = FRAME_PAIR(2);
+const CGRect kFullBleedShadowViewFrame = IPHONE_FRAME(10);
+
+const CGFloat kStackButtonNormalColors[] = {
+    85.0 / 255.0,   // ToolbarControllerStyleLightMode
+    238.0 / 255.0,  // ToolbarControllerStyleDarkMode
+    238.0 / 255.0,  // ToolbarControllerStyleIncognitoMode
+};
+const int kStackButtonHighlightedColors[] = {
+    0x4285F4,  // ToolbarControllerStyleLightMode
+    0x888a8c,  // ToolbarControllerStyleDarkMode
+    0x888a8c,  // ToolbarControllerStyleIncognitoMode
+};
+
+// clang-format off
+const LayoutRect kStackButtonFrame =
+{kPortraitWidth[IPHONE_IDIOM], {230, 4}, {48, 48}};
+const LayoutRect kShareMenuButtonFrame =
+{kPortraitWidth[IPAD_IDIOM], {680, 4}, {46, 48}};
+const LayoutRect kToolsMenuButtonFrame[INTERFACE_IDIOM_COUNT] = {
+  {kPortraitWidth[IPHONE_IDIOM], {276, 4}, {44, 48}},
+  {kPortraitWidth[IPAD_IDIOM], {723, 4}, {46, 48}}
+};
+// clang-format on
+
+const LayoutOffset kButtonFadeOutXOffset = 10;
+
+const CGFloat kPopoverAnchorHorizontalPadding = 10.0;
diff --git a/ios/chrome/browser/ui/toolbar/toolbar_utils.h b/ios/chrome/browser/ui/toolbar/public/toolbar_utils.h
similarity index 100%
rename from ios/chrome/browser/ui/toolbar/toolbar_utils.h
rename to ios/chrome/browser/ui/toolbar/public/toolbar_utils.h
diff --git a/ios/chrome/browser/ui/toolbar/public/toolbar_utils.mm b/ios/chrome/browser/ui/toolbar/public/toolbar_utils.mm
new file mode 100644
index 0000000..3e002a7
--- /dev/null
+++ b/ios/chrome/browser/ui/toolbar/public/toolbar_utils.mm
@@ -0,0 +1,25 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#import "ios/chrome/browser/ui/toolbar/public/toolbar_utils.h"
+
+#include "base/feature_list.h"
+#include "base/logging.h"
+#import "ios/chrome/browser/ui/toolbar/public/toolbar_controller_base_feature.h"
+#import "ios/chrome/browser/ui/toolbar/public/toolbar_controller_constants.h"
+#import "ios/chrome/browser/ui/ui_util.h"
+
+#if !defined(__has_feature) || !__has_feature(objc_arc)
+#error "This file requires ARC support."
+#endif
+
+CGFloat ToolbarHeightWithTopOfScreenOffset(CGFloat status_bar_offset) {
+  DCHECK(base::FeatureList::IsEnabled(kSafeAreaCompatibleToolbar));
+  InterfaceIdiom idiom = IsIPadIdiom() ? IPAD_IDIOM : IPHONE_IDIOM;
+  CGRect frame = kToolbarFrame[idiom];
+  if (idiom == IPHONE_IDIOM) {
+    frame.size.height += status_bar_offset;
+  }
+  return frame.size.height;
+}
diff --git a/ios/chrome/browser/ui/toolbar/public/web_toolbar_controller_constants.h b/ios/chrome/browser/ui/toolbar/public/web_toolbar_controller_constants.h
new file mode 100644
index 0000000..5feeed64
--- /dev/null
+++ b/ios/chrome/browser/ui/toolbar/public/web_toolbar_controller_constants.h
@@ -0,0 +1,105 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef IOS_CHROME_BROWSER_UI_TOOLBAR_WEB_TOOLBAR_CONTROLLER_CONSTANTS_H_
+#define IOS_CHROME_BROWSER_UI_TOOLBAR_WEB_TOOLBAR_CONTROLLER_CONSTANTS_H_
+
+#import <Foundation/Foundation.h>
+
+#import <UIKit/UIKit.h>
+#include "ios/chrome/browser/ui/rtl_geometry.h"
+#import "ios/chrome/browser/ui/toolbar/public/toolbar_controller_constants.h"
+#include "ios/chrome/browser/ui/ui_util.h"
+
+// The brightness of the omnibox placeholder text in regular mode,
+// on an iPhone.
+extern const CGFloat kiPhoneOmniboxPlaceholderColorBrightness;
+
+// The histogram recording CLAuthorizationStatus for omnibox queries.
+extern const char* const kOmniboxQueryLocationAuthorizationStatusHistogram;
+// The number of possible CLAuthorizationStatus values to report.
+const int kLocationAuthorizationStatusCount = 4;
+
+// The brightness of the toolbar's background color (visible on NTPs when the
+// background view is hidden).
+extern const CGFloat kNTPBackgroundColorBrightness;
+extern const CGFloat kNTPBackgroundColorBrightnessIncognito;
+
+// How far below the omnibox to position the popup.
+extern const CGFloat kiPadOmniboxPopupVerticalOffset;
+
+// Padding to place on the sides of the omnibox when expanded.
+extern const CGFloat kExpandedOmniboxPadding;
+
+// Padding between the back button and the omnibox when the forward button isn't
+// displayed.
+extern const CGFloat kBackButtonTrailingPadding;
+extern const CGFloat kForwardButtonTrailingPadding;
+extern const CGFloat kReloadButtonTrailingPadding;
+
+// Cancel button sizing.
+extern const CGFloat kCancelButtonBottomMargin;
+extern const CGFloat kCancelButtonTopMargin;
+extern const CGFloat kCancelButtonLeadingMargin;
+extern const CGFloat kCancelButtonWidth;
+
+// Additional offset to adjust the y coordinate of the determinate progress bar
+// up by.
+extern const CGFloat kDeterminateProgressBarYOffset;
+extern const CGFloat kMaterialProgressBarHeight;
+extern const CGFloat kLoadCompleteHideProgressBarDelay;
+// The default position animation is 10 pixels toward the trailing side, so
+// that's a negative leading offset.
+extern const LayoutOffset kPositionAnimationLeadingOffset;
+
+extern const CGFloat kIPadToolbarY;
+extern const CGFloat kScrollFadeDistance;
+// Offset from the image edge to the beginning of the visible omnibox rectangle.
+// The image is symmetrical, so the offset is equal on each side.
+extern const CGFloat kBackgroundImageVisibleRectOffset;
+
+extern const CGFloat kWebToolbarWidths[INTERFACE_IDIOM_COUNT];
+// UI layouts.  iPhone values followed by iPad values.
+// Frame for the WebToolbar-specific container, which is a subview of the
+// toolbar view itself.
+extern const LayoutRect kWebToolbarFrame[INTERFACE_IDIOM_COUNT];
+
+// Layouts inside the WebToolbar frame
+extern const LayoutRect kOmniboxFrame[INTERFACE_IDIOM_COUNT];
+extern const LayoutRect kBackButtonFrame[INTERFACE_IDIOM_COUNT];
+extern const LayoutRect kForwardButtonFrame[INTERFACE_IDIOM_COUNT];
+
+// iPad-only layouts
+// Layout for both the stop and reload buttons, which are in the same location.
+extern const LayoutRect kStopReloadButtonFrame;
+extern const LayoutRect kStarButtonFrame;
+extern const LayoutRect kVoiceSearchButtonFrame;
+
+// Vertical distance between the y-coordinate of the omnibox's center and the
+// y-coordinate of the web toolbar's center.
+extern const CGFloat kOmniboxCenterOffsetY;
+
+// Last button in accessory view for keyboard, commonly used TLD.
+extern NSString* const kDotComTLD;
+
+enum {
+  WebToolbarButtonNameBack = NumberOfToolbarButtonNames,
+  WebToolbarButtonNameCallingApp,
+  WebToolbarButtonNameForward,
+  WebToolbarButtonNameReload,
+  WebToolbarButtonNameStar,
+  WebToolbarButtonNameStop,
+  WebToolbarButtonNameTTS,
+  WebToolbarButtonNameVoice,
+  NumberOfWebToolbarButtonNames,
+};
+
+// Helper functions.
+void RunBlockAfterDelay(NSTimeInterval delay, void (^block)(void));
+CGRect RectShiftedDownForStatusBar(CGRect rect);
+CGRect RectShiftedUpForStatusBar(CGRect rect);
+CGRect RectShiftedUpAndResizedForStatusBar(CGRect rect);
+CGRect RectShiftedDownAndResizedForStatusBar(CGRect rect);
+
+#endif  // IOS_CHROME_BROWSER_UI_TOOLBAR_WEB_TOOLBAR_CONTROLLER_CONSTANTS_H_
diff --git a/ios/chrome/browser/ui/toolbar/public/web_toolbar_controller_constants.mm b/ios/chrome/browser/ui/toolbar/public/web_toolbar_controller_constants.mm
new file mode 100644
index 0000000..cd632b7
--- /dev/null
+++ b/ios/chrome/browser/ui/toolbar/public/web_toolbar_controller_constants.mm
@@ -0,0 +1,109 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#import "ios/chrome/browser/ui/toolbar/public/web_toolbar_controller_constants.h"
+
+#include "base/logging.h"
+
+#if !defined(__has_feature) || !__has_feature(objc_arc)
+#error "This file requires ARC support."
+#endif
+
+const CGFloat kiPhoneOmniboxPlaceholderColorBrightness = 150 / 255.0;
+
+const char* const kOmniboxQueryLocationAuthorizationStatusHistogram =
+    "Omnibox.QueryIosLocationAuthorizationStatus";
+
+const CGFloat kNTPBackgroundColorBrightness = 1.0;
+const CGFloat kNTPBackgroundColorBrightnessIncognito = 34.0 / 255.0;
+
+const CGFloat kiPadOmniboxPopupVerticalOffset = 3;
+
+const CGFloat kExpandedOmniboxPadding = 6;
+
+const CGFloat kBackButtonTrailingPadding = 7.0;
+const CGFloat kForwardButtonTrailingPadding = -1.0;
+const CGFloat kReloadButtonTrailingPadding = 4.0;
+
+const CGFloat kCancelButtonBottomMargin = 4.0;
+const CGFloat kCancelButtonTopMargin = 4.0;
+const CGFloat kCancelButtonLeadingMargin = 7.0;
+const CGFloat kCancelButtonWidth = 40.0;
+
+const CGFloat kDeterminateProgressBarYOffset = 1.0;
+const CGFloat kMaterialProgressBarHeight = 2.0;
+const CGFloat kLoadCompleteHideProgressBarDelay = 0.5;
+const LayoutOffset kPositionAnimationLeadingOffset = -10.0;
+
+const CGFloat kIPadToolbarY = 53;
+const CGFloat kScrollFadeDistance = 30;
+const CGFloat kBackgroundImageVisibleRectOffset = 6;
+
+const CGFloat kWebToolbarWidths[INTERFACE_IDIOM_COUNT] = {224, 720};
+// clang-format off
+const LayoutRect kWebToolbarFrame[INTERFACE_IDIOM_COUNT] = {
+  {kPortraitWidth[IPHONE_IDIOM], LayoutRectPositionZero,
+    {kWebToolbarWidths[IPHONE_IDIOM], 56}},
+  {kPortraitWidth[IPAD_IDIOM],   LayoutRectPositionZero,
+    {kWebToolbarWidths[IPAD_IDIOM],   56}},
+};
+
+#define IPHONE_LAYOUT(L, Y, H, W) \
+{ kWebToolbarWidths[IPHONE_IDIOM], {L, Y}, {H, W} }
+#define IPAD_LAYOUT(L, Y, H, W) \
+{ kWebToolbarWidths[IPAD_IDIOM], {L, Y}, {H, W} }
+
+// Layouts inside the WebToolbar frame
+const LayoutRect kOmniboxFrame[INTERFACE_IDIOM_COUNT] = {
+  IPHONE_LAYOUT(55, 7, 169, 43), IPAD_LAYOUT(152, 7, 568, 43),
+};
+const LayoutRect kBackButtonFrame[INTERFACE_IDIOM_COUNT] = {
+  IPHONE_LAYOUT(0, 4, 48, 48), IPAD_LAYOUT(4, 4, 48, 48),
+};
+const LayoutRect kForwardButtonFrame[INTERFACE_IDIOM_COUNT] = {
+  IPHONE_LAYOUT(48, 4, 48, 48), IPAD_LAYOUT(52, 4, 48, 48),
+};
+// clang-format on
+
+const LayoutRect kStopReloadButtonFrame = IPAD_LAYOUT(100, 4, 48, 48);
+const LayoutRect kStarButtonFrame = IPAD_LAYOUT(644, 4, 36, 48);
+const LayoutRect kVoiceSearchButtonFrame = IPAD_LAYOUT(680, 4, 36, 48);
+
+const CGFloat kOmniboxCenterOffsetY = 0.5;
+
+NSString* const kDotComTLD = @".com";
+
+void RunBlockAfterDelay(NSTimeInterval delay, void (^block)(void)) {
+  DCHECK([NSThread isMainThread]);
+  dispatch_after(dispatch_time(DISPATCH_TIME_NOW, NSEC_PER_SEC * delay),
+                 dispatch_get_main_queue(), block);
+}
+
+CGRect RectShiftedDownForStatusBar(CGRect rect) {
+  if (IsIPadIdiom())
+    return rect;
+  rect.origin.y += StatusBarHeight();
+  return rect;
+}
+
+CGRect RectShiftedUpForStatusBar(CGRect rect) {
+  if (IsIPadIdiom())
+    return rect;
+  rect.origin.y -= StatusBarHeight();
+  return rect;
+}
+
+CGRect RectShiftedUpAndResizedForStatusBar(CGRect rect) {
+  if (IsIPadIdiom())
+    return rect;
+  rect.size.height += StatusBarHeight();
+  return RectShiftedUpForStatusBar(rect);
+}
+
+CGRect RectShiftedDownAndResizedForStatusBar(CGRect rect) {
+  if (IsIPadIdiom())
+    return rect;
+  rect.size.height -= StatusBarHeight();
+  return RectShiftedDownForStatusBar(rect);
+}
diff --git a/ios/chrome/browser/ui/toolbar/toolbar_button_tints.h b/ios/chrome/browser/ui/toolbar/toolbar_button_tints.h
index 9be01194..a543d51 100644
--- a/ios/chrome/browser/ui/toolbar/toolbar_button_tints.h
+++ b/ios/chrome/browser/ui/toolbar/toolbar_button_tints.h
@@ -7,7 +7,7 @@
 
 #import <UIKit/UIKit.h>
 
-#import "ios/chrome/browser/ui/toolbar/toolbar_controller_constants.h"
+#import "ios/chrome/browser/ui/toolbar/public/toolbar_controller_constants.h"
 
 namespace toolbar {
 
diff --git a/ios/chrome/browser/ui/toolbar/toolbar_controller+protected.h b/ios/chrome/browser/ui/toolbar/toolbar_controller+protected.h
index 8caf08e9..76671a0 100644
--- a/ios/chrome/browser/ui/toolbar/toolbar_controller+protected.h
+++ b/ios/chrome/browser/ui/toolbar/toolbar_controller+protected.h
@@ -5,8 +5,8 @@
 #ifndef IOS_CHROME_BROWSER_UI_TOOLBAR_TOOLBAR_CONTROLLER_PROTECTED_H_
 #define IOS_CHROME_BROWSER_UI_TOOLBAR_TOOLBAR_CONTROLLER_PROTECTED_H_
 
+#import "ios/chrome/browser/ui/toolbar/public/toolbar_controller_constants.h"
 #import "ios/chrome/browser/ui/toolbar/toolbar_controller.h"
-#import "ios/chrome/browser/ui/toolbar/toolbar_controller_constants.h"
 
 @interface ToolbarController (Protected)
 
diff --git a/ios/chrome/browser/ui/toolbar/toolbar_controller.h b/ios/chrome/browser/ui/toolbar/toolbar_controller.h
index 8c79521..c01bbd4 100644
--- a/ios/chrome/browser/ui/toolbar/toolbar_controller.h
+++ b/ios/chrome/browser/ui/toolbar/toolbar_controller.h
@@ -10,7 +10,7 @@
 #import "base/mac/scoped_nsobject.h"
 #import "ios/chrome/browser/ui/activity_services/requirements/activity_service_positioner.h"
 #import "ios/chrome/browser/ui/bubble/bubble_view_anchor_point_provider.h"
-#import "ios/chrome/browser/ui/toolbar/toolbar_controller_constants.h"
+#import "ios/chrome/browser/ui/toolbar/public/toolbar_controller_constants.h"
 #import "ios/chrome/browser/ui/toolbar/toolbar_view.h"
 #import "ios/chrome/browser/ui/tools_menu/tools_popup_controller.h"
 
diff --git a/ios/chrome/browser/ui/toolbar/toolbar_controller.mm b/ios/chrome/browser/ui/toolbar/toolbar_controller.mm
index d89496e2b..2e5cfc9 100644
--- a/ios/chrome/browser/ui/toolbar/toolbar_controller.mm
+++ b/ios/chrome/browser/ui/toolbar/toolbar_controller.mm
@@ -21,8 +21,8 @@
 #import "ios/chrome/browser/ui/image_util.h"
 #import "ios/chrome/browser/ui/reversed_animation.h"
 #include "ios/chrome/browser/ui/rtl_geometry.h"
+#import "ios/chrome/browser/ui/toolbar/public/toolbar_controller_base_feature.h"
 #import "ios/chrome/browser/ui/toolbar/toolbar_controller+protected.h"
-#import "ios/chrome/browser/ui/toolbar/toolbar_controller_base_feature.h"
 #include "ios/chrome/browser/ui/toolbar/toolbar_resource_macros.h"
 #import "ios/chrome/browser/ui/toolbar/toolbar_tools_menu_button.h"
 #import "ios/chrome/browser/ui/toolbar/tools_menu_button_observer_bridge.h"
diff --git a/ios/chrome/browser/ui/toolbar/toolbar_controller_base_feature.mm b/ios/chrome/browser/ui/toolbar/toolbar_controller_base_feature.mm
deleted file mode 100644
index 259bef7..0000000
--- a/ios/chrome/browser/ui/toolbar/toolbar_controller_base_feature.mm
+++ /dev/null
@@ -1,8 +0,0 @@
-// Copyright 2017 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#import "ios/chrome/browser/ui/toolbar/toolbar_controller_base_feature.h"
-
-const base::Feature kSafeAreaCompatibleToolbar{
-    "SafeAreaCompatibleToolbar", base::FEATURE_DISABLED_BY_DEFAULT};
diff --git a/ios/chrome/browser/ui/toolbar/toolbar_controller_constants.mm b/ios/chrome/browser/ui/toolbar/toolbar_controller_constants.mm
deleted file mode 100644
index 91bbbed..0000000
--- a/ios/chrome/browser/ui/toolbar/toolbar_controller_constants.mm
+++ /dev/null
@@ -1,73 +0,0 @@
-// Copyright 2017 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#import "ios/chrome/browser/ui/toolbar/toolbar_controller_constants.h"
-
-#if !defined(__has_feature) || !__has_feature(objc_arc)
-#error "This file requires ARC support."
-#endif
-
-const int64_t kNonInitialImageAdditionDelayNanosec = 500000LL;
-
-NSString* const kMenuWillShowNotification = @"kMenuWillShowNotification";
-NSString* const kMenuWillHideNotification = @"kMenuWillHideNotification";
-
-NSString* const kToolbarIdentifier = @"kToolbarIdentifier";
-NSString* const kIncognitoToolbarIdentifier = @"kIncognitoToolbarIdentifier";
-NSString* const kToolbarToolsMenuButtonIdentifier =
-    @"kToolbarToolsMenuButtonIdentifier";
-NSString* const kToolbarStackButtonIdentifier =
-    @"kToolbarStackButtonIdentifier";
-NSString* const kToolbarShareButtonIdentifier =
-    @"kToolbarShareButtonIdentifier";
-
-const NSInteger kStackButtonMaxTabCount = 99;
-
-NSString* const kToolbarTransitionAnimationKey = @"ToolbarTransitionAnimation";
-
-const NSInteger kFontSizeFewerThanTenTabs = 11;
-const NSInteger kFontSizeTenTabsOrMore = 9;
-
-const NSUInteger kTransitionLayerCapacity = 11;
-
-// Macros for creating CGRects of height H, origin (0,0), with the portrait
-// width of phone/pad devices.
-// clang-format off
-#define IPHONE_FRAME(H) { { 0, 0 }, { kPortraitWidth[IPHONE_IDIOM], H } }
-#define IPAD_FRAME(H)   { { 0, 0 }, { kPortraitWidth[IPAD_IDIOM],   H } }
-// Makes a two-element C array of CGRects as described above, one for each
-// device idiom.
-#define FRAME_PAIR(H) { IPHONE_FRAME(H), IPAD_FRAME(H) }
-// clang-format on
-
-const CGRect kToolbarFrame[INTERFACE_IDIOM_COUNT] = FRAME_PAIR(56);
-const CGRect kBackgroundViewFrame[INTERFACE_IDIOM_COUNT] = FRAME_PAIR(56);
-const CGRect kShadowViewFrame[INTERFACE_IDIOM_COUNT] = FRAME_PAIR(2);
-const CGRect kFullBleedShadowViewFrame = IPHONE_FRAME(10);
-
-const CGFloat kStackButtonNormalColors[] = {
-    85.0 / 255.0,   // ToolbarControllerStyleLightMode
-    238.0 / 255.0,  // ToolbarControllerStyleDarkMode
-    238.0 / 255.0,  // ToolbarControllerStyleIncognitoMode
-};
-const int kStackButtonHighlightedColors[] = {
-    0x4285F4,  // ToolbarControllerStyleLightMode
-    0x888a8c,  // ToolbarControllerStyleDarkMode
-    0x888a8c,  // ToolbarControllerStyleIncognitoMode
-};
-
-// clang-format off
-const LayoutRect kStackButtonFrame =
-{kPortraitWidth[IPHONE_IDIOM], {230, 4}, {48, 48}};
-const LayoutRect kShareMenuButtonFrame =
-{kPortraitWidth[IPAD_IDIOM], {680, 4}, {46, 48}};
-const LayoutRect kToolsMenuButtonFrame[INTERFACE_IDIOM_COUNT] = {
-  {kPortraitWidth[IPHONE_IDIOM], {276, 4}, {44, 48}},
-  {kPortraitWidth[IPAD_IDIOM], {723, 4}, {46, 48}}
-};
-// clang-format on
-
-const LayoutOffset kButtonFadeOutXOffset = 10;
-
-const CGFloat kPopoverAnchorHorizontalPadding = 10.0;
diff --git a/ios/chrome/browser/ui/toolbar/toolbar_coordinator.h b/ios/chrome/browser/ui/toolbar/toolbar_coordinator.h
index 9e6d6e7..49079b0 100644
--- a/ios/chrome/browser/ui/toolbar/toolbar_coordinator.h
+++ b/ios/chrome/browser/ui/toolbar/toolbar_coordinator.h
@@ -10,10 +10,13 @@
 #import "ios/chrome/browser/chrome_coordinator.h"
 #import "ios/chrome/browser/ui/bubble/bubble_view_anchor_point_provider.h"
 #import "ios/chrome/browser/ui/ntp/incognito_view_controller_delegate.h"
+#import "ios/chrome/browser/ui/side_swipe/side_swipe_toolbar_interacting.h"
 #import "ios/chrome/browser/ui/toolbar/omnibox_focuser.h"
+#import "ios/chrome/browser/ui/toolbar/toolbar_snapshot_providing.h"
 
 @protocol ActivityServicePositioner;
 @protocol QRScannerResultLoading;
+@class Tab;
 @protocol TabHistoryPositioner;
 @protocol TabHistoryUIUpdater;
 @class TabModel;
@@ -27,7 +30,9 @@
 @interface LegacyToolbarCoordinator
     : ChromeCoordinator<BubbleViewAnchorPointProvider,
                         IncognitoViewControllerDelegate,
-                        OmniboxFocuser>
+                        OmniboxFocuser,
+                        SideSwipeToolbarInteracting,
+                        ToolbarSnapshotProviding>
 
 @property(nonatomic, weak) TabModel* tabModel;
 @property(nonatomic, readonly, strong) UIView* view;
diff --git a/ios/chrome/browser/ui/toolbar/toolbar_coordinator.mm b/ios/chrome/browser/ui/toolbar/toolbar_coordinator.mm
index 4f8bda5..3d11fac 100644
--- a/ios/chrome/browser/ui/toolbar/toolbar_coordinator.mm
+++ b/ios/chrome/browser/ui/toolbar/toolbar_coordinator.mm
@@ -4,8 +4,9 @@
 
 #import "ios/chrome/browser/ui/toolbar/toolbar_coordinator.h"
 
-#import "ios/chrome/browser/ui/toolbar/toolbar_utils.h"
+#import "ios/chrome/browser/ui/toolbar/public/toolbar_utils.h"
 #import "ios/chrome/browser/ui/toolbar/web_toolbar_controller.h"
+#import "ios/chrome/browser/ui/uikit_ui_util.h"
 
 #if !defined(__has_feature) || !__has_feature(objc_arc)
 #error "This file requires ARC support."
@@ -47,6 +48,8 @@
   self.webToolbarController.delegate = delegate;
 }
 
+#pragma mark - Public
+
 - (void)adjustToolbarHeight {
   self.webToolbarController.heightConstraint.constant =
       ToolbarHeightWithTopOfScreenOffset(
@@ -140,6 +143,40 @@
   [self.webToolbarController onFakeboxAnimationComplete];
 }
 
+#pragma mark - SideSwipeToolbarInteracting
+
+- (UIView*)toolbarView {
+  return self.view;
+}
+
+- (BOOL)canBeginToolbarSwipe {
+  return ![self isOmniboxFirstResponder] && ![self showingOmniboxPopup];
+}
+
+- (UIImage*)toolbarSideSwipeSnapshotForTab:(Tab*)tab {
+  [self.webToolbarController updateToolbarForSideSwipeSnapshot:tab];
+  UIImage* toolbarSnapshot = CaptureViewWithOption(
+      [self.webToolbarController view], [[UIScreen mainScreen] scale],
+      kClientSideRendering);
+
+  [self.webToolbarController resetToolbarAfterSideSwipeSnapshot];
+  return toolbarSnapshot;
+}
+
+#pragma mark - ToolbarSnapshotProviding
+
+- (UIView*)snapshotForTabSwitcher {
+  UIView* toolbarSnapshotView;
+  if ([self.view window]) {
+    toolbarSnapshotView = [self.view snapshotViewAfterScreenUpdates:NO];
+  } else {
+    toolbarSnapshotView = [[UIView alloc] initWithFrame:self.view.frame];
+    [toolbarSnapshotView layer].contents = static_cast<id>(
+        CaptureViewWithOption(self.view, 1, kClientSideRendering).CGImage);
+  }
+  return toolbarSnapshotView;
+}
+
 #pragma mark - IncognitoViewControllerDelegate
 
 - (void)setToolbarBackgroundAlpha:(CGFloat)alpha {
diff --git a/ios/chrome/browser/ui/toolbar/toolbar_snapshot_providing.h b/ios/chrome/browser/ui/toolbar/toolbar_snapshot_providing.h
new file mode 100644
index 0000000..d0fc336
--- /dev/null
+++ b/ios/chrome/browser/ui/toolbar/toolbar_snapshot_providing.h
@@ -0,0 +1,18 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef IOS_CHROME_BROWSER_UI_TOOLBAR_TOOLBAR_SNAPSHOT_PROVIDER_H_
+#define IOS_CHROME_BROWSER_UI_TOOLBAR_TOOLBAR_SNAPSHOT_PROVIDER_H_
+
+#import <UIKit/UIKit.h>
+
+// Protocol for an object providing toolbar snapshot.
+@protocol ToolbarSnapshotProviding
+
+// Snapshot used by the TabSwitcher.
+- (UIView*)snapshotForTabSwitcher;
+
+@end
+
+#endif  // IOS_CHROME_BROWSER_UI_TOOLBAR_TOOLBAR_SNAPSHOT_PROVIDER_H_
diff --git a/ios/chrome/browser/ui/toolbar/toolbar_tools_menu_button.h b/ios/chrome/browser/ui/toolbar/toolbar_tools_menu_button.h
index 2bd468e..8493342 100644
--- a/ios/chrome/browser/ui/toolbar/toolbar_tools_menu_button.h
+++ b/ios/chrome/browser/ui/toolbar/toolbar_tools_menu_button.h
@@ -8,7 +8,7 @@
 #import <UIKit/UIKit.h>
 
 #import "ios/chrome/browser/ui/fancy_ui/colored_button.h"
-#import "ios/chrome/browser/ui/toolbar/toolbar_controller_constants.h"
+#import "ios/chrome/browser/ui/toolbar/public/toolbar_controller_constants.h"
 
 // ColoredButton specialization that updates the tint color when the tools menu
 // is visible or when the reading list associated with |readingListModel|
diff --git a/ios/chrome/browser/ui/toolbar/toolbar_utils.mm b/ios/chrome/browser/ui/toolbar/toolbar_utils.mm
deleted file mode 100644
index 4953cd8..0000000
--- a/ios/chrome/browser/ui/toolbar/toolbar_utils.mm
+++ /dev/null
@@ -1,25 +0,0 @@
-// Copyright 2017 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#import "ios/chrome/browser/ui/toolbar/toolbar_utils.h"
-
-#include "base/feature_list.h"
-#include "base/logging.h"
-#import "ios/chrome/browser/ui/toolbar/toolbar_controller_base_feature.h"
-#import "ios/chrome/browser/ui/toolbar/toolbar_controller_constants.h"
-#import "ios/chrome/browser/ui/ui_util.h"
-
-#if !defined(__has_feature) || !__has_feature(objc_arc)
-#error "This file requires ARC support."
-#endif
-
-CGFloat ToolbarHeightWithTopOfScreenOffset(CGFloat status_bar_offset) {
-  DCHECK(base::FeatureList::IsEnabled(kSafeAreaCompatibleToolbar));
-  InterfaceIdiom idiom = IsIPadIdiom() ? IPAD_IDIOM : IPHONE_IDIOM;
-  CGRect frame = kToolbarFrame[idiom];
-  if (idiom == IPHONE_IDIOM) {
-    frame.size.height += status_bar_offset;
-  }
-  return frame.size.height;
-}
diff --git a/ios/chrome/browser/ui/toolbar/toolbar_view.mm b/ios/chrome/browser/ui/toolbar/toolbar_view.mm
index ef4a858..a83a149f 100644
--- a/ios/chrome/browser/ui/toolbar/toolbar_view.mm
+++ b/ios/chrome/browser/ui/toolbar/toolbar_view.mm
@@ -4,7 +4,7 @@
 
 #import "ios/chrome/browser/ui/toolbar/toolbar_view.h"
 
-#import "ios/chrome/browser/ui/toolbar/toolbar_controller_base_feature.h"
+#import "ios/chrome/browser/ui/toolbar/public/toolbar_controller_base_feature.h"
 #import "ios/chrome/browser/ui/toolbar/toolbar_frame_delegate.h"
 
 @implementation ToolbarView
diff --git a/ios/chrome/browser/ui/toolbar/web_toolbar_controller.mm b/ios/chrome/browser/ui/toolbar/web_toolbar_controller.mm
index 3d3cf16..5c6efbbd 100644
--- a/ios/chrome/browser/ui/toolbar/web_toolbar_controller.mm
+++ b/ios/chrome/browser/ui/toolbar/web_toolbar_controller.mm
@@ -55,13 +55,13 @@
 #include "ios/chrome/browser/ui/rtl_geometry.h"
 #import "ios/chrome/browser/ui/toolbar/keyboard_assist/toolbar_assistive_keyboard_delegate.h"
 #import "ios/chrome/browser/ui/toolbar/keyboard_assist/toolbar_assistive_keyboard_views.h"
+#import "ios/chrome/browser/ui/toolbar/public/toolbar_controller_base_feature.h"
+#import "ios/chrome/browser/ui/toolbar/public/toolbar_utils.h"
+#import "ios/chrome/browser/ui/toolbar/public/web_toolbar_controller_constants.h"
 #import "ios/chrome/browser/ui/toolbar/toolbar_controller+protected.h"
-#import "ios/chrome/browser/ui/toolbar/toolbar_controller_base_feature.h"
 #import "ios/chrome/browser/ui/toolbar/toolbar_frame_delegate.h"
 #import "ios/chrome/browser/ui/toolbar/toolbar_model_ios.h"
 #include "ios/chrome/browser/ui/toolbar/toolbar_resource_macros.h"
-#import "ios/chrome/browser/ui/toolbar/toolbar_utils.h"
-#import "ios/chrome/browser/ui/toolbar/web_toolbar_controller_constants.h"
 #import "ios/chrome/browser/ui/toolbar/web_toolbar_delegate.h"
 #include "ios/chrome/browser/ui/ui_util.h"
 #import "ios/chrome/browser/ui/uikit_ui_util.h"
diff --git a/ios/chrome/browser/ui/toolbar/web_toolbar_controller_constants.h b/ios/chrome/browser/ui/toolbar/web_toolbar_controller_constants.h
deleted file mode 100644
index 26b544c..0000000
--- a/ios/chrome/browser/ui/toolbar/web_toolbar_controller_constants.h
+++ /dev/null
@@ -1,105 +0,0 @@
-// Copyright 2017 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef IOS_CHROME_BROWSER_UI_TOOLBAR_WEB_TOOLBAR_CONTROLLER_CONSTANTS_H_
-#define IOS_CHROME_BROWSER_UI_TOOLBAR_WEB_TOOLBAR_CONTROLLER_CONSTANTS_H_
-
-#import <Foundation/Foundation.h>
-
-#import <UIKit/UIKit.h>
-#include "ios/chrome/browser/ui/rtl_geometry.h"
-#import "ios/chrome/browser/ui/toolbar/toolbar_controller.h"
-#include "ios/chrome/browser/ui/ui_util.h"
-
-// The brightness of the omnibox placeholder text in regular mode,
-// on an iPhone.
-extern const CGFloat kiPhoneOmniboxPlaceholderColorBrightness;
-
-// The histogram recording CLAuthorizationStatus for omnibox queries.
-extern const char* const kOmniboxQueryLocationAuthorizationStatusHistogram;
-// The number of possible CLAuthorizationStatus values to report.
-const int kLocationAuthorizationStatusCount = 4;
-
-// The brightness of the toolbar's background color (visible on NTPs when the
-// background view is hidden).
-extern const CGFloat kNTPBackgroundColorBrightness;
-extern const CGFloat kNTPBackgroundColorBrightnessIncognito;
-
-// How far below the omnibox to position the popup.
-extern const CGFloat kiPadOmniboxPopupVerticalOffset;
-
-// Padding to place on the sides of the omnibox when expanded.
-extern const CGFloat kExpandedOmniboxPadding;
-
-// Padding between the back button and the omnibox when the forward button isn't
-// displayed.
-extern const CGFloat kBackButtonTrailingPadding;
-extern const CGFloat kForwardButtonTrailingPadding;
-extern const CGFloat kReloadButtonTrailingPadding;
-
-// Cancel button sizing.
-extern const CGFloat kCancelButtonBottomMargin;
-extern const CGFloat kCancelButtonTopMargin;
-extern const CGFloat kCancelButtonLeadingMargin;
-extern const CGFloat kCancelButtonWidth;
-
-// Additional offset to adjust the y coordinate of the determinate progress bar
-// up by.
-extern const CGFloat kDeterminateProgressBarYOffset;
-extern const CGFloat kMaterialProgressBarHeight;
-extern const CGFloat kLoadCompleteHideProgressBarDelay;
-// The default position animation is 10 pixels toward the trailing side, so
-// that's a negative leading offset.
-extern const LayoutOffset kPositionAnimationLeadingOffset;
-
-extern const CGFloat kIPadToolbarY;
-extern const CGFloat kScrollFadeDistance;
-// Offset from the image edge to the beginning of the visible omnibox rectangle.
-// The image is symmetrical, so the offset is equal on each side.
-extern const CGFloat kBackgroundImageVisibleRectOffset;
-
-extern const CGFloat kWebToolbarWidths[INTERFACE_IDIOM_COUNT];
-// UI layouts.  iPhone values followed by iPad values.
-// Frame for the WebToolbar-specific container, which is a subview of the
-// toolbar view itself.
-extern const LayoutRect kWebToolbarFrame[INTERFACE_IDIOM_COUNT];
-
-// Layouts inside the WebToolbar frame
-extern const LayoutRect kOmniboxFrame[INTERFACE_IDIOM_COUNT];
-extern const LayoutRect kBackButtonFrame[INTERFACE_IDIOM_COUNT];
-extern const LayoutRect kForwardButtonFrame[INTERFACE_IDIOM_COUNT];
-
-// iPad-only layouts
-// Layout for both the stop and reload buttons, which are in the same location.
-extern const LayoutRect kStopReloadButtonFrame;
-extern const LayoutRect kStarButtonFrame;
-extern const LayoutRect kVoiceSearchButtonFrame;
-
-// Vertical distance between the y-coordinate of the omnibox's center and the
-// y-coordinate of the web toolbar's center.
-extern const CGFloat kOmniboxCenterOffsetY;
-
-// Last button in accessory view for keyboard, commonly used TLD.
-extern NSString* const kDotComTLD;
-
-enum {
-  WebToolbarButtonNameBack = NumberOfToolbarButtonNames,
-  WebToolbarButtonNameCallingApp,
-  WebToolbarButtonNameForward,
-  WebToolbarButtonNameReload,
-  WebToolbarButtonNameStar,
-  WebToolbarButtonNameStop,
-  WebToolbarButtonNameTTS,
-  WebToolbarButtonNameVoice,
-  NumberOfWebToolbarButtonNames,
-};
-
-// Helper functions.
-void RunBlockAfterDelay(NSTimeInterval delay, void (^block)(void));
-CGRect RectShiftedDownForStatusBar(CGRect rect);
-CGRect RectShiftedUpForStatusBar(CGRect rect);
-CGRect RectShiftedUpAndResizedForStatusBar(CGRect rect);
-CGRect RectShiftedDownAndResizedForStatusBar(CGRect rect);
-
-#endif  // IOS_CHROME_BROWSER_UI_TOOLBAR_WEB_TOOLBAR_CONTROLLER_CONSTANTS_H_
diff --git a/ios/chrome/browser/ui/toolbar/web_toolbar_controller_constants.mm b/ios/chrome/browser/ui/toolbar/web_toolbar_controller_constants.mm
deleted file mode 100644
index 7c789f1..0000000
--- a/ios/chrome/browser/ui/toolbar/web_toolbar_controller_constants.mm
+++ /dev/null
@@ -1,109 +0,0 @@
-// Copyright 2017 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#import "ios/chrome/browser/ui/toolbar/web_toolbar_controller_constants.h"
-
-#include "base/logging.h"
-
-#if !defined(__has_feature) || !__has_feature(objc_arc)
-#error "This file requires ARC support."
-#endif
-
-const CGFloat kiPhoneOmniboxPlaceholderColorBrightness = 150 / 255.0;
-
-const char* const kOmniboxQueryLocationAuthorizationStatusHistogram =
-    "Omnibox.QueryIosLocationAuthorizationStatus";
-
-const CGFloat kNTPBackgroundColorBrightness = 1.0;
-const CGFloat kNTPBackgroundColorBrightnessIncognito = 34.0 / 255.0;
-
-const CGFloat kiPadOmniboxPopupVerticalOffset = 3;
-
-const CGFloat kExpandedOmniboxPadding = 6;
-
-const CGFloat kBackButtonTrailingPadding = 7.0;
-const CGFloat kForwardButtonTrailingPadding = -1.0;
-const CGFloat kReloadButtonTrailingPadding = 4.0;
-
-const CGFloat kCancelButtonBottomMargin = 4.0;
-const CGFloat kCancelButtonTopMargin = 4.0;
-const CGFloat kCancelButtonLeadingMargin = 7.0;
-const CGFloat kCancelButtonWidth = 40.0;
-
-const CGFloat kDeterminateProgressBarYOffset = 1.0;
-const CGFloat kMaterialProgressBarHeight = 2.0;
-const CGFloat kLoadCompleteHideProgressBarDelay = 0.5;
-const LayoutOffset kPositionAnimationLeadingOffset = -10.0;
-
-const CGFloat kIPadToolbarY = 53;
-const CGFloat kScrollFadeDistance = 30;
-const CGFloat kBackgroundImageVisibleRectOffset = 6;
-
-const CGFloat kWebToolbarWidths[INTERFACE_IDIOM_COUNT] = {224, 720};
-// clang-format off
-const LayoutRect kWebToolbarFrame[INTERFACE_IDIOM_COUNT] = {
-  {kPortraitWidth[IPHONE_IDIOM], LayoutRectPositionZero,
-    {kWebToolbarWidths[IPHONE_IDIOM], 56}},
-  {kPortraitWidth[IPAD_IDIOM],   LayoutRectPositionZero,
-    {kWebToolbarWidths[IPAD_IDIOM],   56}},
-};
-
-#define IPHONE_LAYOUT(L, Y, H, W) \
-{ kWebToolbarWidths[IPHONE_IDIOM], {L, Y}, {H, W} }
-#define IPAD_LAYOUT(L, Y, H, W) \
-{ kWebToolbarWidths[IPAD_IDIOM], {L, Y}, {H, W} }
-
-// Layouts inside the WebToolbar frame
-const LayoutRect kOmniboxFrame[INTERFACE_IDIOM_COUNT] = {
-  IPHONE_LAYOUT(55, 7, 169, 43), IPAD_LAYOUT(152, 7, 568, 43),
-};
-const LayoutRect kBackButtonFrame[INTERFACE_IDIOM_COUNT] = {
-  IPHONE_LAYOUT(0, 4, 48, 48), IPAD_LAYOUT(4, 4, 48, 48),
-};
-const LayoutRect kForwardButtonFrame[INTERFACE_IDIOM_COUNT] = {
-  IPHONE_LAYOUT(48, 4, 48, 48), IPAD_LAYOUT(52, 4, 48, 48),
-};
-// clang-format on
-
-const LayoutRect kStopReloadButtonFrame = IPAD_LAYOUT(100, 4, 48, 48);
-const LayoutRect kStarButtonFrame = IPAD_LAYOUT(644, 4, 36, 48);
-const LayoutRect kVoiceSearchButtonFrame = IPAD_LAYOUT(680, 4, 36, 48);
-
-const CGFloat kOmniboxCenterOffsetY = 0.5;
-
-NSString* const kDotComTLD = @".com";
-
-void RunBlockAfterDelay(NSTimeInterval delay, void (^block)(void)) {
-  DCHECK([NSThread isMainThread]);
-  dispatch_after(dispatch_time(DISPATCH_TIME_NOW, NSEC_PER_SEC * delay),
-                 dispatch_get_main_queue(), block);
-}
-
-CGRect RectShiftedDownForStatusBar(CGRect rect) {
-  if (IsIPadIdiom())
-    return rect;
-  rect.origin.y += StatusBarHeight();
-  return rect;
-}
-
-CGRect RectShiftedUpForStatusBar(CGRect rect) {
-  if (IsIPadIdiom())
-    return rect;
-  rect.origin.y -= StatusBarHeight();
-  return rect;
-}
-
-CGRect RectShiftedUpAndResizedForStatusBar(CGRect rect) {
-  if (IsIPadIdiom())
-    return rect;
-  rect.size.height += StatusBarHeight();
-  return RectShiftedUpForStatusBar(rect);
-}
-
-CGRect RectShiftedDownAndResizedForStatusBar(CGRect rect) {
-  if (IsIPadIdiom())
-    return rect;
-  rect.size.height -= StatusBarHeight();
-  return RectShiftedDownForStatusBar(rect);
-}
diff --git a/ios/chrome/browser/ui/ui_util.mm b/ios/chrome/browser/ui/ui_util.mm
index c0e548b..208f6679 100644
--- a/ios/chrome/browser/ui/ui_util.mm
+++ b/ios/chrome/browser/ui/ui_util.mm
@@ -9,7 +9,7 @@
 
 #include "base/feature_list.h"
 #include "base/logging.h"
-#import "ios/chrome/browser/ui/toolbar/toolbar_controller_base_feature.h"
+#import "ios/chrome/browser/ui/toolbar/public/toolbar_controller_base_feature.h"
 #import "ios/chrome/browser/ui/uikit_ui_util.h"
 #include "ui/base/device_form_factor.h"
 #include "ui/gfx/ios/uikit_util.h"
diff --git a/ios/chrome/browser/web/BUILD.gn b/ios/chrome/browser/web/BUILD.gn
index 23470ef7..19323cf5 100644
--- a/ios/chrome/browser/web/BUILD.gn
+++ b/ios/chrome/browser/web/BUILD.gn
@@ -9,8 +9,6 @@
   sources = [
     "dom_altering_lock.h",
     "dom_altering_lock.mm",
-    "legacy_mailto_url_rewriter.h",
-    "legacy_mailto_url_rewriter.mm",
     "load_timing_tab_helper.h",
     "load_timing_tab_helper.mm",
     "mailto_handler.h",
@@ -39,7 +37,6 @@
     "tab_id_tab_helper.mm",
   ]
   deps = [
-    ":features",
     ":tab_helper_delegates",
     "//base",
     "//components/strings",
@@ -54,16 +51,6 @@
   ]
 }
 
-source_set("features") {
-  configs += [ "//build/config/compiler:enable_arc" ]
-  sources = [
-    "features.h",
-    "features.mm",
-  ]
-  deps = [
-    "//base",
-  ]
-}
 source_set("tab_helper_delegates") {
   configs += [ "//build/config/compiler:enable_arc" ]
   sources = [
@@ -77,7 +64,6 @@
   configs += [ "//build/config/compiler:enable_arc" ]
   testonly = true
   sources = [
-    "legacy_mailto_url_rewriter_unittest.mm",
     "load_timing_tab_helper_unittest.mm",
     "mailto_handler_gmail_unittest.mm",
     "mailto_handler_inbox_unittest.mm",
@@ -159,7 +145,6 @@
   ]
   deps = [
     ":chrome_bundle",
-    ":features",
     "//base",
     "//components/content_settings/core/browser",
     "//components/dom_distiller/core",
@@ -216,6 +201,7 @@
     "//ios/chrome/browser/passwords",
     "//ios/chrome/browser/ui:ui_internal",
     "//ios/chrome/browser/ui/fullscreen",
+    "//ios/chrome/browser/ui/fullscreen:legacy_fullscreen",
     "//ios/chrome/browser/web",
     "//ios/web",
     "//ios/web/public/test",
diff --git a/ios/chrome/browser/web/chrome_web_client.h b/ios/chrome/browser/web/chrome_web_client.h
index fef040d..a298d361 100644
--- a/ios/chrome/browser/web/chrome_web_client.h
+++ b/ios/chrome/browser/web/chrome_web_client.h
@@ -45,7 +45,6 @@
       const GURL& request_url,
       bool overridable,
       const base::Callback<void(bool)>& callback) override;
-  bool IsSlimNavigationManagerEnabled() const override;
 
  private:
   DISALLOW_COPY_AND_ASSIGN(ChromeWebClient);
diff --git a/ios/chrome/browser/web/chrome_web_client.mm b/ios/chrome/browser/web/chrome_web_client.mm
index 3d2069e..6fcdbea 100644
--- a/ios/chrome/browser/web/chrome_web_client.mm
+++ b/ios/chrome/browser/web/chrome_web_client.mm
@@ -193,7 +193,3 @@
   IOSSSLErrorHandler::HandleSSLError(web_state, cert_error, info, request_url,
                                      overridable, callback);
 }
-
-bool ChromeWebClient::IsSlimNavigationManagerEnabled() const {
-  return experimental_flags::IsSlimNavigationManagerEnabled();
-}
diff --git a/ios/chrome/browser/web/external_app_launcher.mm b/ios/chrome/browser/web/external_app_launcher.mm
index 6ff2929..c93bffe 100644
--- a/ios/chrome/browser/web/external_app_launcher.mm
+++ b/ios/chrome/browser/web/external_app_launcher.mm
@@ -13,10 +13,7 @@
 #include "components/strings/grit/components_strings.h"
 #import "ios/chrome/browser/open_url_util.h"
 #import "ios/chrome/browser/ui/external_app/open_mail_handler_view_controller.h"
-#import "ios/chrome/browser/ui/ui_util.h"
 #import "ios/chrome/browser/web/external_apps_launch_policy_decider.h"
-#include "ios/chrome/browser/web/features.h"
-#import "ios/chrome/browser/web/legacy_mailto_url_rewriter.h"
 #import "ios/chrome/browser/web/mailto_handler.h"
 #import "ios/chrome/browser/web/mailto_url_rewriter.h"
 #import "ios/chrome/browser/web/nullable_mailto_url_rewriter.h"
@@ -90,14 +87,10 @@
 // Used to check for repeated launches and provide policy for launching apps.
 @property(nonatomic, strong) ExternalAppsLaunchPolicyDecider* policyDecider;
 
-// Shows a prompt for the user to choose which mail client app to use to
-// handle a mailto:// URL.
-- (void)promptForMailClientWithURL:(const GURL&)URL
-                       URLRewriter:(MailtoURLRewriter*)rewriter;
 // Shows a prompt in Material Design for the user to choose which mail client
 // app to use to handle a mailto:// URL.
-- (void)promptMDCStyleForMailClientWithURL:(const GURL&)URL
-                               URLRewriter:(MailtoURLRewriter*)rewriter;
+- (void)promptForMailClientWithURL:(const GURL&)URL
+                       URLRewriter:(MailtoURLRewriter*)rewriter;
 // Presents an alert controller with |prompt| and |openLabel| as button label
 // on the root view controller before launching an external app identified by
 // |URL|.
@@ -150,50 +143,6 @@
 
 - (void)promptForMailClientWithURL:(const GURL&)URL
                        URLRewriter:(MailtoURLRewriter*)rewriter {
-  // No user chosen default. Prompt user now.
-  NSString* title =
-      l10n_util::GetNSString(IDS_IOS_CHOOSE_DEFAULT_EMAIL_CLIENT_APP);
-  NSString* subtitle =
-      l10n_util::GetNSString(IDS_IOS_CHOOSE_EMAIL_APP_HOW_TO_CHANGE);
-  // TODO(crbug.com/761519): Use Action Sheet style for iPad as well.
-  UIAlertControllerStyle style = IsIPadIdiom()
-                                     ? UIAlertControllerStyleAlert
-                                     : UIAlertControllerStyleActionSheet;
-  UIAlertController* alertController =
-      [UIAlertController alertControllerWithTitle:title
-                                          message:subtitle
-                                   preferredStyle:style];
-  // There must be more than one available handlers to present a prompt to user.
-  DCHECK([[rewriter defaultHandlers] count] > 1U);
-  GURL copiedURLToOpen = URL;
-  for (MailtoHandler* handler in [rewriter defaultHandlers]) {
-    if (![handler isAvailable])
-      continue;
-    UIAlertAction* action = [UIAlertAction
-        actionWithTitle:[handler appName]
-                  style:UIAlertActionStyleDefault
-                handler:^(UIAlertAction* _Nonnull action) {
-                  DCHECK(handler);
-                  [rewriter setDefaultHandlerID:[handler appStoreID]];
-                  LaunchMailClientApp(copiedURLToOpen, handler);
-                }];
-    [alertController addAction:action];
-  }
-
-  UIAlertAction* cancelAction =
-      [UIAlertAction actionWithTitle:l10n_util::GetNSString(IDS_CANCEL)
-                               style:UIAlertActionStyleCancel
-                             handler:nil];
-  [alertController addAction:cancelAction];
-
-  [[[[UIApplication sharedApplication] keyWindow] rootViewController]
-      presentViewController:alertController
-                   animated:YES
-                 completion:nil];
-}
-
-- (void)promptMDCStyleForMailClientWithURL:(const GURL&)URL
-                               URLRewriter:(MailtoURLRewriter*)rewriter {
   GURL copiedURLToOpen = URL;
   OpenMailHandlerViewController* mailHandlerChooser =
       [[OpenMailHandlerViewController alloc]
@@ -359,20 +308,13 @@
     }
   }
 
-  // If feature mailto: URL rewriting is enabled, replaces |URL| with a
-  // rewritten URL if it is of mailto: scheme.
-  if (base::FeatureList::IsEnabled(kMailtoUrlRewriting) &&
-      gURL.SchemeIs(url::kMailToScheme)) {
+  // Replaces |URL| with a rewritten URL if it is of mailto: scheme.
+  if (gURL.SchemeIs(url::kMailToScheme)) {
     MailtoURLRewriter* rewriter =
-        base::FeatureList::IsEnabled(kMailtoPromptForUserChoice)
-            ? [NullableMailtoURLRewriter mailtoURLRewriterWithStandardHandlers]
-            : [LegacyMailtoURLRewriter mailtoURLRewriterWithStandardHandlers];
+        [NullableMailtoURLRewriter mailtoURLRewriterWithStandardHandlers];
     NSString* handlerID = [rewriter defaultHandlerID];
     if (!handlerID) {
-      if (base::FeatureList::IsEnabled(kMailtoPromptInMdcStyle))
-        [self promptMDCStyleForMailClientWithURL:gURL URLRewriter:rewriter];
-      else
-        [self promptForMailClientWithURL:gURL URLRewriter:rewriter];
+      [self promptForMailClientWithURL:gURL URLRewriter:rewriter];
       return YES;
     }
     MailtoHandler* handler = [rewriter defaultHandlerByID:handlerID];
diff --git a/ios/chrome/browser/web/features.h b/ios/chrome/browser/web/features.h
deleted file mode 100644
index f749643..0000000
--- a/ios/chrome/browser/web/features.h
+++ /dev/null
@@ -1,24 +0,0 @@
-// Copyright 2017 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef IOS_CHROME_BROWSER_WEB_FEATURES_H_
-#define IOS_CHROME_BROWSER_WEB_FEATURES_H_
-
-#include "base/feature_list.h"
-
-// Feature flag to enable rewriting of mailto: URLs to launch Mail client app
-// of user's choice.
-extern const base::Feature kMailtoUrlRewriting;
-
-// Feature flag to prompt user to choose a mail client app. User is prompted
-// at the first time that the user taps on a mailto: URL. This feature can be
-// enabled only when kMailtoUrlRewriting is also enabled.
-extern const base::Feature kMailtoPromptForUserChoice;
-
-// Feature flag to choose whether to use Material Design style bottom sheet
-// to present choices to the user. With MDC, it is possible to show a custom
-// row with a toggle switch to remember the setting for future use.
-extern const base::Feature kMailtoPromptInMdcStyle;
-
-#endif  // IOS_CHROME_BROWSER_WEB_FEATURES_H_
diff --git a/ios/chrome/browser/web/features.mm b/ios/chrome/browser/web/features.mm
deleted file mode 100644
index 8ca3c32..0000000
--- a/ios/chrome/browser/web/features.mm
+++ /dev/null
@@ -1,25 +0,0 @@
-// Copyright 2017 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "ios/chrome/browser/web/features.h"
-
-#if !defined(__has_feature) || !__has_feature(objc_arc)
-#error "This file requires ARC support."
-#endif
-
-// Feature flag to control default value for mailto: URL rewriting feature.
-// Change the default value here to enable or disable this feature.
-const base::Feature kMailtoUrlRewriting{"MailtoUrlRewriting",
-                                        base::FEATURE_ENABLED_BY_DEFAULT};
-
-// Feature flag to prompt user to choose a mail client app. Change the default
-// value here to enable or disable this feature.
-const base::Feature kMailtoPromptForUserChoice{
-    "MailtoPromptForUserChoice", base::FEATURE_ENABLED_BY_DEFAULT};
-
-// Feature flag to choose whether to use Material Design style bottom sheet
-// to present choices to the user. Change the default value here to enable
-// to disable this feature.
-const base::Feature kMailtoPromptInMdcStyle{"MailtoPromptInMdcStyle",
-                                            base::FEATURE_ENABLED_BY_DEFAULT};
diff --git a/ios/chrome/browser/web/legacy_mailto_url_rewriter.h b/ios/chrome/browser/web/legacy_mailto_url_rewriter.h
deleted file mode 100644
index 8e460514..0000000
--- a/ios/chrome/browser/web/legacy_mailto_url_rewriter.h
+++ /dev/null
@@ -1,18 +0,0 @@
-// Copyright 2017 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef IOS_CHROME_BROWSER_WEB_LEGACY_MAILTO_URL_REWRITER_H_
-#define IOS_CHROME_BROWSER_WEB_LEGACY_MAILTO_URL_REWRITER_H_
-
-#import "ios/chrome/browser/web/mailto_url_rewriter.h"
-
-// An object that manages the available Mail client apps. The currently selected
-// Mail client to handle mailto: URL is stored in a key in NSUserDefaults.
-// If the key in NSUserDefaults is not set or the corresponding app is no longer
-// installed, the system-provided Mail client app will be used.
-@interface LegacyMailtoURLRewriter : MailtoURLRewriter
-
-@end
-
-#endif  // IOS_CHROME_BROWSER_WEB_LEGACY_MAILTO_URL_REWRITER_H_
diff --git a/ios/chrome/browser/web/legacy_mailto_url_rewriter.mm b/ios/chrome/browser/web/legacy_mailto_url_rewriter.mm
deleted file mode 100644
index 309317a..0000000
--- a/ios/chrome/browser/web/legacy_mailto_url_rewriter.mm
+++ /dev/null
@@ -1,210 +0,0 @@
-// Copyright 2017 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#import "ios/chrome/browser/web/legacy_mailto_url_rewriter.h"
-
-#import <Foundation/Foundation.h>
-
-#import "base/logging.h"
-#import "ios/chrome/browser/web/mailto_handler.h"
-#import "ios/chrome/browser/web/mailto_handler_gmail.h"
-#import "ios/chrome/browser/web/mailto_handler_system_mail.h"
-
-#if !defined(__has_feature) || !__has_feature(objc_arc)
-#error "This file requires ARC support."
-#endif
-
-@interface LegacyMailtoURLRewriter ()
-
-// Dictionary keyed by the App Store ID of the Mail client and the value is
-// the MailtoHandler object that can rewrite a mailto: URL.
-@property(nonatomic, strong)
-    NSMutableDictionary<NSString*, MailtoHandler*>* handlers;
-
-// Custom logic to handle the migration from Google Native App Launcher options
-// to this simplified mailto: URL only system. This must be called after
-// -addMailtoApp: has been called to add all the known Mail client apps.
-// TODO(crbug.com/718601): At some point in the future when almost all users
-// have upgraded, this method can be removed.
-- (void)migrateLegacyOptions;
-
-// For users who have not made an explicit choice (kMailtoDefaultHandlerKey
-// not set), if Gmail is detected, make an explicit choice for the user to
-// use Gmail app as the default mailto: handler.
-- (void)autoDefaultToGmailIfInstalled;
-
-@end
-
-@implementation LegacyMailtoURLRewriter
-@synthesize handlers = _handlers;
-
-+ (NSString*)userDefaultsKey {
-  // The key for NSUserDefaults to store the Mail client selected to handle
-  // mailto: URL scheme. If this key is not set, user has not made an explicit
-  // choice for default mailto: handler and system-provided Mail client app will
-  // be used.
-  return @"MailtoHandlerDefault";
-}
-
-+ (instancetype)mailtoURLRewriterWithStandardHandlers {
-  id result = [[LegacyMailtoURLRewriter alloc] init];
-  [result setDefaultHandlers:@[
-    [[MailtoHandlerSystemMail alloc] init], [[MailtoHandlerGmail alloc] init]
-  ]];
-  return result;
-}
-
-- (instancetype)init {
-  self = [super init];
-  if (self) {
-    _handlers = [NSMutableDictionary dictionary];
-  }
-  return self;
-}
-
-- (NSArray<MailtoHandler*>*)defaultHandlers {
-  return [[_handlers allValues]
-      sortedArrayUsingComparator:^NSComparisonResult(
-          MailtoHandler* _Nonnull obj1, MailtoHandler* _Nonnull obj2) {
-        return [[obj1 appName] compare:[obj2 appName]];
-      }];
-}
-
-- (void)setDefaultHandlers:(NSArray<MailtoHandler*>*)handlerApps {
-  for (MailtoHandler* app in handlerApps) {
-    [_handlers setObject:app forKey:[app appStoreID]];
-  }
-  [self migrateLegacyOptions];
-  [self autoDefaultToGmailIfInstalled];
-}
-
-- (NSString*)defaultHandlerID {
-  NSString* value = [[NSUserDefaults standardUserDefaults]
-      stringForKey:[[self class] userDefaultsKey]];
-  // This implementation of MailtoURLRewriter always returns a non-nil mailto:
-  // URL handler ID.
-  if ([_handlers[value] isAvailable])
-    return value;
-  return [[self class] systemMailApp];
-}
-
-- (void)setDefaultHandlerID:(NSString*)appStoreID {
-  // This implementation of MailtoURLRewriter does not allow the unsetting of
-  // a mailto: URL handler.
-  DCHECK([appStoreID length]);
-  NSUserDefaults* defaults = [NSUserDefaults standardUserDefaults];
-  NSString* defaultsKey = [[self class] userDefaultsKey];
-  if ([appStoreID isEqual:[defaults objectForKey:defaultsKey]])
-    return;
-  [defaults setObject:appStoreID forKey:defaultsKey];
-  [self.observer rewriterDidChange:self];
-}
-
-- (NSString*)defaultHandlerName {
-  NSString* handlerID = [self defaultHandlerID];
-  MailtoHandler* handler = _handlers[handlerID];
-  return [handler appName];
-}
-
-- (MailtoHandler*)defaultHandlerByID:(NSString*)handlerID {
-  return _handlers[handlerID];
-}
-
-- (NSString*)rewriteMailtoURL:(const GURL&)URL {
-  NSString* value = [self defaultHandlerID];
-  if ([value length]) {
-    MailtoHandler* handler = _handlers[value];
-    if ([handler isAvailable]) {
-      return [handler rewriteMailtoURL:URL];
-    }
-  }
-  return nil;
-}
-
-#pragma mark - Private
-
-//
-// Implements the migration logic for users of previous versions of Google
-// Chrome which supports Google Native App Launcher. The goal is to preserve
-// the previous behavior and support user choice of non-system provided Mail
-// client apps. System-provided Mail client app will be referred to as
-// "System Mail". The migration goals are:
-// - If a user has not made a choice for preferred mailto: handler in the past,
-//   the behavior after upgrading to this version should not change.
-// - If a user had disabled Gmail app as the preferred mailto: handler in the
-//   past, System Mail should be selected as the default mailto: handler.
-// - If a user installs Gmail app after the installation of Chrome, Gmail app
-//   will be chosen as the default mailto: handler, preserving the previous
-//   behavior.
-// - If a user installs another 3rd party mail client app, assuming that the
-//   3rd party mail client app is explicitly supported in Chrome, the new 3rd
-//   party mail client app can be set as the default mailto: handler through
-//   Tools > Settings > Content Settings.
-//
-// Two NSUserDefaults keys are interpreted with the following meanings:
-// - kLegacyShouldAutoOpenKey: The existence of this key implies that the user
-//   has used Chrome in the past and had Gmail app installed. Gmail app may or
-//   may not be installed currently.
-// - kMailtoDefaultHandlerKey: If this key is not set, System Mail app is used
-//   to handle mailto: URLs. If this key is set, the value is a string that is
-//   the key to |_handlers| which maps to a MailtoHandler object.
-//
-- (void)migrateLegacyOptions {
-  NSUserDefaults* defaults = [NSUserDefaults standardUserDefaults];
-  NSString* defaultsKey = [[self class] userDefaultsKey];
-
-  // User previously had a selection made for opening mailto: links with Gmail,
-  // upgrade will set Gmail app to be the default mailto: handler. If user had
-  // opted out to using Gmail app (even when it was installed), migrate user
-  // to use system-provided Mail client.
-  // The key used in NSUserDefaults is from legacy code when Native App
-  // Launcher was still in use. The general format is a string prefix,
-  // underscore, then followed by the App Store ID of the application.
-  NSString* const kGmailAppStoreID = @"422689480";
-  NSString* const kLegacyShouldAutoOpenKey =
-      [NSString stringWithFormat:@"ShouldAutoOpenLinks_%@", kGmailAppStoreID];
-  NSNumber* legacyValue = [defaults objectForKey:kLegacyShouldAutoOpenKey];
-  if (legacyValue) {
-    switch ([legacyValue intValue]) {
-      case 0:
-      case 2: {
-        // If legacy user was using default (kAutoOpenLinksNotSet) or had
-        // explicitly chosen to use Gmail (kAutoOpenLinksYes), migrate to use
-        // Gmail app.
-        MailtoHandler* gmailHandler = _handlers[kGmailAppStoreID];
-        if ([gmailHandler isAvailable])
-          [defaults setObject:kGmailAppStoreID forKey:defaultsKey];
-        else
-          [defaults removeObjectForKey:defaultsKey];
-        break;
-      }
-      case 1:
-        // If legacy user was not using Gmail to handle mailto: links
-        // (kAutoOpenLinksNo), consider this an explicit user choice and
-        // migrate to use system-provided Mail app.
-        [defaults setObject:[[self class] systemMailApp] forKey:defaultsKey];
-        break;
-      default:
-        NOTREACHED();
-        break;
-    }
-    [defaults removeObjectForKey:kLegacyShouldAutoOpenKey];
-  }
-}
-
-- (void)autoDefaultToGmailIfInstalled {
-  NSUserDefaults* defaults = [NSUserDefaults standardUserDefaults];
-  NSString* defaultsKey = [[self class] userDefaultsKey];
-  // If a default handler for mailto: has already been set, user had made an
-  // explicit choice and no further changes should be done.
-  if ([defaults objectForKey:defaultsKey])
-    return;
-
-  NSString* const kGmailAppStoreID = @"422689480";
-  MailtoHandler* gmailHandler = _handlers[kGmailAppStoreID];
-  if ([gmailHandler isAvailable])
-    [defaults setObject:kGmailAppStoreID forKey:defaultsKey];
-}
-
-@end
diff --git a/ios/chrome/browser/web/legacy_mailto_url_rewriter_unittest.mm b/ios/chrome/browser/web/legacy_mailto_url_rewriter_unittest.mm
deleted file mode 100644
index 2d8c260..0000000
--- a/ios/chrome/browser/web/legacy_mailto_url_rewriter_unittest.mm
+++ /dev/null
@@ -1,251 +0,0 @@
-// Copyright 2017 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#import "ios/chrome/browser/web/legacy_mailto_url_rewriter.h"
-
-#import "ios/chrome/browser/web/fake_mailto_handler_helpers.h"
-#import "ios/chrome/browser/web/mailto_handler_system_mail.h"
-#include "testing/gtest/include/gtest/gtest.h"
-#include "testing/gtest_mac.h"
-#include "testing/platform_test.h"
-
-#if !defined(__has_feature) || !__has_feature(objc_arc)
-#error "This file requires ARC support."
-#endif
-
-namespace {
-
-// Defines the 3 valid states for ShouldAutoOpenLinks_422689480.
-enum {
-  kAutoOpenLinksNotSet = 0,
-  kAutoOpenLinksNo = 1,
-  kAutoOpenLinksYes = 2,
-};
-NSString* const kLegacyShouldAutoOpenKey = @"ShouldAutoOpenLinks_422689480";
-NSString* const kGmailAppStoreID = @"422689480";
-
-}  // namespace
-
-#pragma mark - Unit Test Cases
-
-class LegacyMailtoURLRewriterTest : public PlatformTest {
- public:
-  LegacyMailtoURLRewriterTest() {
-    [[NSUserDefaults standardUserDefaults]
-        removeObjectForKey:[LegacyMailtoURLRewriter userDefaultsKey]];
-  }
-};
-
-// Tests that a standard instance has the expected values.
-TEST_F(LegacyMailtoURLRewriterTest, TestStandardInstance) {
-  LegacyMailtoURLRewriter* rewriter =
-      [LegacyMailtoURLRewriter mailtoURLRewriterWithStandardHandlers];
-  EXPECT_TRUE(rewriter);
-  EXPECT_GT([[rewriter defaultHandlerName] length], 0U);
-  // ID for system Mail client app must not be an empty string.
-  EXPECT_GT([[LegacyMailtoURLRewriter systemMailApp] length], 0U);
-
-  NSArray<MailtoHandler*>* handlers = [rewriter defaultHandlers];
-  EXPECT_GE([handlers count], 1U);
-  for (MailtoHandler* handler in handlers) {
-    ASSERT_TRUE(handler);
-    NSString* appStoreID = [handler appStoreID];
-    NSString* expectedDefaultAppID =
-        [handler isAvailable] ? appStoreID
-                              : [LegacyMailtoURLRewriter systemMailApp];
-    [rewriter setDefaultHandlerID:appStoreID];
-    EXPECT_NSEQ(expectedDefaultAppID, [rewriter defaultHandlerID]);
-    MailtoHandler* foundHandler = [rewriter defaultHandlerByID:appStoreID];
-    EXPECT_NSEQ(handler, foundHandler);
-  }
-}
-
-TEST_F(LegacyMailtoURLRewriterTest, TestDefaultsInvalidToSystemMail) {
-  // Sets up a LegacyMailtoURLRewriter with 2 MailtoHandler objects:
-  // - system-provided Mail client app
-  // - Gmail app, but it is not installed
-  LegacyMailtoURLRewriter* rewriter = [[LegacyMailtoURLRewriter alloc] init];
-  MailtoHandler* systemMailHandler = [[MailtoHandlerSystemMail alloc] init];
-  MailtoHandler* fakeGmailHandler =
-      [[FakeMailtoHandlerGmailNotInstalled alloc] init];
-  [rewriter setDefaultHandlers:@[ systemMailHandler, fakeGmailHandler ]];
-  // Sets the default handler to Gmail (which is not installed). This simulates
-  // the situation when Gmail was installed and set as the default handler.
-  // Then Gmail app is deleted from the device.
-  [rewriter setDefaultHandlerID:[fakeGmailHandler appStoreID]];
-  // Verifies that the system-provided Mail app automatically assumes the
-  // default handler.
-  EXPECT_NSEQ([LegacyMailtoURLRewriter systemMailApp],
-              [rewriter defaultHandlerID]);
-}
-
-TEST_F(LegacyMailtoURLRewriterTest, TestUserPreferencePersistence) {
-  // Sets up a first LegacyMailtoURLRewriter with at least 2 MailtoHandler
-  // objects. A faked Gmail handler that is installed must be used or
-  // -setDefaultHandlers: will just skip it.
-  LegacyMailtoURLRewriter* rewriter = [[LegacyMailtoURLRewriter alloc] init];
-  MailtoHandler* systemMailHandler = [[MailtoHandlerSystemMail alloc] init];
-  MailtoHandler* fakeGmailHandler =
-      [[FakeMailtoHandlerGmailInstalled alloc] init];
-  [rewriter setDefaultHandlers:@[ systemMailHandler, fakeGmailHandler ]];
-
-  // Verifies that there must be 2 registered handlers. Then find a
-  // MailtoHandler that is not the current default and set that as the new
-  // default.
-  NSArray<MailtoHandler*>* handlers = [rewriter defaultHandlers];
-  ASSERT_GE([handlers count], 2U);
-  NSString* initialHandlerID = [rewriter defaultHandlerID];
-  NSString* otherHandlerID = nil;
-  for (MailtoHandler* handler in handlers) {
-    if (![initialHandlerID isEqualToString:[handler appStoreID]]) {
-      otherHandlerID = [handler appStoreID];
-      break;
-    }
-  }
-  ASSERT_TRUE([otherHandlerID length]);
-  [rewriter setDefaultHandlerID:otherHandlerID];
-
-  // Create a new LegacyMailtoURLRewriter object and verify that the current
-  // default is the |otherHandlerID| set in the previous step.
-  LegacyMailtoURLRewriter* rewriter2 = [[LegacyMailtoURLRewriter alloc] init];
-  [rewriter2 setDefaultHandlers:@[ systemMailHandler, fakeGmailHandler ]];
-  EXPECT_NSEQ(otherHandlerID, [rewriter2 defaultHandlerID]);
-}
-
-TEST_F(LegacyMailtoURLRewriterTest, TestChangeObserver) {
-  CountingMailtoURLRewriterObserver* observer =
-      [[CountingMailtoURLRewriterObserver alloc] init];
-  ASSERT_EQ(0, [observer changeCount]);
-
-  // Sets up a LegacyMailtoURLRewriter object. The default handler is Gmail app
-  // because |fakeGmailHandler| reports that it is "installed".
-  LegacyMailtoURLRewriter* rewriter = [[LegacyMailtoURLRewriter alloc] init];
-  MailtoHandler* systemMailHandler = [[MailtoHandlerSystemMail alloc] init];
-  MailtoHandler* fakeGmailHandler =
-      [[FakeMailtoHandlerGmailInstalled alloc] init];
-  [rewriter setDefaultHandlers:@[ systemMailHandler, fakeGmailHandler ]];
-  EXPECT_NSEQ([fakeGmailHandler appStoreID], [rewriter defaultHandlerID]);
-  [rewriter setObserver:observer];
-
-  // Setting system Mail app as handler while current handler is Gmail should
-  // trigger the observer callback, incrementing count from 0 to 1.
-  [rewriter setDefaultHandlerID:[systemMailHandler appStoreID]];
-  EXPECT_EQ(1, [observer changeCount]);
-
-  // Setting system Mail app as handler while current handler is already
-  // system Mail app should not trigger the observer callback. Count remains
-  // at 1.
-  [rewriter setDefaultHandlerID:[systemMailHandler appStoreID]];
-  EXPECT_EQ(1, [observer changeCount]);
-
-  // Setting Gmail app as the default handler when current handler is system
-  // Mail app should trigger the observer callback. Count increases from 1 to 2.
-  [rewriter setDefaultHandlerID:[fakeGmailHandler appStoreID]];
-  EXPECT_EQ(2, [observer changeCount]);
-
-  // Deallocates the observer to test that there are no ill side-effects (e.g.
-  // crashes) when observer's lifetime is shorter than the rewriter.
-  observer = nil;
-  [rewriter setDefaultHandlerID:[systemMailHandler appStoreID]];
-}
-
-// Tests that a new user without Gmail app installed launches system Mail app.
-TEST_F(LegacyMailtoURLRewriterTest, TestNewUserNoGmail) {
-  // Sets pre-condition for a user who did not have Chrome installed.
-  NSUserDefaults* defaults = [NSUserDefaults standardUserDefaults];
-  [defaults removeObjectForKey:kLegacyShouldAutoOpenKey];
-  // A faked MailtoHandler for Gmail.
-  MailtoHandler* fakeGmailHandler =
-      [[FakeMailtoHandlerGmailNotInstalled alloc] init];
-
-  // Sets up a LegacyMailtoURLRewriter for testing.
-  LegacyMailtoURLRewriter* rewriter = [[LegacyMailtoURLRewriter alloc] init];
-  MailtoHandler* systemMailHandler = [[MailtoHandlerSystemMail alloc] init];
-  [rewriter setDefaultHandlers:@[ systemMailHandler, fakeGmailHandler ]];
-
-  // Verify that LegacyMailtoURLRewriter will use the system Mail app.
-  EXPECT_NSEQ([LegacyMailtoURLRewriter systemMailApp],
-              [rewriter defaultHandlerID]);
-}
-
-// Tests that a new user with Gmail app installed launches Gmail app.
-TEST_F(LegacyMailtoURLRewriterTest, TestNewUserWithGmail) {
-  // Sets pre-condition for a user who did not have Chrome installed.
-  NSUserDefaults* defaults = [NSUserDefaults standardUserDefaults];
-  [defaults removeObjectForKey:kLegacyShouldAutoOpenKey];
-  // A faked MailtoHandler for Gmail.
-  MailtoHandler* fakeGmailHandler =
-      [[FakeMailtoHandlerGmailInstalled alloc] init];
-
-  // Sets up a LegacyMailtoURLRewriter for testing.
-  LegacyMailtoURLRewriter* rewriter = [[LegacyMailtoURLRewriter alloc] init];
-  MailtoHandler* systemMailHandler = [[MailtoHandlerSystemMail alloc] init];
-  [rewriter setDefaultHandlers:@[ systemMailHandler, fakeGmailHandler ]];
-
-  // Verify that LegacyMailtoURLRewriter will use Gmail app.
-  EXPECT_NSEQ(kGmailAppStoreID, [rewriter defaultHandlerID]);
-}
-
-// Tests that a user who has Gmail installed but has chosen not to use Gmail
-// as the app to handle mailto: links retains the same behavior when upgrading
-// Chrome.
-TEST_F(LegacyMailtoURLRewriterTest, TestUpgradeUserWithGmailDisabled) {
-  // Sets pre-condition for a user who had Chrome installed.
-  NSUserDefaults* defaults = [NSUserDefaults standardUserDefaults];
-  [defaults setObject:@(kAutoOpenLinksNo) forKey:kLegacyShouldAutoOpenKey];
-  // A faked MailtoHandler for Gmail.
-  MailtoHandler* fakeGmailHandler =
-      [[FakeMailtoHandlerGmailInstalled alloc] init];
-
-  // Sets up a LegacyMailtoURLRewriter for testing.
-  LegacyMailtoURLRewriter* rewriter = [[LegacyMailtoURLRewriter alloc] init];
-  MailtoHandler* systemMailHandler = [[MailtoHandlerSystemMail alloc] init];
-  [rewriter setDefaultHandlers:@[ systemMailHandler, fakeGmailHandler ]];
-
-  // Verify that LegacyMailtoURLRewriter will use the system Mail app. As part
-  // of the "upgrade", the legacy key should be removed as well.
-  EXPECT_NSEQ([LegacyMailtoURLRewriter systemMailApp],
-              [rewriter defaultHandlerID]);
-  EXPECT_FALSE([defaults objectForKey:kLegacyShouldAutoOpenKey]);
-}
-
-// Tests that a user who has Gmail installed and has chosen to use Gmail as the
-// app to handle mailto: links retains the same behavior.
-TEST_F(LegacyMailtoURLRewriterTest, TestUpgradeUserWithGmailEnabled) {
-  // Sets pre-condition for a user who did not have Chrome installed.
-  NSUserDefaults* defaults = [NSUserDefaults standardUserDefaults];
-  [defaults setObject:@(kAutoOpenLinksYes) forKey:kLegacyShouldAutoOpenKey];
-  // A faked MailtoHandler for Gmail.
-  MailtoHandler* fakeGmailHandler =
-      [[FakeMailtoHandlerGmailInstalled alloc] init];
-
-  // Sets up a LegacyMailtoURLRewriter for testing.
-  LegacyMailtoURLRewriter* rewriter = [[LegacyMailtoURLRewriter alloc] init];
-  MailtoHandler* systemMailHandler = [[MailtoHandlerSystemMail alloc] init];
-  [rewriter setDefaultHandlers:@[ systemMailHandler, fakeGmailHandler ]];
-
-  // Verify that LegacyMailtoURLRewriter will use Gmail app. As part of the
-  // upgrade, the legacy key should be removed as well.
-  EXPECT_NSEQ(kGmailAppStoreID, [rewriter defaultHandlerID]);
-  EXPECT_FALSE([defaults objectForKey:kLegacyShouldAutoOpenKey]);
-}
-
-// Tests that a user who installed Gmail after started using Chrome gets Gmail
-// as the handler of mailto: links.
-TEST_F(LegacyMailtoURLRewriterTest, TestInstalledGmailAfterChrome) {
-  // Pre-condition for a user who did not have Chrome installed.
-  NSUserDefaults* defaults = [NSUserDefaults standardUserDefaults];
-  [defaults removeObjectForKey:kLegacyShouldAutoOpenKey];
-  // A faked MailtoHandler for Gmail.
-  MailtoHandler* fakeGmailHandler =
-      [[FakeMailtoHandlerGmailInstalled alloc] init];
-
-  // Sets up a LegacyMailtoURLRewriter for testing.
-  LegacyMailtoURLRewriter* rewriter = [[LegacyMailtoURLRewriter alloc] init];
-  MailtoHandler* systemMailHandler = [[MailtoHandlerSystemMail alloc] init];
-  [rewriter setDefaultHandlers:@[ systemMailHandler, fakeGmailHandler ]];
-
-  // Verify that LegacyMailtoURLRewriter will use Gmail app.
-  EXPECT_NSEQ(kGmailAppStoreID, [rewriter defaultHandlerID]);
-}
diff --git a/ios/chrome/test/BUILD.gn b/ios/chrome/test/BUILD.gn
index 5d2c08d..fbdb197 100644
--- a/ios/chrome/test/BUILD.gn
+++ b/ios/chrome/test/BUILD.gn
@@ -189,7 +189,7 @@
     "//ios/chrome/browser/ui/external_search:unit_tests",
     "//ios/chrome/browser/ui/fancy_ui:unit_tests",
     "//ios/chrome/browser/ui/first_run:unit_tests",
-    "//ios/chrome/browser/ui/fullscreen:unit_tests",
+    "//ios/chrome/browser/ui/fullscreen:legacy_unit_tests",
     "//ios/chrome/browser/ui/history:unit_tests",
     "//ios/chrome/browser/ui/history_popup:unit_tests",
     "//ios/chrome/browser/ui/icons:unit_tests",
diff --git a/ios/chrome/test/earl_grey/BUILD.gn b/ios/chrome/test/earl_grey/BUILD.gn
index 49309e9..57b330b 100644
--- a/ios/chrome/test/earl_grey/BUILD.gn
+++ b/ios/chrome/test/earl_grey/BUILD.gn
@@ -200,7 +200,7 @@
     "//ios/chrome/browser/ui/payments:payments_ui",
     "//ios/chrome/browser/ui/settings:settings",
     "//ios/chrome/browser/ui/static_content",
-    "//ios/chrome/browser/ui/toolbar",
+    "//ios/chrome/browser/ui/toolbar/public",
     "//ios/chrome/browser/ui/tools_menu",
     "//ios/chrome/test/app:test_support",
     "//ios/testing:ios_test_support",
diff --git a/ios/chrome/test/earl_grey/chrome_matchers.mm b/ios/chrome/test/earl_grey/chrome_matchers.mm
index 15ca6ec7..bb30cf0 100644
--- a/ios/chrome/test/earl_grey/chrome_matchers.mm
+++ b/ios/chrome/test/earl_grey/chrome_matchers.mm
@@ -23,7 +23,7 @@
 #import "ios/chrome/browser/ui/settings/settings_collection_view_controller.h"
 #import "ios/chrome/browser/ui/settings/sync_settings_collection_view_controller.h"
 #import "ios/chrome/browser/ui/static_content/static_html_view_controller.h"
-#import "ios/chrome/browser/ui/toolbar/toolbar_controller_constants.h"
+#import "ios/chrome/browser/ui/toolbar/public/toolbar_controller_constants.h"
 #import "ios/chrome/browser/ui/tools_menu/tools_menu_constants.h"
 #import "ios/chrome/browser/ui/tools_menu/tools_popup_controller.h"
 #import "ios/chrome/browser/ui/uikit_ui_util.h"
diff --git a/ios/clean/chrome/browser/ui/adaptor/application_commands_adaptor.mm b/ios/clean/chrome/browser/ui/adaptor/application_commands_adaptor.mm
index df4635b..58ccd603 100644
--- a/ios/clean/chrome/browser/ui/adaptor/application_commands_adaptor.mm
+++ b/ios/clean/chrome/browser/ui/adaptor/application_commands_adaptor.mm
@@ -82,8 +82,9 @@
 
 #pragma mark - ApplicationSettingsCommands
 
-- (void)showAccountsSettings {
-  [self showAlert:@"showAccountsSettings"];
+- (void)showAccountsSettingsFromViewController:
+    (UIViewController*)baseViewController {
+  [self showAlert:@"showAccountsSettingsFromViewController:"];
 }
 
 - (void)showSyncSettings {
diff --git a/ios/clean/chrome/browser/ui/toolbar/BUILD.gn b/ios/clean/chrome/browser/ui/toolbar/BUILD.gn
index a78a5e6..b2d1043 100644
--- a/ios/clean/chrome/browser/ui/toolbar/BUILD.gn
+++ b/ios/clean/chrome/browser/ui/toolbar/BUILD.gn
@@ -47,7 +47,7 @@
     "//ios/chrome/browser/ui",
     "//ios/chrome/browser/ui/commands",
     "//ios/chrome/browser/ui/history_popup/requirements",
-    "//ios/chrome/browser/ui/toolbar",
+    "//ios/chrome/browser/ui/toolbar/public",
     "//ios/clean/chrome/browser/ui/commands",
     "//ios/clean/chrome/browser/ui/tools",
     "//ios/clean/chrome/browser/ui/transitions/animators",
diff --git a/ios/clean/chrome/browser/ui/toolbar/toolbar_view_controller.mm b/ios/clean/chrome/browser/ui/toolbar/toolbar_view_controller.mm
index d5c27c9..08930a4 100644
--- a/ios/clean/chrome/browser/ui/toolbar/toolbar_view_controller.mm
+++ b/ios/clean/chrome/browser/ui/toolbar/toolbar_view_controller.mm
@@ -7,7 +7,7 @@
 #import "base/mac/foundation_util.h"
 #import "ios/chrome/browser/ui/commands/history_popup_commands.h"
 #include "ios/chrome/browser/ui/rtl_geometry.h"
-#import "ios/chrome/browser/ui/toolbar/toolbar_controller_constants.h"
+#import "ios/chrome/browser/ui/toolbar/public/toolbar_controller_constants.h"
 #import "ios/chrome/browser/ui/uikit_ui_util.h"
 #import "ios/clean/chrome/browser/ui/commands/navigation_commands.h"
 #import "ios/clean/chrome/browser/ui/commands/tab_grid_commands.h"
diff --git a/ios/web/BUILD.gn b/ios/web/BUILD.gn
index 36635316..da3d3340 100644
--- a/ios/web/BUILD.gn
+++ b/ios/web/BUILD.gn
@@ -19,7 +19,18 @@
 source_set("web") {
   public_deps = [
     ":service_names",
+
+    # TODO(crbug.com/616244): Remove private files from public dependencies.
+    "//ios/web/navigation:core",
+    "//ios/web/net",
     "//ios/web/public",
+    "//ios/web/web_state",
+    "//ios/web/web_state:error_translation_util",
+    "//ios/web/web_state:navigation_context",
+    "//ios/web/web_state:web_state_impl_header",
+    "//ios/web/web_state/ui",
+    "//ios/web/web_state/ui:wk_web_view_configuration_provider",
+    "//ios/web/webui",
     "//net",
   ]
 
@@ -29,23 +40,15 @@
     ":navigation_resources",
     ":resources",
     "//base",
-    "//components/url_formatter",
-    "//ios/net",
-    "//ios/third_party/blink:html_tokenizer",
+    "//ios/web/interstitials",
+    "//ios/web/navigation",
+    "//ios/web/net",
     "//ios/web/public",
-    "//mojo/public/cpp/system",
-    "//mojo/public/js",
+    "//ios/web/web_state:web_view_internal_creation_util",
     "//services/catalog/public/cpp",
     "//services/service_manager",
     "//services/service_manager/embedder",
-    "//services/service_manager/public/cpp",
     "//services/service_manager/runner/common",
-    "//services/service_manager/runner/host:lib",
-    "//ui/base",
-    "//ui/gfx",
-    "//ui/gfx/geometry",
-    "//ui/resources",
-    "//url",
   ]
 
   sources = [
@@ -53,63 +56,8 @@
     "browser_url_rewriter_impl.h",
     "browser_url_rewriter_impl.mm",
     "crw_navigation_item_storage.mm",
-    "interstitials/html_web_interstitial_impl.h",
-    "interstitials/html_web_interstitial_impl.mm",
-    "interstitials/native_web_interstitial_impl.h",
-    "interstitials/native_web_interstitial_impl.mm",
-    "interstitials/web_interstitial_impl.h",
-    "interstitials/web_interstitial_impl.mm",
+    "features.mm",
     "load_committed_details.cc",
-    "navigation/crw_navigation_item_holder.h",
-    "navigation/crw_navigation_item_holder.mm",
-    "navigation/crw_placeholder_navigation_info.h",
-    "navigation/crw_placeholder_navigation_info.mm",
-    "navigation/crw_session_controller+private_constructors.h",
-    "navigation/crw_session_controller.h",
-    "navigation/crw_session_controller.mm",
-    "navigation/legacy_navigation_manager_impl.h",
-    "navigation/legacy_navigation_manager_impl.mm",
-    "navigation/navigation_item_impl.h",
-    "navigation/navigation_item_impl.mm",
-    "navigation/navigation_item_impl_list.h",
-    "navigation/navigation_item_impl_list.mm",
-    "navigation/navigation_item_storage_builder.h",
-    "navigation/navigation_item_storage_builder.mm",
-    "navigation/navigation_manager_delegate.h",
-    "navigation/navigation_manager_impl.h",
-    "navigation/navigation_manager_impl.mm",
-    "navigation/navigation_manager_util.h",
-    "navigation/navigation_manager_util.mm",
-    "navigation/nscoder_util.h",
-    "navigation/nscoder_util.mm",
-    "navigation/placeholder_navigation_util.h",
-    "navigation/placeholder_navigation_util.mm",
-    "navigation/serializable_user_data_manager_impl.h",
-    "navigation/serializable_user_data_manager_impl.mm",
-    "navigation/session_storage_builder.h",
-    "navigation/session_storage_builder.mm",
-    "navigation/time_smoother.cc",
-    "navigation/time_smoother.h",
-    "navigation/wk_based_navigation_manager_impl.h",
-    "navigation/wk_based_navigation_manager_impl.mm",
-    "net/cert_host_pair.cc",
-    "net/cert_host_pair.h",
-    "net/cert_policy.cc",
-    "net/certificate_policy_cache.cc",
-    "net/cookie_notification_bridge.h",
-    "net/cookie_notification_bridge.mm",
-    "net/crw_cert_verification_controller.h",
-    "net/crw_cert_verification_controller.mm",
-    "net/crw_ssl_status_updater.h",
-    "net/crw_ssl_status_updater.mm",
-    "net/request_group_util.h",
-    "net/request_group_util.mm",
-    "net/request_tracker_factory_impl.h",
-    "net/request_tracker_factory_impl.mm",
-    "net/request_tracker_impl.h",
-    "net/request_tracker_impl.mm",
-    "net/web_http_protocol_handler_delegate.h",
-    "net/web_http_protocol_handler_delegate.mm",
     "service_manager_connection_impl.cc",
     "service_manager_connection_impl.h",
     "service_manager_context.h",
@@ -118,103 +66,9 @@
     "url_util.cc",
     "web_client.mm",
     "web_kit_constants.cc",
-    "web_state/context_menu_constants.h",
-    "web_state/context_menu_constants.mm",
-    "web_state/context_menu_params.mm",
-    "web_state/context_menu_params_utils.h",
-    "web_state/context_menu_params_utils.mm",
-    "web_state/crw_pass_kit_downloader.h",
-    "web_state/crw_pass_kit_downloader.mm",
-    "web_state/error_translation_util.h",
-    "web_state/error_translation_util.mm",
-    "web_state/global_web_state_event_tracker.h",
-    "web_state/global_web_state_event_tracker.mm",
-    "web_state/global_web_state_observer.cc",
-    "web_state/js/crw_js_injection_manager.mm",
-    "web_state/js/crw_js_injection_receiver.mm",
-    "web_state/js/crw_js_plugin_placeholder_manager.h",
-    "web_state/js/crw_js_plugin_placeholder_manager.mm",
-    "web_state/js/crw_js_post_request_loader.h",
-    "web_state/js/crw_js_post_request_loader.mm",
-    "web_state/js/crw_js_window_id_manager.h",
-    "web_state/js/crw_js_window_id_manager.mm",
-    "web_state/js/page_script_util.h",
-    "web_state/js/page_script_util.mm",
-    "web_state/navigation_context_impl.h",
-    "web_state/navigation_context_impl.mm",
-    "web_state/page_viewport_state.h",
-    "web_state/page_viewport_state.mm",
-    "web_state/session_certificate_policy_cache_impl.h",
-    "web_state/session_certificate_policy_cache_impl.mm",
-    "web_state/session_certificate_policy_cache_storage_builder.h",
-    "web_state/session_certificate_policy_cache_storage_builder.mm",
-    "web_state/ui/crw_context_menu_controller.h",
-    "web_state/ui/crw_context_menu_controller.mm",
-    "web_state/ui/crw_generic_content_view.mm",
-    "web_state/ui/crw_swipe_recognizer_provider.h",
-    "web_state/ui/crw_touch_tracking_recognizer.h",
-    "web_state/ui/crw_touch_tracking_recognizer.mm",
-    "web_state/ui/crw_web_controller.h",
-    "web_state/ui/crw_web_controller.mm",
-    "web_state/ui/crw_web_controller_container_view.h",
-    "web_state/ui/crw_web_controller_container_view.mm",
-    "web_state/ui/crw_web_view_content_view.mm",
-    "web_state/ui/crw_web_view_navigation_proxy.h",
-    "web_state/ui/crw_web_view_proxy_impl.h",
-    "web_state/ui/crw_web_view_proxy_impl.mm",
-    "web_state/ui/crw_web_view_scroll_view_proxy.mm",
-    "web_state/ui/crw_wk_navigation_states.h",
-    "web_state/ui/crw_wk_navigation_states.mm",
-    "web_state/ui/crw_wk_script_message_router.h",
-    "web_state/ui/crw_wk_script_message_router.mm",
-    "web_state/ui/web_view_js_utils.h",
-    "web_state/ui/web_view_js_utils.mm",
-    "web_state/ui/wk_back_forward_list_item_holder.h",
-    "web_state/ui/wk_back_forward_list_item_holder.mm",
-    "web_state/ui/wk_web_view_configuration_provider.h",
-    "web_state/ui/wk_web_view_configuration_provider.mm",
-    "web_state/web_controller_observer_bridge.h",
-    "web_state/web_controller_observer_bridge.mm",
-    "web_state/web_state.mm",
-    "web_state/web_state_delegate.mm",
-    "web_state/web_state_delegate_bridge.mm",
-    "web_state/web_state_impl.h",
-    "web_state/web_state_impl.mm",
-    "web_state/web_state_observer.mm",
-    "web_state/web_state_observer_bridge.mm",
-    "web_state/web_state_policy_decider.mm",
-    "web_state/web_state_weak_ptr_factory.h",
-    "web_state/web_state_weak_ptr_factory.mm",
-    "web_state/web_view_internal_creation_util.h",
-    "web_state/web_view_internal_creation_util.mm",
-    "web_state/wk_web_view_security_util.h",
-    "web_state/wk_web_view_security_util.mm",
     "web_thread_impl.cc",
     "web_thread_impl.h",
     "web_view_creation_util.mm",
-    "webui/crw_web_ui_manager.h",
-    "webui/crw_web_ui_manager.mm",
-    "webui/crw_web_ui_page_builder.h",
-    "webui/crw_web_ui_page_builder.mm",
-    "webui/mojo_facade.h",
-    "webui/mojo_facade.mm",
-    "webui/shared_resources_data_source_ios.h",
-    "webui/shared_resources_data_source_ios.mm",
-    "webui/url_data_manager_ios.cc",
-    "webui/url_data_manager_ios.h",
-    "webui/url_data_manager_ios_backend.h",
-    "webui/url_data_manager_ios_backend.mm",
-    "webui/url_data_source_ios.mm",
-    "webui/url_data_source_ios_impl.cc",
-    "webui/url_data_source_ios_impl.h",
-    "webui/url_fetcher_block_adapter.h",
-    "webui/url_fetcher_block_adapter.mm",
-    "webui/web_ui_ios_controller_factory_registry.cc",
-    "webui/web_ui_ios_controller_factory_registry.h",
-    "webui/web_ui_ios_data_source_impl.h",
-    "webui/web_ui_ios_data_source_impl.mm",
-    "webui/web_ui_ios_impl.h",
-    "webui/web_ui_ios_impl.mm",
   ]
 
   libs = [ "WebKit.framework" ]
@@ -252,6 +106,7 @@
     "//ios/testing:ios_test_support",
     "//ios/testing/earl_grey:earl_grey_support",
     "//ios/third_party/earl_grey:earl_grey+link",
+    "//ios/web/interstitials",
     "//ios/web/public/test",
     "//net",
   ]
@@ -365,6 +220,8 @@
     "//ios/net",
     "//ios/testing:ios_test_support",
     "//ios/testing:ocmock_support",
+    "//ios/web/navigation",
+    "//ios/web/navigation:core",
     "//ios/web/public",
     "//ios/web/public/test",
     "//ios/web/public/test/fakes",
@@ -372,6 +229,7 @@
     "//ios/web/test:test_constants",
     "//ios/web/test:test_support",
     "//ios/web/test/fakes",
+    "//ios/web/web_state/ui:crw_web_view_navigation_proxy",
     "//net:test_support",
     "//services/service_manager/public/cpp",
     "//testing/gmock",
@@ -410,6 +268,7 @@
     "//ios/net",
     "//ios/testing:ios_test_support",
     "//ios/testing:ocmock_support",
+    "//ios/web/navigation",
     "//ios/web/public",
     "//ios/web/public/test",
     "//ios/web/public/test/fakes",
@@ -417,6 +276,7 @@
     "//ios/web/test:test_constants",
     "//ios/web/test:test_support",
     "//ios/web/test/fakes",
+    "//ios/web/web_state:wk_web_view_security_util",
     "//net:test_support",
     "//services/service_manager/public/cpp",
     "//testing/gmock",
@@ -468,6 +328,7 @@
     "//ios/web/test:mojo_bindings",
     "//ios/web/test:test_constants",
     "//ios/web/test:test_support",
+    "//ios/web/web_state:page_viewport_state",
     "//net:test_support",
     "//services/service_manager/public/cpp",
     "//testing/gmock",
@@ -506,6 +367,11 @@
     "//ios/web/test:mojo_bindings",
     "//ios/web/test:test_constants",
     "//ios/web/test:test_support",
+    "//ios/web/web_state:context_menu",
+    "//ios/web/web_state:crw_pass_kit_downloader",
+    "//ios/web/web_state:session_certificate_policy_cache",
+    "//ios/web/web_state:web_view_internal_creation_util",
+    "//ios/web/web_state:wk_web_view_security_util",
     "//net:test_support",
     "//services/service_manager/public/cpp",
     "//testing/gmock",
@@ -550,6 +416,9 @@
     "//ios/web/test:mojo_bindings",
     "//ios/web/test:test_constants",
     "//ios/web/test:test_support",
+    "//ios/web/web_state:context_menu",
+    "//ios/web/web_state/js",
+    "//ios/web/web_state/ui:crw_wk_script_message_router",
     "//net:test_support",
     "//services/service_manager/public/cpp",
     "//testing/gmock",
@@ -580,12 +449,19 @@
     "//ios/net",
     "//ios/testing:ios_test_support",
     "//ios/testing:ocmock_support",
+    "//ios/web/navigation",
+    "//ios/web/navigation:core",
     "//ios/web/public",
     "//ios/web/public/test",
     "//ios/web/public/test/fakes",
     "//ios/web/test:mojo_bindings",
     "//ios/web/test:test_constants",
     "//ios/web/test:test_support",
+    "//ios/web/test/fakes:fakes",
+    "//ios/web/web_state:wk_web_view_security_util",
+    "//ios/web/web_state/js",
+    "//ios/web/web_state/ui:crw_wk_script_message_router",
+    "//ios/web/web_state/ui:web_view_js_utils",
     "//net:test_support",
     "//services/service_manager/public/cpp",
     "//testing/gmock",
@@ -649,6 +525,7 @@
     "//ios/testing:http_server_bundle_data",
     "//ios/testing:ios_test_support",
     "//ios/web:resources_grit",
+    "//ios/web/navigation:core",
     "//ios/web/public/test",
     "//ios/web/public/test/fakes",
     "//ios/web/public/test/http_server",
diff --git a/ios/web/features.mm b/ios/web/features.mm
new file mode 100644
index 0000000..a110e72
--- /dev/null
+++ b/ios/web/features.mm
@@ -0,0 +1,14 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ios/web/public/features.h"
+
+namespace web {
+namespace features {
+
+const base::Feature kSlimNavigationManager{"SlimNavigationManager",
+                                           base::FEATURE_DISABLED_BY_DEFAULT};
+
+}  // namespace features
+}  // namespace web
diff --git a/ios/web/interstitials/BUILD.gn b/ios/web/interstitials/BUILD.gn
new file mode 100644
index 0000000..92c972e
--- /dev/null
+++ b/ios/web/interstitials/BUILD.gn
@@ -0,0 +1,27 @@
+# Copyright 2017 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import("//ios/build/config.gni")
+
+source_set("interstitials") {
+  deps = [
+    "//base",
+    "//ios/web/navigation:core",
+    "//ios/web/public",
+    "//ios/web/web_state:web_state_impl_header",
+    "//ios/web/web_state/ui:web_view_js_utils",
+    "//ui/gfx/geometry",
+  ]
+
+  sources = [
+    "html_web_interstitial_impl.h",
+    "html_web_interstitial_impl.mm",
+    "native_web_interstitial_impl.h",
+    "native_web_interstitial_impl.mm",
+    "web_interstitial_impl.h",
+    "web_interstitial_impl.mm",
+  ]
+
+  configs += [ "//build/config/compiler:enable_arc" ]
+}
diff --git a/ios/web/navigation/BUILD.gn b/ios/web/navigation/BUILD.gn
new file mode 100644
index 0000000..f0e1216
--- /dev/null
+++ b/ios/web/navigation/BUILD.gn
@@ -0,0 +1,70 @@
+# Copyright 2017 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import("//ios/build/config.gni")
+
+source_set("navigation") {
+  deps = [
+    ":core",
+    "//base",
+    "//ios/web:core",
+    "//ios/web/public",
+    "//ios/web/web_state:session_certificate_policy_cache",
+    "//ios/web/web_state:web_state_impl_header",
+    "//ios/web/web_state/ui:crw_web_view_navigation_proxy",
+    "//ui/base",
+    "//url",
+  ]
+
+  sources = [
+    "crw_navigation_item_holder.h",
+    "crw_navigation_item_holder.mm",
+    "crw_placeholder_navigation_info.h",
+    "crw_placeholder_navigation_info.mm",
+    "crw_session_controller+private_constructors.h",
+    "crw_session_controller.h",
+    "crw_session_controller.mm",
+    "legacy_navigation_manager_impl.h",
+    "legacy_navigation_manager_impl.mm",
+    "navigation_item_impl_list.h",
+    "navigation_item_impl_list.mm",
+    "navigation_item_storage_builder.h",
+    "navigation_item_storage_builder.mm",
+    "nscoder_util.h",
+    "nscoder_util.mm",
+    "placeholder_navigation_util.h",
+    "placeholder_navigation_util.mm",
+    "serializable_user_data_manager_impl.h",
+    "serializable_user_data_manager_impl.mm",
+    "session_storage_builder.h",
+    "session_storage_builder.mm",
+    "time_smoother.cc",
+    "time_smoother.h",
+    "wk_based_navigation_manager_impl.h",
+    "wk_based_navigation_manager_impl.mm",
+  ]
+
+  configs += [ "//build/config/compiler:enable_arc" ]
+}
+
+source_set("core") {
+  deps = [
+    "//base",
+    "//components/url_formatter:url_formatter",
+    "//ios/web/public",
+    "//ui/base",
+  ]
+
+  sources = [
+    "navigation_item_impl.h",
+    "navigation_item_impl.mm",
+    "navigation_manager_delegate.h",
+    "navigation_manager_impl.h",
+    "navigation_manager_impl.mm",
+    "navigation_manager_util.h",
+    "navigation_manager_util.mm",
+  ]
+
+  configs += [ "//build/config/compiler:enable_arc" ]
+}
diff --git a/ios/web/net/BUILD.gn b/ios/web/net/BUILD.gn
new file mode 100644
index 0000000..c25c7817
--- /dev/null
+++ b/ios/web/net/BUILD.gn
@@ -0,0 +1,40 @@
+# Copyright 2017 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import("//ios/build/config.gni")
+
+source_set("net") {
+  deps = [
+    "//base",
+    "//ios/net",
+    "//ios/web:core",
+    "//ios/web/navigation:core",
+    "//ios/web/public",
+    "//ios/web/web_state:wk_web_view_security_util",
+    "//net",
+  ]
+
+  sources = [
+    "cert_host_pair.cc",
+    "cert_host_pair.h",
+    "cert_policy.cc",
+    "certificate_policy_cache.cc",
+    "cookie_notification_bridge.h",
+    "cookie_notification_bridge.mm",
+    "crw_cert_verification_controller.h",
+    "crw_cert_verification_controller.mm",
+    "crw_ssl_status_updater.h",
+    "crw_ssl_status_updater.mm",
+    "request_group_util.h",
+    "request_group_util.mm",
+    "request_tracker_factory_impl.h",
+    "request_tracker_factory_impl.mm",
+    "request_tracker_impl.h",
+    "request_tracker_impl.mm",
+    "web_http_protocol_handler_delegate.h",
+    "web_http_protocol_handler_delegate.mm",
+  ]
+
+  configs += [ "//build/config/compiler:enable_arc" ]
+}
diff --git a/ios/web/public/BUILD.gn b/ios/web/public/BUILD.gn
index dca3bc0..db5e21b1 100644
--- a/ios/web/public/BUILD.gn
+++ b/ios/web/public/BUILD.gn
@@ -30,6 +30,7 @@
     "favicon_status.h",
     "favicon_url.cc",
     "favicon_url.h",
+    "features.h",
     "interstitials/web_interstitial.h",
     "interstitials/web_interstitial_delegate.h",
     "java_script_dialog_callback.h",
diff --git a/ios/web/public/features.h b/ios/web/public/features.h
new file mode 100644
index 0000000..3161def
--- /dev/null
+++ b/ios/web/public/features.h
@@ -0,0 +1,19 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef IOS_WEB_PUBLIC_FEATURES_H_
+#define IOS_WEB_PUBLIC_FEATURES_H_
+
+#include "base/feature_list.h"
+
+namespace web {
+namespace features {
+
+// Used to enable the WKBackForwardList based navigation manager.
+extern const base::Feature kSlimNavigationManager;
+
+}  // namespace features
+}  // namespace web
+
+#endif  // IOS_WEB_PUBLIC_FEATURES_H_
diff --git a/ios/web/public/test/BUILD.gn b/ios/web/public/test/BUILD.gn
index 5512303..5e8d8dd 100644
--- a/ios/web/public/test/BUILD.gn
+++ b/ios/web/public/test/BUILD.gn
@@ -11,6 +11,8 @@
     "//base/test:test_support",
     "//ios/testing:ios_test_support",
     "//ios/web:web",
+    "//ios/web/interstitials",
+    "//ios/web/navigation:core",
     "//ios/web/public/test/fakes",
     "//ios/web/public/test/http_server",
     "//ios/web/test:test_support",
diff --git a/ios/web/public/test/fakes/BUILD.gn b/ios/web/public/test/fakes/BUILD.gn
index 58ba28de..af7b70a 100644
--- a/ios/web/public/test/fakes/BUILD.gn
+++ b/ios/web/public/test/fakes/BUILD.gn
@@ -8,9 +8,12 @@
 
   deps = [
     "//base",
-    "//ios/web:web",
+    "//ios/web/public",
     "//ios/web/test:test_constants",
-    "//mojo/common:common_custom_types",
+    "//ios/web/web_state:navigation_context",
+    "//ios/web/web_state/ui:crw_web_view_navigation_proxy",
+    "//ios/web/web_state/ui:web_view_js_utils",
+    "//ios/web/webui:webui",
     "//net:test_support",
     "//testing/gtest",
     "//ui/base",
diff --git a/ios/web/public/test/fakes/test_web_client.h b/ios/web/public/test/fakes/test_web_client.h
index e02f51d..0e79b5c1 100644
--- a/ios/web/public/test/fakes/test_web_client.h
+++ b/ios/web/public/test/fakes/test_web_client.h
@@ -35,7 +35,6 @@
                              const GURL&,
                              bool overridable,
                              const base::Callback<void(bool)>&) override;
-  bool IsSlimNavigationManagerEnabled() const override;
 
   // Changes Early Page Script for testing purposes.
   void SetEarlyPageScript(NSString* page_script);
@@ -50,9 +49,6 @@
   }
   bool last_cert_error_overridable() { return last_cert_error_overridable_; }
 
-  // Makes |IsSlimNavigationManagerEnabled| return the given flag value.
-  void SetIsSlimNavigationManager(bool flag);
-
  private:
   NSString* early_page_script_;
   // Last arguments passed to AllowCertificateError.
@@ -60,7 +56,6 @@
   net::SSLInfo last_cert_error_ssl_info_;
   GURL last_cert_error_request_url_;
   bool last_cert_error_overridable_;
-  bool is_slim_navigation_manager_enabled_;
 };
 
 }  // namespace web
diff --git a/ios/web/public/test/fakes/test_web_client.mm b/ios/web/public/test/fakes/test_web_client.mm
index 3a26d76..2524605 100644
--- a/ios/web/public/test/fakes/test_web_client.mm
+++ b/ios/web/public/test/fakes/test_web_client.mm
@@ -5,6 +5,7 @@
 #import "ios/web/public/test/fakes/test_web_client.h"
 
 #include "base/logging.h"
+#include "ios/web/public/features.h"
 #include "ios/web/test/test_url_constants.h"
 #include "ui/base/resource/resource_bundle.h"
 #include "url/gurl.h"
@@ -16,9 +17,7 @@
 namespace web {
 
 TestWebClient::TestWebClient()
-    : last_cert_error_code_(0),
-      last_cert_error_overridable_(true),
-      is_slim_navigation_manager_enabled_(false) {}
+    : last_cert_error_code_(0), last_cert_error_overridable_(true) {}
 
 TestWebClient::~TestWebClient() {}
 
@@ -63,12 +62,4 @@
   callback.Run(false);
 }
 
-bool TestWebClient::IsSlimNavigationManagerEnabled() const {
-  return is_slim_navigation_manager_enabled_;
-}
-
-void TestWebClient::SetIsSlimNavigationManager(bool flag) {
-  is_slim_navigation_manager_enabled_ = flag;
-}
-
 }  // namespace web
diff --git a/ios/web/test/BUILD.gn b/ios/web/test/BUILD.gn
index fa8bc67f..999f82b 100644
--- a/ios/web/test/BUILD.gn
+++ b/ios/web/test/BUILD.gn
@@ -57,6 +57,7 @@
     "//base",
     "//base/test:test_support",
     "//ios/web:web",
+    "//ios/web/navigation:core",
     "//ios/web/public/test/fakes",
     "//ios/web/public/test/http_server",
     "//ios/web/test/fakes",
diff --git a/ios/web/test/fakes/BUILD.gn b/ios/web/test/fakes/BUILD.gn
index 6f944bd..5d4e8fbe 100644
--- a/ios/web/test/fakes/BUILD.gn
+++ b/ios/web/test/fakes/BUILD.gn
@@ -7,7 +7,10 @@
   testonly = true
 
   deps = [
-    "//ios/web:web",
+    "//base",
+    "//ios/web/navigation:core",
+    "//ios/web/public:public",
+    "//ios/web/web_state/ui:crw_web_view_navigation_proxy",
     "//third_party/ocmock:ocmock",
   ]
 
diff --git a/ios/web/web_client.mm b/ios/web/web_client.mm
index 7d9bd6a..aac6ef9 100644
--- a/ios/web/web_client.mm
+++ b/ios/web/web_client.mm
@@ -7,6 +7,7 @@
 #import <Foundation/Foundation.h>
 
 #include "ios/web/public/app/web_main_parts.h"
+#include "ios/web/public/features.h"
 
 #if !defined(__has_feature) || !__has_feature(objc_arc)
 #error "This file requires ARC support."
@@ -93,7 +94,7 @@
 }
 
 bool WebClient::IsSlimNavigationManagerEnabled() const {
-  return false;
+  return base::FeatureList::IsEnabled(web::features::kSlimNavigationManager);
 }
 
 }  // namespace web
diff --git a/ios/web/web_state/BUILD.gn b/ios/web/web_state/BUILD.gn
new file mode 100644
index 0000000..61dcb84
--- /dev/null
+++ b/ios/web/web_state/BUILD.gn
@@ -0,0 +1,194 @@
+# Copyright 2017 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import("//ios/build/config.gni")
+
+source_set("web_state") {
+  deps = [
+    ":context_menu",
+    ":navigation_context",
+    ":session_certificate_policy_cache",
+    ":web_controller_observer_bridge",
+    ":web_state_impl_header",
+    ":wk_web_view_security_util",
+    "//base",
+    "//ios/web/interstitials",
+    "//ios/web/navigation",
+    "//ios/web/navigation:core",
+    "//ios/web/public",
+    "//ios/web/web_state/ui",
+    "//ios/web/web_state/ui:crw_web_view_navigation_proxy",
+    "//ios/web/webui",
+    "//ui/gfx",
+  ]
+
+  sources = [
+    "global_web_state_event_tracker.h",
+    "global_web_state_event_tracker.mm",
+    "global_web_state_observer.cc",
+    "web_state.mm",
+    "web_state_delegate.mm",
+    "web_state_delegate_bridge.mm",
+    "web_state_impl.mm",
+    "web_state_observer.mm",
+    "web_state_observer_bridge.mm",
+    "web_state_policy_decider.mm",
+    "web_state_weak_ptr_factory.h",
+    "web_state_weak_ptr_factory.mm",
+  ]
+
+  libs = [ "WebKit.framework" ]
+
+  configs += [ "//build/config/compiler:enable_arc" ]
+}
+
+source_set("wk_web_view_security_util") {
+  deps = [
+    "//base",
+    "//ios/web/public",
+  ]
+
+  sources = [
+    "wk_web_view_security_util.h",
+    "wk_web_view_security_util.mm",
+  ]
+
+  configs += [ "//build/config/compiler:enable_arc" ]
+}
+
+source_set("navigation_context") {
+  deps = [
+    "//base",
+    "//ios/web/public",
+  ]
+
+  sources = [
+    "navigation_context_impl.h",
+    "navigation_context_impl.mm",
+  ]
+
+  configs += [ "//build/config/compiler:enable_arc" ]
+}
+
+source_set("web_state_impl_header") {
+  deps = [
+    "//base",
+    "//ios/web/navigation:core",
+    "//ios/web/public",
+  ]
+
+  sources = [
+    "web_state_impl.h",
+  ]
+
+  configs += [ "//build/config/compiler:enable_arc" ]
+}
+
+source_set("session_certificate_policy_cache") {
+  deps = [
+    "//base",
+    "//ios/web/public",
+  ]
+
+  sources = [
+    "session_certificate_policy_cache_impl.h",
+    "session_certificate_policy_cache_impl.mm",
+    "session_certificate_policy_cache_storage_builder.h",
+    "session_certificate_policy_cache_storage_builder.mm",
+  ]
+
+  configs += [ "//build/config/compiler:enable_arc" ]
+}
+
+source_set("crw_pass_kit_downloader") {
+  deps = [
+    "//base",
+    "//components/url_formatter",
+    "//ios/web/public",
+  ]
+
+  sources = [
+    "crw_pass_kit_downloader.h",
+    "crw_pass_kit_downloader.mm",
+  ]
+
+  configs += [ "//build/config/compiler:enable_arc" ]
+}
+
+source_set("error_translation_util") {
+  deps = [
+    "//base",
+    "//net",
+  ]
+
+  sources = [
+    "error_translation_util.h",
+    "error_translation_util.mm",
+  ]
+
+  configs += [ "//build/config/compiler:enable_arc" ]
+}
+
+source_set("page_viewport_state") {
+  deps = [
+    "//base",
+    "//net",
+  ]
+
+  sources = [
+    "page_viewport_state.h",
+    "page_viewport_state.mm",
+  ]
+
+  configs += [ "//build/config/compiler:enable_arc" ]
+}
+
+source_set("web_controller_observer_bridge") {
+  deps = [
+    "//base",
+    "//ios/web/public",
+  ]
+
+  sources = [
+    "web_controller_observer_bridge.h",
+    "web_controller_observer_bridge.mm",
+  ]
+
+  configs += [ "//build/config/compiler:enable_arc" ]
+}
+
+source_set("web_view_internal_creation_util") {
+  deps = [
+    "//base",
+    "//ios/web/public",
+    "//ios/web/public:user_agent",
+    "//ios/web/web_state/ui:crw_context_menu_controller",
+    "//ios/web/web_state/ui:wk_web_view_configuration_provider",
+  ]
+
+  sources = [
+    "web_view_internal_creation_util.h",
+    "web_view_internal_creation_util.mm",
+  ]
+
+  configs += [ "//build/config/compiler:enable_arc" ]
+}
+
+source_set("context_menu") {
+  deps = [
+    "//base",
+    "//components/url_formatter",
+    "//ios/web/public",
+  ]
+
+  sources = [
+    "context_menu_constants.h",
+    "context_menu_constants.mm",
+    "context_menu_params.mm",
+    "context_menu_params_utils.h",
+    "context_menu_params_utils.mm",
+  ]
+
+  configs += [ "//build/config/compiler:enable_arc" ]
+}
diff --git a/ios/web/web_state/js/BUILD.gn b/ios/web/web_state/js/BUILD.gn
new file mode 100644
index 0000000..9612c47d
--- /dev/null
+++ b/ios/web/web_state/js/BUILD.gn
@@ -0,0 +1,28 @@
+# Copyright 2017 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import("//ios/build/config.gni")
+
+source_set("js") {
+  deps = [
+    "//base",
+    "//ios/web/public",
+    "//ios/web/web_state/ui:crw_wk_script_message_router",
+  ]
+
+  sources = [
+    "crw_js_injection_manager.mm",
+    "crw_js_injection_receiver.mm",
+    "crw_js_plugin_placeholder_manager.h",
+    "crw_js_plugin_placeholder_manager.mm",
+    "crw_js_post_request_loader.h",
+    "crw_js_post_request_loader.mm",
+    "crw_js_window_id_manager.h",
+    "crw_js_window_id_manager.mm",
+    "page_script_util.h",
+    "page_script_util.mm",
+  ]
+
+  configs += [ "//build/config/compiler:enable_arc" ]
+}
diff --git a/ios/web/web_state/ui/BUILD.gn b/ios/web/web_state/ui/BUILD.gn
new file mode 100644
index 0000000..3aa08a52
--- /dev/null
+++ b/ios/web/web_state/ui/BUILD.gn
@@ -0,0 +1,133 @@
+# Copyright 2017 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import("//ios/build/config.gni")
+
+source_set("ui") {
+  deps = [
+    ":crw_context_menu_controller",
+    ":crw_web_view_navigation_proxy",
+    ":crw_wk_script_message_router",
+    ":web_view_js_utils",
+    "//base",
+    "//ios/net",
+    "//ios/web:core",
+    "//ios/web/interstitials",
+    "//ios/web/navigation",
+    "//ios/web/navigation:core",
+    "//ios/web/net:net",
+    "//ios/web/public",
+    "//ios/web/web_state:context_menu",
+    "//ios/web/web_state:crw_pass_kit_downloader",
+    "//ios/web/web_state:error_translation_util",
+    "//ios/web/web_state:navigation_context",
+    "//ios/web/web_state:page_viewport_state",
+    "//ios/web/web_state:web_controller_observer_bridge",
+    "//ios/web/web_state:web_state_impl_header",
+    "//ios/web/web_state:web_view_internal_creation_util",
+    "//ios/web/web_state:wk_web_view_security_util",
+    "//ios/web/web_state/js",
+    "//ios/web/web_state/ui:wk_web_view_configuration_provider",
+    "//ios/web/webui:webui",
+    "//ui/base",
+    "//url",
+  ]
+
+  sources = [
+    "crw_generic_content_view.mm",
+    "crw_swipe_recognizer_provider.h",
+    "crw_touch_tracking_recognizer.h",
+    "crw_touch_tracking_recognizer.mm",
+    "crw_web_controller.h",
+    "crw_web_controller.mm",
+    "crw_web_controller_container_view.h",
+    "crw_web_controller_container_view.mm",
+    "crw_web_view_content_view.mm",
+    "crw_web_view_proxy_impl.h",
+    "crw_web_view_proxy_impl.mm",
+    "crw_web_view_scroll_view_proxy.mm",
+    "crw_wk_navigation_states.h",
+    "crw_wk_navigation_states.mm",
+    "wk_back_forward_list_item_holder.h",
+    "wk_back_forward_list_item_holder.mm",
+  ]
+
+  libs = [ "WebKit.framework" ]
+
+  configs += [ "//build/config/compiler:enable_arc" ]
+}
+
+source_set("crw_wk_script_message_router") {
+  deps = [
+    "//base",
+  ]
+
+  sources = [
+    "crw_wk_script_message_router.h",
+    "crw_wk_script_message_router.mm",
+  ]
+
+  libs = [ "WebKit.framework" ]
+
+  configs += [ "//build/config/compiler:enable_arc" ]
+}
+
+source_set("crw_web_view_navigation_proxy") {
+  sources = [
+    "crw_web_view_navigation_proxy.h",
+  ]
+
+  libs = [ "WebKit.framework" ]
+
+  configs += [ "//build/config/compiler:enable_arc" ]
+}
+
+source_set("crw_context_menu_controller") {
+  deps = [
+    "//base",
+    "//ios/web/public",
+    "//ios/web/web_state:context_menu",
+  ]
+
+  sources = [
+    "crw_context_menu_controller.h",
+    "crw_context_menu_controller.mm",
+  ]
+
+  configs += [ "//build/config/compiler:enable_arc" ]
+}
+
+source_set("wk_web_view_configuration_provider") {
+  deps = [
+    ":crw_wk_script_message_router",
+    "//base",
+    "//ios/web/public",
+    "//ios/web/web_state/js",
+  ]
+
+  sources = [
+    "wk_web_view_configuration_provider.h",
+    "wk_web_view_configuration_provider.mm",
+  ]
+
+  libs = [ "WebKit.framework" ]
+
+  configs += [ "//build/config/compiler:enable_arc" ]
+}
+
+source_set("web_view_js_utils") {
+  deps = [
+    "//base",
+    "//ios/web/public",
+  ]
+
+  sources = [
+    "web_view_js_utils.h",
+    "web_view_js_utils.mm",
+  ]
+
+  libs = [ "WebKit.framework" ]
+
+  configs += [ "//build/config/compiler:enable_arc" ]
+}
diff --git a/ios/web/web_state/ui/crw_web_controller_unittest.mm b/ios/web/web_state/ui/crw_web_controller_unittest.mm
index 0f6f7ca..f8b916f 100644
--- a/ios/web/web_state/ui/crw_web_controller_unittest.mm
+++ b/ios/web/web_state/ui/crw_web_controller_unittest.mm
@@ -15,6 +15,7 @@
 #include "base/strings/utf_string_conversions.h"
 #import "base/test/ios/wait_util.h"
 #import "ios/testing/ocmock_complex_type_helper.h"
+#import "ios/testing/wait_util.h"
 #import "ios/web/navigation/crw_session_controller.h"
 #import "ios/web/navigation/navigation_item_impl.h"
 #import "ios/web/navigation/navigation_manager_impl.h"
@@ -35,6 +36,7 @@
 #import "ios/web/public/web_state/ui/crw_web_view_content_view.h"
 #include "ios/web/public/web_state/url_verification_constants.h"
 #include "ios/web/public/web_state/web_state_observer.h"
+#import "ios/web/test/fakes/crw_test_back_forward_list.h"
 #import "ios/web/test/web_test_with_web_controller.h"
 #import "ios/web/test/wk_web_view_crash_utils.h"
 #import "ios/web/web_state/ui/crw_web_controller_container_view.h"
@@ -165,7 +167,8 @@
     }
 #endif
 
-    [[result stub] backForwardList];
+    mock_wk_list_ = [[CRWTestBackForwardList alloc] init];
+    OCMStub([result backForwardList]).andReturn(mock_wk_list_);
     [[[result stub] andReturn:[NSURL URLWithString:@(kTestURLString)]] URL];
     [[result stub] setNavigationDelegate:[OCMArg checkWithBlock:^(id delegate) {
                      navigation_delegate_ = delegate;
@@ -185,6 +188,7 @@
   __weak id<WKNavigationDelegate> navigation_delegate_;
   UIScrollView* scroll_view_;
   id mock_web_view_;
+  CRWTestBackForwardList* mock_wk_list_;
 };
 
 // Tests that AllowCertificateError is called with correct arguments if
@@ -622,6 +626,7 @@
   // Simulate a page load to trigger a URL update.
   [navigation_delegate_ webView:mock_web_view_
       didStartProvisionalNavigation:nil];
+  [mock_wk_list_ setCurrentURL:@"http://chromium.test"];
   [navigation_delegate_ webView:mock_web_view_ didCommitNavigation:nil];
 
   URLVerificationTrustLevel trust_level = kNone;
@@ -641,6 +646,7 @@
   }
 
   void Load(const GURL& URL) {
+    TestWebStateObserver observer(web_state());
     NavigationManagerImpl& navigation_manager =
         [web_controller() webStateImpl]->GetNavigationManagerImpl();
     navigation_manager.AddPendingItem(
@@ -648,6 +654,16 @@
         NavigationInitiationType::USER_INITIATED,
         NavigationManager::UserAgentOverrideOption::INHERIT);
     [web_controller() loadCurrentURL];
+
+    // Native URL is loaded asynchronously with WKBasedNavigationManager. Wait
+    // for navigation to finish before asserting.
+    if (GetWebClient()->IsSlimNavigationManagerEnabled()) {
+      TestWebStateObserver* observer_ptr = &observer;
+      ASSERT_TRUE(testing::WaitUntilConditionOrTimeout(
+          testing::kWaitForPageLoadTimeout, ^{
+            return observer_ptr->did_finish_navigation_info() != nullptr;
+          }));
+    }
   }
 
   TestNativeContentProvider* mock_native_provider_;
diff --git a/ios/web/webui/BUILD.gn b/ios/web/webui/BUILD.gn
new file mode 100644
index 0000000..5e84fef
--- /dev/null
+++ b/ios/web/webui/BUILD.gn
@@ -0,0 +1,47 @@
+# Copyright 2017 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import("//ios/build/config.gni")
+
+source_set("webui") {
+  deps = [
+    "//base",
+    "//ios/web:resources",
+    "//ios/web:resources_grit",
+    "//ios/web/public",
+    "//ios/web/web_state:web_state_impl_header",
+    "//services/service_manager/runner/common",
+    "//ui/base",
+    "//ui/resources",
+    "//url",
+  ]
+
+  sources = [
+    "crw_web_ui_manager.h",
+    "crw_web_ui_manager.mm",
+    "crw_web_ui_page_builder.h",
+    "crw_web_ui_page_builder.mm",
+    "mojo_facade.h",
+    "mojo_facade.mm",
+    "shared_resources_data_source_ios.h",
+    "shared_resources_data_source_ios.mm",
+    "url_data_manager_ios.cc",
+    "url_data_manager_ios.h",
+    "url_data_manager_ios_backend.h",
+    "url_data_manager_ios_backend.mm",
+    "url_data_source_ios.mm",
+    "url_data_source_ios_impl.cc",
+    "url_data_source_ios_impl.h",
+    "url_fetcher_block_adapter.h",
+    "url_fetcher_block_adapter.mm",
+    "web_ui_ios_controller_factory_registry.cc",
+    "web_ui_ios_controller_factory_registry.h",
+    "web_ui_ios_data_source_impl.h",
+    "web_ui_ios_data_source_impl.mm",
+    "web_ui_ios_impl.h",
+    "web_ui_ios_impl.mm",
+  ]
+
+  configs += [ "//build/config/compiler:enable_arc" ]
+}
diff --git a/ios/web_view/BUILD.gn b/ios/web_view/BUILD.gn
index 56fddc5..8f1bbc1 100644
--- a/ios/web_view/BUILD.gn
+++ b/ios/web_view/BUILD.gn
@@ -227,6 +227,7 @@
   testonly = true
   sources = [
     "internal/cwv_html_element_unittest.mm",
+    "internal/cwv_preferences_unittest.mm",
     "internal/cwv_preview_element_info_unittest.mm",
   ]
   sources += ios_web_view_sources
diff --git a/ios/web_view/internal/cwv_preferences.mm b/ios/web_view/internal/cwv_preferences.mm
index 7ebd2ed..9a3df1c2 100644
--- a/ios/web_view/internal/cwv_preferences.mm
+++ b/ios/web_view/internal/cwv_preferences.mm
@@ -4,6 +4,7 @@
 
 #import "ios/web_view/internal/cwv_preferences_internal.h"
 
+#include "components/autofill/core/common/autofill_pref_names.h"
 #include "components/prefs/pref_service.h"
 #include "components/translate/core/browser/translate_pref_names.h"
 #include "components/translate/core/browser/translate_prefs.h"
@@ -42,4 +43,12 @@
   translatePrefs.ResetToDefaults();
 }
 
+- (void)setAutofillEnabled:(BOOL)enabled {
+  _prefService->SetBoolean(autofill::prefs::kAutofillEnabled, enabled);
+}
+
+- (BOOL)isAutofillEnabled {
+  return _prefService->GetBoolean(autofill::prefs::kAutofillEnabled);
+}
+
 @end
diff --git a/ios/web_view/internal/cwv_preferences_unittest.mm b/ios/web_view/internal/cwv_preferences_unittest.mm
new file mode 100644
index 0000000..2c370e5
--- /dev/null
+++ b/ios/web_view/internal/cwv_preferences_unittest.mm
@@ -0,0 +1,62 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#import "ios/web_view/internal/cwv_preferences_internal.h"
+
+#import <Foundation/Foundation.h>
+#include <memory>
+
+#include "base/memory/scoped_refptr.h"
+#include "components/autofill/core/common/autofill_pref_names.h"
+#include "components/pref_registry/pref_registry_syncable.h"
+#include "components/prefs/in_memory_pref_store.h"
+#include "components/prefs/pref_service.h"
+#include "components/prefs/pref_service_factory.h"
+#include "components/translate/core/browser/translate_pref_names.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#import "testing/gtest_mac.h"
+#include "testing/platform_test.h"
+
+#if !defined(__has_feature) || !__has_feature(objc_arc)
+#error "This file requires ARC support."
+#endif
+
+namespace ios_web_view {
+
+class CWVPreferencesTest : public PlatformTest {
+ protected:
+  CWVPreferencesTest() {
+    scoped_refptr<user_prefs::PrefRegistrySyncable> pref_registry =
+        new user_prefs::PrefRegistrySyncable;
+    pref_registry->RegisterBooleanPref(autofill::prefs::kAutofillEnabled, true);
+    pref_registry->RegisterBooleanPref(prefs::kEnableTranslate, true);
+
+    scoped_refptr<PersistentPrefStore> pref_store = new InMemoryPrefStore();
+    PrefServiceFactory factory;
+    factory.set_user_prefs(pref_store);
+
+    pref_service_ = factory.Create(pref_registry.get());
+    preferences_ =
+        [[CWVPreferences alloc] initWithPrefService:pref_service_.get()];
+  }
+
+  std::unique_ptr<PrefService> pref_service_;
+  CWVPreferences* preferences_;
+};
+
+// Tests CWVPreferences |autofillEnabled|.
+TEST_F(CWVPreferencesTest, AutofillEnabled) {
+  EXPECT_TRUE(preferences_.autofillEnabled);
+  preferences_.autofillEnabled = NO;
+  EXPECT_FALSE(preferences_.autofillEnabled);
+}
+
+// Tests CWVPreferences |translationEnabled|.
+TEST_F(CWVPreferencesTest, TranslationEnabled) {
+  EXPECT_TRUE(preferences_.translationEnabled);
+  preferences_.translationEnabled = NO;
+  EXPECT_FALSE(preferences_.translationEnabled);
+}
+
+}  // namespace ios_web_view
diff --git a/ios/web_view/internal/web_view_browser_state.mm b/ios/web_view/internal/web_view_browser_state.mm
index 1aae7bc..cd812efe 100644
--- a/ios/web_view/internal/web_view_browser_state.mm
+++ b/ios/web_view/internal/web_view_browser_state.mm
@@ -70,9 +70,7 @@
 
   base::ThreadRestrictions::SetIOAllowed(wasIOAllowed);
 
-  ActiveStateManager* active_state_manager =
-      ActiveStateManager::FromBrowserState(this);
-  active_state_manager->SetActive(true);
+  ActiveStateManager::FromBrowserState(this)->SetActive(true);
 
   BrowserStateDependencyManager::GetInstance()->CreateBrowserStateServices(
       this);
@@ -81,6 +79,8 @@
 WebViewBrowserState::~WebViewBrowserState() {
   BrowserStateDependencyManager::GetInstance()->DestroyBrowserStateServices(
       this);
+
+  ActiveStateManager::FromBrowserState(this)->SetActive(false);
 }
 
 PrefService* WebViewBrowserState::GetPrefs() {
diff --git a/ios/web_view/public/cwv_autofill_controller.h b/ios/web_view/public/cwv_autofill_controller.h
new file mode 100644
index 0000000..29ba068
--- /dev/null
+++ b/ios/web_view/public/cwv_autofill_controller.h
@@ -0,0 +1,52 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef IOS_WEB_VIEW_PUBLIC_CWV_AUTOFILL_CONTROLLER_H_
+#define IOS_WEB_VIEW_PUBLIC_CWV_AUTOFILL_CONTROLLER_H_
+
+#import <Foundation/Foundation.h>
+
+#import "cwv_export.h"
+
+NS_ASSUME_NONNULL_BEGIN
+
+@class CWVAutofillSuggestion;
+@protocol CWVAutofillControllerDelegate;
+
+CWV_EXPORT
+// Exposes features that allow autofilling html forms. Forms maybe include
+// single fields, address forms, or credit card forms.
+@interface CWVAutofillController : NSObject
+
+// Delegate to receive autofill callbacks.
+@property(nonatomic, weak, nullable) id<CWVAutofillControllerDelegate> delegate;
+
+// Clears the html form element with the 'name' attribute equal to |formName|.
+// No-op if no such form is found.
+// |completionHandler| will only be called on success.
+- (void)clearFormWithName:(NSString*)formName
+        completionHandler:(nullable void (^)(void))completionHandler;
+
+// For the field named |fieldName| in the form named |formName|, fetches
+// suggestions that can be used to autofill.
+// No-op if no such form and field can be found in the current page.
+// |completionHandler| will only be called on success.
+- (void)fetchSuggestionsForFormWithName:(NSString*)formName
+                              fieldName:(NSString*)fieldName
+                      completionHandler:
+                          (void (^)(NSArray<CWVAutofillSuggestion*>*))
+                              completionHandler;
+
+// Takes the |suggestion| and finds the form matching its |formName| and
+// |fieldName| property. If found, autofills the values in to the page.
+// No-op if no such form and field can be found in the current page.
+// |completionHandler| will only be called on success.
+- (void)fillSuggestion:(CWVAutofillSuggestion*)suggestion
+     completionHandler:(nullable void (^)(void))completionHandler;
+
+@end
+
+NS_ASSUME_NONNULL_END
+
+#endif  // IOS_WEB_VIEW_PUBLIC_CWV_AUTOFILL_CONTROLLER_H_
diff --git a/ios/web_view/public/cwv_autofill_controller_delegate.h b/ios/web_view/public/cwv_autofill_controller_delegate.h
new file mode 100644
index 0000000..fc8b7fec
--- /dev/null
+++ b/ios/web_view/public/cwv_autofill_controller_delegate.h
@@ -0,0 +1,52 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef IOS_WEB_VIEW_PUBLIC_CWV_AUTOFILL_CONTROLLER_DELEGATE_H_
+#define IOS_WEB_VIEW_PUBLIC_CWV_AUTOFILL_CONTROLLER_DELEGATE_H_
+
+#import <Foundation/Foundation.h>
+
+#import "cwv_export.h"
+
+NS_ASSUME_NONNULL_BEGIN
+
+@class CWVAutofillController;
+@class CWVAutofillFormSuggestion;
+
+CWV_EXPORT
+// Protocol to receive callbacks related to autofill.
+// |fieldName| is the 'name' attribute of a html field.
+// |formName| is the 'name' attribute of a html <form>.
+// |value| is the 'value' attribute of the html field.
+// Example:
+// <form name='_formName_'>
+//   <input name='_fieldName_' value='_value_'>
+// </form>
+@protocol CWVAutofillControllerDelegate<NSObject>
+
+@optional
+
+// Called when a form field element receives a "focus" event.
+- (void)autofillController:(CWVAutofillController*)autofillController
+    didFocusOnFieldWithName:(NSString*)fieldName
+                   formName:(NSString*)formName
+                      value:(NSString*)value;
+
+// Called when a form field element receives an "input" event.
+- (void)autofillController:(CWVAutofillController*)autofillController
+    didInputInFieldWithName:(NSString*)fieldName
+                   formName:(NSString*)formName
+                      value:(NSString*)value;
+
+// Called when a form field element receives a "blur" (un-focused) event.
+- (void)autofillController:(CWVAutofillController*)autofillController
+    didBlurOnFieldWithName:(NSString*)fieldName
+                  formName:(NSString*)formName
+                     value:(NSString*)value;
+
+@end
+
+NS_ASSUME_NONNULL_END
+
+#endif  // IOS_WEB_VIEW_PUBLIC_CWV_AUTOFILL_CONTROLLER_DELEGATE_H_
diff --git a/ios/web_view/public/cwv_autofill_suggestion.h b/ios/web_view/public/cwv_autofill_suggestion.h
new file mode 100644
index 0000000..355573d2
--- /dev/null
+++ b/ios/web_view/public/cwv_autofill_suggestion.h
@@ -0,0 +1,61 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef IOS_WEB_VIEW_PUBLIC_CWV_AUTOFILL_SUGGESTION_H_
+#define IOS_WEB_VIEW_PUBLIC_CWV_AUTOFILL_SUGGESTION_H_
+
+#import <Foundation/Foundation.h>
+
+#import "cwv_export.h"
+
+NS_ASSUME_NONNULL_BEGIN
+
+CWV_EXPORT
+// Represents a suggestion for a form based off of a single field.
+// In the case that this suggestion is created from a credit card or address
+// profile, filling using a suggestion may fill more than one field at once.
+// Example:
+//   If an address profile is:
+//   John Doe
+//   1600 Amiphtheatre Pkwy
+//   Mountain View, CA 94403
+//   Then if
+//   <form name="shipping_info">
+//     <input type='text' name="first_name"> <-- focused on this
+//     <input type='text' name="last_name">
+//     <input type='text' name="address_1">
+//     <input type='text' name="address_2">
+//     <input type='text' name="state">
+//     <input type='text' name="country">
+//     <input type='text' name="zip_code">
+//   </form>
+//   The suggestion may look like:
+//   |formName| "shipping_info"
+//   |fieldName| "first_name"
+//   |value| "John"
+//   |displayDescription| "1600 Amphitheatre Pkwy ..."
+//   Using this suggestion would replace all fields with the appropriate value.
+@interface CWVAutofillSuggestion : NSObject
+
+// The 'name' attribute of the html form element.
+@property(nonatomic, copy, readonly) NSString* formName;
+
+// The 'name' attribute of the html field element.
+@property(nonatomic, copy, readonly) NSString* fieldName;
+
+// The string that will replace the field with |fieldName|'s value attribute.
+@property(nonatomic, copy, readonly) NSString* value;
+
+// Non-nil if this suggestion is created from a credit card or address profile.
+// Contain extra information from that profile to help differentiate from other
+// suggestions.
+@property(nonatomic, copy, readonly, nullable) NSString* displayDescription;
+
+- (instancetype)init NS_UNAVAILABLE;
+
+@end
+
+NS_ASSUME_NONNULL_END
+
+#endif  // IOS_WEB_VIEW_PUBLIC_CWV_AUTOFILL_SUGGESTION_H_
diff --git a/ios/web_view/public/cwv_preferences.h b/ios/web_view/public/cwv_preferences.h
index 4e0aefe..66ff2b16 100644
--- a/ios/web_view/public/cwv_preferences.h
+++ b/ios/web_view/public/cwv_preferences.h
@@ -13,12 +13,17 @@
 CWV_EXPORT
 @interface CWVPreferences : NSObject
 
-// Whether or not translation as a feature is turned on.
+// Whether or not translation as a feature is turned on. Defaults to |YES|.
 // Because translate settings are shared from incognito to non-incognito, this
 // has no effect if this instance is from an incognito CWVWebViewConfiguration.
 @property(nonatomic, assign, getter=isTranslationEnabled)
     BOOL translationEnabled;
 
+// Whether or not autofill as a feature is turned on. Defaults to |YES|.
+// If enabled, contents of submitted forms may be saved and offered as a
+// suggestion in either the same or similar forms.
+@property(nonatomic, assign, getter=isAutofillEnabled) BOOL autofillEnabled;
+
 - (instancetype)init NS_UNAVAILABLE;
 
 // Resets all translation settings back to default. In particular, this will
diff --git a/ipc/ipc_channel_mojo.cc b/ipc/ipc_channel_mojo.cc
index 6471d83..80bd7f9 100644
--- a/ipc/ipc_channel_mojo.cc
+++ b/ipc/ipc_channel_mojo.cc
@@ -111,6 +111,7 @@
       pipe_(handle.get()),
       listener_(listener),
       weak_factory_(this) {
+  weak_ptr_ = weak_factory_.GetWeakPtr();
   bootstrap_ = MojoBootstrap::Create(std::move(handle), mode, ipc_task_runner);
 }
 
@@ -183,9 +184,8 @@
   if (task_runner_->RunsTasksInCurrentSequence()) {
     listener_->OnChannelError();
   } else {
-    task_runner_->PostTask(
-        FROM_HERE,
-        base::Bind(&ChannelMojo::OnPipeError, weak_factory_.GetWeakPtr()));
+    task_runner_->PostTask(FROM_HERE,
+                           base::Bind(&ChannelMojo::OnPipeError, weak_ptr_));
   }
 }
 
@@ -230,10 +230,9 @@
 ChannelMojo::CreateThreadSafeChannel() {
   return std::make_unique<mojo::ThreadSafeForwarder<mojom::Channel>>(
       task_runner_,
-      base::Bind(&ChannelMojo::ForwardMessageFromThreadSafePtr,
-                 weak_factory_.GetWeakPtr()),
+      base::Bind(&ChannelMojo::ForwardMessageFromThreadSafePtr, weak_ptr_),
       base::Bind(&ChannelMojo::ForwardMessageWithResponderFromThreadSafePtr,
-                 weak_factory_.GetWeakPtr()),
+                 weak_ptr_),
       *bootstrap_->GetAssociatedGroup());
 }
 
diff --git a/ipc/ipc_channel_mojo.h b/ipc/ipc_channel_mojo.h
index 61bc0db..d5aab3f 100644
--- a/ipc/ipc_channel_mojo.h
+++ b/ipc/ipc_channel_mojo.h
@@ -114,6 +114,8 @@
       const std::string& name,
       mojo::ScopedInterfaceEndpointHandle handle) override;
 
+  base::WeakPtr<ChannelMojo> weak_ptr_;
+
   // A TaskRunner which runs tasks on the ChannelMojo's owning thread.
   scoped_refptr<base::SingleThreadTaskRunner> task_runner_;
 
diff --git a/media/BUILD.gn b/media/BUILD.gn
index 4273c44..e92085b 100644
--- a/media/BUILD.gn
+++ b/media/BUILD.gn
@@ -376,4 +376,48 @@
       "//base",
     ]
   }
+
+  fuzzer_test("media_mp4_box_reader_fuzzer") {
+    sources = [
+      "formats/mp4/mp4_box_reader_fuzzer.cc",
+    ]
+    deps = [
+      ":media",
+      "//base",
+    ]
+    libfuzzer_options = [ "max_len=500" ]
+    dict = "test/mp4.dict"
+  }
+}
+
+if (enable_mse_mpeg2ts_stream_parser) {
+  fuzzer_test("media_es_parser_adts_fuzzer") {
+    sources = [
+      "formats/mp2t/es_parser_adts_fuzzer.cc",
+    ]
+    deps = [
+      ":media",
+      "//base",
+    ]
+  }
+
+  fuzzer_test("media_es_parser_h264_fuzzer") {
+    sources = [
+      "formats/mp2t/es_parser_h264_fuzzer.cc",
+    ]
+    deps = [
+      ":media",
+      "//base",
+    ]
+  }
+
+  fuzzer_test("media_es_parser_mpeg1audio_fuzzer") {
+    sources = [
+      "formats/mp2t/es_parser_mpeg1audio_fuzzer.cc",
+    ]
+    deps = [
+      ":media",
+      "//base",
+    ]
+  }
 }
diff --git a/media/audio/win/audio_device_listener_win_unittest.cc b/media/audio/win/audio_device_listener_win_unittest.cc
index 61b2663..690bcd1a 100644
--- a/media/audio/win/audio_device_listener_win_unittest.cc
+++ b/media/audio/win/audio_device_listener_win_unittest.cc
@@ -29,7 +29,7 @@
 class AudioDeviceListenerWinTest : public testing::Test {
  public:
   AudioDeviceListenerWinTest() {
-    DCHECK(com_init_.succeeded());
+    DCHECK(com_init_.Succeeded());
   }
 
   virtual void SetUp() {
diff --git a/media/audio/win/core_audio_util_win_unittest.cc b/media/audio/win/core_audio_util_win_unittest.cc
index a2814cb..2c53456a 100644
--- a/media/audio/win/core_audio_util_win_unittest.cc
+++ b/media/audio/win/core_audio_util_win_unittest.cc
@@ -29,7 +29,7 @@
   // If we don't initialize the COM library on a thread before using COM,
   // all function calls will return CO_E_NOTINITIALIZED.
   CoreAudioUtilWinTest() {
-    DCHECK(com_init_.succeeded());
+    DCHECK(com_init_.Succeeded());
   }
   ~CoreAudioUtilWinTest() override {}
 
diff --git a/media/base/BUILD.gn b/media/base/BUILD.gn
index 17cfc97..65db677 100644
--- a/media/base/BUILD.gn
+++ b/media/base/BUILD.gn
@@ -126,6 +126,7 @@
     "decryptor.h",
     "demuxer.cc",
     "demuxer.h",
+    "demuxer_memory_limit.h",
     "demuxer_stream.cc",
     "demuxer_stream.h",
     "djb2.cc",
@@ -344,6 +345,12 @@
   if (is_win) {
     deps += [ "//media/base/win" ]
   }
+
+  if (use_low_memory_buffer) {
+    sources += [ "demuxer_memory_limit_lowmem.cc" ]
+  } else {
+    sources += [ "demuxer_memory_limit.cc" ]
+  }
 }
 
 source_set("video_facing") {
diff --git a/media/base/demuxer_memory_limit.cc b/media/base/demuxer_memory_limit.cc
new file mode 100644
index 0000000..d4d6363
--- /dev/null
+++ b/media/base/demuxer_memory_limit.cc
@@ -0,0 +1,18 @@
+// 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 "media/base/demuxer_memory_limit.h"
+
+namespace media {
+
+// 12MB: approximately 5 minutes of 320Kbps content.
+const size_t kDemuxerStreamAudioMemoryLimit = 12 * 1024 * 1024;
+
+// 150MB: approximately 5 minutes of 4Mbps content.
+const size_t kDemuxerStreamVideoMemoryLimit = 150 * 1024 * 1024;
+
+const size_t kDemuxerMemoryLimit =
+    kDemuxerStreamAudioMemoryLimit + kDemuxerStreamVideoMemoryLimit;
+
+}  // namespace media
diff --git a/media/base/demuxer_memory_limit.h b/media/base/demuxer_memory_limit.h
new file mode 100644
index 0000000..1e9bde2
--- /dev/null
+++ b/media/base/demuxer_memory_limit.h
@@ -0,0 +1,24 @@
+// 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 MEDIA_BASE_DEMUXER_MEMORY_LIMIT_H_
+#define MEDIA_BASE_DEMUXER_MEMORY_LIMIT_H_
+
+#include <stddef.h>
+
+#include "media/base/media_export.h"
+
+namespace media {
+
+// The maximum amount of data (in bytes) a demuxer can keep in memory, for a
+// particular type of stream.
+extern const size_t kDemuxerStreamAudioMemoryLimit;
+extern const size_t kDemuxerStreamVideoMemoryLimit;
+
+// The maximum amount of data (in bytes) a demuxer can keep in memory overall.
+extern const size_t kDemuxerMemoryLimit;
+
+}  // namespace media
+
+#endif  // MEDIA_BASE_DEMUXER_MEMORY_LIMIT_H_
diff --git a/media/base/demuxer_memory_limit_lowmem.cc b/media/base/demuxer_memory_limit_lowmem.cc
new file mode 100644
index 0000000..e25d703
--- /dev/null
+++ b/media/base/demuxer_memory_limit_lowmem.cc
@@ -0,0 +1,18 @@
+// 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 "media/base/demuxer_memory_limit.h"
+
+namespace media {
+
+// 2MB: approximately 1 minute of 256Kbps content.
+const size_t kDemuxerStreamAudioMemoryLimit = 2 * 1024 * 1024;
+
+// 30MB: approximately 1 minute of 4Mbps content.
+const size_t kDemuxerStreamVideoMemoryLimit = 30 * 1024 * 1024;
+
+const size_t kDemuxerMemoryLimit =
+    kDemuxerStreamAudioMemoryLimit + kDemuxerStreamVideoMemoryLimit;
+
+}  // namespace media
diff --git a/media/base/video_frame.cc b/media/base/video_frame.cc
index 4ff5fb8..fe944e4a 100644
--- a/media/base/video_frame.cc
+++ b/media/base/video_frame.cc
@@ -1066,15 +1066,9 @@
     const gfx::Size& natural_size,
     base::TimeDelta timestamp,
     bool zero_initialize_memory) {
-  if (!IsYuvPlanar(format)) {
-    NOTIMPLEMENTED();
-    return nullptr;
-  }
-
-  // Since we're creating a new YUV frame (and allocating memory for it
-  // ourselves), we can pad the requested |coded_size| if necessary if the
-  // request does not line up on sample boundaries. See discussion at
-  // http://crrev.com/1240833003
+  // Since we're creating a new frame (and allocating memory for it ourselves),
+  // we can pad the requested |coded_size| if necessary if the request does not
+  // line up on sample boundaries. See discussion at http://crrev.com/1240833003
   const gfx::Size new_coded_size = DetermineAlignedSize(format, coded_size);
   const StorageType storage = STORAGE_OWNED_MEMORY;
   if (!IsValidConfig(format, storage, new_coded_size, visible_rect,
@@ -1087,7 +1081,7 @@
 
   scoped_refptr<VideoFrame> frame(new VideoFrame(
       format, storage, new_coded_size, visible_rect, natural_size, timestamp));
-  frame->AllocateYUV(zero_initialize_memory);
+  frame->AllocateMemory(zero_initialize_memory);
   return frame;
 }
 
@@ -1203,29 +1197,36 @@
   return gfx::Size(max_sample_width, max_sample_height);
 }
 
-void VideoFrame::AllocateYUV(bool zero_initialize_memory) {
+void VideoFrame::AllocateMemory(bool zero_initialize_memory) {
   DCHECK_EQ(storage_type_, STORAGE_OWNED_MEMORY);
   static_assert(0 == kYPlane, "y plane data must be index 0");
 
   size_t data_size = 0;
   size_t offset[kMaxPlanes];
-  for (size_t plane = 0; plane < NumPlanes(format_); ++plane) {
-    // The *2 in alignment for height is because some formats (e.g. h264) allow
-    // interlaced coding, and then the size needs to be a multiple of two
-    // macroblocks (vertically). See
-    // libavcodec/utils.c:avcodec_align_dimensions2().
-    const size_t height = RoundUp(rows(plane), kFrameSizeAlignment * 2);
-    strides_[plane] = RoundUp(row_bytes(plane), kFrameSizeAlignment);
-    offset[plane] = data_size;
-    data_size += height * strides_[plane];
-  }
 
-  // The extra line of UV being allocated is because h264 chroma MC
-  // overreads by one line in some cases, see libavcodec/utils.c:
-  // avcodec_align_dimensions2() and libavcodec/x86/h264_chromamc.asm:
-  // put_h264_chroma_mc4_ssse3().
-  DCHECK(IsValidPlane(kUPlane, format_));
-  data_size += strides_[kUPlane] + kFrameSizePadding;
+  // Tightly pack if it is single planar.
+  if (NumPlanes(format_) == 1) {
+    data_size = AllocationSize(format_, coded_size_);
+    offset[0] = 0;
+  } else {
+    for (size_t plane = 0; plane < NumPlanes(format_); ++plane) {
+      // The *2 in alignment for height is because some formats (e.g. h264)
+      // allow interlaced coding, and then the size needs to be a multiple of
+      // two macroblocks (vertically). See
+      // libavcodec/utils.c:avcodec_align_dimensions2().
+      const size_t height = RoundUp(rows(plane), kFrameSizeAlignment * 2);
+      strides_[plane] = RoundUp(row_bytes(plane), kFrameSizeAlignment);
+      offset[plane] = data_size;
+      data_size += height * strides_[plane];
+    }
+
+    // The extra line of UV being allocated is because h264 chroma MC
+    // overreads by one line in some cases, see libavcodec/utils.c:
+    // avcodec_align_dimensions2() and libavcodec/x86/h264_chromamc.asm:
+    // put_h264_chroma_mc4_ssse3().
+    DCHECK(IsValidPlane(kUPlane, format_));
+    data_size += strides_[kUPlane] + kFrameSizePadding;
+  }
 
   uint8_t* data = reinterpret_cast<uint8_t*>(
       base::AlignedAlloc(data_size, kFrameAddressAlignment));
diff --git a/media/base/video_frame.h b/media/base/video_frame.h
index a61cce26..f0d708d6 100644
--- a/media/base/video_frame.h
+++ b/media/base/video_frame.h
@@ -100,11 +100,10 @@
                             const gfx::Rect& visible_rect,
                             const gfx::Size& natural_size);
 
-  // Creates a new YUV frame in system memory with given parameters (|format|
-  // must be YUV). Buffers for the frame are allocated but not initialized. The
-  // caller most not make assumptions about the actual underlying size(s), but
-  // check the returned VideoFrame instead.
-  // TODO(mcasas): implement the RGB version of this factory method.
+  // Creates a new frame in system memory with given parameters. Buffers for the
+  // frame are allocated but not initialized. The caller most not make
+  // assumptions about the actual underlying size(s), but check the returned
+  // VideoFrame instead.
   static scoped_refptr<VideoFrame> CreateFrame(VideoPixelFormat format,
                                                const gfx::Size& coded_size,
                                                const gfx::Rect& visible_rect,
@@ -491,7 +490,7 @@
   // alignment for each individual plane.
   static gfx::Size CommonAlignment(VideoPixelFormat format);
 
-  void AllocateYUV(bool zero_initialize_memory);
+  void AllocateMemory(bool zero_initialize_memory);
 
   // Frame format.
   const VideoPixelFormat format_;
diff --git a/media/base/video_frame_pool_unittest.cc b/media/base/video_frame_pool_unittest.cc
index 9b3f721..4ce5702 100644
--- a/media/base/video_frame_pool_unittest.cc
+++ b/media/base/video_frame_pool_unittest.cc
@@ -12,7 +12,7 @@
 
 namespace media {
 
-class VideoFramePoolTest : public ::testing::Test {
+class VideoFramePoolTest : public ::testing::TestWithParam<VideoPixelFormat> {
  public:
   VideoFramePoolTest() : pool_(new VideoFramePool()) {
     // Seed test clock with some dummy non-zero value to avoid confusion with
@@ -50,14 +50,20 @@
   std::unique_ptr<VideoFramePool> pool_;
 };
 
-TEST_F(VideoFramePoolTest, FrameInitializedAndZeroed) {
-  scoped_refptr<VideoFrame> frame = CreateFrame(PIXEL_FORMAT_YV12, 10);
+TEST_P(VideoFramePoolTest, FrameInitializedAndZeroed) {
+  scoped_refptr<VideoFrame> frame = CreateFrame(GetParam(), 10);
 
   // Verify that frame is initialized with zeros.
   for (size_t i = 0; i < VideoFrame::NumPlanes(frame->format()); ++i)
     EXPECT_EQ(0, frame->data(i)[0]);
 }
 
+INSTANTIATE_TEST_CASE_P(,
+                        VideoFramePoolTest,
+                        testing::Values(PIXEL_FORMAT_YV12,
+                                        PIXEL_FORMAT_NV12,
+                                        PIXEL_FORMAT_ARGB));
+
 TEST_F(VideoFramePoolTest, SimpleFrameReuse) {
   scoped_refptr<VideoFrame> frame = CreateFrame(PIXEL_FORMAT_YV12, 10);
   const uint8_t* old_y_data = frame->data(VideoFrame::kYPlane);
diff --git a/media/base/video_frame_unittest.cc b/media/base/video_frame_unittest.cc
index 943b9ec..8b95019 100644
--- a/media/base/video_frame_unittest.cc
+++ b/media/base/video_frame_unittest.cc
@@ -154,6 +154,16 @@
   base::MD5Final(&digest, &context);
   EXPECT_EQ(MD5DigestToBase16(digest), "911991d51438ad2e1a40ed5f6fc7c796");
 
+  // Test single planar frame.
+  frame = VideoFrame::CreateFrame(media::PIXEL_FORMAT_ARGB, size,
+                                  gfx::Rect(size), size, kTimestamp);
+  EXPECT_EQ(media::PIXEL_FORMAT_ARGB, frame->format());
+
+  // Test double planar frame.
+  frame = VideoFrame::CreateFrame(media::PIXEL_FORMAT_NV12, size,
+                                  gfx::Rect(size), size, kTimestamp);
+  EXPECT_EQ(media::PIXEL_FORMAT_NV12, frame->format());
+
   // Test an empty frame.
   frame = VideoFrame::CreateEOSFrame();
   EXPECT_TRUE(
diff --git a/media/blink/video_decode_stats_reporter.cc b/media/blink/video_decode_stats_reporter.cc
index 5cfb269..a310eb2c 100644
--- a/media/blink/video_decode_stats_reporter.cc
+++ b/media/blink/video_decode_stats_reporter.cc
@@ -315,6 +315,9 @@
 void VideoDecodeStatsReporter::UpdateStats() {
   DCHECK(ShouldBeReporting());
 
+  DVLOG(2) << __func__ << " error encountered? "
+           << recorder_ptr_.encountered_error();
+
   PipelineStatistics stats = get_pipeline_stats_cb_.Run();
   DVLOG(2) << __func__ << " Raw stats -- dropped:" << stats.video_frames_dropped
            << "/" << stats.video_frames_decoded
diff --git a/media/blink/webmediacapabilitiesclient_impl.cc b/media/blink/webmediacapabilitiesclient_impl.cc
index 21eec988..b61ad6b 100644
--- a/media/blink/webmediacapabilitiesclient_impl.cc
+++ b/media/blink/webmediacapabilitiesclient_impl.cc
@@ -21,6 +21,7 @@
 namespace media {
 
 void BindToHistoryService(mojom::VideoDecodePerfHistoryPtr* history_ptr) {
+  DVLOG(2) << __func__;
   blink::Platform* platform = blink::Platform::Current();
   service_manager::Connector* connector = platform->GetConnector();
 
diff --git a/media/blink/webmediaplayer_impl_unittest.cc b/media/blink/webmediaplayer_impl_unittest.cc
index ed04959..b730277d 100644
--- a/media/blink/webmediaplayer_impl_unittest.cc
+++ b/media/blink/webmediaplayer_impl_unittest.cc
@@ -31,6 +31,7 @@
 #include "media/mojo/services/video_decode_stats_recorder.h"
 #include "media/mojo/services/watch_time_recorder.h"
 #include "media/renderers/default_renderer_factory.h"
+#include "mojo/public/cpp/bindings/strong_binding.h"
 #include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "third_party/WebKit/public/platform/WebMediaPlayer.h"
@@ -74,9 +75,19 @@
                                   std::string(new_rate_string));
 }
 
+class FakeVideoDecodeStatsRecorder : public mojom::VideoDecodeStatsRecorder {
+ public:
+  void StartNewRecord(VideoCodecProfile profile,
+                      const gfx::Size& natural_size,
+                      int frames_per_sec) override {}
+  void UpdateRecord(uint32_t frames_decoded, uint32_t frames_dropped) override {
+  }
+};
+
 mojom::VideoDecodeStatsRecorderPtr CreateCapabilitiesRecorder() {
   mojom::VideoDecodeStatsRecorderPtr recorder;
-  VideoDecodeStatsRecorder::Create(mojo::MakeRequest(&recorder));
+  mojo::MakeStrongBinding(std::make_unique<FakeVideoDecodeStatsRecorder>(),
+                          mojo::MakeRequest(&recorder));
   return recorder;
 }
 
diff --git a/media/capture/video/chromeos/local_gpu_memory_buffer_manager.cc b/media/capture/video/chromeos/local_gpu_memory_buffer_manager.cc
index f224fe4e..43551253 100644
--- a/media/capture/video/chromeos/local_gpu_memory_buffer_manager.cc
+++ b/media/capture/video/chromeos/local_gpu_memory_buffer_manager.cc
@@ -146,7 +146,7 @@
     return gbm_bo_get_plane_stride(buffer_object_, plane);
   }
 
-  void SetColorSpaceForScanout(const gfx::ColorSpace& color_space) override {}
+  void SetColorSpace(const gfx::ColorSpace& color_space) override {}
 
   gfx::GpuMemoryBufferId GetId() const override { return handle_.id; }
 
diff --git a/media/capture/video/chromeos/mock_gpu_memory_buffer_manager.h b/media/capture/video/chromeos/mock_gpu_memory_buffer_manager.h
index 6b5c7228..c03671f 100644
--- a/media/capture/video/chromeos/mock_gpu_memory_buffer_manager.h
+++ b/media/capture/video/chromeos/mock_gpu_memory_buffer_manager.h
@@ -31,8 +31,7 @@
 
   MOCK_CONST_METHOD1(stride, int(size_t plane));
 
-  MOCK_METHOD1(SetColorSpaceForScanout,
-               void(const gfx::ColorSpace& color_space));
+  MOCK_METHOD1(SetColorSpace, void(const gfx::ColorSpace& color_space));
 
   MOCK_CONST_METHOD0(GetId, gfx::GpuMemoryBufferId());
 
diff --git a/media/cdm/cdm_adapter.cc b/media/cdm/cdm_adapter.cc
index ecfcc2f..fba6cdf 100644
--- a/media/cdm/cdm_adapter.cc
+++ b/media/cdm/cdm_adapter.cc
@@ -447,8 +447,6 @@
       session_closed_cb_(session_closed_cb),
       session_keys_change_cb_(session_keys_change_cb),
       session_expiration_update_cb_(session_expiration_update_cb),
-      audio_samples_per_second_(0),
-      audio_channel_layout_(CHANNEL_LAYOUT_NONE),
       helper_(std::move(helper)),
       task_runner_(base::ThreadTaskRunnerHandle::Get()),
       pool_(new AudioBufferMemoryPool()),
diff --git a/media/cdm/cdm_adapter.h b/media/cdm/cdm_adapter.h
index c2ece06..2e0c563 100644
--- a/media/cdm/cdm_adapter.h
+++ b/media/cdm/cdm_adapter.h
@@ -204,12 +204,8 @@
                                 uint32_t link_mask,
                                 uint32_t protection_mask);
 
-  // Used to keep track of promises while the CDM is processing the request.
-  CdmPromiseAdapter cdm_promise_adapter_;
-
-  std::unique_ptr<CdmWrapper> cdm_;
-  std::string key_system_;
-  CdmConfig cdm_config_;
+  const std::string key_system_;
+  const CdmConfig cdm_config_;
 
   // Callbacks for firing session events.
   SessionMessageCB session_message_cb_;
@@ -217,6 +213,12 @@
   SessionKeysChangeCB session_keys_change_cb_;
   SessionExpirationUpdateCB session_expiration_update_cb_;
 
+  // Helper that provides additional functionality for the CDM.
+  std::unique_ptr<CdmAuxiliaryHelper> helper_;
+
+  scoped_refptr<base::SingleThreadTaskRunner> task_runner_;
+  scoped_refptr<AudioBufferMemoryPool> pool_;
+
   // Callbacks for deferred initialization.
   DecoderInitCB audio_init_cb_;
   DecoderInitCB video_init_cb_;
@@ -225,20 +227,20 @@
   NewKeyCB new_audio_key_cb_;
   NewKeyCB new_video_key_cb_;
 
+  // Keep track of audio parameters.
+  int audio_samples_per_second_ = 0;
+  ChannelLayout audio_channel_layout_ = CHANNEL_LAYOUT_NONE;
+
   // Keep track of video frame natural size from the latest configuration
   // as the CDM doesn't provide it.
   gfx::Size natural_size_;
 
-  // Keep track of audio parameters.
-  int audio_samples_per_second_;
-  ChannelLayout audio_channel_layout_;
+  // Used to keep track of promises while the CDM is processing the request.
+  CdmPromiseAdapter cdm_promise_adapter_;
 
-  // Helper that provides additional functionality for the CDM.
-  std::unique_ptr<CdmAuxiliaryHelper> helper_;
-
-  scoped_refptr<base::SingleThreadTaskRunner> task_runner_;
-
-  scoped_refptr<AudioBufferMemoryPool> pool_;
+  // Declare |cdm_| after other member variables to avoid the CDM accessing
+  // deleted objects (e.g. |helper_|) during destruction.
+  std::unique_ptr<CdmWrapper> cdm_;
 
   // NOTE: Weak pointers must be invalidated before all other member variables.
   base::WeakPtrFactory<CdmAdapter> weak_factory_;
diff --git a/media/cdm/cdm_module.cc b/media/cdm/cdm_module.cc
index 150f2e0..2bf399f7 100644
--- a/media/cdm/cdm_module.cc
+++ b/media/cdm/cdm_module.cc
@@ -4,11 +4,13 @@
 
 #include "media/cdm/cdm_module.h"
 
+#include "base/files/file_util.h"
 #include "base/memory/ptr_util.h"
+#include "base/metrics/histogram_macros.h"
+#include "base/time/time.h"
 #include "build/build_config.h"
 
 #if BUILDFLAG(ENABLE_CDM_HOST_VERIFICATION)
-#include "base/metrics/histogram_macros.h"
 #include "media/cdm/cdm_host_files.h"
 #endif  // BUILDFLAG(ENABLE_CDM_HOST_VERIFICATION)
 
@@ -25,10 +27,6 @@
 static CdmModule* g_cdm_module = nullptr;
 
 #if BUILDFLAG(ENABLE_CDM_HOST_VERIFICATION)
-// Initialize CDM host verification. Returns false if fatal error happened.
-// Otherwise returns true.
-// TODO(xhwang): Add comments on the sandbox model after the CDM process is
-// sandboxed.
 void InitCdmHostVerification(
     base::NativeLibrary cdm_library,
     const base::FilePath& cdm_path,
@@ -45,6 +43,34 @@
 }
 #endif  // BUILDFLAG(ENABLE_CDM_HOST_VERIFICATION)
 
+// These enums are reported to UMA so values should not be renumbered or reused.
+enum class LoadResult {
+  kLoadSuccess,
+  kFileMissing,        // The CDM does not exist.
+  kLoadFailed,         // CDM exists but LoadNativeLibrary() failed.
+  kEntryPointMissing,  // CDM loaded but somce required entry point missing.
+  // NOTE: Add new values only immediately above this line.
+  kLoadResultCount  // Boundary value for UMA_HISTOGRAM_ENUMERATION.
+};
+
+void ReportLoadResult(LoadResult load_result) {
+  DCHECK_LT(load_result, LoadResult::kLoadResultCount);
+  UMA_HISTOGRAM_ENUMERATION("Media.EME.CdmLoadResult", load_result,
+                            LoadResult::kLoadResultCount);
+}
+
+void ReportLoadErrorCode(const base::NativeLibraryLoadError& error) {
+// Only report load error code on Windows because that's the only platform that
+// has a numerical error value.
+#if defined(OS_WIN)
+  UMA_HISTOGRAM_SPARSE_SLOWLY("Media.EME.CdmLoadErrorCode", error.code);
+#endif
+}
+
+void ReportLoadTime(const base::TimeDelta load_time) {
+  UMA_HISTOGRAM_TIMES("Media.EME.CdmLoadTime", load_time);
+}
+
 }  // namespace
 
 // static
@@ -100,15 +126,22 @@
   cdm_path_ = cdm_path;
 
   // Load the CDM.
-  // TODO(xhwang): Report CDM load error to UMA.
   base::NativeLibraryLoadError error;
+  base::TimeTicks start = base::TimeTicks::Now();
   library_.Reset(base::LoadNativeLibrary(cdm_path, &error));
+  base::TimeDelta load_time = base::TimeTicks::Now() - start;
   if (!library_.is_valid()) {
     LOG(ERROR) << "CDM at " << cdm_path.value() << " could not be loaded.";
     LOG(ERROR) << "Error: " << error.ToString();
+    ReportLoadResult(base::PathExists(cdm_path) ? LoadResult::kLoadFailed
+                                                : LoadResult::kFileMissing);
+    ReportLoadErrorCode(error);
     return false;
   }
 
+  // Only report load time for success loads.
+  ReportLoadTime(load_time);
+
   // Get function pointers.
   // TODO(xhwang): Define function names in macros to avoid typo errors.
   initialize_cdm_module_func_ = reinterpret_cast<InitializeCdmModuleFunc>(
@@ -125,6 +158,7 @@
     deinitialize_cdm_module_func_ = nullptr;
     create_cdm_func_ = nullptr;
     library_.Release();
+    ReportLoadResult(LoadResult::kEntryPointMissing);
     return false;
   }
 
@@ -138,6 +172,7 @@
   InitCdmHostVerification(library_.get(), cdm_path_, cdm_host_file_paths);
 #endif  // BUILDFLAG(ENABLE_CDM_HOST_VERIFICATION)
 
+  ReportLoadResult(LoadResult::kLoadSuccess);
   return true;
 }
 
diff --git a/media/cdm/ppapi/cdm_file_io_test.cc b/media/cdm/ppapi/cdm_file_io_test.cc
index e8885c06..48e374b 100644
--- a/media/cdm/ppapi/cdm_file_io_test.cc
+++ b/media/cdm/ppapi/cdm_file_io_test.cc
@@ -638,6 +638,7 @@
     file_io_stack_.pop();
   }
   FILE_IO_DVLOG(3) << test_name_ << (success ? " PASSED" : " FAILED");
+  DLOG_IF(WARNING, !success) << test_name_ << " FAILED";
   base::ResetAndReturn(&completion_cb_).Run(success);
 }
 
diff --git a/media/filters/BUILD.gn b/media/filters/BUILD.gn
index 490722cf..d0f64952 100644
--- a/media/filters/BUILD.gn
+++ b/media/filters/BUILD.gn
@@ -195,18 +195,6 @@
       "h264_bitstream_buffer.h",
     ]
   }
-
-  if (use_low_memory_buffer) {
-    sources += [
-      "source_buffer_platform.h",
-      "source_buffer_platform_lowmem.cc",
-    ]
-  } else {
-    sources += [
-      "source_buffer_platform.cc",
-      "source_buffer_platform.h",
-    ]
-  }
 }
 
 source_set("perftests") {
diff --git a/media/filters/ffmpeg_demuxer.cc b/media/filters/ffmpeg_demuxer.cc
index 04cc05e..6e673cf 100644
--- a/media/filters/ffmpeg_demuxer.cc
+++ b/media/filters/ffmpeg_demuxer.cc
@@ -29,6 +29,7 @@
 #include "build/build_config.h"
 #include "media/base/bind_to_current_loop.h"
 #include "media/base/decrypt_config.h"
+#include "media/base/demuxer_memory_limit.h"
 #include "media/base/limits.h"
 #include "media/base/media_log.h"
 #include "media/base/media_tracks.h"
@@ -1853,9 +1854,6 @@
 bool FFmpegDemuxer::IsMaxMemoryUsageReached() const {
   DCHECK(task_runner_->BelongsToCurrentThread());
 
-  // Max allowed memory usage, all streams combined.
-  const size_t kDemuxerMemoryLimit = 150 * 1024 * 1024;
-
   size_t memory_left = kDemuxerMemoryLimit;
   for (const auto& stream : streams_) {
     if (!stream)
diff --git a/media/filters/source_buffer_platform.cc b/media/filters/source_buffer_platform.cc
deleted file mode 100644
index 89761a1..0000000
--- a/media/filters/source_buffer_platform.cc
+++ /dev/null
@@ -1,14 +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 "media/filters/source_buffer_platform.h"
-
-namespace media {
-
-// 12MB: approximately 5 minutes of 320Kbps content.
-// 150MB: approximately 5 minutes of 4Mbps content.
-const size_t kSourceBufferAudioMemoryLimit = 12 * 1024 * 1024;
-const size_t kSourceBufferVideoMemoryLimit = 150 * 1024 * 1024;
-
-}  // namespace media
diff --git a/media/filters/source_buffer_platform.h b/media/filters/source_buffer_platform.h
deleted file mode 100644
index 09a3f07..0000000
--- a/media/filters/source_buffer_platform.h
+++ /dev/null
@@ -1,20 +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 MEDIA_FILTERS_SOURCE_BUFFER_PLATFORM_H_
-#define MEDIA_FILTERS_SOURCE_BUFFER_PLATFORM_H_
-
-#include <stddef.h>
-
-#include "media/base/media_export.h"
-
-namespace media {
-
-// The maximum amount of data in bytes the stream will keep in memory.
-MEDIA_EXPORT extern const size_t kSourceBufferAudioMemoryLimit;
-MEDIA_EXPORT extern const size_t kSourceBufferVideoMemoryLimit;
-
-}  // namespace media
-
-#endif  // MEDIA_FILTERS_SOURCE_BUFFER_PLATFORM_H_
diff --git a/media/filters/source_buffer_platform_lowmem.cc b/media/filters/source_buffer_platform_lowmem.cc
deleted file mode 100644
index 9fc0c653..0000000
--- a/media/filters/source_buffer_platform_lowmem.cc
+++ /dev/null
@@ -1,16 +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 <stddef.h>
-
-#include "media/filters/source_buffer_platform.h"
-
-namespace media {
-
-// 2MB: approximately 1 minute of 256Kbps content.
-// 30MB: approximately 1 minute of 4Mbps content.
-const size_t kSourceBufferAudioMemoryLimit = 2 * 1024 * 1024;
-const size_t kSourceBufferVideoMemoryLimit = 30 * 1024 * 1024;
-
-}  // namespace media
diff --git a/media/filters/source_buffer_state.cc b/media/filters/source_buffer_state.cc
index 72c18aa..1b4f773d 100644
--- a/media/filters/source_buffer_state.cc
+++ b/media/filters/source_buffer_state.cc
@@ -8,6 +8,7 @@
 
 #include "base/callback_helpers.h"
 #include "base/command_line.h"
+#include "base/rand_util.h"
 #include "base/strings/string_number_conversions.h"
 #include "media/base/media_switches.h"
 #include "media/base/media_track.h"
@@ -120,11 +121,11 @@
     std::unique_ptr<FrameProcessor> frame_processor,
     const CreateDemuxerStreamCB& create_demuxer_stream_cb,
     MediaLog* media_log)
-    : create_demuxer_stream_cb_(create_demuxer_stream_cb),
-      timestamp_offset_during_append_(NULL),
+    : timestamp_offset_during_append_(NULL),
       parsing_media_segment_(false),
       stream_parser_(stream_parser.release()),
       frame_processor_(frame_processor.release()),
+      create_demuxer_stream_cb_(create_demuxer_stream_cb),
       media_log_(media_log),
       state_(UNINITIALIZED),
       auto_update_timestamp_offset_(false) {
@@ -142,8 +143,9 @@
     const StreamParser::EncryptedMediaInitDataCB& encrypted_media_init_data_cb,
     const NewTextTrackCB& new_text_track_cb) {
   DCHECK_EQ(state_, UNINITIALIZED);
-  new_text_track_cb_ = new_text_track_cb;
   init_cb_ = init_cb;
+  encrypted_media_init_data_cb_ = encrypted_media_init_data_cb;
+  new_text_track_cb_ = new_text_track_cb;
 
   std::vector<std::string> expected_codecs_parsed;
   SplitCodecsToVector(expected_codecs, &expected_codecs_parsed, false);
@@ -170,7 +172,9 @@
       base::Bind(&SourceBufferState::OnNewConfigs, base::Unretained(this),
                  expected_codecs),
       base::Bind(&SourceBufferState::OnNewBuffers, base::Unretained(this)),
-      new_text_track_cb_.is_null(), encrypted_media_init_data_cb,
+      new_text_track_cb_.is_null(),
+      base::Bind(&SourceBufferState::OnEncryptedMediaInitData,
+                 base::Unretained(this)),
       base::Bind(&SourceBufferState::OnNewMediaSegment, base::Unretained(this)),
       base::Bind(&SourceBufferState::OnEndOfMediaSegment,
                  base::Unretained(this)),
@@ -224,7 +228,25 @@
         << __func__ << ": stream parsing failed. Data size=" << length
         << " append_window_start=" << append_window_start.InSecondsF()
         << " append_window_end=" << append_window_end.InSecondsF();
+
+    // Crash with a 1/10 chance to investigate https://crbug.com/778363.
+    // CHECK on different conditions so we can more easily distinguish between
+    // different cases.
+    // TODO(crbug.com/778363): Remove after investigation is done.
+    int n = base::RandInt(1, 10);
+    if (state_ == PARSER_INITIALIZED) {
+      if (encrypted_media_init_data_reported_)
+        CHECK(n != 1);
+      else
+        CHECK(n != 2);
+    } else {
+      if (encrypted_media_init_data_reported_)
+        CHECK(n != 3);
+      else
+        CHECK(n != 4);
+    }
   }
+
   timestamp_offset_during_append_ = NULL;
   append_in_progress_ = false;
   return result;
@@ -913,6 +935,14 @@
 
   return true;
 }
+
+void SourceBufferState::OnEncryptedMediaInitData(
+    EmeInitDataType type,
+    const std::vector<uint8_t>& init_data) {
+  encrypted_media_init_data_reported_ = true;
+  encrypted_media_init_data_cb_.Run(type, init_data);
+}
+
 void SourceBufferState::OnSourceInitDone(
     const StreamParser::InitParameters& params) {
   DCHECK_EQ(state_, PENDING_PARSER_INIT);
diff --git a/media/filters/source_buffer_state.h b/media/filters/source_buffer_state.h
index fe689f7a..c487344 100644
--- a/media/filters/source_buffer_state.h
+++ b/media/filters/source_buffer_state.h
@@ -171,6 +171,10 @@
   // processing the buffers.
   bool OnNewBuffers(const StreamParser::BufferQueueMap& buffer_queue_map);
 
+  // Called when StreamParser encounters encrypted media init data.
+  void OnEncryptedMediaInitData(EmeInitDataType type,
+                                const std::vector<uint8_t>& init_data);
+
   void OnSourceInitDone(const StreamParser::InitParameters& params);
 
   // Sets memory limits for all demuxer streams.
@@ -180,9 +184,6 @@
   // or video blocks. Useful to prevent log spam.
   int num_missing_track_logs_ = 0;
 
-  CreateDemuxerStreamCB create_demuxer_stream_cb_;
-  NewTextTrackCB new_text_track_cb_;
-
   // During Append(), if OnNewBuffers() coded frame processing updates the
   // timestamp offset then |*timestamp_offset_during_append_| is also updated
   // so Append()'s caller can know the new offset. This pointer is only non-NULL
@@ -213,8 +214,12 @@
   DemuxerStreamMap text_streams_;
 
   std::unique_ptr<FrameProcessor> frame_processor_;
+  CreateDemuxerStreamCB create_demuxer_stream_cb_;
   MediaLog* media_log_;
+
   StreamParser::InitCB init_cb_;
+  StreamParser::EncryptedMediaInitDataCB encrypted_media_init_data_cb_;
+  NewTextTrackCB new_text_track_cb_;
 
   State state_;
 
@@ -227,6 +232,7 @@
   Demuxer::MediaTracksUpdatedCB init_segment_received_cb_;
   bool append_in_progress_ = false;
   bool first_init_segment_received_ = false;
+  bool encrypted_media_init_data_reported_ = false;
 
   std::vector<AudioCodec> expected_audio_codecs_;
   std::vector<VideoCodec> expected_video_codecs_;
diff --git a/media/filters/source_buffer_stream.cc b/media/filters/source_buffer_stream.cc
index b1e4e70..c9af7b87 100644
--- a/media/filters/source_buffer_stream.cc
+++ b/media/filters/source_buffer_stream.cc
@@ -13,9 +13,9 @@
 #include "base/logging.h"
 #include "base/memory/ptr_util.h"
 #include "base/trace_event/trace_event.h"
+#include "media/base/demuxer_memory_limit.h"
 #include "media/base/media_switches.h"
 #include "media/base/timestamp_constants.h"
-#include "media/filters/source_buffer_platform.h"
 #include "media/filters/source_buffer_range_by_dts.h"
 #include "media/filters/source_buffer_range_by_pts.h"
 
@@ -194,7 +194,7 @@
       range_for_next_append_(ranges_.end()),
       highest_output_buffer_timestamp_(kNoDecodeTimestamp()),
       max_interbuffer_distance_(kNoTimestamp),
-      memory_limit_(kSourceBufferAudioMemoryLimit) {
+      memory_limit_(kDemuxerStreamAudioMemoryLimit) {
   DCHECK(audio_config.IsValidConfig());
   audio_configs_.push_back(audio_config);
 }
@@ -209,7 +209,7 @@
       range_for_next_append_(ranges_.end()),
       highest_output_buffer_timestamp_(kNoDecodeTimestamp()),
       max_interbuffer_distance_(kNoTimestamp),
-      memory_limit_(kSourceBufferVideoMemoryLimit) {
+      memory_limit_(kDemuxerStreamVideoMemoryLimit) {
   DCHECK(video_config.IsValidConfig());
   video_configs_.push_back(video_config);
 }
@@ -225,7 +225,7 @@
       range_for_next_append_(ranges_.end()),
       highest_output_buffer_timestamp_(kNoDecodeTimestamp()),
       max_interbuffer_distance_(kNoTimestamp),
-      memory_limit_(kSourceBufferAudioMemoryLimit) {}
+      memory_limit_(kDemuxerStreamAudioMemoryLimit) {}
 
 template <typename RangeClass>
 SourceBufferStream<RangeClass>::~SourceBufferStream() {}
diff --git a/media/formats/BUILD.gn b/media/formats/BUILD.gn
index 907c15c1c..05622409 100644
--- a/media/formats/BUILD.gn
+++ b/media/formats/BUILD.gn
@@ -75,8 +75,11 @@
       "mp4/box_reader.h",
       "mp4/es_descriptor.cc",
       "mp4/es_descriptor.h",
+      "mp4/fourccs.h",
       "mp4/mp4_stream_parser.cc",
       "mp4/mp4_stream_parser.h",
+      "mp4/parse_result.h",
+      "mp4/rcheck.h",
       "mp4/sample_to_group_iterator.cc",
       "mp4/sample_to_group_iterator.h",
       "mp4/track_run_iterator.cc",
diff --git a/testing/libfuzzer/fuzzers/es_parser_adts_fuzzer.cc b/media/formats/mp2t/es_parser_adts_fuzzer.cc
similarity index 100%
rename from testing/libfuzzer/fuzzers/es_parser_adts_fuzzer.cc
rename to media/formats/mp2t/es_parser_adts_fuzzer.cc
diff --git a/testing/libfuzzer/fuzzers/es_parser_h264_fuzzer.cc b/media/formats/mp2t/es_parser_h264_fuzzer.cc
similarity index 100%
rename from testing/libfuzzer/fuzzers/es_parser_h264_fuzzer.cc
rename to media/formats/mp2t/es_parser_h264_fuzzer.cc
diff --git a/media/formats/mp2t/es_parser_mpeg1audio_fuzzer.cc b/media/formats/mp2t/es_parser_mpeg1audio_fuzzer.cc
new file mode 100644
index 0000000..638a2e5
--- /dev/null
+++ b/media/formats/mp2t/es_parser_mpeg1audio_fuzzer.cc
@@ -0,0 +1,38 @@
+// 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 <stddef.h>
+#include <stdint.h>
+
+#include <memory>
+
+#include "base/bind.h"
+#include "media/base/media_log.h"
+#include "media/formats/mp2t/es_parser_mpeg1audio.h"
+
+class NullMediaLog : public media::MediaLog {
+ public:
+  NullMediaLog() {}
+  ~NullMediaLog() override {}
+
+  void AddEvent(std::unique_ptr<media::MediaLogEvent> event) override {}
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(NullMediaLog);
+};
+
+static void NewAudioConfig(const media::AudioDecoderConfig& config) {}
+static void EmitBuffer(scoped_refptr<media::StreamParserBuffer> buffer) {}
+
+// Entry point for LibFuzzer.
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
+  NullMediaLog media_log;
+  media::mp2t::EsParserMpeg1Audio es_parser(
+      base::Bind(&NewAudioConfig), base::Bind(&EmitBuffer), &media_log);
+  if (es_parser.Parse(data, size, media::kNoTimestamp,
+                      media::kNoDecodeTimestamp())) {
+    es_parser.Flush();
+  }
+  return 0;
+}
diff --git a/media/formats/mp4/box_reader.cc b/media/formats/mp4/box_reader.cc
index 8e22539..0ba56fb 100644
--- a/media/formats/mp4/box_reader.cc
+++ b/media/formats/mp4/box_reader.cc
@@ -8,7 +8,6 @@
 #include <string.h>
 
 #include <algorithm>
-#include <memory>
 #include <set>
 
 #include "media/formats/mp4/box_definitions.h"
@@ -115,44 +114,31 @@
 }
 
 // static
-BoxReader* BoxReader::ReadTopLevelBox(const uint8_t* buf,
-                                      const size_t buf_size,
-                                      MediaLog* media_log,
-                                      bool* err) {
+ParseResult BoxReader::ReadTopLevelBox(const uint8_t* buf,
+                                       const size_t buf_size,
+                                       MediaLog* media_log,
+                                       std::unique_ptr<BoxReader>* out_reader) {
+  DCHECK(out_reader);
   std::unique_ptr<BoxReader> reader(
       new BoxReader(buf, buf_size, media_log, false));
-  if (!reader->ReadHeader(err))
-    return NULL;
-
-  // BoxReader::ReadHeader is expected to return false if box_size > buf_size.
-  // This may happen if a partial mp4 box is appended, or if the box header is
-  // corrupt.
-  CHECK(reader->box_size() <= static_cast<uint64_t>(buf_size));
-
-  if (!IsValidTopLevelBox(reader->type(), media_log)) {
-    *err = true;
-    return NULL;
-  }
-
-  return reader.release();
+  RCHECK_OK_PARSE_RESULT(reader->ReadHeader());
+  if (!IsValidTopLevelBox(reader->type(), media_log))
+    return ParseResult::kError;
+  *out_reader = std::move(reader);
+  return ParseResult::kOk;
 }
 
 // static
-bool BoxReader::StartTopLevelBox(const uint8_t* buf,
-                                 const size_t buf_size,
-                                 MediaLog* media_log,
-                                 FourCC* type,
-                                 size_t* box_size,
-                                 bool* err) {
-  BoxReader reader(buf, buf_size, media_log, false);
-  if (!reader.ReadHeader(err)) return false;
-  if (!IsValidTopLevelBox(reader.type(), media_log)) {
-    *err = true;
-    return false;
-  }
-  *type = reader.type();
-  *box_size = reader.box_size();
-  return true;
+ParseResult BoxReader::StartTopLevelBox(const uint8_t* buf,
+                                        const size_t buf_size,
+                                        MediaLog* media_log,
+                                        FourCC* out_type,
+                                        size_t* out_box_size) {
+  std::unique_ptr<BoxReader> reader;
+  RCHECK_OK_PARSE_RESULT(ReadTopLevelBox(buf, buf_size, media_log, &reader));
+  *out_type = reader->type();
+  *out_box_size = reader->box_size();
+  return ParseResult::kOk;
 }
 
 // static
@@ -206,16 +192,16 @@
   DCHECK(!scanned_);
   scanned_ = true;
 
-  bool err = false;
   while (pos_ < box_size_) {
     BoxReader child(&buf_[pos_], box_size_ - pos_, media_log_, is_EOS_);
-    if (!child.ReadHeader(&err)) break;
-
+    if (child.ReadHeader() != ParseResult::kOk)
+      return false;
     children_.insert(std::pair<FourCC, BoxReader>(child.type(), child));
     pos_ += child.box_size();
   }
 
-  return !err && pos_ == box_size_;
+  DCHECK(pos_ == box_size_);
+  return true;
 }
 
 bool BoxReader::HasChild(Box* child) {
@@ -249,57 +235,50 @@
   return true;
 }
 
-bool BoxReader::ReadHeader(bool* err) {
+ParseResult BoxReader::ReadHeader() {
   uint64_t box_size = 0;
-  *err = false;
 
-  if (!HasBytes(8)) {
-    // If EOS is known, then this is an error. If not, additional data may be
-    // appended later, so this is a soft error.
-    *err = is_EOS_;
-    return false;
-  }
-  CHECK(Read4Into8(&box_size) && ReadFourCC(&type_));
+  if (!HasBytes(8))
+    return is_EOS_ ? ParseResult::kError : ParseResult::kNeedMoreData;
+  CHECK(Read4Into8(&box_size));
+  CHECK(ReadFourCC(&type_));
 
   if (box_size == 0) {
     if (is_EOS_) {
       // All the data bytes are expected to be provided.
-      box_size = base::checked_cast<uint64_t>(buf_size_);
+      // TODO(sandersd): The whole |is_EOS_| feature seems to exist just for
+      // this special case (and is used only for PSSH parsing). Can we get rid
+      // of it? The caller can treat kNeedMoreData as an error, and the only
+      // difference would be lack of support for |box_size == 0|.
+      box_size = base::strict_cast<uint64_t>(buf_size_);
     } else {
       MEDIA_LOG(DEBUG, media_log_)
           << "ISO BMFF boxes that run to EOS are not supported";
-      *err = true;
-      return false;
+      return ParseResult::kError;
     }
   } else if (box_size == 1) {
-    if (!HasBytes(8)) {
-      // If EOS is known, then this is an error. If not, it's a soft error.
-      *err = is_EOS_;
-      return false;
-    }
+    if (!HasBytes(8))
+      return is_EOS_ ? ParseResult::kError : ParseResult::kNeedMoreData;
     CHECK(Read8(&box_size));
   }
 
   // Implementation-specific: support for boxes larger than 2^31 has been
   // removed.
-  if (box_size < static_cast<uint64_t>(pos_) ||
+  if (box_size < base::strict_cast<uint64_t>(pos_) ||
       box_size > static_cast<uint64_t>(std::numeric_limits<int32_t>::max())) {
-    *err = true;
-    return false;
+    return ParseResult::kError;
   }
 
   // Make sure the buffer contains at least the expected number of bytes.
   // Since the data may be appended in pieces, this is only an error if EOS.
-  if (box_size > base::checked_cast<size_t>(buf_size_)) {
-    *err = is_EOS_;
-    return false;
-  }
+  if (box_size > base::strict_cast<uint64_t>(buf_size_))
+    return is_EOS_ ? ParseResult::kError : ParseResult::kNeedMoreData;
 
   // Note that the pos_ head has advanced to the byte immediately after the
   // header, which is where we want it.
   box_size_ = base::checked_cast<size_t>(box_size);
   box_size_known_ = true;
-  return true;
+  return ParseResult::kOk;
 }
 
 }  // namespace mp4
diff --git a/media/formats/mp4/box_reader.h b/media/formats/mp4/box_reader.h
index 320b64f..16b5792a 100644
--- a/media/formats/mp4/box_reader.h
+++ b/media/formats/mp4/box_reader.h
@@ -9,6 +9,7 @@
 
 #include <limits>
 #include <map>
+#include <memory>
 #include <vector>
 
 #include "base/compiler_specific.h"
@@ -17,6 +18,7 @@
 #include "media/base/media_export.h"
 #include "media/base/media_log.h"
 #include "media/formats/mp4/fourccs.h"
+#include "media/formats/mp4/parse_result.h"
 #include "media/formats/mp4/rcheck.h"
 
 namespace media {
@@ -93,29 +95,26 @@
   BoxReader(const BoxReader& other);
   ~BoxReader();
 
-  // Create a BoxReader from a buffer. Note that this function may return NULL
-  // if an intact, complete box was not available in the buffer. If |*err| is
-  // set, there was a stream-level error when creating the box; otherwise, NULL
-  // values are only expected when insufficient data is available.
+  // Create a BoxReader from a buffer. If the result is kOk, then |out_reader|
+  // will be set, otherwise |out_reader| will be unchanged.
   //
   // |buf| is retained but not owned, and must outlive the BoxReader instance.
-  static BoxReader* ReadTopLevelBox(const uint8_t* buf,
-                                    const size_t buf_size,
-                                    MediaLog* media_log,
-                                    bool* err);
+  static ParseResult ReadTopLevelBox(const uint8_t* buf,
+                                     const size_t buf_size,
+                                     MediaLog* media_log,
+                                     std::unique_ptr<BoxReader>* out_reader)
+      WARN_UNUSED_RESULT;
 
-  // Read the box header from the current buffer. This function returns true if
-  // there is enough data to read the header and the header is sane; that is, it
-  // does not check to ensure the entire box is in the buffer before returning
-  // true. The semantics of |*err| are the same as above.
+  // Read the box header from the current buffer, and return its type and size.
+  // This function returns kNeedMoreData if the box is incomplete, even if the
+  // box header is complete.
   //
   // |buf| is not retained.
-  static bool StartTopLevelBox(const uint8_t* buf,
-                               const size_t buf_size,
-                               MediaLog* media_log,
-                               FourCC* type,
-                               size_t* box_size,
-                               bool* err) WARN_UNUSED_RESULT;
+  static ParseResult StartTopLevelBox(const uint8_t* buf,
+                                      const size_t buf_size,
+                                      MediaLog* media_log,
+                                      FourCC* out_type,
+                                      size_t* out_box_size) WARN_UNUSED_RESULT;
 
   // Create a BoxReader from a buffer. |buf| must be the complete buffer, as
   // errors are returned when sufficient data is not available. |buf| can start
@@ -193,14 +192,8 @@
             MediaLog* media_log,
             bool is_EOS);
 
-  // Must be called immediately after init. If the return is false, this
-  // indicates that the box header and its contents were not available in the
-  // stream or were nonsensical, and that the box must not be used further. In
-  // this case, if |*err| is false, the problem was simply a lack of data, and
-  // should only be an error condition if some higher-level component knows that
-  // no more data is coming (i.e. EOS or end of containing box). If |*err| is
-  // true, the error is unrecoverable and the stream should be aborted.
-  bool ReadHeader(bool* err);
+  // Must be called immediately after init.
+  ParseResult ReadHeader() WARN_UNUSED_RESULT;
 
   // Read all children, optionally checking FourCC. Returns true if all
   // children are successfully parsed and, if |check_box_type|, have the
@@ -275,11 +268,10 @@
   // Must know our box size before attempting to parse child boxes.
   RCHECK(box_size_known_);
 
-  bool err = false;
   while (pos_ < box_size_) {
     BoxReader child_reader(&buf_[pos_], box_size_ - pos_, media_log_, is_EOS_);
 
-    if (!child_reader.ReadHeader(&err))
+    if (child_reader.ReadHeader() != ParseResult::kOk)
       return false;
 
     T child;
@@ -289,7 +281,7 @@
     pos_ += child_reader.box_size();
   }
 
-  return !err;
+  return true;
 }
 
 }  // namespace mp4
diff --git a/media/formats/mp4/box_reader_unittest.cc b/media/formats/mp4/box_reader_unittest.cc
index 08d0bb79..4ee2bd1f 100644
--- a/media/formats/mp4/box_reader_unittest.cc
+++ b/media/formats/mp4/box_reader_unittest.cc
@@ -12,6 +12,7 @@
 #include "base/logging.h"
 #include "media/base/mock_media_log.h"
 #include "media/formats/mp4/box_definitions.h"
+#include "media/formats/mp4/parse_result.h"
 #include "media/formats/mp4/rcheck.h"
 #include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
@@ -93,11 +94,11 @@
   void TestTopLevelBox(const uint8_t* data, size_t data_size, uint32_t fourCC) {
     std::vector<uint8_t> buf(data, data + data_size);
 
-    bool err;
-    std::unique_ptr<BoxReader> reader(
-        BoxReader::ReadTopLevelBox(&buf[0], buf.size(), &media_log_, &err));
+    std::unique_ptr<BoxReader> reader;
+    ParseResult result =
+        BoxReader::ReadTopLevelBox(&buf[0], buf.size(), &media_log_, &reader);
 
-    EXPECT_FALSE(err);
+    EXPECT_EQ(result, ParseResult::kOk);
     EXPECT_TRUE(reader);
     EXPECT_EQ(fourCC, reader->type());
     EXPECT_EQ(reader->box_size(), data_size);
@@ -125,10 +126,10 @@
         base::IsValueInRangeForNumericType<uint8_t>(buffer_wrapper.size()));
     buffer_wrapper[3] = buffer_wrapper.size();
 
-    bool err;
-    std::unique_ptr<BoxReader> reader(BoxReader::ReadTopLevelBox(
-        &buffer_wrapper[0], buffer_wrapper.size(), &media_log_, &err));
-    EXPECT_FALSE(err);
+    std::unique_ptr<BoxReader> reader;
+    ParseResult result = BoxReader::ReadTopLevelBox(
+        &buffer_wrapper[0], buffer_wrapper.size(), &media_log_, &reader);
+    EXPECT_EQ(result, ParseResult::kOk);
     EXPECT_TRUE(reader);
     EXPECT_EQ(FOURCC_EMSG, reader->type());
 
@@ -153,11 +154,11 @@
 
 TEST_F(BoxReaderTest, ExpectedOperationTest) {
   std::vector<uint8_t> buf = GetBuf();
-  bool err;
-  std::unique_ptr<BoxReader> reader(
-      BoxReader::ReadTopLevelBox(&buf[0], buf.size(), &media_log_, &err));
-  EXPECT_FALSE(err);
-  EXPECT_TRUE(reader.get());
+  std::unique_ptr<BoxReader> reader;
+  ParseResult result =
+      BoxReader::ReadTopLevelBox(&buf[0], buf.size(), &media_log_, &reader);
+  EXPECT_EQ(result, ParseResult::kOk);
+  EXPECT_TRUE(reader);
 
   SkipBox box;
   EXPECT_TRUE(box.Parse(reader.get()));
@@ -179,24 +180,25 @@
 
 TEST_F(BoxReaderTest, OuterTooShortTest) {
   std::vector<uint8_t> buf = GetBuf();
-  bool err;
 
   // Create a soft failure by truncating the outer box.
-  std::unique_ptr<BoxReader> r(
-      BoxReader::ReadTopLevelBox(&buf[0], buf.size() - 2, &media_log_, &err));
+  std::unique_ptr<BoxReader> r;
+  ParseResult result =
+      BoxReader::ReadTopLevelBox(&buf[0], buf.size() - 2, &media_log_, &r);
 
-  EXPECT_FALSE(err);
-  EXPECT_FALSE(r.get());
+  EXPECT_EQ(result, ParseResult::kNeedMoreData);
+  EXPECT_FALSE(r);
 }
 
 TEST_F(BoxReaderTest, InnerTooLongTest) {
   std::vector<uint8_t> buf = GetBuf();
-  bool err;
 
   // Make an inner box too big for its outer box.
   buf[25] = 1;
-  std::unique_ptr<BoxReader> reader(
-      BoxReader::ReadTopLevelBox(&buf[0], buf.size(), &media_log_, &err));
+  std::unique_ptr<BoxReader> reader;
+  ParseResult result =
+      BoxReader::ReadTopLevelBox(&buf[0], buf.size(), &media_log_, &reader);
+  EXPECT_EQ(result, ParseResult::kOk);
 
   SkipBox box;
   EXPECT_FALSE(box.Parse(reader.get()));
@@ -204,7 +206,6 @@
 
 TEST_F(BoxReaderTest, WrongFourCCTest) {
   std::vector<uint8_t> buf = GetBuf();
-  bool err;
 
   // Set an unrecognized top-level FourCC.
   buf[4] = 0x44;
@@ -214,18 +215,20 @@
 
   EXPECT_MEDIA_LOG(HasSubstr("Unrecognized top-level box type DALE"));
 
-  std::unique_ptr<BoxReader> reader(
-      BoxReader::ReadTopLevelBox(&buf[0], buf.size(), &media_log_, &err));
-  EXPECT_FALSE(reader.get());
-  EXPECT_TRUE(err);
+  std::unique_ptr<BoxReader> reader;
+  ParseResult result =
+      BoxReader::ReadTopLevelBox(&buf[0], buf.size(), &media_log_, &reader);
+  EXPECT_FALSE(reader);
+  EXPECT_EQ(result, ParseResult::kError);
 }
 
 TEST_F(BoxReaderTest, ScanChildrenTest) {
   std::vector<uint8_t> buf = GetBuf();
-  bool err;
-  std::unique_ptr<BoxReader> reader(
-      BoxReader::ReadTopLevelBox(&buf[0], buf.size(), &media_log_, &err));
+  std::unique_ptr<BoxReader> reader;
+  ParseResult result =
+      BoxReader::ReadTopLevelBox(&buf[0], buf.size(), &media_log_, &reader);
 
+  EXPECT_EQ(result, ParseResult::kOk);
   EXPECT_TRUE(reader->SkipBytes(16) && reader->ScanChildren());
 
   FreeBox free;
@@ -246,9 +249,10 @@
   std::vector<uint8_t> buf = GetBuf();
   // Modify buffer to exclude its last 'free' box
   buf[3] = 0x38;
-  bool err;
-  std::unique_ptr<BoxReader> reader(
-      BoxReader::ReadTopLevelBox(&buf[0], buf.size(), &media_log_, &err));
+  std::unique_ptr<BoxReader> reader;
+  ParseResult result =
+      BoxReader::ReadTopLevelBox(&buf[0], buf.size(), &media_log_, &reader);
+  EXPECT_EQ(result, ParseResult::kOk);
 
   std::vector<PsshBox> kids;
   EXPECT_TRUE(reader->SkipBytes(16) && reader->ReadAllChildren(&kids));
@@ -304,11 +308,11 @@
       0x00, 0x01, 0x00, 0xff, 0xff, 0x00, 0x3b, 0x03,  // random data for rest
       0x00, 0x01, 0x00, 0x03, 0x00, 0x03, 0x00, 0x04, 0x05, 0x06, 0x07, 0x08};
 
-  bool err;
-  std::unique_ptr<BoxReader> reader(
-      BoxReader::ReadTopLevelBox(kData, sizeof(kData), &media_log_, &err));
+  std::unique_ptr<BoxReader> reader;
+  ParseResult result =
+      BoxReader::ReadTopLevelBox(kData, sizeof(kData), &media_log_, &reader);
 
-  EXPECT_FALSE(err);
+  EXPECT_EQ(result, ParseResult::kOk);
   EXPECT_TRUE(reader);
   EXPECT_EQ(FOURCC_EMSG, reader->type());
   EXPECT_FALSE(reader->ScanChildren());
@@ -329,11 +333,11 @@
       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
 
-  bool err;
-  std::unique_ptr<BoxReader> reader(
-      BoxReader::ReadTopLevelBox(kData, sizeof(kData), &media_log_, &err));
+  std::unique_ptr<BoxReader> reader;
+  ParseResult result =
+      BoxReader::ReadTopLevelBox(kData, sizeof(kData), &media_log_, &reader);
 
-  EXPECT_FALSE(err);
+  EXPECT_EQ(result, ParseResult::kOk);
   EXPECT_TRUE(reader);
   EXPECT_EQ(FOURCC_EMSG, reader->type());
   EXPECT_TRUE(reader->ScanChildren());
@@ -350,11 +354,11 @@
       0x00, 0x00, 0x00, 0x10, 'p', 's', 's', 'h',  // nested box
   };
 
-  bool err;
-  std::unique_ptr<BoxReader> reader(
-      BoxReader::ReadTopLevelBox(kData, sizeof(kData), &media_log_, &err));
+  std::unique_ptr<BoxReader> reader;
+  ParseResult result =
+      BoxReader::ReadTopLevelBox(kData, sizeof(kData), &media_log_, &reader);
 
-  EXPECT_FALSE(err);
+  EXPECT_EQ(result, ParseResult::kOk);
   EXPECT_TRUE(reader);
   EXPECT_EQ(FOURCC_SKIP, reader->type());
 
diff --git a/media/formats/mp4/mp4_box_reader_fuzzer.cc b/media/formats/mp4/mp4_box_reader_fuzzer.cc
new file mode 100644
index 0000000..7cafff5d
--- /dev/null
+++ b/media/formats/mp4/mp4_box_reader_fuzzer.cc
@@ -0,0 +1,36 @@
+// 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 <stddef.h>
+#include <stdint.h>
+
+#include <memory>
+
+#include "base/logging.h"
+#include "base/macros.h"
+#include "media/base/media_log.h"
+#include "media/formats/mp4/box_reader.h"
+
+class NullMediaLog : public media::MediaLog {
+ public:
+  NullMediaLog() {}
+  ~NullMediaLog() override {}
+
+  void AddEvent(std::unique_ptr<media::MediaLogEvent> event) override {}
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(NullMediaLog);
+};
+
+// Entry point for LibFuzzer.
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
+  NullMediaLog media_log;
+  std::unique_ptr<media::mp4::BoxReader> reader;
+  if (media::mp4::BoxReader::ReadTopLevelBox(data, size, &media_log, &reader) ==
+      media::mp4::ParseResult::kOk) {
+    CHECK(reader);
+    ignore_result(reader->ScanChildren());
+  }
+  return 0;
+}
diff --git a/media/formats/mp4/mp4_stream_parser.cc b/media/formats/mp4/mp4_stream_parser.cc
index 14936d4..e6d435b 100644
--- a/media/formats/mp4/mp4_stream_parser.cc
+++ b/media/formats/mp4/mp4_stream_parser.cc
@@ -145,6 +145,8 @@
 
   BufferQueueMap buffers;
 
+  // TODO(sandersd): Remove these bools. ParseResult replaced their purpose, but
+  // this method needs to be refactored to complete that work.
   bool result = false;
   bool err = false;
 
@@ -155,9 +157,12 @@
         NOTREACHED();
         return false;
 
-      case kParsingBoxes:
-        result = ParseBox(&err);
+      case kParsingBoxes: {
+        ParseResult pr = ParseBox();
+        result = pr == ParseResult::kOk;
+        err = pr == ParseResult::kError;
         break;
+      }
 
       case kWaitingForSampleData:
         result = HaveEnoughDataToEnqueueSamples();
@@ -165,13 +170,16 @@
           ChangeState(kEmittingSamples);
         break;
 
-      case kEmittingSamples:
-        result = EnqueueSample(&buffers, &err);
+      case kEmittingSamples: {
+        ParseResult pr = EnqueueSample(&buffers);
+        result = pr == ParseResult::kOk;
+        err = pr == ParseResult::kError;
         if (result) {
           int64_t max_clear = runs_->GetMaxClearOffset() + moof_head_;
           err = !ReadAndDiscardMDATsUntil(max_clear);
         }
         break;
+      }
     }
   } while (result && !err);
 
@@ -189,21 +197,27 @@
   return true;
 }
 
-bool MP4StreamParser::ParseBox(bool* err) {
+ParseResult MP4StreamParser::ParseBox() {
   const uint8_t* buf;
   int size;
   queue_.Peek(&buf, &size);
-  if (!size) return false;
+  if (!size)
+    return ParseResult::kNeedMoreData;
 
-  std::unique_ptr<BoxReader> reader(
-      BoxReader::ReadTopLevelBox(buf, size, media_log_, err));
-  if (reader.get() == NULL) return false;
+  std::unique_ptr<BoxReader> reader;
+  ParseResult result =
+      BoxReader::ReadTopLevelBox(buf, size, media_log_, &reader);
+  if (result != ParseResult::kOk)
+    return result;
 
+  DCHECK(reader);
   if (reader->type() == FOURCC_MOOV) {
-    *err = !ParseMoov(reader.get());
+    if (!ParseMoov(reader.get()))
+      return ParseResult::kError;
   } else if (reader->type() == FOURCC_MOOF) {
     moof_head_ = queue_.head();
-    *err = !ParseMoof(reader.get());
+    if (!ParseMoof(reader.get()))
+      return ParseResult::kError;
 
     // Set up first mdat offset for ReadMDATsUntil().
     mdat_tail_ = queue_.head() + reader->box_size();
@@ -212,7 +226,7 @@
     // be located anywhere in the file, including inside the 'moof' itself.
     // (Since 'default-base-is-moof' is mandated, no data references can come
     // before the head of the 'moof', so keeping this box around is sufficient.)
-    return !(*err);
+    return ParseResult::kOk;
   } else {
     // TODO(wolenetz,chcunningham): Enforce more strict adherence to MSE byte
     // stream spec for ftyp and styp. See http://crbug.com/504514.
@@ -221,7 +235,7 @@
   }
 
   queue_.Pop(reader->box_size());
-  return !(*err);
+  return ParseResult::kOk;
 }
 
 bool MP4StreamParser::ParseMoov(BoxReader* reader) {
@@ -597,39 +611,40 @@
   return true;
 }
 
-bool MP4StreamParser::EnqueueSample(BufferQueueMap* buffers, bool* err) {
+ParseResult MP4StreamParser::EnqueueSample(BufferQueueMap* buffers) {
   DCHECK_EQ(state_, kEmittingSamples);
 
   if (!runs_->IsRunValid()) {
     // Flush any buffers we've gotten in this chunk so that buffers don't
     // cross |new_segment_cb_| calls
-    *err = !SendAndFlushSamples(buffers);
-    if (*err)
-      return false;
+    if (!SendAndFlushSamples(buffers))
+      return ParseResult::kError;
 
     // Remain in kEmittingSamples state, discarding data, until the end of
     // the current 'mdat' box has been appended to the queue.
+    // TODO(sandersd): As I understand it, this Trim() will always succeed,
+    // since |mdat_tail_| is never outside of the queue. It's also plausible
+    // that this Trim() is always a no-op, but perhaps if all runs are empty
+    // this still does something?
     if (!queue_.Trim(mdat_tail_))
-      return false;
+      return ParseResult::kNeedMoreData;
 
     ChangeState(kParsingBoxes);
     end_of_segment_cb_.Run();
-    return true;
+    return ParseResult::kOk;
   }
 
   if (!runs_->IsSampleValid()) {
-    *err = !runs_->AdvanceRun();
-    if (*err)
-      return false;
-    return true;
+    if (!runs_->AdvanceRun())
+      return ParseResult::kError;
+    return ParseResult::kOk;
   }
 
-  DCHECK(!(*err));
-
   const uint8_t* buf;
   int buf_size;
   queue_.Peek(&buf, &buf_size);
-  if (!buf_size) return false;
+  if (!buf_size)
+    return ParseResult::kNeedMoreData;
 
   bool audio =
       audio_track_ids_.find(runs_->track_id()) != audio_track_ids_.end();
@@ -638,10 +653,9 @@
 
   // Skip this entire track if it's not one we're interested in
   if (!audio && !video) {
-    *err = !runs_->AdvanceRun();
-    if (*err)
-      return false;
-    return true;
+    if (!runs_->AdvanceRun())
+      return ParseResult::kError;
+    return ParseResult::kOk;
   }
 
   // Attempt to cache the auxiliary information first. Aux info is usually
@@ -653,9 +667,11 @@
   // portion of the total system memory.
   if (runs_->AuxInfoNeedsToBeCached()) {
     queue_.PeekAt(runs_->aux_info_offset() + moof_head_, &buf, &buf_size);
-    if (buf_size < runs_->aux_info_size()) return false;
-    *err = !runs_->CacheAuxInfo(buf, buf_size);
-    return !*err;
+    if (buf_size < runs_->aux_info_size())
+      return ParseResult::kNeedMoreData;
+    if (!runs_->CacheAuxInfo(buf, buf_size))
+      return ParseResult::kError;
+    return ParseResult::kOk;
   }
 
   queue_.PeekAt(runs_->sample_offset() + moof_head_, &buf, &buf_size);
@@ -663,14 +679,13 @@
   if (runs_->sample_size() >
       static_cast<uint32_t>(std::numeric_limits<int>::max())) {
     MEDIA_LOG(ERROR, media_log_) << "Sample size is too large";
-    *err = true;
-    return false;
+    return ParseResult::kError;
   }
 
   int sample_size = base::checked_cast<int>(runs_->sample_size());
 
   if (buf_size < sample_size)
-    return false;
+    return ParseResult::kNeedMoreData;
 
   if (sample_size == 0) {
     // Generally not expected, but spec allows it. Code below this block assumes
@@ -678,20 +693,17 @@
     LIMITED_MEDIA_LOG(DEBUG, media_log_, num_empty_samples_skipped_,
                       kMaxEmptySampleLogs)
         << "Skipping 'trun' sample with size of 0.";
-    *err = !runs_->AdvanceSample();
-    if (*err)
-      return false;
-    return true;
+    if (!runs_->AdvanceSample())
+      return ParseResult::kError;
+    return ParseResult::kOk;
   }
 
   std::unique_ptr<DecryptConfig> decrypt_config;
   std::vector<SubsampleEntry> subsamples;
   if (runs_->is_encrypted()) {
     decrypt_config = runs_->GetDecryptConfig();
-    if (!decrypt_config) {
-      *err = true;
-      return false;
-    }
+    if (!decrypt_config)
+      return ParseResult::kError;
     subsamples = decrypt_config->subsamples();
   }
 
@@ -705,8 +717,7 @@
               &frame_buf, runs_->is_keyframe(), &subsamples)) {
         MEDIA_LOG(ERROR, media_log_)
             << "Failed to prepare video sample for decode";
-        *err = true;
-        return false;
+        return ParseResult::kError;
       }
       if (!runs_->video_description().frame_bitstream_converter->IsValid(
               &frame_buf, &subsamples)) {
@@ -722,8 +733,7 @@
         !PrepareAACBuffer(runs_->audio_description().esds.aac,
                           &frame_buf, &subsamples)) {
       MEDIA_LOG(ERROR, media_log_) << "Failed to prepare AAC sample for decode";
-      *err = true;
-      return false;
+      return ParseResult::kError;
     }
   }
 
@@ -756,24 +766,21 @@
   } else {
     MEDIA_LOG(ERROR, media_log_) << "Frame duration exceeds representable "
                                  << "limit";
-    *err = true;
-    return false;
+    return ParseResult::kError;
   }
 
   if (runs_->cts() != kNoTimestamp) {
     stream_buf->set_timestamp(runs_->cts());
   } else {
     MEDIA_LOG(ERROR, media_log_) << "Frame PTS exceeds representable limit";
-    *err = true;
-    return false;
+    return ParseResult::kError;
   }
 
   if (runs_->dts() != kNoDecodeTimestamp()) {
     stream_buf->SetDecodeTimestamp(runs_->dts());
   } else {
     MEDIA_LOG(ERROR, media_log_) << "Frame DTS exceeds representable limit";
-    *err = true;
-    return false;
+    return ParseResult::kError;
   }
 
   DVLOG(3) << "Emit " << (audio ? "audio" : "video") << " frame: "
@@ -785,10 +792,9 @@
            << ", size=" << sample_size;
 
   (*buffers)[runs_->track_id()].push_back(stream_buf);
-  *err = !runs_->AdvanceSample();
-  if (*err)
-    return false;
-  return true;
+  if (!runs_->AdvanceSample())
+    return ParseResult::kError;
+  return ParseResult::kOk;
 }
 
 bool MP4StreamParser::SendAndFlushSamples(BufferQueueMap* buffers) {
@@ -800,7 +806,7 @@
 }
 
 bool MP4StreamParser::ReadAndDiscardMDATsUntil(int64_t max_clear_offset) {
-  bool err = false;
+  ParseResult result = ParseResult::kOk;
   int64_t upper_bound = std::min(max_clear_offset, queue_.tail());
   while (mdat_tail_ < upper_bound) {
     const uint8_t* buf = NULL;
@@ -809,8 +815,8 @@
 
     FourCC type;
     size_t box_sz;
-    if (!BoxReader::StartTopLevelBox(buf, size, media_log_, &type, &box_sz,
-                                     &err))
+    result = BoxReader::StartTopLevelBox(buf, size, media_log_, &type, &box_sz);
+    if (result != ParseResult::kOk)
       break;
 
     if (type != FOURCC_MDAT) {
@@ -819,10 +825,14 @@
           << FourCCToString(type);
     }
     // TODO(chcunningham): Fix mdat_tail_ and ByteQueue classes to use size_t.
+    // TODO(sandersd): The whole |mdat_tail_| mechanism appears to be pointless
+    // because StartTopLevelBox() only succeeds for complete boxes. Either
+    // remove |mdat_tail_| throughout this class or implement the ability to
+    // discard partial mdats.
     mdat_tail_ += base::checked_cast<int64_t>(box_sz);
   }
   queue_.Trim(std::min(mdat_tail_, upper_bound));
-  return !err;
+  return result != ParseResult::kError;
 }
 
 void MP4StreamParser::ChangeState(State new_state) {
diff --git a/media/formats/mp4/mp4_stream_parser.h b/media/formats/mp4/mp4_stream_parser.h
index 81593fc..ff1d84a2 100644
--- a/media/formats/mp4/mp4_stream_parser.h
+++ b/media/formats/mp4/mp4_stream_parser.h
@@ -17,6 +17,7 @@
 #include "media/base/media_export.h"
 #include "media/base/stream_parser.h"
 #include "media/formats/common/offset_byte_queue.h"
+#include "media/formats/mp4/parse_result.h"
 #include "media/formats/mp4/track_run_iterator.h"
 
 namespace media {
@@ -52,7 +53,7 @@
     kError
   };
 
-  bool ParseBox(bool* err);
+  ParseResult ParseBox();
   bool ParseMoov(mp4::BoxReader* reader);
   bool ParseMoof(mp4::BoxReader* reader);
 
@@ -75,7 +76,7 @@
   bool PrepareAACBuffer(const AAC& aac_config,
                         std::vector<uint8_t>* frame_buf,
                         std::vector<SubsampleEntry>* subsamples) const;
-  bool EnqueueSample(BufferQueueMap* buffers, bool* err);
+  ParseResult EnqueueSample(BufferQueueMap* buffers);
   bool SendAndFlushSamples(BufferQueueMap* buffers);
 
   void Reset();
diff --git a/media/formats/mp4/parse_result.h b/media/formats/mp4/parse_result.h
new file mode 100644
index 0000000..b5c8cb8
--- /dev/null
+++ b/media/formats/mp4/parse_result.h
@@ -0,0 +1,31 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef MEDIA_FORMATS_MP4_PARSE_RESULT_H_
+#define MEDIA_FORMATS_MP4_PARSE_RESULT_H_
+
+namespace media {
+namespace mp4 {
+
+enum class ParseResult {
+  kOk,            // Parsing was successful.
+  kError,         // The data is invalid (usually unrecoverable).
+  kNeedMoreData,  // More data is required to parse successfully.
+};
+
+// Evaluate |expr| once. If the result is not ParseResult::kOk, (early) return
+// it from the containing function.
+#define RCHECK_OK_PARSE_RESULT(expr)                      \
+  do {                                                    \
+    ::media::mp4::ParseResult result = (expr);            \
+    if (result == ::media::mp4::ParseResult::kError)      \
+      DLOG(ERROR) << "Failure while parsing MP4: " #expr; \
+    if (result != ::media::mp4::ParseResult::kOk)         \
+      return result;                                      \
+  } while (0)
+
+}  // namespace mp4
+}  // namespace media
+
+#endif  // MEDIA_FORMATS_MP4_PARSE_RESULT_H_
diff --git a/media/formats/mp4/rcheck.h b/media/formats/mp4/rcheck.h
index d756487..0c9700f 100644
--- a/media/formats/mp4/rcheck.h
+++ b/media/formats/mp4/rcheck.h
@@ -8,15 +8,19 @@
 #include "base/logging.h"
 #include "media/base/media_log.h"
 
-#define RCHECK_MEDIA_LOGGED(condition, log_cb, msg)                 \
-  do {                                                              \
-    if (!(condition)) {                                             \
-      DLOG(ERROR) << "Failure while parsing MP4: " #condition;      \
-      MEDIA_LOG(ERROR, log_cb) << "Failure parsing MP4: " << (msg); \
-      return false;                                                 \
-    }                                                               \
+// Evaluate |condition| once. If the result is false, log |msg| to |media_log|,
+// and (early) return false from the containing function.
+#define RCHECK_MEDIA_LOGGED(condition, media_log, msg)                 \
+  do {                                                                 \
+    if (!(condition)) {                                                \
+      DLOG(ERROR) << "Failure while parsing MP4: " #condition;         \
+      MEDIA_LOG(ERROR, media_log) << "Failure parsing MP4: " << (msg); \
+      return false;                                                    \
+    }                                                                  \
   } while (0)
 
+// Evaluate |condition| once. If the result is false, (early) return false from
+// the containing function.
 // TODO(wolenetz,chcunningham): Where appropriate, replace usage of this macro
 // in favor of RCHECK_MEDIA_LOGGED. See https://crbug.com/487410.
 #define RCHECK(condition)                                      \
diff --git a/media/formats/mp4/track_run_iterator.cc b/media/formats/mp4/track_run_iterator.cc
index 367c92d..88e59b3 100644
--- a/media/formats/mp4/track_run_iterator.cc
+++ b/media/formats/mp4/track_run_iterator.cc
@@ -12,6 +12,7 @@
 #include "base/macros.h"
 #include "base/numerics/checked_math.h"
 #include "base/numerics/safe_conversions.h"
+#include "media/base/demuxer_memory_limit.h"
 #include "media/base/timestamp_constants.h"
 #include "media/formats/mp4/rcheck.h"
 #include "media/formats/mp4/sample_to_group_iterator.h"
@@ -394,10 +395,8 @@
       }
 
       // Avoid allocating insane sample counts for invalid media.
-      // TODO(sandersd): Merge this limit with kDemuxerMemoryLimit,
-      // kSourceBuffer{Audio,Video}MemoryLimit.
       const size_t max_sample_count =
-          (150 * 1024 * 1024) / sizeof(decltype(tri.samples)::value_type);
+          kDemuxerMemoryLimit / sizeof(decltype(tri.samples)::value_type);
       RCHECK_MEDIA_LOGGED(
           base::strict_cast<size_t>(trun.sample_count) <= max_sample_count,
           media_log_, "Metadata overhead exceeds storage limit.");
diff --git a/media/gpu/BUILD.gn b/media/gpu/BUILD.gn
index b706437..3aa95b92 100644
--- a/media/gpu/BUILD.gn
+++ b/media/gpu/BUILD.gn
@@ -300,6 +300,7 @@
 
   if (use_vaapi) {
     sources += [
+                 "va_surface.cc",
                  "va_surface.h",
                  "vaapi_jpeg_decode_accelerator.cc",
                  "vaapi_jpeg_decode_accelerator.h",
diff --git a/media/gpu/va_surface.cc b/media/gpu/va_surface.cc
new file mode 100644
index 0000000..a1f3a84
--- /dev/null
+++ b/media/gpu/va_surface.cc
@@ -0,0 +1,24 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "media/gpu/va_surface.h"
+
+namespace media {
+
+VASurface::VASurface(VASurfaceID va_surface_id,
+                     const gfx::Size& size,
+                     unsigned int format,
+                     const ReleaseCB& release_cb)
+    : va_surface_id_(va_surface_id),
+      size_(size),
+      format_(format),
+      release_cb_(release_cb) {
+  DCHECK(!release_cb_.is_null());
+}
+
+VASurface::~VASurface() {
+  release_cb_.Run(va_surface_id_);
+}
+
+}  // namespace media
diff --git a/media/gpu/va_surface.h b/media/gpu/va_surface.h
index 0ad963ba..3734345 100644
--- a/media/gpu/va_surface.h
+++ b/media/gpu/va_surface.h
@@ -89,15 +89,14 @@
  public:
   // Provided by user, will be called when all references to the surface
   // are released.
-  typedef base::Callback<void(VASurfaceID)> ReleaseCB;
+  using ReleaseCB = base::Callback<void(VASurfaceID)>;
 
   VASurface(VASurfaceID va_surface_id,
             const gfx::Size& size,
             unsigned int format,
             const ReleaseCB& release_cb);
 
-  VASurfaceID id() { return va_surface_id_; }
-
+  VASurfaceID id() const { return va_surface_id_; }
   const gfx::Size& size() const { return size_; }
   unsigned int format() const { return format_; }
 
@@ -106,9 +105,9 @@
   ~VASurface();
 
   const VASurfaceID va_surface_id_;
-  gfx::Size size_;
-  unsigned int format_;
-  ReleaseCB release_cb_;
+  const gfx::Size size_;
+  const unsigned int format_;
+  const ReleaseCB release_cb_;
 
   DISALLOW_COPY_AND_ASSIGN(VASurface);
 };
diff --git a/media/gpu/vaapi_video_encode_accelerator.cc b/media/gpu/vaapi_video_encode_accelerator.cc
index 54fa92d..6ae28fbb 100644
--- a/media/gpu/vaapi_video_encode_accelerator.cc
+++ b/media/gpu/vaapi_video_encode_accelerator.cc
@@ -534,33 +534,45 @@
   if (state_ != kEncoding)
     return;
 
-  if (submitted_encode_jobs_.empty() || available_bitstream_buffers_.empty())
-    return;
+  while (!submitted_encode_jobs_.empty()) {
+    linked_ptr<EncodeJob> encode_job = submitted_encode_jobs_.front();
+    // An null job indicates a flush command.
+    if (encode_job == nullptr) {
+      submitted_encode_jobs_.pop();
+      DVLOGF(2) << "FlushDone";
+      DCHECK(flush_callback_);
+      child_task_runner_->PostTask(
+          FROM_HERE, base::BindOnce(std::move(flush_callback_), true));
+      continue;
+    }
 
-  linked_ptr<BitstreamBufferRef> buffer = available_bitstream_buffers_.front();
-  available_bitstream_buffers_.pop();
+    if (available_bitstream_buffers_.empty())
+      break;
+    auto buffer = available_bitstream_buffers_.front();
 
-  uint8_t* target_data = reinterpret_cast<uint8_t*>(buffer->shm->memory());
+    available_bitstream_buffers_.pop();
+    submitted_encode_jobs_.pop();
 
-  linked_ptr<EncodeJob> encode_job = submitted_encode_jobs_.front();
-  submitted_encode_jobs_.pop();
+    uint8_t* target_data = reinterpret_cast<uint8_t*>(buffer->shm->memory());
 
-  size_t data_size = 0;
-  if (!vaapi_wrapper_->DownloadAndDestroyCodedBuffer(
-          encode_job->coded_buffer, encode_job->input_surface->id(),
-          target_data, buffer->shm->size(), &data_size)) {
-    NOTIFY_ERROR(kPlatformFailureError, "Failed downloading coded buffer");
-    return;
+    size_t data_size = 0;
+    if (!vaapi_wrapper_->DownloadAndDestroyCodedBuffer(
+            encode_job->coded_buffer, encode_job->input_surface->id(),
+            target_data, buffer->shm->size(), &data_size)) {
+      NOTIFY_ERROR(kPlatformFailureError, "Failed downloading coded buffer");
+      return;
+    }
+
+    DVLOGF(4) << "Returning bitstream buffer "
+              << (encode_job->keyframe ? "(keyframe)" : "")
+              << " id: " << buffer->id << " size: " << data_size;
+
+    child_task_runner_->PostTask(
+        FROM_HERE,
+        base::Bind(&Client::BitstreamBufferReady, client_, buffer->id,
+                   data_size, encode_job->keyframe, encode_job->timestamp));
+    break;
   }
-
-  DVLOGF(4) << "Returning bitstream buffer "
-            << (encode_job->keyframe ? "(keyframe)" : "")
-            << " id: " << buffer->id << " size: " << data_size;
-
-  child_task_runner_->PostTask(
-      FROM_HERE,
-      base::Bind(&Client::BitstreamBufferReady, client_, buffer->id, data_size,
-                 encode_job->keyframe, encode_job->timestamp));
 }
 
 void VaapiVideoEncodeAccelerator::Encode(const scoped_refptr<VideoFrame>& frame,
@@ -747,6 +759,28 @@
   encoding_parameters_changed_ = true;
 }
 
+void VaapiVideoEncodeAccelerator::Flush(FlushCallback flush_callback) {
+  DVLOGF(2);
+  DCHECK(child_task_runner_->BelongsToCurrentThread());
+  if (flush_callback_) {
+    NOTIFY_ERROR(kIllegalStateError, "There is a pending flush");
+    std::move(flush_callback).Run(false);
+    return;
+  }
+  flush_callback_ = std::move(flush_callback);
+  encoder_thread_task_runner_->PostTask(
+      FROM_HERE, base::Bind(&VaapiVideoEncodeAccelerator::FlushTask,
+                            base::Unretained(this)));
+}
+
+void VaapiVideoEncodeAccelerator::FlushTask() {
+  DCHECK(encoder_thread_task_runner_->BelongsToCurrentThread());
+
+  // Insert an null job to indicate a flush command.
+  submitted_encode_jobs_.push(linked_ptr<EncodeJob>(nullptr));
+  TryToReturnBitstreamBuffer();
+}
+
 void VaapiVideoEncodeAccelerator::Destroy() {
   DCHECK(child_task_runner_->BelongsToCurrentThread());
 
@@ -762,6 +796,9 @@
     encoder_thread_.Stop();
   }
 
+  if (flush_callback_)
+    std::move(flush_callback_).Run(false);
+
   delete this;
 }
 
diff --git a/media/gpu/vaapi_video_encode_accelerator.h b/media/gpu/vaapi_video_encode_accelerator.h
index 42e2aee..33aeb83 100644
--- a/media/gpu/vaapi_video_encode_accelerator.h
+++ b/media/gpu/vaapi_video_encode_accelerator.h
@@ -46,6 +46,7 @@
   void RequestEncodingParametersChange(uint32_t bitrate,
                                        uint32_t framerate) override;
   void Destroy() override;
+  void Flush(FlushCallback flush_callback) override;
 
  private:
   // Reference picture list.
@@ -100,6 +101,7 @@
   void RequestEncodingParametersChangeTask(uint32_t bitrate,
                                            uint32_t framerate);
   void DestroyTask();
+  void FlushTask();
 
   // Prepare and schedule an encode job if we have an input to encode
   // and enough resources to proceed.
@@ -238,6 +240,8 @@
   base::queue<linked_ptr<BitstreamBufferRef>> available_bitstream_buffers_;
 
   // Jobs submitted for encode, awaiting bitstream buffers to become available.
+  // A pending flush command, indicated by a null job, will be also put in the
+  // queue.
   base::queue<linked_ptr<EncodeJob>> submitted_encode_jobs_;
 
   // Encoder thread. All tasks are executed on it.
@@ -259,6 +263,9 @@
   base::WeakPtr<VaapiVideoEncodeAccelerator> weak_this_;
   base::WeakPtrFactory<VaapiVideoEncodeAccelerator> weak_this_ptr_factory_;
 
+  // The completion callback of the Flush() function.
+  FlushCallback flush_callback_;
+
   DISALLOW_COPY_AND_ASSIGN(VaapiVideoEncodeAccelerator);
 };
 
diff --git a/media/gpu/vaapi_wrapper.cc b/media/gpu/vaapi_wrapper.cc
index 0c753b5..4d9011e 100644
--- a/media/gpu/vaapi_wrapper.cc
+++ b/media/gpu/vaapi_wrapper.cc
@@ -104,6 +104,8 @@
 
 namespace media {
 
+namespace {
+
 // Maximum framerate of encoded profile. This value is an arbitary limit
 // and not taken from HW documentation.
 const int kMaxEncoderFramerate = 30;
@@ -136,6 +138,113 @@
     // TODO(mcasas): support other VP9 Profiles, https://crbug.com/778093.
 };
 
+// This class is a wrapper around its |va_display_| (and its associated
+// |va_lock_|) to guarantee mutual exclusion and singleton behaviour.
+class VADisplayState {
+ public:
+  static VADisplayState* Get();
+
+  VADisplayState();
+  ~VADisplayState() = delete;
+
+  // |va_lock_| must be held on entry.
+  bool Initialize();
+  void Deinitialize(VAStatus* status);
+
+  base::Lock* va_lock() { return &va_lock_; }
+  VADisplay va_display() const { return va_display_; }
+
+#if defined(USE_OZONE)
+  void SetDrmFd(base::PlatformFile fd) { drm_fd_.reset(HANDLE_EINTR(dup(fd))); }
+#endif  // USE_OZONE
+
+ private:
+  // Protected by |va_lock_|.
+  int refcount_;
+
+  // Libva is not thread safe, so we have to do locking for it ourselves.
+  // This lock is to be taken for the duration of all VA-API calls and for
+  // the entire job submission sequence in ExecuteAndDestroyPendingBuffers().
+  base::Lock va_lock_;
+
+#if defined(USE_OZONE)
+  // Drm fd used to obtain access to the driver interface by VA.
+  base::ScopedFD drm_fd_;
+#endif  // USE_OZONE
+
+  // The VADisplay handle.
+  VADisplay va_display_;
+
+  // True if vaInitialize() has been called successfully.
+  bool va_initialized_;
+};
+
+// static
+VADisplayState* VADisplayState::Get() {
+  static VADisplayState* display_state = new VADisplayState();
+  return display_state;
+}
+
+VADisplayState::VADisplayState()
+    : refcount_(0), va_display_(nullptr), va_initialized_(false) {}
+
+bool VADisplayState::Initialize() {
+  va_lock_.AssertAcquired();
+  if (refcount_++ > 0)
+    return true;
+#if defined(USE_X11)
+  va_display_ = vaGetDisplay(gfx::GetXDisplay());
+#elif defined(USE_OZONE)
+  va_display_ = vaGetDisplayDRM(drm_fd_.get());
+#endif  // USE_X11
+
+  if (!vaDisplayIsValid(va_display_)) {
+    LOG(ERROR) << "Could not get a valid VA display";
+    return false;
+  }
+
+  // Set VA logging level to enable error messages, unless already set
+  constexpr char libva_log_level_env[] = "LIBVA_MESSAGING_LEVEL";
+  std::unique_ptr<base::Environment> env(base::Environment::Create());
+  if (!env->HasVar(libva_log_level_env))
+    env->SetVar(libva_log_level_env, "1");
+
+  // The VAAPI version.
+  int major_version, minor_version;
+  VAStatus va_res = vaInitialize(va_display_, &major_version, &minor_version);
+  if (va_res != VA_STATUS_SUCCESS) {
+    LOG(ERROR) << "vaInitialize failed: " << vaErrorStr(va_res);
+    return false;
+  }
+
+  va_initialized_ = true;
+  DVLOG(1) << "VAAPI version: " << major_version << "." << minor_version;
+
+  if (major_version != VA_MAJOR_VERSION || minor_version != VA_MINOR_VERSION) {
+    LOG(ERROR) << "This build of Chromium requires VA-API version "
+               << VA_MAJOR_VERSION << "." << VA_MINOR_VERSION
+               << ", system version: " << major_version << "." << minor_version;
+    return false;
+  }
+  return true;
+}
+
+void VADisplayState::Deinitialize(VAStatus* status) {
+  va_lock_.AssertAcquired();
+  if (--refcount_ > 0)
+    return;
+
+  // Must check if vaInitialize completed successfully, to work around a bug in
+  // libva. The bug was fixed upstream:
+  // http://lists.freedesktop.org/archives/libva/2013-July/001807.html
+  // TODO(mgiuca): Remove this check, and the |va_initialized_| variable, once
+  // the fix has rolled out sufficiently.
+  if (va_initialized_ && va_display_)
+    *status = vaTerminate(va_display_);
+  va_initialized_ = false;
+  va_display_ = nullptr;
+}
+
 static std::vector<VAConfigAttrib> GetRequiredAttribs(
     VaapiWrapper::CodecMode mode) {
   std::vector<VAConfigAttrib> required_attribs;
@@ -150,20 +259,7 @@
   return required_attribs;
 }
 
-VASurface::VASurface(VASurfaceID va_surface_id,
-                     const gfx::Size& size,
-                     unsigned int format,
-                     const ReleaseCB& release_cb)
-    : va_surface_id_(va_surface_id),
-      size_(size),
-      format_(format),
-      release_cb_(release_cb) {
-  DCHECK(!release_cb_.is_null());
-}
-
-VASurface::~VASurface() {
-  release_cb_.Run(va_surface_id_);
-}
+}  // namespace
 
 VaapiWrapper::VaapiWrapper()
     : va_surface_format_(0),
@@ -173,7 +269,7 @@
       va_vpp_config_id_(VA_INVALID_ID),
       va_vpp_context_id_(VA_INVALID_ID),
       va_vpp_buffer_id_(VA_INVALID_ID) {
-  va_lock_ = GetDisplayState()->va_lock();
+  va_lock_ = VADisplayState::Get()->va_lock();
 }
 
 VaapiWrapper::~VaapiWrapper() {
@@ -359,10 +455,10 @@
   report_error_to_uma_cb_ = report_error_to_uma_cb;
 
   base::AutoLock auto_lock(*va_lock_);
-  if (!GetDisplayState()->Initialize())
+  if (!VADisplayState::Get()->Initialize())
     return false;
 
-  va_display_ = GetDisplayState()->va_display();
+  va_display_ = VADisplayState::Get()->va_display();
   return true;
 }
 
@@ -509,7 +605,7 @@
   }
 
   VAStatus va_res = VA_STATUS_SUCCESS;
-  GetDisplayState()->Deinitialize(&va_res);
+  VADisplayState::Get()->Deinitialize(&va_res);
   VA_LOG_ON_ERROR(va_res, "vaTerminate failed");
 
   va_config_id_ = VA_INVALID_ID;
@@ -1086,7 +1182,7 @@
       base::FilePath::FromUTF8Unsafe(kDriRenderNode0Path),
       base::File::FLAG_OPEN | base::File::FLAG_READ | base::File::FLAG_WRITE);
   if (drm_file.IsValid())
-    GetDisplayState()->SetDrmFd(drm_file.GetPlatformFile());
+    VADisplayState::Get()->SetDrmFd(drm_file.GetPlatformFile());
 #endif
 }
 
@@ -1106,12 +1202,6 @@
 }
 
 // static
-VaapiWrapper::VADisplayState* VaapiWrapper::GetDisplayState() {
-  static VADisplayState* display_state = new VADisplayState();
-  return display_state;
-}
-
-// static
 VaapiWrapper::LazyProfileInfos* VaapiWrapper::GetProfileInfos() {
   static LazyProfileInfos* profile_infos = new LazyProfileInfos();
   return profile_infos;
@@ -1147,78 +1237,4 @@
   return false;
 }
 
-VaapiWrapper::VADisplayState::VADisplayState()
-    : refcount_(0),
-      va_display_(nullptr),
-      major_version_(-1),
-      minor_version_(-1),
-      va_initialized_(false) {}
-
-VaapiWrapper::VADisplayState::~VADisplayState() {}
-
-bool VaapiWrapper::VADisplayState::Initialize() {
-  va_lock_.AssertAcquired();
-  if (refcount_++ == 0) {
-#if defined(USE_X11)
-    va_display_ = vaGetDisplay(gfx::GetXDisplay());
-#elif defined(USE_OZONE)
-    va_display_ = vaGetDisplayDRM(drm_fd_.get());
-#endif  // USE_X11
-
-    if (!vaDisplayIsValid(va_display_)) {
-      LOG(ERROR) << "Could not get a valid VA display";
-      return false;
-    }
-
-    // Set VA logging level to enable error messages, unless already set
-    constexpr char libva_log_level_env[] = "LIBVA_MESSAGING_LEVEL";
-    std::unique_ptr<base::Environment> env(base::Environment::Create());
-    if (!env->HasVar(libva_log_level_env))
-      env->SetVar(libva_log_level_env, "1");
-
-    VAStatus va_res =
-        vaInitialize(va_display_, &major_version_, &minor_version_);
-    if (va_res != VA_STATUS_SUCCESS) {
-      LOG(ERROR) << "vaInitialize failed: " << vaErrorStr(va_res);
-      return false;
-    }
-
-    va_initialized_ = true;
-    DVLOG(1) << "VAAPI version: " << major_version_ << "." << minor_version_;
-  }
-
-  if (major_version_ != VA_MAJOR_VERSION ||
-      minor_version_ != VA_MINOR_VERSION) {
-    LOG(ERROR) << "This build of Chromium requires VA-API version "
-               << VA_MAJOR_VERSION << "." << VA_MINOR_VERSION
-               << ", system version: " << major_version_ << "."
-               << minor_version_;
-    return false;
-  }
-  return true;
-}
-
-void VaapiWrapper::VADisplayState::Deinitialize(VAStatus* status) {
-  va_lock_.AssertAcquired();
-  if (--refcount_ > 0)
-    return;
-
-  // Must check if vaInitialize completed successfully, to work around a bug in
-  // libva. The bug was fixed upstream:
-  // http://lists.freedesktop.org/archives/libva/2013-July/001807.html
-  // TODO(mgiuca): Remove this check, and the |va_initialized_| variable, once
-  // the fix has rolled out sufficiently.
-  if (va_initialized_ && va_display_) {
-    *status = vaTerminate(va_display_);
-  }
-  va_initialized_ = false;
-  va_display_ = nullptr;
-}
-
-#if defined(USE_OZONE)
-void VaapiWrapper::VADisplayState::SetDrmFd(base::PlatformFile fd) {
-  drm_fd_.reset(HANDLE_EINTR(dup(fd)));
-}
-#endif  // USE_OZONE
-
 }  // namespace media
diff --git a/media/gpu/vaapi_wrapper.h b/media/gpu/vaapi_wrapper.h
index 2be412d..3a7cff0e 100644
--- a/media/gpu/vaapi_wrapper.h
+++ b/media/gpu/vaapi_wrapper.h
@@ -226,46 +226,6 @@
     std::vector<ProfileInfo> supported_profiles_[kCodecModeMax];
   };
 
-  class VADisplayState {
-   public:
-    VADisplayState();
-    ~VADisplayState();
-
-    // |va_lock_| must be held on entry.
-    bool Initialize();
-    void Deinitialize(VAStatus* status);
-
-    base::Lock* va_lock() { return &va_lock_; }
-    VADisplay va_display() const { return va_display_; }
-
-#if defined(USE_OZONE)
-    void SetDrmFd(base::PlatformFile fd);
-#endif  // USE_OZONE
-
-   private:
-    // Protected by |va_lock_|.
-    int refcount_;
-
-    // Libva is not thread safe, so we have to do locking for it ourselves.
-    // This lock is to be taken for the duration of all VA-API calls and for
-    // the entire job submission sequence in ExecuteAndDestroyPendingBuffers().
-    base::Lock va_lock_;
-
-#if defined(USE_OZONE)
-    // Drm fd used to obtain access to the driver interface by VA.
-    base::ScopedFD drm_fd_;
-#endif  // USE_OZONE
-
-    // The VADisplay handle.
-    VADisplay va_display_;
-
-    // The VAAPI version.
-    int major_version_, minor_version_;
-
-    // True if vaInitialize has been called successfully.
-    bool va_initialized_;
-  };
-
   VaapiWrapper();
   ~VaapiWrapper();
 
@@ -330,7 +290,6 @@
                                       CodecMode mode);
 
   // Singleton accessors.
-  static VADisplayState* GetDisplayState();
   static LazyProfileInfos* GetProfileInfos();
 
   // Pointer to VADisplayState's member |va_lock_|. Guaranteed to be valid for
diff --git a/media/gpu/vt_video_encode_accelerator_mac.cc b/media/gpu/vt_video_encode_accelerator_mac.cc
index de0d8d7..86cc1ba 100644
--- a/media/gpu/vt_video_encode_accelerator_mac.cc
+++ b/media/gpu/vt_video_encode_accelerator_mac.cc
@@ -26,6 +26,23 @@
 const size_t kMaxResolutionHeight = 2160;
 const size_t kNumInputBuffers = 3;
 
+const VideoCodecProfile kSupportedProfiles[] = {
+    H264PROFILE_BASELINE, H264PROFILE_MAIN, H264PROFILE_HIGH};
+
+static CFStringRef VideoCodecProfileToVTProfile(VideoCodecProfile profile) {
+  switch (profile) {
+    case H264PROFILE_BASELINE:
+      return kVTProfileLevel_H264_Baseline_AutoLevel;
+    case H264PROFILE_MAIN:
+      return kVTProfileLevel_H264_Main_AutoLevel;
+    case H264PROFILE_HIGH:
+      return kVTProfileLevel_H264_High_AutoLevel;
+    default:
+      NOTREACHED();
+  }
+  return kVTProfileLevel_H264_Baseline_AutoLevel;
+}
+
 }  // namespace
 
 struct VTVideoEncodeAccelerator::InProgressFrameEncode {
@@ -75,6 +92,7 @@
 // of time.
 VTVideoEncodeAccelerator::VTVideoEncodeAccelerator()
     : target_bitrate_(0),
+      h264_profile_(H264PROFILE_BASELINE),
       bitrate_adjuster_(webrtc::Clock::GetRealTimeClock(), .5, .95),
       client_task_runner_(base::ThreadTaskRunnerHandle::Get()),
       encoder_thread_("VTEncoderThread"),
@@ -106,11 +124,13 @@
   }
 
   SupportedProfile profile;
-  profile.profile = H264PROFILE_BASELINE;
   profile.max_framerate_numerator = kMaxFrameRateNumerator;
   profile.max_framerate_denominator = kMaxFrameRateDenominator;
   profile.max_resolution = gfx::Size(kMaxResolutionWidth, kMaxResolutionHeight);
-  profiles.push_back(profile);
+  for (const auto& supported_profile : kSupportedProfiles) {
+    profile.profile = supported_profile;
+    profiles.push_back(profile);
+  }
   return profiles;
 }
 
@@ -131,11 +151,13 @@
                 << VideoPixelFormatToString(format);
     return false;
   }
-  if (H264PROFILE_BASELINE != output_profile) {
+  if (std::find(std::begin(kSupportedProfiles), std::end(kSupportedProfiles),
+                output_profile) == std::end(kSupportedProfiles)) {
     DLOG(ERROR) << "Output profile not supported= "
                 << GetProfileName(output_profile);
     return false;
   }
+  h264_profile_ = output_profile;
 
   client_ptr_factory_.reset(new base::WeakPtrFactory<Client>(client));
   client_ = client_ptr_factory_->GetWeakPtr();
@@ -507,8 +529,9 @@
   video_toolbox::SessionPropertySetter session_property_setter(
       compression_session_);
   bool rv = true;
-  rv &= session_property_setter.Set(kVTCompressionPropertyKey_ProfileLevel,
-                                    kVTProfileLevel_H264_Baseline_AutoLevel);
+  rv &=
+      session_property_setter.Set(kVTCompressionPropertyKey_ProfileLevel,
+                                  VideoCodecProfileToVTProfile(h264_profile_));
   rv &= session_property_setter.Set(kVTCompressionPropertyKey_RealTime, true);
   rv &= session_property_setter.Set(
       kVTCompressionPropertyKey_AllowFrameReordering, false);
diff --git a/media/gpu/vt_video_encode_accelerator_mac.h b/media/gpu/vt_video_encode_accelerator_mac.h
index 6cf7faf1..09e88a3 100644
--- a/media/gpu/vt_video_encode_accelerator_mac.h
+++ b/media/gpu/vt_video_encode_accelerator_mac.h
@@ -106,6 +106,7 @@
   int32_t initial_bitrate_;
   int32_t target_bitrate_;
   int32_t encoder_set_bitrate_;
+  VideoCodecProfile h264_profile_;
 
   // Bitrate adjuster used to fix VideoToolbox's inconsistent bitrate issues.
   webrtc::BitrateAdjuster bitrate_adjuster_;
diff --git a/media/mojo/BUILD.gn b/media/mojo/BUILD.gn
index 2fef1b9e..d9c03d0 100644
--- a/media/mojo/BUILD.gn
+++ b/media/mojo/BUILD.gn
@@ -125,7 +125,10 @@
   }
 
   if (enable_library_cdms) {
-    sources += [ "services/mojo_cdm_allocator_unittest.cc" ]
+    sources += [
+      "services/mojo_cdm_allocator_unittest.cc",
+      "services/mojo_cdm_file_io_unittest.cc",
+    ]
     deps += [ "//media/cdm:cdm_api" ]
   }
 }
diff --git a/media/mojo/interfaces/cdm_storage.mojom b/media/mojo/interfaces/cdm_storage.mojom
index 2e2046f2..3012a65d 100644
--- a/media/mojo/interfaces/cdm_storage.mojom
+++ b/media/mojo/interfaces/cdm_storage.mojom
@@ -15,27 +15,42 @@
     kFailure   // Unable to open file.
   };
 
-  // Opens the file specified by |file_name| for read or write. Can be called
-  // multiple times for different files, or for the same file if the first one
-  // has been closed. If successful, kSuccess will be returned, |file| can
-  // be used to access the contents, and |releaser| should be closed when
-  // access to the file is no longer needed (i.e. file closed). On failure,
-  // |status| <> kSuccess and |file| and |releaser| are null.
-  // - If the file is already opened by another CDM instance, kInUse will
-  //   be returned in |status|.
+  // Opens the file specified by |file_name| for read only. Writing to the file
+  // is done using a temporary file created with the CdmFile interface returned.
+  // Can be called multiple times for different files, or for the same file if
+  // the first one has been closed. If successful, kSuccess will be returned,
+  // |file_for_reading| can be used to read the contents, and |cdm_file| should
+  // be closed when access to the file is no longer needed (i.e. file closed).
+  // On failure, |status| <> kSuccess and |file_for_reading| and |cdm_file|
+  // are null.
+  // - If the file is already opened, kInUse will be returned in |status|.
   // - |file_name| must not contain forward slash ('/') or backslash ('\'),
   //   and must not start with an underscore ('_'). If this happens,
   //   |status| == kFailure is returned.
-  // - if |key_system| passed to Initialize() is not recognized, kFailure
-  //   will be returned.
   Open(string file_name)
     => (Status status,
-        mojo.common.mojom.File? file,
-        associated CdmFileReleaser? releaser);
+        mojo.common.mojom.File? file_for_reading,
+        associated CdmFile? cdm_file);
 };
 
 // Provides a way to keep track of the file opened. When the connection to this
 // object is broken, it is assumed that the file has been closed and that no
 // more operations will be performed on it.
-interface CdmFileReleaser {
+//
+// This interface is also used to be able to write to the file. Due to sandbox
+// restrictions on some platforms (crbug.com/774762), setting the length of the
+// file explicitly is not allowed in sandboxed processes. To get around this
+// (and avoid file corruption issues), writing is done by opening a new file,
+// letting the client write to it, and then replace the original file after
+// writing.
+interface CdmFile {
+  // Open a new file that can be written to. This file will be in the same
+  // directory as the original file. If successful, returns |file_for_writing|
+  // which can be written to.
+  OpenFileForWriting() => (mojo.common.mojom.File? file_for_writing);
+
+  // Closes the file opened for writing and replaces the original file.
+  // Returns a new file descriptor that should be used to read the original
+  // file from now on.
+  CommitWrite() => (mojo.common.mojom.File? updated_file_for_reading);
 };
diff --git a/media/mojo/services/BUILD.gn b/media/mojo/services/BUILD.gn
index 47f96f7..7f0d2d8 100644
--- a/media/mojo/services/BUILD.gn
+++ b/media/mojo/services/BUILD.gn
@@ -125,6 +125,8 @@
     sources += [
       "mojo_cdm_allocator.cc",
       "mojo_cdm_allocator.h",
+      "mojo_cdm_file_io.cc",
+      "mojo_cdm_file_io.h",
       "mojo_cdm_helper.cc",
       "mojo_cdm_helper.h",
     ]
diff --git a/media/mojo/services/mojo_cdm_file_io.cc b/media/mojo/services/mojo_cdm_file_io.cc
new file mode 100644
index 0000000..bf7c324
--- /dev/null
+++ b/media/mojo/services/mojo_cdm_file_io.cc
@@ -0,0 +1,318 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "media/mojo/services/mojo_cdm_file_io.h"
+
+#include <utility>
+#include <vector>
+
+#include "base/bind.h"
+#include "base/callback.h"
+#include "base/task_scheduler/post_task.h"
+#include "media/base/scoped_callback_runner.h"
+
+namespace media {
+
+namespace {
+
+using ClientStatus = cdm::FileIOClient::Status;
+using StorageStatus = media::mojom::CdmStorage::Status;
+
+// File size limit is 32MB. Licenses saved by the CDM are typically several
+// hundreds of bytes.
+const int64_t kMaxFileSizeBytes = 32 * 1024 * 1024;
+
+// Maximum length of a file name.
+const size_t kFileNameMaxLength = 256;
+
+// File names must only contain letters (A-Za-z), digits(0-9), or "._-",
+// and not start with "_". It must contain at least 1 character, and not
+// more then |kFileNameMaxLength| characters.
+bool IsValidFileName(const std::string& name) {
+  if (name.empty() || name.length() > kFileNameMaxLength || name[0] == '_')
+    return false;
+
+  for (auto ch : name) {
+    if (!base::IsAsciiAlpha(ch) && !base::IsAsciiDigit(ch) && ch != '.' &&
+        ch != '_' && ch != '-') {
+      return false;
+    }
+  }
+
+  return true;
+}
+
+}  // namespace
+
+MojoCdmFileIO::MojoCdmFileIO(cdm::FileIOClient* client,
+                             mojom::CdmStorage* cdm_storage)
+    : client_(client), cdm_storage_(cdm_storage), weak_factory_(this) {
+  DVLOG(3) << __func__;
+  DCHECK(client_);
+  DCHECK(cdm_storage_);
+}
+
+MojoCdmFileIO::~MojoCdmFileIO() {
+  // The destructor is private. |this| can only be destructed through Close().
+}
+
+void MojoCdmFileIO::Open(const char* file_name, uint32_t file_name_size) {
+  std::string file_name_string(file_name, file_name_size);
+  DVLOG(3) << __func__ << " file: " << file_name_string;
+
+  // Open is only allowed if the current state is kUnopened and the file name
+  // is valid.
+  if (state_ != State::kUnopened) {
+    OnError(ErrorType::kOpenError);
+    return;
+  }
+
+  if (!IsValidFileName(file_name_string)) {
+    OnError(ErrorType::kOpenError);
+    return;
+  }
+
+  state_ = State::kOpening;
+  file_name_ = file_name_string;
+
+  auto callback = ScopedCallbackRunner(
+      base::BindOnce(&MojoCdmFileIO::OnFileOpened, weak_factory_.GetWeakPtr()),
+      StorageStatus::kFailure, base::File(), nullptr);
+  cdm_storage_->Open(file_name_string, std::move(callback));
+}
+
+void MojoCdmFileIO::OnFileOpened(StorageStatus status,
+                                 base::File file,
+                                 mojom::CdmFileAssociatedPtrInfo cdm_file) {
+  DVLOG(3) << __func__ << " file: " << file_name_ << ", status: " << status;
+
+  switch (status) {
+    case StorageStatus::kSuccess:
+      if (!file.IsValid()) {
+        NOTREACHED() << "File received is invalid.";
+        state_ = State::kError;
+        OnError(ErrorType::kOpenError);
+        return;
+      }
+
+      // File was successfully opened.
+      state_ = State::kOpened;
+      file_for_reading_ = std::move(file);
+      cdm_file_.Bind(std::move(cdm_file));
+      client_->OnOpenComplete(ClientStatus::kSuccess);
+      return;
+    case StorageStatus::kInUse:
+      // File already open by somebody else.
+      state_ = State::kUnopened;
+      OnError(ErrorType::kOpenInUse);
+      return;
+    case StorageStatus::kFailure:
+      // Something went wrong.
+      state_ = State::kError;
+      OnError(ErrorType::kOpenError);
+      return;
+  }
+
+  NOTREACHED();
+}
+
+void MojoCdmFileIO::Read() {
+  DVLOG(3) << __func__ << " file: " << file_name_;
+
+  // If another operation is in progress, fail.
+  if (state_ == State::kReading || state_ == State::kWriting) {
+    OnError(ErrorType::kReadInUse);
+    return;
+  }
+
+  // If the file is not open, fail.
+  if (state_ != State::kOpened) {
+    OnError(ErrorType::kReadError);
+    return;
+  }
+
+  // Determine the size of the file (so we know how many bytes to read).
+  int64_t num_bytes = file_for_reading_.GetLength();
+  if (num_bytes < 0) {
+    // Negative bytes mean failure, so fail. This error is not recoverable,
+    // so don't allow any more operations other than close on the file.
+    state_ = State::kError;
+    OnError(ErrorType::kReadError);
+    return;
+  }
+
+  // Files are limited to 32MB, so fail if file too big. Setting |state_|
+  // back to Opened so that the CDM could write something valid to this file.
+  if (num_bytes > kMaxFileSizeBytes) {
+    DLOG(WARNING) << __func__
+                  << " Too much data to read. #bytes = " << num_bytes;
+    OnError(ErrorType::kReadError);
+    return;
+  }
+
+  // Do the actual read asynchronously so that we don't need to copy the
+  // data when calling |client_|.
+  state_ = State::kReading;
+  base::ThreadTaskRunnerHandle::Get()->PostTask(
+      FROM_HERE, base::BindOnce(&MojoCdmFileIO::DoRead,
+                                weak_factory_.GetWeakPtr(), num_bytes));
+}
+
+void MojoCdmFileIO::DoRead(int64_t num_bytes) {
+  DVLOG(3) << __func__ << " file: " << file_name_;
+  DCHECK_EQ(State::kReading, state_);
+
+  // We know how much data is available, so read the complete contents of the
+  // file into a buffer and passing it back to |client_|. As these should be
+  // small files, we don't worry about breaking it up into chunks to read it.
+
+  // If the file has 0 bytes, no need to read anything.
+  if (num_bytes == 0) {
+    state_ = State::kOpened;
+    client_->OnReadComplete(ClientStatus::kSuccess, nullptr, 0);
+    return;
+  }
+
+  // Read the contents of the file. Read() sizes (provided and returned) are
+  // type int, so cast appropriately.
+  int bytes_to_read = base::checked_cast<int>(num_bytes);
+  std::vector<uint8_t> buffer(bytes_to_read);
+  int bytes_read = file_for_reading_.Read(
+      0, reinterpret_cast<char*>(buffer.data()), bytes_to_read);
+  if (bytes_to_read != bytes_read) {
+    // Unable to read the contents of the file. Setting |state_| to kOpened
+    // so that the CDM can write something valid to this file.
+    DVLOG(1) << "Failed to read file " << file_name_ << ". Requested "
+             << bytes_to_read << " bytes, got " << bytes_read;
+    state_ = State::kOpened;
+    OnError(ErrorType::kReadError);
+    return;
+  }
+
+  state_ = State::kOpened;
+  client_->OnReadComplete(ClientStatus::kSuccess, buffer.data(), buffer.size());
+}
+
+void MojoCdmFileIO::Write(const uint8_t* data, uint32_t data_size) {
+  DVLOG(3) << __func__ << " file: " << file_name_ << ", bytes: " << data_size;
+
+  // If another operation is in progress, fail.
+  if (state_ == State::kReading || state_ == State::kWriting) {
+    OnError(ErrorType::kWriteInUse);
+    return;
+  }
+
+  // If the file is not open, fail.
+  if (state_ != State::kOpened) {
+    OnError(ErrorType::kWriteError);
+    return;
+  }
+
+  // Files are limited to 32MB, so fail if file too big.
+  if (data_size > kMaxFileSizeBytes) {
+    DLOG(WARNING) << __func__
+                  << " Too much data to write. #bytes = " << data_size;
+    OnError(ErrorType::kWriteError);
+    return;
+  }
+
+  // Now open a temporary file for writing. Close |file_for_reading_| as it
+  // won't be used again.
+  state_ = State::kWriting;
+  file_for_reading_.Close();
+  cdm_file_->OpenFileForWriting(base::BindOnce(
+      &MojoCdmFileIO::OnFileOpenedForWriting, weak_factory_.GetWeakPtr(),
+      std::vector<uint8_t>(data, data + data_size)));
+}
+
+void MojoCdmFileIO::OnFileOpenedForWriting(const std::vector<uint8_t>& data,
+                                           base::File temporary_file) {
+  DVLOG(3) << __func__ << " file: " << file_name_ << ", result: "
+           << base::File::ErrorToString(temporary_file.error_details());
+  DCHECK_EQ(State::kWriting, state_);
+
+  if (!temporary_file.IsValid()) {
+    // Failed to open temporary file.
+    state_ = State::kError;
+    OnError(ErrorType::kWriteError);
+    return;
+  }
+
+  // As the temporary file should have been newly created, it should be empty.
+  // No need to call write() if there is no data.
+  CHECK_EQ(0u, temporary_file.GetLength()) << "Temporary file is not empty.";
+  int bytes_to_write = base::checked_cast<int>(data.size());
+  if (bytes_to_write > 0) {
+    int bytes_written = temporary_file.Write(
+        0, reinterpret_cast<const char*>(data.data()), bytes_to_write);
+    if (bytes_written != bytes_to_write) {
+      // Failed to write to the temporary file.
+      state_ = State::kError;
+      OnError(ErrorType::kWriteError);
+      return;
+    }
+  }
+
+  // Close the temporary file returned before renaming. Original file was
+  // closed previously.
+  temporary_file.Close();
+  DCHECK(!file_for_reading_.IsValid()) << "Original file was not closed.";
+  cdm_file_->CommitWrite(base::BindOnce(&MojoCdmFileIO::OnWriteCommitted,
+                                        weak_factory_.GetWeakPtr()));
+}
+
+void MojoCdmFileIO::OnWriteCommitted(base::File reopened_file) {
+  DVLOG(3) << __func__ << " file: " << file_name_;
+  DCHECK_EQ(State::kWriting, state_);
+  DCHECK(!file_for_reading_.IsValid()) << "Original file was not closed.";
+
+  if (!reopened_file.IsValid()) {
+    // Rename failed, and no file to use.
+    state_ = State::kError;
+    OnError(ErrorType::kWriteError);
+    return;
+  }
+
+  state_ = State::kOpened;
+  file_for_reading_ = std::move(reopened_file);
+  client_->OnWriteComplete(ClientStatus::kSuccess);
+}
+
+void MojoCdmFileIO::Close() {
+  DVLOG(3) << __func__ << " file: " << file_name_;
+  delete this;
+}
+
+void MojoCdmFileIO::OnError(ErrorType error) {
+  DVLOG(3) << __func__ << " file: " << file_name_ << ", error: " << (int)error;
+
+  base::ThreadTaskRunnerHandle::Get()->PostTask(
+      FROM_HERE, base::BindOnce(&MojoCdmFileIO::NotifyClientOfError,
+                                weak_factory_.GetWeakPtr(), error));
+}
+
+void MojoCdmFileIO::NotifyClientOfError(ErrorType error) {
+  switch (error) {
+    case ErrorType::kOpenError:
+      client_->OnOpenComplete(ClientStatus::kError);
+      break;
+    case ErrorType::kOpenInUse:
+      client_->OnOpenComplete(ClientStatus::kInUse);
+      break;
+    case ErrorType::kReadError:
+      client_->OnReadComplete(ClientStatus::kError, nullptr, 0);
+      break;
+    case ErrorType::kReadInUse:
+      client_->OnReadComplete(ClientStatus::kInUse, nullptr, 0);
+      break;
+    case ErrorType::kWriteError:
+      client_->OnWriteComplete(ClientStatus::kError);
+      break;
+    case ErrorType::kWriteInUse:
+      client_->OnWriteComplete(ClientStatus::kInUse);
+      break;
+  }
+}
+
+}  // namespace media
diff --git a/media/mojo/services/mojo_cdm_file_io.h b/media/mojo/services/mojo_cdm_file_io.h
new file mode 100644
index 0000000..b1fa8169
--- /dev/null
+++ b/media/mojo/services/mojo_cdm_file_io.h
@@ -0,0 +1,114 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef MEDIA_MOJO_SERVICES_MOJO_CDM_FILE_IO_H_
+#define MEDIA_MOJO_SERVICES_MOJO_CDM_FILE_IO_H_
+
+#include <stdint.h>
+
+#include <string>
+#include <vector>
+
+#include "base/callback_forward.h"
+#include "base/files/file.h"
+#include "base/files/file_path.h"
+#include "base/macros.h"
+#include "base/memory/ref_counted.h"
+#include "base/memory/weak_ptr.h"
+#include "media/cdm/api/content_decryption_module.h"
+#include "media/cdm/cdm_file_io.h"
+#include "media/mojo/interfaces/cdm_storage.mojom.h"
+#include "media/mojo/services/media_mojo_export.h"
+
+namespace media {
+
+// TODO(crbug.com/774160): This class should do the Read/Write operations on a
+// separate thread so as to not impact decoding happening on the same thread.
+// The new thread may need to block shutdown so that the file is not corrupted.
+
+// Implements a CdmFileIO that communicates with mojom::CdmStorage.
+class MEDIA_MOJO_EXPORT MojoCdmFileIO : public CdmFileIO {
+ public:
+  MojoCdmFileIO(cdm::FileIOClient* client, mojom::CdmStorage* cdm_storage);
+  ~MojoCdmFileIO() override;
+
+  // CdmFileIO implementation.
+  void Open(const char* file_name, uint32_t file_name_size) final;
+  void Read() final;
+  void Write(const uint8_t* data, uint32_t data_size) final;
+  void Close() final;
+
+ private:
+  // Allowed state transitions:
+  //   kUnopened -> kOpening -> kOpened
+  //   kUnopened -> kOpening -> kUnopened (if file in use)
+  //   kUnopened -> kOpening -> kError (if file not available)
+  //   kOpened -> kReading -> kOpened
+  //   kOpened -> kWriting -> kOpened
+  // Once state = kError, only Close() can be called.
+  enum class State { kUnopened, kOpening, kOpened, kReading, kWriting, kError };
+
+  // Error that needs to be reported back to the client.
+  enum class ErrorType {
+    kOpenError,
+    kOpenInUse,
+    kReadError,
+    kReadInUse,
+    kWriteError,
+    kWriteInUse
+  };
+
+  // Called when the file is opened (or not).
+  void OnFileOpened(mojom::CdmStorage::Status status,
+                    base::File file,
+                    mojom::CdmFileAssociatedPtrInfo cdm_file);
+
+  // Reading the file is done asynchronously.
+  void DoRead(int64_t num_bytes);
+
+  // Called when a temporary file has been opened for writing.
+  void OnFileOpenedForWriting(const std::vector<uint8_t>& data,
+                              base::File temporary_file);
+
+  // Called after the write has been committed and replaces the original file.
+  void OnWriteCommitted(base::File reopened_file);
+
+  // Called when an error occurs. Calls client_->OnXxxxComplete with kError
+  // or kInUse asynchronously. In some cases we could actually call them
+  // synchronously, but since these errors shouldn't happen in normal cases,
+  // we are not optimizing such cases.
+  void OnError(ErrorType error);
+
+  // Callback to notify client of error asynchronously.
+  void NotifyClientOfError(ErrorType error);
+
+  // Results of CdmFileIO operations are sent asynchronously via |client_|.
+  cdm::FileIOClient* client_;
+
+  mojom::CdmStorage* cdm_storage_;
+
+  // Keep track of the file being used. As this class can only be used for
+  // accessing a single file, once |file_name_| is set it shouldn't be changed.
+  // |file_name_| is only saved for logging purposes.
+  std::string file_name_;
+
+  // Current file open for reading.
+  base::File file_for_reading_;
+
+  // |cdm_file_| is used to write to the file and is released when the file is
+  // closed so that CdmStorage can tell that the file is no longer being used.
+  mojom::CdmFileAssociatedPtr cdm_file_;
+
+  // Keep track of operations in progress.
+  State state_ = State::kUnopened;
+
+  // NOTE: Weak pointers must be invalidated before all other member variables.
+  base::WeakPtrFactory<MojoCdmFileIO> weak_factory_;
+
+  DISALLOW_COPY_AND_ASSIGN(MojoCdmFileIO);
+};
+
+}  // namespace media
+
+#endif  // MEDIA_MOJO_SERVICES_MOJO_CDM_FILE_IO_H_
diff --git a/media/mojo/services/mojo_cdm_file_io_unittest.cc b/media/mojo/services/mojo_cdm_file_io_unittest.cc
new file mode 100644
index 0000000..0f23c48
--- /dev/null
+++ b/media/mojo/services/mojo_cdm_file_io_unittest.cc
@@ -0,0 +1,186 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "media/mojo/services/mojo_cdm_file_io.h"
+
+#include "base/files/file.h"
+#include "base/files/file_util.h"
+#include "base/files/scoped_temp_dir.h"
+#include "base/run_loop.h"
+#include "base/test/scoped_task_environment.h"
+#include "media/cdm/api/content_decryption_module.h"
+#include "mojo/public/cpp/bindings/strong_associated_binding.h"
+#include "testing/gmock/include/gmock/gmock.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+using ::testing::_;
+using ::testing::SaveArg;
+using ::testing::StrictMock;
+using Status = cdm::FileIOClient::Status;
+
+namespace media {
+
+namespace {
+
+class MockFileIOClient : public cdm::FileIOClient {
+ public:
+  MockFileIOClient() {}
+  ~MockFileIOClient() override {}
+
+  MOCK_METHOD1(OnOpenComplete, void(Status));
+  MOCK_METHOD3(OnReadComplete, void(Status, const uint8_t*, uint32_t));
+  MOCK_METHOD1(OnWriteComplete, void(Status));
+};
+
+class MockCdmStorage : public mojom::CdmStorage {
+ public:
+  MockCdmStorage() {}
+  ~MockCdmStorage() override {}
+
+  bool SetUp() { return temp_directory_.CreateUniqueTempDir(); }
+
+  // MojoCdmFileIO calls CdmStorage::Open() to actually open the file.
+  // Simulate this by creating a file in the temp directory and returning it.
+  void Open(const std::string& file_name, OpenCallback callback) override {
+    base::FilePath temp_file = temp_directory_.GetPath().AppendASCII(file_name);
+    DVLOG(1) << __func__ << " " << temp_file;
+    base::File file(temp_file, base::File::FLAG_CREATE_ALWAYS |
+                                   base::File::FLAG_READ |
+                                   base::File::FLAG_WRITE);
+    std::move(callback).Run(mojom::CdmStorage::Status::kSuccess,
+                            std::move(file), nullptr);
+  }
+
+ private:
+  base::ScopedTempDir temp_directory_;
+};
+
+}  // namespace
+
+// Currently MockCdmStorage::Open() returns NULL for the
+// CdmFileAssociatedPtrInfo, so it is not possible to connect to a CdmFile
+// object when writing data. This will require setting up a mojo connection
+// between MojoCdmFileIOTest and CdmStorage, rather than using the object
+// directly.
+//
+// Note that the current browser_test ECKEncryptedMediaTest.FileIOTest
+// does test writing (and reading) files using mojo. However, additional
+// unittests would be good.
+// TODO(crbug.com/777550): Implement tests that write to files.
+
+class MojoCdmFileIOTest : public testing::Test {
+ protected:
+  MojoCdmFileIOTest() {}
+  ~MojoCdmFileIOTest() override {}
+
+  void SetUp() override {
+    client_ = std::make_unique<MockFileIOClient>();
+    cdm_storage_ = std::make_unique<MockCdmStorage>();
+    ASSERT_TRUE(cdm_storage_->SetUp());
+    file_io_ =
+        std::make_unique<MojoCdmFileIO>(client_.get(), cdm_storage_.get());
+  }
+
+  base::test::ScopedTaskEnvironment scoped_task_environment_;
+  std::unique_ptr<MojoCdmFileIO> file_io_;
+  std::unique_ptr<MockCdmStorage> cdm_storage_;
+  std::unique_ptr<MockFileIOClient> client_;
+};
+
+TEST_F(MojoCdmFileIOTest, OpenFile) {
+  const std::string kFileName = "openfile";
+  EXPECT_CALL(*client_.get(), OnOpenComplete(Status::kSuccess));
+  file_io_->Open(kFileName.data(), kFileName.length());
+
+  base::RunLoop().RunUntilIdle();
+}
+
+TEST_F(MojoCdmFileIOTest, OpenFileTwice) {
+  const std::string kFileName = "openfile";
+  EXPECT_CALL(*client_.get(), OnOpenComplete(Status::kSuccess));
+  file_io_->Open(kFileName.data(), kFileName.length());
+
+  EXPECT_CALL(*client_.get(), OnOpenComplete(Status::kError));
+  file_io_->Open(kFileName.data(), kFileName.length());
+
+  base::RunLoop().RunUntilIdle();
+}
+
+TEST_F(MojoCdmFileIOTest, OpenFileAfterOpen) {
+  const std::string kFileName = "openfile";
+  EXPECT_CALL(*client_.get(), OnOpenComplete(Status::kSuccess));
+  file_io_->Open(kFileName.data(), kFileName.length());
+
+  // Run now so that the file is opened.
+  base::RunLoop().RunUntilIdle();
+
+  EXPECT_CALL(*client_.get(), OnOpenComplete(Status::kError));
+  file_io_->Open(kFileName.data(), kFileName.length());
+
+  // Run a second time so Open() tries after the file is already open.
+  base::RunLoop().RunUntilIdle();
+}
+
+TEST_F(MojoCdmFileIOTest, OpenDifferentFiles) {
+  const std::string kFileName1 = "openfile1";
+  EXPECT_CALL(*client_.get(), OnOpenComplete(Status::kSuccess));
+  file_io_->Open(kFileName1.data(), kFileName1.length());
+
+  const std::string kFileName2 = "openfile2";
+  EXPECT_CALL(*client_.get(), OnOpenComplete(Status::kError));
+  file_io_->Open(kFileName2.data(), kFileName2.length());
+
+  base::RunLoop().RunUntilIdle();
+}
+
+TEST_F(MojoCdmFileIOTest, OpenBadFileName) {
+  // Anything other than ASCII letter, digits, and -._ will fail. Add a
+  // Unicode character to the name.
+  const std::string kFileName = "openfile\u1234";
+  EXPECT_CALL(*client_.get(), OnOpenComplete(Status::kError));
+  file_io_->Open(kFileName.data(), kFileName.length());
+  base::RunLoop().RunUntilIdle();
+}
+
+TEST_F(MojoCdmFileIOTest, OpenTooLongFileName) {
+  // Limit is 256 characters, so try a file name with 257.
+  const std::string kFileName(257, 'a');
+  EXPECT_CALL(*client_.get(), OnOpenComplete(Status::kError));
+  file_io_->Open(kFileName.data(), kFileName.length());
+  base::RunLoop().RunUntilIdle();
+}
+
+TEST_F(MojoCdmFileIOTest, Read) {
+  const std::string kFileName = "readfile";
+  EXPECT_CALL(*client_.get(), OnOpenComplete(Status::kSuccess));
+  file_io_->Open(kFileName.data(), kFileName.length());
+  base::RunLoop().RunUntilIdle();
+
+  // File doesn't exist, so reading it should return 0 length buffer.
+  EXPECT_CALL(*client_.get(), OnReadComplete(Status::kSuccess, _, 0));
+  file_io_->Read();
+  base::RunLoop().RunUntilIdle();
+}
+
+TEST_F(MojoCdmFileIOTest, ReadBeforeOpen) {
+  // File not open, so reading should fail.
+  EXPECT_CALL(*client_.get(), OnReadComplete(Status::kError, _, _));
+  file_io_->Read();
+  base::RunLoop().RunUntilIdle();
+}
+
+TEST_F(MojoCdmFileIOTest, TwoReads) {
+  const std::string kFileName = "readfile";
+  EXPECT_CALL(*client_.get(), OnOpenComplete(Status::kSuccess));
+  file_io_->Open(kFileName.data(), kFileName.length());
+  base::RunLoop().RunUntilIdle();
+
+  EXPECT_CALL(*client_.get(), OnReadComplete(Status::kSuccess, _, 0));
+  EXPECT_CALL(*client_.get(), OnReadComplete(Status::kInUse, _, 0));
+  file_io_->Read();
+  file_io_->Read();
+  base::RunLoop().RunUntilIdle();
+}
+
+}  // namespace media
diff --git a/media/mojo/services/mojo_cdm_helper.cc b/media/mojo/services/mojo_cdm_helper.cc
index 0bb4836e..d76ee1a 100644
--- a/media/mojo/services/mojo_cdm_helper.cc
+++ b/media/mojo/services/mojo_cdm_helper.cc
@@ -7,20 +7,23 @@
 #include "media/base/scoped_callback_runner.h"
 #include "media/cdm/cdm_helpers.h"
 #include "media/mojo/services/mojo_cdm_allocator.h"
+#include "media/mojo/services/mojo_cdm_file_io.h"
 #include "services/service_manager/public/cpp/connect.h"
 
 namespace media {
 
 MojoCdmHelper::MojoCdmHelper(
     service_manager::mojom::InterfaceProvider* interface_provider)
-    : interface_provider_(interface_provider) {}
+    : interface_provider_(interface_provider), weak_factory_(this) {}
 
 MojoCdmHelper::~MojoCdmHelper() {}
 
 std::unique_ptr<CdmFileIO> MojoCdmHelper::CreateCdmFileIO(
     cdm::FileIOClient* client) {
-  // TODO(jrummell): Hook up File IO. http://crbug.com/479923.
-  return nullptr;
+  ConnectToCdmStorage();
+
+  // Pass a reference to CdmStorage so that MojoCdmFileIO can open a file.
+  return std::make_unique<MojoCdmFileIO>(client, cdm_storage_ptr_.get());
 }
 
 cdm::Buffer* MojoCdmHelper::CreateCdmBuffer(size_t capacity) {
@@ -34,21 +37,17 @@
 void MojoCdmHelper::QueryStatus(QueryStatusCB callback) {
   QueryStatusCB scoped_callback =
       ScopedCallbackRunner(std::move(callback), false, 0, 0);
-  if (!ConnectToOutputProtection())
-    return;
-
-  output_protection_->QueryStatus(std::move(scoped_callback));
+  ConnectToOutputProtection();
+  output_protection_ptr_->QueryStatus(std::move(scoped_callback));
 }
 
 void MojoCdmHelper::EnableProtection(uint32_t desired_protection_mask,
                                      EnableProtectionCB callback) {
   EnableProtectionCB scoped_callback =
       ScopedCallbackRunner(std::move(callback), false);
-  if (!ConnectToOutputProtection())
-    return;
-
-  output_protection_->EnableProtection(desired_protection_mask,
-                                       std::move(scoped_callback));
+  ConnectToOutputProtection();
+  output_protection_ptr_->EnableProtection(desired_protection_mask,
+                                           std::move(scoped_callback));
 }
 
 void MojoCdmHelper::ChallengePlatform(const std::string& service_id,
@@ -56,11 +55,9 @@
                                       ChallengePlatformCB callback) {
   ChallengePlatformCB scoped_callback =
       ScopedCallbackRunner(std::move(callback), false, "", "", "");
-  if (!ConnectToPlatformVerification())
-    return;
-
-  platform_verification_->ChallengePlatform(service_id, challenge,
-                                            std::move(scoped_callback));
+  ConnectToPlatformVerification();
+  platform_verification_ptr_->ChallengePlatform(service_id, challenge,
+                                                std::move(scoped_callback));
 }
 
 void MojoCdmHelper::GetStorageId(uint32_t version, StorageIdCB callback) {
@@ -70,28 +67,31 @@
   // http://crbug.com/478960.
 }
 
+void MojoCdmHelper::ConnectToCdmStorage() {
+  if (!cdm_storage_ptr_) {
+    service_manager::GetInterface<mojom::CdmStorage>(interface_provider_,
+                                                     &cdm_storage_ptr_);
+  }
+}
+
 CdmAllocator* MojoCdmHelper::GetAllocator() {
   if (!allocator_)
     allocator_ = base::MakeUnique<MojoCdmAllocator>();
   return allocator_.get();
 }
 
-bool MojoCdmHelper::ConnectToOutputProtection() {
-  if (!output_protection_attempted_) {
-    output_protection_attempted_ = true;
-    service_manager::GetInterface<mojom::OutputProtection>(interface_provider_,
-                                                           &output_protection_);
+void MojoCdmHelper::ConnectToOutputProtection() {
+  if (!output_protection_ptr_) {
+    service_manager::GetInterface<mojom::OutputProtection>(
+        interface_provider_, &output_protection_ptr_);
   }
-  return output_protection_.is_bound();
 }
 
-bool MojoCdmHelper::ConnectToPlatformVerification() {
-  if (!platform_verification_attempted_) {
-    platform_verification_attempted_ = true;
+void MojoCdmHelper::ConnectToPlatformVerification() {
+  if (!platform_verification_ptr_) {
     service_manager::GetInterface<mojom::PlatformVerification>(
-        interface_provider_, &platform_verification_);
+        interface_provider_, &platform_verification_ptr_);
   }
-  return platform_verification_.is_bound();
 }
 
 }  // namespace media
diff --git a/media/mojo/services/mojo_cdm_helper.h b/media/mojo/services/mojo_cdm_helper.h
index 167fdfd..51455e8 100644
--- a/media/mojo/services/mojo_cdm_helper.h
+++ b/media/mojo/services/mojo_cdm_helper.h
@@ -9,7 +9,9 @@
 
 #include "base/compiler_specific.h"
 #include "base/macros.h"
+#include "base/memory/weak_ptr.h"
 #include "media/cdm/cdm_auxiliary_helper.h"
+#include "media/mojo/interfaces/cdm_storage.mojom.h"
 #include "media/mojo/interfaces/output_protection.mojom.h"
 #include "media/mojo/interfaces/platform_verification.mojom.h"
 #include "media/mojo/services/media_mojo_export.h"
@@ -32,8 +34,7 @@
   ~MojoCdmHelper() final;
 
   // CdmAuxiliaryHelper implementation.
-  std::unique_ptr<media::CdmFileIO> CreateCdmFileIO(
-      cdm::FileIOClient* client) final;
+  std::unique_ptr<CdmFileIO> CreateCdmFileIO(cdm::FileIOClient* client) final;
   cdm::Buffer* CreateCdmBuffer(size_t capacity) final;
   std::unique_ptr<VideoFrameImpl> CreateCdmVideoFrame() final;
   void QueryStatus(QueryStatusCB callback) final;
@@ -46,21 +47,25 @@
 
  private:
   // All services are created lazily.
+  void ConnectToCdmStorage();
   CdmAllocator* GetAllocator();
-  bool ConnectToOutputProtection();
-  bool ConnectToPlatformVerification();
+  void ConnectToOutputProtection();
+  void ConnectToPlatformVerification();
 
   // Provides interfaces when needed.
   service_manager::mojom::InterfaceProvider* interface_provider_;
 
-  // Keep track if connection to the Mojo service has been attempted once.
-  // The service may not exist, or may fail later.
-  bool output_protection_attempted_ = false;
-  bool platform_verification_attempted_ = false;
+  // Connections to the additional services. For the mojom classes, if a
+  // connection error occurs, we will not be able to reconnect to the
+  // service as the document has been destroyed (see FrameServiceBase) or
+  // the browser crashed, so there's no point in trying to reconnect.
+  mojom::CdmStoragePtr cdm_storage_ptr_;
+  std::unique_ptr<CdmAllocator> allocator_;
+  mojom::OutputProtectionPtr output_protection_ptr_;
+  mojom::PlatformVerificationPtr platform_verification_ptr_;
 
-  std::unique_ptr<media::CdmAllocator> allocator_;
-  media::mojom::OutputProtectionPtr output_protection_;
-  media::mojom::PlatformVerificationPtr platform_verification_;
+  base::WeakPtrFactory<MojoCdmHelper> weak_factory_;
+  DISALLOW_COPY_AND_ASSIGN(MojoCdmHelper);
 };
 
 }  // namespace media
diff --git a/media/mojo/services/video_decode_perf_history.cc b/media/mojo/services/video_decode_perf_history.cc
index 7ddb26ca..5f79000 100644
--- a/media/mojo/services/video_decode_perf_history.cc
+++ b/media/mojo/services/video_decode_perf_history.cc
@@ -14,26 +14,11 @@
 
 namespace media {
 
-VideoDecodeStatsDB* g_database = nullptr;
-
-// static
-void VideoDecodePerfHistory::Initialize(VideoDecodeStatsDB* db_instance) {
-  DVLOG(2) << __func__;
-  g_database = db_instance;
-}
-
-// static
-void VideoDecodePerfHistory::BindRequest(
-    mojom::VideoDecodePerfHistoryRequest request) {
-  DVLOG(2) << __func__;
-
-  // Single static instance should serve all requests.
-  static VideoDecodePerfHistory* instance = new VideoDecodePerfHistory();
-
-  instance->BindRequestInternal(std::move(request));
-}
-
-VideoDecodePerfHistory::VideoDecodePerfHistory() {
+VideoDecodePerfHistory::VideoDecodePerfHistory(
+    std::unique_ptr<VideoDecodeStatsDBFactory> db_factory)
+    : db_factory_(std::move(db_factory)),
+      db_init_status_(UNINITIALIZED),
+      weak_ptr_factory_(this) {
   DVLOG(2) << __func__;
 }
 
@@ -42,55 +27,37 @@
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
 }
 
-void VideoDecodePerfHistory::BindRequestInternal(
+void VideoDecodePerfHistory::BindRequest(
     mojom::VideoDecodePerfHistoryRequest request) {
+  DVLOG(3) << __func__;
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   bindings_.AddBinding(this, std::move(request));
 }
 
-void VideoDecodePerfHistory::OnGotStatsEntry(
-    const VideoDecodeStatsDB::VideoDescKey& key,
-    GetPerfInfoCallback mojo_cb,
-    bool database_success,
-    std::unique_ptr<VideoDecodeStatsDB::DecodeStatsEntry> entry) {
+void VideoDecodePerfHistory::InitDatabase() {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
-  DCHECK(!mojo_cb.is_null());
 
-  bool is_power_efficient;
-  bool is_smooth;
-  double percent_dropped = 0;
+  if (db_init_status_ == PENDING)
+    return;
 
-  if (entry.get()) {
-    DCHECK(database_success);
-    percent_dropped =
-        static_cast<double>(entry->frames_dropped) / entry->frames_decoded;
+  db_ = db_factory_->CreateDB();
+  db_->Initialize(base::BindOnce(&VideoDecodePerfHistory::OnDatabaseInit,
+                                 weak_ptr_factory_.GetWeakPtr()));
+  db_init_status_ = PENDING;
+}
 
-    // TODO(chcunningham): add statistics for power efficiency to database.
-    is_power_efficient = true;
-    is_smooth = percent_dropped <= kMaxSmoothDroppedFramesPercent;
-  } else {
-    // TODO(chcunningham/mlamouri): Refactor database API to give us nearby
-    // entry entry whenever we don't have a perfect match. If higher
-    // resolutions/framerates are known to be smooth, we can report this as
-    // smooth. If lower resolutions/frames are known to be janky, we can assume
-    // this will be janky.
+void VideoDecodePerfHistory::OnDatabaseInit(bool success) {
+  DVLOG(2) << __func__ << " " << success;
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+  DCHECK_EQ(db_init_status_, PENDING);
 
-    // No entry? Lets be optimistic.
-    is_power_efficient = true;
-    is_smooth = true;
+  db_init_status_ = success ? COMPLETE : FAILED;
+
+  // Run all the deferred API calls as if they're just now coming in.
+  for (auto& deferred_call : init_deferred_api_calls_) {
+    std::move(deferred_call).Run();
   }
-
-  DVLOG(3) << __func__
-           << base::StringPrintf(" profile:%s size:%s fps:%d --> ",
-                                 GetProfileName(key.codec_profile).c_str(),
-                                 key.size.ToString().c_str(), key.frame_rate)
-           << (entry.get()
-                   ? base::StringPrintf(
-                         "smooth:%d frames_decoded:%" PRIu64 " pcnt_dropped:%f",
-                         is_smooth, entry->frames_decoded, percent_dropped)
-                   : (database_success ? "no info" : "query FAILED"));
-
-  std::move(mojo_cb).Run(is_smooth, is_power_efficient);
+  init_deferred_api_calls_.clear();
 }
 
 void VideoDecodePerfHistory::GetPerfInfo(VideoCodecProfile profile,
@@ -104,20 +71,132 @@
   DCHECK_GT(frame_rate, 0);
   DCHECK(natural_size.width() > 0 && natural_size.height() > 0);
 
-  // TODO(chcunningham): Make this an error condition once the database impl
-  // has landed. Hardcoding results for now.
-  if (!g_database) {
-    DVLOG(2) << __func__ << " No database! Assuming smooth/efficient perf.";
+  if (db_init_status_ == FAILED) {
+    // Optimistically claim perf is both smooth and power efficient.
     std::move(callback).Run(true, true);
     return;
   }
 
-  VideoDecodeStatsDB::VideoDescKey key(profile, natural_size, frame_rate);
+  // Defer this request until the DB is initialized.
+  if (db_init_status_ != COMPLETE) {
+    init_deferred_api_calls_.push_back(base::BindOnce(
+        &VideoDecodePerfHistory::GetPerfInfo, weak_ptr_factory_.GetWeakPtr(),
+        profile, natural_size, frame_rate, std::move(callback)));
+    InitDatabase();
+    return;
+  }
 
-  // Unretained is safe because this is a leaky singleton.
-  g_database->GetDecodeStats(
-      key, base::BindOnce(&VideoDecodePerfHistory::OnGotStatsEntry,
-                          base::Unretained(this), key, std::move(callback)));
+  VideoDecodeStatsDB::VideoDescKey video_key(profile, natural_size, frame_rate);
+
+  db_->GetDecodeStats(
+      video_key, base::BindOnce(&VideoDecodePerfHistory::OnGotStatsForRequest,
+                                weak_ptr_factory_.GetWeakPtr(), video_key,
+                                std::move(callback)));
+}
+
+void VideoDecodePerfHistory::OnGotStatsForRequest(
+    const VideoDecodeStatsDB::VideoDescKey& video_key,
+    GetPerfInfoCallback mojo_cb,
+    bool database_success,
+    std::unique_ptr<VideoDecodeStatsDB::DecodeStatsEntry> stats) {
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+  DCHECK(!mojo_cb.is_null());
+  DCHECK_EQ(db_init_status_, COMPLETE);
+
+  bool is_power_efficient;
+  bool is_smooth;
+  double percent_dropped = 0;
+
+  if (stats) {
+    DCHECK(database_success);
+    percent_dropped =
+        static_cast<double>(stats->frames_dropped) / stats->frames_decoded;
+
+    // TODO(chcunningham): add statistics for power efficiency to database.
+    is_power_efficient = true;
+    is_smooth = percent_dropped <= kMaxSmoothDroppedFramesPercent;
+  } else {
+    // TODO(chcunningham/mlamouri): Refactor database API to give us nearby
+    // stats whenever we don't have a perfect match. If higher
+    // resolutions/frame rates are known to be smooth, we can report this as
+    /// smooth. If lower resolutions/frames are known to be janky, we can assume
+    // this will be janky.
+
+    // No stats? Lets be optimistic.
+    is_power_efficient = true;
+    is_smooth = true;
+  }
+
+  DVLOG(3) << __func__
+           << base::StringPrintf(
+                  " profile:%s size:%s fps:%d --> ",
+                  GetProfileName(video_key.codec_profile).c_str(),
+                  video_key.size.ToString().c_str(), video_key.frame_rate)
+           << (stats.get()
+                   ? base::StringPrintf(
+                         "smooth:%d frames_decoded:%" PRIu64 " pcnt_dropped:%f",
+                         is_smooth, stats->frames_decoded, percent_dropped)
+                   : (database_success ? "no info" : "query FAILED"));
+
+  std::move(mojo_cb).Run(is_smooth, is_power_efficient);
+}
+
+void VideoDecodePerfHistory::SavePerfRecord(VideoCodecProfile profile,
+                                            const gfx::Size& natural_size,
+                                            int frame_rate,
+                                            uint32_t frames_decoded,
+                                            uint32_t frames_dropped) {
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+
+  if (db_init_status_ == FAILED) {
+    DVLOG(3) << __func__ << " Can't save stats. No DB!";
+    return;
+  }
+
+  // Defer this request until the DB is initialized.
+  if (db_init_status_ != COMPLETE) {
+    init_deferred_api_calls_.push_back(base::BindOnce(
+        &VideoDecodePerfHistory::SavePerfRecord, weak_ptr_factory_.GetWeakPtr(),
+        profile, natural_size, frame_rate, frames_decoded, frames_dropped));
+    InitDatabase();
+    return;
+  }
+
+  VideoDecodeStatsDB::VideoDescKey video_key(profile, natural_size, frame_rate);
+  VideoDecodeStatsDB::DecodeStatsEntry new_stats(frames_decoded,
+                                                 frames_dropped);
+
+  // Get past perf info and report UKM metrics before saving this record.
+  db_->GetDecodeStats(
+      video_key,
+      base::BindOnce(&VideoDecodePerfHistory::OnGotStatsForSave,
+                     weak_ptr_factory_.GetWeakPtr(), video_key, new_stats));
+}
+
+void VideoDecodePerfHistory::OnGotStatsForSave(
+    const VideoDecodeStatsDB::VideoDescKey& video_key,
+    const VideoDecodeStatsDB::DecodeStatsEntry& new_stats,
+    bool success,
+    std::unique_ptr<VideoDecodeStatsDB::DecodeStatsEntry> past_stats) {
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+  DCHECK_EQ(db_init_status_, COMPLETE);
+
+  if (!success) {
+    DVLOG(3) << __func__ << " FAILED! Aborting save.";
+    return;
+  }
+
+  ReportUkmMetrics(video_key, new_stats, past_stats.get());
+
+  db_->AppendDecodeStats(video_key, new_stats);
+}
+
+void VideoDecodePerfHistory::ReportUkmMetrics(
+    const VideoDecodeStatsDB::VideoDescKey& video_key,
+    const VideoDecodeStatsDB::DecodeStatsEntry& new_stats,
+    VideoDecodeStatsDB::DecodeStatsEntry* past_stats) {
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+  // TODO(chcunningham): Report metrics.
 }
 
 }  // namespace media
diff --git a/media/mojo/services/video_decode_perf_history.h b/media/mojo/services/video_decode_perf_history.h
index 1b3db8d..92a923ea 100644
--- a/media/mojo/services/video_decode_perf_history.h
+++ b/media/mojo/services/video_decode_perf_history.h
@@ -7,10 +7,12 @@
 
 #include <stdint.h>
 #include <memory>
+#include <queue>
 #include <string>
 
 #include "base/callback.h"
 #include "base/sequence_checker.h"
+#include "base/supports_user_data.h"
 #include "media/base/video_codecs.h"
 #include "media/mojo/interfaces/video_decode_perf_history.mojom.h"
 #include "media/mojo/services/media_mojo_export.h"
@@ -20,29 +22,37 @@
 
 namespace media {
 
-// This browser-process service helps render-process clients respond to
-// MediaCapabilities queries by looking up past performance for a given video
-// configuration.
+// This class saves and retrieves video decode performance statistics on behalf
+// of the MediaCapabilities API. It also helps to grade the accuracy of the API
+// by comparing its history-based assessment of smoothness/power-efficiency to
+// the observed performance as new stats are saved.
 //
-// Smoothness and power efficiency are assessed by evaluating raw stats from the
-// MediaCapabilitiesDatabse.
+// The database is lazily initialized/loaded upon the first API call requiring
+// DB access. DB implementations must take care to perform work on a separate
+// task runner.
 //
-// The object is lazily created upon the first call to BindRequest(). Future
-// calls will bind to the same instance.
+// Retrieving stats is triggered by calls to the GetPerfInfo() Mojo interface.
+// The raw values are reduced to booleans (is_smooth, is_power_efficient) which
+// are sent along the Mojo callback.
 //
-// This class is not thread safe. All calls to BindRequest() and GetPerfInfo()
-// should be made on the same sequence (generally stemming from inbound Mojo
-// IPCs on the browser IO sequence).
+// Saving stats is performed by SavePerfRecord(), where a record is defined as a
+// continuous playback of a stream with fixed decode characteristics (profile,
+// natural size, frame rate).
+//
+// THREAD SAFETY:
+// This class is not thread safe. All API calls should be made on the same
+// sequence.
 class MEDIA_MOJO_EXPORT VideoDecodePerfHistory
-    : public mojom::VideoDecodePerfHistory {
+    : public mojom::VideoDecodePerfHistory,
+      public base::SupportsUserData::Data {
  public:
-  // Provides |db_instance| for use once VideoDecodePerfHistory is lazily (upon
-  // first BindRequest) instantiated. Database lifetime should match/exceed that
-  // of the VideoDecodePerfHistory singleton.
-  static void Initialize(VideoDecodeStatsDB* db_instance);
+  explicit VideoDecodePerfHistory(
+      std::unique_ptr<VideoDecodeStatsDBFactory> db_factory);
+  ~VideoDecodePerfHistory() override;
 
-  // Bind the request to singleton instance.
-  static void BindRequest(mojom::VideoDecodePerfHistoryRequest request);
+  // Bind the mojo request to this instance. Single instance will be used to
+  // serve multiple requests.
+  void BindRequest(mojom::VideoDecodePerfHistoryRequest request);
 
   // mojom::VideoDecodePerfHistory implementation:
   void GetPerfInfo(VideoCodecProfile profile,
@@ -50,28 +60,73 @@
                    int frame_rate,
                    GetPerfInfoCallback callback) override;
 
+  // Save a record of the given performance stats for the described stream.
+  void SavePerfRecord(VideoCodecProfile profile,
+                      const gfx::Size& natural_size,
+                      int frame_rate,
+                      uint32_t frames_decoded,
+                      uint32_t frames_dropped);
+
  private:
-  // Friends so it can create its own instances with mock database.
   friend class VideoDecodePerfHistoryTest;
 
+  // Track the status of database lazily initialization.
+  enum InitStatus {
+    UNINITIALIZED,
+    PENDING,
+    COMPLETE,
+    FAILED,
+  };
+
   // Decode capabilities will be described as "smooth" whenever the percentage
   // of dropped frames is less-than-or-equal-to this value. 10% chosen as a
   // lenient value after manual testing.
   static constexpr double kMaxSmoothDroppedFramesPercent = .10;
 
-  VideoDecodePerfHistory();
-  ~VideoDecodePerfHistory() override;
+  // Create and initialize the database.
+  void InitDatabase();
 
-  // Binds |request| to this instance.
-  void BindRequestInternal(mojom::VideoDecodePerfHistoryRequest request);
+  // Callback from |db_->Initialize()|.
+  void OnDatabaseInit(bool success);
 
-  // Internal callback for |database_| queries. Will assess performance history
-  // from database and pass results on to |mojo_cb|.
-  void OnGotStatsEntry(
-      const VideoDecodeStatsDB::VideoDescKey& key,
+  // Internal callback for database queries made from GetPerfInfo() (mojo API).
+  // Assesses performance from database stats and passes results to |mojo_cb|.
+  void OnGotStatsForRequest(
+      const VideoDecodeStatsDB::VideoDescKey& video_key,
       GetPerfInfoCallback mojo_cb,
       bool database_success,
-      std::unique_ptr<VideoDecodeStatsDB::DecodeStatsEntry> entry);
+      std::unique_ptr<VideoDecodeStatsDB::DecodeStatsEntry> stats);
+
+  // Internal callback for database queries made from SavePerfRecord(). Compares
+  // past performance to this latest record as means of "grading" the accuracy
+  // of the GetPerfInfo() API. Comparison is recorded via UKM. Then saves the
+  // |new_*| performance stats to the database.
+  void OnGotStatsForSave(
+      const VideoDecodeStatsDB::VideoDescKey& video_key,
+      const VideoDecodeStatsDB::DecodeStatsEntry& new_stats,
+      bool success,
+      std::unique_ptr<VideoDecodeStatsDB::DecodeStatsEntry> past_stats);
+
+  // Report UKM metrics to grade the claims of the API by evaluating how well
+  // |past_stats| predicts |new_stats|.
+  void ReportUkmMetrics(const VideoDecodeStatsDB::VideoDescKey& video_key,
+                        const VideoDecodeStatsDB::DecodeStatsEntry& new_stats,
+                        VideoDecodeStatsDB::DecodeStatsEntry* past_stats);
+
+  // Factory for creating |db_|.
+  std::unique_ptr<VideoDecodeStatsDBFactory> db_factory_;
+
+  // Tracks whether we've received OnDatabaseIniti() callback. All database
+  // operations should be deferred until initialization is complete.
+  InitStatus db_init_status_;
+
+  // Database helper for managing/coalescing decode stats.
+  // TODO(chcunningham): tear down |db_| if idle for extended period.
+  std::unique_ptr<VideoDecodeStatsDB> db_;
+
+  // Vector of bound public API calls, to be run once DB initialization
+  // completes.
+  std::vector<base::OnceClosure> init_deferred_api_calls_;
 
   // Maps bindings from several render-processes to this single browser-process
   // service.
@@ -80,6 +135,8 @@
   // Ensures all access to class members come on the same sequence.
   SEQUENCE_CHECKER(sequence_checker_);
 
+  base::WeakPtrFactory<VideoDecodePerfHistory> weak_ptr_factory_;
+
   DISALLOW_COPY_AND_ASSIGN(VideoDecodePerfHistory);
 };
 
diff --git a/media/mojo/services/video_decode_perf_history_unittest.cc b/media/mojo/services/video_decode_perf_history_unittest.cc
index a946aa8..57d67e4 100644
--- a/media/mojo/services/video_decode_perf_history_unittest.cc
+++ b/media/mojo/services/video_decode_perf_history_unittest.cc
@@ -3,10 +3,13 @@
 // found in the LICENSE file.
 
 #include <map>
-#include <sstream>
 #include <string>
 
 #include "base/memory/ptr_util.h"
+#include "base/run_loop.h"
+#include "base/strings/stringprintf.h"
+#include "base/task_scheduler/post_task.h"
+#include "base/test/scoped_task_environment.h"
 #include "media/mojo/services/video_decode_perf_history.h"
 #include "media/mojo/services/video_decode_stats_db.h"
 #include "testing/gmock/include/gmock/gmock.h"
@@ -14,23 +17,37 @@
 
 namespace media {
 
+// Aliases for readability.
+const bool kIsSmooth = true;
+const bool kIsNotSmooth = false;
+const bool kIsPowerEfficient = true;
+
 class FakeVideoDecodeStatsDB : public VideoDecodeStatsDB {
  public:
   FakeVideoDecodeStatsDB() = default;
   ~FakeVideoDecodeStatsDB() override {}
 
+  // Call CompleteInitialize(...) to run |init_cb| callback.
+  void Initialize(base::OnceCallback<void(bool)> init_cb) override {
+    pendnding_init_cb_ = std::move(init_cb);
+  }
+
+  // Completes fake initialization, running |init_cb| with the supplied value
+  // for success.
+  void CompleteInitialize(bool success) {
+    std::move(pendnding_init_cb_).Run(success);
+  }
+
   void AppendDecodeStats(const VideoDescKey& key,
-                         const DecodeStatsEntry& entry) override {
+                         const DecodeStatsEntry& new_entry) override {
     std::string key_str = MakeKeyString(key);
     if (entries_.find(key_str) == entries_.end()) {
-      entries_.emplace(std::make_pair(key_str, entry));
+      entries_.emplace(std::make_pair(key_str, new_entry));
     } else {
       const DecodeStatsEntry& known_entry = entries_.at(key_str);
-      uint32_t frames_decoded =
-          known_entry.frames_decoded + known_entry.frames_decoded;
-      uint32_t frames_dropped =
-          known_entry.frames_dropped + known_entry.frames_dropped;
-      entries_.at(key_str) = DecodeStatsEntry(frames_decoded, frames_dropped);
+      entries_.at(key_str) = DecodeStatsEntry(
+          known_entry.frames_decoded + new_entry.frames_decoded,
+          known_entry.frames_dropped + new_entry.frames_dropped);
     }
   }
 
@@ -47,32 +64,62 @@
 
  private:
   static std::string MakeKeyString(const VideoDescKey& key) {
-    std::stringstream ss;
-    ss << key.codec_profile << "|" << key.size.ToString() << "|"
-       << key.frame_rate;
-    return ss.str();
+    return base::StringPrintf("%d|%s|%d", static_cast<int>(key.codec_profile),
+                              key.size.ToString().c_str(), key.frame_rate);
   }
 
   std::map<std::string, DecodeStatsEntry> entries_;
+
+  base::OnceCallback<void(bool)> pendnding_init_cb_;
 };
 
-class VideoDecodePerfHistoryTest : public ::testing::Test {
+// Simple factory that always returns the pointer its given. The lifetime of
+// |db| is managed by the CreateDB() caller.
+class FakeVideoDecodeStatsDBFactory : public VideoDecodeStatsDBFactory {
+ public:
+  FakeVideoDecodeStatsDBFactory(FakeVideoDecodeStatsDB* db) : db_(db) {}
+  ~FakeVideoDecodeStatsDBFactory() override = default;
+
+  std::unique_ptr<VideoDecodeStatsDB> CreateDB() override {
+    return std::unique_ptr<VideoDecodeStatsDB>(db_);
+  }
+
+ private:
+  FakeVideoDecodeStatsDB* db_;
+};
+
+// When bool param is true, tests should wait until the end to run
+// database_->CompleteInitialize(). Otherwise run CompleteInitialize() at the
+// test start.
+class VideoDecodePerfHistoryTest : public testing::TestWithParam<bool> {
  public:
   void SetUp() override {
-    // Sniff the database pointer so tests can inject entries.
-    database_ = base::MakeUnique<FakeVideoDecodeStatsDB>();
-    VideoDecodePerfHistory::Initialize(database_.get());
+    // Sniff the database pointer so tests can inject entries. The factory will
+    // return this pointer when requested by VideoDecodePerfHistory.
+    database_ = new FakeVideoDecodeStatsDB();
 
     // Make tests hermetic by creating a new instance. Cannot use unique_ptr
     // here because the constructor/destructor are private and only accessible
     // to this test via friending.
-    perf_history_ = new VideoDecodePerfHistory();
+    perf_history_ = new VideoDecodePerfHistory(
+        std::make_unique<FakeVideoDecodeStatsDBFactory>(database_));
   }
 
   void TearDown() override {
     // Avoid leaking between tests.
     delete perf_history_;
     perf_history_ = nullptr;
+
+    // |perf_history_| owns the |database_| and will delete it.
+    database_ = nullptr;
+  }
+
+  void PreInitializeDB(bool initialize_success) {
+    // Invoke private method to start initialization. Usually invoked by first
+    // API call requiring DB access.
+    perf_history_->InitDatabase();
+    // Complete initialization by firing callback from our fake DB.
+    database_->CompleteInitialize(initialize_success);
   }
 
   // Tests may set this as the callback for VideoDecodePerfHistory::GetPerfInfo
@@ -87,16 +134,28 @@
   static constexpr double kMaxSmoothDroppedFramesPercent =
       VideoDecodePerfHistory::kMaxSmoothDroppedFramesPercent;
 
+  base::test::ScopedTaskEnvironment scoped_task_environment_;
+
   // The VideoDecodeStatsReporter being tested.
   VideoDecodePerfHistory* perf_history_;
 
   // The database |perf_history_| uses to store/query performance stats.
-  std::unique_ptr<FakeVideoDecodeStatsDB> database_;
+  FakeVideoDecodeStatsDB* database_;
 };
 
-TEST_F(VideoDecodePerfHistoryTest, GetPerfInfo_Smooth) {
-  // Prepare database with 2 entries. The second entry has a higher framerate
-  // and a higher number of dropped frames such that it is "not smooth".
+TEST_P(VideoDecodePerfHistoryTest, GetPerfInfo_Smooth) {
+  // NOTE: The when the DB initialization is deferred, All EXPECT_CALLs are then
+  // delayed until we db_->CompleteInitialize(). testing::InSequence enforces
+  // that EXPECT_CALLs arrive in top-to-bottom order.
+  bool defer_initialize = GetParam();
+  testing::InSequence dummy;
+
+  // Complete initialization in advance of API calls when not asked to defer.
+  if (!defer_initialize)
+    PreInitializeDB(/* success */ true);
+
+  // First add 2 records to the history. The second record has a higher frame
+  // rate and a higher number of dropped frames such that it is "not smooth".
   const VideoCodecProfile kKnownProfile = VP9PROFILE_PROFILE0;
   const gfx::Size kKownSize(100, 200);
   const int kSmoothFrameRate = 30;
@@ -110,25 +169,20 @@
       kFramesDecoded * kMaxSmoothDroppedFramesPercent + 1;
 
   // Add the entries.
-  database_->AppendDecodeStats(
-      VideoDescKey(kKnownProfile, kKownSize, kSmoothFrameRate),
-      DecodeStatsEntry(kFramesDecoded, kSmoothFramesDropped));
-  database_->AppendDecodeStats(
-      VideoDescKey(kKnownProfile, kKownSize, kNotSmoothFrameRate),
-      DecodeStatsEntry(kFramesDecoded, kNotSmoothFramesDropped));
+  perf_history_->SavePerfRecord(kKnownProfile, kKownSize, kSmoothFrameRate,
+                                kFramesDecoded, kSmoothFramesDropped);
+  perf_history_->SavePerfRecord(kKnownProfile, kKownSize, kNotSmoothFrameRate,
+                                kFramesDecoded, kNotSmoothFramesDropped);
 
   // Verify perf history returns is_smooth = true for the smooth entry.
-  bool is_smooth = true;
-  bool is_power_efficient = true;
-  EXPECT_CALL(*this, MockGetPerfInfoCB(is_smooth, is_power_efficient));
+  EXPECT_CALL(*this, MockGetPerfInfoCB(kIsSmooth, kIsPowerEfficient));
   perf_history_->GetPerfInfo(
       kKnownProfile, kKownSize, kSmoothFrameRate,
       base::BindOnce(&VideoDecodePerfHistoryTest::MockGetPerfInfoCB,
                      base::Unretained(this)));
 
   // Verify perf history returns is_smooth = false for the NOT smooth entry.
-  is_smooth = false;
-  EXPECT_CALL(*this, MockGetPerfInfoCB(is_smooth, is_power_efficient));
+  EXPECT_CALL(*this, MockGetPerfInfoCB(kIsNotSmooth, kIsPowerEfficient));
   perf_history_->GetPerfInfo(
       kKnownProfile, kKownSize, kNotSmoothFrameRate,
       base::BindOnce(&VideoDecodePerfHistoryTest::MockGetPerfInfoCB,
@@ -137,12 +191,54 @@
   // Verify perf history optimistically returns is_smooth = true when no entry
   // can be found with the given configuration.
   const VideoCodecProfile kUnknownProfile = VP9PROFILE_PROFILE2;
-  is_smooth = true;
-  EXPECT_CALL(*this, MockGetPerfInfoCB(is_smooth, is_power_efficient));
+  EXPECT_CALL(*this, MockGetPerfInfoCB(kIsSmooth, kIsPowerEfficient));
   perf_history_->GetPerfInfo(
       kUnknownProfile, kKownSize, kNotSmoothFrameRate,
       base::BindOnce(&VideoDecodePerfHistoryTest::MockGetPerfInfoCB,
                      base::Unretained(this)));
+
+  // Complete successful deferred DB initialization (see comment at top of test)
+  if (defer_initialize) {
+    database_->CompleteInitialize(true);
+
+    // Allow initialize-deferred API calls to complete.
+    base::RunLoop run_loop;
+    base::PostTask(FROM_HERE, base::BindOnce(run_loop.QuitWhenIdleClosure()));
+    run_loop.Run();
+  }
 }
 
+TEST_P(VideoDecodePerfHistoryTest, GetPerfInfo_FailedInitialize) {
+  bool defer_initialize = GetParam();
+  // Fail initialization in advance of API calls when not asked to defer.
+  if (!defer_initialize)
+    PreInitializeDB(/* success */ false);
+
+  const VideoCodecProfile kProfile = VP9PROFILE_PROFILE0;
+  const gfx::Size kSize(100, 200);
+  const int kFrameRate = 30;
+
+  // When initialization fails, callback should optimistically claim both smooth
+  // and power efficient performance.
+  EXPECT_CALL(*this, MockGetPerfInfoCB(kIsSmooth, kIsPowerEfficient));
+  perf_history_->GetPerfInfo(
+      kProfile, kSize, kFrameRate,
+      base::BindOnce(&VideoDecodePerfHistoryTest::MockGetPerfInfoCB,
+                     base::Unretained(this)));
+
+  // Fail deferred DB initialization (see comment at top of test).
+  if (defer_initialize) {
+    database_->CompleteInitialize(false);
+
+    // Allow initialize-deferred API calls to complete.
+    base::RunLoop run_loop;
+    base::PostTask(FROM_HERE, base::BindOnce(run_loop.QuitWhenIdleClosure()));
+    run_loop.Run();
+  }
+}
+
+INSTANTIATE_TEST_CASE_P(VaryDBInitTiming,
+                        VideoDecodePerfHistoryTest,
+                        ::testing::Values(true, false));
+
 }  // namespace media
diff --git a/media/mojo/services/video_decode_stats_db.h b/media/mojo/services/video_decode_stats_db.h
index 23900d46..86f6e32 100644
--- a/media/mojo/services/video_decode_stats_db.h
+++ b/media/mojo/services/video_decode_stats_db.h
@@ -40,6 +40,10 @@
 
   virtual ~VideoDecodeStatsDB() = default;
 
+  // Run asynchronous initialization of database. Initialization must complete
+  // before calling other APIs. |init_cb| must not be a null callback.
+  virtual void Initialize(base::OnceCallback<void(bool)> init_cb) = 0;
+
   // Appends `stats` to existing entry associated with `key`. Will create a new
   // entry if none exists. The operation is asynchronous. The caller should be
   // aware of potential race conditions when calling this method for the same
@@ -56,6 +60,13 @@
                               GetDecodeStatsCB callback) = 0;
 };
 
+// Factory interface to create a DB instance.
+class MEDIA_MOJO_EXPORT VideoDecodeStatsDBFactory {
+ public:
+  virtual ~VideoDecodeStatsDBFactory() {}
+  virtual std::unique_ptr<VideoDecodeStatsDB> CreateDB() = 0;
+};
+
 }  // namespace media
 
 #endif  // MEDIA_MOJO_SERVICES_VIDEO_DECODE_STATS_DB_H_
diff --git a/media/mojo/services/video_decode_stats_db_impl.cc b/media/mojo/services/video_decode_stats_db_impl.cc
index 3363ac5..ace8ef2 100644
--- a/media/mojo/services/video_decode_stats_db_impl.cc
+++ b/media/mojo/services/video_decode_stats_db_impl.cc
@@ -43,30 +43,62 @@
 
 };  // namespace
 
-VideoDecodeStatsDBImpl::VideoDecodeStatsDBImpl() : weak_ptr_factory_(this) {}
+VideoDecodeStatsDBImplFactory::VideoDecodeStatsDBImplFactory(
+    base::FilePath db_dir)
+    : db_dir_(db_dir) {
+  DVLOG(2) << __func__ << " db_dir:" << db_dir_;
+}
+
+VideoDecodeStatsDBImplFactory::~VideoDecodeStatsDBImplFactory() = default;
+
+std::unique_ptr<VideoDecodeStatsDB> VideoDecodeStatsDBImplFactory::CreateDB() {
+  std::unique_ptr<leveldb_proto::ProtoDatabase<DecodeStatsProto>> db_;
+
+  auto inner_db =
+      std::make_unique<leveldb_proto::ProtoDatabaseImpl<DecodeStatsProto>>(
+          base::CreateSequencedTaskRunnerWithTraits(
+              {base::MayBlock(), base::TaskPriority::BACKGROUND,
+               base::TaskShutdownBehavior::CONTINUE_ON_SHUTDOWN}));
+
+  // Temporarily disallow writing to the DB until we've enabled clearing via
+  // chrome://settings/clearBrowserData
+  bool allow_writes = false;
+
+  return std::make_unique<VideoDecodeStatsDBImpl>(std::move(inner_db), db_dir_,
+                                                  allow_writes);
+}
+
+VideoDecodeStatsDBImpl::VideoDecodeStatsDBImpl(
+    std::unique_ptr<leveldb_proto::ProtoDatabase<DecodeStatsProto>> db,
+    const base::FilePath& db_dir,
+    bool allow_writes)
+    : db_(std::move(db)),
+      db_dir_(db_dir),
+      allow_writes_(allow_writes),
+      weak_ptr_factory_(this) {
+  DCHECK(db_);
+  DCHECK(!db_dir_.empty());
+}
 
 VideoDecodeStatsDBImpl::~VideoDecodeStatsDBImpl() {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
 }
 
 void VideoDecodeStatsDBImpl::Initialize(
-    std::unique_ptr<leveldb_proto::ProtoDatabase<DecodeStatsProto>> db,
-    const base::FilePath& dir) {
-  DCHECK(db.get());
+    base::OnceCallback<void(bool)> init_cb) {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
-
-  db_ = std::move(db);
-
+  DCHECK(init_cb);
   // "Simple options" will use the default global cache of 8MB. In the worst
   // case our whole DB will be less than 35K, so we aren't worried about
   // spamming the cache.
   // TODO(chcunningham): Keep an eye on the size as the table evolves.
-  db_->Init(kDatabaseClientName, dir, leveldb_proto::CreateSimpleOptions(),
+  db_->Init(kDatabaseClientName, db_dir_, leveldb_proto::CreateSimpleOptions(),
             base::BindOnce(&VideoDecodeStatsDBImpl::OnInit,
-                           weak_ptr_factory_.GetWeakPtr()));
+                           weak_ptr_factory_.GetWeakPtr(), std::move(init_cb)));
 }
 
-void VideoDecodeStatsDBImpl::OnInit(bool success) {
+void VideoDecodeStatsDBImpl::OnInit(base::OnceCallback<void(bool)> init_cb,
+                                    bool success) {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   DVLOG(2) << __func__ << (success ? " succeeded" : " FAILED!");
 
@@ -76,25 +108,19 @@
   // TODO(chcunningham): Record UMA.
   if (!success)
     db_.reset();
+
+  std::move(init_cb).Run(success);
 }
 
-bool VideoDecodeStatsDBImpl::IsDatabaseReady(const std::string& operation) {
-  if (!db_init_ || !db_) {
-    DVLOG_IF(2, !operation.empty()) << __func__ << " DB is not initialized; "
-                                    << "ignoring operation: " << operation;
-    return false;
-  }
-
-  return true;
+bool VideoDecodeStatsDBImpl::IsInitialized() {
+  // |db_| will be null if Initialization failed.
+  return db_init_ && db_;
 }
 
 void VideoDecodeStatsDBImpl::AppendDecodeStats(const VideoDescKey& key,
                                                const DecodeStatsEntry& entry) {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
-
-  if (!IsDatabaseReady("AppendDecodeStats")) {
-    return;
-  }
+  DCHECK(IsInitialized());
 
   DVLOG(3) << __func__ << " Reading key " << KeyToString(key)
            << " from DB with intent to update with " << EntryToString(entry);
@@ -107,11 +133,7 @@
 void VideoDecodeStatsDBImpl::GetDecodeStats(const VideoDescKey& key,
                                             GetDecodeStatsCB callback) {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
-
-  if (!IsDatabaseReady("GetDecodeStats")) {
-    std::move(callback).Run(false, nullptr);
-    return;
-  }
+  DCHECK(IsInitialized());
 
   db_->GetEntry(
       SerializeKey(key),
@@ -125,6 +147,13 @@
     bool read_success,
     std::unique_ptr<DecodeStatsProto> prev_stats_proto) {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+  DCHECK(IsInitialized());
+
+  // TODO(chcunningham): Always allow writes once the DB can be cleared.
+  if (!allow_writes_) {
+    DVLOG(3) << __func__ << " IGNORING WRITE - writes not allowed";
+    return;
+  }
 
   // TODO(chcunningham): Record UMA.
   if (!read_success) {
@@ -133,8 +162,6 @@
     return;
   }
 
-  DCHECK(IsDatabaseReady("WriteUpdatedEntry"));
-
   if (!prev_stats_proto) {
     prev_stats_proto.reset(new DecodeStatsProto());
     prev_stats_proto->set_frames_decoded(0);
diff --git a/media/mojo/services/video_decode_stats_db_impl.h b/media/mojo/services/video_decode_stats_db_impl.h
index 92b545f..60008ec 100644
--- a/media/mojo/services/video_decode_stats_db_impl.h
+++ b/media/mojo/services/video_decode_stats_db_impl.h
@@ -7,6 +7,7 @@
 
 #include <memory>
 
+#include "base/files/file_path.h"
 #include "base/memory/weak_ptr.h"
 #include "components/leveldb_proto/proto_database.h"
 #include "media/base/video_codecs.h"
@@ -22,23 +23,41 @@
 
 class DecodeStatsProto;
 
+// Factory interface to create a DB instance.
+class MEDIA_MOJO_EXPORT VideoDecodeStatsDBImplFactory
+    : public VideoDecodeStatsDBFactory {
+ public:
+  explicit VideoDecodeStatsDBImplFactory(base::FilePath db_dir);
+  ~VideoDecodeStatsDBImplFactory() override;
+  std::unique_ptr<VideoDecodeStatsDB> CreateDB() override;
+
+ private:
+  base::FilePath db_dir_;
+
+  DISALLOW_COPY_AND_ASSIGN(VideoDecodeStatsDBImplFactory);
+};
+
 // LevelDB implementation of VideoDecodeStatsDB. This class is not
 // thread safe. All API calls should happen on the same sequence used for
 // construction. API callbacks will also occur on this sequence.
 class MEDIA_MOJO_EXPORT VideoDecodeStatsDBImpl : public VideoDecodeStatsDB {
  public:
-  VideoDecodeStatsDBImpl();
-  ~VideoDecodeStatsDBImpl() override;
-
+  // Constructs the database. NOTE: must call Initialize() before using.
   // |db| injects the level_db database instance for storing capabilities info.
   // |dir| specifies where to store LevelDB files to disk. LevelDB generates a
   // handful of files, so its recommended to provide a dedicated directory to
   // keep them isolated.
-  void Initialize(
+  // |allow_writes| determines whether DB write operations will be allowed. This
+  // is a temporary mechanism to disable writes in production until we've added
+  // the ability to clear the database via chrome://settings/clearBrowserData.
+  VideoDecodeStatsDBImpl(
       std::unique_ptr<leveldb_proto::ProtoDatabase<DecodeStatsProto>> db,
-      const base::FilePath& dir);
+      const base::FilePath& dir,
+      bool allow_writes);
+  ~VideoDecodeStatsDBImpl() override;
 
-  // See header for VideoDecodeStatsDB.
+  // Implement VideoDecodeStatsDB.
+  void Initialize(base::OnceCallback<void(bool)> init_cb) override;
   void AppendDecodeStats(const VideoDescKey& key,
                          const DecodeStatsEntry& entry) override;
   void GetDecodeStats(const VideoDescKey& key,
@@ -47,12 +66,12 @@
  private:
   friend class VideoDecodeStatsDBTest;
 
-  // Called when the database has been initialized.
-  void OnInit(bool success);
+  // Called when the database has been initialized. Will immediately call
+  // |init_cb| to forward |success|.
+  void OnInit(base::OnceCallback<void(bool)> init_cb, bool success);
 
-  // Returns true if the DB is initialized and ready for use. The optional
-  // |operation| is used to issue log warnings when the DB is not ready.
-  bool IsDatabaseReady(const std::string& operation = "");
+  // Returns true if the DB is successfully initialized.
+  bool IsInitialized();
 
   // Passed as the callback for |OnGotDecodeStats| by |AppendDecodeStats| to
   // update the database once we've read the existing stats entry.
@@ -81,6 +100,14 @@
   // encountered.
   std::unique_ptr<leveldb_proto::ProtoDatabase<DecodeStatsProto>> db_;
 
+  // Directory where levelDB should store database files.
+  base::FilePath db_dir_;
+
+  // Determines whether DB write operations will be allowed. This is a temporary
+  // mechanism to disable writes in production until we've added the ability to
+  // clear the database via chrome://settings/clearBrowserData.
+  bool allow_writes_;
+
   // Ensures all access to class members come on the same sequence. API calls
   // and callbacks should occur on the same sequence used during construction.
   // LevelDB operations happen on a separate task runner, but all LevelDB
diff --git a/media/mojo/services/video_decode_stats_db_unittest.cc b/media/mojo/services/video_decode_stats_db_unittest.cc
index ca3ae05..cdb06f1 100644
--- a/media/mojo/services/video_decode_stats_db_unittest.cc
+++ b/media/mojo/services/video_decode_stats_db_unittest.cc
@@ -7,7 +7,6 @@
 #include "base/bind.h"
 #include "base/bind_helpers.h"
 #include "base/files/file_path.h"
-#include "base/files/scoped_temp_dir.h"
 #include "base/logging.h"
 #include "base/memory/ptr_util.h"
 #include "base/test/scoped_task_environment.h"
@@ -39,10 +38,14 @@
     fake_db_ = new FakeDB<DecodeStatsProto>(fake_db_map_.get());
 
     // Make our DB wrapper and kick off Initialize. Each test should start
-    // by completing initialize, calling fake_db_->InitCallback(...).
-    stats_db_ = std::make_unique<VideoDecodeStatsDBImpl>();
-    stats_db_->Initialize(std::unique_ptr<FakeDB<DecodeStatsProto>>(fake_db_),
-                          base::FilePath(FILE_PATH_LITERAL("/fake/path")));
+    // by completing initialize, calling fake_db_->InitCallback(...) and
+    // verifying the callback argument.
+    stats_db_ = std::make_unique<VideoDecodeStatsDBImpl>(
+        std::unique_ptr<FakeDB<DecodeStatsProto>>(fake_db_),
+        base::FilePath(FILE_PATH_LITERAL("/fake/path")),
+        true /* allow_writes */);
+    stats_db_->Initialize(base::BindOnce(
+        &VideoDecodeStatsDBImplTest::OnInitialize, base::Unretained(this)));
   }
 
   void TearDown() override {
@@ -57,6 +60,8 @@
     MockGetDecodeStatsCb(success, entry.get());
   }
 
+  MOCK_METHOD1(OnInitialize, void(bool success));
+
   MOCK_METHOD2(MockGetDecodeStatsCb,
                void(bool success, VideoDecodeStatsDB::DecodeStatsEntry* entry));
 
@@ -86,6 +91,7 @@
 }
 
 TEST_F(VideoDecodeStatsDBImplTest, ReadExpectingNothing) {
+  EXPECT_CALL(*this, OnInitialize(true));
   fake_db_->InitCallback(true);
 
   VideoDescKey entry(VP9PROFILE_PROFILE3, gfx::Size(1024, 768), 60);
@@ -100,6 +106,7 @@
 }
 
 TEST_F(VideoDecodeStatsDBImplTest, WriteAndRead) {
+  EXPECT_CALL(*this, OnInitialize(true));
   fake_db_->InitCallback(true);
 
   VideoDescKey key(VP9PROFILE_PROFILE3, gfx::Size(1024, 768), 60);
@@ -128,18 +135,4 @@
   fake_db_->GetCallback(true);
 }
 
-TEST_F(VideoDecodeStatsDBImplTest, GetDecodeStatsDbNotInitialized) {
-  // Simulate failed/forgotten initialization.
-  fake_db_->InitCallback(false);
-
-  VideoDescKey key(VP9PROFILE_PROFILE3, gfx::Size(1024, 768), 60);
-  EXPECT_CALL(*this, MockGetDecodeStatsCb(false, nullptr));
-  // Note that no |fake_db_| is not instructed to execute the GetCallback(...).
-  // The DB is not initialized, so the callback is executed (failed) early
-  // without consulting the DB.
-  stats_db_->GetDecodeStats(
-      key, base::BindOnce(&VideoDecodeStatsDBImplTest::GetDecodeStatsCb,
-                          base::Unretained(this)));
-}
-
 }  // namespace media
diff --git a/media/mojo/services/video_decode_stats_recorder.cc b/media/mojo/services/video_decode_stats_recorder.cc
index 79ffce87..5fb2817 100644
--- a/media/mojo/services/video_decode_stats_recorder.cc
+++ b/media/mojo/services/video_decode_stats_recorder.cc
@@ -4,12 +4,19 @@
 
 #include "media/mojo/services/video_decode_stats_recorder.h"
 #include "base/memory/ptr_util.h"
+#include "media/mojo/services/video_decode_perf_history.h"
 #include "mojo/public/cpp/bindings/strong_binding.h"
 
 #include "base/logging.h"
 
 namespace media {
 
+VideoDecodeStatsRecorder::VideoDecodeStatsRecorder(
+    VideoDecodePerfHistory* perf_history)
+    : perf_history_(perf_history) {
+  DCHECK(perf_history_);
+}
+
 VideoDecodeStatsRecorder::~VideoDecodeStatsRecorder() {
   DVLOG(2) << __func__ << " Finalize for IPC disconnect";
   FinalizeRecord();
@@ -17,9 +24,11 @@
 
 // static
 void VideoDecodeStatsRecorder::Create(
+    VideoDecodePerfHistory* perf_history,
     mojom::VideoDecodeStatsRecorderRequest request) {
-  mojo::MakeStrongBinding(base::MakeUnique<VideoDecodeStatsRecorder>(),
-                          std::move(request));
+  mojo::MakeStrongBinding(
+      base::MakeUnique<VideoDecodeStatsRecorder>(perf_history),
+      std::move(request));
 }
 
 void VideoDecodeStatsRecorder::StartNewRecord(VideoCodecProfile profile,
@@ -64,7 +73,8 @@
            << " size:" << natural_size_.ToString() << " fps:" << frames_per_sec_
            << " decoded:" << frames_decoded_ << " dropped:" << frames_dropped_;
 
-  // TODO(chcunningham): Save everything to DB.
+  perf_history_->SavePerfRecord(profile_, natural_size_, frames_per_sec_,
+                                frames_decoded_, frames_dropped_);
 }
 
 }  // namespace media
\ No newline at end of file
diff --git a/media/mojo/services/video_decode_stats_recorder.h b/media/mojo/services/video_decode_stats_recorder.h
index a5ff531..f267fc51 100644
--- a/media/mojo/services/video_decode_stats_recorder.h
+++ b/media/mojo/services/video_decode_stats_recorder.h
@@ -16,14 +16,21 @@
 
 namespace media {
 
+class VideoDecodePerfHistory;
+
 // See mojom::VideoDecodeStatsRecorder for documentation.
 class MEDIA_MOJO_EXPORT VideoDecodeStatsRecorder
     : public mojom::VideoDecodeStatsRecorder {
  public:
-  VideoDecodeStatsRecorder() = default;
+  // See Create().
+  explicit VideoDecodeStatsRecorder(VideoDecodePerfHistory* perf_history);
+
   ~VideoDecodeStatsRecorder() override;
 
-  static void Create(mojom::VideoDecodeStatsRecorderRequest request);
+  // |perf_history| required to save decode stats to local database and report
+  // metrics. Callers must ensure that |perf_history| outlives this object.
+  static void Create(VideoDecodePerfHistory* perf_history,
+                     mojom::VideoDecodeStatsRecorderRequest request);
 
   // mojom::VideoDecodeStatsRecorder implementation:
   void StartNewRecord(VideoCodecProfile profile,
@@ -36,6 +43,7 @@
   // starting a new record.
   void FinalizeRecord();
 
+  VideoDecodePerfHistory* perf_history_;
   VideoCodecProfile profile_ = VIDEO_CODEC_PROFILE_UNKNOWN;
   gfx::Size natural_size_;
   int frames_per_sec_ = 0;
diff --git a/media/test/data/test-25fps.h264.md5 b/media/test/data/test-25fps.h264.md5
index 03c868a..9ed549d4 100644
--- a/media/test/data/test-25fps.h264.md5
+++ b/media/test/data/test-25fps.h264.md5
@@ -1,31 +1,17 @@
 # --test_video_data="test-25fps.h264:320:240:250:258:35:150:1"
 # Intel Sandy Brige - EGL
-42e78b8ac231dc24e6db5fac2d26da7b
-# Intel - Broadwell / Haswell - EGL
-11899ca545a269b6af28116b0480c0bd
-# Intel - Ivy Bridge - EGL
-d16d0662406b9d4ebb413ed3da3896e0
+1a69a608521e3542f6fb060855f5ba14
+# Intel - VA_FILTER_SCALING_DEFAULT
+d924f9464d01847f3c3d2dee739603cc
+# TODO(hiroh): Update X11 value
 # Intel - Haswell - X11
 # Intel - Ivy Bridge - X11
-5f697b015b7af0afa7ff202905f748fa
+# 5f697b015b7af0afa7ff202905f748fa
 # Intel - Sandy Bridge - X11
-07bac7ad907bcb75004324645637a06c
+# 07bac7ad907bcb75004324645637a06c
 # ARM - Mali
 82c979d493a00ee2188f7259230a8de9
 # ARM - Tegra
 b55cda7d10c37104d8c49d27c2699e40
 # ARM - MediaTek
 af21b8aa5ea63c4e88f0472ee948d01a
-# Intel - VA_FILTER_SCALING_DEFAULT
-27ddce017b884f8bbfa159ad180a71d2
-
-# TODO(llandwerlin): Remove the following hashes when the libva-intel-driver
-# is updated.
-# Intel Haswell - EGL
-92a0c14b4c1a13ca21317d2e75f17f76
-# Intel Ivy Bridge - EGL
-75d2f70272df8687dbda32e2eddd0a00
-# Intel (various) libva-intel-driver 1.5.1 with VA_PROC_PIPELINE_FAST
-8bbc743c7ac92c2442d09e8b3fb9f4f5
-# Intel - SKL
-2ec057b15cd26d087b8df10003493085
diff --git a/media/test/data/test-25fps.vp8.md5 b/media/test/data/test-25fps.vp8.md5
index 1a138846..bccedf6 100644
--- a/media/test/data/test-25fps.vp8.md5
+++ b/media/test/data/test-25fps.vp8.md5
@@ -4,16 +4,7 @@
 cd355b553ce7660283c52675232e9227
 # ARM - MediaTek
 5acb8209d79c02ed9bc12048e07908e4
-# Intel - BDW
-bea8039e6921d930bb1c86185f62b1b0
 # Intel - VA_FILTER_SCALING_DEFAULT
-32a3c4257dac03df92a5c7593ee7e31f
+66f40a833b8b23dc52bbdfc0ef0e268f
 # Intel - go2001
-5e06153339e8f83f4d8f76331f54423d
-
-# TODO(llandwerlin): Remove the following hash when the libva-intel-driver
-# is updated.
-# Intel - BDW
-4da7ec5484a99195c2c05b5e591940f9
-#Intel -SKL
-205a4000b3fbde1f2f927c8791c2afe9
+f9c98d3808b3ca06d3375d005ab31537
diff --git a/media/test/data/test-25fps.vp9.md5 b/media/test/data/test-25fps.vp9.md5
index fc248c63..c255395d 100644
--- a/media/test/data/test-25fps.vp9.md5
+++ b/media/test/data/test-25fps.vp9.md5
@@ -4,12 +4,5 @@
 4db6e435d694180354a6d763afb27894
 # ARM - RK3399
 82647609e45a19f8e22fd1880a9edf3d
-
-# Intel - Haswell
-9dc9c009b062f98691a6151e322c7df2
-# Intel - Broadwell
-f85e57dadd517b171109580a6ebd9b34
-#Intel - SKL
-67dd7a5db69123d325485a6ebecbd6c0
 # Intel - VA_FILTER_SCALING_DEFAULT
-8a3b6a803530a9eb3dc3ddfd0b02dc38
+3533e744155fa94830151df0c15b8459
diff --git a/testing/libfuzzer/fuzzers/dicts/mp4.dict b/media/test/mp4.dict
similarity index 100%
rename from testing/libfuzzer/fuzzers/dicts/mp4.dict
rename to media/test/mp4.dict
diff --git a/media/video/gpu_memory_buffer_video_frame_pool.cc b/media/video/gpu_memory_buffer_video_frame_pool.cc
index 9e7e90ef..8497c2be 100644
--- a/media/video/gpu_memory_buffer_video_frame_pool.cc
+++ b/media/video/gpu_memory_buffer_video_frame_pool.cc
@@ -524,7 +524,7 @@
   for (const auto& plane_resource : frame_resources->plane_resources) {
     if (plane_resource.gpu_memory_buffer) {
       plane_resource.gpu_memory_buffer->Unmap();
-      plane_resource.gpu_memory_buffer->SetColorSpaceForScanout(
+      plane_resource.gpu_memory_buffer->SetColorSpace(
           video_frame->ColorSpace());
     }
   }
diff --git a/mojo/common/string16.mojom b/mojo/common/string16.mojom
index 08c39e7..03333c07 100644
--- a/mojo/common/string16.mojom
+++ b/mojo/common/string16.mojom
@@ -7,6 +7,10 @@
 // Corresponds to |base::string16| in base/strings/string16.h
 // Corresponds to |WTF::String| in
 // third_party/WebKit/Source/platform/wtf/text/WTFString.h.
+// Don't make backwards-incompatible changes to this definition!
+// It's used in PageState serialization, so backwards incompatible changes
+// would cause stored PageState objects to be un-parseable. Please contact the
+// page state serialization owners before making such a change.
 struct String16 {
   array<uint16> data;
 };
diff --git a/mojo/public/cpp/bindings/lib/message_header_validator.cc b/mojo/public/cpp/bindings/lib/message_header_validator.cc
index e326762..46bc5ed6 100644
--- a/mojo/public/cpp/bindings/lib/message_header_validator.cc
+++ b/mojo/public/cpp/bindings/lib/message_header_validator.cc
@@ -73,7 +73,7 @@
   //   payload size).
   // - Validation of the payload contents will be done separately based on the
   //   payload type.
-  if (!internal::ValidatePointerNonNullable(header_v2->payload, 0,
+  if (!internal::ValidatePointerNonNullable(header_v2->payload, 5,
                                             validation_context) ||
       !internal::ValidatePointer(header_v2->payload, validation_context) ||
       !validation_context->ClaimMemory(header_v2->payload.Get(), 1)) {
diff --git a/net/BUILD.gn b/net/BUILD.gn
index 5962d19..68a1209 100644
--- a/net/BUILD.gn
+++ b/net/BUILD.gn
@@ -253,7 +253,6 @@
     "cert/x509_cert_types.h",
     "cert/x509_certificate.cc",
     "cert/x509_certificate.h",
-    "cert/x509_certificate_bytes.cc",
     "cert/x509_certificate_net_log_param.cc",
     "cert/x509_certificate_net_log_param.h",
     "cert/x509_util.cc",
diff --git a/net/PRESUBMIT.py b/net/PRESUBMIT.py
new file mode 100644
index 0000000..dde1bd0
--- /dev/null
+++ b/net/PRESUBMIT.py
@@ -0,0 +1,23 @@
+# Copyright 2017 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+"""Presubmit script for net/.
+
+See http://dev.chromium.org/developers/how-tos/depottools/presubmit-scripts
+for more details about the presubmit API built into depot_tools.
+"""
+
+def PostUploadHook(cl, change, output_api):
+  """git cl upload will call this hook after the issue is created/modified.
+
+  This hook adds an extra line to the CL description in order to run Cronet
+  tests in addition to CQ bots.
+  """
+
+  # TODO(crbug.com/712733): Remove this once Cronet bots are deployed on CQ.
+  try_bots = ['master.tryserver.chromium.android:android_cronet_tester',
+              'master.tryserver.chromium.mac:ios-simulator-cronet']
+
+  return output_api.EnsureCQIncludeTrybotsAreAdded(
+    cl, try_bots, 'Automatically added Cronet trybots to run tests on CQ.')
diff --git a/net/android/network_change_notifier_android.h b/net/android/network_change_notifier_android.h
index 38f6f7b..2fc3323 100644
--- a/net/android/network_change_notifier_android.h
+++ b/net/android/network_change_notifier_android.h
@@ -72,9 +72,9 @@
   void OnNetworkDisconnected(NetworkHandle network) override;
   void OnNetworkMadeDefault(NetworkHandle network) override;
 
-  // Promote GetMaxBandwidthForConnectionSubtype to public for the Android
+  // Promote GetMaxBandwidthMbpsForConnectionSubtype to public for the Android
   // delegate class.
-  using NetworkChangeNotifier::GetMaxBandwidthForConnectionSubtype;
+  using NetworkChangeNotifier::GetMaxBandwidthMbpsForConnectionSubtype;
 
  protected:
   void OnFinalizingMetricsLogRecord() override;
diff --git a/net/android/network_change_notifier_delegate_android.cc b/net/android/network_change_notifier_delegate_android.cc
index 8d6e74cf..830219b 100644
--- a/net/android/network_change_notifier_delegate_android.cc
+++ b/net/android/network_change_notifier_delegate_android.cc
@@ -73,7 +73,7 @@
       ConvertConnectionType(Java_NetworkChangeNotifier_getCurrentConnectionType(
           env, java_network_change_notifier_)));
   SetCurrentMaxBandwidth(
-      NetworkChangeNotifierAndroid::GetMaxBandwidthForConnectionSubtype(
+      NetworkChangeNotifierAndroid::GetMaxBandwidthMbpsForConnectionSubtype(
           GetCurrentConnectionSubtype()));
   SetCurrentDefaultNetwork(Java_NetworkChangeNotifier_getCurrentDefaultNetId(
       env, java_network_change_notifier_));
@@ -185,7 +185,7 @@
     jint subtype) {
   DCHECK(thread_checker_.CalledOnValidThread());
   double new_max_bandwidth =
-      NetworkChangeNotifierAndroid::GetMaxBandwidthForConnectionSubtype(
+      NetworkChangeNotifierAndroid::GetMaxBandwidthMbpsForConnectionSubtype(
           ConvertConnectionSubtype(subtype));
   SetCurrentMaxBandwidth(new_max_bandwidth);
   observers_->Notify(FROM_HERE, &Observer::OnMaxBandwidthChanged,
diff --git a/net/base/net_error_list.h b/net/base/net_error_list.h
index a043327..4c70993a 100644
--- a/net/base/net_error_list.h
+++ b/net/base/net_error_list.h
@@ -404,6 +404,9 @@
 //    is unlikely.
 NET_ERROR(SSL_VERSION_INTERFERENCE, -175)
 
+// No socket buffer space is available.
+NET_ERROR(NO_BUFFER_SPACE, -176)
+
 // Certificate error codes
 //
 // The values of certificate error codes must be consecutive.
diff --git a/net/base/net_errors_posix.cc b/net/base/net_errors_posix.cc
index c7993e8..366c55e 100644
--- a/net/base/net_errors_posix.cc
+++ b/net/base/net_errors_posix.cc
@@ -83,7 +83,7 @@
     case ENFILE:  // Too many open files in system.
       return ERR_INSUFFICIENT_RESOURCES;
     case ENOBUFS:  // No buffer space available.
-      return ERR_OUT_OF_MEMORY;
+      return ERR_NO_BUFFER_SPACE;
     case ENODEV:  // No such device.
       return ERR_INVALID_ARGUMENT;
     case ENOENT:  // No such file or directory.
diff --git a/net/base/network_change_notifier.cc b/net/base/network_change_notifier.cc
index 770a0eb..6329d5d 100644
--- a/net/base/network_change_notifier.cc
+++ b/net/base/network_change_notifier.cc
@@ -563,7 +563,8 @@
     ConnectionType* connection_type) {
   if (!g_network_change_notifier) {
     *connection_type = CONNECTION_UNKNOWN;
-    *max_bandwidth_mbps = GetMaxBandwidthForConnectionSubtype(SUBTYPE_UNKNOWN);
+    *max_bandwidth_mbps =
+        GetMaxBandwidthMbpsForConnectionSubtype(SUBTYPE_UNKNOWN);
     return;
   }
 
@@ -572,7 +573,7 @@
 }
 
 // static
-double NetworkChangeNotifier::GetMaxBandwidthForConnectionSubtype(
+double NetworkChangeNotifier::GetMaxBandwidthMbpsForConnectionSubtype(
     ConnectionSubtype subtype) {
   switch (subtype) {
     case SUBTYPE_GSM:
@@ -1035,8 +1036,8 @@
   *connection_type = GetCurrentConnectionType();
   *max_bandwidth_mbps =
       *connection_type == CONNECTION_NONE
-          ? GetMaxBandwidthForConnectionSubtype(SUBTYPE_NONE)
-          : GetMaxBandwidthForConnectionSubtype(SUBTYPE_UNKNOWN);
+          ? GetMaxBandwidthMbpsForConnectionSubtype(SUBTYPE_NONE)
+          : GetMaxBandwidthMbpsForConnectionSubtype(SUBTYPE_UNKNOWN);
 }
 
 bool NetworkChangeNotifier::AreNetworkHandlesCurrentlySupported() const {
diff --git a/net/base/network_change_notifier.h b/net/base/network_change_notifier.h
index 8ad03c99..3fa2d36 100644
--- a/net/base/network_change_notifier.h
+++ b/net/base/network_change_notifier.h
@@ -304,8 +304,8 @@
   // Returns a theoretical upper limit (in Mbps) on download bandwidth given a
   // connection subtype. The mapping of connection type to maximum bandwidth is
   // provided in the NetInfo spec: http://w3c.github.io/netinfo/.
-  // TODO(jkarlin): Rename to GetMaxBandwidthMbpsForConnectionSubtype.
-  static double GetMaxBandwidthForConnectionSubtype(ConnectionSubtype subtype);
+  static double GetMaxBandwidthMbpsForConnectionSubtype(
+      ConnectionSubtype subtype);
 
   // Returns true if the platform supports use of APIs based on NetworkHandles.
   // Public methods that use NetworkHandles are GetNetworkConnectionType(),
diff --git a/net/base/network_change_notifier_linux.cc b/net/base/network_change_notifier_linux.cc
index 8b2bd578..ef11c57 100644
--- a/net/base/network_change_notifier_linux.cc
+++ b/net/base/network_change_notifier_linux.cc
@@ -88,7 +88,7 @@
     NetworkChangeNotifier::NotifyObserversOfConnectionTypeChange();
     last_type_ = GetCurrentConnectionType();
     double max_bandwidth_mbps =
-        NetworkChangeNotifier::GetMaxBandwidthForConnectionSubtype(
+        NetworkChangeNotifier::GetMaxBandwidthMbpsForConnectionSubtype(
             last_type_ == CONNECTION_NONE ? SUBTYPE_NONE : SUBTYPE_UNKNOWN);
     NetworkChangeNotifier::NotifyObserversOfMaxBandwidthChange(
         max_bandwidth_mbps, last_type_);
diff --git a/net/base/network_change_notifier_mac.cc b/net/base/network_change_notifier_mac.cc
index fd56572..7931123 100644
--- a/net/base/network_change_notifier_mac.cc
+++ b/net/base/network_change_notifier_mac.cc
@@ -259,7 +259,7 @@
   if (old_type != new_type) {
     NotifyObserversOfConnectionTypeChange();
     double max_bandwidth_mbps =
-        NetworkChangeNotifier::GetMaxBandwidthForConnectionSubtype(
+        NetworkChangeNotifier::GetMaxBandwidthMbpsForConnectionSubtype(
             new_type == CONNECTION_NONE ? SUBTYPE_NONE : SUBTYPE_UNKNOWN);
     NotifyObserversOfMaxBandwidthChange(max_bandwidth_mbps, new_type);
   }
diff --git a/net/cert/cert_verify_proc_mac.cc b/net/cert/cert_verify_proc_mac.cc
index a345cfc..539d27e 100644
--- a/net/cert/cert_verify_proc_mac.cc
+++ b/net/cert/cert_verify_proc_mac.cc
@@ -242,15 +242,15 @@
 
   const CSSM_OID* alg_oid = &sig_algorithm->algorithm;
 
-  return (CSSMOIDEqual(alg_oid, &CSSMOID_MD2WithRSA) ||
-          CSSMOIDEqual(alg_oid, &CSSMOID_MD4WithRSA) ||
-          CSSMOIDEqual(alg_oid, &CSSMOID_MD5WithRSA) ||
-          CSSMOIDEqual(alg_oid, &CSSMOID_SHA1WithRSA) ||
-          CSSMOIDEqual(alg_oid, &CSSMOID_SHA1WithRSA_OIW) ||
-          CSSMOIDEqual(alg_oid, &CSSMOID_SHA1WithDSA) ||
-          CSSMOIDEqual(alg_oid, &CSSMOID_SHA1WithDSA_CMS) ||
-          CSSMOIDEqual(alg_oid, &CSSMOID_SHA1WithDSA_JDK) ||
-          CSSMOIDEqual(alg_oid, &CSSMOID_ECDSA_WithSHA1));
+  return (x509_util::CSSMOIDEqual(alg_oid, &CSSMOID_MD2WithRSA) ||
+          x509_util::CSSMOIDEqual(alg_oid, &CSSMOID_MD4WithRSA) ||
+          x509_util::CSSMOIDEqual(alg_oid, &CSSMOID_MD5WithRSA) ||
+          x509_util::CSSMOIDEqual(alg_oid, &CSSMOID_SHA1WithRSA) ||
+          x509_util::CSSMOIDEqual(alg_oid, &CSSMOID_SHA1WithRSA_OIW) ||
+          x509_util::CSSMOIDEqual(alg_oid, &CSSMOID_SHA1WithDSA) ||
+          x509_util::CSSMOIDEqual(alg_oid, &CSSMOID_SHA1WithDSA_CMS) ||
+          x509_util::CSSMOIDEqual(alg_oid, &CSSMOID_SHA1WithDSA_JDK) ||
+          x509_util::CSSMOIDEqual(alg_oid, &CSSMOID_ECDSA_WithSHA1));
 }
 
 // Returns true if the intermediates (excluding trusted certificates) use a
diff --git a/net/cert/x509_cert_types.h b/net/cert/x509_cert_types.h
index 9408082..3317d93 100644
--- a/net/cert/x509_cert_types.h
+++ b/net/cert/x509_cert_types.h
@@ -20,10 +20,6 @@
 #include "net/base/net_export.h"
 #include "net/cert/cert_status_flags.h"
 
-#if defined(OS_MACOSX) && !defined(OS_IOS)
-#include <Security/x509defs.h>
-#endif
-
 namespace base {
 class Time;
 }  // namespace base
@@ -67,14 +63,6 @@
   std::vector<std::string> domain_components;
 };
 
-#if defined(OS_MACOSX) && !defined(OS_IOS)
-// Compares two OIDs by value.
-inline bool CSSMOIDEqual(const CSSM_OID* oid1, const CSSM_OID* oid2) {
-  return oid1->Length == oid2->Length &&
-  (memcmp(oid1->Data, oid2->Data, oid1->Length) == 0);
-}
-#endif
-
 // A list of ASN.1 date/time formats that ParseCertificateDate() supports,
 // encoded in the canonical forms specified in RFC 2459/3280/5280.
 enum CertDateFormat {
diff --git a/net/cert/x509_certificate.cc b/net/cert/x509_certificate.cc
index 8a5d523..1e3e27acf 100644
--- a/net/cert/x509_certificate.cc
+++ b/net/cert/x509_certificate.cc
@@ -14,15 +14,32 @@
 #include "base/base64.h"
 #include "base/logging.h"
 #include "base/macros.h"
+#include "base/numerics/safe_conversions.h"
 #include "base/pickle.h"
 #include "base/stl_util.h"
 #include "base/strings/string_piece.h"
 #include "base/strings/string_util.h"
 #include "base/time/time.h"
 #include "base/trace_event/trace_event.h"
+#include "build/build_config.h"
+#include "crypto/openssl_util.h"
+#include "net/base/ip_address.h"
 #include "net/base/registry_controlled_domains/registry_controlled_domain.h"
 #include "net/base/url_util.h"
+#include "net/cert/asn1_util.h"
+#include "net/cert/internal/cert_errors.h"
+#include "net/cert/internal/name_constraints.h"
+#include "net/cert/internal/parsed_certificate.h"
+#include "net/cert/internal/signature_algorithm.h"
+#include "net/cert/internal/verify_name_match.h"
+#include "net/cert/internal/verify_signed_data.h"
 #include "net/cert/pem_tokenizer.h"
+#include "net/cert/x509_util.h"
+#include "net/der/parser.h"
+#include "third_party/boringssl/src/include/openssl/evp.h"
+#include "third_party/boringssl/src/include/openssl/pkcs7.h"
+#include "third_party/boringssl/src/include/openssl/pool.h"
+#include "third_party/boringssl/src/include/openssl/sha.h"
 #include "url/url_canon.h"
 
 namespace net {
@@ -58,6 +75,104 @@
   }
 }
 
+// Converts a GeneralizedTime struct to a base::Time, returning true on success
+// or false if |generalized| was invalid or cannot be represented by
+// base::Time.
+bool GeneralizedTimeToBaseTime(const der::GeneralizedTime& generalized,
+                               base::Time* result) {
+  base::Time::Exploded exploded = {0};
+  exploded.year = generalized.year;
+  exploded.month = generalized.month;
+  exploded.day_of_month = generalized.day;
+  exploded.hour = generalized.hours;
+  exploded.minute = generalized.minutes;
+  exploded.second = generalized.seconds;
+#if defined(OS_POSIX) && !defined(OS_MACOSX) && !defined(OS_ANDROID)
+  if (base::Time::FromUTCExploded(exploded, result))
+    return true;
+
+  if (sizeof(time_t) == 4) {
+    // Fail on obviously bad dates before trying the 32-bit hacks.
+    if (!exploded.HasValidValues())
+      return false;
+
+    // Hack to handle dates that can't be converted on 32-bit systems.
+    // TODO(mattm): consider consolidating this with
+    // SaturatedTimeFromUTCExploded from cookie_util.cc
+    if (generalized.year >= 2038) {
+      *result = base::Time::Max();
+      return true;
+    }
+    if (generalized.year < 1970) {
+      *result = base::Time::Min();
+      return true;
+    }
+  }
+  return false;
+#else
+  return base::Time::FromUTCExploded(exploded, result);
+#endif
+}
+
+// Sets |value| to the Value from a DER Sequence Tag-Length-Value and return
+// true, or return false if the TLV was not a valid DER Sequence.
+WARN_UNUSED_RESULT bool GetSequenceValue(const der::Input& tlv,
+                                         der::Input* value) {
+  der::Parser parser(tlv);
+  return parser.ReadTag(der::kSequence, value) && !parser.HasMore();
+}
+
+// Normalize |cert|'s Issuer and store it in |out_normalized_issuer|, returning
+// true on success or false if there was a parsing error.
+bool GetNormalizedCertIssuer(CRYPTO_BUFFER* cert,
+                             std::string* out_normalized_issuer) {
+  der::Input tbs_certificate_tlv;
+  der::Input signature_algorithm_tlv;
+  der::BitString signature_value;
+  if (!ParseCertificate(
+          der::Input(CRYPTO_BUFFER_data(cert), CRYPTO_BUFFER_len(cert)),
+          &tbs_certificate_tlv, &signature_algorithm_tlv, &signature_value,
+          nullptr)) {
+    return false;
+  }
+  ParsedTbsCertificate tbs;
+  if (!ParseTbsCertificate(tbs_certificate_tlv,
+                           x509_util::DefaultParseCertificateOptions(), &tbs,
+                           nullptr))
+    return false;
+
+  der::Input issuer_value;
+  if (!GetSequenceValue(tbs.issuer_tlv, &issuer_value))
+    return false;
+
+  CertErrors errors;
+  return NormalizeName(issuer_value, out_normalized_issuer, &errors);
+}
+
+// Parses certificates from a PKCS#7 SignedData structure, appending them to
+// |handles|.
+void CreateOSCertHandlesFromPKCS7Bytes(
+    const char* data,
+    size_t length,
+    X509Certificate::OSCertHandles* handles) {
+  crypto::EnsureOpenSSLInit();
+  crypto::OpenSSLErrStackTracer err_cleaner(FROM_HERE);
+
+  CBS der_data;
+  CBS_init(&der_data, reinterpret_cast<const uint8_t*>(data), length);
+  STACK_OF(CRYPTO_BUFFER)* certs = sk_CRYPTO_BUFFER_new_null();
+
+  if (PKCS7_get_raw_certificates(certs, &der_data,
+                                 x509_util::GetBufferPool())) {
+    for (size_t i = 0; i < sk_CRYPTO_BUFFER_num(certs); ++i) {
+      handles->push_back(sk_CRYPTO_BUFFER_value(certs, i));
+    }
+  }
+  // |handles| took ownership of the individual buffers, so only free the list
+  // itself.
+  sk_CRYPTO_BUFFER_free(certs);
+}
+
 }  // namespace
 
 // static
@@ -320,6 +435,64 @@
     dns_names->push_back(subject_.common_name);
 }
 
+bool X509Certificate::GetSubjectAltName(
+    std::vector<std::string>* dns_names,
+    std::vector<std::string>* ip_addrs) const {
+  if (dns_names)
+    dns_names->clear();
+  if (ip_addrs)
+    ip_addrs->clear();
+
+  der::Input tbs_certificate_tlv;
+  der::Input signature_algorithm_tlv;
+  der::BitString signature_value;
+  if (!ParseCertificate(der::Input(CRYPTO_BUFFER_data(cert_handle_),
+                                   CRYPTO_BUFFER_len(cert_handle_)),
+                        &tbs_certificate_tlv, &signature_algorithm_tlv,
+                        &signature_value, nullptr)) {
+    return false;
+  }
+
+  ParsedTbsCertificate tbs;
+  if (!ParseTbsCertificate(tbs_certificate_tlv,
+                           x509_util::DefaultParseCertificateOptions(), &tbs,
+                           nullptr))
+    return false;
+  if (!tbs.has_extensions)
+    return false;
+
+  std::map<der::Input, ParsedExtension> extensions;
+  if (!ParseExtensions(tbs.extensions_tlv, &extensions))
+    return false;
+
+  ParsedExtension subject_alt_names_extension;
+  if (!ConsumeExtension(SubjectAltNameOid(), &extensions,
+                        &subject_alt_names_extension)) {
+    return false;
+  }
+
+  CertErrors errors;
+  std::unique_ptr<GeneralNames> subject_alt_names =
+      GeneralNames::Create(subject_alt_names_extension.value, &errors);
+  if (!subject_alt_names)
+    return false;
+
+  if (dns_names) {
+    for (const auto& dns_name : subject_alt_names->dns_names)
+      dns_names->push_back(dns_name.as_string());
+  }
+  if (ip_addrs) {
+    for (const IPAddress& addr : subject_alt_names->ip_addresses) {
+      ip_addrs->push_back(
+          std::string(reinterpret_cast<const char*>(addr.bytes().data()),
+                      addr.bytes().size()));
+    }
+  }
+
+  return !subject_alt_names->dns_names.empty() ||
+         !subject_alt_names->ip_addresses.empty();
+}
+
 bool X509Certificate::HasExpired() const {
   return base::Time::Now() > valid_expiry();
 }
@@ -328,6 +501,35 @@
   return IsSameOSCert(cert_handle_, other->cert_handle_);
 }
 
+bool X509Certificate::IsIssuedByEncoded(
+    const std::vector<std::string>& valid_issuers) {
+  std::vector<std::string> normalized_issuers;
+  CertErrors errors;
+  for (const auto& raw_issuer : valid_issuers) {
+    der::Input issuer_value;
+    std::string normalized_issuer;
+    if (!GetSequenceValue(der::Input(&raw_issuer), &issuer_value) ||
+        !NormalizeName(issuer_value, &normalized_issuer, &errors)) {
+      continue;
+    }
+    normalized_issuers.push_back(std::move(normalized_issuer));
+  }
+
+  std::string normalized_cert_issuer;
+  if (!GetNormalizedCertIssuer(cert_handle_, &normalized_cert_issuer))
+    return false;
+  if (base::ContainsValue(normalized_issuers, normalized_cert_issuer))
+    return true;
+
+  for (CRYPTO_BUFFER* intermediate : intermediate_ca_certs_) {
+    if (!GetNormalizedCertIssuer(intermediate, &normalized_cert_issuer))
+      return false;
+    if (base::ContainsValue(normalized_issuers, normalized_cert_issuer))
+      return true;
+  }
+  return false;
+}
+
 // static
 bool X509Certificate::VerifyHostname(
     const std::string& hostname,
@@ -480,6 +682,17 @@
 }
 
 // static
+bool X509Certificate::GetDEREncoded(X509Certificate::OSCertHandle cert_handle,
+                                    std::string* encoded) {
+  if (!cert_handle)
+    return false;
+  encoded->assign(
+      reinterpret_cast<const char*>(CRYPTO_BUFFER_data(cert_handle)),
+      CRYPTO_BUFFER_len(cert_handle));
+  return true;
+}
+
+// static
 bool X509Certificate::GetPEMEncodedFromDER(const std::string& der_encoded,
                                            std::string* pem_encoded) {
   if (der_encoded.empty())
@@ -527,6 +740,143 @@
 }
 
 // static
+void X509Certificate::GetPublicKeyInfo(OSCertHandle cert_handle,
+                                       size_t* size_bits,
+                                       PublicKeyType* type) {
+  *type = kPublicKeyTypeUnknown;
+  *size_bits = 0;
+
+  base::StringPiece spki;
+  if (!asn1::ExtractSPKIFromDERCert(
+          base::StringPiece(
+              reinterpret_cast<const char*>(CRYPTO_BUFFER_data(cert_handle)),
+              CRYPTO_BUFFER_len(cert_handle)),
+          &spki)) {
+    return;
+  }
+
+  bssl::UniquePtr<EVP_PKEY> pkey;
+  crypto::OpenSSLErrStackTracer err_tracer(FROM_HERE);
+  CBS cbs;
+  CBS_init(&cbs, reinterpret_cast<const uint8_t*>(spki.data()), spki.size());
+  pkey.reset(EVP_parse_public_key(&cbs));
+  if (!pkey)
+    return;
+
+  switch (pkey->type) {
+    case EVP_PKEY_RSA:
+      *type = kPublicKeyTypeRSA;
+      break;
+    case EVP_PKEY_DSA:
+      *type = kPublicKeyTypeDSA;
+      break;
+    case EVP_PKEY_EC:
+      *type = kPublicKeyTypeECDSA;
+      break;
+    case EVP_PKEY_DH:
+      *type = kPublicKeyTypeDH;
+      break;
+  }
+  *size_bits = base::saturated_cast<size_t>(EVP_PKEY_bits(pkey.get()));
+}
+
+// static
+bool X509Certificate::IsSameOSCert(X509Certificate::OSCertHandle a,
+                                   X509Certificate::OSCertHandle b) {
+  DCHECK(a && b);
+  if (a == b)
+    return true;
+  return CRYPTO_BUFFER_len(a) == CRYPTO_BUFFER_len(b) &&
+         memcmp(CRYPTO_BUFFER_data(a), CRYPTO_BUFFER_data(b),
+                CRYPTO_BUFFER_len(a)) == 0;
+}
+
+// static
+X509Certificate::OSCertHandle X509Certificate::CreateOSCertHandleFromBytes(
+    const char* data,
+    size_t length) {
+  der::Input tbs_certificate_tlv;
+  der::Input signature_algorithm_tlv;
+  der::BitString signature_value;
+  // Do a bare minimum of DER parsing here to make sure the input is not
+  // completely crazy. (This is required for at least
+  // CreateCertificateListFromBytes with FORMAT_AUTO, if not more.)
+  if (!ParseCertificate(
+          der::Input(reinterpret_cast<const uint8_t*>(data), length),
+          &tbs_certificate_tlv, &signature_algorithm_tlv, &signature_value,
+          nullptr)) {
+    return nullptr;
+  }
+
+  return CRYPTO_BUFFER_new(reinterpret_cast<const uint8_t*>(data), length,
+                           x509_util::GetBufferPool());
+}
+
+// static
+X509Certificate::OSCertHandles X509Certificate::CreateOSCertHandlesFromBytes(
+    const char* data,
+    size_t length,
+    Format format) {
+  OSCertHandles results;
+
+  switch (format) {
+    case FORMAT_SINGLE_CERTIFICATE: {
+      OSCertHandle handle = CreateOSCertHandleFromBytes(data, length);
+      if (handle)
+        results.push_back(handle);
+      break;
+    }
+    case FORMAT_PKCS7: {
+      CreateOSCertHandlesFromPKCS7Bytes(data, length, &results);
+      break;
+    }
+    default: {
+      NOTREACHED() << "Certificate format " << format << " unimplemented";
+      break;
+    }
+  }
+
+  return results;
+}
+
+// static
+X509Certificate::OSCertHandle X509Certificate::DupOSCertHandle(
+    OSCertHandle cert_handle) {
+  CRYPTO_BUFFER_up_ref(cert_handle);
+  return cert_handle;
+}
+
+// static
+void X509Certificate::FreeOSCertHandle(OSCertHandle cert_handle) {
+  CRYPTO_BUFFER_free(cert_handle);
+}
+
+// static
+SHA256HashValue X509Certificate::CalculateFingerprint256(OSCertHandle cert) {
+  SHA256HashValue sha256;
+
+  SHA256(CRYPTO_BUFFER_data(cert), CRYPTO_BUFFER_len(cert), sha256.data);
+  return sha256;
+}
+
+// static
+SHA256HashValue X509Certificate::CalculateCAFingerprint256(
+    const OSCertHandles& intermediates) {
+  SHA256HashValue sha256;
+  memset(sha256.data, 0, sizeof(sha256.data));
+
+  SHA256_CTX sha256_ctx;
+  SHA256_Init(&sha256_ctx);
+  for (CRYPTO_BUFFER* cert : intermediates) {
+    SHA256_Update(&sha256_ctx, CRYPTO_BUFFER_data(cert),
+                  CRYPTO_BUFFER_len(cert));
+  }
+  SHA256_Final(sha256.data, &sha256_ctx);
+
+  return sha256;
+}
+
+// static
 SHA256HashValue X509Certificate::CalculateChainFingerprint256(
     OSCertHandle leaf,
     const OSCertHandles& intermediates) {
@@ -537,6 +887,52 @@
   return CalculateCAFingerprint256(chain);
 }
 
+// static
+bool X509Certificate::IsSelfSigned(OSCertHandle cert_handle) {
+  der::Input tbs_certificate_tlv;
+  der::Input signature_algorithm_tlv;
+  der::BitString signature_value;
+  if (!ParseCertificate(der::Input(CRYPTO_BUFFER_data(cert_handle),
+                                   CRYPTO_BUFFER_len(cert_handle)),
+                        &tbs_certificate_tlv, &signature_algorithm_tlv,
+                        &signature_value, nullptr)) {
+    return false;
+  }
+  ParsedTbsCertificate tbs;
+  if (!ParseTbsCertificate(tbs_certificate_tlv,
+                           x509_util::DefaultParseCertificateOptions(), &tbs,
+                           nullptr)) {
+    return false;
+  }
+
+  der::Input subject_value;
+  CertErrors errors;
+  std::string normalized_subject;
+  if (!GetSequenceValue(tbs.subject_tlv, &subject_value) ||
+      !NormalizeName(subject_value, &normalized_subject, &errors)) {
+    return false;
+  }
+  der::Input issuer_value;
+  std::string normalized_issuer;
+  if (!GetSequenceValue(tbs.issuer_tlv, &issuer_value) ||
+      !NormalizeName(issuer_value, &normalized_issuer, &errors)) {
+    return false;
+  }
+
+  if (normalized_subject != normalized_issuer)
+    return false;
+
+  std::unique_ptr<SignatureAlgorithm> signature_algorithm =
+      SignatureAlgorithm::Create(signature_algorithm_tlv, nullptr /* errors */);
+  if (!signature_algorithm)
+    return false;
+
+  // Don't enforce any minimum key size or restrict the algorithm, since when
+  // self signed not very relevant.
+  return VerifySignedData(*signature_algorithm, tbs_certificate_tlv,
+                          signature_value, tbs.spki_tlv);
+}
+
 X509Certificate::X509Certificate(OSCertHandle cert_handle,
                                  const OSCertHandles& intermediates)
     : X509Certificate(cert_handle, intermediates, {}) {}
@@ -565,4 +961,62 @@
     FreeOSCertHandle(intermediate_ca_certs_[i]);
 }
 
+bool X509Certificate::Initialize(UnsafeCreateOptions options) {
+  der::Input tbs_certificate_tlv;
+  der::Input signature_algorithm_tlv;
+  der::BitString signature_value;
+
+  if (!ParseCertificate(der::Input(CRYPTO_BUFFER_data(cert_handle_),
+                                   CRYPTO_BUFFER_len(cert_handle_)),
+                        &tbs_certificate_tlv, &signature_algorithm_tlv,
+                        &signature_value, nullptr)) {
+    return false;
+  }
+
+  ParsedTbsCertificate tbs;
+  if (!ParseTbsCertificate(tbs_certificate_tlv,
+                           x509_util::DefaultParseCertificateOptions(), &tbs,
+                           nullptr))
+    return false;
+
+  CertPrincipal::PrintableStringHandling printable_string_handling =
+      options.printable_string_is_utf8
+          ? CertPrincipal::PrintableStringHandling::kAsUTF8Hack
+          : CertPrincipal::PrintableStringHandling::kDefault;
+  if (!subject_.ParseDistinguishedName(tbs.subject_tlv.UnsafeData(),
+                                       tbs.subject_tlv.Length(),
+                                       printable_string_handling) ||
+      !issuer_.ParseDistinguishedName(tbs.issuer_tlv.UnsafeData(),
+                                      tbs.issuer_tlv.Length(),
+                                      printable_string_handling)) {
+    return false;
+  }
+
+  if (!GeneralizedTimeToBaseTime(tbs.validity_not_before, &valid_start_) ||
+      !GeneralizedTimeToBaseTime(tbs.validity_not_after, &valid_expiry_)) {
+    return false;
+  }
+  serial_number_ = tbs.serial_number.AsString();
+  return true;
+}
+
+// static
+X509Certificate::OSCertHandle X509Certificate::ReadOSCertHandleFromPickle(
+    base::PickleIterator* pickle_iter) {
+  const char* data;
+  int length;
+  if (!pickle_iter->ReadData(&data, &length))
+    return NULL;
+
+  return CreateOSCertHandleFromBytes(data, length);
+}
+
+// static
+void X509Certificate::WriteOSCertHandleToPickle(OSCertHandle cert_handle,
+                                                base::Pickle* pickle) {
+  pickle->WriteData(
+      reinterpret_cast<const char*>(CRYPTO_BUFFER_data(cert_handle)),
+      CRYPTO_BUFFER_len(cert_handle));
+}
+
 }  // namespace net
diff --git a/net/cert/x509_certificate_bytes.cc b/net/cert/x509_certificate_bytes.cc
deleted file mode 100644
index c78fc0b1..0000000
--- a/net/cert/x509_certificate_bytes.cc
+++ /dev/null
@@ -1,470 +0,0 @@
-// Copyright 2017 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "net/cert/x509_certificate.h"
-
-#include "base/numerics/safe_conversions.h"
-#include "base/pickle.h"
-#include "base/stl_util.h"
-#include "build/build_config.h"
-#include "crypto/openssl_util.h"
-#include "net/base/ip_address.h"
-#include "net/cert/asn1_util.h"
-#include "net/cert/internal/cert_errors.h"
-#include "net/cert/internal/name_constraints.h"
-#include "net/cert/internal/parsed_certificate.h"
-#include "net/cert/internal/signature_algorithm.h"
-#include "net/cert/internal/verify_name_match.h"
-#include "net/cert/internal/verify_signed_data.h"
-#include "net/cert/x509_util.h"
-#include "net/der/parser.h"
-#include "third_party/boringssl/src/include/openssl/evp.h"
-#include "third_party/boringssl/src/include/openssl/pkcs7.h"
-#include "third_party/boringssl/src/include/openssl/pool.h"
-#include "third_party/boringssl/src/include/openssl/sha.h"
-
-namespace net {
-
-namespace {
-
-// Converts a GeneralizedTime struct to a base::Time, returning true on success
-// or false if |generalized| was invalid or cannot be represented by
-// base::Time.
-bool GeneralizedTimeToBaseTime(const der::GeneralizedTime& generalized,
-                               base::Time* result) {
-  base::Time::Exploded exploded = {0};
-  exploded.year = generalized.year;
-  exploded.month = generalized.month;
-  exploded.day_of_month = generalized.day;
-  exploded.hour = generalized.hours;
-  exploded.minute = generalized.minutes;
-  exploded.second = generalized.seconds;
-#if defined(OS_POSIX) && !defined(OS_MACOSX) && !defined(OS_ANDROID)
-  if (base::Time::FromUTCExploded(exploded, result))
-    return true;
-
-  if (sizeof(time_t) == 4) {
-    // Fail on obviously bad dates before trying the 32-bit hacks.
-    if (!exploded.HasValidValues())
-      return false;
-
-    // Hack to handle dates that can't be converted on 32-bit systems.
-    // TODO(mattm): consider consolidating this with
-    // SaturatedTimeFromUTCExploded from cookie_util.cc
-    if (generalized.year >= 2038) {
-      *result = base::Time::Max();
-      return true;
-    }
-    if (generalized.year < 1970) {
-      *result = base::Time::Min();
-      return true;
-    }
-  }
-  return false;
-#else
-  return base::Time::FromUTCExploded(exploded, result);
-#endif
-}
-
-// Sets |value| to the Value from a DER Sequence Tag-Length-Value and return
-// true, or return false if the TLV was not a valid DER Sequence.
-WARN_UNUSED_RESULT bool GetSequenceValue(const der::Input& tlv,
-                                         der::Input* value) {
-  der::Parser parser(tlv);
-  return parser.ReadTag(der::kSequence, value) && !parser.HasMore();
-}
-
-// Normalize |cert|'s Issuer and store it in |out_normalized_issuer|, returning
-// true on success or false if there was a parsing error.
-bool GetNormalizedCertIssuer(CRYPTO_BUFFER* cert,
-                             std::string* out_normalized_issuer) {
-  der::Input tbs_certificate_tlv;
-  der::Input signature_algorithm_tlv;
-  der::BitString signature_value;
-  if (!ParseCertificate(
-          der::Input(CRYPTO_BUFFER_data(cert), CRYPTO_BUFFER_len(cert)),
-          &tbs_certificate_tlv, &signature_algorithm_tlv, &signature_value,
-          nullptr)) {
-    return false;
-  }
-  ParsedTbsCertificate tbs;
-  if (!ParseTbsCertificate(tbs_certificate_tlv,
-                           x509_util::DefaultParseCertificateOptions(), &tbs,
-                           nullptr))
-    return false;
-
-  der::Input issuer_value;
-  if (!GetSequenceValue(tbs.issuer_tlv, &issuer_value))
-    return false;
-
-  CertErrors errors;
-  return NormalizeName(issuer_value, out_normalized_issuer, &errors);
-}
-
-// Parses certificates from a PKCS#7 SignedData structure, appending them to
-// |handles|.
-void CreateOSCertHandlesFromPKCS7Bytes(
-    const char* data,
-    size_t length,
-    X509Certificate::OSCertHandles* handles) {
-  crypto::EnsureOpenSSLInit();
-  crypto::OpenSSLErrStackTracer err_cleaner(FROM_HERE);
-
-  CBS der_data;
-  CBS_init(&der_data, reinterpret_cast<const uint8_t*>(data), length);
-  STACK_OF(CRYPTO_BUFFER)* certs = sk_CRYPTO_BUFFER_new_null();
-
-  if (PKCS7_get_raw_certificates(certs, &der_data,
-                                 x509_util::GetBufferPool())) {
-    for (size_t i = 0; i < sk_CRYPTO_BUFFER_num(certs); ++i) {
-      handles->push_back(sk_CRYPTO_BUFFER_value(certs, i));
-    }
-  }
-  // |handles| took ownership of the individual buffers, so only free the list
-  // itself.
-  sk_CRYPTO_BUFFER_free(certs);
-}
-
-}  // namespace
-
-bool X509Certificate::Initialize(UnsafeCreateOptions options) {
-  der::Input tbs_certificate_tlv;
-  der::Input signature_algorithm_tlv;
-  der::BitString signature_value;
-
-  if (!ParseCertificate(der::Input(CRYPTO_BUFFER_data(cert_handle_),
-                                   CRYPTO_BUFFER_len(cert_handle_)),
-                        &tbs_certificate_tlv, &signature_algorithm_tlv,
-                        &signature_value, nullptr)) {
-    return false;
-  }
-
-  ParsedTbsCertificate tbs;
-  if (!ParseTbsCertificate(tbs_certificate_tlv,
-                           x509_util::DefaultParseCertificateOptions(), &tbs,
-                           nullptr))
-    return false;
-
-  CertPrincipal::PrintableStringHandling printable_string_handling =
-      options.printable_string_is_utf8
-          ? CertPrincipal::PrintableStringHandling::kAsUTF8Hack
-          : CertPrincipal::PrintableStringHandling::kDefault;
-  if (!subject_.ParseDistinguishedName(tbs.subject_tlv.UnsafeData(),
-                                       tbs.subject_tlv.Length(),
-                                       printable_string_handling) ||
-      !issuer_.ParseDistinguishedName(tbs.issuer_tlv.UnsafeData(),
-                                      tbs.issuer_tlv.Length(),
-                                      printable_string_handling)) {
-    return false;
-  }
-
-  if (!GeneralizedTimeToBaseTime(tbs.validity_not_before, &valid_start_) ||
-      !GeneralizedTimeToBaseTime(tbs.validity_not_after, &valid_expiry_)) {
-    return false;
-  }
-  serial_number_ = tbs.serial_number.AsString();
-  return true;
-}
-
-bool X509Certificate::GetSubjectAltName(
-    std::vector<std::string>* dns_names,
-    std::vector<std::string>* ip_addrs) const {
-  if (dns_names)
-    dns_names->clear();
-  if (ip_addrs)
-    ip_addrs->clear();
-
-  der::Input tbs_certificate_tlv;
-  der::Input signature_algorithm_tlv;
-  der::BitString signature_value;
-  if (!ParseCertificate(der::Input(CRYPTO_BUFFER_data(cert_handle_),
-                                   CRYPTO_BUFFER_len(cert_handle_)),
-                        &tbs_certificate_tlv, &signature_algorithm_tlv,
-                        &signature_value, nullptr)) {
-    return false;
-  }
-
-  ParsedTbsCertificate tbs;
-  if (!ParseTbsCertificate(tbs_certificate_tlv,
-                           x509_util::DefaultParseCertificateOptions(), &tbs,
-                           nullptr))
-    return false;
-  if (!tbs.has_extensions)
-    return false;
-
-  std::map<der::Input, ParsedExtension> extensions;
-  if (!ParseExtensions(tbs.extensions_tlv, &extensions))
-    return false;
-
-  ParsedExtension subject_alt_names_extension;
-  if (!ConsumeExtension(SubjectAltNameOid(), &extensions,
-                        &subject_alt_names_extension)) {
-    return false;
-  }
-
-  CertErrors errors;
-  std::unique_ptr<GeneralNames> subject_alt_names =
-      GeneralNames::Create(subject_alt_names_extension.value, &errors);
-  if (!subject_alt_names)
-    return false;
-
-  if (dns_names) {
-    for (const auto& dns_name : subject_alt_names->dns_names)
-      dns_names->push_back(dns_name.as_string());
-  }
-  if (ip_addrs) {
-    for (const IPAddress& addr : subject_alt_names->ip_addresses) {
-      ip_addrs->push_back(
-          std::string(reinterpret_cast<const char*>(addr.bytes().data()),
-                      addr.bytes().size()));
-    }
-  }
-
-  return !subject_alt_names->dns_names.empty() ||
-         !subject_alt_names->ip_addresses.empty();
-}
-
-bool X509Certificate::IsIssuedByEncoded(
-    const std::vector<std::string>& valid_issuers) {
-  std::vector<std::string> normalized_issuers;
-  CertErrors errors;
-  for (const auto& raw_issuer : valid_issuers) {
-    der::Input issuer_value;
-    std::string normalized_issuer;
-    if (!GetSequenceValue(der::Input(&raw_issuer), &issuer_value) ||
-        !NormalizeName(issuer_value, &normalized_issuer, &errors)) {
-      continue;
-    }
-    normalized_issuers.push_back(std::move(normalized_issuer));
-  }
-
-  std::string normalized_cert_issuer;
-  if (!GetNormalizedCertIssuer(cert_handle_, &normalized_cert_issuer))
-    return false;
-  if (base::ContainsValue(normalized_issuers, normalized_cert_issuer))
-    return true;
-
-  for (CRYPTO_BUFFER* intermediate : intermediate_ca_certs_) {
-    if (!GetNormalizedCertIssuer(intermediate, &normalized_cert_issuer))
-      return false;
-    if (base::ContainsValue(normalized_issuers, normalized_cert_issuer))
-      return true;
-  }
-  return false;
-}
-
-// static
-bool X509Certificate::GetDEREncoded(X509Certificate::OSCertHandle cert_handle,
-                                    std::string* encoded) {
-  if (!cert_handle)
-    return false;
-  encoded->assign(
-      reinterpret_cast<const char*>(CRYPTO_BUFFER_data(cert_handle)),
-      CRYPTO_BUFFER_len(cert_handle));
-  return true;
-}
-
-// static
-void X509Certificate::GetPublicKeyInfo(OSCertHandle cert_handle,
-                                       size_t* size_bits,
-                                       PublicKeyType* type) {
-  *type = kPublicKeyTypeUnknown;
-  *size_bits = 0;
-
-  base::StringPiece spki;
-  if (!asn1::ExtractSPKIFromDERCert(
-          base::StringPiece(
-              reinterpret_cast<const char*>(CRYPTO_BUFFER_data(cert_handle)),
-              CRYPTO_BUFFER_len(cert_handle)),
-          &spki)) {
-    return;
-  }
-
-  bssl::UniquePtr<EVP_PKEY> pkey;
-  crypto::OpenSSLErrStackTracer err_tracer(FROM_HERE);
-  CBS cbs;
-  CBS_init(&cbs, reinterpret_cast<const uint8_t*>(spki.data()), spki.size());
-  pkey.reset(EVP_parse_public_key(&cbs));
-  if (!pkey)
-    return;
-
-  switch (pkey->type) {
-    case EVP_PKEY_RSA:
-      *type = kPublicKeyTypeRSA;
-      break;
-    case EVP_PKEY_DSA:
-      *type = kPublicKeyTypeDSA;
-      break;
-    case EVP_PKEY_EC:
-      *type = kPublicKeyTypeECDSA;
-      break;
-    case EVP_PKEY_DH:
-      *type = kPublicKeyTypeDH;
-      break;
-  }
-  *size_bits = base::saturated_cast<size_t>(EVP_PKEY_bits(pkey.get()));
-}
-
-// static
-bool X509Certificate::IsSameOSCert(X509Certificate::OSCertHandle a,
-                                   X509Certificate::OSCertHandle b) {
-  DCHECK(a && b);
-  if (a == b)
-    return true;
-  return CRYPTO_BUFFER_len(a) == CRYPTO_BUFFER_len(b) &&
-         memcmp(CRYPTO_BUFFER_data(a), CRYPTO_BUFFER_data(b),
-                CRYPTO_BUFFER_len(a)) == 0;
-}
-
-// static
-X509Certificate::OSCertHandle X509Certificate::CreateOSCertHandleFromBytes(
-    const char* data,
-    size_t length) {
-  der::Input tbs_certificate_tlv;
-  der::Input signature_algorithm_tlv;
-  der::BitString signature_value;
-  // Do a bare minimum of DER parsing here to make sure the input is not
-  // completely crazy. (This is required for at least
-  // CreateCertificateListFromBytes with FORMAT_AUTO, if not more.)
-  if (!ParseCertificate(
-          der::Input(reinterpret_cast<const uint8_t*>(data), length),
-          &tbs_certificate_tlv, &signature_algorithm_tlv, &signature_value,
-          nullptr)) {
-    return nullptr;
-  }
-
-  return CRYPTO_BUFFER_new(reinterpret_cast<const uint8_t*>(data), length,
-                           x509_util::GetBufferPool());
-}
-
-// static
-X509Certificate::OSCertHandles X509Certificate::CreateOSCertHandlesFromBytes(
-    const char* data,
-    size_t length,
-    Format format) {
-  OSCertHandles results;
-
-  switch (format) {
-    case FORMAT_SINGLE_CERTIFICATE: {
-      OSCertHandle handle = CreateOSCertHandleFromBytes(data, length);
-      if (handle)
-        results.push_back(handle);
-      break;
-    }
-    case FORMAT_PKCS7: {
-      CreateOSCertHandlesFromPKCS7Bytes(data, length, &results);
-      break;
-    }
-    default: {
-      NOTREACHED() << "Certificate format " << format << " unimplemented";
-      break;
-    }
-  }
-
-  return results;
-}
-
-// static
-X509Certificate::OSCertHandle X509Certificate::DupOSCertHandle(
-    OSCertHandle cert_handle) {
-  CRYPTO_BUFFER_up_ref(cert_handle);
-  return cert_handle;
-}
-
-// static
-void X509Certificate::FreeOSCertHandle(OSCertHandle cert_handle) {
-  CRYPTO_BUFFER_free(cert_handle);
-}
-
-// static
-SHA256HashValue X509Certificate::CalculateFingerprint256(OSCertHandle cert) {
-  SHA256HashValue sha256;
-
-  SHA256(CRYPTO_BUFFER_data(cert), CRYPTO_BUFFER_len(cert), sha256.data);
-  return sha256;
-}
-
-// static
-SHA256HashValue X509Certificate::CalculateCAFingerprint256(
-    const OSCertHandles& intermediates) {
-  SHA256HashValue sha256;
-  memset(sha256.data, 0, sizeof(sha256.data));
-
-  SHA256_CTX sha256_ctx;
-  SHA256_Init(&sha256_ctx);
-  for (CRYPTO_BUFFER* cert : intermediates) {
-    SHA256_Update(&sha256_ctx, CRYPTO_BUFFER_data(cert),
-                  CRYPTO_BUFFER_len(cert));
-  }
-  SHA256_Final(sha256.data, &sha256_ctx);
-
-  return sha256;
-}
-
-// static
-bool X509Certificate::IsSelfSigned(OSCertHandle cert_handle) {
-  der::Input tbs_certificate_tlv;
-  der::Input signature_algorithm_tlv;
-  der::BitString signature_value;
-  if (!ParseCertificate(der::Input(CRYPTO_BUFFER_data(cert_handle),
-                                   CRYPTO_BUFFER_len(cert_handle)),
-                        &tbs_certificate_tlv, &signature_algorithm_tlv,
-                        &signature_value, nullptr)) {
-    return false;
-  }
-  ParsedTbsCertificate tbs;
-  if (!ParseTbsCertificate(tbs_certificate_tlv,
-                           x509_util::DefaultParseCertificateOptions(), &tbs,
-                           nullptr)) {
-    return false;
-  }
-
-  der::Input subject_value;
-  CertErrors errors;
-  std::string normalized_subject;
-  if (!GetSequenceValue(tbs.subject_tlv, &subject_value) ||
-      !NormalizeName(subject_value, &normalized_subject, &errors)) {
-    return false;
-  }
-  der::Input issuer_value;
-  std::string normalized_issuer;
-  if (!GetSequenceValue(tbs.issuer_tlv, &issuer_value) ||
-      !NormalizeName(issuer_value, &normalized_issuer, &errors)) {
-    return false;
-  }
-
-  if (normalized_subject != normalized_issuer)
-    return false;
-
-  std::unique_ptr<SignatureAlgorithm> signature_algorithm =
-      SignatureAlgorithm::Create(signature_algorithm_tlv, nullptr /* errors */);
-  if (!signature_algorithm)
-    return false;
-
-  // Don't enforce any minimum key size or restrict the algorithm, since when
-  // self signed not very relevant.
-  return VerifySignedData(*signature_algorithm, tbs_certificate_tlv,
-                          signature_value, tbs.spki_tlv);
-}
-
-// static
-X509Certificate::OSCertHandle X509Certificate::ReadOSCertHandleFromPickle(
-    base::PickleIterator* pickle_iter) {
-  const char* data;
-  int length;
-  if (!pickle_iter->ReadData(&data, &length))
-    return NULL;
-
-  return CreateOSCertHandleFromBytes(data, length);
-}
-
-// static
-void X509Certificate::WriteOSCertHandleToPickle(OSCertHandle cert_handle,
-                                                base::Pickle* pickle) {
-  pickle->WriteData(
-      reinterpret_cast<const char*>(CRYPTO_BUFFER_data(cert_handle)),
-      CRYPTO_BUFFER_len(cert_handle));
-}
-
-}  // namespace net
diff --git a/net/cert/x509_util_mac.h b/net/cert/x509_util_mac.h
index ea3e304..77050562 100644
--- a/net/cert/x509_util_mac.h
+++ b/net/cert/x509_util_mac.h
@@ -178,6 +178,12 @@
   CSSM_HANDLE cached_cert_handle_;
 };
 
+// Compares two OIDs by value.
+inline bool CSSMOIDEqual(const CSSM_OID* oid1, const CSSM_OID* oid2) {
+  return oid1->Length == oid2->Length &&
+         (memcmp(oid1->Data, oid2->Data, oid1->Length) == 0);
+}
+
 #pragma clang diagnostic pop  // "-Wdeprecated-declarations"
 
 }  // namespace x509_util
diff --git a/net/http/http_cache.cc b/net/http/http_cache.cc
index cf958b2..2ed7db8 100644
--- a/net/http/http_cache.cc
+++ b/net/http/http_cache.cc
@@ -116,6 +116,11 @@
   return HasNoTransactions() && !writers && !will_process_queued_transactions;
 }
 
+bool HttpCache::ActiveEntry::TransactionInReaders(
+    Transaction* transaction) const {
+  return readers.count(transaction) > 0;
+}
+
 //-----------------------------------------------------------------------------
 
 // This structure keeps track of work items that are attempting to create or
@@ -947,12 +952,18 @@
     return;
   }
 
-  // Add any idle writers to readers.
-  entry->writers.reset();
   if (success) {
-    entry->readers.insert(make_readers.begin(), make_readers.end());
+    // Add any idle writers to readers.
+    for (auto* reader : make_readers) {
+      reader->WriteModeTransactionAboutToBecomeReader();
+      entry->readers.insert(reader);
+    }
+    // Reset writers here so that WriteModeTransactionAboutToBecomeReader can
+    // access the network transaction.
+    entry->writers.reset();
     ProcessQueuedTransactions(entry);
   } else {
+    entry->writers.reset();
     ProcessEntryFailure(entry);
   }
 }
@@ -1072,16 +1083,37 @@
   DCHECK(!entry->done_headers_queue.empty());
 
   Transaction* transaction = entry->done_headers_queue.front();
+  bool is_partial = transaction->partial() != nullptr;
 
-  // If this transaction is responsible for writing the response body.
-  if (transaction->mode() & Transaction::WRITE) {
+  if (IsWritingInProgress(entry)) {
+    if (is_partial || transaction->mode() == Transaction::READ) {
+      // TODO(shivanisha): Returning from here instead of checking the next
+      // transaction in the queue because the FIFO order is maintained
+      // throughout, until it becomes a reader or writer. May be at this point
+      // the ordering is not important but that would be optimizing a rare
+      // scenario where write mode transactions are insterspersed with read-only
+      // transactions.
+      return;
+    }
     AddTransactionToWriters(entry, transaction);
-  } else {
-    // If a transaction is in front of this queue with only read mode set and
-    // there is no writer, it implies response body is already written, convert
-    // to a reader.
-    auto return_val = entry->readers.insert(transaction);
-    DCHECK_EQ(return_val.second, true);
+  } else {  // no writing in progress
+    if (transaction->mode() & Transaction::WRITE) {
+      if (is_partial) {
+        AddTransactionToWriters(entry, transaction);
+      } else {
+        // Add the transaction to readers since the response body should have
+        // already been written. (If it was the first writer about to start
+        // writing to the cache, it would have been added to writers in
+        // DoneWithResponseHeaders, thus no writers here signify the response
+        // was completely written).
+        transaction->WriteModeTransactionAboutToBecomeReader();
+        auto return_val = entry->readers.insert(transaction);
+        DCHECK(return_val.second);
+      }
+    } else {  // mode READ
+      auto return_val = entry->readers.insert(transaction);
+      DCHECK(return_val.second);
+    }
   }
 
   // Post another task to give a chance to more transactions to either join
@@ -1100,12 +1132,11 @@
 
   DCHECK(entry->writers->CanAddWriters());
 
-  // TODO(shivanisha), is_exclusive should be set conditionally. Currently
-  // setting it for all cases to test the reduced case of at most 1 writer.
   Writers::TransactionInfo info(transaction->partial(),
                                 transaction->is_truncated(),
                                 *(transaction->GetResponseInfo()));
-  entry->writers->AddTransaction(transaction, true /* is_exclusive */,
+  entry->writers->AddTransaction(transaction,
+                                 transaction->partial() /* is_exclusive */,
                                  transaction->priority(), info);
 }
 
diff --git a/net/http/http_cache.h b/net/http/http_cache.h
index c4c02b78..1a94ddf 100644
--- a/net/http/http_cache.h
+++ b/net/http/http_cache.h
@@ -292,6 +292,8 @@
     // writers is not present.
     bool SafeToDestroy();
 
+    bool TransactionInReaders(Transaction* transaction) const;
+
     disk_cache::Entry* disk_entry = nullptr;
 
     // Transactions waiting to be added to entry.
diff --git a/net/http/http_cache_transaction.cc b/net/http/http_cache_transaction.cc
index d4c3fba..d539e41 100644
--- a/net/http/http_cache_transaction.cc
+++ b/net/http/http_cache_transaction.cc
@@ -178,6 +178,7 @@
       cache_entry_status_(CacheEntryStatus::ENTRY_UNDEFINED),
       validation_cause_(VALIDATION_CAUSE_UNDEFINED),
       recorded_histograms_(false),
+      moved_network_transaction_to_writers_(false),
       websocket_handshake_stream_base_create_helper_(NULL),
       in_do_loop_(false),
       weak_factory_(this) {
@@ -401,15 +402,16 @@
   if (!InWriters()) {
     // Since transaction is not a writer and we are in Read(), it must be a
     // reader.
-    DCHECK(entry_->readers.count(this));
+    DCHECK(entry_->TransactionInReaders(this));
     DCHECK(mode_ == READ || (mode_ == READ_WRITE && partial_));
     next_state_ = STATE_CACHE_READ_DATA;
     return OK;
   }
 
+  DCHECK(mode_ & WRITE || mode_ == NONE);
+
   // If it's a writer and it is partial then it may need to read from the cache
   // or from the network based on whether network transaction is present or not.
-  DCHECK(mode_ == WRITE || mode_ == NONE || (mode_ == READ_WRITE && partial_));
   if (partial_) {
     if (entry_->writers->network_transaction())
       next_state_ = STATE_NETWORK_READ_CACHE_WRITE;
@@ -448,7 +450,7 @@
 
 bool HttpCache::Transaction::GetFullRequestHeaders(
     HttpRequestHeaders* headers) const {
-  const HttpTransaction* transaction = network_transaction();
+  const HttpTransaction* transaction = GetOwnedOrMovedNetworkTransaction();
   if (transaction) {
     return transaction->GetFullRequestHeaders(headers);
   } else if (!network_transaction_info_.full_request_headers.IsEmpty()) {
@@ -462,7 +464,7 @@
 
 int64_t HttpCache::Transaction::GetTotalReceivedBytes() const {
   int64_t total_received_bytes = network_transaction_info_.total_received_bytes;
-  const HttpTransaction* transaction = network_transaction();
+  const HttpTransaction* transaction = GetOwnedOrMovedNetworkTransaction();
   if (transaction)
     total_received_bytes += transaction->GetTotalReceivedBytes();
   return total_received_bytes;
@@ -470,7 +472,7 @@
 
 int64_t HttpCache::Transaction::GetTotalSentBytes() const {
   int64_t total_sent_bytes = network_transaction_info_.total_sent_bytes;
-  const HttpTransaction* transaction = network_transaction();
+  const HttpTransaction* transaction = GetOwnedOrMovedNetworkTransaction();
   if (transaction)
     total_sent_bytes += transaction->GetTotalSentBytes();
   return total_sent_bytes;
@@ -511,7 +513,7 @@
 
 bool HttpCache::Transaction::GetLoadTimingInfo(
     LoadTimingInfo* load_timing_info) const {
-  const HttpTransaction* transaction = network_transaction();
+  const HttpTransaction* transaction = GetOwnedOrMovedNetworkTransaction();
   if (transaction)
     return transaction->GetLoadTimingInfo(load_timing_info);
 
@@ -533,7 +535,7 @@
 }
 
 bool HttpCache::Transaction::GetRemoteEndpoint(IPEndPoint* endpoint) const {
-  const HttpTransaction* transaction = network_transaction();
+  const HttpTransaction* transaction = GetOwnedOrMovedNetworkTransaction();
   if (transaction)
     return transaction->GetRemoteEndpoint(endpoint);
 
@@ -547,7 +549,7 @@
 
 void HttpCache::Transaction::PopulateNetErrorDetails(
     NetErrorDetails* details) const {
-  const HttpTransaction* transaction = network_transaction();
+  const HttpTransaction* transaction = GetOwnedOrMovedNetworkTransaction();
   if (transaction)
     return transaction->PopulateNetErrorDetails(details);
   return;
@@ -607,7 +609,7 @@
 void HttpCache::Transaction::GetConnectionAttempts(
     ConnectionAttempts* out) const {
   ConnectionAttempts new_connection_attempts;
-  const HttpTransaction* transaction = network_transaction();
+  const HttpTransaction* transaction = GetOwnedOrMovedNetworkTransaction();
   if (transaction)
     transaction->GetConnectionAttempts(&new_connection_attempts);
 
@@ -636,7 +638,8 @@
 
   // Since the transaction can no longer access the network transaction, save
   // all network related info now.
-  if (InWriters() && entry_->writers->network_transaction()) {
+  if (InWriters() && entry_->writers->network_transaction() &&
+      moved_network_transaction_to_writers_) {
     SaveNetworkTransactionInfo(*(entry_->writers->network_transaction()));
   }
 
@@ -650,6 +653,14 @@
   }
 }
 
+void HttpCache::Transaction::WriteModeTransactionAboutToBecomeReader() {
+  mode_ = READ;
+  if (InWriters() && entry_->writers->network_transaction() &&
+      moved_network_transaction_to_writers_) {
+    SaveNetworkTransactionInfo(*(entry_->writers->network_transaction()));
+  }
+}
+
 //-----------------------------------------------------------------------------
 
 // A few common patterns: (Foo* means Foo -> FooComplete)
@@ -1784,7 +1795,8 @@
     DoneWithEntry(true);
   } else if (entry_ && !handling_206_) {
     DCHECK_EQ(READ_WRITE, mode_);
-    if (!partial_ || partial_->IsLastRange()) {
+    if ((!partial_ && !cache_->IsWritingInProgress(entry_)) ||
+        partial_->IsLastRange()) {
       mode_ = READ;
     }
     // We no longer need the network transaction, so destroy it.
@@ -2007,6 +2019,7 @@
 
   if (network_trans_ && InWriters()) {
     entry_->writers->SetNetworkTransaction(this, std::move(network_trans_));
+    moved_network_transaction_to_writers_ = true;
   }
 
   // If already reading, that means it is a partial request coming back to the
@@ -2057,7 +2070,6 @@
 
 int HttpCache::Transaction::DoNetworkReadCacheWriteComplete(int result) {
   TRACE_EVENT0("io", "HttpCacheTransaction::DoNetworkReadCacheWriteComplete");
-  DCHECK(mode_ & WRITE || mode_ == NONE);
   if (!cache_.get()) {
     TransitionToState(STATE_NONE);
     return ERR_UNEXPECTED;
@@ -2819,7 +2831,8 @@
     }
   }
 
-  mode_ = READ;
+  if (!cache_->IsWritingInProgress(entry_))
+    mode_ = READ;
 
   if (method_ == "HEAD")
     FixHeadersForHead();
@@ -3049,6 +3062,15 @@
   return nullptr;
 }
 
+const HttpTransaction*
+HttpCache::Transaction::GetOwnedOrMovedNetworkTransaction() const {
+  if (network_trans_)
+    return network_trans_.get();
+  if (InWriters() && moved_network_transaction_to_writers_)
+    return entry_->writers->network_transaction();
+  return nullptr;
+}
+
 HttpTransaction* HttpCache::Transaction::network_transaction() {
   return const_cast<HttpTransaction*>(
       static_cast<const Transaction*>(this)->network_transaction());
@@ -3306,9 +3328,11 @@
   if (transaction.GetLoadTimingInfo(&load_timing))
     network_transaction_info_.old_network_trans_load_timing.reset(
         new LoadTimingInfo(load_timing));
+
   network_transaction_info_.total_received_bytes +=
       transaction.GetTotalReceivedBytes();
   network_transaction_info_.total_sent_bytes += transaction.GetTotalSentBytes();
+
   ConnectionAttempts attempts;
   transaction.GetConnectionAttempts(&attempts);
   for (const auto& attempt : attempts)
@@ -3316,10 +3340,6 @@
   network_transaction_info_.old_remote_endpoint = IPEndPoint();
   transaction.GetRemoteEndpoint(&network_transaction_info_.old_remote_endpoint);
 
-  // Do not overwrite the headers for a full request again for a parallel
-  // writing transaction.
-  if (!partial_ && !network_transaction_info_.full_request_headers.IsEmpty())
-    return;
   transaction.GetFullRequestHeaders(
       &network_transaction_info_.full_request_headers);
 }
diff --git a/net/http/http_cache_transaction.h b/net/http/http_cache_transaction.h
index 1a498b9..ec0589ba 100644
--- a/net/http/http_cache_transaction.h
+++ b/net/http/http_cache_transaction.h
@@ -186,6 +186,10 @@
   // If result is an error code, a future Read should fail with |result|.
   void WriterAboutToBeRemovedFromEntry(int result);
 
+  // Invoked when this transaction is about to become a reader because the cache
+  // entry has finished writing.
+  void WriteModeTransactionAboutToBecomeReader();
+
  private:
   static const size_t kNumValidationHeaders = 2;
   // Helper struct to pair a header name with its value, for
@@ -479,6 +483,11 @@
   const HttpTransaction* network_transaction() const;
   HttpTransaction* network_transaction();
 
+  // Returns the network transaction from |this| or from writers only if it was
+  // moved from |this| to writers. This is so that statistics of the network
+  // transaction are not attributed to any other writer member.
+  const HttpTransaction* GetOwnedOrMovedNetworkTransaction() const;
+
   // Returns true if we should bother attempting to resume this request if it is
   // aborted while in progress. If |has_data| is true, the size of the stored
   // data is considered for the result.
@@ -592,6 +601,15 @@
 
   NetworkTransactionInfo network_transaction_info_;
 
+  // True if this transaction created the network transaction that is now being
+  // used by writers. This is used to check that only this transaction should
+  // account for the network bytes and other statistics of the network
+  // transaction.
+  // TODO(shivanisha) Note that if this transaction dies mid-way and there are
+  // other writer transactions, no transaction then accounts for those
+  // statistics.
+  bool moved_network_transaction_to_writers_;
+
   // The helper object to use to create WebSocketHandshakeStreamBase
   // objects. Only relevant when establishing a WebSocket connection.
   // This is passed to the underlying network transaction. It is stored here in
diff --git a/net/http/http_cache_unittest.cc b/net/http/http_cache_unittest.cc
index 6199e34..d312312 100644
--- a/net/http/http_cache_unittest.cc
+++ b/net/http/http_cache_unittest.cc
@@ -1389,19 +1389,15 @@
   // Allow all requests to move from the Create queue to the active entry.
   base::RunLoop().RunUntilIdle();
 
-  // The first request should be a writer at this point, and the subsequent
-  // requests should have passed the validation phase and waiting for the
-  // response to be written to the cache before they can read.
-  EXPECT_TRUE(cache.IsWriterPresent(kSimpleGET_Transaction.url));
-  EXPECT_EQ(kNumTransactions - 1,
-            cache.GetCountDoneHeadersQueue(kSimpleGET_Transaction.url));
+  // All requests are added to writers.
+  EXPECT_EQ(kNumTransactions,
+            cache.GetCountWriterTransactions(kSimpleGET_Transaction.url));
 
   EXPECT_EQ(1, cache.network_layer()->transaction_count());
   EXPECT_EQ(0, cache.disk_cache()->open_count());
   EXPECT_EQ(1, cache.disk_cache()->create_count());
 
-  // All requests depend on the writer, and the writer is between Start and
-  // Read, i.e. idle.
+  // All requests are between Start and Read, i.e. idle.
   for (auto& context : context_list) {
     EXPECT_EQ(LOAD_STATE_IDLE, context->trans->GetLoadState());
   }
@@ -1411,6 +1407,8 @@
     if (c->result == ERR_IO_PENDING)
       c->result = c->callback.WaitForResult();
 
+    // After the 1st transaction has completed the response, all transactions
+    // get added to readers.
     if (i > 0) {
       EXPECT_FALSE(cache.IsWriterPresent(kSimpleGET_Transaction.url));
       EXPECT_EQ(kNumTransactions - i,
@@ -1421,7 +1419,6 @@
   }
 
   // We should not have had to re-open the disk entry
-
   EXPECT_EQ(1, cache.network_layer()->transaction_count());
   EXPECT_EQ(0, cache.disk_cache()->open_count());
   EXPECT_EQ(1, cache.disk_cache()->create_count());
@@ -2131,24 +2128,21 @@
   // Allow all requests to move from the Create queue to the active entry.
   base::RunLoop().RunUntilIdle();
 
-  // The first request should be a writer at this point, and the second
-  // request should have passed the validation phase and created a new
-  // entry. Rest of them should be added to the new entry.
-  EXPECT_TRUE(cache.IsWriterPresent(kSimpleGET_Transaction.url));
-  EXPECT_EQ(3, cache.GetCountDoneHeadersQueue(kSimpleGET_Transaction.url));
+  // The new entry will have all the transactions except the first one which
+  // will continue in the doomed entry.
+  EXPECT_EQ(kNumTransactions - 1,
+            cache.GetCountWriterTransactions(kSimpleGET_Transaction.url));
+
+  EXPECT_EQ(1, cache.disk_cache()->doomed_count());
 
   EXPECT_EQ(2, cache.network_layer()->transaction_count());
   EXPECT_EQ(0, cache.disk_cache()->open_count());
   EXPECT_EQ(2, cache.disk_cache()->create_count());
 
-  // All requests depend on the writer, and the writer is between Start and
-  // Read, i.e. idle.
   for (auto& context : context_list) {
     EXPECT_EQ(LOAD_STATE_IDLE, context->trans->GetLoadState());
   }
 
-  EXPECT_EQ(1, cache.disk_cache()->doomed_count());
-
   for (size_t i = 0; i < context_list.size(); i++) {
     if (context_list[i]->result == ERR_IO_PENDING)
       context_list[i]->result = context_list[i]->callback.WaitForResult();
@@ -2234,6 +2228,10 @@
 
   MockHttpRequest request(kSimpleGET_Transaction);
 
+  MockTransaction transaction(kSimpleGET_Transaction);
+  transaction.load_flags |= LOAD_ONLY_FROM_CACHE;
+  MockHttpRequest read_only_request(transaction);
+
   std::vector<std::unique_ptr<Context>> context_list;
   const int kNumTransactions = 2;
 
@@ -2244,21 +2242,20 @@
     c->result = cache.CreateTransaction(&c->trans);
     ASSERT_THAT(c->result, IsOk());
 
-    c->result =
-        c->trans->Start(&request, c->callback.callback(), NetLogWithSource());
+    MockHttpRequest* current_request = i == 1 ? &read_only_request : &request;
+
+    c->result = c->trans->Start(current_request, c->callback.callback(),
+                                NetLogWithSource());
   }
 
   // Allow all requests to move from the Create queue to the active entry.
   base::RunLoop().RunUntilIdle();
 
-  // The first request should be a writer at this point, and the subsequent
-  // requests should have completed validation.
-
   EXPECT_EQ(1, cache.network_layer()->transaction_count());
   EXPECT_EQ(0, cache.disk_cache()->open_count());
   EXPECT_EQ(1, cache.disk_cache()->create_count());
 
-  EXPECT_TRUE(cache.IsWriterPresent(kSimpleGET_Transaction.url));
+  EXPECT_EQ(1, cache.GetCountWriterTransactions(kSimpleGET_Transaction.url));
   EXPECT_EQ(1, cache.GetCountDoneHeadersQueue(kSimpleGET_Transaction.url));
 
   context_list[1].reset();
@@ -2277,9 +2274,9 @@
   EXPECT_EQ(1, cache.disk_cache()->create_count());
 }
 
-// Tests that a transaction which is in validated queue can timeout and start
-// reading from the network without writing to the cache.
-TEST(HttpCache, SimpleGET_ParallelValidationValidatedTimeout) {
+// Tests that an idle writer transaction can be deleted without impacting the
+// existing writers.
+TEST(HttpCache, SimpleGET_ParallelWritingCancelIdleTransaction) {
   MockHttpCache cache;
 
   MockHttpRequest request(kSimpleGET_Transaction);
@@ -2291,9 +2288,6 @@
     context_list.push_back(std::make_unique<Context>());
     auto& c = context_list[i];
 
-    if (i == 1)
-      cache.SimulateCacheLockTimeoutAfterHeaders();
-
     c->result = cache.CreateTransaction(&c->trans);
     ASSERT_THAT(c->result, IsOk());
 
@@ -2304,24 +2298,83 @@
   // Allow all requests to move from the Create queue to the active entry.
   base::RunLoop().RunUntilIdle();
 
+  EXPECT_EQ(1, cache.network_layer()->transaction_count());
+  EXPECT_EQ(0, cache.disk_cache()->open_count());
+  EXPECT_EQ(1, cache.disk_cache()->create_count());
+
+  // Both transactions would be added to writers.
+  EXPECT_EQ(kNumTransactions,
+            cache.GetCountWriterTransactions(kSimpleGET_Transaction.url));
+
+  context_list[1].reset();
+
+  EXPECT_EQ(kNumTransactions - 1,
+            cache.GetCountWriterTransactions(kSimpleGET_Transaction.url));
+
+  // Complete the rest of the transactions.
+  for (auto& context : context_list) {
+    if (!context)
+      continue;
+    ReadAndVerifyTransaction(context->trans.get(), kSimpleGET_Transaction);
+  }
+
+  EXPECT_EQ(1, cache.network_layer()->transaction_count());
+  EXPECT_EQ(0, cache.disk_cache()->open_count());
+  EXPECT_EQ(1, cache.disk_cache()->create_count());
+}
+
+// Tests that a transaction which is in validated queue can timeout and start
+// the headers phase again.
+TEST(HttpCache, SimpleGET_ParallelValidationValidatedTimeout) {
+  MockHttpCache cache;
+
+  MockHttpRequest request(kSimpleGET_Transaction);
+
+  MockTransaction transaction(kSimpleGET_Transaction);
+  transaction.load_flags |= LOAD_ONLY_FROM_CACHE;
+  MockHttpRequest read_only_request(transaction);
+
+  std::vector<std::unique_ptr<Context>> context_list;
+  const int kNumTransactions = 2;
+
+  for (int i = 0; i < kNumTransactions; ++i) {
+    context_list.push_back(std::make_unique<Context>());
+    auto& c = context_list[i];
+
+    MockHttpRequest* this_request = &request;
+    if (i == 1) {
+      this_request = &read_only_request;
+      cache.SimulateCacheLockTimeoutAfterHeaders();
+    }
+
+    c->result = cache.CreateTransaction(&c->trans);
+    ASSERT_THAT(c->result, IsOk());
+
+    c->result = c->trans->Start(this_request, c->callback.callback(),
+                                NetLogWithSource());
+  }
+
+  // Allow all requests to move from the Create queue to the active entry.
+  base::RunLoop().RunUntilIdle();
+
   // The first request should be a writer at this point, and the subsequent
   // requests should have completed validation, timed out and restarted.
+  // Since it is a read only request, it will error out.
 
-  EXPECT_EQ(2, cache.network_layer()->transaction_count());
+  EXPECT_EQ(1, cache.network_layer()->transaction_count());
   EXPECT_EQ(0, cache.disk_cache()->open_count());
   EXPECT_EQ(1, cache.disk_cache()->create_count());
 
   EXPECT_TRUE(cache.IsWriterPresent(kSimpleGET_Transaction.url));
   EXPECT_EQ(0, cache.GetCountDoneHeadersQueue(kSimpleGET_Transaction.url));
 
-  // Complete the rest of the transactions.
-  for (auto& context : context_list) {
-    ReadAndVerifyTransaction(context->trans.get(), kSimpleGET_Transaction);
-  }
+  base::RunLoop().RunUntilIdle();
 
-  EXPECT_EQ(2, cache.network_layer()->transaction_count());
-  EXPECT_EQ(0, cache.disk_cache()->open_count());
-  EXPECT_EQ(1, cache.disk_cache()->create_count());
+  int rv = context_list[1]->callback.WaitForResult();
+  EXPECT_EQ(ERR_CACHE_MISS, rv);
+
+  ReadAndVerifyTransaction(context_list[0]->trans.get(),
+                           kSimpleGET_Transaction);
 }
 
 // Tests that a transaction which is in readers can be destroyed without
@@ -2362,8 +2415,8 @@
   EXPECT_EQ(0, cache.disk_cache()->open_count());
   EXPECT_EQ(1, cache.disk_cache()->create_count());
 
-  EXPECT_TRUE(cache.IsWriterPresent(kSimpleGET_Transaction.url));
-  EXPECT_EQ(2, cache.GetCountDoneHeadersQueue(kSimpleGET_Transaction.url));
+  EXPECT_EQ(kNumTransactions - 1,
+            cache.GetCountWriterTransactions(kSimpleGET_Transaction.url));
   EXPECT_TRUE(cache.IsHeadersTransactionPresent(kSimpleGET_Transaction.url));
 
   // Complete the response body.
@@ -2372,7 +2425,8 @@
 
   // Rest of the transactions should move to readers.
   EXPECT_FALSE(cache.IsWriterPresent(kSimpleGET_Transaction.url));
-  EXPECT_EQ(2, cache.GetCountReaders(kSimpleGET_Transaction.url));
+  EXPECT_EQ(kNumTransactions - 2,
+            cache.GetCountReaders(kSimpleGET_Transaction.url));
   EXPECT_EQ(0, cache.GetCountDoneHeadersQueue(kSimpleGET_Transaction.url));
   EXPECT_TRUE(cache.IsHeadersTransactionPresent(kSimpleGET_Transaction.url));
 
@@ -2405,11 +2459,10 @@
   auto& context = context_list[3];
   context->trans->ResumeNetworkStart();
 
-  // The pending transactions will be added to a new entry.
+  // The pending transactions will be added to a new entry as writers.
   base::RunLoop().RunUntilIdle();
 
-  EXPECT_EQ(2, cache.GetCountDoneHeadersQueue(kSimpleGET_Transaction.url));
-  EXPECT_TRUE(cache.IsWriterPresent(kSimpleGET_Transaction.url));
+  EXPECT_EQ(3, cache.GetCountWriterTransactions(kSimpleGET_Transaction.url));
 
   // Complete the rest of the transactions.
   for (int i = 2; i < kNumTransactions; ++i) {
@@ -2422,9 +2475,10 @@
   EXPECT_EQ(2, cache.disk_cache()->create_count());
 }
 
-// Tests that a transaction is in validated queue and writer is destroyed
-// leading to restarting the validated transaction.
-TEST(HttpCache, SimpleGET_ParallelValidationCancelWriter) {
+// Tests that a transaction writer can be destroyed mid-read.
+// A waiting for read transaction should be able to read the data that was
+// driven by the Read started by the cancelled writer.
+TEST(HttpCache, SimpleGET_ParallelWritingCancelWriter) {
   MockHttpCache cache;
 
   MockHttpRequest request(kSimpleGET_Transaction);
@@ -2460,43 +2514,304 @@
   EXPECT_EQ(0, cache.disk_cache()->open_count());
   EXPECT_EQ(1, cache.disk_cache()->create_count());
 
-  EXPECT_TRUE(cache.IsWriterPresent(kSimpleGET_Transaction.url));
   EXPECT_TRUE(cache.IsHeadersTransactionPresent(kSimpleGET_Transaction.url));
-  EXPECT_EQ(1, cache.GetCountDoneHeadersQueue(kSimpleGET_Transaction.url));
+  EXPECT_EQ(2, cache.GetCountWriterTransactions(kSimpleGET_Transaction.url));
 
-  // Deleting the writer at this point will lead to destroying the entry and
-  // restarting the remaining transactions which will then create a new entry.
-  context_list[0].reset();
+  // Initiate Read from both writers and kill 1 of them mid-read.
+  std::string first_read;
+  for (int i = 0; i < 2; i++) {
+    auto& c = context_list[i];
+    const int kBufferSize = 5;
+    scoped_refptr<IOBuffer> buffer(new IOBuffer(kBufferSize));
+    ReleaseBufferCompletionCallback cb(buffer.get());
+    c->result = c->trans->Read(buffer.get(), kBufferSize, cb.callback());
+    EXPECT_EQ(ERR_IO_PENDING, c->result);
+    // Deleting one writer at this point will not impact other transactions
+    // since writers contain more transactions.
+    if (i == 1) {
+      context_list[0].reset();
+      base::RunLoop().RunUntilIdle();
+      EXPECT_EQ(kBufferSize, cb.GetResult(c->result));
+      std::string data_read(buffer->data(), kBufferSize);
+      first_read = data_read;
+    }
+  }
 
-  // Resume network start for headers_transaction. It should be restarted due to
-  // writer cancellation.
+  // Resume network start for headers_transaction. It will doom the existing
+  // entry and create a new entry due to validation returning a 200.
   auto& c = context_list[2];
   c->trans->ResumeNetworkStart();
 
   base::RunLoop().RunUntilIdle();
 
-  EXPECT_TRUE(cache.IsWriterPresent(kSimpleGET_Transaction.url));
-  EXPECT_TRUE(cache.IsHeadersTransactionPresent(kSimpleGET_Transaction.url));
-
-  // Resume network start for the transaction the second time.
-  c->trans->ResumeNetworkStart();
-  base::RunLoop().RunUntilIdle();
+  EXPECT_EQ(1, cache.GetCountWriterTransactions(kSimpleGET_Transaction.url));
 
   // Complete the rest of the transactions.
-  for (auto& context : context_list) {
+  for (int i = 0; i < kNumTransactions; i++) {
+    auto& context = context_list[i];
     if (!context)
       continue;
-    ReadAndVerifyTransaction(context->trans.get(), kSimpleGET_Transaction);
+    if (i == 1)
+      ReadRemainingAndVerifyTransaction(context->trans.get(), first_read,
+                                        kSimpleGET_Transaction);
+    else
+      ReadAndVerifyTransaction(context->trans.get(), kSimpleGET_Transaction);
   }
 
-  EXPECT_EQ(4, cache.network_layer()->transaction_count());
+  EXPECT_EQ(2, cache.network_layer()->transaction_count());
   EXPECT_EQ(0, cache.disk_cache()->open_count());
-  EXPECT_EQ(3, cache.disk_cache()->create_count());
+  EXPECT_EQ(2, cache.disk_cache()->create_count());
 }
 
-// Tests when a writer is destroyed mid-read and entry is marked as truncated,
-// it should lead to restarting the dependent transactions.
-TEST(HttpCache, SimpleGET_ParallelValidationCancelWriterTruncateEntry) {
+// Tests the case when network read failure happens. Idle and waiting
+// transactions should fail and headers transaction should be restarted.
+TEST(HttpCache, SimpleGET_ParallelWritingNetworkReadFailed) {
+  MockHttpCache cache;
+
+  ScopedMockTransaction fail_transaction(kSimpleGET_Transaction);
+  fail_transaction.read_return_code = ERR_INTERNET_DISCONNECTED;
+  MockHttpRequest failing_request(fail_transaction);
+
+  MockHttpRequest request(kSimpleGET_Transaction);
+
+  MockTransaction transaction(kSimpleGET_Transaction);
+  transaction.load_flags |= LOAD_ONLY_FROM_CACHE;
+  MockHttpRequest read_request(transaction);
+
+  const int kNumTransactions = 4;
+  std::vector<std::unique_ptr<Context>> context_list;
+
+  for (int i = 0; i < kNumTransactions; ++i) {
+    context_list.push_back(std::make_unique<Context>());
+    auto& c = context_list[i];
+
+    c->result = cache.CreateTransaction(&c->trans);
+    ASSERT_THAT(c->result, IsOk());
+
+    MockHttpRequest* this_request = &request;
+    if (i == 0)
+      this_request = &failing_request;
+    if (i == 3)
+      this_request = &read_request;
+
+    c->result = c->trans->Start(this_request, c->callback.callback(),
+                                NetLogWithSource());
+  }
+
+  // Allow all requests to move from the Create queue to the active entry.
+  base::RunLoop().RunUntilIdle();
+
+  EXPECT_EQ(1, cache.network_layer()->transaction_count());
+  EXPECT_EQ(0, cache.disk_cache()->open_count());
+  EXPECT_EQ(1, cache.disk_cache()->create_count());
+
+  EXPECT_EQ(3, cache.GetCountWriterTransactions(kSimpleGET_Transaction.url));
+  EXPECT_EQ(1, cache.GetCountDoneHeadersQueue(kSimpleGET_Transaction.url));
+
+  // Initiate Read from two writers and let the first get a network failure.
+  for (int i = 0; i < 2; i++) {
+    auto& c = context_list[i];
+    const int kBufferSize = 5;
+    scoped_refptr<IOBuffer> buffer(new IOBuffer(kBufferSize));
+    c->result =
+        c->trans->Read(buffer.get(), kBufferSize, c->callback.callback());
+    EXPECT_EQ(ERR_IO_PENDING, c->result);
+  }
+
+  base::RunLoop().RunUntilIdle();
+  for (int i = 0; i < 2; i++) {
+    auto& c = context_list[i];
+    c->result = c->callback.WaitForResult();
+    EXPECT_EQ(ERR_INTERNET_DISCONNECTED, c->result);
+  }
+
+  // The entry should have been doomed and destroyed and the headers transaction
+  // restarted. Since headers transaction is read-only it will error out.
+  auto& read_only = context_list[3];
+  read_only->result = read_only->callback.WaitForResult();
+  EXPECT_EQ(ERR_CACHE_MISS, read_only->result);
+
+  EXPECT_FALSE(cache.IsWriterPresent(kSimpleGET_Transaction.url));
+
+  // Invoke Read on the 3rd transaction and it should get the error code back.
+  auto& c = context_list[2];
+  const int kBufferSize = 5;
+  scoped_refptr<IOBuffer> buffer(new IOBuffer(kBufferSize));
+  c->result = c->trans->Read(buffer.get(), kBufferSize, c->callback.callback());
+  EXPECT_EQ(ERR_INTERNET_DISCONNECTED, c->result);
+}
+
+// Tests the case when cache write failure happens. Idle and waiting
+// transactions should fail and headers transaction should be restarted.
+TEST(HttpCache, SimpleGET_ParallelWritingCacheWriteFailed) {
+  MockHttpCache cache;
+
+  MockHttpRequest request(kSimpleGET_Transaction);
+
+  MockTransaction transaction(kSimpleGET_Transaction);
+  transaction.load_flags |= LOAD_ONLY_FROM_CACHE;
+  MockHttpRequest read_request(transaction);
+
+  const int kNumTransactions = 4;
+  std::vector<std::unique_ptr<Context>> context_list;
+
+  for (int i = 0; i < kNumTransactions; ++i) {
+    context_list.push_back(std::make_unique<Context>());
+    auto& c = context_list[i];
+
+    c->result = cache.CreateTransaction(&c->trans);
+    ASSERT_THAT(c->result, IsOk());
+
+    MockHttpRequest* this_request = &request;
+    if (i == 3)
+      this_request = &read_request;
+
+    c->result = c->trans->Start(this_request, c->callback.callback(),
+                                NetLogWithSource());
+  }
+
+  // Allow all requests to move from the Create queue to the active entry.
+  base::RunLoop().RunUntilIdle();
+
+  EXPECT_EQ(1, cache.network_layer()->transaction_count());
+  EXPECT_EQ(0, cache.disk_cache()->open_count());
+  EXPECT_EQ(1, cache.disk_cache()->create_count());
+
+  EXPECT_EQ(3, cache.GetCountWriterTransactions(kSimpleGET_Transaction.url));
+  EXPECT_EQ(1, cache.GetCountDoneHeadersQueue(kSimpleGET_Transaction.url));
+
+  // Initiate Read from two writers and let the first get a cache write failure.
+  cache.disk_cache()->set_soft_failures(true);
+  // We have to open the entry again to propagate the failure flag.
+  disk_cache::Entry* en;
+  cache.OpenBackendEntry(kSimpleGET_Transaction.url, &en);
+  en->Close();
+  const int kBufferSize = 5;
+  std::vector<scoped_refptr<IOBuffer>> buffer(3, new IOBuffer(kBufferSize));
+  for (int i = 0; i < 2; i++) {
+    auto& c = context_list[i];
+    c->result =
+        c->trans->Read(buffer[i].get(), kBufferSize, c->callback.callback());
+    EXPECT_EQ(ERR_IO_PENDING, c->result);
+  }
+
+  std::string first_read;
+  base::RunLoop().RunUntilIdle();
+  for (int i = 0; i < 2; i++) {
+    auto& c = context_list[i];
+    c->result = c->callback.WaitForResult();
+    if (i == 0) {
+      EXPECT_EQ(5, c->result);
+      std::string data_read(buffer[i]->data(), kBufferSize);
+      first_read = data_read;
+    } else {
+      EXPECT_EQ(ERR_CACHE_WRITE_FAILURE, c->result);
+    }
+  }
+
+  // The entry should have been doomed and destroyed and the headers transaction
+  // restarted. Since headers transaction is read-only it will error out.
+  auto& read_only = context_list[3];
+  read_only->result = read_only->callback.WaitForResult();
+  EXPECT_EQ(ERR_CACHE_MISS, read_only->result);
+
+  EXPECT_FALSE(cache.IsWriterPresent(kSimpleGET_Transaction.url));
+
+  // Invoke Read on the 3rd transaction and it should get the error code back.
+  auto& c = context_list[2];
+  c->result =
+      c->trans->Read(buffer[2].get(), kBufferSize, c->callback.callback());
+  EXPECT_EQ(ERR_CACHE_WRITE_FAILURE, c->result);
+
+  // The first transaction should be able to continue to read from the network
+  // without writing to the cache.
+  auto& succ_read = context_list[0];
+  ReadRemainingAndVerifyTransaction(succ_read->trans.get(), first_read,
+                                    kSimpleGET_Transaction);
+}
+
+// Tests the case when parallel writing succeeds. Tests both idle and waiting
+// transactions.
+TEST(HttpCache, SimpleGET_ParallelWritingSuccess) {
+  MockHttpCache cache;
+
+  MockHttpRequest request(kSimpleGET_Transaction);
+
+  MockTransaction transaction(kSimpleGET_Transaction);
+  transaction.load_flags |= LOAD_ONLY_FROM_CACHE;
+  MockHttpRequest read_request(transaction);
+
+  const int kNumTransactions = 4;
+  std::vector<std::unique_ptr<Context>> context_list;
+
+  for (int i = 0; i < kNumTransactions; ++i) {
+    context_list.push_back(std::make_unique<Context>());
+    auto& c = context_list[i];
+
+    c->result = cache.CreateTransaction(&c->trans);
+    ASSERT_THAT(c->result, IsOk());
+
+    MockHttpRequest* this_request = &request;
+    if (i == 3)
+      this_request = &read_request;
+
+    c->result = c->trans->Start(this_request, c->callback.callback(),
+                                NetLogWithSource());
+  }
+
+  // Allow all requests to move from the Create queue to the active entry.
+  base::RunLoop().RunUntilIdle();
+
+  EXPECT_EQ(1, cache.network_layer()->transaction_count());
+  EXPECT_EQ(0, cache.disk_cache()->open_count());
+  EXPECT_EQ(1, cache.disk_cache()->create_count());
+
+  EXPECT_EQ(3, cache.GetCountWriterTransactions(kSimpleGET_Transaction.url));
+  EXPECT_EQ(1, cache.GetCountDoneHeadersQueue(kSimpleGET_Transaction.url));
+
+  // Initiate Read from two writers.
+  const int kBufferSize = 5;
+  std::vector<scoped_refptr<IOBuffer>> buffer(3, new IOBuffer(kBufferSize));
+  for (int i = 0; i < 2; i++) {
+    auto& c = context_list[i];
+    c->result =
+        c->trans->Read(buffer[i].get(), kBufferSize, c->callback.callback());
+    EXPECT_EQ(ERR_IO_PENDING, c->result);
+  }
+
+  std::vector<std::string> first_read(2);
+  base::RunLoop().RunUntilIdle();
+  for (int i = 0; i < 2; i++) {
+    auto& c = context_list[i];
+    c->result = c->callback.WaitForResult();
+    EXPECT_EQ(5, c->result);
+    std::string data_read(buffer[i]->data(), kBufferSize);
+    first_read[i] = data_read;
+  }
+  EXPECT_EQ(first_read[0], first_read[1]);
+
+  // The first transaction should be able to continue to read from the network
+  // without writing to the cache.
+  for (int i = 0; i < 2; i++) {
+    auto& c = context_list[i];
+    ReadRemainingAndVerifyTransaction(c->trans.get(), first_read[i],
+                                      kSimpleGET_Transaction);
+    if (i == 0) {
+      // Remaining transactions should now be readers.
+      EXPECT_EQ(3, cache.GetCountReaders(kSimpleGET_Transaction.url));
+    }
+  }
+
+  // Verify the rest of the transactions.
+  for (int i = 2; i < kNumTransactions; i++) {
+    auto& c = context_list[i];
+    ReadAndVerifyTransaction(c->trans.get(), kSimpleGET_Transaction);
+  }
+}
+
+// Tests when a writer is destroyed mid-read, all the other writer transactions
+// can continue writing to the entry.
+TEST(HttpCache, SimpleGET_ParallelValidationCancelWriter) {
   MockHttpCache cache;
 
   ScopedMockTransaction transaction(kSimpleGET_Transaction);
@@ -2527,11 +2842,10 @@
   EXPECT_EQ(0, cache.disk_cache()->open_count());
   EXPECT_EQ(1, cache.disk_cache()->create_count());
 
-  EXPECT_TRUE(cache.IsWriterPresent(kSimpleGET_Transaction.url));
-  EXPECT_EQ(2, cache.GetCountDoneHeadersQueue(kSimpleGET_Transaction.url));
+  EXPECT_EQ(kNumTransactions,
+            cache.GetCountWriterTransactions(kSimpleGET_Transaction.url));
 
-  // Let first transaction read some bytes, so that entry can be marked as
-  // truncated.
+  // Let first transaction read some bytes.
   {
     auto& c = context_list[0];
     const int kBufferSize = 5;
@@ -2541,14 +2855,13 @@
     EXPECT_EQ(kBufferSize, cb.GetResult(c->result));
   }
 
-  // Deleting the writer at this point will lead to restarting the remaining
-  // transactions which will then be able to read the truncated status of the
-  // entry.
+  // Deleting the active transaction at this point will not impact the other
+  // transactions since there are other transactions in writers.
   context_list[0].reset();
 
   base::RunLoop().RunUntilIdle();
 
-  EXPECT_EQ(2, cache.network_layer()->transaction_count());
+  EXPECT_EQ(1, cache.network_layer()->transaction_count());
   EXPECT_EQ(0, cache.disk_cache()->open_count());
   EXPECT_EQ(1, cache.disk_cache()->create_count());
 
@@ -2568,6 +2881,61 @@
   MockHttpRequest request(kSimpleGET_Transaction);
 
   MockTransaction transaction(kSimpleGET_Transaction);
+  transaction.load_flags |= LOAD_ONLY_FROM_CACHE;
+  MockHttpRequest read_only_request(transaction);
+
+  const int kNumTransactions = 2;
+  std::vector<std::unique_ptr<Context>> context_list;
+
+  for (int i = 0; i < kNumTransactions; ++i) {
+    context_list.push_back(std::make_unique<Context>());
+    auto& c = context_list[i];
+
+    c->result = cache.CreateTransaction(&c->trans);
+    ASSERT_THAT(c->result, IsOk());
+
+    MockHttpRequest* this_request = &request;
+    if (i == 1) {
+      this_request = &read_only_request;
+    }
+
+    c->result = c->trans->Start(this_request, c->callback.callback(),
+                                NetLogWithSource());
+  }
+
+  // Allow all requests to move from the Create queue to the active entry.
+  base::RunLoop().RunUntilIdle();
+
+  EXPECT_EQ(1, cache.network_layer()->transaction_count());
+  EXPECT_EQ(0, cache.disk_cache()->open_count());
+  EXPECT_EQ(1, cache.disk_cache()->create_count());
+
+  EXPECT_EQ(kNumTransactions - 1,
+            cache.GetCountWriterTransactions(kSimpleGET_Transaction.url));
+  EXPECT_EQ(1, cache.GetCountDoneHeadersQueue(kSimpleGET_Transaction.url));
+
+  // Invoking StopCaching on the writer will lead to dooming the entry and
+  // restarting the validated transactions. Since it is a read-only transaction
+  // it will error out.
+  context_list[0]->trans->StopCaching();
+
+  base::RunLoop().RunUntilIdle();
+
+  int rv = context_list[1]->callback.WaitForResult();
+  EXPECT_EQ(ERR_CACHE_MISS, rv);
+
+  ReadAndVerifyTransaction(context_list[0]->trans.get(),
+                           kSimpleGET_Transaction);
+}
+
+// Tests that when StopCaching is invoked on a writer transaction, it is a
+// no-op if there are other writer transactions.
+TEST(HttpCache, SimpleGET_ParallelWritersStopCachingNoOp) {
+  MockHttpCache cache;
+
+  MockHttpRequest request(kSimpleGET_Transaction);
+
+  MockTransaction transaction(kSimpleGET_Transaction);
   transaction.load_flags |= LOAD_VALIDATE_CACHE;
   MockHttpRequest validate_request(transaction);
 
@@ -2598,27 +2966,21 @@
   EXPECT_EQ(0, cache.disk_cache()->open_count());
   EXPECT_EQ(1, cache.disk_cache()->create_count());
 
-  EXPECT_TRUE(cache.IsWriterPresent(kSimpleGET_Transaction.url));
   EXPECT_TRUE(cache.IsHeadersTransactionPresent(kSimpleGET_Transaction.url));
-  EXPECT_EQ(1, cache.GetCountDoneHeadersQueue(kSimpleGET_Transaction.url));
+  EXPECT_EQ(kNumTransactions - 1,
+            cache.GetCountWriterTransactions(kSimpleGET_Transaction.url));
 
-  // Invoking StopCaching on the writer will lead to dooming the entry and
-  // restarting the remaining transactions which will then create a new entry.
+  // Invoking StopCaching on the writer will be a no-op since there are multiple
+  // transaction in writers.
   context_list[0]->trans->StopCaching();
 
-  // Resume network start for headers_transaction. It should be restarted due to
-  // writer cancellation.
+  // Resume network start for headers_transaction.
   auto& c = context_list[2];
   c->trans->ResumeNetworkStart();
-
   base::RunLoop().RunUntilIdle();
-
-  EXPECT_TRUE(cache.IsWriterPresent(kSimpleGET_Transaction.url));
-  EXPECT_TRUE(cache.IsHeadersTransactionPresent(kSimpleGET_Transaction.url));
-
-  // Resume network start for the transaction the second time.
-  c->trans->ResumeNetworkStart();
-  base::RunLoop().RunUntilIdle();
+  // After validation old entry will be doomed and headers_transaction will be
+  // added to the new entry.
+  EXPECT_EQ(1, cache.GetCountWriterTransactions(kSimpleGET_Transaction.url));
 
   // Complete the rest of the transactions.
   for (auto& context : context_list) {
@@ -2627,9 +2989,9 @@
     ReadAndVerifyTransaction(context->trans.get(), kSimpleGET_Transaction);
   }
 
-  EXPECT_EQ(4, cache.network_layer()->transaction_count());
+  EXPECT_EQ(2, cache.network_layer()->transaction_count());
   EXPECT_EQ(0, cache.disk_cache()->open_count());
-  EXPECT_EQ(3, cache.disk_cache()->create_count());
+  EXPECT_EQ(2, cache.disk_cache()->create_count());
 }
 
 // Tests that a transaction is currently in headers phase and is destroyed
@@ -2684,7 +3046,7 @@
 
 // Similar to the above test, except here cache write fails and the
 // validated transactions should be restarted.
-TEST(HttpCache, SimpleGET_ParallelValidationFailWrite) {
+TEST(HttpCache, SimpleGET_ParallelWritersFailWrite) {
   MockHttpCache cache;
 
   MockHttpRequest request(kSimpleGET_Transaction);
@@ -2712,11 +3074,9 @@
   // Allow all requests to move from the Create queue to the active entry.
   base::RunLoop().RunUntilIdle();
 
-  // The first request should be a writer at this point, and the subsequent
-  // requests should have passed the validation phase and waiting for the
-  // response to be written to the cache before they can read.
-  EXPECT_TRUE(cache.IsWriterPresent(kSimpleGET_Transaction.url));
-  EXPECT_EQ(4, cache.GetCountDoneHeadersQueue(kSimpleGET_Transaction.url));
+  // All transactions become writers.
+  EXPECT_EQ(kNumTransactions,
+            cache.GetCountWriterTransactions(kSimpleGET_Transaction.url));
 
   // All requests depend on the writer, and the writer is between Start and
   // Read, i.e. idle.
@@ -2724,10 +3084,6 @@
     EXPECT_EQ(LOAD_STATE_IDLE, context->trans->GetLoadState());
   }
 
-  // The first request should be a writer at this point, and the subsequent
-  // requests should have passed the validation phase and waiting for the
-  // response to be written to the cache before they can read.
-
   EXPECT_EQ(1, cache.network_layer()->transaction_count());
   EXPECT_EQ(0, cache.disk_cache()->open_count());
   EXPECT_EQ(1, cache.disk_cache()->create_count());
@@ -2748,14 +3104,19 @@
       EXPECT_TRUE(
           cache.disk_cache()->IsDiskEntryDoomed(kSimpleGET_Transaction.url));
     }
-    ReadAndVerifyTransaction(c->trans.get(), kSimpleGET_Transaction);
-  }
 
-  // Since validated transactions were restarted and new entry read/write
-  // operations would also fail, all requests would have gone to the network.
-  EXPECT_EQ(5, cache.network_layer()->transaction_count());
-  EXPECT_EQ(1, cache.disk_cache()->open_count());
-  EXPECT_EQ(5, cache.disk_cache()->create_count());
+    if (i == 0) {
+      // Consumer gets the response even if cache write failed.
+      ReadAndVerifyTransaction(c->trans.get(), kSimpleGET_Transaction);
+    } else {
+      // Read should lead to a failure being returned.
+      const int kBufferSize = 5;
+      scoped_refptr<IOBuffer> buffer(new IOBuffer(kBufferSize));
+      ReleaseBufferCompletionCallback cb(buffer.get());
+      c->result = c->trans->Read(buffer.get(), kBufferSize, cb.callback());
+      EXPECT_EQ(ERR_CACHE_WRITE_FAILURE, cb.GetResult(c->result));
+    }
+  }
 }
 
 // This is a test for http://code.google.com/p/chromium/issues/detail?id=4769.
@@ -2963,11 +3324,13 @@
   }
 
   // Allow all requests to move from the Create queue to the active entry.
+  // All would have been added to writers.
   base::RunLoop().RunUntilIdle();
+  EXPECT_EQ(kNumTransactions,
+            cache.GetCountWriterTransactions(kSimpleGET_Transaction.url));
 
-  // The first request should be a writer at this point, and the subsequent
-  // requests should be pending.
-
+  // The second transaction skipped validation, thus only one network
+  // transaction is created.
   EXPECT_EQ(1, cache.network_layer()->transaction_count());
   EXPECT_EQ(0, cache.disk_cache()->open_count());
   EXPECT_EQ(1, cache.disk_cache()->create_count());
@@ -2977,9 +3340,8 @@
     if (c->result == ERR_IO_PENDING)
       c->result = c->callback.WaitForResult();
     // Destroy only the first transaction.
-    // This should lead to all transactions to restart, even those that have
-    // validated themselves and were waiting for the writer transaction to
-    // complete writing to the cache.
+    // This should not impact the other writer transaction and the network
+    // transaction will continue to be used by that transaction.
     if (i == 0) {
       context_list[i].reset();
     }
@@ -2991,11 +3353,9 @@
     ReadAndVerifyTransaction(c->trans.get(), kSimpleGET_Transaction);
   }
 
-  // We should have had to re-open the disk entry.
-
-  EXPECT_EQ(2, cache.network_layer()->transaction_count());
+  EXPECT_EQ(1, cache.network_layer()->transaction_count());
   EXPECT_EQ(0, cache.disk_cache()->open_count());
-  EXPECT_EQ(2, cache.disk_cache()->create_count());
+  EXPECT_EQ(1, cache.disk_cache()->create_count());
 }
 
 // Tests that we can cancel requests that are queued waiting to open the disk
diff --git a/net/http/http_cache_writers.cc b/net/http/http_cache_writers.cc
index 338129ef..c8ca995e0 100644
--- a/net/http/http_cache_writers.cc
+++ b/net/http/http_cache_writers.cc
@@ -117,10 +117,10 @@
   should_keep_entry_ =
       IsValidResponseForWriter(info.partial != nullptr, &(info.response_info));
 
-  if (info.partial && !info.truncated)
+  if (info.partial && !info.truncated) {
+    DCHECK(!partial_do_not_truncate_);
     partial_do_not_truncate_ = true;
-  else
-    partial_do_not_truncate_ = false;
+  }
 
   std::pair<Transaction*, TransactionInfo> writer(transaction, info);
   all_writers_.insert(writer);
@@ -553,11 +553,9 @@
     // Invoke entry processing.
     DCHECK(ContainsOnlyIdleWriters());
     TransactionSet make_readers;
-    for (auto& writer : all_writers_) {
+    for (auto& writer : all_writers_)
       make_readers.insert(writer.first);
-    }
     all_writers_.clear();
-    network_transaction_.reset();
     SetCacheCallback(true, make_readers);
     return;
   }
@@ -607,7 +605,7 @@
     it = waiting_for_read_.erase(it);
 
     // If its response completion or failure, this transaction needs to be
-    // removed.
+    // removed from writers.
     if (result <= 0)
       EraseTransaction(transaction, result);
   }
diff --git a/net/http/http_cache_writers.h b/net/http/http_cache_writers.h
index 8410ecff..0d9ad28 100644
--- a/net/http/http_cache_writers.h
+++ b/net/http/http_cache_writers.h
@@ -240,7 +240,6 @@
   void EraseTransaction(Transaction* transaction, int result);
   TransactionMap::iterator EraseTransaction(TransactionMap::iterator it,
                                             int result);
-
   void SetCacheCallback(bool success, const TransactionSet& make_readers);
 
   // IO Completion callback function.
diff --git a/net/http/http_stream_factory_impl.cc b/net/http/http_stream_factory_impl.cc
index d44bbe6..caaaa31 100644
--- a/net/http/http_stream_factory_impl.cc
+++ b/net/http/http_stream_factory_impl.cc
@@ -246,9 +246,9 @@
 
 void HttpStreamFactoryImpl::AddJobControllerCountToHistograms() {
   // Only log the count of JobControllers when the count is hitting one of the
-  // boundaries for the first time which is a multiple of 100: 100, 200, 300,
-  // etc.
-  if (job_controller_set_.size() % 100 != 0 ||
+  // boundaries for the first time which is a multiple of 1000: 1000, 2000,
+  // 3000, etc.
+  if (job_controller_set_.size() % 1000 != 0 ||
       job_controller_set_.size() <= last_logged_job_controller_count_) {
     return;
   }
@@ -260,12 +260,8 @@
   size_t num_controllers_with_request = 0;
   size_t num_controllers_for_preconnect = 0;
   for (const auto& job_controller : job_controller_set_) {
-    DCHECK(job_controller->HasPendingAltJob() ||
-           job_controller->HasPendingMainJob());
-    // Additionally logs the states of the jobs if there are at least 500
-    // controllers, which suggests that there might be a leak.
-    if (job_controller_set_.size() >= 500)
-      job_controller->LogHistograms();
+    // Additionally log the states of the jobs.
+    job_controller->LogHistograms();
     // For a preconnect controller, it should have exactly the main job.
     if (job_controller->is_preconnect()) {
       num_controllers_for_preconnect++;
diff --git a/net/http/mock_http_cache.cc b/net/http/mock_http_cache.cc
index f425d84..f1cb3a27 100644
--- a/net/http/mock_http_cache.cc
+++ b/net/http/mock_http_cache.cc
@@ -735,23 +735,22 @@
 
 int MockHttpCache::GetCountReaders(const std::string& key) {
   HttpCache::ActiveEntry* entry = http_cache_.FindActiveEntry(key);
-  if (entry)
-    return entry->readers.size();
-  return false;
+  return entry ? entry->readers.size() : 0;
 }
 
 int MockHttpCache::GetCountAddToEntryQueue(const std::string& key) {
   HttpCache::ActiveEntry* entry = http_cache_.FindActiveEntry(key);
-  if (entry)
-    return entry->add_to_entry_queue.size();
-  return false;
+  return entry ? entry->add_to_entry_queue.size() : 0;
 }
 
 int MockHttpCache::GetCountDoneHeadersQueue(const std::string& key) {
   HttpCache::ActiveEntry* entry = http_cache_.FindActiveEntry(key);
-  if (entry)
-    return entry->done_headers_queue.size();
-  return false;
+  return entry ? entry->done_headers_queue.size() : 0;
+}
+
+int MockHttpCache::GetCountWriterTransactions(const std::string& key) {
+  HttpCache::ActiveEntry* entry = http_cache_.FindActiveEntry(key);
+  return entry && entry->writers ? entry->writers->GetTransactionsCount() : 0;
 }
 
 //-----------------------------------------------------------------------------
diff --git a/net/http/mock_http_cache.h b/net/http/mock_http_cache.h
index 97bfded..6e4589ab 100644
--- a/net/http/mock_http_cache.h
+++ b/net/http/mock_http_cache.h
@@ -299,6 +299,7 @@
   int GetCountReaders(const std::string& key);
   int GetCountAddToEntryQueue(const std::string& key);
   int GetCountDoneHeadersQueue(const std::string& key);
+  int GetCountWriterTransactions(const std::string& key);
 
  private:
   HttpCache http_cache_;
diff --git a/net/http/transport_security_state.cc b/net/http/transport_security_state.cc
index 964494f..4d658e27 100644
--- a/net/http/transport_security_state.cc
+++ b/net/http/transport_security_state.cc
@@ -898,7 +898,7 @@
   ExpectCTState state;
   if (is_issued_by_known_root && IsDynamicExpectCTEnabled() &&
       GetDynamicExpectCTState(hostname, &state)) {
-    if (expect_ct_reporter_ && !state.report_uri.is_empty() &&
+    if (!complies && expect_ct_reporter_ && !state.report_uri.is_empty() &&
         report_status == ENABLE_EXPECT_CT_REPORTS) {
       MaybeNotifyExpectCTFailed(host_port_pair, state.report_uri, state.expiry,
                                 validated_certificate_chain,
diff --git a/net/http/transport_security_state_unittest.cc b/net/http/transport_security_state_unittest.cc
index 3d0abd3..e71f2dc 100644
--- a/net/http/transport_security_state_unittest.cc
+++ b/net/http/transport_security_state_unittest.cc
@@ -2522,6 +2522,45 @@
   EXPECT_EQ(1u, reporter.num_failures());
 }
 
+// Tests that the Expect-CT reporter is not notified for CT-compliant
+// connections.
+TEST_F(TransportSecurityStateTest, DynamicExpectCTCompliantConnection) {
+  const char kHeader[] = "max-age=123,report-uri=\"http://foo.test\"";
+  SSLInfo ssl;
+  ssl.is_issued_by_known_root = true;
+  ssl.ct_compliance_details_available = true;
+  ssl.ct_cert_policy_compliance =
+      ct::CertPolicyCompliance::CERT_POLICY_COMPLIES_VIA_SCTS;
+
+  scoped_refptr<X509Certificate> cert1 =
+      ImportCertFromFile(GetTestCertsDirectory(), "ok_cert.pem");
+  ASSERT_TRUE(cert1);
+  scoped_refptr<X509Certificate> cert2 =
+      ImportCertFromFile(GetTestCertsDirectory(), "expired_cert.pem");
+  ASSERT_TRUE(cert2);
+
+  SignedCertificateTimestampAndStatusList sct_list;
+
+  base::test::ScopedFeatureList feature_list;
+  feature_list.InitAndEnableFeature(
+      TransportSecurityState::kDynamicExpectCTFeature);
+
+  TransportSecurityState state;
+  MockExpectCTReporter reporter;
+  state.SetExpectCTReporter(&reporter);
+  state.ProcessExpectCTHeader(kHeader, HostPortPair("example.test", 443), ssl);
+
+  // No report should be sent when the header was processed over a connection
+  // that complied with CT policy.
+  EXPECT_EQ(TransportSecurityState::CT_NOT_REQUIRED,
+            state.CheckCTRequirements(
+                HostPortPair("example.test", 443), true, HashValueVector(),
+                cert1.get(), cert2.get(), sct_list,
+                TransportSecurityState::ENABLE_EXPECT_CT_REPORTS,
+                ct::CertPolicyCompliance::CERT_POLICY_COMPLIES_VIA_SCTS));
+  EXPECT_EQ(0u, reporter.num_failures());
+}
+
 // Tests that the Expect-CT reporter is not notified when the Expect-CT header
 // is received repeatedly over non-compliant connections.
 TEST_F(TransportSecurityStateTest, DynamicExpectCTHeaderProcessingDeduping) {
@@ -3259,13 +3298,7 @@
   EXPECT_TRUE(StaticShouldRedirect("foo.crate.io"));
 }
 
-// http://crbug.com/624946
-#if defined(OS_IOS)
-#define MAYBE_PreloadedPins DISABLED_PreloadedPins
-#else
-#define MAYBE_PreloadedPins PreloadedPins
-#endif
-TEST_F(TransportSecurityStateStaticTest, MAYBE_PreloadedPins) {
+TEST_F(TransportSecurityStateStaticTest, PreloadedPins) {
   TransportSecurityState state;
   EnableStaticPins(&state);
   TransportSecurityState::STSState sts_state;
@@ -3395,13 +3428,7 @@
   EXPECT_TRUE(HasStaticPublicKeyPins("si0.twimg.com"));
 }
 
-// http://crbug.com/624946
-#if defined(OS_IOS)
-#define MAYBE_OptionalHSTSCertPins DISABLED_OptionalHSTSCertPins
-#else
-#define MAYBE_OptionalHSTSCertPins OptionalHSTSCertPins
-#endif
-TEST_F(TransportSecurityStateStaticTest, MAYBE_OptionalHSTSCertPins) {
+TEST_F(TransportSecurityStateStaticTest, OptionalHSTSCertPins) {
   TransportSecurityState state;
   EnableStaticPins(&state);
 
@@ -3438,4 +3465,4 @@
 }
 #endif  // BUILDFLAG(INCLUDE_TRANSPORT_SECURITY_STATE_PRELOAD_LIST)
 
-}  // namespace net
\ No newline at end of file
+}  // namespace net
diff --git a/net/nqe/network_quality.cc b/net/nqe/network_quality.cc
index 293d4cb..f54b00b 100644
--- a/net/nqe/network_quality.cc
+++ b/net/nqe/network_quality.cc
@@ -13,7 +13,7 @@
 }
 
 NetworkQuality::NetworkQuality()
-    : NetworkQuality(InvalidRTT(), InvalidRTT(), kInvalidThroughput) {}
+    : NetworkQuality(InvalidRTT(), InvalidRTT(), INVALID_RTT_THROUGHPUT) {}
 
 NetworkQuality::NetworkQuality(const base::TimeDelta& http_rtt,
                                const base::TimeDelta& transport_rtt,
@@ -21,7 +21,7 @@
     : http_rtt_(http_rtt),
       transport_rtt_(transport_rtt),
       downstream_throughput_kbps_(downstream_throughput_kbps) {
-  DCHECK_GE(downstream_throughput_kbps_, kInvalidThroughput);
+  DCHECK_GE(downstream_throughput_kbps_, INVALID_RTT_THROUGHPUT);
 }
 
 NetworkQuality::NetworkQuality(const NetworkQuality& other)
@@ -50,8 +50,8 @@
          (transport_rtt() == InvalidRTT() ||
           other.transport_rtt() == InvalidRTT() ||
           transport_rtt() <= other.transport_rtt()) &&
-         (downstream_throughput_kbps() == kInvalidThroughput ||
-          other.downstream_throughput_kbps() == kInvalidThroughput ||
+         (downstream_throughput_kbps() == INVALID_RTT_THROUGHPUT ||
+          other.downstream_throughput_kbps() == INVALID_RTT_THROUGHPUT ||
           downstream_throughput_kbps() >= other.downstream_throughput_kbps());
 }
 
diff --git a/net/nqe/network_quality.h b/net/nqe/network_quality.h
index a4c5f84..73afb69 100644
--- a/net/nqe/network_quality.h
+++ b/net/nqe/network_quality.h
@@ -30,13 +30,6 @@
 // |INVALID_RTT_THROUGHPUT|.
 NET_EXPORT_PRIVATE base::TimeDelta InvalidRTT();
 
-// Throughput is set to |kInvalidThroughput| if a valid value is
-// unavailable. Readers should discard throughput value if it is set to
-// |kInvalidThroughput|.
-// TODO(tbansal): Remove this variable, and replace all calls by
-// |INVALID_RTT_THROUGHPUT|.
-const int32_t kInvalidThroughput = INVALID_RTT_THROUGHPUT;
-
 // NetworkQuality is used to cache the quality of a network connection.
 class NET_EXPORT_PRIVATE NetworkQuality {
  public:
diff --git a/net/nqe/network_quality_estimator.cc b/net/nqe/network_quality_estimator.cc
index d48e6b0..fb4541d 100644
--- a/net/nqe/network_quality_estimator.cc
+++ b/net/nqe/network_quality_estimator.cc
@@ -314,7 +314,8 @@
   }
 
   if (params_->DefaultObservation(current_network_id_.type)
-          .downstream_throughput_kbps() != nqe::internal::kInvalidThroughput) {
+          .downstream_throughput_kbps() !=
+      nqe::internal::INVALID_RTT_THROUGHPUT) {
     Observation throughput_observation(
         params_->DefaultObservation(current_network_id_.type)
             .downstream_throughput_kbps(),
@@ -475,7 +476,7 @@
 
   int32_t recent_downstream_throughput_kbps;
   if (estimated_quality_at_last_main_frame_.downstream_throughput_kbps() !=
-          nqe::internal::kInvalidThroughput &&
+          nqe::internal::INVALID_RTT_THROUGHPUT &&
       GetRecentDownlinkThroughputKbps(last_main_frame_request_,
                                       &recent_downstream_throughput_kbps)) {
     const int estimated_observed_diff =
@@ -578,7 +579,7 @@
   int32_t rtt = 0;
 
   if (estimated_quality_at_last_main_frame_.downstream_throughput_kbps() ==
-      nqe::internal::kInvalidThroughput) {
+      nqe::internal::INVALID_RTT_THROUGHPUT) {
     return;
   }
 
@@ -924,7 +925,7 @@
                             nqe::internal::InvalidRTT());
 
   if (estimated_quality_at_last_main_frame_.downstream_throughput_kbps() !=
-      nqe::internal::kInvalidThroughput) {
+      nqe::internal::INVALID_RTT_THROUGHPUT) {
     // Add the 50th percentile value.
     UMA_HISTOGRAM_COUNTS_1M(
         "NQE.MainFrame.Kbps.Percentile50",
@@ -933,7 +934,7 @@
   UMA_HISTOGRAM_BOOLEAN(
       "NQE.EstimateAvailable.MainFrame.Kbps",
       estimated_quality_at_last_main_frame_.downstream_throughput_kbps() !=
-          nqe::internal::kInvalidThroughput);
+          nqe::internal::INVALID_RTT_THROUGHPUT);
 
   UMA_HISTOGRAM_ENUMERATION("NQE.MainFrame.EffectiveConnectionType",
                             effective_connection_type_at_last_main_frame_,
@@ -962,7 +963,7 @@
 
   int32_t downlink_throughput_kbps =
       GetDownlinkThroughputKbpsEstimateInternal(base::TimeTicks(), 20);
-  if (downlink_throughput_kbps == nqe::internal::kInvalidThroughput)
+  if (downlink_throughput_kbps == nqe::internal::INVALID_RTT_THROUGHPUT)
     return;
 
   bandwidth_delay_product_kbits_ =
@@ -1101,7 +1102,7 @@
 
   base::TimeDelta http_rtt = nqe::internal::InvalidRTT();
   base::TimeDelta transport_rtt = nqe::internal::InvalidRTT();
-  int32_t downstream_throughput_kbps = nqe::internal::kInvalidThroughput;
+  int32_t downstream_throughput_kbps = nqe::internal::INVALID_RTT_THROUGHPUT;
 
   effective_connection_type_ =
       GetRecentEffectiveConnectionTypeAndNetworkQuality(
@@ -1157,7 +1158,7 @@
 
   base::TimeDelta http_rtt = nqe::internal::InvalidRTT();
   base::TimeDelta transport_rtt = nqe::internal::InvalidRTT();
-  int32_t downstream_throughput_kbps = nqe::internal::kInvalidThroughput;
+  int32_t downstream_throughput_kbps = nqe::internal::INVALID_RTT_THROUGHPUT;
 
   return GetRecentEffectiveConnectionTypeAndNetworkQuality(
       start_time, &http_rtt, &transport_rtt, &downstream_throughput_kbps);
@@ -1231,7 +1232,7 @@
 
   *http_rtt = nqe::internal::InvalidRTT();
   *transport_rtt = nqe::internal::InvalidRTT();
-  *downstream_throughput_kbps = nqe::internal::kInvalidThroughput;
+  *downstream_throughput_kbps = nqe::internal::INVALID_RTT_THROUGHPUT;
 
   if (params_->forced_effective_connection_type()) {
     *http_rtt = params_
@@ -1283,7 +1284,7 @@
   }
 
   if (!GetRecentDownlinkThroughputKbps(start_time, downstream_throughput_kbps))
-    *downstream_throughput_kbps = nqe::internal::kInvalidThroughput;
+    *downstream_throughput_kbps = nqe::internal::INVALID_RTT_THROUGHPUT;
 
   if (*http_rtt == nqe::internal::InvalidRTT() &&
       http_rtt_metric == NetworkQualityEstimator::MetricUsage::MUST_BE_USED) {
@@ -1296,7 +1297,7 @@
     return EFFECTIVE_CONNECTION_TYPE_UNKNOWN;
   }
 
-  if (*downstream_throughput_kbps == nqe::internal::kInvalidThroughput &&
+  if (*downstream_throughput_kbps == nqe::internal::INVALID_RTT_THROUGHPUT &&
       downstream_throughput_kbps_metric ==
           NetworkQualityEstimator::MetricUsage::MUST_BE_USED) {
     return EFFECTIVE_CONNECTION_TYPE_UNKNOWN;
@@ -1304,7 +1305,7 @@
 
   if (*http_rtt == nqe::internal::InvalidRTT() &&
       *transport_rtt == nqe::internal::InvalidRTT() &&
-      *downstream_throughput_kbps == nqe::internal::kInvalidThroughput) {
+      *downstream_throughput_kbps == nqe::internal::INVALID_RTT_THROUGHPUT) {
     // None of the metrics are available.
     return EFFECTIVE_CONNECTION_TYPE_UNKNOWN;
   }
@@ -1335,9 +1336,9 @@
     const bool estimated_throughput_is_lower_than_threshold =
         downstream_throughput_kbps_metric !=
             NetworkQualityEstimator::MetricUsage::DO_NOT_USE &&
-        *downstream_throughput_kbps != nqe::internal::kInvalidThroughput &&
+        *downstream_throughput_kbps != nqe::internal::INVALID_RTT_THROUGHPUT &&
         params_->ConnectionThreshold(type).downstream_throughput_kbps() !=
-            nqe::internal::kInvalidThroughput &&
+            nqe::internal::INVALID_RTT_THROUGHPUT &&
         *downstream_throughput_kbps <=
             params_->ConnectionThreshold(type).downstream_throughput_kbps();
 
@@ -1416,7 +1417,7 @@
     int32_t* kbps) const {
   DCHECK(thread_checker_.CalledOnValidThread());
   *kbps = GetDownlinkThroughputKbpsEstimateInternal(start_time, 50);
-  return (*kbps != nqe::internal::kInvalidThroughput);
+  return (*kbps != nqe::internal::INVALID_RTT_THROUGHPUT);
 }
 
 base::TimeDelta NetworkQualityEstimator::GetRTTEstimateInternal(
@@ -1536,7 +1537,7 @@
   const base::TimeTicks now = tick_clock_->NowTicks();
 
   if (cached_network_quality.network_quality().downstream_throughput_kbps() !=
-      nqe::internal::kInvalidThroughput) {
+      nqe::internal::INVALID_RTT_THROUGHPUT) {
     Observation througphput_observation(
         cached_network_quality.network_quality().downstream_throughput_kbps(),
         now, INT32_MIN,
@@ -1662,7 +1663,7 @@
 void NetworkQualityEstimator::AddAndNotifyObserversOfThroughput(
     const Observation& observation) {
   DCHECK(thread_checker_.CalledOnValidThread());
-  DCHECK_NE(nqe::internal::kInvalidThroughput, observation.value());
+  DCHECK_NE(nqe::internal::INVALID_RTT_THROUGHPUT, observation.value());
   DCHECK_GT(NETWORK_QUALITY_OBSERVATION_SOURCE_MAX, observation.source());
 
   downstream_throughput_kbps_observations_.AddObservation(observation);
@@ -1692,7 +1693,7 @@
   if (downstream_kbps <= 0)
     return;
 
-  DCHECK_NE(nqe::internal::kInvalidThroughput, downstream_kbps);
+  DCHECK_NE(nqe::internal::INVALID_RTT_THROUGHPUT, downstream_kbps);
 
   Observation throughput_observation(downstream_kbps, tick_clock_->NowTicks(),
                                      signal_strength_,
@@ -1810,7 +1811,7 @@
               it.second.network_quality().http_rtt());
     DCHECK_EQ(nqe::internal::InvalidRTT(),
               it.second.network_quality().transport_rtt());
-    DCHECK_EQ(nqe::internal::kInvalidThroughput,
+    DCHECK_EQ(nqe::internal::INVALID_RTT_THROUGHPUT,
               it.second.network_quality().downstream_throughput_kbps());
 
     nqe::internal::CachedNetworkQuality cached_network_quality(
@@ -1845,7 +1846,7 @@
   DCHECK(thread_checker_.CalledOnValidThread());
 
   if (network_quality_.downstream_throughput_kbps() ==
-      nqe::internal::kInvalidThroughput) {
+      nqe::internal::INVALID_RTT_THROUGHPUT) {
     return base::Optional<int32_t>();
   }
   return network_quality_.downstream_throughput_kbps();
@@ -1890,7 +1891,7 @@
 
   // TODO(tbansal): crbug.com/673977: Remove this check.
   if (cached_network_quality.network_quality().downstream_throughput_kbps() !=
-      nqe::internal::kInvalidThroughput) {
+      nqe::internal::INVALID_RTT_THROUGHPUT) {
     Observation throughput_observation(
         cached_network_quality.network_quality().downstream_throughput_kbps(),
         base::TimeTicks::Now(), INT32_MIN,
diff --git a/net/nqe/network_quality_estimator_params.cc b/net/nqe/network_quality_estimator_params.cc
index 5e9a1761..d74212b 100644
--- a/net/nqe/network_quality_estimator_params.cc
+++ b/net/nqe/network_quality_estimator_params.cc
@@ -138,7 +138,7 @@
     DCHECK_EQ(nqe::internal::InvalidRTT(), default_observations[i].http_rtt());
     DCHECK_EQ(nqe::internal::InvalidRTT(),
               default_observations[i].transport_rtt());
-    DCHECK_EQ(nqe::internal::kInvalidThroughput,
+    DCHECK_EQ(nqe::internal::INVALID_RTT_THROUGHPUT,
               default_observations[i].downstream_throughput_kbps());
   }
 
@@ -242,7 +242,7 @@
               typical_network_quality[i].http_rtt());
     DCHECK_EQ(nqe::internal::InvalidRTT(),
               typical_network_quality[i].transport_rtt());
-    DCHECK_EQ(nqe::internal::kInvalidThroughput,
+    DCHECK_EQ(nqe::internal::INVALID_RTT_THROUGHPUT,
               typical_network_quality[i].downstream_throughput_kbps());
   }
 
@@ -295,21 +295,21 @@
           // Set to the 66th percentile of 2G RTT observations on Android.
           base::TimeDelta::FromMilliseconds(2010),
           base::TimeDelta::FromMilliseconds(1870),
-          nqe::internal::kInvalidThroughput);
+          nqe::internal::INVALID_RTT_THROUGHPUT);
 
   default_effective_connection_type_thresholds[EFFECTIVE_CONNECTION_TYPE_2G] =
       nqe::internal::NetworkQuality(
           // Set to the 50th percentile of RTT observations on Android.
           base::TimeDelta::FromMilliseconds(1420),
           base::TimeDelta::FromMilliseconds(1280),
-          nqe::internal::kInvalidThroughput);
+          nqe::internal::INVALID_RTT_THROUGHPUT);
 
   default_effective_connection_type_thresholds[EFFECTIVE_CONNECTION_TYPE_3G] =
       nqe::internal::NetworkQuality(
           // Set to the 50th percentile of 3G RTT observations on Android.
           base::TimeDelta::FromMilliseconds(273),
           base::TimeDelta::FromMilliseconds(204),
-          nqe::internal::kInvalidThroughput);
+          nqe::internal::INVALID_RTT_THROUGHPUT);
 
   // Connection threshold should not be set for 4G effective connection type
   // since it is the fastest.
@@ -325,7 +325,7 @@
     DCHECK_EQ(nqe::internal::InvalidRTT(), connection_thresholds[i].http_rtt());
     DCHECK_EQ(nqe::internal::InvalidRTT(),
               connection_thresholds[i].transport_rtt());
-    DCHECK_EQ(nqe::internal::kInvalidThroughput,
+    DCHECK_EQ(nqe::internal::INVALID_RTT_THROUGHPUT,
               connection_thresholds[i].downstream_throughput_kbps());
     if (effective_connection_type == EFFECTIVE_CONNECTION_TYPE_UNKNOWN)
       continue;
@@ -426,7 +426,7 @@
       hanging_request_duration_http_rtt_multiplier_(GetValueForVariationParam(
           params_,
           "hanging_request_duration_http_rtt_multiplier",
-          -1)),
+          5)),
       hanging_request_min_duration_(base::TimeDelta::FromMilliseconds(
           GetValueForVariationParam(params_,
                                     "hanging_request_min_duration_msec",
diff --git a/net/nqe/network_quality_estimator_params_unittest.cc b/net/nqe/network_quality_estimator_params_unittest.cc
index 288cd72..3626f19 100644
--- a/net/nqe/network_quality_estimator_params_unittest.cc
+++ b/net/nqe/network_quality_estimator_params_unittest.cc
@@ -81,7 +81,7 @@
     // The typical throughput for an effective connection type should not be
     // more than the threshold throughput.
     if (params.ConnectionThreshold(ect).downstream_throughput_kbps() !=
-        nqe::internal::kInvalidThroughput) {
+        nqe::internal::INVALID_RTT_THROUGHPUT) {
       EXPECT_LT(params.TypicalNetworkQuality(ect).downstream_throughput_kbps(),
                 params.ConnectionThreshold(ect).downstream_throughput_kbps());
     }
@@ -97,7 +97,8 @@
           .transport_rtt(),
       params.ConnectionThreshold(EFFECTIVE_CONNECTION_TYPE_3G).transport_rtt());
   if (params.ConnectionThreshold(EFFECTIVE_CONNECTION_TYPE_3G)
-          .downstream_throughput_kbps() != nqe::internal::kInvalidThroughput) {
+          .downstream_throughput_kbps() !=
+      nqe::internal::INVALID_RTT_THROUGHPUT) {
     EXPECT_GT(params.TypicalNetworkQuality(EFFECTIVE_CONNECTION_TYPE_4G)
                   .downstream_throughput_kbps(),
               params.ConnectionThreshold(EFFECTIVE_CONNECTION_TYPE_3G)
@@ -144,4 +145,4 @@
 
 }  // namespace nqe
 
-}  // namespace net
\ No newline at end of file
+}  // namespace net
diff --git a/net/nqe/network_quality_estimator_unittest.cc b/net/nqe/network_quality_estimator_unittest.cc
index 6eefee2..84e239c 100644
--- a/net/nqe/network_quality_estimator_unittest.cc
+++ b/net/nqe/network_quality_estimator_unittest.cc
@@ -95,7 +95,7 @@
   TestRTTAndThroughputEstimatesObserver()
       : http_rtt_(nqe::internal::InvalidRTT()),
         transport_rtt_(nqe::internal::InvalidRTT()),
-        downstream_throughput_kbps_(nqe::internal::kInvalidThroughput),
+        downstream_throughput_kbps_(nqe::internal::INVALID_RTT_THROUGHPUT),
         notifications_received_(0) {}
 
   // RTTAndThroughputEstimatesObserver implementation:
@@ -606,7 +606,7 @@
             estimator.GetRTTEstimateInternal(
                 disallowed_observation_sources, base::TimeTicks(),
                 base::Optional<NetworkQualityEstimator::Statistic>(), 100));
-  EXPECT_EQ(nqe::internal::kInvalidThroughput,
+  EXPECT_EQ(nqe::internal::INVALID_RTT_THROUGHPUT,
             estimator.GetDownlinkThroughputKbpsEstimateInternal(
                 base::TimeTicks(), 100));
 
@@ -1898,7 +1898,7 @@
 
   EXPECT_EQ(nqe::internal::InvalidRTT(), observer.http_rtt());
   EXPECT_EQ(nqe::internal::InvalidRTT(), observer.transport_rtt());
-  EXPECT_EQ(nqe::internal::kInvalidThroughput,
+  EXPECT_EQ(nqe::internal::INVALID_RTT_THROUGHPUT,
             observer.downstream_throughput_kbps());
   int notifications_received = observer.notifications_received();
   EXPECT_EQ(0, notifications_received);
@@ -1955,12 +1955,12 @@
   estimator.AddRTTAndThroughputEstimatesObserver(&observer_2);
   EXPECT_EQ(nqe::internal::InvalidRTT(), observer_2.http_rtt());
   EXPECT_EQ(nqe::internal::InvalidRTT(), observer_2.transport_rtt());
-  EXPECT_EQ(nqe::internal::kInvalidThroughput,
+  EXPECT_EQ(nqe::internal::INVALID_RTT_THROUGHPUT,
             observer_2.downstream_throughput_kbps());
   base::RunLoop().RunUntilIdle();
   EXPECT_NE(nqe::internal::InvalidRTT(), observer_2.http_rtt());
   EXPECT_NE(nqe::internal::InvalidRTT(), observer_2.transport_rtt());
-  EXPECT_NE(nqe::internal::kInvalidThroughput,
+  EXPECT_NE(nqe::internal::INVALID_RTT_THROUGHPUT,
             observer_2.downstream_throughput_kbps());
 
   // |observer_3| should not be notified because it is unregisters before the
@@ -1969,13 +1969,13 @@
   estimator.AddRTTAndThroughputEstimatesObserver(&observer_3);
   EXPECT_EQ(nqe::internal::InvalidRTT(), observer_3.http_rtt());
   EXPECT_EQ(nqe::internal::InvalidRTT(), observer_3.transport_rtt());
-  EXPECT_EQ(nqe::internal::kInvalidThroughput,
+  EXPECT_EQ(nqe::internal::INVALID_RTT_THROUGHPUT,
             observer_3.downstream_throughput_kbps());
   estimator.RemoveRTTAndThroughputEstimatesObserver(&observer_3);
   base::RunLoop().RunUntilIdle();
   EXPECT_EQ(nqe::internal::InvalidRTT(), observer_3.http_rtt());
   EXPECT_EQ(nqe::internal::InvalidRTT(), observer_3.transport_rtt());
-  EXPECT_EQ(nqe::internal::kInvalidThroughput,
+  EXPECT_EQ(nqe::internal::INVALID_RTT_THROUGHPUT,
             observer_3.downstream_throughput_kbps());
 }
 
@@ -2635,7 +2635,7 @@
           // unavailable.
           false, 0.3, 0.4, base::TimeDelta::FromSeconds(1), 1000 >> kTrimBits,
           base::TimeDelta::FromSeconds(2), 2000 >> kTrimBits,
-          nqe::internal::kInvalidThroughput, 3000 >> kTrimBits,
+          nqe::internal::INVALID_RTT_THROUGHPUT, 3000 >> kTrimBits,
       },
       {
           // Verify that the metric is recorded if the logging probability is
@@ -2716,7 +2716,8 @@
           "NQE.Correlation.ResourceLoadTime.0Kb_128Kb", 0);
       continue;
     }
-    if (test.downstream_throughput_kbps == nqe::internal::kInvalidThroughput) {
+    if (test.downstream_throughput_kbps ==
+        nqe::internal::INVALID_RTT_THROUGHPUT) {
       histogram_tester.ExpectTotalCount(
           "NQE.Correlation.ResourceLoadTime.0Kb_128Kb", 0);
       continue;
@@ -2898,7 +2899,7 @@
                   rtt_throughput_observer.http_rtt());
         EXPECT_EQ(nqe::internal::InvalidRTT(),
                   rtt_throughput_observer.transport_rtt());
-        EXPECT_EQ(nqe::internal::kInvalidThroughput,
+        EXPECT_EQ(nqe::internal::INVALID_RTT_THROUGHPUT,
                   rtt_throughput_observer.downstream_throughput_kbps());
       } else {
         EXPECT_EQ(estimator.params_->TypicalNetworkQuality(ect_type).http_rtt(),
diff --git a/net/nqe/rtt_throughput_estimates_observer.h b/net/nqe/rtt_throughput_estimates_observer.h
index 00a96ea..bf05c5d 100644
--- a/net/nqe/rtt_throughput_estimates_observer.h
+++ b/net/nqe/rtt_throughput_estimates_observer.h
@@ -28,7 +28,7 @@
   // throughput (in kilobits per second), respectively. If an estimate of the
   // HTTP or transport RTT is unavailable, it will be set to
   // nqe::internal::InvalidRTT(). If the throughput estimate is unavailable,
-  // it will be set to nqe::internal::kInvalidThroughput.
+  // it will be set to nqe::internal::INVALID_RTT_THROUGHPUT.
   virtual void OnRTTOrThroughputEstimatesComputed(
       base::TimeDelta http_rtt,
       base::TimeDelta transport_rtt,
diff --git a/net/quic/chromium/bidirectional_stream_quic_impl_unittest.cc b/net/quic/chromium/bidirectional_stream_quic_impl_unittest.cc
index e447186..e238ab3 100644
--- a/net/quic/chromium/bidirectional_stream_quic_impl_unittest.cc
+++ b/net/quic/chromium/bidirectional_stream_quic_impl_unittest.cc
@@ -953,17 +953,28 @@
   AddWrite(ConstructRequestHeadersPacketInner(
       2, GetNthClientInitiatedStreamId(0), !kFin, DEFAULT_PRIORITY,
       &spdy_request_headers_frame_length, &header_stream_offset));
-  AddWrite(ConstructClientMultipleDataFramesPacket(3, kIncludeVersion, !kFin, 0,
-                                                   {kBody1, kBody2}));
+  if (FLAGS_quic_reloadable_flag_quic_use_mem_slices) {
+    AddWrite(ConstructDataPacket(3, kIncludeVersion, !kFin, 0,
+                                 "here are some datadata keep coming",
+                                 &client_maker_));
+  } else {
+    AddWrite(ConstructClientMultipleDataFramesPacket(3, kIncludeVersion, !kFin,
+                                                     0, {kBody1, kBody2}));
+  }
   // Ack server's data packet.
   AddWrite(ConstructClientAckPacket(4, 3, 1, 1));
   const char kBody3[] = "hello there";
   const char kBody4[] = "another piece of small data";
   const char kBody5[] = "really small";
   QuicStreamOffset data_offset = strlen(kBody1) + strlen(kBody2);
-  AddWrite(ConstructClientMultipleDataFramesPacket(
-      5, !kIncludeVersion, kFin, data_offset, {kBody3, kBody4, kBody5}));
-
+  if (FLAGS_quic_reloadable_flag_quic_use_mem_slices) {
+    AddWrite(ConstructDataPacket(
+        5, !kIncludeVersion, kFin, data_offset,
+        "hello thereanother piece of small datareally small", &client_maker_));
+  } else {
+    AddWrite(ConstructClientMultipleDataFramesPacket(
+        5, !kIncludeVersion, kFin, data_offset, {kBody3, kBody4, kBody5}));
+  }
   Initialize();
 
   BidirectionalStreamRequestInfo request;
@@ -1157,19 +1168,27 @@
   AddWrite(ConstructInitialSettingsPacket(1, &header_stream_offset));
   const char kBody1[] = "here are some data";
   const char kBody2[] = "data keep coming";
+  const char kBody1And2[] = "here are some datadata keep coming";
   std::vector<std::string> two_writes = {kBody1, kBody2};
+  std::vector<std::string> one_write = {kBody1And2};
   AddWrite(ConstructRequestHeadersAndMultipleDataFramesPacket(
       2, !kFin, DEFAULT_PRIORITY, &header_stream_offset,
-      &spdy_request_headers_frame_length, two_writes));
+      &spdy_request_headers_frame_length,
+      FLAGS_quic_reloadable_flag_quic_use_mem_slices ? one_write : two_writes));
   // Ack server's data packet.
   AddWrite(ConstructClientAckPacket(3, 3, 1, 1));
   const char kBody3[] = "hello there";
   const char kBody4[] = "another piece of small data";
   const char kBody5[] = "really small";
   QuicStreamOffset data_offset = strlen(kBody1) + strlen(kBody2);
-  AddWrite(ConstructClientMultipleDataFramesPacket(
-      4, !kIncludeVersion, kFin, data_offset, {kBody3, kBody4, kBody5}));
-
+  if (FLAGS_quic_reloadable_flag_quic_use_mem_slices) {
+    AddWrite(ConstructDataPacket(
+        4, !kIncludeVersion, kFin, data_offset,
+        "hello thereanother piece of small datareally small", &client_maker_));
+  } else {
+    AddWrite(ConstructClientMultipleDataFramesPacket(
+        4, !kIncludeVersion, kFin, data_offset, {kBody3, kBody4, kBody5}));
+  }
   Initialize();
 
   BidirectionalStreamRequestInfo request;
diff --git a/net/quic/chromium/quic_chromium_client_stream_test.cc b/net/quic/chromium/quic_chromium_client_stream_test.cc
index 84c3975..984ab7b 100644
--- a/net/quic/chromium/quic_chromium_client_stream_test.cc
+++ b/net/quic/chromium/quic_chromium_client_stream_test.cc
@@ -599,9 +599,14 @@
       new StringIOBuffer("Just a small payload"));
 
   // All data written.
-  EXPECT_CALL(session_, WritevData(stream_, stream_->id(), _, _, _))
-      .WillOnce(Return(QuicConsumedData(buf1->size(), false)))
-      .WillOnce(Return(QuicConsumedData(buf2->size(), true)));
+  if (session_.can_use_slices()) {
+    EXPECT_CALL(session_, WritevData(stream_, stream_->id(), _, _, _))
+        .WillOnce(Return(QuicConsumedData(buf1->size() + buf2->size(), true)));
+  } else {
+    EXPECT_CALL(session_, WritevData(stream_, stream_->id(), _, _, _))
+        .WillOnce(Return(QuicConsumedData(buf1->size(), false)))
+        .WillOnce(Return(QuicConsumedData(buf2->size(), true)));
+  }
   TestCompletionCallback callback;
   EXPECT_EQ(
       OK, handle_->WritevStreamData({buf1, buf2}, {buf1->size(), buf2->size()},
@@ -614,11 +619,16 @@
       new StringIOBuffer("Just a small payload"));
 
   // Only a part of the data is written.
-  EXPECT_CALL(session_, WritevData(stream_, stream_->id(), _, _, _))
-      // First piece of data is written.
-      .WillOnce(Return(QuicConsumedData(buf1->size(), false)))
-      // Second piece of data is queued.
-      .WillOnce(Return(QuicConsumedData(0, false)));
+  if (session_.can_use_slices()) {
+    EXPECT_CALL(session_, WritevData(stream_, stream_->id(), _, _, _))
+        .WillOnce(Return(QuicConsumedData(buf1->size(), false)));
+  } else {
+    EXPECT_CALL(session_, WritevData(stream_, stream_->id(), _, _, _))
+        // First piece of data is written.
+        .WillOnce(Return(QuicConsumedData(buf1->size(), false)))
+        // Second piece of data is queued.
+        .WillOnce(Return(QuicConsumedData(0, false)));
+  }
   TestCompletionCallback callback;
   EXPECT_EQ(ERR_IO_PENDING,
             handle_->WritevStreamData({buf1.get(), buf2.get()},
diff --git a/net/quic/chromium/quic_chromium_packet_writer.cc b/net/quic/chromium/quic_chromium_packet_writer.cc
index d9c6c1d..7b9829a 100644
--- a/net/quic/chromium/quic_chromium_packet_writer.cc
+++ b/net/quic/chromium/quic_chromium_packet_writer.cc
@@ -25,11 +25,18 @@
   NUM_NOT_REUSABLE_REASONS = 3,
 };
 
+const int kMaxRetries = 20;
+
 void RecordNotReusableReason(NotReusableReason reason) {
   UMA_HISTOGRAM_ENUMERATION("Net.QuicSession.WritePacketNotReusable", reason,
                             NUM_NOT_REUSABLE_REASONS);
 }
 
+void RecordRetryCount(int count) {
+  UMA_HISTOGRAM_EXACT_LINEAR("Net.QuicSession.RetryAfterWriteErrorCount", count,
+                             kMaxRetries + 1);
+}
+
 }  // namespace
 
 QuicChromiumPacketWriter::ReusableIOBuffer::ReusableIOBuffer(size_t capacity)
@@ -52,6 +59,7 @@
       delegate_(nullptr),
       packet_(new ReusableIOBuffer(kMaxPacketSize)),
       write_blocked_(false),
+      retry_count_(0),
       weak_factory_(this) {
   write_callback_ = base::Bind(&QuicChromiumPacketWriter::OnWriteComplete,
                                weak_factory_.GetWeakPtr());
@@ -98,6 +106,9 @@
   base::TimeTicks now = base::TimeTicks::Now();
   int rv = socket_->Write(packet_.get(), packet_->size(), write_callback_);
 
+  if (MaybeRetryAfterWriteError(rv))
+    return WriteResult(WRITE_STATUS_BLOCKED, ERR_IO_PENDING);
+
   if (rv < 0 && rv != ERR_IO_PENDING && delegate_ != nullptr) {
     // If write error, then call delegate's HandleWriteError, which
     // may be able to migrate and rewrite packet on a new socket.
@@ -127,6 +138,13 @@
   return WriteResult(status, rv);
 }
 
+void QuicChromiumPacketWriter::RetryPacketAfterNoBuffers() {
+  DCHECK_GT(retry_count_, 0);
+  WriteResult result = WritePacketToSocketImpl();
+  if (result.error_code != ERR_IO_PENDING)
+    OnWriteComplete(result.error_code);
+}
+
 bool QuicChromiumPacketWriter::IsWriteBlockedDataBuffered() const {
   // Chrome sockets' Write() methods buffer the data until the Write is
   // permitted.
@@ -146,6 +164,9 @@
   DCHECK(delegate_) << "Uninitialized delegate.";
   write_blocked_ = false;
   if (rv < 0) {
+    if (MaybeRetryAfterWriteError(rv))
+      return;
+
     // If write error, then call delegate's HandleWriteError, which
     // may be able to migrate and rewrite packet on a new socket.
     // HandleWriteError returns the outcome of that rewrite attempt.
@@ -154,6 +175,10 @@
     if (rv == ERR_IO_PENDING)
       return;
   }
+  if (retry_count_ != 0) {
+    RecordRetryCount(retry_count_);
+    retry_count_ = 0;
+  }
 
   if (rv < 0)
     delegate_->OnWriteError(rv);
@@ -161,6 +186,24 @@
     delegate_->OnWriteUnblocked();
 }
 
+bool QuicChromiumPacketWriter::MaybeRetryAfterWriteError(int rv) {
+  if (rv != ERR_NO_BUFFER_SPACE)
+    return false;
+
+  if (retry_count_ >= kMaxRetries) {
+    RecordRetryCount(retry_count_);
+    return false;
+  }
+
+  retry_timer_.Start(
+      FROM_HERE, base::TimeDelta::FromMilliseconds(1),
+      base::Bind(&QuicChromiumPacketWriter::RetryPacketAfterNoBuffers,
+                 weak_factory_.GetWeakPtr()));
+  retry_count_++;
+  write_blocked_ = true;
+  return true;
+}
+
 QuicByteCount QuicChromiumPacketWriter::GetMaxPacketSize(
     const QuicSocketAddress& peer_address) const {
   return kMaxPacketSize;
diff --git a/net/quic/chromium/quic_chromium_packet_writer.h b/net/quic/chromium/quic_chromium_packet_writer.h
index daf4c85ca..5e1f3e27 100644
--- a/net/quic/chromium/quic_chromium_packet_writer.h
+++ b/net/quic/chromium/quic_chromium_packet_writer.h
@@ -9,6 +9,7 @@
 
 #include "base/macros.h"
 #include "base/memory/weak_ptr.h"
+#include "base/timer/timer.h"
 #include "net/base/io_buffer.h"
 #include "net/base/net_export.h"
 #include "net/quic/core/quic_connection.h"
@@ -91,6 +92,8 @@
 
  private:
   void SetPacket(const char* buffer, size_t buf_len);
+  bool MaybeRetryAfterWriteError(int rv);
+  void RetryPacketAfterNoBuffers();
   WriteResult WritePacketToSocketImpl();
   DatagramClientSocket* socket_;  // Unowned.
   Delegate* delegate_;  // Unowned.
@@ -101,6 +104,10 @@
   // Whether a write is currently in flight.
   bool write_blocked_;
 
+  int retry_count_;
+  // Timer set when a packet should be retried after ENOBUFS.
+  base::OneShotTimer retry_timer_;
+
   CompletionCallback write_callback_;
   base::WeakPtrFactory<QuicChromiumPacketWriter> weak_factory_;
 
diff --git a/net/quic/chromium/quic_network_transaction_unittest.cc b/net/quic/chromium/quic_network_transaction_unittest.cc
index 77e74534..52a4cbff 100644
--- a/net/quic/chromium/quic_network_transaction_unittest.cc
+++ b/net/quic/chromium/quic_network_transaction_unittest.cc
@@ -4714,6 +4714,104 @@
   session_.reset();
 }
 
+TEST_P(QuicNetworkTransactionTest, RetryAfterAsyncNoBufferSpace) {
+  session_params_.origins_to_force_quic_on.insert(
+      HostPortPair::FromString("mail.example.org:443"));
+
+  MockQuicData socket_data;
+  QuicStreamOffset offset = 0;
+  socket_data.AddWrite(ConstructInitialSettingsPacket(1, &offset));
+  socket_data.AddWrite(ASYNC, ERR_NO_BUFFER_SPACE);
+  socket_data.AddWrite(ConstructClientRequestHeadersPacket(
+      2, GetNthClientInitiatedStreamId(0), true, true,
+      GetRequestHeaders("GET", "https", "/"), &offset));
+  socket_data.AddRead(ConstructServerResponseHeadersPacket(
+      1, GetNthClientInitiatedStreamId(0), false, false,
+      GetResponseHeaders("200 OK")));
+  socket_data.AddRead(ConstructServerDataPacket(
+      2, GetNthClientInitiatedStreamId(0), false, true, 0, "hello!"));
+  socket_data.AddWrite(ConstructClientAckPacket(3, 2, 1, 1));
+  socket_data.AddRead(SYNCHRONOUS, ERR_IO_PENDING);  // No more data to read
+
+  socket_data.AddSocketDataToFactory(&socket_factory_);
+
+  CreateSession();
+
+  SendRequestAndExpectQuicResponse("hello!");
+  session_.reset();
+}
+
+TEST_P(QuicNetworkTransactionTest, RetryAfterSynchronousNoBufferSpace) {
+  session_params_.origins_to_force_quic_on.insert(
+      HostPortPair::FromString("mail.example.org:443"));
+
+  MockQuicData socket_data;
+  QuicStreamOffset offset = 0;
+  socket_data.AddWrite(ConstructInitialSettingsPacket(1, &offset));
+  socket_data.AddWrite(SYNCHRONOUS, ERR_NO_BUFFER_SPACE);
+  socket_data.AddWrite(ConstructClientRequestHeadersPacket(
+      2, GetNthClientInitiatedStreamId(0), true, true,
+      GetRequestHeaders("GET", "https", "/"), &offset));
+  socket_data.AddRead(ConstructServerResponseHeadersPacket(
+      1, GetNthClientInitiatedStreamId(0), false, false,
+      GetResponseHeaders("200 OK")));
+  socket_data.AddRead(ConstructServerDataPacket(
+      2, GetNthClientInitiatedStreamId(0), false, true, 0, "hello!"));
+  socket_data.AddWrite(ConstructClientAckPacket(3, 2, 1, 1));
+  socket_data.AddRead(SYNCHRONOUS, ERR_IO_PENDING);  // No more data to read
+
+  socket_data.AddSocketDataToFactory(&socket_factory_);
+
+  CreateSession();
+
+  SendRequestAndExpectQuicResponse("hello!");
+  session_.reset();
+}
+
+TEST_P(QuicNetworkTransactionTest, RetryAgainAfterAsyncNoBufferSpace) {
+  session_params_.origins_to_force_quic_on.insert(
+      HostPortPair::FromString("mail.example.org:443"));
+
+  MockQuicData socket_data;
+  QuicStreamOffset offset = 0;
+  socket_data.AddRead(SYNCHRONOUS, ERR_IO_PENDING);  // No more data to read
+  socket_data.AddWrite(ConstructInitialSettingsPacket(1, &offset));
+  for (int i = 0; i < 21; ++i) {
+    socket_data.AddWrite(ASYNC, ERR_NO_BUFFER_SPACE);
+  }
+  socket_data.AddSocketDataToFactory(&socket_factory_);
+
+  CreateSession();
+
+  HttpNetworkTransaction trans(DEFAULT_PRIORITY, session_.get());
+  TestCompletionCallback callback;
+  int rv = trans.Start(&request_, callback.callback(), net_log_.bound());
+  EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
+  EXPECT_THAT(callback.WaitForResult(), IsError(ERR_QUIC_PROTOCOL_ERROR));
+}
+
+TEST_P(QuicNetworkTransactionTest, RetryOnceAfterSynchronousNoBufferSpace) {
+  session_params_.origins_to_force_quic_on.insert(
+      HostPortPair::FromString("mail.example.org:443"));
+
+  MockQuicData socket_data;
+  QuicStreamOffset offset = 0;
+  socket_data.AddRead(SYNCHRONOUS, ERR_IO_PENDING);  // No more data to read
+  socket_data.AddWrite(ConstructInitialSettingsPacket(1, &offset));
+  for (int i = 0; i < 21; ++i) {
+    socket_data.AddWrite(ASYNC, ERR_NO_BUFFER_SPACE);
+  }
+  socket_data.AddSocketDataToFactory(&socket_factory_);
+
+  CreateSession();
+
+  HttpNetworkTransaction trans(DEFAULT_PRIORITY, session_.get());
+  TestCompletionCallback callback;
+  int rv = trans.Start(&request_, callback.callback(), net_log_.bound());
+  EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
+  EXPECT_THAT(callback.WaitForResult(), IsError(ERR_QUIC_PROTOCOL_ERROR));
+}
+
 // Adds coverage to catch regression such as https://crbug.com/622043
 TEST_P(QuicNetworkTransactionTest, QuicServerPush) {
   session_params_.origins_to_force_quic_on.insert(
diff --git a/net/quic/core/quic_flags_list.h b/net/quic/core/quic_flags_list.h
index b4cc9599..1cd46893 100644
--- a/net/quic/core/quic_flags_list.h
+++ b/net/quic/core/quic_flags_list.h
@@ -140,7 +140,7 @@
 
 // If true, QUIC can take ownership of data provided in a reference counted
 // memory to avoid data copy.
-QUIC_FLAG(bool, FLAGS_quic_reloadable_flag_quic_use_mem_slices, false)
+QUIC_FLAG(bool, FLAGS_quic_reloadable_flag_quic_use_mem_slices, true)
 
 // Allow QUIC to accept initial packet numbers that are random, not 1.
 QUIC_FLAG(bool, FLAGS_quic_restart_flag_quic_enable_accept_random_ipn, false)
diff --git a/net/quic/platform/api/quic_mem_slice_span_test.cc b/net/quic/platform/api/quic_mem_slice_span_test.cc
index 827dc78..e14be12 100644
--- a/net/quic/platform/api/quic_mem_slice_span_test.cc
+++ b/net/quic/platform/api/quic_mem_slice_span_test.cc
@@ -34,6 +34,16 @@
   EXPECT_EQ(10u, send_buffer.size());
 }
 
+TEST_F(QuicMemSliceSpanImplTest, SaveEmptyMemSliceInSendBuffer) {
+  SimpleBufferAllocator allocator;
+  QuicStreamSendBuffer send_buffer(&allocator);
+  buffers_.push_back(std::make_pair(nullptr, 0));
+  QuicTestMemSliceVector vector(buffers_);
+  EXPECT_EQ(10 * 1024u, vector.span().SaveMemSlicesInSendBuffer(&send_buffer));
+  // Verify the empty slice does not get saved.
+  EXPECT_EQ(10u, send_buffer.size());
+}
+
 }  // namespace
 }  // namespace test
 }  // namespace net
diff --git a/net/quic/platform/impl/quic_mem_slice_span_impl.cc b/net/quic/platform/impl/quic_mem_slice_span_impl.cc
index 2f488f5..a42f11f3 100644
--- a/net/quic/platform/impl/quic_mem_slice_span_impl.cc
+++ b/net/quic/platform/impl/quic_mem_slice_span_impl.cc
@@ -30,6 +30,10 @@
     QuicStreamSendBuffer* send_buffer) {
   size_t saved_length = 0;
   for (size_t i = 0; i < num_buffers_; ++i) {
+    if (lengths_[i] == 0) {
+      // Skip empty buffer.
+      continue;
+    }
     saved_length += lengths_[i];
     send_buffer->SaveMemSlice(
         QuicMemSlice(QuicMemSliceImpl(buffers_[i], lengths_[i])));
diff --git a/net/ssl/client_cert_store_mac.cc b/net/ssl/client_cert_store_mac.cc
index 318f26e..cbbc35b 100644
--- a/net/ssl/client_cert_store_mac.cc
+++ b/net/ssl/client_cert_store_mac.cc
@@ -142,9 +142,10 @@
 bool ExtendedKeyUsageAllows(const CE_ExtendedKeyUsage* usage,
                             const CSSM_OID* purpose) {
   for (unsigned p = 0; p < usage->numPurposes; ++p) {
-    if (CSSMOIDEqual(&usage->purposes[p], purpose))
+    if (x509_util::CSSMOIDEqual(&usage->purposes[p], purpose))
       return true;
-    if (CSSMOIDEqual(&usage->purposes[p], &CSSMOID_ExtendedKeyUsageAny))
+    if (x509_util::CSSMOIDEqual(&usage->purposes[p],
+                                &CSSMOID_ExtendedKeyUsageAny))
       return true;
   }
   return false;
diff --git a/net/ssl/client_cert_store_nss.cc b/net/ssl/client_cert_store_nss.cc
index bd6a8f0..959f497 100644
--- a/net/ssl/client_cert_store_nss.cc
+++ b/net/ssl/client_cert_store_nss.cc
@@ -53,8 +53,7 @@
         FROM_HERE,
         {base::MayBlock(), base::TaskShutdownBehavior::CONTINUE_ON_SHUTDOWN},
         base::Bind(&FetchClientCertPrivateKey, base::Unretained(certificate()),
-                   cert_certificate_.get(),
-                   base::Unretained(password_delegate_.get())),
+                   cert_certificate_.get(), password_delegate_),
         private_key_callback);
   }
 
diff --git a/net/ssl/ssl_platform_key_nss.cc b/net/ssl/ssl_platform_key_nss.cc
index 9361ad8..e0d220d 100644
--- a/net/ssl/ssl_platform_key_nss.cc
+++ b/net/ssl/ssl_platform_key_nss.cc
@@ -45,8 +45,13 @@
 
 class SSLPlatformKeyNSS : public ThreadedSSLPrivateKey::Delegate {
  public:
-  SSLPlatformKeyNSS(int type, crypto::ScopedSECKEYPrivateKey key)
-      : type_(type), key_(std::move(key)) {}
+  SSLPlatformKeyNSS(int type,
+                    scoped_refptr<crypto::CryptoModuleBlockingPasswordDelegate>
+                        password_delegate,
+                    crypto::ScopedSECKEYPrivateKey key)
+      : type_(type),
+        password_delegate_(std::move(password_delegate)),
+        key_(std::move(key)) {}
   ~SSLPlatformKeyNSS() override {}
 
   std::vector<SSLPrivateKey::Hash> GetDigestPreferences() override {
@@ -147,6 +152,10 @@
 
  private:
   int type_;
+  // NSS retains a pointer to the password delegate, so retain a reference here
+  // to ensure the lifetimes are correct.
+  scoped_refptr<crypto::CryptoModuleBlockingPasswordDelegate>
+      password_delegate_;
   crypto::ScopedSECKEYPrivateKey key_;
 
   DISALLOW_COPY_AND_ASSIGN(SSLPlatformKeyNSS);
@@ -157,7 +166,8 @@
 scoped_refptr<SSLPrivateKey> FetchClientCertPrivateKey(
     const X509Certificate* certificate,
     CERTCertificate* cert_certificate,
-    crypto::CryptoModuleBlockingPasswordDelegate* password_delegate) {
+    scoped_refptr<crypto::CryptoModuleBlockingPasswordDelegate>
+        password_delegate) {
   // This function may acquire the NSS lock or reenter this code via extension
   // hooks (such as smart card UI). To ensure threads are not starved or
   // deadlocked, the base::ScopedBlockingCall below increments the thread pool
@@ -175,8 +185,13 @@
   if (!GetClientCertInfo(certificate, &type, &max_length))
     return nullptr;
 
+  // Note that key contains a reference to password_delegate->wincx() and may
+  // use it in PK11_Sign. Thus password_delegate must outlive key. We pass it
+  // into SSLPlatformKeyNSS to tie the lifetimes together. See
+  // https://crbug.com/779090.
   return base::MakeRefCounted<ThreadedSSLPrivateKey>(
-      std::make_unique<SSLPlatformKeyNSS>(type, std::move(key)),
+      std::make_unique<SSLPlatformKeyNSS>(type, std::move(password_delegate),
+                                          std::move(key)),
       GetSSLPlatformKeyTaskRunner());
 }
 
diff --git a/net/ssl/ssl_platform_key_nss.h b/net/ssl/ssl_platform_key_nss.h
index 54b6ad8..726b7d1 100644
--- a/net/ssl/ssl_platform_key_nss.h
+++ b/net/ssl/ssl_platform_key_nss.h
@@ -21,11 +21,13 @@
 
 // Returns an SSLPrivateKey backed by the NSS private key that corresponds to
 // |certificate|'s public key. If |password_delegate| is non-null, it will be
-// used to prompt for a password if necessary to unlock a slot.
+// used to prompt for a password if necessary to unlock a slot or perform
+// signing operations.
 NET_EXPORT scoped_refptr<SSLPrivateKey> FetchClientCertPrivateKey(
     const X509Certificate* certificate,
     CERTCertificate* cert_certificate,
-    crypto::CryptoModuleBlockingPasswordDelegate* password_delegate);
+    scoped_refptr<crypto::CryptoModuleBlockingPasswordDelegate>
+        password_delegate);
 
 }  // namespace net
 
diff --git a/net/ssl/ssl_platform_key_nss_unittest.cc b/net/ssl/ssl_platform_key_nss_unittest.cc
index 887e8a78..4d5e7fd 100644
--- a/net/ssl/ssl_platform_key_nss_unittest.cc
+++ b/net/ssl/ssl_platform_key_nss_unittest.cc
@@ -17,6 +17,7 @@
 #include "base/files/file_util.h"
 #include "base/memory/ref_counted.h"
 #include "crypto/ec_private_key.h"
+#include "crypto/nss_crypto_module_delegate.h"
 #include "crypto/scoped_nss_types.h"
 #include "crypto/scoped_test_nss_db.h"
 #include "net/cert/x509_util_nss.h"
diff --git a/net/test/embedded_test_server/default_handlers.cc b/net/test/embedded_test_server/default_handlers.cc
index 057d9a85..a1bf86b 100644
--- a/net/test/embedded_test_server/default_handlers.cc
+++ b/net/test/embedded_test_server/default_handlers.cc
@@ -28,6 +28,7 @@
 #include "base/strings/stringprintf.h"
 #include "base/threading/thread_task_runner_handle.h"
 #include "base/time/time.h"
+#include "base/unguessable_token.h"
 #include "net/base/escape.h"
 #include "net/base/url_util.h"
 #include "net/filter/filter_source_stream_test_util.h"
@@ -148,7 +149,7 @@
   std::unique_ptr<BasicHttpResponse> http_response(new BasicHttpResponse);
 
   std::string body =
-      "<html><head><style>"
+      "<html><head><title>EmbeddedTestServer - EchoAll</title><style>"
       "pre { border: 1px solid black; margin: 5px; padding: 5px }"
       "</style></head><body>"
       "<div style=\"float: right\">"
@@ -165,9 +166,9 @@
   body +=
       "</pre>"
       "<h1>Request Headers:</h1><pre>" +
-      request.all_headers +
-      "</pre>"
-      "</body></html>";
+      request.all_headers + "</pre>" +
+      "<h1>Response nonce:</h1><pre id='response-nonce'>" +
+      base::UnguessableToken::Create().ToString() + "</pre></body></html>";
 
   http_response->set_content_type("text/html");
   http_response->set_content(body);
diff --git a/net/tools/transport_security_state_generator/input_file_parsers.cc b/net/tools/transport_security_state_generator/input_file_parsers.cc
index 691b403..9536fde 100644
--- a/net/tools/transport_security_state_generator/input_file_parsers.cc
+++ b/net/tools/transport_security_state_generator/input_file_parsers.cc
@@ -4,6 +4,7 @@
 
 #include "net/tools/transport_security_state_generator/input_file_parsers.h"
 
+#include <set>
 #include <sstream>
 #include <vector>
 
@@ -164,6 +165,20 @@
   IN_PUBLIC_KEY
 };
 
+// Valid JSON keys.
+static const char kNameJSONKey[] = "name";
+static const char kIncludeSubdomainsJSONKey[] = "include_subdomains";
+static const char kIncludeSubdomainsForPinningJSONKey[] =
+    "include_subdomains_for_pinning";
+static const char kModeJSONKey[] = "mode";
+static const char kPinsJSONKey[] = "pins";
+static const char kExpectCTJSONKey[] = "expect_ct";
+static const char kExpectCTReportURIJSONKey[] = "expect_ct_report_uri";
+static const char kExpectStapleJSONKey[] = "expect_staple";
+static const char kExpectStapleReportURIJSONKey[] = "expect_staple_report_uri";
+static const char kIncludeSubdomainsForExpectStapleJSONKey[] =
+    "include_subdomains_for_expect_staple";
+
 }  // namespace
 
 bool ParseCertificatesFile(base::StringPiece certs_input, Pinsets* pinsets) {
@@ -279,6 +294,17 @@
 bool ParseJSON(base::StringPiece json,
                TransportSecurityStateEntries* entries,
                Pinsets* pinsets) {
+  std::set<std::string> valid_keys = {kNameJSONKey,
+                                      kIncludeSubdomainsJSONKey,
+                                      kIncludeSubdomainsForPinningJSONKey,
+                                      kModeJSONKey,
+                                      kPinsJSONKey,
+                                      kExpectCTJSONKey,
+                                      kExpectCTReportURIJSONKey,
+                                      kExpectStapleJSONKey,
+                                      kExpectStapleReportURIJSONKey,
+                                      kIncludeSubdomainsForExpectStapleJSONKey};
+
   std::unique_ptr<base::Value> value = base::JSONReader::Read(json);
   base::DictionaryValue* dict_value = nullptr;
   if (!value.get() || !value->GetAsDictionary(&dict_value)) {
@@ -303,7 +329,7 @@
     std::unique_ptr<TransportSecurityStateEntry> entry(
         new TransportSecurityStateEntry());
 
-    if (!parsed->GetString("name", &entry->hostname)) {
+    if (!parsed->GetString(kNameJSONKey, &entry->hostname)) {
       LOG(ERROR) << "Could not extract the hostname for entry "
                  << base::SizeTToString(i) << " from the input JSON";
       return false;
@@ -315,19 +341,34 @@
       return false;
     }
 
-    parsed->GetBoolean("include_subdomains", &entry->include_subdomains);
+    for (const auto& entry_value : *parsed) {
+      if (valid_keys.find(entry_value.first) == valid_keys.cend()) {
+        LOG(ERROR) << "The entry for " << entry->hostname
+                   << " contains an unknown " << entry_value.first << " field";
+        return false;
+      }
+    }
+
     std::string mode;
-    parsed->GetString("mode", &mode);
-    entry->force_https = (mode == "force-https");
-    parsed->GetBoolean("include_subdomains_for_pinning",
+    parsed->GetString(kModeJSONKey, &mode);
+    entry->force_https = false;
+    if (mode == "force-https") {
+      entry->force_https = true;
+    } else if (!mode.empty()) {
+      LOG(ERROR) << "An unknown mode is set for entry " << entry->hostname;
+      return false;
+    }
+
+    parsed->GetBoolean(kIncludeSubdomainsJSONKey, &entry->include_subdomains);
+    parsed->GetBoolean(kIncludeSubdomainsForPinningJSONKey,
                        &entry->hpkp_include_subdomains);
-    parsed->GetString("pins", &entry->pinset);
-    parsed->GetBoolean("expect_ct", &entry->expect_ct);
-    parsed->GetString("expect_ct_report_uri", &entry->expect_ct_report_uri);
-    parsed->GetBoolean("expect_staple", &entry->expect_staple);
-    parsed->GetBoolean("include_subdomains_for_expect_staple",
+    parsed->GetString(kPinsJSONKey, &entry->pinset);
+    parsed->GetBoolean(kExpectCTJSONKey, &entry->expect_ct);
+    parsed->GetString(kExpectCTReportURIJSONKey, &entry->expect_ct_report_uri);
+    parsed->GetBoolean(kExpectStapleJSONKey, &entry->expect_staple);
+    parsed->GetBoolean(kIncludeSubdomainsForExpectStapleJSONKey,
                        &entry->expect_staple_include_subdomains);
-    parsed->GetString("expect_staple_report_uri",
+    parsed->GetString(kExpectStapleReportURIJSONKey,
                       &entry->expect_staple_report_uri);
 
     entries->push_back(std::move(entry));
diff --git a/net/tools/transport_security_state_generator/input_file_parsers_unittest.cc b/net/tools/transport_security_state_generator/input_file_parsers_unittest.cc
index 733a6fb..45e94b5c 100644
--- a/net/tools/transport_security_state_generator/input_file_parsers_unittest.cc
+++ b/net/tools/transport_security_state_generator/input_file_parsers_unittest.cc
@@ -214,6 +214,44 @@
   EXPECT_FALSE(ParseJSON(missing_pinset_name, &entries, &pinsets));
 }
 
+// Test that parsing valid JSON containing an entry with an invalid mode fails.
+TEST(InputFileParsersTest, ParseJSONInvalidMode) {
+  TransportSecurityStateEntries entries;
+  Pinsets pinsets;
+
+  std::string invalid_mode =
+      "{"
+      "  \"pinsets\": [],"
+      "  \"entries\": ["
+      "    {"
+      "      \"name\": \"preloaded.test\","
+      "      \"mode\": \"something-invalid\""
+      "    }"
+      "  ]"
+      "}";
+
+  EXPECT_FALSE(ParseJSON(invalid_mode, &entries, &pinsets));
+}
+
+// Test that parsing valid JSON containing an entry with an unknown field fails.
+TEST(InputFileParsersTest, ParseJSONUnkownField) {
+  TransportSecurityStateEntries entries;
+  Pinsets pinsets;
+
+  std::string unknown_field =
+      "{"
+      "  \"pinsets\": [],"
+      "  \"entries\": ["
+      "    {"
+      "      \"name\": \"preloaded.test\","
+      "      \"unknown_key\": \"value\""
+      "    }"
+      "  ]"
+      "}";
+
+  EXPECT_FALSE(ParseJSON(unknown_field, &entries, &pinsets));
+}
+
 // Test parsing of all 3 SPKI formats.
 TEST(InputFileParsersTest, ParseCertificatesFile) {
   std::string valid =
diff --git a/ppapi/shared_impl/ppb_gamepad_shared.h b/ppapi/shared_impl/ppb_gamepad_shared.h
index 24f3cb0..e478faf 100644
--- a/ppapi/shared_impl/ppb_gamepad_shared.h
+++ b/ppapi/shared_impl/ppb_gamepad_shared.h
@@ -29,6 +29,16 @@
   double value;
 };
 
+enum WebKitGamepadHapticActuatorType {
+  WEBKIT_GAMEPAD_HAPTIC_ACTUATOR_TYPE_VIBRATION = 0,
+  WEBKIT_GAMEPAD_HAPTIC_ACTUATOR_TYPE_DUAL_RUMBLE = 1
+};
+
+struct WebKitGamepadHapticActuator {
+  bool notNull;
+  WebKitGamepadHapticActuatorType type;
+};
+
 struct WebKitGamepadVector {
   bool notNull;
   float x, y, z;
@@ -60,7 +70,8 @@
 };
 
 // This must match the definition of blink::Gamepad. The GamepadHost unit test
-// has some compile asserts to validate this.
+// has some compile asserts to validate this. Some members are unused but must
+// be present to ensure the struct layout is the same.
 struct WebKitGamepad {
   static const size_t kIdLengthCap = 128;
   static const size_t kMappingLengthCap = 16;
@@ -89,11 +100,16 @@
   // Normalized values representing buttons, in the range [0..1].
   WebKitGamepadButton buttons[kButtonsLengthCap];
 
+  // Gamepad Extensions member, unused by ppapi.
+  WebKitGamepadHapticActuator vibrationActuator;
+
   // Mapping type (for example "standard")
   base::char16 mapping[kMappingLengthCap];
 
+  // Gamepad Extensions member, unused by ppapi.
   WebKitGamepadPose pose;
 
+  // Gamepad Extensions member, unused by ppapi.
   WebKitGamepadHand hand;
 
   // ID of the VRDisplay this gamepad is associated with, if any.
diff --git a/remoting/android/client_java_tmpl.gni b/remoting/android/client_java_tmpl.gni
index 2da3288..bc24b69 100644
--- a/remoting/android/client_java_tmpl.gni
+++ b/remoting/android/client_java_tmpl.gni
@@ -80,6 +80,7 @@
       "//base:base_java",
       "//remoting/android:remoting_android_client_java_resources",
       "//remoting/android:remoting_apk_manifest",
+      "//third_party/android_tools:android_arch_lifecycle_common_java",
       "//third_party/android_tools:android_support_annotations_java",
       "//third_party/android_tools:android_support_compat_java",
       "//third_party/android_tools:android_support_core_ui_java",
diff --git a/remoting/client/BUILD.gn b/remoting/client/BUILD.gn
index 6192de7c..26afdbce 100644
--- a/remoting/client/BUILD.gn
+++ b/remoting/client/BUILD.gn
@@ -17,8 +17,6 @@
     "connect_to_host_info.h",
     "cursor_shape_stub_proxy.cc",
     "cursor_shape_stub_proxy.h",
-    "dual_buffer_frame_consumer.cc",
-    "dual_buffer_frame_consumer.h",
     "empty_cursor_filter.cc",
     "empty_cursor_filter.h",
     "host_experiment_sender.cc",
@@ -53,6 +51,8 @@
     sources += [
       "chromoting_client_runtime.cc",
       "chromoting_client_runtime.h",
+      "dual_buffer_frame_consumer.cc",
+      "dual_buffer_frame_consumer.h",
       "gesture_interpreter.cc",
       "gesture_interpreter.h",
     ]
diff --git a/remoting/client/dual_buffer_frame_consumer.cc b/remoting/client/dual_buffer_frame_consumer.cc
index 662e7264..6008d80 100644
--- a/remoting/client/dual_buffer_frame_consumer.cc
+++ b/remoting/client/dual_buffer_frame_consumer.cc
@@ -4,6 +4,8 @@
 
 #include "remoting/client/dual_buffer_frame_consumer.h"
 
+#include <memory>
+
 #include "base/bind.h"
 #include "base/bind_helpers.h"
 #include "base/location.h"
@@ -13,6 +15,58 @@
 
 namespace remoting {
 
+namespace {
+
+// The implementation is mostly the same as webrtc::BasicDesktopFrame, except
+// that it has an extra padding of one row at the end of the buffer. This is
+// to workaround a bug in iOS' implementation of glTexSubimage2D that causes
+// occasional SIGSEGV.
+//
+// glTexSubimage2D is supposed to only read
+// kBytesPerPixel * width * (height - 1) bytes from the buffer but it seems to
+// be reading more than that, which may end up reading protected memory.
+//
+// See details in crbug.com/778550
+class PaddedDesktopFrame : public webrtc::DesktopFrame {
+ public:
+  explicit PaddedDesktopFrame(webrtc::DesktopSize size);
+  ~PaddedDesktopFrame() override;
+
+  // Creates a PaddedDesktopFrame that contains copy of |frame|.
+  static std::unique_ptr<webrtc::DesktopFrame> CopyOf(
+      const webrtc::DesktopFrame& frame);
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(PaddedDesktopFrame);
+};
+
+PaddedDesktopFrame::PaddedDesktopFrame(webrtc::DesktopSize size)
+    : DesktopFrame(
+          size,
+          kBytesPerPixel * size.width(),
+          new uint8_t[kBytesPerPixel * size.width() * (size.height() + 1)],
+          nullptr) {}
+
+PaddedDesktopFrame::~PaddedDesktopFrame() {
+  delete[] data_;
+}
+
+// static
+std::unique_ptr<webrtc::DesktopFrame> PaddedDesktopFrame::CopyOf(
+    const webrtc::DesktopFrame& frame) {
+  std::unique_ptr<PaddedDesktopFrame> result =
+      std::make_unique<PaddedDesktopFrame>(frame.size());
+  for (int y = 0; y < frame.size().height(); ++y) {
+    memcpy(result->data() + y * result->stride(),
+           frame.data() + y * frame.stride(),
+           frame.size().width() * kBytesPerPixel);
+  }
+  result->CopyFrameInfoFrom(frame);
+  return result;
+}
+
+}  // namespace
+
 DualBufferFrameConsumer::DualBufferFrameConsumer(
     const RenderCallback& callback,
     scoped_refptr<base::SingleThreadTaskRunner> task_runner,
@@ -37,8 +91,8 @@
   DCHECK(buffers_[0]->size().equals(buffers_[1]->size()));
   // This creates a copy of buffers_[0] and merges area defined in
   // |buffer_1_mask_| from buffers_[1] into the copy.
-  std::unique_ptr<webrtc::DesktopFrame> full_frame(
-      webrtc::BasicDesktopFrame::CopyOf(*buffers_[0]));
+  std::unique_ptr<webrtc::DesktopFrame> full_frame =
+      PaddedDesktopFrame::CopyOf(*buffers_[0]);
   webrtc::DesktopRect desktop_rect =
         webrtc::DesktopRect::MakeSize(buffers_[0]->size());
   for (webrtc::DesktopRegion::Iterator i(buffer_1_mask_); !i.IsAtEnd();
@@ -58,9 +112,9 @@
   // Both buffers are reallocated whenever screen size changes.
   if (!buffers_[0] || !buffers_[0]->size().equals(size)) {
     buffers_[0] = webrtc::SharedDesktopFrame::Wrap(
-        base::MakeUnique<webrtc::BasicDesktopFrame>(size));
+        base::MakeUnique<PaddedDesktopFrame>(size));
     buffers_[1] = webrtc::SharedDesktopFrame::Wrap(
-        base::MakeUnique<webrtc::BasicDesktopFrame>(size));
+        base::MakeUnique<PaddedDesktopFrame>(size));
     buffer_1_mask_.Clear();
     current_buffer_ = 0;
   } else {
diff --git a/remoting/host/win/chromoting_module.cc b/remoting/host/win/chromoting_module.cc
index 75c6e9d..c0cae132 100644
--- a/remoting/host/win/chromoting_module.cc
+++ b/remoting/host/win/chromoting_module.cc
@@ -81,7 +81,7 @@
     : classes_(classes),
       classes_end_(classes_end) {
   // Don't do anything if COM initialization failed.
-  if (!com_initializer_.succeeded())
+  if (!com_initializer_.Succeeded())
     return;
 
   ATL::_AtlComModule.ExecuteObjectMain(true);
@@ -89,7 +89,7 @@
 
 ChromotingModule::~ChromotingModule() {
   // Don't do anything if COM initialization failed.
-  if (!com_initializer_.succeeded())
+  if (!com_initializer_.Succeeded())
     return;
 
   Term();
@@ -103,7 +103,7 @@
 
 bool ChromotingModule::Run() {
   // Don't do anything if COM initialization failed.
-  if (!com_initializer_.succeeded())
+  if (!com_initializer_.Succeeded())
     return false;
 
   // Register class objects.
diff --git a/remoting/host/win/host_service.cc b/remoting/host/win/host_service.cc
index 3c1f019..7fc475b 100644
--- a/remoting/host/win/host_service.cc
+++ b/remoting/host/win/host_service.cc
@@ -267,7 +267,7 @@
 
   // Initialize COM.
   base::win::ScopedCOMInitializer com_initializer;
-  if (!com_initializer.succeeded())
+  if (!com_initializer.Succeeded())
     return;
 
   if (!InitializeComSecurity(base::WideToUTF8(kComProcessSd),
@@ -304,7 +304,7 @@
 
   // Initialize COM.
   base::win::ScopedCOMInitializer com_initializer;
-  if (!com_initializer.succeeded())
+  if (!com_initializer.Succeeded())
     return result;
 
   if (!InitializeComSecurity(base::WideToUTF8(kComProcessSd),
diff --git a/remoting/ios/app/host_view_controller.mm b/remoting/ios/app/host_view_controller.mm
index bd021d4..eba4817 100644
--- a/remoting/ios/app/host_view_controller.mm
+++ b/remoting/ios/app/host_view_controller.mm
@@ -81,12 +81,6 @@
     _hasPhysicalKeyboard = NO;
     _settings =
         [[RemotingPreferences instance] settingsForHost:client.hostInfo.hostId];
-    _surfaceSizeAnimationLink = [CADisplayLink
-        displayLinkWithTarget:self
-                     selector:@selector(animateHostSurfaceSize:)];
-    _surfaceSizeAnimationLink.paused = YES;
-    [_surfaceSizeAnimationLink addToRunLoop:NSRunLoop.currentRunLoop
-                                    forMode:NSDefaultRunLoopMode];
 
     BOOL fabIsRight =
         [UIView userInterfaceLayoutDirectionForSemanticContentAttribute:
@@ -231,6 +225,13 @@
          selector:@selector(keyboardWillHide:)
              name:UIKeyboardWillHideNotification
            object:nil];
+
+  _surfaceSizeAnimationLink =
+      [CADisplayLink displayLinkWithTarget:self
+                                  selector:@selector(animateHostSurfaceSize:)];
+  _surfaceSizeAnimationLink.paused = YES;
+  [_surfaceSizeAnimationLink addToRunLoop:NSRunLoop.currentRunLoop
+                                  forMode:NSDefaultRunLoopMode];
 }
 
 - (void)viewWillDisappear:(BOOL)animated {
@@ -240,6 +241,9 @@
                                       forHost:_client.hostInfo.hostId];
 
   [[NSNotificationCenter defaultCenter] removeObserver:self];
+
+  _surfaceSizeAnimationLink.paused = YES;
+  [_surfaceSizeAnimationLink invalidate];
 }
 
 - (void)viewDidLayoutSubviews {
diff --git a/remoting/ios/app/remoting_view_controller.mm b/remoting/ios/app/remoting_view_controller.mm
index 9cec710..c469cb4 100644
--- a/remoting/ios/app/remoting_view_controller.mm
+++ b/remoting/ios/app/remoting_view_controller.mm
@@ -369,15 +369,6 @@
       contentViewController.collectionView;
   self.contentViewController = contentViewController;
   self.contentViewController.view.frame = self.view.bounds;
-
-  if (@available(iOS 11.0, *)) {
-    // TODO(crbug.com/766892): This is a workaround for material component bug
-    // https://github.com/material-components/material-components-ios/issues/1962
-    // Remove once it is resolved.
-    self.headerViewController.headerView.trackingScrollView
-        .contentInsetAdjustmentBehavior =
-        UIScrollViewContentInsetAdjustmentNever;
-  }
 }
 
 - (void)handleHostListFetchFailure:(HostListFetchFailureReason)reason {
diff --git a/remoting/resources/remoting_strings.grd b/remoting/resources/remoting_strings.grd
index 55dca1e..d5e8496 100644
--- a/remoting/resources/remoting_strings.grd
+++ b/remoting/resources/remoting_strings.grd
@@ -1312,10 +1312,7 @@
       <message desc="Message displayed before sharing computer in 'It2Me' mode when the email of the remote user attempting to connect is known." name="IDS_SHARE_CONFIRM_DIALOG_MESSAGE_WITH_USERNAME" >
         Would you like to allow <ph name="CLIENT_USERNAME">{0}<ex>client@email.com</ex></ph> to see and control your computer?
       </message>
-      <message desc="Label for the button to accept sharing the computer in 'It2Me' mode." name="IDS_SHARE_CONFIRM_DIALOG_CONFIRM" >
-        Share
-      </message>
-      <message desc="Label for the button to accept sharing the computer in 'It2Me' mode." meaning="Accept share request." name="IDS_SHARE_CONFIRM_DIALOG_CONFIRM_TEMP" >
+      <message desc="Label for the button to accept sharing the computer in 'It2Me' mode." meaning="Accept share request." name="IDS_SHARE_CONFIRM_DIALOG_CONFIRM" >
         Share
       </message>
       <message desc="Label for the button to decline sharing the computer in 'It2Me' mode." name="IDS_SHARE_CONFIRM_DIALOG_DECLINE" >
diff --git a/services/identity/identity_manager_unittest.cc b/services/identity/identity_manager_unittest.cc
index c6f7b43e..3ebbfd2 100644
--- a/services/identity/identity_manager_unittest.cc
+++ b/services/identity/identity_manager_unittest.cc
@@ -87,7 +87,7 @@
 class IdentityManagerTest : public service_manager::test::ServiceTest {
  public:
   IdentityManagerTest()
-      : ServiceTest("identity_unittests", false),
+      : ServiceTest("identity_unittests"),
         signin_client_(&pref_service_),
 #if defined(OS_CHROMEOS)
         signin_manager_(&signin_client_, &account_tracker_) {
diff --git a/services/metrics/public/cpp/mojo_ukm_recorder.h b/services/metrics/public/cpp/mojo_ukm_recorder.h
index 032a105f..08f0c03c 100644
--- a/services/metrics/public/cpp/mojo_ukm_recorder.h
+++ b/services/metrics/public/cpp/mojo_ukm_recorder.h
@@ -27,7 +27,7 @@
  */
 class METRICS_EXPORT MojoUkmRecorder : public UkmRecorder {
  public:
-  explicit MojoUkmRecorder(mojom::UkmRecorderInterfacePtr interface);
+  explicit MojoUkmRecorder(mojom::UkmRecorderInterfacePtr recorder_interface);
   ~MojoUkmRecorder() override;
 
   // UkmRecorder:
diff --git a/services/metrics/public/cpp/ukm_recorder.h b/services/metrics/public/cpp/ukm_recorder.h
index 09fc22f..d244d9a 100644
--- a/services/metrics/public/cpp/ukm_recorder.h
+++ b/services/metrics/public/cpp/ukm_recorder.h
@@ -30,6 +30,10 @@
 class AutoplayUmaHelper;
 }
 
+namespace cc {
+class UkmManager;
+}
+
 namespace content {
 class RenderWidgetHostLatencyTracker;
 }  // namespace content
@@ -78,6 +82,7 @@
 
  private:
   friend blink::AutoplayUmaHelper;
+  friend cc::UkmManager;
   friend ContextualSearchRankerLoggerImpl;
   friend PluginInfoMessageFilter;
   friend UkmPageLoadMetricsObserver;
diff --git a/services/preferences/pref_service_factory_unittest.cc b/services/preferences/pref_service_factory_unittest.cc
index 17cd934..db6b027 100644
--- a/services/preferences/pref_service_factory_unittest.cc
+++ b/services/preferences/pref_service_factory_unittest.cc
@@ -93,7 +93,7 @@
 
 class PrefServiceFactoryTest : public service_manager::test::ServiceTest {
  public:
-  PrefServiceFactoryTest() : ServiceTest("prefs_unittests", false) {}
+  PrefServiceFactoryTest() : ServiceTest("prefs_unittests") {}
 
  protected:
   void SetUp() override {
diff --git a/services/resource_coordinator/tracing/agent_registry.cc b/services/resource_coordinator/tracing/agent_registry.cc
index 5bdd7ad..f8002917 100644
--- a/services/resource_coordinator/tracing/agent_registry.cc
+++ b/services/resource_coordinator/tracing/agent_registry.cc
@@ -33,7 +33,7 @@
       is_tracing_(false) {
   DCHECK(!label.empty());
   agent_.set_connection_error_handler(base::BindRepeating(
-      &AgentRegistry::AgentEntry::OnConnectionError, base::Unretained(this)));
+      &AgentRegistry::AgentEntry::OnConnectionError, AsWeakPtr()));
 }
 
 AgentRegistry::AgentEntry::~AgentEntry() = default;
diff --git a/services/resource_coordinator/tracing/agent_registry.h b/services/resource_coordinator/tracing/agent_registry.h
index f224785..202d6b8 100644
--- a/services/resource_coordinator/tracing/agent_registry.h
+++ b/services/resource_coordinator/tracing/agent_registry.h
@@ -11,6 +11,7 @@
 
 #include "base/callback_forward.h"
 #include "base/macros.h"
+#include "base/memory/weak_ptr.h"
 #include "base/threading/thread_checker.h"
 #include "mojo/public/cpp/bindings/binding_set.h"
 #include "services/resource_coordinator/public/interfaces/tracing/tracing.mojom.h"
@@ -24,7 +25,7 @@
 
 class AgentRegistry : public mojom::AgentRegistry {
  public:
-  class AgentEntry {
+  class AgentEntry : public base::SupportsWeakPtr<AgentEntry> {
    public:
     AgentEntry(size_t id,
                AgentRegistry* agent_registry,
diff --git a/services/resource_coordinator/tracing/coordinator.cc b/services/resource_coordinator/tracing/coordinator.cc
index ef033ea2..28feee721 100644
--- a/services/resource_coordinator/tracing/coordinator.cc
+++ b/services/resource_coordinator/tracing/coordinator.cc
@@ -48,6 +48,222 @@
 
 namespace tracing {
 
+class Coordinator::TraceStreamer : public base::SupportsWeakPtr<TraceStreamer> {
+ public:
+  // Constructed on |main_task_runner_|.
+  TraceStreamer(
+      mojo::ScopedDataPipeProducerHandle stream,
+      const std::string& agent_label,
+      const scoped_refptr<base::SequencedTaskRunner>& main_task_runner,
+      base::WeakPtr<Coordinator> coordinator)
+      : stream_(std::move(stream)),
+        agent_label_(agent_label),
+        main_task_runner_(main_task_runner),
+        coordinator_(coordinator),
+        metadata_(new base::DictionaryValue()),
+        stream_is_empty_(true),
+        json_field_name_written_(false) {}
+
+  // Destroyed on |background_task_runner_|.
+  ~TraceStreamer() = default;
+
+  // Called from |background_task_runner_|.
+  void CreateAndSendRecorder(
+      const std::string& label,
+      mojom::TraceDataType type,
+      base::WeakPtr<AgentRegistry::AgentEntry> agent_entry) {
+    mojom::RecorderPtr ptr;
+    auto recorder = std::make_unique<Recorder>(
+        MakeRequest(&ptr), type,
+        base::BindRepeating(&Coordinator::TraceStreamer::OnRecorderDataChange,
+                            AsWeakPtr(), label));
+    recorders_[label].insert(std::move(recorder));
+    DCHECK(type != mojom::TraceDataType::STRING ||
+           recorders_[label].size() == 1);
+
+    // Tracing agent proxies are bound on the main thread and should be called
+    // from the main thread.
+    main_task_runner_->PostTask(
+        FROM_HERE, base::BindOnce(&Coordinator::SendRecorder, coordinator_,
+                                  agent_entry, std::move(ptr)));
+  }
+
+  // Called from |background_task_runner_| to close the recorder proxy on the
+  // correct task runner.
+  void CloseRecorder(mojom::RecorderPtr recorder) {}
+
+  // Called from |main_task_runner_| either after flushing is complete or at
+  // shutdown. We either will not write to the stream afterwards or do not care
+  // what happens to what we try to write.
+  void CloseStream() {
+    DCHECK(stream_.is_valid());
+    stream_.reset();
+  }
+
+  // Called from |main_task_runner_| after flushing is completed. So we are sure
+  // there is no race in accessing metadata_.
+  std::unique_ptr<base::DictionaryValue> GetMetadata() {
+    return std::move(metadata_);
+  }
+
+ private:
+  // Called from |background_task_runner_|.
+  void OnRecorderDataChange(const std::string& label) {
+    // Bail out if we are in the middle of writing events for another label to
+    // the stream, since we do not want to interleave chunks for different
+    // fields. For example, we do not want to mix |traceEvent| chunks with
+    // |battor| chunks.
+    //
+    // If we receive a |battor| chunk from an agent while writing |traceEvent|
+    // chunks to the stream, we wait until all agents that send |traceEvent|
+    // chunks are done, and then, we start writing |battor| chunks.
+    if (!streaming_label_.empty() && streaming_label_ != label)
+      return;
+
+    while (streaming_label_.empty() || !StreamEventsForCurrentLabel()) {
+      // We are not waiting for data from any particular label now. So, we look
+      // at the recorders that have some data available and select the next
+      // label to stream.
+      streaming_label_.clear();
+      bool all_finished = true;
+      for (const auto& key_value : recorders_) {
+        for (const auto& recorder : key_value.second) {
+          all_finished &= !recorder->is_recording();
+          if (!recorder->data().empty()) {
+            streaming_label_ = key_value.first;
+            json_field_name_written_ = false;
+            break;
+          }
+        }
+        if (!streaming_label_.empty())
+          break;
+      }
+
+      if (streaming_label_.empty()) {
+        // No recorder has any data for us, right now.
+        if (all_finished) {
+          StreamMetadata();
+          if (!stream_is_empty_ && agent_label_.empty()) {
+            mojo::common::BlockingCopyFromString("}", stream_);
+            stream_is_empty_ = false;
+          }
+          // Recorder connections should be closed on their binding thread.
+          main_task_runner_->PostTask(
+              FROM_HERE,
+              base::BindOnce(&Coordinator::OnFlushDone, coordinator_));
+        }
+        return;
+      }
+    }
+  }
+
+  // Called from |background_task_runner_|.
+  bool StreamEventsForCurrentLabel() {
+    bool waiting_for_agents = false;
+    mojom::TraceDataType data_type =
+        (*recorders_[streaming_label_].begin())->data_type();
+    for (const auto& recorder : recorders_[streaming_label_]) {
+      waiting_for_agents |= recorder->is_recording();
+      if (!agent_label_.empty() && streaming_label_ != agent_label_)
+        recorder->clear_data();
+      if (recorder->data().empty())
+        continue;
+
+      std::string prefix;
+      if (!json_field_name_written_ && agent_label_.empty()) {
+        prefix = (stream_is_empty_ ? "{\"" : ",\"") + streaming_label_ + "\":";
+        switch (data_type) {
+          case mojom::TraceDataType::ARRAY:
+            prefix += "[";
+            break;
+          case mojom::TraceDataType::OBJECT:
+            prefix += "{";
+            break;
+          case mojom::TraceDataType::STRING:
+            prefix += "\"";
+            break;
+          default:
+            NOTREACHED();
+        }
+        json_field_name_written_ = true;
+      }
+      if (data_type == mojom::TraceDataType::STRING) {
+        // Escape characters if needed for string data.
+        std::string escaped;
+        base::EscapeJSONString(recorder->data(), false /* put_in_quotes */,
+                               &escaped);
+        mojo::common::BlockingCopyFromString(prefix + escaped, stream_);
+      } else {
+        if (prefix.empty() && !stream_is_empty_)
+          prefix = ",";
+        mojo::common::BlockingCopyFromString(prefix + recorder->data(),
+                                             stream_);
+      }
+      stream_is_empty_ = false;
+      recorder->clear_data();
+    }
+    if (!waiting_for_agents) {
+      if (json_field_name_written_) {
+        switch (data_type) {
+          case mojom::TraceDataType::ARRAY:
+            mojo::common::BlockingCopyFromString("]", stream_);
+            break;
+          case mojom::TraceDataType::OBJECT:
+            mojo::common::BlockingCopyFromString("}", stream_);
+            break;
+          case mojom::TraceDataType::STRING:
+            mojo::common::BlockingCopyFromString("\"", stream_);
+            break;
+          default:
+            NOTREACHED();
+        }
+        stream_is_empty_ = false;
+      }
+    }
+    return waiting_for_agents;
+  }
+
+  // Called from |background_task_runner_|.
+  void StreamMetadata() {
+    if (!agent_label_.empty())
+      return;
+
+    for (const auto& key_value : recorders_) {
+      for (const auto& recorder : key_value.second) {
+        metadata_->MergeDictionary(&(recorder->metadata()));
+      }
+    }
+
+    std::string metadataJSON;
+    if (!metadata_->empty() &&
+        base::JSONWriter::Write(*metadata_, &metadataJSON)) {
+      std::string prefix = stream_is_empty_ ? "{\"" : ",\"";
+      mojo::common::BlockingCopyFromString(
+          prefix + std::string(kMetadataTraceLabel) + "\":" + metadataJSON,
+          stream_);
+      stream_is_empty_ = false;
+    }
+  }
+
+  // The stream to which trace events from different agents should be
+  // serialized, eventually. This is set when tracing is stopped.
+  mojo::ScopedDataPipeProducerHandle stream_;
+  std::string agent_label_;
+  scoped_refptr<base::SequencedTaskRunner> main_task_runner_;
+  base::WeakPtr<Coordinator> coordinator_;
+
+  std::map<std::string, std::set<std::unique_ptr<Recorder>>> recorders_;
+
+  // If |streaming_label_| is not empty, it shows the label for which we are
+  // writing chunks to the output stream.
+  std::string streaming_label_;
+  std::unique_ptr<base::DictionaryValue> metadata_;
+  bool stream_is_empty_;
+  bool json_field_name_written_;
+
+  DISALLOW_COPY_AND_ASSIGN(TraceStreamer);
+};
+
 // static
 Coordinator* Coordinator::GetInstance() {
   DCHECK(g_coordinator);
@@ -57,7 +273,8 @@
 Coordinator::Coordinator()
     : binding_(this),
       task_runner_(base::ThreadTaskRunnerHandle::Get()),
-      agent_registry_(AgentRegistry::GetInstance()) {
+      agent_registry_(AgentRegistry::GetInstance()),
+      weak_ptr_factory_(this) {
   DCHECK(!g_coordinator);
   DCHECK(agent_registry_);
   g_coordinator = this;
@@ -68,8 +285,10 @@
 }
 
 Coordinator::~Coordinator() {
-  if (!stop_and_flush_callback_.is_null())
-    stop_and_flush_callback_.Run(std::make_unique<base::DictionaryValue>());
+  if (!stop_and_flush_callback_.is_null()) {
+    base::ResetAndReturn(&stop_and_flush_callback_)
+        .Run(std::make_unique<base::DictionaryValue>());
+  }
   if (!start_tracing_callback_.is_null())
     base::ResetAndReturn(&start_tracing_callback_).Run(false);
   if (!request_buffer_usage_callback_.is_null())
@@ -77,6 +296,17 @@
   if (!get_categories_callback_.is_null())
     base::ResetAndReturn(&get_categories_callback_).Run(false, "");
 
+  if (trace_streamer_) {
+    // We are in the middle of flushing trace data. We need to
+    // 1- Close the stream so that the TraceStreamer does not block on writing
+    //    to it.
+    // 2- Delete the TraceStreamer on the background task runner; it owns
+    //    recorders that should be destructed on the background task runner
+    //    because they are bound on the background task runner.
+    trace_streamer_->CloseStream();
+    background_task_runner_->DeleteSoon(FROM_HERE, trace_streamer_.release());
+  }
+
   g_coordinator = nullptr;
 }
 
@@ -97,7 +327,7 @@
   is_tracing_ = true;
   config_ = config;
   agent_registry_->SetAgentInitializationCallback(base::BindRepeating(
-      &Coordinator::SendStartTracingToAgent, base::Unretained(this)));
+      &Coordinator::SendStartTracingToAgent, weak_ptr_factory_.GetWeakPtr()));
   if (!agent_registry_->HasDisconnectClosure(&kStartTracingClosureName)) {
     callback.Run(true);
     return;
@@ -110,12 +340,13 @@
   DCHECK(!agent_entry->is_tracing());
   agent_entry->AddDisconnectClosure(
       &kStartTracingClosureName,
-      base::BindOnce(&Coordinator::OnTracingStarted, base::Unretained(this),
+      base::BindOnce(&Coordinator::OnTracingStarted,
+                     weak_ptr_factory_.GetWeakPtr(),
                      base::Unretained(agent_entry), false));
   agent_entry->agent()->StartTracing(
       config_, base::TimeTicks::Now(),
       base::BindRepeating(&Coordinator::OnTracingStarted,
-                          base::Unretained(this),
+                          weak_ptr_factory_.GetWeakPtr(),
                           base::Unretained(agent_entry)));
 }
 
@@ -145,14 +376,15 @@
     callback.Run(std::make_unique<base::DictionaryValue>());
     return;
   }
-  DCHECK(!stream_.is_valid());
+  DCHECK(!trace_streamer_);
   DCHECK(stream.is_valid());
 
   // Do not send |StartTracing| to agents that connect from now on.
   agent_registry_->RemoveAgentInitializationCallback();
-  agent_label_ = agent_label;
+  trace_streamer_.reset(new Coordinator::TraceStreamer(
+      std::move(stream), agent_label, task_runner_,
+      weak_ptr_factory_.GetWeakPtr()));
   stop_and_flush_callback_ = callback;
-  stream_ = std::move(stream);
   StopAndFlushInternal();
 }
 
@@ -163,7 +395,7 @@
     task_runner_->PostDelayedTask(
         FROM_HERE,
         base::BindRepeating(&Coordinator::StopAndFlushInternal,
-                            base::Unretained(this)),
+                            weak_ptr_factory_.GetWeakPtr()),
         base::TimeDelta::FromMilliseconds(
             mojom::kStopTracingRetryTimeMilliseconds));
     return;
@@ -178,12 +410,13 @@
     agent_entry->AddDisconnectClosure(
         &kRequestClockSyncMarkerClosureName,
         base::BindOnce(&Coordinator::OnRequestClockSyncMarkerResponse,
-                       base::Unretained(this), base::Unretained(agent_entry),
-                       sync_id, base::TimeTicks(), base::TimeTicks()));
+                       weak_ptr_factory_.GetWeakPtr(),
+                       base::Unretained(agent_entry), sync_id,
+                       base::TimeTicks(), base::TimeTicks()));
     agent_entry->agent()->RequestClockSyncMarker(
         sync_id,
         base::BindRepeating(&Coordinator::OnRequestClockSyncMarkerResponse,
-                            base::Unretained(this),
+                            weak_ptr_factory_.GetWeakPtr(),
                             base::Unretained(agent_entry), sync_id));
   });
   if (!agent_registry_->HasDisconnectClosure(
@@ -214,169 +447,40 @@
 }
 
 void Coordinator::StopAndFlushAfterClockSync() {
-  metadata_.reset(new base::DictionaryValue());
-  stream_is_empty_ = true;
-  streaming_label_.clear();
-
-  agent_registry_->ForAllAgents([this](AgentRegistry::AgentEntry* agent_entry) {
-    if (!agent_entry->is_tracing())
-      return;
-    mojom::RecorderPtr ptr;
-    recorders_[agent_entry->label()].insert(std::make_unique<Recorder>(
-        MakeRequest(&ptr), agent_entry->type(),
-        base::BindRepeating(&Coordinator::OnRecorderDataChange,
-                            base::Unretained(this), agent_entry->label()),
-        background_task_runner_));
-    DCHECK(agent_entry->type() != mojom::TraceDataType::STRING ||
-           recorders_[agent_entry->label()].size() == 1);
-    agent_entry->agent()->StopAndFlush(std::move(ptr));
-  });
-
-  if (recorders_.empty())
+  bool has_tracing_agents = false;
+  agent_registry_->ForAllAgents(
+      [this, &has_tracing_agents](AgentRegistry::AgentEntry* agent_entry) {
+        if (!agent_entry->is_tracing())
+          return;
+        has_tracing_agents = true;
+        background_task_runner_->PostTask(
+            FROM_HERE,
+            base::BindOnce(&Coordinator::TraceStreamer::CreateAndSendRecorder,
+                           trace_streamer_->AsWeakPtr(), agent_entry->label(),
+                           agent_entry->type(), agent_entry->AsWeakPtr()));
+      });
+  if (!has_tracing_agents)
     OnFlushDone();
 }
 
-void Coordinator::OnRecorderDataChange(const std::string& label) {
-  DCHECK(background_task_runner_->RunsTasksInCurrentSequence());
-
-  // Bail out if we are in the middle of writing events for another label to the
-  // stream, since we do not want to interleave chunks for different fields. For
-  // example, we do not want to mix |traceEvent| chunks with |battor| chunks.
-  //
-  // If we receive a |battor| chunk from an agent while writing |traceEvent|
-  // chunks to the stream, we wait until all agents that send |traceEvent|
-  // chunks are done, and then, we start writing |battor| chunks.
-  if (!streaming_label_.empty() && streaming_label_ != label)
-    return;
-
-  while (streaming_label_.empty() || !StreamEventsForCurrentLabel()) {
-    // We are not waiting for data from any particular label now. So, we look at
-    // the recorders that have some data available and select the next label to
-    // stream.
-    streaming_label_.clear();
-    bool all_finished = true;
-    for (const auto& key_value : recorders_) {
-      for (const auto& recorder : key_value.second) {
-        all_finished &= !recorder->is_recording();
-        if (!recorder->data().empty()) {
-          streaming_label_ = key_value.first;
-          json_field_name_written_ = false;
-          break;
-        }
-      }
-      if (!streaming_label_.empty())
-        break;
-    }
-
-    if (streaming_label_.empty()) {
-      // No recorder has any data for us, right now.
-      if (all_finished) {
-        StreamMetadata();
-        if (!stream_is_empty_ && agent_label_.empty()) {
-          mojo::common::BlockingCopyFromString("}", stream_);
-          stream_is_empty_ = false;
-        }
-        // Recorder connections should be closed on their binding thread.
-        task_runner_->PostTask(
-            FROM_HERE,
-            base::BindOnce(&Coordinator::OnFlushDone, base::Unretained(this)));
-      }
-      return;
-    }
-  }
-}
-
-bool Coordinator::StreamEventsForCurrentLabel() {
-  DCHECK(background_task_runner_->RunsTasksInCurrentSequence());
-  bool waiting_for_agents = false;
-  mojom::TraceDataType data_type =
-      (*recorders_[streaming_label_].begin())->data_type();
-  for (const auto& recorder : recorders_[streaming_label_]) {
-    waiting_for_agents |= recorder->is_recording();
-    if (!agent_label_.empty() && streaming_label_ != agent_label_)
-      recorder->clear_data();
-    if (recorder->data().empty())
-      continue;
-
-    std::string prefix;
-    if (!json_field_name_written_ && agent_label_.empty()) {
-      prefix = (stream_is_empty_ ? "{\"" : ",\"") + streaming_label_ + "\":";
-      switch (data_type) {
-        case mojom::TraceDataType::ARRAY:
-          prefix += "[";
-          break;
-        case mojom::TraceDataType::OBJECT:
-          prefix += "{";
-          break;
-        case mojom::TraceDataType::STRING:
-          prefix += "\"";
-          break;
-        default:
-          NOTREACHED();
-      }
-      json_field_name_written_ = true;
-    }
-    if (data_type == mojom::TraceDataType::STRING) {
-      // Escape characters if needed for string data.
-      std::string escaped;
-      base::EscapeJSONString(recorder->data(), false /* put_in_quotes */,
-                             &escaped);
-      mojo::common::BlockingCopyFromString(prefix + escaped, stream_);
-    } else {
-      if (prefix.empty() && !stream_is_empty_)
-        prefix = ",";
-      mojo::common::BlockingCopyFromString(prefix + recorder->data(), stream_);
-    }
-    stream_is_empty_ = false;
-    recorder->clear_data();
-  }
-  if (!waiting_for_agents) {
-    if (json_field_name_written_) {
-      switch (data_type) {
-        case mojom::TraceDataType::ARRAY:
-          mojo::common::BlockingCopyFromString("]", stream_);
-          break;
-        case mojom::TraceDataType::OBJECT:
-          mojo::common::BlockingCopyFromString("}", stream_);
-          break;
-        case mojom::TraceDataType::STRING:
-          mojo::common::BlockingCopyFromString("\"", stream_);
-          break;
-        default:
-          NOTREACHED();
-      }
-      stream_is_empty_ = false;
-    }
-  }
-  return waiting_for_agents;
-}
-
-void Coordinator::StreamMetadata() {
-  DCHECK(background_task_runner_->RunsTasksInCurrentSequence());
-  if (!agent_label_.empty())
-    return;
-
-  for (const auto& key_value : recorders_) {
-    for (const auto& recorder : key_value.second) {
-      metadata_->MergeDictionary(&(recorder->metadata()));
-    }
-  }
-
-  std::string metadataJSON;
-  if (!metadata_->empty() &&
-      base::JSONWriter::Write(*metadata_, &metadataJSON)) {
-    std::string prefix = stream_is_empty_ ? "{\"" : ",\"";
-    mojo::common::BlockingCopyFromString(
-        prefix + std::string(kMetadataTraceLabel) + "\":" + metadataJSON,
-        stream_);
-    stream_is_empty_ = false;
+void Coordinator::SendRecorder(
+    base::WeakPtr<AgentRegistry::AgentEntry> agent_entry,
+    mojom::RecorderPtr recorder) {
+  if (agent_entry) {
+    agent_entry->agent()->StopAndFlush(std::move(recorder));
+  } else {
+    // Recorders are created and closed on |background_task_runner_|.
+    background_task_runner_->PostTask(
+        FROM_HERE,
+        base::BindOnce(&Coordinator::TraceStreamer::CloseRecorder,
+                       trace_streamer_->AsWeakPtr(), std::move(recorder)));
   }
 }
 
 void Coordinator::OnFlushDone() {
-  recorders_.clear();
-  stream_.reset();
-  base::ResetAndReturn(&stop_and_flush_callback_).Run(std::move(metadata_));
+  base::ResetAndReturn(&stop_and_flush_callback_)
+      .Run(trace_streamer_->GetMetadata());
+  background_task_runner_->DeleteSoon(FROM_HERE, trace_streamer_.release());
   agent_registry_->ForAllAgents([this](AgentRegistry::AgentEntry* agent_entry) {
     agent_entry->set_is_tracing(false);
   });
@@ -401,11 +505,12 @@
     agent_entry->AddDisconnectClosure(
         &kRequestBufferUsageClosureName,
         base::BindOnce(&Coordinator::OnRequestBufferStatusResponse,
-                       base::Unretained(this), base::Unretained(agent_entry),
-                       0 /* capacity */, 0 /* count */));
+                       weak_ptr_factory_.GetWeakPtr(),
+                       base::Unretained(agent_entry), 0 /* capacity */,
+                       0 /* count */));
     agent_entry->agent()->RequestBufferStatus(base::BindRepeating(
-        &Coordinator::OnRequestBufferStatusResponse, base::Unretained(this),
-        base::Unretained(agent_entry)));
+        &Coordinator::OnRequestBufferStatusResponse,
+        weak_ptr_factory_.GetWeakPtr(), base::Unretained(agent_entry)));
   });
 }
 
@@ -444,10 +549,10 @@
     agent_entry->AddDisconnectClosure(
         &kGetCategoriesClosureName,
         base::BindOnce(&Coordinator::OnGetCategoriesResponse,
-                       base::Unretained(this), base::Unretained(agent_entry),
-                       ""));
+                       weak_ptr_factory_.GetWeakPtr(),
+                       base::Unretained(agent_entry), ""));
     agent_entry->agent()->GetCategories(base::BindRepeating(
-        &Coordinator::OnGetCategoriesResponse, base::Unretained(this),
+        &Coordinator::OnGetCategoriesResponse, weak_ptr_factory_.GetWeakPtr(),
         base::Unretained(agent_entry)));
   });
 }
diff --git a/services/resource_coordinator/tracing/coordinator.h b/services/resource_coordinator/tracing/coordinator.h
index 6a2978a9..5ce69676 100644
--- a/services/resource_coordinator/tracing/coordinator.h
+++ b/services/resource_coordinator/tracing/coordinator.h
@@ -11,6 +11,7 @@
 #include <string>
 
 #include "base/memory/ref_counted.h"
+#include "base/memory/weak_ptr.h"
 #include "base/sequenced_task_runner.h"
 #include "base/single_thread_task_runner.h"
 #include "base/values.h"
@@ -51,6 +52,8 @@
   friend std::default_delete<Coordinator>;
   friend class CoordinatorTest;  // For testing.
 
+  class TraceStreamer;
+
   ~Coordinator() override;
 
   // mojom::Coordinator
@@ -74,9 +77,8 @@
                                         base::TimeTicks issue_ts,
                                         base::TimeTicks issue_end_ts);
   void StopAndFlushAfterClockSync();
-  void OnRecorderDataChange(const std::string& label);
-  bool StreamEventsForCurrentLabel();
-  void StreamMetadata();
+  void SendRecorder(base::WeakPtr<AgentRegistry::AgentEntry> agent_entry,
+                    mojom::RecorderPtr recorder);
   void OnFlushDone();
 
   void OnRequestBufferStatusResponse(AgentRegistry::AgentEntry* agent_entry,
@@ -91,20 +93,9 @@
   scoped_refptr<base::SequencedTaskRunner> background_task_runner_;
   AgentRegistry* agent_registry_;
   std::string config_;
-  std::map<std::string, std::set<std::unique_ptr<Recorder>>> recorders_;
   bool is_tracing_ = false;
 
-  std::string agent_label_;
-
-  // The stream to which trace events from different agents should be
-  // serialized, eventually. This is set when tracing is stopped.
-  mojo::ScopedDataPipeProducerHandle stream_;
-  // If |streaming_label_| is not empty, it shows the label for which we are
-  // writing chunks to the output stream.
-  std::string streaming_label_;
-  std::unique_ptr<base::DictionaryValue> metadata_;
-  bool stream_is_empty_ = true;
-  bool json_field_name_written_ = false;
+  std::unique_ptr<TraceStreamer> trace_streamer_;
   StartTracingCallback start_tracing_callback_;
   StopAndFlushCallback stop_and_flush_callback_;
 
@@ -117,6 +108,8 @@
   std::set<std::string> category_set_;
   GetCategoriesCallback get_categories_callback_;
 
+  base::WeakPtrFactory<Coordinator> weak_ptr_factory_;
+
   DISALLOW_COPY_AND_ASSIGN(Coordinator);
 };
 
diff --git a/services/resource_coordinator/tracing/recorder.cc b/services/resource_coordinator/tracing/recorder.cc
index 7c1a236..33b117d6 100644
--- a/services/resource_coordinator/tracing/recorder.cc
+++ b/services/resource_coordinator/tracing/recorder.cc
@@ -6,43 +6,20 @@
 
 #include "base/callback_forward.h"
 #include "base/memory/ref_counted.h"
-#include "base/sequenced_task_runner.h"
 #include "services/resource_coordinator/public/interfaces/tracing/tracing.mojom.h"
 
 namespace tracing {
 
-Recorder::Recorder(
-    mojom::RecorderRequest request,
-    mojom::TraceDataType data_type,
-    const base::Closure& on_data_change_callback,
-    const scoped_refptr<base::SequencedTaskRunner>& background_task_runner)
+Recorder::Recorder(mojom::RecorderRequest request,
+                   mojom::TraceDataType data_type,
+                   const base::RepeatingClosure& on_data_change_callback)
     : is_recording_(true),
       data_type_(data_type),
       on_data_change_callback_(on_data_change_callback),
-      background_task_runner_(background_task_runner),
-      binding_(this, std::move(request)) {
-  // A recorder should be deleted only if |is_recording_| is false to ensure
-  // that:
-  //
-  // 1- |OnConnectionError| is already executed and so using Unretained(this) is
-  // safe here.
-  //
-  // 2- The task possibly posted by |OnConnectionError| is already executed and
-  // so using Unretained(this) is safe in that PostTask.
-  //
-  // 3- Since the connection is closed, the tasks posted by |AddChunk| are
-  // already executed and so using Unretained(this) is safe in the PostTask in
-  // |AddChunk|.
-  //
-  // We cannot use a weak pointer factory here since the weak pointers should be
-  // dereferenced on the same SequencedTaskRunner. We could use two weak pointer
-  // factories but that increases the complexity of the code since each factory
-  // should be created on the correct thread and we should deal with cases that
-  // one of the factories is not created, yet.
-  //
-  // The tracing coordinator deletes a recorder when |is_recording_| is false.
-  binding_.set_connection_error_handler(base::BindRepeating(
-      &Recorder::OnConnectionError, base::Unretained(this)));
+      binding_(this, std::move(request)),
+      weak_ptr_factory_(this) {
+  binding_.set_connection_error_handler(base::BindOnce(
+      &Recorder::OnConnectionError, weak_ptr_factory_.GetWeakPtr()));
 }
 
 Recorder::~Recorder() = default;
@@ -50,12 +27,6 @@
 void Recorder::AddChunk(const std::string& chunk) {
   if (chunk.empty())
     return;
-  if (!background_task_runner_->RunsTasksInCurrentSequence()) {
-    background_task_runner_->PostTask(
-        FROM_HERE, base::BindRepeating(&Recorder::AddChunk,
-                                       base::Unretained(this), chunk));
-    return;
-  }
   if (data_type_ != mojom::TraceDataType::STRING && !data_.empty())
     data_.append(",");
   data_.append(chunk);
@@ -67,12 +38,6 @@
 }
 
 void Recorder::OnConnectionError() {
-  if (!background_task_runner_->RunsTasksInCurrentSequence()) {
-    background_task_runner_->PostTask(
-        FROM_HERE, base::BindRepeating(&Recorder::OnConnectionError,
-                                       base::Unretained(this)));
-    return;
-  }
   is_recording_ = false;
   on_data_change_callback_.Run();
 }
diff --git a/services/resource_coordinator/tracing/recorder.h b/services/resource_coordinator/tracing/recorder.h
index 421df03..3c8baa2 100644
--- a/services/resource_coordinator/tracing/recorder.h
+++ b/services/resource_coordinator/tracing/recorder.h
@@ -9,7 +9,7 @@
 #include "base/logging.h"
 #include "base/macros.h"
 #include "base/memory/ref_counted.h"
-#include "base/sequenced_task_runner.h"
+#include "base/memory/weak_ptr.h"
 #include "base/values.h"
 #include "mojo/public/cpp/bindings/binding.h"
 #include "services/resource_coordinator/public/interfaces/tracing/tracing.mojom.h"
@@ -29,26 +29,16 @@
   // |on_data_change_callback| is run whenever the recorder receives data from
   // the agent or when the connection is lost to notify the tracing service of
   // the data change.
-  //
-  // |background_task_runner| is used so that if the tracing service is run on
-  // the UI thread we do not block it. So buffering trace events and copying
-  // them to data pipes are done on a background thread.
-  Recorder(
-      mojom::RecorderRequest request,
-      mojom::TraceDataType data_type,
-      const base::Closure& on_data_change_callback,
-      const scoped_refptr<base::SequencedTaskRunner>& background_task_runner);
+  Recorder(mojom::RecorderRequest request,
+           mojom::TraceDataType data_type,
+           const base::RepeatingClosure& on_data_change_callback);
   ~Recorder() override;
 
   const std::string& data() const {
-    // All access to |data_| should be done on the background thread.
-    DCHECK(background_task_runner_->RunsTasksInCurrentSequence());
     return data_;
   }
 
   void clear_data() {
-    // All access to |data_| should be done on the background thread.
-    DCHECK(background_task_runner_->RunsTasksInCurrentSequence());
     data_.clear();
   }
 
@@ -69,13 +59,11 @@
   base::DictionaryValue metadata_;
   bool is_recording_;
   mojom::TraceDataType data_type_;
-  base::Closure on_data_change_callback_;
-  // To avoid blocking the UI thread if the tracing service is run on the UI
-  // thread, we make sure that buffering trace events and copying them to the
-  // final stream is done on a background thread.
-  scoped_refptr<base::SequencedTaskRunner> background_task_runner_;
+  base::RepeatingClosure on_data_change_callback_;
   mojo::Binding<mojom::Recorder> binding_;
 
+  base::WeakPtrFactory<Recorder> weak_ptr_factory_;
+
   DISALLOW_COPY_AND_ASSIGN(Recorder);
 };
 
diff --git a/services/resource_coordinator/tracing/recorder_unittest.cc b/services/resource_coordinator/tracing/recorder_unittest.cc
index 70f0612..e316153d 100644
--- a/services/resource_coordinator/tracing/recorder_unittest.cc
+++ b/services/resource_coordinator/tracing/recorder_unittest.cc
@@ -26,8 +26,7 @@
   void CreateRecorder(mojom::RecorderRequest request,
                       mojom::TraceDataType data_type,
                       const base::Closure& callback) {
-    recorder_.reset(new Recorder(std::move(request), data_type, callback,
-                                 base::ThreadTaskRunnerHandle::Get()));
+    recorder_.reset(new Recorder(std::move(request), data_type, callback));
   }
 
   void CreateRecorder(mojom::TraceDataType data_type,
diff --git a/services/service_manager/public/cpp/identity.cc b/services/service_manager/public/cpp/identity.cc
index 01c61fb..13db9b0e 100644
--- a/services/service_manager/public/cpp/identity.cc
+++ b/services/service_manager/public/cpp/identity.cc
@@ -29,6 +29,13 @@
 
 Identity::~Identity() {}
 
+Identity& Identity::operator=(const Identity& other) {
+  name_ = other.name_;
+  user_id_ = other.user_id_;
+  instance_ = other.instance_;
+  return *this;
+}
+
 bool Identity::operator<(const Identity& other) const {
   if (name_ != other.name_)
     return name_ < other.name_;
diff --git a/services/service_manager/public/cpp/identity.h b/services/service_manager/public/cpp/identity.h
index 210468d..564b511 100644
--- a/services/service_manager/public/cpp/identity.h
+++ b/services/service_manager/public/cpp/identity.h
@@ -29,6 +29,7 @@
   Identity(const Identity& other);
   ~Identity();
 
+  Identity& operator=(const Identity& other);
   bool operator<(const Identity& other) const;
   bool operator==(const Identity& other) const;
   bool IsValid() const;
diff --git a/services/service_manager/public/cpp/service_test.cc b/services/service_manager/public/cpp/service_test.cc
index 9419d24..0c92551 100644
--- a/services/service_manager/public/cpp/service_test.cc
+++ b/services/service_manager/public/cpp/service_test.cc
@@ -32,14 +32,11 @@
     const std::string& interface_name,
     mojo::ScopedMessagePipeHandle interface_pipe) {}
 
-ServiceTest::ServiceTest() : ServiceTest(std::string(), true) {}
+ServiceTest::ServiceTest() : ServiceTest(std::string()) {}
 
 ServiceTest::ServiceTest(const std::string& test_name,
-                         bool init_edk,
                          base::test::ScopedTaskEnvironment::MainThreadType type)
-    : scoped_task_environment_(type),
-      test_name_(test_name),
-      init_edk_(init_edk) {}
+    : scoped_task_environment_(type), test_name_(test_name) {}
 
 ServiceTest::~ServiceTest() {}
 
@@ -62,8 +59,6 @@
 }
 
 void ServiceTest::SetUp() {
-  DCHECK(!init_edk_);
-
   background_service_manager_ =
       base::MakeUnique<service_manager::BackgroundServiceManager>(nullptr,
                                                                   nullptr);
diff --git a/services/service_manager/public/cpp/service_test.h b/services/service_manager/public/cpp/service_test.h
index 3014409..fdc942b6 100644
--- a/services/service_manager/public/cpp/service_test.h
+++ b/services/service_manager/public/cpp/service_test.h
@@ -61,7 +61,6 @@
   // InitTestName(). The test executable must provide a manifest in the
   // appropriate location that specifies this name also.
   ServiceTest(const std::string& test_name,
-              bool init_edk = false,
               base::test::ScopedTaskEnvironment::MainThreadType type =
                   base::test::ScopedTaskEnvironment::MainThreadType::UI);
   ~ServiceTest() override;
@@ -70,7 +69,7 @@
   // See constructor. Can only be called once.
   void InitTestName(const std::string& test_name);
 
-  Connector* connector() { return connector_; }
+  Connector* connector() const { return connector_; }
 
   // Instance information received from the Service Manager during OnStart().
   const std::string& test_name() const { return initialize_name_; }
@@ -101,7 +100,6 @@
 
   // See constructor.
   std::string test_name_;
-  bool init_edk_;
   std::unique_ptr<base::Thread> ipc_thread_;
   std::unique_ptr<mojo::edk::ScopedIPCSupport> ipc_support_;
 
diff --git a/services/service_manager/public/cpp/test/test_connector_factory.cc b/services/service_manager/public/cpp/test/test_connector_factory.cc
index dd784ff9..406f493 100644
--- a/services/service_manager/public/cpp/test/test_connector_factory.cc
+++ b/services/service_manager/public/cpp/test/test_connector_factory.cc
@@ -7,6 +7,7 @@
 #include "base/macros.h"
 #include "mojo/public/cpp/bindings/binding_set.h"
 #include "services/service_manager/public/cpp/service.h"
+#include "services/service_manager/public/cpp/service_context.h"
 #include "services/service_manager/public/interfaces/connector.mojom.h"
 
 namespace service_manager {
@@ -15,8 +16,14 @@
 
 class TestConnectorImpl : public mojom::Connector {
  public:
-  TestConnectorImpl(TestConnectorFactory* factory, Service* service)
-      : factory_(factory), service_(service) {}
+  TestConnectorImpl(TestConnectorFactory* factory,
+                    std::unique_ptr<Service> service)
+      : service_context_(std::move(service), mojo::MakeRequest(&service_ptr_)),
+        factory_(factory) {
+    service_ptr_->OnStart(factory_->source_identity(),
+                          base::BindOnce(&TestConnectorImpl::OnStartCallback,
+                                         base::Unretained(this)));
+  }
 
   ~TestConnectorImpl() override = default;
 
@@ -24,9 +31,10 @@
                      const std::string& interface_name,
                      mojo::ScopedMessagePipeHandle interface_pipe,
                      BindInterfaceCallback callback) override {
-    service_->OnBindInterface(
+    service_ptr_->OnBindInterface(
         BindSourceInfo(factory_->source_identity(), CapabilitySet()),
-        interface_name, std::move(interface_pipe));
+        interface_name, std::move(interface_pipe),
+        base::Bind(&base::DoNothing));
     std::move(callback).Run(mojom::ConnectResult::SUCCEEDED, Identity());
   }
 
@@ -60,8 +68,14 @@
   }
 
  private:
+  void OnStartCallback(
+      service_manager::mojom::ConnectorRequest request,
+      service_manager::mojom::ServiceControlAssociatedRequest control_request) {
+  }
+
+  mojom::ServicePtr service_ptr_;
+  service_manager::ServiceContext service_context_;
   TestConnectorFactory* const factory_;
-  Service* const service_;
   mojo::BindingSet<mojom::Connector> bindings_;
 
   DISALLOW_COPY_AND_ASSIGN(TestConnectorImpl);
@@ -69,9 +83,9 @@
 
 }  // namespace
 
-TestConnectorFactory::TestConnectorFactory(Service* service)
+TestConnectorFactory::TestConnectorFactory(std::unique_ptr<Service> service)
     : source_identity_("TestConnectorFactory"),
-      impl_(base::MakeUnique<TestConnectorImpl>(this, service)) {}
+      impl_(std::make_unique<TestConnectorImpl>(this, std::move(service))) {}
 
 TestConnectorFactory::~TestConnectorFactory() = default;
 
diff --git a/services/service_manager/public/cpp/test/test_connector_factory.h b/services/service_manager/public/cpp/test/test_connector_factory.h
index 6573893..cb34796 100644
--- a/services/service_manager/public/cpp/test/test_connector_factory.h
+++ b/services/service_manager/public/cpp/test/test_connector_factory.h
@@ -40,7 +40,7 @@
   // Constructs a new TestConnectorFactory which creates Connectors whose
   // requests are routed directly to |service|. |service| is not owned and must
   // outlive this TestConnectorFactory instance.
-  explicit TestConnectorFactory(Service* service);
+  explicit TestConnectorFactory(std::unique_ptr<Service> service);
   ~TestConnectorFactory();
 
   // Allows a test to override the default Identity seen by the target service
diff --git a/services/service_manager/service_manager.cc b/services/service_manager/service_manager.cc
index 62af9b6..b7156c3 100644
--- a/services/service_manager/service_manager.cc
+++ b/services/service_manager/service_manager.cc
@@ -49,6 +49,7 @@
 const char kCapability_UserID[] = "service_manager:user_id";
 const char kCapability_ClientProcess[] = "service_manager:client_process";
 const char kCapability_InstanceName[] = "service_manager:instance_name";
+const char kCapability_Singleton[] = "service_manager:singleton";
 const char kCapability_AllUsers[] = "service_manager:all_users";
 const char kCapability_ServiceManager[] = "service_manager:service_manager";
 
@@ -573,9 +574,13 @@
     // TODO(beng): Need to do the following additional policy validation of
     // whether this instance is allowed to connect using:
     // - non-null client process info.
-    if (target.user_id() != identity_.user_id() &&
-        target.user_id() != mojom::kRootUserID &&
-        !HasCapability(connection_spec, kCapability_UserID)) {
+    bool skip_user_check =
+        HasCapability(connection_spec, kCapability_Singleton) ||
+        HasCapability(connection_spec, kCapability_AllUsers) ||
+        HasCapability(connection_spec, kCapability_UserID);
+
+    if (!skip_user_check && target.user_id() != identity_.user_id() &&
+        target.user_id() != mojom::kRootUserID) {
       LOG(ERROR) << "Instance: " << identity_.name()
                  << " running as: " << identity_.user_id()
                  << " attempting to connect to: " << target.name()
@@ -721,19 +726,90 @@
   DISALLOW_COPY_AND_ASSIGN(ServiceImpl);
 };
 
-// static
-ServiceManager::TestAPI::TestAPI(ServiceManager* service_manager)
-    : service_manager_(service_manager) {}
-ServiceManager::TestAPI::~TestAPI() {}
+// A container of Instances that stores them with an Identity and an
+// InstanceType so they can be resolved based on part of that Identity:
+// - all_users services are resolved based on the service name and instance ID.
+// - singleton services are resolved uniquely on the service name.
+// - other services ("regular" ones) are resolved using the full Identity.
+class ServiceManager::IdentityToInstanceMap {
+ public:
+  IdentityToInstanceMap() = default;
+  ~IdentityToInstanceMap() = default;
 
-bool ServiceManager::TestAPI::HasRunningInstanceForName(
-    const std::string& name) const {
-  for (const auto& entry : service_manager_->identity_to_instance_) {
-    if (entry.first.name() == name)
-      return true;
+  void Insert(const Identity& identity, InstanceType type, Instance* instance) {
+    DCHECK_NE(instance, nullptr);
+    DCHECK_EQ(Get(identity), nullptr);
+    switch (type) {
+      case InstanceType::kRegular:
+        regular_instances_.insert(std::make_pair(identity, instance));
+        break;
+      case InstanceType::kAllUsers:
+        all_user_instances_.insert(std::make_pair(
+            NameAndInstanceId(identity.name(), identity.instance()), instance));
+        break;
+      case InstanceType::kSingleton:
+        singleton_instances_.insert(std::make_pair(identity.name(), instance));
+        break;
+      default:
+        NOTREACHED();
+    }
   }
-  return false;
-}
+
+  Instance* Get(const Identity& identity) {
+    auto default_iter = regular_instances_.find(identity);
+    if (default_iter != regular_instances_.end())
+      return default_iter->second;
+    auto all_user_iter = all_user_instances_.find(
+        NameAndInstanceId(identity.name(), identity.instance()));
+    if (all_user_iter != all_user_instances_.end())
+      return all_user_iter->second;
+    auto singleton_iter = singleton_instances_.find(identity.name());
+    if (singleton_iter != singleton_instances_.end())
+      return singleton_iter->second;
+    return nullptr;
+  }
+
+  bool Erase(const Identity& identity) {
+    auto default_iter = regular_instances_.find(identity);
+    if (default_iter != regular_instances_.end()) {
+      regular_instances_.erase(default_iter);
+      return true;
+    }
+    auto all_user_iter = all_user_instances_.find(
+        NameAndInstanceId(identity.name(), identity.instance()));
+    if (all_user_iter != all_user_instances_.end()) {
+      all_user_instances_.erase(all_user_iter);
+      return true;
+    }
+    auto singleton_iter = singleton_instances_.find(identity.name());
+    if (singleton_iter != singleton_instances_.end()) {
+      singleton_instances_.erase(singleton_iter);
+      return true;
+    }
+    return false;
+  }
+
+  void PopulateRunningServiceInfo(
+      std::vector<mojom::RunningServiceInfoPtr>* running_service_info) {
+    running_service_info->reserve(regular_instances_.size() +
+                                  all_user_instances_.size() +
+                                  singleton_instances_.size());
+    for (auto iter : regular_instances_)
+      running_service_info->push_back(iter.second->CreateRunningServiceInfo());
+    for (auto iter : all_user_instances_)
+      running_service_info->push_back(iter.second->CreateRunningServiceInfo());
+    for (auto iter : singleton_instances_)
+      running_service_info->push_back(iter.second->CreateRunningServiceInfo());
+  }
+
+ private:
+  std::map<Identity, Instance*> regular_instances_;
+  using NameAndInstanceId = std::pair<std::string, std::string>;
+  std::map<NameAndInstanceId, Instance*> all_user_instances_;
+  std::map<std::string, Instance*> singleton_instances_;
+
+  DISALLOW_COPY_AND_ASSIGN(IdentityToInstanceMap);
+};
 
 ////////////////////////////////////////////////////////////////////////////////
 // ServiceManager, public:
@@ -743,6 +819,7 @@
                                std::unique_ptr<base::Value> catalog_contents,
                                catalog::ManifestProvider* manifest_provider)
     : catalog_(std::move(catalog_contents), manifest_provider),
+      identity_to_instance_(std::make_unique<IdentityToInstanceMap>()),
       service_process_launcher_factory_(
           std::move(service_process_launcher_factory)),
       weak_ptr_factory_(this) {
@@ -753,9 +830,9 @@
   InterfaceProviderSpecMap specs;
   specs[mojom::kServiceManager_ConnectorSpec] = std::move(spec);
 
-  service_manager_instance_ = CreateInstance(
-      Identity(), CreateServiceManagerIdentity(), std::move(specs));
-  singletons_.insert(service_manager::mojom::kServiceName);
+  service_manager_instance_ =
+      CreateInstance(Identity(), CreateServiceManagerIdentity(),
+                     InstanceType::kSingleton, std::move(specs));
 
   mojom::ServicePtr service;
   service_context_.reset(new ServiceContext(base::MakeUnique<ServiceImpl>(this),
@@ -799,7 +876,7 @@
   DCHECK(base::IsValidGUID(params->target().user_id()));
   DCHECK_NE(mojom::kInheritUserID, params->target().user_id());
   DCHECK(!params->HasClientProcessInfo() ||
-         !identity_to_instance_.count(params->target()));
+         GetExistingInstance(params->target()) == nullptr);
 
   // Connect to an existing matching instance, if possible.
   if (!params->HasClientProcessInfo() && ConnectToExistingInstance(&params))
@@ -825,13 +902,10 @@
           ? it->second
           : GetPermissiveInterfaceProviderSpec();
 
+  bool all_user_instance = HasCapability(connection_spec, kCapability_AllUsers);
+  bool singleton_instance =
+      HasCapability(connection_spec, kCapability_Singleton);
   const Identity original_target(params->target());
-  const std::string user_id =
-      HasCapability(connection_spec, kCapability_AllUsers)
-          ? base::GenerateGUID()
-          : params->target().user_id();
-  const Identity target(params->target().name(), user_id, instance_name);
-  params->set_target(target);
 
   // Services that request "all_users" class from the Service Manager are
   // allowed to field connection requests from any user. They also run with a
@@ -840,16 +914,34 @@
   // the lifetime of the service that started them, instead they are owned by
   // the Service Manager.
   Identity source_identity_for_creation;
-  if (HasCapability(connection_spec, kCapability_AllUsers)) {
-    singletons_.insert(target.name());
+
+  InstanceType instance_type;
+  if (singleton_instance)
+    instance_type = InstanceType::kSingleton;
+  else if (all_user_instance)
+    instance_type = InstanceType::kAllUsers;
+  else
+    instance_type = InstanceType::kRegular;
+
+  Identity target;
+  if (instance_type == InstanceType::kSingleton) {
     source_identity_for_creation = CreateServiceManagerIdentity();
+    target = Identity(params->target().name(), base::GenerateGUID());
+  } else if (instance_type == InstanceType::kAllUsers) {
+    source_identity_for_creation = CreateServiceManagerIdentity();
+    target =
+        Identity(params->target().name(), base::GenerateGUID(), instance_name);
   } else {
+    DCHECK_EQ(instance_type, InstanceType::kRegular);
     source_identity_for_creation = params->source();
+    target = Identity(params->target().name(), params->target().user_id(),
+                      instance_name);
   }
+  params->set_target(target);
 
   bool result_interface_provider_specs_empty = interface_provider_specs.empty();
   Instance* instance = CreateInstance(source_identity_for_creation, target,
-                                      interface_provider_specs);
+                                      instance_type, interface_provider_specs);
 
   // Below are various paths through which a new Instance can be bound to a
   // Service proxy.
@@ -876,8 +968,8 @@
     const std::string* target_user_id = &target.user_id();
     std::string factory_instance_name = instance_name;
 
-    // Use the original user ID so the existing embedder factory can
-    // be found and used to create the new service.
+    // Use the original user ID so the existing embedder factory can be found
+    // and used to create the new service.
     target_user_id = &original_target.user_id();
     Identity packaged_service_target(target);
     packaged_service_target.set_user_id(original_target.user_id());
@@ -965,8 +1057,7 @@
 
   Instance* instance =
       CreateInstance(CreateServiceManagerIdentity(), CreateCatalogIdentity(),
-                     std::move(specs));
-  singletons_.insert(catalog::mojom::kServiceName);
+                     InstanceType::kSingleton, std::move(specs));
   instance->StartWithService(std::move(catalog));
 }
 
@@ -1000,42 +1091,11 @@
 
 ServiceManager::Instance* ServiceManager::GetExistingInstance(
     const Identity& identity) const {
-  const auto& it = identity_to_instance_.find(identity);
-  Instance* instance = it != identity_to_instance_.end() ? it->second : nullptr;
-  if (instance)
-    return instance;
-
-  if (singletons_.find(identity.name()) != singletons_.end()) {
-    for (auto entry : identity_to_instance_) {
-      if (entry.first.name() == identity.name() &&
-          entry.first.instance() == identity.instance()) {
-        return entry.second;
-      }
-    }
-  }
-  return nullptr;
+  return identity_to_instance_->Get(identity);
 }
 
 void ServiceManager::EraseInstanceIdentity(Instance* instance) {
-  const Identity& identity = instance->identity();
-
-  auto it = identity_to_instance_.find(identity);
-  if (it != identity_to_instance_.end()) {
-    identity_to_instance_.erase(it);
-    return;
-  }
-
-  if (singletons_.find(identity.name()) != singletons_.end()) {
-    singletons_.erase(identity.name());
-    for (auto it = identity_to_instance_.begin();
-         it != identity_to_instance_.end(); ++it) {
-      if (it->first.name() == identity.name() &&
-          it->first.instance() == identity.instance()) {
-        identity_to_instance_.erase(it);
-        return;
-      }
-    }
-  }
+  identity_to_instance_->Erase(instance->identity());
 }
 
 void ServiceManager::NotifyServiceStarted(const Identity& identity,
@@ -1074,6 +1134,7 @@
 ServiceManager::Instance* ServiceManager::CreateInstance(
     const Identity& source,
     const Identity& target,
+    InstanceType instance_type,
     const InterfaceProviderSpecMap& specs) {
   CHECK(target.user_id() != mojom::kInheritUserID);
 
@@ -1085,9 +1146,7 @@
   // NOTE: |instance| has been passed elsewhere. Use |raw_instance| from this
   // point forward. It's safe for the extent of this method.
 
-  auto result =
-      identity_to_instance_.insert(std::make_pair(target, raw_instance));
-  DCHECK(result.second);
+  identity_to_instance_->Insert(target, instance_type, raw_instance);
 
   mojom::RunningServiceInfoPtr info = raw_instance->CreateRunningServiceInfo();
   listeners_.ForAllPtrs([&info](mojom::ServiceManagerListener* listener) {
@@ -1100,11 +1159,8 @@
 void ServiceManager::AddListener(mojom::ServiceManagerListenerPtr listener) {
   // TODO(beng): filter instances provided by those visible to this service.
   std::vector<mojom::RunningServiceInfoPtr> instances;
-  instances.reserve(identity_to_instance_.size());
-  for (auto& instance : identity_to_instance_)
-    instances.push_back(instance.second->CreateRunningServiceInfo());
+  identity_to_instance_->PopulateRunningServiceInfo(&instances);
   listener->OnInit(std::move(instances));
-
   listeners_.AddPtr(std::move(listener));
 }
 
diff --git a/services/service_manager/service_manager.h b/services/service_manager/service_manager.h
index edc3e2e..5632544c 100644
--- a/services/service_manager/service_manager.h
+++ b/services/service_manager/service_manager.h
@@ -41,20 +41,6 @@
 
 class ServiceManager {
  public:
-  // API for testing.
-  class TestAPI {
-   public:
-    explicit TestAPI(ServiceManager* service_manager);
-    ~TestAPI();
-
-    // Returns true if there is a Instance for this name.
-    bool HasRunningInstanceForName(const std::string& name) const;
-   private:
-    ServiceManager* service_manager_;
-
-    DISALLOW_COPY_AND_ASSIGN(TestAPI);
-  };
-
   // |service_process_launcher_factory| is an instance of an object capable of
   // vending implementations of ServiceProcessLauncher, e.g. for out-of-process
   // execution.
@@ -100,8 +86,17 @@
 
  private:
   class Instance;
+  class IdentityToInstanceMap;
   class ServiceImpl;
 
+  // Used in CreateInstance to specify how an instance should be shared between
+  // various identities.
+  enum class InstanceType {
+    kRegular,   // Unique for each user and each instance name.
+    kAllUsers,  // Same instance for all users. Unique for each instance name.
+    kSingleton  // Same instance for all users and all instance names.
+  };
+
   void InitCatalog(mojom::ServicePtr catalog);
 
   // Called when |instance| encounters an error. Deletes |instance|.
@@ -115,7 +110,8 @@
   void OnInstanceStopped(const Identity& identity);
 
   // Returns a running instance matching |identity|. This might be an instance
-  // running as a different user if one is available that services all users.
+  // running as a different user or with a different instance name if one is
+  // available that services all users or is a singleton.
   Instance* GetExistingInstance(const Identity& identity) const;
 
   // Erases any identities mapping to |instance|. Following this call it is
@@ -127,13 +123,14 @@
 
   void NotifyServicePIDReceived(const Identity& identity, base::ProcessId pid);
 
-  // Attempt to complete the connection requested by |params| by connecting to
+  // Attempts to complete the connection requested by |params| by connecting to
   // an existing instance. If there is an existing instance, |params| is taken,
   // and this function returns true.
   bool ConnectToExistingInstance(std::unique_ptr<ConnectParams>* params);
 
   Instance* CreateInstance(const Identity& source,
                            const Identity& target,
+                           InstanceType instance_type,
                            const InterfaceProviderSpecMap& specs);
 
   // Called from the instance implementing mojom::ServiceManager.
@@ -156,18 +153,14 @@
 
   catalog::Catalog catalog_;
 
-  // Maps service identities to reachable instances. Note that the Instance*
-  // values here are NOT owned by this map.
-  std::map<Identity, Instance*> identity_to_instance_;
+  // Maps service identities to reachable instances. Note that the Instance
+  // values stored in that map are NOT owned by this map.
+  std::unique_ptr<IdentityToInstanceMap> identity_to_instance_;
 
   // Always points to the ServiceManager's own Instance. Note that this
   // Instance still has an entry in |instances_|.
   Instance* service_manager_instance_;
 
-  // Tracks the names of instances that are allowed to field connection requests
-  // from all users.
-  std::set<std::string> singletons_;
-
   std::map<Identity, mojom::ServiceFactoryPtr> service_factories_;
   mojo::InterfacePtrSet<mojom::ServiceManagerListener> listeners_;
   base::Callback<void(const Identity&)> instance_quit_callback_;
diff --git a/services/service_manager/tests/service_manager/BUILD.gn b/services/service_manager/tests/service_manager/BUILD.gn
index 8da02bc5..dc24bd6b 100644
--- a/services/service_manager/tests/service_manager/BUILD.gn
+++ b/services/service_manager/tests/service_manager/BUILD.gn
@@ -72,7 +72,16 @@
 service_manifest("embedder_manifest") {
   name = "service_manager_unittest_embedder"
   source = "embedder_manifest.json"
-  packaged_services = [ ":singleton_manifest" ]
+  packaged_services = [
+    ":all_users_manifest",
+    ":regular_manifest",
+    ":singleton_manifest",
+  ]
+}
+
+service_manifest("all_users_manifest") {
+  name = "service_manager_unittest_all_users"
+  source = "all_users_manifest.json"
 }
 
 service_manifest("singleton_manifest") {
@@ -80,6 +89,11 @@
   source = "singleton_manifest.json"
 }
 
+service_manifest("regular_manifest") {
+  name = "service_manager_unittest_regular"
+  source = "regular_manifest.json"
+}
+
 service("service_manager_unittest_embedder") {
   testonly = true
 
diff --git a/services/service_manager/tests/service_manager/OWNERS b/services/service_manager/tests/service_manager/OWNERS
index 34e7ffd..608e1c84 100644
--- a/services/service_manager/tests/service_manager/OWNERS
+++ b/services/service_manager/tests/service_manager/OWNERS
@@ -7,6 +7,12 @@
 per-file service_manager_unittest_manifest.json=set noparent
 per-file service_manager_unittest_manifest.json=file://ipc/SECURITY_OWNERS
 
+per-file all_users_manifest.json=set noparent
+per-file all_users_manifest.json=file://ipc/SECURITY_OWNERS
+
+per-file regular_manifest.json=set noparent
+per-file regular_manifest.json=file://ipc/SECURITY_OWNERS
+
 per-file singleton_manifest.json=set noparent
 per-file singleton_manifest.json=file://ipc/SECURITY_OWNERS
 
diff --git a/services/service_manager/tests/service_manager/all_users_manifest.json b/services/service_manager/tests/service_manager/all_users_manifest.json
new file mode 100644
index 0000000..824ec00
--- /dev/null
+++ b/services/service_manager/tests/service_manager/all_users_manifest.json
@@ -0,0 +1,15 @@
+{
+  "name": "service_manager_unittest_all_users",
+  "display_name": "Service Manager Unittest: All users",
+  "interface_provider_specs": {
+    "service_manager:connector": {
+      "provides": {
+        "service_manager_unittest:all_users": [ ]
+      },
+      "requires": {
+        "service_manager_unittest_target": [ ],
+        "service_manager": [ "service_manager:all_users" ]
+      }
+    }
+  }
+}
diff --git a/services/service_manager/tests/service_manager/embedder.cc b/services/service_manager/tests/service_manager/embedder.cc
index bed481b2..827258a 100644
--- a/services/service_manager/tests/service_manager/embedder.cc
+++ b/services/service_manager/tests/service_manager/embedder.cc
@@ -20,10 +20,10 @@
 
 namespace {
 
-class Singleton : public service_manager::Service {
+class RegularService : public service_manager::Service {
  public:
-  explicit Singleton() {}
-  ~Singleton() override {}
+  RegularService() = default;
+  ~RegularService() override = default;
 
  private:
   // service_manager::Service:
@@ -31,7 +31,35 @@
                        const std::string& interface_name,
                        mojo::ScopedMessagePipeHandle interface_pipe) override {}
 
-  DISALLOW_COPY_AND_ASSIGN(Singleton);
+  DISALLOW_COPY_AND_ASSIGN(RegularService);
+};
+
+class AllUsersService : public service_manager::Service {
+ public:
+  AllUsersService() = default;
+  ~AllUsersService() override = default;
+
+ private:
+  // service_manager::Service:
+  void OnBindInterface(const service_manager::BindSourceInfo& source_info,
+                       const std::string& interface_name,
+                       mojo::ScopedMessagePipeHandle interface_pipe) override {}
+
+  DISALLOW_COPY_AND_ASSIGN(AllUsersService);
+};
+
+class SingletonService : public service_manager::Service {
+ public:
+  explicit SingletonService() = default;
+  ~SingletonService() override = default;
+
+ private:
+  // service_manager::Service:
+  void OnBindInterface(const service_manager::BindSourceInfo& source_info,
+                       const std::string& interface_name,
+                       mojo::ScopedMessagePipeHandle interface_pipe) override {}
+
+  DISALLOW_COPY_AND_ASSIGN(SingletonService);
 };
 
 class Embedder : public service_manager::Service,
@@ -63,9 +91,17 @@
   // mojom::ServiceFactory:
   void CreateService(service_manager::mojom::ServiceRequest request,
                      const std::string& name) override {
-    if (name == "service_manager_unittest_singleton") {
+    if (name == "service_manager_unittest_all_users") {
       context_.reset(new service_manager::ServiceContext(
-          base::MakeUnique<Singleton>(), std::move(request)));
+          base::MakeUnique<AllUsersService>(), std::move(request)));
+    } else if (name == "service_manager_unittest_singleton") {
+      context_.reset(new service_manager::ServiceContext(
+          base::MakeUnique<SingletonService>(), std::move(request)));
+    } else if (name == "service_manager_unittest_regular") {
+      context_.reset(new service_manager::ServiceContext(
+          base::MakeUnique<RegularService>(), std::move(request)));
+    } else {
+      LOG(ERROR) << "Failed to create unknow service " << name;
     }
   }
 
diff --git a/services/service_manager/tests/service_manager/embedder_manifest.json b/services/service_manager/tests/service_manager/embedder_manifest.json
index 0e76baa2..491da5ddd 100644
--- a/services/service_manager/tests/service_manager/embedder_manifest.json
+++ b/services/service_manager/tests/service_manager/embedder_manifest.json
@@ -10,6 +10,7 @@
         ]
       },
       "requires": {
+        "service_manager": [ "service_manager:singleton" ],
         "service_manager_unittest_target": [ ]
       }
     }
diff --git a/services/service_manager/tests/service_manager/regular_manifest.json b/services/service_manager/tests/service_manager/regular_manifest.json
new file mode 100644
index 0000000..40f03f107
--- /dev/null
+++ b/services/service_manager/tests/service_manager/regular_manifest.json
@@ -0,0 +1,15 @@
+{
+  "name": "service_manager_unittest_regular",
+  "display_name": "Service Manager Unittest: Regular",
+  "interface_provider_specs": {
+    "service_manager:connector": {
+      "provides": {
+        "service_manager_unittest:regular": [ ]
+      },
+      "requires": {
+        "service_manager_unittest_target": [ ],
+        "service_manager": [ ]
+      }
+    }
+  }
+}
diff --git a/services/service_manager/tests/service_manager/service_manager_unittest.cc b/services/service_manager/tests/service_manager/service_manager_unittest.cc
index 21e3052f..6bd5d56 100644
--- a/services/service_manager/tests/service_manager/service_manager_unittest.cc
+++ b/services/service_manager/tests/service_manager/service_manager_unittest.cc
@@ -20,6 +20,7 @@
 #include "base/process/process.h"
 #include "base/process/process_handle.h"
 #include "base/run_loop.h"
+#include "base/strings/string_number_conversions.h"
 #include "build/build_config.h"
 #include "mojo/edk/embedder/embedder.h"
 #include "mojo/edk/embedder/outgoing_broker_client_invitation.h"
@@ -39,6 +40,32 @@
 
 namespace {
 
+void OnServiceStartedCallback(int* start_count,
+                              std::string* service_name,
+                              const base::Closure& continuation,
+                              const service_manager::Identity& identity) {
+  (*start_count)++;
+  *service_name = identity.name();
+  continuation.Run();
+}
+
+void OnServiceFailedToStartCallback(bool* run,
+                                    const base::Closure& continuation,
+                                    const service_manager::Identity& identity) {
+  *run = true;
+  continuation.Run();
+}
+
+void OnServicePIDReceivedCallback(std::string* service_name,
+                                  uint32_t* serivce_pid,
+                                  const base::Closure& continuation,
+                                  const service_manager::Identity& identity,
+                                  uint32_t pid) {
+  *service_name = identity.name();
+  *serivce_pid = pid;
+  continuation.Run();
+}
+
 class ServiceManagerTestClient : public test::ServiceTestClient,
                                  public test::mojom::CreateInstanceTest {
  public:
@@ -273,6 +300,54 @@
                                     platform_channel_pair.PassServerHandle()));
   }
 
+  void StartEmbedderService() {
+    base::RunLoop loop;
+    int start_count = 0;
+    std::string service_name;
+    set_service_started_callback(
+        base::BindRepeating(&OnServiceStartedCallback, &start_count,
+                            &service_name, loop.QuitClosure()));
+    bool failed_to_start = false;
+    set_service_failed_to_start_callback(base::BindRepeating(
+        &OnServiceFailedToStartCallback, &failed_to_start, loop.QuitClosure()));
+
+    connector()->StartService("service_manager_unittest_embedder");
+    loop.Run();
+    EXPECT_FALSE(failed_to_start);
+    EXPECT_EQ(1, start_count);
+    EXPECT_EQ("service_manager_unittest_embedder", service_name);
+  }
+
+  void StartService(const Identity& identity, bool expect_service_started) {
+    int start_count = 0;
+    base::RunLoop loop;
+    std::string service_name;
+    set_service_started_callback(
+        base::BindRepeating(&OnServiceStartedCallback, &start_count,
+                            &service_name, loop.QuitClosure()));
+    bool failed_to_start = false;
+    set_service_failed_to_start_callback(base::BindRepeating(
+        &OnServiceFailedToStartCallback, &failed_to_start, loop.QuitClosure()));
+
+    connector()->StartService(identity);
+    if (!expect_service_started) {
+      // Wait briefly and test no new service was created.
+      base::MessageLoop::current()->task_runner()->PostDelayedTask(
+          FROM_HERE, loop.QuitClosure(), base::TimeDelta::FromSeconds(1));
+    }
+
+    loop.Run();
+    EXPECT_FALSE(failed_to_start);
+    if (expect_service_started) {
+      EXPECT_EQ(1, start_count);
+      EXPECT_EQ(identity.name(), service_name);
+    } else {
+      // The callback was not invoked, nothing should have been set.
+      EXPECT_EQ(0, start_count);
+      EXPECT_TRUE(service_name.empty());
+    }
+  }
+
   void KillTarget() {
     target_.Terminate(0, false);
   }
@@ -371,76 +446,82 @@
   KillTarget();
 }
 
-void OnServiceStartedCallback(int* start_count,
-                              std::string* service_name,
-                              const base::Closure& continuation,
-                              const service_manager::Identity& identity) {
-  (*start_count)++;
-  *service_name = identity.name();
-  continuation.Run();
-}
+// Tests that starting a regular packaged service works, and that when starting
+// the service again, a new service is created unless the same user ID and
+// instance names are used.
+TEST_F(ServiceManagerTest, CreatePackagedRegularInstances) {
+  constexpr char kRegularServiceName[] = "service_manager_unittest_regular";
 
-void OnServiceFailedToStartCallback(
-      bool* run,
-      const base::Closure& continuation,
-      const service_manager::Identity& identity) {
-  *run = true;
-  continuation.Run();
-}
-
-void OnServicePIDReceivedCallback(std::string* service_name,
-                                  uint32_t* serivce_pid,
-                                  const base::Closure& continuation,
-                                  const service_manager::Identity& identity,
-                                  uint32_t pid) {
-  *service_name = identity.name();
-  *serivce_pid = pid;
-  continuation.Run();
-}
-
-// Tests that creating connecting to a singleton packaged service work.
-TEST_F(ServiceManagerTest, CreatePackagedSingletonInstance) {
   AddListenerAndWaitForApplications();
 
   // Connect to the embedder service first.
-  {
-    base::RunLoop loop;
-    int start_count = 0;
-    std::string service_name;
-    set_service_started_callback(base::BindRepeating(
-        &OnServiceStartedCallback,
-        &start_count, &service_name, loop.QuitClosure()));
-    bool failed_to_start = false;
-    set_service_failed_to_start_callback(base::BindRepeating(
-        &OnServiceFailedToStartCallback,
-        &failed_to_start, loop.QuitClosure()));
+  StartEmbedderService();
 
-    connector()->StartService("service_manager_unittest_embedder");
-    loop.Run();
-    EXPECT_FALSE(failed_to_start);
-    EXPECT_EQ(1, start_count);
-    EXPECT_EQ("service_manager_unittest_embedder", service_name);
-  }
+  Identity identity(kRegularServiceName);
+  StartService(identity, /*expect_service_started=*/true);
 
-  {
-    base::RunLoop loop;
-    int start_count = 0;
-    std::string service_name;
-    set_service_started_callback(base::BindRepeating(
-        &OnServiceStartedCallback,
-        &start_count, &service_name, loop.QuitClosure()));
-    bool failed_to_start = false;
-    set_service_failed_to_start_callback(base::BindRepeating(
-        &OnServiceFailedToStartCallback,
-        &failed_to_start, loop.QuitClosure()));
+  // Retstarting with the same identity reuses the existing service.
+  StartService(identity, /*expect_service_started=*/false);
 
-    // Connect to the packaged singleton service.
-    connector()->StartService("service_manager_unittest_singleton");
-    loop.Run();
-    EXPECT_FALSE(failed_to_start);
-    EXPECT_EQ(1, start_count);
-    EXPECT_EQ("service_manager_unittest_singleton", service_name);
-  }
+  // Starting with a different user ID creates a new service.
+  Identity other_user_identity(kRegularServiceName, base::GenerateGUID());
+  StartService(other_user_identity, /*expect_service_started=*/true);
+
+  // Starting with a different instance name creates a new service as well.
+  Identity instance_identity(kRegularServiceName, mojom::kInheritUserID,
+                             "my_instance");
+  StartService(instance_identity, /*expect_service_started=*/true);
+}
+
+// Tests that starting an all_users packaged service works, and that when
+// starting that service again, a new service is created only when a different
+// instance name is specified.
+TEST_F(ServiceManagerTest, CreatePackagedAllUsersInstances) {
+  constexpr char kAllUsersServiceName[] = "service_manager_unittest_all_users";
+
+  AddListenerAndWaitForApplications();
+
+  // Connect to the embedder service first.
+  StartEmbedderService();
+
+  Identity identity(kAllUsersServiceName);
+  StartService(identity, /*expect_service_started=*/true);
+
+  // Start again with a different user-id, the existing service should be
+  // reused.
+  Identity other_user_identity(kAllUsersServiceName, base::GenerateGUID());
+  StartService(other_user_identity, /*expect_service_started=*/false);
+
+  // Start again with a difference instance name, in that case a new service
+  // should get created.
+  Identity instance_identity(kAllUsersServiceName, base::GenerateGUID(),
+                             "my_instance");
+  StartService(instance_identity, /*expect_service_started=*/true);
+}
+
+// Tests that creating a singleton packaged service works, and that when
+// starting that service again a new service is never created.
+TEST_F(ServiceManagerTest, CreatePackagedSingletonInstances) {
+  constexpr char kSingletonServiceName[] = "service_manager_unittest_singleton";
+  AddListenerAndWaitForApplications();
+
+  // Connect to the embedder service first.
+  StartEmbedderService();
+
+  Identity identity(kSingletonServiceName);
+  StartService(identity, /*expect_service_started=*/true);
+
+  // Start again with a different user-id, the existing service should be
+  // reused.
+  Identity other_user_identity(kSingletonServiceName, base::GenerateGUID());
+  StartService(other_user_identity, /*expect_service_started=*/false);
+
+  // Start again with the same user-ID but a difference instance name, the
+  // existing service should still be reused.
+  // should get created.
+  Identity instance_identity(kSingletonServiceName, mojom::kInheritUserID,
+                             "my_instance");
+  StartService(instance_identity, /*expect_service_started=*/false);
 }
 
 TEST_F(ServiceManagerTest, PIDReceivedCallback) {
diff --git a/services/service_manager/tests/service_manager/service_manager_unittest_manifest.json b/services/service_manager/tests/service_manager/service_manager_unittest_manifest.json
index 11ca3ca..ccbd8337 100644
--- a/services/service_manager/tests/service_manager/service_manager_unittest_manifest.json
+++ b/services/service_manager/tests/service_manager/service_manager_unittest_manifest.json
@@ -10,6 +10,7 @@
       },
       "requires": {
         "service_manager": [
+          "service_manager:singleton",
           "service_manager:service_manager",
           "service_manager:client_process",
           "service_manager:instance_name"
@@ -20,6 +21,12 @@
         "service_manager_unittest_singleton": [
           "service_manager_unittest:singleton"
         ],
+        "service_manager_unittest_all_users": [
+          "service_manager_unittest:all_users"
+        ],
+        "service_manager_unittest_regular": [
+          "service_manager_unittest:regular"
+        ],
         "service_manager_unittest_target": [ ]
       }
     }
diff --git a/services/service_manager/tests/service_manager/singleton_manifest.json b/services/service_manager/tests/service_manager/singleton_manifest.json
index 12178e8..11524ed 100644
--- a/services/service_manager/tests/service_manager/singleton_manifest.json
+++ b/services/service_manager/tests/service_manager/singleton_manifest.json
@@ -8,7 +8,7 @@
       },
       "requires": {
         "service_manager_unittest_target": [ ],
-        "service_manager": [ "service_manager:all_users" ]
+        "service_manager": [ "service_manager:singleton" ]
       }
     }
   }
diff --git a/services/service_manager/tests/test_support_unittest.cc b/services/service_manager/tests/test_support_unittest.cc
index add4038..32a4a9e 100644
--- a/services/service_manager/tests/test_support_unittest.cc
+++ b/services/service_manager/tests/test_support_unittest.cc
@@ -3,13 +3,17 @@
 // found in the LICENSE file.
 
 #include "base/bind.h"
+#include "base/bind_helpers.h"
 #include "base/callback.h"
 #include "base/macros.h"
 #include "base/run_loop.h"
 #include "base/test/scoped_task_environment.h"
 #include "mojo/public/cpp/bindings/binding_set.h"
+#include "mojo/public/cpp/bindings/strong_binding.h"
+#include "services/service_manager/public/cpp/binder_registry.h"
 #include "services/service_manager/public/cpp/connector.h"
 #include "services/service_manager/public/cpp/service.h"
+#include "services/service_manager/public/cpp/service_context_ref.h"
 #include "services/service_manager/public/cpp/test/test_connector_factory.h"
 #include "services/service_manager/tests/test.mojom.h"
 #include "testing/gtest/include/gtest/gtest.h"
@@ -18,6 +22,29 @@
 
 namespace {
 
+// A simple test interface on the service, which can be pinged by test code to
+// verify a working service connection.
+class TestCImpl : public TestC {
+ public:
+  explicit TestCImpl(std::unique_ptr<ServiceContextRef> service_ref)
+      : service_ref_(std::move(service_ref)) {}
+  ~TestCImpl() override = default;
+
+ private:
+  // TestC:
+  void C(CCallback callback) override { std::move(callback).Run(); }
+
+  const std::unique_ptr<service_manager::ServiceContextRef> service_ref_;
+
+  DISALLOW_COPY_AND_ASSIGN(TestCImpl);
+};
+
+void OnTestCRequest(service_manager::ServiceContextRefFactory* ref_factory,
+                    TestCRequest request) {
+  mojo::MakeStrongBinding(std::make_unique<TestCImpl>(ref_factory->CreateRef()),
+                          std::move(request));
+}
+
 // This is a test service used to demonstrate usage of TestConnectorFactory.
 // See documentation on TestConnectorFactory for more details about usage.
 class TestServiceImpl : public Service {
@@ -32,33 +59,25 @@
   }
 
   // Service:
+  void OnStart() override {
+    ref_factory_.reset(
+        new ServiceContextRefFactory(base::Bind(&base::DoNothing)));
+    registry_.AddInterface(base::Bind(&OnTestCRequest, ref_factory_.get()));
+  }
+
   void OnBindInterface(const BindSourceInfo& source_info,
                        const std::string& interface_name,
                        mojo::ScopedMessagePipeHandle interface_pipe) override {
-    if (interface_name == TestC::Name_)
-      c_bindings_.AddBinding(&c_impl_, TestCRequest(std::move(interface_pipe)));
-
+    registry_.BindInterface(interface_name, std::move(interface_pipe));
     if (on_bind_interface_callback_)
       on_bind_interface_callback_.Run(source_info.identity);
   }
 
  private:
-  // A simple test interface on the service, which can be pinged by test code
-  // to verify a working service connection.
-  class TestCImpl : public TestC {
-   public:
-    TestCImpl() = default;
-    ~TestCImpl() override = default;
+  // State needed to manage service lifecycle and lifecycle of bound clients.
+  std::unique_ptr<service_manager::ServiceContextRefFactory> ref_factory_;
+  service_manager::BinderRegistry registry_;
 
-    // TestC:
-    void C(CCallback callback) override { std::move(callback).Run(); }
-
-   private:
-    DISALLOW_COPY_AND_ASSIGN(TestCImpl);
-  };
-
-  TestCImpl c_impl_;
-  mojo::BindingSet<TestC> c_bindings_;
   OnBindInterfaceCallback on_bind_interface_callback_;
 
   DISALLOW_COPY_AND_ASSIGN(TestServiceImpl);
@@ -69,13 +88,10 @@
 TEST(ServiceManagerTestSupport, TestConnectorFactory) {
   base::test::ScopedTaskEnvironment task_environment;
 
-  TestServiceImpl service;
-  TestConnectorFactory factory(&service);
+  TestConnectorFactory factory(std::make_unique<TestServiceImpl>());
   std::unique_ptr<Connector> connector = factory.CreateConnector();
-
   TestCPtr c;
-  connector->BindInterface("ignored", &c);
-
+  connector->BindInterface(TestC::Name_, &c);
   base::RunLoop loop;
   c->C(loop.QuitClosure());
   loop.Run();
@@ -84,25 +100,27 @@
 TEST(ServiceManagerTestSupport, TestConnectorFactoryOverrideSourceIdentity) {
   base::test::ScopedTaskEnvironment task_environment;
 
-  TestServiceImpl service;
-
   static const std::string kTestSourceIdentity = "worst. service. ever.";
-  TestConnectorFactory factory(&service);
+  // Verify that the test service sees our overridden source identity.
+  auto bind_identity = std::make_unique<Identity>();
+  auto service = std::make_unique<TestServiceImpl>();
+  service->set_on_bind_interface_callback(base::Bind(
+      [](std::unique_ptr<Identity>* identity, const Identity& source_identity) {
+        *identity = std::make_unique<Identity>(source_identity);
+      },
+      &bind_identity));
+
+  TestConnectorFactory factory(std::move(service));
   factory.set_source_identity(Identity(kTestSourceIdentity));
   std::unique_ptr<Connector> connector = factory.CreateConnector();
 
-  // Verify that the test service sees our overridden source identity.
-  service.set_on_bind_interface_callback(
-      base::Bind([](const Identity& source_identity) {
-        EXPECT_EQ(kTestSourceIdentity, source_identity.name());
-      }));
-
   TestCPtr c;
-  connector->BindInterface("ignored", &c);
+  connector->BindInterface(TestC::Name_, &c);
 
   base::RunLoop loop;
   c->C(loop.QuitClosure());
   loop.Run();
+  EXPECT_EQ(kTestSourceIdentity, bind_identity->name());
 }
 
 }  // namespace service_manager
diff --git a/services/shape_detection/BUILD.gn b/services/shape_detection/BUILD.gn
index 3765c024..37104ed 100644
--- a/services/shape_detection/BUILD.gn
+++ b/services/shape_detection/BUILD.gn
@@ -27,6 +27,13 @@
       "text_detection_impl_mac.mm",
     ]
     libs = [ "QuartzCore.framework" ]
+  } else if (is_win) {
+    sources += [
+      "barcode_detection_impl.cc",
+      "face_detection_impl_win.cc",
+      "face_detection_impl_win.h",
+      "text_detection_impl.cc",
+    ]
   } else {
     sources += [
       "barcode_detection_impl.cc",
@@ -110,18 +117,20 @@
       "CoreGraphics.framework",
       "QuartzCore.framework",
     ]
-
-    deps = [
-      ":lib",
-      "//base",
-      "//skia",
-      "//testing/gmock",
-      "//testing/gtest",
-      "//ui/gfx",
-      "//ui/gl",
-    ]
-    data = [
-      "//services/test/data/mona_lisa.jpg",
-    ]
+  } else if (is_win) {
+    sources += [ "face_detection_impl_win_unittest.cc" ]
   }
+
+  deps = [
+    ":lib",
+    "//base",
+    "//skia",
+    "//testing/gmock",
+    "//testing/gtest",
+    "//ui/gfx",
+    "//ui/gl",
+  ]
+  data = [
+    "//services/test/data/mona_lisa.jpg",
+  ]
 }
diff --git a/services/shape_detection/PRESUBMIT.py b/services/shape_detection/PRESUBMIT.py
index 93854d4dc..6358b80 100644
--- a/services/shape_detection/PRESUBMIT.py
+++ b/services/shape_detection/PRESUBMIT.py
@@ -14,11 +14,12 @@
   """git cl upload will call this hook after the issue is created/modified.
 
   This hook adds an extra try bot list to the CL description in order to run
-  the Mac GPU bots in addition to the usual CQ try bots.
+  the Mac GPU and Windows 10 bots in addition to the usual CQ try bots.
   """
   return output_api.EnsureCQIncludeTrybotsAreAdded(
     cl,
     [
-      'master.tryserver.chromium.mac:mac_optional_gpu_tests_rel'
+      'master.tryserver.chromium.mac:mac_optional_gpu_tests_rel',
+      'master.tryserver.chromium.win:win10_chromium_x64_rel_ng'
     ],
-    'Automatically added optional Mac GPU tests to run on CQ.')
+    'Automatically added optional Mac GPU and Windows 10 tests to run on CQ.')
diff --git a/services/shape_detection/face_detection_impl_win.cc b/services/shape_detection/face_detection_impl_win.cc
new file mode 100644
index 0000000..1f2704b
--- /dev/null
+++ b/services/shape_detection/face_detection_impl_win.cc
@@ -0,0 +1,74 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "services/shape_detection/face_detection_impl_win.h"
+
+#include <windows.media.faceanalysis.h>
+
+#include "base/scoped_generic.h"
+#include "base/win/core_winrt_util.h"
+#include "base/win/scoped_hstring.h"
+#include "base/win/windows_version.h"
+#include "media/base/scoped_callback_runner.h"
+#include "mojo/public/cpp/bindings/strong_binding.h"
+#include "services/shape_detection/face_detection_provider_impl.h"
+
+namespace shape_detection {
+
+using base::win::ScopedHString;
+using base::win::GetActivationFactory;
+
+void FaceDetectionProviderImpl::CreateFaceDetection(
+    shape_detection::mojom::FaceDetectionRequest request,
+    shape_detection::mojom::FaceDetectorOptionsPtr options) {
+  auto impl = FaceDetectionImplWin::Create();
+  if (!impl)
+    return;
+
+  mojo::MakeStrongBinding(std::move(impl), std::move(request));
+}
+
+// static
+std::unique_ptr<FaceDetectionImplWin> FaceDetectionImplWin::Create() {
+  // FaceDetector class is only available in Win 10 onwards (v10.0.10240.0).
+  if (base::win::GetVersion() < base::win::VERSION_WIN10) {
+    DVLOG(1) << "FaceDetector not supported before Windows 10";
+    return nullptr;
+  }
+  // Loads functions dynamically at runtime to prevent library dependencies.
+  if (!(base::win::ResolveCoreWinRTDelayload() &&
+        ScopedHString::ResolveCoreWinRTStringDelayload())) {
+    DLOG(ERROR) << "Failed loading functions from combase.dll";
+    return nullptr;
+  }
+
+  Microsoft::WRL::ComPtr<IFaceDetectorStatics> factory;
+  const HRESULT hr = GetActivationFactory<
+      IFaceDetectorStatics,
+      RuntimeClass_Windows_Media_FaceAnalysis_FaceDetector>(&factory);
+  if (FAILED(hr)) {
+    DLOG(ERROR) << "IFaceDetectorStatics factory failed: "
+                << logging::SystemErrorCodeToString(hr);
+    return nullptr;
+  }
+
+  boolean is_supported = FALSE;
+  factory->get_IsSupported(&is_supported);
+  return (is_supported == FALSE)
+             ? nullptr
+             : std::make_unique<FaceDetectionImplWin>(std::move(factory));
+}
+
+FaceDetectionImplWin::FaceDetectionImplWin(
+    Microsoft::WRL::ComPtr<IFaceDetectorStatics> factory)
+    : face_detector_factory_(std::move(factory)) {}
+
+FaceDetectionImplWin::~FaceDetectionImplWin() = default;
+
+void FaceDetectionImplWin::Detect(const SkBitmap& bitmap,
+                                  DetectCallback callback) {
+  DCHECK_EQ(kN32_SkColorType, bitmap.colorType());
+}
+
+}  // namespace shape_detection
\ No newline at end of file
diff --git a/services/shape_detection/face_detection_impl_win.h b/services/shape_detection/face_detection_impl_win.h
new file mode 100644
index 0000000..4c76729
--- /dev/null
+++ b/services/shape_detection/face_detection_impl_win.h
@@ -0,0 +1,48 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef SERVICES_SHAPE_DETECTION_FACE_DETECTION_IMPL_WIN_H_
+#define SERVICES_SHAPE_DETECTION_FACE_DETECTION_IMPL_WIN_H_
+
+#include <wrl/client.h>
+
+#include "services/shape_detection/public/interfaces/facedetection.mojom.h"
+
+class SkBitmap;
+
+namespace ABI {
+namespace Windows {
+namespace Media {
+namespace FaceAnalysis {
+struct IFaceDetectorStatics;
+}  // namespace FaceAnalysis
+}  // namespace Media
+}  // namespace Windows
+}  // namespace ABI
+
+namespace shape_detection {
+
+class FaceDetectionImplWin : public mojom::FaceDetection {
+ public:
+  using IFaceDetectorStatics =
+      ABI::Windows::Media::FaceAnalysis::IFaceDetectorStatics;
+
+  static std::unique_ptr<FaceDetectionImplWin> Create();
+
+  explicit FaceDetectionImplWin(
+      Microsoft::WRL::ComPtr<IFaceDetectorStatics> factory);
+  ~FaceDetectionImplWin() override;
+
+  void Detect(const SkBitmap& bitmap,
+              mojom::FaceDetection::DetectCallback callback) override;
+
+ private:
+  Microsoft::WRL::ComPtr<IFaceDetectorStatics> face_detector_factory_;
+
+  DISALLOW_COPY_AND_ASSIGN(FaceDetectionImplWin);
+};
+
+}  // namespace shape_detection
+
+#endif  // SERVICES_SHAPE_DETECTION_FACE_DETECTION_IMPL_WIN_H_
\ No newline at end of file
diff --git a/services/shape_detection/face_detection_impl_win_unittest.cc b/services/shape_detection/face_detection_impl_win_unittest.cc
new file mode 100644
index 0000000..f770b7f
--- /dev/null
+++ b/services/shape_detection/face_detection_impl_win_unittest.cc
@@ -0,0 +1,28 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "services/shape_detection/face_detection_impl_win.h"
+
+#include "base/win/scoped_com_initializer.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace shape_detection {
+
+class FaceDetectionImplWinTest : public testing::Test {
+ protected:
+  void SetUp() override {
+    scoped_com_initializer_ = base::MakeUnique<base::win::ScopedCOMInitializer>(
+        base::win::ScopedCOMInitializer::kMTA);
+    ASSERT_TRUE(scoped_com_initializer_->Succeeded());
+  }
+
+ private:
+  std::unique_ptr<base::win::ScopedCOMInitializer> scoped_com_initializer_;
+};
+
+TEST_F(FaceDetectionImplWinTest, CreateAndDestroy) {
+  auto impl = FaceDetectionImplWin::Create();
+}
+
+}  // namespace shape_detection
diff --git a/skia/BUILD.gn b/skia/BUILD.gn
index 54491001..65a9de2 100644
--- a/skia/BUILD.gn
+++ b/skia/BUILD.gn
@@ -124,7 +124,7 @@
   # TODO: remove after Skia shader relocation (https://skia-review.googlesource.com/c/17927)
   include_dirs += [ "//third_party/skia/src/effects/gradients" ]
 
-  defines = [ "SK_IGNORE_SUBPIXEL_HINTING_FIX" ]
+  defines = []
 
   if (!is_ios && !use_system_freetype) {
     defines += [ "SK_FREETYPE_MINIMUM_RUNTIME_VERSION=(((FREETYPE_MAJOR) * 0x01000000) | ((FREETYPE_MINOR) * 0x00010000) | ((FREETYPE_PATCH) * 0x00000100))" ]
diff --git a/storage/browser/fileapi/dragged_file_util_unittest.cc b/storage/browser/fileapi/dragged_file_util_unittest.cc
index 01fbc7a..5a62aa80 100644
--- a/storage/browser/fileapi/dragged_file_util_unittest.cc
+++ b/storage/browser/fileapi/dragged_file_util_unittest.cc
@@ -377,7 +377,7 @@
       entry.name = current.BaseName().value();
       expected_entry_map[entry.name] = entry;
 
-#if defined(OS_POSIX)
+#if defined(OS_POSIX) && !defined(OS_FUCHSIA)
       // Creates a symlink for each file/directory.
       // They should be ignored by ReadDirectory, so we don't add them
       // to expected_entry_map.
diff --git a/storage/browser/fileapi/local_file_util_unittest.cc b/storage/browser/fileapi/local_file_util_unittest.cc
index 7a3ff502..2e1cca2 100644
--- a/storage/browser/fileapi/local_file_util_unittest.cc
+++ b/storage/browser/fileapi/local_file_util_unittest.cc
@@ -141,8 +141,8 @@
   std::unique_ptr<FileSystemOperationContext> context(NewContext());
 }
 
-// base::CreateSymbolicLink is only supported on POSIX.
-#if defined(OS_POSIX)
+// base::CreateSymbolicLink is supported on most POSIX, but not on Fuchsia.
+#if defined(OS_POSIX) && !defined(OS_FUCHSIA)
 TEST_F(LocalFileUtilTest, CreateFailForSymlink) {
   // Create symlink target file.
   const char *target_name = "symlink_target";
diff --git a/testing/buildbot/chromium.android.fyi.json b/testing/buildbot/chromium.android.fyi.json
index 85031887..fa943c7 100644
--- a/testing/buildbot/chromium.android.fyi.json
+++ b/testing/buildbot/chromium.android.fyi.json
@@ -3548,6 +3548,39 @@
       }
     ]
   },
+  "Oreo Phone Tester": {
+    "gtest_tests": [
+      {
+        "merge": {
+          "args": [
+            "--bucket",
+            "chromium-result-details",
+            "--test-name",
+            "chrome_public_test_apk"
+          ],
+          "script": "//build/android/pylib/results/presentation/test_results_presentation.py"
+        },
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "cipd_packages": [
+            {
+              "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
+              "location": "bin",
+              "revision": "git_revision:ff387eadf445b24c935f1cf7d6ddd279f8a6b04c"
+            }
+          ],
+          "dimension_sets": [
+            {
+              "device_os": "OPR6.170623.012",
+              "device_type": "marlin"
+            }
+          ],
+          "shards": 5
+        },
+        "test": "chrome_public_test_apk"
+      }
+    ]
+  },
   "Unswarmed N5 Tests Dummy Builder": {
     "gtest_tests": [
       {
diff --git a/testing/buildbot/chromium.clang.json b/testing/buildbot/chromium.clang.json
index 6ee9d32..d545919 100644
--- a/testing/buildbot/chromium.clang.json
+++ b/testing/buildbot/chromium.clang.json
@@ -5176,6 +5176,19 @@
           "can_use_on_swarming_builders": true,
           "dimension_sets": [
             {
+              "device_os": "MMB29Q",
+              "device_type": "bullhead"
+            }
+          ]
+        },
+        "test": "android_webview_unittests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "device_os": "MMB29Q",
               "device_type": "bullhead"
             }
           ]
@@ -5187,11 +5200,468 @@
           "can_use_on_swarming_builders": true,
           "dimension_sets": [
             {
+              "device_os": "MMB29Q",
+              "device_type": "bullhead"
+            }
+          ]
+        },
+        "test": "blink_heap_unittests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "device_os": "MMB29Q",
               "device_type": "bullhead"
             }
           ]
         },
         "test": "breakpad_unittests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "device_os": "MMB29Q",
+              "device_type": "bullhead"
+            }
+          ]
+        },
+        "test": "capture_unittests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "device_os": "MMB29Q",
+              "device_type": "bullhead"
+            }
+          ]
+        },
+        "test": "cc_unittests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "device_os": "MMB29Q",
+              "device_type": "bullhead"
+            }
+          ]
+        },
+        "test": "chrome_public_test_vr_apk"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "device_os": "MMB29Q",
+              "device_type": "bullhead"
+            }
+          ]
+        },
+        "test": "chrome_sync_shell_test_apk"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "device_os": "MMB29Q",
+              "device_type": "bullhead"
+            }
+          ]
+        },
+        "test": "components_browsertests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "device_os": "MMB29Q",
+              "device_type": "bullhead"
+            }
+          ]
+        },
+        "test": "components_unittests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "device_os": "MMB29Q",
+              "device_type": "bullhead"
+            }
+          ]
+        },
+        "test": "content_browsertests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "device_os": "MMB29Q",
+              "device_type": "bullhead"
+            }
+          ]
+        },
+        "test": "content_shell_test_apk"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "device_os": "MMB29Q",
+              "device_type": "bullhead"
+            }
+          ]
+        },
+        "test": "content_unittests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "device_os": "MMB29Q",
+              "device_type": "bullhead"
+            }
+          ]
+        },
+        "test": "device_unittests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "device_os": "MMB29Q",
+              "device_type": "bullhead"
+            }
+          ]
+        },
+        "test": "events_unittests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "device_os": "MMB29Q",
+              "device_type": "bullhead"
+            }
+          ]
+        },
+        "test": "gfx_unittests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "device_os": "MMB29Q",
+              "device_type": "bullhead"
+            }
+          ]
+        },
+        "test": "gl_tests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "device_os": "MMB29Q",
+              "device_type": "bullhead"
+            }
+          ]
+        },
+        "test": "gl_unittests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "device_os": "MMB29Q",
+              "device_type": "bullhead"
+            }
+          ]
+        },
+        "test": "gpu_ipc_service_unittests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "device_os": "MMB29Q",
+              "device_type": "bullhead"
+            }
+          ]
+        },
+        "test": "gpu_unittests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "device_os": "MMB29Q",
+              "device_type": "bullhead"
+            }
+          ]
+        },
+        "test": "ipc_tests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "device_os": "MMB29Q",
+              "device_type": "bullhead"
+            }
+          ]
+        },
+        "test": "latency_unittests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "device_os": "MMB29Q",
+              "device_type": "bullhead"
+            }
+          ]
+        },
+        "test": "media_blink_unittests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "device_os": "MMB29Q",
+              "device_type": "bullhead"
+            }
+          ]
+        },
+        "test": "media_unittests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "device_os": "MMB29Q",
+              "device_type": "bullhead"
+            }
+          ]
+        },
+        "test": "mojo_common_unittests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "device_os": "MMB29Q",
+              "device_type": "bullhead"
+            }
+          ]
+        },
+        "test": "mojo_public_bindings_unittests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "device_os": "MMB29Q",
+              "device_type": "bullhead"
+            }
+          ]
+        },
+        "test": "mojo_public_system_unittests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "device_os": "MMB29Q",
+              "device_type": "bullhead"
+            }
+          ]
+        },
+        "test": "mojo_system_unittests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "device_os": "MMB29Q",
+              "device_type": "bullhead"
+            }
+          ]
+        },
+        "test": "mojo_test_apk"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "device_os": "MMB29Q",
+              "device_type": "bullhead"
+            }
+          ]
+        },
+        "test": "net_unittests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "device_os": "MMB29Q",
+              "device_type": "bullhead"
+            }
+          ]
+        },
+        "test": "sandbox_linux_unittests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "device_os": "MMB29Q",
+              "device_type": "bullhead"
+            }
+          ]
+        },
+        "test": "services_unittests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "device_os": "MMB29Q",
+              "device_type": "bullhead"
+            }
+          ]
+        },
+        "test": "sql_unittests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "device_os": "MMB29Q",
+              "device_type": "bullhead"
+            }
+          ]
+        },
+        "test": "storage_unittests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "device_os": "MMB29Q",
+              "device_type": "bullhead"
+            }
+          ]
+        },
+        "test": "ui_android_unittests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "device_os": "MMB29Q",
+              "device_type": "bullhead"
+            }
+          ]
+        },
+        "test": "ui_base_unittests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "device_os": "MMB29Q",
+              "device_type": "bullhead"
+            }
+          ]
+        },
+        "test": "ui_touch_selection_unittests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "device_os": "MMB29Q",
+              "device_type": "bullhead"
+            }
+          ]
+        },
+        "test": "unit_tests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "device_os": "MMB29Q",
+              "device_type": "bullhead"
+            }
+          ]
+        },
+        "test": "viz_unittests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "device_os": "MMB29Q",
+              "device_type": "bullhead"
+            }
+          ]
+        },
+        "test": "vr_common_unittests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "device_os": "MMB29Q",
+              "device_type": "bullhead"
+            }
+          ]
+        },
+        "test": "webview_instrumentation_test_apk"
       }
     ]
   },
diff --git a/testing/buildbot/chromium.fyi.json b/testing/buildbot/chromium.fyi.json
index 635df302..0b3e658 100644
--- a/testing/buildbot/chromium.fyi.json
+++ b/testing/buildbot/chromium.fyi.json
@@ -2824,5775 +2824,6 @@
       }
     ]
   },
-  "ClangToTAndroid x64": {
-    "gtest_tests": [
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "dimension_sets": [
-            {
-              "device_type": "coho"
-            }
-          ]
-        },
-        "test": "angle_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "dimension_sets": [
-            {
-              "device_type": "coho"
-            }
-          ]
-        },
-        "test": "base_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "dimension_sets": [
-            {
-              "device_type": "coho"
-            }
-          ]
-        },
-        "test": "blink_heap_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "dimension_sets": [
-            {
-              "device_type": "coho"
-            }
-          ]
-        },
-        "test": "breakpad_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "dimension_sets": [
-            {
-              "device_type": "coho"
-            }
-          ]
-        },
-        "test": "cacheinvalidation_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "dimension_sets": [
-            {
-              "device_type": "coho"
-            }
-          ]
-        },
-        "test": "capture_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "dimension_sets": [
-            {
-              "device_type": "coho"
-            }
-          ]
-        },
-        "test": "cast_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "dimension_sets": [
-            {
-              "device_type": "coho"
-            }
-          ]
-        },
-        "test": "cc_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "dimension_sets": [
-            {
-              "device_type": "coho"
-            }
-          ]
-        },
-        "test": "chrome_public_test_apk"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "dimension_sets": [
-            {
-              "device_type": "coho"
-            }
-          ]
-        },
-        "test": "chrome_sync_shell_test_apk"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "dimension_sets": [
-            {
-              "device_type": "coho"
-            }
-          ]
-        },
-        "test": "components_browsertests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "dimension_sets": [
-            {
-              "device_type": "coho"
-            }
-          ]
-        },
-        "test": "components_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "dimension_sets": [
-            {
-              "device_type": "coho"
-            }
-          ]
-        },
-        "test": "content_browsertests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "dimension_sets": [
-            {
-              "device_type": "coho"
-            }
-          ]
-        },
-        "test": "content_shell_test_apk"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "dimension_sets": [
-            {
-              "device_type": "coho"
-            }
-          ]
-        },
-        "test": "content_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "dimension_sets": [
-            {
-              "device_type": "coho"
-            }
-          ]
-        },
-        "test": "crypto_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "dimension_sets": [
-            {
-              "device_type": "coho"
-            }
-          ]
-        },
-        "test": "device_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "dimension_sets": [
-            {
-              "device_type": "coho"
-            }
-          ]
-        },
-        "test": "display_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "dimension_sets": [
-            {
-              "device_type": "coho"
-            }
-          ]
-        },
-        "test": "events_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "dimension_sets": [
-            {
-              "device_type": "coho"
-            }
-          ]
-        },
-        "test": "gcm_unit_tests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "dimension_sets": [
-            {
-              "device_type": "coho"
-            }
-          ]
-        },
-        "test": "gfx_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "dimension_sets": [
-            {
-              "device_type": "coho"
-            }
-          ]
-        },
-        "test": "gl_tests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "dimension_sets": [
-            {
-              "device_type": "coho"
-            }
-          ]
-        },
-        "test": "gl_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "dimension_sets": [
-            {
-              "device_type": "coho"
-            }
-          ]
-        },
-        "test": "google_apis_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "dimension_sets": [
-            {
-              "device_type": "coho"
-            }
-          ]
-        },
-        "test": "gpu_ipc_service_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "dimension_sets": [
-            {
-              "device_type": "coho"
-            }
-          ]
-        },
-        "test": "gpu_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "dimension_sets": [
-            {
-              "device_type": "coho"
-            }
-          ]
-        },
-        "test": "ipc_tests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "dimension_sets": [
-            {
-              "device_type": "coho"
-            }
-          ]
-        },
-        "test": "jingle_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "dimension_sets": [
-            {
-              "device_type": "coho"
-            }
-          ]
-        },
-        "test": "media_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "dimension_sets": [
-            {
-              "device_type": "coho"
-            }
-          ]
-        },
-        "test": "midi_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "dimension_sets": [
-            {
-              "device_type": "coho"
-            }
-          ]
-        },
-        "test": "mojo_common_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "dimension_sets": [
-            {
-              "device_type": "coho"
-            }
-          ]
-        },
-        "test": "mojo_public_bindings_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "dimension_sets": [
-            {
-              "device_type": "coho"
-            }
-          ]
-        },
-        "test": "mojo_public_system_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "dimension_sets": [
-            {
-              "device_type": "coho"
-            }
-          ]
-        },
-        "test": "mojo_system_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "dimension_sets": [
-            {
-              "device_type": "coho"
-            }
-          ]
-        },
-        "test": "net_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "dimension_sets": [
-            {
-              "device_type": "coho"
-            }
-          ]
-        },
-        "test": "remoting_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "dimension_sets": [
-            {
-              "device_type": "coho"
-            }
-          ]
-        },
-        "test": "sandbox_linux_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "dimension_sets": [
-            {
-              "device_type": "coho"
-            }
-          ]
-        },
-        "test": "services_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "dimension_sets": [
-            {
-              "device_type": "coho"
-            }
-          ]
-        },
-        "test": "skia_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "dimension_sets": [
-            {
-              "device_type": "coho"
-            }
-          ]
-        },
-        "test": "sql_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "dimension_sets": [
-            {
-              "device_type": "coho"
-            }
-          ]
-        },
-        "test": "storage_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "dimension_sets": [
-            {
-              "device_type": "coho"
-            }
-          ]
-        },
-        "test": "ui_android_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "dimension_sets": [
-            {
-              "device_type": "coho"
-            }
-          ]
-        },
-        "test": "ui_base_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "dimension_sets": [
-            {
-              "device_type": "coho"
-            }
-          ]
-        },
-        "test": "ui_touch_selection_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "dimension_sets": [
-            {
-              "device_type": "coho"
-            }
-          ]
-        },
-        "test": "unit_tests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "dimension_sets": [
-            {
-              "device_type": "coho"
-            }
-          ]
-        },
-        "test": "url_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "dimension_sets": [
-            {
-              "device_type": "coho"
-            }
-          ]
-        },
-        "test": "webkit_unit_tests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "dimension_sets": [
-            {
-              "device_type": "coho"
-            }
-          ]
-        },
-        "test": "wtf_unittests"
-      }
-    ]
-  },
-  "ClangToTAndroidASan": {
-    "gtest_tests": [
-      {
-        "args": [
-          "--tool=asan"
-        ],
-        "swarming": {
-          "can_use_on_swarming_builders": false
-        },
-        "test": "base_unittests"
-      },
-      {
-        "args": [
-          "--tool=asan"
-        ],
-        "swarming": {
-          "can_use_on_swarming_builders": false
-        },
-        "test": "components_browsertests"
-      }
-    ],
-    "junit_tests": [
-      {
-        "test": "base_junit_tests"
-      }
-    ]
-  },
-  "ClangToTLinux": {
-    "scripts": [
-      {
-        "name": "check_gn_headers",
-        "script": "check_gn_headers.py"
-      }
-    ]
-  },
-  "ClangToTLinux tester": {
-    "gtest_tests": [
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "accessibility_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "angle_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "app_shell_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "aura_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "base_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "blink_heap_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "blink_platform_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "shards": 5
-        },
-        "test": "browser_tests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "cacheinvalidation_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "capture_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "cast_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "cc_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "chromedriver_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "components_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "compositor_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "content_browsertests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "content_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "crypto_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "dbus_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "device_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "display_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "events_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "extensions_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "gcm_unit_tests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "gfx_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "google_apis_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "gpu_ipc_service_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "gpu_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "interactive_ui_tests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "ipc_tests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "jingle_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "media_blink_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "media_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "midi_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "mojo_common_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "mojo_public_bindings_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "mojo_public_system_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "mojo_system_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "nacl_helper_nonsfi_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "nacl_loader_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "native_theme_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "net_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "pdf_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "ppapi_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "printing_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "remoting_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "sandbox_linux_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "services_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "skia_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "sql_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "storage_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "ui_base_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "ui_touch_selection_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "unit_tests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "url_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "views_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "webkit_unit_tests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "wm_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "wtf_unittests"
-      }
-    ]
-  },
-  "ClangToTLinuxASan tester": {
-    "gtest_tests": [
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "accessibility_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "angle_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "base_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "blink_heap_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "blink_platform_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "shards": 5
-        },
-        "test": "browser_tests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "cacheinvalidation_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "capture_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "cast_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "cc_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "components_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "content_browsertests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "content_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "crypto_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "device_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "display_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "extensions_browsertests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "extensions_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "gcm_unit_tests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "gfx_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "google_apis_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "gpu_ipc_service_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "gpu_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "interactive_ui_tests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "ipc_tests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "jingle_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "media_blink_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "media_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "midi_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "shards": 4
-        },
-        "test": "net_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "pdf_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "ppapi_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "printing_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "remoting_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "sandbox_linux_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "services_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "skia_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "sql_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "ui_base_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "shards": 2
-        },
-        "test": "unit_tests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "url_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "webkit_unit_tests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "wtf_unittests"
-      }
-    ]
-  },
-  "ClangToTLinuxLLD tester": {
-    "gtest_tests": [
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "accessibility_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "angle_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "app_shell_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "aura_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "base_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "blink_heap_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "blink_platform_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "shards": 5
-        },
-        "test": "browser_tests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "cacheinvalidation_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "capture_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "cast_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "cc_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "chromedriver_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "components_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "compositor_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "content_browsertests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "content_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "crypto_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "dbus_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "device_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "display_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "events_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "extensions_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "gcm_unit_tests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "gfx_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "google_apis_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "gpu_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "interactive_ui_tests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "ipc_tests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "jingle_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "media_blink_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "media_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "midi_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "mojo_common_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "mojo_public_bindings_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "mojo_public_system_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "mojo_system_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "nacl_helper_nonsfi_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "nacl_loader_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "native_theme_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "net_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "pdf_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "ppapi_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "printing_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "remoting_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "sandbox_linux_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "services_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "skia_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "sql_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "ui_base_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "ui_touch_selection_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "unit_tests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "url_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "views_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "webkit_unit_tests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "wm_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "wtf_unittests"
-      }
-    ]
-  },
-  "ClangToTLinuxMSan": {
-    "gtest_tests": [
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "accessibility_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "aura_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "base_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "shards": 10
-        },
-        "test": "browser_tests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "cacheinvalidation_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "capture_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "cast_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "cc_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "chromedriver_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "components_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "compositor_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "content_browsertests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "content_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "crypto_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "dbus_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "device_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "display_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "events_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "extensions_browsertests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "extensions_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "gcm_unit_tests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "gfx_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "google_apis_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "gpu_ipc_service_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "gpu_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "interactive_ui_tests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "ipc_tests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "jingle_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "latency_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "media_blink_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "media_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "midi_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "mojo_common_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "mojo_public_bindings_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "mojo_public_system_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "mojo_system_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "nacl_loader_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "native_theme_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "net_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "pdf_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "ppapi_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "printing_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "remoting_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "sandbox_linux_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "skia_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "sql_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "storage_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "ui_base_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "ui_touch_selection_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "unit_tests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "url_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "views_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "viz_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "wm_unittests"
-      }
-    ]
-  },
-  "ClangToTLinuxThinLTO": {
-    "gtest_tests": [
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": false
-        },
-        "test": "accessibility_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": false
-        },
-        "test": "angle_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": false
-        },
-        "test": "app_shell_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": false
-        },
-        "test": "aura_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": false
-        },
-        "test": "base_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": false
-        },
-        "test": "blink_heap_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": false
-        },
-        "test": "blink_platform_unittests"
-      },
-      {
-        "args": [
-          "--gtest_filter=-SaveType/SavePageMultiFrameBrowserTest.ObjectElements/0"
-        ],
-        "swarming": {
-          "can_use_on_swarming_builders": false,
-          "shards": 10
-        },
-        "test": "browser_tests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": false
-        },
-        "test": "cacheinvalidation_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": false
-        },
-        "test": "capture_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": false
-        },
-        "test": "cc_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": false
-        },
-        "test": "chromedriver_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": false
-        },
-        "test": "components_browsertests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": false
-        },
-        "test": "components_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": false
-        },
-        "test": "compositor_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": false
-        },
-        "test": "content_browsertests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": false
-        },
-        "test": "content_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": false
-        },
-        "test": "crypto_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": false
-        },
-        "test": "dbus_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": false
-        },
-        "test": "device_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": false
-        },
-        "test": "display_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": false
-        },
-        "test": "events_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": false
-        },
-        "test": "extensions_browsertests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": false
-        },
-        "test": "extensions_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": false
-        },
-        "test": "gcm_unit_tests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": false
-        },
-        "test": "gfx_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": false
-        },
-        "test": "gin_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": false
-        },
-        "test": "gl_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": false
-        },
-        "test": "gn_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": false
-        },
-        "test": "google_apis_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": false
-        },
-        "test": "gpu_ipc_service_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": false
-        },
-        "test": "gpu_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": false
-        },
-        "test": "interactive_ui_tests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": false
-        },
-        "test": "ipc_tests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": false
-        },
-        "test": "jingle_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": false
-        },
-        "test": "media_blink_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": false
-        },
-        "test": "media_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": false
-        },
-        "test": "midi_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": false
-        },
-        "test": "mojo_common_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": false
-        },
-        "test": "mojo_public_bindings_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": false
-        },
-        "test": "mojo_public_system_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": false
-        },
-        "test": "mojo_system_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": false
-        },
-        "test": "nacl_loader_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": false
-        },
-        "test": "native_theme_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": false
-        },
-        "test": "net_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": false
-        },
-        "test": "pdf_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": false
-        },
-        "test": "ppapi_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": false
-        },
-        "test": "printing_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": false
-        },
-        "test": "remoting_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": false
-        },
-        "test": "sandbox_linux_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": false
-        },
-        "test": "skia_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": false
-        },
-        "test": "sql_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": false
-        },
-        "test": "ui_base_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": false
-        },
-        "test": "ui_touch_selection_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": false
-        },
-        "test": "unit_tests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": false
-        },
-        "test": "url_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": false
-        },
-        "test": "views_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": false
-        },
-        "test": "wm_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": false
-        },
-        "test": "wtf_unittests"
-      }
-    ]
-  },
-  "ClangToTLinuxUBSanVptr tester": {
-    "gtest_tests": [
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "accessibility_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "angle_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "base_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "blink_heap_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "blink_platform_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "cacheinvalidation_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "cast_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "cc_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "shards": 5
-        },
-        "test": "content_browsertests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "content_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "crypto_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "device_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "display_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "extensions_browsertests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "extensions_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "gcm_unit_tests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "gfx_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "google_apis_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "gpu_ipc_service_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "gpu_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "ipc_tests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "jingle_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "media_blink_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "midi_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "native_theme_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "net_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "pdf_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "ppapi_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "printing_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "remoting_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "sandbox_linux_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "services_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "skia_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "sql_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "ui_base_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "unit_tests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "url_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "views_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "webkit_unit_tests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "wtf_unittests"
-      }
-    ]
-  },
-  "ClangToTMac tester": {
-    "gtest_tests": [
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "accessibility_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "angle_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "shards": 5
-        },
-        "test": "base_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "blink_heap_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "blink_platform_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "shards": 10
-        },
-        "test": "browser_tests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "cacheinvalidation_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "capture_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "cast_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "cc_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "chromedriver_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "components_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "content_browsertests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "content_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "crypto_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "display_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "extensions_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "gcm_unit_tests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "gfx_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "google_apis_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "gpu_ipc_service_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "gpu_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "interactive_ui_tests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "ipc_tests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "jingle_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "media_blink_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "media_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "midi_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "mojo_common_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "mojo_public_bindings_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "mojo_public_system_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "mojo_system_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "native_theme_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "net_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "pdf_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "ppapi_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "printing_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "remoting_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "sandbox_mac_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "services_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "skia_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "sql_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "sync_integration_tests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "ui_base_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "unit_tests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "url_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "views_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "webkit_unit_tests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "wtf_unittests"
-      }
-    ],
-    "isolated_scripts": [
-      {
-        "isolate_name": "telemetry_gpu_unittests",
-        "name": "telemetry_gpu_unittests",
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        }
-      },
-      {
-        "isolate_name": "telemetry_perf_unittests",
-        "name": "telemetry_perf_unittests",
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "hard_timeout": 960,
-          "shards": 12
-        }
-      },
-      {
-        "isolate_name": "telemetry_unittests",
-        "name": "telemetry_unittests",
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "shards": 2
-        }
-      }
-    ]
-  },
-  "ClangToTMacASan tester": {
-    "gtest_tests": [
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "accessibility_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "angle_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "base_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "blink_heap_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "blink_platform_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "shards": 10
-        },
-        "test": "browser_tests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "cacheinvalidation_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "capture_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "cast_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "cc_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "chromedriver_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "components_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "content_browsertests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "content_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "crypto_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "display_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "extensions_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "gcm_unit_tests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "gfx_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "google_apis_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "gpu_ipc_service_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "gpu_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "interactive_ui_tests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "ipc_tests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "jingle_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "media_blink_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "media_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "midi_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "mojo_common_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "mojo_public_bindings_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "mojo_public_system_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "mojo_system_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "net_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "pdf_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "ppapi_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "printing_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "remoting_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "sandbox_mac_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "services_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "skia_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "sql_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "sync_integration_tests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "ui_base_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "unit_tests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "url_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "webkit_unit_tests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "wtf_unittests"
-      }
-    ]
-  },
-  "ClangToTWin tester": {
-    "gtest_tests": [
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "angle_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "base_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "blink_heap_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "blink_platform_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "shards": 10
-        },
-        "test": "browser_tests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "cacheinvalidation_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "capture_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "chrome_app_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "chrome_elf_import_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "chrome_elf_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "components_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "content_browsertests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "content_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "courgette_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "crypto_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "device_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "extensions_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "gcm_unit_tests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "google_apis_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "gpu_ipc_service_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "gpu_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "install_static_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "dimension_sets": [
-            {
-              "integrity": "high"
-            }
-          ]
-        },
-        "test": "installer_util_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "ipc_tests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "jingle_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "media_blink_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "media_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "midi_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "native_theme_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "net_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "pdf_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "ppapi_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "printing_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "remoting_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "dimension_sets": [
-            {
-              "integrity": "high"
-            }
-          ]
-        },
-        "test": "sbox_integration_tests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "sbox_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "sbox_validation_tests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "services_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "dimension_sets": [
-            {
-              "integrity": "high"
-            }
-          ]
-        },
-        "test": "setup_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "skia_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "sql_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "ui_base_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "unit_tests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "url_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "views_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "webkit_unit_tests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "wtf_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "zucchini_unittests"
-      }
-    ]
-  },
-  "ClangToTWin(dbg) tester": {
-    "gtest_tests": [
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "angle_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "base_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "blink_heap_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "blink_platform_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "shards": 20
-        },
-        "test": "browser_tests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "cacheinvalidation_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "capture_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "chrome_app_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "chrome_elf_import_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "chrome_elf_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "components_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "content_browsertests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "content_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "courgette_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "crypto_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "device_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "extensions_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "gcm_unit_tests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "google_apis_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "gpu_ipc_service_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "gpu_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "dimension_sets": [
-            {
-              "integrity": "high"
-            }
-          ]
-        },
-        "test": "installer_util_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "ipc_tests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "jingle_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "media_blink_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "media_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "midi_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "native_theme_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "net_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "pdf_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "ppapi_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "printing_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "remoting_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "dimension_sets": [
-            {
-              "integrity": "high"
-            }
-          ]
-        },
-        "test": "sbox_integration_tests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "sbox_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "sbox_validation_tests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "services_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "dimension_sets": [
-            {
-              "integrity": "high"
-            }
-          ]
-        },
-        "test": "setup_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "skia_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "sql_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "ui_base_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "unit_tests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "url_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "views_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "webkit_unit_tests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "wtf_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "zucchini_unittests"
-      }
-    ]
-  },
-  "ClangToTWin(dll) tester": {
-    "gtest_tests": [
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "angle_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "base_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "blink_heap_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "blink_platform_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "shards": 10
-        },
-        "test": "browser_tests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "cacheinvalidation_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "capture_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "chrome_app_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "chrome_elf_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "components_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "content_browsertests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "content_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "courgette_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "crypto_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "device_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "extensions_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "gcm_unit_tests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "google_apis_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "gpu_ipc_service_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "gpu_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "dimension_sets": [
-            {
-              "integrity": "high"
-            }
-          ]
-        },
-        "test": "installer_util_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "ipc_tests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "jingle_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "media_blink_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "media_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "midi_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "native_theme_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "net_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "pdf_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "ppapi_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "printing_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "remoting_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "dimension_sets": [
-            {
-              "integrity": "high"
-            }
-          ]
-        },
-        "test": "sbox_integration_tests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "sbox_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "sbox_validation_tests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "services_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "dimension_sets": [
-            {
-              "integrity": "high"
-            }
-          ]
-        },
-        "test": "setup_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "skia_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "sql_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "ui_base_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "unit_tests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "url_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "views_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "webkit_unit_tests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "wtf_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "zucchini_unittests"
-      }
-    ]
-  },
-  "ClangToTWin64 tester": {
-    "gtest_tests": [
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "angle_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "base_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "blink_heap_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "blink_platform_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "shards": 10
-        },
-        "test": "browser_tests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "cacheinvalidation_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "capture_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "chrome_app_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "chrome_elf_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "components_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "content_browsertests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "content_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "courgette_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "crypto_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "device_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "extensions_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "gcm_unit_tests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "google_apis_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "gpu_ipc_service_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "gpu_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "dimension_sets": [
-            {
-              "integrity": "high"
-            }
-          ]
-        },
-        "test": "installer_util_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "ipc_tests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "jingle_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "media_blink_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "media_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "midi_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "native_theme_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "net_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "pdf_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "ppapi_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "printing_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "remoting_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "dimension_sets": [
-            {
-              "integrity": "high"
-            }
-          ]
-        },
-        "test": "sbox_integration_tests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "sbox_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "sbox_validation_tests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "services_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "dimension_sets": [
-            {
-              "integrity": "high"
-            }
-          ]
-        },
-        "test": "setup_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "skia_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "sql_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "ui_base_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "unit_tests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "url_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "views_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "webkit_unit_tests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "wtf_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "zucchini_unittests"
-      }
-    ]
-  },
-  "ClangToTWin64(dbg) tester": {
-    "gtest_tests": [
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "angle_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "base_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "blink_heap_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "blink_platform_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "shards": 20
-        },
-        "test": "browser_tests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "cacheinvalidation_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "capture_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "chrome_app_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "chrome_elf_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "components_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "content_browsertests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "content_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "courgette_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "crypto_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "device_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "extensions_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "gcm_unit_tests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "google_apis_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "gpu_ipc_service_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "gpu_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "dimension_sets": [
-            {
-              "integrity": "high"
-            }
-          ]
-        },
-        "test": "installer_util_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "ipc_tests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "jingle_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "media_blink_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "media_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "midi_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "native_theme_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "net_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "pdf_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "ppapi_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "printing_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "remoting_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "dimension_sets": [
-            {
-              "integrity": "high"
-            }
-          ]
-        },
-        "test": "sbox_integration_tests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "sbox_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "sbox_validation_tests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "services_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "dimension_sets": [
-            {
-              "integrity": "high"
-            }
-          ]
-        },
-        "test": "setup_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "skia_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "sql_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "ui_base_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "unit_tests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "url_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "views_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "webkit_unit_tests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "wtf_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "zucchini_unittests"
-      }
-    ]
-  },
-  "ClangToTWin64(dll) tester": {
-    "gtest_tests": [
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "angle_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "base_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "blink_heap_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "blink_platform_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "shards": 10
-        },
-        "test": "browser_tests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "cacheinvalidation_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "capture_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "chrome_app_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "chrome_elf_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "components_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "content_browsertests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "content_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "courgette_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "crypto_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "device_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "extensions_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "gcm_unit_tests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "google_apis_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "gpu_ipc_service_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "gpu_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "dimension_sets": [
-            {
-              "integrity": "high"
-            }
-          ]
-        },
-        "test": "installer_util_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "ipc_tests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "jingle_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "media_blink_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "media_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "midi_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "native_theme_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "net_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "pdf_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "ppapi_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "printing_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "remoting_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "dimension_sets": [
-            {
-              "integrity": "high"
-            }
-          ]
-        },
-        "test": "sbox_integration_tests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "sbox_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "sbox_validation_tests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "services_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "dimension_sets": [
-            {
-              "integrity": "high"
-            }
-          ]
-        },
-        "test": "setup_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "skia_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "sql_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "ui_base_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "unit_tests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "url_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "views_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "webkit_unit_tests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "wtf_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "zucchini_unittests"
-      }
-    ]
-  },
-  "ClangToTWinCFI": {
-    "gtest_tests": [
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "angle_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "base_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "blink_heap_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "blink_platform_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "shards": 10
-        },
-        "test": "browser_tests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "cacheinvalidation_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "capture_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "chrome_app_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "chrome_elf_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "components_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "content_browsertests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "content_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "courgette_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "crypto_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "device_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "extensions_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "gcm_unit_tests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "google_apis_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "gpu_ipc_service_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "gpu_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "dimension_sets": [
-            {
-              "integrity": "high"
-            }
-          ]
-        },
-        "test": "installer_util_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "ipc_tests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "jingle_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "media_blink_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "media_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "midi_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "native_theme_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "net_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "pdf_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "ppapi_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "printing_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "remoting_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "dimension_sets": [
-            {
-              "integrity": "high"
-            }
-          ]
-        },
-        "test": "sbox_integration_tests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "sbox_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "sbox_validation_tests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "services_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "dimension_sets": [
-            {
-              "integrity": "high"
-            }
-          ]
-        },
-        "test": "setup_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "skia_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "sql_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "ui_base_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "unit_tests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "url_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "views_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "webkit_unit_tests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "wtf_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "zucchini_unittests"
-      }
-    ]
-  },
-  "ClangToTWinCFI64": {
-    "gtest_tests": [
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "angle_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "base_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "blink_heap_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "blink_platform_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "shards": 10
-        },
-        "test": "browser_tests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "cacheinvalidation_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "capture_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "chrome_app_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "chrome_elf_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "components_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "content_browsertests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "content_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "courgette_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "crypto_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "device_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "extensions_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "gcm_unit_tests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "google_apis_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "gpu_ipc_service_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "gpu_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "dimension_sets": [
-            {
-              "integrity": "high"
-            }
-          ]
-        },
-        "test": "installer_util_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "ipc_tests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "jingle_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "media_blink_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "media_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "midi_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "native_theme_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "net_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "pdf_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "ppapi_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "printing_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "remoting_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "dimension_sets": [
-            {
-              "integrity": "high"
-            }
-          ]
-        },
-        "test": "sbox_integration_tests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "sbox_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "sbox_validation_tests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "services_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "dimension_sets": [
-            {
-              "integrity": "high"
-            }
-          ]
-        },
-        "test": "setup_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "skia_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "sql_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "ui_base_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "unit_tests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "url_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "views_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "webkit_unit_tests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "wtf_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "zucchini_unittests"
-      }
-    ]
-  },
-  "ClangToTWinThinLTO64": {
-    "gtest_tests": [
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "angle_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "base_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "blink_heap_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "blink_platform_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "shards": 10
-        },
-        "test": "browser_tests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "cacheinvalidation_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "capture_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "chrome_app_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "chrome_elf_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "components_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "content_browsertests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "content_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "courgette_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "crypto_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "device_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "extensions_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "gcm_unit_tests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "google_apis_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "gpu_ipc_service_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "gpu_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "dimension_sets": [
-            {
-              "integrity": "high"
-            }
-          ]
-        },
-        "test": "installer_util_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "ipc_tests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "jingle_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "media_blink_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "media_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "midi_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "native_theme_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "net_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "pdf_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "ppapi_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "printing_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "remoting_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "dimension_sets": [
-            {
-              "integrity": "high"
-            }
-          ]
-        },
-        "test": "sbox_integration_tests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "sbox_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "sbox_validation_tests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "services_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "dimension_sets": [
-            {
-              "integrity": "high"
-            }
-          ]
-        },
-        "test": "setup_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "skia_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "sql_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "ui_base_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "unit_tests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "url_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "views_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "webkit_unit_tests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "wtf_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "zucchini_unittests"
-      }
-    ]
-  },
   "CrWin7Goma": {
     "gtest_tests": [
       {
@@ -9436,1782 +3667,6 @@
       }
     ]
   },
-  "CrWinClang tester": {
-    "gtest_tests": [
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "angle_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "base_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "blink_heap_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "blink_platform_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "shards": 10
-        },
-        "test": "browser_tests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "cacheinvalidation_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "capture_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "chrome_app_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "chrome_elf_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "components_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "content_browsertests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "content_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "courgette_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "crypto_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "device_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "extensions_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "gcm_unit_tests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "google_apis_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "gpu_ipc_service_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "gpu_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "dimension_sets": [
-            {
-              "integrity": "high"
-            }
-          ]
-        },
-        "test": "installer_util_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "ipc_tests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "jingle_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "media_blink_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "media_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "midi_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "native_theme_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "net_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "pdf_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "ppapi_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "printing_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "remoting_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "dimension_sets": [
-            {
-              "integrity": "high"
-            }
-          ]
-        },
-        "test": "sbox_integration_tests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "sbox_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "sbox_validation_tests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "services_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "dimension_sets": [
-            {
-              "integrity": "high"
-            }
-          ]
-        },
-        "test": "setup_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "skia_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "sql_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "ui_base_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "unit_tests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "url_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "views_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "webkit_unit_tests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "wtf_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "zucchini_unittests"
-      }
-    ]
-  },
-  "CrWinClang(dbg) tester": {
-    "gtest_tests": [
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "angle_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "base_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "blink_heap_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "blink_platform_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "shards": 20
-        },
-        "test": "browser_tests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "cacheinvalidation_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "capture_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "chrome_app_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "chrome_elf_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "components_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "content_browsertests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "content_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "courgette_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "crypto_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "device_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "extensions_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "gcm_unit_tests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "google_apis_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "gpu_ipc_service_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "gpu_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "dimension_sets": [
-            {
-              "integrity": "high"
-            }
-          ]
-        },
-        "test": "installer_util_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "ipc_tests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "jingle_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "media_blink_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "media_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "midi_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "native_theme_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "net_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "pdf_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "ppapi_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "printing_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "remoting_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "dimension_sets": [
-            {
-              "integrity": "high"
-            }
-          ]
-        },
-        "test": "sbox_integration_tests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "sbox_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "sbox_validation_tests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "services_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "dimension_sets": [
-            {
-              "integrity": "high"
-            }
-          ]
-        },
-        "test": "setup_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "skia_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "sql_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "ui_base_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "unit_tests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "url_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "views_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "webkit_unit_tests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "wtf_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "zucchini_unittests"
-      }
-    ]
-  },
-  "CrWinClang(shared) tester": {
-    "gtest_tests": [
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "angle_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "base_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "blink_heap_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "blink_platform_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "shards": 10
-        },
-        "test": "browser_tests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "cacheinvalidation_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "capture_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "chrome_app_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "chrome_elf_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "components_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "content_browsertests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "content_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "courgette_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "crypto_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "device_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "extensions_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "gcm_unit_tests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "google_apis_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "gpu_ipc_service_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "gpu_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "dimension_sets": [
-            {
-              "integrity": "high"
-            }
-          ]
-        },
-        "test": "installer_util_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "ipc_tests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "jingle_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "media_blink_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "media_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "midi_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "native_theme_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "net_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "pdf_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "ppapi_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "printing_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "remoting_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "dimension_sets": [
-            {
-              "integrity": "high"
-            }
-          ]
-        },
-        "test": "sbox_integration_tests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "sbox_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "sbox_validation_tests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "services_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "dimension_sets": [
-            {
-              "integrity": "high"
-            }
-          ]
-        },
-        "test": "setup_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "skia_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "sql_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "ui_base_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "unit_tests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "url_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "views_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "webkit_unit_tests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "wtf_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "zucchini_unittests"
-      }
-    ]
-  },
-  "CrWinClang64 tester": {
-    "gtest_tests": [
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "angle_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "base_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "blink_heap_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "blink_platform_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "shards": 10
-        },
-        "test": "browser_tests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "cacheinvalidation_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "capture_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "chrome_app_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "chrome_elf_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "components_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "content_browsertests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "content_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "courgette_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "crypto_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "device_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "extensions_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "gcm_unit_tests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "google_apis_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "gpu_ipc_service_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "gpu_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "dimension_sets": [
-            {
-              "integrity": "high"
-            }
-          ]
-        },
-        "test": "installer_util_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "ipc_tests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "jingle_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "media_blink_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "media_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "midi_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "native_theme_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "net_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "pdf_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "ppapi_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "printing_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "remoting_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "dimension_sets": [
-            {
-              "integrity": "high"
-            }
-          ]
-        },
-        "test": "sbox_integration_tests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "sbox_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "sbox_validation_tests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "services_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "dimension_sets": [
-            {
-              "integrity": "high"
-            }
-          ]
-        },
-        "test": "setup_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "skia_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "sql_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "ui_base_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "unit_tests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "url_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "views_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "webkit_unit_tests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "wtf_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "zucchini_unittests"
-      }
-    ]
-  },
-  "CrWinClang64(dbg) tester": {
-    "gtest_tests": [
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "angle_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "base_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "blink_heap_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "blink_platform_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "shards": 20
-        },
-        "test": "browser_tests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "cacheinvalidation_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "capture_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "chrome_app_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "chrome_elf_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "components_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "content_browsertests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "content_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "courgette_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "crypto_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "device_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "extensions_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "gcm_unit_tests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "google_apis_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "gpu_ipc_service_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "gpu_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "dimension_sets": [
-            {
-              "integrity": "high"
-            }
-          ]
-        },
-        "test": "installer_util_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "ipc_tests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "jingle_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "media_blink_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "media_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "midi_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "native_theme_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "net_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "pdf_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "ppapi_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "printing_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "remoting_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "dimension_sets": [
-            {
-              "integrity": "high"
-            }
-          ]
-        },
-        "test": "sbox_integration_tests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "sbox_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "sbox_validation_tests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "services_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "dimension_sets": [
-            {
-              "integrity": "high"
-            }
-          ]
-        },
-        "test": "setup_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "skia_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "sql_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "ui_base_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "unit_tests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "url_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "views_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "webkit_unit_tests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "wtf_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "zucchini_unittests"
-      }
-    ]
-  },
-  "CrWinClang64(dll) tester": {
-    "gtest_tests": [
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "angle_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "base_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "blink_heap_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "blink_platform_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "shards": 10
-        },
-        "test": "browser_tests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "cacheinvalidation_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "capture_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "chrome_app_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "chrome_elf_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "components_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "content_browsertests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "content_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "courgette_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "crypto_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "device_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "extensions_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "gcm_unit_tests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "google_apis_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "gpu_ipc_service_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "gpu_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "dimension_sets": [
-            {
-              "integrity": "high"
-            }
-          ]
-        },
-        "test": "installer_util_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "ipc_tests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "jingle_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "media_blink_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "media_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "midi_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "native_theme_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "net_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "pdf_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "ppapi_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "printing_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "remoting_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "dimension_sets": [
-            {
-              "integrity": "high"
-            }
-          ]
-        },
-        "test": "sbox_integration_tests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "sbox_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "sbox_validation_tests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "services_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "dimension_sets": [
-            {
-              "integrity": "high"
-            }
-          ]
-        },
-        "test": "setup_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "skia_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "sql_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "ui_base_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "unit_tests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "url_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "views_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "webkit_unit_tests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "wtf_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "zucchini_unittests"
-      }
-    ]
-  },
   "CrWinClangGoma": {
     "gtest_tests": [
       {
@@ -11228,1181 +3683,19 @@
       }
     ]
   },
-  "CrWinClangLLD tester": {
+  "CrWinClexeGoma": {
     "gtest_tests": [
       {
         "swarming": {
           "can_use_on_swarming_builders": true
         },
-        "test": "angle_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
         "test": "base_unittests"
       },
       {
         "swarming": {
           "can_use_on_swarming_builders": true
         },
-        "test": "blink_heap_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "blink_platform_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "shards": 10
-        },
-        "test": "browser_tests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "cacheinvalidation_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "capture_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "chrome_app_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "chrome_elf_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "components_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "content_browsertests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
         "test": "content_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "courgette_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "crypto_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "device_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "extensions_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "gcm_unit_tests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "google_apis_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "gpu_ipc_service_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "gpu_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "dimension_sets": [
-            {
-              "integrity": "high"
-            }
-          ]
-        },
-        "test": "installer_util_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "ipc_tests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "jingle_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "media_blink_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "media_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "midi_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "native_theme_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "net_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "pdf_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "ppapi_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "printing_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "remoting_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "dimension_sets": [
-            {
-              "integrity": "high"
-            }
-          ]
-        },
-        "test": "sbox_integration_tests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "sbox_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "sbox_validation_tests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "services_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "dimension_sets": [
-            {
-              "integrity": "high"
-            }
-          ]
-        },
-        "test": "setup_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "skia_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "sql_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "ui_base_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "unit_tests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "url_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "views_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "webkit_unit_tests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "wtf_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "zucchini_unittests"
-      }
-    ]
-  },
-  "CrWinClangLLD64 tester": {
-    "gtest_tests": [
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "angle_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "base_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "blink_heap_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "blink_platform_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "shards": 10
-        },
-        "test": "browser_tests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "cacheinvalidation_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "capture_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "chrome_app_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "chrome_elf_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "components_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "content_browsertests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "content_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "courgette_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "crypto_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "device_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "extensions_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "gcm_unit_tests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "google_apis_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "gpu_ipc_service_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "gpu_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "dimension_sets": [
-            {
-              "integrity": "high"
-            }
-          ]
-        },
-        "test": "installer_util_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "ipc_tests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "jingle_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "media_blink_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "media_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "midi_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "native_theme_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "net_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "pdf_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "ppapi_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "printing_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "remoting_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "dimension_sets": [
-            {
-              "integrity": "high"
-            }
-          ]
-        },
-        "test": "sbox_integration_tests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "sbox_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "sbox_validation_tests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "services_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "dimension_sets": [
-            {
-              "integrity": "high"
-            }
-          ]
-        },
-        "test": "setup_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "skia_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "sql_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "ui_base_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "unit_tests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "url_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "views_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "webkit_unit_tests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "wtf_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "zucchini_unittests"
-      }
-    ]
-  },
-  "CrWinClngLLD64dbg tester": {
-    "gtest_tests": [
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "angle_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "base_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "blink_heap_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "blink_platform_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "shards": 10
-        },
-        "test": "browser_tests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "cacheinvalidation_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "capture_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "chrome_app_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "chrome_elf_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "components_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "content_browsertests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "content_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "courgette_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "crypto_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "device_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "extensions_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "gcm_unit_tests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "google_apis_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "gpu_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "dimension_sets": [
-            {
-              "integrity": "high"
-            }
-          ]
-        },
-        "test": "installer_util_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "ipc_tests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "jingle_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "media_blink_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "media_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "midi_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "native_theme_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "net_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "pdf_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "ppapi_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "printing_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "remoting_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "dimension_sets": [
-            {
-              "integrity": "high"
-            }
-          ]
-        },
-        "test": "sbox_integration_tests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "sbox_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "sbox_validation_tests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "services_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "dimension_sets": [
-            {
-              "integrity": "high"
-            }
-          ]
-        },
-        "test": "setup_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "skia_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "sql_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "ui_base_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "unit_tests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "url_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "views_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "webkit_unit_tests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "wtf_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "zucchini_unittests"
-      }
-    ]
-  },
-  "CrWinClngLLDdbg tester": {
-    "gtest_tests": [
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "angle_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "base_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "blink_heap_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "blink_platform_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "shards": 10
-        },
-        "test": "browser_tests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "cacheinvalidation_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "capture_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "chrome_app_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "chrome_elf_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "components_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "content_browsertests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "content_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "courgette_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "crypto_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "device_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "extensions_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "gcm_unit_tests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "google_apis_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "gpu_ipc_service_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "gpu_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "dimension_sets": [
-            {
-              "integrity": "high"
-            }
-          ]
-        },
-        "test": "installer_util_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "ipc_tests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "jingle_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "media_blink_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "media_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "midi_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "native_theme_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "net_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "pdf_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "ppapi_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "printing_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "remoting_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "dimension_sets": [
-            {
-              "integrity": "high"
-            }
-          ]
-        },
-        "test": "sbox_integration_tests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "sbox_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "sbox_validation_tests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "services_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "dimension_sets": [
-            {
-              "integrity": "high"
-            }
-          ]
-        },
-        "test": "setup_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "skia_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "sql_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "ui_base_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "unit_tests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "url_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "views_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "webkit_unit_tests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "wtf_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "zucchini_unittests"
       }
     ]
   },
@@ -12456,6 +3749,8 @@
   },
   "Fuchsia": {
     "additional_compile_targets": [
+      "content_browsertests",
+      "content_shell",
       "gl_unittests",
       "headless_shell"
     ],
@@ -12657,8 +3952,10 @@
   },
   "Fuchsia (dbg)": {
     "additional_compile_targets": [
-      "gl_unittests",
+      "content_browsertests",
+      "content_shell",
       "content_unittests",
+      "gl_unittests",
       "media_unittests",
       "net_unittests"
     ],
@@ -12828,9 +4125,9 @@
   },
   "Fuchsia ARM64": {
     "additional_compile_targets": [
-      "base_unittests",
+      "content_browsertests",
+      "content_shell",
       "content_unittests",
-      "crypto_unittests",
       "gl_unittests",
       "headless_shell",
       "ipc_tests",
@@ -12844,6 +4141,23 @@
       "skia_unittests",
       "service_manager_unittests",
       "ui_base_unittests"
+    ],
+    "gtest_tests": [
+      {
+        "args": [
+          "--test-launcher-filter-file=../../testing/buildbot/filters/fuchsia.base_unittests.filter"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true
+        },
+        "test": "base_unittests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": true
+        },
+        "test": "crypto_unittests"
+      }
     ]
   },
   "Headless Linux (dbg)": {
@@ -15775,6 +7089,34 @@
       }
     ]
   },
+  "WebKit Linux root_layer_scrolls Dummy Builder": {
+    "isolated_scripts": [
+      {
+        "args": [
+          "--additional-driver-flag=--root-layer-scrolls"
+        ],
+        "isolate_name": "webkit_layout_tests_exparchive",
+        "merge": {
+          "args": [
+            "--verbose"
+          ],
+          "script": "//third_party/WebKit/Tools/Scripts/merge-layout-test-results"
+        },
+        "name": "webkit_layout_tests",
+        "results_handler": "layout tests",
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "os": "Ubuntu-14.04"
+            }
+          ],
+          "hard_timeout": 900,
+          "shards": 15
+        }
+      }
+    ]
+  },
   "WebKit Linux slimming_paint_v2 Dummy Builder": {
     "isolated_scripts": [
       {
diff --git a/testing/buildbot/chromium.linux.json b/testing/buildbot/chromium.linux.json
index c394715..602c5551 100644
--- a/testing/buildbot/chromium.linux.json
+++ b/testing/buildbot/chromium.linux.json
@@ -3055,12 +3055,15 @@
   },
   "Cast Android (dbg)": {
     "additional_compile_targets": [
-      "cast_shell_apk"
+      "cast_junit_test_lists",
+      "cast_shell_apk",
+      "cast_test_lists"
     ]
   },
   "Cast Audio Linux": {
     "additional_compile_targets": [
-      "cast_shell"
+      "cast_shell",
+      "cast_test_lists"
     ],
     "gtest_tests": [
       {
@@ -3244,7 +3247,8 @@
   },
   "Cast Linux": {
     "additional_compile_targets": [
-      "cast_shell"
+      "cast_shell",
+      "cast_test_lists"
     ],
     "gtest_tests": [
       {
@@ -3456,6 +3460,8 @@
   "Fuchsia x64": {
     "additional_compile_targets": [
       "base_unittests",
+      "content_browsertests",
+      "content_shell",
       "content_unittests",
       "gl_unittests",
       "headless_shell",
diff --git a/testing/buildbot/chromium.perf.fyi.json b/testing/buildbot/chromium.perf.fyi.json
index 678a877..b30955f1 100644
--- a/testing/buildbot/chromium.perf.fyi.json
+++ b/testing/buildbot/chromium.perf.fyi.json
@@ -83,6 +83,8 @@
     "isolated_scripts": [
       {
         "args": [
+          "--bot",
+          "swarm823-c4",
           "--builder",
           "One Buildbot Step Test Builder",
           "-v",
@@ -100,6 +102,7 @@
           "can_use_on_swarming_builders": true,
           "dimension_sets": [
             {
+              "id": "swarm823-c4",
               "pool": "Chrome-perf-fyi"
             }
           ],
@@ -107,17 +110,6 @@
           "hard_timeout": 10800,
           "ignore_task_failure": false,
           "io_timeout": 3600
-        },
-        "trigger_script": {
-          "args": [
-            "--bot-id",
-            "swarm823-c4",
-            "--bot-id",
-            "swarm846-c4",
-            "--bot-id",
-            "swarm847-c4"
-          ],
-          "script": "//tools/perf/perf_device_trigger.py"
         }
       }
     ]
diff --git a/testing/buildbot/chromium.perf.json b/testing/buildbot/chromium.perf.json
index 07ad10df..a2cbc94 100644
--- a/testing/buildbot/chromium.perf.json
+++ b/testing/buildbot/chromium.perf.json
@@ -75872,6 +75872,30 @@
       },
       {
         "args": [
+          "--use-cmd-decoder=passthrough",
+          "--use-angle=gl-null"
+        ],
+        "isolate_name": "command_buffer_perftests",
+        "name": "passthrough_command_buffer_perftests",
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "gpu": "10de:104a",
+              "id": "build94-m1",
+              "os": "Windows-2008ServerR2-SP1",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 36000,
+          "hard_timeout": 10800,
+          "ignore_task_failure": false,
+          "io_timeout": 600,
+          "upload_test_results": false
+        }
+      },
+      {
+        "args": [
           "power.idle_platform",
           "-v",
           "--upload-results",
@@ -77978,6 +78002,30 @@
       },
       {
         "args": [
+          "--use-cmd-decoder=validating",
+          "--use-stub"
+        ],
+        "isolate_name": "command_buffer_perftests",
+        "name": "validating_command_buffer_perftests",
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "gpu": "10de:104a",
+              "id": "build94-m1",
+              "os": "Windows-2008ServerR2-SP1",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 36000,
+          "hard_timeout": 10800,
+          "ignore_task_failure": false,
+          "io_timeout": 600,
+          "upload_test_results": false
+        }
+      },
+      {
+        "args": [
           "webrtc",
           "-v",
           "--upload-results",
diff --git a/testing/buildbot/chromium.webkit.json b/testing/buildbot/chromium.webkit.json
index fe13bd96..320fb842 100644
--- a/testing/buildbot/chromium.webkit.json
+++ b/testing/buildbot/chromium.webkit.json
@@ -330,7 +330,7 @@
               "os": "Mac-10.10.5"
             }
           ],
-          "shards": 2
+          "shards": 4
         }
       }
     ],
@@ -379,7 +379,7 @@
               "os": "Mac-10.11.6"
             }
           ],
-          "shards": 2
+          "shards": 4
         }
       }
     ],
@@ -481,7 +481,7 @@
               "os": "Mac-10.12.6"
             }
           ],
-          "shards": 2
+          "shards": 4
         }
       }
     ],
diff --git a/testing/buildbot/filters/BUILD.gn b/testing/buildbot/filters/BUILD.gn
index 904fdabd..7236cb4 100644
--- a/testing/buildbot/filters/BUILD.gn
+++ b/testing/buildbot/filters/BUILD.gn
@@ -29,7 +29,6 @@
   testonly = true
 
   data = [
-    "//testing/buildbot/filters/isolate-extensions.browser_tests.filter",
     "//testing/buildbot/filters/mash.browser_tests.filter",
     "//testing/buildbot/filters/mojo.fyi.browser_tests.filter",
     "//testing/buildbot/filters/mojo.fyi.mus.browser_tests.filter",
@@ -45,7 +44,6 @@
 
   data = [
     "//testing/buildbot/filters/cast-linux.content_browsertests.filter",
-    "//testing/buildbot/filters/isolate-extensions.content_browsertests.filter",
     "//testing/buildbot/filters/mojo.fyi.network_content_browsertests.filter",
     "//testing/buildbot/filters/site-per-process.content_browsertests.filter",
   ]
diff --git a/testing/buildbot/filters/ash_unittests_mash.filter b/testing/buildbot/filters/ash_unittests_mash.filter
index dc8b18d..9d775e1 100644
--- a/testing/buildbot/filters/ash_unittests_mash.filter
+++ b/testing/buildbot/filters/ash_unittests_mash.filter
@@ -38,24 +38,24 @@
 # TODO: Extended desktop. http://crbug.com/695570
 -ExtendedDesktopTest.KeyEventsOnLockScreen
 -ExtendedDesktopTest.TestCursor
--FullscreenAppListPresenterDelegateTest.AppListViewDragHandler
--FullscreenAppListPresenterDelegateTest.AppListViewDragHandlerTabletModeFromSearch
--FullscreenAppListPresenterDelegateTest.BottomShelfAlignmentTextStateTransitions
--FullscreenAppListPresenterDelegateTest.HalfToFullscreenWhenTabletModeIsActive
--FullscreenAppListPresenterDelegateTest.HalfToPeekingByClickOrTap/0
--FullscreenAppListPresenterDelegateTest.HalfToPeekingByClickOrTap/1
--FullscreenAppListPresenterDelegateTest.KeyPressEnablesSearchBox
--FullscreenAppListPresenterDelegateTest.LongUpwardDragInFullscreenShouldNotClose/1
--FullscreenAppListPresenterDelegateTest.PeekingToFullscreenWhenTabletModeIsActive
--FullscreenAppListPresenterDelegateTest.SideShelfAlignmentTextStateTransitions
--FullscreenAppListPresenterDelegateTest.StateTransitionsByTapAndClickingAppListBodyFromHalf/0
--FullscreenAppListPresenterDelegateTest.StateTransitionsByTapAndClickingAppListBodyFromHalf/1
--FullscreenAppListPresenterDelegateTest.StateTransitionsByTappingAppListBodyFromFullscreen/0
--FullscreenAppListPresenterDelegateTest.StateTransitionsByTappingAppListBodyFromFullscreen/1
--FullscreenAppListPresenterDelegateTest.TabletModeTextStateTransitions
--FullscreenAppListPresenterDelegateTest.TapAndClickOutsideClosesHalfAppList/0
--FullscreenAppListPresenterDelegateTest.TapAndClickOutsideClosesHalfAppList/1
--FullscreenAppListPresenterDelegateTest.WhitespaceQuery
+-AppListPresenterDelegateTest.AppListViewDragHandler
+-AppListPresenterDelegateTest.AppListViewDragHandlerTabletModeFromSearch
+-AppListPresenterDelegateTest.BottomShelfAlignmentTextStateTransitions
+-AppListPresenterDelegateTest.HalfToFullscreenWhenTabletModeIsActive
+-AppListPresenterDelegateTest.HalfToPeekingByClickOrTap/0
+-AppListPresenterDelegateTest.HalfToPeekingByClickOrTap/1
+-AppListPresenterDelegateTest.KeyPressEnablesSearchBox
+-AppListPresenterDelegateTest.LongUpwardDragInFullscreenShouldNotClose/1
+-AppListPresenterDelegateTest.PeekingToFullscreenWhenTabletModeIsActive
+-AppListPresenterDelegateTest.SideShelfAlignmentTextStateTransitions
+-AppListPresenterDelegateTest.StateTransitionsByTapAndClickingAppListBodyFromHalf/0
+-AppListPresenterDelegateTest.StateTransitionsByTapAndClickingAppListBodyFromHalf/1
+-AppListPresenterDelegateTest.StateTransitionsByTappingAppListBodyFromFullscreen/0
+-AppListPresenterDelegateTest.StateTransitionsByTappingAppListBodyFromFullscreen/1
+-AppListPresenterDelegateTest.TabletModeTextStateTransitions
+-AppListPresenterDelegateTest.TapAndClickOutsideClosesHalfAppList/0
+-AppListPresenterDelegateTest.TapAndClickOutsideClosesHalfAppList/1
+-AppListPresenterDelegateTest.WhitespaceQuery
 -LockActionHandlerLayoutManagerTest.KeyboardBounds
 -LockLayoutManagerTest.AccessibilityPanel
 -LockLayoutManagerTest.AccessibilityPanelWithMultipleMonitors
@@ -122,8 +122,8 @@
 -ScreenshotControllerTest.MultipleDisplays
 -ScreenshotToolTest.EnablingCaptureRegionCallsDelegateAndDisablesTool
 -ScreenshotToolTest.EnablingCaptureScreenCallsDelegateAndDisablesTool
--ShelfLayoutManagerFullscreenAppListTest.SwipingUpOnShelfInLaptopModeForFullscreenAppList
--ShelfLayoutManagerFullscreenAppListTest.SwipingUpOnShelfInTabletModeForFullscreenAppList
+-ShelfLayoutManagerTest.SwipingUpOnShelfInLaptopModeForFullscreenAppList
+-ShelfLayoutManagerTest.SwipingUpOnShelfInTabletModeForFullscreenAppList
 -ShelfLayoutManagerTest.AutoHide
 -ShelfLayoutManagerTest.AutoHideShelfOnScreenBoundary
 -ShelfLayoutManagerTest.GestureDrag
diff --git a/testing/buildbot/filters/fuchsia.base_unittests.filter b/testing/buildbot/filters/fuchsia.base_unittests.filter
index d437369..524604c 100644
--- a/testing/buildbot/filters/fuchsia.base_unittests.filter
+++ b/testing/buildbot/filters/fuchsia.base_unittests.filter
@@ -58,3 +58,10 @@
 
 # https://crbug.com/752368.
 -FieldTrialListTest.ClearParamsFromSharedMemory
+
+# https://crbug.com/779645 - requires ability to set address-space limits.
+-PartitionAllocTest.RepeatedReturnNull
+-PartitionAllocTest.RepeatedReturnNullDirect
+
+# https://crbug.com/779668 - fails under Fuchsia/ARM64 due to Time::Now issue.
+-BuildTime.InThePast
diff --git a/testing/buildbot/filters/fuchsia.content_unittests.filter b/testing/buildbot/filters/fuchsia.content_unittests.filter
index f1b39521..40ccef4 100644
--- a/testing/buildbot/filters/fuchsia.content_unittests.filter
+++ b/testing/buildbot/filters/fuchsia.content_unittests.filter
@@ -44,6 +44,7 @@
 
 # Flaky: https://crbug.com/776424.
 -RenderWidgetHostViewAuraOverscrollTest.*
+-RenderWidgetHostViewAuraWheelScrollLatchingEnabledTest.*
 -RenderWidgetHostViewGuestSurfaceTest.TestGuestSurface
 
 # Flaky: https://crbug.com/777916.
diff --git a/testing/buildbot/filters/isolate-extensions.browser_tests.filter b/testing/buildbot/filters/isolate-extensions.browser_tests.filter
deleted file mode 100644
index 2c902e6..0000000
--- a/testing/buildbot/filters/isolate-extensions.browser_tests.filter
+++ /dev/null
@@ -1,3 +0,0 @@
-# List below tests to be excluded from running.
-
-# This list is currently empty. Hooray!
diff --git a/testing/buildbot/filters/isolate-extensions.content_browsertests.filter b/testing/buildbot/filters/isolate-extensions.content_browsertests.filter
deleted file mode 100644
index 2c902e6..0000000
--- a/testing/buildbot/filters/isolate-extensions.content_browsertests.filter
+++ /dev/null
@@ -1,3 +0,0 @@
-# List below tests to be excluded from running.
-
-# This list is currently empty. Hooray!
diff --git a/testing/buildbot/filters/mojo.fyi.network_browser_tests.filter b/testing/buildbot/filters/mojo.fyi.network_browser_tests.filter
index 366085e..a44dea6 100644
--- a/testing/buildbot/filters/mojo.fyi.network_browser_tests.filter
+++ b/testing/buildbot/filters/mojo.fyi.network_browser_tests.filter
@@ -2,60 +2,137 @@
 # See https://crbug.com/769401
 
 # Crashed tests that haven't been categorized.
--BrowserTestNonsecureURLRequest.DidChangeVisibleSecurityStateObserverObsoleteTLSSettings
--ChromeResourceDispatcherHostDelegateBrowserTest.NavigationDataProcessed
--ChromeServiceWorkerFetchTest.EmbedPdfOtherOrigin
--ChromeSitePerProcessPDFTest.EmbeddedPDFInsideCrossOriginFrame
--CrSettingsPeoplePageTest.All
--DevToolsExtensionTest.HttpIframeInDevToolsExtensionPanel
--DevToolsReattachAfterCrashTest.TestReattachAfterCrashOnNetwork
--DevToolsReattachAfterCrashTest.TestReattachAfterCrashOnTimeline
--DomDistillerTabUtilsBrowserTest.TestDistillIntoWebContents
--DomDistillerViewerSourceBrowserTest.DistillerJavaScriptExposed
--DomDistillerViewerSourceBrowserTest.DistillerJavaScriptNotInMainWorld
--DomDistillerViewerSourceBrowserTest.EarlyTemplateLoad
--DomDistillerViewerSourceBrowserTest.MultiPageArticle
--DomDistillerViewerSourceBrowserTest.NoWebUIBindingsArticleExists
--DomDistillerViewerSourceBrowserTest.NoWebUIBindingsArticleNotFound
--DomDistillerViewerSourceBrowserTest.PrefPersist
--DownloadTest.SaveLinkAsReferrerPolicyOrigin
--FlashEmbeds/ChromeContentRendererClientBrowserTest.RewriteYouTubeFlashEmbed/0
--FlashEmbeds/ChromeContentRendererClientBrowserTest.RewriteYouTubeFlashEmbed/1
--FlashEmbeds/ChromeContentRendererClientBrowserTest.RewriteYouTubeFlashEmbed/2
--FlashEmbeds/ChromeContentRendererClientBrowserTest.RewriteYouTubeFlashEmbed/3
--FlashEmbeds/ChromeContentRendererClientBrowserTest.RewriteYouTubeFlashEmbed/4
--FlashEmbeds/ChromeContentRendererClientBrowserTest.RewriteYouTubeFlashEmbedObject/2
--FlashEmbeds/ChromeContentRendererClientBrowserTest.RewriteYouTubeFlashEmbedObject/3
--FlashEmbeds/ChromeContentRendererClientBrowserTest.RewriteYouTubeFlashEmbedObject/4
--HotwordInstallerBrowserTest.AbortInstallOnShutdown
--IncognitoWindowTrackerBrowserTest.ShowPromo
--NewTabTrackerBrowserTest.TestShowPromo
--NoStatePrefetchBrowserTest/NoStatePrefetchBrowserTest.SSLError/0
--PDFExtensionTest.EnsureCrossOriginRepliesBlocked
--PDFExtensionTest.PostMessageForZeroSizedEmbed
--PDFExtensionTest.TabTitleWithEmbeddedPdf
--PrintPreviewDialogControllerBrowserTest.PdfPluginDisabled
--PrintPreviewDialogControllerBrowserTest.PrintPreviewPdfAccessibility
+-AdsPageLoadMetricsObserverBrowserTest.DocOverwritesNavigation
+-AdsPageLoadMetricsObserverBrowserTest.SubresourceFilter
+-CrExtensionsCodeSectionTest.Layout
+-CrExtensionsDetailViewTest.ClickableElements
+-CrExtensionsDetailViewTest.IndicatorTest
+-CrExtensionsDetailViewTest.Layout
+-CrExtensionsDetailViewTest.Warnings
+-CrExtensionsErrorPageTest.CodeSection
+-CrExtensionsErrorPageTest.ErrorSelection
+-CrExtensionsErrorPageTest.Layout
+-CrExtensionsItemListTest.NoItems
+-CrExtensionsItemListTest.NoSearchResults
+-CrExtensionsItemsTest.ClickableItems
+-CrExtensionsItemsTest.DeveloperState
+-CrExtensionsItemsTest.EnableToggle
+-CrExtensionsItemsTest.NormalState
+-CrExtensionsItemsTest.RemoveButton
+-CrExtensionsItemsTest.SourceIndicator
+-CrExtensionsItemsTest.Warnings
+-CrExtensionsLoadErrorTest.CodeSection
+-CrExtensionsLoadErrorTest.Interaction
+-CrExtensionsManagerTestWithIdQueryParam.NavigationToDetails
+-CrExtensionsManagerTestWithMultipleExtensionTypesInstalled.ChangePages
+-CrExtensionsManagerTestWithMultipleExtensionTypesInstalled.ItemListVisibility
+-CrExtensionsManagerTestWithMultipleExtensionTypesInstalled.SplitItems
+-CrExtensionsManagerTest.ItemOrder
+-CrExtensionsManagerTest.UpdateItemData
+-CrExtensionsNavigationHelperTest.Basic
+-CrExtensionsNavigationHelperTest.Conversion
+-CrExtensionsNavigationHelperTest.PushAndReplaceState
+-CrExtensionsNavigationHelperTest.SupportedRoutes
+-CrExtensionsOptionsDialogTest.Layout
+-CrExtensionsPackDialogTest.Interaction
+-CrExtensionsPackDialogTest.PackError
+-CrExtensionsPackDialogTest.PackSuccess
+-CrExtensionsPackDialogTest.PackWarning
+-CrExtensionsServiceTest.ProfileSettings
+-CrExtensionsServiceTest.ToggleEnable
+-CrExtensionsServiceTest.ToggleIncognito
+-CrExtensionsServiceTest.Uninstall
+-CrExtensionsSidebarTest.LayoutAndClickHandlers
+-CrExtensionsSidebarTest.SetSelected
+-CrExtensionsShortcutTest.Basic
+-CrExtensionsShortcutTest.Layout
+-CrExtensionsToggleRowTest.ToggleRowTest
+-CrExtensionsToolbarTest.ClickHandlers
+-CrExtensionsToolbarTest.Layout
+-CrExtensionsViewManagerTest.EventFiringTest
+-CrExtensionsViewManagerTest.VisibilityTest
+-CredentialManagerBrowserTest.StoreInUnloadHandler_SameSite_OnDemandMojoPipe
+-DiceMigrationBrowserTest.Signin
+-DiceMigrationBrowserTest.Signout
+-ExtensionsA11yTestFixture.BASIC_EXTENSIONS_region
+-LocalNTPDoodleTest.ShouldAnimateLogoWhenClicked
+-LocalNTPJavascriptTest.SimpleJavascriptTests
+-LocalNTPVoiceJavascriptTest.MicrophoneTests
+-LocalNTPVoiceJavascriptTest.SpeechTests
+-LocalNTPVoiceJavascriptTest.TextTests
+-LocalNTPVoiceJavascriptTest.ViewTests
+-MSE_ExternalClearKey_Mojo/EncryptedMediaTest.Playback_AudioClearVideo_WebM/0
+-Mojo/ECKEncryptedMediaTest.CDMCrashDuringDecode/0
+-Mojo/ECKEncryptedMediaTest.DecryptOnly_VideoAudio_WebM/0
+-Mojo/ECKEncryptedMediaTest.FileIOTest/0
+-Mojo/ECKEncryptedMediaTest.LoadUnknownSession/0
+-Mojo/ECKEncryptedMediaTest.LoadLoadableSession/0
+-Mojo/ECKEncryptedMediaTest.MultipleCdmTypes/0
+-Mojo/ECKEncryptedMediaTest.OutputProtectionTest/0
+-Mojo/ECKEncryptedMediaTest.PlatformVerificationTest/0
+-Mojo/ECKEncryptedMediaTest.Renewal/0
+-MSE_ExternalClearKey_Mojo/EncryptedMediaTest.ConfigChangeVideo_ClearToEncrypted/0
+-MSE_ExternalClearKey_Mojo/EncryptedMediaTest.ConfigChangeVideo_EncryptedToClear/0
+-MSE_ExternalClearKey_Mojo/EncryptedMediaTest.ConfigChangeVideo_EncryptedToEncrypted/0
+-MSE_ExternalClearKey_Mojo/EncryptedMediaTest.FrameSizeChangeVideo/0
+-MSE_ExternalClearKey_Mojo/EncryptedMediaTest.InvalidResponseKeyError/0
+-MSE_ExternalClearKey_Mojo/EncryptedMediaTest.Playback_Multiple_VideoAudio_WebM/0
+-MSE_ExternalClearKey_Mojo/EncryptedMediaTest.Playback_VideoAudio_WebM_Opus/0
+-MSE_ExternalClearKey_Mojo/EncryptedMediaTest.Playback_VideoAudio_WebM/0
+-MSE_ExternalClearKey_Mojo/EncryptedMediaTest.Playback_VideoClearAudio_WebM/0
+-MSE_ExternalClearKey_Mojo/EncryptedMediaTest.Playback_VideoClearAudio_WebM_Opus/0
+-MSE_ExternalClearKey_Mojo/EncryptedMediaTest.Playback_VP9Video_WebM_Fullsample/0
+-MSE_ExternalClearKey_Mojo/EncryptedMediaTest.Playback_VP9Video_WebM_Subsample/0
+-MSE_ExternalClearKey_Mojo/EncryptedMediaTest.PolicyCheck/0
+-NoStatePrefetchBrowserTest/NoStatePrefetchBrowserTest.PrefetchHistograms/1
+-PolicyTest.BookmarkBarEnabled
+-PolicyTest.HomepageLocation
+-PredictorBrowserTest.CrossSiteNoReferrerNoPredictionAfterOneNavigation
+-PredictorBrowserTest.CrossSiteRedirectNoPredictionWithPath
+-PredictorBrowserTest.CrossSiteSimplePredictionAfterOneNavigationNoInterceptor
+-PredictorBrowserTest.CrossSiteUseOneSocket
+-PredictorBrowserTest.CrossSiteUseThreeSockets
+-PredictorBrowserTest.DoNotEvictRecentlyUsed
+-PredictorBrowserTest.ForgetBadPrediction
+-PredictorBrowserTest.PreconnectAndFetchCORS
+-PredictorBrowserTest.PreconnectAndFetchNonCORS
+-ProcessMemoryMetricsEmitterTest.FetchAndEmitMetricsWithExtensions
+-ProcessMemoryMetricsEmitterTest.FetchAndEmitMetricsWithExtensionsAndHostReuse
 -ProxySettingsApiTest.SettingsRemovedOnPolicyBlacklist
--ReferrerPolicyTest.ContextMenuRedirect
--ReferrerPolicyTest.HttpsContextMenuOrigin
--ReferrerPolicyTest.HttpsContextMenuRedirect
--SBNavigationObserverBrowserTest.AddIPMapping
--SBNavigationObserverBrowserTest.DownloadViaHTML5FileApiWithUserGesture
--SBNavigationObserverBrowserTest.DownloadViaHTML5FileApiWithoutUserGesture
--SSLUITest.TestInterstitialJavaScriptGoesBack
--SSLUITest.TestInterstitialJavaScriptProceeds
--SSLUITestWithExtendedReporting.TestBadClockReportingWithNoOptIn
--SSLUITestWithExtendedReporting.TestBadClockReportingWithOptIn
--SavePageBrowserTest.SavePageBrowserTest_NonMHTML
--SaveType/SavePageOriginalVsSavedComparisonTest.ObjectElementsViaFile/0
--SaveType/SavePageOriginalVsSavedComparisonTest.ObjectElementsViaHttp/0
--SpellingMenuObserverTest.SuggestionsForceTopSeparator
--WebRtcBrowserTest.RunsAudioVideoWebRTCCallInTwoTabsVP8
--WebRtcBrowserTest.RunsAudioVideoWebRTCCallInTwoTabsVP9
--WebrtcEventLogApiTest.TestStartStopWebRtcEventLogging
--WebrtcEventLogApiTest.TestStartTimedWebRtcEventLogging
--WebstoreInlineInstallerListenerTest.BothListenersTest
+-ResourcePrefetchPredictorBrowserTest.AlwaysRevalidate
+-ResourcePrefetchPredictorBrowserTest.CrossSiteNavigation
+-ResourcePrefetchPredictorBrowserTest.HttpToHttpsRedirect
+-ResourcePrefetchPredictorBrowserTest.IframeShouldBeIgnored
+-ResourcePrefetchPredictorBrowserTest.JavascriptAppendChild
+-ResourcePrefetchPredictorBrowserTest.JavascriptDocumentWrite
+-ResourcePrefetchPredictorBrowserTest.JavascriptInnerHtml
+-ResourcePrefetchPredictorBrowserTest.JavascriptRedirectsAreNotHandled
+-ResourcePrefetchPredictorBrowserTest.JavascriptXHR
+-ResourcePrefetchPredictorBrowserTest.Redirect
+-ResourcePrefetchPredictorBrowserTest.RedirectChain
+-ResourcePrefetchPredictorBrowserTest.Simple
+-ResourcePrefetchPredictorBrowserTest.TabIdBehavingAsExpected
+-ResourcePrefetchPredictorPrefetchingBrowserTest.Redirect
+-ResourcePrefetchPredictorPrefetchingBrowserTest.Simple
+-SSLUIWorkerFetchTest.TestUnsafeContentsInWorkerWithUserException/2
+-SSLUIWorkerFetchTest.TestUnsafeContentsInWorkerWithUserException/3
+-SafeBrowsingBlockingPageBrowserTestWithThreatTypeAndIsolationSetting/SafeBrowsingBlockingPageBrowserTest.SecurityStateGoBackOnSubresourceInterstitial/0
+-SafeBrowsingBlockingPageBrowserTestWithThreatTypeAndIsolationSetting/SafeBrowsingBlockingPageBrowserTest.SecurityStateGoBackOnSubresourceInterstitial/1
+-SafeBrowsingBlockingPageBrowserTestWithThreatTypeAndIsolationSetting/SafeBrowsingBlockingPageBrowserTest.SecurityStateGoBackOnSubresourceInterstitial/2
+-SafeBrowsingBlockingPageBrowserTestWithThreatTypeAndIsolationSetting/SafeBrowsingBlockingPageBrowserTest.SecurityStateGoBackOnSubresourceInterstitial/3
+-SafeBrowsingBlockingPageBrowserTestWithThreatTypeAndIsolationSetting/SafeBrowsingBlockingPageBrowserTest.SecurityStateGoBackOnSubresourceInterstitial/4
+-SafeBrowsingBlockingPageBrowserTestWithThreatTypeAndIsolationSetting/SafeBrowsingBlockingPageBrowserTest.SecurityStateGoBackOnSubresourceInterstitial/5
+-SafeBrowsingTriggeredPopupBlockerBrowserTest.BlockCreatingNewWindows
+-SafeBrowsingTriggeredPopupBlockerBrowserTest.BlockOpenURLFromTab
+-SafeBrowsingTriggeredPopupBlockerBrowserTest.BlockOpenURLFromTabInIframe
+-SafeBrowsingTriggeredPopupBlockerBrowserTest.MultipleNavigations
+-SafeBrowsingTriggeredPopupBlockerBrowserTest.WarningAllowCreatingNewWindows_LogsToConsole
+-SafeBrowsingTriggeredPopupBlockerBrowserTest.WarningDoNotBlockCreatingNewWindows_LogsToConsole
+-SavePageBrowserTest.SaveUnauthorizedResource
+-ServiceWorkerPaymentAppFactoryBrowserTest.AllOringsSupported
+-ServiceWorkerPaymentAppFactoryBrowserTest.SupportedOrigin
+-ServiceWorkerPaymentAppFactoryBrowserTest.TwoAppsDifferentMethods
+-ServiceWorkerPaymentAppFactoryBrowserTest.TwoAppsSameMethod
 
 # Timed out tests that haven't been categorized.
 -ActivityLogApiTest.TriggerEvent
@@ -194,6 +271,7 @@
 -BrowserOnly/MemlogBrowserTest.EndToEndTracing/0
 -BrowserTest.CancelBeforeUnloadResetsURL
 -BrowserTest.InterstitialCancelsGuestViewDialogs
+-BrowserTest.ReloadThenCancelBeforeUnload
 -BrowsingDataRemoverBrowserTest.CookieDeletion
 -BrowsingDataRemoverBrowserTest.Database
 -CastChannelAPITest.TestOpenError
@@ -313,6 +391,7 @@
 -DidChangeVisibleSecurityStateTest.DidChangeVisibleSecurityStateObserver
 -DidChangeVisibleSecurityStateTest.DidChangeVisibleSecurityStateObserverGoBack
 -DisabledSignInIsolationBrowserTest.SyntheticTrial
+-DomainReliabilityBrowserTest.Upload
 -DownloadsApiTest.DownloadsApiTest
 -EnabledSignInIsolationBrowserTest.SyntheticTrial
 -ErrorConsoleBrowserTest.BadAPIArgumentsRuntimeError
@@ -500,8 +579,11 @@
 -ExtensionModuleApiTest.IncognitoNoFile
 -ExtensionModuleTest.TestModulesAvailable
 -ExtensionOptionsApiTests/ExtensionOptionsApiTest.CannotEmbedUsingInvalidExtensionIds/0
+-ExtensionOptionsApiTests/ExtensionOptionsApiTest.CannotEmbedUsingInvalidExtensionIds/1
+-ExtensionOptionsApiTests/ExtensionOptionsApiTest.ExtensionCanEmbedOwnOptions/1
 -ExtensionOptionsApiTests/ExtensionOptionsApiTest.ExtensionCanEmbedOwnOptions/0
 -ExtensionOptionsApiTests/ExtensionOptionsApiTest.ShouldNotEmbedOtherExtensionsOptions/0
+-ExtensionOptionsApiTests/ExtensionOptionsApiTest.ShouldNotEmbedOtherExtensionsOptions/1
 -ExtensionOverrideTest.OverrideHistory
 -ExtensionOverrideTest.OverrideNewTab
 -ExtensionOverrideTest.OverrideNewTabMultiple
@@ -624,6 +706,14 @@
 -FileSystemApiTest.FileSystemApiSaveNewFileWithWriteTest
 -FileSystemApiTest.RequestFileSystem_NotChromeOS
 -FlagOffExtensionActionRunnerBrowserTest.ScriptsExecuteWhenFlagAbsent
+-FlashEmbeds/ChromeContentRendererClientBrowserTest.RewriteYouTubeFlashEmbed/0
+-FlashEmbeds/ChromeContentRendererClientBrowserTest.RewriteYouTubeFlashEmbed/1
+-FlashEmbeds/ChromeContentRendererClientBrowserTest.RewriteYouTubeFlashEmbed/2
+-FlashEmbeds/ChromeContentRendererClientBrowserTest.RewriteYouTubeFlashEmbed/3
+-FlashEmbeds/ChromeContentRendererClientBrowserTest.RewriteYouTubeFlashEmbed/4
+-FlashEmbeds/ChromeContentRendererClientBrowserTest.RewriteYouTubeFlashEmbedObject/2
+-FlashEmbeds/ChromeContentRendererClientBrowserTest.RewriteYouTubeFlashEmbedObject/3
+-FlashEmbeds/ChromeContentRendererClientBrowserTest.RewriteYouTubeFlashEmbedObject/4
 -GcmApiTest.Incognito
 -GcmApiTest.OnMessage
 -GcmApiTest.OnMessagesDeleted
@@ -762,16 +852,28 @@
 -MessagingApiTest.MessagingNoBackground
 -MessagingApiTest.MessagingOnUnload
 -MimeHandlerViewTests/MimeHandlerViewTest.Abort/0
+-MimeHandlerViewTests/MimeHandlerViewTest.Abort/1
 -MimeHandlerViewTests/MimeHandlerViewTest.Basic/0
+-MimeHandlerViewTests/MimeHandlerViewTest.Basic/1
 -MimeHandlerViewTests/MimeHandlerViewTest.DataUrl/0
+-MimeHandlerViewTests/MimeHandlerViewTest.DataUrl/1
 -MimeHandlerViewTests/MimeHandlerViewTest.Embedded/0
+-MimeHandlerViewTests/MimeHandlerViewTest.Embedded/1
 -MimeHandlerViewTests/MimeHandlerViewTest.EmbeddedDataUrlEmbed/0
+-MimeHandlerViewTests/MimeHandlerViewTest.EmbeddedDataUrlEmbed/1
 -MimeHandlerViewTests/MimeHandlerViewTest.EmbeddedDataUrlLong/0
+-MimeHandlerViewTests/MimeHandlerViewTest.EmbeddedDataUrlLong/1
 -MimeHandlerViewTests/MimeHandlerViewTest.EmbeddedDataUrlObject/0
+-MimeHandlerViewTests/MimeHandlerViewTest.EmbeddedDataUrlObject/1
 -MimeHandlerViewTests/MimeHandlerViewTest.Iframe/0
+-MimeHandlerViewTests/MimeHandlerViewTest.Iframe/1
 -MimeHandlerViewTests/MimeHandlerViewTest.NonAsciiHeaders/0
+-MimeHandlerViewTests/MimeHandlerViewTest.NonAsciiHeaders/1
 -MimeHandlerViewTests/MimeHandlerViewTest.PostMessage/0
+-MimeHandlerViewTests/MimeHandlerViewTest.PostMessage/1
 -MimeHandlerViewTests/MimeHandlerViewTest.ResizeBeforeAttach/0
+-MimeHandlerViewTests/MimeHandlerViewTest.ResizeBeforeAttach/1
+-MimeHandlerViewTests/MimeHandlerViewTest.SingleRequest/1
 -MusicManagerPrivateTest.DeviceIdValueReturned
 -NaClBrowserTestGLibcVcacheExtension.ValidationCacheOfMainNexe
 -NaClBrowserTestNewlibVcacheExtension.ValidationCacheOfMainNexe
@@ -819,6 +921,29 @@
 -NewlibPackagedAppTest.NoSocketPermissions
 -NewlibPackagedAppTest.SocketPermissions
 -NewlibPackagedAppTest.SuccessfulLoad
+-NoStatePrefetchBrowserTest/NoStatePrefetchBrowserTest.AppCacheHtmlUninitialized/1
+-NoStatePrefetchBrowserTest/NoStatePrefetchBrowserTest.IssuesIdlePriorityRequests/1
+-NoStatePrefetchBrowserTest/NoStatePrefetchBrowserTest.Jpeg/1
+-NoStatePrefetchBrowserTest/NoStatePrefetchBrowserTest.Loop/1
+-NoStatePrefetchBrowserTest/NoStatePrefetchBrowserTest.MetaTagCSP/1
+-NoStatePrefetchBrowserTest/NoStatePrefetchBrowserTest.Png/1
+-NoStatePrefetchBrowserTest/NoStatePrefetchBrowserTest.Prefetch301LoadFlags/1
+-NoStatePrefetchBrowserTest/NoStatePrefetchBrowserTest.Prefetch301Redirect/1
+-NoStatePrefetchBrowserTest/NoStatePrefetchBrowserTest.Prefetch301Subresource/1
+-NoStatePrefetchBrowserTest/NoStatePrefetchBrowserTest.PrefetchClientRedirect/1
+-NoStatePrefetchBrowserTest/NoStatePrefetchBrowserTest.PrefetchCrossDomain/1
+-NoStatePrefetchBrowserTest/NoStatePrefetchBrowserTest.PrefetchHttps/1
+-NoStatePrefetchBrowserTest/NoStatePrefetchBrowserTest.PrefetchImage/1
+-NoStatePrefetchBrowserTest/NoStatePrefetchBrowserTest.PrefetchLoadFlag/1
+-NoStatePrefetchBrowserTest/NoStatePrefetchBrowserTest.PrefetchMultipleRequest/1
+-NoStatePrefetchBrowserTest/NoStatePrefetchBrowserTest.PrefetchSimple/1
+-NoStatePrefetchBrowserTest/NoStatePrefetchBrowserTest.PrefetchSimultaneous/1
+-NoStatePrefetchBrowserTest/NoStatePrefetchBrowserTest.PrerenderSafeBrowsingSubresource/1
+-NoStatePrefetchBrowserTest/NoStatePrefetchBrowserTest.ResponseHeaderCSP/1
+-NoStatePrefetchBrowserTest/NoStatePrefetchBrowserTest.ServiceWorkerIntercept/1
+-NoStatePrefetchBrowserTest/NoStatePrefetchBrowserTest.SSLError/0
+-NoStatePrefetchBrowserTest/NoStatePrefetchBrowserTest.SSLError/1
+-NoStatePrefetchBrowserTest/NoStatePrefetchBrowserTest.SSLSubresourceError/1
 -OmniboxApiTest.OnInputEntered
 -PDFExtensionClipboardTest.CombinedShiftArrowPresses
 -PDFExtensionClipboardTest.CombinedShiftRightArrowPresses
@@ -1216,6 +1341,156 @@
 -RepostFormWarningTest.TestLoginAfterRepost
 -ResourcesPrivateApiTest.GetStrings
 -RuntimeAPIUpdateTest.TerminatedExtensionUpdateHasCorrectPreviousVersion
+-SafeBrowsingBlockingPageBrowserTestWithThreatTypeAndIsolationSetting/SafeBrowsingBlockingPageBrowserTest.DontProceed/0
+-SafeBrowsingBlockingPageBrowserTestWithThreatTypeAndIsolationSetting/SafeBrowsingBlockingPageBrowserTest.DontProceed/1
+-SafeBrowsingBlockingPageBrowserTestWithThreatTypeAndIsolationSetting/SafeBrowsingBlockingPageBrowserTest.DontProceed/2
+-SafeBrowsingBlockingPageBrowserTestWithThreatTypeAndIsolationSetting/SafeBrowsingBlockingPageBrowserTest.DontProceed/3
+-SafeBrowsingBlockingPageBrowserTestWithThreatTypeAndIsolationSetting/SafeBrowsingBlockingPageBrowserTest.DontProceed/4
+-SafeBrowsingBlockingPageBrowserTestWithThreatTypeAndIsolationSetting/SafeBrowsingBlockingPageBrowserTest.DontProceed/5
+-SafeBrowsingBlockingPageBrowserTestWithThreatTypeAndIsolationSetting/SafeBrowsingBlockingPageBrowserTest.Histograms_DontProceed/0
+-SafeBrowsingBlockingPageBrowserTestWithThreatTypeAndIsolationSetting/SafeBrowsingBlockingPageBrowserTest.Histograms_DontProceed/1
+-SafeBrowsingBlockingPageBrowserTestWithThreatTypeAndIsolationSetting/SafeBrowsingBlockingPageBrowserTest.Histograms_DontProceed/2
+-SafeBrowsingBlockingPageBrowserTestWithThreatTypeAndIsolationSetting/SafeBrowsingBlockingPageBrowserTest.Histograms_DontProceed/3
+-SafeBrowsingBlockingPageBrowserTestWithThreatTypeAndIsolationSetting/SafeBrowsingBlockingPageBrowserTest.Histograms_DontProceed/4
+-SafeBrowsingBlockingPageBrowserTestWithThreatTypeAndIsolationSetting/SafeBrowsingBlockingPageBrowserTest.Histograms_DontProceed/5
+-SafeBrowsingBlockingPageBrowserTestWithThreatTypeAndIsolationSetting/SafeBrowsingBlockingPageBrowserTest.Histograms_Proceed/0
+-SafeBrowsingBlockingPageBrowserTestWithThreatTypeAndIsolationSetting/SafeBrowsingBlockingPageBrowserTest.Histograms_Proceed/1
+-SafeBrowsingBlockingPageBrowserTestWithThreatTypeAndIsolationSetting/SafeBrowsingBlockingPageBrowserTest.Histograms_Proceed/2
+-SafeBrowsingBlockingPageBrowserTestWithThreatTypeAndIsolationSetting/SafeBrowsingBlockingPageBrowserTest.Histograms_Proceed/3
+-SafeBrowsingBlockingPageBrowserTestWithThreatTypeAndIsolationSetting/SafeBrowsingBlockingPageBrowserTest.Histograms_Proceed/4
+-SafeBrowsingBlockingPageBrowserTestWithThreatTypeAndIsolationSetting/SafeBrowsingBlockingPageBrowserTest.Histograms_Proceed/5
+-SafeBrowsingBlockingPageBrowserTestWithThreatTypeAndIsolationSetting/SafeBrowsingBlockingPageBrowserTest.IframeDontProceed/0
+-SafeBrowsingBlockingPageBrowserTestWithThreatTypeAndIsolationSetting/SafeBrowsingBlockingPageBrowserTest.IframeDontProceed/1
+-SafeBrowsingBlockingPageBrowserTestWithThreatTypeAndIsolationSetting/SafeBrowsingBlockingPageBrowserTest.IframeDontProceed/2
+-SafeBrowsingBlockingPageBrowserTestWithThreatTypeAndIsolationSetting/SafeBrowsingBlockingPageBrowserTest.IframeDontProceed/3
+-SafeBrowsingBlockingPageBrowserTestWithThreatTypeAndIsolationSetting/SafeBrowsingBlockingPageBrowserTest.IframeDontProceed/4
+-SafeBrowsingBlockingPageBrowserTestWithThreatTypeAndIsolationSetting/SafeBrowsingBlockingPageBrowserTest.IframeDontProceed/5
+-SafeBrowsingBlockingPageBrowserTestWithThreatTypeAndIsolationSetting/SafeBrowsingBlockingPageBrowserTest.IframeOptInAndReportThreatDetails/0
+-SafeBrowsingBlockingPageBrowserTestWithThreatTypeAndIsolationSetting/SafeBrowsingBlockingPageBrowserTest.IframeOptInAndReportThreatDetails/1
+-SafeBrowsingBlockingPageBrowserTestWithThreatTypeAndIsolationSetting/SafeBrowsingBlockingPageBrowserTest.IframeOptInAndReportThreatDetails/2
+-SafeBrowsingBlockingPageBrowserTestWithThreatTypeAndIsolationSetting/SafeBrowsingBlockingPageBrowserTest.IframeOptInAndReportThreatDetails/3
+-SafeBrowsingBlockingPageBrowserTestWithThreatTypeAndIsolationSetting/SafeBrowsingBlockingPageBrowserTest.IframeOptInAndReportThreatDetails/4
+-SafeBrowsingBlockingPageBrowserTestWithThreatTypeAndIsolationSetting/SafeBrowsingBlockingPageBrowserTest.IframeOptInAndReportThreatDetails/5
+-SafeBrowsingBlockingPageBrowserTestWithThreatTypeAndIsolationSetting/SafeBrowsingBlockingPageBrowserTest.IframeProceed/0
+-SafeBrowsingBlockingPageBrowserTestWithThreatTypeAndIsolationSetting/SafeBrowsingBlockingPageBrowserTest.IframeProceed/1
+-SafeBrowsingBlockingPageBrowserTestWithThreatTypeAndIsolationSetting/SafeBrowsingBlockingPageBrowserTest.IframeProceed/2
+-SafeBrowsingBlockingPageBrowserTestWithThreatTypeAndIsolationSetting/SafeBrowsingBlockingPageBrowserTest.IframeProceed/3
+-SafeBrowsingBlockingPageBrowserTestWithThreatTypeAndIsolationSetting/SafeBrowsingBlockingPageBrowserTest.IframeProceed/4
+-SafeBrowsingBlockingPageBrowserTestWithThreatTypeAndIsolationSetting/SafeBrowsingBlockingPageBrowserTest.IframeProceed/5
+-SafeBrowsingBlockingPageBrowserTestWithThreatTypeAndIsolationSetting/SafeBrowsingBlockingPageBrowserTest.LearnMore/0
+-SafeBrowsingBlockingPageBrowserTestWithThreatTypeAndIsolationSetting/SafeBrowsingBlockingPageBrowserTest.LearnMore/1
+-SafeBrowsingBlockingPageBrowserTestWithThreatTypeAndIsolationSetting/SafeBrowsingBlockingPageBrowserTest.LearnMore/2
+-SafeBrowsingBlockingPageBrowserTestWithThreatTypeAndIsolationSetting/SafeBrowsingBlockingPageBrowserTest.LearnMore/3
+-SafeBrowsingBlockingPageBrowserTestWithThreatTypeAndIsolationSetting/SafeBrowsingBlockingPageBrowserTest.LearnMore/4
+-SafeBrowsingBlockingPageBrowserTestWithThreatTypeAndIsolationSetting/SafeBrowsingBlockingPageBrowserTest.LearnMore/5
+-SafeBrowsingBlockingPageBrowserTestWithThreatTypeAndIsolationSetting/SafeBrowsingBlockingPageBrowserTest.MainFrameBlockedShouldHaveNoDOMDetailsWhenDontProceed/0
+-SafeBrowsingBlockingPageBrowserTestWithThreatTypeAndIsolationSetting/SafeBrowsingBlockingPageBrowserTest.MainFrameBlockedShouldHaveNoDOMDetailsWhenDontProceed/1
+-SafeBrowsingBlockingPageBrowserTestWithThreatTypeAndIsolationSetting/SafeBrowsingBlockingPageBrowserTest.MainFrameBlockedShouldHaveNoDOMDetailsWhenDontProceed/2
+-SafeBrowsingBlockingPageBrowserTestWithThreatTypeAndIsolationSetting/SafeBrowsingBlockingPageBrowserTest.MainFrameBlockedShouldHaveNoDOMDetailsWhenDontProceed/3
+-SafeBrowsingBlockingPageBrowserTestWithThreatTypeAndIsolationSetting/SafeBrowsingBlockingPageBrowserTest.MainFrameBlockedShouldHaveNoDOMDetailsWhenDontProceed/4
+-SafeBrowsingBlockingPageBrowserTestWithThreatTypeAndIsolationSetting/SafeBrowsingBlockingPageBrowserTest.MainFrameBlockedShouldHaveNoDOMDetailsWhenDontProceed/5
+-SafeBrowsingBlockingPageBrowserTestWithThreatTypeAndIsolationSetting/SafeBrowsingBlockingPageBrowserTest.MainFrameBlockedShouldHaveNoDOMDetailsWhenProceeding/0
+-SafeBrowsingBlockingPageBrowserTestWithThreatTypeAndIsolationSetting/SafeBrowsingBlockingPageBrowserTest.MainFrameBlockedShouldHaveNoDOMDetailsWhenProceeding/1
+-SafeBrowsingBlockingPageBrowserTestWithThreatTypeAndIsolationSetting/SafeBrowsingBlockingPageBrowserTest.MainFrameBlockedShouldHaveNoDOMDetailsWhenProceeding/2
+-SafeBrowsingBlockingPageBrowserTestWithThreatTypeAndIsolationSetting/SafeBrowsingBlockingPageBrowserTest.MainFrameBlockedShouldHaveNoDOMDetailsWhenProceeding/3
+-SafeBrowsingBlockingPageBrowserTestWithThreatTypeAndIsolationSetting/SafeBrowsingBlockingPageBrowserTest.MainFrameBlockedShouldHaveNoDOMDetailsWhenProceeding/4
+-SafeBrowsingBlockingPageBrowserTestWithThreatTypeAndIsolationSetting/SafeBrowsingBlockingPageBrowserTest.MainFrameBlockedShouldHaveNoDOMDetailsWhenProceeding/5
+-SafeBrowsingBlockingPageBrowserTestWithThreatTypeAndIsolationSetting/SafeBrowsingBlockingPageBrowserTest.Proceed/0
+-SafeBrowsingBlockingPageBrowserTestWithThreatTypeAndIsolationSetting/SafeBrowsingBlockingPageBrowserTest.Proceed/1
+-SafeBrowsingBlockingPageBrowserTestWithThreatTypeAndIsolationSetting/SafeBrowsingBlockingPageBrowserTest.Proceed/2
+-SafeBrowsingBlockingPageBrowserTestWithThreatTypeAndIsolationSetting/SafeBrowsingBlockingPageBrowserTest.Proceed/3
+-SafeBrowsingBlockingPageBrowserTestWithThreatTypeAndIsolationSetting/SafeBrowsingBlockingPageBrowserTest.Proceed/4
+-SafeBrowsingBlockingPageBrowserTestWithThreatTypeAndIsolationSetting/SafeBrowsingBlockingPageBrowserTest.Proceed/5
+-SafeBrowsingBlockingPageBrowserTestWithThreatTypeAndIsolationSetting/SafeBrowsingBlockingPageBrowserTest.ProceedDisabled/0
+-SafeBrowsingBlockingPageBrowserTestWithThreatTypeAndIsolationSetting/SafeBrowsingBlockingPageBrowserTest.ProceedDisabled/1
+-SafeBrowsingBlockingPageBrowserTestWithThreatTypeAndIsolationSetting/SafeBrowsingBlockingPageBrowserTest.ProceedDisabled/2
+-SafeBrowsingBlockingPageBrowserTestWithThreatTypeAndIsolationSetting/SafeBrowsingBlockingPageBrowserTest.ProceedDisabled/3
+-SafeBrowsingBlockingPageBrowserTestWithThreatTypeAndIsolationSetting/SafeBrowsingBlockingPageBrowserTest.ProceedDisabled/4
+-SafeBrowsingBlockingPageBrowserTestWithThreatTypeAndIsolationSetting/SafeBrowsingBlockingPageBrowserTest.ProceedDisabled/5
+-SafeBrowsingBlockingPageBrowserTestWithThreatTypeAndIsolationSetting/SafeBrowsingBlockingPageBrowserTest.RedirectCanceled/0
+-SafeBrowsingBlockingPageBrowserTestWithThreatTypeAndIsolationSetting/SafeBrowsingBlockingPageBrowserTest.RedirectCanceled/1
+-SafeBrowsingBlockingPageBrowserTestWithThreatTypeAndIsolationSetting/SafeBrowsingBlockingPageBrowserTest.RedirectCanceled/2
+-SafeBrowsingBlockingPageBrowserTestWithThreatTypeAndIsolationSetting/SafeBrowsingBlockingPageBrowserTest.RedirectCanceled/3
+-SafeBrowsingBlockingPageBrowserTestWithThreatTypeAndIsolationSetting/SafeBrowsingBlockingPageBrowserTest.RedirectCanceled/4
+-SafeBrowsingBlockingPageBrowserTestWithThreatTypeAndIsolationSetting/SafeBrowsingBlockingPageBrowserTest.RedirectCanceled/5
+-SafeBrowsingBlockingPageBrowserTestWithThreatTypeAndIsolationSetting/SafeBrowsingBlockingPageBrowserTest.ReloadWhileInterstitialShowing/0
+-SafeBrowsingBlockingPageBrowserTestWithThreatTypeAndIsolationSetting/SafeBrowsingBlockingPageBrowserTest.ReloadWhileInterstitialShowing/1
+-SafeBrowsingBlockingPageBrowserTestWithThreatTypeAndIsolationSetting/SafeBrowsingBlockingPageBrowserTest.ReloadWhileInterstitialShowing/2
+-SafeBrowsingBlockingPageBrowserTestWithThreatTypeAndIsolationSetting/SafeBrowsingBlockingPageBrowserTest.ReloadWhileInterstitialShowing/3
+-SafeBrowsingBlockingPageBrowserTestWithThreatTypeAndIsolationSetting/SafeBrowsingBlockingPageBrowserTest.ReloadWhileInterstitialShowing/4
+-SafeBrowsingBlockingPageBrowserTestWithThreatTypeAndIsolationSetting/SafeBrowsingBlockingPageBrowserTest.ReloadWhileInterstitialShowing/5
+-SafeBrowsingBlockingPageBrowserTestWithThreatTypeAndIsolationSetting/SafeBrowsingBlockingPageBrowserTest.ReportingDisabledByPolicy/0
+-SafeBrowsingBlockingPageBrowserTestWithThreatTypeAndIsolationSetting/SafeBrowsingBlockingPageBrowserTest.ReportingDisabledByPolicy/1
+-SafeBrowsingBlockingPageBrowserTestWithThreatTypeAndIsolationSetting/SafeBrowsingBlockingPageBrowserTest.ReportingDisabledByPolicy/2
+-SafeBrowsingBlockingPageBrowserTestWithThreatTypeAndIsolationSetting/SafeBrowsingBlockingPageBrowserTest.ReportingDisabledByPolicy/3
+-SafeBrowsingBlockingPageBrowserTestWithThreatTypeAndIsolationSetting/SafeBrowsingBlockingPageBrowserTest.ReportingDisabledByPolicy/4
+-SafeBrowsingBlockingPageBrowserTestWithThreatTypeAndIsolationSetting/SafeBrowsingBlockingPageBrowserTest.ReportingDisabledByPolicy/5
+-SafeBrowsingBlockingPageBrowserTestWithThreatTypeAndIsolationSetting/SafeBrowsingBlockingPageBrowserTest.SecurityStateDowngradedForSubresourceInterstitial/0
+-SafeBrowsingBlockingPageBrowserTestWithThreatTypeAndIsolationSetting/SafeBrowsingBlockingPageBrowserTest.SecurityStateDowngradedForSubresourceInterstitial/1
+-SafeBrowsingBlockingPageBrowserTestWithThreatTypeAndIsolationSetting/SafeBrowsingBlockingPageBrowserTest.SecurityStateDowngradedForSubresourceInterstitial/2
+-SafeBrowsingBlockingPageBrowserTestWithThreatTypeAndIsolationSetting/SafeBrowsingBlockingPageBrowserTest.SecurityStateDowngradedForSubresourceInterstitial/3
+-SafeBrowsingBlockingPageBrowserTestWithThreatTypeAndIsolationSetting/SafeBrowsingBlockingPageBrowserTest.SecurityStateDowngradedForSubresourceInterstitial/4
+-SafeBrowsingBlockingPageBrowserTestWithThreatTypeAndIsolationSetting/SafeBrowsingBlockingPageBrowserTest.SecurityStateDowngradedForSubresourceInterstitial/5
+-SafeBrowsingBlockingPageBrowserTestWithThreatTypeAndIsolationSetting/SafeBrowsingBlockingPageBrowserTest.SecurityStateGoBack/0
+-SafeBrowsingBlockingPageBrowserTestWithThreatTypeAndIsolationSetting/SafeBrowsingBlockingPageBrowserTest.SecurityStateGoBack/1
+-SafeBrowsingBlockingPageBrowserTestWithThreatTypeAndIsolationSetting/SafeBrowsingBlockingPageBrowserTest.SecurityStateGoBack/2
+-SafeBrowsingBlockingPageBrowserTestWithThreatTypeAndIsolationSetting/SafeBrowsingBlockingPageBrowserTest.SecurityStateGoBack/3
+-SafeBrowsingBlockingPageBrowserTestWithThreatTypeAndIsolationSetting/SafeBrowsingBlockingPageBrowserTest.SecurityStateGoBack/4
+-SafeBrowsingBlockingPageBrowserTestWithThreatTypeAndIsolationSetting/SafeBrowsingBlockingPageBrowserTest.SecurityStateGoBack/5
+-SafeBrowsingBlockingPageBrowserTestWithThreatTypeAndIsolationSetting/SafeBrowsingBlockingPageBrowserTest.SecurityState_HTTP/0
+-SafeBrowsingBlockingPageBrowserTestWithThreatTypeAndIsolationSetting/SafeBrowsingBlockingPageBrowserTest.SecurityState_HTTP/1
+-SafeBrowsingBlockingPageBrowserTestWithThreatTypeAndIsolationSetting/SafeBrowsingBlockingPageBrowserTest.SecurityState_HTTP/2
+-SafeBrowsingBlockingPageBrowserTestWithThreatTypeAndIsolationSetting/SafeBrowsingBlockingPageBrowserTest.SecurityState_HTTP/3
+-SafeBrowsingBlockingPageBrowserTestWithThreatTypeAndIsolationSetting/SafeBrowsingBlockingPageBrowserTest.SecurityState_HTTP/4
+-SafeBrowsingBlockingPageBrowserTestWithThreatTypeAndIsolationSetting/SafeBrowsingBlockingPageBrowserTest.SecurityState_HTTP/5
+-SafeBrowsingBlockingPageBrowserTestWithThreatTypeAndIsolationSetting/SafeBrowsingBlockingPageBrowserTest.SecurityState_InvalidHTTPS/0
+-SafeBrowsingBlockingPageBrowserTestWithThreatTypeAndIsolationSetting/SafeBrowsingBlockingPageBrowserTest.SecurityState_InvalidHTTPS/1
+-SafeBrowsingBlockingPageBrowserTestWithThreatTypeAndIsolationSetting/SafeBrowsingBlockingPageBrowserTest.SecurityState_InvalidHTTPS/2
+-SafeBrowsingBlockingPageBrowserTestWithThreatTypeAndIsolationSetting/SafeBrowsingBlockingPageBrowserTest.SecurityState_InvalidHTTPS/3
+-SafeBrowsingBlockingPageBrowserTestWithThreatTypeAndIsolationSetting/SafeBrowsingBlockingPageBrowserTest.SecurityState_InvalidHTTPS/4
+-SafeBrowsingBlockingPageBrowserTestWithThreatTypeAndIsolationSetting/SafeBrowsingBlockingPageBrowserTest.SecurityState_InvalidHTTPS/5
+-SafeBrowsingBlockingPageBrowserTestWithThreatTypeAndIsolationSetting/SafeBrowsingBlockingPageBrowserTest.VerifyHitReportNotSentOnIncognito/0
+-SafeBrowsingBlockingPageBrowserTestWithThreatTypeAndIsolationSetting/SafeBrowsingBlockingPageBrowserTest.VerifyHitReportNotSentOnIncognito/1
+-SafeBrowsingBlockingPageBrowserTestWithThreatTypeAndIsolationSetting/SafeBrowsingBlockingPageBrowserTest.VerifyHitReportNotSentOnIncognito/2
+-SafeBrowsingBlockingPageBrowserTestWithThreatTypeAndIsolationSetting/SafeBrowsingBlockingPageBrowserTest.VerifyHitReportNotSentOnIncognito/3
+-SafeBrowsingBlockingPageBrowserTestWithThreatTypeAndIsolationSetting/SafeBrowsingBlockingPageBrowserTest.VerifyHitReportNotSentOnIncognito/4
+-SafeBrowsingBlockingPageBrowserTestWithThreatTypeAndIsolationSetting/SafeBrowsingBlockingPageBrowserTest.VerifyHitReportNotSentOnIncognito/5
+-SafeBrowsingBlockingPageBrowserTestWithThreatTypeAndIsolationSetting/SafeBrowsingBlockingPageBrowserTest.VerifyHitReportNotSentWithoutSBER/0
+-SafeBrowsingBlockingPageBrowserTestWithThreatTypeAndIsolationSetting/SafeBrowsingBlockingPageBrowserTest.VerifyHitReportNotSentWithoutSBER/1
+-SafeBrowsingBlockingPageBrowserTestWithThreatTypeAndIsolationSetting/SafeBrowsingBlockingPageBrowserTest.VerifyHitReportNotSentWithoutSBER/2
+-SafeBrowsingBlockingPageBrowserTestWithThreatTypeAndIsolationSetting/SafeBrowsingBlockingPageBrowserTest.VerifyHitReportNotSentWithoutSBER/3
+-SafeBrowsingBlockingPageBrowserTestWithThreatTypeAndIsolationSetting/SafeBrowsingBlockingPageBrowserTest.VerifyHitReportNotSentWithoutSBER/4
+-SafeBrowsingBlockingPageBrowserTestWithThreatTypeAndIsolationSetting/SafeBrowsingBlockingPageBrowserTest.VerifyHitReportNotSentWithoutSBER/5
+-SafeBrowsingBlockingPageBrowserTestWithThreatTypeAndIsolationSetting/SafeBrowsingBlockingPageBrowserTest.VerifyHitReportSentOnSBERAndNotIncognito/0
+-SafeBrowsingBlockingPageBrowserTestWithThreatTypeAndIsolationSetting/SafeBrowsingBlockingPageBrowserTest.VerifyHitReportSentOnSBERAndNotIncognito/1
+-SafeBrowsingBlockingPageBrowserTestWithThreatTypeAndIsolationSetting/SafeBrowsingBlockingPageBrowserTest.VerifyHitReportSentOnSBERAndNotIncognito/2
+-SafeBrowsingBlockingPageBrowserTestWithThreatTypeAndIsolationSetting/SafeBrowsingBlockingPageBrowserTest.VerifyHitReportSentOnSBERAndNotIncognito/3
+-SafeBrowsingBlockingPageBrowserTestWithThreatTypeAndIsolationSetting/SafeBrowsingBlockingPageBrowserTest.VerifyHitReportSentOnSBERAndNotIncognito/4
+-SafeBrowsingBlockingPageBrowserTestWithThreatTypeAndIsolationSetting/SafeBrowsingBlockingPageBrowserTest.VerifyHitReportSentOnSBERAndNotIncognito/5
+-SafeBrowsingBlockingPageBrowserTestWithThreatTypeAndIsolationSetting/SafeBrowsingBlockingPageBrowserTest.VisitWhitePaper/0
+-SafeBrowsingBlockingPageBrowserTestWithThreatTypeAndIsolationSetting/SafeBrowsingBlockingPageBrowserTest.VisitWhitePaper/1
+-SafeBrowsingBlockingPageBrowserTestWithThreatTypeAndIsolationSetting/SafeBrowsingBlockingPageBrowserTest.VisitWhitePaper/2
+-SafeBrowsingBlockingPageBrowserTestWithThreatTypeAndIsolationSetting/SafeBrowsingBlockingPageBrowserTest.VisitWhitePaper/3
+-SafeBrowsingBlockingPageBrowserTestWithThreatTypeAndIsolationSetting/SafeBrowsingBlockingPageBrowserTest.VisitWhitePaper/4
+-SafeBrowsingBlockingPageBrowserTestWithThreatTypeAndIsolationSetting/SafeBrowsingBlockingPageBrowserTest.VisitWhitePaper/5
+-SafeBrowsingBlockingPageBrowserTestWithThreatTypeAndIsolationSetting/SafeBrowsingBlockingPageBrowserTest.WhitelistIframeRevisit/0
+-SafeBrowsingBlockingPageBrowserTestWithThreatTypeAndIsolationSetting/SafeBrowsingBlockingPageBrowserTest.WhitelistIframeRevisit/1
+-SafeBrowsingBlockingPageBrowserTestWithThreatTypeAndIsolationSetting/SafeBrowsingBlockingPageBrowserTest.WhitelistIframeRevisit/2
+-SafeBrowsingBlockingPageBrowserTestWithThreatTypeAndIsolationSetting/SafeBrowsingBlockingPageBrowserTest.WhitelistIframeRevisit/3
+-SafeBrowsingBlockingPageBrowserTestWithThreatTypeAndIsolationSetting/SafeBrowsingBlockingPageBrowserTest.WhitelistIframeRevisit/4
+-SafeBrowsingBlockingPageBrowserTestWithThreatTypeAndIsolationSetting/SafeBrowsingBlockingPageBrowserTest.WhitelistIframeRevisit/5
+-SafeBrowsingBlockingPageBrowserTestWithThreatTypeAndIsolationSetting/SafeBrowsingBlockingPageBrowserTest.WhitelistRevisit/0
+-SafeBrowsingBlockingPageBrowserTestWithThreatTypeAndIsolationSetting/SafeBrowsingBlockingPageBrowserTest.WhitelistRevisit/1
+-SafeBrowsingBlockingPageBrowserTestWithThreatTypeAndIsolationSetting/SafeBrowsingBlockingPageBrowserTest.WhitelistRevisit/2
+-SafeBrowsingBlockingPageBrowserTestWithThreatTypeAndIsolationSetting/SafeBrowsingBlockingPageBrowserTest.WhitelistRevisit/3
+-SafeBrowsingBlockingPageBrowserTestWithThreatTypeAndIsolationSetting/SafeBrowsingBlockingPageBrowserTest.WhitelistRevisit/4
+-SafeBrowsingBlockingPageBrowserTestWithThreatTypeAndIsolationSetting/SafeBrowsingBlockingPageBrowserTest.WhitelistRevisit/5
+-SafeBrowsingBlockingPageBrowserTestWithThreatTypeAndIsolationSetting/SafeBrowsingBlockingPageBrowserTest.WhitelistUnsaved/0
+-SafeBrowsingBlockingPageBrowserTestWithThreatTypeAndIsolationSetting/SafeBrowsingBlockingPageBrowserTest.WhitelistUnsaved/1
+-SafeBrowsingBlockingPageBrowserTestWithThreatTypeAndIsolationSetting/SafeBrowsingBlockingPageBrowserTest.WhitelistUnsaved/2
+-SafeBrowsingBlockingPageBrowserTestWithThreatTypeAndIsolationSetting/SafeBrowsingBlockingPageBrowserTest.WhitelistUnsaved/3
+-SafeBrowsingBlockingPageBrowserTestWithThreatTypeAndIsolationSetting/SafeBrowsingBlockingPageBrowserTest.WhitelistUnsaved/4
+-SafeBrowsingBlockingPageBrowserTestWithThreatTypeAndIsolationSetting/SafeBrowsingBlockingPageBrowserTest.WhitelistUnsaved/5
 -SafeBrowsingRedirectTracking/WebstoreInlineInstallerRedirectTest.IncludesRedirectData/0
 -SafeBrowsingTriggeredPopupBlockerBrowserTest.NoFeature_AllowCreatingNewWindows
 -SafeBrowsingTriggeredPopupBlockerBrowserTest.NoFeature_NoMessages
@@ -1364,6 +1639,8 @@
 -WebSocketBrowserTest.ReuseMainPageBasicAuthCredentialsForWebSocket
 -WebViewScrollBubbling/WebViewGuestScrollTouchTest.TestGuestGestureScrollsBubble/0
 -WebViewScrollBubbling/WebViewGuestScrollTouchTest.TestGuestGestureScrollsBubble/1
+-WebViewScrollBubbling/WebViewGuestScrollTouchTest.TestGuestGestureScrollsBubble/2
+-WebViewScrollBubbling/WebViewGuestScrollTouchTest.TestGuestGestureScrollsBubble/3
 -WebViewScrollGuestContent/WebViewScrollGuestContentTest.OverscrollControllerSeesConsumedScrollsInGuest/0
 -WebViewTests/IsolatedOriginWebViewTest.IsolatedOriginInWebview/0
 -WebViewTests/IsolatedOriginWebViewTest.IsolatedOriginInWebview/1
@@ -1393,6 +1670,8 @@
 -WebViewTests/WebViewNewWindowTest.Shim_TestNewWindowNoReferrerLink/1
 -WebViewTests/WebViewNewWindowTest.Shim_TestNewWindowTwoListeners/0
 -WebViewTests/WebViewNewWindowTest.Shim_TestNewWindowTwoListeners/1
+-WebViewTests/WebViewNewWindowTest.Shim_TestWebViewAndEmbedderInNewWindow/0
+-WebViewTests/WebViewNewWindowTest.Shim_TestWebViewAndEmbedderInNewWindow/1
 -WebViewTests/WebViewNewWindowTest.UserAgent_NewWindow/0
 -WebViewTests/WebViewNewWindowTest.UserAgent_NewWindow/1
 -WebViewTests/WebViewPluginTest.TestLoadPluginEvent/0
@@ -1521,8 +1800,14 @@
 -WebViewTests/WebViewTest.GeolocationAPIEmbedderHasNoAccessDeny/1
 -WebViewTests/WebViewTest.IndexedDBIsolation/0
 -WebViewTests/WebViewTest.IndexedDBIsolation/1
+-WebViewTests/WebViewTest.InterstitialPage/0
+-WebViewTests/WebViewTest.InterstitialPage/1
 -WebViewTests/WebViewTest.InterstitialPageDetach/0
 -WebViewTests/WebViewTest.InterstitialPageDetach/1
+-WebViewTests/WebViewTest.InterstitialPageFocusedWidget/0
+-WebViewTests/WebViewTest.InterstitialPageFocusedWidget/1
+-WebViewTests/WebViewTest.InterstitialPageRouteEvents/0
+-WebViewTests/WebViewTest.InterstitialPageRouteEvents/1
 -WebViewTests/WebViewTest.InterstitialTeardown/0
 -WebViewTests/WebViewTest.InterstitialTeardown/1
 -WebViewTests/WebViewTest.LoadWebviewAccessibleResource/0
@@ -1563,6 +1848,8 @@
 -WebViewTests/WebViewTest.OpenURLFromTab_CurrentTab_Abort/1
 -WebViewTests/WebViewTest.OpenURLFromTab_CurrentTab_Succeed/0
 -WebViewTests/WebViewTest.OpenURLFromTab_CurrentTab_Succeed/1
+-WebViewTests/WebViewTest.ReloadAfterCrash/0
+-WebViewTests/WebViewTest.ReloadAfterCrash/1
 -WebViewTests/WebViewTest.ReloadEmbedder/0
 -WebViewTests/WebViewTest.ReloadEmbedder/1
 -WebViewTests/WebViewTest.ReloadWebviewAccessibleResource/0
@@ -2453,12 +2740,6 @@
 -SSLUIWorkerFetchTest.MixedContentSettingsWithBlockingCSP/1
 -SSLUIWorkerFetchTest.MixedContentSubFrame/0
 -SSLUIWorkerFetchTest.MixedContentSubFrame/1
--SavePageAsMHTMLBrowserTest.SavePageAsMHTML
--SavePageBrowserTest.DangerousSubresources
--SavePageBrowserTest.FileNameFromPageTitle
--SavePageBrowserTest.SaveCompleteHTML
--SavePageBrowserTest.SaveDownloadableIFrame
--SavePageBrowserTest.SaveUnauthorizedResource
 -UnloadTest.CrossSiteInfiniteBeforeUnloadAsync
 -UnloadTest.CrossSiteInfiniteUnloadAsync
 -UnloadTest.CrossSiteInfiniteUnloadSync
@@ -2483,3 +2764,81 @@
 -PolicyTest.FileURLBlacklist
 -PolicyTest.URLBlacklist
 -PolicyTest.URLBlacklistSubresources
+
+# crbug.com/751738 Service worker subresource loader doesn't yet support request bodies.
+# crbug.com/778821 Null response body is given to NavigationURLLoaderDelegate::OnResponseStarted() as parameter.
+-WebRtcBrowserTest.RunsAudioVideoWebRTCCallInTwoTabsVP8
+-WebRtcBrowserTest.RunsAudioVideoWebRTCCallInTwoTabsVP9
+-WebrtcEventLogApiTest.TestStartStopWebRtcEventLogging
+-WebrtcEventLogApiTest.TestStartTimedWebRtcEventLogging
+
+# crbug.com/778814 Null NavigationData is given to NavigationURLLoaderDelegate::OnResponseStarted() as parameter.
+-ChromeResourceDispatcherHostDelegateBrowserTest.NavigationDataProcessed
+
+# crbug.com/778842 CHECK_EQ(num_bytes, output_size) failed in ReadData() at web_ui_url_loader_factory.cc.
+-DevToolsReattachAfterCrashTest.TestReattachAfterCrashOnNetwork
+-DevToolsReattachAfterCrashTest.TestReattachAfterCrashOnTimeline
+
+# crbug.com/778846 DCHECK() failed at URLDataManagerBackend::CheckURLIsValid().
+-CrSettingsPeoplePageTest.All
+-DomDistillerTabUtilsBrowserTest.TestDistillIntoWebContents
+-DomDistillerViewerSourceBrowserTest.DistillerJavaScriptExposed
+-DomDistillerViewerSourceBrowserTest.DistillerJavaScriptNotInMainWorld
+-DomDistillerViewerSourceBrowserTest.EarlyTemplateLoad
+-DomDistillerViewerSourceBrowserTest.MultiPageArticle
+-DomDistillerViewerSourceBrowserTest.NoWebUIBindingsArticleExists
+-DomDistillerViewerSourceBrowserTest.NoWebUIBindingsArticleNotFound
+-DomDistillerViewerSourceBrowserTest.PrefPersist
+-PrintPreviewDialogControllerBrowserTest.PdfPluginDisabled
+-PrintPreviewDialogControllerBrowserTest.PrintPreviewPdfAccessibility
+
+# crbug.com/778860 SecurityStyleExplanations::info_explanations is empty.
+-BrowserTestNonsecureURLRequest.DidChangeVisibleSecurityStateObserverObsoleteTLSSettings
+
+# crbug.com/778862 The URL of the extension to navigate to contains non utf-8 character.
+-ChromeSitePerProcessPDFTest.EmbeddedPDFInsideCrossOriginFrame
+-PDFExtensionTest.EnsureCrossOriginRepliesBlocked
+-PDFExtensionTest.PostMessageForZeroSizedEmbed
+-PDFExtensionTest.TabTitleWithEmbeddedPdf
+-SaveType/SavePageOriginalVsSavedComparisonTest.ObjectElementsViaFile/0
+-SaveType/SavePageOriginalVsSavedComparisonTest.ObjectElementsViaHttp/0
+
+# crbug.com/779115 The |devtools_extension_panel_rfh| is nullptr.
+-DevToolsExtensionTest.HttpIframeInDevToolsExtensionPanel
+
+# crbug.com/779121 The |url_chain_| contains one empty string at DownloadUrlSBClient::StartCheck().
+-DownloadTest.SaveLinkAsReferrerPolicyOrigin
+
+# crbug.com/779153 DCHECK(browser->IsActive()) fails at GetAppMenuButton().
+-IncognitoWindowTrackerBrowserTest.ShowPromo
+
+# crbug.com/779160 BrowserView::GetBrowserViewForBrowser(browser())->tabstrip()->new_tab_button()->new_tab_promo() is nullptr.
+-NewTabTrackerBrowserTest.TestShowPromo
+
+# crbug.com/779178 The |interstitial_page| is nullptr.
+-SSLUITest.TestInterstitialJavaScriptGoesBack
+-SSLUITest.TestInterstitialJavaScriptProceeds
+-SSLUITestWithExtendedReporting.TestBadClockReportingWithNoOptIn
+-SSLUITestWithExtendedReporting.TestBadClockReportingWithOptIn
+
+# crbug.com/779181 The |ip_map->at(test_server_host)| is empty.
+-SBNavigationObserverBrowserTest.AddIPMapping
+
+# crbug.com/779197 The |state_| is actualy CANCELLED_INTERNAL.
+-SBNavigationObserverBrowserTest.DownloadViaHTML5FileApiWithUserGesture
+-SBNavigationObserverBrowserTest.DownloadViaHTML5FileApiWithoutUserGesture
+
+# crbug.com/779210 NOTREACHED() reached at SaveFileManager::OnSaveURL().
+-SavePageBrowserTest.SavePageBrowserTest_NonMHTML
+
+# crbug.com/779215 The extension hasn't been installed when the test runs.
+-WebstoreInlineInstallerListenerTest.BothListenersTest
+
+# crbug.com/779217 The NetworkContext is not created when the network service is enabled.
+-HotwordInstallerBrowserTest.AbortInstallOnShutdown
+-SpellingMenuObserverTest.SuggestionsForceTopSeparator
+
+# crbug.com/779236 DCHECK(!params->url.is_empty()) fails at chrome::Navigate().
+-ReferrerPolicyTest.ContextMenuRedirect
+-ReferrerPolicyTest.HttpsContextMenuOrigin
+-ReferrerPolicyTest.HttpsContextMenuRedirect
diff --git a/testing/buildbot/gn_isolate_map.pyl b/testing/buildbot/gn_isolate_map.pyl
index d0f310eb..cd0426c0 100644
--- a/testing/buildbot/gn_isolate_map.pyl
+++ b/testing/buildbot/gn_isolate_map.pyl
@@ -236,6 +236,10 @@
     "label": "//chromecast/graphics:cast_graphics_unittests",
     "type": "console_test_launcher",
   },
+  "cast_junit_test_lists": {
+    "label": "//chromecast:cast_junit_test_lists",
+    "type": "additional_compile_target",
+  },
   "cast_media_unittests": {
     "label": "//chromecast/media:cast_media_unittests",
     "type": "console_test_launcher",
@@ -256,6 +260,10 @@
     "label": "//chromecast:cast_shell_unittests",
     "type": "console_test_launcher",
   },
+  "cast_test_lists": {
+    "label": "//chromecast:cast_test_lists",
+    "type": "additional_compile_target",
+  },
   "cast_unittests": {
     "label": "//media/cast:cast_unittests",
     "type": "windowed_test_launcher",
@@ -380,6 +388,10 @@
     "label": "//content/public/android:content_junit_tests",
     "type": "junit_test",
   },
+  "content_shell": {
+    "label": "//content/shell:content_shell",
+    "type": "raw",
+  },
   "content_shell_crash_test": {
     "label": "//content/shell:content_shell_crash_test",
     "type": "script",
diff --git a/testing/libfuzzer/fuzzers/BUILD.gn b/testing/libfuzzer/fuzzers/BUILD.gn
index 922a4f56..4c8b7907 100644
--- a/testing/libfuzzer/fuzzers/BUILD.gn
+++ b/testing/libfuzzer/fuzzers/BUILD.gn
@@ -5,7 +5,6 @@
 # Individual libfuzzer tests that didn't find their home yet.
 
 import("//build/config/features.gni")
-import("//media/media_options.gni")
 import("//testing/libfuzzer/fuzzer_test.gni")
 import("//third_party/protobuf/proto_library.gni")
 
@@ -41,52 +40,6 @@
   ]
 }
 
-if (proprietary_codecs) {
-  fuzzer_test("mp4_box_reader_fuzzer") {
-    sources = [
-      "mp4_box_reader_fuzzer.cc",
-    ]
-    deps = [
-      "//base",
-      "//media",
-    ]
-    libfuzzer_options = [ "max_len=500" ]
-    dict = "dicts/mp4.dict"
-  }
-}
-
-if (enable_mse_mpeg2ts_stream_parser) {
-  fuzzer_test("es_parser_adts_fuzzer") {
-    sources = [
-      "es_parser_adts_fuzzer.cc",
-    ]
-    deps = [
-      "//base",
-      "//media",
-    ]
-  }
-
-  fuzzer_test("es_parser_h264_fuzzer") {
-    sources = [
-      "es_parser_h264_fuzzer.cc",
-    ]
-    deps = [
-      "//base",
-      "//media",
-    ]
-  }
-
-  fuzzer_test("es_parser_mpeg1audio_fuzzer") {
-    sources = [
-      "es_parser_mpeg1audio_fuzzer.cc",
-    ]
-    deps = [
-      "//base",
-      "//media",
-    ]
-  }
-}
-
 fuzzer_test("snappy_fuzzer") {
   sources = [
     "snappy_fuzzer.cc",
@@ -464,6 +417,13 @@
   libfuzzer_options = [ "max_len=1000" ]
 }
 
+fuzzer_test("swiftshader_vertex_routine_fuzzer") {
+  sources = []
+  deps = [
+    "//third_party/swiftshader:vertex_routine_fuzzer",
+  ]
+}
+
 fuzzer_test("sha1_fuzzer") {
   sources = [
     "sha1_fuzzer.cc",
diff --git a/testing/libfuzzer/fuzzers/es_parser_mpeg1audio_fuzzer.cc b/testing/libfuzzer/fuzzers/es_parser_mpeg1audio_fuzzer.cc
deleted file mode 100644
index 6afacd2..0000000
--- a/testing/libfuzzer/fuzzers/es_parser_mpeg1audio_fuzzer.cc
+++ /dev/null
@@ -1,37 +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 <stddef.h>
-#include <stdint.h>
-
-#include <memory>
-
-#include "base/bind.h"
-#include "media/formats/mp2t/es_parser_mpeg1audio.h"
-
-class NullMediaLog : public media::MediaLog {
- public:
-  NullMediaLog() {}
-  ~NullMediaLog() override {}
-
-  void AddEvent(std::unique_ptr<media::MediaLogEvent> event) override {}
-
- private:
-  DISALLOW_COPY_AND_ASSIGN(NullMediaLog);
-};
-
-static void NewAudioConfig(const media::AudioDecoderConfig& config) {}
-static void EmitBuffer(scoped_refptr<media::StreamParserBuffer> buffer) {}
-
-// Entry point for LibFuzzer.
-extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
-  NullMediaLog media_log;
-  media::mp2t::EsParserMpeg1Audio es_parser(
-      base::Bind(&NewAudioConfig), base::Bind(&EmitBuffer), &media_log);
-  if (es_parser.Parse(data, size, media::kNoTimestamp,
-                      media::kNoDecodeTimestamp())) {
-    es_parser.Flush();
-  }
-  return 0;
-}
diff --git a/testing/libfuzzer/fuzzers/mp4_box_reader_fuzzer.cc b/testing/libfuzzer/fuzzers/mp4_box_reader_fuzzer.cc
deleted file mode 100644
index ff6f5791..0000000
--- a/testing/libfuzzer/fuzzers/mp4_box_reader_fuzzer.cc
+++ /dev/null
@@ -1,32 +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 <stddef.h>
-#include <stdint.h>
-
-#include <memory>
-
-#include "base/logging.h"
-#include "media/formats/mp4/box_reader.h"
-
-class NullMediaLog : public media::MediaLog {
- public:
-  NullMediaLog() {}
-  ~NullMediaLog() override {}
-
-  void AddEvent(std::unique_ptr<media::MediaLogEvent> event) override {}
-
- private:
-  DISALLOW_COPY_AND_ASSIGN(NullMediaLog);
-};
-
-// Entry point for LibFuzzer.
-extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
-  bool err;
-  NullMediaLog media_log;
-  std::unique_ptr<media::mp4::BoxReader> reader(
-      media::mp4::BoxReader::ReadTopLevelBox(data, static_cast<int>(size),
-                                             &media_log, &err));
-  return !err && reader && reader->ScanChildren() ? 0 : 0;
-}
diff --git a/testing/variations/fieldtrial_testing_config.json b/testing/variations/fieldtrial_testing_config.json
index f2e1553..9b9e982 100644
--- a/testing/variations/fieldtrial_testing_config.json
+++ b/testing/variations/fieldtrial_testing_config.json
@@ -2902,6 +2902,25 @@
             ]
         }
     ],
+    "S13nSafeBrowsingParallelUrlCheck": [
+        {
+            "platforms": [
+                "android",
+                "chromeos",
+                "linux",
+                "mac",
+                "win"
+            ],
+            "experiments": [
+                {
+                    "name": "CanaryDev_Enabled",
+                    "enable_features": [
+                        "S13nSafeBrowsingParallelUrlCheck"
+                    ]
+                }
+            ]
+        }
+    ],
     "SRTExperimentalEngineTrial": [
         {
             "platforms": [
@@ -3754,6 +3773,25 @@
             ]
         }
     ],
+    "UseMojoAudioOutputStreamFactory": [
+        {
+            "platforms": [
+                "android",
+                "chromeos",
+                "linux",
+                "mac",
+                "win"
+            ],
+            "experiments": [
+                {
+                    "name": "UseMojoAudioOutputStreamFactory",
+                    "enable_features": [
+                        "UseMojoAudioOutputStreamFactory"
+                    ]
+                }
+            ]
+        }
+    ],
     "V8AsmJSToWasm": [
         {
             "platforms": [
diff --git a/third_party/.gitignore b/third_party/.gitignore
index a4b0795d..777630b 100644
--- a/third_party/.gitignore
+++ b/third_party/.gitignore
@@ -98,6 +98,7 @@
 /leakcanary/src
 /leveldatabase/src
 /leveldb
+/libaom/source/libaom
 /libc++-static/libc++.a
 /libaddressinput/src
 /libdrm/src
diff --git a/third_party/WebKit/LayoutTests/FlagExpectations/enable-blink-features=LayoutNG b/third_party/WebKit/LayoutTests/FlagExpectations/enable-blink-features=LayoutNG
index 1dc261b..ba740c67 100644
--- a/third_party/WebKit/LayoutTests/FlagExpectations/enable-blink-features=LayoutNG
+++ b/third_party/WebKit/LayoutTests/FlagExpectations/enable-blink-features=LayoutNG
@@ -1986,7 +1986,7 @@
 crbug.com/591099 css3/selectors3/xml/css3-modsel-d4.xml [ Failure Pass ]
 crbug.com/591099 cssom/cssvalue-comparison.html [ Failure ]
 crbug.com/591099 editing/assert_selection.html [ Crash Failure ]
-crbug.com/591099 editing/caret/caret-color-001.html [ Failure ]
+crbug.com/591099 editing/caret/caret-color-001.html [ Crash Failure Timeout ]
 crbug.com/591099 editing/caret/caret-color-002.html [ Failure ]
 crbug.com/591099 editing/caret/caret-color-003.html [ Failure ]
 crbug.com/591099 editing/caret/caret-color-004.html [ Failure ]
@@ -2019,7 +2019,7 @@
 crbug.com/591099 editing/deleting/delete-contiguous-ws-001.html [ Crash Failure ]
 crbug.com/591099 editing/deleting/delete-empty-table.html [ Failure ]
 crbug.com/591099 editing/deleting/delete-first-list-item.html [ Failure Pass ]
-crbug.com/591099 editing/deleting/delete-leading-ws-001.html [ Failure ]
+crbug.com/591099 editing/deleting/delete-leading-ws-001.html [ Crash Failure ]
 crbug.com/591099 editing/deleting/delete-line-001.html [ Failure ]
 crbug.com/591099 editing/deleting/delete-line-002.html [ Failure ]
 crbug.com/591099 editing/deleting/delete-line-004.html [ Failure ]
@@ -5398,6 +5398,7 @@
 crbug.com/591099 compositing/will-change/will-change-preserve-backface-visibility.html [ Crash ]
 crbug.com/591099 compositing/z-order/collect-layers-does-not-initialize-pos-z-order-list.html [ Crash ]
 crbug.com/591099 css3/flexbox/flexitem-stretch-range.html [ Crash ]
+crbug.com/591099 editing/caret/caret-painting-low-dpi.html [ Failure ]
 crbug.com/591099 editing/execCommand/insert_list/insert_list_in_summary_crash.html [ Crash ]
 crbug.com/591099 editing/execCommand/query-text-alignment.html [ Pass Timeout ]
 crbug.com/591099 editing/execCommand/remove-format-elements.html [ Crash ]
@@ -6310,6 +6311,7 @@
 crbug.com/591099 fragmentation/change-fragmentainer-height-line-float.html [ Failure Pass ]
 crbug.com/591099 fragmentation/class-c-break-after-clearance.html [ Failure Timeout ]
 crbug.com/591099 fragmentation/collapsing-class-a-breakpoints.html [ Failure ]
+crbug.com/591099 fragmentation/column-fill-auto-child.html [ Failure ]
 crbug.com/591099 fragmentation/first-child-large-top-margin.html [ Crash ]
 crbug.com/591099 fragmentation/float-after-forced-break.html [ Failure ]
 crbug.com/591099 fragmentation/float-margin-top.html [ Failure Pass ]
@@ -6660,7 +6662,7 @@
 crbug.com/591099 http/tests/devtools/elements/styles-2/force-pseudo-state.html [ Crash ]
 crbug.com/591099 http/tests/devtools/elements/styles-2/get-set-stylesheet-text.js [ Crash Pass Timeout ]
 crbug.com/591099 http/tests/devtools/elements/styles-2/import-pseudoclass-crash.js [ Crash Pass Timeout ]
-crbug.com/591099 http/tests/devtools/elements/styles-2/inject-stylesheet.js [ Crash ]
+crbug.com/591099 http/tests/devtools/elements/styles-2/inject-stylesheet.js [ Crash Timeout ]
 crbug.com/591099 http/tests/devtools/elements/styles-2/media-emulation.js [ Crash ]
 crbug.com/591099 http/tests/devtools/elements/styles-2/multiple-imports-edit-crash.html [ Crash ]
 crbug.com/591099 http/tests/devtools/elements/styles-2/page-reload-update-sidebar.js [ Crash Timeout ]
@@ -6669,7 +6671,7 @@
 crbug.com/591099 http/tests/devtools/elements/styles-2/perform-undo-perform-of-mergable-action.js [ Crash Timeout ]
 crbug.com/591099 http/tests/devtools/elements/styles-2/pseudo-elements.html [ Crash Pass Timeout ]
 crbug.com/591099 http/tests/devtools/elements/styles-3/computed-properties-retain-expanded.js [ Crash ]
-crbug.com/591099 http/tests/devtools/elements/styles-3/remove-shadow-host.js [ Crash ]
+crbug.com/591099 http/tests/devtools/elements/styles-3/remove-shadow-host.js [ Crash Timeout ]
 crbug.com/591099 http/tests/devtools/elements/styles-3/simple-selector.js [ Crash Pass ]
 crbug.com/591099 http/tests/devtools/elements/styles-3/style-autocomplete.js [ Crash Failure Pass ]
 crbug.com/591099 http/tests/devtools/elements/styles-3/style-rule-from-imported-stylesheet.html [ Crash Failure ]
@@ -6685,7 +6687,7 @@
 crbug.com/591099 http/tests/devtools/elements/styles-3/styles-computed-trace.js [ Crash ]
 crbug.com/591099 http/tests/devtools/elements/styles-3/styles-disable-inherited.js [ Crash Failure Pass ]
 crbug.com/591099 http/tests/devtools/elements/styles-3/styles-disable-property-after-selector-edit.js [ Crash ]
-crbug.com/591099 http/tests/devtools/elements/styles-3/styles-disable-then-change.js [ Crash ]
+crbug.com/591099 http/tests/devtools/elements/styles-3/styles-disable-then-change.js [ Crash Timeout ]
 crbug.com/591099 http/tests/devtools/elements/styles-3/styles-disable-then-delete.js [ Crash ]
 crbug.com/591099 http/tests/devtools/elements/styles-3/styles-disable-then-enable-overriden-ua.html [ Crash ]
 crbug.com/591099 http/tests/devtools/elements/styles-3/styles-disable-then-enable.js [ Crash ]
@@ -6696,7 +6698,7 @@
 crbug.com/591099 http/tests/devtools/elements/styles-4/style-update-during-selector-edit.js [ Crash Failure Pass ]
 crbug.com/591099 http/tests/devtools/elements/styles-4/styles-do-not-detach-sourcemap-on-edits.js [ Crash Timeout ]
 crbug.com/591099 http/tests/devtools/elements/styles-4/styles-edit-property-after-invalid-rule.js [ Crash ]
-crbug.com/591099 http/tests/devtools/elements/styles-4/styles-formatting.js [ Crash ]
+crbug.com/591099 http/tests/devtools/elements/styles-4/styles-formatting.js [ Crash Timeout ]
 crbug.com/591099 http/tests/devtools/elements/styles-4/styles-history.js [ Crash ]
 crbug.com/591099 http/tests/devtools/elements/styles-4/styles-iframe.js [ Crash ]
 crbug.com/591099 http/tests/devtools/elements/styles-4/styles-inline-element-style-changes-should-not-force-style-recalc.js [ Crash Failure Pass ]
@@ -7097,7 +7099,7 @@
 crbug.com/591099 images/zoomed-img-size.html [ Crash Failure ]
 crbug.com/591099 inspector-protocol/accessibility/accessibility-ignoredNodes.js [ Crash Failure Timeout ]
 crbug.com/591099 inspector-protocol/accessibility/accessibility-modal.js [ Crash ]
-crbug.com/591099 inspector-protocol/accessibility/accessibility-nameSources-img-figure.js [ Crash Failure Timeout ]
+crbug.com/591099 inspector-protocol/accessibility/accessibility-nameSources-img-figure.js [ Crash Failure Pass Timeout ]
 crbug.com/591099 inspector-protocol/accessibility/accessibility-nameSources-input-buttons.js [ Crash Timeout ]
 crbug.com/591099 inspector-protocol/accessibility/accessibility-nameSources-input.js [ Crash Failure Timeout ]
 crbug.com/591099 inspector-protocol/accessibility/accessibility-nameSources-labelledby.js [ Crash Failure Timeout ]
diff --git a/third_party/WebKit/LayoutTests/FlagExpectations/enable-slimming-paint-v2 b/third_party/WebKit/LayoutTests/FlagExpectations/enable-slimming-paint-v2
index 375749b..5fc0ce6f 100644
--- a/third_party/WebKit/LayoutTests/FlagExpectations/enable-slimming-paint-v2
+++ b/third_party/WebKit/LayoutTests/FlagExpectations/enable-slimming-paint-v2
@@ -1793,3 +1793,8 @@
 Bug(none) fast/multicol/newmulticol/clipping-top-overflow.html [ Failure ]
 Bug(none) fast/multicol/overflow-content.html [ Failure ]
 Bug(none) fast/multicol/scale-transform-text.html [ Failure ]
+
+Bug(none) compositing/rendering-contexts.html [ Failure ]
+
+Bug(none) paint/invalidation/filters/effect-reference-repaint-primitive-attr-mutation.html [ Failure ]
+Bug(none) compositing/overflow-trumps-transform-style.html [ Failure ]
diff --git a/third_party/WebKit/LayoutTests/FlagExpectations/isolate-extensions b/third_party/WebKit/LayoutTests/FlagExpectations/isolate-extensions
deleted file mode 100644
index c4ee30e6..0000000
--- a/third_party/WebKit/LayoutTests/FlagExpectations/isolate-extensions
+++ /dev/null
@@ -1 +0,0 @@
-# Any tests below fail when they run with --isolate-sites-for-testing=*.is
diff --git a/third_party/WebKit/LayoutTests/FlagExpectations/root-layer-scrolls b/third_party/WebKit/LayoutTests/FlagExpectations/root-layer-scrolls
index 82af898c..c4d909f 100644
--- a/third_party/WebKit/LayoutTests/FlagExpectations/root-layer-scrolls
+++ b/third_party/WebKit/LayoutTests/FlagExpectations/root-layer-scrolls
@@ -30,9 +30,6 @@
 crbug.com/417782 compositing/squashing/squash-above-fixed-3.html [ Failure ]
 crbug.com/417782 compositing/squashing/squashing-print.html [ Failure ]
 crbug.com/417782 compositing/visibility/visibility-image-layers-dynamic.html [ Failure ]
-crbug.com/417782 css3/filters/composited-layer-child-bounds-after-composited-to-sw-shadow-change.html [ Failure ]
-crbug.com/417782 css3/filters/composited-layer-promotion-after-outset-overlap-change-using-composited-shadow.html [ Failure ]
-crbug.com/417782 css3/filters/composited-layer-promotion-after-outset-overlap-change-using-sw-shadow.html [ Failure ]
 crbug.com/417782 css3/filters/nested-filter.html [ Failure ]
 crbug.com/417782 editing/input/scroll-viewport-page-up-down.html [ Failure ]
 crbug.com/417782 external/wpt/css/css-position-3/position-sticky-root-scroller.html [ Failure ]
@@ -54,11 +51,6 @@
 crbug.com/417782 fast/events/pointerevents/pointer-event-mouse-coords-in-zoom-and-scroll.html [ Failure ]
 crbug.com/417782 fast/events/pointerevents/pointer-event-pen-coords-in-zoom-and-scroll.html [ Failure Timeout ]
 crbug.com/417782 fast/events/scale-and-scroll-iframe-window.html [ Failure ]
-crbug.com/417782 fast/events/touch/compositor-touch-hit-rects-animation.html [ Failure ]
-crbug.com/417782 fast/events/touch/compositor-touch-hit-rects-global.html [ Failure ]
-crbug.com/417782 fast/events/touch/compositor-touch-hit-rects-non-composited-scroll.html [ Failure ]
-crbug.com/417782 fast/events/touch/compositor-touch-hit-rects-transform-changed-nolayout.html [ Failure ]
-crbug.com/417782 fast/events/touch/compositor-touch-hit-rects.html [ Failure ]
 crbug.com/417782 fast/events/touch/gesture/gesture-tap-frame-scrolled.html [ Failure ]
 crbug.com/417782 fast/events/touch/gesture/gesture-tap-scrolled.html [ Failure ]
 crbug.com/417782 fast/events/touch/touch-coords-in-zoom-and-scroll.html [ Failure ]
@@ -106,108 +98,20 @@
 crbug.com/417782 inspector-protocol/dom-snapshot/dom-snapshot-getSnapshot.js [ Failure ]
 crbug.com/417782 inspector-protocol/layers/paint-profiler.js [ Crash ]
 crbug.com/417782 inspector-protocol/page/get-layout-metrics.js [ Failure ]
-crbug.com/417782 paint/invalidation/absolute-position-change-containing-block.html [ Failure ]
-crbug.com/417782 paint/invalidation/absolute-position-moved.html [ Failure ]
-crbug.com/417782 paint/invalidation/abspos-shift-image-incorrect-repaint.html [ Failure ]
-crbug.com/417782 paint/invalidation/background-image-paint-invalidation-large-abspos-div.html [ Failure ]
-crbug.com/417782 paint/invalidation/background-misaligned.html [ Failure ]
-crbug.com/417782 paint/invalidation/background-resize-height.html [ Failure ]
-crbug.com/417782 paint/invalidation/backgroundSizeRepaint.html [ Failure ]
-crbug.com/417782 paint/invalidation/body-background-image.html [ Failure ]
-crbug.com/417782 paint/invalidation/border-image-outset-add-repaint.html [ Failure ]
-crbug.com/417782 paint/invalidation/border-image-outset-change-repaint.html [ Failure ]
-crbug.com/417782 paint/invalidation/clipped-relative.html [ Failure ]
 crbug.com/417782 paint/invalidation/composited-iframe-scroll-repaint.html [ Failure ]
 crbug.com/417782 paint/invalidation/compositing/composited-document-element.html [ Failure ]
-crbug.com/417782 paint/invalidation/compositing/containing-block-removed-individual.html [ Failure ]
-crbug.com/417782 paint/invalidation/compositing/containing-block-removed.html [ Failure ]
-crbug.com/417782 paint/invalidation/compositing/fixed-pos-with-abs-pos-child-scroll.html [ Failure ]
-crbug.com/417782 paint/invalidation/compositing/overlap-test-with-filter.html [ Failure ]
-crbug.com/417782 paint/invalidation/compositing/page-scale-repaint.html [ Failure ]
-crbug.com/417782 paint/invalidation/css-grid-layout/grid-element-change-columns-repaint.html [ Failure ]
-crbug.com/417782 paint/invalidation/css-grid-layout/grid-element-change-rows-repaint.html [ Failure ]
-crbug.com/417782 paint/invalidation/css-grid-layout/grid-item-change-column-repaint.html [ Failure ]
-crbug.com/417782 paint/invalidation/css-grid-layout/grid-item-change-row-repaint.html [ Failure ]
-crbug.com/417782 paint/invalidation/css-grid-layout/grid-item-z-index-change-repaint.html [ Failure ]
-crbug.com/417782 paint/invalidation/destroy-composited-scrollbar.html [ Failure ]
-crbug.com/417782 paint/invalidation/do-not-paint-below-image-baseline.html [ Failure ]
-crbug.com/417782 paint/invalidation/filters/effect-reference-repaint-primitive-attr-mutation.html [ Failure ]
-crbug.com/417782 paint/invalidation/filters/effect-reference-repaint-primitive-attr-removal.html [ Failure ]
-crbug.com/417782 paint/invalidation/filters/effect-reference-repaint-primitive-removed.html [ Failure ]
-crbug.com/417782 paint/invalidation/fixed-position-transparency-with-overflow.html [ Failure ]
-crbug.com/417782 paint/invalidation/fixed-to-relative-position-with-absolute-child.html [ Failure ]
 crbug.com/417782 paint/invalidation/iframe-scroll-repaint.html [ Failure ]
-crbug.com/417782 paint/invalidation/image-resize.html [ Failure ]
-crbug.com/417782 paint/invalidation/japanese-rl-selection-repaint.html [ Failure ]
 crbug.com/417782 paint/invalidation/media-audio-no-spurious-repaints.html [ Failure ]
-crbug.com/417782 paint/invalidation/multicol-as-paint-container.html [ Failure ]
-crbug.com/417782 paint/invalidation/multicol-repaint.html [ Failure ]
-crbug.com/417782 paint/invalidation/multicol-resize-with-rule.html [ Failure ]
-crbug.com/417782 [ Mac Win ] paint/invalidation/multicol-with-block.html [ Failure ]
-crbug.com/417782 paint/invalidation/multicol-with-inline.html [ Failure ]
-crbug.com/417782 paint/invalidation/multicol-with-overflowing-block-rl.html [ Failure ]
-crbug.com/417782 paint/invalidation/multicol-with-text.html [ Failure ]
-crbug.com/417782 paint/invalidation/multiple-backgrounds-style-change.html [ Failure ]
-crbug.com/417782 paint/invalidation/overflow-hide.html [ Failure ]
 crbug.com/417782 paint/invalidation/overflow-scroll-body-appear.html [ Failure ]
-crbug.com/417782 paint/invalidation/overflow-show.html [ Failure ]
-crbug.com/417782 paint/invalidation/paged-with-overflowing-block-rl.html [ Failure ]
-crbug.com/417782 paint/invalidation/percent-size-image-resize-container.html [ Failure ]
 crbug.com/417782 paint/invalidation/positioned-document-element.html [ Crash ]
-crbug.com/417782 paint/invalidation/repaint-across-writing-mode-boundary.html [ Failure ]
-crbug.com/417782 paint/invalidation/replaced-clipped-positioned-not-wrong-incremental-repainting.html [ Failure ]
-crbug.com/417782 paint/invalidation/requestAnimation-translation-leave-traces.html [ Failure ]
 crbug.com/417782 paint/invalidation/resize-iframe-text.html [ Failure ]
 crbug.com/417782 paint/invalidation/scroll-in-transformed-layer.html [ Failure ]
-crbug.com/417782 [ Linux Mac ] paint/invalidation/scrollbar-damage-and-full-viewport-repaint.html [ Failure ]
-crbug.com/417782 paint/invalidation/scrolled-iframe-scrollbar-change.html [ Failure ]
-crbug.com/417782 paint/invalidation/selection-after-remove.html [ Failure ]
-crbug.com/417782 paint/invalidation/selection-change-in-iframe-with-relative-parent.html [ Failure ]
-crbug.com/417782 paint/invalidation/selection-clear.html [ Failure ]
-crbug.com/417782 paint/invalidation/selection-rl.html [ Failure ]
-crbug.com/417782 paint/invalidation/selection/invalidation-rect-includes-newline-for-rtl.html [ Failure ]
-crbug.com/417782 paint/invalidation/selection/invalidation-rect-includes-newline-for-vertical-lr.html [ Failure ]
-crbug.com/417782 paint/invalidation/selection/invalidation-rect-includes-newline-for-vertical-rl.html [ Failure ]
-crbug.com/417782 paint/invalidation/selection/invalidation-rect-includes-newline.html [ Failure ]
-crbug.com/417782 paint/invalidation/selection/invalidation-rect-with-br-includes-newline.html [ Failure ]
-crbug.com/417782 paint/invalidation/selection/repaint-rect-for-vertical-writing-mode-with-positioned-root.html [ Failure ]
-crbug.com/417782 paint/invalidation/selection/selection-in-non-composited-scrolling-container.html [ Failure ]
-crbug.com/417782 paint/invalidation/selection/selection-within-composited-scroller.html [ Failure ]
-crbug.com/417782 paint/invalidation/shift-relative-positioned-container-with-image-addition.html [ Failure ]
-crbug.com/417782 paint/invalidation/shift-relative-positioned-container-with-image-removal.html [ Failure ]
 crbug.com/417782 paint/invalidation/subpixel-shadow-included-in-invalidation.html [ Failure ]
 crbug.com/417782 paint/invalidation/svg/absolute-sized-document-no-scrollbars.svg [ Failure ]
-crbug.com/417782 paint/invalidation/svg/append-text-node-to-tspan.html [ Failure ]
 crbug.com/417782 paint/invalidation/svg/deep-nested-embedded-svg-size-changes-no-layout-triggers-1.html [ Failure ]
 crbug.com/417782 paint/invalidation/svg/deep-nested-embedded-svg-size-changes-no-layout-triggers-2.html [ Failure ]
 crbug.com/417782 paint/invalidation/svg/feImage-target-add-to-document.svg [ Failure ]
 crbug.com/417782 paint/invalidation/svg/feImage-target-reappend-to-document.svg [ Failure ]
-crbug.com/417782 [ Mac ] paint/invalidation/svg/js-late-gradient-and-object-creation.svg [ Failure ]
-crbug.com/417782 [ Mac ] paint/invalidation/svg/js-late-gradient-creation.svg [ Failure ]
-crbug.com/417782 [ Mac ] paint/invalidation/svg/js-late-pattern-and-object-creation.svg [ Failure ]
-crbug.com/417782 [ Mac ] paint/invalidation/svg/js-late-pattern-creation.svg [ Failure ]
-crbug.com/417782 paint/invalidation/svg/modify-text-node-in-tspan.html [ Failure ]
-crbug.com/417782 paint/invalidation/svg/modify-transferred-listitem-different-attr.html [ Failure ]
-crbug.com/417782 paint/invalidation/svg/relative-sized-document-scrollbars.svg [ Failure ]
-crbug.com/417782 paint/invalidation/svg/remove-text-node-from-tspan.html [ Failure ]
-crbug.com/417782 paint/invalidation/svg/remove-tspan-from-text.html [ Failure ]
-crbug.com/417782 paint/invalidation/svg/text-viewbox-rescale.html [ Failure ]
-crbug.com/417782 paint/invalidation/svg/use-detach.svg [ Failure ]
-crbug.com/417782 paint/invalidation/svg/window.svg [ Failure ]
-crbug.com/417782 paint/invalidation/table/cached-cell-append.html [ Failure ]
-crbug.com/417782 paint/invalidation/table/cached-change-cell-border-color.html [ Failure ]
-crbug.com/417782 paint/invalidation/table/cached-change-cell-border-width.html [ Failure ]
-crbug.com/417782 paint/invalidation/table/cached-change-cell-sl-border-color.html [ Failure ]
-crbug.com/417782 paint/invalidation/table/cached-change-col-border-color.html [ Failure ]
-crbug.com/417782 paint/invalidation/table/cached-change-col-border-width.html [ Failure ]
-crbug.com/417782 paint/invalidation/table/cached-change-colgroup-border-color.html [ Failure ]
-crbug.com/417782 paint/invalidation/table/cached-change-colgroup-border-width.html [ Failure ]
-crbug.com/417782 paint/invalidation/table/cached-change-row-border-color.html [ Failure ]
-crbug.com/417782 paint/invalidation/table/cached-change-row-border-width.html [ Failure ]
-crbug.com/417782 paint/invalidation/table/cached-change-table-border-color.html [ Failure ]
-crbug.com/417782 paint/invalidation/table/cached-change-table-border-width.html [ Failure ]
-crbug.com/417782 paint/invalidation/table/cached-change-tbody-border-color.html [ Failure ]
-crbug.com/417782 paint/invalidation/table/cached-change-tbody-border-width.html [ Failure ]
 crbug.com/417782 paint/invalidation/viewport-gradient-background-html-resize.html [ Crash ]
 crbug.com/417782 paint/invalidation/window-resize-background-image-fixed-centered-composited.html [ Failure ]
 crbug.com/417782 paint/invalidation/window-resize-background-image-fixed-centered.html [ Failure ]
diff --git a/third_party/WebKit/LayoutTests/NeverFixTests b/third_party/WebKit/LayoutTests/NeverFixTests
index f3b679c..45cd531c 100644
--- a/third_party/WebKit/LayoutTests/NeverFixTests
+++ b/third_party/WebKit/LayoutTests/NeverFixTests
@@ -985,16 +985,16 @@
 external/wpt/vibration/pattern-array-with-0-manual.html [ WontFix ]
 external/wpt/vibration/simple-array-manual.html [ WontFix ]
 external/wpt/vibration/simple-scalar-manual.html [ WontFix ]
-external/wpt/viewport/viewport-attribute-event-handlers-manual.html [ WontFix ]
-external/wpt/viewport/viewport-dimensions-custom-scrollbars-manual.html [ WontFix ]
-external/wpt/viewport/viewport-dimensions-scrollbars-manual.html [ WontFix ]
-external/wpt/viewport/viewport-offset-manual.html [ WontFix ]
-external/wpt/viewport/viewport-page-manual.html [ WontFix ]
-external/wpt/viewport/viewport-resize-event-manual.html [ WontFix ]
-external/wpt/viewport/viewport-scale-iframe-manual.html [ WontFix ]
-external/wpt/viewport/viewport-scale-manual.html [ WontFix ]
-external/wpt/viewport/viewport-scroll-event-manual.html [ WontFix ]
-external/wpt/viewport/viewport-url-bar-changes-height-manual.html [ WontFix ]
+external/wpt/visual-viewport/viewport-attribute-event-handlers-manual.html [ WontFix ]
+external/wpt/visual-viewport/viewport-dimensions-custom-scrollbars-manual.html [ WontFix ]
+external/wpt/visual-viewport/viewport-dimensions-scrollbars-manual.html [ WontFix ]
+external/wpt/visual-viewport/viewport-offset-manual.html [ WontFix ]
+external/wpt/visual-viewport/viewport-page-manual.html [ WontFix ]
+external/wpt/visual-viewport/viewport-resize-event-manual.html [ WontFix ]
+external/wpt/visual-viewport/viewport-scale-iframe-manual.html [ WontFix ]
+external/wpt/visual-viewport/viewport-scale-manual.html [ WontFix ]
+external/wpt/visual-viewport/viewport-scroll-event-manual.html [ WontFix ]
+external/wpt/visual-viewport/viewport-url-bar-changes-height-manual.html [ WontFix ]
 external/wpt/web-share/share-cancel-manual.html [ WontFix ]
 external/wpt/web-share/share-extra-argument-manual.html [ WontFix ]
 external/wpt/web-share/share-extra-field-manual.html [ WontFix ]
diff --git a/third_party/WebKit/LayoutTests/TestExpectations b/third_party/WebKit/LayoutTests/TestExpectations
index 80c6977..8dfe3cf 100644
--- a/third_party/WebKit/LayoutTests/TestExpectations
+++ b/third_party/WebKit/LayoutTests/TestExpectations
@@ -384,17 +384,6 @@
 crbug.com/635619 virtual/layout_ng/external/wpt/css/CSS2/normal-flow/inlines-005.xht [ Skip ]
 crbug.com/635619 virtual/layout_ng/external/wpt/css/CSS2/normal-flow/inlines-006.xht [ Skip ]
 
-# Canvas color extensions are incomplete.
-crbug.com/772189 virtual/color_space/fast/canvas/color-space/canvas-createImageBitmap-linear-rgb.html [ Crash ]
-crbug.com/772189 virtual/color_space/fast/canvas/color-space/canvas-createImageBitmap-p3.html [ Crash ]
-crbug.com/772189 virtual/color_space/fast/canvas/color-space/canvas-createImageBitmap-rec2020.html [ Crash ]
-crbug.com/772189 virtual/color_space/fast/canvas/color-space/canvas-createPutGetImageData-colorManaged.html [ Crash ]
-crbug.com/772189 virtual/color_space/fast/canvas/color-space/canvas-getImageData-linear-rgb.html [ Crash ]
-crbug.com/772189 virtual/color_space/fast/canvas/color-space/imageData-colorManagedBehavior.html [ Crash ]
-crbug.com/772189 virtual/color_space/fast/canvas/color-space/canvas-colorspace-arguments.html [ Failure ]
-crbug.com/772189 virtual/color_space/fast/canvas/color-space/canvas-drawImage-linear-rgb.html [ Failure ]
-crbug.com/772189 virtual/color_space/fast/canvas/color-space/display_linear-rgb.html [ Failure ]
-
 # Tables.
 crbug.com/635619 virtual/layout_ng/external/wpt/css/CSS2/normal-flow/max-width-applies-to-005.xht [ Failure ]
 crbug.com/635619 virtual/layout_ng/external/wpt/css/CSS2/normal-flow/max-width-applies-to-006.xht [ Failure ]
@@ -1746,6 +1735,11 @@
 crbug.com/771729 [ Win Debug ] external/wpt/html/semantics/scripting-1/the-script-element/execution-timing/039.html [ Pass Failure ]
 
 # ====== New tests from wpt-importer added here ======
+crbug.com/626703 [ Linux Mac10.10 Mac10.11 Mac10.12 Retina Win ] external/wpt/css/css-fonts-3/font-synthesis-01.html [ Failure ]
+crbug.com/626703 [ Linux Mac10.10 Mac10.11 Mac10.12 Retina Win ] external/wpt/css/css-fonts-3/font-synthesis-02.html [ Failure ]
+crbug.com/626703 [ Linux Mac10.10 Mac10.11 Mac10.12 Retina Win ] external/wpt/css/css-fonts-3/font-synthesis-03.html [ Failure ]
+crbug.com/626703 [ Linux Mac10.10 Mac10.11 Mac10.12 Retina Win ] external/wpt/css/css-fonts-3/font-synthesis-04.html [ Failure ]
+crbug.com/626703 [ Linux Mac10.10 Mac10.11 Mac10.12 Retina Win ] external/wpt/css/css-fonts-3/font-synthesis-05.html [ Failure ]
 crbug.com/626703 [ Linux Mac10.10 Mac10.11 Mac10.12 Retina Win ] external/wpt/requestidlecallback/idlharness.html [ Timeout ]
 crbug.com/626703 [ Android Linux Mac10.10 Mac10.11 Mac10.12 Retina Win ] external/wpt/acid/acid2/reftest.html [ Failure ]
 crbug.com/626703 [ Android Linux Mac10.10 Mac10.11 Mac10.12 Retina Win ] external/wpt/acid/acid3/test.html [ Failure ]
diff --git a/third_party/WebKit/LayoutTests/VirtualTestSuites b/third_party/WebKit/LayoutTests/VirtualTestSuites
index 81895618..6fefa2a 100644
--- a/third_party/WebKit/LayoutTests/VirtualTestSuites
+++ b/third_party/WebKit/LayoutTests/VirtualTestSuites
@@ -2,8 +2,7 @@
   {
     "prefix": "color_space",
     "base": "fast/canvas/color-space",
-    "args": ["--enable-blink-features=ColorCanvasExtensions",
-             "--force-color-profile=srgb"]
+    "args": ["--force-color-profile=srgb"]
   },
   {
     "prefix": "gpu",
@@ -115,11 +114,6 @@
   },
   {
     "prefix": "feature-policy-permissions",
-    "base": "http/tests/webmidi",
-    "args": ["--enable-features=UseFeaturePolicyForPermissions"]
-  },
-  {
-    "prefix": "feature-policy-permissions",
     "base": "external/wpt/mediacapture-streams",
     "args": ["--enable-features=UseFeaturePolicyForPermissions",
              "--use-fake-device-for-media-stream",
diff --git a/third_party/WebKit/LayoutTests/device_orientation/orientation/add-listener-from-callback-expected.txt b/third_party/WebKit/LayoutTests/device_orientation/orientation/add-listener-from-callback-expected.txt
deleted file mode 100644
index 56362dc..0000000
--- a/third_party/WebKit/LayoutTests/device_orientation/orientation/add-listener-from-callback-expected.txt
+++ /dev/null
@@ -1,17 +0,0 @@
-Tests that adding a new event listener from a callback works as expected.
-
-On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
-
-
-PASS deviceOrientationEvent.alpha is mockAlpha
-PASS deviceOrientationEvent.beta is mockBeta
-PASS deviceOrientationEvent.gamma is mockGamma
-PASS deviceOrientationEvent.absolute is mockAbsolute
-PASS deviceOrientationEvent.alpha is mockAlpha
-PASS deviceOrientationEvent.beta is mockBeta
-PASS deviceOrientationEvent.gamma is mockGamma
-PASS deviceOrientationEvent.absolute is mockAbsolute
-PASS successfullyParsed is true
-
-TEST COMPLETE
-
diff --git a/third_party/WebKit/LayoutTests/device_orientation/orientation/add-listener-from-callback.html b/third_party/WebKit/LayoutTests/device_orientation/orientation/add-listener-from-callback.html
index af25eb3..c026ac3 100644
--- a/third_party/WebKit/LayoutTests/device_orientation/orientation/add-listener-from-callback.html
+++ b/third_party/WebKit/LayoutTests/device_orientation/orientation/add-listener-from-callback.html
@@ -1,49 +1,36 @@
 <!DOCTYPE html>
 <html>
 <body>
-<script src="../../resources/js-test.js"></script>
+<script src="../../resources/testharness.js"></script>
+<script src="../../resources/testharnessreport.js"></script>
+<script src="../resources/device-orientation-helpers.js"></script>
 <script>
-description('Tests that adding a new event listener from a callback works as expected.');
+'use strict';
 
-var mockAlpha = 1.1;
-var mockBeta = 2.2;
-var mockGamma = 3.3;
-var mockAbsolute = true;
+async_test(test => {
+  assertTestRunner();
+  var orientationData = generateOrientationData(1.1, 2.2, 3.3, true);
 
-if (window.testRunner)
-    testRunner.setMockDeviceOrientation(true, mockAlpha, true, mockBeta, true, mockGamma, mockAbsolute);
-else
-    debug('This test can not be run without the TestRunner');
-
-var deviceOrientationEvent;
-function checkOrientation(event) {
-    deviceOrientationEvent = event;
-    shouldBe('deviceOrientationEvent.alpha', 'mockAlpha');
-    shouldBe('deviceOrientationEvent.beta', 'mockBeta');
-    shouldBe('deviceOrientationEvent.gamma', 'mockGamma');
-    shouldBe('deviceOrientationEvent.absolute', 'mockAbsolute');
-}
-
-var firstListenerEvents = 0;
-function firstListener(event) {
-    checkOrientation(event);
+  var firstListenerEvents = 0;
+  var firstListener = test.step_func(event => {
+    checkOrientation(event, orientationData);
     window.removeEventListener('deviceorientation', firstListener);
     if (++firstListenerEvents == 1)
-        window.addEventListener('deviceorientation', secondListener);
-}
+      window.addEventListener('deviceorientation', secondListener);
+  });
 
-var secondListenerEvents = 0;
-function secondListener(event) {
-    checkOrientation(event);
+  var secondListenerEvents = 0;
+  var secondListener = test.step_func(event => {
+    checkOrientation(event, orientationData);
     ++secondListenerEvents;
-    if (firstListenerEvents != 1 || secondListenerEvents != 1)
-        testFailed('Too many events fired for first or second listener');
-    finishJSTest();
-}
+    assert_equals(firstListenerEvents, 1, "Too many events fired for the first listener");
+    assert_equals(secondListenerEvents, 1, "Too many events fired for the second listener");
+    test.done();
+  });
 
-window.addEventListener('deviceorientation', firstListener);
-
-window.jsTestIsAsync = true;
+  setMockOrientation(orientationData);
+  window.addEventListener('deviceorientation', firstListener);
+}, 'Tests that adding a new deviceorientation event listener from a callback works as expected.');
 </script>
 </body>
 </html>
diff --git a/third_party/WebKit/LayoutTests/device_orientation/orientation/basic-operation-absolute-expected.txt b/third_party/WebKit/LayoutTests/device_orientation/orientation/basic-operation-absolute-expected.txt
deleted file mode 100644
index 51944fa..0000000
--- a/third_party/WebKit/LayoutTests/device_orientation/orientation/basic-operation-absolute-expected.txt
+++ /dev/null
@@ -1,13 +0,0 @@
-Tests basic operation of deviceorientationabsolute event using mock data.
-
-On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
-
-
-PASS event.alpha is mockAlpha
-PASS event.beta is mockBeta
-PASS event.gamma is mockGamma
-PASS event.absolute is mockAbsolute
-PASS successfullyParsed is true
-
-TEST COMPLETE
-
diff --git a/third_party/WebKit/LayoutTests/device_orientation/orientation/basic-operation-absolute.html b/third_party/WebKit/LayoutTests/device_orientation/orientation/basic-operation-absolute.html
index bf3605b1..7755ea89 100644
--- a/third_party/WebKit/LayoutTests/device_orientation/orientation/basic-operation-absolute.html
+++ b/third_party/WebKit/LayoutTests/device_orientation/orientation/basic-operation-absolute.html
@@ -1,11 +1,24 @@
 <!DOCTYPE html>
 <html>
 <body>
-<script src="../../resources/js-test.js"></script>
-<script src="resources/basic-operation.js"></script>
+<script src="../../resources/testharness.js"></script>
+<script src="../../resources/testharnessreport.js"></script>
+<script src="../resources/device-orientation-helpers.js"></script>
 <script>
-description('Tests basic operation of deviceorientationabsolute event using mock data.');
-testBasicOperation('deviceorientationabsolute');
+'use strict';
+
+async_test(test => {
+  assertTestRunner();
+  var orientationData = generateOrientationData(1.1, 2.2, 3.3, true);
+
+  var listener = test.step_func(event => {
+    checkOrientation(event, orientationData);
+    test.done();
+  });
+
+  setMockOrientation(orientationData);
+  window.addEventListener('deviceorientationabsolute', listener);
+}, 'Tests basic operation of deviceorientationabsolute event using mock data.');
 </script>
 </body>
 </html>
diff --git a/third_party/WebKit/LayoutTests/device_orientation/orientation/basic-operation-expected.txt b/third_party/WebKit/LayoutTests/device_orientation/orientation/basic-operation-expected.txt
deleted file mode 100644
index 8ef26d03..0000000
--- a/third_party/WebKit/LayoutTests/device_orientation/orientation/basic-operation-expected.txt
+++ /dev/null
@@ -1,13 +0,0 @@
-Tests basic operation of the deviceorientation event using mock data.
-
-On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
-
-
-PASS event.alpha is mockAlpha
-PASS event.beta is mockBeta
-PASS event.gamma is mockGamma
-PASS event.absolute is mockAbsolute
-PASS successfullyParsed is true
-
-TEST COMPLETE
-
diff --git a/third_party/WebKit/LayoutTests/device_orientation/orientation/basic-operation.html b/third_party/WebKit/LayoutTests/device_orientation/orientation/basic-operation.html
index 4c78cdda..63cf1ba9 100644
--- a/third_party/WebKit/LayoutTests/device_orientation/orientation/basic-operation.html
+++ b/third_party/WebKit/LayoutTests/device_orientation/orientation/basic-operation.html
@@ -1,11 +1,24 @@
 <!DOCTYPE html>
 <html>
 <body>
-<script src="../../resources/js-test.js"></script>
-<script src="resources/basic-operation.js"></script>
+<script src="../../resources/testharness.js"></script>
+<script src="../../resources/testharnessreport.js"></script>
+<script src="../resources/device-orientation-helpers.js"></script>
 <script>
-description('Tests basic operation of the deviceorientation event using mock data.');
-testBasicOperation('deviceorientation');
+'use strict';
+
+async_test(test => {
+  assertTestRunner();
+  var orientationData = generateOrientationData(1.1, 2.2, 3.3, true);
+
+  var listener = test.step_func(event => {
+    checkOrientation(event, orientationData);
+    test.done();
+  });
+
+  setMockOrientation(orientationData);
+  window.addEventListener('deviceorientation', listener);
+}, 'Tests basic operation of deviceorientation event using mock data.');
 </script>
 </body>
 </html>
diff --git a/third_party/WebKit/LayoutTests/device_orientation/orientation/create-event-expected.txt b/third_party/WebKit/LayoutTests/device_orientation/orientation/create-event-expected.txt
deleted file mode 100644
index 4cd23e5c..0000000
--- a/third_party/WebKit/LayoutTests/device_orientation/orientation/create-event-expected.txt
+++ /dev/null
@@ -1,28 +0,0 @@
-Tests that document.createEvent() works with DeviceOrientationEvent.
-
-On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
-
-
-PASS typeof event == 'object' is true
-PASS event.__proto__ is DeviceOrientationEvent.prototype
-PASS 'type' in event is true
-PASS 'bubbles' in event is true
-PASS 'cancelable' in event is true
-PASS 'alpha' in event is true
-PASS 'beta' in event is true
-PASS 'gamma' in event is true
-PASS 'absolute' in event is true
-PASS typeof event.type == 'string' is true
-PASS typeof event.bubbles == 'boolean' is true
-PASS typeof event.cancelable == 'boolean' is true
-PASS typeof event.alpha == 'object' is true
-PASS typeof event.beta == 'object' is true
-PASS typeof event.gamma == 'object' is true
-PASS typeof event.absolute == 'boolean' is true
-PASS newEvent.type is "deviceorientation"
-PASS newEvent.bubbles is false
-PASS newEvent.cancelable is false
-PASS successfullyParsed is true
-
-TEST COMPLETE
-
diff --git a/third_party/WebKit/LayoutTests/device_orientation/orientation/create-event.html b/third_party/WebKit/LayoutTests/device_orientation/orientation/create-event.html
index d8e41ad..4b2b56d 100644
--- a/third_party/WebKit/LayoutTests/device_orientation/orientation/create-event.html
+++ b/third_party/WebKit/LayoutTests/device_orientation/orientation/create-event.html
@@ -1,42 +1,44 @@
 <!DOCTYPE html>
 <html>
 <body>
-<script src="../../resources/js-test.js"></script>
+<script src="../../resources/testharness.js"></script>
+<script src="../../resources/testharnessreport.js"></script>
 <script>
-description('Tests that document.createEvent() works with DeviceOrientationEvent.');
+'use strict';
 
-var event = document.createEvent('DeviceOrientationEvent');
-var newEvent = new CustomEvent("deviceorientation", {
-    bubbles: false, cancelable: false,
-    alpha: 1.0,
-    beta: 2.0,
-    gama: 3.0,
-    absolute: false
-});
+test(test => {
+  var event = document.createEvent('DeviceOrientationEvent');
+  var newEvent = new CustomEvent("deviceorientation", {
+      bubbles: false, cancelable: false,
+      alpha: 1.0,
+      beta: 2.0,
+      gama: 3.0,
+      absolute: false
+  });
 
-shouldBeTrue("typeof event == 'object'");
-shouldBe("event.__proto__", "DeviceOrientationEvent.prototype");
+  assert_equals(typeof event, 'object');
+  assert_equals(event.__proto__, DeviceOrientationEvent.prototype);
 
-shouldBeTrue("'type' in event");
-shouldBeTrue("'bubbles' in event");
-shouldBeTrue("'cancelable' in event");
-shouldBeTrue("'alpha' in event");
-shouldBeTrue("'beta' in event");
-shouldBeTrue("'gamma' in event");
-shouldBeTrue("'absolute' in event");
+  assert_true('type' in event);
+  assert_true('bubbles' in event);
+  assert_true('cancelable' in event);
+  assert_true('alpha' in event);
+  assert_true('beta' in event);
+  assert_true('gamma' in event);
+  assert_true('absolute' in event);
 
-shouldBeTrue("typeof event.type == 'string'");
-shouldBeTrue("typeof event.bubbles == 'boolean'");
-shouldBeTrue("typeof event.cancelable == 'boolean'");
-shouldBeTrue("typeof event.alpha == 'object'");
-shouldBeTrue("typeof event.beta == 'object'");
-shouldBeTrue("typeof event.gamma == 'object'");
-shouldBeTrue("typeof event.absolute == 'boolean'");
+  assert_equals(typeof event.type, 'string');
+  assert_equals(typeof event.bubbles, 'boolean');
+  assert_equals(typeof event.cancelable, 'boolean');
+  assert_equals(typeof event.alpha, 'object');
+  assert_equals(typeof event.beta, 'object');
+  assert_equals(typeof event.gamma, 'object');
+  assert_equals(typeof event.absolute, 'boolean');
 
-shouldBeEqualToString("newEvent.type", "deviceorientation");
-shouldBeFalse("newEvent.bubbles");
-shouldBeFalse("newEvent.cancelable");
-
+  assert_equals(newEvent.type, "deviceorientation");
+  assert_false(newEvent.bubbles);
+  assert_false(newEvent.cancelable);
+}, 'Tests that document.createEvent() works with DeviceOrientationEvent.');
 </script>
 </body>
 </html>
diff --git a/third_party/WebKit/LayoutTests/device_orientation/orientation/multiple-event-listeners-expected.txt b/third_party/WebKit/LayoutTests/device_orientation/orientation/multiple-event-listeners-expected.txt
deleted file mode 100644
index 7de9465f..0000000
--- a/third_party/WebKit/LayoutTests/device_orientation/orientation/multiple-event-listeners-expected.txt
+++ /dev/null
@@ -1,25 +0,0 @@
-Tests using multiple event handlers for the Device Orientation API.
-
-On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
-
-
-PASS deviceOrientationEvent.alpha is expectedEvent.alpha
-PASS deviceOrientationEvent.beta is expectedEvent.beta
-PASS deviceOrientationEvent.gamma is expectedEvent.gamma
-PASS deviceOrientationEvent.absolute is expectedEvent.absolute
-PASS deviceOrientationEvent.alpha is expectedEvent.alpha
-PASS deviceOrientationEvent.beta is expectedEvent.beta
-PASS deviceOrientationEvent.gamma is expectedEvent.gamma
-PASS deviceOrientationEvent.absolute is expectedEvent.absolute
-PASS deviceOrientationEvent.alpha is expectedEvent.alpha
-PASS deviceOrientationEvent.beta is expectedEvent.beta
-PASS deviceOrientationEvent.gamma is expectedEvent.gamma
-PASS deviceOrientationEvent.absolute is expectedEvent.absolute
-PASS deviceOrientationEvent.alpha is expectedEvent.alpha
-PASS deviceOrientationEvent.beta is expectedEvent.beta
-PASS deviceOrientationEvent.gamma is expectedEvent.gamma
-PASS deviceOrientationEvent.absolute is expectedEvent.absolute
-PASS successfullyParsed is true
-
-TEST COMPLETE
-
diff --git a/third_party/WebKit/LayoutTests/device_orientation/orientation/multiple-event-listeners.html b/third_party/WebKit/LayoutTests/device_orientation/orientation/multiple-event-listeners.html
index 2e774ba..193fece 100644
--- a/third_party/WebKit/LayoutTests/device_orientation/orientation/multiple-event-listeners.html
+++ b/third_party/WebKit/LayoutTests/device_orientation/orientation/multiple-event-listeners.html
@@ -1,88 +1,69 @@
+<!DOCTYPE html>
 <html>
-<head>
-<script src="../../resources/js-test.js"></script>
-</head>
 <body>
+<script src="../../resources/testharness.js"></script>
+<script src="../../resources/testharnessreport.js"></script>
+<script src="../resources/device-orientation-helpers.js"></script>
 <script>
+'use strict';
 
-description('Tests using multiple event handlers for the Device Orientation API.');
+async_test(test => {
+  assertTestRunner();
+  var orientationData1 = generateOrientationData(1, 2, 3, true);
+  var orientationData2 = generateOrientationData(11, 12, 13, true);
+  var counter = 0;
 
-var mockEvent;
-var expectedEvent;
-function setMockOrientation(alpha, beta, gamma, absolute) {
-    mockEvent = {alpha: alpha, beta: beta, gamma: gamma, absolute: absolute};
-    if (window.testRunner)
-        testRunner.setMockDeviceOrientation(
-            true, mockEvent.alpha, true, mockEvent.beta, true, mockEvent.gamma, mockEvent.absolute);
-    else
-        debug('This test can not be run without the TestRunner');
-}
-
-var deviceOrientationEvent;
-function checkOrientation(event) {
-    deviceOrientationEvent = event;
-    shouldBe('deviceOrientationEvent.alpha', 'expectedEvent.alpha');
-    shouldBe('deviceOrientationEvent.beta', 'expectedEvent.beta');
-    shouldBe('deviceOrientationEvent.gamma', 'expectedEvent.gamma');
-    shouldBe('deviceOrientationEvent.absolute', 'expectedEvent.absolute');
-}
-
-var counter = 0;
-function firstListener(event) {
-    checkOrientation(event);
-    counter++;
+  var firstListener = test.step_func(event => {
+    checkOrientation(event, orientationData1);
+    ++counter;
     proceedIfNecessary();
-}
+  });
 
-function secondListener(event) {
-    checkOrientation(event);
-    counter++;
+  var secondListener = test.step_func(event => {
+    checkOrientation(event, orientationData1);
+    ++counter;
     proceedIfNecessary();
-}
+  });
 
-function proceedIfNecessary() {
+  function proceedIfNecessary() {
     if (counter == 2) {
-        setMockOrientation(11, 12, 13, true);
-        // Note: this should not stop Device Orientation updates,
-        // because there is still one listener active.
-        window.removeEventListener('deviceorientation', secondListener);
-        setTimeout(function(){initThirdListener();}, 0);
+      setMockOrientation(orientationData2);
+      // Note: this should not stop Device Orientation updates,
+      // because there is still one listener active.
+      window.removeEventListener('deviceorientation', secondListener);
+      setTimeout(initThirdListener, 0);
     }
-}
+  }
 
-var childFrame;
-function initThirdListener() {
+  var childFrame;
+  function initThirdListener() {
     childFrame = document.createElement('iframe');
     document.body.appendChild(childFrame);
     childFrame.contentWindow.addEventListener('deviceorientation', thirdListener);
-}
+  }
 
-function thirdListener(event) {
+  var thirdListener = test.step_func(event => {
     // Expect the cached event because Device Orientation was already active
     // when third listener was added.
-    checkOrientation(event);
+    checkOrientation(event, orientationData1);
     window.removeEventListener('deviceorientation', firstListener);
     childFrame.contentWindow.removeEventListener('deviceorientation', thirdListener);
-    setTimeout(function(){initFourthListener();}, 0);
-}
+    setTimeout(initFourthListener, 0);
+  });
 
-function initFourthListener() {
-    expectedEvent = mockEvent;
+  function initFourthListener() {
     window.addEventListener('deviceorientation', fourthListener);
-}
+  }
 
-function fourthListener(event) {
-    checkOrientation(event);
-    finishJSTest();
-}
+  var fourthListener = test.step_func(event => {
+    checkOrientation(event, orientationData2);
+    test.done();
+  });
 
-setMockOrientation(1, 2, 3, true);
-expectedEvent = mockEvent;
-window.addEventListener('deviceorientation', firstListener);
-window.addEventListener('deviceorientation', secondListener);
-
-window.jsTestIsAsync = true;
-
+  setMockOrientation(orientationData1);
+  window.addEventListener('deviceorientation', firstListener);
+  window.addEventListener('deviceorientation', secondListener);
+}, 'Tests using multiple event handlers for the Device Orientation API.');
 </script>
 </body>
 </html>
diff --git a/third_party/WebKit/LayoutTests/device_orientation/orientation/multiple-frames-expected.txt b/third_party/WebKit/LayoutTests/device_orientation/orientation/multiple-frames-expected.txt
deleted file mode 100644
index a15512aa..0000000
--- a/third_party/WebKit/LayoutTests/device_orientation/orientation/multiple-frames-expected.txt
+++ /dev/null
@@ -1,17 +0,0 @@
-Tests using DeviceOrientation from multiple frames.
-
-On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
-
-
-PASS deviceOrientationEvent.alpha is mockEvent.alpha
-PASS deviceOrientationEvent.beta is mockEvent.beta
-PASS deviceOrientationEvent.gamma is mockEvent.gamma
-PASS deviceOrientationEvent.absolute is mockEvent.absolute
-PASS deviceOrientationEvent.alpha is mockEvent.alpha
-PASS deviceOrientationEvent.beta is mockEvent.beta
-PASS deviceOrientationEvent.gamma is mockEvent.gamma
-PASS deviceOrientationEvent.absolute is mockEvent.absolute
-PASS successfullyParsed is true
-
-TEST COMPLETE
-
diff --git a/third_party/WebKit/LayoutTests/device_orientation/orientation/multiple-frames.html b/third_party/WebKit/LayoutTests/device_orientation/orientation/multiple-frames.html
index efe82da..e11a9322 100644
--- a/third_party/WebKit/LayoutTests/device_orientation/orientation/multiple-frames.html
+++ b/third_party/WebKit/LayoutTests/device_orientation/orientation/multiple-frames.html
@@ -1,51 +1,43 @@
 <!DOCTYPE html>
 <html>
 <body>
-<script src="../../resources/js-test.js"></script>
+<script src="../../resources/testharness.js"></script>
+<script src="../../resources/testharnessreport.js"></script>
+<script src="../resources/device-orientation-helpers.js"></script>
 <script>
-description('Tests using DeviceOrientation from multiple frames.');
+'use strict';
 
-var mockEvent = {alpha: 1.1, beta: 2.2, gamma: 3.3, absolute: true};
-if (window.testRunner)
-    testRunner.setMockDeviceOrientation(true, mockEvent.alpha, true, mockEvent.beta, true, mockEvent.gamma, mockEvent.absolute);
-else
-    debug('This test can not be run without the TestRunner');
+async_test(test => {
+  assertTestRunner();
+  var orientationData = generateOrientationData(1.1, 2.2, 3.3, true);
+  var hasMainFrameEventFired = false;
+  var hasChildFrameEventFired = false;
 
-var deviceOrientationEvent;
-function checkOrientation(event) {
-    deviceOrientationEvent = event;
-    shouldBe('deviceOrientationEvent.alpha', 'mockEvent.alpha');
-    shouldBe('deviceOrientationEvent.beta', 'mockEvent.beta');
-    shouldBe('deviceOrientationEvent.gamma', 'mockEvent.gamma');
-    shouldBe('deviceOrientationEvent.absolute', 'mockEvent.absolute');
-}
-
-var hasMainFrameEventFired = false;
-function mainFrameListener(event) {
-    checkOrientation(event);
+  var mainFrameListener = test.step_func(event => {
+    checkOrientation(event, orientationData);
     hasMainFrameEventFired = true;
     maybeFinishTest();
-}
+  });
 
-var hasChildFrameEventFired = false;
-function childFrameListener(event) {
-    checkOrientation(event);
+  var childFrameListener = test.step_func(event => {
+    checkOrientation(event, orientationData);
     hasChildFrameEventFired = true;
     maybeFinishTest();
-}
+  });
 
-function maybeFinishTest() {
+  function maybeFinishTest() {
     if (hasMainFrameEventFired && hasChildFrameEventFired)
-        finishJSTest();
-}
+      test.done();
+  }
 
-var childFrame = document.createElement('iframe');
-document.body.appendChild(childFrame);
-childFrame.contentWindow.addEventListener('deviceorientation', childFrameListener);
+  setMockOrientation(orientationData);
 
-window.addEventListener('deviceorientation', mainFrameListener);
+  var childFrame = document.createElement('iframe');
+  document.body.appendChild(childFrame);
+  childFrame.contentWindow.addEventListener('deviceorientation', childFrameListener);
 
-window.jsTestIsAsync = true;
+  window.addEventListener('deviceorientation', mainFrameListener);
+}, 'Tests using DeviceOrientation from multiple frames.');
 </script>
 </body>
-</html>
+</html>
\ No newline at end of file
diff --git a/third_party/WebKit/LayoutTests/device_orientation/orientation/no-synchronous-events-expected.txt b/third_party/WebKit/LayoutTests/device_orientation/orientation/no-synchronous-events-expected.txt
deleted file mode 100644
index 9fd8a11..0000000
--- a/third_party/WebKit/LayoutTests/device_orientation/orientation/no-synchronous-events-expected.txt
+++ /dev/null
@@ -1,10 +0,0 @@
-Tests that events are never fired synchronously from a call to window.addEventListener().
-
-On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
-
-
-PASS hasAddEventListenerReturned is true
-PASS successfullyParsed is true
-
-TEST COMPLETE
-
diff --git a/third_party/WebKit/LayoutTests/device_orientation/orientation/no-synchronous-events.html b/third_party/WebKit/LayoutTests/device_orientation/orientation/no-synchronous-events.html
index 6505088..450d4f0 100644
--- a/third_party/WebKit/LayoutTests/device_orientation/orientation/no-synchronous-events.html
+++ b/third_party/WebKit/LayoutTests/device_orientation/orientation/no-synchronous-events.html
@@ -1,23 +1,24 @@
 <!DOCTYPE html>
 <html>
 <body>
-<script src="../../resources/js-test.js"></script>
+<script src="../../resources/testharness.js"></script>
+<script src="../../resources/testharnessreport.js"></script>
+<script src="../resources/device-orientation-helpers.js"></script>
 <script>
-description('Tests that events are never fired synchronously from a call to window.addEventListener().');
+'use strict';
 
-if (window.testRunner)
-    testRunner.setMockDeviceOrientation(true, 1.1, true, 2.2, true, 3.3, true);
-else
-    debug('This test can not be run without the TestRunner');
+async_test(test => {
+  assertTestRunner();
+  var orientationData = generateOrientationData(1.1, 2.2, 3.3, true);
 
-var hasAddEventListenerReturned = false;
-window.addEventListener('deviceorientation', function() {
-    shouldBeTrue('hasAddEventListenerReturned');
-    finishJSTest();
-});
-hasAddEventListenerReturned = true;
+  setMockOrientation(orientationData);
 
-window.jsTestIsAsync = true;
+  var hasAddEventListenerReturned = false;
+  window.addEventListener('deviceorientation', test.step_func_done(() => {
+    assert_true(hasAddEventListenerReturned);
+  }));
+  hasAddEventListenerReturned = true;
+}, 'Tests that events are never fired synchronously from a call to window.addEventListener().');
 </script>
 </body>
 </html>
diff --git a/third_party/WebKit/LayoutTests/device_orientation/orientation/null-values-expected.txt b/third_party/WebKit/LayoutTests/device_orientation/orientation/null-values-expected.txt
deleted file mode 100644
index a6b2e5a0..0000000
--- a/third_party/WebKit/LayoutTests/device_orientation/orientation/null-values-expected.txt
+++ /dev/null
@@ -1,25 +0,0 @@
-Tests using null values for some of the event properties.
-
-On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
-
-
-PASS deviceOrientationEvent.alpha is mockEvent.alpha
-PASS deviceOrientationEvent.beta is mockEvent.beta
-PASS deviceOrientationEvent.gamma is mockEvent.gamma
-PASS deviceOrientationEvent.absolute is mockEvent.absolute
-PASS deviceOrientationEvent.alpha is mockEvent.alpha
-PASS deviceOrientationEvent.beta is mockEvent.beta
-PASS deviceOrientationEvent.gamma is mockEvent.gamma
-PASS deviceOrientationEvent.absolute is mockEvent.absolute
-PASS deviceOrientationEvent.alpha is mockEvent.alpha
-PASS deviceOrientationEvent.beta is mockEvent.beta
-PASS deviceOrientationEvent.gamma is mockEvent.gamma
-PASS deviceOrientationEvent.absolute is mockEvent.absolute
-PASS deviceOrientationEvent.alpha is mockEvent.alpha
-PASS deviceOrientationEvent.beta is mockEvent.beta
-PASS deviceOrientationEvent.gamma is mockEvent.gamma
-PASS deviceOrientationEvent.absolute is mockEvent.absolute
-PASS successfullyParsed is true
-
-TEST COMPLETE
-
diff --git a/third_party/WebKit/LayoutTests/device_orientation/orientation/null-values.html b/third_party/WebKit/LayoutTests/device_orientation/orientation/null-values.html
index 7a0280e..ffd7cbf 100644
--- a/third_party/WebKit/LayoutTests/device_orientation/orientation/null-values.html
+++ b/third_party/WebKit/LayoutTests/device_orientation/orientation/null-values.html
@@ -1,74 +1,60 @@
 <!DOCTYPE html>
 <html>
 <body>
-<script src="../../resources/js-test.js"></script>
+<script src="../../resources/testharness.js"></script>
+<script src="../../resources/testharnessreport.js"></script>
+<script src="../resources/device-orientation-helpers.js"></script>
 <script>
-description('Tests using null values for some of the event properties.');
+'use strict';
 
-var mockEvent;
-function setMockOrientation(alpha, beta, gamma, absolute) {
-    mockEvent = {alpha: alpha, beta: beta, gamma: gamma, absolute: absolute};
-    if (window.testRunner)
-        testRunner.setMockDeviceOrientation(
-            null != mockEvent.alpha, null == mockEvent.alpha ? 0 : mockEvent.alpha,
-            null != mockEvent.beta, null == mockEvent.beta ? 0 : mockEvent.beta,
-            null != mockEvent.gamma, null == mockEvent.gamma ? 0 : mockEvent.gamma,
-            mockEvent.absolute);
-    else
-        debug('This test can not be run without the TestRunner');
-}
+async_test(test => {
+  assertTestRunner();
+  var orientationData1 = generateOrientationData(null, null, null, false);
+  var orientationData2 = generateOrientationData(1.1, null, null, true);
+  var orientationData3 = generateOrientationData(null, 2.2, null, true);
+  var orientationData4 = generateOrientationData(null, null, 3.3, true);
 
-var deviceOrientationEvent;
-function checkOrientation(event) {
-    deviceOrientationEvent = event;
-    shouldBe('deviceOrientationEvent.alpha', 'mockEvent.alpha');
-    shouldBe('deviceOrientationEvent.beta', 'mockEvent.beta');
-    shouldBe('deviceOrientationEvent.gamma', 'mockEvent.gamma');
-    shouldBe('deviceOrientationEvent.absolute', 'mockEvent.absolute');
-}
-
-function firstListener(event) {
-    checkOrientation(event);
+  var firstListener = test.step_func(event => {
+    checkOrientation(event, orientationData1);
     window.removeEventListener('deviceorientation', firstListener);
-    setTimeout(function(){initSecondListener();}, 0);
-}
+    setTimeout(initSecondListener, 0);
+  });
 
-function initSecondListener() {
-    setMockOrientation(1.1, null, null, true);
+  function initSecondListener() {
+    setMockOrientation(orientationData2);
     window.addEventListener('deviceorientation', secondListener);
-}
+  }
 
-function secondListener(event) {
-    checkOrientation(event);
+  var secondListener = test.step_func(event => {
+    checkOrientation(event, orientationData2);
     window.removeEventListener('deviceorientation', secondListener);
-    setTimeout(function(){initThirdListener();}, 0);
-}
+    setTimeout(initThirdListener, 0);
+  });
 
-function initThirdListener() {
-    setMockOrientation(null, 2.2, null, true);
+  function initThirdListener() {
+    setMockOrientation(orientationData3);
     window.addEventListener('deviceorientation', thirdListener);
-}
+  }
 
-function thirdListener(event) {
-    checkOrientation(event);
+  var thirdListener = test.step_func(event => {
+    checkOrientation(event, orientationData3);
     window.removeEventListener('deviceorientation', thirdListener);
-    setTimeout(function(){initFourthListener();}, 0);
-}
+    setTimeout(initFourthListener, 0);
+  });
 
-function initFourthListener() {
-    setMockOrientation(null, null, 3.3, true);
+  function initFourthListener() {
+    setMockOrientation(orientationData4);
     window.addEventListener('deviceorientation', fourthListener);
-}
+  }
 
-function fourthListener(event) {
-    checkOrientation(event);
-    finishJSTest();
-}
+  var fourthListener = test.step_func(event => {
+    checkOrientation(event, orientationData4);
+    test.done();
+  });
 
-setMockOrientation(null, null, null, false);
-window.addEventListener('deviceorientation', firstListener);
-
-window.jsTestIsAsync = true;
+  setMockOrientation(orientationData1);
+  window.addEventListener('deviceorientation', firstListener);
+}, 'Tests using null values for some of the event properties.');
 </script>
 </body>
 </html>
diff --git a/third_party/WebKit/LayoutTests/device_orientation/orientation/optional-event-properties-expected.txt b/third_party/WebKit/LayoutTests/device_orientation/orientation/optional-event-properties-expected.txt
deleted file mode 100644
index 0965c147..0000000
--- a/third_party/WebKit/LayoutTests/device_orientation/orientation/optional-event-properties-expected.txt
+++ /dev/null
@@ -1,49 +0,0 @@
-Tests the optional properties of DeviceOrientationEvent. Each property should be null if not set, or set to null or undefined.
-
-On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
-
-
-event = document.createEvent('DeviceOrientationEvent')
-PASS event.alpha == null is true
-PASS event.beta == null is true
-PASS event.gamma == null is true
-PASS event.absolute is false
-event = new DeviceOrientationEvent('', {alpha: 0, beta: 1, gamma: 2, absolute: false})
-PASS event.alpha == 0 is true
-PASS event.beta == 1 is true
-PASS event.gamma == 2 is true
-PASS event.absolute is false
-event = new DeviceOrientationEvent('', {alpha: 0, beta: 1, gamma: 2, absolute: true})
-PASS event.alpha == 0 is true
-PASS event.beta == 1 is true
-PASS event.gamma == 2 is true
-PASS event.absolute is true
-event = new DeviceOrientationEvent('')
-PASS event.alpha == null is true
-PASS event.beta == null is true
-PASS event.gamma == null is true
-PASS event.absolute is false
-event = new DeviceOrientationEvent('', {alpha: [], beta: [], gamma: [], absolute: []})
-PASS event.alpha == 0 is true
-PASS event.beta == 0 is true
-PASS event.gamma == 0 is true
-PASS event.absolute is true
-event = new DeviceOrientationEvent('', {alpha: undefined, beta: undefined, gamma: undefined, absolute: undefined})
-PASS event.alpha == null is true
-PASS event.beta == null is true
-PASS event.gamma == null is true
-PASS event.absolute is false
-event = new DeviceOrientationEvent('', {alpha: '', beta: '', gamma: '', absolute: ''})
-PASS event.alpha == 0 is true
-PASS event.beta == 0 is true
-PASS event.gamma == 0 is true
-PASS event.absolute is false
-event = new DeviceOrientationEvent('', {alpha: null, beta: null, gamma: null, absolute: null})
-PASS event.alpha == null is true
-PASS event.beta == null is true
-PASS event.gamma == null is true
-PASS event.absolute is false
-PASS successfullyParsed is true
-
-TEST COMPLETE
-
diff --git a/third_party/WebKit/LayoutTests/device_orientation/orientation/optional-event-properties.html b/third_party/WebKit/LayoutTests/device_orientation/orientation/optional-event-properties.html
index 5640194..aa48bef 100644
--- a/third_party/WebKit/LayoutTests/device_orientation/orientation/optional-event-properties.html
+++ b/third_party/WebKit/LayoutTests/device_orientation/orientation/optional-event-properties.html
@@ -1,59 +1,75 @@
 <!DOCTYPE html>
 <html>
 <body>
-<script src="../../resources/js-test.js"></script>
+<script src="../../resources/testharness.js"></script>
+<script src="../../resources/testharnessreport.js"></script>
 <script>
-description('Tests the optional properties of DeviceOrientationEvent. Each property should be null if not set, or set to null or undefined.');
+'use strict';
 
-var event;
+test(test => {
+  event = document.createEvent('DeviceOrientationEvent');
+  assert_equals(event.alpha, null);
+  assert_equals(event.beta, null);
+  assert_equals(event.gamma, null);
+  assert_false(event.absolute);
+}, 'Tests creating a DeviceOrientationEvent.');
 
-evalAndLog("event = document.createEvent('DeviceOrientationEvent')");
-shouldBeTrue("event.alpha == null");
-shouldBeTrue("event.beta == null");
-shouldBeTrue("event.gamma == null");
-shouldBeFalse("event.absolute");
+test(test => {
+  event = new DeviceOrientationEvent('', {alpha: 0, beta: 1, gamma: 2, absolute: false});
+  assert_equals(event.alpha, 0);
+  assert_equals(event.beta, 1);
+  assert_equals(event.gamma, 2);
+  assert_false(event.absolute);
+}, 'Tests no missing value (absolute field is false).');
 
-evalAndLog("event = new DeviceOrientationEvent('', {alpha: 0, beta: 1, gamma: 2, absolute: false})");
-shouldBeTrue("event.alpha == 0");
-shouldBeTrue("event.beta == 1");
-shouldBeTrue("event.gamma == 2");
-shouldBeFalse("event.absolute");
+test(test => {
+  event = new DeviceOrientationEvent('', {alpha: 0, beta: 1, gamma: 2, absolute: true});
+  assert_equals(event.alpha, 0);
+  assert_equals(event.beta, 1);
+  assert_equals(event.gamma, 2);
+  assert_true(event.absolute);
+}, 'Tests no missing value (absolute field is true).');
 
-evalAndLog("event = new DeviceOrientationEvent('', {alpha: 0, beta: 1, gamma: 2, absolute: true})");
-shouldBeTrue("event.alpha == 0");
-shouldBeTrue("event.beta == 1");
-shouldBeTrue("event.gamma == 2");
-shouldBeTrue("event.absolute");
+test(test => {
+  event = new DeviceOrientationEvent('');
+  assert_equals(event.alpha, null);
+  assert_equals(event.beta, null);
+  assert_equals(event.gamma, null);
+  assert_false(event.absolute);
+}, 'Tests DeviceOrientationEvent default constructor.');
 
-evalAndLog("event = new DeviceOrientationEvent('')");
-shouldBeTrue("event.alpha == null");
-shouldBeTrue("event.beta == null");
-shouldBeTrue("event.gamma == null");
-shouldBeFalse("event.absolute");
+test(test => {
+  event = new DeviceOrientationEvent('', {alpha: [], beta: [], gamma: [], absolute: []});
+  assert_equals(event.alpha, 0);
+  assert_equals(event.beta, 0);
+  assert_equals(event.gamma, 0);
+  assert_true(event.absolute);
+}, 'Tests all values are empty array.');
 
-evalAndLog("event = new DeviceOrientationEvent('', {alpha: [], beta: [], gamma: [], absolute: []})");
-shouldBeTrue("event.alpha == 0");
-shouldBeTrue("event.beta == 0");
-shouldBeTrue("event.gamma == 0");
-shouldBeTrue("event.absolute");
+test(test => {
+  event = new DeviceOrientationEvent('', {alpha: undefined, beta: undefined, gamma: undefined, absolute: undefined});
+  assert_equals(event.alpha, null);
+  assert_equals(event.beta, null);
+  assert_equals(event.gamma, null);
+  assert_false(event.absolute);
+}, 'Tests all values are undefined.');
 
-evalAndLog("event = new DeviceOrientationEvent('', {alpha: undefined, beta: undefined, gamma: undefined, absolute: undefined})");
-shouldBeTrue("event.alpha == null");
-shouldBeTrue("event.beta == null");
-shouldBeTrue("event.gamma == null");
-shouldBeFalse("event.absolute");
+test(test => {
+  event = new DeviceOrientationEvent('', {alpha: '', beta: '', gamma: '', absolute: ''});
+  assert_equals(event.alpha, 0);
+  assert_equals(event.beta, 0);
+  assert_equals(event.gamma, 0);
+  assert_false(event.absolute);
+}, 'Tests all values are empty string.');
 
-evalAndLog("event = new DeviceOrientationEvent('', {alpha: '', beta: '', gamma: '', absolute: ''})");
-shouldBeTrue("event.alpha == 0");
-shouldBeTrue("event.beta == 0");
-shouldBeTrue("event.gamma == 0");
-shouldBeFalse("event.absolute");
 
-evalAndLog("event = new DeviceOrientationEvent('', {alpha: null, beta: null, gamma: null, absolute: null})");
-shouldBeTrue("event.alpha == null");
-shouldBeTrue("event.beta == null");
-shouldBeTrue("event.gamma == null");
-shouldBeFalse("event.absolute");
+test(test => {
+  event = new DeviceOrientationEvent('', {alpha: null, beta: null, gamma: null, absolute: null});
+  assert_equals(event.alpha, null);
+  assert_equals(event.beta, null);
+  assert_equals(event.gamma, null);
+  assert_false(event.absolute);
+}, 'Tests all values are null.');
 </script>
 </body>
 </html>
diff --git a/third_party/WebKit/LayoutTests/device_orientation/orientation/page-visibility-expected.txt b/third_party/WebKit/LayoutTests/device_orientation/orientation/page-visibility-expected.txt
deleted file mode 100644
index 18426afc..0000000
--- a/third_party/WebKit/LayoutTests/device_orientation/orientation/page-visibility-expected.txt
+++ /dev/null
@@ -1,15 +0,0 @@
-Tests to check that deviceorientation events are not fired when the page is not visible.
-
-On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
-
-
-* Page is visible
-PASS Received a deviceorientation event
-* Page is hidden
-PASS Did not receive a deviceorientation event
-* Page is visible
-PASS Received a deviceorientation event
-PASS successfullyParsed is true
-
-TEST COMPLETE
-
diff --git a/third_party/WebKit/LayoutTests/device_orientation/orientation/page-visibility.html b/third_party/WebKit/LayoutTests/device_orientation/orientation/page-visibility.html
index e869ba8..c6d3d411 100644
--- a/third_party/WebKit/LayoutTests/device_orientation/orientation/page-visibility.html
+++ b/third_party/WebKit/LayoutTests/device_orientation/orientation/page-visibility.html
@@ -1,54 +1,42 @@
 <!DOCTYPE html>
 <html>
 <body>
-<script src="../../resources/js-test.js"></script>
+<script src="../../resources/testharness.js"></script>
+<script src="../../resources/testharnessreport.js"></script>
+<script src="../resources/device-orientation-helpers.js"></script>
 <script>
-description('Tests to check that deviceorientation events are not fired when the page is not visible.');
-window.jsTestIsAsync = true;
+'use strict';
 
-function succeedAndFinish()
-{
-    testPassed("Received a deviceorientation event");
-    finishJSTest();
-}
+async_test(test => {
+  assertTestRunner();
 
-function testWithPageVisible()
-{
-    testPassed("Did not receive a deviceorientation event");
+  var orientationData = generateOrientationData(1, 2, 3, true);
+  var succeedAndFinish = test.step_func_done(() => {});
+
+  function testWithPageVisible() {
     window.removeEventListener('deviceorientation', failAndFinish);
-    if (window.testRunner)
-        testRunner.setPageVisibility("visible");
-    debug("* Page is visible");
+    testRunner.setPageVisibility("visible");
     window.addEventListener('deviceorientation', succeedAndFinish);
-}
+  }
 
-function failAndFinish()
-{
-    testFailed('Should not have received a deviceorientation event while the page was hidden');
-    finishJSTest();
-}
+  var failAndFinish = test.step_func_done(() => {
+    assert_unreached("Should not have received a deviceorientation event while the page was hidden");
+  });
 
-function testWithPageHidden()
-{
-    testPassed("Received a deviceorientation event");
+  function testWithPageHidden() {
     window.removeEventListener('deviceorientation', deviceOrientationListener);
-    if (window.testRunner)
-        testRunner.setPageVisibility("hidden");
-    debug("* Page is hidden");
+    testRunner.setPageVisibility("hidden");
     window.addEventListener('deviceorientation', failAndFinish);
-
     setTimeout(testWithPageVisible, 100);
-}
+  }
 
-function deviceOrientationListener(event) {
+  var deviceOrientationListener = test.step_func(() => {
     setTimeout(testWithPageHidden, 0);
-}
+  });
 
-if (window.testRunner)
-   testRunner.setMockDeviceOrientation(true, 1, true, 2, true, 3, true);
-
-debug("* Page is visible");
-window.addEventListener('deviceorientation', deviceOrientationListener);
+  setMockOrientation(orientationData);
+  window.addEventListener('deviceorientation', deviceOrientationListener);
+}, 'Tests to check that deviceorientation events are not fired when the page is not visible.');
 </script>
 </body>
-</html>
+</html>
\ No newline at end of file
diff --git a/third_party/WebKit/LayoutTests/device_orientation/orientation/resources/basic-operation.js b/third_party/WebKit/LayoutTests/device_orientation/orientation/resources/basic-operation.js
deleted file mode 100644
index f945f2b3..0000000
--- a/third_party/WebKit/LayoutTests/device_orientation/orientation/resources/basic-operation.js
+++ /dev/null
@@ -1,21 +0,0 @@
-// This test can be used to test device orientation event types: 'deviceorientation' and 'deviceorientationabsolute'.
-function testBasicOperation(eventType) {
-    window.jsTestIsAsync = true;
-    if (!window.testRunner)
-        debug('This test can not be run without the TestRunner');
-
-    mockAlpha = 1.1;
-    mockBeta = 2.2;
-    mockGamma = 3.3;
-    mockAbsolute = true;
-    testRunner.setMockDeviceOrientation(true, mockAlpha, true, mockBeta, true, mockGamma, mockAbsolute);
-
-    window.addEventListener(eventType, function(e) {
-        event = e;
-        shouldBe('event.alpha', 'mockAlpha');
-        shouldBe('event.beta', 'mockBeta');
-        shouldBe('event.gamma', 'mockGamma');
-        shouldBe('event.absolute', 'mockAbsolute');
-        finishJSTest();
-    });
-}
diff --git a/third_party/WebKit/LayoutTests/device_orientation/orientation/updates-expected.txt b/third_party/WebKit/LayoutTests/device_orientation/orientation/updates-expected.txt
deleted file mode 100644
index 3b2e39a..0000000
--- a/third_party/WebKit/LayoutTests/device_orientation/orientation/updates-expected.txt
+++ /dev/null
@@ -1,17 +0,0 @@
-Tests that updates to the orientation causes new events to fire.
-
-On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
-
-
-PASS deviceOrientationEvent.alpha is mockEvent.alpha
-PASS deviceOrientationEvent.beta is mockEvent.beta
-PASS deviceOrientationEvent.gamma is mockEvent.gamma
-PASS deviceOrientationEvent.absolute is mockEvent.absolute
-PASS deviceOrientationEvent.alpha is mockEvent.alpha
-PASS deviceOrientationEvent.beta is mockEvent.beta
-PASS deviceOrientationEvent.gamma is mockEvent.gamma
-PASS deviceOrientationEvent.absolute is mockEvent.absolute
-PASS successfullyParsed is true
-
-TEST COMPLETE
-
diff --git a/third_party/WebKit/LayoutTests/device_orientation/orientation/updates.html b/third_party/WebKit/LayoutTests/device_orientation/orientation/updates.html
index 6e73fbd..81a2fd9 100644
--- a/third_party/WebKit/LayoutTests/device_orientation/orientation/updates.html
+++ b/third_party/WebKit/LayoutTests/device_orientation/orientation/updates.html
@@ -1,48 +1,35 @@
 <!DOCTYPE html>
 <html>
 <body>
-<script src="../../resources/js-test.js"></script>
+<script src="../../resources/testharness.js"></script>
+<script src="../../resources/testharnessreport.js"></script>
+<script src="../resources/device-orientation-helpers.js"></script>
 <script>
-description('Tests that updates to the orientation causes new events to fire.');
+'use strict';
 
-var mockEvent;
-function setMockOrientation(alpha, beta, gamma, absolute) {
-    mockEvent = {alpha: alpha, beta: beta, gamma: gamma, absolute: absolute};
-    if (window.testRunner)
-        testRunner.setMockDeviceOrientation(true, mockEvent.alpha, true, mockEvent.beta, true, mockEvent.gamma, mockEvent.absolute);
-    else
-        debug('This test can not be run without the TestRunner');
-}
+async_test(test => {
+  assertTestRunner();
+  var orientationData1 = generateOrientationData(1.1, 2.2, 3.3, true);
+  var orientationData2 = generateOrientationData(11.1, 22.2, 33.3, true);
 
-var deviceOrientationEvent;
-function checkOrientation(event) {
-    deviceOrientationEvent = event;
-    shouldBe('deviceOrientationEvent.alpha', 'mockEvent.alpha');
-    shouldBe('deviceOrientationEvent.beta', 'mockEvent.beta');
-    shouldBe('deviceOrientationEvent.gamma', 'mockEvent.gamma');
-    shouldBe('deviceOrientationEvent.absolute', 'mockEvent.absolute');
-}
-
-function firstListener(event) {
-    checkOrientation(event);
+  var firstListener = test.step_func(event => {
+    checkOrientation(event, orientationData1);
     window.removeEventListener('deviceorientation', firstListener);
-    setTimeout(function(){initUpdateListener();}, 0);
-}
+    setTimeout(initUpdateListener, 0);
+  });
 
-function initUpdateListener() {
-    setMockOrientation(11.1, 22.2, 33.3, true);
+  function initUpdateListener() {
+    setMockOrientation(orientationData2);
     window.addEventListener('deviceorientation', updateListener);
-}
+  }
 
-function updateListener(event) {
-    checkOrientation(event);
-    finishJSTest();
-}
+  var updateListener = test.step_func_done(event => {
+    checkOrientation(event, orientationData2);
+  });
 
-setMockOrientation(1.1, 2.2, 3.3, true);
-window.addEventListener('deviceorientation', firstListener);
-
-window.jsTestIsAsync = true;
+  setMockOrientation(orientationData1);
+  window.addEventListener('deviceorientation', firstListener);
+}, 'Tests that updates to the orientation causes new events to fire.');
 </script>
 </body>
 </html>
diff --git a/third_party/WebKit/LayoutTests/device_orientation/orientation/window-property-expected.txt b/third_party/WebKit/LayoutTests/device_orientation/orientation/window-property-expected.txt
deleted file mode 100644
index 9893a276..0000000
--- a/third_party/WebKit/LayoutTests/device_orientation/orientation/window-property-expected.txt
+++ /dev/null
@@ -1,22 +0,0 @@
-Tests that the window.DeviceOrientationEvent and window.ondeviceorientation and window.ondeviceorientationabsolute properties are present.
-
-On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
-
-
-FAIL typeof window.DeviceOrientationEvent == 'object' should be true. Was false.
-FAIL typeof window.DeviceOrientationEvent == 'function' should be false. Was true.
-PASS window.propertyIsEnumerable('DeviceOrientationEvent') is false
-PASS 'DeviceOrientationEvent' in window is true
-PASS window.hasOwnProperty('DeviceOrientationEvent') is true
-PASS typeof window.ondeviceorientation == 'object' is true
-PASS typeof window.ondeviceorientationabsolute == 'object' is true
-PASS hasProperty('ondeviceorientation') is true
-PASS hasProperty('ondeviceorientationabsolute') is true
-PASS 'ondeviceorientation' in window is true
-PASS 'ondeviceorientationabsolute' in window is true
-PASS window.hasOwnProperty('ondeviceorientation') is true
-PASS window.hasOwnProperty('ondeviceorientationabsolute') is true
-PASS successfullyParsed is true
-
-TEST COMPLETE
-
diff --git a/third_party/WebKit/LayoutTests/device_orientation/orientation/window-property.html b/third_party/WebKit/LayoutTests/device_orientation/orientation/window-property.html
index 86f62f4..02e43d8c 100644
--- a/third_party/WebKit/LayoutTests/device_orientation/orientation/window-property.html
+++ b/third_party/WebKit/LayoutTests/device_orientation/orientation/window-property.html
@@ -1,34 +1,35 @@
 <!DOCTYPE html>
 <html>
 <body>
-<script src="../../resources/js-test.js"></script>
+<script src="../../resources/testharness.js"></script>
+<script src="../../resources/testharnessreport.js"></script>
 <script>
-description('Tests that the window.DeviceOrientationEvent and window.ondeviceorientation and window.ondeviceorientationabsolute properties are present.');
-
-shouldBeTrue("typeof window.DeviceOrientationEvent == 'object'");
-shouldBeFalse("typeof window.DeviceOrientationEvent == 'function'");
-shouldBeFalse("window.propertyIsEnumerable('DeviceOrientationEvent')");
-shouldBeTrue("'DeviceOrientationEvent' in window");
-shouldBeTrue("window.hasOwnProperty('DeviceOrientationEvent')");
+'use strict';
 
 function hasProperty(orientationProperty)
 {
-    for (var property in window) {
-        if (property == orientationProperty)
-            return true;
-    }
-    return false;
+  for (var property in window) {
+    if (property == orientationProperty)
+      return true;
+  }
+  return false;
 }
 
-shouldBeTrue("typeof window.ondeviceorientation == 'object'");
-shouldBeTrue("typeof window.ondeviceorientationabsolute == 'object'");
-shouldBeTrue("hasProperty('ondeviceorientation')");
-shouldBeTrue("hasProperty('ondeviceorientationabsolute')");
-shouldBeTrue("'ondeviceorientation' in window");
-shouldBeTrue("'ondeviceorientationabsolute' in window");
-shouldBeTrue("window.hasOwnProperty('ondeviceorientation')");
-shouldBeTrue("window.hasOwnProperty('ondeviceorientationabsolute')");
+test(test => {
+  assert_equals(typeof window.DeviceOrientationEvent, 'function');
+  assert_false(window.propertyIsEnumerable('DeviceOrientationEvent'));
+  assert_true('DeviceOrientationEvent' in window);
+  assert_true(window.hasOwnProperty('DeviceOrientationEvent'));
+
+  assert_equals(typeof window.ondeviceorientation, 'object');
+  assert_equals(typeof window.ondeviceorientationabsolute, 'object');
+  assert_true(hasProperty('ondeviceorientation'));
+  assert_true(hasProperty('ondeviceorientationabsolute'));
+  assert_true('ondeviceorientation' in window);
+  assert_true('ondeviceorientationabsolute' in window);
+  assert_true(window.hasOwnProperty('ondeviceorientation'));
+  assert_true(window.hasOwnProperty('ondeviceorientationabsolute'));
+}, 'Tests that the window.DeviceOrientationEvent and window.ondeviceorientation and window.ondeviceorientationabsolute properties are present.');
 </script>
 </body>
 </html>
-
diff --git a/third_party/WebKit/LayoutTests/device_orientation/resources/device-orientation-helpers.js b/third_party/WebKit/LayoutTests/device_orientation/resources/device-orientation-helpers.js
index 7c432c8e..656473b81 100644
--- a/third_party/WebKit/LayoutTests/device_orientation/resources/device-orientation-helpers.js
+++ b/third_party/WebKit/LayoutTests/device_orientation/resources/device-orientation-helpers.js
@@ -24,6 +24,14 @@
   return motionData;
 }
 
+function generateOrientationData(alpha, beta, gamma, absolute) {
+  var orientationData = {alpha: alpha,
+                         beta: beta,
+                         gamma: gamma,
+                         absolute: absolute};
+  return orientationData;
+}
+
 function setMockMotion(motionData) {
   testRunner.setMockDeviceMotion(null != motionData.accelerationX,
       null == motionData.accelerationX ? 0 : motionData.accelerationX,
@@ -46,6 +54,16 @@
       motionData.interval);
 }
 
+function setMockOrientation(orientationData) {
+  testRunner.setMockDeviceOrientation(null != orientationData.alpha,
+      null == orientationData.alpha ? 0 : orientationData.alpha,
+      null != orientationData.beta,
+      null == orientationData.beta ? 0 : orientationData.beta,
+      null != orientationData.gamma,
+      null == orientationData.gamma ? 0 : orientationData.gamma,
+      orientationData.absolute);
+}
+
 function checkMotion(event, expectedMotionData) {
   assert_equals(event.acceleration.x, expectedMotionData.accelerationX, "acceleration.x");
   assert_equals(event.acceleration.y, expectedMotionData.accelerationY, "acceleration.y");
@@ -61,3 +79,11 @@
 
   assert_equals(event.interval, expectedMotionData.interval, "interval");
 }
+
+function checkOrientation(event, expectedOrientationData) {
+  assert_equals(event.alpha, expectedOrientationData.alpha, "alpha");
+  assert_equals(event.beta, expectedOrientationData.beta, "beta");
+  assert_equals(event.gamma, expectedOrientationData.gamma, "gamma");
+
+  assert_equals(event.absolute, expectedOrientationData.absolute, "absolute");
+}
diff --git a/third_party/WebKit/LayoutTests/editing/caret/caret-painting-low-dpi.html b/third_party/WebKit/LayoutTests/editing/caret/caret-painting-low-dpi.html
new file mode 100644
index 0000000..357b81e
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/editing/caret/caret-painting-low-dpi.html
@@ -0,0 +1,26 @@
+<!DOCTYPE html>
+<style>
+    #test {
+        width: 200px;
+        border: 2px solid black;
+        height: 40px;
+        resize: none;
+        overflow: hidden;
+    }
+</style>
+<textarea id="test">Some text</textarea>
+<script src="../../resources/run-after-layout-and-paint.js"></script>
+<script>
+  window.onload = function() {
+    if (window.testRunner) {
+      document.getElementById("test").focus();
+      testRunner.setBackingScaleFactor(0.9,
+        function() { runAfterLayoutAndPaint(
+          function() { testRunner.dumpAsTextWithPixelResults();
+          }, true)
+        }
+      );
+    }
+  }
+</script>
+
diff --git a/third_party/WebKit/LayoutTests/external/WPT_BASE_MANIFEST.json b/third_party/WebKit/LayoutTests/external/WPT_BASE_MANIFEST.json
index 9187b36..9794f2e2 100644
--- a/third_party/WebKit/LayoutTests/external/WPT_BASE_MANIFEST.json
+++ b/third_party/WebKit/LayoutTests/external/WPT_BASE_MANIFEST.json
@@ -4903,63 +4903,63 @@
      {}
     ]
    ],
-   "viewport/viewport-attribute-event-handlers-manual.html": [
+   "visual-viewport/viewport-attribute-event-handlers-manual.html": [
     [
-     "/viewport/viewport-attribute-event-handlers-manual.html",
+     "/visual-viewport/viewport-attribute-event-handlers-manual.html",
      {}
     ]
    ],
-   "viewport/viewport-dimensions-custom-scrollbars-manual.html": [
+   "visual-viewport/viewport-dimensions-custom-scrollbars-manual.html": [
     [
-     "/viewport/viewport-dimensions-custom-scrollbars-manual.html",
+     "/visual-viewport/viewport-dimensions-custom-scrollbars-manual.html",
      {}
     ]
    ],
-   "viewport/viewport-dimensions-scrollbars-manual.html": [
+   "visual-viewport/viewport-dimensions-scrollbars-manual.html": [
     [
-     "/viewport/viewport-dimensions-scrollbars-manual.html",
+     "/visual-viewport/viewport-dimensions-scrollbars-manual.html",
      {}
     ]
    ],
-   "viewport/viewport-offset-manual.html": [
+   "visual-viewport/viewport-offset-manual.html": [
     [
-     "/viewport/viewport-offset-manual.html",
+     "/visual-viewport/viewport-offset-manual.html",
      {}
     ]
    ],
-   "viewport/viewport-page-manual.html": [
+   "visual-viewport/viewport-page-manual.html": [
     [
-     "/viewport/viewport-page-manual.html",
+     "/visual-viewport/viewport-page-manual.html",
      {}
     ]
    ],
-   "viewport/viewport-resize-event-manual.html": [
+   "visual-viewport/viewport-resize-event-manual.html": [
     [
-     "/viewport/viewport-resize-event-manual.html",
+     "/visual-viewport/viewport-resize-event-manual.html",
      {}
     ]
    ],
-   "viewport/viewport-scale-iframe-manual.html": [
+   "visual-viewport/viewport-scale-iframe-manual.html": [
     [
-     "/viewport/viewport-scale-iframe-manual.html",
+     "/visual-viewport/viewport-scale-iframe-manual.html",
      {}
     ]
    ],
-   "viewport/viewport-scale-manual.html": [
+   "visual-viewport/viewport-scale-manual.html": [
     [
-     "/viewport/viewport-scale-manual.html",
+     "/visual-viewport/viewport-scale-manual.html",
      {}
     ]
    ],
-   "viewport/viewport-scroll-event-manual.html": [
+   "visual-viewport/viewport-scroll-event-manual.html": [
     [
-     "/viewport/viewport-scroll-event-manual.html",
+     "/visual-viewport/viewport-scroll-event-manual.html",
      {}
     ]
    ],
-   "viewport/viewport-url-bar-changes-height-manual.html": [
+   "visual-viewport/viewport-url-bar-changes-height-manual.html": [
     [
-     "/viewport/viewport-url-bar-changes-height-manual.html",
+     "/visual-viewport/viewport-url-bar-changes-height-manual.html",
      {}
     ]
    ],
@@ -33227,6 +33227,282 @@
      {}
     ]
    ],
+   "css/css-fonts-3/font-stretch-01.html": [
+    [
+     "/css/css-fonts-3/font-stretch-01.html",
+     [
+      [
+       "/css/css-fonts-3/font-stretch-pass-ref.html",
+       "=="
+      ]
+     ],
+     {}
+    ]
+   ],
+   "css/css-fonts-3/font-stretch-02.html": [
+    [
+     "/css/css-fonts-3/font-stretch-02.html",
+     [
+      [
+       "/css/css-fonts-3/font-stretch-pass-ref.html",
+       "=="
+      ]
+     ],
+     {}
+    ]
+   ],
+   "css/css-fonts-3/font-stretch-03.html": [
+    [
+     "/css/css-fonts-3/font-stretch-03.html",
+     [
+      [
+       "/css/css-fonts-3/font-stretch-pass-ref.html",
+       "=="
+      ]
+     ],
+     {}
+    ]
+   ],
+   "css/css-fonts-3/font-stretch-04.html": [
+    [
+     "/css/css-fonts-3/font-stretch-04.html",
+     [
+      [
+       "/css/css-fonts-3/font-stretch-pass-ref.html",
+       "=="
+      ]
+     ],
+     {}
+    ]
+   ],
+   "css/css-fonts-3/font-stretch-05.html": [
+    [
+     "/css/css-fonts-3/font-stretch-05.html",
+     [
+      [
+       "/css/css-fonts-3/font-stretch-pass-ref.html",
+       "=="
+      ]
+     ],
+     {}
+    ]
+   ],
+   "css/css-fonts-3/font-stretch-06.html": [
+    [
+     "/css/css-fonts-3/font-stretch-06.html",
+     [
+      [
+       "/css/css-fonts-3/font-stretch-pass-ref.html",
+       "=="
+      ]
+     ],
+     {}
+    ]
+   ],
+   "css/css-fonts-3/font-stretch-07.html": [
+    [
+     "/css/css-fonts-3/font-stretch-07.html",
+     [
+      [
+       "/css/css-fonts-3/font-stretch-pass-ref.html",
+       "=="
+      ]
+     ],
+     {}
+    ]
+   ],
+   "css/css-fonts-3/font-stretch-08.html": [
+    [
+     "/css/css-fonts-3/font-stretch-08.html",
+     [
+      [
+       "/css/css-fonts-3/font-stretch-pass-ref.html",
+       "=="
+      ]
+     ],
+     {}
+    ]
+   ],
+   "css/css-fonts-3/font-stretch-09.html": [
+    [
+     "/css/css-fonts-3/font-stretch-09.html",
+     [
+      [
+       "/css/css-fonts-3/font-stretch-pass-ref.html",
+       "=="
+      ]
+     ],
+     {}
+    ]
+   ],
+   "css/css-fonts-3/font-stretch-10.html": [
+    [
+     "/css/css-fonts-3/font-stretch-10.html",
+     [
+      [
+       "/css/css-fonts-3/font-stretch-pass-ref.html",
+       "=="
+      ]
+     ],
+     {}
+    ]
+   ],
+   "css/css-fonts-3/font-stretch-11.html": [
+    [
+     "/css/css-fonts-3/font-stretch-11.html",
+     [
+      [
+       "/css/css-fonts-3/font-stretch-pass-ref.html",
+       "=="
+      ]
+     ],
+     {}
+    ]
+   ],
+   "css/css-fonts-3/font-stretch-12.html": [
+    [
+     "/css/css-fonts-3/font-stretch-12.html",
+     [
+      [
+       "/css/css-fonts-3/font-stretch-pass-ref.html",
+       "=="
+      ]
+     ],
+     {}
+    ]
+   ],
+   "css/css-fonts-3/font-stretch-13.html": [
+    [
+     "/css/css-fonts-3/font-stretch-13.html",
+     [
+      [
+       "/css/css-fonts-3/font-stretch-pass-ref.html",
+       "=="
+      ]
+     ],
+     {}
+    ]
+   ],
+   "css/css-fonts-3/font-stretch-14.html": [
+    [
+     "/css/css-fonts-3/font-stretch-14.html",
+     [
+      [
+       "/css/css-fonts-3/font-stretch-pass-ref.html",
+       "=="
+      ]
+     ],
+     {}
+    ]
+   ],
+   "css/css-fonts-3/font-stretch-15.html": [
+    [
+     "/css/css-fonts-3/font-stretch-15.html",
+     [
+      [
+       "/css/css-fonts-3/font-stretch-pass-ref.html",
+       "=="
+      ]
+     ],
+     {}
+    ]
+   ],
+   "css/css-fonts-3/font-stretch-16.html": [
+    [
+     "/css/css-fonts-3/font-stretch-16.html",
+     [
+      [
+       "/css/css-fonts-3/font-stretch-pass-ref.html",
+       "=="
+      ]
+     ],
+     {}
+    ]
+   ],
+   "css/css-fonts-3/font-stretch-17.html": [
+    [
+     "/css/css-fonts-3/font-stretch-17.html",
+     [
+      [
+       "/css/css-fonts-3/font-stretch-pass-ref.html",
+       "=="
+      ]
+     ],
+     {}
+    ]
+   ],
+   "css/css-fonts-3/font-stretch-18.html": [
+    [
+     "/css/css-fonts-3/font-stretch-18.html",
+     [
+      [
+       "/css/css-fonts-3/font-stretch-pass-ref.html",
+       "=="
+      ]
+     ],
+     {}
+    ]
+   ],
+   "css/css-fonts-3/font-synthesis-01.html": [
+    [
+     "/css/css-fonts-3/font-synthesis-01.html",
+     [
+      [
+       "/css/css-fonts-3/font-synthesis-01-ref.html",
+       "=="
+      ]
+     ],
+     {}
+    ]
+   ],
+   "css/css-fonts-3/font-synthesis-02.html": [
+    [
+     "/css/css-fonts-3/font-synthesis-02.html",
+     [
+      [
+       "/css/css-fonts-3/font-synthesis-02-ref.html",
+       "=="
+      ]
+     ],
+     {}
+    ]
+   ],
+   "css/css-fonts-3/font-synthesis-03.html": [
+    [
+     "/css/css-fonts-3/font-synthesis-03.html",
+     [
+      [
+       "/css/css-fonts-3/font-synthesis-03-ref.html",
+       "=="
+      ]
+     ],
+     {}
+    ]
+   ],
+   "css/css-fonts-3/font-synthesis-04.html": [
+    [
+     "/css/css-fonts-3/font-synthesis-04.html",
+     [
+      [
+       "/css/css-fonts-3/font-synthesis-04-ref.html",
+       "=="
+      ]
+     ],
+     {}
+    ]
+   ],
+   "css/css-fonts-3/font-synthesis-05.html": [
+    [
+     "/css/css-fonts-3/font-synthesis-05.html",
+     [
+      [
+       "/css/css-fonts-3/font-synthesis-03-ref.html",
+       "=="
+      ]
+     ],
+     {}
+    ]
+   ],
    "css/css-fonts-3/font-variant-01.html": [
     [
      "/css/css-fonts-3/font-variant-01.html",
@@ -33995,30 +34271,6 @@
      {}
     ]
    ],
-   "css/css-fonts-3/font-variant-position-02.html": [
-    [
-     "/css/css-fonts-3/font-variant-position-02.html",
-     [
-      [
-       "/css/css-fonts-3/font-variant-position-02-ref.html",
-       "=="
-      ]
-     ],
-     {}
-    ]
-   ],
-   "css/css-fonts-3/font-variant-position-03.html": [
-    [
-     "/css/css-fonts-3/font-variant-position-03.html",
-     [
-      [
-       "/css/css-fonts-3/font-variant-position-03-ref.html",
-       "=="
-      ]
-     ],
-     {}
-    ]
-   ],
    "css/css-fonts-3/font-variant-position.html": [
     [
      "/css/css-fonts-3/font-variant-position.html",
@@ -71912,11 +72164,6 @@
      {}
     ]
    ],
-   "compat/historical-expected.txt": [
-    [
-     {}
-    ]
-   ],
    "compat/webkit-text-fill-color-property-001-ref.html": [
     [
      {}
@@ -71967,41 +72214,6 @@
      {}
     ]
    ],
-   "content-security-policy/child-src/child-src-about-blank-allowed-by-default.sub.html.sub.headers": [
-    [
-     {}
-    ]
-   ],
-   "content-security-policy/child-src/child-src-about-blank-allowed-by-scheme.sub.html.sub.headers": [
-    [
-     {}
-    ]
-   ],
-   "content-security-policy/child-src/child-src-allowed.sub.html.sub.headers": [
-    [
-     {}
-    ]
-   ],
-   "content-security-policy/child-src/child-src-blocked.sub.html.sub.headers": [
-    [
-     {}
-    ]
-   ],
-   "content-security-policy/child-src/child-src-conflicting-frame-src.sub.html.sub.headers": [
-    [
-     {}
-    ]
-   ],
-   "content-security-policy/child-src/child-src-cross-origin-load.sub.html.sub.headers": [
-    [
-     {}
-    ]
-   ],
-   "content-security-policy/child-src/child-src-redirect-blocked.sub.html.sub.headers": [
-    [
-     {}
-    ]
-   ],
    "content-security-policy/connect-src/resources/simple-event-stream": [
     [
      {}
@@ -72212,56 +72424,6 @@
      {}
     ]
    ],
-   "content-security-policy/generic/generic-0_1-img-src.html.sub.headers": [
-    [
-     {}
-    ]
-   ],
-   "content-security-policy/generic/generic-0_1-script-src.html.sub.headers": [
-    [
-     {}
-    ]
-   ],
-   "content-security-policy/generic/generic-0_10.html.sub.headers": [
-    [
-     {}
-    ]
-   ],
-   "content-security-policy/generic/generic-0_10_1.sub.html.sub.headers": [
-    [
-     {}
-    ]
-   ],
-   "content-security-policy/generic/generic-0_2.html.sub.headers": [
-    [
-     {}
-    ]
-   ],
-   "content-security-policy/generic/generic-0_2_2.sub.html.sub.headers": [
-    [
-     {}
-    ]
-   ],
-   "content-security-policy/generic/generic-0_2_3.html.sub.headers": [
-    [
-     {}
-    ]
-   ],
-   "content-security-policy/generic/generic-0_8.html.sub.headers": [
-    [
-     {}
-    ]
-   ],
-   "content-security-policy/generic/generic-0_8_1.sub.html.sub.headers": [
-    [
-     {}
-    ]
-   ],
-   "content-security-policy/generic/generic-0_9.sub.html.sub.headers": [
-    [
-     {}
-    ]
-   ],
    "content-security-policy/generic/negativeTests.js": [
     [
      {}
@@ -72347,46 +72509,6 @@
      {}
     ]
    ],
-   "content-security-policy/media-src/media-src-7_1.html.sub.headers": [
-    [
-     {}
-    ]
-   ],
-   "content-security-policy/media-src/media-src-7_1_2.sub.html.sub.headers": [
-    [
-     {}
-    ]
-   ],
-   "content-security-policy/media-src/media-src-7_2.html.sub.headers": [
-    [
-     {}
-    ]
-   ],
-   "content-security-policy/media-src/media-src-7_2_2.sub.html.sub.headers": [
-    [
-     {}
-    ]
-   ],
-   "content-security-policy/media-src/media-src-7_3.sub.html.sub.headers": [
-    [
-     {}
-    ]
-   ],
-   "content-security-policy/media-src/media-src-7_3_2.sub.html.sub.headers": [
-    [
-     {}
-    ]
-   ],
-   "content-security-policy/media-src/media-src-blocked.sub.html.sub.headers": [
-    [
-     {}
-    ]
-   ],
-   "content-security-policy/media-src/media-src-redir-bug.sub.html.sub.headers": [
-    [
-     {}
-    ]
-   ],
    "content-security-policy/meta/combine-header-and-meta-policies.sub.html.sub.headers": [
     [
      {}
@@ -72432,6 +72554,31 @@
      {}
     ]
    ],
+   "content-security-policy/reporting/reporting-api-doesnt-send-reports-without-violation.https.sub.html.sub.headers": [
+    [
+     {}
+    ]
+   ],
+   "content-security-policy/reporting/reporting-api-report-only-sends-reports-on-violation.https.sub.html.sub.headers": [
+    [
+     {}
+    ]
+   ],
+   "content-security-policy/reporting/reporting-api-report-to-overrides-report-uri-1.https.sub.html.sub.headers": [
+    [
+     {}
+    ]
+   ],
+   "content-security-policy/reporting/reporting-api-report-to-overrides-report-uri-2.https.sub.html.sub.headers": [
+    [
+     {}
+    ]
+   ],
+   "content-security-policy/reporting/reporting-api-sends-reports-on-violation.https.sub.html.sub.headers": [
+    [
+     {}
+    ]
+   ],
    "content-security-policy/sandbox/support/sandboxed-data-iframe.sub.html": [
     [
      {}
@@ -72512,51 +72659,6 @@
      {}
     ]
    ],
-   "content-security-policy/script-src/script-src-1_1.html.sub.headers": [
-    [
-     {}
-    ]
-   ],
-   "content-security-policy/script-src/script-src-1_10.html.sub.headers": [
-    [
-     {}
-    ]
-   ],
-   "content-security-policy/script-src/script-src-1_10_1.html.sub.headers": [
-    [
-     {}
-    ]
-   ],
-   "content-security-policy/script-src/script-src-1_2.html.sub.headers": [
-    [
-     {}
-    ]
-   ],
-   "content-security-policy/script-src/script-src-1_2_1.html.sub.headers": [
-    [
-     {}
-    ]
-   ],
-   "content-security-policy/script-src/script-src-1_3.html.sub.headers": [
-    [
-     {}
-    ]
-   ],
-   "content-security-policy/script-src/script-src-1_4.html.sub.headers": [
-    [
-     {}
-    ]
-   ],
-   "content-security-policy/script-src/script-src-1_4_1.html.sub.headers": [
-    [
-     {}
-    ]
-   ],
-   "content-security-policy/script-src/script-src-1_4_2.html.sub.headers": [
-    [
-     {}
-    ]
-   ],
    "content-security-policy/script-src/script-src-multiple-policies-multiple-hashing-algorithms.html.sub.headers": [
     [
      {}
@@ -72922,11 +73024,6 @@
      {}
     ]
    ],
-   "content-security-policy/svg/svg-inline.sub.html.sub.headers": [
-    [
-     {}
-    ]
-   ],
    "cookies/OWNERS": [
     [
      {}
@@ -79102,11 +79199,6 @@
      {}
     ]
    ],
-   "css/css-flexbox-1/support/check-layout-th.js": [
-    [
-     {}
-    ]
-   ],
    "css/css-flexbox-1/support/flexbox.css": [
     [
      {}
@@ -79347,6 +79439,36 @@
      {}
     ]
    ],
+   "css/css-fonts-3/font-stretch-pass-ref.html": [
+    [
+     {}
+    ]
+   ],
+   "css/css-fonts-3/font-synthesis-01-ref.html": [
+    [
+     {}
+    ]
+   ],
+   "css/css-fonts-3/font-synthesis-02-ref.html": [
+    [
+     {}
+    ]
+   ],
+   "css/css-fonts-3/font-synthesis-03-ref.html": [
+    [
+     {}
+    ]
+   ],
+   "css/css-fonts-3/font-synthesis-04-ref.html": [
+    [
+     {}
+    ]
+   ],
+   "css/css-fonts-3/font-synthesis-05-ref.html": [
+    [
+     {}
+    ]
+   ],
    "css/css-fonts-3/font-variant-01-ref.html": [
     [
      {}
@@ -79822,6 +79944,26 @@
      {}
     ]
    ],
+   "css/css-fonts-3/support/fonts/Exo-DemiBold.otf": [
+    [
+     {}
+    ]
+   ],
+   "css/css-fonts-3/support/fonts/Exo2-SemiBold.otf": [
+    [
+     {}
+    ]
+   ],
+   "css/css-fonts-3/support/fonts/Exo2-SemiBoldCondensed.otf": [
+    [
+     {}
+    ]
+   ],
+   "css/css-fonts-3/support/fonts/Exo2-SemiBoldExpanded.otf": [
+    [
+     {}
+    ]
+   ],
    "css/css-fonts-3/support/fonts/FontWithFancyFeatures.otf": [
     [
      {}
@@ -79857,6 +79999,11 @@
      {}
     ]
    ],
+   "css/css-fonts-3/support/fonts/fail.woff": [
+    [
+     {}
+    ]
+   ],
    "css/css-fonts-3/support/fonts/font-feature-settings-rendering-2-expected.html": [
     [
      {}
@@ -87107,6 +87254,11 @@
      {}
     ]
    ],
+   "css/css-fonts-3/support/fonts/pass.woff": [
+    [
+     {}
+    ]
+   ],
    "css/css-fonts-3/support/green15x15.png": [
     [
      {}
@@ -87577,11 +87729,6 @@
      {}
     ]
    ],
-   "css/css-grid-1/support/check-layout-th.js": [
-    [
-     {}
-    ]
-   ],
    "css/css-grid-1/support/grid-alignment.css": [
     [
      {}
@@ -88497,11 +88644,6 @@
      {}
     ]
    ],
-   "css/css-tables-3/support/check-layout-th.js": [
-    [
-     {}
-    ]
-   ],
    "css/css-tables-3/table-model-fixup-expected.txt": [
     [
      {}
@@ -100417,21 +100559,11 @@
      {}
     ]
    ],
-   "fetch/api/request/request-cache-no-cache-expected.txt": [
-    [
-     {}
-    ]
-   ],
    "fetch/api/request/request-cache-no-store-expected.txt": [
     [
      {}
     ]
    ],
-   "fetch/api/request/request-cache-only-if-cached-expected.txt": [
-    [
-     {}
-    ]
-   ],
    "fetch/api/request/request-cache-reload-expected.txt": [
     [
      {}
@@ -107802,6 +107934,16 @@
      {}
     ]
    ],
+   "html/editing/focus/processing-model/preventScroll-expected.txt": [
+    [
+     {}
+    ]
+   ],
+   "html/editing/focus/processing-model/support/preventScroll-helper.html": [
+    [
+     {}
+    ]
+   ],
    "html/editing/focus/sequential-focus-navigation-and-the-tabindex-attribute/.gitkeep": [
     [
      {}
@@ -113517,6 +113659,11 @@
      {}
     ]
    ],
+   "interfaces/ambient-light.idl": [
+    [
+     {}
+    ]
+   ],
    "interfaces/clipboard.idl": [
     [
      {}
@@ -118597,11 +118744,31 @@
      {}
     ]
    ],
+   "secure-contexts/basic-dedicated-worker-expected.txt": [
+    [
+     {}
+    ]
+   ],
+   "secure-contexts/basic-dedicated-worker.https-expected.txt": [
+    [
+     {}
+    ]
+   ],
    "secure-contexts/basic-popup-and-iframe-tests.https.js": [
     [
      {}
     ]
    ],
+   "secure-contexts/basic-shared-worker-expected.txt": [
+    [
+     {}
+    ]
+   ],
+   "secure-contexts/basic-shared-worker.https-expected.txt": [
+    [
+     {}
+    ]
+   ],
    "secure-contexts/postMessage-helper.html": [
     [
      {}
@@ -118617,6 +118784,16 @@
      {}
     ]
    ],
+   "secure-contexts/shared-worker-insecure-first.https-expected.txt": [
+    [
+     {}
+    ]
+   ],
+   "secure-contexts/shared-worker-secure-first.https-expected.txt": [
+    [
+     {}
+    ]
+   ],
    "secure-contexts/support/dedicated-worker-script.js": [
     [
      {}
@@ -120127,16 +120304,6 @@
      {}
     ]
    ],
-   "service-workers/service-worker/resources/request-body-blob-iframe.html": [
-    [
-     {}
-    ]
-   ],
-   "service-workers/service-worker/resources/request-body-blob-worker.js": [
-    [
-     {}
-    ]
-   ],
    "service-workers/service-worker/resources/request-end-to-end-worker.js": [
     [
      {}
@@ -121682,7 +121849,7 @@
      {}
     ]
    ],
-   "viewport/viewport_support.js": [
+   "visual-viewport/viewport_support.js": [
     [
      {}
     ]
@@ -122012,6 +122179,26 @@
      {}
     ]
    ],
+   "webaudio/chrome/resources/audioparam-testing.js": [
+    [
+     {}
+    ]
+   ],
+   "webaudio/chrome/resources/audit-util.js": [
+    [
+     {}
+    ]
+   ],
+   "webaudio/chrome/resources/audit.js": [
+    [
+     {}
+    ]
+   ],
+   "webaudio/chrome/resources/start-stop-exceptions.js": [
+    [
+     {}
+    ]
+   ],
    "webaudio/js/buffer-loader.js": [
     [
      {}
@@ -125677,11 +125864,31 @@
      {}
     ]
    ],
+   "worklets/resources/referrer-tests.js": [
+    [
+     {}
+    ]
+   ],
+   "worklets/resources/referrer-window.html": [
+    [
+     {}
+    ]
+   ],
+   "worklets/resources/referrer.py": [
+    [
+     {}
+    ]
+   ],
    "worklets/resources/throwing-worklet-script.js": [
     [
      {}
     ]
    ],
+   "worklets/resources/worklet-test-utils.js": [
+    [
+     {}
+    ]
+   ],
    "x-frame-options/OWNERS": [
     [
      {}
@@ -136198,9 +136405,9 @@
      {}
     ]
    ],
-   "content-security-policy/generic/generic-0_8.html": [
+   "content-security-policy/generic/generic-0_8.sub.html": [
     [
-     "/content-security-policy/generic/generic-0_8.html",
+     "/content-security-policy/generic/generic-0_8.sub.html",
      {}
     ]
    ],
@@ -136333,9 +136540,7 @@
    "content-security-policy/media-src/media-src-7_1_2.sub.html": [
     [
      "/content-security-policy/media-src/media-src-7_1_2.sub.html",
-     {
-      "timeout": "long"
-     }
+     {}
     ]
    ],
    "content-security-policy/media-src/media-src-7_2.html": [
@@ -136347,9 +136552,7 @@
    "content-security-policy/media-src/media-src-7_2_2.sub.html": [
     [
      "/content-security-policy/media-src/media-src-7_2_2.sub.html",
-     {
-      "timeout": "long"
-     }
+     {}
     ]
    ],
    "content-security-policy/media-src/media-src-7_3.sub.html": [
@@ -136367,9 +136570,7 @@
    "content-security-policy/media-src/media-src-blocked.sub.html": [
     [
      "/content-security-policy/media-src/media-src-blocked.sub.html",
-     {
-      "timeout": "long"
-     }
+     {}
     ]
    ],
    "content-security-policy/media-src/media-src-redir-bug.sub.html": [
@@ -136520,6 +136721,38 @@
      {}
     ]
    ],
+   "content-security-policy/reporting/reporting-api-doesnt-send-reports-without-violation.https.sub.html": [
+    [
+     "/content-security-policy/reporting/reporting-api-doesnt-send-reports-without-violation.https.sub.html",
+     {}
+    ]
+   ],
+   "content-security-policy/reporting/reporting-api-report-only-sends-reports-on-violation.https.sub.html": [
+    [
+     "/content-security-policy/reporting/reporting-api-report-only-sends-reports-on-violation.https.sub.html",
+     {}
+    ]
+   ],
+   "content-security-policy/reporting/reporting-api-report-to-overrides-report-uri-1.https.sub.html": [
+    [
+     "/content-security-policy/reporting/reporting-api-report-to-overrides-report-uri-1.https.sub.html",
+     {}
+    ]
+   ],
+   "content-security-policy/reporting/reporting-api-report-to-overrides-report-uri-2.https.sub.html": [
+    [
+     "/content-security-policy/reporting/reporting-api-report-to-overrides-report-uri-2.https.sub.html",
+     {
+      "timeout": "long"
+     }
+    ]
+   ],
+   "content-security-policy/reporting/reporting-api-sends-reports-on-violation.https.sub.html": [
+    [
+     "/content-security-policy/reporting/reporting-api-sends-reports-on-violation.https.sub.html",
+     {}
+    ]
+   ],
    "content-security-policy/reporting/securitypolicyviolation-idl.html": [
     [
      "/content-security-policy/reporting/securitypolicyviolation-idl.html",
@@ -150714,6 +150947,12 @@
      {}
     ]
    ],
+   "html/editing/focus/processing-model/preventScroll.html": [
+    [
+     "/html/editing/focus/processing-model/preventScroll.html",
+     {}
+    ]
+   ],
    "html/editing/focus/sequential-focus-navigation-and-the-tabindex-attribute/focus-tabindex-default-value.html": [
     [
      "/html/editing/focus/sequential-focus-navigation-and-the-tabindex-attribute/focus-tabindex-default-value.html",
@@ -180538,12 +180777,6 @@
      {}
     ]
    ],
-   "service-workers/service-worker/request-body-blob.https.html": [
-    [
-     "/service-workers/service-worker/request-body-blob.https.html",
-     {}
-    ]
-   ],
    "service-workers/service-worker/request-end-to-end.https.html": [
     [
      "/service-workers/service-worker/request-end-to-end.https.html",
@@ -182924,75 +183157,75 @@
      {}
     ]
    ],
-   "viewport/viewport-no-resize-event-on-overflow-recalc.html": [
+   "visual-viewport/viewport-no-resize-event-on-overflow-recalc.html": [
     [
-     "/viewport/viewport-no-resize-event-on-overflow-recalc.html",
+     "/visual-viewport/viewport-no-resize-event-on-overflow-recalc.html",
      {}
     ]
    ],
-   "viewport/viewport-read-size-causes-layout.html": [
+   "visual-viewport/viewport-read-size-causes-layout.html": [
     [
-     "/viewport/viewport-read-size-causes-layout.html",
+     "/visual-viewport/viewport-read-size-causes-layout.html",
      {}
     ]
    ],
-   "viewport/viewport-read-size-in-iframe-causes-layout.html": [
+   "visual-viewport/viewport-read-size-in-iframe-causes-layout.html": [
     [
-     "/viewport/viewport-read-size-in-iframe-causes-layout.html",
+     "/visual-viewport/viewport-read-size-in-iframe-causes-layout.html",
      {}
     ]
    ],
-   "viewport/viewport-resize-event-on-load-overflowing-page.html": [
+   "visual-viewport/viewport-resize-event-on-load-overflowing-page.html": [
     [
-     "/viewport/viewport-resize-event-on-load-overflowing-page.html",
+     "/visual-viewport/viewport-resize-event-on-load-overflowing-page.html",
      {}
     ]
    ],
-   "viewport/viewport-scrollbars-cause-resize.html": [
+   "visual-viewport/viewport-scrollbars-cause-resize.html": [
     [
-     "/viewport/viewport-scrollbars-cause-resize.html",
+     "/visual-viewport/viewport-scrollbars-cause-resize.html",
      {}
     ]
    ],
-   "viewport/viewport-type.html": [
+   "visual-viewport/viewport-type.html": [
     [
-     "/viewport/viewport-type.html",
+     "/visual-viewport/viewport-type.html",
      {}
     ]
    ],
-   "viewport/viewport-unscaled-scale-iframe.html": [
+   "visual-viewport/viewport-unscaled-scale-iframe.html": [
     [
-     "/viewport/viewport-unscaled-scale-iframe.html",
+     "/visual-viewport/viewport-unscaled-scale-iframe.html",
      {}
     ]
    ],
-   "viewport/viewport-unscaled-scale.html": [
+   "visual-viewport/viewport-unscaled-scale.html": [
     [
-     "/viewport/viewport-unscaled-scale.html",
+     "/visual-viewport/viewport-unscaled-scale.html",
      {}
     ]
    ],
-   "viewport/viewport-unscaled-scroll-iframe.html": [
+   "visual-viewport/viewport-unscaled-scroll-iframe.html": [
     [
-     "/viewport/viewport-unscaled-scroll-iframe.html",
+     "/visual-viewport/viewport-unscaled-scroll-iframe.html",
      {}
     ]
    ],
-   "viewport/viewport-unscaled-scroll.html": [
+   "visual-viewport/viewport-unscaled-scroll.html": [
     [
-     "/viewport/viewport-unscaled-scroll.html",
+     "/visual-viewport/viewport-unscaled-scroll.html",
      {}
     ]
    ],
-   "viewport/viewport-unscaled-size-iframe.html": [
+   "visual-viewport/viewport-unscaled-size-iframe.html": [
     [
-     "/viewport/viewport-unscaled-size-iframe.html",
+     "/visual-viewport/viewport-unscaled-size-iframe.html",
      {}
     ]
    ],
-   "viewport/viewport-unscaled-size.html": [
+   "visual-viewport/viewport-unscaled-size.html": [
     [
-     "/viewport/viewport-unscaled-size.html",
+     "/visual-viewport/viewport-unscaled-size.html",
      {}
     ]
    ],
@@ -183494,6 +183727,24 @@
      {}
     ]
    ],
+   "webaudio/chrome/the-constantsourcenode-interface/constant-source-basic.html": [
+    [
+     "/webaudio/chrome/the-constantsourcenode-interface/constant-source-basic.html",
+     {}
+    ]
+   ],
+   "webaudio/chrome/the-constantsourcenode-interface/constant-source-onended.html": [
+    [
+     "/webaudio/chrome/the-constantsourcenode-interface/constant-source-onended.html",
+     {}
+    ]
+   ],
+   "webaudio/chrome/the-constantsourcenode-interface/constant-source-output.html": [
+    [
+     "/webaudio/chrome/the-constantsourcenode-interface/constant-source-output.html",
+     {}
+    ]
+   ],
    "webaudio/historical.html": [
     [
      "/webaudio/historical.html",
@@ -188302,12 +188553,24 @@
      {}
     ]
    ],
+   "worklets/animation-worklet-referrer.html": [
+    [
+     "/worklets/animation-worklet-referrer.html",
+     {}
+    ]
+   ],
    "worklets/paint-worklet-import.html": [
     [
      "/worklets/paint-worklet-import.html",
      {}
     ]
    ],
+   "worklets/paint-worklet-referrer.html": [
+    [
+     "/worklets/paint-worklet-referrer.html",
+     {}
+    ]
+   ],
    "x-frame-options/deny.sub.html": [
     [
      "/x-frame-options/deny.sub.html",
@@ -192186,6 +192449,18 @@
      {}
     ]
    ],
+   "css/css-fonts-3/font-variant-position-02.html": [
+    [
+     "/css/css-fonts-3/font-variant-position-02.html",
+     {}
+    ]
+   ],
+   "css/css-fonts-3/font-variant-position-03.html": [
+    [
+     "/css/css-fonts-3/font-variant-position-03.html",
+     {}
+    ]
+   ],
    "css/css-fonts-3/language-specific-01.html": [
     [
      "/css/css-fonts-3/language-specific-01.html",
@@ -192736,7 +193011,7 @@
    "support"
   ],
   "./README.md": [
-   "fa83617dc51fcc6f69732e43be203bc94de05ec1",
+   "7f6536f9d3a69dfcea7d74de767cbc5bee00a37f",
    "support"
   ],
   "./lint.whitelist": [
@@ -201743,10 +202018,6 @@
    "4b23ea52d785a6dd19785bd4278bf700eb5547f8",
    "support"
   ],
-  "compat/historical-expected.txt": [
-   "b7835af0dca3ccb149cd16099d6d84bc3badda0f",
-   "support"
-  ],
   "compat/historical.html": [
    "2d71e7532fc32af61d2410927b6405a9e79279a4",
    "testharness"
@@ -201896,61 +202167,33 @@
    "testharness"
   ],
   "content-security-policy/child-src/child-src-about-blank-allowed-by-default.sub.html": [
-   "3cfb06c55ac7dc026170b1ae886beba63cebac57",
+   "aaaca916f886f938cba52da4763b49a82f2b6ef8",
    "testharness"
   ],
-  "content-security-policy/child-src/child-src-about-blank-allowed-by-default.sub.html.sub.headers": [
-   "a042bfb6a20b4dee27d81fe8eda457536a4b09bc",
-   "support"
-  ],
   "content-security-policy/child-src/child-src-about-blank-allowed-by-scheme.sub.html": [
-   "34d092dcdd9d2c2287b1b15b16e6df3d70bcf666",
+   "f1b9578036a258488f81a8301b54063feb56d8f0",
    "testharness"
   ],
-  "content-security-policy/child-src/child-src-about-blank-allowed-by-scheme.sub.html.sub.headers": [
-   "66526f2ff5107dee1f999feb96d0ed0b1eea0b20",
-   "support"
-  ],
   "content-security-policy/child-src/child-src-allowed.sub.html": [
-   "8e70e19dbaffa7ca6b45b84b860eb11e343ce630",
+   "d1771ab8136386cee64c7f2d83a24b6d797f55f8",
    "testharness"
   ],
-  "content-security-policy/child-src/child-src-allowed.sub.html.sub.headers": [
-   "2fd7d14ff9446ef3208893c0e49c273afcfd8abf",
-   "support"
-  ],
   "content-security-policy/child-src/child-src-blocked.sub.html": [
-   "19fd649af944749546aee5af41fc2b4d7f135aed",
+   "0441b79da3a4e318b2c20f7b8f89b705dec7804f",
    "testharness"
   ],
-  "content-security-policy/child-src/child-src-blocked.sub.html.sub.headers": [
-   "da6c31fe646685e11c57558db29d9ba8ee1b697b",
-   "support"
-  ],
   "content-security-policy/child-src/child-src-conflicting-frame-src.sub.html": [
-   "8c903c4be2ccb11bdaff13fc3ae8690fe04ba755",
+   "dfc2e12a25932ba08753c6a960c731e144a0ae12",
    "testharness"
   ],
-  "content-security-policy/child-src/child-src-conflicting-frame-src.sub.html.sub.headers": [
-   "5ac25b74237593f6fc32c87f9a715e1cd99b5f9b",
-   "support"
-  ],
   "content-security-policy/child-src/child-src-cross-origin-load.sub.html": [
-   "51bbb0f02e67722433604c78f54a8619cb498dc0",
+   "5e35ab6c4a3384f87d23cfaab6a66ecfdf7dc862",
    "testharness"
   ],
-  "content-security-policy/child-src/child-src-cross-origin-load.sub.html.sub.headers": [
-   "a7b058f47360dee56f92e6caa3cc5eab1dc3706f",
-   "support"
-  ],
   "content-security-policy/child-src/child-src-redirect-blocked.sub.html": [
-   "1d7108c31df11379c79181a21a37822a5137fa73",
+   "97f865df60cc22c3d7ee1888db7dc20be2a7e81a",
    "testharness"
   ],
-  "content-security-policy/child-src/child-src-redirect-blocked.sub.html.sub.headers": [
-   "268d2bc1c16366626596649ea24b776609849f9e",
-   "support"
-  ],
   "content-security-policy/child-src/child-src-worker-allowed.sub.html": [
    "da18b70d2f859c83f1599e5f65bfeb67d1183ee4",
    "testharness"
@@ -202468,85 +202711,45 @@
    "testharness"
   ],
   "content-security-policy/generic/generic-0_1-img-src.html": [
-   "b9e456586e6acc8f56864ab36bea8c9ff67b3959",
+   "9c9ecb2f935d93d18ecf6175b0645b98f409d595",
    "testharness"
   ],
-  "content-security-policy/generic/generic-0_1-img-src.html.sub.headers": [
-   "ab1abd1bbb19ba7993d1d14e361171253224b7cb",
-   "support"
-  ],
   "content-security-policy/generic/generic-0_1-script-src.html": [
-   "d1d01090fb8ae7f33357d0d4d75e2606d637a881",
+   "cb765191d00459fcdd69c31b9b2a7d7f87bd09b3",
    "testharness"
   ],
-  "content-security-policy/generic/generic-0_1-script-src.html.sub.headers": [
-   "0596cdfbe4fda423101bb8bea3a7d732903b74cb",
-   "support"
-  ],
   "content-security-policy/generic/generic-0_10.html": [
-   "31f03b4b65e85d07610dd376415eeca43f7f91a2",
+   "bda8cdc3f50bc52a20a396febb6d305e64b00292",
    "testharness"
   ],
-  "content-security-policy/generic/generic-0_10.html.sub.headers": [
-   "16ab2c0e27dcca98ec2546d0e7196961bcbf30e3",
-   "support"
-  ],
   "content-security-policy/generic/generic-0_10_1.sub.html": [
-   "631cbab994285429f906832b4a192243bdc19009",
+   "9c6717bff2355b320c43ea60d01ba1aa0689f818",
    "testharness"
   ],
-  "content-security-policy/generic/generic-0_10_1.sub.html.sub.headers": [
-   "a3af477cdf51f8f6848edc913aa7601cf2c6a6b5",
-   "support"
-  ],
   "content-security-policy/generic/generic-0_2.html": [
-   "bdad4dc8303926e800159b6548c983a8b6261a74",
+   "1be199db848a5ce5a80255aa4013dd763c7859cd",
    "testharness"
   ],
-  "content-security-policy/generic/generic-0_2.html.sub.headers": [
-   "6e8122bdd2f39fade65c209582bbd7ece84bd627",
-   "support"
-  ],
   "content-security-policy/generic/generic-0_2_2.sub.html": [
-   "3ddc5a08c817fdc0d31826e170d08eb0b2261f20",
+   "8f275f169e1257400cea6e7dff26b0d457f3f82f",
    "testharness"
   ],
-  "content-security-policy/generic/generic-0_2_2.sub.html.sub.headers": [
-   "a6707834e433b30a0a31eb5300b6621cd6982583",
-   "support"
-  ],
   "content-security-policy/generic/generic-0_2_3.html": [
-   "ad2f16b5c0ac137f2d0c847de0e27ca87e7faaf5",
+   "c202f424814bb3c4f662c8fbec49031ed3ed405f",
    "testharness"
   ],
-  "content-security-policy/generic/generic-0_2_3.html.sub.headers": [
-   "1e3dde6acf0b11c9f2c0f1b56497ea84a879d978",
-   "support"
-  ],
-  "content-security-policy/generic/generic-0_8.html": [
-   "e536ca439e419494b32fd5d8c3041b3edc4dd6fb",
+  "content-security-policy/generic/generic-0_8.sub.html": [
+   "6e9aeddf1a5e308036ca1a659d138cc45fd7ea00",
    "testharness"
   ],
-  "content-security-policy/generic/generic-0_8.html.sub.headers": [
-   "a589ee90bb6c25f843d155477d281d3fabd9cb73",
-   "support"
-  ],
   "content-security-policy/generic/generic-0_8_1.sub.html": [
-   "c8fcd374917a8acd3ae198ddda1b59e150048739",
+   "e5913fc5feb3e2352172c96e366389e4216c55f3",
    "testharness"
   ],
-  "content-security-policy/generic/generic-0_8_1.sub.html.sub.headers": [
-   "e9ebd794d83d50b03f63c1cc97b5cb739490bab4",
-   "support"
-  ],
   "content-security-policy/generic/generic-0_9.sub.html": [
-   "b8ccc5ebb8b8f106bd284bb733dc8c808cc72dff",
+   "5b0adf26a3922c5a596333ea26a4102066e8ff8a",
    "testharness"
   ],
-  "content-security-policy/generic/generic-0_9.sub.html.sub.headers": [
-   "0f07964b8a88d54ac34b8f935c21026b43e89280",
-   "support"
-  ],
   "content-security-policy/generic/negativeTests.js": [
    "1d2009b245fa9483ad9058e0a587d5873e3578f3",
    "support"
@@ -202688,69 +202891,37 @@
    "support"
   ],
   "content-security-policy/media-src/media-src-7_1.html": [
-   "ce49162aecb9ca292ceeaa65b7a4206d430d21b4",
+   "dccf6c0e20dc0f109ecd40e59b27e0e37815487d",
    "testharness"
   ],
-  "content-security-policy/media-src/media-src-7_1.html.sub.headers": [
-   "4a918e8bcec9726cd388ae1d518d6e1a4d700823",
-   "support"
-  ],
   "content-security-policy/media-src/media-src-7_1_2.sub.html": [
-   "0ee3a4df705e1281c16bb0f71d24af881a1f0f60",
+   "fe5327fdd729fc7b47ad7eb963e22901df1cb692",
    "testharness"
   ],
-  "content-security-policy/media-src/media-src-7_1_2.sub.html.sub.headers": [
-   "71308d3aaf2908bb3d40469a64ace31e8eb41c44",
-   "support"
-  ],
   "content-security-policy/media-src/media-src-7_2.html": [
-   "b6c8bb9af6530ccd7ab1d1ade214d4b0b6678017",
+   "23257fa9395dae688804fcefaf4ec44bcb9995d3",
    "testharness"
   ],
-  "content-security-policy/media-src/media-src-7_2.html.sub.headers": [
-   "2b3e01914edac2809467daddfe5044030244020c",
-   "support"
-  ],
   "content-security-policy/media-src/media-src-7_2_2.sub.html": [
-   "e1cad846ee8e7d42a3ea130427f5b61e863a5836",
+   "d6dee44a6d82d50693a24e0de6eaab735372b37f",
    "testharness"
   ],
-  "content-security-policy/media-src/media-src-7_2_2.sub.html.sub.headers": [
-   "a561247903c77984842c4e4c02459d713c0de5dd",
-   "support"
-  ],
   "content-security-policy/media-src/media-src-7_3.sub.html": [
-   "dba52c4be3092a637eb129e626502c93322df44d",
+   "ff35e0bb1d1cebf81fd12d054960b489f7a088b9",
    "testharness"
   ],
-  "content-security-policy/media-src/media-src-7_3.sub.html.sub.headers": [
-   "05bab36a991f04ab8144daaa582e396863276aba",
-   "support"
-  ],
   "content-security-policy/media-src/media-src-7_3_2.sub.html": [
-   "7484051e7dc1e270e5251b5684cbb95cb900ccf7",
+   "401bd857abb420f17a3b548ef49ad0b1545e0144",
    "testharness"
   ],
-  "content-security-policy/media-src/media-src-7_3_2.sub.html.sub.headers": [
-   "c7623ee2c025f15eede625064f062d927543803a",
-   "support"
-  ],
   "content-security-policy/media-src/media-src-blocked.sub.html": [
-   "d7af07adf3ff35f0067f551c41c74c49d8daaa36",
+   "e5b408c372c8c2c152dc28ba947c6b41b8429ab9",
    "testharness"
   ],
-  "content-security-policy/media-src/media-src-blocked.sub.html.sub.headers": [
-   "e87df4f2889add93d8c50b79a00e830d76309a75",
-   "support"
-  ],
   "content-security-policy/media-src/media-src-redir-bug.sub.html": [
-   "581a76348d3c8cc415c2ac109f587a5a0b6ded23",
+   "c5d7eb88656e3fc0033588ae3c40c42e293c7528",
    "testharness"
   ],
-  "content-security-policy/media-src/media-src-redir-bug.sub.html.sub.headers": [
-   "578cb8e80efdf326dc8bbf43837cc1771c549352",
-   "support"
-  ],
   "content-security-policy/meta/combine-header-and-meta-policies.sub.html": [
    "779f494e1bce17d77c0f8a989de51b6195544563",
    "testharness"
@@ -202879,8 +203050,48 @@
    "cae24a6958eae450d1b21a47f4e13c407cac33be",
    "testharness"
   ],
+  "content-security-policy/reporting/reporting-api-doesnt-send-reports-without-violation.https.sub.html": [
+   "7be3a72eb885841e8ccb674eeae3761f638adf2c",
+   "testharness"
+  ],
+  "content-security-policy/reporting/reporting-api-doesnt-send-reports-without-violation.https.sub.html.sub.headers": [
+   "ddf99f2d2ed8bdfa56f5efbf371b324924c1c286",
+   "support"
+  ],
+  "content-security-policy/reporting/reporting-api-report-only-sends-reports-on-violation.https.sub.html": [
+   "19e6a43463fb72a74a0a03e2515d564f2df49234",
+   "testharness"
+  ],
+  "content-security-policy/reporting/reporting-api-report-only-sends-reports-on-violation.https.sub.html.sub.headers": [
+   "588c5767e4d7290ea7fd27be8218dd8420982848",
+   "support"
+  ],
+  "content-security-policy/reporting/reporting-api-report-to-overrides-report-uri-1.https.sub.html": [
+   "08311936720a8ee3835d029f572e924dd4f45e6e",
+   "testharness"
+  ],
+  "content-security-policy/reporting/reporting-api-report-to-overrides-report-uri-1.https.sub.html.sub.headers": [
+   "d0dddb85abb59ded83c36f71b4776881ce626e40",
+   "support"
+  ],
+  "content-security-policy/reporting/reporting-api-report-to-overrides-report-uri-2.https.sub.html": [
+   "41f777a06556d6cb4d8110d4d1fe70a6e58c2709",
+   "testharness"
+  ],
+  "content-security-policy/reporting/reporting-api-report-to-overrides-report-uri-2.https.sub.html.sub.headers": [
+   "1d58caea3b04f568e837678dbd27136fec73730c",
+   "support"
+  ],
+  "content-security-policy/reporting/reporting-api-sends-reports-on-violation.https.sub.html": [
+   "131b261ef9a6b79714eeacd4c9a525bdfafab21c",
+   "testharness"
+  ],
+  "content-security-policy/reporting/reporting-api-sends-reports-on-violation.https.sub.html.sub.headers": [
+   "966fcc13016f5980750ad1a4d5acf240762c2e0d",
+   "support"
+  ],
   "content-security-policy/reporting/securitypolicyviolation-idl.html": [
-   "ff5ed000c0c33f0e0495493e41ed4330844ec780",
+   "5f64e7ffb556afda675d52b7f9987f04612dccfd",
    "testharness"
   ],
   "content-security-policy/sandbox/iframe-inside-csp.sub.html": [
@@ -202928,15 +203139,15 @@
    "support"
   ],
   "content-security-policy/script-src/10_1_support_1.js": [
-   "bd10b9f495c679323ceeba54bf04a48c8a2fd4b4",
+   "6916d52aa90921bb59cd9a677f58176255f4f2fd",
    "support"
   ],
   "content-security-policy/script-src/10_1_support_2.js": [
-   "d7cde9fb4644245699893333e230d1c5fd79ca71",
+   "ee8d6589daed63364ed139a6776a787efc4ba44d",
    "support"
   ],
   "content-security-policy/script-src/addInlineTestsWithDOMManipulation.js": [
-   "ec7ba8726955690cee6a7f75b002a3d0d39db7d0",
+   "2ec0aedb07299313f8f337d6a1cb620f1da57a4a",
    "support"
   ],
   "content-security-policy/script-src/buildInlineWorker.js": [
@@ -202964,15 +203175,15 @@
    "testharness"
   ],
   "content-security-policy/script-src/inlineSuccessTest.js": [
-   "a591a02337841f6e8e822174a390a723ee6a3656",
+   "730190d637dee362ce20ce82aaed663c873dcbce",
    "support"
   ],
   "content-security-policy/script-src/inlineTests.js": [
-   "9256478a189aeabb765763a48fda9a6fd2ab077e",
+   "b07e007c036a4856f9bc11064639c65a97cf30bb",
    "support"
   ],
   "content-security-policy/script-src/javascript-window-open-blocked.html": [
-   "7d047c4966eee6c35a6bf24a80b4fbb672cb89b4",
+   "8907681d25a20a954c4db413d0fd78efd9dc6199",
    "testharness"
   ],
   "content-security-policy/script-src/javascript-window-open-blocked.html.sub.headers": [
@@ -202980,91 +203191,55 @@
    "support"
   ],
   "content-security-policy/script-src/script-src-1_1.html": [
-   "c547fd94e350bfd49541734515a4068de44f525d",
+   "b4285b63b3f9a8fab266ac93b3b7c1a70a7bdfcc",
    "testharness"
   ],
-  "content-security-policy/script-src/script-src-1_1.html.sub.headers": [
-   "58cb9b7acbda0e8017a83c1598f0ea1ea5f8cf4f",
-   "support"
-  ],
   "content-security-policy/script-src/script-src-1_10.html": [
-   "5a55427c869b1c5a0bee3ecf4619846f072d1e53",
+   "8d86fa302fa6f1262ab5c880bf2ce756f606d661",
    "testharness"
   ],
-  "content-security-policy/script-src/script-src-1_10.html.sub.headers": [
-   "c6da3920eb563d64585901f1e94aaa11a76e5270",
-   "support"
-  ],
   "content-security-policy/script-src/script-src-1_10_1.html": [
-   "a97e3cbdce7084b97eee28be5e3d3d42b5803966",
+   "46f535a4b373bdcc2b69ad78d333fb76d5f485bc",
    "testharness"
   ],
-  "content-security-policy/script-src/script-src-1_10_1.html.sub.headers": [
-   "ad7550efbc8ebb318bb2e32d96ea575c78596ffd",
-   "support"
-  ],
   "content-security-policy/script-src/script-src-1_2.html": [
-   "b3356097531989881006c444d0412cd8d488ca6e",
+   "e3b1b1ffe070be0258e18563c14b4af4e0b4f5e3",
    "testharness"
   ],
-  "content-security-policy/script-src/script-src-1_2.html.sub.headers": [
-   "b90d160699a5c3144933a0f4a5f79236aefb9ae0",
-   "support"
-  ],
   "content-security-policy/script-src/script-src-1_2_1.html": [
-   "907c529ec0b1186e72dd6ac095e46c001413639e",
+   "548eefcd46832140999a2754d7f62ad508cc7e28",
    "testharness"
   ],
-  "content-security-policy/script-src/script-src-1_2_1.html.sub.headers": [
-   "5e47b083224fa789bf14f90e4be4d72807d448e4",
-   "support"
-  ],
   "content-security-policy/script-src/script-src-1_3.html": [
-   "027ae9ff64cf5d1599541d0a2a5804096f71aad0",
+   "abf79935376e924c9fc1c8fea6f3b6d1c0b52227",
    "testharness"
   ],
-  "content-security-policy/script-src/script-src-1_3.html.sub.headers": [
-   "6e86dbda4c9fa33a27df5f25bca3e56a367eb5c6",
-   "support"
-  ],
   "content-security-policy/script-src/script-src-1_4.html": [
-   "62ba9216e12868cf0a6b4f791bf5305daa21dac6",
+   "d7369a16421ca7aadca158b0a6aff8c4cde35487",
    "testharness"
   ],
-  "content-security-policy/script-src/script-src-1_4.html.sub.headers": [
-   "8d484ffc9bb161edd31b0fb349a67eb0c5a30e7c",
-   "support"
-  ],
   "content-security-policy/script-src/script-src-1_4_1.html": [
-   "ff43ce545cc42d33809b5f48efe6f52bf57ccd41",
+   "4ac0b814c672862a1628e5e6c7fd4a6541a1421f",
    "testharness"
   ],
-  "content-security-policy/script-src/script-src-1_4_1.html.sub.headers": [
-   "90288741141736b1d59cc27070565e08393d821f",
-   "support"
-  ],
   "content-security-policy/script-src/script-src-1_4_2.html": [
-   "5a1d5c9393455aeb34a73a1c59c6d75783a3d936",
+   "6047332aa8240cc0e53e88d72834efcc8cfea2fd",
    "testharness"
   ],
-  "content-security-policy/script-src/script-src-1_4_2.html.sub.headers": [
-   "4c2700452b8e0cb5451ee00aaa8ff92f12e9623e",
-   "support"
-  ],
   "content-security-policy/script-src/script-src-multiple-policies-multiple-hashing-algorithms.html": [
-   "0f0f571fbc0db3b96112cb62f66d03c45674c127",
+   "66c96a85d3accfb20317501504ca3187ba7683f8",
    "testharness"
   ],
   "content-security-policy/script-src/script-src-multiple-policies-multiple-hashing-algorithms.html.sub.headers": [
-   "dec2d5659d318a58d7e957837ce3a217db2ea649",
+   "384cbb40a778c35dcfc5dc68e5ba26932e00445e",
    "support"
   ],
   "content-security-policy/script-src/script-src-multiple-policies-one-using-hashing-algorithms.html": [
-   "c0407821e7f7de5d80d601c7e693b0e283902e61",
+   "746a6b0340e1fa2e04b13c58c86644fcb8452516",
    "testharness"
   ],
   "content-security-policy/script-src/script-src-multiple-policies-one-using-hashing-algorithms.html.sub.headers": [
-   "39b7686073001e610bee5ba2a2c1083080b1aa68",
+   "4ea96701507b699f643a8ed77b7f20b443705e4c",
    "support"
   ],
   "content-security-policy/script-src/script-src-overrides-default-src.sub.html": [
@@ -203072,19 +203247,19 @@
    "testharness"
   ],
   "content-security-policy/script-src/script-src-report-only-policy-works-with-external-hash-policy.html": [
-   "f43c7510cf175e41d18b87f084136efeb22a0d86",
+   "9666194acc39933368bc101c53e3870a7d326f82",
    "testharness"
   ],
   "content-security-policy/script-src/script-src-report-only-policy-works-with-external-hash-policy.html.sub.headers": [
-   "6d5a35850052379753d5e39fe30aca1ddc9635f7",
+   "71ef442f2942a4d35c1d8ee95812c866d79fbda0",
    "support"
   ],
   "content-security-policy/script-src/script-src-report-only-policy-works-with-hash-policy.html": [
-   "a7b51858b4c9a967bf740e76a5e1de726f5dfcdd",
+   "d3a1f5be326ff4d394c4f436073a6c7a930292fb",
    "testharness"
   ],
   "content-security-policy/script-src/script-src-report-only-policy-works-with-hash-policy.html.sub.headers": [
-   "57c9026a7add5b8de2b153b14039787d44cbfa83",
+   "1001cdd06a04940bb842604ec0d05974df28d8ce",
    "support"
   ],
   "content-security-policy/script-src/script-src-sri_hash.sub.html": [
@@ -203616,7 +203791,7 @@
    "support"
   ],
   "content-security-policy/support/checkReport.sub.js": [
-   "90f36e63c4a18b6d755fda05b4e126e0cabf0e94",
+   "50b8b274a0a846ad527c2a369ba870def28e45e6",
    "support"
   ],
   "content-security-policy/support/document-write-alert-fail.js": [
@@ -203732,13 +203907,9 @@
    "testharness"
   ],
   "content-security-policy/svg/svg-inline.sub.html": [
-   "699d329c0929525b899e5ecc848ea0eff4ad02b8",
+   "9ef364019d2e2822a44cde9d07bf71ae36ff92eb",
    "testharness"
   ],
-  "content-security-policy/svg/svg-inline.sub.html.sub.headers": [
-   "8804cfb21823324551f0f98977ecb80588099150",
-   "support"
-  ],
   "content-security-policy/svg/svg-policy-resource-doc-includes.html": [
    "474d542398a46e302add6494151628a1e6e144e1",
    "testharness"
@@ -221672,11 +221843,11 @@
    "testharness"
   ],
   "css/css-flexbox-1/percentage-heights-000.html": [
-   "fbb795af85abb6bb28a2c3ac94012aad7e99b45b",
+   "9f5db2023fe4ac61108546602a5cdd2fe6ad8203",
    "testharness"
   ],
   "css/css-flexbox-1/percentage-heights-001.html": [
-   "5c3c576ee34a20e61e33a9851d332c743a9f078a",
+   "0bc00907610df6c5e03b884bf1a5633d80eff38b",
    "testharness"
   ],
   "css/css-flexbox-1/percentage-heights-002-ref.html": [
@@ -221696,19 +221867,19 @@
    "reftest"
   ],
   "css/css-flexbox-1/position-absolute-001.html": [
-   "bcf0ce321b9aca0fba213f677e9db92d595175fc",
+   "1c12d945aaece1a3c7c9e6b4b9986d5351956c4c",
    "testharness"
   ],
   "css/css-flexbox-1/position-absolute-002.html": [
-   "459087f00f8417a3345f0bfc25b6d66d44364a5f",
+   "f8b0ae2faf24d6810e3936307cd34a0b246fb3a8",
    "testharness"
   ],
   "css/css-flexbox-1/position-absolute-003.html": [
-   "25d21bf70a43936b159001b9a405e9df65e0f222",
+   "d1982c9167f9e73848b96722392b6c7e8ca7372e",
    "testharness"
   ],
   "css/css-flexbox-1/position-absolute-004.html": [
-   "222c04822ec756d6f4f504ed507aa678c7960b75",
+   "42bf61d230422676bcf0e2bae1f7dffee1ba340f",
    "testharness"
   ],
   "css/css-flexbox-1/position-absolute-005-ref.html": [
@@ -221927,10 +222098,6 @@
    "461fd17b274662b88500cdf42bab7f3b79e6019d",
    "support"
   ],
-  "css/css-flexbox-1/support/check-layout-th.js": [
-   "86c180327b87c617cdf8fa65fb079df08a0983e7",
-   "support"
-  ],
   "css/css-flexbox-1/support/flexbox.css": [
    "1ed29ddf429bf5efe54b65ce8b66d59c8c23a5f1",
    "support"
@@ -222359,6 +222526,122 @@
    "7b4cb600b9df97cd022504c4541b2143af22d29f",
    "reftest"
   ],
+  "css/css-fonts-3/font-stretch-01.html": [
+   "81f846d3cb087fb1a84f534a04320e706b49a212",
+   "reftest"
+  ],
+  "css/css-fonts-3/font-stretch-02.html": [
+   "86cd31128a1051e607015e9dadc1b78fea553b47",
+   "reftest"
+  ],
+  "css/css-fonts-3/font-stretch-03.html": [
+   "89b7d76992c5ade46281384971c7b933f9c13669",
+   "reftest"
+  ],
+  "css/css-fonts-3/font-stretch-04.html": [
+   "d2f26924c10a7ef4754babe06ccd050bda9332b8",
+   "reftest"
+  ],
+  "css/css-fonts-3/font-stretch-05.html": [
+   "bfd111699b5553f84522bbfb84ca49c177967ed4",
+   "reftest"
+  ],
+  "css/css-fonts-3/font-stretch-06.html": [
+   "fe90f418ab95706b0ec0110d545a8707773935fb",
+   "reftest"
+  ],
+  "css/css-fonts-3/font-stretch-07.html": [
+   "6fc64aada50f8fc8b1525cdf8917050c4d062b43",
+   "reftest"
+  ],
+  "css/css-fonts-3/font-stretch-08.html": [
+   "c113be451ff508c83cbc3ed589b721c23a5c3e92",
+   "reftest"
+  ],
+  "css/css-fonts-3/font-stretch-09.html": [
+   "67e3ce27e575d7bebbe090e20f8cac651da1e803",
+   "reftest"
+  ],
+  "css/css-fonts-3/font-stretch-10.html": [
+   "1d7c21ba01880a024511102488f199283e777dbd",
+   "reftest"
+  ],
+  "css/css-fonts-3/font-stretch-11.html": [
+   "fdfa62d43cec5c4e98af04f7791ffdbbc9efde87",
+   "reftest"
+  ],
+  "css/css-fonts-3/font-stretch-12.html": [
+   "fff585669f5c2fa963613c1679c5020729daa66e",
+   "reftest"
+  ],
+  "css/css-fonts-3/font-stretch-13.html": [
+   "50322d78f923052e51034ec80c5b1dd44ca618be",
+   "reftest"
+  ],
+  "css/css-fonts-3/font-stretch-14.html": [
+   "c4e2815ef769546c745a6fbebeb4db05e102a2ef",
+   "reftest"
+  ],
+  "css/css-fonts-3/font-stretch-15.html": [
+   "004e1a669c3cb3d3301c02ef84bc59d6af0f7238",
+   "reftest"
+  ],
+  "css/css-fonts-3/font-stretch-16.html": [
+   "cb06cd30d8d111217e940d8de85ccf6fcf2a0a77",
+   "reftest"
+  ],
+  "css/css-fonts-3/font-stretch-17.html": [
+   "86f077b63e2a7ba6f60965c87c30b1ac94f3cee0",
+   "reftest"
+  ],
+  "css/css-fonts-3/font-stretch-18.html": [
+   "035d0f522d507efcdaf259b6fb99baeac9251766",
+   "reftest"
+  ],
+  "css/css-fonts-3/font-stretch-pass-ref.html": [
+   "33a2a751324acb824907eac5853a91f96a3bd86f",
+   "support"
+  ],
+  "css/css-fonts-3/font-synthesis-01-ref.html": [
+   "4b02221e4811f2041c03698237c71e84173033b4",
+   "support"
+  ],
+  "css/css-fonts-3/font-synthesis-01.html": [
+   "df13a99fc3916de93cbd8b92f8520393ebffccd0",
+   "reftest"
+  ],
+  "css/css-fonts-3/font-synthesis-02-ref.html": [
+   "37caa18f5f1f4a76da775b6618fc9a4edbb7e6da",
+   "support"
+  ],
+  "css/css-fonts-3/font-synthesis-02.html": [
+   "295747b4f9cf02154f3daae95ab8bbab75ccb386",
+   "reftest"
+  ],
+  "css/css-fonts-3/font-synthesis-03-ref.html": [
+   "521b4dbd1ba6cecce7349080c1c757bb19a984f8",
+   "support"
+  ],
+  "css/css-fonts-3/font-synthesis-03.html": [
+   "46f41bdaf44ced16707fb01f598fe83acab3b8c6",
+   "reftest"
+  ],
+  "css/css-fonts-3/font-synthesis-04-ref.html": [
+   "37ae6d66d5ff56b42963bb749c0ba3c51800b1e9",
+   "support"
+  ],
+  "css/css-fonts-3/font-synthesis-04.html": [
+   "43e1f2bfa2e74cd9ba489f3ca4f156907fb7cb6c",
+   "reftest"
+  ],
+  "css/css-fonts-3/font-synthesis-05-ref.html": [
+   "7c54b978bb6beb1c5e6c145c0adce7eb62c5efae",
+   "support"
+  ],
+  "css/css-fonts-3/font-synthesis-05.html": [
+   "b46ea0f9864807dd0f36f90ff7668d5f733dd326",
+   "reftest"
+  ],
   "css/css-fonts-3/font-variant-01-ref.html": [
    "996de9843a58617c022174e77c6420816087dbe9",
    "support"
@@ -222880,16 +223163,16 @@
    "support"
   ],
   "css/css-fonts-3/font-variant-position-02.html": [
-   "1f0130c363d56c078dc7bb72906a89245d352226",
-   "reftest"
+   "831af35c0ac730263a3061c3052e865bf719997c",
+   "visual"
   ],
   "css/css-fonts-3/font-variant-position-03-ref.html": [
    "21f6fd83c6b63b57c75a43f08023bb6b3c6f8a87",
    "support"
   ],
   "css/css-fonts-3/font-variant-position-03.html": [
-   "777fca83be2a37bca768fde84d3226448662c181",
-   "reftest"
+   "7ad4b9d97ada6410e4e2c92b217d2aaa1317946c",
+   "visual"
   ],
   "css/css-fonts-3/font-variant-position-ref.html": [
    "986683fda8ba407d03e9d5e385ad4083b8ee6862",
@@ -223023,6 +223306,22 @@
    "f4f2fdd3f411fca8cd03b1f7f737694c73c0220b",
    "support"
   ],
+  "css/css-fonts-3/support/fonts/Exo-DemiBold.otf": [
+   "a239ac3082ff3c19edef8461a5ab9b778361f7b4",
+   "support"
+  ],
+  "css/css-fonts-3/support/fonts/Exo2-SemiBold.otf": [
+   "b1d02e8b1ee47bb1d200e81742876fce74b92436",
+   "support"
+  ],
+  "css/css-fonts-3/support/fonts/Exo2-SemiBoldCondensed.otf": [
+   "a4b11be0affd64e9f927095e3bc3653544d827d2",
+   "support"
+  ],
+  "css/css-fonts-3/support/fonts/Exo2-SemiBoldExpanded.otf": [
+   "60d232dc51a04464558ebe3680304c250d1e2ecd",
+   "support"
+  ],
   "css/css-fonts-3/support/fonts/FontWithFancyFeatures.otf": [
    "ce1bc123ba75345ab3816af7c18b481badbfd5eb",
    "support"
@@ -223051,6 +223350,10 @@
    "3d219e370db37a3392e07eb0c804d10ca7caf9c9",
    "support"
   ],
+  "css/css-fonts-3/support/fonts/fail.woff": [
+   "69e4080710f24b062203f56aa6ae2d991d4fa19a",
+   "support"
+  ],
   "css/css-fonts-3/support/fonts/font-feature-settings-rendering-2-expected.html": [
    "883083cdde66caca05384d3d6930070454e94fad",
    "support"
@@ -228851,6 +229154,10 @@
    "085a994b4b934056d0811cc989727e6390c37d66",
    "support"
   ],
+  "css/css-fonts-3/support/fonts/pass.woff": [
+   "cd8655ca01c5579a273f2063174a01126b10b78c",
+   "support"
+  ],
   "css/css-fonts-3/support/green15x15.png": [
    "de1830c21195763f7327f270b14b6d50dfdfb21d",
    "support"
@@ -229024,15 +229331,15 @@
    "reftest"
   ],
   "css/css-grid-1/abspos/absolute-positioning-definite-sizes-001.html": [
-   "884098260e1c51873c90d8328e31973f69adb224",
+   "8d917ad490835e4248956865571e3c4762973d0b",
    "testharness"
   ],
   "css/css-grid-1/abspos/absolute-positioning-grid-container-containing-block-001.html": [
-   "d7a6d2f0196a3e1e7b9bd618a1f885ae58dd05fb",
+   "ae306e9e6e980d4a575d6d10cee6401379283014",
    "testharness"
   ],
   "css/css-grid-1/abspos/absolute-positioning-grid-container-parent-001.html": [
-   "a7d866aed9b5021e681dadb85eca50462db1d748",
+   "b64d2b6f87d105d4631b7c539ed451e598d9a0f1",
    "testharness"
   ],
   "css/css-grid-1/abspos/grid-item-absolute-positioning-dynamic-001.html": [
@@ -229076,43 +229383,43 @@
    "reftest"
   ],
   "css/css-grid-1/abspos/grid-positioned-items-content-alignment-001.html": [
-   "dc376db419836c1fb2cc0d0477b20454159813e9",
+   "53c8139254cd0f62abf20b434132cd6ffa04be0f",
    "testharness"
   ],
   "css/css-grid-1/abspos/grid-positioned-items-content-alignment-rtl-001.html": [
-   "4530ed56a6b6b37d876cb9e56d73718440560f7f",
+   "566dcee47358c1e490786d0a8b995e4dbc11f076",
    "testharness"
   ],
   "css/css-grid-1/abspos/grid-positioned-items-gaps-001.html": [
-   "09614159f2996973a825a574ce884679aff69283",
+   "490d474f560501ede900e5cf448b0dc9dc9fa116",
    "testharness"
   ],
   "css/css-grid-1/abspos/grid-positioned-items-gaps-rtl-001.html": [
-   "b92090cc95a982097b54ba0695c4b0b43fb26b5e",
+   "8666f9bcaca645602fc2e790db2ab4cc7a28af5c",
    "testharness"
   ],
   "css/css-grid-1/abspos/grid-positioned-items-implicit-grid-001.html": [
-   "41cc2addf301921ffef0c1b98fb34ab41af059c6",
+   "eb058474779ddb8e4a31546fc2d89126a562e465",
    "testharness"
   ],
   "css/css-grid-1/abspos/grid-positioned-items-implicit-grid-line-001.html": [
-   "7e1f3ea3a2db26462048f2614725c8467095e934",
+   "d0e71cc3e8fce7329982eb37c1c1747fc62fce9e",
    "testharness"
   ],
   "css/css-grid-1/abspos/grid-positioned-items-padding-001.html": [
-   "024ababa5af46ec7fe3195ecbb2af5a7d1aab075",
+   "b4c31742faf89abbfd22fec978c77ba0836d7f03",
    "testharness"
   ],
   "css/css-grid-1/abspos/grid-positioned-items-unknown-named-grid-line-001.html": [
-   "a0a24530691fd19fc07986657375033c1d7eb524",
+   "e33299485785ec3ae16b7fd9b727c651ce5c2a8e",
    "testharness"
   ],
   "css/css-grid-1/abspos/grid-positioned-items-within-grid-implicit-track-001.html": [
-   "36d607db41c6cd74eb66859e550cfd339d3cd6f8",
+   "6ca9c08237d698a8f29ab04dc0cae117b04d7c02",
    "testharness"
   ],
   "css/css-grid-1/abspos/grid-sizing-positioned-items-001.html": [
-   "44c77a955845c78f581e039f78364a8caed6a6c1",
+   "9389a43ede1cdadda820a5db21cb08cf25b4f9b9",
    "testharness"
   ],
   "css/css-grid-1/abspos/orthogonal-positioned-grid-items-001-ref.html": [
@@ -229356,11 +229663,11 @@
    "reftest"
   ],
   "css/css-grid-1/abspos/positioned-grid-items-should-not-create-implicit-tracks-001.html": [
-   "f042dd8f7e7c4d228ef9f1a7eae641899f516940",
+   "20fce922797d8d29a3301d90d0113f659827b1a8",
    "testharness"
   ],
   "css/css-grid-1/abspos/positioned-grid-items-should-not-take-up-space-001.html": [
-   "2d6dec61a1a2902a58f50b3b8e1330c97ce547b9",
+   "171c6bbf8b1126781f71b60774e9d01ba7588cc7",
    "testharness"
   ],
   "css/css-grid-1/abspos/positioned-grid-items-sizing-001-ref.html": [
@@ -229372,147 +229679,147 @@
    "reftest"
   ],
   "css/css-grid-1/alignment/grid-alignment-implies-size-change-001.html": [
-   "19ae01ab31a15efc601d2857d3ca1dd879cb4e66",
+   "99d3941d430705202a7094276de59dc5edf69321",
    "testharness"
   ],
   "css/css-grid-1/alignment/grid-alignment-implies-size-change-002.html": [
-   "abb8f221910dc58b87ff1d3f5b9f346994688a8d",
+   "399c23ecc22e3ab5376044847fdcc0e778bc0bad",
    "testharness"
   ],
   "css/css-grid-1/alignment/grid-alignment-implies-size-change-003.html": [
-   "1dee7406f817681eaec5c1b5607b9762bc546329",
+   "bcdc1d68ddff37c67204341a6e93dc81a325a8f2",
    "testharness"
   ],
   "css/css-grid-1/alignment/grid-alignment-implies-size-change-004.html": [
-   "03da21bdcbb4fdb53f93c372da2af4a175fc0bc9",
+   "163ebbb7c462f803de9f85fbde11a384847f4faf",
    "testharness"
   ],
   "css/css-grid-1/alignment/grid-alignment-implies-size-change-005.html": [
-   "c4e793351e05b74a9d859286407f30f019e581ee",
+   "0e759ebbad7f7de553ebd8ccc50892d3af40d9eb",
    "testharness"
   ],
   "css/css-grid-1/alignment/grid-alignment-implies-size-change-006.html": [
-   "ab2604e1dd0396402ce6ab0acea3a340d107ad08",
+   "106f9a163e1d1621827e1d34bf1cc0c043b01898",
    "testharness"
   ],
   "css/css-grid-1/alignment/grid-alignment-implies-size-change-007.html": [
-   "17b0c72f106d9103af25c654e913ad00c2a5ee19",
+   "247606b98201e9a73f6162432ec4f032e7822d98",
    "testharness"
   ],
   "css/css-grid-1/alignment/grid-alignment-implies-size-change-008.html": [
-   "32b50873af5b434817de9ca3fb5ea3b79808bdbc",
+   "ce14fc5adc6e6bc08f9d67f7c432e42e1fa06994",
    "testharness"
   ],
   "css/css-grid-1/alignment/grid-alignment-implies-size-change-009.html": [
-   "29551eeae983adc5cdd9b518b64a1d0c9560f062",
+   "78f5c7dc3382ef9e06cb98266a1aea04858b36a8",
    "testharness"
   ],
   "css/css-grid-1/alignment/grid-alignment-implies-size-change-010.html": [
-   "396afc15a311bb0a636ba2570b57366a52fbc770",
+   "572eaddac3bcad2a78f595a2d7252ed61e284173",
    "testharness"
   ],
   "css/css-grid-1/alignment/grid-alignment-implies-size-change-011.html": [
-   "49109ff240399f0f1f60308850f805779dfc4b21",
+   "70681816b62b12c0b47dd59e92c82c57c5195df4",
    "testharness"
   ],
   "css/css-grid-1/alignment/grid-alignment-implies-size-change-012.html": [
-   "45a9279c62d4052a150a6da13ae9c177a38f01a2",
+   "45434202efd7954308d6f87023cdbc245a412c47",
    "testharness"
   ],
   "css/css-grid-1/alignment/grid-alignment-implies-size-change-013.html": [
-   "29d4695a9ad8eb5eebcdf15b3693a714bc412779",
+   "93ae6b0da898b80b39b7c3315b862024345625bd",
    "testharness"
   ],
   "css/css-grid-1/alignment/grid-alignment-implies-size-change-014.html": [
-   "66d7b70d305869abb453caf2f0e51a274bd1a537",
+   "439df61ce437200c65c09605d46461f889b0c236",
    "testharness"
   ],
   "css/css-grid-1/alignment/grid-alignment-implies-size-change-015.html": [
-   "874f6b55e6b204d6cfc41c73a2c00a5f4229d298",
+   "4944467ea75bbd7468f08ede5dd19a88196ab9d3",
    "testharness"
   ],
   "css/css-grid-1/alignment/grid-alignment-implies-size-change-016.html": [
-   "51b59909bd41adefa471e9b8bf9ff75e9ed92259",
+   "e0b7eeddc7cdd5187c3a07186407360026b6a0d4",
    "testharness"
   ],
   "css/css-grid-1/alignment/grid-alignment-implies-size-change-017.html": [
-   "6423406f9bfaf43ac97fd4547a784c2bb8d19bc0",
+   "47d65e49c206a554caa1738e44f0d41f2650431a",
    "testharness"
   ],
   "css/css-grid-1/alignment/grid-alignment-implies-size-change-018.html": [
-   "123575acf3c090c6479e5e4fa064c75fcea56bda",
+   "08367b30d4b332dcff0be6f7967c1dc8ef4bd9af",
    "testharness"
   ],
   "css/css-grid-1/alignment/grid-alignment-implies-size-change-019.html": [
-   "f611e34104ae873f1124032aa22621dfcf4fa128",
+   "f357a479479fb871c6e6eeb49ac028db55757d81",
    "testharness"
   ],
   "css/css-grid-1/alignment/grid-alignment-implies-size-change-020.html": [
-   "c0a3bf24655a77c05dce301b0173f18d0fa42234",
+   "4271df1342f4600e39f6ec3b1daae20ff369a5a8",
    "testharness"
   ],
   "css/css-grid-1/alignment/grid-alignment-implies-size-change-021.html": [
-   "e39bd0c869b5c69f99ddb0e43ecd516c23e22051",
+   "c72cbc118d7af2378cc2026ccd4eff5b2b3dada3",
    "testharness"
   ],
   "css/css-grid-1/alignment/grid-alignment-implies-size-change-022.html": [
-   "436855cb48c5de8f913f209ba8172644c0e97226",
+   "d1bcda40064849f8250ca423c07210ef6f7135da",
    "testharness"
   ],
   "css/css-grid-1/alignment/grid-alignment-implies-size-change-023.html": [
-   "07ea8b43529cc3abe597b5cbaf71b577c0e08a81",
+   "5ffaf7fb23cd317c684633b26ce027beb83aef20",
    "testharness"
   ],
   "css/css-grid-1/alignment/grid-alignment-implies-size-change-024.html": [
-   "4ef7fd0b4687fe9f08513cccff2707bb05d92a78",
+   "7c475cebcd650192507dadee416e5e5a7318f0f9",
    "testharness"
   ],
   "css/css-grid-1/alignment/grid-alignment-implies-size-change-025.html": [
-   "4ecabe7266535153ce6e38e1bee6e4eba28c5260",
+   "b5100c40529365ed36531bfca7310370f3cd017f",
    "testharness"
   ],
   "css/css-grid-1/alignment/grid-alignment-implies-size-change-026.html": [
-   "dc702a1d181ef4efcf4d5161ff1b10bbb8e08337",
+   "1e8a5e7c21da8a8197b2d35943d2c4a67050c583",
    "testharness"
   ],
   "css/css-grid-1/alignment/grid-alignment-implies-size-change-027.html": [
-   "a5646db94e62b9455c9ed44e9f1a86f1cda74153",
+   "1e87d9f38001a7a1407ee6983c3a4f7b1dc8da92",
    "testharness"
   ],
   "css/css-grid-1/alignment/grid-alignment-implies-size-change-028.html": [
-   "9940f6e83d28a45ad87a50b24afe5eca1c3ff596",
+   "a8d71f02f9233d070eb99cf3f7d9c9e69995c570",
    "testharness"
   ],
   "css/css-grid-1/alignment/grid-alignment-implies-size-change-029.html": [
-   "ed6197207c84d52614f2e4bda31aa0794ac244ce",
+   "cd4207c50b24057e84f52e2df9ee40df0bc1e490",
    "testharness"
   ],
   "css/css-grid-1/alignment/grid-alignment-implies-size-change-030.html": [
-   "df920f26e14d9adb3e987771b74f3ca21d001b9d",
+   "9fe22b9a8a575ad8176f3a657a9b9ddfe71a7753",
    "testharness"
   ],
   "css/css-grid-1/alignment/grid-alignment-implies-size-change-031.html": [
-   "24cdde781a98046593d3f0a57906b756326c4d83",
+   "082342d57257892308c3909c8ca4c3b270021551",
    "testharness"
   ],
   "css/css-grid-1/alignment/grid-alignment-implies-size-change-032.html": [
-   "489c89b0d82b3ad92e342db2b680b152e4bab404",
+   "8eb6d46e01bbc2383198ff4d906ce1c8053dd56d",
    "testharness"
   ],
   "css/css-grid-1/alignment/grid-alignment-implies-size-change-033.html": [
-   "4905906bd110e7b9ef3ad1ca4e0b01417b0998c8",
+   "151c7aebb20d2fe130351503641fdf200bfc1d3f",
    "testharness"
   ],
   "css/css-grid-1/alignment/grid-alignment-implies-size-change-034.html": [
-   "c9ef480494c982efd2cc2b6801eb0c308de0a608",
+   "d06920746566a28b934d301107b73e1d54c1aba5",
    "testharness"
   ],
   "css/css-grid-1/alignment/grid-alignment-implies-size-change-035.html": [
-   "f93f4f2a62aa2073676466dcfc5975556dd04739",
+   "d747922cd9b2711dff260de987a0242ea6989235",
    "testharness"
   ],
   "css/css-grid-1/alignment/grid-alignment-implies-size-change-036.html": [
-   "748d617dac4b7c97592967c0df1ee82f6a43cc0a",
+   "4739f523e02112bb7dd6638dc5b986d1d7bce44f",
    "testharness"
   ],
   "css/css-grid-1/alignment/grid-content-distribution-001.html": [
@@ -229712,199 +230019,199 @@
    "reftest"
   ],
   "css/css-grid-1/alignment/grid-fit-content-tracks-dont-stretch-001.html": [
-   "9fbe55ecef2ac64d864d6592cb9b81198acac261",
+   "04b805be2d4db49e730ec64ade4af951c510ad97",
    "testharness"
   ],
   "css/css-grid-1/alignment/grid-self-alignment-stretch-001.html": [
-   "faa0a4a8e6660d8bb12cec2ccbe86e8e23bcc936",
+   "917e0b3e2c98cface73510fb00b62e609ea94ecc",
    "testharness"
   ],
   "css/css-grid-1/alignment/grid-self-alignment-stretch-002.html": [
-   "735b425c34d147a32b97e60606a5d088389fecfc",
+   "a32fc988586c078db1c437a81a3a7b2fab2e921f",
    "testharness"
   ],
   "css/css-grid-1/alignment/grid-self-alignment-stretch-003.html": [
-   "7f5a41bc81b97bb4b62e55b69fa1ecfe241edaed",
+   "79346c92de73ab8e88c9ea86c963b99ec437854a",
    "testharness"
   ],
   "css/css-grid-1/alignment/grid-self-alignment-stretch-004.html": [
-   "0e12bf8b99c417c9176100f7b945b9a83d53f69c",
+   "5a02e719fc6d65cddd2dd97c2aedfbea1b0d7eae",
    "testharness"
   ],
   "css/css-grid-1/alignment/grid-self-alignment-stretch-005.html": [
-   "d28606de466e787ac8e4c1f742806c2bbf570a88",
+   "a33ab3b46bd68238bcafc86350f1bee36fb78373",
    "testharness"
   ],
   "css/css-grid-1/alignment/grid-self-alignment-stretch-006.html": [
-   "2ea3e018bf73940231af89dc72c2352fe2985732",
+   "61c927b4280011667fea7869eb82071d29dd2207",
    "testharness"
   ],
   "css/css-grid-1/alignment/grid-self-alignment-stretch-007.html": [
-   "d2ff7e0efbb1240bfa4b21b0d2e7eb0891950348",
+   "35a0411b69e1ee32e00b2894db7eb1e1e173cb15",
    "testharness"
   ],
   "css/css-grid-1/alignment/grid-self-alignment-stretch-008.html": [
-   "0ee2f7d1f4bed6383a762f86efa6dc2a8a27bf4b",
+   "fc0e18c677cbae1dab7bb55688fb60da6de0ff1e",
    "testharness"
   ],
   "css/css-grid-1/alignment/grid-self-alignment-stretch-009.html": [
-   "d64052253097bade696ff9c8bee42bfa8cca9604",
+   "9e836b1cbc598eaf29f40fa783ac1666441131a0",
    "testharness"
   ],
   "css/css-grid-1/alignment/grid-self-alignment-stretch-010.html": [
-   "9523288742cb15e2451b41b85596ff868b6b4648",
+   "8168c74fc8ea39b72e7327685231aa91a6985ceb",
    "testharness"
   ],
   "css/css-grid-1/alignment/grid-self-alignment-stretch-011.html": [
-   "9929a38f502a2e82ae93b6a39910eacb04ee6e58",
+   "e6bd704502d9dbe6ac453d92ebf7f61d5ec5805a",
    "testharness"
   ],
   "css/css-grid-1/alignment/grid-self-alignment-stretch-012.html": [
-   "9a19df31cfded6c4270da40070c3e8390c8366b2",
+   "618b7bbae71741c700534d8c5dcf7b471cccd52b",
    "testharness"
   ],
   "css/css-grid-1/alignment/grid-self-alignment-stretch-013.html": [
-   "a8cb352297f011b42b3740fd73f2f78f0bdca29d",
+   "4588a246fa623f272000d7d2ca95ff9413fa7ce2",
    "testharness"
   ],
   "css/css-grid-1/alignment/grid-self-alignment-stretch-014.html": [
-   "11e3cb854d0c9fb7535a7408a56e9f372acf7b74",
+   "eb5bf50d24837a38d7f1f70508030c0d83e22dfd",
    "testharness"
   ],
   "css/css-grid-1/alignment/grid-self-alignment-stretch-015.html": [
-   "7b145fe80d78b51f42f1a257e64b77f256324029",
+   "af43ff2ee5ea8f4bfc8eaca775f30bc56fce2429",
    "testharness"
   ],
   "css/css-grid-1/alignment/grid-self-alignment-stretch-016.html": [
-   "3d7b17fa76b3f21ccd882072158f25c723698b24",
+   "d7d3dd523cc6897b701b57dfdb41c13e93209eb2",
    "testharness"
   ],
   "css/css-grid-1/alignment/grid-self-alignment-stretch-vertical-lr-001.html": [
-   "613da8787ea601c01cd79348e68d94cbdf4f6c12",
+   "a541ceec457d826677469e1dde2f2fbdbc3f7448",
    "testharness"
   ],
   "css/css-grid-1/alignment/grid-self-alignment-stretch-vertical-lr-002.html": [
-   "bfbfeef9485cd0a842729d72ae6a7d2978fed0ee",
+   "8ee1d02283ddd96ab042e10f31e02d19998ee1f3",
    "testharness"
   ],
   "css/css-grid-1/alignment/grid-self-alignment-stretch-vertical-lr-003.html": [
-   "47f8fa7e366a0928a1ef6ee30d3e97898d10b882",
+   "a2039c7a3a995613595375b8dbd6f0a4d6eee077",
    "testharness"
   ],
   "css/css-grid-1/alignment/grid-self-alignment-stretch-vertical-lr-004.html": [
-   "0277d86138e1e5aecea0fcde768a48a8b841046c",
+   "6c24f14a89c33bc7813274c0818dc0842e9c1e83",
    "testharness"
   ],
   "css/css-grid-1/alignment/grid-self-alignment-stretch-vertical-lr-005.html": [
-   "b82ead09258f8746f6c7d4d9fd363b2bdfe2fe42",
+   "c7b147c20408781c3e3998f867a5878916960ed5",
    "testharness"
   ],
   "css/css-grid-1/alignment/grid-self-alignment-stretch-vertical-lr-006.html": [
-   "290d852faea189b602457356f6abf8df51f4e306",
+   "0cca9ab651aadb24b3fa17c2d991f8498aae49ec",
    "testharness"
   ],
   "css/css-grid-1/alignment/grid-self-alignment-stretch-vertical-lr-007.html": [
-   "f8418fe79ca641e453791ca1c202cdad50220b2e",
+   "8552960b768a80146861772e61c5ba66f49b2c59",
    "testharness"
   ],
   "css/css-grid-1/alignment/grid-self-alignment-stretch-vertical-lr-008.html": [
-   "10e77671b9a37de05f4898e035aa29fde999f64c",
+   "81be158b4ee68340a69586369ddfe38e2e4a5eb4",
    "testharness"
   ],
   "css/css-grid-1/alignment/grid-self-alignment-stretch-vertical-lr-009.html": [
-   "9f7f821d8fd60bf5ab47f5341a3a103afe94d3a8",
+   "067c428854205595ea4cb7bd94e4cd331428949e",
    "testharness"
   ],
   "css/css-grid-1/alignment/grid-self-alignment-stretch-vertical-lr-010.html": [
-   "f5327de3394428415fed804e4e79efc0fe963817",
+   "b53540415c065d41bf22d0d6f49708b5216695fb",
    "testharness"
   ],
   "css/css-grid-1/alignment/grid-self-alignment-stretch-vertical-lr-011.html": [
-   "a7aac5da4c4e085b14c77a0088a4d608c637f9bc",
+   "b6078329294d7b7a26722e0e9e82171cb250607f",
    "testharness"
   ],
   "css/css-grid-1/alignment/grid-self-alignment-stretch-vertical-lr-012.html": [
-   "b35ad113f09d62cb40cf4a16ff6faca82d73de35",
+   "55db10daf6be8aa2a75be718929bb0137ec668a7",
    "testharness"
   ],
   "css/css-grid-1/alignment/grid-self-alignment-stretch-vertical-lr-013.html": [
-   "5e97e65254d39476e883cb847d421a54496c71a8",
+   "84d9d4a608a03d5ef129abe2526b6fa55668492b",
    "testharness"
   ],
   "css/css-grid-1/alignment/grid-self-alignment-stretch-vertical-lr-014.html": [
-   "cf7374a5f900e4d6a675dc32a9181cfd1653075d",
+   "bbfe2d5190c6c4bcb208ec6f25990d52f75b7134",
    "testharness"
   ],
   "css/css-grid-1/alignment/grid-self-alignment-stretch-vertical-lr-015.html": [
-   "1ebbfc6564b9c8350fa618bea97ecab3fb44eade",
+   "f4dc41a4ce328418c9f572074f7b881104c805b2",
    "testharness"
   ],
   "css/css-grid-1/alignment/grid-self-alignment-stretch-vertical-lr-016.html": [
-   "74711c54c4c2148895e75132d9cebc225a9128a2",
+   "448d66b5757cb939fc9a3f03680ab1b9b8825ec3",
    "testharness"
   ],
   "css/css-grid-1/alignment/grid-self-alignment-stretch-vertical-rl-001.html": [
-   "a4d4dec0f3fb7f490c2e046d535d8f86a89ec519",
+   "ffe1ef9427e3847e89a0f59f5637bf94e80ca4f7",
    "testharness"
   ],
   "css/css-grid-1/alignment/grid-self-alignment-stretch-vertical-rl-002.html": [
-   "2ab21074fa42c487f294866c39859e06364715de",
+   "99cee6353da618a175033a2dbdb49315024ec083",
    "testharness"
   ],
   "css/css-grid-1/alignment/grid-self-alignment-stretch-vertical-rl-003.html": [
-   "695ee5fa198c111a3f8dcee1520938878b003410",
+   "327f6d87554010b433b90ae0363814d935398b23",
    "testharness"
   ],
   "css/css-grid-1/alignment/grid-self-alignment-stretch-vertical-rl-004.html": [
-   "6625c4aa82c02c86075a49d0485160b24f5ed5b6",
+   "9941214f81451e89e231d4e979ef21fae2d73cbb",
    "testharness"
   ],
   "css/css-grid-1/alignment/grid-self-alignment-stretch-vertical-rl-005.html": [
-   "5c400ff43392287f0203102c100ae1d286286e94",
+   "143ca0175c875529c74b9fd9a1cc2fe2067386ca",
    "testharness"
   ],
   "css/css-grid-1/alignment/grid-self-alignment-stretch-vertical-rl-006.html": [
-   "5c4f715f864ee0718a28cd56aef5bb63549042da",
+   "8d2a905743959c7a2f227f187286e3cb23f39e59",
    "testharness"
   ],
   "css/css-grid-1/alignment/grid-self-alignment-stretch-vertical-rl-007.html": [
-   "82b67b0f255a36275c9e2179f7c0a6c194b80881",
+   "6574fa2ea2a9776689367c4f64edaf5c8c844736",
    "testharness"
   ],
   "css/css-grid-1/alignment/grid-self-alignment-stretch-vertical-rl-008.html": [
-   "df9a693d3d6a7ecfb8767b1e53af0f71b54e4cac",
+   "f201af5919cc79fa8a3834900048c7fe2a794a72",
    "testharness"
   ],
   "css/css-grid-1/alignment/grid-self-alignment-stretch-vertical-rl-009.html": [
-   "9223ee50b9c22c737e42f113e67418c3b9f42312",
+   "59047d7646baef9aac63ed8c130030bc4725c780",
    "testharness"
   ],
   "css/css-grid-1/alignment/grid-self-alignment-stretch-vertical-rl-010.html": [
-   "065d965da5145e629517941de214c53a990e7d04",
+   "60d4108239c5ca52d7998f8b1882dd7adf38b567",
    "testharness"
   ],
   "css/css-grid-1/alignment/grid-self-alignment-stretch-vertical-rl-011.html": [
-   "819fb3899679610911df95110f051973ef4fcbb6",
+   "9c868b3e52a6604a9ee810a58f811fae92a48fa1",
    "testharness"
   ],
   "css/css-grid-1/alignment/grid-self-alignment-stretch-vertical-rl-012.html": [
-   "52459738d7455d7ed97045aea124b2160d37643a",
+   "87e41d80af965f86f5d43a9594cc324e1b365d9b",
    "testharness"
   ],
   "css/css-grid-1/alignment/grid-self-alignment-stretch-vertical-rl-013.html": [
-   "09be06f107f5ea97fc6db45b8bca150e10dc7296",
+   "cbc79b5b2b117ed2e1e286c91e6ce92b57d3112a",
    "testharness"
   ],
   "css/css-grid-1/alignment/grid-self-alignment-stretch-vertical-rl-014.html": [
-   "0270a89bde2e54d3108d8ab8b8dbb3f64ae855af",
+   "526ea2640f2fc150bd90f1eb7552686d39437906",
    "testharness"
   ],
   "css/css-grid-1/alignment/grid-self-alignment-stretch-vertical-rl-015.html": [
-   "f49ae99abd185af7bc9937c16bb7f4bb2044bdc6",
+   "9c97198c58873215469e20469219fa29197ba2b3",
    "testharness"
   ],
   "css/css-grid-1/alignment/grid-self-alignment-stretch-vertical-rl-016.html": [
-   "86d478dee444129ccd10f76aed6d80c75251ff13",
+   "a60c43c1c32b908c3df899f3cba0ddf1c0fb0824",
    "testharness"
   ],
   "css/css-grid-1/alignment/self-baseline/grid-self-baseline-changes-grid-area-size-001.html": [
@@ -229964,7 +230271,7 @@
    "reftest"
   ],
   "css/css-grid-1/grid-definition/grid-change-fit-content-argument-001.html": [
-   "acde93379376d7e845b780a751ac5c8818d74948",
+   "3bb5904f2a6c36b0575c395a3cc1b008e4cbcf0c",
    "testharness"
   ],
   "css/css-grid-1/grid-definition/grid-inline-support-flexible-lengths-001.html": [
@@ -230412,7 +230719,7 @@
    "reftest"
   ],
   "css/css-grid-1/grid-model/grid-box-sizing-001.html": [
-   "fe071fc877fb900b6e138b1fb28623bbb319f5b6",
+   "69eb267879e0b899efa996f4923414f72ecc52bf",
    "testharness"
   ],
   "css/css-grid-1/grid-model/grid-computed-value-display-floated-items-001.html": [
@@ -230615,10 +230922,6 @@
    "feb53485e24aeaf9a5f27be5e42cc4a6fc5b8df0",
    "support"
   ],
-  "css/css-grid-1/support/check-layout-th.js": [
-   "86c180327b87c617cdf8fa65fb079df08a0983e7",
-   "support"
-  ],
   "css/css-grid-1/support/grid-alignment.css": [
    "b45aee51245613ceddf8eda70d995a26027671bd",
    "support"
@@ -232428,7 +232731,7 @@
    "testharness"
   ],
   "css/css-tables-3/fixed-layout-calc-width-001.html": [
-   "0b8262ca3abd6104e86c305d738a2c70f6cb1f87",
+   "df167ec3c296c684230a8be95c1411c2329b87d9",
    "testharness"
   ],
   "css/css-tables-3/fixed-layout-excess-width-distribution-001-expected.txt": [
@@ -232436,7 +232739,7 @@
    "support"
   ],
   "css/css-tables-3/fixed-layout-excess-width-distribution-001.html": [
-   "36b7b7893dba1f3ddc2edf46fee323d75e5af49d",
+   "d0cdc5a206aa1b70ece371ff65bfbfeac7adcb2f",
    "testharness"
   ],
   "css/css-tables-3/floats/floats-wrap-bfc-006b-ref.xht": [
@@ -232523,10 +232826,6 @@
    "abe7468e88cad3aef32c7e59fa4a33a7930ef53b",
    "support"
   ],
-  "css/css-tables-3/support/check-layout-th.js": [
-   "86c180327b87c617cdf8fa65fb079df08a0983e7",
-   "support"
-  ],
   "css/css-tables-3/table-model-fixup-2.html": [
    "19e3577e862601a0cf00dd4644017218c363f0db",
    "testharness"
@@ -249815,6 +250114,10 @@
    "82a6920db4d0be087e6ed621313ecf92e3e2ed68",
    "testharness"
   ],
+  "cssom-view/overscrollBehavior-manual.html": [
+   "ca369af991f1e1c34116f2effe0d53a806ed9df5",
+   "manual"
+  ],
   "cssom-view/resources/elementsFromPoint.js": [
    "0c31158817d4d6f9e59df0d2ebe0e41c6ce41bb5",
    "support"
@@ -249827,10 +250130,6 @@
    "0a8784c474ccdd4a3e76cb936855a8ef59566217",
    "support"
   ],
-  "cssom-view/overscrollBehavior-manual.html": [
-   "987051cdbad355cbb1bbb8ea1030a3b17e533f09",
-   "manual"
-  ],
   "cssom-view/scrollIntoView-shadow.html": [
    "3c4a18992105fd7bf19cbf29f0b6d80cb12ca98c",
    "testharness"
@@ -255756,17 +256055,13 @@
    "testharness"
   ],
   "fetch/api/request/request-cache-force-cache-expected.txt": [
-   "fb85a7bd372168eeb61f5a8921a77c3df329fead",
+   "c1a812e73eaed7caf0bc1f568e93935362d9fb6f",
    "support"
   ],
   "fetch/api/request/request-cache-force-cache.html": [
    "290ddf79c62c0a753bc6d22e136f815662c00cc8",
    "testharness"
   ],
-  "fetch/api/request/request-cache-no-cache-expected.txt": [
-   "0149c40a255e489193c5c71f07394fb793dbe903",
-   "support"
-  ],
   "fetch/api/request/request-cache-no-cache.html": [
    "457b8c8f6347f32eedf1bb7af881259a8a08e068",
    "testharness"
@@ -255779,10 +256074,6 @@
    "245129d1d5239af70fc48e0da664bba5c004ded8",
    "testharness"
   ],
-  "fetch/api/request/request-cache-only-if-cached-expected.txt": [
-   "5adb820773a93d2f67a1cfab5947dcfcbc3d488d",
-   "support"
-  ],
   "fetch/api/request/request-cache-only-if-cached.html": [
    "25b18acb3552b1a431532c2b8e57b872aa511e7c",
    "testharness"
@@ -260328,7 +260619,7 @@
    "testharness"
   ],
   "html/dom/elements-embedded.js": [
-   "5d5d208f38657e9fda1741654909c29807e67d13",
+   "2c20b7d2856d8f7f72b7835b2677ed47abc43629",
    "support"
   ],
   "html/dom/elements-forms.js": [
@@ -261180,7 +261471,7 @@
    "support"
   ],
   "html/dom/interfaces-expected.txt": [
-   "2539115cc7d3162b45e92d9a1541963edfc2b6e4",
+   "9d4a858c84e413af3f599066db6e75c49bdb9a04",
    "support"
   ],
   "html/dom/interfaces.html": [
@@ -261204,7 +261495,7 @@
    "support"
   ],
   "html/dom/reflection-embedded-expected.txt": [
-   "e61530b9d8964c39c65d362481c31065ac0d64de",
+   "22b36aa05ed600f98679502c700de867de26c138",
    "support"
   ],
   "html/dom/reflection-embedded.html": [
@@ -264859,6 +265150,18 @@
    "270a8c31ce78e9ae07d8169367224051baf91fd8",
    "testharness"
   ],
+  "html/editing/focus/processing-model/preventScroll-expected.txt": [
+   "5987135d08933b9e5ad9b5e46c06461a6fcbfeec",
+   "support"
+  ],
+  "html/editing/focus/processing-model/preventScroll.html": [
+   "fca882d5c3a5a78e486d6527d8b0cbf09d23c3e7",
+   "testharness"
+  ],
+  "html/editing/focus/processing-model/support/preventScroll-helper.html": [
+   "ffd270caa596ffb41d5b5f1cdca450fb20a5fded",
+   "support"
+  ],
   "html/editing/focus/sequential-focus-navigation-and-the-tabindex-attribute/.gitkeep": [
    "da39a3ee5e6b4b0d3255bfef95601890afd80709",
    "support"
@@ -269112,7 +269415,7 @@
    "testharness"
   ],
   "html/semantics/embedded-content/the-object-element/object-attributes-expected.txt": [
-   "ec830c03d6014ff85d04cb925b69af99fcbc869b",
+   "71191145d5ede61021ea60606904c203f4f0b81c",
    "support"
   ],
   "html/semantics/embedded-content/the-object-element/object-attributes.html": [
@@ -275071,6 +275374,10 @@
    "f585014db144083ee2f70f6fd65f78bf2e289093",
    "manual"
   ],
+  "interfaces/ambient-light.idl": [
+   "bdede54deab80b5465f904a9726ee86f1260858d",
+   "support"
+  ],
   "interfaces/clipboard.idl": [
    "5af2846c7f9ff93f2f4f13780d0356cdac6a0d4f",
    "support"
@@ -275108,7 +275415,7 @@
    "support"
   ],
   "interfaces/html.idl": [
-   "72c1401cb1c68b8415f631925a0718d728c2d966",
+   "30bf215678945a0b5732673d0364cbd64867095e",
    "support"
   ],
   "interfaces/mediacapture-main.idl": [
@@ -275204,7 +275511,7 @@
    "testharness"
   ],
   "intersection-observer/observer-exceptions.html": [
-   "28ccc6905713894b43033e30949170439215bf2e",
+   "85d5416475091c1020e0ff92b15f841bf58c606e",
    "testharness"
   ],
   "intersection-observer/observer-in-iframe.html": [
@@ -293287,12 +293594,20 @@
    "8192f07581fe6d258c8b404d2a436e00b50fb459",
    "support"
   ],
+  "secure-contexts/basic-dedicated-worker-expected.txt": [
+   "58c95513a3aa5f96cf7494958c979e9dd36ddf98",
+   "support"
+  ],
   "secure-contexts/basic-dedicated-worker.html": [
-   "075f4170b133fe13e282ff5450871ef7960faf50",
+   "3e2dc8d37996552fc830ee6931f67091e83aa174",
    "testharness"
   ],
+  "secure-contexts/basic-dedicated-worker.https-expected.txt": [
+   "10263e5a8c3639c74e04bb19f174b62f8357526d",
+   "support"
+  ],
   "secure-contexts/basic-dedicated-worker.https.html": [
-   "05beced009e36f577a1393f80198158f3d37063c",
+   "13ce3f1a8ef03b87cca968fd3710d968f35a2439",
    "testharness"
   ],
   "secure-contexts/basic-popup-and-iframe-tests.html": [
@@ -293304,13 +293619,21 @@
    "testharness"
   ],
   "secure-contexts/basic-popup-and-iframe-tests.https.js": [
-   "26c7c307334b8a0e10265cf6fe3664d84cdd72cc",
+   "edc438d81762f199c6e7ffa7f638f74d9b6af701",
+   "support"
+  ],
+  "secure-contexts/basic-shared-worker-expected.txt": [
+   "5a2e6c596d22c1224101d37ade49b6b2da4c2e43",
    "support"
   ],
   "secure-contexts/basic-shared-worker.html": [
    "c9e83a73d9dfdf9880bc27f5f9ae5c20c918715d",
    "testharness"
   ],
+  "secure-contexts/basic-shared-worker.https-expected.txt": [
+   "c56ad15b99b5962393ba44d8dcfd488e793719c1",
+   "support"
+  ],
   "secure-contexts/basic-shared-worker.https.html": [
    "7241035c47bc2a0251826d2c9ad3bc5f9acd61d2",
    "testharness"
@@ -293327,12 +293650,20 @@
    "557c6bc670e807004ca08df15af14ca9edaa26aa",
    "support"
   ],
+  "secure-contexts/shared-worker-insecure-first.https-expected.txt": [
+   "a585cbf46dbea81b02ef31a97d5f17b57b023dd8",
+   "support"
+  ],
   "secure-contexts/shared-worker-insecure-first.https.html": [
    "81c9cd152b620dd70b11b72db021f4324dad16fa",
    "testharness"
   ],
+  "secure-contexts/shared-worker-secure-first.https-expected.txt": [
+   "9a3bb6ff5597556508208f56bbdd4180a16716cb",
+   "support"
+  ],
   "secure-contexts/shared-worker-secure-first.https.html": [
-   "38c411b3a8fa1acf9d87e4f68c58a52f54c3d379",
+   "cdb342e7b302d5a0bf7d282788f0e0292a486285",
    "testharness"
   ],
   "secure-contexts/support/dedicated-worker-script.js": [
@@ -293340,7 +293671,7 @@
    "support"
   ],
   "secure-contexts/support/https-subframe-dedicated.html": [
-   "5a9c1cee739efbad41f2ef6c4d70eda1f7b01646",
+   "a022992d2cf1ac230bcbbb988b3e83c94c50957e",
    "support"
   ],
   "secure-contexts/support/https-subframe-shared.html": [
@@ -293348,11 +293679,11 @@
    "support"
   ],
   "secure-contexts/support/parent-dedicated-worker-script.js": [
-   "f30fd69030eb48c6d98f07f0f61cf7c75410991f",
+   "f900be624e6fbecbbfc164439f25045bb0612996",
    "support"
   ],
   "secure-contexts/support/parent-shared-worker-script.js": [
-   "fe110557d01f13b1b62606bf39d4ed54ebb5eb23",
+   "a7b5ffa139addf2af9f40b088b8996e0a5a4d26d",
    "support"
   ],
   "secure-contexts/support/shared-worker-insecure-popup.html": [
@@ -294144,11 +294475,11 @@
    "testharness"
   ],
   "service-workers/service-worker/fetch-event.https-expected.txt": [
-   "fc4af5afdb5ff77cb3bd614f7f10ae6fde50af96",
+   "719610ce6e2204dfa1be68776658340a0787dfc7",
    "support"
   ],
   "service-workers/service-worker/fetch-event.https.html": [
-   "8fb51ce7439e3b8ee21eb5bc8924b2db884fd412",
+   "22cfed652ec3779afae9ec77fda14ad0de9f03ba",
    "testharness"
   ],
   "service-workers/service-worker/fetch-frame-resource.https.html": [
@@ -294663,10 +294994,6 @@
    "785a18ac3c8001034f583a8e97195aa47093bd0d",
    "testharness"
   ],
-  "service-workers/service-worker/request-body-blob.https.html": [
-   "14dcf42e1dbfdc7589f9df64e2622cc599411174",
-   "testharness"
-  ],
   "service-workers/service-worker/request-end-to-end.https.html": [
    "ee9f8140b492daf89cb715643ee40557f6ed904e",
    "testharness"
@@ -294928,7 +295255,7 @@
    "support"
   ],
   "service-workers/service-worker/resources/fetch-event-test-worker.js": [
-   "f9eab9a493f43ec5a8a662815a979e70fb3e3900",
+   "f42ca5c4f05c89df3bb37249ed4b09af0aae25be",
    "support"
   ],
   "service-workers/service-worker/resources/fetch-event-within-sw-worker.js": [
@@ -295411,14 +295738,6 @@
    "7fb39d9609893a0fbcada161c92dc3df40721f90",
    "support"
   ],
-  "service-workers/service-worker/resources/request-body-blob-iframe.html": [
-   "b1f805a1120f3728a0e7accbc62041363e668ab0",
-   "support"
-  ],
-  "service-workers/service-worker/resources/request-body-blob-worker.js": [
-   "867de00970be85ce6fbe25c175191450eb83c906",
-   "support"
-  ],
   "service-workers/service-worker/resources/request-end-to-end-worker.js": [
    "984ea18286a9fa7446562a77284b942fa7e5217c",
    "support"
@@ -298547,95 +298866,95 @@
    "a4fed30c25d50d5ce774e4e5b431efa99f73ecf3",
    "support"
   ],
-  "viewport/viewport-attribute-event-handlers-manual.html": [
+  "visual-viewport/viewport-attribute-event-handlers-manual.html": [
    "09901d9056f2e31f630becdd07f800e00496700a",
    "manual"
   ],
-  "viewport/viewport-dimensions-custom-scrollbars-manual.html": [
+  "visual-viewport/viewport-dimensions-custom-scrollbars-manual.html": [
    "ccef0829da2e4ebcad983235f97a6f3f767a0f51",
    "manual"
   ],
-  "viewport/viewport-dimensions-scrollbars-manual.html": [
+  "visual-viewport/viewport-dimensions-scrollbars-manual.html": [
    "465eb63a9f09880f98636502d4b3ee3b5e3ec794",
    "manual"
   ],
-  "viewport/viewport-no-resize-event-on-overflow-recalc.html": [
+  "visual-viewport/viewport-no-resize-event-on-overflow-recalc.html": [
    "f4d6cb3f76e4cf790875b3be90de821a279b3d82",
    "testharness"
   ],
-  "viewport/viewport-offset-manual.html": [
+  "visual-viewport/viewport-offset-manual.html": [
    "1d39d721a49e44d87583cb173cf0bba648fba352",
    "manual"
   ],
-  "viewport/viewport-page-manual.html": [
+  "visual-viewport/viewport-page-manual.html": [
    "1431cc6a8495343697c01ef62d237c31a5850e99",
    "manual"
   ],
-  "viewport/viewport-read-size-causes-layout.html": [
+  "visual-viewport/viewport-read-size-causes-layout.html": [
    "64a511ff2dd9c0381588b56b15fe1c82e0b1e07a",
    "testharness"
   ],
-  "viewport/viewport-read-size-in-iframe-causes-layout.html": [
+  "visual-viewport/viewport-read-size-in-iframe-causes-layout.html": [
    "8bf7b6c1a5721da2c1d1fc896d62a44893446a73",
    "testharness"
   ],
-  "viewport/viewport-resize-event-manual.html": [
+  "visual-viewport/viewport-resize-event-manual.html": [
    "38280c144ed74af990ebf9b65ad1d68052f93372",
    "manual"
   ],
-  "viewport/viewport-resize-event-on-load-overflowing-page.html": [
+  "visual-viewport/viewport-resize-event-on-load-overflowing-page.html": [
    "cd13682091b00c182e570a87eac642613a3c05c2",
    "testharness"
   ],
-  "viewport/viewport-scale-iframe-manual.html": [
+  "visual-viewport/viewport-scale-iframe-manual.html": [
    "4ccf4a4bb7d13bc12afc6d9bbbc8072b460f87ec",
    "manual"
   ],
-  "viewport/viewport-scale-manual.html": [
+  "visual-viewport/viewport-scale-manual.html": [
    "fd089f974778969d95cd7f6aa6389a6cf9dfb543",
    "manual"
   ],
-  "viewport/viewport-scroll-event-manual.html": [
+  "visual-viewport/viewport-scroll-event-manual.html": [
    "43e7031d3734a1c377e64d0f6a8247fef0782ceb",
    "manual"
   ],
-  "viewport/viewport-scrollbars-cause-resize.html": [
+  "visual-viewport/viewport-scrollbars-cause-resize.html": [
    "a1017cff8faadfdcae008fd5f27e9c8e7c5383d3",
    "testharness"
   ],
-  "viewport/viewport-type.html": [
+  "visual-viewport/viewport-type.html": [
    "45334f4775607cd8547788e4107e81b03fad319f",
    "testharness"
   ],
-  "viewport/viewport-unscaled-scale-iframe.html": [
+  "visual-viewport/viewport-unscaled-scale-iframe.html": [
    "d88c0bd1ce525137fb739182a35ae22bd6455c0f",
    "testharness"
   ],
-  "viewport/viewport-unscaled-scale.html": [
+  "visual-viewport/viewport-unscaled-scale.html": [
    "eb5a1e32e015808651f008ebaaa785ec84d7a1f3",
    "testharness"
   ],
-  "viewport/viewport-unscaled-scroll-iframe.html": [
+  "visual-viewport/viewport-unscaled-scroll-iframe.html": [
    "14e88914da4ce92b90cb191278aaa0a26e00ee7a",
    "testharness"
   ],
-  "viewport/viewport-unscaled-scroll.html": [
+  "visual-viewport/viewport-unscaled-scroll.html": [
    "12f4366f75a8fb078e1691c3ad091ea15a8561f9",
    "testharness"
   ],
-  "viewport/viewport-unscaled-size-iframe.html": [
+  "visual-viewport/viewport-unscaled-size-iframe.html": [
    "937198c3bf9f26413c35e48f90b5b3b35e1c96a2",
    "testharness"
   ],
-  "viewport/viewport-unscaled-size.html": [
+  "visual-viewport/viewport-unscaled-size.html": [
    "e92beb18c8adcf1f7d89cfa0512df46765440a5a",
    "testharness"
   ],
-  "viewport/viewport-url-bar-changes-height-manual.html": [
+  "visual-viewport/viewport-url-bar-changes-height-manual.html": [
    "6b7e0dfc4b8bf51f7e5799a3089c2263e6dac63d",
    "manual"
   ],
-  "viewport/viewport_support.js": [
+  "visual-viewport/viewport_support.js": [
    "2e2e9480e8ccca07d4334d957b6a1c597a1f8fbd",
    "support"
   ],
@@ -299319,6 +299638,34 @@
    "230684ec60fd2e408f9b6014417f3eddfe2dc95a",
    "support"
   ],
+  "webaudio/chrome/resources/audioparam-testing.js": [
+   "2855fbee30e629ea397166911b9bcdec74bd4fdf",
+   "support"
+  ],
+  "webaudio/chrome/resources/audit-util.js": [
+   "4405458b8f8bdc621c95c1d9ec1c1ad4e6002f1e",
+   "support"
+  ],
+  "webaudio/chrome/resources/audit.js": [
+   "7f7051364808eadc207207a7dadcc191a95a2db3",
+   "support"
+  ],
+  "webaudio/chrome/resources/start-stop-exceptions.js": [
+   "70e0f890a721786f8afa4cd032e75ef85b5fc6bb",
+   "support"
+  ],
+  "webaudio/chrome/the-constantsourcenode-interface/constant-source-basic.html": [
+   "7c9fed4798e8119ca3cedda3958788fe989d4dd4",
+   "testharness"
+  ],
+  "webaudio/chrome/the-constantsourcenode-interface/constant-source-onended.html": [
+   "10f6b84a4c8de1a8b689cc443f2526b0455a4d27",
+   "testharness"
+  ],
+  "webaudio/chrome/the-constantsourcenode-interface/constant-source-output.html": [
+   "ff83b807b7a39fa40ad3df8db42c20eb859f34a8",
+   "testharness"
+  ],
   "webaudio/historical.html": [
    "93068df297042344669093ce899f0230c87ebf54",
    "testharness"
@@ -300376,11 +300723,11 @@
    "support"
   ],
   "webrtc/RTCPeerConnection-setRemoteDescription-offer-expected.txt": [
-   "a3b91255480d09eaab9121aa546fc73a7be16d63",
+   "e14aa0307eada138c7cad59e897ebf0c864ef272",
    "support"
   ],
   "webrtc/RTCPeerConnection-setRemoteDescription-offer.html": [
-   "ce5345bbaf5b5230b1fd53bbb55ab4439c3eb979",
+   "34337ef2126bfe276675db8884cd2a9aaa2d4432",
    "testharness"
   ],
   "webrtc/RTCPeerConnection-setRemoteDescription-pranswer-expected.txt": [
@@ -300780,7 +301127,7 @@
    "support"
   ],
   "websockets/README.md": [
-   "1b8473c8d482b7628fc7337e263c78aca7ca5088",
+   "42c6183f2b71442d96a023f2c05ab6ed10f06180",
    "support"
   ],
   "websockets/Secure-Close-1000-reason.htm": [
@@ -305980,11 +306327,19 @@
    "support"
   ],
   "worklets/animation-worklet-import.html": [
-   "42ad4c05fb7093051344351c7b8802f8ef8fbf4c",
+   "6e92613e720ac1fa1cdec91665cc1ca68a6e0bc8",
+   "testharness"
+  ],
+  "worklets/animation-worklet-referrer.html": [
+   "7c6e4a94815093e9353d184b877046ad7627bae9",
    "testharness"
   ],
   "worklets/paint-worklet-import.html": [
-   "0319b5195ba14348c6b5031d1198c5f401d13938",
+   "a1a5fe53abb00fe37c7688032038110a67f988ee",
+   "testharness"
+  ],
+  "worklets/paint-worklet-referrer.html": [
+   "86e7c0fe4de0764a7064ed22eef2b66ab09d4a62",
    "testharness"
   ],
   "worklets/resources/empty-worklet-script.js": [
@@ -306004,13 +306359,29 @@
    "support"
   ],
   "worklets/resources/import-tests.js": [
-   "7fd020b68f1ef3fc0bf8d057d30af3970f9b06cd",
+   "62d2e0030328c0d0f64ccfff2402634a3e99c637",
+   "support"
+  ],
+  "worklets/resources/referrer-tests.js": [
+   "47d8ae6d90b88ab8fb856e305b1599a34173852f",
+   "support"
+  ],
+  "worklets/resources/referrer-window.html": [
+   "d098da333b3c3c27999c7436af5e2f986bf9df28",
+   "support"
+  ],
+  "worklets/resources/referrer.py": [
+   "ed296faa934f89efcca9a116f6a2e931cafd831e",
    "support"
   ],
   "worklets/resources/throwing-worklet-script.js": [
    "a7164f899afec387321c7737aa1006aa5f225669",
    "support"
   ],
+  "worklets/resources/worklet-test-utils.js": [
+   "f05d557ba57bca35228a5ebbc418816cc3d01ee4",
+   "support"
+  ],
   "x-frame-options/OWNERS": [
    "fad08f267635717c6a2930de14df27107039b3a8",
    "support"
diff --git a/third_party/WebKit/LayoutTests/external/wpt/README.md b/third_party/WebKit/LayoutTests/external/wpt/README.md
index 1f713ba..f91ec5f 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/README.md
+++ b/third_party/WebKit/LayoutTests/external/wpt/README.md
@@ -108,6 +108,15 @@
 brew install nss
 ```
 
+On other platforms, download the firefox archive and common.tests.zip
+archive for your platform from
+[https://archive.mozilla.org/pub/firefox/nightly/latest-mozilla-central/](Mozilla CI)
+
+Then extract `certutil[.exe]` from the tests.zip package and
+`libnss3[.so|.dll|.dynlib]` and put the former on your path and the latter on
+your library path.
+
+
 Command Line Tools
 ==================
 
diff --git a/third_party/WebKit/LayoutTests/external/wpt/compat/historical-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/compat/historical-expected.txt
deleted file mode 100644
index f4a68fc5..0000000
--- a/third_party/WebKit/LayoutTests/external/wpt/compat/historical-expected.txt
+++ /dev/null
@@ -1,6 +0,0 @@
-This is a testharness.js-based test.
-FAIL getMatchedCSSRules() should not exist assert_false: expected false got true
-PASS webkitHidden should not exist
-PASS webkitVisibilityState should not exist
-Harness: the test ran to completion.
-
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-flexbox-1/percentage-heights-000.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-flexbox-1/percentage-heights-000.html
index 136ef2b..c23a439 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/css/css-flexbox-1/percentage-heights-000.html
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-flexbox-1/percentage-heights-000.html
@@ -34,7 +34,7 @@
 </style>
 <script src="/resources/testharness.js"></script>
 <script src="/resources/testharnessreport.js"></script>
-<script src="support/check-layout-th.js"></script>
+<script src="/resources/check-layout-th.js">"></script>
 <body onload="checkLayout('.flexbox')">
 <div id=log></div>
 
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-flexbox-1/percentage-heights-001.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-flexbox-1/percentage-heights-001.html
index f24eee9..6550206 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/css/css-flexbox-1/percentage-heights-001.html
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-flexbox-1/percentage-heights-001.html
@@ -9,7 +9,7 @@
 
 <script src="/resources/testharness.js"></script>
 <script src="/resources/testharnessreport.js"></script>
-<script src="support/check-layout-th.js"></script>
+<script src="/resources/check-layout-th.js">"></script>
 
 <style>
 .rect {
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-flexbox-1/position-absolute-001.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-flexbox-1/position-absolute-001.html
index d3d8089..2e65533a 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/css/css-flexbox-1/position-absolute-001.html
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-flexbox-1/position-absolute-001.html
@@ -80,7 +80,7 @@
 </style>
 <script src="/resources/testharness.js"></script>
 <script src="/resources/testharnessreport.js"></script>
-<script src="support/check-layout-th.js"></script>
+<script src="/resources/check-layout-th.js">"></script>
 <body onload="checkLayout('.flexbox')">
 <div id=log></div>
 <script>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-flexbox-1/position-absolute-002.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-flexbox-1/position-absolute-002.html
index bf69765..9c1cc42 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/css/css-flexbox-1/position-absolute-002.html
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-flexbox-1/position-absolute-002.html
@@ -67,7 +67,7 @@
 
 <script src="/resources/testharness.js"></script>
 <script src="/resources/testharnessreport.js"></script>
-<script src="support/check-layout-th.js"></script>
+<script src="/resources/check-layout-th.js">"></script>
 
 <body onload="checkLayout('.flexbox')">
 <div id=log></div>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-flexbox-1/position-absolute-003.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-flexbox-1/position-absolute-003.html
index 025aef6f..94763c8 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/css/css-flexbox-1/position-absolute-003.html
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-flexbox-1/position-absolute-003.html
@@ -25,7 +25,7 @@
 
 <script src="/resources/testharness.js"></script>
 <script src="/resources/testharnessreport.js"></script>
-<script src="support/check-layout-th.js"></script>
+<script src="/resources/check-layout-th.js">"></script>
 
 <body onload="checkLayout('.rect')">
 <div id=log></div>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-flexbox-1/position-absolute-004.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-flexbox-1/position-absolute-004.html
index ff14f35b..aa8ee516 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/css/css-flexbox-1/position-absolute-004.html
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-flexbox-1/position-absolute-004.html
@@ -25,7 +25,7 @@
 
 <script src="/resources/testharness.js"></script>
 <script src="/resources/testharnessreport.js"></script>
-<script src="support/check-layout-th.js"></script>
+<script src="/resources/check-layout-th.js">"></script>
 
 <script>
 function update() {
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-flexbox-1/support/check-layout-th.js b/third_party/WebKit/LayoutTests/external/wpt/css/css-flexbox-1/support/check-layout-th.js
deleted file mode 100644
index 9b83df7..0000000
--- a/third_party/WebKit/LayoutTests/external/wpt/css/css-flexbox-1/support/check-layout-th.js
+++ /dev/null
@@ -1,197 +0,0 @@
-(function() {
-// Test is initiated from body.onload, so explicit done() call is required.
-setup({ explicit_done: true });
-
-function checkSubtreeExpectedValues(t, parent, prefix)
-{
-    var checkedLayout = checkExpectedValues(t, parent, prefix);
-    Array.prototype.forEach.call(parent.childNodes, function(node) {
-        checkedLayout |= checkSubtreeExpectedValues(t, node, prefix);
-    });
-    return checkedLayout;
-}
-
-function checkAttribute(output, node, attribute)
-{
-    var result = node.getAttribute && node.getAttribute(attribute);
-    output.checked |= !!result;
-    return result;
-}
-
-function assert_tolerance(actual, expected, message)
-{
-    if (isNaN(expected) || Math.abs(actual - expected) >= 1) {
-        assert_equals(actual, Number(expected), message);
-    }
-}
-
-function checkExpectedValues(t, node, prefix)
-{
-    var output = { checked: false };
-
-    var expectedWidth = checkAttribute(output, node, "data-expected-width");
-    if (expectedWidth) {
-        assert_tolerance(node.offsetWidth, expectedWidth, prefix + "width");
-    }
-
-    var expectedHeight = checkAttribute(output, node, "data-expected-height");
-    if (expectedHeight) {
-        assert_tolerance(node.offsetHeight, expectedHeight, prefix + "height");
-    }
-
-    var expectedOffset = checkAttribute(output, node, "data-offset-x");
-    if (expectedOffset) {
-        assert_tolerance(node.offsetLeft, expectedOffset, prefix + "offsetLeft");
-    }
-
-    var expectedOffset = checkAttribute(output, node, "data-offset-y");
-    if (expectedOffset) {
-        assert_tolerance(node.offsetTop, expectedOffset, prefix + "offsetTop");
-    }
-
-    var expectedWidth = checkAttribute(output, node, "data-expected-client-width");
-    if (expectedWidth) {
-        assert_tolerance(node.clientWidth, expectedWidth, prefix + "clientWidth");
-    }
-
-    var expectedHeight = checkAttribute(output, node, "data-expected-client-height");
-    if (expectedHeight) {
-        assert_tolerance(node.clientHeight, expectedHeight, prefix + "clientHeight");
-    }
-
-    var expectedWidth = checkAttribute(output, node, "data-expected-scroll-width");
-    if (expectedWidth) {
-        assert_tolerance(node.scrollWidth, expectedWidth, prefix + "scrollWidth");
-    }
-
-    var expectedHeight = checkAttribute(output, node, "data-expected-scroll-height");
-    if (expectedHeight) {
-        assert_tolerance(node.scrollHeight, expectedHeight, prefix + "scrollHeight");
-    }
-
-    var expectedWidth = checkAttribute(output, node, "data-expected-bounding-client-rect-width");
-    if (expectedWidth) {
-        assert_tolerance(node.getBoundingClientRect().width, expectedWidth, prefix + "getBoundingClientRect().width");
-    }
-
-    var expectedOffset = checkAttribute(output, node, "data-total-x");
-    if (expectedOffset) {
-        var totalLeft = node.clientLeft + node.offsetLeft;
-        assert_tolerance(totalLeft, expectedOffset, prefix +
-                         "clientLeft+offsetLeft (" + node.clientLeft + " + " + node.offsetLeft + ")");
-    }
-
-    var expectedOffset = checkAttribute(output, node, "data-total-y");
-    if (expectedOffset) {
-        var totalTop = node.clientTop + node.offsetTop;
-        assert_tolerance(totalTop, expectedOffset, prefix +
-                         "clientTop+offsetTop (" + node.clientTop + " + " + node.offsetTop + ")");
-    }
-
-    var expectedDisplay = checkAttribute(output, node, "data-expected-display");
-    if (expectedDisplay) {
-        var actualDisplay = getComputedStyle(node).display;
-        assert_equals(actualDisplay, expectedDisplay, prefix + "display");
-    }
-
-    var expectedPaddingTop = checkAttribute(output, node, "data-expected-padding-top");
-    if (expectedPaddingTop) {
-        var actualPaddingTop = getComputedStyle(node).paddingTop;
-        // Trim the unit "px" from the output.
-        actualPaddingTop = actualPaddingTop.slice(0, -2);
-        assert_equals(actualPaddingTop, expectedPaddingTop, prefix + "padding-top");
-    }
-
-    var expectedPaddingBottom = checkAttribute(output, node, "data-expected-padding-bottom");
-    if (expectedPaddingBottom) {
-        var actualPaddingBottom = getComputedStyle(node).paddingBottom;
-        // Trim the unit "px" from the output.
-        actualPaddingBottom = actualPaddingBottom.slice(0, -2);
-        assert_equals(actualPaddingBottom, expectedPaddingBottom, prefix + "padding-bottom");
-    }
-
-    var expectedPaddingLeft = checkAttribute(output, node, "data-expected-padding-left");
-    if (expectedPaddingLeft) {
-        var actualPaddingLeft = getComputedStyle(node).paddingLeft;
-        // Trim the unit "px" from the output.
-        actualPaddingLeft = actualPaddingLeft.slice(0, -2);
-        assert_equals(actualPaddingLeft, expectedPaddingLeft, prefix + "padding-left");
-    }
-
-    var expectedPaddingRight = checkAttribute(output, node, "data-expected-padding-right");
-    if (expectedPaddingRight) {
-        var actualPaddingRight = getComputedStyle(node).paddingRight;
-        // Trim the unit "px" from the output.
-        actualPaddingRight = actualPaddingRight.slice(0, -2);
-        assert_equals(actualPaddingRight, expectedPaddingRight, prefix + "padding-right");
-    }
-
-    var expectedMarginTop = checkAttribute(output, node, "data-expected-margin-top");
-    if (expectedMarginTop) {
-        var actualMarginTop = getComputedStyle(node).marginTop;
-        // Trim the unit "px" from the output.
-        actualMarginTop = actualMarginTop.slice(0, -2);
-        assert_equals(actualMarginTop, expectedMarginTop, prefix + "margin-top");
-    }
-
-    var expectedMarginBottom = checkAttribute(output, node, "data-expected-margin-bottom");
-    if (expectedMarginBottom) {
-        var actualMarginBottom = getComputedStyle(node).marginBottom;
-        // Trim the unit "px" from the output.
-        actualMarginBottom = actualMarginBottom.slice(0, -2);
-        assert_equals(actualMarginBottom, expectedMarginBottom, prefix + "margin-bottom");
-    }
-
-    var expectedMarginLeft = checkAttribute(output, node, "data-expected-margin-left");
-    if (expectedMarginLeft) {
-        var actualMarginLeft = getComputedStyle(node).marginLeft;
-        // Trim the unit "px" from the output.
-        actualMarginLeft = actualMarginLeft.slice(0, -2);
-        assert_equals(actualMarginLeft, expectedMarginLeft, prefix + "margin-left");
-    }
-
-    var expectedMarginRight = checkAttribute(output, node, "data-expected-margin-right");
-    if (expectedMarginRight) {
-        var actualMarginRight = getComputedStyle(node).marginRight;
-        // Trim the unit "px" from the output.
-        actualMarginRight = actualMarginRight.slice(0, -2);
-        assert_equals(actualMarginRight, expectedMarginRight, prefix + "margin-right");
-    }
-
-    return output.checked;
-}
-
-var testNumber = 0;
-
-window.checkLayout = function(selectorList, callDone = true)
-{
-    if (!selectorList) {
-        console.error("You must provide a CSS selector of nodes to check.");
-        return;
-    }
-    var nodes = document.querySelectorAll(selectorList);
-    nodes = Array.prototype.slice.call(nodes);
-    nodes.reverse();
-    var checkedLayout = false;
-    Array.prototype.forEach.call(nodes, function(node) {
-        test(function(t) {
-            var container = node.parentNode.className == 'container' ? node.parentNode : node;
-            var prefix = "\n" + container.outerHTML + "\n";
-            var passed = false;
-            try {
-                checkedLayout |= checkExpectedValues(t, node.parentNode, prefix);
-                checkedLayout |= checkSubtreeExpectedValues(t, node, prefix);
-                passed = true;
-            } finally {
-                checkedLayout |= !passed;
-            }
-        }, selectorList + ' ' + String(++testNumber));
-    });
-    if (!checkedLayout) {
-        console.error("No valid data-* attributes found in selector list : " + selectorList);
-    }
-    if (callDone)
-        done();
-};
-
-})();
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-fonts-3/font-stretch-01.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-fonts-3/font-stretch-01.html
new file mode 100644
index 0000000..4d7dcd8
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-fonts-3/font-stretch-01.html
@@ -0,0 +1,31 @@
+<!DOCTYPE html>
+<html lang="en">
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
+<title>CSS Test:  font-stretch property initial value is normal</title>
+<link rel="author" title="Chris Lilley" href="chris@w3.org">
+<link rel="match" href="font-stretch-pass-ref.html">
+<link rel="help" href="https://www.w3.org/TR/css-fonts-3/#font-stretch-prop">
+<link rel="help" href="https://www.w3.org/TR/css-fonts-3/#font-prop-desc>"
+<meta name="assert" content="The ‘font-stretch’ property selects a normal, condensed, or expanded face from a font family.">
+<style>
+    @font-face {
+				font-family: "test";
+				src: url(support/fonts/fail.woff) format("woff");
+                font-stretch: ultra-expanded;
+			}
+    @font-face {
+				font-family: "test";
+				src: url(support/fonts/pass.woff) format("woff");
+                font-stretch: normal;
+			}
+    .test {
+				font-family: "test";
+				font-size: 6em;
+			}
+
+</style>
+
+<p>Test passes if the word PASS appears below.</p>
+<section class="test">
+    <p>P</p>
+</section>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-fonts-3/font-stretch-02.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-fonts-3/font-stretch-02.html
new file mode 100644
index 0000000..e07394d
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-fonts-3/font-stretch-02.html
@@ -0,0 +1,32 @@
+<!DOCTYPE html>
+<html lang="en">
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
+<title>CSS Test:  font-stretch property ultra-expanded</title>
+<link rel="author" title="Chris Lilley" href="chris@w3.org">
+<link rel="match" href="font-stretch-pass-ref.html">
+<link rel="help" href="https://www.w3.org/TR/css-fonts-3/#font-stretch-prop">
+<link rel="help" href="https://www.w3.org/TR/css-fonts-3/#font-prop-desc>"
+<meta name="assert" content="The ‘font-stretch’ property selects a normal, condensed, or expanded face from a font family.">
+<style>
+    @font-face {
+				font-family: "test";
+				src: url(support/fonts/fail.woff) format("woff");
+                font-stretch: normal;
+			}
+    @font-face {
+				font-family: "test";
+				src: url(support/fonts/pass.woff) format("woff");
+                font-stretch: ultra-expanded;
+			}
+    .test {
+				font-family: "test";
+				font-size: 6em;
+                font-stretch: ultra-expanded;
+			}
+
+</style>
+
+<p>Test passes if the word PASS appears below.</p>
+<section class="test">
+    <p>P</p>
+</section>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-fonts-3/font-stretch-03.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-fonts-3/font-stretch-03.html
new file mode 100644
index 0000000..75cddfe
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-fonts-3/font-stretch-03.html
@@ -0,0 +1,32 @@
+<!DOCTYPE html>
+<html lang="en">
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
+<title>CSS Test:  font-stretch property extra-expanded</title>
+<link rel="author" title="Chris Lilley" href="chris@w3.org">
+<link rel="match" href="font-stretch-pass-ref.html">
+<link rel="help" href="https://www.w3.org/TR/css-fonts-3/#font-stretch-prop">
+<link rel="help" href="https://www.w3.org/TR/css-fonts-3/#font-prop-desc>"
+<meta name="assert" content="The ‘font-stretch’ property selects a normal, condensed, or expanded face from a font family.">
+<style>
+    @font-face {
+				font-family: "test";
+				src: url(support/fonts/fail.woff) format("woff");
+                font-stretch: normal;
+			}
+    @font-face {
+				font-family: "test";
+				src: url(support/fonts/pass.woff) format("woff");
+                font-stretch: extra-expanded;
+			}
+    .test {
+				font-family: "test";
+				font-size: 6em;
+                font-stretch: extra-expanded;
+			}
+
+</style>
+
+<p>Test passes if the word PASS appears below.</p>
+<section class="test">
+    <p>P</p>
+</section>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-fonts-3/font-stretch-04.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-fonts-3/font-stretch-04.html
new file mode 100644
index 0000000..85d7c20
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-fonts-3/font-stretch-04.html
@@ -0,0 +1,32 @@
+<!DOCTYPE html>
+<html lang="en">
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
+<title>CSS Test:  font-stretch property, expanded</title>
+<link rel="author" title="Chris Lilley" href="chris@w3.org">
+<link rel="match" href="font-stretch-pass-ref.html">
+<link rel="help" href="https://www.w3.org/TR/css-fonts-3/#font-stretch-prop">
+<link rel="help" href="https://www.w3.org/TR/css-fonts-3/#font-prop-desc>"
+<meta name="assert" content="The ‘font-stretch’ property selects a normal, condensed, or expanded face from a font family.">
+<style>
+    @font-face {
+				font-family: "test";
+				src: url(support/fonts/fail.woff) format("woff");
+                font-stretch: normal;
+			}
+    @font-face {
+				font-family: "test";
+				src: url(support/fonts/pass.woff) format("woff");
+                font-stretch: expanded;
+			}
+    .test {
+				font-family: "test";
+				font-size: 6em;
+                font-stretch: expanded;
+			}
+
+</style>
+
+<p>Test passes if the word PASS appears below.</p>
+<section class="test">
+    <p>P</p>
+</section>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-fonts-3/font-stretch-05.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-fonts-3/font-stretch-05.html
new file mode 100644
index 0000000..2bb45288
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-fonts-3/font-stretch-05.html
@@ -0,0 +1,32 @@
+<!DOCTYPE html>
+<html lang="en">
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
+<title>CSS Test:  font-stretch property, semi-expanded</title>
+<link rel="author" title="Chris Lilley" href="chris@w3.org">
+<link rel="match" href="font-stretch-pass-ref.html">
+<link rel="help" href="https://www.w3.org/TR/css-fonts-3/#font-stretch-prop">
+<link rel="help" href="https://www.w3.org/TR/css-fonts-3/#font-prop-desc>"
+<meta name="assert" content="The ‘font-stretch’ property selects a normal, condensed, or expanded face from a font family.">
+<style>
+    @font-face {
+				font-family: "test";
+				src: url(support/fonts/fail.woff) format("woff");
+                font-stretch: normal;
+			}
+    @font-face {
+				font-family: "test";
+				src: url(support/fonts/pass.woff) format("woff");
+                font-stretch: semi-expanded;
+			}
+    .test {
+				font-family: "test";
+				font-size: 6em;
+                font-stretch: semi-expanded;
+			}
+
+</style>
+
+<p>Test passes if the word PASS appears below.</p>
+<section class="test">
+    <p>P</p>
+</section>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-fonts-3/font-stretch-06.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-fonts-3/font-stretch-06.html
new file mode 100644
index 0000000..6118d3f
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-fonts-3/font-stretch-06.html
@@ -0,0 +1,32 @@
+<!DOCTYPE html>
+<html lang="en">
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
+<title>CSS Test:  font-stretch property, normal</title>
+<link rel="author" title="Chris Lilley" href="chris@w3.org">
+<link rel="match" href="font-stretch-pass-ref.html">
+<link rel="help" href="https://www.w3.org/TR/css-fonts-3/#font-stretch-prop">
+<link rel="help" href="https://www.w3.org/TR/css-fonts-3/#font-prop-desc>"
+<meta name="assert" content="The ‘font-stretch’ property selects a normal, condensed, or expanded face from a font family.">
+<style>
+    @font-face {
+				font-family: "test";
+				src: url(support/fonts/fail.woff) format("woff");
+                font-stretch: semi-expanded;
+			}
+    @font-face {
+				font-family: "test";
+				src: url(support/fonts/pass.woff) format("woff");
+                font-stretch: normal;
+			}
+    .test {
+				font-family: "test";
+				font-size: 6em;
+                font-stretch: normal;
+			}
+
+</style>
+
+<p>Test passes if the word PASS appears below.</p>
+<section class="test">
+    <p>P</p>
+</section>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-fonts-3/font-stretch-07.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-fonts-3/font-stretch-07.html
new file mode 100644
index 0000000..c94ddfa
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-fonts-3/font-stretch-07.html
@@ -0,0 +1,32 @@
+<!DOCTYPE html>
+<html lang="en">
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
+<title>CSS Test:  font-stretch property, semi-condensed</title>
+<link rel="author" title="Chris Lilley" href="chris@w3.org">
+<link rel="match" href="font-stretch-pass-ref.html">
+<link rel="help" href="https://www.w3.org/TR/css-fonts-3/#font-stretch-prop">
+<link rel="help" href="https://www.w3.org/TR/css-fonts-3/#font-prop-desc>"
+<meta name="assert" content="The ‘font-stretch’ property selects a normal, condensed, or expanded face from a font family.">
+<style>
+    @font-face {
+				font-family: "test";
+				src: url(support/fonts/fail.woff) format("woff");
+                font-stretch: normal;
+			}
+    @font-face {
+				font-family: "test";
+				src: url(support/fonts/pass.woff) format("woff");
+                font-stretch: semi-condensed;
+			}
+    .test {
+				font-family: "test";
+				font-size: 6em;
+                font-stretch: semi-condensed;
+			}
+
+</style>
+
+<p>Test passes if the word PASS appears below.</p>
+<section class="test">
+    <p>P</p>
+</section>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-fonts-3/font-stretch-08.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-fonts-3/font-stretch-08.html
new file mode 100644
index 0000000..e9da446
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-fonts-3/font-stretch-08.html
@@ -0,0 +1,32 @@
+<!DOCTYPE html>
+<html lang="en">
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
+<title>CSS Test:  font-stretch property, condensed</title>
+<link rel="author" title="Chris Lilley" href="chris@w3.org">
+<link rel="match" href="font-stretch-pass-ref.html">
+<link rel="help" href="https://www.w3.org/TR/css-fonts-3/#font-stretch-prop">
+<link rel="help" href="https://www.w3.org/TR/css-fonts-3/#font-prop-desc">
+<meta name="assert" content="The ‘font-stretch’ property selects a normal, condensed, or expanded face from a font family.">
+<style>
+    @font-face {
+				font-family: "test";
+				src: url(support/fonts/fail.woff) format("woff");
+                font-stretch: normal;
+			}
+    @font-face {
+				font-family: "test";
+				src: url(support/fonts/pass.woff) format("woff");
+                font-stretch: condensed;
+			}
+    .test {
+				font-family: "test";
+				font-size: 6em;
+                font-stretch: condensed;
+			}
+
+</style>
+
+<p>Test passes if the word PASS appears below.</p>
+<section class="test">
+    <p>P</p>
+</section>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-fonts-3/font-stretch-09.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-fonts-3/font-stretch-09.html
new file mode 100644
index 0000000..0fcd04e
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-fonts-3/font-stretch-09.html
@@ -0,0 +1,32 @@
+<!DOCTYPE html>
+<html lang="en">
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
+<title>CSS Test:  font-stretch property, extra-condensed</title>
+<link rel="author" title="Chris Lilley" href="chris@w3.org">
+<link rel="match" href="font-stretch-pass-ref.html">
+<link rel="help" href="https://www.w3.org/TR/css-fonts-3/#font-stretch-prop">
+<link rel="help" href="https://www.w3.org/TR/css-fonts-3/#font-prop-desc">
+<meta name="assert" content="The ‘font-stretch’ property selects a normal, condensed, or expanded face from a font family.">
+<style>
+    @font-face {
+				font-family: "test";
+				src: url(support/fonts/fail.woff) format("woff");
+                font-stretch: normal;
+			}
+    @font-face {
+				font-family: "test";
+				src: url(support/fonts/pass.woff) format("woff");
+                font-stretch: extra-condensed;
+			}
+    .test {
+				font-family: "test";
+				font-size: 6em;
+                font-stretch: extra-condensed;
+			}
+
+</style>
+
+<p>Test passes if the word PASS appears below.</p>
+<section class="test">
+    <p>P</p>
+</section>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-fonts-3/font-stretch-10.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-fonts-3/font-stretch-10.html
new file mode 100644
index 0000000..55a3fa5
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-fonts-3/font-stretch-10.html
@@ -0,0 +1,32 @@
+<!DOCTYPE html>
+<html lang="en">
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
+<title>CSS Test:  font-stretch property, ultra-condensed</title>
+<link rel="author" title="Chris Lilley" href="chris@w3.org">
+<link rel="match" href="font-stretch-pass-ref.html">
+<link rel="help" href="https://www.w3.org/TR/css-fonts-3/#font-stretch-prop">
+<link rel="help" href="https://www.w3.org/TR/css-fonts-3/#font-prop-desc">
+<meta name="assert" content="The ‘font-stretch’ property selects a normal, condensed, or expanded face from a font family.">
+<style>
+    @font-face {
+				font-family: "test";
+				src: url(support/fonts/fail.woff) format("woff");
+                font-stretch: normal;
+			}
+    @font-face {
+				font-family: "test";
+				src: url(support/fonts/pass.woff) format("woff");
+                font-stretch: ultra-condensed;
+			}
+    .test {
+				font-family: "test";
+				font-size: 6em;
+                font-stretch: ultra-condensed;
+			}
+
+</style>
+
+<p>Test passes if the word PASS appears below.</p>
+<section class="test">
+    <p>P</p>
+</section>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-fonts-3/font-stretch-11.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-fonts-3/font-stretch-11.html
new file mode 100644
index 0000000..151a436
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-fonts-3/font-stretch-11.html
@@ -0,0 +1,32 @@
+<!DOCTYPE html>
+<html lang="en">
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
+<title>CSS Test:  font-stretch property, mapping values</title>
+<link rel="author" title="Chris Lilley" href="chris@w3.org">
+<link rel="match" href="font-stretch-pass-ref.html">
+<link rel="help" href="https://www.w3.org/TR/css-fonts-3/#font-stretch-prop">
+<link rel="help" href="https://www.w3.org/TR/css-fonts-3/#font-prop-desc>"
+<meta name="assert" content="When a face does not exist for a given width, normal or condensed values map to a narrower face, otherwise a wider face.">
+<style>
+    @font-face {
+				font-family: "test";
+				src: url(support/fonts/fail.woff) format("woff");
+                font-stretch: normal;
+			}
+    @font-face {
+				font-family: "test";
+				src: url(support/fonts/pass.woff) format("woff");
+                font-stretch: condensed;
+			}
+    .test {
+				font-family: "test";
+				font-size: 6em;
+                font-stretch: ultra-condensed;
+			}
+
+</style>
+
+<p>Test passes if the word PASS appears below.</p>
+<section class="test">
+    <p>P</p>
+</section>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-fonts-3/font-stretch-12.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-fonts-3/font-stretch-12.html
new file mode 100644
index 0000000..f3d0532
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-fonts-3/font-stretch-12.html
@@ -0,0 +1,33 @@
+<!DOCTYPE html>
+<html lang="en">
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
+<title>CSS Test:  font-stretch property, mapping values</title>
+<link rel="author" title="Chris Lilley" href="chris@w3.org">
+<link rel="match" href="font-stretch-pass-ref.html">
+<link rel="help" href="https://www.w3.org/TR/css-fonts-3/#font-stretch-prop">
+<link rel="help" href="https://www.w3.org/TR/css-fonts-3/#font-prop-desc>"
+<meta name="assert" content="When a face does not exist for a given width, normal or condensed values map to a narrower face, otherwise a wider face.">
+<style>
+    @font-face {
+				font-family: "test";
+				src: url(support/fonts/pass.woff) format("woff");
+                font-stretch: condensed;
+			}
+    @font-face {
+				font-family: "test";
+				src: url(support/fonts/fail.woff) format("woff");
+                font-stretch: normal;
+			}
+    .test {
+				font-family: "test";
+				font-size: 6em;
+                font-stretch: semi-condensed;
+			}
+
+</style>
+<!-- per Fig 17,  where the narrower face is used 'otherwise'
+	for semi condensed, before the normal face gets examined -->
+<p>Test passes if the word PASS appears below.</p>
+<section class="test">
+    <p>P</p>
+</section>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-fonts-3/font-stretch-13.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-fonts-3/font-stretch-13.html
new file mode 100644
index 0000000..c4e1694
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-fonts-3/font-stretch-13.html
@@ -0,0 +1,32 @@
+<!DOCTYPE html>
+<html lang="en">
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
+<title>CSS Test:  font-stretch property, mapping values</title>
+<link rel="author" title="Chris Lilley" href="chris@w3.org">
+<link rel="match" href="font-stretch-pass-ref.html">
+<link rel="help" href="https://www.w3.org/TR/css-fonts-3/#font-stretch-prop">
+<link rel="help" href="https://www.w3.org/TR/css-fonts-3/#font-prop-desc>"
+<meta name="assert" content="When a face does not exist for a given width, normal or condensed values map to a narrower face, otherwise a wider face.">
+<style>
+    @font-face {
+				font-family: "test";
+				src: url(support/fonts/pass.woff) format("woff");
+                font-stretch: normal;
+			}
+    @font-face {
+				font-family: "test";
+				src: url(support/fonts/fail.woff) format("woff");
+                font-stretch: condensed;
+			}
+    .test {
+				font-family: "test";
+				font-size: 6em;
+                font-stretch: expanded;
+			}
+
+</style>
+
+<p>Test passes if the word PASS appears below.</p>
+<section class="test">
+    <p>P</p>
+</section>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-fonts-3/font-stretch-14.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-fonts-3/font-stretch-14.html
new file mode 100644
index 0000000..51736a1
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-fonts-3/font-stretch-14.html
@@ -0,0 +1,32 @@
+<!DOCTYPE html>
+<html lang="en">
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
+<title>CSS Test:  font-stretch property, mapping values</title>
+<link rel="author" title="Chris Lilley" href="chris@w3.org">
+<link rel="match" href="font-stretch-pass-ref.html">
+<link rel="help" href="https://www.w3.org/TR/css-fonts-3/#font-stretch-prop">
+<link rel="help" href="https://www.w3.org/TR/css-fonts-3/#font-prop-desc>"
+<meta name="assert" content="When a face does not exist for a given width, normal or condensed values map to a narrower face, otherwise a wider face.">
+<style>
+    @font-face {
+				font-family: "test";
+				src: url(support/fonts/pass.woff) format("woff");
+                font-stretch: expanded;
+			}
+    @font-face {
+				font-family: "test";
+				src: url(support/fonts/fail.woff) format("woff");
+                font-stretch: normal;
+			}
+    .test {
+				font-family: "test";
+				font-size: 6em;
+                font-stretch: semi-expanded;
+			}
+
+</style>
+
+<p>Test passes if the word PASS appears below.</p>
+<section class="test">
+    <p>P</p>
+</section>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-fonts-3/font-stretch-15.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-fonts-3/font-stretch-15.html
new file mode 100644
index 0000000..8607ac9
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-fonts-3/font-stretch-15.html
@@ -0,0 +1,32 @@
+<!DOCTYPE html>
+<html lang="en">
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
+<title>CSS Test:  font-stretch property, mapping values</title>
+<link rel="author" title="Chris Lilley" href="chris@w3.org">
+<link rel="match" href="font-stretch-pass-ref.html">
+<link rel="help" href="https://www.w3.org/TR/css-fonts-3/#font-stretch-prop">
+<link rel="help" href="https://www.w3.org/TR/css-fonts-3/#font-prop-desc>"
+<meta name="assert" content="When a face does not exist for a given width, normal or condensed values map to a narrower face, otherwise a wider face.">
+<style>
+    @font-face {
+				font-family: "test";
+				src: url(support/fonts/pass.woff) format("woff");
+                font-stretch: expanded;
+			}
+    @font-face {
+				font-family: "test";
+				src: url(support/fonts/fail.woff) format("woff");
+                font-stretch: condensed;
+			}
+    .test {
+				font-family: "test";
+				font-size: 6em;
+                font-stretch: semi-expanded;
+			}
+
+</style>
+
+<p>Test passes if the word PASS appears below.</p>
+<section class="test">
+    <p>P</p>
+</section>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-fonts-3/font-stretch-16.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-fonts-3/font-stretch-16.html
new file mode 100644
index 0000000..70f81f0
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-fonts-3/font-stretch-16.html
@@ -0,0 +1,32 @@
+<!DOCTYPE html>
+<html lang="en">
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
+<title>CSS Test:  font-stretch property, mapping values</title>
+<link rel="author" title="Chris Lilley" href="chris@w3.org">
+<link rel="match" href="font-stretch-pass-ref.html">
+<link rel="help" href="https://www.w3.org/TR/css-fonts-3/#font-stretch-prop">
+<link rel="help" href="https://www.w3.org/TR/css-fonts-3/#font-prop-desc>"
+<meta name="assert" content="When a face does not exist for a given width, normal or condensed values map to a narrower face, otherwise a wider face.">
+<style>
+    @font-face {
+				font-family: "test";
+				src: url(support/fonts/pass.woff) format("woff");
+                font-stretch: condensed;
+			}
+    @font-face {
+				font-family: "test";
+				src: url(support/fonts/fail.woff) format("woff");
+                font-stretch: expanded;
+			}
+    .test {
+				font-family: "test";
+				font-size: 6em;
+                font-stretch: normal;
+			}
+
+</style>
+
+<p>Test passes if the word PASS appears below.</p>
+<section class="test">
+    <p>P</p>
+</section>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-fonts-3/font-stretch-17.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-fonts-3/font-stretch-17.html
new file mode 100644
index 0000000..3938ced
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-fonts-3/font-stretch-17.html
@@ -0,0 +1,32 @@
+<!DOCTYPE html>
+<html lang="en">
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
+<title>CSS Test:  font-stretch property, mapping values</title>
+<link rel="author" title="Chris Lilley" href="chris@w3.org">
+<link rel="match" href="font-stretch-pass-ref.html">
+<link rel="help" href="https://www.w3.org/TR/css-fonts-3/#font-stretch-prop">
+<link rel="help" href="https://www.w3.org/TR/css-fonts-3/#font-prop-desc>"
+<meta name="assert" content="When a face does not exist for a given width, normal or condensed values map to a narrower face, otherwise a wider face.">
+<style>
+    @font-face {
+				font-family: "test";
+				src: url(support/fonts/pass.woff) format("woff");
+                font-stretch: condensed;
+			}
+    @font-face {
+				font-family: "test";
+				src: url(support/fonts/fail.woff) format("woff");
+                font-stretch: expanded;
+			}
+    .test {
+				font-family: "test";
+				font-size: 6em;
+                font-stretch: semi-condensed;
+			}
+
+</style>
+
+<p>Test passes if the word PASS appears below.</p>
+<section class="test">
+    <p>P</p>
+</section>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-fonts-3/font-stretch-18.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-fonts-3/font-stretch-18.html
new file mode 100644
index 0000000..496c16d
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-fonts-3/font-stretch-18.html
@@ -0,0 +1,32 @@
+<!DOCTYPE html>
+<html lang="en">
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
+<title>CSS Test:  font-stretch property, mapping values</title>
+<link rel="author" title="Chris Lilley" href="chris@w3.org">
+<link rel="match" href="font-stretch-pass-ref.html">
+<link rel="help" href="https://www.w3.org/TR/css-fonts-3/#font-stretch-prop">
+<link rel="help" href="https://www.w3.org/TR/css-fonts-3/#font-prop-desc>"
+<meta name="assert" content="When a face does not exist for a given width, normal or condensed values map to a narrower face, otherwise a wider face.">
+<style>
+    @font-face {
+				font-family: "test";
+				src: url(support/fonts/pass.woff) format("woff");
+                font-stretch: extra-condensed;
+			}
+    @font-face {
+				font-family: "test";
+				src: url(support/fonts/fail.woff) format("woff");
+                font-stretch: expanded;
+			}
+    .test {
+				font-family: "test";
+				font-size: 6em;
+                font-stretch: condensed;
+			}
+
+</style>
+
+<p>Test passes if the word PASS appears below.</p>
+<section class="test">
+    <p>P</p>
+</section>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-fonts-3/font-stretch-pass-ref.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-fonts-3/font-stretch-pass-ref.html
new file mode 100644
index 0000000..0bd11557
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-fonts-3/font-stretch-pass-ref.html
@@ -0,0 +1,22 @@
+<!DOCTYPE html>
+<html lang="en">
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
+<title>CSS Test:  pass reference</title>
+<link rel="author" title="Chris Lilley" href="chris@w3.org">
+<style>
+    @font-face {
+				font-family: "test";
+				src: url(support/fonts/pass.woff) format("woff");
+                font-stretch: normal;
+			}
+    .test {
+				font-family: "test";
+				font-size: 6em;
+			}
+
+</style>
+
+<p>Test passes if the word PASS appears below.</p>
+<section class="test">
+    <p>P</p>
+</section>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-fonts-3/font-synthesis-01-ref.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-fonts-3/font-synthesis-01-ref.html
new file mode 100644
index 0000000..5355182
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-fonts-3/font-synthesis-01-ref.html
@@ -0,0 +1,21 @@
+<!DOCTYPE html>
+<html lang="en">
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
+<title>CSS Test:  font-synthesis: none disables fake bold</title>
+<link rel="author" title="Chris Lilley" href="chris@w3.org">
+<style>
+    @font-face {
+				font-family: "test";
+				src: url(support/fonts/Lato-Medium.ttf);
+			}
+    .test {
+				font-family: "test";
+				font-size: 3em;
+			}
+</style>
+
+<p>Test passes if the two lines below are identical (the second line is <em>not bold</em>), and there is no red.</p>
+<section class="test">
+    <p>Filler text</p>
+    <p class="nosynth">Filler text</p>
+</section>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-fonts-3/font-synthesis-01.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-fonts-3/font-synthesis-01.html
new file mode 100644
index 0000000..cf6d099e
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-fonts-3/font-synthesis-01.html
@@ -0,0 +1,31 @@
+<!DOCTYPE html>
+<html lang="en">
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
+<title>CSS Test:  font-synthesis: none disables fake bold</title>
+<link rel="author" title="Chris Lilley" href="chris@w3.org">
+<link rel="match" href="font-synthesis-01-ref.html">
+<link rel="help" href="https://www.w3.org/TR/css-fonts-3/#font-synthesis-prop">
+<meta name="assert" content=" If ‘weight’ is not specified, user agents must not synthesize bold faces">
+<style>
+    @font-face {
+				font-family: "test";
+				src: url(support/fonts/Lato-Medium.ttf);
+			}
+    @supports not (font-synthesis: none) {
+        .test {color: red;}
+    }
+    .test {
+				font-family: "test";
+				font-size: 3em;
+			}
+    .nosynth {
+        font-weight: bold;
+        font-synthesis: none;
+    }
+</style>
+
+<p>Test passes if the two lines below are identical (the second line is <em>not bold</em>), and there is no red.</p>
+<section class="test">
+    <p>Filler text</p>
+    <p class="nosynth">Filler text</p>
+</section>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-fonts-3/font-synthesis-02-ref.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-fonts-3/font-synthesis-02-ref.html
new file mode 100644
index 0000000..5f80bcd
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-fonts-3/font-synthesis-02-ref.html
@@ -0,0 +1,21 @@
+<!DOCTYPE html>
+<html lang="en">
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
+<title>CSS Test:  font-synthesis: style disables fake bold</title>
+<link rel="author" title="Chris Lilley" href="chris@w3.org">
+<style>
+    @font-face {
+				font-family: "test";
+				src: url(support/fonts/Lato-Medium.ttf);
+			}
+    .test {
+				font-family: "test";
+				font-size: 3em;
+			}
+</style>
+
+<p>Test passes if the two lines below are identical (the second line is <em>not bold</em>), and there is no red.</p>
+<section class="test">
+    <p>Filler text</p>
+    <p class="nosynth">Filler text</p>
+</section>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-fonts-3/font-synthesis-02.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-fonts-3/font-synthesis-02.html
new file mode 100644
index 0000000..59243c4
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-fonts-3/font-synthesis-02.html
@@ -0,0 +1,31 @@
+<!DOCTYPE html>
+<html lang="en">
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
+<title>CSS Test:  font-synthesis: style disables fake bold</title>
+<link rel="author" title="Chris Lilley" href="chris@w3.org">
+<link rel="match" href="font-synthesis-02-ref.html">
+<link rel="help" href="https://www.w3.org/TR/css-fonts-3/#font-synthesis-prop">
+<meta name="assert" content=" If ‘weight’ is not specified, user agents must not synthesize bold faces">
+<style>
+    @font-face {
+				font-family: "test";
+				src: url(support/fonts/Lato-Medium.ttf);
+			}
+    @supports not (font-synthesis: style) {
+        .test {color: red;}
+    }
+    .test {
+				font-family: "test";
+				font-size: 3em;
+			}
+    .nosynth {
+        font-weight: bold;
+        font-synthesis: style;
+    }
+</style>
+
+<p>Test passes if the two lines below are identical (the second line is <em>not bold</em>), and there is no red.</p>
+<section class="test">
+    <p>Filler text</p>
+    <p class="nosynth">Filler text</p>
+</section>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-fonts-3/font-synthesis-03-ref.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-fonts-3/font-synthesis-03-ref.html
new file mode 100644
index 0000000..8f36b311
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-fonts-3/font-synthesis-03-ref.html
@@ -0,0 +1,21 @@
+<!DOCTYPE html>
+<html lang="en">
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
+<title>CSS Test:  font-synthesis: none disables fake italic/oblique</title>
+<link rel="author" title="Chris Lilley" href="chris@w3.org">
+<style>
+    @font-face {
+				font-family: "test";
+				src: url(support/fonts/Lato-Medium.ttf);
+			}
+    .test {
+				font-family: "test";
+				font-size: 3em;
+			}
+</style>
+
+<p>Test passes if the two lines below are identical (the second line is <em>not obliqued</em>), and there is no red.</p>
+<section class="test">
+    <p>Filler text</p>
+    <p class="nosynth">Filler text</p>
+</section>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-fonts-3/font-synthesis-03.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-fonts-3/font-synthesis-03.html
new file mode 100644
index 0000000..53cac8e
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-fonts-3/font-synthesis-03.html
@@ -0,0 +1,31 @@
+<!DOCTYPE html>
+<html lang="en">
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
+<title>CSS Test:  font-synthesis: none disables fake italic/oblique</title>
+<link rel="author" title="Chris Lilley" href="chris@w3.org">
+<link rel="match" href="font-synthesis-03-ref.html">
+<link rel="help" href="https://www.w3.org/TR/css-fonts-3/#font-synthesis-prop">
+<meta name="assert" content="if ‘style’ is not specified user agents must not synthesize italic faces">
+<style>
+    @font-face {
+				font-family: "test";
+				src: url(support/fonts/Lato-Medium.ttf);
+			}
+    @supports not (font-synthesis: none) {
+        .test {color: red;}
+    }
+    .test {
+				font-family: "test";
+				font-size: 3em;
+			}
+    .nosynth {
+        font-style: italic;
+        font-synthesis: none;
+    }
+</style>
+
+<p>Test passes if the two lines below are identical (the second line is <em>not obliqued</em>), and there is no red.</p>
+<section class="test">
+    <p>Filler text</p>
+    <p class="nosynth">Filler text</p>
+</section>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-fonts-3/font-synthesis-04-ref.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-fonts-3/font-synthesis-04-ref.html
new file mode 100644
index 0000000..f3b6548
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-fonts-3/font-synthesis-04-ref.html
@@ -0,0 +1,21 @@
+<!DOCTYPE html>
+<html lang="en">
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
+<title>CSS Test:  font-synthesis: bold disables fake italic/oblique</title>
+<link rel="author" title="Chris Lilley" href="chris@w3.org">
+<style>
+    @font-face {
+				font-family: "test";
+				src: url(support/fonts/Lato-Medium.ttf);
+			}
+    .test {
+				font-family: "test";
+				font-size: 3em;
+			}
+</style>
+
+<p>Test passes if the two lines below are identical (the second line is <em>not obliqued</em>), and there is no red.</p>
+<section class="test">
+    <p>Filler text</p>
+    <p class="nosynth">Filler text</p>
+</section>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-fonts-3/font-synthesis-04.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-fonts-3/font-synthesis-04.html
new file mode 100644
index 0000000..9081715
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-fonts-3/font-synthesis-04.html
@@ -0,0 +1,31 @@
+<!DOCTYPE html>
+<html lang="en">
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
+<title>CSS Test:  font-synthesis: bold disables fake italic/oblique</title>
+<link rel="author" title="Chris Lilley" href="chris@w3.org">
+<link rel="match" href="font-synthesis-04-ref.html">
+<link rel="help" href="https://www.w3.org/TR/css-fonts-3/#font-synthesis-prop">
+<meta name="assert" content="if ‘style’ is not specified user agents must not synthesize italic faces">
+<style>
+    @font-face {
+				font-family: "test";
+				src: url(support/fonts/Lato-Medium.ttf);
+			}
+    @supports not (font-synthesis: weight) {
+        .test {color: red;}
+    }
+    .test {
+				font-family: "test";
+				font-size: 3em;
+			}
+    .nosynth {
+        font-style: italic;
+        font-synthesis: weight;
+    }
+</style>
+
+<p>Test passes if the two lines below are identical (the second line is <em>not obliqued</em>), and there is no red.</p>
+<section class="test">
+    <p>Filler text</p>
+    <p class="nosynth">Filler text</p>
+</section>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-fonts-3/font-synthesis-05-ref.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-fonts-3/font-synthesis-05-ref.html
new file mode 100644
index 0000000..801889d
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-fonts-3/font-synthesis-05-ref.html
@@ -0,0 +1,23 @@
+<!DOCTYPE html>
+<html lang="en">
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
+<title>CSS Test:  font-synthesis: initial value</title>
+<link rel="author" title="Chris Lilley" href="chris@w3.org">
+<style>
+    @font-face {
+				font-family: "test";
+				src: url(support/fonts/Lato-Medium.ttf);
+			}
+    .test {
+				font-family: "test";
+				font-size: 3em;
+                font-synthesis: weight style;
+                color: green;
+			}
+</style>
+
+<p>Test passes if the text below is green, not red.</p>
+<section class="test">
+    <p>Filler text</p>
+    <!-- Synthesis is allowed, but not required -->
+</section>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-fonts-3/font-synthesis-05.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-fonts-3/font-synthesis-05.html
new file mode 100644
index 0000000..bdbc22f9
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-fonts-3/font-synthesis-05.html
@@ -0,0 +1,29 @@
+<!DOCTYPE html>
+<html lang="en">
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
+<title>CSS Test:  font-synthesis: initial value</title>
+<link rel="author" title="Chris Lilley" href="chris@w3.org">
+<link rel="match" href="font-synthesis-03-ref.html">
+<link rel="help" href="https://www.w3.org/TR/css-fonts-3/#font-synthesis-prop">
+<meta name="assert" content="This property controls whether user agents are allowed to synthesize bold or oblique font faces">
+<style>
+    @font-face {
+				font-family: "test";
+				src: url(support/fonts/Lato-Medium.ttf);
+			}
+    @supports not (font-synthesis: weight style) {
+        .test p {color: red;}
+    }
+    .test {
+				font-family: "test";
+				font-size: 3em;
+                font-synthesis: weight style;
+                color: green;
+			}
+</style>
+
+<p>Test passes if the text below is green, not red.</p>
+<section class="test">
+    <p>Filler text</p>
+    <!-- Synthesis is allowed, but not required -->
+</section>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-fonts-3/font-variant-position-02.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-fonts-3/font-variant-position-02.html
index 9301023..842c726 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/css/css-fonts-3/font-variant-position-02.html
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-fonts-3/font-variant-position-02.html
@@ -5,7 +5,6 @@
 <link rel="author" title="Chris Lilley" href="chris@w3.org">
 <link rel="help" href="https://www.w3.org/TR/css-fonts-3/#font-variant-position-prop">
 <link rel="help" href="https://www.w3.org/TR/css-fonts-3/#font-feature-settings-prop">
-<link rel="match" href="font-variant-position-02-ref.html">
 <meta name="assert" content="Enables display of subscript variants (OpenType feature: subs).">
 <style>
   @font-face {
@@ -23,18 +22,13 @@
   .low {
 	font-feature-settings: "subs" on, "sups" off;
   }
-.foo {
-  color: #100;
-}
-.bar {
-  color: #001;
-}
 </style>
 <body>
-<p>Test passes if the three lines below are identical, with one checkmark (✓) followed by one cross (✗)</p>
-<!-- Identical? If the UA is allowed to simulate subscripts and superscripts then the first line will use smaller glyphs than the second and third. Maybe "similar" and point out size doesn't matter on this test?  -->
+<p>Test passes if the second and third lines below are identical, with two checkmarks (✓) followed by one cross (✗); and
+  also, if the first line is <em>either</em> identical to the other two, <em>or</em> has one checkmark followed by two <b>subscript</b> crosses.
+  If the first line has a checkmark followed by two normally sized crosses, the test fails.  </p>
 <section class="test">
-  <p class="high"><span class="foo">H</span><span class="bar">I</span></p>
-  <p class="high"><span class="foo">H</span><span class="bar">I</span></p>
-	<p class="ref">AB</p>
+  <p>A<span class="high">HI</span></p>
+  <p>A<span class="low">HI</span></p>
+	<p class="ref">AAB</p>
 </section>
\ No newline at end of file
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-fonts-3/font-variant-position-03.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-fonts-3/font-variant-position-03.html
index 02ea087..f0fc871 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/css/css-fonts-3/font-variant-position-03.html
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-fonts-3/font-variant-position-03.html
@@ -5,7 +5,6 @@
 <link rel="author" title="Chris Lilley" href="chris@w3.org">
 <link rel="help" href="https://www.w3.org/TR/css-fonts-3/#font-variant-position-prop">
 <link rel="help" href="https://www.w3.org/TR/css-fonts-3/#font-feature-settings-prop">
-<link rel="match" href="font-variant-position-03-ref.html">
 <meta name="assert" content="Enables display of subscript variants (OpenType feature: subs).">
 <style>
   @font-face {
@@ -23,19 +22,14 @@
   .low {
 	font-feature-settings: "subs" off, "sups" on;
   }
-.foo {
-  color: #100;
-}
-.bar {
-  color: #001;
-}
 </style>
 <body>
-<p>Test passes if the three lines below are identical, with one cross (✗) followed by one checkmark (✓)  </p>
-<!-- Identical? If the UA is allowed to simulate subscripts and superscripts then the first line will use smaller glyphs than the second and third. Maybe "similar" and point out size doesn't matter on this test?  -->
+<p>Test passes if the second and third lines below are identical, with two crosses (✗) followed by one checkmark (✓); and
+  also, if the first line is <em>either</em> identical to the other two, <em>or</em> has one  cross followed by two <b>superscript</b> crosses.
+  If the first line has three normally sized crosses, the test fails.</p>
 
 <section class="test">
-  <p class="high"><span class="foo">H</span><span class="bar">I</span></p>
-  <p class="high"><span class="foo">H</span><span class="bar">I</span></p>
-	<p class="ref">BA</p>
+  <p>B<span class="high">HI</span></p>
+  <p>B<span class="low">HI</span></p>
+	<p class="ref">BBA</p>
 </section>
\ No newline at end of file
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-fonts-3/support/fonts/Exo-DemiBold.otf b/third_party/WebKit/LayoutTests/external/wpt/css/css-fonts-3/support/fonts/Exo-DemiBold.otf
new file mode 100644
index 0000000..b83a13a
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-fonts-3/support/fonts/Exo-DemiBold.otf
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-fonts-3/support/fonts/Exo2-SemiBold.otf b/third_party/WebKit/LayoutTests/external/wpt/css/css-fonts-3/support/fonts/Exo2-SemiBold.otf
new file mode 100644
index 0000000..76b49cd
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-fonts-3/support/fonts/Exo2-SemiBold.otf
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-fonts-3/support/fonts/Exo2-SemiBoldCondensed.otf b/third_party/WebKit/LayoutTests/external/wpt/css/css-fonts-3/support/fonts/Exo2-SemiBoldCondensed.otf
new file mode 100644
index 0000000..832e1b4
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-fonts-3/support/fonts/Exo2-SemiBoldCondensed.otf
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-fonts-3/support/fonts/Exo2-SemiBoldExpanded.otf b/third_party/WebKit/LayoutTests/external/wpt/css/css-fonts-3/support/fonts/Exo2-SemiBoldExpanded.otf
new file mode 100644
index 0000000..f764e13
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-fonts-3/support/fonts/Exo2-SemiBoldExpanded.otf
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-fonts-3/support/fonts/fail.woff b/third_party/WebKit/LayoutTests/external/wpt/css/css-fonts-3/support/fonts/fail.woff
new file mode 100644
index 0000000..33487cd
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-fonts-3/support/fonts/fail.woff
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-fonts-3/support/fonts/pass.woff b/third_party/WebKit/LayoutTests/external/wpt/css/css-fonts-3/support/fonts/pass.woff
new file mode 100644
index 0000000..839bb20
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-fonts-3/support/fonts/pass.woff
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/abspos/absolute-positioning-definite-sizes-001.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/abspos/absolute-positioning-definite-sizes-001.html
index 1249a142..e522fc4 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/abspos/absolute-positioning-definite-sizes-001.html
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/abspos/absolute-positioning-definite-sizes-001.html
@@ -33,7 +33,7 @@
 </style>
 <script src="/resources/testharness.js"></script>
 <script src="/resources/testharnessreport.js"></script>
-<script src="../support/check-layout-th.js"></script>
+<script src="/resources/check-layout-th.js">"></script>
 
 <body onload="checkLayout('.grid')">
 
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/abspos/absolute-positioning-grid-container-containing-block-001.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/abspos/absolute-positioning-grid-container-containing-block-001.html
index 65a358e..cf9407e 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/abspos/absolute-positioning-grid-container-containing-block-001.html
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/abspos/absolute-positioning-grid-container-containing-block-001.html
@@ -112,7 +112,7 @@
 </style>
 <script src="/resources/testharness.js"></script>
 <script src="/resources/testharnessreport.js"></script>
-<script src="../support/check-layout-th.js"></script>
+<script src="/resources/check-layout-th.js">"></script>
 <body onload="checkLayout('.grid')">
 
 <div id="log"></div>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/abspos/absolute-positioning-grid-container-parent-001.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/abspos/absolute-positioning-grid-container-parent-001.html
index 3ea36c7d..15ed632 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/abspos/absolute-positioning-grid-container-parent-001.html
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/abspos/absolute-positioning-grid-container-parent-001.html
@@ -34,7 +34,7 @@
 </style>
 <script src="/resources/testharness.js"></script>
 <script src="/resources/testharnessreport.js"></script>
-<script src="../support/check-layout-th.js"></script>
+<script src="/resources/check-layout-th.js">"></script>
 <body onload="checkLayout('.container')">
 
 <div id="log"></div>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/abspos/grid-positioned-items-content-alignment-001.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/abspos/grid-positioned-items-content-alignment-001.html
index d92c9b7c..737efcb 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/abspos/grid-positioned-items-content-alignment-001.html
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/abspos/grid-positioned-items-content-alignment-001.html
@@ -34,7 +34,7 @@
 </style>
 <script src="/resources/testharness.js"></script>
 <script src="/resources/testharnessreport.js"></script>
-<script src="../support/check-layout-th.js"></script>
+<script src="/resources/check-layout-th.js">"></script>
 
 <body onload="checkLayout('.grid')">
 
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/abspos/grid-positioned-items-content-alignment-rtl-001.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/abspos/grid-positioned-items-content-alignment-rtl-001.html
index 748cb6f..e0aa177 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/abspos/grid-positioned-items-content-alignment-rtl-001.html
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/abspos/grid-positioned-items-content-alignment-rtl-001.html
@@ -34,7 +34,7 @@
 </style>
 <script src="/resources/testharness.js"></script>
 <script src="/resources/testharnessreport.js"></script>
-<script src="../support/check-layout-th.js"></script>
+<script src="/resources/check-layout-th.js">"></script>
 
 <body onload="checkLayout('.grid')">
 
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/abspos/grid-positioned-items-gaps-001.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/abspos/grid-positioned-items-gaps-001.html
index 5869bfb..41d3ffb 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/abspos/grid-positioned-items-gaps-001.html
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/abspos/grid-positioned-items-gaps-001.html
@@ -36,7 +36,7 @@
 </style>
 <script src="/resources/testharness.js"></script>
 <script src="/resources/testharnessreport.js"></script>
-<script src="../support/check-layout-th.js"></script>
+<script src="/resources/check-layout-th.js">"></script>
 
 <body onload="checkLayout('.grid')">
 
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/abspos/grid-positioned-items-gaps-rtl-001.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/abspos/grid-positioned-items-gaps-rtl-001.html
index e6fe7c2..17a2b3d 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/abspos/grid-positioned-items-gaps-rtl-001.html
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/abspos/grid-positioned-items-gaps-rtl-001.html
@@ -36,7 +36,7 @@
 </style>
 <script src="/resources/testharness.js"></script>
 <script src="/resources/testharnessreport.js"></script>
-<script src="../support/check-layout-th.js"></script>
+<script src="/resources/check-layout-th.js">"></script>
 
 <body onload="checkLayout('.grid')">
 
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/abspos/grid-positioned-items-implicit-grid-001.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/abspos/grid-positioned-items-implicit-grid-001.html
index 063da56f..882ebdc 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/abspos/grid-positioned-items-implicit-grid-001.html
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/abspos/grid-positioned-items-implicit-grid-001.html
@@ -30,7 +30,7 @@
 </style>
 <script src="/resources/testharness.js"></script>
 <script src="/resources/testharnessreport.js"></script>
-<script src="../support/check-layout-th.js"></script>
+<script src="/resources/check-layout-th.js">"></script>
 
 <body onload="checkLayout('.grid')">
 
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/abspos/grid-positioned-items-implicit-grid-line-001.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/abspos/grid-positioned-items-implicit-grid-line-001.html
index 908ea39e..35199838 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/abspos/grid-positioned-items-implicit-grid-line-001.html
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/abspos/grid-positioned-items-implicit-grid-line-001.html
@@ -51,7 +51,7 @@
 </style>
 <script src="/resources/testharness.js"></script>
 <script src="/resources/testharnessreport.js"></script>
-<script src="../support/check-layout-th.js"></script>
+<script src="/resources/check-layout-th.js">"></script>
 
 <body onload="checkLayout('.grid')">
 
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/abspos/grid-positioned-items-padding-001.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/abspos/grid-positioned-items-padding-001.html
index 5a7244c7..2ba5cd23 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/abspos/grid-positioned-items-padding-001.html
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/abspos/grid-positioned-items-padding-001.html
@@ -38,7 +38,7 @@
 </style>
 <script src="/resources/testharness.js"></script>
 <script src="/resources/testharnessreport.js"></script>
-<script src="../support/check-layout-th.js"></script>
+<script src="/resources/check-layout-th.js">"></script>
 
 <body onload="checkLayout('.grid')">
 
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/abspos/grid-positioned-items-unknown-named-grid-line-001.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/abspos/grid-positioned-items-unknown-named-grid-line-001.html
index 6aee082..5cde2ec 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/abspos/grid-positioned-items-unknown-named-grid-line-001.html
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/abspos/grid-positioned-items-unknown-named-grid-line-001.html
@@ -44,7 +44,7 @@
 </style>
 <script src="/resources/testharness.js"></script>
 <script src="/resources/testharnessreport.js"></script>
-<script src="../support/check-layout-th.js"></script>
+<script src="/resources/check-layout-th.js">"></script>
 
 <body onload="checkLayout('.grid')">
 
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/abspos/grid-positioned-items-within-grid-implicit-track-001.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/abspos/grid-positioned-items-within-grid-implicit-track-001.html
index 1c82feb0..078d51b 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/abspos/grid-positioned-items-within-grid-implicit-track-001.html
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/abspos/grid-positioned-items-within-grid-implicit-track-001.html
@@ -40,7 +40,7 @@
 </style>
 <script src="/resources/testharness.js"></script>
 <script src="/resources/testharnessreport.js"></script>
-<script src="../support/check-layout-th.js"></script>
+<script src="/resources/check-layout-th.js">"></script>
 
 <body onload="checkLayout('.grid')">
 
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/abspos/grid-sizing-positioned-items-001.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/abspos/grid-sizing-positioned-items-001.html
index 4bd43cc9..390630c 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/abspos/grid-sizing-positioned-items-001.html
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/abspos/grid-sizing-positioned-items-001.html
@@ -55,7 +55,7 @@
 </style>
 <script src="/resources/testharness.js"></script>
 <script src="/resources/testharnessreport.js"></script>
-<script src="../support/check-layout-th.js"></script>
+<script src="/resources/check-layout-th.js">"></script>
 
 <body onload="checkLayout('.grid')">
 
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/abspos/positioned-grid-items-should-not-create-implicit-tracks-001.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/abspos/positioned-grid-items-should-not-create-implicit-tracks-001.html
index 25881a4..f993583 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/abspos/positioned-grid-items-should-not-create-implicit-tracks-001.html
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/abspos/positioned-grid-items-should-not-create-implicit-tracks-001.html
@@ -29,7 +29,7 @@
 </style>
 <script src="/resources/testharness.js"></script>
 <script src="/resources/testharnessreport.js"></script>
-<script src="../support/check-layout-th.js"></script>
+<script src="/resources/check-layout-th.js">"></script>
 
 <body onload="checkLayout('.grid')">
 
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/abspos/positioned-grid-items-should-not-take-up-space-001.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/abspos/positioned-grid-items-should-not-take-up-space-001.html
index c7983671..75ef482 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/abspos/positioned-grid-items-should-not-take-up-space-001.html
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/abspos/positioned-grid-items-should-not-take-up-space-001.html
@@ -33,7 +33,7 @@
 </style>
 <script src="/resources/testharness.js"></script>
 <script src="/resources/testharnessreport.js"></script>
-<script src="../support/check-layout-th.js"></script>
+<script src="/resources/check-layout-th.js">"></script>
 
 <body onload="checkLayout('.grid')">
 
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/alignment/grid-alignment-implies-size-change-001.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/alignment/grid-alignment-implies-size-change-001.html
index 71e1ee8..f8da0b8 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/alignment/grid-alignment-implies-size-change-001.html
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/alignment/grid-alignment-implies-size-change-001.html
@@ -25,7 +25,7 @@
 </style>
 <script src="/resources/testharness.js"></script>
 <script src="/resources/testharnessreport.js"></script>
-<script src="../support/check-layout-th.js"></script>
+<script src="/resources/check-layout-th.js">"></script>
 <script src="../support/style-change.js"></script>
 <script>
 function runTest() {
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/alignment/grid-alignment-implies-size-change-002.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/alignment/grid-alignment-implies-size-change-002.html
index 01f48ccd..d04de07 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/alignment/grid-alignment-implies-size-change-002.html
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/alignment/grid-alignment-implies-size-change-002.html
@@ -25,7 +25,7 @@
 </style>
 <script src="/resources/testharness.js"></script>
 <script src="/resources/testharnessreport.js"></script>
-<script src="../support/check-layout-th.js"></script>
+<script src="/resources/check-layout-th.js">"></script>
 <script src="../support/style-change.js"></script>
 <script>
 function runTest() {
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/alignment/grid-alignment-implies-size-change-003.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/alignment/grid-alignment-implies-size-change-003.html
index d3c5ae1..99bc2f8 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/alignment/grid-alignment-implies-size-change-003.html
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/alignment/grid-alignment-implies-size-change-003.html
@@ -25,7 +25,7 @@
 </style>
 <script src="/resources/testharness.js"></script>
 <script src="/resources/testharnessreport.js"></script>
-<script src="../support/check-layout-th.js"></script>
+<script src="/resources/check-layout-th.js">"></script>
 <script src="../support/style-change.js"></script>
 <script>
 function runTest() {
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/alignment/grid-alignment-implies-size-change-004.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/alignment/grid-alignment-implies-size-change-004.html
index 1f5ca8d1..da38a85 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/alignment/grid-alignment-implies-size-change-004.html
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/alignment/grid-alignment-implies-size-change-004.html
@@ -25,7 +25,7 @@
 </style>
 <script src="/resources/testharness.js"></script>
 <script src="/resources/testharnessreport.js"></script>
-<script src="../support/check-layout-th.js"></script>
+<script src="/resources/check-layout-th.js">"></script>
 <script src="../support/style-change.js"></script>
 <script>
 function runTest() {
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/alignment/grid-alignment-implies-size-change-005.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/alignment/grid-alignment-implies-size-change-005.html
index 07b0aca7..c91f470a 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/alignment/grid-alignment-implies-size-change-005.html
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/alignment/grid-alignment-implies-size-change-005.html
@@ -25,7 +25,7 @@
 </style>
 <script src="/resources/testharness.js"></script>
 <script src="/resources/testharnessreport.js"></script>
-<script src="../support/check-layout-th.js"></script>
+<script src="/resources/check-layout-th.js">"></script>
 <script src="../support/style-change.js"></script>
 <script>
 function runTest() {
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/alignment/grid-alignment-implies-size-change-006.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/alignment/grid-alignment-implies-size-change-006.html
index f0f4d5d4..7d6e3bb 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/alignment/grid-alignment-implies-size-change-006.html
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/alignment/grid-alignment-implies-size-change-006.html
@@ -25,7 +25,7 @@
 </style>
 <script src="/resources/testharness.js"></script>
 <script src="/resources/testharnessreport.js"></script>
-<script src="../support/check-layout-th.js"></script>
+<script src="/resources/check-layout-th.js">"></script>
 <script src="../support/style-change.js"></script>
 <script>
 function runTest() {
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/alignment/grid-alignment-implies-size-change-007.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/alignment/grid-alignment-implies-size-change-007.html
index 5dd70bd1..4bd585b 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/alignment/grid-alignment-implies-size-change-007.html
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/alignment/grid-alignment-implies-size-change-007.html
@@ -25,7 +25,7 @@
 </style>
 <script src="/resources/testharness.js"></script>
 <script src="/resources/testharnessreport.js"></script>
-<script src="../support/check-layout-th.js"></script>
+<script src="/resources/check-layout-th.js">"></script>
 <script src="../support/style-change.js"></script>
 <script>
 function runTest() {
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/alignment/grid-alignment-implies-size-change-008.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/alignment/grid-alignment-implies-size-change-008.html
index f1b22c56..613f638 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/alignment/grid-alignment-implies-size-change-008.html
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/alignment/grid-alignment-implies-size-change-008.html
@@ -25,7 +25,7 @@
 </style>
 <script src="/resources/testharness.js"></script>
 <script src="/resources/testharnessreport.js"></script>
-<script src="../support/check-layout-th.js"></script>
+<script src="/resources/check-layout-th.js">"></script>
 <script src="../support/style-change.js"></script>
 <script>
 function runTest() {
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/alignment/grid-alignment-implies-size-change-009.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/alignment/grid-alignment-implies-size-change-009.html
index fb0041c..fd0bc524d 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/alignment/grid-alignment-implies-size-change-009.html
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/alignment/grid-alignment-implies-size-change-009.html
@@ -25,7 +25,7 @@
 </style>
 <script src="/resources/testharness.js"></script>
 <script src="/resources/testharnessreport.js"></script>
-<script src="../support/check-layout-th.js"></script>
+<script src="/resources/check-layout-th.js">"></script>
 <script src="../support/style-change.js"></script>
 <script>
 function runTest() {
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/alignment/grid-alignment-implies-size-change-010.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/alignment/grid-alignment-implies-size-change-010.html
index 1e68845b..e776bb1 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/alignment/grid-alignment-implies-size-change-010.html
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/alignment/grid-alignment-implies-size-change-010.html
@@ -25,7 +25,7 @@
 </style>
 <script src="/resources/testharness.js"></script>
 <script src="/resources/testharnessreport.js"></script>
-<script src="../support/check-layout-th.js"></script>
+<script src="/resources/check-layout-th.js">"></script>
 <script src="../support/style-change.js"></script>
 <script>
 function runTest() {
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/alignment/grid-alignment-implies-size-change-011.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/alignment/grid-alignment-implies-size-change-011.html
index e388520..c5bbd89 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/alignment/grid-alignment-implies-size-change-011.html
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/alignment/grid-alignment-implies-size-change-011.html
@@ -25,7 +25,7 @@
 </style>
 <script src="/resources/testharness.js"></script>
 <script src="/resources/testharnessreport.js"></script>
-<script src="../support/check-layout-th.js"></script>
+<script src="/resources/check-layout-th.js">"></script>
 <script src="../support/style-change.js"></script>
 <script>
 function runTest() {
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/alignment/grid-alignment-implies-size-change-012.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/alignment/grid-alignment-implies-size-change-012.html
index 3ab4977a..767049a2 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/alignment/grid-alignment-implies-size-change-012.html
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/alignment/grid-alignment-implies-size-change-012.html
@@ -25,7 +25,7 @@
 </style>
 <script src="/resources/testharness.js"></script>
 <script src="/resources/testharnessreport.js"></script>
-<script src="../support/check-layout-th.js"></script>
+<script src="/resources/check-layout-th.js">"></script>
 <script src="../support/style-change.js"></script>
 <script>
 function runTest() {
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/alignment/grid-alignment-implies-size-change-013.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/alignment/grid-alignment-implies-size-change-013.html
index bd6ce3f..0930bdc 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/alignment/grid-alignment-implies-size-change-013.html
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/alignment/grid-alignment-implies-size-change-013.html
@@ -25,7 +25,7 @@
 </style>
 <script src="/resources/testharness.js"></script>
 <script src="/resources/testharnessreport.js"></script>
-<script src="../support/check-layout-th.js"></script>
+<script src="/resources/check-layout-th.js">"></script>
 <script src="../support/style-change.js"></script>
 <script>
 function runTest() {
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/alignment/grid-alignment-implies-size-change-014.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/alignment/grid-alignment-implies-size-change-014.html
index ab56566..fbc529ad 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/alignment/grid-alignment-implies-size-change-014.html
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/alignment/grid-alignment-implies-size-change-014.html
@@ -25,7 +25,7 @@
 </style>
 <script src="/resources/testharness.js"></script>
 <script src="/resources/testharnessreport.js"></script>
-<script src="../support/check-layout-th.js"></script>
+<script src="/resources/check-layout-th.js">"></script>
 <script src="../support/style-change.js"></script>
 <script>
 function runTest() {
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/alignment/grid-alignment-implies-size-change-015.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/alignment/grid-alignment-implies-size-change-015.html
index 844713a..40869f8 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/alignment/grid-alignment-implies-size-change-015.html
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/alignment/grid-alignment-implies-size-change-015.html
@@ -25,7 +25,7 @@
 </style>
 <script src="/resources/testharness.js"></script>
 <script src="/resources/testharnessreport.js"></script>
-<script src="../support/check-layout-th.js"></script>
+<script src="/resources/check-layout-th.js">"></script>
 <script src="../support/style-change.js"></script>
 <script>
 function runTest() {
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/alignment/grid-alignment-implies-size-change-016.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/alignment/grid-alignment-implies-size-change-016.html
index dd3b4be..e0035096 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/alignment/grid-alignment-implies-size-change-016.html
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/alignment/grid-alignment-implies-size-change-016.html
@@ -25,7 +25,7 @@
 </style>
 <script src="/resources/testharness.js"></script>
 <script src="/resources/testharnessreport.js"></script>
-<script src="../support/check-layout-th.js"></script>
+<script src="/resources/check-layout-th.js">"></script>
 <script src="../support/style-change.js"></script>
 <script>
 function runTest() {
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/alignment/grid-alignment-implies-size-change-017.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/alignment/grid-alignment-implies-size-change-017.html
index 5b2c20e..74da9fe 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/alignment/grid-alignment-implies-size-change-017.html
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/alignment/grid-alignment-implies-size-change-017.html
@@ -25,7 +25,7 @@
 </style>
 <script src="/resources/testharness.js"></script>
 <script src="/resources/testharnessreport.js"></script>
-<script src="../support/check-layout-th.js"></script>
+<script src="/resources/check-layout-th.js">"></script>
 <script src="../support/style-change.js"></script>
 <script>
 function runTest() {
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/alignment/grid-alignment-implies-size-change-018.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/alignment/grid-alignment-implies-size-change-018.html
index 77711aaa..05c579ac 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/alignment/grid-alignment-implies-size-change-018.html
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/alignment/grid-alignment-implies-size-change-018.html
@@ -25,7 +25,7 @@
 </style>
 <script src="/resources/testharness.js"></script>
 <script src="/resources/testharnessreport.js"></script>
-<script src="../support/check-layout-th.js"></script>
+<script src="/resources/check-layout-th.js">"></script>
 <script src="../support/style-change.js"></script>
 <script>
 function runTest() {
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/alignment/grid-alignment-implies-size-change-019.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/alignment/grid-alignment-implies-size-change-019.html
index 9d0bbc9..ee9b581 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/alignment/grid-alignment-implies-size-change-019.html
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/alignment/grid-alignment-implies-size-change-019.html
@@ -25,7 +25,7 @@
 </style>
 <script src="/resources/testharness.js"></script>
 <script src="/resources/testharnessreport.js"></script>
-<script src="../support/check-layout-th.js"></script>
+<script src="/resources/check-layout-th.js">"></script>
 <script src="../support/style-change.js"></script>
 <script>
 function runTest() {
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/alignment/grid-alignment-implies-size-change-020.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/alignment/grid-alignment-implies-size-change-020.html
index 86dc271..e42a46b 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/alignment/grid-alignment-implies-size-change-020.html
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/alignment/grid-alignment-implies-size-change-020.html
@@ -25,7 +25,7 @@
 </style>
 <script src="/resources/testharness.js"></script>
 <script src="/resources/testharnessreport.js"></script>
-<script src="../support/check-layout-th.js"></script>
+<script src="/resources/check-layout-th.js">"></script>
 <script src="../support/style-change.js"></script>
 <script>
 function runTest() {
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/alignment/grid-alignment-implies-size-change-021.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/alignment/grid-alignment-implies-size-change-021.html
index 1c92223..d4cb725 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/alignment/grid-alignment-implies-size-change-021.html
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/alignment/grid-alignment-implies-size-change-021.html
@@ -25,7 +25,7 @@
 </style>
 <script src="/resources/testharness.js"></script>
 <script src="/resources/testharnessreport.js"></script>
-<script src="../support/check-layout-th.js"></script>
+<script src="/resources/check-layout-th.js">"></script>
 <script src="../support/style-change.js"></script>
 <script>
 function runTest() {
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/alignment/grid-alignment-implies-size-change-022.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/alignment/grid-alignment-implies-size-change-022.html
index 94a634b..6d8c204d 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/alignment/grid-alignment-implies-size-change-022.html
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/alignment/grid-alignment-implies-size-change-022.html
@@ -25,7 +25,7 @@
 </style>
 <script src="/resources/testharness.js"></script>
 <script src="/resources/testharnessreport.js"></script>
-<script src="../support/check-layout-th.js"></script>
+<script src="/resources/check-layout-th.js">"></script>
 <script src="../support/style-change.js"></script>
 <script>
 function runTest() {
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/alignment/grid-alignment-implies-size-change-023.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/alignment/grid-alignment-implies-size-change-023.html
index 3476f122..4bb3796a 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/alignment/grid-alignment-implies-size-change-023.html
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/alignment/grid-alignment-implies-size-change-023.html
@@ -25,7 +25,7 @@
 </style>
 <script src="/resources/testharness.js"></script>
 <script src="/resources/testharnessreport.js"></script>
-<script src="../support/check-layout-th.js"></script>
+<script src="/resources/check-layout-th.js">"></script>
 <script src="../support/style-change.js"></script>
 <script>
 function runTest() {
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/alignment/grid-alignment-implies-size-change-024.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/alignment/grid-alignment-implies-size-change-024.html
index 92db002..8aaef60f8 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/alignment/grid-alignment-implies-size-change-024.html
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/alignment/grid-alignment-implies-size-change-024.html
@@ -25,7 +25,7 @@
 </style>
 <script src="/resources/testharness.js"></script>
 <script src="/resources/testharnessreport.js"></script>
-<script src="../support/check-layout-th.js"></script>
+<script src="/resources/check-layout-th.js">"></script>
 <script src="../support/style-change.js"></script>
 <script>
 function runTest() {
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/alignment/grid-alignment-implies-size-change-025.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/alignment/grid-alignment-implies-size-change-025.html
index 997fa85..0ef21c9 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/alignment/grid-alignment-implies-size-change-025.html
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/alignment/grid-alignment-implies-size-change-025.html
@@ -25,7 +25,7 @@
 </style>
 <script src="/resources/testharness.js"></script>
 <script src="/resources/testharnessreport.js"></script>
-<script src="../support/check-layout-th.js"></script>
+<script src="/resources/check-layout-th.js">"></script>
 <script src="../support/style-change.js"></script>
 <script>
 function runTest() {
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/alignment/grid-alignment-implies-size-change-026.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/alignment/grid-alignment-implies-size-change-026.html
index 9d18be6..56c7e3f 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/alignment/grid-alignment-implies-size-change-026.html
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/alignment/grid-alignment-implies-size-change-026.html
@@ -25,7 +25,7 @@
 </style>
 <script src="/resources/testharness.js"></script>
 <script src="/resources/testharnessreport.js"></script>
-<script src="../support/check-layout-th.js"></script>
+<script src="/resources/check-layout-th.js">"></script>
 <script src="../support/style-change.js"></script>
 <script>
 function runTest() {
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/alignment/grid-alignment-implies-size-change-027.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/alignment/grid-alignment-implies-size-change-027.html
index 78b9fbd..8f8797e 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/alignment/grid-alignment-implies-size-change-027.html
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/alignment/grid-alignment-implies-size-change-027.html
@@ -25,7 +25,7 @@
 </style>
 <script src="/resources/testharness.js"></script>
 <script src="/resources/testharnessreport.js"></script>
-<script src="../support/check-layout-th.js"></script>
+<script src="/resources/check-layout-th.js">"></script>
 <script src="../support/style-change.js"></script>
 <script>
 function runTest() {
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/alignment/grid-alignment-implies-size-change-028.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/alignment/grid-alignment-implies-size-change-028.html
index 1426cc41..38021f9 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/alignment/grid-alignment-implies-size-change-028.html
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/alignment/grid-alignment-implies-size-change-028.html
@@ -25,7 +25,7 @@
 </style>
 <script src="/resources/testharness.js"></script>
 <script src="/resources/testharnessreport.js"></script>
-<script src="../support/check-layout-th.js"></script>
+<script src="/resources/check-layout-th.js">"></script>
 <script src="../support/style-change.js"></script>
 <script>
 function runTest() {
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/alignment/grid-alignment-implies-size-change-029.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/alignment/grid-alignment-implies-size-change-029.html
index ca9f47a..cfdf51d 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/alignment/grid-alignment-implies-size-change-029.html
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/alignment/grid-alignment-implies-size-change-029.html
@@ -25,7 +25,7 @@
 </style>
 <script src="/resources/testharness.js"></script>
 <script src="/resources/testharnessreport.js"></script>
-<script src="../support/check-layout-th.js"></script>
+<script src="/resources/check-layout-th.js">"></script>
 <script src="../support/style-change.js"></script>
 <script>
 function runTest() {
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/alignment/grid-alignment-implies-size-change-030.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/alignment/grid-alignment-implies-size-change-030.html
index 103b04d..1fb01728 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/alignment/grid-alignment-implies-size-change-030.html
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/alignment/grid-alignment-implies-size-change-030.html
@@ -25,7 +25,7 @@
 </style>
 <script src="/resources/testharness.js"></script>
 <script src="/resources/testharnessreport.js"></script>
-<script src="../support/check-layout-th.js"></script>
+<script src="/resources/check-layout-th.js">"></script>
 <script src="../support/style-change.js"></script>
 <script>
 function runTest() {
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/alignment/grid-alignment-implies-size-change-031.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/alignment/grid-alignment-implies-size-change-031.html
index 9c85e5a..9cdaabbf 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/alignment/grid-alignment-implies-size-change-031.html
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/alignment/grid-alignment-implies-size-change-031.html
@@ -25,7 +25,7 @@
 </style>
 <script src="/resources/testharness.js"></script>
 <script src="/resources/testharnessreport.js"></script>
-<script src="../support/check-layout-th.js"></script>
+<script src="/resources/check-layout-th.js">"></script>
 <script src="../support/style-change.js"></script>
 <script>
 function runTest() {
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/alignment/grid-alignment-implies-size-change-032.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/alignment/grid-alignment-implies-size-change-032.html
index 093c0f9..c4941dd6 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/alignment/grid-alignment-implies-size-change-032.html
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/alignment/grid-alignment-implies-size-change-032.html
@@ -25,7 +25,7 @@
 </style>
 <script src="/resources/testharness.js"></script>
 <script src="/resources/testharnessreport.js"></script>
-<script src="../support/check-layout-th.js"></script>
+<script src="/resources/check-layout-th.js">"></script>
 <script src="../support/style-change.js"></script>
 <script>
 function runTest() {
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/alignment/grid-alignment-implies-size-change-033.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/alignment/grid-alignment-implies-size-change-033.html
index 1cf53580..fb89cc1c 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/alignment/grid-alignment-implies-size-change-033.html
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/alignment/grid-alignment-implies-size-change-033.html
@@ -25,7 +25,7 @@
 </style>
 <script src="/resources/testharness.js"></script>
 <script src="/resources/testharnessreport.js"></script>
-<script src="../support/check-layout-th.js"></script>
+<script src="/resources/check-layout-th.js">"></script>
 <script src="../support/style-change.js"></script>
 <script>
 function runTest() {
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/alignment/grid-alignment-implies-size-change-034.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/alignment/grid-alignment-implies-size-change-034.html
index 87ec1ae..3932ceb 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/alignment/grid-alignment-implies-size-change-034.html
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/alignment/grid-alignment-implies-size-change-034.html
@@ -25,7 +25,7 @@
 </style>
 <script src="/resources/testharness.js"></script>
 <script src="/resources/testharnessreport.js"></script>
-<script src="../support/check-layout-th.js"></script>
+<script src="/resources/check-layout-th.js">"></script>
 <script src="../support/style-change.js"></script>
 <script>
 function runTest() {
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/alignment/grid-alignment-implies-size-change-035.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/alignment/grid-alignment-implies-size-change-035.html
index 1968522..f0c4394 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/alignment/grid-alignment-implies-size-change-035.html
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/alignment/grid-alignment-implies-size-change-035.html
@@ -25,7 +25,7 @@
 </style>
 <script src="/resources/testharness.js"></script>
 <script src="/resources/testharnessreport.js"></script>
-<script src="../support/check-layout-th.js"></script>
+<script src="/resources/check-layout-th.js">"></script>
 <script src="../support/style-change.js"></script>
 <script>
 function runTest() {
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/alignment/grid-alignment-implies-size-change-036.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/alignment/grid-alignment-implies-size-change-036.html
index a797403..694cb05 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/alignment/grid-alignment-implies-size-change-036.html
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/alignment/grid-alignment-implies-size-change-036.html
@@ -25,7 +25,7 @@
 </style>
 <script src="/resources/testharness.js"></script>
 <script src="/resources/testharnessreport.js"></script>
-<script src="../support/check-layout-th.js"></script>
+<script src="/resources/check-layout-th.js">"></script>
 <script src="../support/style-change.js"></script>
 <script>
 function runTest() {
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/alignment/grid-fit-content-tracks-dont-stretch-001.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/alignment/grid-fit-content-tracks-dont-stretch-001.html
index 367386c2..8aafe35e 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/alignment/grid-fit-content-tracks-dont-stretch-001.html
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/alignment/grid-fit-content-tracks-dont-stretch-001.html
@@ -37,7 +37,7 @@
 
 <script src="/resources/testharness.js"></script>
 <script src="/resources/testharnessreport.js"></script>
-<script src="../support/check-layout-th.js"></script>
+<script src="/resources/check-layout-th.js">"></script>
 
 <body onLoad="checkLayout('.grid');">
 
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/alignment/grid-self-alignment-stretch-001.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/alignment/grid-self-alignment-stretch-001.html
index e700587..9a2cea50 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/alignment/grid-self-alignment-stretch-001.html
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/alignment/grid-self-alignment-stretch-001.html
@@ -48,7 +48,7 @@
 </style>
 <script src="/resources/testharness.js"></script>
 <script src="/resources/testharnessreport.js"></script>
-<script src="../support/check-layout-th.js"></script>
+<script src="/resources/check-layout-th.js">"></script>
 <body onload="checkLayout('.grid')">
 <div class="grid">
   <div data-offset-x="0"   data-offset-y="0"   data-expected-width="100" data-expected-height="10"  class="firstRowFirstColumn">X XX X</div>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/alignment/grid-self-alignment-stretch-002.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/alignment/grid-self-alignment-stretch-002.html
index 30413e0bb..6c7b2dc 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/alignment/grid-self-alignment-stretch-002.html
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/alignment/grid-self-alignment-stretch-002.html
@@ -52,7 +52,7 @@
 </style>
 <script src="/resources/testharness.js"></script>
 <script src="/resources/testharnessreport.js"></script>
-<script src="../support/check-layout-th.js"></script>
+<script src="/resources/check-layout-th.js">"></script>
 <body onload="checkLayout('.grid')">
 <div class="grid">
   <div data-offset-x="0"   data-offset-y="0"   data-expected-width="90"  data-expected-height="10"  class="firstRowFirstColumn">X XX X</div>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/alignment/grid-self-alignment-stretch-003.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/alignment/grid-self-alignment-stretch-003.html
index 63ab28e7..a3920371 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/alignment/grid-self-alignment-stretch-003.html
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/alignment/grid-self-alignment-stretch-003.html
@@ -53,7 +53,7 @@
 </style>
 <script src="/resources/testharness.js"></script>
 <script src="/resources/testharnessreport.js"></script>
-<script src="../support/check-layout-th.js"></script>
+<script src="/resources/check-layout-th.js">"></script>
 <body onload="checkLayout('.grid')">
 <div class="grid">
   <div data-offset-x="0"   data-offset-y="0"   data-expected-width="100" data-expected-height="10"  class="firstRowFirstColumn">X XX X</div>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/alignment/grid-self-alignment-stretch-004.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/alignment/grid-self-alignment-stretch-004.html
index 6566e9c1..1661d07 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/alignment/grid-self-alignment-stretch-004.html
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/alignment/grid-self-alignment-stretch-004.html
@@ -52,7 +52,7 @@
 </style>
 <script src="/resources/testharness.js"></script>
 <script src="/resources/testharnessreport.js"></script>
-<script src="../support/check-layout-th.js"></script>
+<script src="/resources/check-layout-th.js">"></script>
 <body onload="checkLayout('.grid')">
 <div class="grid">
   <div data-offset-x="0"   data-offset-y="0"   data-expected-width="100" data-expected-height="10"  class="firstRowFirstColumn">X XX X</div>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/alignment/grid-self-alignment-stretch-005.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/alignment/grid-self-alignment-stretch-005.html
index 1689032..93b217f 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/alignment/grid-self-alignment-stretch-005.html
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/alignment/grid-self-alignment-stretch-005.html
@@ -49,7 +49,7 @@
 </style>
 <script src="/resources/testharness.js"></script>
 <script src="/resources/testharnessreport.js"></script>
-<script src="../support/check-layout-th.js"></script>
+<script src="/resources/check-layout-th.js">"></script>
 <body onload="checkLayout('.grid')">
 <div class="grid">
   <div data-offset-x="0"   data-offset-y="0"   data-expected-width="100" data-expected-height="60"  class="firstRowFirstColumn">X XX X</div>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/alignment/grid-self-alignment-stretch-006.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/alignment/grid-self-alignment-stretch-006.html
index c090ef8..683ab1b 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/alignment/grid-self-alignment-stretch-006.html
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/alignment/grid-self-alignment-stretch-006.html
@@ -53,7 +53,7 @@
 </style>
 <script src="/resources/testharness.js"></script>
 <script src="/resources/testharnessreport.js"></script>
-<script src="../support/check-layout-th.js"></script>
+<script src="/resources/check-layout-th.js">"></script>
 <body onload="checkLayout('.grid')">
 <div class="grid">
   <div data-offset-x="0"   data-offset-y="0"   data-expected-width="90"  data-expected-height="60"  class="firstRowFirstColumn">X XX X</div>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/alignment/grid-self-alignment-stretch-007.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/alignment/grid-self-alignment-stretch-007.html
index 8a5161ce..33dd6aac 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/alignment/grid-self-alignment-stretch-007.html
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/alignment/grid-self-alignment-stretch-007.html
@@ -54,7 +54,7 @@
 </style>
 <script src="/resources/testharness.js"></script>
 <script src="/resources/testharnessreport.js"></script>
-<script src="../support/check-layout-th.js"></script>
+<script src="/resources/check-layout-th.js">"></script>
 <body onload="checkLayout('.grid')">
 <div class="grid">
   <div data-offset-x="0"   data-offset-y="0"   data-expected-width="100" data-expected-height="60"  class="firstRowFirstColumn">X XX X</div>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/alignment/grid-self-alignment-stretch-008.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/alignment/grid-self-alignment-stretch-008.html
index d103a448..7f47b38 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/alignment/grid-self-alignment-stretch-008.html
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/alignment/grid-self-alignment-stretch-008.html
@@ -53,7 +53,7 @@
 </style>
 <script src="/resources/testharness.js"></script>
 <script src="/resources/testharnessreport.js"></script>
-<script src="../support/check-layout-th.js"></script>
+<script src="/resources/check-layout-th.js">"></script>
 <body onload="checkLayout('.grid')">
 <div class="grid">
   <div data-offset-x="0"   data-offset-y="0"   data-expected-width="100" data-expected-height="60"  class="firstRowFirstColumn">X XX X</div>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/alignment/grid-self-alignment-stretch-009.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/alignment/grid-self-alignment-stretch-009.html
index f971ddb..2f8448e5 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/alignment/grid-self-alignment-stretch-009.html
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/alignment/grid-self-alignment-stretch-009.html
@@ -48,7 +48,7 @@
 </style>
 <script src="/resources/testharness.js"></script>
 <script src="/resources/testharnessreport.js"></script>
-<script src="../support/check-layout-th.js"></script>
+<script src="/resources/check-layout-th.js">"></script>
 <body onload="checkLayout('.grid')">
 <div class="grid">
   <div data-offset-x="0"   data-offset-y="0"   data-expected-width="125" data-expected-height="20"  class="firstRowFirstColumn">XX X</div>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/alignment/grid-self-alignment-stretch-010.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/alignment/grid-self-alignment-stretch-010.html
index 1541a27a..5c4adf36 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/alignment/grid-self-alignment-stretch-010.html
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/alignment/grid-self-alignment-stretch-010.html
@@ -52,7 +52,7 @@
 </style>
 <script src="/resources/testharness.js"></script>
 <script src="/resources/testharnessreport.js"></script>
-<script src="../support/check-layout-th.js"></script>
+<script src="/resources/check-layout-th.js">"></script>
 <body onload="checkLayout('.grid')">
 <div class="grid">
   <div data-offset-x="0"   data-offset-y="0"   data-expected-width="110" data-expected-height="20"  class="firstRowFirstColumn">XX X</div>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/alignment/grid-self-alignment-stretch-011.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/alignment/grid-self-alignment-stretch-011.html
index dc2738b..4ac84493 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/alignment/grid-self-alignment-stretch-011.html
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/alignment/grid-self-alignment-stretch-011.html
@@ -53,7 +53,7 @@
 </style>
 <script src="/resources/testharness.js"></script>
 <script src="/resources/testharnessreport.js"></script>
-<script src="../support/check-layout-th.js"></script>
+<script src="/resources/check-layout-th.js">"></script>
 <body onload="checkLayout('.grid')">
 <div class="grid">
   <div data-offset-x="0"   data-offset-y="0"   data-expected-width="120" data-expected-height="20"  class="firstRowFirstColumn">XX X</div>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/alignment/grid-self-alignment-stretch-012.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/alignment/grid-self-alignment-stretch-012.html
index 1c04de1..91a13a0 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/alignment/grid-self-alignment-stretch-012.html
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/alignment/grid-self-alignment-stretch-012.html
@@ -52,7 +52,7 @@
 </style>
 <script src="/resources/testharness.js"></script>
 <script src="/resources/testharnessreport.js"></script>
-<script src="../support/check-layout-th.js"></script>
+<script src="/resources/check-layout-th.js">"></script>
 <body onload="checkLayout('.grid')">
 <div class="grid">
   <div data-offset-x="0"   data-offset-y="0"   data-expected-width="120" data-expected-height="20"  class="firstRowFirstColumn">XX X</div>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/alignment/grid-self-alignment-stretch-013.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/alignment/grid-self-alignment-stretch-013.html
index d8acd61..cdfdd27 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/alignment/grid-self-alignment-stretch-013.html
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/alignment/grid-self-alignment-stretch-013.html
@@ -49,7 +49,7 @@
 </style>
 <script src="/resources/testharness.js"></script>
 <script src="/resources/testharnessreport.js"></script>
-<script src="../support/check-layout-th.js"></script>
+<script src="/resources/check-layout-th.js">"></script>
 <body onload="checkLayout('.grid')">
 <div class="grid">
   <div data-offset-x="0"   data-offset-y="0"   data-expected-width="125" data-expected-height="80"  class="firstRowFirstColumn">XX X</div>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/alignment/grid-self-alignment-stretch-014.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/alignment/grid-self-alignment-stretch-014.html
index 0b048089..694aaaf 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/alignment/grid-self-alignment-stretch-014.html
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/alignment/grid-self-alignment-stretch-014.html
@@ -53,7 +53,7 @@
 </style>
 <script src="/resources/testharness.js"></script>
 <script src="/resources/testharnessreport.js"></script>
-<script src="../support/check-layout-th.js"></script>
+<script src="/resources/check-layout-th.js">"></script>
 <body onload="checkLayout('.grid')">
 <div class="grid">
   <div data-offset-x="0"   data-offset-y="0"   data-expected-width="110" data-expected-height="80"  class="firstRowFirstColumn">XX X</div>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/alignment/grid-self-alignment-stretch-015.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/alignment/grid-self-alignment-stretch-015.html
index dc366eb..64f6decd 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/alignment/grid-self-alignment-stretch-015.html
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/alignment/grid-self-alignment-stretch-015.html
@@ -54,7 +54,7 @@
 </style>
 <script src="/resources/testharness.js"></script>
 <script src="/resources/testharnessreport.js"></script>
-<script src="../support/check-layout-th.js"></script>
+<script src="/resources/check-layout-th.js">"></script>
 <body onload="checkLayout('.grid')">
 <div class="grid">
   <div data-offset-x="0"   data-offset-y="0"   data-expected-width="120" data-expected-height="80"  class="firstRowFirstColumn">XX X</div>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/alignment/grid-self-alignment-stretch-016.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/alignment/grid-self-alignment-stretch-016.html
index 27dab09b..6f92db1 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/alignment/grid-self-alignment-stretch-016.html
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/alignment/grid-self-alignment-stretch-016.html
@@ -52,7 +52,7 @@
 </style>
 <script src="/resources/testharness.js"></script>
 <script src="/resources/testharnessreport.js"></script>
-<script src="../support/check-layout-th.js"></script>
+<script src="/resources/check-layout-th.js">"></script>
 <body onload="checkLayout('.grid')">
 <div class="grid">
   <div data-offset-x="0"   data-offset-y="0"   data-expected-width="120" data-expected-height="80"  class="firstRowFirstColumn">XX X</div>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/alignment/grid-self-alignment-stretch-vertical-lr-001.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/alignment/grid-self-alignment-stretch-vertical-lr-001.html
index 5c057624..69c17e6 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/alignment/grid-self-alignment-stretch-vertical-lr-001.html
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/alignment/grid-self-alignment-stretch-vertical-lr-001.html
@@ -49,7 +49,7 @@
 </style>
 <script src="/resources/testharness.js"></script>
 <script src="/resources/testharnessreport.js"></script>
-<script src="../support/check-layout-th.js"></script>
+<script src="/resources/check-layout-th.js">"></script>
 <body onload="checkLayout('.grid')">
 <div class="grid">
   <div data-offset-x="0"   data-offset-y="0"   data-expected-width="10"  data-expected-height="100" class="firstRowFirstColumn">X XX X</div>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/alignment/grid-self-alignment-stretch-vertical-lr-002.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/alignment/grid-self-alignment-stretch-vertical-lr-002.html
index abcf06e3..e4a109c1 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/alignment/grid-self-alignment-stretch-vertical-lr-002.html
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/alignment/grid-self-alignment-stretch-vertical-lr-002.html
@@ -53,7 +53,7 @@
 </style>
 <script src="/resources/testharness.js"></script>
 <script src="/resources/testharnessreport.js"></script>
-<script src="../support/check-layout-th.js"></script>
+<script src="/resources/check-layout-th.js">"></script>
 <body onload="checkLayout('.grid')">
 <div class="grid">
   <div data-offset-x="0"   data-offset-y="0"   data-expected-width="10"  data-expected-height="90"  class="firstRowFirstColumn">X XX X</div>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/alignment/grid-self-alignment-stretch-vertical-lr-003.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/alignment/grid-self-alignment-stretch-vertical-lr-003.html
index ca185bd..54a6898 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/alignment/grid-self-alignment-stretch-vertical-lr-003.html
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/alignment/grid-self-alignment-stretch-vertical-lr-003.html
@@ -54,7 +54,7 @@
 </style>
 <script src="/resources/testharness.js"></script>
 <script src="/resources/testharnessreport.js"></script>
-<script src="../support/check-layout-th.js"></script>
+<script src="/resources/check-layout-th.js">"></script>
 <body onload="checkLayout('.grid')">
 <div class="grid">
   <div data-offset-x="0"   data-offset-y="0"   data-expected-width="10"  data-expected-height="100" class="firstRowFirstColumn">X XX X</div>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/alignment/grid-self-alignment-stretch-vertical-lr-004.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/alignment/grid-self-alignment-stretch-vertical-lr-004.html
index bc0b8d6c..14121af 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/alignment/grid-self-alignment-stretch-vertical-lr-004.html
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/alignment/grid-self-alignment-stretch-vertical-lr-004.html
@@ -53,7 +53,7 @@
 </style>
 <script src="/resources/testharness.js"></script>
 <script src="/resources/testharnessreport.js"></script>
-<script src="../support/check-layout-th.js"></script>
+<script src="/resources/check-layout-th.js">"></script>
 <body onload="checkLayout('.grid')">
 <div class="grid">
   <div data-offset-x="0"   data-offset-y="0"   data-expected-width="10"  data-expected-height="100" class="firstRowFirstColumn">X XX X</div>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/alignment/grid-self-alignment-stretch-vertical-lr-005.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/alignment/grid-self-alignment-stretch-vertical-lr-005.html
index b155f5c..a274f51 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/alignment/grid-self-alignment-stretch-vertical-lr-005.html
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/alignment/grid-self-alignment-stretch-vertical-lr-005.html
@@ -50,7 +50,7 @@
 </style>
 <script src="/resources/testharness.js"></script>
 <script src="/resources/testharnessreport.js"></script>
-<script src="../support/check-layout-th.js"></script>
+<script src="/resources/check-layout-th.js">"></script>
 <body onload="checkLayout('.grid')">
 <div class="grid">
   <div data-offset-x="0"   data-offset-y="0"   data-expected-width="60"  data-expected-height="100" class="firstRowFirstColumn">X XX X</div>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/alignment/grid-self-alignment-stretch-vertical-lr-006.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/alignment/grid-self-alignment-stretch-vertical-lr-006.html
index 23ee979..d44d724 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/alignment/grid-self-alignment-stretch-vertical-lr-006.html
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/alignment/grid-self-alignment-stretch-vertical-lr-006.html
@@ -54,7 +54,7 @@
 </style>
 <script src="/resources/testharness.js"></script>
 <script src="/resources/testharnessreport.js"></script>
-<script src="../support/check-layout-th.js"></script>
+<script src="/resources/check-layout-th.js">"></script>
 <body onload="checkLayout('.grid')">
 <div class="grid">
   <div data-offset-x="0"   data-offset-y="0"   data-expected-width="60"  data-expected-height="90"  class="firstRowFirstColumn">X XX X</div>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/alignment/grid-self-alignment-stretch-vertical-lr-007.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/alignment/grid-self-alignment-stretch-vertical-lr-007.html
index 5496e781..03b93b6 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/alignment/grid-self-alignment-stretch-vertical-lr-007.html
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/alignment/grid-self-alignment-stretch-vertical-lr-007.html
@@ -55,7 +55,7 @@
 </style>
 <script src="/resources/testharness.js"></script>
 <script src="/resources/testharnessreport.js"></script>
-<script src="../support/check-layout-th.js"></script>
+<script src="/resources/check-layout-th.js">"></script>
 <body onload="checkLayout('.grid')">
 <div class="grid">
   <div data-offset-x="0"   data-offset-y="0"   data-expected-width="60"  data-expected-height="100" class="firstRowFirstColumn">X XX X</div>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/alignment/grid-self-alignment-stretch-vertical-lr-008.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/alignment/grid-self-alignment-stretch-vertical-lr-008.html
index 556ca0f1..04ce3e7 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/alignment/grid-self-alignment-stretch-vertical-lr-008.html
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/alignment/grid-self-alignment-stretch-vertical-lr-008.html
@@ -54,7 +54,7 @@
 </style>
 <script src="/resources/testharness.js"></script>
 <script src="/resources/testharnessreport.js"></script>
-<script src="../support/check-layout-th.js"></script>
+<script src="/resources/check-layout-th.js">"></script>
 <body onload="checkLayout('.grid')">
 <div class="grid">
   <div data-offset-x="0"   data-offset-y="0"   data-expected-width="60"  data-expected-height="100" class="firstRowFirstColumn">X XX X</div>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/alignment/grid-self-alignment-stretch-vertical-lr-009.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/alignment/grid-self-alignment-stretch-vertical-lr-009.html
index 75433ad..c25eb36 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/alignment/grid-self-alignment-stretch-vertical-lr-009.html
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/alignment/grid-self-alignment-stretch-vertical-lr-009.html
@@ -49,7 +49,7 @@
 </style>
 <script src="/resources/testharness.js"></script>
 <script src="/resources/testharnessreport.js"></script>
-<script src="../support/check-layout-th.js"></script>
+<script src="/resources/check-layout-th.js">"></script>
 <body onload="checkLayout('.grid')">
 <div class="grid">
   <div data-offset-x="0"   data-offset-y="0"   data-expected-width="20"  data-expected-height="125" class="firstRowFirstColumn">XX X</div>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/alignment/grid-self-alignment-stretch-vertical-lr-010.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/alignment/grid-self-alignment-stretch-vertical-lr-010.html
index 7ed26cf..b7ad29f 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/alignment/grid-self-alignment-stretch-vertical-lr-010.html
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/alignment/grid-self-alignment-stretch-vertical-lr-010.html
@@ -53,7 +53,7 @@
 </style>
 <script src="/resources/testharness.js"></script>
 <script src="/resources/testharnessreport.js"></script>
-<script src="../support/check-layout-th.js"></script>
+<script src="/resources/check-layout-th.js">"></script>
 <body onload="checkLayout('.grid')">
 <div class="grid">
   <div data-offset-x="0"   data-offset-y="0"   data-expected-width="20"  data-expected-height="110" class="firstRowFirstColumn">XX X</div>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/alignment/grid-self-alignment-stretch-vertical-lr-011.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/alignment/grid-self-alignment-stretch-vertical-lr-011.html
index 701d9a8..ef6a9dc 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/alignment/grid-self-alignment-stretch-vertical-lr-011.html
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/alignment/grid-self-alignment-stretch-vertical-lr-011.html
@@ -54,7 +54,7 @@
 </style>
 <script src="/resources/testharness.js"></script>
 <script src="/resources/testharnessreport.js"></script>
-<script src="../support/check-layout-th.js"></script>
+<script src="/resources/check-layout-th.js">"></script>
 <body onload="checkLayout('.grid')">
 <div class="grid">
   <div data-offset-x="0"   data-offset-y="0"   data-expected-width="20"  data-expected-height="120" class="firstRowFirstColumn">XX X</div>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/alignment/grid-self-alignment-stretch-vertical-lr-012.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/alignment/grid-self-alignment-stretch-vertical-lr-012.html
index 323ad98..06575bd 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/alignment/grid-self-alignment-stretch-vertical-lr-012.html
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/alignment/grid-self-alignment-stretch-vertical-lr-012.html
@@ -53,7 +53,7 @@
 </style>
 <script src="/resources/testharness.js"></script>
 <script src="/resources/testharnessreport.js"></script>
-<script src="../support/check-layout-th.js"></script>
+<script src="/resources/check-layout-th.js">"></script>
 <body onload="checkLayout('.grid')">
 <div class="grid">
   <div data-offset-x="0"   data-offset-y="0"   data-expected-width="20"  data-expected-height="120" class="firstRowFirstColumn">XX X</div>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/alignment/grid-self-alignment-stretch-vertical-lr-013.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/alignment/grid-self-alignment-stretch-vertical-lr-013.html
index dde2a18e..64c6c533 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/alignment/grid-self-alignment-stretch-vertical-lr-013.html
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/alignment/grid-self-alignment-stretch-vertical-lr-013.html
@@ -50,7 +50,7 @@
 </style>
 <script src="/resources/testharness.js"></script>
 <script src="/resources/testharnessreport.js"></script>
-<script src="../support/check-layout-th.js"></script>
+<script src="/resources/check-layout-th.js">"></script>
 <body onload="checkLayout('.grid')">
 <div class="grid">
   <div data-offset-x="0"   data-offset-y="0"   data-expected-width="80"  data-expected-height="125" class="firstRowFirstColumn">XX X</div>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/alignment/grid-self-alignment-stretch-vertical-lr-014.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/alignment/grid-self-alignment-stretch-vertical-lr-014.html
index 2a80035..cc2520d 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/alignment/grid-self-alignment-stretch-vertical-lr-014.html
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/alignment/grid-self-alignment-stretch-vertical-lr-014.html
@@ -54,7 +54,7 @@
 </style>
 <script src="/resources/testharness.js"></script>
 <script src="/resources/testharnessreport.js"></script>
-<script src="../support/check-layout-th.js"></script>
+<script src="/resources/check-layout-th.js">"></script>
 <body onload="checkLayout('.grid')">
 <div class="grid">
   <div data-offset-x="0"   data-offset-y="0"   data-expected-width="80"  data-expected-height="110" class="firstRowFirstColumn">XX X</div>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/alignment/grid-self-alignment-stretch-vertical-lr-015.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/alignment/grid-self-alignment-stretch-vertical-lr-015.html
index 34e501f..1382c63 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/alignment/grid-self-alignment-stretch-vertical-lr-015.html
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/alignment/grid-self-alignment-stretch-vertical-lr-015.html
@@ -55,7 +55,7 @@
 </style>
 <script src="/resources/testharness.js"></script>
 <script src="/resources/testharnessreport.js"></script>
-<script src="../support/check-layout-th.js"></script>
+<script src="/resources/check-layout-th.js">"></script>
 <body onload="checkLayout('.grid')">
 <div class="grid">
   <div data-offset-x="0"   data-offset-y="0"   data-expected-width="80"  data-expected-height="120" class="firstRowFirstColumn">XX X</div>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/alignment/grid-self-alignment-stretch-vertical-lr-016.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/alignment/grid-self-alignment-stretch-vertical-lr-016.html
index 5cc5a02..3a82292 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/alignment/grid-self-alignment-stretch-vertical-lr-016.html
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/alignment/grid-self-alignment-stretch-vertical-lr-016.html
@@ -53,7 +53,7 @@
 </style>
 <script src="/resources/testharness.js"></script>
 <script src="/resources/testharnessreport.js"></script>
-<script src="../support/check-layout-th.js"></script>
+<script src="/resources/check-layout-th.js">"></script>
 <body onload="checkLayout('.grid')">
 <div class="grid">
   <div data-offset-x="0"   data-offset-y="0"   data-expected-width="80"  data-expected-height="120" class="firstRowFirstColumn">XX X</div>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/alignment/grid-self-alignment-stretch-vertical-rl-001.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/alignment/grid-self-alignment-stretch-vertical-rl-001.html
index 28a7830..269d48a 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/alignment/grid-self-alignment-stretch-vertical-rl-001.html
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/alignment/grid-self-alignment-stretch-vertical-rl-001.html
@@ -49,7 +49,7 @@
 </style>
 <script src="/resources/testharness.js"></script>
 <script src="/resources/testharnessreport.js"></script>
-<script src="../support/check-layout-th.js"></script>
+<script src="/resources/check-layout-th.js">"></script>
 <body onload="checkLayout('.grid')">
 <div class="grid">
   <div data-offset-x="240" data-offset-y="0"   data-expected-width="10"  data-expected-height="100" class="firstRowFirstColumn">X XX X</div>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/alignment/grid-self-alignment-stretch-vertical-rl-002.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/alignment/grid-self-alignment-stretch-vertical-rl-002.html
index 297b5ff..af1a853 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/alignment/grid-self-alignment-stretch-vertical-rl-002.html
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/alignment/grid-self-alignment-stretch-vertical-rl-002.html
@@ -53,7 +53,7 @@
 </style>
 <script src="/resources/testharness.js"></script>
 <script src="/resources/testharnessreport.js"></script>
-<script src="../support/check-layout-th.js"></script>
+<script src="/resources/check-layout-th.js">"></script>
 <body onload="checkLayout('.grid')">
 <div class="grid">
   <div data-offset-x="240" data-offset-y="0"   data-expected-width="10"  data-expected-height="90"  class="firstRowFirstColumn">X XX X</div>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/alignment/grid-self-alignment-stretch-vertical-rl-003.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/alignment/grid-self-alignment-stretch-vertical-rl-003.html
index e958ec26..9707eeff 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/alignment/grid-self-alignment-stretch-vertical-rl-003.html
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/alignment/grid-self-alignment-stretch-vertical-rl-003.html
@@ -54,7 +54,7 @@
 </style>
 <script src="/resources/testharness.js"></script>
 <script src="/resources/testharnessreport.js"></script>
-<script src="../support/check-layout-th.js"></script>
+<script src="/resources/check-layout-th.js">"></script>
 <body onload="checkLayout('.grid')">
 <div class="grid">
   <div data-offset-x="240" data-offset-y="0"   data-expected-width="10"  data-expected-height="100" class="firstRowFirstColumn">X XX X</div>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/alignment/grid-self-alignment-stretch-vertical-rl-004.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/alignment/grid-self-alignment-stretch-vertical-rl-004.html
index ef2a7e6..906641a 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/alignment/grid-self-alignment-stretch-vertical-rl-004.html
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/alignment/grid-self-alignment-stretch-vertical-rl-004.html
@@ -53,7 +53,7 @@
 </style>
 <script src="/resources/testharness.js"></script>
 <script src="/resources/testharnessreport.js"></script>
-<script src="../support/check-layout-th.js"></script>
+<script src="/resources/check-layout-th.js">"></script>
 <body onload="checkLayout('.grid')">
 <div class="grid">
   <div data-offset-x="240" data-offset-y="0"   data-expected-width="10"  data-expected-height="100" class="firstRowFirstColumn">X XX X</div>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/alignment/grid-self-alignment-stretch-vertical-rl-005.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/alignment/grid-self-alignment-stretch-vertical-rl-005.html
index c512afe..248c521 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/alignment/grid-self-alignment-stretch-vertical-rl-005.html
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/alignment/grid-self-alignment-stretch-vertical-rl-005.html
@@ -50,7 +50,7 @@
 </style>
 <script src="/resources/testharness.js"></script>
 <script src="/resources/testharnessreport.js"></script>
-<script src="../support/check-layout-th.js"></script>
+<script src="/resources/check-layout-th.js">"></script>
 <body onload="checkLayout('.grid')">
 <div class="grid">
   <div data-offset-x="190" data-offset-y="0"   data-expected-width="60"  data-expected-height="100" class="firstRowFirstColumn">X XX X</div>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/alignment/grid-self-alignment-stretch-vertical-rl-006.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/alignment/grid-self-alignment-stretch-vertical-rl-006.html
index 584bfb9..45b20c8 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/alignment/grid-self-alignment-stretch-vertical-rl-006.html
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/alignment/grid-self-alignment-stretch-vertical-rl-006.html
@@ -54,7 +54,7 @@
 </style>
 <script src="/resources/testharness.js"></script>
 <script src="/resources/testharnessreport.js"></script>
-<script src="../support/check-layout-th.js"></script>
+<script src="/resources/check-layout-th.js">"></script>
 <body onload="checkLayout('.grid')">
 <div class="grid">
   <div data-offset-x="190" data-offset-y="0"   data-expected-width="60"  data-expected-height="90"  class="firstRowFirstColumn">X XX X</div>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/alignment/grid-self-alignment-stretch-vertical-rl-007.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/alignment/grid-self-alignment-stretch-vertical-rl-007.html
index 257de49..6d0dd07 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/alignment/grid-self-alignment-stretch-vertical-rl-007.html
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/alignment/grid-self-alignment-stretch-vertical-rl-007.html
@@ -55,7 +55,7 @@
 </style>
 <script src="/resources/testharness.js"></script>
 <script src="/resources/testharnessreport.js"></script>
-<script src="../support/check-layout-th.js"></script>
+<script src="/resources/check-layout-th.js">"></script>
 <body onload="checkLayout('.grid')">
 <div class="grid">
   <div data-offset-x="190" data-offset-y="0"   data-expected-width="60"  data-expected-height="100" class="firstRowFirstColumn">X XX X</div>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/alignment/grid-self-alignment-stretch-vertical-rl-008.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/alignment/grid-self-alignment-stretch-vertical-rl-008.html
index 4e9c264f..043f83f6 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/alignment/grid-self-alignment-stretch-vertical-rl-008.html
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/alignment/grid-self-alignment-stretch-vertical-rl-008.html
@@ -54,7 +54,7 @@
 </style>
 <script src="/resources/testharness.js"></script>
 <script src="/resources/testharnessreport.js"></script>
-<script src="../support/check-layout-th.js"></script>
+<script src="/resources/check-layout-th.js">"></script>
 <body onload="checkLayout('.grid')">
 <div class="grid">
   <div data-offset-x="190" data-offset-y="0"   data-expected-width="60"  data-expected-height="100" class="firstRowFirstColumn">X XX X</div>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/alignment/grid-self-alignment-stretch-vertical-rl-009.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/alignment/grid-self-alignment-stretch-vertical-rl-009.html
index cb66f61..96bebc75 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/alignment/grid-self-alignment-stretch-vertical-rl-009.html
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/alignment/grid-self-alignment-stretch-vertical-rl-009.html
@@ -49,7 +49,7 @@
 </style>
 <script src="/resources/testharness.js"></script>
 <script src="/resources/testharnessreport.js"></script>
-<script src="../support/check-layout-th.js"></script>
+<script src="/resources/check-layout-th.js">"></script>
 <body onload="checkLayout('.grid')">
 <div class="grid">
   <div data-offset-x="230" data-offset-y="0"   data-expected-width="20"  data-expected-height="125" class="firstRowFirstColumn">XX X</div>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/alignment/grid-self-alignment-stretch-vertical-rl-010.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/alignment/grid-self-alignment-stretch-vertical-rl-010.html
index b551d3e..1afcfc4 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/alignment/grid-self-alignment-stretch-vertical-rl-010.html
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/alignment/grid-self-alignment-stretch-vertical-rl-010.html
@@ -53,7 +53,7 @@
 </style>
 <script src="/resources/testharness.js"></script>
 <script src="/resources/testharnessreport.js"></script>
-<script src="../support/check-layout-th.js"></script>
+<script src="/resources/check-layout-th.js">"></script>
 <body onload="checkLayout('.grid')">
 <div class="grid">
   <div data-offset-x="230" data-offset-y="0"   data-expected-width="20"  data-expected-height="110" class="firstRowFirstColumn">XX X</div>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/alignment/grid-self-alignment-stretch-vertical-rl-011.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/alignment/grid-self-alignment-stretch-vertical-rl-011.html
index a56e83a2..736ff94 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/alignment/grid-self-alignment-stretch-vertical-rl-011.html
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/alignment/grid-self-alignment-stretch-vertical-rl-011.html
@@ -54,7 +54,7 @@
 </style>
 <script src="/resources/testharness.js"></script>
 <script src="/resources/testharnessreport.js"></script>
-<script src="../support/check-layout-th.js"></script>
+<script src="/resources/check-layout-th.js">"></script>
 <body onload="checkLayout('.grid')">
 <div class="grid">
   <div data-offset-x="230" data-offset-y="0"   data-expected-width="20"  data-expected-height="120" class="firstRowFirstColumn">XX X</div>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/alignment/grid-self-alignment-stretch-vertical-rl-012.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/alignment/grid-self-alignment-stretch-vertical-rl-012.html
index 91c8ce6..c34b435b 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/alignment/grid-self-alignment-stretch-vertical-rl-012.html
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/alignment/grid-self-alignment-stretch-vertical-rl-012.html
@@ -53,7 +53,7 @@
 </style>
 <script src="/resources/testharness.js"></script>
 <script src="/resources/testharnessreport.js"></script>
-<script src="../support/check-layout-th.js"></script>
+<script src="/resources/check-layout-th.js">"></script>
 <body onload="checkLayout('.grid')">
 <div class="grid">
   <div data-offset-x="230" data-offset-y="0"   data-expected-width="20"  data-expected-height="120" class="firstRowFirstColumn">XX X</div>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/alignment/grid-self-alignment-stretch-vertical-rl-013.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/alignment/grid-self-alignment-stretch-vertical-rl-013.html
index 20eafb78..6e8d3243 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/alignment/grid-self-alignment-stretch-vertical-rl-013.html
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/alignment/grid-self-alignment-stretch-vertical-rl-013.html
@@ -50,7 +50,7 @@
 </style>
 <script src="/resources/testharness.js"></script>
 <script src="/resources/testharnessreport.js"></script>
-<script src="../support/check-layout-th.js"></script>
+<script src="/resources/check-layout-th.js">"></script>
 <body onload="checkLayout('.grid')">
 <div class="grid">
   <div data-offset-x="170" data-offset-y="0"   data-expected-width="80"  data-expected-height="125" class="firstRowFirstColumn">XX X</div>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/alignment/grid-self-alignment-stretch-vertical-rl-014.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/alignment/grid-self-alignment-stretch-vertical-rl-014.html
index 61038b2..4a72112 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/alignment/grid-self-alignment-stretch-vertical-rl-014.html
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/alignment/grid-self-alignment-stretch-vertical-rl-014.html
@@ -54,7 +54,7 @@
 </style>
 <script src="/resources/testharness.js"></script>
 <script src="/resources/testharnessreport.js"></script>
-<script src="../support/check-layout-th.js"></script>
+<script src="/resources/check-layout-th.js">"></script>
 <body onload="checkLayout('.grid')">
 <div class="grid">
   <div data-offset-x="170" data-offset-y="0"   data-expected-width="80"  data-expected-height="110" class="firstRowFirstColumn">XX X</div>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/alignment/grid-self-alignment-stretch-vertical-rl-015.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/alignment/grid-self-alignment-stretch-vertical-rl-015.html
index 3cadf7f..d061174 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/alignment/grid-self-alignment-stretch-vertical-rl-015.html
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/alignment/grid-self-alignment-stretch-vertical-rl-015.html
@@ -55,7 +55,7 @@
 </style>
 <script src="/resources/testharness.js"></script>
 <script src="/resources/testharnessreport.js"></script>
-<script src="../support/check-layout-th.js"></script>
+<script src="/resources/check-layout-th.js">"></script>
 <body onload="checkLayout('.grid')">
 <div class="grid">
   <div data-offset-x="170" data-offset-y="0"   data-expected-width="80"  data-expected-height="120" class="firstRowFirstColumn">XX X</div>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/alignment/grid-self-alignment-stretch-vertical-rl-016.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/alignment/grid-self-alignment-stretch-vertical-rl-016.html
index 03d6f7d..623c026 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/alignment/grid-self-alignment-stretch-vertical-rl-016.html
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/alignment/grid-self-alignment-stretch-vertical-rl-016.html
@@ -54,7 +54,7 @@
 </style>
 <script src="/resources/testharness.js"></script>
 <script src="/resources/testharnessreport.js"></script>
-<script src="../support/check-layout-th.js"></script>
+<script src="/resources/check-layout-th.js">"></script>
 <body onload="checkLayout('.grid')">
 <div class="grid">
   <div data-offset-x="170" data-offset-y="0"   data-expected-width="80"  data-expected-height="120" class="firstRowFirstColumn">XX X</div>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/grid-definition/grid-change-fit-content-argument-001.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/grid-definition/grid-change-fit-content-argument-001.html
index b16de19..9dfb555 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/grid-definition/grid-change-fit-content-argument-001.html
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/grid-definition/grid-change-fit-content-argument-001.html
@@ -22,7 +22,7 @@
 </style>
 <script src="/resources/testharness.js"></script>
 <script src="/resources/testharnessreport.js"></script>
-<script src="../support/check-layout-th.js"></script>
+<script src="/resources/check-layout-th.js">"></script>
 <script>
 function setGridTemplate(id, gridTemplateRows, gridTemplateColumns)
 {
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/grid-model/grid-box-sizing-001.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/grid-model/grid-box-sizing-001.html
index a498d80a..825d35e 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/grid-model/grid-box-sizing-001.html
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/grid-model/grid-box-sizing-001.html
@@ -35,7 +35,7 @@
 </style>
 <script src="/resources/testharness.js"></script>
 <script src="/resources/testharnessreport.js"></script>
-<script src="../support/check-layout-th.js"></script>
+<script src="/resources/check-layout-th.js">"></script>
 
 <body onload="checkLayout('.grid')">
 
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-tables-3/fixed-layout-calc-width-001.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-tables-3/fixed-layout-calc-width-001.html
index 91c665e..4d3622b 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/css/css-tables-3/fixed-layout-calc-width-001.html
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-tables-3/fixed-layout-calc-width-001.html
@@ -1,7 +1,7 @@
 <!DOCTYPE html>
 <script src="/resources/testharness.js"></script>
 <script src="/resources/testharnessreport.js"></script>
-<script src="support/check-layout-th.js"></script>
+<script src="/resources/check-layout-th.js">"></script>
 <link rel="author" title="David Grogan" href="dgrogan@chromium.org">
 <link rel="help" href="https://drafts.csswg.org/css-tables-3/#distributing-width-to-columns">
 
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-tables-3/fixed-layout-excess-width-distribution-001.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-tables-3/fixed-layout-excess-width-distribution-001.html
index a9a78bd..a2d1884 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/css/css-tables-3/fixed-layout-excess-width-distribution-001.html
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-tables-3/fixed-layout-excess-width-distribution-001.html
@@ -1,7 +1,7 @@
 <!DOCTYPE html>
 <script src="/resources/testharness.js"></script>
 <script src="/resources/testharnessreport.js"></script>
-<script src="support/check-layout-th.js"></script>
+<script src="/resources/check-layout-th.js">"></script>
 <link rel="author" title="David Grogan" href="dgrogan@chromium.org">
 <link rel="help" href="https://drafts.csswg.org/css-tables-3/#distributing-width-to-columns">
 
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-tables-3/support/check-layout-th.js b/third_party/WebKit/LayoutTests/external/wpt/css/css-tables-3/support/check-layout-th.js
deleted file mode 100644
index 9b83df7..0000000
--- a/third_party/WebKit/LayoutTests/external/wpt/css/css-tables-3/support/check-layout-th.js
+++ /dev/null
@@ -1,197 +0,0 @@
-(function() {
-// Test is initiated from body.onload, so explicit done() call is required.
-setup({ explicit_done: true });
-
-function checkSubtreeExpectedValues(t, parent, prefix)
-{
-    var checkedLayout = checkExpectedValues(t, parent, prefix);
-    Array.prototype.forEach.call(parent.childNodes, function(node) {
-        checkedLayout |= checkSubtreeExpectedValues(t, node, prefix);
-    });
-    return checkedLayout;
-}
-
-function checkAttribute(output, node, attribute)
-{
-    var result = node.getAttribute && node.getAttribute(attribute);
-    output.checked |= !!result;
-    return result;
-}
-
-function assert_tolerance(actual, expected, message)
-{
-    if (isNaN(expected) || Math.abs(actual - expected) >= 1) {
-        assert_equals(actual, Number(expected), message);
-    }
-}
-
-function checkExpectedValues(t, node, prefix)
-{
-    var output = { checked: false };
-
-    var expectedWidth = checkAttribute(output, node, "data-expected-width");
-    if (expectedWidth) {
-        assert_tolerance(node.offsetWidth, expectedWidth, prefix + "width");
-    }
-
-    var expectedHeight = checkAttribute(output, node, "data-expected-height");
-    if (expectedHeight) {
-        assert_tolerance(node.offsetHeight, expectedHeight, prefix + "height");
-    }
-
-    var expectedOffset = checkAttribute(output, node, "data-offset-x");
-    if (expectedOffset) {
-        assert_tolerance(node.offsetLeft, expectedOffset, prefix + "offsetLeft");
-    }
-
-    var expectedOffset = checkAttribute(output, node, "data-offset-y");
-    if (expectedOffset) {
-        assert_tolerance(node.offsetTop, expectedOffset, prefix + "offsetTop");
-    }
-
-    var expectedWidth = checkAttribute(output, node, "data-expected-client-width");
-    if (expectedWidth) {
-        assert_tolerance(node.clientWidth, expectedWidth, prefix + "clientWidth");
-    }
-
-    var expectedHeight = checkAttribute(output, node, "data-expected-client-height");
-    if (expectedHeight) {
-        assert_tolerance(node.clientHeight, expectedHeight, prefix + "clientHeight");
-    }
-
-    var expectedWidth = checkAttribute(output, node, "data-expected-scroll-width");
-    if (expectedWidth) {
-        assert_tolerance(node.scrollWidth, expectedWidth, prefix + "scrollWidth");
-    }
-
-    var expectedHeight = checkAttribute(output, node, "data-expected-scroll-height");
-    if (expectedHeight) {
-        assert_tolerance(node.scrollHeight, expectedHeight, prefix + "scrollHeight");
-    }
-
-    var expectedWidth = checkAttribute(output, node, "data-expected-bounding-client-rect-width");
-    if (expectedWidth) {
-        assert_tolerance(node.getBoundingClientRect().width, expectedWidth, prefix + "getBoundingClientRect().width");
-    }
-
-    var expectedOffset = checkAttribute(output, node, "data-total-x");
-    if (expectedOffset) {
-        var totalLeft = node.clientLeft + node.offsetLeft;
-        assert_tolerance(totalLeft, expectedOffset, prefix +
-                         "clientLeft+offsetLeft (" + node.clientLeft + " + " + node.offsetLeft + ")");
-    }
-
-    var expectedOffset = checkAttribute(output, node, "data-total-y");
-    if (expectedOffset) {
-        var totalTop = node.clientTop + node.offsetTop;
-        assert_tolerance(totalTop, expectedOffset, prefix +
-                         "clientTop+offsetTop (" + node.clientTop + " + " + node.offsetTop + ")");
-    }
-
-    var expectedDisplay = checkAttribute(output, node, "data-expected-display");
-    if (expectedDisplay) {
-        var actualDisplay = getComputedStyle(node).display;
-        assert_equals(actualDisplay, expectedDisplay, prefix + "display");
-    }
-
-    var expectedPaddingTop = checkAttribute(output, node, "data-expected-padding-top");
-    if (expectedPaddingTop) {
-        var actualPaddingTop = getComputedStyle(node).paddingTop;
-        // Trim the unit "px" from the output.
-        actualPaddingTop = actualPaddingTop.slice(0, -2);
-        assert_equals(actualPaddingTop, expectedPaddingTop, prefix + "padding-top");
-    }
-
-    var expectedPaddingBottom = checkAttribute(output, node, "data-expected-padding-bottom");
-    if (expectedPaddingBottom) {
-        var actualPaddingBottom = getComputedStyle(node).paddingBottom;
-        // Trim the unit "px" from the output.
-        actualPaddingBottom = actualPaddingBottom.slice(0, -2);
-        assert_equals(actualPaddingBottom, expectedPaddingBottom, prefix + "padding-bottom");
-    }
-
-    var expectedPaddingLeft = checkAttribute(output, node, "data-expected-padding-left");
-    if (expectedPaddingLeft) {
-        var actualPaddingLeft = getComputedStyle(node).paddingLeft;
-        // Trim the unit "px" from the output.
-        actualPaddingLeft = actualPaddingLeft.slice(0, -2);
-        assert_equals(actualPaddingLeft, expectedPaddingLeft, prefix + "padding-left");
-    }
-
-    var expectedPaddingRight = checkAttribute(output, node, "data-expected-padding-right");
-    if (expectedPaddingRight) {
-        var actualPaddingRight = getComputedStyle(node).paddingRight;
-        // Trim the unit "px" from the output.
-        actualPaddingRight = actualPaddingRight.slice(0, -2);
-        assert_equals(actualPaddingRight, expectedPaddingRight, prefix + "padding-right");
-    }
-
-    var expectedMarginTop = checkAttribute(output, node, "data-expected-margin-top");
-    if (expectedMarginTop) {
-        var actualMarginTop = getComputedStyle(node).marginTop;
-        // Trim the unit "px" from the output.
-        actualMarginTop = actualMarginTop.slice(0, -2);
-        assert_equals(actualMarginTop, expectedMarginTop, prefix + "margin-top");
-    }
-
-    var expectedMarginBottom = checkAttribute(output, node, "data-expected-margin-bottom");
-    if (expectedMarginBottom) {
-        var actualMarginBottom = getComputedStyle(node).marginBottom;
-        // Trim the unit "px" from the output.
-        actualMarginBottom = actualMarginBottom.slice(0, -2);
-        assert_equals(actualMarginBottom, expectedMarginBottom, prefix + "margin-bottom");
-    }
-
-    var expectedMarginLeft = checkAttribute(output, node, "data-expected-margin-left");
-    if (expectedMarginLeft) {
-        var actualMarginLeft = getComputedStyle(node).marginLeft;
-        // Trim the unit "px" from the output.
-        actualMarginLeft = actualMarginLeft.slice(0, -2);
-        assert_equals(actualMarginLeft, expectedMarginLeft, prefix + "margin-left");
-    }
-
-    var expectedMarginRight = checkAttribute(output, node, "data-expected-margin-right");
-    if (expectedMarginRight) {
-        var actualMarginRight = getComputedStyle(node).marginRight;
-        // Trim the unit "px" from the output.
-        actualMarginRight = actualMarginRight.slice(0, -2);
-        assert_equals(actualMarginRight, expectedMarginRight, prefix + "margin-right");
-    }
-
-    return output.checked;
-}
-
-var testNumber = 0;
-
-window.checkLayout = function(selectorList, callDone = true)
-{
-    if (!selectorList) {
-        console.error("You must provide a CSS selector of nodes to check.");
-        return;
-    }
-    var nodes = document.querySelectorAll(selectorList);
-    nodes = Array.prototype.slice.call(nodes);
-    nodes.reverse();
-    var checkedLayout = false;
-    Array.prototype.forEach.call(nodes, function(node) {
-        test(function(t) {
-            var container = node.parentNode.className == 'container' ? node.parentNode : node;
-            var prefix = "\n" + container.outerHTML + "\n";
-            var passed = false;
-            try {
-                checkedLayout |= checkExpectedValues(t, node.parentNode, prefix);
-                checkedLayout |= checkSubtreeExpectedValues(t, node, prefix);
-                passed = true;
-            } finally {
-                checkedLayout |= !passed;
-            }
-        }, selectorList + ' ' + String(++testNumber));
-    });
-    if (!checkedLayout) {
-        console.error("No valid data-* attributes found in selector list : " + selectorList);
-    }
-    if (callDone)
-        done();
-};
-
-})();
diff --git a/third_party/WebKit/LayoutTests/external/wpt/html/dom/interfaces-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/html/dom/interfaces-expected.txt
index bc7464b7..50fb1d8 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/html/dom/interfaces-expected.txt
+++ b/third_party/WebKit/LayoutTests/external/wpt/html/dom/interfaces-expected.txt
@@ -1,5 +1,5 @@
 This is a testharness.js-based test.
-Found 5285 tests; 5165 PASS, 120 FAIL, 0 TIMEOUT, 0 NOTRUN.
+Found 5286 tests; 5166 PASS, 120 FAIL, 0 TIMEOUT, 0 NOTRUN.
 PASS Test driver
 PASS Document interface: attribute domain
 PASS Document interface: attribute referrer
@@ -542,7 +542,7 @@
 PASS HTMLElement interface: attribute hidden
 PASS HTMLElement interface: operation click()
 PASS HTMLElement interface: attribute tabIndex
-PASS HTMLElement interface: operation focus()
+PASS HTMLElement interface: operation focus(FocusOptions)
 PASS HTMLElement interface: operation blur()
 PASS HTMLElement interface: attribute accessKey
 FAIL HTMLElement interface: attribute accessKeyLabel assert_true: The prototype object must have a property "accessKeyLabel" expected true got false
@@ -626,7 +626,8 @@
 PASS HTMLElement interface: document.createElement("noscript") must inherit property "hidden" with the proper type
 PASS HTMLElement interface: document.createElement("noscript") must inherit property "click()" with the proper type
 PASS HTMLElement interface: document.createElement("noscript") must inherit property "tabIndex" with the proper type
-PASS HTMLElement interface: document.createElement("noscript") must inherit property "focus()" with the proper type
+PASS HTMLElement interface: document.createElement("noscript") must inherit property "focus(FocusOptions)" with the proper type
+PASS HTMLElement interface: calling focus(FocusOptions) on document.createElement("noscript") with too few arguments must throw TypeError
 PASS HTMLElement interface: document.createElement("noscript") must inherit property "blur()" with the proper type
 PASS HTMLElement interface: document.createElement("noscript") must inherit property "accessKey" with the proper type
 FAIL HTMLElement interface: document.createElement("noscript") must inherit property "accessKeyLabel" with the proper type assert_inherits: property "accessKeyLabel" not found in prototype chain
diff --git a/third_party/WebKit/LayoutTests/external/wpt/html/editing/focus/processing-model/preventScroll-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/html/editing/focus/processing-model/preventScroll-expected.txt
new file mode 100644
index 0000000..3e0d12a
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/html/editing/focus/processing-model/preventScroll-expected.txt
@@ -0,0 +1,10 @@
+This is a testharness.js-based test.
+PASS Sanity test
+PASS elm.focus() without arguments
+PASS elm.focus(undefined)
+PASS elm.focus(null)
+PASS elm.focus({})
+PASS elm.focus({preventScroll: false})
+FAIL elm.focus({preventScroll: true}) assert_false: expected false got true
+Harness: the test ran to completion.
+
diff --git a/third_party/WebKit/LayoutTests/external/wpt/html/editing/focus/processing-model/preventScroll.html b/third_party/WebKit/LayoutTests/external/wpt/html/editing/focus/processing-model/preventScroll.html
new file mode 100644
index 0000000..fda9480
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/html/editing/focus/processing-model/preventScroll.html
@@ -0,0 +1,75 @@
+<!doctype html>
+<title>focus(options) - preventScroll</title>
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<style>
+#iframe { width: 500px; height: 500px; border: none }
+</style>
+<iframe id=iframe src="support/preventScroll-helper.html"></iframe>
+<script>
+function isEntirelyInView(elm, win) {
+  const inViewHorizontal = (elm.offsetLeft >= win.scrollX) &&
+                           ((elm.offsetLeft + elm.clientWidth) <= (win.scrollX + win.innerWidth));
+  const inViewVertical = (elm.offsetTop >= win.scrollY) &&
+                         ((elm.offsetTop + elm.clientHeight) <= (win.scrollY + win.innerHeight));
+  return inViewHorizontal && inViewVertical;
+}
+
+setup({explicit_done: true});
+
+function resetState(win) {
+  win.scrollTo(0, 0);
+  win.document.activeElement.blur();
+}
+
+onload = () => {
+  const win = document.getElementById('iframe').contentWindow;
+  const elm = win.document.getElementById('button');
+
+  test(() => {
+    assert_false(isEntirelyInView(elm, win), 'initial state');
+    elm.scrollIntoView();
+    assert_true(isEntirelyInView(elm, win), 'after elm.scrollIntoView()');
+    resetState(win);
+    assert_false(isEntirelyInView(elm, win), 'after resetScrollPosition(win)');
+  }, 'Sanity test');
+
+  test(() => {
+    resetState(win);
+    elm.focus();
+    assert_true(isEntirelyInView(elm, win));
+  }, 'elm.focus() without arguments');
+
+  test(() => {
+    resetState(win);
+    elm.focus(undefined);
+    assert_true(isEntirelyInView(elm, win));
+  }, 'elm.focus(undefined)');
+
+  test(() => {
+    resetState(win);
+    elm.focus(null);
+    assert_true(isEntirelyInView(elm, win));
+  }, 'elm.focus(null)');
+
+  test(() => {
+    resetState(win);
+    elm.focus({});
+    assert_true(isEntirelyInView(elm, win));
+  }, 'elm.focus({})');
+
+  test(() => {
+    resetState(win);
+    elm.focus({preventScroll: false});
+    assert_true(isEntirelyInView(elm, win));
+  }, 'elm.focus({preventScroll: false})');
+
+  test(() => {
+    resetState(win);
+    elm.focus({preventScroll: true});
+    assert_false(isEntirelyInView(elm, win));
+  }, 'elm.focus({preventScroll: true})');
+
+  done();
+}
+</script>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/html/editing/focus/processing-model/support/preventScroll-helper.html b/third_party/WebKit/LayoutTests/external/wpt/html/editing/focus/processing-model/support/preventScroll-helper.html
new file mode 100644
index 0000000..43c6d86
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/html/editing/focus/processing-model/support/preventScroll-helper.html
@@ -0,0 +1,6 @@
+<!doctype html>
+<title>Helper document for preventScroll test</title>
+<style>
+body { padding: 2000px }
+</style>
+<button id=button>X</button>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/html/semantics/scripting-1/the-script-element/module/integrity-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/html/semantics/scripting-1/the-script-element/module/integrity-expected.txt
deleted file mode 100644
index 5a25e7b..0000000
--- a/third_party/WebKit/LayoutTests/external/wpt/html/semantics/scripting-1/the-script-element/module/integrity-expected.txt
+++ /dev/null
@@ -1,6 +0,0 @@
-This is a testharness.js-based test.
-PASS The integrity attribute must have no affect on inline module scripts
-PASS The integrity attribute must be verified on the top-level of a module and allow it to execute when it matches
-FAIL The integrity attribute must be verified on the top-level of a module and not allow it to execute when there's a mismatch assert_array_equals: The module and its dependency must not have executed lengths differ, expected 0 got 2
-Harness: the test ran to completion.
-
diff --git a/third_party/WebKit/LayoutTests/external/wpt/interfaces/ambient-light.idl b/third_party/WebKit/LayoutTests/external/wpt/interfaces/ambient-light.idl
new file mode 100644
index 0000000..0bdc9cb
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/interfaces/ambient-light.idl
@@ -0,0 +1,4 @@
+[Constructor(optional SensorOptions sensorOptions), SecureContext, Exposed=Window]
+interface AmbientLightSensor : Sensor {
+  readonly attribute double? illuminance;
+};
diff --git a/third_party/WebKit/LayoutTests/external/wpt/interfaces/html.idl b/third_party/WebKit/LayoutTests/external/wpt/interfaces/html.idl
index 2dc65f08..a869334 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/interfaces/html.idl
+++ b/third_party/WebKit/LayoutTests/external/wpt/interfaces/html.idl
@@ -101,7 +101,7 @@
   [CEReactions] attribute boolean hidden;
   void click();
   [CEReactions] attribute long tabIndex;
-  void focus();
+  void focus(optional FocusOptions options);
   void blur();
   [CEReactions] attribute DOMString accessKey;
   readonly attribute DOMString accessKeyLabel;
@@ -111,6 +111,10 @@
   [CEReactions] attribute [TreatNullAs=EmptyString] DOMString innerText;
 };
 
+dictionary FocusOptions {
+  boolean preventScroll = false;
+};
+
 HTMLElement implements GlobalEventHandlers;
 HTMLElement implements DocumentAndElementEventHandlers;
 HTMLElement implements ElementContentEditable;
diff --git a/third_party/WebKit/LayoutTests/external/wpt/intersection-observer/observer-exceptions.html b/third_party/WebKit/LayoutTests/external/wpt/intersection-observer/observer-exceptions.html
index b44b7bd..d4f178b 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/intersection-observer/observer-exceptions.html
+++ b/third_party/WebKit/LayoutTests/external/wpt/intersection-observer/observer-exceptions.html
@@ -31,7 +31,19 @@
   assert_throws("SYNTAX_ERR", function() {
     new IntersectionObserver(e => {}, {rootMargin: "auto"})
   })
-}, 'IntersectionObserver constructor width { rootMargin: "auto" }');
+}, 'IntersectionObserver constructor with { rootMargin: "auto" }');
+
+test(function () {
+  assert_throws("SYNTAX_ERR", function() {
+    new IntersectionObserver(e => {}, {rootMargin: "calc(1px + 2px)"})
+  })
+}, 'IntersectionObserver constructor with { rootMargin: "calc(1px + 2px)" }');
+
+test(function () {
+  assert_throws("SYNTAX_ERR", function() {
+    new IntersectionObserver(e => {}, {rootMargin: "1px !important"})
+  })
+}, 'IntersectionObserver constructor with { rootMargin: "1px !important" }');
 
 test(function () {
   assert_throws("SYNTAX_ERR", function() {
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/support/check-layout-th.js b/third_party/WebKit/LayoutTests/external/wpt/resources/check-layout-th.js
similarity index 100%
rename from third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/support/check-layout-th.js
rename to third_party/WebKit/LayoutTests/external/wpt/resources/check-layout-th.js
diff --git a/third_party/WebKit/LayoutTests/external/wpt/resources/idlharness.js b/third_party/WebKit/LayoutTests/external/wpt/resources/idlharness.js
index eda6a42..587325c 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/resources/idlharness.js
+++ b/third_party/WebKit/LayoutTests/external/wpt/resources/idlharness.js
@@ -167,11 +167,11 @@
 };
 
 //@}
-IdlArray.prototype.add_idls = function(raw_idls)
+IdlArray.prototype.add_idls = function(raw_idls, options)
 //@{
 {
     /** Entry point.  See documentation at beginning of file. */
-    this.internal_add_idls(WebIDL2.parse(raw_idls));
+    this.internal_add_idls(WebIDL2.parse(raw_idls), options);
 };
 
 //@}
@@ -195,27 +195,60 @@
 };
 
 //@}
-IdlArray.prototype.internal_add_idls = function(parsed_idls)
+IdlArray.prototype.internal_add_idls = function(parsed_idls, options)
 //@{
 {
     /**
      * Internal helper called by add_idls() and add_untested_idls().
+     *
      * parsed_idls is an array of objects that come from WebIDLParser.js's
      * "definitions" production.  The add_untested_idls() entry point
      * additionally sets an .untested property on each object (and its
      * .members) so that they'll be skipped by test() -- they'll only be
      * used for base interfaces of tested interfaces, return types, etc.
+     *
+     * options is a dictionary that can have an only or except member which are
+     * arrays. If only is given then only members, partials and interface
+     * targets listed will be added, and if except is given only those that
+     * aren't listed will be added. Only one of only and except can be used.
      */
+
+    if (options && options.only && options.except)
+    {
+        throw "The only and except options can't be used together."
+    }
+
+    function should_skip(name)
+    {
+        if (options && options.only && options.only.indexOf(name) == -1)
+        {
+            return true;
+        }
+        if (options && options.except && options.except.indexOf(name) != -1)
+        {
+            return true;
+        }
+        return false;
+    }
+
     parsed_idls.forEach(function(parsed_idl)
     {
         if (parsed_idl.type == "interface" && parsed_idl.partial)
         {
+            if (should_skip(parsed_idl.name))
+            {
+                return;
+            }
             this.partials.push(parsed_idl);
             return;
         }
 
         if (parsed_idl.type == "implements")
         {
+            if (should_skip(parsed_idl.target))
+            {
+                return;
+            }
             if (!(parsed_idl.target in this["implements"]))
             {
                 this["implements"][parsed_idl.target] = [];
@@ -229,6 +262,10 @@
         {
             throw "Duplicate identifier " + parsed_idl.name;
         }
+        if (should_skip(parsed_idl.name))
+        {
+            return;
+        }
         switch(parsed_idl.type)
         {
         case "interface":
diff --git a/third_party/WebKit/LayoutTests/external/wpt/viewport/viewport-attribute-event-handlers-manual.html b/third_party/WebKit/LayoutTests/external/wpt/visual-viewport/viewport-attribute-event-handlers-manual.html
similarity index 100%
rename from third_party/WebKit/LayoutTests/external/wpt/viewport/viewport-attribute-event-handlers-manual.html
rename to third_party/WebKit/LayoutTests/external/wpt/visual-viewport/viewport-attribute-event-handlers-manual.html
diff --git a/third_party/WebKit/LayoutTests/external/wpt/viewport/viewport-dimensions-custom-scrollbars-manual.html b/third_party/WebKit/LayoutTests/external/wpt/visual-viewport/viewport-dimensions-custom-scrollbars-manual.html
similarity index 100%
rename from third_party/WebKit/LayoutTests/external/wpt/viewport/viewport-dimensions-custom-scrollbars-manual.html
rename to third_party/WebKit/LayoutTests/external/wpt/visual-viewport/viewport-dimensions-custom-scrollbars-manual.html
diff --git a/third_party/WebKit/LayoutTests/external/wpt/viewport/viewport-dimensions-scrollbars-manual.html b/third_party/WebKit/LayoutTests/external/wpt/visual-viewport/viewport-dimensions-scrollbars-manual.html
similarity index 100%
rename from third_party/WebKit/LayoutTests/external/wpt/viewport/viewport-dimensions-scrollbars-manual.html
rename to third_party/WebKit/LayoutTests/external/wpt/visual-viewport/viewport-dimensions-scrollbars-manual.html
diff --git a/third_party/WebKit/LayoutTests/external/wpt/viewport/viewport-no-resize-event-on-overflow-recalc.html b/third_party/WebKit/LayoutTests/external/wpt/visual-viewport/viewport-no-resize-event-on-overflow-recalc.html
similarity index 100%
rename from third_party/WebKit/LayoutTests/external/wpt/viewport/viewport-no-resize-event-on-overflow-recalc.html
rename to third_party/WebKit/LayoutTests/external/wpt/visual-viewport/viewport-no-resize-event-on-overflow-recalc.html
diff --git a/third_party/WebKit/LayoutTests/external/wpt/viewport/viewport-offset-manual.html b/third_party/WebKit/LayoutTests/external/wpt/visual-viewport/viewport-offset-manual.html
similarity index 100%
rename from third_party/WebKit/LayoutTests/external/wpt/viewport/viewport-offset-manual.html
rename to third_party/WebKit/LayoutTests/external/wpt/visual-viewport/viewport-offset-manual.html
diff --git a/third_party/WebKit/LayoutTests/external/wpt/viewport/viewport-page-manual.html b/third_party/WebKit/LayoutTests/external/wpt/visual-viewport/viewport-page-manual.html
similarity index 100%
rename from third_party/WebKit/LayoutTests/external/wpt/viewport/viewport-page-manual.html
rename to third_party/WebKit/LayoutTests/external/wpt/visual-viewport/viewport-page-manual.html
diff --git a/third_party/WebKit/LayoutTests/external/wpt/viewport/viewport-read-size-causes-layout.html b/third_party/WebKit/LayoutTests/external/wpt/visual-viewport/viewport-read-size-causes-layout.html
similarity index 100%
rename from third_party/WebKit/LayoutTests/external/wpt/viewport/viewport-read-size-causes-layout.html
rename to third_party/WebKit/LayoutTests/external/wpt/visual-viewport/viewport-read-size-causes-layout.html
diff --git a/third_party/WebKit/LayoutTests/external/wpt/viewport/viewport-read-size-in-iframe-causes-layout.html b/third_party/WebKit/LayoutTests/external/wpt/visual-viewport/viewport-read-size-in-iframe-causes-layout.html
similarity index 100%
rename from third_party/WebKit/LayoutTests/external/wpt/viewport/viewport-read-size-in-iframe-causes-layout.html
rename to third_party/WebKit/LayoutTests/external/wpt/visual-viewport/viewport-read-size-in-iframe-causes-layout.html
diff --git a/third_party/WebKit/LayoutTests/external/wpt/viewport/viewport-resize-event-manual.html b/third_party/WebKit/LayoutTests/external/wpt/visual-viewport/viewport-resize-event-manual.html
similarity index 100%
rename from third_party/WebKit/LayoutTests/external/wpt/viewport/viewport-resize-event-manual.html
rename to third_party/WebKit/LayoutTests/external/wpt/visual-viewport/viewport-resize-event-manual.html
diff --git a/third_party/WebKit/LayoutTests/external/wpt/viewport/viewport-resize-event-on-load-overflowing-page.html b/third_party/WebKit/LayoutTests/external/wpt/visual-viewport/viewport-resize-event-on-load-overflowing-page.html
similarity index 100%
rename from third_party/WebKit/LayoutTests/external/wpt/viewport/viewport-resize-event-on-load-overflowing-page.html
rename to third_party/WebKit/LayoutTests/external/wpt/visual-viewport/viewport-resize-event-on-load-overflowing-page.html
diff --git a/third_party/WebKit/LayoutTests/external/wpt/viewport/viewport-scale-iframe-manual.html b/third_party/WebKit/LayoutTests/external/wpt/visual-viewport/viewport-scale-iframe-manual.html
similarity index 100%
rename from third_party/WebKit/LayoutTests/external/wpt/viewport/viewport-scale-iframe-manual.html
rename to third_party/WebKit/LayoutTests/external/wpt/visual-viewport/viewport-scale-iframe-manual.html
diff --git a/third_party/WebKit/LayoutTests/external/wpt/viewport/viewport-scale-manual.html b/third_party/WebKit/LayoutTests/external/wpt/visual-viewport/viewport-scale-manual.html
similarity index 100%
rename from third_party/WebKit/LayoutTests/external/wpt/viewport/viewport-scale-manual.html
rename to third_party/WebKit/LayoutTests/external/wpt/visual-viewport/viewport-scale-manual.html
diff --git a/third_party/WebKit/LayoutTests/external/wpt/viewport/viewport-scroll-event-manual.html b/third_party/WebKit/LayoutTests/external/wpt/visual-viewport/viewport-scroll-event-manual.html
similarity index 100%
rename from third_party/WebKit/LayoutTests/external/wpt/viewport/viewport-scroll-event-manual.html
rename to third_party/WebKit/LayoutTests/external/wpt/visual-viewport/viewport-scroll-event-manual.html
diff --git a/third_party/WebKit/LayoutTests/external/wpt/viewport/viewport-scrollbars-cause-resize.html b/third_party/WebKit/LayoutTests/external/wpt/visual-viewport/viewport-scrollbars-cause-resize.html
similarity index 100%
rename from third_party/WebKit/LayoutTests/external/wpt/viewport/viewport-scrollbars-cause-resize.html
rename to third_party/WebKit/LayoutTests/external/wpt/visual-viewport/viewport-scrollbars-cause-resize.html
diff --git a/third_party/WebKit/LayoutTests/external/wpt/viewport/viewport-type.html b/third_party/WebKit/LayoutTests/external/wpt/visual-viewport/viewport-type.html
similarity index 100%
rename from third_party/WebKit/LayoutTests/external/wpt/viewport/viewport-type.html
rename to third_party/WebKit/LayoutTests/external/wpt/visual-viewport/viewport-type.html
diff --git a/third_party/WebKit/LayoutTests/external/wpt/viewport/viewport-unscaled-scale-iframe.html b/third_party/WebKit/LayoutTests/external/wpt/visual-viewport/viewport-unscaled-scale-iframe.html
similarity index 100%
rename from third_party/WebKit/LayoutTests/external/wpt/viewport/viewport-unscaled-scale-iframe.html
rename to third_party/WebKit/LayoutTests/external/wpt/visual-viewport/viewport-unscaled-scale-iframe.html
diff --git a/third_party/WebKit/LayoutTests/external/wpt/viewport/viewport-unscaled-scale.html b/third_party/WebKit/LayoutTests/external/wpt/visual-viewport/viewport-unscaled-scale.html
similarity index 100%
rename from third_party/WebKit/LayoutTests/external/wpt/viewport/viewport-unscaled-scale.html
rename to third_party/WebKit/LayoutTests/external/wpt/visual-viewport/viewport-unscaled-scale.html
diff --git a/third_party/WebKit/LayoutTests/external/wpt/viewport/viewport-unscaled-scroll-iframe.html b/third_party/WebKit/LayoutTests/external/wpt/visual-viewport/viewport-unscaled-scroll-iframe.html
similarity index 100%
rename from third_party/WebKit/LayoutTests/external/wpt/viewport/viewport-unscaled-scroll-iframe.html
rename to third_party/WebKit/LayoutTests/external/wpt/visual-viewport/viewport-unscaled-scroll-iframe.html
diff --git a/third_party/WebKit/LayoutTests/external/wpt/viewport/viewport-unscaled-scroll.html b/third_party/WebKit/LayoutTests/external/wpt/visual-viewport/viewport-unscaled-scroll.html
similarity index 100%
rename from third_party/WebKit/LayoutTests/external/wpt/viewport/viewport-unscaled-scroll.html
rename to third_party/WebKit/LayoutTests/external/wpt/visual-viewport/viewport-unscaled-scroll.html
diff --git a/third_party/WebKit/LayoutTests/external/wpt/viewport/viewport-unscaled-size-iframe.html b/third_party/WebKit/LayoutTests/external/wpt/visual-viewport/viewport-unscaled-size-iframe.html
similarity index 100%
rename from third_party/WebKit/LayoutTests/external/wpt/viewport/viewport-unscaled-size-iframe.html
rename to third_party/WebKit/LayoutTests/external/wpt/visual-viewport/viewport-unscaled-size-iframe.html
diff --git a/third_party/WebKit/LayoutTests/external/wpt/viewport/viewport-unscaled-size.html b/third_party/WebKit/LayoutTests/external/wpt/visual-viewport/viewport-unscaled-size.html
similarity index 100%
rename from third_party/WebKit/LayoutTests/external/wpt/viewport/viewport-unscaled-size.html
rename to third_party/WebKit/LayoutTests/external/wpt/visual-viewport/viewport-unscaled-size.html
diff --git a/third_party/WebKit/LayoutTests/external/wpt/viewport/viewport-url-bar-changes-height-manual.html b/third_party/WebKit/LayoutTests/external/wpt/visual-viewport/viewport-url-bar-changes-height-manual.html
similarity index 100%
rename from third_party/WebKit/LayoutTests/external/wpt/viewport/viewport-url-bar-changes-height-manual.html
rename to third_party/WebKit/LayoutTests/external/wpt/visual-viewport/viewport-url-bar-changes-height-manual.html
diff --git a/third_party/WebKit/LayoutTests/external/wpt/viewport/viewport_support.js b/third_party/WebKit/LayoutTests/external/wpt/visual-viewport/viewport_support.js
similarity index 100%
rename from third_party/WebKit/LayoutTests/external/wpt/viewport/viewport_support.js
rename to third_party/WebKit/LayoutTests/external/wpt/visual-viewport/viewport_support.js
diff --git a/third_party/WebKit/LayoutTests/external/wpt/websockets/README.md b/third_party/WebKit/LayoutTests/external/wpt/websockets/README.md
index 0e5ffd68..b4f173a 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/websockets/README.md
+++ b/third_party/WebKit/LayoutTests/external/wpt/websockets/README.md
@@ -1,2 +1,2 @@
 These are the `WebSocket` tests for the
-[Web sockets chapter of the HTML Standard](https://html.spec.whatwg.org/multipage/comms.html#network).
+[Web sockets chapter of the HTML Standard](https://html.spec.whatwg.org/multipage/web-sockets.html#network).
diff --git a/third_party/WebKit/LayoutTests/external/wpt/worklets/animation-worklet-import.html b/third_party/WebKit/LayoutTests/external/wpt/worklets/animation-worklet-import.html
index 3457d44..98b56d3 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/worklets/animation-worklet-import.html
+++ b/third_party/WebKit/LayoutTests/external/wpt/worklets/animation-worklet-import.html
@@ -4,11 +4,12 @@
     <script src="/common/get-host-info.sub.js"></script>
     <script src="/resources/testharness.js"></script>
     <script src="/resources/testharnessreport.js"></script>
+    <script src="resources/worklet-test-utils.js"></script>
     <script src="resources/import-tests.js"></script>
 </head>
 <body>
 <script>
-    runImportTests(window.animationWorklet);
+    runImportTests("animation");
 </script>
 </body>
 </html>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/worklets/animation-worklet-referrer.html b/third_party/WebKit/LayoutTests/external/wpt/worklets/animation-worklet-referrer.html
new file mode 100644
index 0000000..494e06a
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/worklets/animation-worklet-referrer.html
@@ -0,0 +1,15 @@
+<!DOCTYPE html>
+<html>
+<head>
+    <script src="/common/get-host-info.sub.js"></script>
+    <script src="/resources/testharness.js"></script>
+    <script src="/resources/testharnessreport.js"></script>
+    <script src="resources/worklet-test-utils.js"></script>
+    <script src="resources/referrer-tests.js"></script>
+</head>
+<body>
+<script>
+    runReferrerTests("animation");
+</script>
+</body>
+</html>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/worklets/paint-worklet-import.html b/third_party/WebKit/LayoutTests/external/wpt/worklets/paint-worklet-import.html
index f65e308a..68e926c8 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/worklets/paint-worklet-import.html
+++ b/third_party/WebKit/LayoutTests/external/wpt/worklets/paint-worklet-import.html
@@ -4,11 +4,12 @@
     <script src="/common/get-host-info.sub.js"></script>
     <script src="/resources/testharness.js"></script>
     <script src="/resources/testharnessreport.js"></script>
+    <script src="resources/worklet-test-utils.js"></script>
     <script src="resources/import-tests.js"></script>
 </head>
 <body>
 <script>
-    runImportTests(CSS.paintWorklet);
+    runImportTests("paint");
 </script>
 </body>
 </html>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/worklets/paint-worklet-referrer.html b/third_party/WebKit/LayoutTests/external/wpt/worklets/paint-worklet-referrer.html
new file mode 100644
index 0000000..a4b5a6f49
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/worklets/paint-worklet-referrer.html
@@ -0,0 +1,15 @@
+<!DOCTYPE html>
+<html>
+<head>
+    <script src="/common/get-host-info.sub.js"></script>
+    <script src="/resources/testharness.js"></script>
+    <script src="/resources/testharnessreport.js"></script>
+    <script src="resources/worklet-test-utils.js"></script>
+    <script src="resources/referrer-tests.js"></script>
+</head>
+<body>
+<script>
+    runReferrerTests("paint");
+</script>
+</body>
+</html>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/worklets/resources/import-tests.js b/third_party/WebKit/LayoutTests/external/wpt/worklets/resources/import-tests.js
index d40ed3e..b2374e76 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/worklets/resources/import-tests.js
+++ b/third_party/WebKit/LayoutTests/external/wpt/worklets/resources/import-tests.js
@@ -1,8 +1,10 @@
 // Runs a series of tests related to importing scripts on a worklet.
 //
 // Usage:
-// runImportTests(workletType);
-function runImportTests(worklet) {
+// runImportTests("paint");
+function runImportTests(worklet_type) {
+    const worklet = get_worklet(worklet_type);
+
     promise_test(() => {
         const kScriptURL = 'resources/empty-worklet-script.js';
         return worklet.addModule(kScriptURL).then(undefined_arg => {
diff --git a/third_party/WebKit/LayoutTests/external/wpt/worklets/resources/referrer-tests.js b/third_party/WebKit/LayoutTests/external/wpt/worklets/resources/referrer-tests.js
new file mode 100644
index 0000000..366bb9b
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/worklets/resources/referrer-tests.js
@@ -0,0 +1,96 @@
+function openWindow(url) {
+  return new Promise(resolve => {
+      let win = window.open(url, '_blank');
+      add_completion_callback(() => win.close());
+      window.onmessage = e => {
+        assert_equals(e.data, 'LOADED');
+        resolve(win);
+      };
+    });
+}
+
+// Runs a series of tests related to the referrer policy on a worklet.
+//
+// Usage:
+// runReferrerTests("paint");
+function runReferrerTests(worklet_type) {
+  const worklet = get_worklet(worklet_type);
+
+  promise_test(() => {
+      const kWindowURL = "resources/referrer-window.html" +
+                         "?pipe=header(Referrer-Policy,no-referrer)";
+      return openWindow(kWindowURL).then(win => {
+          const promise = new Promise(resolve => window.onmessage = resolve);
+          win.postMessage({ type: worklet_type,
+                            referrer_policy: 'no-referrer',
+                            is_cross_origin: false }, '*');
+          return promise;
+      }).then(msg_event => assert_equals(msg_event.data, 'RESOLVED'));
+  }, 'Importing a same-origin script from a page that has "no-referrer" ' +
+     'referrer policy should not send referrer.');
+
+  promise_test(() => {
+      const kWindowURL = "resources/referrer-window.html" +
+                         "?pipe=header(Referrer-Policy,no-referrer)";
+      return openWindow(kWindowURL).then(win => {
+          const promise = new Promise(resolve => window.onmessage = resolve);
+          win.postMessage({ type: worklet_type,
+                            referrer_policy: 'no-referrer',
+                            is_cross_origin: true }, '*');
+          return promise;
+      }).then(msg_event => assert_equals(msg_event.data, 'RESOLVED'));
+  }, 'Importing a remote-origin script from a page that has "no-referrer" ' +
+     'referrer policy should not send referrer.');
+
+  promise_test(() => {
+      const kWindowURL = 'resources/referrer-window.html' +
+                         '?pipe=header(Referrer-Policy,origin)';
+      return openWindow(kWindowURL).then(win => {
+          const promise = new Promise(resolve => window.onmessage = resolve);
+          win.postMessage({ type: worklet_type,
+                            referrer_policy: 'origin',
+                            is_cross_origin: false }, '*');
+          return promise;
+      }).then(msg_event => assert_equals(msg_event.data, 'RESOLVED'));
+  }, 'Importing a same-origin script from a page that has "origin" ' +
+     'referrer policy should send only an origin as referrer.');
+
+  promise_test(() => {
+      const kWindowURL = 'resources/referrer-window.html' +
+                         '?pipe=header(Referrer-Policy,origin)';
+      return openWindow(kWindowURL).then(win => {
+          const promise = new Promise(resolve => window.onmessage = resolve);
+          win.postMessage({ type: worklet_type,
+                            referrer_policy: 'origin',
+                            is_cross_origin: true }, '*');
+          return promise;
+      }).then(msg_event => assert_equals(msg_event.data, 'RESOLVED'));
+  }, 'Importing a remote-origin script from a page that has "origin" ' +
+     'referrer policy should send only an origin as referrer.');
+
+  promise_test(() => {
+      const kWindowURL = 'resources/referrer-window.html' +
+                         '?pipe=header(Referrer-Policy,same-origin)';
+      return openWindow(kWindowURL).then(win => {
+          const promise = new Promise(resolve => window.onmessage = resolve);
+          win.postMessage({ type: worklet_type,
+                            referrer_policy: 'same-origin',
+                            is_cross_origin: false }, '*');
+          return promise;
+      }).then(msg_event => assert_equals(msg_event.data, 'RESOLVED'));
+  }, 'Importing a same-origin script from a page that has "same-origin" ' +
+     'referrer policy should send referrer.');
+
+  promise_test(() => {
+      const kWindowURL = 'resources/referrer-window.html' +
+                         '?pipe=header(Referrer-Policy,same-origin)';
+      return openWindow(kWindowURL).then(win => {
+          const promise = new Promise(resolve => window.onmessage = resolve);
+          win.postMessage({ type: worklet_type,
+                            referrer_policy: 'same-origin',
+                            is_cross_origin: true }, '*');
+          return promise;
+      }).then(msg_event => assert_equals(msg_event.data, 'RESOLVED'));
+  }, 'Importing a remote-origin script from a page that has "same-origin" ' +
+     'referrer policy should not send referrer.');
+}
diff --git a/third_party/WebKit/LayoutTests/external/wpt/worklets/resources/referrer-window.html b/third_party/WebKit/LayoutTests/external/wpt/worklets/resources/referrer-window.html
new file mode 100644
index 0000000..406b025
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/worklets/resources/referrer-window.html
@@ -0,0 +1,35 @@
+<!DOCTYPE html>
+<html>
+<head>
+  <title>Worklet: Referrer</title>
+  <script src="/common/get-host-info.sub.js"></script>
+  <script src="/resources/testharness.js"></script>
+  <script src="/resources/testharnessreport.js"></script>
+  <script src="worklet-test-utils.js"></script>
+</head>
+<body>
+<script>
+window.onmessage = e => {
+  const worklet_type = e.data.type;
+  const is_cross_origin = e.data.is_cross_origin;
+
+  const params = new URLSearchParams;
+  params.append('referrer_policy', e.data.referrer_policy)
+  params.append('source_origin', get_host_info().HTTP_ORIGIN);
+
+  let script_url = '';
+  if (is_cross_origin) {
+    params.append('is_cross_origin', 'true')
+    script_url = get_host_info().HTTP_REMOTE_ORIGIN + '/worklets/resources/';
+  }
+  script_url += 'referrer.py?' + params;
+
+  get_worklet(worklet_type).addModule(script_url)
+      .then(() => window.opener.postMessage('RESOLVED', '*'))
+      .catch(e => window.opener.postMessage(e.message, '*'));
+};
+
+window.opener.postMessage('LOADED', '*');
+</script>
+</body>
+</html>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/worklets/resources/referrer.py b/third_party/WebKit/LayoutTests/external/wpt/worklets/resources/referrer.py
new file mode 100644
index 0000000..62dd4a1
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/worklets/resources/referrer.py
@@ -0,0 +1,30 @@
+# Returns a valid response when request's |referrer| matches |referrer_policy|.
+def main(request, response):
+    referrer = request.headers.get("referer", None)
+    referrer_policy = request.GET.first("referrer_policy")
+    source_origin = request.GET.first("source_origin")
+    is_cross_origin = request.GET.first("is_cross_origin", False)
+
+    response_headers = [("Content-Type", "text/javascript"),
+                        ("Access-Control-Allow-Origin", source_origin)];
+
+    # When the referrer policy is "no-referrer", the referrer header shouldn't
+    # be sent.
+    if referrer_policy == "no-referrer" and not referrer:
+        return (200, response_headers, "")
+
+    # When the referrer policy is "origin", the referrer header should contain
+    # only the origin. Note that |referrer| contains a trailing slash, while
+    # |source_origin| doesn't.
+    if referrer_policy == "origin" and referrer == source_origin + "/":
+        return (200, response_headers, "")
+
+    # When the referrer policy is "same-origin", the referrer header should be
+    # sent only for a same-origin request.
+    if referrer_policy == "same-origin":
+        if is_cross_origin and not referrer:
+            return (200, response_headers, "")
+        if not is_cross_origin and referrer:
+            return (200, response_headers, "")
+
+    return (404)
diff --git a/third_party/WebKit/LayoutTests/external/wpt/worklets/resources/worklet-test-utils.js b/third_party/WebKit/LayoutTests/external/wpt/worklets/resources/worklet-test-utils.js
new file mode 100644
index 0000000..4912dadb
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/worklets/resources/worklet-test-utils.js
@@ -0,0 +1,8 @@
+// Returns a reference to a worklet object corresponding to a given type.
+function get_worklet(type) {
+  if (type == 'paint')
+    return CSS.paintWorklet;
+  if (type == 'animation')
+    return window.animationWorklet;
+  return undefined;
+}
diff --git a/third_party/WebKit/LayoutTests/fast/canvas-api/canvas-textMetrics-all.html b/third_party/WebKit/LayoutTests/fast/canvas-api/canvas-textMetrics-all.html
new file mode 100644
index 0000000..b075e87b
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/fast/canvas-api/canvas-textMetrics-all.html
@@ -0,0 +1,90 @@
+<!DOCTYPE HTML>
+<head>
+<style>
+@font-face {
+  font-family: Libertine;
+  src: url('../../third_party/Libertine/LinLibertine_R.woff');
+}
+</style>
+</head>
+<script src="../../resources/testharness.js"></script>
+<script src="../../resources/testharnessreport.js"></script>
+<script>
+function testTextMetrics(textMetrics, expected)
+{
+    var w  = textMetrics.width;
+    var ab = textMetrics.alphabeticBaseline;
+    var hb = textMetrics.hangingBaseline;
+    var ib = textMetrics.ideographicBaseline;
+    var fa = textMetrics.fontBoundingBoxAscent;
+    var fd = textMetrics.fontBoundingBoxDescent;
+    var ea = textMetrics.emHeightAscent;
+    var ed = textMetrics.emHeightDescent;
+    var lb = textMetrics.actualBoundingBoxLeft;
+    var rb = textMetrics.actualBoundingBoxRight;
+    var aa = textMetrics.actualBoundingBoxAscent;
+    var ad = textMetrics.actualBoundingBoxDescent;
+
+    var epsilon = 2;
+    assert_approx_equals(w,  expected[0], epsilon, "testing width");
+    assert_approx_equals(ab, expected[1], epsilon, "testing alphabeticBaseline");
+    assert_approx_equals(hb, expected[2], epsilon, "testing hangingBaseline");
+    assert_approx_equals(ib, expected[3], epsilon, "testing ideographicBaseline");
+    assert_approx_equals(fa, expected[4], epsilon, "testing fontBoundingBoxAscent");
+    assert_approx_equals(fd, expected[5], epsilon, "testing fontBoundingBoxDescent");
+    assert_approx_equals(ea, expected[6], epsilon, "testing emHeightAscent");
+    assert_approx_equals(ed, expected[7], epsilon, "testing emHeightDescent");
+    assert_approx_equals(lb, expected[8], epsilon, "testing actualBoundingBoxLeft");
+    assert_approx_equals(rb, expected[9], epsilon, "testing actualBoundingBoxRight");
+    assert_approx_equals(aa, expected[10], epsilon, "testing actualBoundingBoxAscent");
+    assert_approx_equals(ad, expected[11], epsilon, "testing actualBoundingBoxDescent");
+}
+
+function measureMetrics(ctx)
+{
+    var text = "Hello World";
+
+    ctx.textBaseline = "top";
+    var textMetrics = ctx.measureText(text);
+    var expected = [249, -44, -8.8, -57, 0, 57, 13, 44, -0, 249, -9, 46];
+    testTextMetrics(textMetrics, expected);
+
+    ctx.textBaseline = "hanging";
+    var textMetrics = ctx.measureText(text);
+    expected = [249, -35, 0.2, -48, 9, 48, 22, 35, -0, 249, 0, 37];
+    testTextMetrics(textMetrics, expected);
+
+    ctx.textBaseline = "middle";
+    var textMetrics = ctx.measureText(text);
+    expected = [249, -15, 20.2, -28, 29, 28, 42, 15, -0, 249, 20, 17];
+    testTextMetrics(textMetrics, expected);
+
+    ctx.textBaseline = "alphabetic";
+    var textMetrics = ctx.measureText(text);
+    expected = [249, -0, 35.2, -13, 44, 13, 57, 0, -0, 249, 35, 2];
+    testTextMetrics(textMetrics, expected);
+
+    ctx.textBaseline = "ideographic";
+    var textMetrics = ctx.measureText(text);
+    expected = [249, 13, 48.2, 0, 57, 0, 70, -13, -0, 249, 48, -11];
+    testTextMetrics(textMetrics, expected);
+
+    ctx.textBaseline = "bottom";
+    var textMetrics = ctx.measureText(text);
+    expected = [249, 13, 48.2, 0, 57, 0, 70, -13, -0, 249, 48, -11];
+    testTextMetrics(textMetrics, expected);
+}
+
+async_test(t => {
+    var canvas = document.createElement('canvas');
+    canvas.width = 100;
+    canvas.height = 100;
+    var ctx = canvas.getContext('2d');
+    ctx.font = '50px Libertine';
+    // Kick off loading of the font
+    ctx.fillText(" ", 0, 0);
+    document.fonts.addEventListener('loadingdone', t.step_func_done(function() {
+        measureMetrics(ctx);
+    }));
+}, "Test all attributes of TextMetrics.");
+</script>
diff --git a/third_party/WebKit/LayoutTests/fast/canvas-api/textMetrics.html b/third_party/WebKit/LayoutTests/fast/canvas-api/textMetrics.html
new file mode 100644
index 0000000..75b538ec
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/fast/canvas-api/textMetrics.html
@@ -0,0 +1,180 @@
+<!DOCTYPE HTML>
+<head>
+<meta charset="UTF-8">
+<style>
+@font-face {
+  font-family: Libertine;
+  src: url('../../third_party/Libertine/LinLibertine_R.woff');
+}
+</style>
+</head>
+<script src="../../resources/testharness.js"></script>
+<script src="../../resources/testharnessreport.js"></script>
+<script>
+
+function getMetric(ctx, text, baseline, align, rtl, metric) {
+  ctx.font = '50px Libertine';
+  ctx.textBaseline = baseline;
+  ctx.textAlign = align;
+  ctx.direction = rtl ? "rtl": "ltr";
+
+  const tm = ctx.measureText(text);
+  tm.actualBoundingBoxWidth = Math.abs(tm.actualBoundingBoxRight + tm.actualBoundingBoxLeft);
+  tm.actualBoundingBoxHeight = Math.abs(tm.actualBoundingBoxDescent + tm.actualBoundingBoxAscent);
+
+  return tm[metric];
+}
+
+function testMetric(name, ctx, text, baseline, align, rtl, metric, expected_value, epsilon = 0) {
+  const value = getMetric(ctx, text, baseline, align, rtl, metric);
+  assert_approx_equals(value, expected_value, epsilon ? Math.ceil(epsilon * expected_value) : 1.0,
+    name + ": " + metric + " for '" + text +
+    "' (" + baseline + ", " + align + ")");
+  return value;
+}
+
+const kAligns = [ "left", "right", "center", "start", "end" ];
+const kBaselines =  ['top','hanging','middle','alphabetic',
+                     'ideographic','bottom'];
+
+// Those bbox are given from alphabetic,left.
+// bbox = [ left, right, ascent, descent ].
+const kTexts = [
+  { text: "", bbox: [0, 0, 0, 0], rtl: false },
+  { text: "hello", bbox: [0, 101, 35, 1], rtl: false },
+  { text: "gypsy", bbox: [0, 122, 24, 12], rtl: false },
+  { text: "傳統是假的", bbox: [0, 250, 42, 7], rtl: false },
+  { text: "フェミニズム", bbox: [0, 300, 42, 3], rtl: false },
+  { text: "एक आम भाषा", bbox: [0, 240, 34, 5], rtl: false },
+  { text: "ليس في اسمنا", bbox: [0, 221, 41, 12], rtl: true },
+]
+
+function forEachExample(fn) {
+  for (const ex of kTexts) {
+    for (const bline of kBaselines) {
+      for (const align of kAligns) {
+        fn(ex, bline, align);
+      }
+    }
+  }
+}
+
+// Widths shouldn't change over baseline/align.
+function testWidth(ctx) {
+  forEachExample((ex, bline, align) => {
+    testMetric("width", ctx, ex.text, bline, align, ex.rtl, "width", ex.bbox[1] + ex.bbox[0]);
+  });
+}
+
+// Reality check that the bounding box we are using for input
+// match the returned values with a big confidence interval.
+// If it does, we adapt to the actual values to accomodate for different OSes.
+function testAndFixBasicExpectations(ctx) {
+  const max_diff = 0.75;
+  for (const ex of kTexts) {
+    ex.bbox[0] = testMetric("expectations", ctx, ex.text, "alphabetic", "left", ex.rtl, "actualBoundingBoxLeft", ex.bbox[0], max_diff);
+    ex.bbox[1] = testMetric("expectations", ctx, ex.text, "alphabetic", "left", ex.rtl, "actualBoundingBoxRight", ex.bbox[1], max_diff);
+    ex.bbox[2] = testMetric("expectations", ctx, ex.text, "alphabetic", "left", ex.rtl, "actualBoundingBoxAscent", ex.bbox[2], max_diff);
+    ex.bbox[3] = testMetric("expectations", ctx, ex.text, "alphabetic", "left", ex.rtl, "actualBoundingBoxDescent", ex.bbox[3], max_diff);
+  }
+}
+
+
+function testBaselines(ctx) {
+  // on their own baseline, metrics should be 0.
+  for (const ex of kTexts) {
+    for (const bline of ["alphabetic", "ideographic", "hanging"]) {
+      for (const align of kAligns) {
+        testMetric("own baselines", ctx, ex.text, bline, align, ex.rtl, bline + "Baseline", 0);
+      }
+    }
+  }
+
+  // Those 3 baselines are font size dependent, so everything should be fixed.
+  forEachExample((ex, _, align) => {
+    testMetric("top baseline", ctx, ex.text, "top", align, ex.rtl, "alphabeticBaseline", -44);
+  });
+
+  forEachExample((ex, _, align) => {
+    testMetric("middle baseline", ctx, ex.text, "middle", align, ex.rtl, "alphabeticBaseline", -15);
+  });
+
+  forEachExample((ex, _, align) => {
+    testMetric("bottom baseline", ctx, ex.text, "bottom", align, ex.rtl, "alphabeticBaseline", 13);
+  });
+}
+
+function testBoundingBox(ctx) {
+  // Width/Height should remain the same across baseline/align.
+  forEachExample((ex, bline, align) => {
+    testMetric("boundingbox", ctx, ex.text, bline, align, ex.rtl, "actualBoundingBoxWidth",
+      ex.bbox[1] + ex.bbox[0]);
+    testMetric("boundingbox", ctx, ex.text, bline, align, ex.rtl, "actualBoundingBoxHeight",
+      ex.bbox[2] + ex.bbox[3]);
+  });
+
+  // Left changes depending on what is the alignment.
+  forEachExample((ex, bline, align) => {
+    let left = 0;
+    let calign = align;
+    if (align == "start") calign = ex.rtl ? "right" : "left";
+    if (align == "end") calign = ex.rtl ? "left" : "right";
+
+    if (calign == "left") left = 0;
+    else if (calign == "right") left = ex.bbox[1] + ex.bbox[0];
+    else if (calign == "center") left = (ex.bbox[1] + ex.bbox[0])/2.0;
+
+    testMetric("boundigbox alignment", ctx, ex.text, bline, align, ex.rtl, "actualBoundingBoxLeft", left);
+  });
+
+  // Right changes depending on what is the alignment.
+  forEachExample((ex, bline, align) => {
+    let right = 0;
+    let calign = align;
+    if (align == "start") calign = ex.rtl ? "right" : "left";
+    if (align == "end") calign = ex.rtl ? "left" : "right";
+
+    if (calign == "left") right = ex.bbox[1] + ex.bbox[0];
+    else if (calign == "right") right = 0;
+    else if (calign == "center") right = (ex.bbox[1] + ex.bbox[0])/2.0;
+
+    testMetric("boundingbox alignment", ctx, ex.text, bline, align, ex.rtl, "actualBoundingBoxRight", right);
+  });
+}
+
+// fontAscent/Descent always includes actual.
+function testFontAscentDescent(ctx) {
+  forEachExample((ex, bline, align) => {
+    const font_asc = getMetric(ctx, ex.text, bline, align, ex.rtl, "fontBoundingBoxAscent");
+    const font_des = getMetric(ctx, ex.text, bline, align, ex.rtl, "fontBoundingBoxAscent");
+    const actual_asc = getMetric(ctx, ex.text, bline, align, ex.rtl, "actualBoundingBoxAscent");
+    const actual_des = getMetric(ctx, ex.text, bline, align, ex.rtl, "actualBoundingBoxAscent");
+
+    assert_greater_than(font_asc, actual_asc, "font_asc > actual_asc for '" + ex.text + "'");
+    assert_greater_than(font_des + font_asc, actual_asc + actual_des, "font_end > actal_end '" + ex.text + "'");
+  });
+}
+
+function measureMetrics(ctx) {
+  testAndFixBasicExpectations(ctx);
+  testWidth(ctx);
+  testBaselines(ctx);
+  testBoundingBox(ctx);
+  testFontAscentDescent(ctx);
+  // TODO(fserb): missing hanging/ideographic baseline tests.
+  // TODO(fserb): missing emHeight tests.
+}
+
+async_test(t => {
+    var canvas = document.createElement('canvas');
+    canvas.width = 100;
+    canvas.height = 100;
+    var ctx = canvas.getContext('2d');
+    ctx.font = '50px Libertine';
+    // Kick off loading of the font
+    ctx.fillText(" ", 0, 0);
+    document.fonts.addEventListener('loadingdone', t.step_func_done(function() {
+        measureMetrics(ctx);
+    }));
+}, "Test all attributes of TextMetrics.");
+</script>
diff --git a/third_party/WebKit/LayoutTests/fast/canvas/canvas-textMetrics-all.html b/third_party/WebKit/LayoutTests/fast/canvas/canvas-textMetrics-all.html
deleted file mode 100644
index a7dcb41..0000000
--- a/third_party/WebKit/LayoutTests/fast/canvas/canvas-textMetrics-all.html
+++ /dev/null
@@ -1,90 +0,0 @@
-<!DOCTYPE HTML>
-<head>
-<style>
-@font-face {
-  font-family: Libertine;
-  src: url('../../third_party/Libertine/LinLibertine_R.woff');
-}
-</style>
-</head>
-<script src="../../resources/testharness.js"></script>
-<script src="../../resources/testharnessreport.js"></script>
-<script>
-function testTextMetrics(textMetrics, expected)
-{
-    var w  = textMetrics.width;
-    var ab = textMetrics.alphabeticBaseline;
-    var hb = textMetrics.hangingBaseline;
-    var ib = textMetrics.ideographicBaseline;
-    var fa = textMetrics.fontBoundingBoxAscent;
-    var fd = textMetrics.fontBoundingBoxDescent;
-    var ea = textMetrics.emHeightAscent;
-    var ed = textMetrics.emHeightDescent;
-    var lb = textMetrics.actualBoundingBoxLeft;
-    var rb = textMetrics.actualBoundingBoxRight;
-    var aa = textMetrics.actualBoundingBoxAscent;
-    var ad = textMetrics.actualBoundingBoxDescent;
-
-    var epsilon = 1.0;
-    assert_approx_equals(w,  expected[0], epsilon, "testing width");
-    assert_approx_equals(ab, expected[1], epsilon, "testing alphabeticBaseline");
-    assert_approx_equals(hb, expected[2], epsilon, "testing hangingBaseline");
-    assert_approx_equals(ib, expected[3], epsilon, "testing ideographicBaseline");
-    assert_approx_equals(fa, expected[4], epsilon, "testing fontBoundingBoxAscent");
-    assert_approx_equals(fd, expected[5], epsilon, "testing fontBoundingBoxDescent");
-    assert_approx_equals(ea, expected[6], epsilon, "testing emHeightAscent");
-    assert_approx_equals(ed, expected[7], epsilon, "testing emHeightDescent");
-    assert_approx_equals(lb, expected[8], epsilon, "testing actualBoundingBoxLeft");
-    assert_approx_equals(rb, expected[9], epsilon, "testing actualBoundingBoxRight");
-    assert_approx_equals(aa, expected[10], epsilon, "testing actualBoundingBoxAscent");
-    assert_approx_equals(ad, expected[11], epsilon, "testing actualBoundingBoxDescent");
-}
-
-function measureMetrics(ctx)
-{
-    var text = "Hello World";
-
-    ctx.textBaseline = "top";
-    var textMetrics = ctx.measureText(text);
-    var expected = [248.5, -44, -8.8, -57, 0, 57, 13, 44, -0, 249, 0, 57];
-    testTextMetrics(textMetrics, expected);
-
-    ctx.textBaseline = "hanging";
-    var textMetrics = ctx.measureText(text);
-    expected = [248.5, -35, 0.2, -48, 9, 48, 22, 35, -0, 249, 9, 48];
-    testTextMetrics(textMetrics, expected);
-
-    ctx.textBaseline = "middle";
-    var textMetrics = ctx.measureText(text);
-    expected = [248.5, -15, 20.2, -28, 29, 28, 42, 15, -0, 249, 29, 28];
-    testTextMetrics(textMetrics, expected);
-
-    ctx.textBaseline = "alphabetic";
-    var textMetrics = ctx.measureText(text);
-    expected = [248.5, -0, 35.2, -13, 44, 13, 57, 0, -0, 249, 44, 13];
-    testTextMetrics(textMetrics, expected);
-
-    ctx.textBaseline = "ideographic";
-    var textMetrics = ctx.measureText(text);
-    expected = [248.5, 13, 48.2, 0, 57, 0, 70, -13, -0, 249, 57, 0];
-    testTextMetrics(textMetrics, expected);
-
-    ctx.textBaseline = "bottom";
-    var textMetrics = ctx.measureText(text);
-    expected = [248.5, 13, 48.2, 0, 57, 0, 70, -13, -0, 249, 57, 0];
-    testTextMetrics(textMetrics, expected);
-}
-
-async_test(t => {
-    var canvas = document.createElement('canvas');
-    canvas.width = 100;
-    canvas.height = 100;
-    var ctx = canvas.getContext('2d');
-    ctx.font = '50px Libertine';
-    // Kick off loading of the font
-    ctx.fillText(" ", 0, 0);
-    document.fonts.addEventListener('loadingdone', t.step_func_done(function() {
-        measureMetrics(ctx);
-    }));
-}, "Test all attributes of TextMetrics.");
-</script>
diff --git a/third_party/WebKit/LayoutTests/fast/dom/Window/window-open-subresource-loading.html b/third_party/WebKit/LayoutTests/fast/dom/Window/window-open-subresource-loading.html
new file mode 100644
index 0000000..9ec02c9
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/fast/dom/Window/window-open-subresource-loading.html
@@ -0,0 +1,32 @@
+<!doctype html>
+<title>window.open: subresource loading</title>
+<script src="../../../resources/testharness.js"></script>
+<script src="../../../resources/testharnessreport.js"></script>
+<script>
+promise_test(() => {
+  const readAndReportBlobContents = () => {
+    const xhr = new XMLHttpRequest;
+    xhr.open('GET', self.blobUrl, true);
+    xhr.responseType = 'blob';
+    xhr.onload = e => {
+      const reader = new FileReader;
+      reader.onloadend = e => { self.reportBlobContents(reader.result); };
+      reader.readAsText(xhr.response);
+    };
+    xhr.send();
+  };
+
+  const kBlobText = 'hello i am blob';
+  const target = self.open();
+  const blob = new Blob([kBlobText], {type: 'text/plain'});
+  const blobUrl = URL.createObjectURL(blob);
+  return new Promise((resolve, reject) => {
+    target.blobUrl = blobUrl;
+    target.reportBlobContents = resolve;
+    target.document.write('<script>(' + readAndReportBlobContents + ')();</' +
+        'script>\n');
+  }).then(readBlobText => {
+    assert_equals(readBlobText, kBlobText);
+  });
+}, 'Check that new blank windows can load subresources.');
+</script>
diff --git a/third_party/WebKit/LayoutTests/fast/forms/suggested-value-after-empty-suggested-value-expected.txt b/third_party/WebKit/LayoutTests/fast/forms/suggested-value-after-empty-suggested-value-expected.txt
index 2f2b607..700de04 100644
--- a/third_party/WebKit/LayoutTests/fast/forms/suggested-value-after-empty-suggested-value-expected.txt
+++ b/third_party/WebKit/LayoutTests/fast/forms/suggested-value-after-empty-suggested-value-expected.txt
@@ -86,9 +86,9 @@
 |   <shadow:root>
 |     <div>
 |       id="placeholder"
-|       pseudo="-webkit-input-suggested"
-|       style="display: none !important;"
-|       shadow:pseudoId="-webkit-input-suggested"
+|       pseudo="-internal-input-suggested"
+|       style="display: block !important;"
+|       shadow:pseudoId="-internal-input-suggested"
 |       "suggested value"
 |     <div>
 | <br>
@@ -102,9 +102,9 @@
 |   <shadow:root>
 |     <div>
 |       id="placeholder"
-|       pseudo="-webkit-input-suggested"
+|       pseudo="-internal-input-suggested"
 |       style="display: block !important; text-overflow: clip;"
-|       shadow:pseudoId="-webkit-input-suggested"
+|       shadow:pseudoId="-internal-input-suggested"
 |       "suggested value"
 |     <div>
 | <br>
@@ -117,9 +117,9 @@
 |   <shadow:root>
 |     <div>
 |       id="placeholder"
-|       pseudo="-webkit-input-suggested"
+|       pseudo="-internal-input-suggested"
 |       style="display: none !important;"
-|       shadow:pseudoId="-webkit-input-suggested"
+|       shadow:pseudoId="-internal-input-suggested"
 |       "suggested value"
 |     <div>
 | <br>
@@ -132,9 +132,9 @@
 |   <shadow:root>
 |     <div>
 |       id="placeholder"
-|       pseudo="-webkit-input-suggested"
+|       pseudo="-internal-input-suggested"
 |       style="display: block !important;"
-|       shadow:pseudoId="-webkit-input-suggested"
+|       shadow:pseudoId="-internal-input-suggested"
 |       "suggested value"
 |     <div>
 | <br>
diff --git a/third_party/WebKit/LayoutTests/fast/forms/suggested-value-after-setvalue-expected.txt b/third_party/WebKit/LayoutTests/fast/forms/suggested-value-after-setvalue-expected.txt
index c1d8668..c42a487 100644
--- a/third_party/WebKit/LayoutTests/fast/forms/suggested-value-after-setvalue-expected.txt
+++ b/third_party/WebKit/LayoutTests/fast/forms/suggested-value-after-setvalue-expected.txt
@@ -9,9 +9,9 @@
 |   <shadow:root>
 |     <div>
 |       id="placeholder"
-|       pseudo="-webkit-input-suggested"
-|       style="display: none !important;"
-|       shadow:pseudoId="-webkit-input-suggested"
+|       pseudo="-internal-input-suggested"
+|       style="display: block !important;"
+|       shadow:pseudoId="-internal-input-suggested"
 |       "suggested value"
 |     <div>
 | "input.value: initial value"
diff --git a/third_party/WebKit/LayoutTests/fast/forms/suggested-value-expected.txt b/third_party/WebKit/LayoutTests/fast/forms/suggested-value-expected.txt
index cd3f7c81..bc8307a0 100644
--- a/third_party/WebKit/LayoutTests/fast/forms/suggested-value-expected.txt
+++ b/third_party/WebKit/LayoutTests/fast/forms/suggested-value-expected.txt
@@ -9,9 +9,9 @@
 |   <shadow:root>
 |     <div>
 |       id="placeholder"
-|       pseudo="-webkit-input-suggested"
-|       style="display: none !important;"
-|       shadow:pseudoId="-webkit-input-suggested"
+|       pseudo="-internal-input-suggested"
+|       style="display: block !important;"
+|       shadow:pseudoId="-internal-input-suggested"
 |       "suggested value"
 |     <div>
 | <input>
@@ -70,9 +70,9 @@
 |   <shadow:root>
 |     <div>
 |       id="placeholder"
-|       pseudo="-webkit-input-suggested"
+|       pseudo="-internal-input-suggested"
 |       style="display: none !important;"
-|       shadow:pseudoId="-webkit-input-suggested"
+|       shadow:pseudoId="-internal-input-suggested"
 |       "suggested value"
 |     <div>
 | <select>
diff --git a/third_party/WebKit/LayoutTests/fast/table/auto-fit-cell-page-zoom-expected.html b/third_party/WebKit/LayoutTests/fast/table/auto-fit-cell-page-zoom-expected.html
new file mode 100644
index 0000000..7e0bfe2b
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/fast/table/auto-fit-cell-page-zoom-expected.html
@@ -0,0 +1,12 @@
+<!DOCTYPE html>
+<script>
+if (window.eventSender)
+  eventSender.setPageZoomFactor(1.25);
+</script>
+<style>
+td { border: 1px solid white; width: 400px; }
+</style>
+The text should not wrap in any page zoom factor.
+<table>
+  <tr><td>Tennis- en squashcentrum Nieuwe Sloot</td></tr>
+</table>
diff --git a/third_party/WebKit/LayoutTests/fast/table/auto-fit-cell-page-zoom.html b/third_party/WebKit/LayoutTests/fast/table/auto-fit-cell-page-zoom.html
new file mode 100644
index 0000000..e3b8a49
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/fast/table/auto-fit-cell-page-zoom.html
@@ -0,0 +1,12 @@
+<!DOCTYPE html>
+<script>
+if (window.eventSender)
+  eventSender.setPageZoomFactor(1.25);
+</script>
+<style>
+td { border: 1px solid white; }
+</style>
+The text should not wrap in any page zoom factor.
+<table>
+  <tr><td>Tennis- en squashcentrum Nieuwe Sloot</td></tr>
+</table>
diff --git a/third_party/WebKit/LayoutTests/fast/workers/shared-worker-load-error.html b/third_party/WebKit/LayoutTests/fast/workers/shared-worker-load-error.html
index c69266a..13dfa461 100644
--- a/third_party/WebKit/LayoutTests/fast/workers/shared-worker-load-error.html
+++ b/third_party/WebKit/LayoutTests/fast/workers/shared-worker-load-error.html
@@ -1,3 +1,4 @@
+<script src="../../resources/gc.js"></script>
 <body>
 <p>Test SharedWorker onerror functionality. Prints multiple SUCCESS lines, then DONE when complete.</p>
 <div id=result></div>
@@ -29,17 +30,6 @@
     gc();
 }
 
-function gc()
-{
-    if (window.GCController)
-        return GCController.collect();
-
-    for (var i = 0; i < 10000; i++) { // force garbage collection (FF requires about 9K allocations before a collect)
-        var s = new String("abc");
-    }
-}
-
-
 function handleError(evt) {
     log("PASS: Received error event after worker GC'd: " + evt);
     log("DONE");
diff --git a/third_party/WebKit/LayoutTests/fast/workers/worker-messageport-gc.html b/third_party/WebKit/LayoutTests/fast/workers/worker-messageport-gc.html
index 35d0563..40b2617 100644
--- a/third_party/WebKit/LayoutTests/fast/workers/worker-messageport-gc.html
+++ b/third_party/WebKit/LayoutTests/fast/workers/worker-messageport-gc.html
@@ -1,3 +1,4 @@
+<script src="../../resources/gc.js"></script>
 <body>
 <p>Test that workers stay reachable via message ports.
 Should print "DONE" when done.</p>
@@ -35,16 +36,6 @@
     channel.port2.postMessage("ping");
 }
 
-function gc()
-{
-    if (window.GCController)
-        return GCController.collectAll();
-
-    for (var i = 0; i < 10000; i++) { // force garbage collection (FF requires about 9K allocations before a collect)
-        var s = new String("abc");
-    }
-}
-
 function done()
 {
     log("DONE");
diff --git a/third_party/WebKit/LayoutTests/fast/xpath/xpath-iterator-result-should-mark-its-nodeset.html b/third_party/WebKit/LayoutTests/fast/xpath/xpath-iterator-result-should-mark-its-nodeset.html
index 98c9f18b..922c91f 100644
--- a/third_party/WebKit/LayoutTests/fast/xpath/xpath-iterator-result-should-mark-its-nodeset.html
+++ b/third_party/WebKit/LayoutTests/fast/xpath/xpath-iterator-result-should-mark-its-nodeset.html
@@ -1,4 +1,5 @@
 <html><head>
+    <script src="../../resources/gc.js"></script>
     <script>
         if (window.testRunner)
             testRunner.dumpAsText();
@@ -8,16 +9,6 @@
                       XPathResult.UNORDERED_NODE_ITERATOR_TYPE
                     ];
 
-        function gc()
-        {
-            if (window.GCController)
-                return GCController.collect();
-
-            for (var i = 0; i < 10000; i++) { // > force garbage collection (FF requires about 9K allocations before a collect)
-                var s = new String("abc");
-            }
-        }
-
         function test(type)
         {
             var doc, result;
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v175/compositing/overflow/mask-with-filter-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v175/compositing/overflow/mask-with-filter-expected.png
new file mode 100644
index 0000000..316b194
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v175/compositing/overflow/mask-with-filter-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v175/compositing/overflow/mask-with-small-content-rect-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v175/compositing/overflow/mask-with-small-content-rect-expected.png
new file mode 100644
index 0000000..66fa0662
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v175/compositing/overflow/mask-with-small-content-rect-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v175/compositing/overflow/nested-border-radius-clipping-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v175/compositing/overflow/nested-border-radius-clipping-expected.png
new file mode 100644
index 0000000..f422893
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v175/compositing/overflow/nested-border-radius-clipping-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v175/compositing/overflow/scaled-mask-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v175/compositing/overflow/scaled-mask-expected.png
new file mode 100644
index 0000000..7fca626b
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v175/compositing/overflow/scaled-mask-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v175/compositing/reflections/nested-reflection-transformed-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v175/compositing/reflections/nested-reflection-transformed-expected.png
new file mode 100644
index 0000000..fe2d7d5
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v175/compositing/reflections/nested-reflection-transformed-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v175/compositing/reflections/nested-reflection-transformed2-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v175/compositing/reflections/nested-reflection-transformed2-expected.png
new file mode 100644
index 0000000..29ec3cd2
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v175/compositing/reflections/nested-reflection-transformed2-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v175/compositing/reflections/reflection-in-composited-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v175/compositing/reflections/reflection-in-composited-expected.png
new file mode 100644
index 0000000..f073f2f
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v175/compositing/reflections/reflection-in-composited-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v175/compositing/squashing/add-remove-squashed-layers-expected.txt b/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v175/compositing/squashing/add-remove-squashed-layers-expected.txt
new file mode 100644
index 0000000..ac17cb08
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v175/compositing/squashing/add-remove-squashed-layers-expected.txt
@@ -0,0 +1,304 @@
+Test that layers can be nicely added or removed from a squashed layer, without unnecessary repaints on any layer. Click anywhere to test interactively; keep clicking to proceed through the test.
+
+CASE 1, original layer tree with overlap1 and overlap2:
+{
+  "layers": [
+    {
+      "name": "LayoutView #document",
+      "bounds": [800, 600],
+      "contentsOpaque": true,
+      "backgroundColor": "#FFFFFF"
+    },
+    {
+      "name": "Squashing Containment Layer",
+      "drawsContent": false
+    },
+    {
+      "name": "LayoutBlockFlow (positioned) DIV class='composited'",
+      "bounds": [400, 400],
+      "contentsOpaque": true,
+      "backgroundColor": "#808080",
+      "transform": 1
+    },
+    {
+      "name": "Squashing Layer (first squashed layer: LayoutBlockFlow (positioned) DIV id='A' class='overlap1')",
+      "position": [140, 140],
+      "bounds": [180, 180]
+    }
+  ],
+  "transforms": [
+    {
+      "id": 1,
+      "transform": [
+        [1, 0, 0, 0],
+        [0, 1, 0, 0],
+        [0, 0, 1, 0],
+        [60, 60, 0, 1]
+      ],
+      "flattenInheritedTransform": false
+    }
+  ]
+}
+CASE 2, overlap3 gets added:
+{
+  "layers": [
+    {
+      "name": "LayoutView #document",
+      "bounds": [800, 600],
+      "contentsOpaque": true,
+      "backgroundColor": "#FFFFFF"
+    },
+    {
+      "name": "Squashing Containment Layer",
+      "drawsContent": false
+    },
+    {
+      "name": "LayoutBlockFlow (positioned) DIV class='composited'",
+      "bounds": [400, 400],
+      "contentsOpaque": true,
+      "backgroundColor": "#808080",
+      "transform": 1
+    },
+    {
+      "name": "Squashing Layer (first squashed layer: LayoutBlockFlow (positioned) DIV id='A' class='overlap1')",
+      "position": [140, 140],
+      "bounds": [260, 260],
+      "paintInvalidations": [
+        {
+          "object": "LayoutBlockFlow (positioned) DIV id='C' class='overlap3'",
+          "rect": [160, 160, 100, 100],
+          "reason": "appeared"
+        }
+      ]
+    }
+  ],
+  "transforms": [
+    {
+      "id": 1,
+      "transform": [
+        [1, 0, 0, 0],
+        [0, 1, 0, 0],
+        [0, 0, 1, 0],
+        [60, 60, 0, 1]
+      ],
+      "flattenInheritedTransform": false
+    }
+  ],
+  "objectPaintInvalidations": [
+    {
+      "object": "LayoutBlockFlow (positioned) DIV id='C' class='overlap3'",
+      "reason": "appeared"
+    }
+  ]
+}
+CASE 3, overlap2 gets removed. Since this does not resize the layer, there should only be a repaint of overlap2:
+{
+  "layers": [
+    {
+      "name": "LayoutView #document",
+      "bounds": [800, 600],
+      "contentsOpaque": true,
+      "backgroundColor": "#FFFFFF"
+    },
+    {
+      "name": "Squashing Containment Layer",
+      "drawsContent": false
+    },
+    {
+      "name": "LayoutBlockFlow (positioned) DIV class='composited'",
+      "bounds": [400, 400],
+      "contentsOpaque": true,
+      "backgroundColor": "#808080",
+      "transform": 1
+    },
+    {
+      "name": "Squashing Layer (first squashed layer: LayoutBlockFlow (positioned) DIV id='A' class='overlap1')",
+      "position": [140, 140],
+      "bounds": [260, 260],
+      "paintInvalidations": [
+        {
+          "object": "LayoutBlockFlow (positioned) DIV id='B' class='overlap2'",
+          "rect": [80, 80, 100, 100],
+          "reason": "disappeared"
+        }
+      ]
+    }
+  ],
+  "transforms": [
+    {
+      "id": 1,
+      "transform": [
+        [1, 0, 0, 0],
+        [0, 1, 0, 0],
+        [0, 0, 1, 0],
+        [60, 60, 0, 1]
+      ],
+      "flattenInheritedTransform": false
+    }
+  ]
+}
+CASE 4, overlap1 gets removed:
+{
+  "layers": [
+    {
+      "name": "LayoutView #document",
+      "bounds": [800, 600],
+      "contentsOpaque": true,
+      "backgroundColor": "#FFFFFF"
+    },
+    {
+      "name": "Squashing Containment Layer",
+      "drawsContent": false
+    },
+    {
+      "name": "LayoutBlockFlow (positioned) DIV class='composited'",
+      "bounds": [400, 400],
+      "contentsOpaque": true,
+      "backgroundColor": "#808080",
+      "transform": 1
+    },
+    {
+      "name": "Squashing Layer (first squashed layer: LayoutBlockFlow (positioned) DIV id='C' class='overlap3')",
+      "position": [300, 300],
+      "bounds": [100, 100],
+      "paintInvalidations": [
+        {
+          "object": "Squashing Layer (first squashed layer: LayoutBlockFlow (positioned) DIV id='C' class='overlap3')",
+          "rect": [0, 0, 100, 100],
+          "reason": "full layer"
+        }
+      ]
+    }
+  ],
+  "transforms": [
+    {
+      "id": 1,
+      "transform": [
+        [1, 0, 0, 0],
+        [0, 1, 0, 0],
+        [0, 0, 1, 0],
+        [60, 60, 0, 1]
+      ],
+      "flattenInheritedTransform": false
+    }
+  ],
+  "objectPaintInvalidations": [
+    {
+      "object": "LayoutBlockFlow (positioned) DIV id='C' class='overlap3'",
+      "reason": "compositing update"
+    }
+  ]
+}
+CASE 5, overlap2 gets added back:
+{
+  "layers": [
+    {
+      "name": "LayoutView #document",
+      "bounds": [800, 600],
+      "contentsOpaque": true,
+      "backgroundColor": "#FFFFFF"
+    },
+    {
+      "name": "Squashing Containment Layer",
+      "drawsContent": false
+    },
+    {
+      "name": "LayoutBlockFlow (positioned) DIV class='composited'",
+      "bounds": [400, 400],
+      "contentsOpaque": true,
+      "backgroundColor": "#808080",
+      "transform": 1
+    },
+    {
+      "name": "Squashing Layer (first squashed layer: LayoutBlockFlow (positioned) DIV id='B' class='overlap2')",
+      "position": [220, 220],
+      "bounds": [180, 180],
+      "paintInvalidations": [
+        {
+          "object": "Squashing Layer (first squashed layer: LayoutBlockFlow (positioned) DIV id='B' class='overlap2')",
+          "rect": [0, 0, 180, 180],
+          "reason": "full layer"
+        }
+      ]
+    }
+  ],
+  "transforms": [
+    {
+      "id": 1,
+      "transform": [
+        [1, 0, 0, 0],
+        [0, 1, 0, 0],
+        [0, 0, 1, 0],
+        [60, 60, 0, 1]
+      ],
+      "flattenInheritedTransform": false
+    }
+  ],
+  "objectPaintInvalidations": [
+    {
+      "object": "LayoutBlockFlow (positioned) DIV id='B' class='overlap2'",
+      "reason": "appeared"
+    },
+    {
+      "object": "LayoutBlockFlow (positioned) DIV id='C' class='overlap3'",
+      "reason": "compositing update"
+    }
+  ]
+}
+CASE 6, overlap1 gets added back, and overlap3 gets removed:
+{
+  "layers": [
+    {
+      "name": "LayoutView #document",
+      "bounds": [800, 600],
+      "contentsOpaque": true,
+      "backgroundColor": "#FFFFFF"
+    },
+    {
+      "name": "Squashing Containment Layer",
+      "drawsContent": false
+    },
+    {
+      "name": "LayoutBlockFlow (positioned) DIV class='composited'",
+      "bounds": [400, 400],
+      "contentsOpaque": true,
+      "backgroundColor": "#808080",
+      "transform": 1
+    },
+    {
+      "name": "Squashing Layer (first squashed layer: LayoutBlockFlow (positioned) DIV id='A' class='overlap1')",
+      "position": [140, 140],
+      "bounds": [180, 180],
+      "paintInvalidations": [
+        {
+          "object": "Squashing Layer (first squashed layer: LayoutBlockFlow (positioned) DIV id='A' class='overlap1')",
+          "rect": [0, 0, 180, 180],
+          "reason": "full layer"
+        }
+      ]
+    }
+  ],
+  "transforms": [
+    {
+      "id": 1,
+      "transform": [
+        [1, 0, 0, 0],
+        [0, 1, 0, 0],
+        [0, 0, 1, 0],
+        [60, 60, 0, 1]
+      ],
+      "flattenInheritedTransform": false
+    }
+  ],
+  "objectPaintInvalidations": [
+    {
+      "object": "LayoutBlockFlow (positioned) DIV id='A' class='overlap1'",
+      "reason": "appeared"
+    },
+    {
+      "object": "LayoutBlockFlow (positioned) DIV id='B' class='overlap2'",
+      "reason": "compositing update"
+    }
+  ]
+}
+
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v175/compositing/squashing/selection-repaint-with-gaps-expected.txt b/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v175/compositing/squashing/selection-repaint-with-gaps-expected.txt
new file mode 100644
index 0000000..cab8077
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v175/compositing/squashing/selection-repaint-with-gaps-expected.txt
@@ -0,0 +1,149 @@
+{
+  "layers": [
+    {
+      "name": "LayoutView #document",
+      "bounds": [800, 600],
+      "contentsOpaque": true,
+      "backgroundColor": "#FFFFFF"
+    },
+    {
+      "name": "Squashing Containment Layer",
+      "drawsContent": false
+    },
+    {
+      "name": "LayoutBlockFlow DIV class='overlap'",
+      "bounds": [300, 500],
+      "drawsContent": false,
+      "transform": 1
+    },
+    {
+      "name": "Squashing Layer (first squashed layer: LayoutBlockFlow (positioned) DIV class='item')",
+      "position": [15, 35],
+      "bounds": [100, 210],
+      "paintInvalidations": [
+        {
+          "object": "InlineTextBox 'ipsum'",
+          "rect": [0, 80, 40, 39],
+          "reason": "geometry"
+        },
+        {
+          "object": "InlineTextBox 'lorem'",
+          "rect": [0, 80, 40, 39],
+          "reason": "geometry"
+        }
+      ]
+    }
+  ],
+  "transforms": [
+    {
+      "id": 1,
+      "transform": [
+        [1, 0, 0, 0],
+        [0, 1, 0, 0],
+        [0, 0, 1, 0],
+        [8, 8, 0, 1]
+      ],
+      "flattenInheritedTransform": false
+    }
+  ],
+  "objectPaintInvalidations": [
+    {
+      "object": "LayoutText #text",
+      "reason": "geometry"
+    },
+    {
+      "object": "InlineTextBox 'lorem'",
+      "reason": "geometry"
+    },
+    {
+      "object": "InlineTextBox 'ipsum'",
+      "reason": "geometry"
+    }
+  ]
+}
+{
+  "layers": [
+    {
+      "name": "LayoutView #document",
+      "bounds": [800, 600],
+      "contentsOpaque": true,
+      "backgroundColor": "#FFFFFF"
+    },
+    {
+      "name": "Squashing Containment Layer",
+      "drawsContent": false
+    },
+    {
+      "name": "LayoutBlockFlow DIV class='overlap'",
+      "bounds": [300, 500],
+      "drawsContent": false,
+      "transform": 1
+    },
+    {
+      "name": "Squashing Layer (first squashed layer: LayoutBlockFlow (positioned) DIV class='item')",
+      "position": [15, 35],
+      "bounds": [100, 210],
+      "paintInvalidations": [
+        {
+          "object": "InlineTextBox 'ipsum'",
+          "rect": [0, 80, 42, 39],
+          "reason": "geometry"
+        },
+        {
+          "object": "InlineTextBox 'lorem'",
+          "rect": [0, 80, 42, 39],
+          "reason": "geometry"
+        },
+        {
+          "object": "InlineTextBox 'ipsum'",
+          "rect": [0, 160, 40, 39],
+          "reason": "geometry"
+        },
+        {
+          "object": "InlineTextBox 'lorem'",
+          "rect": [0, 160, 40, 39],
+          "reason": "geometry"
+        }
+      ]
+    }
+  ],
+  "transforms": [
+    {
+      "id": 1,
+      "transform": [
+        [1, 0, 0, 0],
+        [0, 1, 0, 0],
+        [0, 0, 1, 0],
+        [8, 8, 0, 1]
+      ],
+      "flattenInheritedTransform": false
+    }
+  ],
+  "objectPaintInvalidations": [
+    {
+      "object": "LayoutText #text",
+      "reason": "geometry"
+    },
+    {
+      "object": "InlineTextBox 'lorem'",
+      "reason": "geometry"
+    },
+    {
+      "object": "InlineTextBox 'ipsum'",
+      "reason": "geometry"
+    },
+    {
+      "object": "LayoutText #text",
+      "reason": "geometry"
+    },
+    {
+      "object": "InlineTextBox 'lorem'",
+      "reason": "geometry"
+    },
+    {
+      "object": "InlineTextBox 'ipsum'",
+      "reason": "geometry"
+    }
+  ]
+}
+
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v175/compositing/squashing/squash-above-fixed-1-expected.txt b/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v175/compositing/squashing/squash-above-fixed-1-expected.txt
new file mode 100644
index 0000000..fa657ba
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v175/compositing/squashing/squash-above-fixed-1-expected.txt
@@ -0,0 +1,309 @@
+The gray div is a composited fixed-position element, and the cyan/lime elements should be squashed together on top. When scrolling, paragraphs may pop in-and-out of the squashing layer when they change overlapping status with respect to the composited layer underneath.
+
+This scenario tests (1) that content repaints correctly as layers pop in and out of squashing, and (2) that the positioning of the squashing layer remains correct (i.e. scrolls properly) when the squashing layer is on top of a fixed-position composited layer.
+
+CASE 1, original layer tree:
+{
+  "layers": [
+    {
+      "name": "LayoutView #document",
+      "bounds": [785, 1400],
+      "contentsOpaque": true,
+      "backgroundColor": "#FFFFFF"
+    },
+    {
+      "name": "LayoutBlockFlow (positioned) DIV class='composited background'",
+      "bounds": [300, 300],
+      "contentsOpaque": true,
+      "backgroundColor": "#D3D3D3",
+      "transform": 1
+    },
+    {
+      "name": "Squashing Containment Layer",
+      "drawsContent": false
+    },
+    {
+      "name": "LayoutBlockFlow (relative positioned) DIV id='paragraph-b' class='overlapping lime'",
+      "position": [0, 100],
+      "bounds": [200, 100],
+      "contentsOpaque": true,
+      "backgroundColor": "#00FF00"
+    },
+    {
+      "name": "Squashing Layer (first squashed layer: LayoutBlockFlow (relative positioned) DIV id='paragraph-c' class='overlapping cyan')",
+      "position": [0, 200],
+      "bounds": [200, 300]
+    }
+  ],
+  "transforms": [
+    {
+      "id": 1,
+      "transform": [
+        [1, 0, 0, 0],
+        [0, 1, 0, 0],
+        [0, 0, 1, 0],
+        [100, 150, 0, 1]
+      ]
+    }
+  ]
+}
+CASE 2, scrolling y to 80, new layers will be squashed, so things repaint:
+{
+  "layers": [
+    {
+      "name": "LayoutView #document",
+      "bounds": [785, 1400],
+      "contentsOpaque": true,
+      "backgroundColor": "#FFFFFF",
+      "paintInvalidations": [
+        {
+          "object": "LayoutBlockFlow (relative positioned) DIV id='paragraph-f' class='overlapping lime'",
+          "rect": [0, 500, 200, 100],
+          "reason": "disappeared"
+        },
+        {
+          "object": "LayoutBlockFlow (relative positioned) DIV id='paragraph-b' class='overlapping lime'",
+          "rect": [0, 100, 200, 100],
+          "reason": "appeared"
+        }
+      ],
+      "transform": 1
+    },
+    {
+      "name": "LayoutBlockFlow (positioned) DIV class='composited background'",
+      "bounds": [300, 300],
+      "contentsOpaque": true,
+      "backgroundColor": "#D3D3D3",
+      "transform": 2
+    },
+    {
+      "name": "Squashing Containment Layer",
+      "drawsContent": false,
+      "transform": 1
+    },
+    {
+      "name": "LayoutBlockFlow (relative positioned) DIV id='paragraph-c' class='overlapping cyan'",
+      "position": [0, 200],
+      "bounds": [200, 100],
+      "contentsOpaque": true,
+      "backgroundColor": "#00FFFF",
+      "paintInvalidations": [
+        {
+          "object": "LayoutBlockFlow (relative positioned) DIV id='paragraph-c' class='overlapping cyan'",
+          "rect": [0, 0, 200, 100],
+          "reason": "full"
+        }
+      ],
+      "transform": 1
+    },
+    {
+      "name": "Squashing Layer (first squashed layer: LayoutBlockFlow (relative positioned) DIV id='paragraph-d' class='overlapping lime')",
+      "position": [0, 300],
+      "bounds": [200, 300],
+      "transform": 1
+    }
+  ],
+  "transforms": [
+    {
+      "id": 1,
+      "transform": [
+        [1, 0, 0, 0],
+        [0, 1, 0, 0],
+        [0, 0, 1, 0],
+        [0, -80, 0, 1]
+      ]
+    },
+    {
+      "id": 2,
+      "parent": 1,
+      "transform": [
+        [1, 0, 0, 0],
+        [0, 1, 0, 0],
+        [0, 0, 1, 0],
+        [100, 230, 0, 1]
+      ]
+    }
+  ],
+  "objectPaintInvalidations": [
+    {
+      "object": "LayoutBlockFlow (relative positioned) DIV id='paragraph-b' class='overlapping lime'",
+      "reason": "compositing update"
+    },
+    {
+      "object": "LayoutBlockFlow (relative positioned) DIV id='paragraph-c' class='overlapping cyan'",
+      "reason": "compositing update"
+    },
+    {
+      "object": "LayoutBlockFlow (relative positioned) DIV id='paragraph-d' class='overlapping lime'",
+      "reason": "compositing update"
+    },
+    {
+      "object": "LayoutBlockFlow (relative positioned) DIV id='paragraph-e' class='overlapping cyan'",
+      "reason": "compositing update"
+    },
+    {
+      "object": "LayoutBlockFlow (relative positioned) DIV id='paragraph-f' class='overlapping lime'",
+      "reason": "compositing update"
+    }
+  ]
+}
+CASE 3, scrolling y to 120, no repaints expected:
+{
+  "layers": [
+    {
+      "name": "LayoutView #document",
+      "bounds": [785, 1400],
+      "contentsOpaque": true,
+      "backgroundColor": "#FFFFFF",
+      "transform": 1
+    },
+    {
+      "name": "LayoutBlockFlow (positioned) DIV class='composited background'",
+      "bounds": [300, 300],
+      "contentsOpaque": true,
+      "backgroundColor": "#D3D3D3",
+      "transform": 2
+    },
+    {
+      "name": "Squashing Containment Layer",
+      "drawsContent": false,
+      "transform": 1
+    },
+    {
+      "name": "LayoutBlockFlow (relative positioned) DIV id='paragraph-c' class='overlapping cyan'",
+      "position": [0, 200],
+      "bounds": [200, 100],
+      "contentsOpaque": true,
+      "backgroundColor": "#00FFFF",
+      "transform": 1
+    },
+    {
+      "name": "Squashing Layer (first squashed layer: LayoutBlockFlow (relative positioned) DIV id='paragraph-d' class='overlapping lime')",
+      "position": [0, 300],
+      "bounds": [200, 300],
+      "transform": 1
+    }
+  ],
+  "transforms": [
+    {
+      "id": 1,
+      "transform": [
+        [1, 0, 0, 0],
+        [0, 1, 0, 0],
+        [0, 0, 1, 0],
+        [0, -120, 0, 1]
+      ]
+    },
+    {
+      "id": 2,
+      "parent": 1,
+      "transform": [
+        [1, 0, 0, 0],
+        [0, 1, 0, 0],
+        [0, 0, 1, 0],
+        [100, 270, 0, 1]
+      ]
+    }
+  ]
+}
+CASE 4, scrolling y to 170 new layers will be squashed, so things repaint:
+{
+  "layers": [
+    {
+      "name": "LayoutView #document",
+      "bounds": [785, 1400],
+      "contentsOpaque": true,
+      "backgroundColor": "#FFFFFF",
+      "paintInvalidations": [
+        {
+          "object": "LayoutBlockFlow (relative positioned) DIV id='paragraph-g' class='overlapping cyan'",
+          "rect": [0, 600, 200, 100],
+          "reason": "disappeared"
+        },
+        {
+          "object": "LayoutBlockFlow (relative positioned) DIV id='paragraph-c' class='overlapping cyan'",
+          "rect": [0, 200, 200, 100],
+          "reason": "appeared"
+        }
+      ],
+      "transform": 1
+    },
+    {
+      "name": "LayoutBlockFlow (positioned) DIV class='composited background'",
+      "bounds": [300, 300],
+      "contentsOpaque": true,
+      "backgroundColor": "#D3D3D3",
+      "transform": 2
+    },
+    {
+      "name": "Squashing Containment Layer",
+      "drawsContent": false,
+      "transform": 1
+    },
+    {
+      "name": "LayoutBlockFlow (relative positioned) DIV id='paragraph-d' class='overlapping lime'",
+      "position": [0, 300],
+      "bounds": [200, 100],
+      "contentsOpaque": true,
+      "backgroundColor": "#00FF00",
+      "paintInvalidations": [
+        {
+          "object": "LayoutBlockFlow (relative positioned) DIV id='paragraph-d' class='overlapping lime'",
+          "rect": [0, 0, 200, 100],
+          "reason": "full"
+        }
+      ],
+      "transform": 1
+    },
+    {
+      "name": "Squashing Layer (first squashed layer: LayoutBlockFlow (relative positioned) DIV id='paragraph-e' class='overlapping cyan')",
+      "position": [0, 400],
+      "bounds": [200, 300],
+      "transform": 1
+    }
+  ],
+  "transforms": [
+    {
+      "id": 1,
+      "transform": [
+        [1, 0, 0, 0],
+        [0, 1, 0, 0],
+        [0, 0, 1, 0],
+        [0, -170, 0, 1]
+      ]
+    },
+    {
+      "id": 2,
+      "parent": 1,
+      "transform": [
+        [1, 0, 0, 0],
+        [0, 1, 0, 0],
+        [0, 0, 1, 0],
+        [100, 320, 0, 1]
+      ]
+    }
+  ],
+  "objectPaintInvalidations": [
+    {
+      "object": "LayoutBlockFlow (relative positioned) DIV id='paragraph-c' class='overlapping cyan'",
+      "reason": "compositing update"
+    },
+    {
+      "object": "LayoutBlockFlow (relative positioned) DIV id='paragraph-d' class='overlapping lime'",
+      "reason": "compositing update"
+    },
+    {
+      "object": "LayoutBlockFlow (relative positioned) DIV id='paragraph-e' class='overlapping cyan'",
+      "reason": "compositing update"
+    },
+    {
+      "object": "LayoutBlockFlow (relative positioned) DIV id='paragraph-f' class='overlapping lime'",
+      "reason": "compositing update"
+    },
+    {
+      "object": "LayoutBlockFlow (relative positioned) DIV id='paragraph-g' class='overlapping cyan'",
+      "reason": "compositing update"
+    }
+  ]
+}
+
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v175/compositing/squashing/squash-above-fixed-3-expected.txt b/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v175/compositing/squashing/squash-above-fixed-3-expected.txt
new file mode 100644
index 0000000..8292e9b
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v175/compositing/squashing/squash-above-fixed-3-expected.txt
@@ -0,0 +1,204 @@
+This scenario verifies that the green "container" element and lime "innerScrolling" element scroll properly even though there is a blue fixed-position element layered in between them.
+
+The catch is that the squashing requirements should be computed in correct paint order, so that the green container does not accidentally position itself with respect to the wrong layer and not scroll.
+
+CASE 1, original layer tree:
+{
+  "layers": [
+    {
+      "name": "LayoutView #document",
+      "bounds": [785, 4100],
+      "contentsOpaque": true,
+      "backgroundColor": "#FFFFFF"
+    },
+    {
+      "name": "LayoutBlockFlow (positioned) DIV id='backgroundFixed'",
+      "bounds": [400, 400],
+      "contentsOpaque": true,
+      "backgroundColor": "#808080"
+    },
+    {
+      "name": "LayoutBlockFlow (positioned) DIV id='container'",
+      "position": [100, 100],
+      "bounds": [100, 4000],
+      "contentsOpaque": true,
+      "backgroundColor": "#008000"
+    },
+    {
+      "name": "LayoutBlockFlow (positioned) DIV id='innerFixed'",
+      "bounds": [200, 100],
+      "contentsOpaque": true,
+      "backgroundColor": "#0000FF",
+      "transform": 1
+    },
+    {
+      "name": "LayoutBlockFlow (positioned) DIV id='innerScrolling'",
+      "position": [200, 100],
+      "bounds": [100, 100],
+      "contentsOpaque": true,
+      "backgroundColor": "#00FF00"
+    }
+  ],
+  "transforms": [
+    {
+      "id": 1,
+      "transform": [
+        [1, 0, 0, 0],
+        [0, 1, 0, 0],
+        [0, 0, 1, 0],
+        [100, 150, 0, 1]
+      ]
+    }
+  ]
+}
+CASE 2, scrolling y by 10 pixels, both the "container" and "inner" should scroll properly.
+{
+  "layers": [
+    {
+      "name": "LayoutView #document",
+      "bounds": [785, 4100],
+      "contentsOpaque": true,
+      "backgroundColor": "#FFFFFF",
+      "transform": 1
+    },
+    {
+      "name": "LayoutBlockFlow (positioned) DIV id='backgroundFixed'",
+      "bounds": [400, 400],
+      "contentsOpaque": true,
+      "backgroundColor": "#808080",
+      "transform": 2
+    },
+    {
+      "name": "LayoutBlockFlow (positioned) DIV id='container'",
+      "position": [100, 100],
+      "bounds": [100, 4000],
+      "contentsOpaque": true,
+      "backgroundColor": "#008000",
+      "transform": 1
+    },
+    {
+      "name": "LayoutBlockFlow (positioned) DIV id='innerFixed'",
+      "bounds": [200, 100],
+      "contentsOpaque": true,
+      "backgroundColor": "#0000FF",
+      "transform": 3
+    },
+    {
+      "name": "LayoutBlockFlow (positioned) DIV id='innerScrolling'",
+      "position": [200, 100],
+      "bounds": [100, 100],
+      "contentsOpaque": true,
+      "backgroundColor": "#00FF00",
+      "transform": 1
+    }
+  ],
+  "transforms": [
+    {
+      "id": 1,
+      "transform": [
+        [1, 0, 0, 0],
+        [0, 1, 0, 0],
+        [0, 0, 1, 0],
+        [0, -10, 0, 1]
+      ]
+    },
+    {
+      "id": 2,
+      "parent": 1,
+      "transform": [
+        [1, 0, 0, 0],
+        [0, 1, 0, 0],
+        [0, 0, 1, 0],
+        [0, 10, 0, 1]
+      ]
+    },
+    {
+      "id": 3,
+      "parent": 1,
+      "transform": [
+        [1, 0, 0, 0],
+        [0, 1, 0, 0],
+        [0, 0, 1, 0],
+        [100, 160, 0, 1]
+      ]
+    }
+  ]
+}
+CASE 3, scrolling y further so that "inner" no longer overlaps the fixed-pos layer, then the stacking context of "container" includes the "innerScrolling" layer, and doubles in width:
+{
+  "layers": [
+    {
+      "name": "LayoutView #document",
+      "bounds": [785, 4100],
+      "contentsOpaque": true,
+      "backgroundColor": "#FFFFFF",
+      "transform": 1
+    },
+    {
+      "name": "LayoutBlockFlow (positioned) DIV id='backgroundFixed'",
+      "bounds": [400, 400],
+      "contentsOpaque": true,
+      "backgroundColor": "#808080",
+      "transform": 2
+    },
+    {
+      "name": "LayoutBlockFlow (positioned) DIV id='container'",
+      "position": [100, 100],
+      "bounds": [200, 4000],
+      "backgroundColor": "#008000",
+      "paintInvalidations": [
+        {
+          "object": "LayoutBlockFlow (positioned) DIV id='innerScrolling'",
+          "rect": [100, 0, 100, 100],
+          "reason": "appeared"
+        }
+      ],
+      "transform": 1
+    },
+    {
+      "name": "LayoutBlockFlow (positioned) DIV id='innerFixed'",
+      "bounds": [200, 100],
+      "contentsOpaque": true,
+      "backgroundColor": "#0000FF",
+      "transform": 3
+    }
+  ],
+  "transforms": [
+    {
+      "id": 1,
+      "transform": [
+        [1, 0, 0, 0],
+        [0, 1, 0, 0],
+        [0, 0, 1, 0],
+        [0, -110, 0, 1]
+      ]
+    },
+    {
+      "id": 2,
+      "parent": 1,
+      "transform": [
+        [1, 0, 0, 0],
+        [0, 1, 0, 0],
+        [0, 0, 1, 0],
+        [0, 110, 0, 1]
+      ]
+    },
+    {
+      "id": 3,
+      "parent": 1,
+      "transform": [
+        [1, 0, 0, 0],
+        [0, 1, 0, 0],
+        [0, 0, 1, 0],
+        [100, 260, 0, 1]
+      ]
+    }
+  ],
+  "objectPaintInvalidations": [
+    {
+      "object": "LayoutBlockFlow (positioned) DIV id='innerScrolling'",
+      "reason": "compositing update"
+    }
+  ]
+}
+
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v175/compositing/squashing/squash-transform-repainting-transformed-child-expected.txt b/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v175/compositing/squashing/squash-transform-repainting-transformed-child-expected.txt
new file mode 100644
index 0000000..6225ed0
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v175/compositing/squashing/squash-transform-repainting-transformed-child-expected.txt
@@ -0,0 +1,153 @@
+CASE 1, original layer tree
+{
+  "layers": [
+    {
+      "name": "LayoutView #document",
+      "bounds": [800, 600],
+      "contentsOpaque": true,
+      "backgroundColor": "#FFFFFF"
+    },
+    {
+      "name": "Squashing Containment Layer",
+      "drawsContent": false
+    },
+    {
+      "name": "LayoutBlockFlow (positioned) DIV class='composited box behind'",
+      "bounds": [100, 100],
+      "contentsOpaque": true,
+      "backgroundColor": "#0000FF",
+      "transform": 1
+    },
+    {
+      "name": "Squashing Layer (first squashed layer: LayoutBlockFlow (positioned) DIV class='box middle')",
+      "position": [4, 4],
+      "bounds": [276, 276]
+    }
+  ],
+  "transforms": [
+    {
+      "id": 1,
+      "transform": [
+        [1, 0, 0, 0],
+        [0, 1, 0, 0],
+        [0, 0, 1, 0],
+        [100, 100, 0, 1]
+      ],
+      "flattenInheritedTransform": false
+    }
+  ]
+}
+CASE 2, hovering over the outer div
+{
+  "layers": [
+    {
+      "name": "LayoutView #document",
+      "bounds": [800, 600],
+      "contentsOpaque": true,
+      "backgroundColor": "#FFFFFF"
+    },
+    {
+      "name": "Squashing Containment Layer",
+      "drawsContent": false
+    },
+    {
+      "name": "LayoutBlockFlow (positioned) DIV class='composited box behind'",
+      "bounds": [100, 100],
+      "contentsOpaque": true,
+      "backgroundColor": "#0000FF",
+      "transform": 1
+    },
+    {
+      "name": "Squashing Layer (first squashed layer: LayoutBlockFlow (positioned) DIV class='box middle')",
+      "position": [4, 4],
+      "bounds": [276, 276],
+      "paintInvalidations": [
+        {
+          "object": "LayoutBlockFlow (positioned) DIV class='box middle'",
+          "rect": [0, 0, 132, 132],
+          "reason": "style change"
+        }
+      ]
+    }
+  ],
+  "transforms": [
+    {
+      "id": 1,
+      "transform": [
+        [1, 0, 0, 0],
+        [0, 1, 0, 0],
+        [0, 0, 1, 0],
+        [100, 100, 0, 1]
+      ],
+      "flattenInheritedTransform": false
+    }
+  ],
+  "objectPaintInvalidations": [
+    {
+      "object": "LayoutBlockFlow (positioned) DIV class='box middle'",
+      "reason": "style change"
+    }
+  ]
+}
+CASE 3, hovering over the inner div
+{
+  "layers": [
+    {
+      "name": "LayoutView #document",
+      "bounds": [800, 600],
+      "contentsOpaque": true,
+      "backgroundColor": "#FFFFFF"
+    },
+    {
+      "name": "Squashing Containment Layer",
+      "drawsContent": false
+    },
+    {
+      "name": "LayoutBlockFlow (positioned) DIV class='composited box behind'",
+      "bounds": [100, 100],
+      "contentsOpaque": true,
+      "backgroundColor": "#0000FF",
+      "transform": 1
+    },
+    {
+      "name": "Squashing Layer (first squashed layer: LayoutBlockFlow (positioned) DIV class='box middle')",
+      "position": [4, 4],
+      "bounds": [276, 276],
+      "paintInvalidations": [
+        {
+          "object": "LayoutBlockFlow (positioned) DIV class='box middle'",
+          "rect": [0, 0, 132, 132],
+          "reason": "style change"
+        },
+        {
+          "object": "LayoutBlockFlow (positioned) DIV class='smallbox'",
+          "rect": [26, 28, 71, 72],
+          "reason": "style change"
+        }
+      ]
+    }
+  ],
+  "transforms": [
+    {
+      "id": 1,
+      "transform": [
+        [1, 0, 0, 0],
+        [0, 1, 0, 0],
+        [0, 0, 1, 0],
+        [100, 100, 0, 1]
+      ],
+      "flattenInheritedTransform": false
+    }
+  ],
+  "objectPaintInvalidations": [
+    {
+      "object": "LayoutBlockFlow (positioned) DIV class='box middle'",
+      "reason": "style change"
+    },
+    {
+      "object": "LayoutBlockFlow (positioned) DIV class='smallbox'",
+      "reason": "style change"
+    }
+  ]
+}
+
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v175/paint/invalidation/caret-subpixel-expected.txt b/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v175/paint/invalidation/caret-subpixel-expected.txt
index 67849d0..d688375 100644
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v175/paint/invalidation/caret-subpixel-expected.txt
+++ b/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v175/paint/invalidation/caret-subpixel-expected.txt
@@ -12,7 +12,7 @@
           "reason": "subtree"
         },
         {
-          "object": "LayoutBlockFlow DIV id='inner-editor'",
+          "object": "LayoutBlockFlow DIV",
           "rect": [209, 11, 2, 16],
           "reason": "appeared"
         }
@@ -25,7 +25,7 @@
       "reason": "subtree"
     },
     {
-      "object": "LayoutBlockFlow DIV id='inner-editor'",
+      "object": "LayoutBlockFlow DIV",
       "reason": "subtree"
     },
     {
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v175/paint/invalidation/caret-with-composited-scroll-expected.txt b/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v175/paint/invalidation/caret-with-composited-scroll-expected.txt
new file mode 100644
index 0000000..f524748
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v175/paint/invalidation/caret-with-composited-scroll-expected.txt
@@ -0,0 +1,87 @@
+{
+  "layers": [
+    {
+      "name": "LayoutView #document",
+      "bounds": [800, 600],
+      "contentsOpaque": true,
+      "backgroundColor": "#FFFFFF"
+    },
+    {
+      "name": "LayoutBlockFlow DIV id='scroller'",
+      "position": [8, 48],
+      "bounds": [100, 100]
+    },
+    {
+      "name": "Scrolling Layer",
+      "position": [8, 48],
+      "bounds": [100, 100],
+      "drawsContent": false
+    },
+    {
+      "name": "Scrolling Contents Layer",
+      "position": [8, 48],
+      "bounds": [205, 1022],
+      "paintInvalidations": [
+        {
+          "object": "LayoutTextControl INPUT id='text'",
+          "rect": [-1, 999, 207, 24],
+          "reason": "appeared"
+        },
+        {
+          "object": "LayoutTextControl INPUT id='text'",
+          "rect": [-1, 999, 207, 24],
+          "reason": "subtree"
+        },
+        {
+          "object": "LayoutBlockFlow DIV",
+          "rect": [3, 1003, 1, 16],
+          "reason": "appeared"
+        }
+      ],
+      "transform": 1
+    },
+    {
+      "name": "Overflow Controls Host Layer",
+      "position": [8, 48],
+      "bounds": [100, 100],
+      "drawsContent": false
+    },
+    {
+      "name": "Horizontal Scrollbar Layer",
+      "position": [8, 148],
+      "bounds": [100, 0]
+    },
+    {
+      "name": "Vertical Scrollbar Layer",
+      "position": [108, 48],
+      "bounds": [0, 100]
+    }
+  ],
+  "transforms": [
+    {
+      "id": 1,
+      "transform": [
+        [1, 0, 0, 0],
+        [0, 1, 0, 0],
+        [0, 0, 1, 0],
+        [0, -922, 0, 1]
+      ],
+      "flattenInheritedTransform": false
+    }
+  ],
+  "objectPaintInvalidations": [
+    {
+      "object": "LayoutTextControl INPUT id='text'",
+      "reason": "subtree"
+    },
+    {
+      "object": "LayoutBlockFlow DIV",
+      "reason": "subtree"
+    },
+    {
+      "object": "Caret",
+      "reason": "caret"
+    }
+  ]
+}
+
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v175/paint/invalidation/change-text-content-and-background-color-expected.txt b/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v175/paint/invalidation/change-text-content-and-background-color-expected.txt
index 2d901d5..e07f2a18 100644
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v175/paint/invalidation/change-text-content-and-background-color-expected.txt
+++ b/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v175/paint/invalidation/change-text-content-and-background-color-expected.txt
@@ -30,7 +30,7 @@
       "reason": "style change"
     },
     {
-      "object": "LayoutBlockFlow DIV id='inner-editor'",
+      "object": "LayoutBlockFlow DIV",
       "reason": "geometry"
     },
     {
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v175/paint/invalidation/composited-overflow-with-local-background-expected.txt b/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v175/paint/invalidation/composited-overflow-with-local-background-expected.txt
new file mode 100644
index 0000000..78dc57f
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v175/paint/invalidation/composited-overflow-with-local-background-expected.txt
@@ -0,0 +1,70 @@
+{
+  "layers": [
+    {
+      "name": "LayoutView #document",
+      "bounds": [800, 600],
+      "contentsOpaque": true,
+      "backgroundColor": "#FFFFFF"
+    },
+    {
+      "name": "LayoutBlockFlow DIV id='scroller'",
+      "position": [8, 8],
+      "bounds": [200, 200],
+      "backgroundColor": "#008000"
+    },
+    {
+      "name": "Scrolling Layer",
+      "position": [8, 8],
+      "bounds": [185, 185],
+      "drawsContent": false
+    },
+    {
+      "name": "Scrolling Contents Layer",
+      "position": [8, 8],
+      "bounds": [185, 300],
+      "contentsOpaque": true,
+      "backgroundColor": "#008000",
+      "paintInvalidations": [
+        {
+          "object": "Scrolling Contents Layer",
+          "rect": [0, 0, 185, 300],
+          "reason": "background on scrolling contents layer"
+        }
+      ]
+    },
+    {
+      "name": "Overflow Controls Host Layer",
+      "position": [8, 8],
+      "bounds": [200, 200],
+      "drawsContent": false
+    },
+    {
+      "name": "Horizontal Scrollbar Layer",
+      "position": [8, 193],
+      "bounds": [185, 15],
+      "drawsContent": false
+    },
+    {
+      "name": "Vertical Scrollbar Layer",
+      "position": [193, 8],
+      "bounds": [15, 185],
+      "drawsContent": false
+    },
+    {
+      "name": "Scroll Corner Layer",
+      "position": [193, 193],
+      "bounds": [15, 15]
+    }
+  ],
+  "objectPaintInvalidations": [
+    {
+      "object": "Scrolling Contents Layer",
+      "reason": "background on scrolling contents layer"
+    },
+    {
+      "object": "LayoutBlockFlow DIV id='scroller'",
+      "reason": "style change"
+    }
+  ]
+}
+
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v175/paint/invalidation/compositing/chunk-reorder-expected.txt b/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v175/paint/invalidation/compositing/chunk-reorder-expected.txt
new file mode 100644
index 0000000..8fc606a3
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v175/paint/invalidation/compositing/chunk-reorder-expected.txt
@@ -0,0 +1,39 @@
+{
+  "layers": [
+    {
+      "name": "LayoutView #document",
+      "bounds": [800, 600],
+      "contentsOpaque": true,
+      "backgroundColor": "#FFFFFF"
+    },
+    {
+      "name": "LayoutBlockFlow DIV",
+      "bounds": [784, 550],
+      "paintInvalidations": [
+        {
+          "object": "LayoutBlockFlow (positioned) DIV id='chunk3'",
+          "rect": [400, 400, 100, 100],
+          "reason": "chunk reordered"
+        },
+        {
+          "object": "LayoutBlockFlow (positioned) DIV id='chunk2'",
+          "rect": [0, 0, 1, 1],
+          "reason": "chunk reordered"
+        }
+      ],
+      "transform": 1
+    }
+  ],
+  "transforms": [
+    {
+      "id": 1,
+      "transform": [
+        [1, 0, 0, 0],
+        [0, 1, 0, 0],
+        [0, 0, 1, 0],
+        [8, 8, 0, 1]
+      ]
+    }
+  ]
+}
+
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v175/paint/invalidation/compositing/containing-block-added-expected.txt b/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v175/paint/invalidation/compositing/containing-block-added-expected.txt
new file mode 100644
index 0000000..7a22eb1
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v175/paint/invalidation/compositing/containing-block-added-expected.txt
@@ -0,0 +1,37 @@
+{
+  "layers": [
+    {
+      "name": "LayoutView #document",
+      "bounds": [800, 600],
+      "contentsOpaque": true,
+      "backgroundColor": "#FFFFFF",
+      "paintInvalidations": [
+        {
+          "object": "LayoutBlockFlow (positioned) DIV class='fixed'",
+          "rect": [50, 50, 75, 75],
+          "reason": "disappeared"
+        }
+      ]
+    },
+    {
+      "name": "LayoutBlockFlow (positioned) DIV id='container'",
+      "position": [200, 100],
+      "bounds": [125, 125],
+      "backgroundColor": "#0000FF",
+      "paintInvalidations": [
+        {
+          "object": "LayoutBlockFlow (positioned) DIV class='fixed'",
+          "rect": [50, 50, 75, 75],
+          "reason": "appeared"
+        }
+      ]
+    }
+  ],
+  "objectPaintInvalidations": [
+    {
+      "object": "LayoutBlockFlow (positioned) DIV class='fixed'",
+      "reason": "geometry"
+    }
+  ]
+}
+
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v175/paint/invalidation/compositing/containing-block-added-individual-expected.txt b/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v175/paint/invalidation/compositing/containing-block-added-individual-expected.txt
new file mode 100644
index 0000000..7a22eb1
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v175/paint/invalidation/compositing/containing-block-added-individual-expected.txt
@@ -0,0 +1,37 @@
+{
+  "layers": [
+    {
+      "name": "LayoutView #document",
+      "bounds": [800, 600],
+      "contentsOpaque": true,
+      "backgroundColor": "#FFFFFF",
+      "paintInvalidations": [
+        {
+          "object": "LayoutBlockFlow (positioned) DIV class='fixed'",
+          "rect": [50, 50, 75, 75],
+          "reason": "disappeared"
+        }
+      ]
+    },
+    {
+      "name": "LayoutBlockFlow (positioned) DIV id='container'",
+      "position": [200, 100],
+      "bounds": [125, 125],
+      "backgroundColor": "#0000FF",
+      "paintInvalidations": [
+        {
+          "object": "LayoutBlockFlow (positioned) DIV class='fixed'",
+          "rect": [50, 50, 75, 75],
+          "reason": "appeared"
+        }
+      ]
+    }
+  ],
+  "objectPaintInvalidations": [
+    {
+      "object": "LayoutBlockFlow (positioned) DIV class='fixed'",
+      "reason": "geometry"
+    }
+  ]
+}
+
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v175/paint/invalidation/compositing/containing-block-removed-expected.txt b/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v175/paint/invalidation/compositing/containing-block-removed-expected.txt
new file mode 100644
index 0000000..bb7844a
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v175/paint/invalidation/compositing/containing-block-removed-expected.txt
@@ -0,0 +1,39 @@
+CONSOLE MESSAGE: line 30: debug
+{
+  "layers": [
+    {
+      "name": "LayoutView #document",
+      "bounds": [800, 600],
+      "contentsOpaque": true,
+      "backgroundColor": "#FFFFFF",
+      "paintInvalidations": [
+        {
+          "object": "LayoutBlockFlow (positioned) DIV class='fixed'",
+          "rect": [50, 50, 75, 75],
+          "reason": "appeared"
+        }
+      ]
+    },
+    {
+      "name": "LayoutBlockFlow (positioned) DIV id='container'",
+      "position": [200, 100],
+      "bounds": [100, 100],
+      "contentsOpaque": true,
+      "backgroundColor": "#0000FF",
+      "paintInvalidations": [
+        {
+          "object": "LayoutBlockFlow (positioned) DIV class='fixed'",
+          "rect": [50, 50, 75, 75],
+          "reason": "disappeared"
+        }
+      ]
+    }
+  ],
+  "objectPaintInvalidations": [
+    {
+      "object": "LayoutBlockFlow (positioned) DIV class='fixed'",
+      "reason": "geometry"
+    }
+  ]
+}
+
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v175/paint/invalidation/compositing/containing-block-removed-individual-expected.txt b/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v175/paint/invalidation/compositing/containing-block-removed-individual-expected.txt
new file mode 100644
index 0000000..bb7844a
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v175/paint/invalidation/compositing/containing-block-removed-individual-expected.txt
@@ -0,0 +1,39 @@
+CONSOLE MESSAGE: line 30: debug
+{
+  "layers": [
+    {
+      "name": "LayoutView #document",
+      "bounds": [800, 600],
+      "contentsOpaque": true,
+      "backgroundColor": "#FFFFFF",
+      "paintInvalidations": [
+        {
+          "object": "LayoutBlockFlow (positioned) DIV class='fixed'",
+          "rect": [50, 50, 75, 75],
+          "reason": "appeared"
+        }
+      ]
+    },
+    {
+      "name": "LayoutBlockFlow (positioned) DIV id='container'",
+      "position": [200, 100],
+      "bounds": [100, 100],
+      "contentsOpaque": true,
+      "backgroundColor": "#0000FF",
+      "paintInvalidations": [
+        {
+          "object": "LayoutBlockFlow (positioned) DIV class='fixed'",
+          "rect": [50, 50, 75, 75],
+          "reason": "disappeared"
+        }
+      ]
+    }
+  ],
+  "objectPaintInvalidations": [
+    {
+      "object": "LayoutBlockFlow (positioned) DIV class='fixed'",
+      "reason": "geometry"
+    }
+  ]
+}
+
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v175/paint/invalidation/compositing/fixed-pos-inside-composited-intermediate-layer-expected.txt b/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v175/paint/invalidation/compositing/fixed-pos-inside-composited-intermediate-layer-expected.txt
new file mode 100644
index 0000000..fdc152b
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v175/paint/invalidation/compositing/fixed-pos-inside-composited-intermediate-layer-expected.txt
@@ -0,0 +1,70 @@
+{
+  "layers": [
+    {
+      "name": "LayoutView #document",
+      "bounds": [785, 30020],
+      "contentsOpaque": true,
+      "backgroundColor": "#FFFFFF",
+      "transform": 1
+    },
+    {
+      "name": "Squashing Containment Layer",
+      "drawsContent": false,
+      "transform": 1
+    },
+    {
+      "name": "LayoutBlockFlow DIV class='compositedBehind'",
+      "bounds": [500, 500],
+      "contentsOpaque": true,
+      "backgroundColor": "#00FFFF",
+      "transform": 2
+    },
+    {
+      "name": "Squashing Layer (first squashed layer: LayoutBlockFlow (positioned) DIV class='containerOverlapsComposited')",
+      "position": [20, 20],
+      "bounds": [100, 30000],
+      "paintInvalidations": [
+        {
+          "object": "LayoutBlockFlow (positioned) DIV class='fixed'",
+          "rect": [25, 125, 50, 50],
+          "reason": "paint property change"
+        },
+        {
+          "object": "LayoutBlockFlow (positioned) DIV class='fixed'",
+          "rect": [25, 25, 50, 50],
+          "reason": "paint property change"
+        }
+      ],
+      "transform": 1
+    }
+  ],
+  "transforms": [
+    {
+      "id": 1,
+      "transform": [
+        [1, 0, 0, 0],
+        [0, 1, 0, 0],
+        [0, 0, 1, 0],
+        [0, -100, 0, 1]
+      ]
+    },
+    {
+      "id": 2,
+      "parent": 1,
+      "transform": [
+        [1, 0, 0, 0],
+        [0, 1, 0, 0],
+        [0, 0, 1, 0],
+        [8, 8, 0, 1]
+      ],
+      "flattenInheritedTransform": false
+    }
+  ],
+  "objectPaintInvalidations": [
+    {
+      "object": "LayoutBlockFlow (positioned) DIV class='fixed'",
+      "reason": "subtree"
+    }
+  ]
+}
+
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v175/paint/invalidation/compositing/fixed-scroll-in-empty-root-layer-expected.txt b/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v175/paint/invalidation/compositing/fixed-scroll-in-empty-root-layer-expected.txt
new file mode 100644
index 0000000..84e66e6
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v175/paint/invalidation/compositing/fixed-scroll-in-empty-root-layer-expected.txt
@@ -0,0 +1,61 @@
+{
+  "layers": [
+    {
+      "name": "LayoutView #document",
+      "bounds": [785, 2016],
+      "contentsOpaque": true,
+      "drawsContent": false,
+      "backgroundColor": "#FFFFFF",
+      "transform": 1
+    },
+    {
+      "name": "LayoutBlockFlow HTML",
+      "bounds": [785, 2016],
+      "transform": 1
+    },
+    {
+      "name": "LayoutBlockFlow (positioned) DIV",
+      "position": [0, 250],
+      "bounds": [100, 100],
+      "contentsOpaque": true,
+      "backfaceVisibility": "hidden",
+      "backgroundColor": "#FF0000",
+      "transform": 1
+    },
+    {
+      "name": "LayoutBlockFlow HTML (foreground) Layer",
+      "bounds": [785, 2016],
+      "paintInvalidations": [
+        {
+          "object": "LayoutBlockFlow (positioned) DIV",
+          "rect": [0, 250, 100, 100],
+          "reason": "paint property change"
+        },
+        {
+          "object": "LayoutBlockFlow (positioned) DIV",
+          "rect": [0, 50, 100, 100],
+          "reason": "paint property change"
+        }
+      ],
+      "transform": 1
+    }
+  ],
+  "transforms": [
+    {
+      "id": 1,
+      "transform": [
+        [1, 0, 0, 0],
+        [0, 1, 0, 0],
+        [0, 0, 1, 0],
+        [0, -200, 0, 1]
+      ]
+    }
+  ],
+  "objectPaintInvalidations": [
+    {
+      "object": "LayoutBlockFlow (positioned) DIV",
+      "reason": "subtree"
+    }
+  ]
+}
+
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v175/paint/invalidation/compositing/iframe-inside-squashed-layer-expected.txt b/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v175/paint/invalidation/compositing/iframe-inside-squashed-layer-expected.txt
new file mode 100644
index 0000000..7982783
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v175/paint/invalidation/compositing/iframe-inside-squashed-layer-expected.txt
@@ -0,0 +1,81 @@
+{
+  "layers": [
+    {
+      "name": "LayoutView #document",
+      "bounds": [785, 1016],
+      "contentsOpaque": true,
+      "backgroundColor": "#FFFFFF"
+    },
+    {
+      "name": "Squashing Containment Layer",
+      "drawsContent": false
+    },
+    {
+      "name": "LayoutBlockFlow DIV id='foo'",
+      "bounds": [200, 1000],
+      "contentsOpaque": true,
+      "backgroundColor": "#D3D3D3",
+      "transform": 1
+    },
+    {
+      "name": "Squashing Layer (first squashed layer: LayoutBlockFlow (positioned) DIV)",
+      "position": [8, 0],
+      "bounds": [300, 654],
+      "paintInvalidations": [
+        {
+          "object": "LayoutBlockFlow HTML",
+          "rect": [8, 508, 29, 19],
+          "reason": "paint property change"
+        },
+        {
+          "object": "LayoutView #document",
+          "rect": [285, 500, 15, 150],
+          "reason": "appeared"
+        }
+      ]
+    }
+  ],
+  "transforms": [
+    {
+      "id": 1,
+      "transform": [
+        [1, 0, 0, 0],
+        [0, 1, 0, 0],
+        [0, 0, 1, 0],
+        [8, 8, 0, 1]
+      ],
+      "flattenInheritedTransform": false
+    }
+  ],
+  "objectPaintInvalidations": [
+    {
+      "object": "LayoutView #document",
+      "reason": "geometry"
+    },
+    {
+      "object": "VerticalScrollbar",
+      "reason": "scroll control"
+    },
+    {
+      "object": "LayoutView #document",
+      "reason": "style change"
+    },
+    {
+      "object": "LayoutBlockFlow BODY",
+      "reason": "geometry"
+    },
+    {
+      "object": "RootInlineBox",
+      "reason": "geometry"
+    },
+    {
+      "object": "LayoutText #text",
+      "reason": "geometry"
+    },
+    {
+      "object": "InlineTextBox 'test1'",
+      "reason": "geometry"
+    }
+  ]
+}
+
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v175/paint/invalidation/compositing/remove-squashed-layer-plus-move-expected.txt b/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v175/paint/invalidation/compositing/remove-squashed-layer-plus-move-expected.txt
new file mode 100644
index 0000000..6832468a
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v175/paint/invalidation/compositing/remove-squashed-layer-plus-move-expected.txt
@@ -0,0 +1,80 @@
+{
+  "layers": [
+    {
+      "name": "LayoutView #document",
+      "bounds": [1418, 1008],
+      "contentsOpaque": true,
+      "backgroundColor": "#FFFFFF"
+    },
+    {
+      "name": "Squashing Containment Layer",
+      "drawsContent": false
+    },
+    {
+      "name": "LayoutBlockFlow (positioned) DIV",
+      "bounds": [1000, 1000],
+      "drawsContent": false,
+      "transform": 1
+    },
+    {
+      "name": "Squashing Layer (first squashed layer: LayoutBlockFlow (relative positioned) DIV class='mv-tile')",
+      "position": [8, 8],
+      "bounds": [1000, 105],
+      "paintInvalidations": [
+        {
+          "object": "LayoutBlockFlow (relative positioned) DIV class='mv-tile'",
+          "rect": [0, 55, 100, 50],
+          "reason": "geometry"
+        },
+        {
+          "object": "LayoutBlockFlow (relative positioned) DIV class='mv-tile'",
+          "rect": [0, 0, 100, 50],
+          "reason": "geometry"
+        }
+      ]
+    }
+  ],
+  "transforms": [
+    {
+      "id": 1,
+      "transform": [
+        [1, 0, 0, 0],
+        [0, 1, 0, 0],
+        [0, 0, 1, 0],
+        [8, 8, 0, 1]
+      ],
+      "flattenInheritedTransform": false
+    }
+  ],
+  "objectPaintInvalidations": [
+    {
+      "object": "LayoutBlockFlow DIV id='container'",
+      "reason": "geometry"
+    },
+    {
+      "object": "RootInlineBox",
+      "reason": "geometry"
+    },
+    {
+      "object": "LayoutBlockFlow (relative positioned) DIV class='mv-tile'",
+      "reason": "geometry"
+    },
+    {
+      "object": "LayoutBlockFlow (anonymous)",
+      "reason": "geometry"
+    },
+    {
+      "object": "RootInlineBox",
+      "reason": "geometry"
+    },
+    {
+      "object": "LayoutBlockFlow (relative positioned) DIV class='mv-tile'",
+      "reason": "compositing update"
+    },
+    {
+      "object": "LayoutText #text",
+      "reason": "geometry"
+    }
+  ]
+}
+
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v175/paint/invalidation/compositing/resize-squashing-layer-that-needs-full-repaint-expected.txt b/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v175/paint/invalidation/compositing/resize-squashing-layer-that-needs-full-repaint-expected.txt
new file mode 100644
index 0000000..7912896
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v175/paint/invalidation/compositing/resize-squashing-layer-that-needs-full-repaint-expected.txt
@@ -0,0 +1,56 @@
+{
+  "layers": [
+    {
+      "name": "LayoutView #document",
+      "bounds": [800, 600],
+      "contentsOpaque": true,
+      "backgroundColor": "#FFFFFF"
+    },
+    {
+      "name": "Squashing Containment Layer",
+      "drawsContent": false
+    },
+    {
+      "name": "LayoutBlockFlow DIV",
+      "bounds": [500, 500],
+      "drawsContent": false,
+      "transform": 1
+    },
+    {
+      "name": "Squashing Layer (first squashed layer: LayoutBlockFlow (positioned) DIV)",
+      "position": [55, 55],
+      "bounds": [500, 500],
+      "paintInvalidations": [
+        {
+          "object": "LayoutBlockFlow (positioned) DIV",
+          "rect": [55, 55, 500, 500],
+          "reason": "compositing update"
+        },
+        {
+          "object": "LayoutBlockFlow (positioned) DIV id='to-be-removed'",
+          "rect": [0, 0, 50, 50],
+          "reason": "disappeared"
+        }
+      ]
+    }
+  ],
+  "transforms": [
+    {
+      "id": 1,
+      "transform": [
+        [1, 0, 0, 0],
+        [0, 1, 0, 0],
+        [0, 0, 1, 0],
+        [8, 8, 0, 1]
+      ],
+      "flattenInheritedTransform": false
+    }
+  ],
+  "objectPaintInvalidations": [
+    {
+      "object": "LayoutBlockFlow (positioned) DIV",
+      "reason": "compositing update"
+    }
+  ]
+}
+
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v175/paint/invalidation/compositing/should-not-clip-composited-viewport-scrolling-layer-expected.txt b/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v175/paint/invalidation/compositing/should-not-clip-composited-viewport-scrolling-layer-expected.txt
deleted file mode 100644
index fd42f52c..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v175/paint/invalidation/compositing/should-not-clip-composited-viewport-scrolling-layer-expected.txt
+++ /dev/null
@@ -1,45 +0,0 @@
-{
-  "layers": [
-    {
-      "name": "LayoutView #document",
-      "bounds": [2008, 1516],
-      "contentsOpaque": true,
-      "backgroundColor": "#FFFFFF",
-      "paintInvalidations": [
-        {
-          "object": "LayoutView #document",
-          "rect": [0, 0, 2008, 1516],
-          "reason": "full"
-        },
-        {
-          "object": "LayoutBlockFlow DIV id='content'",
-          "rect": [8, 8, 2000, 1500],
-          "reason": "style change"
-        }
-      ],
-      "transform": 1
-    }
-  ],
-  "transforms": [
-    {
-      "id": 1,
-      "transform": [
-        [1, 0, 0, 0],
-        [0, 1, 0, 0],
-        [0, 0, 1, 0],
-        [-900, -700, 0, 1]
-      ]
-    }
-  ],
-  "objectPaintInvalidations": [
-    {
-      "object": "LayoutBlockFlow DIV id='content'",
-      "reason": "style change"
-    },
-    {
-      "object": "RootInlineBox",
-      "reason": "style change"
-    }
-  ]
-}
-
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v175/paint/invalidation/compositing/should-not-repaint-composited-descendants-expected.txt b/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v175/paint/invalidation/compositing/should-not-repaint-composited-descendants-expected.txt
new file mode 100644
index 0000000..62e6f4d0
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v175/paint/invalidation/compositing/should-not-repaint-composited-descendants-expected.txt
@@ -0,0 +1,55 @@
+{
+  "layers": [
+    {
+      "name": "LayoutView #document",
+      "bounds": [800, 600],
+      "contentsOpaque": true,
+      "backgroundColor": "#FFFFFF"
+    },
+    {
+      "name": "LayoutBlockFlow (positioned) DIV id='composited-box'",
+      "position": [38, 38],
+      "bounds": [20, 70],
+      "contentsOpaque": true,
+      "backfaceVisibility": "hidden",
+      "backgroundColor": "#008000",
+      "paintInvalidations": [
+        {
+          "object": "LayoutBlockFlow (positioned) DIV id='composited-box'",
+          "rect": [0, 0, 20, 70],
+          "reason": "full layer"
+        },
+        {
+          "object": "LayoutBlockFlow (positioned) DIV id='composited-box'",
+          "rect": [0, 0, 10, 60],
+          "reason": "full"
+        }
+      ]
+    },
+    {
+      "name": "Child Containment Layer",
+      "position": [38, 38],
+      "bounds": [90, 90],
+      "drawsContent": false
+    },
+    {
+      "name": "LayoutBlockFlow DIV class='composited child'",
+      "position": [8, 58],
+      "bounds": [50, 50],
+      "contentsOpaque": true,
+      "backfaceVisibility": "hidden",
+      "backgroundColor": "#008000"
+    }
+  ],
+  "objectPaintInvalidations": [
+    {
+      "object": "LayoutBlockFlow (positioned) DIV id='composited-box'",
+      "reason": "subtree"
+    },
+    {
+      "object": "LayoutBlockFlow DIV class='child'",
+      "reason": "subtree"
+    }
+  ]
+}
+
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v175/paint/invalidation/details-open-repaint-expected.txt b/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v175/paint/invalidation/details-open-repaint-expected.txt
index 033e571..11ead38 100644
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v175/paint/invalidation/details-open-repaint-expected.txt
+++ b/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v175/paint/invalidation/details-open-repaint-expected.txt
@@ -37,11 +37,11 @@
       "reason": "appeared"
     },
     {
-      "object": "LayoutBlockFlow DIV id='inner-editor'",
+      "object": "LayoutBlockFlow DIV",
       "reason": "appeared"
     },
     {
-      "object": "LayoutBlockFlow DIV id='inner-editor'",
+      "object": "LayoutBlockFlow DIV",
       "reason": "geometry"
     },
     {
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v175/paint/invalidation/fixed-and-absolute-position-scrolled-expected.txt b/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v175/paint/invalidation/fixed-and-absolute-position-scrolled-expected.txt
new file mode 100644
index 0000000..1e8b2001
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v175/paint/invalidation/fixed-and-absolute-position-scrolled-expected.txt
@@ -0,0 +1,49 @@
+{
+  "layers": [
+    {
+      "name": "LayoutView #document",
+      "bounds": [800, 2016],
+      "contentsOpaque": true,
+      "backgroundColor": "#FFFFFF",
+      "paintInvalidations": [
+        {
+          "object": "LayoutView #document",
+          "rect": [0, 2016, 800, 3792],
+          "reason": "incremental"
+        },
+        {
+          "object": "LayoutBlockFlow (positioned) DIV id='absoluteDiv' class='absolute green'",
+          "rect": [100, 700, 100, 100],
+          "reason": "appeared"
+        }
+      ],
+      "transform": 1
+    }
+  ],
+  "transforms": [
+    {
+      "id": 1,
+      "transform": [
+        [1, 0, 0, 0],
+        [0, 1, 0, 0],
+        [0, 0, 1, 0],
+        [0, -500, 0, 1]
+      ]
+    }
+  ],
+  "objectPaintInvalidations": [
+    {
+      "object": "LayoutView #document",
+      "reason": "incremental"
+    },
+    {
+      "object": "LayoutBlockFlow DIV id='container' class='relative'",
+      "reason": "geometry"
+    },
+    {
+      "object": "LayoutBlockFlow (positioned) DIV id='absoluteDiv' class='absolute green'",
+      "reason": "geometry"
+    }
+  ]
+}
+
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v175/paint/invalidation/fixed-img-src-change-after-scroll-expected.txt b/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v175/paint/invalidation/fixed-img-src-change-after-scroll-expected.txt
new file mode 100644
index 0000000..9d0b8d1e
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v175/paint/invalidation/fixed-img-src-change-after-scroll-expected.txt
@@ -0,0 +1,41 @@
+{
+  "layers": [
+    {
+      "name": "LayoutView #document",
+      "bounds": [785, 2016],
+      "contentsOpaque": true,
+      "backgroundColor": "#FFFFFF",
+      "paintInvalidations": [
+        {
+          "object": "LayoutImage (positioned) IMG id='img'",
+          "rect": [0, 1050, 100, 100],
+          "reason": "paint property change"
+        },
+        {
+          "object": "LayoutImage (positioned) IMG id='img'",
+          "rect": [0, 50, 100, 100],
+          "reason": "paint property change"
+        }
+      ],
+      "transform": 1
+    }
+  ],
+  "transforms": [
+    {
+      "id": 1,
+      "transform": [
+        [1, 0, 0, 0],
+        [0, 1, 0, 0],
+        [0, 0, 1, 0],
+        [0, -1000, 0, 1]
+      ]
+    }
+  ],
+  "objectPaintInvalidations": [
+    {
+      "object": "LayoutImage (positioned) IMG id='img'",
+      "reason": "subtree"
+    }
+  ]
+}
+
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v175/paint/invalidation/fixed-scale-expected.txt b/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v175/paint/invalidation/fixed-scale-expected.txt
new file mode 100644
index 0000000..38be990
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v175/paint/invalidation/fixed-scale-expected.txt
@@ -0,0 +1,41 @@
+{
+  "layers": [
+    {
+      "name": "LayoutView #document",
+      "bounds": [800, 2016],
+      "contentsOpaque": true,
+      "backgroundColor": "#FFFFFF",
+      "paintInvalidations": [
+        {
+          "object": "LayoutBlockFlow (positioned) DIV id='t' class='green translated'",
+          "rect": [100, 300, 100, 100],
+          "reason": "paint property change"
+        },
+        {
+          "object": "LayoutBlockFlow (positioned) DIV id='t' class='green'",
+          "rect": [125, 325, 50, 50],
+          "reason": "paint property change"
+        }
+      ],
+      "transform": 1
+    }
+  ],
+  "transforms": [
+    {
+      "id": 1,
+      "transform": [
+        [1, 0, 0, 0],
+        [0, 1, 0, 0],
+        [0, 0, 1, 0],
+        [0, -200, 0, 1]
+      ]
+    }
+  ],
+  "objectPaintInvalidations": [
+    {
+      "object": "LayoutBlockFlow (positioned) DIV id='t' class='green translated'",
+      "reason": "geometry"
+    }
+  ]
+}
+
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v175/paint/invalidation/fixed-table-cell-expected.txt b/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v175/paint/invalidation/fixed-table-cell-expected.txt
new file mode 100644
index 0000000..137c241
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v175/paint/invalidation/fixed-table-cell-expected.txt
@@ -0,0 +1,53 @@
+{
+  "layers": [
+    {
+      "name": "LayoutView #document",
+      "bounds": [800, 2016],
+      "contentsOpaque": true,
+      "backgroundColor": "#FFFFFF",
+      "paintInvalidations": [
+        {
+          "object": "LayoutTableCell TD id='moveMe'",
+          "rect": [200, 200, 100, 100],
+          "reason": "disappeared"
+        },
+        {
+          "object": "LayoutBlockFlow (positioned) TD id='moveMe' class='fixed'",
+          "rect": [50, 200, 100, 100],
+          "reason": "appeared"
+        }
+      ],
+      "transform": 1
+    }
+  ],
+  "transforms": [
+    {
+      "id": 1,
+      "transform": [
+        [1, 0, 0, 0],
+        [0, 1, 0, 0],
+        [0, 0, 1, 0],
+        [0, -100, 0, 1]
+      ]
+    }
+  ],
+  "objectPaintInvalidations": [
+    {
+      "object": "LayoutTable (positioned) TABLE",
+      "reason": "style change"
+    },
+    {
+      "object": "LayoutTableSection TBODY",
+      "reason": "geometry"
+    },
+    {
+      "object": "LayoutTableCell (anonymous)",
+      "reason": "appeared"
+    },
+    {
+      "object": "LayoutBlockFlow (positioned) TD id='moveMe' class='fixed'",
+      "reason": "appeared"
+    }
+  ]
+}
+
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v175/paint/invalidation/fixed-table-overflow-zindex-expected.txt b/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v175/paint/invalidation/fixed-table-overflow-zindex-expected.txt
new file mode 100644
index 0000000..ed956d98
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v175/paint/invalidation/fixed-table-overflow-zindex-expected.txt
@@ -0,0 +1,53 @@
+{
+  "layers": [
+    {
+      "name": "LayoutView #document",
+      "bounds": [800, 2016],
+      "contentsOpaque": true,
+      "backgroundColor": "#FFFFFF",
+      "paintInvalidations": [
+        {
+          "object": "LayoutBlockFlow (positioned) TD id='moveMe' class='fixed'",
+          "rect": [100, 100, 100, 100],
+          "reason": "appeared"
+        },
+        {
+          "object": "LayoutTableCell TD id='moveMe'",
+          "rect": [0, 100, 100, 100],
+          "reason": "disappeared"
+        }
+      ],
+      "transform": 1
+    }
+  ],
+  "transforms": [
+    {
+      "id": 1,
+      "transform": [
+        [1, 0, 0, 0],
+        [0, 1, 0, 0],
+        [0, 0, 1, 0],
+        [0, -100, 0, 1]
+      ]
+    }
+  ],
+  "objectPaintInvalidations": [
+    {
+      "object": "LayoutTable (positioned) TABLE",
+      "reason": "style change"
+    },
+    {
+      "object": "LayoutTableSection TBODY",
+      "reason": "geometry"
+    },
+    {
+      "object": "LayoutTableCell (anonymous)",
+      "reason": "appeared"
+    },
+    {
+      "object": "LayoutBlockFlow (positioned) TD id='moveMe' class='fixed'",
+      "reason": "appeared"
+    }
+  ]
+}
+
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v175/paint/invalidation/inline-style-change-in-scrolled-view-expected.txt b/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v175/paint/invalidation/inline-style-change-in-scrolled-view-expected.txt
new file mode 100644
index 0000000..1fac11b
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v175/paint/invalidation/inline-style-change-in-scrolled-view-expected.txt
@@ -0,0 +1,40 @@
+{
+  "layers": [
+    {
+      "name": "LayoutView #document",
+      "bounds": [2000, 2000],
+      "contentsOpaque": true,
+      "backgroundColor": "#FFFFFF",
+      "paintInvalidations": [
+        {
+          "object": "InlineTextBox 'Text Text Text Text Text Text Text Text Text Text Text Text Text'",
+          "rect": [0, 320, 412, 19],
+          "reason": "style change"
+        }
+      ],
+      "transform": 1
+    }
+  ],
+  "transforms": [
+    {
+      "id": 1,
+      "transform": [
+        [1, 0, 0, 0],
+        [0, 1, 0, 0],
+        [0, 0, 1, 0],
+        [-200, -200, 0, 1]
+      ]
+    }
+  ],
+  "objectPaintInvalidations": [
+    {
+      "object": "LayoutText #text",
+      "reason": "style change"
+    },
+    {
+      "object": "InlineTextBox 'Text Text Text Text Text Text Text Text Text Text Text Text Text'",
+      "reason": "style change"
+    }
+  ]
+}
+
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v175/paint/invalidation/invalidate-after-composited-scroll-of-window-expected.txt b/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v175/paint/invalidation/invalidate-after-composited-scroll-of-window-expected.txt
new file mode 100644
index 0000000..e6b4837
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v175/paint/invalidation/invalidate-after-composited-scroll-of-window-expected.txt
@@ -0,0 +1,41 @@
+{
+  "layers": [
+    {
+      "name": "LayoutView #document",
+      "bounds": [785, 4936],
+      "contentsOpaque": true,
+      "backgroundColor": "#FFFFFF",
+      "paintInvalidations": [
+        {
+          "object": "InlineTextBox 'Tests that invalidation of a div after scrolling invalidates just the div and no other area.'",
+          "rect": [8, 4908, 540, 19],
+          "reason": "appeared"
+        },
+        {
+          "object": "LayoutBlockFlow DIV id='target'",
+          "rect": [8, 2408, 100, 100],
+          "reason": "style change"
+        }
+      ],
+      "transform": 1
+    }
+  ],
+  "transforms": [
+    {
+      "id": 1,
+      "transform": [
+        [1, 0, 0, 0],
+        [0, 1, 0, 0],
+        [0, 0, 1, 0],
+        [0, -2350, 0, 1]
+      ]
+    }
+  ],
+  "objectPaintInvalidations": [
+    {
+      "object": "LayoutBlockFlow DIV id='target'",
+      "reason": "style change"
+    }
+  ]
+}
+
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v175/paint/invalidation/invalidate-caret-in-composited-scrolling-container-expected.txt b/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v175/paint/invalidation/invalidate-caret-in-composited-scrolling-container-expected.txt
index 431d408..a8b3aef5 100644
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v175/paint/invalidation/invalidate-caret-in-composited-scrolling-container-expected.txt
+++ b/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v175/paint/invalidation/invalidate-caret-in-composited-scrolling-container-expected.txt
@@ -31,7 +31,7 @@
       "reason": "subtree"
     },
     {
-      "object": "LayoutBlockFlow DIV id='inner-editor'",
+      "object": "LayoutBlockFlow DIV",
       "reason": "subtree"
     },
     {
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v175/paint/invalidation/invalidate-caret-in-non-composited-scrolling-container-expected.txt b/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v175/paint/invalidation/invalidate-caret-in-non-composited-scrolling-container-expected.txt
index 431d408..a8b3aef5 100644
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v175/paint/invalidation/invalidate-caret-in-non-composited-scrolling-container-expected.txt
+++ b/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v175/paint/invalidation/invalidate-caret-in-non-composited-scrolling-container-expected.txt
@@ -31,7 +31,7 @@
       "reason": "subtree"
     },
     {
-      "object": "LayoutBlockFlow DIV id='inner-editor'",
+      "object": "LayoutBlockFlow DIV",
       "reason": "subtree"
     },
     {
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v175/paint/invalidation/invalidation-after-opacity-change-subtree-expected.txt b/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v175/paint/invalidation/invalidation-after-opacity-change-subtree-expected.txt
new file mode 100644
index 0000000..23a8ed4
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v175/paint/invalidation/invalidation-after-opacity-change-subtree-expected.txt
@@ -0,0 +1,36 @@
+{
+  "layers": [
+    {
+      "name": "LayoutView #document",
+      "bounds": [785, 2350],
+      "contentsOpaque": true,
+      "backgroundColor": "#FFFFFF",
+      "paintInvalidations": [
+        {
+          "object": "LayoutBlockFlow (positioned) DIV id='absolute'",
+          "rect": [8, 2046, 774, 257],
+          "reason": "appeared"
+        }
+      ],
+      "transform": 1
+    }
+  ],
+  "transforms": [
+    {
+      "id": 1,
+      "transform": [
+        [1, 0, 0, 0],
+        [0, 1, 0, 0],
+        [0, 0, 1, 0],
+        [0, -1750, 0, 1]
+      ]
+    }
+  ],
+  "objectPaintInvalidations": [
+    {
+      "object": "LayoutBlockFlow DIV id='container'",
+      "reason": "style change"
+    }
+  ]
+}
+
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v175/paint/invalidation/invalidation-on-foreground-graphics-layer-expected.txt b/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v175/paint/invalidation/invalidation-on-foreground-graphics-layer-expected.txt
new file mode 100644
index 0000000..e557d84
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v175/paint/invalidation/invalidation-on-foreground-graphics-layer-expected.txt
@@ -0,0 +1,78 @@
+{
+  "layers": [
+    {
+      "name": "LayoutView #document",
+      "bounds": [800, 600],
+      "contentsOpaque": true,
+      "backgroundColor": "#FFFFFF"
+    },
+    {
+      "name": "LayoutBlockFlow DIV",
+      "position": [8, 8],
+      "bounds": [200, 200],
+      "contentsOpaque": true,
+      "backgroundColor": "#D3D3D3"
+    },
+    {
+      "name": "Scrolling Layer",
+      "position": [8, 8],
+      "bounds": [185, 185],
+      "drawsContent": false
+    },
+    {
+      "name": "Scrolling Contents Layer",
+      "position": [8, 8],
+      "bounds": [300, 300],
+      "backgroundColor": "#D3D3D3"
+    },
+    {
+      "name": "LayoutBlockFlow (relative positioned) DIV",
+      "position": [8, 8],
+      "bounds": [200, 200],
+      "contentsOpaque": true,
+      "backgroundColor": "#ADD8E6"
+    },
+    {
+      "name": "LayoutBlockFlow DIV (foreground) Layer",
+      "position": [8, 8],
+      "bounds": [300, 300],
+      "paintInvalidations": [
+        {
+          "object": "LayoutBlockFlow DIV id='target'",
+          "rect": [100, 100, 200, 200],
+          "reason": "style change"
+        }
+      ]
+    },
+    {
+      "name": "Overflow Controls Host Layer",
+      "position": [8, 8],
+      "bounds": [200, 200],
+      "drawsContent": false
+    },
+    {
+      "name": "Horizontal Scrollbar Layer",
+      "position": [8, 193],
+      "bounds": [185, 15],
+      "drawsContent": false
+    },
+    {
+      "name": "Vertical Scrollbar Layer",
+      "position": [193, 8],
+      "bounds": [15, 185],
+      "drawsContent": false
+    },
+    {
+      "name": "Scroll Corner Layer",
+      "position": [193, 193],
+      "bounds": [15, 15]
+    }
+  ],
+  "objectPaintInvalidations": [
+    {
+      "object": "LayoutBlockFlow DIV id='target'",
+      "reason": "style change"
+    }
+  ]
+}
+
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v175/paint/invalidation/multi-layout-one-frame-expected.txt b/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v175/paint/invalidation/multi-layout-one-frame-expected.txt
index 22f0d81..a7074c1 100644
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v175/paint/invalidation/multi-layout-one-frame-expected.txt
+++ b/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v175/paint/invalidation/multi-layout-one-frame-expected.txt
@@ -31,7 +31,7 @@
   ],
   "objectPaintInvalidations": [
     {
-      "object": "LayoutBlockFlow DIV id='inner-editor'",
+      "object": "LayoutBlockFlow DIV",
       "reason": "geometry"
     },
     {
@@ -47,7 +47,7 @@
       "reason": "full"
     },
     {
-      "object": "LayoutBlockFlow DIV id='inner-editor'",
+      "object": "LayoutBlockFlow DIV",
       "reason": "geometry"
     },
     {
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v175/paint/invalidation/multicol-resize-with-rule-expected.txt b/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v175/paint/invalidation/multicol-resize-with-rule-expected.txt
new file mode 100644
index 0000000..7f68e66c
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v175/paint/invalidation/multicol-resize-with-rule-expected.txt
@@ -0,0 +1,88 @@
+{
+  "layers": [
+    {
+      "name": "LayoutView #document",
+      "bounds": [800, 600],
+      "contentsOpaque": true,
+      "backgroundColor": "#FFFFFF",
+      "paintInvalidations": [
+        {
+          "object": "LayoutMultiColumnSet (anonymous)",
+          "rect": [8, 8, 600, 200],
+          "reason": "geometry"
+        }
+      ]
+    }
+  ],
+  "objectPaintInvalidations": [
+    {
+      "object": "LayoutMultiColumnFlowThread (anonymous)",
+      "reason": "geometry"
+    },
+    {
+      "object": "LayoutMultiColumnFlowThread (anonymous)",
+      "reason": "geometry"
+    },
+    {
+      "object": "LayoutMultiColumnFlowThread (anonymous)",
+      "reason": "geometry"
+    },
+    {
+      "object": "LayoutMultiColumnFlowThread (anonymous)",
+      "reason": "geometry"
+    },
+    {
+      "object": "LayoutMultiColumnFlowThread (anonymous)",
+      "reason": "geometry"
+    },
+    {
+      "object": "LayoutMultiColumnFlowThread (anonymous)",
+      "reason": "geometry"
+    },
+    {
+      "object": "LayoutMultiColumnFlowThread (anonymous)",
+      "reason": "geometry"
+    },
+    {
+      "object": "LayoutMultiColumnFlowThread (anonymous)",
+      "reason": "geometry"
+    },
+    {
+      "object": "LayoutBlockFlow DIV",
+      "reason": "geometry"
+    },
+    {
+      "object": "LayoutBlockFlow DIV",
+      "reason": "geometry"
+    },
+    {
+      "object": "LayoutBlockFlow DIV",
+      "reason": "geometry"
+    },
+    {
+      "object": "LayoutBlockFlow DIV",
+      "reason": "geometry"
+    },
+    {
+      "object": "LayoutBlockFlow DIV",
+      "reason": "geometry"
+    },
+    {
+      "object": "LayoutBlockFlow DIV",
+      "reason": "geometry"
+    },
+    {
+      "object": "LayoutBlockFlow DIV",
+      "reason": "geometry"
+    },
+    {
+      "object": "LayoutBlockFlow DIV",
+      "reason": "geometry"
+    },
+    {
+      "object": "LayoutMultiColumnSet (anonymous)",
+      "reason": "geometry"
+    }
+  ]
+}
+
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v175/paint/invalidation/multicol-with-abspos-in-relpos-expected.txt b/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v175/paint/invalidation/multicol-with-abspos-in-relpos-expected.txt
new file mode 100644
index 0000000..8047484
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v175/paint/invalidation/multicol-with-abspos-in-relpos-expected.txt
@@ -0,0 +1,36 @@
+{
+  "layers": [
+    {
+      "name": "LayoutView #document",
+      "bounds": [800, 600],
+      "contentsOpaque": true,
+      "backgroundColor": "#FFFFFF",
+      "paintInvalidations": [
+        {
+          "object": "LayoutBlockFlow (positioned) DIV id='target'",
+          "rect": [508, 28, 80, 20],
+          "reason": "appeared"
+        }
+      ]
+    }
+  ],
+  "objectPaintInvalidations": [
+    {
+      "object": "LayoutBlockFlow (positioned) DIV id='target'",
+      "reason": "style change"
+    },
+    {
+      "object": "RootInlineBox",
+      "reason": "style change"
+    },
+    {
+      "object": "LayoutText #text",
+      "reason": "style change"
+    },
+    {
+      "object": "InlineTextBox 'PASS'",
+      "reason": "style change"
+    }
+  ]
+}
+
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v175/paint/invalidation/multicol-with-relpos-expected.txt b/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v175/paint/invalidation/multicol-with-relpos-expected.txt
new file mode 100644
index 0000000..42721fa
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v175/paint/invalidation/multicol-with-relpos-expected.txt
@@ -0,0 +1,24 @@
+{
+  "layers": [
+    {
+      "name": "LayoutView #document",
+      "bounds": [800, 600],
+      "contentsOpaque": true,
+      "backgroundColor": "#FFFFFF",
+      "paintInvalidations": [
+        {
+          "object": "LayoutBlockFlow (relative positioned) DIV id='target'",
+          "rect": [508, 28, 150, 20],
+          "reason": "appeared"
+        }
+      ]
+    }
+  ],
+  "objectPaintInvalidations": [
+    {
+      "object": "LayoutBlockFlow (relative positioned) DIV id='target'",
+      "reason": "style change"
+    }
+  ]
+}
+
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v175/paint/invalidation/overflow-scroll-local-background-text-color-change-expected.txt b/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v175/paint/invalidation/overflow-scroll-local-background-text-color-change-expected.txt
new file mode 100644
index 0000000..989a1098
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v175/paint/invalidation/overflow-scroll-local-background-text-color-change-expected.txt
@@ -0,0 +1,102 @@
+{
+  "layers": [
+    {
+      "name": "LayoutView #document",
+      "bounds": [800, 600],
+      "contentsOpaque": true,
+      "backgroundColor": "#FFFFFF"
+    },
+    {
+      "name": "LayoutBlockFlow DIV id='scroller'",
+      "position": [8, 8],
+      "bounds": [200, 200],
+      "backgroundColor": "#0000FF"
+    },
+    {
+      "name": "Scrolling Layer",
+      "position": [8, 8],
+      "bounds": [185, 185],
+      "drawsContent": false
+    },
+    {
+      "name": "Scrolling Contents Layer",
+      "position": [8, 8],
+      "bounds": [185, 552],
+      "contentsOpaque": true,
+      "backgroundColor": "#0000FF",
+      "paintInvalidations": [
+        {
+          "object": "Scrolling Contents Layer",
+          "rect": [0, 0, 185, 552],
+          "reason": "background on scrolling contents layer"
+        }
+      ],
+      "transform": 1
+    },
+    {
+      "name": "Overflow Controls Host Layer",
+      "position": [8, 8],
+      "bounds": [200, 200],
+      "drawsContent": false
+    },
+    {
+      "name": "Horizontal Scrollbar Layer",
+      "position": [8, 193],
+      "bounds": [185, 15],
+      "drawsContent": false,
+      "paintInvalidations": [
+        {
+          "object": "Horizontal Scrollbar Layer",
+          "rect": [0, 0, 185, 15],
+          "reason": "full"
+        }
+      ]
+    },
+    {
+      "name": "Vertical Scrollbar Layer",
+      "position": [193, 8],
+      "bounds": [15, 185],
+      "drawsContent": false,
+      "paintInvalidations": [
+        {
+          "object": "Vertical Scrollbar Layer",
+          "rect": [0, 0, 15, 185],
+          "reason": "full"
+        },
+        {
+          "object": "Vertical Scrollbar Layer",
+          "rect": [0, 0, 15, 185],
+          "reason": "full"
+        }
+      ]
+    },
+    {
+      "name": "Scroll Corner Layer",
+      "position": [193, 193],
+      "bounds": [15, 15]
+    }
+  ],
+  "transforms": [
+    {
+      "id": 1,
+      "transform": [
+        [1, 0, 0, 0],
+        [0, 1, 0, 0],
+        [0, 0, 1, 0],
+        [0, -367, 0, 1]
+      ],
+      "flattenInheritedTransform": false
+    }
+  ],
+  "objectPaintInvalidations": [
+    {
+      "object": "Scrolling Contents Layer",
+      "reason": "background on scrolling contents layer"
+    },
+    {
+      "object": "LayoutBlockFlow DIV id='scroller'",
+      "reason": "style change"
+    }
+  ]
+}
+
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v175/paint/invalidation/repaint-subrect-grid-expected.txt b/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v175/paint/invalidation/repaint-subrect-grid-expected.txt
new file mode 100644
index 0000000..2233cf0e
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v175/paint/invalidation/repaint-subrect-grid-expected.txt
@@ -0,0 +1,159 @@
+{
+  "layers": [
+    {
+      "name": "LayoutView #document",
+      "bounds": [800, 600],
+      "contentsOpaque": true,
+      "backgroundColor": "#FFFFFF",
+      "paintInvalidations": [
+        {
+          "object": "LayoutBlockFlow (positioned) DIV id='mask'",
+          "rect": [45, 18, 20, 19],
+          "reason": "geometry"
+        },
+        {
+          "object": "LayoutBlockFlow (positioned) DIV id='mask'",
+          "rect": [45, 18, 20, 19],
+          "reason": "geometry"
+        },
+        {
+          "object": "LayoutBlockFlow (positioned) DIV id='mask'",
+          "rect": [-10, 18, 20, 19],
+          "reason": "geometry"
+        },
+        {
+          "object": "LayoutBlockFlow (positioned) DIV id='mask'",
+          "rect": [-10, 18, 20, 19],
+          "reason": "geometry"
+        },
+        {
+          "object": "LayoutBlockFlow (positioned) DIV id='mask'",
+          "rect": [36, 36, 19, 19],
+          "reason": "geometry"
+        },
+        {
+          "object": "LayoutBlockFlow (positioned) DIV id='mask'",
+          "rect": [36, 36, 19, 19],
+          "reason": "disappeared"
+        },
+        {
+          "object": "LayoutBlockFlow (positioned) DIV id='mask'",
+          "rect": [36, 0, 19, 19],
+          "reason": "geometry"
+        },
+        {
+          "object": "LayoutBlockFlow (positioned) DIV id='mask'",
+          "rect": [36, 0, 19, 19],
+          "reason": "geometry"
+        },
+        {
+          "object": "LayoutBlockFlow (positioned) DIV id='mask'",
+          "rect": [27, 18, 19, 19],
+          "reason": "geometry"
+        },
+        {
+          "object": "LayoutBlockFlow (positioned) DIV id='mask'",
+          "rect": [27, 18, 19, 19],
+          "reason": "geometry"
+        },
+        {
+          "object": "LayoutBlockFlow (positioned) DIV id='mask'",
+          "rect": [18, 36, 19, 19],
+          "reason": "geometry"
+        },
+        {
+          "object": "LayoutBlockFlow (positioned) DIV id='mask'",
+          "rect": [18, 36, 19, 19],
+          "reason": "geometry"
+        },
+        {
+          "object": "LayoutBlockFlow (positioned) DIV id='mask'",
+          "rect": [18, 0, 19, 19],
+          "reason": "geometry"
+        },
+        {
+          "object": "LayoutBlockFlow (positioned) DIV id='mask'",
+          "rect": [18, 0, 19, 19],
+          "reason": "geometry"
+        },
+        {
+          "object": "LayoutBlockFlow (positioned) DIV id='mask'",
+          "rect": [9, 18, 19, 19],
+          "reason": "geometry"
+        },
+        {
+          "object": "LayoutBlockFlow (positioned) DIV id='mask'",
+          "rect": [9, 18, 19, 19],
+          "reason": "geometry"
+        },
+        {
+          "object": "LayoutBlockFlow (positioned) DIV id='mask'",
+          "rect": [0, 36, 19, 19],
+          "reason": "geometry"
+        },
+        {
+          "object": "LayoutBlockFlow (positioned) DIV id='mask'",
+          "rect": [0, 36, 19, 19],
+          "reason": "geometry"
+        },
+        {
+          "object": "LayoutBlockFlow (positioned) DIV id='mask'",
+          "rect": [0, 0, 19, 19],
+          "reason": "geometry"
+        },
+        {
+          "object": "LayoutBlockFlow (positioned) DIV id='mask'",
+          "rect": [0, 0, 19, 19],
+          "reason": "appeared"
+        }
+      ]
+    }
+  ],
+  "objectPaintInvalidations": [
+    {
+      "object": "LayoutBlockFlow (positioned) DIV id='mask'",
+      "reason": "geometry"
+    },
+    {
+      "object": "LayoutBlockFlow (positioned) DIV id='mask'",
+      "reason": "geometry"
+    },
+    {
+      "object": "LayoutBlockFlow (positioned) DIV id='mask'",
+      "reason": "geometry"
+    },
+    {
+      "object": "LayoutBlockFlow (positioned) DIV id='mask'",
+      "reason": "geometry"
+    },
+    {
+      "object": "LayoutBlockFlow (positioned) DIV id='mask'",
+      "reason": "geometry"
+    },
+    {
+      "object": "LayoutBlockFlow (positioned) DIV id='mask'",
+      "reason": "geometry"
+    },
+    {
+      "object": "LayoutBlockFlow (positioned) DIV id='mask'",
+      "reason": "geometry"
+    },
+    {
+      "object": "LayoutBlockFlow (positioned) DIV id='mask'",
+      "reason": "geometry"
+    },
+    {
+      "object": "LayoutBlockFlow (positioned) DIV id='mask'",
+      "reason": "geometry"
+    },
+    {
+      "object": "LayoutBlockFlow (positioned) DIV id='mask'",
+      "reason": "geometry"
+    },
+    {
+      "object": "LayoutBlockFlow (positioned) DIV id='mask'",
+      "reason": "geometry"
+    }
+  ]
+}
+
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v175/paint/invalidation/scroll-absolute-layer-with-reflection-expected.txt b/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v175/paint/invalidation/scroll-absolute-layer-with-reflection-expected.txt
new file mode 100644
index 0000000..2d95a32
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v175/paint/invalidation/scroll-absolute-layer-with-reflection-expected.txt
@@ -0,0 +1,53 @@
+{
+  "layers": [
+    {
+      "name": "LayoutView #document",
+      "bounds": [800, 2016],
+      "contentsOpaque": true,
+      "backgroundColor": "#FFFFFF",
+      "paintInvalidations": [
+        {
+          "object": "LayoutBlockFlow (positioned) DIV class='absolute red'",
+          "rect": [250, 230, 100, 100],
+          "reason": "disappeared"
+        },
+        {
+          "object": "LayoutBlockFlow (relative positioned) DIV class='relative reflected'",
+          "rect": [250, 230, 100, 100],
+          "reason": "appeared"
+        }
+      ],
+      "transform": 1
+    }
+  ],
+  "transforms": [
+    {
+      "id": 1,
+      "transform": [
+        [1, 0, 0, 0],
+        [0, 1, 0, 0],
+        [0, 0, 1, 0],
+        [0, -180, 0, 1]
+      ]
+    }
+  ],
+  "objectPaintInvalidations": [
+    {
+      "object": "LayoutBlockFlow (positioned) DIV id='moveMe' class='absolute clipped'",
+      "reason": "subtree"
+    },
+    {
+      "object": "LayoutBlockFlow (relative positioned) DIV class='relative reflected'",
+      "reason": "subtree"
+    },
+    {
+      "object": "LayoutBlockFlow DIV class='green'",
+      "reason": "subtree"
+    },
+    {
+      "object": "LayoutBlockFlow (positioned) DIV class='absolute red'",
+      "reason": "subtree"
+    }
+  ]
+}
+
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v175/paint/invalidation/scroll-fixed-layer-with-no-visible-content-expected.txt b/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v175/paint/invalidation/scroll-fixed-layer-with-no-visible-content-expected.txt
new file mode 100644
index 0000000..b8b35d1
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v175/paint/invalidation/scroll-fixed-layer-with-no-visible-content-expected.txt
@@ -0,0 +1,40 @@
+{
+  "layers": [
+    {
+      "name": "LayoutView #document",
+      "bounds": [800, 2016],
+      "contentsOpaque": true,
+      "backgroundColor": "#FFFFFF",
+      "paintInvalidations": [
+        {
+          "object": "LayoutBlockFlow (positioned) DIV class='absolute green'",
+          "rect": [100, 1150, 100, 100],
+          "reason": "appeared"
+        }
+      ],
+      "transform": 1
+    }
+  ],
+  "transforms": [
+    {
+      "id": 1,
+      "transform": [
+        [1, 0, 0, 0],
+        [0, 1, 0, 0],
+        [0, 0, 1, 0],
+        [0, -1000, 0, 1]
+      ]
+    }
+  ],
+  "objectPaintInvalidations": [
+    {
+      "object": "LayoutBlockFlow (positioned) DIV id='moveMe' class='fixed clipped'",
+      "reason": "subtree"
+    },
+    {
+      "object": "LayoutBlockFlow (positioned) DIV class='absolute green'",
+      "reason": "subtree"
+    }
+  ]
+}
+
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v175/paint/invalidation/scroll-fixed-layer-with-transformed-parent-layer-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v175/paint/invalidation/scroll-fixed-layer-with-transformed-parent-layer-expected.png
new file mode 100644
index 0000000..d70e46c
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v175/paint/invalidation/scroll-fixed-layer-with-transformed-parent-layer-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v175/paint/invalidation/scroll-fixed-layer-with-transformed-parent-layer-expected.txt b/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v175/paint/invalidation/scroll-fixed-layer-with-transformed-parent-layer-expected.txt
new file mode 100644
index 0000000..8f43d3f
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v175/paint/invalidation/scroll-fixed-layer-with-transformed-parent-layer-expected.txt
@@ -0,0 +1,49 @@
+{
+  "layers": [
+    {
+      "name": "LayoutView #document",
+      "bounds": [800, 2016],
+      "contentsOpaque": true,
+      "backgroundColor": "#FFFFFF",
+      "paintInvalidations": [
+        {
+          "object": "LayoutBlockFlow (positioned) DIV class='absolute green'",
+          "rect": [93, 234, 142, 143],
+          "reason": "appeared"
+        },
+        {
+          "object": "LayoutBlockFlow (positioned) DIV class='absolute red'",
+          "rect": [93, 234, 142, 143],
+          "reason": "disappeared"
+        }
+      ],
+      "transform": 1
+    }
+  ],
+  "transforms": [
+    {
+      "id": 1,
+      "transform": [
+        [1, 0, 0, 0],
+        [0, 1, 0, 0],
+        [0, 0, 1, 0],
+        [0, -180, 0, 1]
+      ]
+    }
+  ],
+  "objectPaintInvalidations": [
+    {
+      "object": "LayoutBlockFlow (positioned) DIV id='moveMe' class='fixed clipped'",
+      "reason": "subtree"
+    },
+    {
+      "object": "LayoutBlockFlow (positioned) DIV class='absolute green'",
+      "reason": "subtree"
+    },
+    {
+      "object": "LayoutBlockFlow (positioned) DIV class='absolute red'",
+      "reason": "subtree"
+    }
+  ]
+}
+
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v175/paint/invalidation/scroll-in-fixed-layer-expected.txt b/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v175/paint/invalidation/scroll-in-fixed-layer-expected.txt
new file mode 100644
index 0000000..efd0c0e2
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v175/paint/invalidation/scroll-in-fixed-layer-expected.txt
@@ -0,0 +1,44 @@
+{
+  "layers": [
+    {
+      "name": "LayoutView #document",
+      "bounds": [800, 2016],
+      "contentsOpaque": true,
+      "backgroundColor": "#FFFFFF",
+      "paintInvalidations": [
+        {
+          "object": "LayoutBlockFlow (positioned) DIV class='absolute green'",
+          "rect": [100, 1150, 100, 100],
+          "reason": "appeared"
+        }
+      ],
+      "transform": 1
+    }
+  ],
+  "transforms": [
+    {
+      "id": 1,
+      "transform": [
+        [1, 0, 0, 0],
+        [0, 1, 0, 0],
+        [0, 0, 1, 0],
+        [0, -1000, 0, 1]
+      ]
+    }
+  ],
+  "objectPaintInvalidations": [
+    {
+      "object": "LayoutBlockFlow (positioned) DIV id='moveMe' class='fixed clipped'",
+      "reason": "subtree"
+    },
+    {
+      "object": "LayoutBlockFlow (positioned) DIV class='absolute green'",
+      "reason": "subtree"
+    },
+    {
+      "object": "LayoutBlockFlow (positioned) DIV class='absolute red'",
+      "reason": "subtree"
+    }
+  ]
+}
+
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v175/paint/invalidation/scroll-in-transformed-layer-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v175/paint/invalidation/scroll-in-transformed-layer-expected.png
new file mode 100644
index 0000000..53f8671
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v175/paint/invalidation/scroll-in-transformed-layer-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v175/paint/invalidation/scroll-in-transformed-layer-expected.txt b/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v175/paint/invalidation/scroll-in-transformed-layer-expected.txt
new file mode 100644
index 0000000..a11484a
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v175/paint/invalidation/scroll-in-transformed-layer-expected.txt
@@ -0,0 +1,37 @@
+{
+  "layers": [
+    {
+      "name": "LayoutView #document",
+      "bounds": [800, 2016],
+      "contentsOpaque": true,
+      "backgroundColor": "#FFFFFF",
+      "paintInvalidations": [
+        {
+          "object": "LayoutBlockFlow (positioned) DIV class='absolute green'",
+          "rect": [79, 129, 142, 142],
+          "reason": "appeared"
+        },
+        {
+          "object": "LayoutBlockFlow (positioned) DIV class='absolute red'",
+          "rect": [100, 150, 100, 100],
+          "reason": "disappeared"
+        }
+      ]
+    }
+  ],
+  "objectPaintInvalidations": [
+    {
+      "object": "LayoutBlockFlow (positioned) DIV id='moveMe' class='absolute clipped rotated'",
+      "reason": "subtree"
+    },
+    {
+      "object": "LayoutBlockFlow (positioned) DIV class='absolute green'",
+      "reason": "subtree"
+    },
+    {
+      "object": "LayoutBlockFlow (positioned) DIV class='absolute red'",
+      "reason": "subtree"
+    }
+  ]
+}
+
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v175/paint/invalidation/scroll-relative-table-inside-table-cell-expected.txt b/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v175/paint/invalidation/scroll-relative-table-inside-table-cell-expected.txt
new file mode 100644
index 0000000..976b528
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v175/paint/invalidation/scroll-relative-table-inside-table-cell-expected.txt
@@ -0,0 +1,68 @@
+{
+  "layers": [
+    {
+      "name": "LayoutView #document",
+      "bounds": [1566, 1781],
+      "contentsOpaque": true,
+      "backgroundColor": "#FFFFFF",
+      "paintInvalidations": [
+        {
+          "object": "LayoutTableCell (relative positioned) TD id='cellToScroll' class='relative'",
+          "rect": [1112, 1312, 454, 469],
+          "reason": "subtree"
+        },
+        {
+          "object": "LayoutTableCell (relative positioned) TD id='cellToScroll' class='relative'",
+          "rect": [1112, 1312, 454, 469],
+          "reason": "subtree"
+        },
+        {
+          "object": "LayoutBlockFlow (positioned) DIV class='absolute green'",
+          "rect": [1114, 1314, 435, 450],
+          "reason": "appeared"
+        },
+        {
+          "object": "LayoutBlockFlow (relative positioned) DIV class='relative red'",
+          "rect": [1114, 1314, 435, 450],
+          "reason": "disappeared"
+        },
+        {
+          "object": "HorizontalScrollbar",
+          "rect": [1114, 1764, 435, 15],
+          "reason": "scroll control"
+        }
+      ],
+      "transform": 1
+    }
+  ],
+  "transforms": [
+    {
+      "id": 1,
+      "transform": [
+        [1, 0, 0, 0],
+        [0, 1, 0, 0],
+        [0, 0, 1, 0],
+        [-766, -1181, 0, 1]
+      ]
+    }
+  ],
+  "objectPaintInvalidations": [
+    {
+      "object": "LayoutTableCell (relative positioned) TD id='cellToScroll' class='relative'",
+      "reason": "subtree"
+    },
+    {
+      "object": "HorizontalScrollbar",
+      "reason": "scroll control"
+    },
+    {
+      "object": "LayoutBlockFlow (relative positioned) DIV class='relative red'",
+      "reason": "subtree"
+    },
+    {
+      "object": "LayoutBlockFlow (positioned) DIV class='absolute green'",
+      "reason": "subtree"
+    }
+  ]
+}
+
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v175/paint/invalidation/scroll-with-transformed-parent-layer-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v175/paint/invalidation/scroll-with-transformed-parent-layer-expected.png
new file mode 100644
index 0000000..53f8671
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v175/paint/invalidation/scroll-with-transformed-parent-layer-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v175/paint/invalidation/scroll-with-transformed-parent-layer-expected.txt b/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v175/paint/invalidation/scroll-with-transformed-parent-layer-expected.txt
new file mode 100644
index 0000000..4ea7439
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v175/paint/invalidation/scroll-with-transformed-parent-layer-expected.txt
@@ -0,0 +1,37 @@
+{
+  "layers": [
+    {
+      "name": "LayoutView #document",
+      "bounds": [800, 2016],
+      "contentsOpaque": true,
+      "backgroundColor": "#FFFFFF",
+      "paintInvalidations": [
+        {
+          "object": "LayoutBlockFlow (positioned) DIV class='absolute green'",
+          "rect": [79, 129, 142, 142],
+          "reason": "appeared"
+        },
+        {
+          "object": "LayoutBlockFlow (positioned) DIV class='absolute red'",
+          "rect": [79, 129, 142, 142],
+          "reason": "disappeared"
+        }
+      ]
+    }
+  ],
+  "objectPaintInvalidations": [
+    {
+      "object": "LayoutBlockFlow (positioned) DIV id='moveMe' class='absolute clipped'",
+      "reason": "subtree"
+    },
+    {
+      "object": "LayoutBlockFlow (positioned) DIV class='absolute green'",
+      "reason": "subtree"
+    },
+    {
+      "object": "LayoutBlockFlow (positioned) DIV class='absolute red'",
+      "reason": "subtree"
+    }
+  ]
+}
+
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v175/paint/invalidation/search-field-cancel-expected.txt b/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v175/paint/invalidation/search-field-cancel-expected.txt
index f8caeb14..8f1e97c 100644
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v175/paint/invalidation/search-field-cancel-expected.txt
+++ b/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v175/paint/invalidation/search-field-cancel-expected.txt
@@ -7,7 +7,7 @@
       "backgroundColor": "#FFFFFF",
       "paintInvalidations": [
         {
-          "object": "LayoutBlockFlow DIV id='inner-editor'",
+          "object": "LayoutBlockFlow DIV",
           "rect": [11, 47, 58, 16],
           "reason": "appeared"
         }
@@ -16,7 +16,7 @@
   ],
   "objectPaintInvalidations": [
     {
-      "object": "LayoutBlockFlow DIV id='inner-editor'",
+      "object": "LayoutBlockFlow DIV",
       "reason": "geometry"
     },
     {
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v175/paint/invalidation/selection/selection-in-composited-scrolling-container-expected.txt b/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v175/paint/invalidation/selection/selection-in-composited-scrolling-container-expected.txt
index 8b081b8..4d3f64b 100644
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v175/paint/invalidation/selection/selection-in-composited-scrolling-container-expected.txt
+++ b/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v175/paint/invalidation/selection/selection-in-composited-scrolling-container-expected.txt
@@ -12,12 +12,12 @@
           "reason": "subtree"
         },
         {
-          "object": "LayoutBlockFlow DIV id='inner-editor'",
+          "object": "LayoutBlockFlow DIV",
           "rect": [10, 11, 60, 16],
           "reason": "paint property change"
         },
         {
-          "object": "LayoutBlockFlow DIV id='inner-editor'",
+          "object": "LayoutBlockFlow DIV",
           "rect": [10, 11, 59, 16],
           "reason": "paint property change"
         }
@@ -30,7 +30,7 @@
       "reason": "subtree"
     },
     {
-      "object": "LayoutBlockFlow DIV id='inner-editor'",
+      "object": "LayoutBlockFlow DIV",
       "reason": "subtree"
     },
     {
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v175/paint/invalidation/selection/selection-in-non-composited-scrolling-container-expected.txt b/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v175/paint/invalidation/selection/selection-in-non-composited-scrolling-container-expected.txt
index 38d8989a..77ff293 100644
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v175/paint/invalidation/selection/selection-in-non-composited-scrolling-container-expected.txt
+++ b/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v175/paint/invalidation/selection/selection-in-non-composited-scrolling-container-expected.txt
@@ -12,7 +12,7 @@
           "reason": "subtree"
         },
         {
-          "object": "LayoutBlockFlow DIV id='inner-editor'",
+          "object": "LayoutBlockFlow DIV",
           "rect": [10, 11, 60, 16],
           "reason": "paint property change"
         }
@@ -25,7 +25,7 @@
       "reason": "subtree"
     },
     {
-      "object": "LayoutBlockFlow DIV id='inner-editor'",
+      "object": "LayoutBlockFlow DIV",
       "reason": "subtree"
     },
     {
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v175/paint/invalidation/selection/selection-within-composited-scroller-expected.txt b/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v175/paint/invalidation/selection/selection-within-composited-scroller-expected.txt
index 0dfd118..a158e806 100644
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v175/paint/invalidation/selection/selection-within-composited-scroller-expected.txt
+++ b/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v175/paint/invalidation/selection/selection-within-composited-scroller-expected.txt
@@ -31,308 +31,6 @@
           "reason": "selection"
         }
       ],
-      "underPaintInvalidations": [
-        {
-          "x": 8,
-          "y": 168,
-          "oldPixel": "#ADD8E6",
-          "newPixel": "#222BFA"
-        },
-        {
-          "x": 9,
-          "y": 168,
-          "oldPixel": "#ADD8E6",
-          "newPixel": "#222BFA"
-        },
-        {
-          "x": 10,
-          "y": 168,
-          "oldPixel": "#ADD8E6",
-          "newPixel": "#222BFA"
-        },
-        {
-          "x": 11,
-          "y": 168,
-          "oldPixel": "#ADD8E6",
-          "newPixel": "#222BFA"
-        },
-        {
-          "x": 12,
-          "y": 168,
-          "oldPixel": "#ADD8E6",
-          "newPixel": "#222BFA"
-        },
-        {
-          "x": 13,
-          "y": 168,
-          "oldPixel": "#ADD8E6",
-          "newPixel": "#222BFA"
-        },
-        {
-          "x": 14,
-          "y": 168,
-          "oldPixel": "#ADD8E6",
-          "newPixel": "#222BFA"
-        },
-        {
-          "x": 15,
-          "y": 168,
-          "oldPixel": "#ADD8E6",
-          "newPixel": "#222BFA"
-        },
-        {
-          "x": 16,
-          "y": 168,
-          "oldPixel": "#ADD8E6",
-          "newPixel": "#222BFA"
-        },
-        {
-          "x": 17,
-          "y": 168,
-          "oldPixel": "#ADD8E6",
-          "newPixel": "#222BFA"
-        },
-        {
-          "x": 18,
-          "y": 168,
-          "oldPixel": "#ADD8E6",
-          "newPixel": "#222BFA"
-        },
-        {
-          "x": 19,
-          "y": 168,
-          "oldPixel": "#ADD8E6",
-          "newPixel": "#222BFA"
-        },
-        {
-          "x": 20,
-          "y": 168,
-          "oldPixel": "#ADD8E6",
-          "newPixel": "#222BFA"
-        },
-        {
-          "x": 21,
-          "y": 168,
-          "oldPixel": "#ADD8E6",
-          "newPixel": "#222BFA"
-        },
-        {
-          "x": 22,
-          "y": 168,
-          "oldPixel": "#ADD8E6",
-          "newPixel": "#222BFA"
-        },
-        {
-          "x": 23,
-          "y": 168,
-          "oldPixel": "#ADD8E6",
-          "newPixel": "#222BFA"
-        },
-        {
-          "x": 24,
-          "y": 168,
-          "oldPixel": "#ADD8E6",
-          "newPixel": "#222BFA"
-        },
-        {
-          "x": 25,
-          "y": 168,
-          "oldPixel": "#ADD8E6",
-          "newPixel": "#222BFA"
-        },
-        {
-          "x": 26,
-          "y": 168,
-          "oldPixel": "#ADD8E6",
-          "newPixel": "#222BFA"
-        },
-        {
-          "x": 27,
-          "y": 168,
-          "oldPixel": "#ADD8E6",
-          "newPixel": "#222BFA"
-        },
-        {
-          "x": 28,
-          "y": 168,
-          "oldPixel": "#ADD8E6",
-          "newPixel": "#222BFA"
-        },
-        {
-          "x": 8,
-          "y": 169,
-          "oldPixel": "#ADD8E6",
-          "newPixel": "#222BFA"
-        },
-        {
-          "x": 9,
-          "y": 169,
-          "oldPixel": "#ADD8E6",
-          "newPixel": "#222BFA"
-        },
-        {
-          "x": 10,
-          "y": 169,
-          "oldPixel": "#ADD8E6",
-          "newPixel": "#222BFA"
-        },
-        {
-          "x": 11,
-          "y": 169,
-          "oldPixel": "#ADD8E6",
-          "newPixel": "#222BFA"
-        },
-        {
-          "x": 12,
-          "y": 169,
-          "oldPixel": "#ADD8E6",
-          "newPixel": "#222BFA"
-        },
-        {
-          "x": 13,
-          "y": 169,
-          "oldPixel": "#ADD8E6",
-          "newPixel": "#222BFA"
-        },
-        {
-          "x": 14,
-          "y": 169,
-          "oldPixel": "#ADD8E6",
-          "newPixel": "#222BFA"
-        },
-        {
-          "x": 15,
-          "y": 169,
-          "oldPixel": "#ADD8E6",
-          "newPixel": "#222BFA"
-        },
-        {
-          "x": 16,
-          "y": 169,
-          "oldPixel": "#ADD8E6",
-          "newPixel": "#222BFA"
-        },
-        {
-          "x": 17,
-          "y": 169,
-          "oldPixel": "#ADD8E6",
-          "newPixel": "#222BFA"
-        },
-        {
-          "x": 18,
-          "y": 169,
-          "oldPixel": "#ADD8E6",
-          "newPixel": "#222BFA"
-        },
-        {
-          "x": 19,
-          "y": 169,
-          "oldPixel": "#ADD8E6",
-          "newPixel": "#222BFA"
-        },
-        {
-          "x": 20,
-          "y": 169,
-          "oldPixel": "#ADD8E6",
-          "newPixel": "#222BFA"
-        },
-        {
-          "x": 21,
-          "y": 169,
-          "oldPixel": "#ADD8E6",
-          "newPixel": "#222BFA"
-        },
-        {
-          "x": 22,
-          "y": 169,
-          "oldPixel": "#ADD8E6",
-          "newPixel": "#222BFA"
-        },
-        {
-          "x": 23,
-          "y": 169,
-          "oldPixel": "#ADD8E6",
-          "newPixel": "#222BFA"
-        },
-        {
-          "x": 24,
-          "y": 169,
-          "oldPixel": "#ADD8E6",
-          "newPixel": "#222BFA"
-        },
-        {
-          "x": 25,
-          "y": 169,
-          "oldPixel": "#ADD8E6",
-          "newPixel": "#222BFA"
-        },
-        {
-          "x": 26,
-          "y": 169,
-          "oldPixel": "#ADD8E6",
-          "newPixel": "#222BFA"
-        },
-        {
-          "x": 27,
-          "y": 169,
-          "oldPixel": "#ADD8E6",
-          "newPixel": "#222BFA"
-        },
-        {
-          "x": 28,
-          "y": 169,
-          "oldPixel": "#ADD8E6",
-          "newPixel": "#222BFA"
-        },
-        {
-          "x": 8,
-          "y": 170,
-          "oldPixel": "#ADD8E6",
-          "newPixel": "#222BFA"
-        },
-        {
-          "x": 9,
-          "y": 170,
-          "oldPixel": "#ADD8E6",
-          "newPixel": "#222BFA"
-        },
-        {
-          "x": 10,
-          "y": 170,
-          "oldPixel": "#ADD8E6",
-          "newPixel": "#222BFA"
-        },
-        {
-          "x": 11,
-          "y": 170,
-          "oldPixel": "#ADD8E6",
-          "newPixel": "#222BFA"
-        },
-        {
-          "x": 12,
-          "y": 170,
-          "oldPixel": "#ADD8E6",
-          "newPixel": "#222BFA"
-        },
-        {
-          "x": 13,
-          "y": 170,
-          "oldPixel": "#ADD8E6",
-          "newPixel": "#222BFA"
-        },
-        {
-          "x": 14,
-          "y": 170,
-          "oldPixel": "#ADD8E6",
-          "newPixel": "#222BFA"
-        },
-        {
-          "x": 15,
-          "y": 170,
-          "oldPixel": "#ADD8E6",
-          "newPixel": "#222BFA"
-        }
-      ],
       "transform": 1
     },
     {
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v175/paint/invalidation/stacking-context-lost-expected.txt b/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v175/paint/invalidation/stacking-context-lost-expected.txt
new file mode 100644
index 0000000..d2e747bb
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v175/paint/invalidation/stacking-context-lost-expected.txt
@@ -0,0 +1,37 @@
+{
+  "layers": [
+    {
+      "name": "LayoutView #document",
+      "bounds": [800, 600],
+      "contentsOpaque": true,
+      "backgroundColor": "#FFFFFF"
+    },
+    {
+      "name": "LayoutBlockFlow (relative positioned) DIV id='outer'",
+      "position": [278, 278],
+      "bounds": [100, 100],
+      "contentsOpaque": true,
+      "backfaceVisibility": "hidden",
+      "backgroundColor": "#008000",
+      "paintInvalidations": [
+        {
+          "object": "LayoutBlockFlow (relative positioned) DIV id='inner'",
+          "rect": [0, 0, 100, 100],
+          "reason": "disappeared"
+        },
+        {
+          "object": "LayoutBlockFlow (relative positioned) DIV id='outer'",
+          "rect": [0, 0, 100, 100],
+          "reason": "appeared"
+        }
+      ]
+    }
+  ],
+  "objectPaintInvalidations": [
+    {
+      "object": "LayoutBlockFlow (relative positioned) DIV id='outer'",
+      "reason": "background"
+    }
+  ]
+}
+
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v175/paint/invalidation/subtree-root-skipped-expected.txt b/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v175/paint/invalidation/subtree-root-skipped-expected.txt
index afe540b3..4412e1b 100644
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v175/paint/invalidation/subtree-root-skipped-expected.txt
+++ b/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v175/paint/invalidation/subtree-root-skipped-expected.txt
@@ -26,7 +26,7 @@
   ],
   "objectPaintInvalidations": [
     {
-      "object": "LayoutBlockFlow DIV id='inner-editor'",
+      "object": "LayoutBlockFlow DIV",
       "reason": "geometry"
     },
     {
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v175/paint/invalidation/svg/animated-path-inside-transformed-html-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v175/paint/invalidation/svg/animated-path-inside-transformed-html-expected.png
new file mode 100644
index 0000000..f6dc8c61
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v175/paint/invalidation/svg/animated-path-inside-transformed-html-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v175/paint/invalidation/svg/animated-path-inside-transformed-html-expected.txt b/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v175/paint/invalidation/svg/animated-path-inside-transformed-html-expected.txt
new file mode 100644
index 0000000..8b3b7cfb
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v175/paint/invalidation/svg/animated-path-inside-transformed-html-expected.txt
@@ -0,0 +1,73 @@
+{
+  "layers": [
+    {
+      "name": "LayoutView #document",
+      "bounds": [800, 600],
+      "contentsOpaque": true,
+      "backgroundColor": "#FFFFFF",
+      "paintInvalidations": [
+        {
+          "object": "InlineTextBox 'This is some text'",
+          "rect": [246, 89, 127, 46],
+          "reason": "disappeared"
+        },
+        {
+          "object": "InlineTextBox 'This is some text'",
+          "rect": [203, 336, 126, 45],
+          "reason": "appeared"
+        },
+        {
+          "object": "LayoutSVGRect rect id='rect'",
+          "rect": [108, 84, 105, 102],
+          "reason": "full"
+        },
+        {
+          "object": "LayoutSVGRect rect id='rect'",
+          "rect": [355, 125, 104, 104],
+          "reason": "full"
+        },
+        {
+          "object": "LayoutSVGImage image id='image'",
+          "rect": [352, 398, 99, 98],
+          "reason": "full"
+        },
+        {
+          "object": "LayoutSVGImage image id='image'",
+          "rect": [90, 207, 98, 99],
+          "reason": "full"
+        }
+      ]
+    }
+  ],
+  "objectPaintInvalidations": [
+    {
+      "object": "LayoutSVGRect rect id='rect'",
+      "reason": "full"
+    },
+    {
+      "object": "LayoutSVGText text id='text'",
+      "reason": "full"
+    },
+    {
+      "object": "RootInlineBox",
+      "reason": "full"
+    },
+    {
+      "object": "LayoutSVGInlineText #text",
+      "reason": "geometry"
+    },
+    {
+      "object": "InlineTextBox 'This is some text'",
+      "reason": "geometry"
+    },
+    {
+      "object": "LayoutSVGImage image id='image'",
+      "reason": "full"
+    },
+    {
+      "object": "LayoutText #text",
+      "reason": "appeared"
+    }
+  ]
+}
+
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v175/paint/invalidation/svg/foreign-object-repaint-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v175/paint/invalidation/svg/foreign-object-repaint-expected.png
new file mode 100644
index 0000000..17bdbb7
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v175/paint/invalidation/svg/foreign-object-repaint-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v175/paint/invalidation/svg/js-update-bounce-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v175/paint/invalidation/svg/js-update-bounce-expected.png
new file mode 100644
index 0000000..7c45db8b
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v175/paint/invalidation/svg/js-update-bounce-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v175/paint/invalidation/svg/js-update-bounce-expected.txt b/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v175/paint/invalidation/svg/js-update-bounce-expected.txt
new file mode 100644
index 0000000..2d2d179d0
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v175/paint/invalidation/svg/js-update-bounce-expected.txt
@@ -0,0 +1,29 @@
+{
+  "layers": [
+    {
+      "name": "LayoutView #document",
+      "bounds": [800, 600],
+      "contentsOpaque": true,
+      "backgroundColor": "#FFFFFF",
+      "paintInvalidations": [
+        {
+          "object": "LayoutSVGEllipse circle id='bounce'",
+          "rect": [101, 101, 68, 68],
+          "reason": "appeared"
+        },
+        {
+          "object": "LayoutSVGRoot svg",
+          "rect": [1, 1, 68, 68],
+          "reason": "disappeared"
+        }
+      ]
+    }
+  ],
+  "objectPaintInvalidations": [
+    {
+      "object": "LayoutSVGEllipse circle id='bounce'",
+      "reason": "full"
+    }
+  ]
+}
+
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v175/paint/invalidation/svg/repaint-paintorder-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v175/paint/invalidation/svg/repaint-paintorder-expected.png
new file mode 100644
index 0000000..a120a31
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v175/paint/invalidation/svg/repaint-paintorder-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v175/paint/invalidation/svg/repaint-paintorder-expected.txt b/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v175/paint/invalidation/svg/repaint-paintorder-expected.txt
new file mode 100644
index 0000000..8e74c0da
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v175/paint/invalidation/svg/repaint-paintorder-expected.txt
@@ -0,0 +1,67 @@
+{
+  "layers": [
+    {
+      "name": "LayoutView #document",
+      "bounds": [800, 600],
+      "contentsOpaque": true,
+      "backgroundColor": "#FFFFFF",
+      "paintInvalidations": [
+        {
+          "object": "LayoutSVGPath polygon",
+          "rect": [456, 165, 134, 134],
+          "reason": "style change"
+        },
+        {
+          "object": "LayoutSVGPath polygon id='t3'",
+          "rect": [319, 165, 134, 134],
+          "reason": "style change"
+        },
+        {
+          "object": "LayoutSVGPath polygon",
+          "rect": [183, 165, 134, 134],
+          "reason": "style change"
+        },
+        {
+          "object": "LayoutSVGPath polygon",
+          "rect": [47, 165, 134, 134],
+          "reason": "style change"
+        }
+      ]
+    }
+  ],
+  "objectPaintInvalidations": [
+    {
+      "object": "LayoutSVGContainer use id='t1'",
+      "reason": "style change"
+    },
+    {
+      "object": "LayoutSVGViewportContainer svg id='poly'",
+      "reason": "style change"
+    },
+    {
+      "object": "LayoutSVGPath polygon",
+      "reason": "style change"
+    },
+    {
+      "object": "LayoutSVGContainer use id='t2'",
+      "reason": "style change"
+    },
+    {
+      "object": "LayoutSVGViewportContainer svg id='poly'",
+      "reason": "style change"
+    },
+    {
+      "object": "LayoutSVGPath polygon",
+      "reason": "style change"
+    },
+    {
+      "object": "LayoutSVGPath polygon id='t3'",
+      "reason": "style change"
+    },
+    {
+      "object": "LayoutSVGPath polygon",
+      "reason": "style change"
+    }
+  ]
+}
+
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v175/paint/invalidation/svg/resize-svg-invalidate-children-2-expected.txt b/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v175/paint/invalidation/svg/resize-svg-invalidate-children-2-expected.txt
new file mode 100644
index 0000000..91286e2
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v175/paint/invalidation/svg/resize-svg-invalidate-children-2-expected.txt
@@ -0,0 +1,53 @@
+{
+  "layers": [
+    {
+      "name": "LayoutView #document",
+      "bounds": [800, 600],
+      "contentsOpaque": true,
+      "backgroundColor": "#FFFFFF"
+    },
+    {
+      "name": "LayoutSVGRoot svg",
+      "bounds": [600, 400],
+      "paintInvalidations": [
+        {
+          "object": "LayoutSVGRoot svg",
+          "rect": [50, 0, 500, 400],
+          "reason": "paint property change"
+        },
+        {
+          "object": "LayoutSVGRoot svg",
+          "rect": [0, 120, 200, 160],
+          "reason": "paint property change"
+        }
+      ],
+      "transform": 1
+    }
+  ],
+  "transforms": [
+    {
+      "id": 1,
+      "transform": [
+        [1, 0, 0, 0],
+        [0, 1, 0, 0],
+        [0, 0, 1, 0],
+        [8, 8, 0, 1]
+      ]
+    }
+  ],
+  "objectPaintInvalidations": [
+    {
+      "object": "LayoutBlockFlow DIV id='target'",
+      "reason": "geometry"
+    },
+    {
+      "object": "RootInlineBox",
+      "reason": "geometry"
+    },
+    {
+      "object": "LayoutSVGRoot svg",
+      "reason": "geometry"
+    }
+  ]
+}
+
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v175/paint/invalidation/svg/scrolling-embedded-svg-file-image-repaint-problem-expected.txt b/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v175/paint/invalidation/svg/scrolling-embedded-svg-file-image-repaint-problem-expected.txt
new file mode 100644
index 0000000..c71942c
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v175/paint/invalidation/svg/scrolling-embedded-svg-file-image-repaint-problem-expected.txt
@@ -0,0 +1,138 @@
+{
+  "layers": [
+    {
+      "name": "LayoutView #document",
+      "bounds": [1026, 1036],
+      "contentsOpaque": true,
+      "backgroundColor": "#FFFFFF",
+      "paintInvalidations": [
+        {
+          "object": "InlineTextBox 'pservers-pattern-01-b \u2190'",
+          "rect": [179, 1012, 202, 19],
+          "reason": "appeared"
+        },
+        {
+          "object": "InlineTextBox 'pservers-pattern-01-b \u2190'",
+          "rect": [179, 1012, 202, 19],
+          "reason": "disappeared"
+        },
+        {
+          "object": "InlineTextBox '\u2192 script-handle-01-b'",
+          "rect": [435, 1012, 171, 19],
+          "reason": "appeared"
+        },
+        {
+          "object": "InlineTextBox '\u2192 script-handle-01-b'",
+          "rect": [435, 1012, 171, 19],
+          "reason": "disappeared"
+        },
+        {
+          "object": "LayoutInline A",
+          "rect": [385, 1011, 46, 21],
+          "reason": "appeared"
+        },
+        {
+          "object": "InlineTextBox 'index'",
+          "rect": [386, 1012, 44, 19],
+          "reason": "appeared"
+        },
+        {
+          "object": "InlineTextBox 'index'",
+          "rect": [386, 1012, 44, 19],
+          "reason": "disappeared"
+        },
+        {
+          "object": "InlineTextBox '\n'",
+          "rect": [429, 1012, 7, 19],
+          "reason": "appeared"
+        },
+        {
+          "object": "InlineTextBox '\n'",
+          "rect": [429, 1012, 7, 19],
+          "reason": "disappeared"
+        },
+        {
+          "object": "InlineTextBox '\n'",
+          "rect": [380, 1012, 7, 19],
+          "reason": "appeared"
+        },
+        {
+          "object": "InlineTextBox '\n'",
+          "rect": [380, 1012, 7, 19],
+          "reason": "disappeared"
+        }
+      ],
+      "transform": 1
+    }
+  ],
+  "transforms": [
+    {
+      "id": 1,
+      "transform": [
+        [1, 0, 0, 0],
+        [0, 1, 0, 0],
+        [0, 0, 1, 0],
+        [0, -451, 0, 1]
+      ]
+    }
+  ],
+  "objectPaintInvalidations": [
+    {
+      "object": "LayoutBlockFlow P",
+      "reason": "geometry"
+    },
+    {
+      "object": "RootInlineBox",
+      "reason": "geometry"
+    },
+    {
+      "object": "LayoutText #text",
+      "reason": "geometry"
+    },
+    {
+      "object": "InlineTextBox 'pservers-pattern-01-b \u2190'",
+      "reason": "geometry"
+    },
+    {
+      "object": "LayoutText #text",
+      "reason": "geometry"
+    },
+    {
+      "object": "InlineTextBox '\n'",
+      "reason": "geometry"
+    },
+    {
+      "object": "LayoutInline A",
+      "reason": "style change"
+    },
+    {
+      "object": "InlineFlowBox",
+      "reason": "style change"
+    },
+    {
+      "object": "LayoutText #text",
+      "reason": "geometry"
+    },
+    {
+      "object": "InlineTextBox 'index'",
+      "reason": "geometry"
+    },
+    {
+      "object": "LayoutText #text",
+      "reason": "geometry"
+    },
+    {
+      "object": "InlineTextBox '\n'",
+      "reason": "geometry"
+    },
+    {
+      "object": "LayoutText #text",
+      "reason": "geometry"
+    },
+    {
+      "object": "InlineTextBox '\u2192 script-handle-01-b'",
+      "reason": "geometry"
+    }
+  ]
+}
+
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v175/paint/invalidation/svg/tabgroup-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v175/paint/invalidation/svg/tabgroup-expected.png
new file mode 100644
index 0000000..7ae0b7b
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v175/paint/invalidation/svg/tabgroup-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v175/paint/invalidation/svg/tabgroup-expected.txt b/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v175/paint/invalidation/svg/tabgroup-expected.txt
new file mode 100644
index 0000000..8c62a9a
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v175/paint/invalidation/svg/tabgroup-expected.txt
@@ -0,0 +1,1020 @@
+{
+  "layers": [
+    {
+      "name": "LayoutView #document",
+      "bounds": [800, 600],
+      "contentsOpaque": true,
+      "backgroundColor": "#FFFFFF",
+      "paintInvalidations": [
+        {
+          "object": "LayoutSVGContainer g",
+          "rect": [389, 37, 316, 82],
+          "reason": "appeared"
+        },
+        {
+          "object": "LayoutSVGContainer g",
+          "rect": [262, 278, 303, 303],
+          "reason": "appeared"
+        },
+        {
+          "object": "LayoutSVGContainer g",
+          "rect": [6, 256, 238, 160],
+          "reason": "appeared"
+        },
+        {
+          "object": "LayoutSVGPath path",
+          "rect": [6, 256, 238, 160],
+          "reason": "appeared"
+        },
+        {
+          "object": "LayoutSVGPath path",
+          "rect": [6, 256, 238, 160],
+          "reason": "appeared"
+        },
+        {
+          "object": "LayoutSVGPath path",
+          "rect": [6, 256, 238, 160],
+          "reason": "appeared"
+        },
+        {
+          "object": "LayoutSVGContainer g",
+          "rect": [506, 233, 238, 159],
+          "reason": "appeared"
+        },
+        {
+          "object": "InlineTextBox 'This is a tabgroup with triangular tab corners'",
+          "rect": [15, 291, 211, 37],
+          "reason": "appeared"
+        },
+        {
+          "object": "LayoutSVGContainer g id='tabgroupRect'",
+          "rect": [37, 6, 160, 238],
+          "reason": "appeared"
+        },
+        {
+          "object": "LayoutSVGText text",
+          "rect": [66, 257, 57, 29],
+          "reason": "appeared"
+        },
+        {
+          "object": "LayoutSVGText text",
+          "rect": [10, 257, 50, 29],
+          "reason": "appeared"
+        },
+        {
+          "object": "LayoutSVGText text",
+          "rect": [130, 257, 47, 29],
+          "reason": "appeared"
+        },
+        {
+          "object": "LayoutSVGText text",
+          "rect": [184, 257, 32, 29],
+          "reason": "appeared"
+        }
+      ]
+    }
+  ],
+  "objectPaintInvalidations": [
+    {
+      "object": "LayoutSVGContainer g id='tabgroupRect'",
+      "reason": "appeared"
+    },
+    {
+      "object": "LayoutSVGContainer g",
+      "reason": "appeared"
+    },
+    {
+      "object": "LayoutSVGContainer g",
+      "reason": "appeared"
+    },
+    {
+      "object": "LayoutSVGPath path",
+      "reason": "appeared"
+    },
+    {
+      "object": "LayoutSVGPath path id='tabgroupRect__0'",
+      "reason": "appeared"
+    },
+    {
+      "object": "LayoutSVGText text",
+      "reason": "appeared"
+    },
+    {
+      "object": "RootInlineBox",
+      "reason": "appeared"
+    },
+    {
+      "object": "LayoutSVGTSpan tspan",
+      "reason": "appeared"
+    },
+    {
+      "object": "InlineFlowBox",
+      "reason": "appeared"
+    },
+    {
+      "object": "LayoutSVGInlineText #text",
+      "reason": "appeared"
+    },
+    {
+      "object": "InlineTextBox 'Biography'",
+      "reason": "appeared"
+    },
+    {
+      "object": "LayoutSVGContainer g id='tabgroupRect__0_content'",
+      "reason": "appeared"
+    },
+    {
+      "object": "LayoutSVGContainer g",
+      "reason": "appeared"
+    },
+    {
+      "object": "LayoutSVGPath path",
+      "reason": "appeared"
+    },
+    {
+      "object": "LayoutSVGPath path id='tabgroupRect__2'",
+      "reason": "appeared"
+    },
+    {
+      "object": "LayoutSVGText text",
+      "reason": "appeared"
+    },
+    {
+      "object": "RootInlineBox",
+      "reason": "appeared"
+    },
+    {
+      "object": "LayoutSVGTSpan tspan",
+      "reason": "appeared"
+    },
+    {
+      "object": "InlineFlowBox",
+      "reason": "appeared"
+    },
+    {
+      "object": "LayoutSVGInlineText #text",
+      "reason": "appeared"
+    },
+    {
+      "object": "InlineTextBox 'Events'",
+      "reason": "appeared"
+    },
+    {
+      "object": "LayoutSVGContainer g id='tabgroupRect__2_content'",
+      "reason": "appeared"
+    },
+    {
+      "object": "LayoutSVGContainer g",
+      "reason": "appeared"
+    },
+    {
+      "object": "LayoutSVGPath path",
+      "reason": "appeared"
+    },
+    {
+      "object": "LayoutSVGPath path id='tabgroupRect__3'",
+      "reason": "appeared"
+    },
+    {
+      "object": "LayoutSVGText text",
+      "reason": "appeared"
+    },
+    {
+      "object": "RootInlineBox",
+      "reason": "appeared"
+    },
+    {
+      "object": "LayoutSVGTSpan tspan",
+      "reason": "appeared"
+    },
+    {
+      "object": "InlineFlowBox",
+      "reason": "appeared"
+    },
+    {
+      "object": "LayoutSVGInlineText #text",
+      "reason": "appeared"
+    },
+    {
+      "object": "InlineTextBox 'Portrait'",
+      "reason": "appeared"
+    },
+    {
+      "object": "LayoutSVGContainer g id='tabgroupRect__3_content'",
+      "reason": "appeared"
+    },
+    {
+      "object": "LayoutSVGContainer g",
+      "reason": "appeared"
+    },
+    {
+      "object": "LayoutSVGPath path",
+      "reason": "appeared"
+    },
+    {
+      "object": "LayoutSVGPath path id='tabgroupRect__1'",
+      "reason": "appeared"
+    },
+    {
+      "object": "LayoutSVGText text",
+      "reason": "appeared"
+    },
+    {
+      "object": "RootInlineBox",
+      "reason": "appeared"
+    },
+    {
+      "object": "LayoutSVGTSpan tspan",
+      "reason": "appeared"
+    },
+    {
+      "object": "InlineFlowBox",
+      "reason": "appeared"
+    },
+    {
+      "object": "LayoutSVGInlineText #text",
+      "reason": "appeared"
+    },
+    {
+      "object": "InlineTextBox 'Relations'",
+      "reason": "appeared"
+    },
+    {
+      "object": "LayoutSVGContainer g id='tabgroupRect__1_content'",
+      "reason": "appeared"
+    },
+    {
+      "object": "LayoutSVGContainer g id='tabgroupTriangle'",
+      "reason": "appeared"
+    },
+    {
+      "object": "LayoutSVGContainer g",
+      "reason": "appeared"
+    },
+    {
+      "object": "LayoutSVGContainer g",
+      "reason": "appeared"
+    },
+    {
+      "object": "LayoutSVGPath path",
+      "reason": "appeared"
+    },
+    {
+      "object": "LayoutSVGPath path id='tabgroupTriangle__1'",
+      "reason": "appeared"
+    },
+    {
+      "object": "LayoutSVGText text",
+      "reason": "appeared"
+    },
+    {
+      "object": "RootInlineBox",
+      "reason": "appeared"
+    },
+    {
+      "object": "LayoutSVGTSpan tspan",
+      "reason": "appeared"
+    },
+    {
+      "object": "InlineFlowBox",
+      "reason": "appeared"
+    },
+    {
+      "object": "LayoutSVGInlineText #text",
+      "reason": "appeared"
+    },
+    {
+      "object": "InlineTextBox 'Download'",
+      "reason": "appeared"
+    },
+    {
+      "object": "LayoutSVGTSpan tspan",
+      "reason": "appeared"
+    },
+    {
+      "object": "InlineFlowBox",
+      "reason": "appeared"
+    },
+    {
+      "object": "LayoutSVGInlineText #text",
+      "reason": "appeared"
+    },
+    {
+      "object": "InlineTextBox 'Folder'",
+      "reason": "appeared"
+    },
+    {
+      "object": "LayoutSVGContainer g",
+      "reason": "appeared"
+    },
+    {
+      "object": "LayoutSVGPath path",
+      "reason": "appeared"
+    },
+    {
+      "object": "LayoutSVGPath path id='tabgroupTriangle__2'",
+      "reason": "appeared"
+    },
+    {
+      "object": "LayoutSVGText text",
+      "reason": "appeared"
+    },
+    {
+      "object": "RootInlineBox",
+      "reason": "appeared"
+    },
+    {
+      "object": "LayoutSVGTSpan tspan",
+      "reason": "appeared"
+    },
+    {
+      "object": "InlineFlowBox",
+      "reason": "appeared"
+    },
+    {
+      "object": "LayoutSVGInlineText #text",
+      "reason": "appeared"
+    },
+    {
+      "object": "InlineTextBox 'Your'",
+      "reason": "appeared"
+    },
+    {
+      "object": "LayoutSVGTSpan tspan",
+      "reason": "appeared"
+    },
+    {
+      "object": "InlineFlowBox",
+      "reason": "appeared"
+    },
+    {
+      "object": "LayoutSVGInlineText #text",
+      "reason": "appeared"
+    },
+    {
+      "object": "InlineTextBox 'Account'",
+      "reason": "appeared"
+    },
+    {
+      "object": "LayoutSVGContainer g",
+      "reason": "appeared"
+    },
+    {
+      "object": "LayoutSVGPath path",
+      "reason": "appeared"
+    },
+    {
+      "object": "LayoutSVGPath path id='tabgroupTriangle__3'",
+      "reason": "appeared"
+    },
+    {
+      "object": "LayoutSVGText text",
+      "reason": "appeared"
+    },
+    {
+      "object": "RootInlineBox",
+      "reason": "appeared"
+    },
+    {
+      "object": "LayoutSVGTSpan tspan",
+      "reason": "appeared"
+    },
+    {
+      "object": "InlineFlowBox",
+      "reason": "appeared"
+    },
+    {
+      "object": "LayoutSVGInlineText #text",
+      "reason": "appeared"
+    },
+    {
+      "object": "InlineTextBox 'Help'",
+      "reason": "appeared"
+    },
+    {
+      "object": "LayoutSVGTSpan tspan",
+      "reason": "appeared"
+    },
+    {
+      "object": "InlineFlowBox",
+      "reason": "appeared"
+    },
+    {
+      "object": "LayoutSVGInlineText #text",
+      "reason": "appeared"
+    },
+    {
+      "object": "InlineTextBox '& Info'",
+      "reason": "appeared"
+    },
+    {
+      "object": "LayoutSVGContainer g",
+      "reason": "appeared"
+    },
+    {
+      "object": "LayoutSVGPath path",
+      "reason": "appeared"
+    },
+    {
+      "object": "LayoutSVGPath path id='tabgroupTriangle__0'",
+      "reason": "appeared"
+    },
+    {
+      "object": "LayoutSVGText text",
+      "reason": "appeared"
+    },
+    {
+      "object": "RootInlineBox",
+      "reason": "appeared"
+    },
+    {
+      "object": "LayoutSVGTSpan tspan",
+      "reason": "appeared"
+    },
+    {
+      "object": "InlineFlowBox",
+      "reason": "appeared"
+    },
+    {
+      "object": "LayoutSVGInlineText #text",
+      "reason": "appeared"
+    },
+    {
+      "object": "InlineTextBox 'Geodata'",
+      "reason": "appeared"
+    },
+    {
+      "object": "LayoutSVGTSpan tspan",
+      "reason": "appeared"
+    },
+    {
+      "object": "InlineFlowBox",
+      "reason": "appeared"
+    },
+    {
+      "object": "LayoutSVGInlineText #text",
+      "reason": "appeared"
+    },
+    {
+      "object": "InlineTextBox 'Browser'",
+      "reason": "appeared"
+    },
+    {
+      "object": "LayoutSVGContainer g id='tabgroupTriangle__0_content'",
+      "reason": "appeared"
+    },
+    {
+      "object": "LayoutSVGText text id='contentTabGroupTriangle0'",
+      "reason": "appeared"
+    },
+    {
+      "object": "RootInlineBox",
+      "reason": "appeared"
+    },
+    {
+      "object": "LayoutSVGInlineText #text",
+      "reason": "appeared"
+    },
+    {
+      "object": "InlineTextBox 'This is a tabgroup with triangular tab corners'",
+      "reason": "appeared"
+    },
+    {
+      "object": "LayoutSVGTSpan tspan",
+      "reason": "appeared"
+    },
+    {
+      "object": "InlineFlowBox",
+      "reason": "appeared"
+    },
+    {
+      "object": "LayoutSVGInlineText #text",
+      "reason": "appeared"
+    },
+    {
+      "object": "InlineTextBox 'and a double line tab. (use \"\\n\" as a line separator)'",
+      "reason": "appeared"
+    },
+    {
+      "object": "LayoutSVGTSpan tspan",
+      "reason": "appeared"
+    },
+    {
+      "object": "InlineFlowBox",
+      "reason": "appeared"
+    },
+    {
+      "object": "LayoutSVGInlineText #text",
+      "reason": "appeared"
+    },
+    {
+      "object": "InlineTextBox 'Click on the second tab to see oversize content'",
+      "reason": "appeared"
+    },
+    {
+      "object": "LayoutSVGContainer g id='tabgroupRectTriangle'",
+      "reason": "appeared"
+    },
+    {
+      "object": "LayoutSVGContainer g",
+      "reason": "appeared"
+    },
+    {
+      "object": "LayoutSVGContainer g",
+      "reason": "appeared"
+    },
+    {
+      "object": "LayoutSVGPath path",
+      "reason": "appeared"
+    },
+    {
+      "object": "LayoutSVGPath path id='tabgroupRectTriangle__0'",
+      "reason": "appeared"
+    },
+    {
+      "object": "LayoutSVGText text",
+      "reason": "appeared"
+    },
+    {
+      "object": "RootInlineBox",
+      "reason": "appeared"
+    },
+    {
+      "object": "LayoutSVGTSpan tspan",
+      "reason": "appeared"
+    },
+    {
+      "object": "InlineFlowBox",
+      "reason": "appeared"
+    },
+    {
+      "object": "LayoutSVGInlineText #text",
+      "reason": "appeared"
+    },
+    {
+      "object": "InlineTextBox 'Biography'",
+      "reason": "appeared"
+    },
+    {
+      "object": "LayoutSVGContainer g id='tabgroupRectTriangle__0_content'",
+      "reason": "appeared"
+    },
+    {
+      "object": "LayoutSVGContainer g",
+      "reason": "appeared"
+    },
+    {
+      "object": "LayoutSVGPath path",
+      "reason": "appeared"
+    },
+    {
+      "object": "LayoutSVGPath path id='tabgroupRectTriangle__1'",
+      "reason": "appeared"
+    },
+    {
+      "object": "LayoutSVGText text",
+      "reason": "appeared"
+    },
+    {
+      "object": "RootInlineBox",
+      "reason": "appeared"
+    },
+    {
+      "object": "LayoutSVGTSpan tspan",
+      "reason": "appeared"
+    },
+    {
+      "object": "InlineFlowBox",
+      "reason": "appeared"
+    },
+    {
+      "object": "LayoutSVGInlineText #text",
+      "reason": "appeared"
+    },
+    {
+      "object": "InlineTextBox 'Relations'",
+      "reason": "appeared"
+    },
+    {
+      "object": "LayoutSVGContainer g id='tabgroupRectTriangle__1_content'",
+      "reason": "appeared"
+    },
+    {
+      "object": "LayoutSVGContainer g",
+      "reason": "appeared"
+    },
+    {
+      "object": "LayoutSVGPath path",
+      "reason": "appeared"
+    },
+    {
+      "object": "LayoutSVGPath path id='tabgroupRectTriangle__3'",
+      "reason": "appeared"
+    },
+    {
+      "object": "LayoutSVGText text",
+      "reason": "appeared"
+    },
+    {
+      "object": "RootInlineBox",
+      "reason": "appeared"
+    },
+    {
+      "object": "LayoutSVGTSpan tspan",
+      "reason": "appeared"
+    },
+    {
+      "object": "InlineFlowBox",
+      "reason": "appeared"
+    },
+    {
+      "object": "LayoutSVGInlineText #text",
+      "reason": "appeared"
+    },
+    {
+      "object": "InlineTextBox 'Portrait'",
+      "reason": "appeared"
+    },
+    {
+      "object": "LayoutSVGContainer g id='tabgroupRectTriangle__3_content'",
+      "reason": "appeared"
+    },
+    {
+      "object": "LayoutSVGContainer g",
+      "reason": "appeared"
+    },
+    {
+      "object": "LayoutSVGPath path",
+      "reason": "appeared"
+    },
+    {
+      "object": "LayoutSVGPath path id='tabgroupRectTriangle__2'",
+      "reason": "appeared"
+    },
+    {
+      "object": "LayoutSVGText text",
+      "reason": "appeared"
+    },
+    {
+      "object": "RootInlineBox",
+      "reason": "appeared"
+    },
+    {
+      "object": "LayoutSVGTSpan tspan",
+      "reason": "appeared"
+    },
+    {
+      "object": "InlineFlowBox",
+      "reason": "appeared"
+    },
+    {
+      "object": "LayoutSVGInlineText #text",
+      "reason": "appeared"
+    },
+    {
+      "object": "InlineTextBox 'Events'",
+      "reason": "appeared"
+    },
+    {
+      "object": "LayoutSVGContainer g id='tabgroupRectTriangle__2_content'",
+      "reason": "appeared"
+    },
+    {
+      "object": "LayoutSVGContainer g id='tabgroupRound'",
+      "reason": "appeared"
+    },
+    {
+      "object": "LayoutSVGContainer g",
+      "reason": "appeared"
+    },
+    {
+      "object": "LayoutSVGContainer g",
+      "reason": "appeared"
+    },
+    {
+      "object": "LayoutSVGPath path",
+      "reason": "appeared"
+    },
+    {
+      "object": "LayoutSVGPath path id='tabgroupRound__0'",
+      "reason": "appeared"
+    },
+    {
+      "object": "LayoutSVGText text",
+      "reason": "appeared"
+    },
+    {
+      "object": "RootInlineBox",
+      "reason": "appeared"
+    },
+    {
+      "object": "LayoutSVGTSpan tspan",
+      "reason": "appeared"
+    },
+    {
+      "object": "InlineFlowBox",
+      "reason": "appeared"
+    },
+    {
+      "object": "LayoutSVGInlineText #text",
+      "reason": "appeared"
+    },
+    {
+      "object": "InlineTextBox 'Biography'",
+      "reason": "appeared"
+    },
+    {
+      "object": "LayoutSVGContainer g id='tabgroupRound__0_content'",
+      "reason": "appeared"
+    },
+    {
+      "object": "LayoutSVGContainer g",
+      "reason": "appeared"
+    },
+    {
+      "object": "LayoutSVGPath path",
+      "reason": "appeared"
+    },
+    {
+      "object": "LayoutSVGPath path id='tabgroupRound__2'",
+      "reason": "appeared"
+    },
+    {
+      "object": "LayoutSVGText text",
+      "reason": "appeared"
+    },
+    {
+      "object": "RootInlineBox",
+      "reason": "appeared"
+    },
+    {
+      "object": "LayoutSVGTSpan tspan",
+      "reason": "appeared"
+    },
+    {
+      "object": "InlineFlowBox",
+      "reason": "appeared"
+    },
+    {
+      "object": "LayoutSVGInlineText #text",
+      "reason": "appeared"
+    },
+    {
+      "object": "InlineTextBox 'Events'",
+      "reason": "appeared"
+    },
+    {
+      "object": "LayoutSVGContainer g id='tabgroupRound__2_content'",
+      "reason": "appeared"
+    },
+    {
+      "object": "LayoutSVGContainer g",
+      "reason": "appeared"
+    },
+    {
+      "object": "LayoutSVGPath path",
+      "reason": "appeared"
+    },
+    {
+      "object": "LayoutSVGPath path id='tabgroupRound__3'",
+      "reason": "appeared"
+    },
+    {
+      "object": "LayoutSVGText text",
+      "reason": "appeared"
+    },
+    {
+      "object": "RootInlineBox",
+      "reason": "appeared"
+    },
+    {
+      "object": "LayoutSVGTSpan tspan",
+      "reason": "appeared"
+    },
+    {
+      "object": "InlineFlowBox",
+      "reason": "appeared"
+    },
+    {
+      "object": "LayoutSVGInlineText #text",
+      "reason": "appeared"
+    },
+    {
+      "object": "InlineTextBox 'Portrait'",
+      "reason": "appeared"
+    },
+    {
+      "object": "LayoutSVGContainer g id='tabgroupRound__3_content'",
+      "reason": "appeared"
+    },
+    {
+      "object": "LayoutSVGContainer g",
+      "reason": "appeared"
+    },
+    {
+      "object": "LayoutSVGPath path",
+      "reason": "appeared"
+    },
+    {
+      "object": "LayoutSVGPath path id='tabgroupRound__1'",
+      "reason": "appeared"
+    },
+    {
+      "object": "LayoutSVGText text",
+      "reason": "appeared"
+    },
+    {
+      "object": "RootInlineBox",
+      "reason": "appeared"
+    },
+    {
+      "object": "LayoutSVGTSpan tspan",
+      "reason": "appeared"
+    },
+    {
+      "object": "InlineFlowBox",
+      "reason": "appeared"
+    },
+    {
+      "object": "LayoutSVGInlineText #text",
+      "reason": "appeared"
+    },
+    {
+      "object": "InlineTextBox 'Relations'",
+      "reason": "appeared"
+    },
+    {
+      "object": "LayoutSVGContainer g id='tabgroupRound__1_content'",
+      "reason": "appeared"
+    },
+    {
+      "object": "LayoutSVGContainer g id='tabgroupRectRound'",
+      "reason": "appeared"
+    },
+    {
+      "object": "LayoutSVGContainer g",
+      "reason": "appeared"
+    },
+    {
+      "object": "LayoutSVGContainer g",
+      "reason": "appeared"
+    },
+    {
+      "object": "LayoutSVGPath path",
+      "reason": "appeared"
+    },
+    {
+      "object": "LayoutSVGPath path id='tabgroupRectRound__1'",
+      "reason": "appeared"
+    },
+    {
+      "object": "LayoutSVGText text",
+      "reason": "appeared"
+    },
+    {
+      "object": "RootInlineBox",
+      "reason": "appeared"
+    },
+    {
+      "object": "LayoutSVGTSpan tspan",
+      "reason": "appeared"
+    },
+    {
+      "object": "InlineFlowBox",
+      "reason": "appeared"
+    },
+    {
+      "object": "LayoutSVGInlineText #text",
+      "reason": "appeared"
+    },
+    {
+      "object": "InlineTextBox 'Relations'",
+      "reason": "appeared"
+    },
+    {
+      "object": "LayoutSVGContainer g id='tabgroupRectRound__1_content'",
+      "reason": "appeared"
+    },
+    {
+      "object": "LayoutSVGContainer g",
+      "reason": "appeared"
+    },
+    {
+      "object": "LayoutSVGPath path",
+      "reason": "appeared"
+    },
+    {
+      "object": "LayoutSVGPath path id='tabgroupRectRound__2'",
+      "reason": "appeared"
+    },
+    {
+      "object": "LayoutSVGText text",
+      "reason": "appeared"
+    },
+    {
+      "object": "RootInlineBox",
+      "reason": "appeared"
+    },
+    {
+      "object": "LayoutSVGTSpan tspan",
+      "reason": "appeared"
+    },
+    {
+      "object": "InlineFlowBox",
+      "reason": "appeared"
+    },
+    {
+      "object": "LayoutSVGInlineText #text",
+      "reason": "appeared"
+    },
+    {
+      "object": "InlineTextBox 'Events'",
+      "reason": "appeared"
+    },
+    {
+      "object": "LayoutSVGContainer g id='tabgroupRectRound__2_content'",
+      "reason": "appeared"
+    },
+    {
+      "object": "LayoutSVGContainer g",
+      "reason": "appeared"
+    },
+    {
+      "object": "LayoutSVGPath path",
+      "reason": "appeared"
+    },
+    {
+      "object": "LayoutSVGPath path id='tabgroupRectRound__3'",
+      "reason": "appeared"
+    },
+    {
+      "object": "LayoutSVGText text",
+      "reason": "appeared"
+    },
+    {
+      "object": "RootInlineBox",
+      "reason": "appeared"
+    },
+    {
+      "object": "LayoutSVGTSpan tspan",
+      "reason": "appeared"
+    },
+    {
+      "object": "InlineFlowBox",
+      "reason": "appeared"
+    },
+    {
+      "object": "LayoutSVGInlineText #text",
+      "reason": "appeared"
+    },
+    {
+      "object": "InlineTextBox 'Portrait'",
+      "reason": "appeared"
+    },
+    {
+      "object": "LayoutSVGContainer g id='tabgroupRectRound__3_content'",
+      "reason": "appeared"
+    },
+    {
+      "object": "LayoutSVGContainer g",
+      "reason": "appeared"
+    },
+    {
+      "object": "LayoutSVGPath path",
+      "reason": "appeared"
+    },
+    {
+      "object": "LayoutSVGPath path id='tabgroupRectRound__0'",
+      "reason": "appeared"
+    },
+    {
+      "object": "LayoutSVGText text",
+      "reason": "appeared"
+    },
+    {
+      "object": "RootInlineBox",
+      "reason": "appeared"
+    },
+    {
+      "object": "LayoutSVGTSpan tspan",
+      "reason": "appeared"
+    },
+    {
+      "object": "InlineFlowBox",
+      "reason": "appeared"
+    },
+    {
+      "object": "LayoutSVGInlineText #text",
+      "reason": "appeared"
+    },
+    {
+      "object": "InlineTextBox 'Biography'",
+      "reason": "appeared"
+    },
+    {
+      "object": "LayoutSVGContainer g id='tabgroupRectRound__0_content'",
+      "reason": "appeared"
+    }
+  ]
+}
+
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v175/paint/invalidation/svg/text-selection-text-05-t-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v175/paint/invalidation/svg/text-selection-text-05-t-expected.png
new file mode 100644
index 0000000..d2e6313
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v175/paint/invalidation/svg/text-selection-text-05-t-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v175/paint/invalidation/svg/text-selection-text-05-t-expected.txt b/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v175/paint/invalidation/svg/text-selection-text-05-t-expected.txt
new file mode 100644
index 0000000..8c29c76
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v175/paint/invalidation/svg/text-selection-text-05-t-expected.txt
@@ -0,0 +1,1177 @@
+{
+  "layers": [
+    {
+      "name": "LayoutView #document",
+      "bounds": [800, 600],
+      "contentsOpaque": true,
+      "backgroundColor": "#FFFFFF",
+      "paintInvalidations": [
+        {
+          "object": "InlineTextBox '$Revision: 1.8 $'",
+          "rect": [-1, -1, 802, 602],
+          "reason": "disappeared"
+        },
+        {
+          "object": "LayoutSVGText text id='revision'",
+          "rect": [-1, -1, 802, 602],
+          "reason": "appeared"
+        },
+        {
+          "object": "InlineTextBox 'text-anchor'",
+          "rect": [352, 12, 131, 36],
+          "reason": "selection"
+        },
+        {
+          "object": "LayoutSVGText text",
+          "rect": [352, 12, 131, 36],
+          "reason": "appeared"
+        },
+        {
+          "object": "InlineTextBox 'text-anchor'",
+          "rect": [519, 12, 130, 36],
+          "reason": "selection"
+        },
+        {
+          "object": "LayoutSVGText text",
+          "rect": [519, 12, 130, 36],
+          "reason": "appeared"
+        },
+        {
+          "object": "InlineTextBox 'text-anchor'",
+          "rect": [186, 12, 130, 36],
+          "reason": "selection"
+        },
+        {
+          "object": "LayoutSVGText text",
+          "rect": [186, 12, 130, 36],
+          "reason": "appeared"
+        },
+        {
+          "object": "InlineTextBox '1'",
+          "rect": [266, 485, 113, 29],
+          "reason": "disappeared"
+        },
+        {
+          "object": "LayoutSVGText text",
+          "rect": [266, 485, 113, 29],
+          "reason": "appeared"
+        },
+        {
+          "object": "InlineTextBox '1'",
+          "rect": [266, 201, 113, 21],
+          "reason": "disappeared"
+        },
+        {
+          "object": "LayoutSVGText text",
+          "rect": [266, 201, 113, 21],
+          "reason": "appeared"
+        },
+        {
+          "object": "InlineTextBox '1'",
+          "rect": [428, 485, 104, 29],
+          "reason": "disappeared"
+        },
+        {
+          "object": "LayoutSVGText text",
+          "rect": [428, 485, 104, 29],
+          "reason": "appeared"
+        },
+        {
+          "object": "InlineTextBox '1'",
+          "rect": [428, 201, 104, 21],
+          "reason": "disappeared"
+        },
+        {
+          "object": "LayoutSVGText text",
+          "rect": [428, 201, 104, 21],
+          "reason": "appeared"
+        },
+        {
+          "object": "InlineTextBox '1'",
+          "rect": [590, 485, 94, 29],
+          "reason": "disappeared"
+        },
+        {
+          "object": "LayoutSVGText text",
+          "rect": [590, 485, 94, 29],
+          "reason": "appeared"
+        },
+        {
+          "object": "InlineTextBox '1'",
+          "rect": [590, 201, 94, 21],
+          "reason": "disappeared"
+        },
+        {
+          "object": "LayoutSVGText text",
+          "rect": [590, 201, 94, 21],
+          "reason": "appeared"
+        },
+        {
+          "object": "InlineTextBox 'middle'",
+          "rect": [376, 36, 82, 35],
+          "reason": "selection"
+        },
+        {
+          "object": "LayoutSVGText text",
+          "rect": [376, 36, 82, 35],
+          "reason": "appeared"
+        },
+        {
+          "object": "InlineTextBox '2.x 2.y'",
+          "rect": [16, 491, 79, 34],
+          "reason": "selection"
+        },
+        {
+          "object": "LayoutSVGText text",
+          "rect": [16, 491, 79, 34],
+          "reason": "appeared"
+        },
+        {
+          "object": "InlineTextBox '4.x 2.y'",
+          "rect": [16, 441, 79, 34],
+          "reason": "selection"
+        },
+        {
+          "object": "LayoutSVGText text",
+          "rect": [16, 441, 79, 34],
+          "reason": "appeared"
+        },
+        {
+          "object": "InlineTextBox '1.x 2.y'",
+          "rect": [16, 391, 79, 34],
+          "reason": "selection"
+        },
+        {
+          "object": "LayoutSVGText text",
+          "rect": [16, 391, 79, 34],
+          "reason": "appeared"
+        },
+        {
+          "object": "InlineTextBox '2.x 4.y'",
+          "rect": [16, 341, 79, 34],
+          "reason": "selection"
+        },
+        {
+          "object": "LayoutSVGText text",
+          "rect": [16, 341, 79, 34],
+          "reason": "appeared"
+        },
+        {
+          "object": "InlineTextBox '4.x 4.y'",
+          "rect": [16, 291, 79, 34],
+          "reason": "selection"
+        },
+        {
+          "object": "LayoutSVGText text",
+          "rect": [16, 291, 79, 34],
+          "reason": "appeared"
+        },
+        {
+          "object": "InlineTextBox '1.x 4.y'",
+          "rect": [16, 241, 79, 34],
+          "reason": "selection"
+        },
+        {
+          "object": "LayoutSVGText text",
+          "rect": [16, 241, 79, 34],
+          "reason": "appeared"
+        },
+        {
+          "object": "InlineTextBox '2.x 1.y'",
+          "rect": [16, 191, 79, 34],
+          "reason": "selection"
+        },
+        {
+          "object": "LayoutSVGText text",
+          "rect": [16, 191, 79, 34],
+          "reason": "appeared"
+        },
+        {
+          "object": "InlineTextBox '4.x 1.y'",
+          "rect": [16, 141, 79, 34],
+          "reason": "selection"
+        },
+        {
+          "object": "LayoutSVGText text",
+          "rect": [16, 141, 79, 34],
+          "reason": "appeared"
+        },
+        {
+          "object": "InlineTextBox '1.x 1.y'",
+          "rect": [16, 91, 79, 34],
+          "reason": "selection"
+        },
+        {
+          "object": "LayoutSVGText text",
+          "rect": [16, 91, 79, 34],
+          "reason": "appeared"
+        },
+        {
+          "object": "InlineTextBox '1'",
+          "rect": [428, 285, 61, 54],
+          "reason": "disappeared"
+        },
+        {
+          "object": "LayoutSVGText text",
+          "rect": [428, 285, 61, 54],
+          "reason": "appeared"
+        },
+        {
+          "object": "InlineTextBox '1'",
+          "rect": [266, 285, 61, 54],
+          "reason": "disappeared"
+        },
+        {
+          "object": "LayoutSVGText text",
+          "rect": [266, 285, 61, 54],
+          "reason": "appeared"
+        },
+        {
+          "object": "InlineTextBox '1'",
+          "rect": [428, 435, 61, 29],
+          "reason": "disappeared"
+        },
+        {
+          "object": "LayoutSVGText text",
+          "rect": [428, 435, 61, 29],
+          "reason": "appeared"
+        },
+        {
+          "object": "InlineTextBox '1'",
+          "rect": [266, 435, 61, 29],
+          "reason": "disappeared"
+        },
+        {
+          "object": "LayoutSVGText text",
+          "rect": [266, 435, 61, 29],
+          "reason": "appeared"
+        },
+        {
+          "object": "InlineTextBox '1'",
+          "rect": [428, 151, 61, 21],
+          "reason": "disappeared"
+        },
+        {
+          "object": "LayoutSVGText text",
+          "rect": [428, 151, 61, 21],
+          "reason": "appeared"
+        },
+        {
+          "object": "InlineTextBox '1'",
+          "rect": [266, 151, 61, 21],
+          "reason": "disappeared"
+        },
+        {
+          "object": "LayoutSVGText text",
+          "rect": [266, 151, 61, 21],
+          "reason": "appeared"
+        },
+        {
+          "object": "InlineTextBox '1'",
+          "rect": [590, 285, 60, 54],
+          "reason": "disappeared"
+        },
+        {
+          "object": "LayoutSVGText text",
+          "rect": [590, 285, 60, 54],
+          "reason": "appeared"
+        },
+        {
+          "object": "InlineTextBox '1'",
+          "rect": [590, 435, 60, 29],
+          "reason": "disappeared"
+        },
+        {
+          "object": "LayoutSVGText text",
+          "rect": [590, 435, 60, 29],
+          "reason": "appeared"
+        },
+        {
+          "object": "InlineTextBox '1'",
+          "rect": [590, 151, 60, 21],
+          "reason": "disappeared"
+        },
+        {
+          "object": "LayoutSVGText text",
+          "rect": [590, 151, 60, 21],
+          "reason": "appeared"
+        },
+        {
+          "object": "InlineTextBox 'start'",
+          "rect": [224, 36, 52, 35],
+          "reason": "selection"
+        },
+        {
+          "object": "LayoutSVGText text",
+          "rect": [224, 36, 52, 35],
+          "reason": "appeared"
+        },
+        {
+          "object": "InlineTextBox '1'",
+          "rect": [428, 335, 46, 54],
+          "reason": "disappeared"
+        },
+        {
+          "object": "LayoutSVGText text",
+          "rect": [428, 335, 46, 54],
+          "reason": "appeared"
+        },
+        {
+          "object": "InlineTextBox '1'",
+          "rect": [266, 335, 46, 54],
+          "reason": "disappeared"
+        },
+        {
+          "object": "LayoutSVGText text",
+          "rect": [266, 335, 46, 54],
+          "reason": "appeared"
+        },
+        {
+          "object": "InlineTextBox '1'",
+          "rect": [590, 335, 45, 54],
+          "reason": "disappeared"
+        },
+        {
+          "object": "LayoutSVGText text",
+          "rect": [590, 335, 45, 54],
+          "reason": "appeared"
+        },
+        {
+          "object": "InlineTextBox 'end'",
+          "rect": [562, 36, 42, 35],
+          "reason": "selection"
+        },
+        {
+          "object": "LayoutSVGText text",
+          "rect": [562, 36, 42, 35],
+          "reason": "appeared"
+        },
+        {
+          "object": "InlineTextBox '1'",
+          "rect": [573, 235, 39, 54],
+          "reason": "disappeared"
+        },
+        {
+          "object": "LayoutSVGText text",
+          "rect": [573, 235, 39, 54],
+          "reason": "appeared"
+        },
+        {
+          "object": "InlineTextBox '1'",
+          "rect": [411, 235, 38, 54],
+          "reason": "disappeared"
+        },
+        {
+          "object": "LayoutSVGText text",
+          "rect": [411, 235, 38, 54],
+          "reason": "appeared"
+        },
+        {
+          "object": "InlineTextBox '1234'",
+          "rect": [546, 101, 38, 21],
+          "reason": "disappeared"
+        },
+        {
+          "object": "LayoutSVGText text",
+          "rect": [546, 101, 38, 21],
+          "reason": "appeared"
+        },
+        {
+          "object": "InlineTextBox '1'",
+          "rect": [250, 235, 37, 54],
+          "reason": "disappeared"
+        },
+        {
+          "object": "LayoutSVGText text",
+          "rect": [250, 235, 37, 54],
+          "reason": "appeared"
+        },
+        {
+          "object": "InlineTextBox '1'",
+          "rect": [250, 385, 37, 45],
+          "reason": "disappeared"
+        },
+        {
+          "object": "LayoutSVGText text",
+          "rect": [250, 385, 37, 45],
+          "reason": "appeared"
+        },
+        {
+          "object": "InlineTextBox '1234'",
+          "rect": [398, 101, 37, 21],
+          "reason": "disappeared"
+        },
+        {
+          "object": "LayoutSVGText text",
+          "rect": [398, 101, 37, 21],
+          "reason": "appeared"
+        },
+        {
+          "object": "InlineTextBox '1234'",
+          "rect": [250, 101, 37, 21],
+          "reason": "disappeared"
+        },
+        {
+          "object": "LayoutSVGText text",
+          "rect": [250, 101, 37, 21],
+          "reason": "appeared"
+        },
+        {
+          "object": "InlineTextBox '1'",
+          "rect": [565, 385, 29, 45],
+          "reason": "disappeared"
+        },
+        {
+          "object": "LayoutSVGText text",
+          "rect": [565, 385, 29, 45],
+          "reason": "appeared"
+        },
+        {
+          "object": "InlineTextBox '1'",
+          "rect": [411, 385, 29, 45],
+          "reason": "disappeared"
+        },
+        {
+          "object": "LayoutSVGText text",
+          "rect": [411, 385, 29, 45],
+          "reason": "appeared"
+        }
+      ]
+    }
+  ],
+  "objectPaintInvalidations": [
+    {
+      "object": "LayoutSVGText text",
+      "reason": "selection"
+    },
+    {
+      "object": "LayoutSVGInlineText #text",
+      "reason": "selection"
+    },
+    {
+      "object": "InlineTextBox '1.x 1.y'",
+      "reason": "selection"
+    },
+    {
+      "object": "LayoutSVGText text",
+      "reason": "selection"
+    },
+    {
+      "object": "LayoutSVGInlineText #text",
+      "reason": "selection"
+    },
+    {
+      "object": "InlineTextBox '4.x 1.y'",
+      "reason": "selection"
+    },
+    {
+      "object": "LayoutSVGText text",
+      "reason": "selection"
+    },
+    {
+      "object": "LayoutSVGInlineText #text",
+      "reason": "selection"
+    },
+    {
+      "object": "InlineTextBox '2.x 1.y'",
+      "reason": "selection"
+    },
+    {
+      "object": "LayoutSVGText text",
+      "reason": "selection"
+    },
+    {
+      "object": "LayoutSVGInlineText #text",
+      "reason": "selection"
+    },
+    {
+      "object": "InlineTextBox '1.x 4.y'",
+      "reason": "selection"
+    },
+    {
+      "object": "LayoutSVGText text",
+      "reason": "selection"
+    },
+    {
+      "object": "LayoutSVGInlineText #text",
+      "reason": "selection"
+    },
+    {
+      "object": "InlineTextBox '4.x 4.y'",
+      "reason": "selection"
+    },
+    {
+      "object": "LayoutSVGText text",
+      "reason": "selection"
+    },
+    {
+      "object": "LayoutSVGInlineText #text",
+      "reason": "selection"
+    },
+    {
+      "object": "InlineTextBox '2.x 4.y'",
+      "reason": "selection"
+    },
+    {
+      "object": "LayoutSVGText text",
+      "reason": "selection"
+    },
+    {
+      "object": "LayoutSVGInlineText #text",
+      "reason": "selection"
+    },
+    {
+      "object": "InlineTextBox '1.x 2.y'",
+      "reason": "selection"
+    },
+    {
+      "object": "LayoutSVGText text",
+      "reason": "selection"
+    },
+    {
+      "object": "LayoutSVGInlineText #text",
+      "reason": "selection"
+    },
+    {
+      "object": "InlineTextBox '4.x 2.y'",
+      "reason": "selection"
+    },
+    {
+      "object": "LayoutSVGText text",
+      "reason": "selection"
+    },
+    {
+      "object": "LayoutSVGInlineText #text",
+      "reason": "selection"
+    },
+    {
+      "object": "InlineTextBox '2.x 2.y'",
+      "reason": "selection"
+    },
+    {
+      "object": "LayoutSVGText text",
+      "reason": "selection"
+    },
+    {
+      "object": "LayoutSVGInlineText #text",
+      "reason": "selection"
+    },
+    {
+      "object": "InlineTextBox 'text-anchor'",
+      "reason": "selection"
+    },
+    {
+      "object": "LayoutSVGText text",
+      "reason": "selection"
+    },
+    {
+      "object": "LayoutSVGInlineText #text",
+      "reason": "selection"
+    },
+    {
+      "object": "InlineTextBox 'start'",
+      "reason": "selection"
+    },
+    {
+      "object": "LayoutSVGText text",
+      "reason": "selection"
+    },
+    {
+      "object": "LayoutSVGInlineText #text",
+      "reason": "selection"
+    },
+    {
+      "object": "InlineTextBox '1234'",
+      "reason": "selection"
+    },
+    {
+      "object": "LayoutSVGText text",
+      "reason": "selection"
+    },
+    {
+      "object": "LayoutSVGInlineText #text",
+      "reason": "selection"
+    },
+    {
+      "object": "InlineTextBox '1'",
+      "reason": "selection"
+    },
+    {
+      "object": "InlineTextBox '2'",
+      "reason": "selection"
+    },
+    {
+      "object": "InlineTextBox '3'",
+      "reason": "selection"
+    },
+    {
+      "object": "InlineTextBox '4'",
+      "reason": "selection"
+    },
+    {
+      "object": "LayoutSVGText text",
+      "reason": "selection"
+    },
+    {
+      "object": "LayoutSVGInlineText #text",
+      "reason": "selection"
+    },
+    {
+      "object": "InlineTextBox '1'",
+      "reason": "selection"
+    },
+    {
+      "object": "InlineTextBox '234'",
+      "reason": "selection"
+    },
+    {
+      "object": "LayoutSVGText text",
+      "reason": "selection"
+    },
+    {
+      "object": "LayoutSVGInlineText #text",
+      "reason": "selection"
+    },
+    {
+      "object": "InlineTextBox '1'",
+      "reason": "selection"
+    },
+    {
+      "object": "InlineTextBox '2'",
+      "reason": "selection"
+    },
+    {
+      "object": "InlineTextBox '3'",
+      "reason": "selection"
+    },
+    {
+      "object": "InlineTextBox '4'",
+      "reason": "selection"
+    },
+    {
+      "object": "LayoutSVGText text",
+      "reason": "selection"
+    },
+    {
+      "object": "LayoutSVGInlineText #text",
+      "reason": "selection"
+    },
+    {
+      "object": "InlineTextBox '1'",
+      "reason": "selection"
+    },
+    {
+      "object": "InlineTextBox '2'",
+      "reason": "selection"
+    },
+    {
+      "object": "InlineTextBox '3'",
+      "reason": "selection"
+    },
+    {
+      "object": "InlineTextBox '4'",
+      "reason": "selection"
+    },
+    {
+      "object": "LayoutSVGText text",
+      "reason": "selection"
+    },
+    {
+      "object": "LayoutSVGInlineText #text",
+      "reason": "selection"
+    },
+    {
+      "object": "InlineTextBox '1'",
+      "reason": "selection"
+    },
+    {
+      "object": "InlineTextBox '2'",
+      "reason": "selection"
+    },
+    {
+      "object": "InlineTextBox '3'",
+      "reason": "selection"
+    },
+    {
+      "object": "InlineTextBox '4'",
+      "reason": "selection"
+    },
+    {
+      "object": "LayoutSVGText text",
+      "reason": "selection"
+    },
+    {
+      "object": "LayoutSVGInlineText #text",
+      "reason": "selection"
+    },
+    {
+      "object": "InlineTextBox '1'",
+      "reason": "selection"
+    },
+    {
+      "object": "InlineTextBox '234'",
+      "reason": "selection"
+    },
+    {
+      "object": "LayoutSVGText text",
+      "reason": "selection"
+    },
+    {
+      "object": "LayoutSVGInlineText #text",
+      "reason": "selection"
+    },
+    {
+      "object": "InlineTextBox '1'",
+      "reason": "selection"
+    },
+    {
+      "object": "InlineTextBox '2'",
+      "reason": "selection"
+    },
+    {
+      "object": "InlineTextBox '3'",
+      "reason": "selection"
+    },
+    {
+      "object": "InlineTextBox '4'",
+      "reason": "selection"
+    },
+    {
+      "object": "LayoutSVGText text",
+      "reason": "selection"
+    },
+    {
+      "object": "LayoutSVGInlineText #text",
+      "reason": "selection"
+    },
+    {
+      "object": "InlineTextBox '1'",
+      "reason": "selection"
+    },
+    {
+      "object": "InlineTextBox '234'",
+      "reason": "selection"
+    },
+    {
+      "object": "LayoutSVGText text",
+      "reason": "selection"
+    },
+    {
+      "object": "LayoutSVGInlineText #text",
+      "reason": "selection"
+    },
+    {
+      "object": "InlineTextBox 'text-anchor'",
+      "reason": "selection"
+    },
+    {
+      "object": "LayoutSVGText text",
+      "reason": "selection"
+    },
+    {
+      "object": "LayoutSVGInlineText #text",
+      "reason": "selection"
+    },
+    {
+      "object": "InlineTextBox 'middle'",
+      "reason": "selection"
+    },
+    {
+      "object": "LayoutSVGText text",
+      "reason": "selection"
+    },
+    {
+      "object": "LayoutSVGInlineText #text",
+      "reason": "selection"
+    },
+    {
+      "object": "InlineTextBox '1234'",
+      "reason": "selection"
+    },
+    {
+      "object": "LayoutSVGText text",
+      "reason": "selection"
+    },
+    {
+      "object": "LayoutSVGInlineText #text",
+      "reason": "selection"
+    },
+    {
+      "object": "InlineTextBox '1'",
+      "reason": "selection"
+    },
+    {
+      "object": "InlineTextBox '2'",
+      "reason": "selection"
+    },
+    {
+      "object": "InlineTextBox '3'",
+      "reason": "selection"
+    },
+    {
+      "object": "InlineTextBox '4'",
+      "reason": "selection"
+    },
+    {
+      "object": "LayoutSVGText text",
+      "reason": "selection"
+    },
+    {
+      "object": "LayoutSVGInlineText #text",
+      "reason": "selection"
+    },
+    {
+      "object": "InlineTextBox '1'",
+      "reason": "selection"
+    },
+    {
+      "object": "InlineTextBox '234'",
+      "reason": "selection"
+    },
+    {
+      "object": "LayoutSVGText text",
+      "reason": "selection"
+    },
+    {
+      "object": "LayoutSVGInlineText #text",
+      "reason": "selection"
+    },
+    {
+      "object": "InlineTextBox '1'",
+      "reason": "selection"
+    },
+    {
+      "object": "InlineTextBox '2'",
+      "reason": "selection"
+    },
+    {
+      "object": "InlineTextBox '3'",
+      "reason": "selection"
+    },
+    {
+      "object": "InlineTextBox '4'",
+      "reason": "selection"
+    },
+    {
+      "object": "LayoutSVGText text",
+      "reason": "selection"
+    },
+    {
+      "object": "LayoutSVGInlineText #text",
+      "reason": "selection"
+    },
+    {
+      "object": "InlineTextBox '1'",
+      "reason": "selection"
+    },
+    {
+      "object": "InlineTextBox '2'",
+      "reason": "selection"
+    },
+    {
+      "object": "InlineTextBox '3'",
+      "reason": "selection"
+    },
+    {
+      "object": "InlineTextBox '4'",
+      "reason": "selection"
+    },
+    {
+      "object": "LayoutSVGText text",
+      "reason": "selection"
+    },
+    {
+      "object": "LayoutSVGInlineText #text",
+      "reason": "selection"
+    },
+    {
+      "object": "InlineTextBox '1'",
+      "reason": "selection"
+    },
+    {
+      "object": "InlineTextBox '2'",
+      "reason": "selection"
+    },
+    {
+      "object": "InlineTextBox '3'",
+      "reason": "selection"
+    },
+    {
+      "object": "InlineTextBox '4'",
+      "reason": "selection"
+    },
+    {
+      "object": "LayoutSVGText text",
+      "reason": "selection"
+    },
+    {
+      "object": "LayoutSVGInlineText #text",
+      "reason": "selection"
+    },
+    {
+      "object": "InlineTextBox '1'",
+      "reason": "selection"
+    },
+    {
+      "object": "InlineTextBox '234'",
+      "reason": "selection"
+    },
+    {
+      "object": "LayoutSVGText text",
+      "reason": "selection"
+    },
+    {
+      "object": "LayoutSVGInlineText #text",
+      "reason": "selection"
+    },
+    {
+      "object": "InlineTextBox '1'",
+      "reason": "selection"
+    },
+    {
+      "object": "InlineTextBox '2'",
+      "reason": "selection"
+    },
+    {
+      "object": "InlineTextBox '3'",
+      "reason": "selection"
+    },
+    {
+      "object": "InlineTextBox '4'",
+      "reason": "selection"
+    },
+    {
+      "object": "LayoutSVGText text",
+      "reason": "selection"
+    },
+    {
+      "object": "LayoutSVGInlineText #text",
+      "reason": "selection"
+    },
+    {
+      "object": "InlineTextBox '1'",
+      "reason": "selection"
+    },
+    {
+      "object": "InlineTextBox '234'",
+      "reason": "selection"
+    },
+    {
+      "object": "LayoutSVGText text",
+      "reason": "selection"
+    },
+    {
+      "object": "LayoutSVGInlineText #text",
+      "reason": "selection"
+    },
+    {
+      "object": "InlineTextBox 'text-anchor'",
+      "reason": "selection"
+    },
+    {
+      "object": "LayoutSVGText text",
+      "reason": "selection"
+    },
+    {
+      "object": "LayoutSVGInlineText #text",
+      "reason": "selection"
+    },
+    {
+      "object": "InlineTextBox 'end'",
+      "reason": "selection"
+    },
+    {
+      "object": "LayoutSVGText text",
+      "reason": "selection"
+    },
+    {
+      "object": "LayoutSVGInlineText #text",
+      "reason": "selection"
+    },
+    {
+      "object": "InlineTextBox '1234'",
+      "reason": "selection"
+    },
+    {
+      "object": "LayoutSVGText text",
+      "reason": "selection"
+    },
+    {
+      "object": "LayoutSVGInlineText #text",
+      "reason": "selection"
+    },
+    {
+      "object": "InlineTextBox '1'",
+      "reason": "selection"
+    },
+    {
+      "object": "InlineTextBox '2'",
+      "reason": "selection"
+    },
+    {
+      "object": "InlineTextBox '3'",
+      "reason": "selection"
+    },
+    {
+      "object": "InlineTextBox '4'",
+      "reason": "selection"
+    },
+    {
+      "object": "LayoutSVGText text",
+      "reason": "selection"
+    },
+    {
+      "object": "LayoutSVGInlineText #text",
+      "reason": "selection"
+    },
+    {
+      "object": "InlineTextBox '1'",
+      "reason": "selection"
+    },
+    {
+      "object": "InlineTextBox '234'",
+      "reason": "selection"
+    },
+    {
+      "object": "LayoutSVGText text",
+      "reason": "selection"
+    },
+    {
+      "object": "LayoutSVGInlineText #text",
+      "reason": "selection"
+    },
+    {
+      "object": "InlineTextBox '1'",
+      "reason": "selection"
+    },
+    {
+      "object": "InlineTextBox '2'",
+      "reason": "selection"
+    },
+    {
+      "object": "InlineTextBox '3'",
+      "reason": "selection"
+    },
+    {
+      "object": "InlineTextBox '4'",
+      "reason": "selection"
+    },
+    {
+      "object": "LayoutSVGText text",
+      "reason": "selection"
+    },
+    {
+      "object": "LayoutSVGInlineText #text",
+      "reason": "selection"
+    },
+    {
+      "object": "InlineTextBox '1'",
+      "reason": "selection"
+    },
+    {
+      "object": "InlineTextBox '2'",
+      "reason": "selection"
+    },
+    {
+      "object": "InlineTextBox '3'",
+      "reason": "selection"
+    },
+    {
+      "object": "InlineTextBox '4'",
+      "reason": "selection"
+    },
+    {
+      "object": "LayoutSVGText text",
+      "reason": "selection"
+    },
+    {
+      "object": "LayoutSVGInlineText #text",
+      "reason": "selection"
+    },
+    {
+      "object": "InlineTextBox '1'",
+      "reason": "selection"
+    },
+    {
+      "object": "InlineTextBox '2'",
+      "reason": "selection"
+    },
+    {
+      "object": "InlineTextBox '3'",
+      "reason": "selection"
+    },
+    {
+      "object": "InlineTextBox '4'",
+      "reason": "selection"
+    },
+    {
+      "object": "LayoutSVGText text",
+      "reason": "selection"
+    },
+    {
+      "object": "LayoutSVGInlineText #text",
+      "reason": "selection"
+    },
+    {
+      "object": "InlineTextBox '1'",
+      "reason": "selection"
+    },
+    {
+      "object": "InlineTextBox '234'",
+      "reason": "selection"
+    },
+    {
+      "object": "LayoutSVGText text",
+      "reason": "selection"
+    },
+    {
+      "object": "LayoutSVGInlineText #text",
+      "reason": "selection"
+    },
+    {
+      "object": "InlineTextBox '1'",
+      "reason": "selection"
+    },
+    {
+      "object": "InlineTextBox '2'",
+      "reason": "selection"
+    },
+    {
+      "object": "InlineTextBox '3'",
+      "reason": "selection"
+    },
+    {
+      "object": "InlineTextBox '4'",
+      "reason": "selection"
+    },
+    {
+      "object": "LayoutSVGText text",
+      "reason": "selection"
+    },
+    {
+      "object": "LayoutSVGInlineText #text",
+      "reason": "selection"
+    },
+    {
+      "object": "InlineTextBox '1'",
+      "reason": "selection"
+    },
+    {
+      "object": "InlineTextBox '234'",
+      "reason": "selection"
+    },
+    {
+      "object": "LayoutSVGText text id='revision'",
+      "reason": "selection"
+    },
+    {
+      "object": "LayoutSVGInlineText #text",
+      "reason": "selection"
+    },
+    {
+      "object": "InlineTextBox '$Revision: 1.8 $'",
+      "reason": "selection"
+    }
+  ]
+}
+
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v175/paint/invalidation/svg/text-xy-updates-SVGList-expected.txt b/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v175/paint/invalidation/svg/text-xy-updates-SVGList-expected.txt
new file mode 100644
index 0000000..d9e9c1f
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v175/paint/invalidation/svg/text-xy-updates-SVGList-expected.txt
@@ -0,0 +1,41 @@
+{
+  "layers": [
+    {
+      "name": "LayoutView #document",
+      "bounds": [808, 621],
+      "contentsOpaque": true,
+      "backgroundColor": "#FFFFFF",
+      "paintInvalidations": [
+        {
+          "object": "InlineTextBox 'Passes, if text is at 200x20'",
+          "rect": [208, 13, 166, 19],
+          "reason": "appeared"
+        },
+        {
+          "object": "InlineTextBox 'Passes, if text is at 200x20'",
+          "rect": [18, 193, 166, 19],
+          "reason": "disappeared"
+        }
+      ]
+    }
+  ],
+  "objectPaintInvalidations": [
+    {
+      "object": "LayoutSVGText text id='ttt'",
+      "reason": "full"
+    },
+    {
+      "object": "RootInlineBox",
+      "reason": "full"
+    },
+    {
+      "object": "LayoutSVGInlineText #text",
+      "reason": "geometry"
+    },
+    {
+      "object": "InlineTextBox 'Passes, if text is at 200x20'",
+      "reason": "geometry"
+    }
+  ]
+}
+
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v175/paint/invalidation/svg/zoom-foreignObject-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v175/paint/invalidation/svg/zoom-foreignObject-expected.png
new file mode 100644
index 0000000..6368e49
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v175/paint/invalidation/svg/zoom-foreignObject-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v175/paint/invalidation/table/composited-table-background-col-expected.txt b/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v175/paint/invalidation/table/composited-table-background-col-expected.txt
new file mode 100644
index 0000000..24de1eb
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v175/paint/invalidation/table/composited-table-background-col-expected.txt
@@ -0,0 +1,33 @@
+{
+  "layers": [
+    {
+      "name": "LayoutView #document",
+      "bounds": [800, 600],
+      "contentsOpaque": true,
+      "backgroundColor": "#FFFFFF",
+      "paintInvalidations": [
+        {
+          "object": "LayoutTableSection TBODY",
+          "rect": [8, 28, 186, 134],
+          "reason": "style change"
+        }
+      ]
+    },
+    {
+      "name": "LayoutTableCell TD",
+      "position": [72, 96],
+      "bounds": [59, 64]
+    }
+  ],
+  "objectPaintInvalidations": [
+    {
+      "object": "LayoutTableSection TBODY",
+      "reason": "style change"
+    },
+    {
+      "object": "LayoutTableCol COL id='target'",
+      "reason": "style change"
+    }
+  ]
+}
+
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v175/paint/invalidation/table/composited-table-background-col-initial-empty-expected.txt b/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v175/paint/invalidation/table/composited-table-background-col-initial-empty-expected.txt
new file mode 100644
index 0000000..f655c36
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v175/paint/invalidation/table/composited-table-background-col-initial-empty-expected.txt
@@ -0,0 +1,33 @@
+{
+  "layers": [
+    {
+      "name": "LayoutView #document",
+      "bounds": [800, 600],
+      "contentsOpaque": true,
+      "backgroundColor": "#FFFFFF",
+      "paintInvalidations": [
+        {
+          "object": "LayoutTableSection TBODY",
+          "rect": [8, 28, 186, 134],
+          "reason": "appeared"
+        }
+      ]
+    },
+    {
+      "name": "LayoutTableCell TD",
+      "position": [72, 96],
+      "bounds": [59, 64]
+    }
+  ],
+  "objectPaintInvalidations": [
+    {
+      "object": "LayoutTableSection TBODY",
+      "reason": "style change"
+    },
+    {
+      "object": "LayoutTableCol COL id='target'",
+      "reason": "style change"
+    }
+  ]
+}
+
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v175/paint/invalidation/table/composited-table-background-col-span-expected.txt b/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v175/paint/invalidation/table/composited-table-background-col-span-expected.txt
new file mode 100644
index 0000000..27fcad36
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v175/paint/invalidation/table/composited-table-background-col-span-expected.txt
@@ -0,0 +1,38 @@
+{
+  "layers": [
+    {
+      "name": "LayoutView #document",
+      "bounds": [800, 600],
+      "contentsOpaque": true,
+      "backgroundColor": "#FFFFFF",
+      "paintInvalidations": [
+        {
+          "object": "LayoutTableSection TBODY",
+          "rect": [8, 28, 186, 134],
+          "reason": "style change"
+        }
+      ]
+    },
+    {
+      "name": "LayoutTableCell TD",
+      "position": [72, 96],
+      "bounds": [59, 64]
+    },
+    {
+      "name": "LayoutTableCell TD",
+      "position": [133, 96],
+      "bounds": [59, 64]
+    }
+  ],
+  "objectPaintInvalidations": [
+    {
+      "object": "LayoutTableSection TBODY",
+      "reason": "style change"
+    },
+    {
+      "object": "LayoutTableCol COL id='target'",
+      "reason": "style change"
+    }
+  ]
+}
+
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v175/paint/invalidation/table/composited-table-background-col-span-initial-empty-expected.txt b/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v175/paint/invalidation/table/composited-table-background-col-span-initial-empty-expected.txt
new file mode 100644
index 0000000..895c23e
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v175/paint/invalidation/table/composited-table-background-col-span-initial-empty-expected.txt
@@ -0,0 +1,38 @@
+{
+  "layers": [
+    {
+      "name": "LayoutView #document",
+      "bounds": [800, 600],
+      "contentsOpaque": true,
+      "backgroundColor": "#FFFFFF",
+      "paintInvalidations": [
+        {
+          "object": "LayoutTableSection TBODY",
+          "rect": [8, 28, 186, 134],
+          "reason": "appeared"
+        }
+      ]
+    },
+    {
+      "name": "LayoutTableCell TD",
+      "position": [72, 96],
+      "bounds": [59, 64]
+    },
+    {
+      "name": "LayoutTableCell TD",
+      "position": [133, 96],
+      "bounds": [59, 64]
+    }
+  ],
+  "objectPaintInvalidations": [
+    {
+      "object": "LayoutTableSection TBODY",
+      "reason": "style change"
+    },
+    {
+      "object": "LayoutTableCol COL id='target'",
+      "reason": "style change"
+    }
+  ]
+}
+
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v175/paint/invalidation/table/composited-table-background-colgroup-expected.txt b/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v175/paint/invalidation/table/composited-table-background-colgroup-expected.txt
new file mode 100644
index 0000000..955d91be
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v175/paint/invalidation/table/composited-table-background-colgroup-expected.txt
@@ -0,0 +1,33 @@
+{
+  "layers": [
+    {
+      "name": "LayoutView #document",
+      "bounds": [800, 600],
+      "contentsOpaque": true,
+      "backgroundColor": "#FFFFFF",
+      "paintInvalidations": [
+        {
+          "object": "LayoutTableSection TBODY",
+          "rect": [8, 28, 186, 134],
+          "reason": "style change"
+        }
+      ]
+    },
+    {
+      "name": "LayoutTableCell TD id='target'",
+      "position": [72, 96],
+      "bounds": [59, 64]
+    }
+  ],
+  "objectPaintInvalidations": [
+    {
+      "object": "LayoutTableSection TBODY",
+      "reason": "style change"
+    },
+    {
+      "object": "LayoutTableCol COLGROUP id='target'",
+      "reason": "style change"
+    }
+  ]
+}
+
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v175/paint/invalidation/table/composited-table-background-colgroup-initial-empty-expected.txt b/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v175/paint/invalidation/table/composited-table-background-colgroup-initial-empty-expected.txt
new file mode 100644
index 0000000..072141d
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v175/paint/invalidation/table/composited-table-background-colgroup-initial-empty-expected.txt
@@ -0,0 +1,33 @@
+{
+  "layers": [
+    {
+      "name": "LayoutView #document",
+      "bounds": [800, 600],
+      "contentsOpaque": true,
+      "backgroundColor": "#FFFFFF",
+      "paintInvalidations": [
+        {
+          "object": "LayoutTableSection TBODY",
+          "rect": [8, 28, 186, 134],
+          "reason": "appeared"
+        }
+      ]
+    },
+    {
+      "name": "LayoutTableCell TD id='target'",
+      "position": [72, 96],
+      "bounds": [59, 64]
+    }
+  ],
+  "objectPaintInvalidations": [
+    {
+      "object": "LayoutTableSection TBODY",
+      "reason": "style change"
+    },
+    {
+      "object": "LayoutTableCol COLGROUP id='target'",
+      "reason": "style change"
+    }
+  ]
+}
+
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v175/paint/invalidation/table/composited-table-background-composited-row-initial-empty-expected.txt b/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v175/paint/invalidation/table/composited-table-background-composited-row-initial-empty-expected.txt
new file mode 100644
index 0000000..650f4e7c
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v175/paint/invalidation/table/composited-table-background-composited-row-initial-empty-expected.txt
@@ -0,0 +1,35 @@
+{
+  "layers": [
+    {
+      "name": "LayoutView #document",
+      "bounds": [800, 600],
+      "contentsOpaque": true,
+      "backgroundColor": "#FFFFFF"
+    },
+    {
+      "name": "LayoutTableRow TR id='target'",
+      "position": [8, 96],
+      "bounds": [186, 64],
+      "backgroundColor": "#ADD8E6",
+      "paintInvalidations": [
+        {
+          "object": "LayoutTableRow TR id='target'",
+          "rect": [0, 0, 186, 64],
+          "reason": "appeared"
+        }
+      ]
+    },
+    {
+      "name": "LayoutTableCell TD",
+      "position": [72, 96],
+      "bounds": [59, 64]
+    }
+  ],
+  "objectPaintInvalidations": [
+    {
+      "object": "LayoutTableRow TR id='target'",
+      "reason": "style change"
+    }
+  ]
+}
+
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v175/paint/invalidation/table/composited-table-background-initial-empty-expected.txt b/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v175/paint/invalidation/table/composited-table-background-initial-empty-expected.txt
new file mode 100644
index 0000000..3fc3780
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v175/paint/invalidation/table/composited-table-background-initial-empty-expected.txt
@@ -0,0 +1,29 @@
+{
+  "layers": [
+    {
+      "name": "LayoutView #document",
+      "bounds": [800, 600],
+      "contentsOpaque": true,
+      "backgroundColor": "#FFFFFF",
+      "paintInvalidations": [
+        {
+          "object": "LayoutTableRow TR id='target'",
+          "rect": [8, 96, 186, 64],
+          "reason": "appeared"
+        }
+      ]
+    },
+    {
+      "name": "LayoutTableCell TD",
+      "position": [72, 96],
+      "bounds": [59, 64]
+    }
+  ],
+  "objectPaintInvalidations": [
+    {
+      "object": "LayoutTableRow TR id='target'",
+      "reason": "style change"
+    }
+  ]
+}
+
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v175/paint/invalidation/table/composited-table-background-section-composited-row-initial-empty-expected.txt b/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v175/paint/invalidation/table/composited-table-background-section-composited-row-initial-empty-expected.txt
new file mode 100644
index 0000000..edf7608
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v175/paint/invalidation/table/composited-table-background-section-composited-row-initial-empty-expected.txt
@@ -0,0 +1,40 @@
+{
+  "layers": [
+    {
+      "name": "LayoutView #document",
+      "bounds": [800, 600],
+      "contentsOpaque": true,
+      "backgroundColor": "#FFFFFF"
+    },
+    {
+      "name": "LayoutTableSection TBODY id='target'",
+      "position": [8, 28],
+      "bounds": [186, 134],
+      "backgroundColor": "#ADD8E6",
+      "paintInvalidations": [
+        {
+          "object": "LayoutTableSection TBODY id='target'",
+          "rect": [0, 0, 186, 134],
+          "reason": "appeared"
+        }
+      ]
+    },
+    {
+      "name": "LayoutTableRow TR",
+      "position": [8, 96],
+      "bounds": [186, 64]
+    },
+    {
+      "name": "LayoutTableCell TD",
+      "position": [72, 96],
+      "bounds": [59, 64]
+    }
+  ],
+  "objectPaintInvalidations": [
+    {
+      "object": "LayoutTableSection TBODY id='target'",
+      "reason": "style change"
+    }
+  ]
+}
+
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v175/paint/invalidation/table/composited-table-background-section-initial-empty-expected.txt b/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v175/paint/invalidation/table/composited-table-background-section-initial-empty-expected.txt
new file mode 100644
index 0000000..30ca6bd7
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v175/paint/invalidation/table/composited-table-background-section-initial-empty-expected.txt
@@ -0,0 +1,35 @@
+{
+  "layers": [
+    {
+      "name": "LayoutView #document",
+      "bounds": [800, 600],
+      "contentsOpaque": true,
+      "backgroundColor": "#FFFFFF"
+    },
+    {
+      "name": "LayoutTableSection TBODY id='target'",
+      "position": [8, 28],
+      "bounds": [186, 134],
+      "backgroundColor": "#ADD8E6",
+      "paintInvalidations": [
+        {
+          "object": "LayoutTableSection TBODY id='target'",
+          "rect": [0, 0, 186, 134],
+          "reason": "appeared"
+        }
+      ]
+    },
+    {
+      "name": "LayoutTableCell TD",
+      "position": [72, 96],
+      "bounds": [59, 64]
+    }
+  ],
+  "objectPaintInvalidations": [
+    {
+      "object": "LayoutTableSection TBODY id='target'",
+      "reason": "style change"
+    }
+  ]
+}
+
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v175/paint/invalidation/textarea-caret-expected.txt b/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v175/paint/invalidation/textarea-caret-expected.txt
index e40dcb65..eb673923 100644
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v175/paint/invalidation/textarea-caret-expected.txt
+++ b/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v175/paint/invalidation/textarea-caret-expected.txt
@@ -53,7 +53,7 @@
       "reason": "scroll control"
     },
     {
-      "object": "LayoutBlockFlow DIV id='inner-editor'",
+      "object": "LayoutBlockFlow DIV",
       "reason": "subtree"
     },
     {
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v175/paint/invalidation/textarea-set-disabled-expected.txt b/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v175/paint/invalidation/textarea-set-disabled-expected.txt
index 5338c079..817259d 100644
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v175/paint/invalidation/textarea-set-disabled-expected.txt
+++ b/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v175/paint/invalidation/textarea-set-disabled-expected.txt
@@ -20,7 +20,7 @@
       "reason": "subtree"
     },
     {
-      "object": "LayoutBlockFlow DIV id='inner-editor'",
+      "object": "LayoutBlockFlow DIV",
       "reason": "subtree"
     }
   ]
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v175/paint/invalidation/video-mute-repaint-expected.txt b/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v175/paint/invalidation/video-mute-repaint-expected.txt
new file mode 100644
index 0000000..77fd793d
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v175/paint/invalidation/video-mute-repaint-expected.txt
@@ -0,0 +1,89 @@
+{
+  "layers": [
+    {
+      "name": "LayoutView #document",
+      "bounds": [800, 600],
+      "contentsOpaque": true,
+      "backgroundColor": "#FFFFFF"
+    },
+    {
+      "name": "LayoutVideo VIDEO id='v'",
+      "position": [8, 8],
+      "bounds": [700, 525],
+      "drawsContent": false
+    },
+    {
+      "name": "Squashing Containment Layer",
+      "drawsContent": false
+    },
+    {
+      "name": "LayoutFlexibleBox (relative positioned) DIV class='phase-ready state-stopped'",
+      "position": [8, 8],
+      "bounds": [700, 525]
+    },
+    {
+      "name": "Squashing Layer (first squashed layer: LayoutFlexibleBox (relative positioned) DIV)",
+      "position": [8, 8],
+      "bounds": [700, 525],
+      "paintInvalidations": [
+        {
+          "object": "LayoutFlexibleBox (relative positioned) DIV",
+          "rect": [0, 493, 700, 32],
+          "reason": "paint property change"
+        },
+        {
+          "object": "LayoutBlockFlow (positioned) DIV",
+          "rect": [108, 508, 404, 2],
+          "reason": "paint property change"
+        },
+        {
+          "object": "LayoutBlockFlow (positioned) DIV",
+          "rect": [580, 508, 70, 2],
+          "reason": "disappeared"
+        },
+        {
+          "object": "LayoutBlockFlow (positioned) DIV id='thumb'",
+          "rect": [632, 493, 36, 32],
+          "reason": "paint property change"
+        },
+        {
+          "object": "LayoutBlockFlow (positioned) DIV id='thumb'",
+          "rect": [562, 493, 36, 32],
+          "reason": "paint property change"
+        },
+        {
+          "object": "LayoutBlockFlow (positioned) DIV id='thumb'",
+          "rect": [90, 493, 36, 32],
+          "reason": "paint property change"
+        }
+      ]
+    }
+  ],
+  "objectPaintInvalidations": [
+    {
+      "object": "LayoutVideo VIDEO id='v'",
+      "reason": "style change"
+    },
+    {
+      "object": "LayoutFlexibleBox (relative positioned) DIV class='phase-ready state-stopped'",
+      "reason": "geometry"
+    },
+    {
+      "object": "LayoutButton INPUT class='muted'",
+      "reason": "full"
+    },
+    {
+      "object": "LayoutFlexibleBox DIV",
+      "reason": "geometry"
+    },
+    {
+      "object": "LayoutBlockFlow (positioned) DIV id='thumb'",
+      "reason": "full"
+    },
+    {
+      "object": "LayoutBlockFlow (positioned) DIV",
+      "reason": "disappeared"
+    }
+  ]
+}
+
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v175/paint/invalidation/video-unmute-repaint-expected.txt b/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v175/paint/invalidation/video-unmute-repaint-expected.txt
new file mode 100644
index 0000000..6ce2aeaf
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v175/paint/invalidation/video-unmute-repaint-expected.txt
@@ -0,0 +1,89 @@
+{
+  "layers": [
+    {
+      "name": "LayoutView #document",
+      "bounds": [800, 600],
+      "contentsOpaque": true,
+      "backgroundColor": "#FFFFFF"
+    },
+    {
+      "name": "LayoutVideo VIDEO id='v'",
+      "position": [8, 8],
+      "bounds": [700, 525],
+      "drawsContent": false
+    },
+    {
+      "name": "Squashing Containment Layer",
+      "drawsContent": false
+    },
+    {
+      "name": "LayoutFlexibleBox (relative positioned) DIV class='phase-ready state-stopped'",
+      "position": [8, 8],
+      "bounds": [700, 525]
+    },
+    {
+      "name": "Squashing Layer (first squashed layer: LayoutFlexibleBox (relative positioned) DIV)",
+      "position": [8, 8],
+      "bounds": [700, 525],
+      "paintInvalidations": [
+        {
+          "object": "LayoutFlexibleBox (relative positioned) DIV",
+          "rect": [0, 493, 700, 32],
+          "reason": "paint property change"
+        },
+        {
+          "object": "LayoutBlockFlow (positioned) DIV",
+          "rect": [108, 508, 404, 2],
+          "reason": "paint property change"
+        },
+        {
+          "object": "LayoutBlockFlow (positioned) DIV id='thumb'",
+          "rect": [597, 493, 36, 32],
+          "reason": "paint property change"
+        },
+        {
+          "object": "LayoutBlockFlow (positioned) DIV id='thumb'",
+          "rect": [562, 493, 36, 32],
+          "reason": "paint property change"
+        },
+        {
+          "object": "LayoutBlockFlow (positioned) DIV id='thumb'",
+          "rect": [90, 493, 36, 32],
+          "reason": "paint property change"
+        },
+        {
+          "object": "LayoutBlockFlow (positioned) DIV",
+          "rect": [580, 508, 35, 2],
+          "reason": "appeared"
+        }
+      ]
+    }
+  ],
+  "objectPaintInvalidations": [
+    {
+      "object": "LayoutVideo VIDEO id='v'",
+      "reason": "style change"
+    },
+    {
+      "object": "LayoutFlexibleBox (relative positioned) DIV class='phase-ready state-stopped'",
+      "reason": "geometry"
+    },
+    {
+      "object": "LayoutButton INPUT",
+      "reason": "full"
+    },
+    {
+      "object": "LayoutFlexibleBox DIV",
+      "reason": "geometry"
+    },
+    {
+      "object": "LayoutBlockFlow (positioned) DIV id='thumb'",
+      "reason": "full"
+    },
+    {
+      "object": "LayoutBlockFlow (positioned) DIV",
+      "reason": "appeared"
+    }
+  ]
+}
+
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v175/paint/printing/print-box-shadow-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v175/paint/printing/print-box-shadow-expected.png
new file mode 100644
index 0000000..5325356
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v175/paint/printing/print-box-shadow-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v175/paint/selection/text-selection-newline-mixed-ltr-rtl-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v175/paint/selection/text-selection-newline-mixed-ltr-rtl-expected.png
new file mode 100644
index 0000000..61fc56f
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v175/paint/selection/text-selection-newline-mixed-ltr-rtl-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v2/paint/invalidation/caret-subpixel-expected.txt b/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v2/paint/invalidation/caret-subpixel-expected.txt
index 67849d0..d688375 100644
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v2/paint/invalidation/caret-subpixel-expected.txt
+++ b/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v2/paint/invalidation/caret-subpixel-expected.txt
@@ -12,7 +12,7 @@
           "reason": "subtree"
         },
         {
-          "object": "LayoutBlockFlow DIV id='inner-editor'",
+          "object": "LayoutBlockFlow DIV",
           "rect": [209, 11, 2, 16],
           "reason": "appeared"
         }
@@ -25,7 +25,7 @@
       "reason": "subtree"
     },
     {
-      "object": "LayoutBlockFlow DIV id='inner-editor'",
+      "object": "LayoutBlockFlow DIV",
       "reason": "subtree"
     },
     {
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v2/paint/invalidation/change-text-content-and-background-color-expected.txt b/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v2/paint/invalidation/change-text-content-and-background-color-expected.txt
index 2d901d5..e07f2a18 100644
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v2/paint/invalidation/change-text-content-and-background-color-expected.txt
+++ b/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v2/paint/invalidation/change-text-content-and-background-color-expected.txt
@@ -30,7 +30,7 @@
       "reason": "style change"
     },
     {
-      "object": "LayoutBlockFlow DIV id='inner-editor'",
+      "object": "LayoutBlockFlow DIV",
       "reason": "geometry"
     },
     {
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v2/paint/invalidation/details-open-repaint-expected.txt b/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v2/paint/invalidation/details-open-repaint-expected.txt
index 033e571..11ead38 100644
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v2/paint/invalidation/details-open-repaint-expected.txt
+++ b/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v2/paint/invalidation/details-open-repaint-expected.txt
@@ -37,11 +37,11 @@
       "reason": "appeared"
     },
     {
-      "object": "LayoutBlockFlow DIV id='inner-editor'",
+      "object": "LayoutBlockFlow DIV",
       "reason": "appeared"
     },
     {
-      "object": "LayoutBlockFlow DIV id='inner-editor'",
+      "object": "LayoutBlockFlow DIV",
       "reason": "geometry"
     },
     {
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v2/paint/invalidation/multi-layout-one-frame-expected.txt b/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v2/paint/invalidation/multi-layout-one-frame-expected.txt
index 22f0d81..a7074c1 100644
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v2/paint/invalidation/multi-layout-one-frame-expected.txt
+++ b/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v2/paint/invalidation/multi-layout-one-frame-expected.txt
@@ -31,7 +31,7 @@
   ],
   "objectPaintInvalidations": [
     {
-      "object": "LayoutBlockFlow DIV id='inner-editor'",
+      "object": "LayoutBlockFlow DIV",
       "reason": "geometry"
     },
     {
@@ -47,7 +47,7 @@
       "reason": "full"
     },
     {
-      "object": "LayoutBlockFlow DIV id='inner-editor'",
+      "object": "LayoutBlockFlow DIV",
       "reason": "geometry"
     },
     {
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v2/paint/invalidation/search-field-cancel-expected.txt b/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v2/paint/invalidation/search-field-cancel-expected.txt
index f8caeb14..8f1e97c 100644
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v2/paint/invalidation/search-field-cancel-expected.txt
+++ b/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v2/paint/invalidation/search-field-cancel-expected.txt
@@ -7,7 +7,7 @@
       "backgroundColor": "#FFFFFF",
       "paintInvalidations": [
         {
-          "object": "LayoutBlockFlow DIV id='inner-editor'",
+          "object": "LayoutBlockFlow DIV",
           "rect": [11, 47, 58, 16],
           "reason": "appeared"
         }
@@ -16,7 +16,7 @@
   ],
   "objectPaintInvalidations": [
     {
-      "object": "LayoutBlockFlow DIV id='inner-editor'",
+      "object": "LayoutBlockFlow DIV",
       "reason": "geometry"
     },
     {
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v2/paint/invalidation/subtree-root-skipped-expected.txt b/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v2/paint/invalidation/subtree-root-skipped-expected.txt
index afe540b3..4412e1b 100644
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v2/paint/invalidation/subtree-root-skipped-expected.txt
+++ b/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v2/paint/invalidation/subtree-root-skipped-expected.txt
@@ -26,7 +26,7 @@
   ],
   "objectPaintInvalidations": [
     {
-      "object": "LayoutBlockFlow DIV id='inner-editor'",
+      "object": "LayoutBlockFlow DIV",
       "reason": "geometry"
     },
     {
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v2/paint/invalidation/textarea-set-disabled-expected.txt b/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v2/paint/invalidation/textarea-set-disabled-expected.txt
index 5338c079..817259d 100644
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v2/paint/invalidation/textarea-set-disabled-expected.txt
+++ b/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v2/paint/invalidation/textarea-set-disabled-expected.txt
@@ -20,7 +20,7 @@
       "reason": "subtree"
     },
     {
-      "object": "LayoutBlockFlow DIV id='inner-editor'",
+      "object": "LayoutBlockFlow DIV",
       "reason": "subtree"
     }
   ]
diff --git a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/fast/events/touch/compositor-touch-hit-rects-animation-expected.txt b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/fast/events/touch/compositor-touch-hit-rects-animation-expected.txt
new file mode 100644
index 0000000..c4fb6a0
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/fast/events/touch/compositor-touch-hit-rects-animation-expected.txt
@@ -0,0 +1,12 @@
+This test verifies the hit test regions are updated correctly when composited layer are created and destroyed without triggering layout update during fast path animation.
+
+[object HTMLDivElement]: #document scrolling (200, 200, 50, 50)
+
+[object HTMLDivElement]: DIV#box (0, 0, 50, 50)
+
+[object HTMLDivElement]: #document scrolling (175, 175, 100, 100)
+
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
diff --git a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/fast/events/touch/compositor-touch-hit-rects-expected.txt b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/fast/events/touch/compositor-touch-hit-rects-expected.txt
new file mode 100644
index 0000000..5bb3d9cc
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/fast/events/touch/compositor-touch-hit-rects-expected.txt
@@ -0,0 +1,49 @@
+This tests verifies the hit test regions given to the compositor. It can only be run in DumpRenderTree. The outputted rects should cover the hit test regions of all the listed elements. Enable visualize mode to quickly validate graphically.
+
+normalFlow: #document scrolling (13, 128, 290, 12)
+
+inlineOverflow: #document scrolling (13, 145, 152, 12)
+inlineOverflow: #document scrolling (13, 157, 42, 10)
+
+absoluteChildContainer: #document scrolling (13, 172, 290, 12)
+absoluteChildContainer: #document scrolling (320, 173, 142, 12)
+
+relativeChildContainer: #document scrolling (13, 189, 290, 22)
+relativeChildContainer: #document scrolling (314, 199, 142, 12)
+
+fixed: #document scrolling (405, 98, 52, 12)
+
+translate: #document scrolling (13, 216, 290, 14)
+translate: #document scrolling (314, 219, 288, 12)
+
+transform2d: #document scrolling (16, 236, 284, 20)
+
+overhangingContainer: #document scrolling (13, 262, 290, 12)
+overhangingContainer: #document scrolling (14, 274, 102, 10)
+overhangingContainer: #document scrolling (14, 284, 111, 10)
+overhangingContainer: #document scrolling (14, 294, 102, 11)
+
+transform3d: DIV#transform3dChild (0, 0, 288, 12)
+transform3d: #document scrolling (13, 315, 290, 14)
+
+negativeOffsetChild: DIV#withNegativeOffsetChild[109,0] (0, 1, 102, 12)
+
+continuation: #document scrolling (13, 355, 101, 11)
+continuation: #document scrolling (13, 366, 290, 12)
+continuation: #document scrolling (13, 378, 121, 11)
+
+inlineAbsoluteChildContainer: #document scrolling (13, 392, 262, 12)
+inlineAbsoluteChildContainer: #document scrolling (320, 393, 252, 12)
+
+list: #document scrolling (13, 413, 290, 14)
+list: #document scrolling (341, 414, 261, 12)
+
+styleModified: #document scrolling (13, 437, 290, 22)
+
+containsSvg: #document scrolling (13, 464, 290, 16)
+
+svgline: #document scrolling (13, 485, 100, 10)
+
+tablecell: #document scrolling (45, 518, 32, 11)
+
+
diff --git a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/fast/events/touch/compositor-touch-hit-rects-global-expected.txt b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/fast/events/touch/compositor-touch-hit-rects-global-expected.txt
new file mode 100644
index 0000000..d41b3708e
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/fast/events/touch/compositor-touch-hit-rects-global-expected.txt
@@ -0,0 +1,11 @@
+This tests verifies the hit test regions given to the compositor in the simple case where touch handles cover (or nearly cover) the entire document. It can only be run in DumpRenderTree.
+
+document: #document (0, 0, 800, 600)
+
+html: #document (0, 0, 800, 600)
+
+body: #document (0, 0, 800, 600)
+
+webPageOverlay: no rects
+
+
diff --git a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/fast/events/touch/compositor-touch-hit-rects-non-composited-scroll-expected.txt b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/fast/events/touch/compositor-touch-hit-rects-non-composited-scroll-expected.txt
new file mode 100644
index 0000000..22f1582
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/fast/events/touch/compositor-touch-hit-rects-non-composited-scroll-expected.txt
@@ -0,0 +1,23 @@
+This test verifies the hit test regions given to the compositor specifically around non-composited overflow scroll elements.
+
+scrollContent: #document scrolling (13, 52, 290, 32)
+
+scrollContainerWithHandler: #document scrolling (13, 89, 290, 32)
+
+nestedContent: #document scrolling (13, 126, 290, 32)
+nestedContent: #document scrolling (15, 158, 256, 2)
+
+fixedPositionContentContainer: #document scrolling (13, 168, 290, 32)
+fixedPositionContentContainer: #document scrolling (310, 190, 132, 12)
+
+overflowwithhandler: #document scrolling (13, 210, 290, 32)
+overflowwithhandler: #document scrolling (14, 242, 273, 6)
+
+divInsideNonScrollableLayer: #document scrolling (13, 252, 290, 32)
+divInsideNonScrollableLayer: #document scrolling (14, 284, 273, 1)
+
+divInsideCompositedLayer: DIV#compositedLayer (0, 10, 273, 12)
+
+overflowwithborder: #document scrolling (13, 336, 290, 50)
+
+
diff --git a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/fast/events/touch/compositor-touch-hit-rects-transform-changed-nolayout-expected.txt b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/fast/events/touch/compositor-touch-hit-rects-transform-changed-nolayout-expected.txt
new file mode 100644
index 0000000..1f7a9186
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/fast/events/touch/compositor-touch-hit-rects-transform-changed-nolayout-expected.txt
@@ -0,0 +1,7 @@
+This test verifies the touch event target rects are updated correctly when an element transfroms without causing layout.
+
+[object HTMLDivElement]: #document scrolling (100, 100, 50, 50)
+
+[object HTMLDivElement]: #document scrolling (150, 100, 50, 50)
+
+
diff --git a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/absolute-display-block-to-none-expected.html b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/absolute-display-block-to-none-expected.html
deleted file mode 100644
index 62ecb863..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/absolute-display-block-to-none-expected.html
+++ /dev/null
@@ -1,2 +0,0 @@
-<!DOCTYPE html>
-When an absolute positioned element is set display:none, we should not invalidate the whole body.
diff --git a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/absolute-margin-change-repaint-expected.html b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/absolute-margin-change-repaint-expected.html
deleted file mode 100644
index 10d9fd7..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/absolute-margin-change-repaint-expected.html
+++ /dev/null
@@ -1,23 +0,0 @@
-<!DOCTYPE HTML>
-<style>
-    body {
-        margin: 0;
-    }
-    #container {
-        position: relative;
-        top: 40px;
-        width: 200px;
-        height: 400px;
-    }
-    #test {
-        position: absolute;
-        background-color: green;
-        width: 100px;
-        height: 100px;
-        margin-top: 20px;
-    }
-</style>
-<div id="container">
-    <div id="test"></div>
-</div>
-Tests the repainting of absolute element when margin-top changes.
diff --git a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/absolute-position-change-containing-block-expected.html b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/absolute-position-change-containing-block-expected.html
deleted file mode 100644
index 7c2a0f6..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/absolute-position-change-containing-block-expected.html
+++ /dev/null
@@ -1,9 +0,0 @@
-<html>
-<head>
-    <link rel="stylesheet" href="resources/default.css">
-</head>
-<body style="height:2000px;">
-    <!-- You should see 2 overlapping rectangles in the output: a green one (on top) and a blue one. -->
-    <div id="container" style="top: 5000px;" class="blue"><div style="top:100px; left:100px;" class="absolute green"></div></div>
-</body>
-</html>
diff --git a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/absolute-position-moved-expected.html b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/absolute-position-moved-expected.html
deleted file mode 100644
index 48e848d..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/absolute-position-moved-expected.html
+++ /dev/null
@@ -1,9 +0,0 @@
-<html>
-<head>
-    <link rel="stylesheet" href="resources/default.css">
-</head>
-<body style="height:2000px;">
-    <!-- You should see 1 green rectangle in the output and no red. -->
-    <div id="absoluteDiv" style="top:100px; left:100px;" class="absolute green"></div>
-</body>
-</html>
diff --git a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/abspos-shift-image-incorrect-repaint-expected.html b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/abspos-shift-image-incorrect-repaint-expected.html
deleted file mode 100644
index 2a5bcd5..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/abspos-shift-image-incorrect-repaint-expected.html
+++ /dev/null
@@ -1,33 +0,0 @@
-<!DOCTYPE html>
-<html xmlns="http://www.w3.org/1999/xhtml" lang="en">
-<head>
-<style>
-.imageWrapper
-{
-    position: relative;
-    display: inline-block;
-    width: 700px;
-}
-
-#shiftMe
-{
-    position: absolute;
-    top: 0px;
-    left: -250px;
-    width: 1500px;
-}
-</style>
-</head>
-<body>
-    <div>This test checks that shifting an abspos container will properly repaint its descendants.</div>
-    <div>The images below should be correctly repainted.</div>
-    <div id="shiftMe">
-        <div class="imageWrapper">
-            <img src="resources/apple.jpg">
-        </div>
-        <div class="imageWrapper">
-            <img src="resources/apple.jpg">
-        </div>
-    </div>
-</body>
-</html>
diff --git a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/add-table-overpaint-expected.html b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/add-table-overpaint-expected.html
deleted file mode 100644
index 45ffc93..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/add-table-overpaint-expected.html
+++ /dev/null
@@ -1,25 +0,0 @@
-
-<!DOCTYPE html>
-<html>
-<body style="margin: 0px">
-<style>
-td {
-  height: 150px;
-  width: 150px;
-  background-color: blue;
-}
-</style>
-<!-- This test adds 3 tables do the document.  Adding the 3rd table should not cause the first table to repaint. -->
-<div id="container">
-  <div>
-    <table><td></td></table>
-  </div>
-  <div>
-    <table><td></td></table>
-  </div>
-  <div>
-    <table><td></td></table>
-  </div>
-</div>
-</body>
-</html>
diff --git a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/align-content-change-expected.html b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/align-content-change-expected.html
deleted file mode 100644
index c189fab..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/align-content-change-expected.html
+++ /dev/null
@@ -1,28 +0,0 @@
-<!DOCTYPE HTML>
-<style>
-body {
-  margin: 0;
-}
-#container {
-  display: flex;
-  align-content: stretch;
-  flex-flow: row wrap;
-  width: 200px;
-  height: 300px;
-  background-color: red;
-}
-.item {
-  background-color: green;
-  border: solid thin blue;
-  width: 200px;
-}
-</style>
-<p style="height: 20px">Tests invalidation on align-content style change. Passes if there is no red.</p>
-<div id="container">
-  <div class="item">
-    <div style="height: 50px"></div>
-  </div>
-  <div class="item">
-    <div style="height: 50px"></div>
-  </div>
-</div>
diff --git a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/align-content-change-keeping-geometry-expected.html b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/align-content-change-keeping-geometry-expected.html
deleted file mode 100644
index 56d3b4c..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/align-content-change-keeping-geometry-expected.html
+++ /dev/null
@@ -1,21 +0,0 @@
-<!DOCTYPE HTML>
-<style>
-#container {
-  display: flex;
-  align-items: flex-start;
-  width: 200px;
-  height: 300px;
-  background-color: red;
-}
-.item {
-  background-color: green;
-  border: solid thin blue;
-  width: 100px;
-  height: 300px;
-}
-</style>
-<p style="height: 20px">There should be no invalidations because align-content style change causes no visual change.</p>
-<div id="container">
-  <div class="item"></div>
-  <div class="item"></div>
-</div>
diff --git a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/align-content-change-no-flex-expected.html b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/align-content-change-no-flex-expected.html
deleted file mode 100644
index 60f1276..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/align-content-change-no-flex-expected.html
+++ /dev/null
@@ -1,22 +0,0 @@
-<!DOCTYPE HTML>
-<style>
-.container {
-  width: 200px;
-  height: 300px;
-  background-color: blue;
-  align-content: flex-end;
-}
-.item {
-  background-color: green;
-  border: solid thin blue;
-}
-</style>
-There should be no invalidations when align-content changes on a non-flex container.
-<div id="container">
-  <div class="item">
-    <div style="height: 100px"></div>
-  </div>
-  <div class="item">
-    <div style="height: 150px"></div>
-  </div>
-</div>
diff --git a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/align-content-distribution-change-grid-expected.html b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/align-content-distribution-change-grid-expected.html
deleted file mode 100644
index b399d0ed..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/align-content-distribution-change-grid-expected.html
+++ /dev/null
@@ -1,30 +0,0 @@
-<!DOCTYPE HTML>
-<style>
-body {
-  margin: 0;
-}
-#container {
-  display: grid;
-  grid-auto-columns: 200px;
-  grid-auto-rows: auto;
-  grid-auto-flow: row;
-  align-content: stretch;
-  width: 200px;
-  height: 300px;
-}
-.item {
-  background-color: green;
-}
-</style>
-<p style="height: 20px">Tests invalidation on align-content style change (distribution). Passes if there is no red.</p>
-<div id="container">
-  <div class="item">
-    <div style="height: 50px"></div>
-  </div>
-  <div class="item">
-    <div style="height: 50px"></div>
-  </div>
-  <div class="item">
-    <div style="height: 50px"></div>
-  </div>
-</div>
diff --git a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/align-content-position-change-grid-expected.html b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/align-content-position-change-grid-expected.html
deleted file mode 100644
index a4aec8d..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/align-content-position-change-grid-expected.html
+++ /dev/null
@@ -1,31 +0,0 @@
-<!DOCTYPE HTML>
-<style>
-body {
-  margin: 0;
-}
-#container {
-  display: grid;
-  grid-auto-columns: 200px;
-  grid-auto-rows: auto;
-  grid-auto-flow: row;
-  align-content: end;
-  width: 200px;
-  height: 300px;
-  background-color: orange;
-}
-.item {
-  background-color: green;
-}
-</style>
-<p style="height: 20px">Tests invalidation on align-content style change (position). Passes if the orange half is on the top.</p>
-<div id="container">
-  <div class="item">
-    <div style="height: 50px"></div>
-  </div>
-  <div class="item">
-    <div style="height: 50px"></div>
-  </div>
-  <div class="item">
-    <div style="height: 50px"></div>
-  </div>
-</div>
diff --git a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/align-items-change-expected.html b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/align-items-change-expected.html
deleted file mode 100644
index 8285627e..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/align-items-change-expected.html
+++ /dev/null
@@ -1,27 +0,0 @@
-<!DOCTYPE HTML>
-<style>
-body {
-  margin: 0;
-}
-#container {
-  display: flex;
-  align-items: stretch;
-  width: 200px;
-  height: 300px;
-  background-color: red;
-}
-.item {
-  background-color: green;
-  border: solid thin blue;
-  width: 100px;
-}
-</style>
-<p style="height: 20px">Tests invalidation on align-items style change. Passes if there is no red.</p>
-<div id="container">
-  <div class="item">
-    <div style="height: 100px"></div>
-  </div>
-  <div class="item">
-    <div style="height: 150px"></div>
-  </div>
-</div>
diff --git a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/align-items-overflow-change-expected.html b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/align-items-overflow-change-expected.html
deleted file mode 100644
index 6ffb231..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/align-items-overflow-change-expected.html
+++ /dev/null
@@ -1,33 +0,0 @@
-<!DOCTYPE HTML>
-<style>
-body {
-  margin: 0;
-}
-#container {
-  display: grid;
-  grid: 150px 150px / 200px;
-  align-items: end safe;
-  width: 200px;
-  height: 300px;
-  background-color: red;
-}
-.item1 {
-  grid-row: 1;
-  grid-column: 1;
-  background-color: green;
-}
-.item2 {
-  grid-row: 2;
-  grid-column: 1;
-  background-color: green;
-}
-</style>
-<p style="height: 20px">Tests invalidation on align-items style change (just overflow). Passes if there is no red.</p>
-<div id="container">
-    <div class="item1">
-        <div style="height: 200px"></div>
-    </div>
-    <div class="item2">
-        <div style="height: 100px"></div>
-    </div>
-</div>
diff --git a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/align-self-change-expected.html b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/align-self-change-expected.html
deleted file mode 100644
index e7e9a83f..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/align-self-change-expected.html
+++ /dev/null
@@ -1,28 +0,0 @@
-<!DOCTYPE HTML>
-<style>
-body {
-  margin: 0;
-}
-.flex {
-  display: flex;
-  align-items: flex-start;
-  width: 200px;
-  height: 300px;
-  background-color: red;
-}
-.item {
-  background-color: green;
-  border: solid thin blue;
-  width: 100px;
-  align-self: stretch;
-}
-</style>
-<p style="height: 20px">Tests invalidation on align-self style change. Passes if there is no red.</p>
-<div class="flex">
-  <div class="item">
-    <div style="height: 100px"></div>
-  </div>
-  <div class="item">
-    <div style="height: 150px"></div>
-  </div>
-</div>
diff --git a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/align-self-change-grid-expected.html b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/align-self-change-grid-expected.html
deleted file mode 100644
index 6be1978..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/align-self-change-grid-expected.html
+++ /dev/null
@@ -1,42 +0,0 @@
-<!DOCTYPE HTML>
-<style>
-body {
-  margin: 0;
-}
-#container {
-  display: grid;
-  grid: 300px / 100px 100px;
-  width: 200px;
-  height: 300px;
-}
-.item1 {
-  grid-row: 1;
-  grid-column: 1;
-  align-self: stretch;
-  background-color: green;
-}
-.item2 {
-  grid-row: 1;
-  grid-column: 2;
-  align-self: start;
-  background-color: green;
-}
-.item3 {
-  grid-row: 1;
-  grid-column: 2;
-  align-self: end;
-  background-color: green;
-}
-</style>
-<p style="height: 20px">Tests invalidation on align-self style change. Passes if there is no red.</p>
-<div id="container">
-  <div class="item1">
-    <div style="height: 50px"></div>
-  </div>
-  <div class="item2">
-    <div style="height: 150px"></div>
-  </div>
-  <div class="item3">
-    <div style="height: 150px"></div>
-  </div>
-</div>
diff --git a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/align-self-change-keeping-geometry-expected.html b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/align-self-change-keeping-geometry-expected.html
deleted file mode 100644
index 151a3c6..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/align-self-change-keeping-geometry-expected.html
+++ /dev/null
@@ -1,22 +0,0 @@
-<!DOCTYPE HTML>
-<style>
-.flex {
-  display: flex;
-  align-items: flex-start;
-  width: 200px;
-  height: 300px;
-  background-color: red;
-}
-.item {
-  background-color: green;
-  border: solid thin blue;
-  width: 100px;
-  height: 300px;
-  align-self: stretch;
-}
-</style>
-<p style="height: 20px">There should be no invalidations because align-self style change causes no visual change.</p>
-<div class="flex">
-  <div class="item"></div>
-  <div class="item"></div>
-</div>
diff --git a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/align-self-change-keeping-geometry-grid-expected.html b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/align-self-change-keeping-geometry-grid-expected.html
deleted file mode 100644
index c40de91..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/align-self-change-keeping-geometry-grid-expected.html
+++ /dev/null
@@ -1,45 +0,0 @@
-<!DOCTYPE HTML>
-<style>
-body {
-  margin: 0;
-}
-#container {
-  display: grid;
-  grid: 300px / 100px 100px;
-  width: 200px;
-  height: 300px;
-  background-color: red;
-}
-.item1 {
-  grid-row: 1;
-  grid-column: 1;
-  align-self: start;
-  height: 300px;
-  width: 100px;
-  background-color: green;
-}
-.item2 {
-  grid-row: 1;
-  grid-column: 2;
-  align-self: start;
-  background-color: green;
-  height: 300px;
-  width: 100px;
-}
-.item3 {
-  grid-row: 1;
-  grid-column: 2;
-  align-self: end;
-  background-color: green;
-  height: 300px;
-  width: 100px;
-}
-</style>
-<p style="height: 20px">There should be no invalidations because align-self style change causes no visual change.</p>
-<div id="container">
-  <div class="item1">
-    <div style="height: 300px;"></div>
-  </div>
-  <div class="item2"></div>
-  <div class="item3"></div>
-</div>
diff --git a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/align-self-change-no-flex-expected.html b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/align-self-change-no-flex-expected.html
deleted file mode 100644
index d3819d0..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/align-self-change-no-flex-expected.html
+++ /dev/null
@@ -1,22 +0,0 @@
-<!DOCTYPE HTML>
-<style>
-.container {
-  width: 200px;
-  height: 300px;
-  background-color: blue;
-}
-.item {
-  background-color: green;
-  border: solid thin blue;
-  align-self: stretch;
-}
-</style>
-There should be no invalidations when align-self changes on a non-flex container.
-<div id="container">
-  <div class="item">
-    <div style="height: 100px"></div>
-  </div>
-  <div class="item">
-    <div style="height: 150px"></div>
-  </div>
-</div>
diff --git a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/align-self-overflow-change-expected.html b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/align-self-overflow-change-expected.html
deleted file mode 100644
index 1c588d3..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/align-self-overflow-change-expected.html
+++ /dev/null
@@ -1,32 +0,0 @@
-<!DOCTYPE HTML>
-<style>
-body {
-  margin: 0;
-}
-#container {
-  display: grid;
-  grid: 150px 150px / 200px;
-  width: 200px;
-  height: 300px;
-}
-.item1 {
-  grid-row: 1;
-  grid-column: 1;
-  align-self: end safe;
-  background-color: green;
-}
-.item2 {
-  grid-row: 2;
-  grid-column: 1;
-  align-self: end safe;
-  background-color: green;
-</style>
-<p style="height: 20px">Tests invalidation on align-self style change (just overflow). Passes if there is no red.</p>
-<div id="container">
-  <div class="item1">
-    <div style="height: 200px"></div>
-  </div>
-  <div class="item2">
-    <div style="height: 100px"></div>
-  </div>
-</div>
diff --git a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/background-currentColor-repaint-expected.html b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/background-currentColor-repaint-expected.html
deleted file mode 100644
index 1fc0572..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/background-currentColor-repaint-expected.html
+++ /dev/null
@@ -1,21 +0,0 @@
-<!DOCTYPE html>
-
-<style>
-div {
-    width: 100px;
-    height: 100px;
-    background: currentColor;    
-}
-
-#div1 {
-    color: transparent;
-}
-
-#div2 {
-    color: blue;
-}
-
-</style>
-
-<div id="div1"></div>
-<div id="div2"></div>
diff --git a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/background-generated-expected.html b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/background-generated-expected.html
deleted file mode 100644
index e24e7cda1..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/background-generated-expected.html
+++ /dev/null
@@ -1,9 +0,0 @@
-<!DOCTYPE HTML>
-<body>
-    <div style="width: 100px;
-                padding-top: 100px;
-                background-image: -webkit-gradient(linear, left top, left bottom, from(red), to(blue));
-    ">
-        <div id="target" style="height: 200px;"></div>
-    </div>
-</body>
diff --git a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/background-misaligned-expected.html b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/background-misaligned-expected.html
deleted file mode 100644
index b9f82cb..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/background-misaligned-expected.html
+++ /dev/null
@@ -1,11 +0,0 @@
-<body>
-    <div style="
-        width: 267px;
-        height: 270px;
-        border: solid black;
-        background-image: url(../../fast/backgrounds/size/resources/bikes.bmp);
-        -webkit-background-size: 500% 500%;
-        position: relative;
-    ">
-    </div>
-</body>
diff --git a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/background-resize-height-expected.html b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/background-resize-height-expected.html
deleted file mode 100644
index 7bb8bc9e..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/background-resize-height-expected.html
+++ /dev/null
@@ -1,85 +0,0 @@
-<!DOCTYPE html>
-<style>
-#container {
-    position: absolute;
-    width: 600px;
-    height: 550px;
-}
-.test {
-    backface-visibility: hidden;
-    position: absolute;
-    width: 10%;
-    height: 8%;
-}
-.image {
-    background-image: url(resources/small-apple.jpg);
-    top: 0px;
-}
-.generated {
-    background-image: linear-gradient(blue, green);
-    top: 100px;
-}
-.size-cover {
-    background-size: cover;
-    left: 50px;
-}
-.size-contain {
-    background-size: contain;
-    left: 100px;
-}
-.fixed-height {
-    background-size: auto 30px;
-    left: 150px;
-}
-.percent-height {
-    background-size: auto 50%;
-    left: 200px;
-}
-.top {
-    background-position: left 0px top 10px;
-    left: 250px;
-}
-.bottom {
-    background-position: left 0px bottom 10px;
-    left: 300px;
-}
-.center {
-    background-position: center;
-    left: 350px;
-}
-.no-repeat {
-    background-repeat: no-repeat;
-    left: 400px;
-}
-.repeat-space {
-    background-repeat: space;
-    left: 450px;
-}
-.repeat-round {
-    background-repeat: round;
-    left: 500px;
-}
-</style>
-<div id="container">
-    <div class="test image"></div>
-    <div class="test image size-cover"></div>
-    <div class="test image size-contain"></div>
-    <div class="test image fixed-height"></div>
-    <div class="test image percent-height"></div>
-    <div class="test image top"></div>
-    <div class="test image bottom"></div>
-    <div class="test image center"></div>
-    <div class="test image no-repeat"></div>
-    <div class="test image repeat-space"></div>
-    <div class="test image repeat-round"></div>
-    <div class="test generated"></div>
-    <div class="test generated size-cover"></div>
-    <div class="test generated size-contain"></div>
-    <div class="test generated percent-height"></div>
-    <div class="test generated top"></div>
-    <div class="test generated bottom"></div>
-    <div class="test generated center"></div>
-    <div class="test generated no-repeat"></div>
-    <div class="test generated repeat-space"></div>
-    <div class="test generated repeat-round"></div>
-</div>
diff --git a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/background-shorthand-with-gradient-and-height-changes-expected.html b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/background-shorthand-with-gradient-and-height-changes-expected.html
deleted file mode 100644
index 1044f56..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/background-shorthand-with-gradient-and-height-changes-expected.html
+++ /dev/null
@@ -1,28 +0,0 @@
-<html>
-<head>
-
-<style>
-#outer {
-    padding-top: 200px;
-    /* background-size is implicitly set to initial via the background shorthand. */
-	background:-webkit-gradient(
-	    linear, 
-	    left top, 
-	    left bottom, 
-	    color-stop(0%, rgba(255,255,0,0)), color-stop(100%, rgba(0,0,0,1))
-	);
-}
-
-#inner {
-    height: 300px;
-}
-</style>
-
-</head>
-<body>
-<div id='outer'>
-    <div id='inner'>
-    </div>
-</div>
-</body>
-</html>
diff --git a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/background-size-auto-with-gradient-and-height-changes-expected.html b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/background-size-auto-with-gradient-and-height-changes-expected.html
deleted file mode 100644
index d1c310db..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/background-size-auto-with-gradient-and-height-changes-expected.html
+++ /dev/null
@@ -1,28 +0,0 @@
-<html>
-<head>
-
-<style>
-#outer {
-    padding-top: 200px;
-    background: -webkit-gradient(
-        linear,
-        left top,
-        left bottom,
-        color-stop(0%, rgba(255,255,0,0)), color-stop(100%, rgba(0,0,0,1))
-    );
-    background-size: auto;
-}
-
-#inner {
-    height: 300px;
-}
-</style>
-</head>
-
-<body>
-<div id='outer'>
-    <div id='inner'>
-    </div>
-</div>
-</body>
-</html>
diff --git a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/backgroundSizeRepaint-expected.html b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/backgroundSizeRepaint-expected.html
deleted file mode 100644
index 44a2e51..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/backgroundSizeRepaint-expected.html
+++ /dev/null
@@ -1,33 +0,0 @@
-<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
-        "http://www.w3.org/TR/html4/strict.dtd">
-<html lang="en">
-<head>
-<style type="text/css">
-    div.test { width: 200px; height: 120px; border: 1px solid blue; padding: 10px; }
-</style>
-</head>
-<body>
-<p><b>BUG ID:</b> <a href="https://bugs.webkit.org/show_bug.cgi?id=8467">Bugzilla bug 8467</a> Block with percentage background-size doesn't repaint properly when it grows</p>
-
-<p id="success" style="background-color:palegreen; padding:3px;"><b>TEST PASS:</b>
-The boxes will resize, and their background images will repaint correctly maintaining the set background-size.
-</p>
-
-<p id="failure" style="background-color:#FF3300; padding:3px;"><b>TEST FAIL:</b> 
-The boxes will resize, but the background images will leave artifacts on the sides.
-</p>
-
-<div class="test">
-    <div style="background-image:url(resources/apple.jpg); -webkit-background-size: auto 100%;">
-        <div id="a" style="height: 40px; margin: 10px; background-color:teal; opacity:0.5;"></div>
-    </div>
-</div>
-<br>
-<div class="test">
-    <div style="background-image:url(resources/apple.jpg); -webkit-background-size: auto 100%;">
-        <div id="b" style="height: 60px; margin: 10px; background:teal; opacity:0.5;"></div>
-    </div>
-</div>
-
-</body>
-</html>
diff --git a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/block-layout-inline-children-float-positioned-expected.html b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/block-layout-inline-children-float-positioned-expected.html
deleted file mode 100644
index b1f51cb..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/block-layout-inline-children-float-positioned-expected.html
+++ /dev/null
@@ -1,22 +0,0 @@
-<head>
-<title>This is a test for regression against https://bugs.webkit.org/show_bug.cgi?id=40142</title>
-<style>
-#target {
-    width: 600px;
-    height: 100px;
-    text-align: center;
-    border: 1px solid #ddd;
-}
-</style>
-</head>
-
-<body style="margin: 0;">
-    <p>This is a test for regression against <a href="https://bugs.webkit.org/show_bug.cgi?id=40142">https://bugs.webkit.org/show_bug.cgi?id=40142</a></p>
-
-    <div>
-        <div id="target">
-            <span style="float: right;">the quick brown fox jumped over the lazy dog</span>
-            <span style="position: absolute;">the quick brown fox jumped over the lazy dog</span>
-        </div>
-    </div>
-</body>
diff --git a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/block-layout-inline-children-replaced-expected.html b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/block-layout-inline-children-replaced-expected.html
deleted file mode 100644
index 44e08daf..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/block-layout-inline-children-replaced-expected.html
+++ /dev/null
@@ -1,19 +0,0 @@
-<head>
-<title>This is a test for regression against https://bugs.webkit.org/show_bug.cgi?id=40142</title>
-<style>
-.target {
-    width: 400px;
-    height: 150px;
-    text-align: center;
-    border: 1px solid #ddd;
-}
-</style>
-</head>
-
-<body style="margin: 0;">
-    <p style="height: 100px">This is a test for regression against <a href="https://bugs.webkit.org/show_bug.cgi?id=40142">https://bugs.webkit.org/show_bug.cgi?id=40142</a></p>
-
-    <div>
-        <div class="target" id="target"><img style="width: 100px; height: 100px; background-color: green"></div>
-    </div>
-</body>
diff --git a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/block-no-inflow-children-expected.html b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/block-no-inflow-children-expected.html
deleted file mode 100644
index aa253f7..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/block-no-inflow-children-expected.html
+++ /dev/null
@@ -1,7 +0,0 @@
-<body style="margin: 0;">
-    <div style="height:200px; width:200px">
-      <div style="position:absolute">
-        <div id="target">La la la la</div>
-      </div>
-    </div>
-</body>
diff --git a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/block-shift-repaint-expected.html b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/block-shift-repaint-expected.html
deleted file mode 100644
index c270f24a..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/block-shift-repaint-expected.html
+++ /dev/null
@@ -1,41 +0,0 @@
-<html>
-<head>
-    <title>Test for http://bugs.webkit.org/show_bug.cgi?id=12079</title>
-    <style type="text/css">
-        div.playground { position: relative; width: 90px; height: 90px; }
-        .red { background-color: yellow; }
-        .blue { background-color: blue; }
-        .green { background-color: green; }
-        .zero { height: 0; width: 60px; }
-        .half { height: 30px; width: 60px; }
-        .full { height: 60px; width: 60px; }
-    </style>
-</head>
-<body>
-    <div class="playground">
-        <div id="div1" class="blue zero"></div>
-        <div class="red half"></div>
-        <div class="green half"></div>
-    </div>
-
-    <div class="playground">
-        <div><div id="top" class="blue zero"></div></div>
-        <div class="red half"></div>
-        <div class="green half"></div>
-    </div>
-
-    <div class="playground">
-        <div id="div2" class="half"></div>
-        <div class="green half"></div>
-        <div class="red half"></div>
-    </div>
-
-    <div class="playground" style="margin-top: 30px;">
-        <div style="width: 10px; margin: auto;">
-            <div id="innerDiv" style="height: 15px"></div>
-        </div>
-        <div class="half"></div>
-        <div class="half" style="border-top: solid yellow 8px;"></div>
-    </div>
-</body>
-</html>
diff --git a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/border-current-color-expected.html b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/border-current-color-expected.html
deleted file mode 100644
index 96c3d229..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/border-current-color-expected.html
+++ /dev/null
@@ -1,12 +0,0 @@
-<!DOCTYPE html>
-<style>
-div {
-  margin: 50px;
-  border-width: 10px;
-  border-style: solid;
-  width: 100px;
-  height: 100px;
-}
-</style>
-<div id="fixed-color" style="border-color: blue"></div>
-<div id="current-color" style="border-color: green"></div>
diff --git a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/border-image-outset-add-repaint-expected.html b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/border-image-outset-add-repaint-expected.html
deleted file mode 100644
index 1778e1dc..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/border-image-outset-add-repaint-expected.html
+++ /dev/null
@@ -1,16 +0,0 @@
-<!DOCTYPE HTML>
-<style>
-    div {
-        border-width: 21px 30px 30px 21px;
-        width: 75px;
-        height: 75px;
-        display: inline-block;
-        border-image-source: url("../../fast/borders/resources/border-image.png");
-        border-image-slice: 21 30 30 21 fill;
-        border-image-width: 5;
-    }
-</style>
-<div id="test"></div>
-<p>
-Tests the repainting of border-image-outset when added.
-</p>
diff --git a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/border-image-outset-change-repaint-expected.html b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/border-image-outset-change-repaint-expected.html
deleted file mode 100644
index a243b645..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/border-image-outset-change-repaint-expected.html
+++ /dev/null
@@ -1,17 +0,0 @@
-<!DOCTYPE HTML>
-<style>
-    div {
-        border-width: 21px 30px 30px 21px;
-        width: 75px;
-        height: 75px;
-        display: inline-block;
-        border-image-source: url("../../fast/borders/resources/border-image.png");
-        border-image-slice: 21 30 30 21 fill;
-        border-image-width: 1;
-        border-image-outset: 5;
-    }
-</style>
-<div id="test"></div>
-<p>
-Tests the repainting of border-image-outset when changed.
-</p>
diff --git a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/border-radius-repaint-expected.html b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/border-radius-repaint-expected.html
deleted file mode 100644
index c6a3cf1b8..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/border-radius-repaint-expected.html
+++ /dev/null
@@ -1,26 +0,0 @@
-<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
-        "http://www.w3.org/TR/html4/strict.dtd">
-<html lang="en">
-<head>
-<style type="text/css">
-    div.test { vertical-align: top; width: 200px; height: 120px; border: 1px solid blue; padding: 10px; }
-</style>
-</head>
-<body>
-<p>
-    Repaint test for <i><a href="http://bugs.webkit.org/show_bug.cgi?id=10699">http://bugs.webkit.org/show_bug.cgi?id=10699</a>
-    div with border-radius does not redraw properly if element inside div is resized</i>.
-</p>
-<div class="test">
-    <div style="background: teal; padding: 0; border: solid red 4px; -webkit-border-radius: 12px;">
-        <div id="a" style="height: 40px; margin: 10px; background:silver;"></div>
-    </div>
-</div>
-<br>
-<div class="test">
-    <div style="background: teal; padding: 0; border: solid red 4px; -webkit-border-radius: 12px;">
-        <div id="b" style="height: 60px; margin: 10px; background:silver;"></div>
-    </div>
-</div>
-</body>
-</html>
diff --git a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/border-radius-with-outline-expected.html b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/border-radius-with-outline-expected.html
deleted file mode 100644
index 93ec19a..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/border-radius-with-outline-expected.html
+++ /dev/null
@@ -1,18 +0,0 @@
-<!DOCTYPE html>
-<style>
-body {
-    margin: 0;
-}
-div {
-    position: absolute;
-    width: 200px;
-    height: 200px;
-    top: 100px;
-    left: 100px;
-    background-color: green;
-    border-radius: 50px;
-    outline: 5px solid green;
-    outline-offset: 50px;
-}
-</style>
-<div id="target"></div>
diff --git a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/border-radius-without-border-expected.html b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/border-radius-without-border-expected.html
deleted file mode 100644
index 0190ced0..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/border-radius-without-border-expected.html
+++ /dev/null
@@ -1,15 +0,0 @@
-<!DOCTYPE html>
-<style>
-body {
-    margin: 0;
-}
-div {
-    width: 100px;
-    height: 100px;
-    background-color: green;
-    border-radius: 10px 15px 20px 25px;
-    position: absolute;
-}
-</style>
-<div id="target1" style="top: 0px; width: 200px"></div>
-<div id="target2" style="top: 200px; height: 200px"></div>
diff --git a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/border-repaint-glitch-expected.html b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/border-repaint-glitch-expected.html
deleted file mode 100644
index 4dd8d74..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/border-repaint-glitch-expected.html
+++ /dev/null
@@ -1,36 +0,0 @@
-<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
-        "http://www.w3.org/TR/html4/strict.dtd">
-<html lang="en">
-<head>
-<style type="text/css">
-    div.test { width: 200px; height: 120px; border: 1px solid blue; padding: 10px; }
-</style>
-</head>
-<body>
-<p><b>BUG ID:</b> <a href="https://bugs.webkit.org/show_bug.cgi?id=6301">Bugzilla bug 6301</a> REGRESSION: Border repaint glitch</p>
-
-<p id="success" style="background-color:palegreen; padding:3px;"><b>TEST PASS:</b>
-The boxes will resize, maintaining their solid red rectangular borders.
-</p>
-
-<p id="failure" style="background-color:#FF3300; padding:3px;"><b>TEST FAIL:</b> 
-The boxes will resize, but the borders will break. The first box will be missing
-small segments from either side of its bottom border. The second box will have
-small red horizontal segments protruding inwards from both sides of the border,
-where the bottom border was before.
-</p>
-
-<div class="test">
-    <div style="background: teal; padding: 0; border: solid red 4px;">
-        <div id="a" style="height: 40px; margin: 10px; background:silver;"></div>
-    </div>
-</div>
-<br>
-<div class="test">
-    <div style="background: teal; padding: 0; border: solid red 4px;">
-        <div id="b" style="height: 60px; margin: 10px; background:silver;"></div>
-    </div>
-</div>
-
-</body>
-</html>
diff --git a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/box-inline-resize-expected.html b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/box-inline-resize-expected.html
deleted file mode 100644
index 7d8de2f..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/box-inline-resize-expected.html
+++ /dev/null
@@ -1,22 +0,0 @@
-<!doctype html>
-<head>
- <style>
- #about-container {
-   display: -webkit-box;
- }
- #foo {
-   background-color: green;
-   width: 32px;
-   height: 32px;
- }
- </style>
-</head>
-
-<p>Test for http://crbug.com/360453</p>
-<p>You should see an invalidation at x=40 of the h2 or this test is broken.</p>
-
-<div id="about-container">
- <img id='foo'/>
- <h2>Chromium</h2>
-</div>
-
diff --git a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/box-shadow-add-repaint-expected.html b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/box-shadow-add-repaint-expected.html
deleted file mode 100644
index 439c81f..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/box-shadow-add-repaint-expected.html
+++ /dev/null
@@ -1,5 +0,0 @@
-<!DOCTYPE HTML>
-<div id="test" style="background-color: green; width: 100px; height: 100px; box-shadow: 5px 5px 5px rgba(0,0,0,0.3);"></div>
-<p>
-Tests the repainting of box shadows when added.
-</p>
diff --git a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/box-shadow-change-repaint-expected.html b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/box-shadow-change-repaint-expected.html
deleted file mode 100644
index 32ea376..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/box-shadow-change-repaint-expected.html
+++ /dev/null
@@ -1,5 +0,0 @@
-<!DOCTYPE HTML>
-<div id="test" style="background-color: green; width: 100px; height: 100px; box-shadow: 5px 5px 5px rgba(0,0,0,0.3);"></div>
-<p>
-Tests the repainting of box shadows when changed.
-</p>
diff --git a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/box-shadow-dynamic-expected.html b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/box-shadow-dynamic-expected.html
deleted file mode 100644
index 096e0ef..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/box-shadow-dynamic-expected.html
+++ /dev/null
@@ -1,24 +0,0 @@
-<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
-        "http://www.w3.org/TR/html4/strict.dtd">
-<html lang="en">
-<head>
-<style type="text/css">
-    div.test { width: 50px; height: 100px; padding: 10px; }
-</style>
-</head>
-<body>
-    <p>
-        Tests the repainting of box shadows when boxes are resized.
-    </p>
-    <div class="test">
-        <div style="background: #ff7; -webkit-box-shadow: black 5px 5px 0;">
-            <div id="a" style="height: 50px; margin: 10px;"></div>
-        </div>
-    </div>
-    <div class="test">
-        <div style="background: #ff7; -webkit-box-shadow: black 5px 5px 0;">
-            <div id="b" style="height: 50px; margin: 10px;"></div>
-        </div>
-    </div>
-</body>
-</html>
diff --git a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/box-shadow-inset-repaint-expected.html b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/box-shadow-inset-repaint-expected.html
deleted file mode 100644
index 31847f6..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/box-shadow-inset-repaint-expected.html
+++ /dev/null
@@ -1,16 +0,0 @@
-<!DOCTYPE html>
-<html>
-<head>
-    <style type="text/css" media="screen">
-        div#container {
-            padding: 15px;
-            box-shadow: inset cyan 0 -60px 0 0;
-        }
-    </style>
-</head>
-<body>
-    <div id="container" style="width:200px;">
-        <div style="width: 100px; height: 100px; background-color: green"></div>
-    </div>
-</body>
-</html>
diff --git a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/box-sizing-border-keeping-size-expected.html b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/box-sizing-border-keeping-size-expected.html
deleted file mode 100644
index 9c54332..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/box-sizing-border-keeping-size-expected.html
+++ /dev/null
@@ -1,23 +0,0 @@
-<!DOCTYPE HTML>
-<style>
-body {
-    margin: 0;
-}
-div {
-    position: absolute;
-    background-color: green;
-}
-.border-box {
-    width: 100px;
-    height: 100px;
-    box-sizing: border-box;
-}
-.content-box {
-    width: 60px;
-    height: 60px;
-    box-sizing: content-box;
-    border: blue solid 20px;
-}
-</style>
-<div id="target1" class="content-box" style="top: 0px"></div>
-<div id="target2" class="border-box" style="top: 200px"></div>
diff --git a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/box-sizing-expected.html b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/box-sizing-expected.html
deleted file mode 100644
index ba1b3e3..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/box-sizing-expected.html
+++ /dev/null
@@ -1,21 +0,0 @@
-<!DOCTYPE HTML>
-<style>
-body {
-    margin: 0;
-}
-div {
-    width: 50%;
-    height: 100px;
-    position: absolute;
-    background-color: green;
-    border: blue solid 20px;
-}
-.border-box {
-    box-sizing: border-box;
-}
-.content-box {
-    box-sizing: content-box;
-}
-</style>
-<div id="target1" class="content-box" style="top: 0px"></div>
-<div id="target2" class="border-box" style="top: 200px"></div>
diff --git a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/box-sizing-padding-keeping-size-expected.html b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/box-sizing-padding-keeping-size-expected.html
deleted file mode 100644
index c48c8a1..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/box-sizing-padding-keeping-size-expected.html
+++ /dev/null
@@ -1,23 +0,0 @@
-<!DOCTYPE HTML>
-<style>
-body {
-    margin: 0;
-}
-div {
-    position: absolute;
-    background-color: green;
-}
-.border-box {
-    width: 100px;
-    height: 100px;
-    box-sizing: border-box;
-}
-.content-box {
-    width: 60px;
-    height: 60px;
-    box-sizing: content-box;
-    padding: 20px;
-}
-</style>
-<div id="target1" class="content-box" style="top: 0px"></div>
-<div id="target2" class="border-box" style="top: 200px"></div>
diff --git a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/bugzilla-3509-expected.html b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/bugzilla-3509-expected.html
deleted file mode 100644
index b6e14fd..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/bugzilla-3509-expected.html
+++ /dev/null
@@ -1,24 +0,0 @@
-<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
-<html lang="en">
-<body>
-<p><b>BUG ID:</b> <a href="https://bugs.webkit.org/show_bug.cgi?id=3509">Bugzilla bug 3509</a> REGRESSION(125-412) Portion of nested table is not painted correctly on cafepress site</p>
-
-<p id="success" style="background-color:palegreen; padding:3px;"><b>TEST PASS:</b>
-The blue rectangle will change into a square.
-</p>
-
-<p id="failure" style="background-color:#FF3300; padding:3px;"><b>TEST FAIL:</b> 
-The blue rectangle will change into a shape that is not square.
-</p>
-
-    <table width="100%">
-        <tr>
-            <td style="width: 100px;">
-                <div id="qu" style="margin-top: 2.0__qem;"></div>
-                <div id="im" style="height: 100px; width: 100px; background: blue;">&nbsp;</div>        
-            </td>
-        </tr>
-    </table>
-
-</body>
-</html>
diff --git a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/bugzilla-5699-expected.html b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/bugzilla-5699-expected.html
deleted file mode 100644
index a91bced..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/bugzilla-5699-expected.html
+++ /dev/null
@@ -1,20 +0,0 @@
-<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
-        "http://www.w3.org/TR/html4/strict.dtd">
-<html lang="en">
-<body>
-<p><b>BUG ID:</b> <a href="https://bugs.webkit.org/show_bug.cgi?id=5699">Bugzilla bug 5699</a> REGRESSION: incomplete repaint</p>
-
-<p id="success" style="background-color:palegreen; padding:3px;"><b>TEST PASS:</b>
-The word &ldquo;Hello&rdquo; will move down.
-</p>
-
-<p id="failure" style="background-color:#FF3300; padding:3px;"><b>TEST FAIL:</b> 
-Another copy of the word &ldquo;Hello&rdquo; will appear.
-</p>
-
-<p>
-<span id="d" style="line-height: 3">&nbsp;</span><br>
-Hello<br>
-</p>
-</body>
-</html>
diff --git a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/bugzilla-6278-expected.html b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/bugzilla-6278-expected.html
deleted file mode 100644
index 305cd1f..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/bugzilla-6278-expected.html
+++ /dev/null
@@ -1,28 +0,0 @@
-<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
-        "http://www.w3.org/TR/html4/strict.dtd">
-<html lang="en">
-<body>
-<p><b>BUG ID:</b> <a href="https://bugs.webkit.org/show_bug.cgi?id=6278">Bugzilla bug 6278</a> REGRESSION: Incomplete repaint when table cell width changes during layout</p>
-
-<p id="success" style="background-color:palegreen; padding:3px;"><b>TEST PASS:</b>
-The purple and green rects will resize, and there will remain separated by a blue horizontal line.
-</p>
-
-<p id="failure" style="background-color:#FF3300; padding:3px;"><b>TEST FAIL:</b> 
-The purple and green rects will resize, but the blue separator will disappear.
-</p>
-<table style="width: 300px;">
-<tr>
-    <td id="col1" style="background: blue; padding:0;">
-        <div style="background: #eeeeff;">
-            Curabitur pretium, quam quis semper malesuada, est libero feugiat libero, vel fringilla orci nibh sed neque. Quisque eu nulla non nisi molestie accumsan. Etiam tellus urna, laoreet ac, laoreet non, suscipit sed, sapien. Phasellus vehicula, sem at posuere vehicula, augue nibh molestie nisl, nec ullamcorper lacus ante vulputate pede.
-        </div>
-        <div style="background: #eeffee; margin-top: 5px; height: 50px;">
-        </div>
-    </td>
-    <td id="target" style="width: 50px"></td>
-</tr>
-</table>
-
-</body>
-</html>
diff --git a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/bugzilla-6388-expected.html b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/bugzilla-6388-expected.html
deleted file mode 100644
index d09b869..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/bugzilla-6388-expected.html
+++ /dev/null
@@ -1,24 +0,0 @@
-<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
-        "http://www.w3.org/TR/html4/strict.dtd">
-<html lang="en">
-<body>
-<p><b>BUG ID:</b> <a href="https://bugs.webkit.org/show_bug.cgi?id=6388">Bugzilla bug 6388</a> REGRESSION: Incomplete repaint when dragging the map on Google maps</p>
-
-<p id="success" style="background-color:palegreen; padding:3px;"><b>TEST PASS:</b>
-The blue square will change to green.
-</p>
-
-<p id="failure" style="background-color:#FF3300; padding:3px;"><b>TEST FAIL:</b> 
-The blue square will NOT change to green.
-</p>
-
-<div style="width: 100px; height: 100px; overflow: hidden; position: relative">
-    <div id="outside" style="position:absolute; width: 0; height: 0; left: -100px">
-        <div style="width: 200px; height: 100px; position: absolute; background: green;">
-            <div style="width: 100px; height: 100px; background: blue;"></div>
-        </div>
-    </div>
-</div>
-<br>
-</body>
-</html>
diff --git a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/bugzilla-6473-expected.html b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/bugzilla-6473-expected.html
deleted file mode 100644
index 4a7bfa77..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/bugzilla-6473-expected.html
+++ /dev/null
@@ -1,22 +0,0 @@
-<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
-        "http://www.w3.org/TR/html4/strict.dtd">
-<html lang="en">
-<body>
-<p><b>BUG ID:</b> <a href="https://bugs.webkit.org/show_bug.cgi?id=6473">Bugzilla bug 6473</a> REGRESSION: Serious painting problems on new iLife and iWorks pages</p>
-
-<p id="success" style="background-color:palegreen; padding:3px;"><b>TEST PASS:</b>
-A green rectangle containing the word SUCCESS will show below.
-</p>
-
-<p id="failure" style="background-color:#FF3300; padding:3px;"><b>TEST FAIL:</b> 
-A green rectangle will not show below.
-</p>
-<div>
-<div id="allcontent">
-<p style="position: relative; background: lime;">
-    SUCCESS
-</p>
-</div>
-</div>
-</body>
-</html>
diff --git a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/button-spurious-layout-hint-expected.html b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/button-spurious-layout-hint-expected.html
deleted file mode 100644
index 71ee2c9..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/button-spurious-layout-hint-expected.html
+++ /dev/null
@@ -1,3 +0,0 @@
-<body>
-    <button id="target" style="height: 100px; width: 100px; background-color: lightpink; border: none;">&nbsp;</button>
-</body>
diff --git a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/change-text-content-and-background-color-expected.html b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/change-text-content-and-background-color-expected.html
deleted file mode 100644
index 54352d6..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/change-text-content-and-background-color-expected.html
+++ /dev/null
@@ -1,11 +0,0 @@
-<!DOCTYPE html>
-<style>
-input {
-    background-color: green;
-    position: absolute;
-    font-size: 20px;
-    padding: 20px;
-    width: 200px;
-}
-</style>
-<input id="input" type="text" value="NEW">
diff --git a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/change-transform-expected.html b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/change-transform-expected.html
deleted file mode 100644
index 4fd0e67..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/change-transform-expected.html
+++ /dev/null
@@ -1,28 +0,0 @@
-<html>
-<head>
-  <style type="text/css" media="screen">
-    body {
-      margin: 10px;
-    }
-    #square {
-      width: 100px;
-      height: 100px;
-    }
-    #overlay {
-      position: absolute;
-      left: 35px;
-      top: 35px;
-      width: 50px;
-      height: 50px;
-      background: green
-    }
-  </style>
-</head>
-<body>
-<div id="square"></div>
-<div id="overlay"></div>
-
-<p><a href="https://bugs.webkit.org/show_bug.cgi?id=19623">https://bugs.webkit.org/show_bug.cgi?id=19623</a></p>
-<p>Test for incomplete repaint when a non-layer object gains a transform. You should see a green square above. If you see any red, the test has failed.</p>
-</body>
-</html>
diff --git a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/child-of-sub-pixel-offset-composited-layer-expected.html b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/child-of-sub-pixel-offset-composited-layer-expected.html
deleted file mode 100644
index ddd4df0..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/child-of-sub-pixel-offset-composited-layer-expected.html
+++ /dev/null
@@ -1,24 +0,0 @@
-<!DOCTYPE html>
-<html>
-<head>
-<style>
-.container {
-  position: absolute;
-  top: 100px;
-  left:100.5px;
-}
-
-#target {
-  position: absolute;
-  left: 0px;
-  width: 10px;
-  height: 10px;
-  border: 2px solid green;
-}
-</style>
-</head>
-<body>
-<div class="container">
-<div id="target">
-</div>
-</div>
diff --git a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/clip-path-constant-repaint-expected.html b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/clip-path-constant-repaint-expected.html
deleted file mode 100644
index 8bb98943..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/clip-path-constant-repaint-expected.html
+++ /dev/null
@@ -1,19 +0,0 @@
-<!DOCTYPE html>
-<html>
-<head>
-<style>
-#clip {
-  width: 100%;
-  height: 300px;
-  position: fixed;
-  background-color: rgba(255, 0, 0, 0.9);
-  clip-path: polygon(0px 0px, 100% 0px, 100% 100%, 0px 83%);
-  backface-visibility: hidden;
-  transform: translateY(100px);
-}
-</style>
-</head>
-<body>
-  <div id="clip"></div>
-</body>
-</html>
diff --git a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/clip-unclip-and-change-expected.html b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/clip-unclip-and-change-expected.html
deleted file mode 100644
index e118549..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/clip-unclip-and-change-expected.html
+++ /dev/null
@@ -1,8 +0,0 @@
-<!DOCTYPE html>
-Tests paint invalidation of previous location of an element which was clipped to be invisible initially, becme visible because of clip change, then changed color and size. Passes if there is a green square.
-<div id="container" style="position: absolute; top: 100px; width: 100px; height: 400px; overflow: hidden">
-  <div style="height: 20px"></div>
-  <div style="width: 100px; height: 300px">
-    <div id="content" style="width: 100px; height: 100px; background-color: green"></div>
-  </div>
-</div>
diff --git a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/clip-with-layout-delta-expected.html b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/clip-with-layout-delta-expected.html
deleted file mode 100644
index 00bf3d3..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/clip-with-layout-delta-expected.html
+++ /dev/null
@@ -1,23 +0,0 @@
-<html>
-<head>
-    <title>Test for http://bugs.webkit.org/show_bug.cgi?id=15994</title>
-    <style type="text/css">
-        div {
-            overflow: hidden;
-        }
-        div, span {
-            height: 100px;
-            width: 100px;
-            display: block;
-        }
-        span.blue {
-            padding: 100px 0 0 0;
-            background: blue;
-        }
-    </style>
-</head>
-<body>
-    <div style="background: green;"><span id="t1">&nbsp;</span></div>
-    <div style="position: relative; margin: -100px 0 0 100px; background: red;"><span id="t2" class="blue">&nbsp;</span></div>
-</body>
-</html>
diff --git a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/clipped-overflow-visible-subtree-expected.html b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/clipped-overflow-visible-subtree-expected.html
deleted file mode 100644
index 8ea2a93..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/clipped-overflow-visible-subtree-expected.html
+++ /dev/null
@@ -1,10 +0,0 @@
-<!DOCTYPE html>
-<div style="visibility: hidden; opacity: 0.9; width: 600px;">
- <div style="float:right">
-  <div style="float:left; width: 300px">
-    <div>
-      <div style="opacity: 0.9; visibility: visible; background-color: green; width: 100px; height: 100px;"> </div>
-    </div>
-  </div>
- </div>
-</div>
diff --git a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/clipped-relative-expected.html b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/clipped-relative-expected.html
deleted file mode 100644
index 0b578b2..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/clipped-relative-expected.html
+++ /dev/null
@@ -1,15 +0,0 @@
-<html>
-<body>
-    <p>
-        This is a repaint test for <i><a href="https://bugs.webkit.org/show_bug.cgi?id=9121">http://bugzilla.opendarwin.org/show_bug.cgi?id=9121</a>
-        REGRESSION: [Incremental Repaint] DHTML movement test failures</i>.
-    </p>
-    <hr>
-    <div id='outer' style="position: relative; overflow: hidden; width: 214px; height: 232px;">
-        <div id="i" style="position: relative; left: 430px;">
-            <div id='inner' style="position: absolute; left: -440px; width: 214px; height: 232px;">
-                <img src="resources/apple.jpg">
-            </div>
-        </div>
-    </div>
-</body>
diff --git a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/composited-vertical-rl-overflow-expected.html b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/composited-vertical-rl-overflow-expected.html
deleted file mode 100644
index 300f2f6..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/composited-vertical-rl-overflow-expected.html
+++ /dev/null
@@ -1,14 +0,0 @@
-<!DOCTYPE html>
-<style>
-#div {
-  box-shadow: -50px 0 green;
-  position: absolute;
-  top: 100px;
-  left: 100px;
-  width: 100px;
-  height: 100px;
-  background-color: blue;
-}
-</style>
-Tests paint invalidation of a composited verticle-rl div with overflow. Passes if no under-invalidation reported and shows no red.
-<div id="div"></div>
diff --git a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/compositing/background-attachment-local-composited-expected.html b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/compositing/background-attachment-local-composited-expected.html
deleted file mode 100644
index 77f8269..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/compositing/background-attachment-local-composited-expected.html
+++ /dev/null
@@ -1,9 +0,0 @@
-<!DOCTYPE html>
-<style>
-#container {
-  width: 400px;
-  height: 400px;
-  background-color: blue;
-}
-</style>
-<div id="container"></div>
diff --git a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/compositing/background-attachment-local-equivalent-expected.html b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/compositing/background-attachment-local-equivalent-expected.html
deleted file mode 100644
index ea1db4b..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/compositing/background-attachment-local-equivalent-expected.html
+++ /dev/null
@@ -1,27 +0,0 @@
-<!DOCTYPE html>
-<style>
-#container {
-  overflow: hidden;
-  will-change: transform;
-  width: 400px;
-  height: 400px;
-
-  background-attachment: local;
-  background-color: blue;
-}
-
-#child {
-  height: 500px;
-}
-</style>
-<div id="container">
-  <div id="child"></div>
-</div>
-<script src="../resources/text-based-repaint.js"></script>
-<script>
-function repaintTest() {
-  child.style.height = '2000px';
-  container.scrollTop = 2000;
-}
-onload = runRepaintAndPixelTest;
-</script>
diff --git a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/compositing/column-span-under-composited-column-child-expected.html b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/compositing/column-span-under-composited-column-child-expected.html
deleted file mode 100644
index f718ea6..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/compositing/column-span-under-composited-column-child-expected.html
+++ /dev/null
@@ -1,2 +0,0 @@
-<!DOCTYPE html>
-<div style="width: 100px; height: 100px; background-color: green"></div>
diff --git a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/compositing/composited-float-under-composited-inline-expected.html b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/compositing/composited-float-under-composited-inline-expected.html
deleted file mode 100644
index 2abd3f6..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/compositing/composited-float-under-composited-inline-expected.html
+++ /dev/null
@@ -1,3 +0,0 @@
-<!DOCTYPE html>
-<div style="position: relative; top: 50px; left: 50px; width: 100px; height: 100px; background-color: green"></div>
-
diff --git a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/compositing/composited-float-under-composited-inline-individual-expected.html b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/compositing/composited-float-under-composited-inline-individual-expected.html
deleted file mode 100644
index 2abd3f6..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/compositing/composited-float-under-composited-inline-individual-expected.html
+++ /dev/null
@@ -1,3 +0,0 @@
-<!DOCTYPE html>
-<div style="position: relative; top: 50px; left: 50px; width: 100px; height: 100px; background-color: green"></div>
-
diff --git a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/compositing/compositing-reason-removed-expected.html b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/compositing/compositing-reason-removed-expected.html
deleted file mode 100644
index febe7e7..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/compositing/compositing-reason-removed-expected.html
+++ /dev/null
@@ -1,10 +0,0 @@
-<!DOCTYPE html>
-<style>
-  #square {
-    background-color: blue;
-    width: 30px;
-    height: 30px;
-    position: relative;
-  }
-</style>
-<div id="square"></div>
diff --git a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/compositing/containing-block-removed-expected.txt b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/compositing/containing-block-removed-expected.txt
new file mode 100644
index 0000000..8a067b90
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/compositing/containing-block-removed-expected.txt
@@ -0,0 +1,75 @@
+CONSOLE MESSAGE: line 30: debug
+{
+  "layers": [
+    {
+      "name": "LayoutView #document",
+      "bounds": [800, 600],
+      "backgroundColor": "#FFFFFF"
+    },
+    {
+      "name": "Scrolling Layer",
+      "bounds": [800, 600],
+      "drawsContent": false
+    },
+    {
+      "name": "Scrolling Contents Layer",
+      "bounds": [800, 600],
+      "contentsOpaque": true,
+      "backgroundColor": "#FFFFFF",
+      "paintInvalidations": [
+        {
+          "object": "LayoutBlockFlow (positioned) DIV class='fixed'",
+          "rect": [50, 50, 75, 75],
+          "reason": "style change"
+        }
+      ]
+    },
+    {
+      "name": "LayoutBlockFlow (positioned) DIV id='container'",
+      "position": [200, 100],
+      "bounds": [100, 100],
+      "contentsOpaque": true,
+      "backgroundColor": "#0000FF",
+      "paintInvalidations": [
+        {
+          "object": "LayoutBlockFlow (positioned) DIV id='container'",
+          "rect": [0, 0, 100, 100],
+          "reason": "style change"
+        },
+        {
+          "object": "LayoutBlockFlow (positioned) DIV id='container'",
+          "rect": [0, 0, 100, 100],
+          "reason": "subtree"
+        },
+        {
+          "object": "LayoutBlockFlow (positioned) DIV class='fixed'",
+          "rect": [50, 50, 75, 75],
+          "reason": "subtree"
+        }
+      ]
+    }
+  ],
+  "objectPaintInvalidations": [
+    {
+      "object": "LayoutBlockFlow (positioned) DIV class='fixed'",
+      "reason": "subtree"
+    },
+    {
+      "object": "LayoutBlockFlow (positioned) DIV id='container'",
+      "reason": "subtree"
+    },
+    {
+      "object": "LayoutBlockFlow (positioned) DIV class='fixed'",
+      "reason": "subtree"
+    },
+    {
+      "object": "LayoutBlockFlow (positioned) DIV id='container'",
+      "reason": "style change"
+    },
+    {
+      "object": "LayoutBlockFlow (positioned) DIV class='fixed'",
+      "reason": "style change"
+    }
+  ]
+}
+
diff --git a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/compositing/containing-block-removed-individual-expected.txt b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/compositing/containing-block-removed-individual-expected.txt
new file mode 100644
index 0000000..8a067b90
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/compositing/containing-block-removed-individual-expected.txt
@@ -0,0 +1,75 @@
+CONSOLE MESSAGE: line 30: debug
+{
+  "layers": [
+    {
+      "name": "LayoutView #document",
+      "bounds": [800, 600],
+      "backgroundColor": "#FFFFFF"
+    },
+    {
+      "name": "Scrolling Layer",
+      "bounds": [800, 600],
+      "drawsContent": false
+    },
+    {
+      "name": "Scrolling Contents Layer",
+      "bounds": [800, 600],
+      "contentsOpaque": true,
+      "backgroundColor": "#FFFFFF",
+      "paintInvalidations": [
+        {
+          "object": "LayoutBlockFlow (positioned) DIV class='fixed'",
+          "rect": [50, 50, 75, 75],
+          "reason": "style change"
+        }
+      ]
+    },
+    {
+      "name": "LayoutBlockFlow (positioned) DIV id='container'",
+      "position": [200, 100],
+      "bounds": [100, 100],
+      "contentsOpaque": true,
+      "backgroundColor": "#0000FF",
+      "paintInvalidations": [
+        {
+          "object": "LayoutBlockFlow (positioned) DIV id='container'",
+          "rect": [0, 0, 100, 100],
+          "reason": "style change"
+        },
+        {
+          "object": "LayoutBlockFlow (positioned) DIV id='container'",
+          "rect": [0, 0, 100, 100],
+          "reason": "subtree"
+        },
+        {
+          "object": "LayoutBlockFlow (positioned) DIV class='fixed'",
+          "rect": [50, 50, 75, 75],
+          "reason": "subtree"
+        }
+      ]
+    }
+  ],
+  "objectPaintInvalidations": [
+    {
+      "object": "LayoutBlockFlow (positioned) DIV class='fixed'",
+      "reason": "subtree"
+    },
+    {
+      "object": "LayoutBlockFlow (positioned) DIV id='container'",
+      "reason": "subtree"
+    },
+    {
+      "object": "LayoutBlockFlow (positioned) DIV class='fixed'",
+      "reason": "subtree"
+    },
+    {
+      "object": "LayoutBlockFlow (positioned) DIV id='container'",
+      "reason": "style change"
+    },
+    {
+      "object": "LayoutBlockFlow (positioned) DIV class='fixed'",
+      "reason": "style change"
+    }
+  ]
+}
+
diff --git a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/compositing/float-under-composited-inline-expected.html b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/compositing/float-under-composited-inline-expected.html
deleted file mode 100644
index 03f5276..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/compositing/float-under-composited-inline-expected.html
+++ /dev/null
@@ -1,3 +0,0 @@
-<!DOCTYPE html>
-<div style="width: 100px; height: 100px; background-color: green"></div>
-
diff --git a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/compositing/invalidate-when-leaving-squashed-layer-expected.html b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/compositing/invalidate-when-leaving-squashed-layer-expected.html
deleted file mode 100644
index f30722e..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/compositing/invalidate-when-leaving-squashed-layer-expected.html
+++ /dev/null
@@ -1,4 +0,0 @@
-<!DOCTYPE html>
-<div style="position:absolute; height: 200px; width: 200px; background: lightgray"></div>
-<div style="position:absolute; height: 200px; width: 200px; top: 50px; left: 50px; background:lightblue"></div>
-<div id="target" style="position:absolute; height: 200px; width: 200px; top: 50px; left: 50px; background:lightblue"></div>
diff --git a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/compositing/invalidation-for-subpixel-offset-of-squashed-layer-expected.html b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/compositing/invalidation-for-subpixel-offset-of-squashed-layer-expected.html
deleted file mode 100644
index 9019711..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/compositing/invalidation-for-subpixel-offset-of-squashed-layer-expected.html
+++ /dev/null
@@ -1,6 +0,0 @@
-<!DOCTYPE html>
-
-<div style="position: absolute; width: 200px; height: 200px; background: lightgray"></div>
-
-<div style="position: absolute; width: 200px; height: 200px; top: 50px; left: 50px; background: lightblue"></div>
-<div id="target" style="position: absolute; width: 200px; height: 200px; top: 100.45px; left: 100.45px; background: red"></div>
diff --git a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/compositing/invalidations-on-composited-layers-expected.html b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/compositing/invalidations-on-composited-layers-expected.html
deleted file mode 100644
index ac9c6a0..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/compositing/invalidations-on-composited-layers-expected.html
+++ /dev/null
@@ -1,32 +0,0 @@
-<!DOCTYPE html>
-
-<!--
-This test checks that repaint testing works with composited layers.
--->
-
-<html>
-<head>
-  <style type="text/css">
-    #parent {
-        width: 400px;
-        height: 400px;
-        background: green;
-    }
-
-    #child {
-        position: relative;
-        left: 50px;
-        top: 50px;
-        width: 75px;
-        height: 75px;
-        background: blue;
-    }
-
-  </style>
-</head>
-<body>
-  <div id="parent">
-    <div id="child"></div>
-  </div>
-</body>
-</html>
diff --git a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/compositing/overlap-test-with-filter-expected.txt b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/compositing/overlap-test-with-filter-expected.txt
new file mode 100644
index 0000000..917c501
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/compositing/overlap-test-with-filter-expected.txt
@@ -0,0 +1,68 @@
+{
+  "layers": [
+    {
+      "name": "LayoutView #document",
+      "bounds": [800, 600],
+      "backgroundColor": "#FFFFFF"
+    },
+    {
+      "name": "Scrolling Layer",
+      "bounds": [800, 600],
+      "drawsContent": false
+    },
+    {
+      "name": "Scrolling Contents Layer",
+      "bounds": [800, 600],
+      "contentsOpaque": true,
+      "backgroundColor": "#FFFFFF"
+    },
+    {
+      "name": "LayoutIFrame IFRAME",
+      "bounds": [300, 100]
+    },
+    {
+      "name": "LayoutView #document",
+      "bounds": [300, 100],
+      "backgroundColor": "#FFFF00"
+    },
+    {
+      "name": "Child Containment Layer",
+      "bounds": [300, 100],
+      "drawsContent": false
+    },
+    {
+      "name": "LayoutBlockFlow BODY",
+      "bounds": [284, 84],
+      "backgroundColor": "#FFFF00",
+      "transform": 1
+    },
+    {
+      "name": "LayoutBlockFlow (positioned) DIV",
+      "bounds": [300, 100],
+      "contentsOpaque": true,
+      "backgroundColor": "#D3D3D3",
+      "transform": 2
+    }
+  ],
+  "transforms": [
+    {
+      "id": 1,
+      "transform": [
+        [1, 0, 0, 0],
+        [0, 1, 0, 0],
+        [0, 0, 1, 0],
+        [8, 8, 0, 1]
+      ]
+    },
+    {
+      "id": 2,
+      "transform": [
+        [1, 0, 0, 0],
+        [0, 1, 0, 0],
+        [0, 0, 1, 0],
+        [151, 0, 0, 1]
+      ]
+    }
+  ]
+}
+
diff --git a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/compositing/page-scale-repaint-expected.txt b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/compositing/page-scale-repaint-expected.txt
new file mode 100644
index 0000000..d1892b6
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/compositing/page-scale-repaint-expected.txt
@@ -0,0 +1,7 @@
+layer at (0,0) size 1600x1200 scrollWidth 4008 scrollHeight 10016
+  LayoutView at (0,0) size 800x600
+layer at (0,0) size 800x10016 backgroundClip at (0,0) size 1600x1200 clip at (0,0) size 1600x1200
+  LayoutBlockFlow {HTML} at (0,0) size 800x10016
+    LayoutBlockFlow {BODY} at (8,8) size 4000x10000
+layer at (8,8) size 4000x0
+  LayoutBlockFlow {DIV} at (0,0) size 4000x0
diff --git a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/compositing/remove-squashed-layer-plus-move-expected.html b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/compositing/remove-squashed-layer-plus-move-expected.html
deleted file mode 100644
index e825e41..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/compositing/remove-squashed-layer-plus-move-expected.html
+++ /dev/null
@@ -1,15 +0,0 @@
-<!DOCTYPE html>
-<style>
-.mv-tile{
-    display:inline-block;
-    height:50px;
-    position:relative;
-    width:100px;
-    margin-right:410px;
-}
-</style>
-<div style="position: absolute; width: 1000px; height: 1000px"></div>
-<div id="container">
-    <div class="mv-tile" style="background-color: lightblue;"></div>
-</div>
-<div class="mv-tile" style="width: 1000px"></div>
diff --git a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/compositing/repaint-squashed-layer-in-rect-expected.html b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/compositing/repaint-squashed-layer-in-rect-expected.html
deleted file mode 100644
index e2a8fec3..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/compositing/repaint-squashed-layer-in-rect-expected.html
+++ /dev/null
@@ -1,9 +0,0 @@
-<!doctype html>
-<div style="height: 800px; width: 800px; background-color: lightgray">
-</div>
-<div style="position:absolute; top: 0px; height: 200px; width: 200px">
-</div>
-<div style="position:absolute; top: 400px; left: 400px; height: 200px; width: 200px; background-color: lightblue">
-  <div id="imgElement" style="height: 200px; width: 200px; background-image: url('data:image/gif;base64,R0lGODdhAgACAIABAAAAAP///ywAAAAAAgACAAACA0QCBQA7')">
-  </div>
-</div>
diff --git a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/compositing/repaint-via-layout-offset-expected.html b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/compositing/repaint-via-layout-offset-expected.html
deleted file mode 100644
index 2dae0a1..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/compositing/repaint-via-layout-offset-expected.html
+++ /dev/null
@@ -1,27 +0,0 @@
-<!DOCTYPE html>
-<style>
-#container {
-  position: absolute;
-  z-index: 0;
-  left: 50px;
-  top: 50px;
-}
-
-.child {
-  position: absolute;
-  width: 40px;
-  height: 40px;
-  background-color: red;
-}
-
-.embiggen {
-  width: 50px;
-  height: 50px;
-  background-color: green;
-}
-</style>
-<div style="width:200px; height:200px; background-color: lightblue"></div>
-<div id="container">
-  <span class="child"></span>
-  <span class="child embiggen"></span>
-</div>
diff --git a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/compositing/resize-repaint-expected.html b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/compositing/resize-repaint-expected.html
deleted file mode 100644
index d6771bd..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/compositing/resize-repaint-expected.html
+++ /dev/null
@@ -1,28 +0,0 @@
-<!DOCTYPE html>
-
-<html>
-<head>
-    <style>
-        #resizing {
-            width: 400px;
-            border: 1px solid black;
-        }
-
-        #resizing > div {
-            height: 50px;
-            margin: 1px;
-            background-color: silver;
-        }
-    </style>
-</head>
-<body>
-
-<div id="resizing">
-  <div></div>
-  <div></div>
-  <div></div>
-  <div></div>
-</div>
-
-</body>
-</html>
diff --git a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/compositing/resize-squashing-layer-that-needs-full-repaint-expected.html b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/compositing/resize-squashing-layer-that-needs-full-repaint-expected.html
deleted file mode 100644
index 6d53abaf..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/compositing/resize-squashing-layer-that-needs-full-repaint-expected.html
+++ /dev/null
@@ -1,4 +0,0 @@
-<!doctype html>
-
-<div style="width: 500px; height: 500px"></div>
-<div style="position: absolute; top: 55px; left: 55px; width: 500px; height: 500px; background-color: lightblue"></div>
diff --git a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/compositing/should-not-repaint-scrolling-contents-outline-change-expected.html b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/compositing/should-not-repaint-scrolling-contents-outline-change-expected.html
deleted file mode 100644
index 10f10d4..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/compositing/should-not-repaint-scrolling-contents-outline-change-expected.html
+++ /dev/null
@@ -1,5 +0,0 @@
-<!DOCTYPE html>
-<div style="overflow: scroll; outline: 10px solid green; width: 200px; height: 200px;
-    background-color: blue">
-  <div style="height: 2000px"></div>
-</div>
diff --git a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/compositing/squash-partial-repaint-inside-squashed-layer-expected.html b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/compositing/squash-partial-repaint-inside-squashed-layer-expected.html
deleted file mode 100644
index 8415aa1..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/compositing/squash-partial-repaint-inside-squashed-layer-expected.html
+++ /dev/null
@@ -1,46 +0,0 @@
-<!DOCTYPE html>
-<head>
-<style>
-.box {
-  width: 100px;
-  height: 100px;
-}
-
-.behind {
-  position: absolute;
-  top: 100px;
-  left: 100px;
-  background-color: blue;
-}
-
-.middle {
-  position: absolute;
-  top: 180px;
-  left: 180px;
-  background-color: lime;
-}
-
-.repaintdiv {
-  position: absolute;
-  top: 260px;
-  left: 260px;
-  width: 182px;
-  height: 29px;
-  background-color:salmon;
-}
-
-.top {
-  position: absolute;
-  top: 280px;
-  left: 340px;
-  background-color: cyan;
-}
-
-</style>
-</head>
-<body>
-    <div class="box behind"></div>
-    <div class="box middle"></div>
-    <img id="repaintdiv" class="repaintdiv"></img>
-    <div class="box top"></div>
-</body>
diff --git a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/compositing/squashing-inside-preserve-3d-element-expected.html b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/compositing/squashing-inside-preserve-3d-element-expected.html
deleted file mode 100644
index ac73079..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/compositing/squashing-inside-preserve-3d-element-expected.html
+++ /dev/null
@@ -1,5 +0,0 @@
-<!doctype html>
-<div style="transform-style: preserve-3d">
-  <div style="width: 100px; height: 100px; background:lightgray; transform: translateZ(0)"></div>
-  <div id="target" style="position: absolute; top: 20px; left: 20px; height: 100px; width: 100px; background:red"></div>
-</div>
diff --git a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/compositing/stacked-float-under-composited-inline-expected.html b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/compositing/stacked-float-under-composited-inline-expected.html
deleted file mode 100644
index 2abd3f6..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/compositing/stacked-float-under-composited-inline-expected.html
+++ /dev/null
@@ -1,3 +0,0 @@
-<!DOCTYPE html>
-<div style="position: relative; top: 50px; left: 50px; width: 100px; height: 100px; background-color: green"></div>
-
diff --git a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/compositing/tricky-element-removal-crash-expected.html b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/compositing/tricky-element-removal-crash-expected.html
deleted file mode 100644
index e815e92..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/compositing/tricky-element-removal-crash-expected.html
+++ /dev/null
@@ -1,3 +0,0 @@
-<!DOCTYPE html>
-<div style="width: 200px; height: 200px; background-color: salmon;"></div>
-<div style="position: absolute; top: 8px; width: 100px; height: 100px"></div>
diff --git a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/containing-block-position-change-expected.html b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/containing-block-position-change-expected.html
deleted file mode 100644
index 3061e14..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/containing-block-position-change-expected.html
+++ /dev/null
@@ -1,12 +0,0 @@
-<html>
-<body>
-    <p>
-        This is a repaint test for <i><a href="https://bugs.webkit.org/show_bug.cgi?id=9121">http://bugzilla.opendarwin.org/show_bug.cgi?id=9121</a>
-        REGRESSION: [Incremental Repaint] DHTML movement test failures</i>.
-    </p>
-    <hr>
-    <div id="t" style="position: relative; left: 50px; width: 500px;">
-        <div style="width: 50px; height: 50px; background: blue; position: absolute; left: 100px;"></div>
-    </div>
-</body>
-</html>
diff --git a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/content-into-overflow-expected.html b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/content-into-overflow-expected.html
deleted file mode 100644
index 2fe3cdb..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/content-into-overflow-expected.html
+++ /dev/null
@@ -1,37 +0,0 @@
-<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
-<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
-<head>
-    <title>Test for http://bugs.webkit.org/show_bug.cgi?id=12885</title>
-    <style type="text/css">
-        div.wide { width: 100px; height: 50px; }
-        div.narrow { width: 50px; }
-        div.tall { width: 50px; height: 100px; }
-        div.short { height: 50px; width: 50px; }
-        #main-content { float: left; width: 100px; height: 80px; }
-        #target3 { clear: both; height: 20px; background: green; }
-    </style>
-</head>
-<body>
-    <div style="position: absolute; border: medium solid green; top: 8px; height: 100px;">
-        <div class="narrow" id="target1" style="width: auto">
-            <div class="wide"></div>
-        </div>
-    </div>
-
-    <div style="position: absolute; border: medium solid green; top: 158px; width: 100px;">
-        <div class="short" id="target2" style="height: auto">
-            <div class="tall"></div>
-        </div>
-    </div>
-
-    <div style="position: absolute; top: 308px;">
-        <div style="background: green;">
-            <div style="position: relative;">
-                <div id="main-content">
-                </div>
-            </div>
-            <div id="target3"></div>
-        </div>
-    </div>
-</body>
-</html>
diff --git a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/control-clip-expected.html b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/control-clip-expected.html
deleted file mode 100644
index 74519cc..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/control-clip-expected.html
+++ /dev/null
@@ -1,22 +0,0 @@
-<html>
-<head>
-    <title></title>
-    <style>
-        select, button { display: block; height: 30px; width: 200px; }
-        select { -webkit-appearance: none; }
-    </style>
-</head>
-<body>
-    <p>
-        Test for <i><a href="http://bugs.webkit.org/show_bug.cgi?id=13391">http://bugs.webkit.org/show_bug.cgi?id=13391</a>
-        REGRESSION (r18819): Incomplete repaint of button text</i>.
-    </p>
-    <p>
-        The popup and the button should say &ldquo;SUCCESS&rdquo; with no sign of &ldquo;FAILURE&rdquo;.
-    </p>
-    <select id="popup">
-        <option selected>SUCCESS</option>
-    </select>
-    <button id="button">SUCCESS</button>
-</body>
-</html>
diff --git a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/crbug-371640-2-expected.html b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/crbug-371640-2-expected.html
deleted file mode 100644
index 0ab3cf7..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/crbug-371640-2-expected.html
+++ /dev/null
@@ -1,40 +0,0 @@
-<!DOCTYPE html>
-<style>
-#wrapper {
-  visibility: hidden;
-  position: absolute;
-  width: 600px;
-}
-.outer { float: left; }
-.inner {
-  float: left;
-  height: 100px;
-  position: relative;
-  width: 260px;
-}
-.abs_pos { position: absolute; }
-#container { float: right; }
-.item {
-  visibility: visible;
-  background-color: green;
-  width: 100px;
-  height: 100px;
-}
-</style>
-
-<p>This is a reduction for http://crbug.com/371640.</p>
-<p>The test PASSES if you see 1 green square and no red square.</p>
-
-<div id='wrapper'>
- <div id='container'>
-  <div id='keep_outer' class='outer'>
-   <div>
-    <div id='keep_inner' class='inner'>
-     <div class='abs_pos'>
-      <div id='keep' class='item'> </div>
-     </div>
-    </div>
-   </div>
-  </div>
- </div>
-</div>
diff --git a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/crbug-371640-3-expected.html b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/crbug-371640-3-expected.html
deleted file mode 100644
index 173b559d..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/crbug-371640-3-expected.html
+++ /dev/null
@@ -1,45 +0,0 @@
-<!DOCTYPE html>
-<style>
-#wrapper {
-  visibility: hidden;
-  position: absolute;
-  width: 600px;
-  float: right;
-}
-#container { float: right; }
-#abs_pos {
-  position: absolute;
-  bottom: 0;
-}
-#keep_child {
-  height: 100px;
-  width: 100px;
-  visibility: visible;
-}
-#keep_child { background-color: green; }
-.outer {
-  float: left;
-  width: 100px;
-  height: 300px;
-}
-#keep_inner {
-  position: relative;
-  height: 220px;
-}
-p { visibility: visible; }
-</style>
-
-<p>This is a reduction for http://crbug.com/371640.</p>
-<p>The test PASSES if you see 1 green square and no red square.</p>
-
-<div id='wrapper'>
- <div id='container'>
-  <div id='keep_outer' class='outer'>
-   <div id='keep_inner'>
-    <div id='abs_pos'>
-     <div id='keep_child'> </div>
-    </div>
-   </div>
-  </div>
- </div>
-</div>
diff --git a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/crbug-371640-4-expected.html b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/crbug-371640-4-expected.html
deleted file mode 100644
index a9d098c..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/crbug-371640-4-expected.html
+++ /dev/null
@@ -1,45 +0,0 @@
-<!DOCTYPE html>
-<style>
-  #wrapper {
-    visibility: hidden;
-    position: absolute;
-    width: 600px;
-  }
-  .outer {
-    display: inline;
-    position: relative;
-    float: right;
-    width: 100px;
-    height: 100px;
-    margin-right: 100px;
-  }
-  .inner {
-    float: left;
-    height: 100px;
-    position: relative;
-    width: 100px;
-  }
-  .abs_pos { position: absolute; }
-  #container { float: right; width: 500px}
-  .item {
-    visibility: visible;
-    background-color: green;
-    width: 100px;
-    height: 100px;
-  }
-</style>
-
-<p>This is a reduction for http://crbug.com/371640.</p>
-<p>The test PASSES if you see 1 green square and no red square.</p>
-
-<div id='wrapper'>
- <div id='container'>
-  <div id='keep_outer' class="outer">
-   <div class='abs_pos'>
-    <div id='keep_inner' class="inner">
-     <div id='keep' class="item">&nbsp;</div>
-    </div>
-   </div>
-  </div>
- </div>
-</div>
diff --git a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/crbug-371640-expected.html b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/crbug-371640-expected.html
deleted file mode 100644
index da9bc539..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/crbug-371640-expected.html
+++ /dev/null
@@ -1,38 +0,0 @@
-<!DOCTYPE html>
-<style>
-  #wrapper {
-    visibility: hidden;
-    position: absolute;
-    width: 600px;
-  }
-  .outer { float: left; }
-  .inner {
-    float: left ;
-    height: 100px;
-    position: relative;
-    width: 260px;
-  }
-  .abs_pos { position: absolute; }
-  #container { float: right; }
-  .item {
-    visibility: visible;
-    background-color: green;
-    width: 100px;
-    height: 100px;
-  }
-</style>
-
-<p>This is a reduction for http://crbug.com/371640.</p>
-<p>The test PASSES if you see 1 green square and no red square.</p>
-
-<div id='wrapper'>
- <div id='container'>
-  <div id='keep_outer' class="outer">
-   <div id='keep_inner' class="inner">
-    <div class="abs_pos">
-     <div id='keep' class="item">&nbsp;</div>
-    </div>
-   </div>
-  </div>
- </div>
-</div>
diff --git a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/create-layer-repaint-expected.html b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/create-layer-repaint-expected.html
deleted file mode 100644
index 18c6a0e..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/create-layer-repaint-expected.html
+++ /dev/null
@@ -1,21 +0,0 @@
-<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
-  "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
-<html>
-<head>
-  <meta http-equiv="Content-type" content="text/html; charset=utf-8">
-  <title>CSS Transition test case</title>
-  <style type="text/css" media="screen">
-    .stretchy {
-      background: green;
-      opacity: 0.5;
-      height: 50px;
-      width: 250px;
-      margin: 20px;
-    }
-  </style>
-</head>
-<body>
-  <p>If you see red, the test failed</p>
-  <div id="test" class="stretchy"></div>
-</body>
-</html>
diff --git a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/css-grid-layout/grid-element-change-columns-repaint-expected.html b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/css-grid-layout/grid-element-change-columns-repaint-expected.html
deleted file mode 100644
index 41aa7f02..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/css-grid-layout/grid-element-change-columns-repaint-expected.html
+++ /dev/null
@@ -1,26 +0,0 @@
-<!DOCTYPE html>
-<html>
-<link href="../../../fast/css-intrinsic-dimensions/resources/width-keyword-classes.css" rel="stylesheet">
-<link href="../../../fast/css-grid-layout/resources/grid.css" rel="stylesheet">
-<style>
-body {
-    font: 10px/1 Ahem;
-}
-
-.grid {
-    grid-template-rows: 50px;
-    grid-template-columns: minmax(50px, 180px) 100px 100px;
-}
-.sizedToGridArea {
-    background-color: purple;
-}
-</style>
-<body>
-<div> This test checks that changing the grid-template-columns lead to a repaint. The final grid element should be 250px * 50px, the grid item should be 50px * 50px. No trace of the elements before the grid-template-columns change should be seen.</div>
-<div class="constrainedContainer">
-    <div class="grid min-content">
-        <div class="sizedToGridArea"></div>
-    </div>
-</div>
-</body>
-</html>
diff --git a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/css-grid-layout/grid-element-change-rows-repaint-expected.html b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/css-grid-layout/grid-element-change-rows-repaint-expected.html
deleted file mode 100644
index 05bb70c..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/css-grid-layout/grid-element-change-rows-repaint-expected.html
+++ /dev/null
@@ -1,26 +0,0 @@
-<!DOCTYPE html>
-<html>
-<link href="../../../fast/css-intrinsic-dimensions/resources/width-keyword-classes.css" rel="stylesheet">
-<link href="../../../fast/css-grid-layout/resources/grid.css" rel="stylesheet">
-<style>
-body {
-    font: 10px/1 Ahem;
-}
-
-.grid {
-    grid-template-rows: 100px 50px;
-    grid-template-columns: 100px;
-}
-.sizedToGridArea {
-    background-color: purple;
-}
-</style>
-<body>
-<div>This test checks that changing the grid-template-rows lead to a repaint. The final grid element should be 100px * 150px, the grid item should be 100px * 100px. No trace of the elements before the grid-template-rows change should be seen.</div>
-<div class="constrainedContainer">
-    <div class="grid fit-content">
-        <div class="sizedToGridArea"></div>
-    </div>
-</div>
-</body>
-</html>
diff --git a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/css-grid-layout/grid-item-change-column-repaint-expected.html b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/css-grid-layout/grid-item-change-column-repaint-expected.html
deleted file mode 100644
index d40fc3a..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/css-grid-layout/grid-item-change-column-repaint-expected.html
+++ /dev/null
@@ -1,27 +0,0 @@
-<!DOCTYPE html>
-<html>
-<link href="../../../fast/css-intrinsic-dimensions/resources/width-keyword-classes.css" rel="stylesheet">
-<link href="../../../fast/css-grid-layout/resources/grid.css" rel="stylesheet">
-<style>
-body {
-    font: 10px/1 Ahem;
-}
-
-.grid {
-    grid-template-rows: 50px;
-    grid-template-columns: minmax(100px, 180px) 100px minmax(50px, 100px);
-}
-.sizedToGridArea {
-    background-color: purple;
-    grid-column: 3;
-}
-</style>
-<body>
-<div>This test checks that changing the grid-column on a grid item properly repaint. The final grid item should be 50px * 50px. There should be no trace of the grid item at the old position.</div>
-<div class="constrainedContainer">
-    <div class="grid fit-content">
-        <div class="sizedToGridArea"></div>
-    </div>
-</div>
-</body>
-</html>
diff --git a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/css-grid-layout/grid-item-change-row-repaint-expected.html b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/css-grid-layout/grid-item-change-row-repaint-expected.html
deleted file mode 100644
index a6086fa..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/css-grid-layout/grid-item-change-row-repaint-expected.html
+++ /dev/null
@@ -1,26 +0,0 @@
-<!DOCTYPE html>
-<html>
-<link href="../../../fast/css-grid-layout/resources/grid.css" rel="stylesheet">
-<style>
-body {
-    font: 10px/1 Ahem;
-}
-
-.grid {
-    grid-template-rows: 50px 100px;
-    grid-template-columns: 100px 50px;
-    /* Make the grid shrink to fit. */
-    position: absolute;
-}
-.sizedToGridArea {
-    background-color: purple;
-    grid-row: 2;
-}
-</style>
-<body>
-<div>This test checks that changing the grid-row on a grid item properly repaint. The final grid item should be 100px * 100px. There should be no trace of the grid item at the old position.</div>
-<div class="grid">
-    <div class="sizedToGridArea"></div>
-</div>
-</body>
-</html>
diff --git a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/css-grid-layout/grid-item-z-index-change-repaint-expected.html b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/css-grid-layout/grid-item-z-index-change-repaint-expected.html
deleted file mode 100644
index b0c4e3c..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/css-grid-layout/grid-item-z-index-change-repaint-expected.html
+++ /dev/null
@@ -1,37 +0,0 @@
-<!DOCTYPE html>
-<html>
-<head>
-<link href="../../../fast/css-intrinsic-dimensions/resources/width-keyword-classes.css" rel="stylesheet">
-<link href="../../../fast/css-grid-layout/resources/grid.css" rel="stylesheet">
-<style>
-.grid {
-    grid-template-rows: 100px;
-    grid-template-columns: 200px 200px;
-    margin-top: 10px;
-}
-.green {
-    background-color: green;
-}
-.red {
-    background-color: red;
-}
-</style>
-</head>
-<body>
-<div style="height: 100px">
-    <p>This test checks that grid items correctly repaint when 'z-index' changes.</p>
-    <p>For this test to pass, there should be no red below.</p>
-</div>
-
-<div class="grid fit-content">
-    <div id="item1" class="sizedToGridArea green"></div>
-    <div class="sizedToGridArea red"></div>
-</div>
-
-<div class="grid fit-content">
-    <div id="item2" class="sizedToGridArea green"></div>
-    <div class="sizedToGridArea red"></div>
-</div>
-
-</body>
-</html>
diff --git a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/destroy-composited-scrollbar-expected.txt b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/destroy-composited-scrollbar-expected.txt
index 1ad8fa50..21c6bd11 100644
--- a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/destroy-composited-scrollbar-expected.txt
+++ b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/destroy-composited-scrollbar-expected.txt
@@ -35,8 +35,13 @@
         },
         {
           "object": "LayoutBlockFlow (positioned) DIV",
-          "rect": [185, 0, 15, 200],
-          "reason": "scroll control"
+          "rect": [0, 0, 200, 200],
+          "reason": "compositing update"
+        },
+        {
+          "object": "LayoutBlockFlow DIV id='content'",
+          "rect": [0, 0, 100, 100],
+          "reason": "compositing update"
         }
       ]
     }
@@ -44,7 +49,11 @@
   "objectPaintInvalidations": [
     {
       "object": "LayoutBlockFlow (positioned) DIV",
-      "reason": "geometry"
+      "reason": "compositing update"
+    },
+    {
+      "object": "LayoutBlockFlow DIV id='content'",
+      "reason": "compositing update"
     }
   ]
 }
diff --git a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/details-open-repaint-expected.html b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/details-open-repaint-expected.html
deleted file mode 100644
index 3514925c..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/details-open-repaint-expected.html
+++ /dev/null
@@ -1,7 +0,0 @@
-<!DOCTYPE html>
-
-<p>This test passes if the arrow rotates to the open position.</p>
-<details open="true">
-  <input>
-  <summary>summary</summary>
-</details>
diff --git a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/do-not-paint-below-image-baseline-expected.html b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/do-not-paint-below-image-baseline-expected.html
deleted file mode 100644
index 4f5e785cb..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/do-not-paint-below-image-baseline-expected.html
+++ /dev/null
@@ -1,18 +0,0 @@
-<!DOCTYPE html>
-<html>
-  <head>
-    <style>
-      img {
-        margin: 50px;
-      }
-      body {
-          margin: 0px;
-      }
-    </style>
-  </head>
-  <body>
-    <img src="../../images/resources/59.jpg">
-    <p> When painting an inline image, do not paint below its baseline unless its selected.
-        The invalidation rect should not extend outside the content rect of the image. </p>
-  </body>
-</html>
diff --git a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/dynamic-table-vertical-alignment-change-expected.html b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/dynamic-table-vertical-alignment-change-expected.html
deleted file mode 100644
index 7a42d7e..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/dynamic-table-vertical-alignment-change-expected.html
+++ /dev/null
@@ -1,22 +0,0 @@
-<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
-        "http://www.w3.org/TR/html4/strict.dtd">
-
-<body>
- <p>
-        Repaint test for <i><a href="https://bugs.webkit.org/show_bug.cgi?id=23524">Bugzilla bug 23524</a></i>
-        Make sure that a table section doesn't stop painting when vertical alignment of cells dynamically changes.
-</p>
-<div style="width: 800px;">
-<table>
-    <tr valign="top">
-        <td>
-            <div id="target" style="css-float: left; background-color: green; width: 100px; height: 100px"></div>
-        </td>
-        <td>
-            <div style="margin: 0 0 1px 0;"></div>
-			<div></div>
-			<div></div>
-        </td>
-    </tr>
-</table>
-</div>
diff --git a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/erase-overflow-expected.html b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/erase-overflow-expected.html
deleted file mode 100644
index 7b151db..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/erase-overflow-expected.html
+++ /dev/null
@@ -1,11 +0,0 @@
-<html>
-<head>
-    <title>Test for http://bugs.webkit.org/show_bug.cgi?id=11935</title>
-    <style type="text/css">
-        div.square { width: 100px; height: 100px; }
-    </style>
-</head>
-<body>
-    <div class="square" style="background-color: green"></div>
-</body>
-</html>
diff --git a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/filter-invalidation-after-display-expected.html b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/filter-invalidation-after-display-expected.html
deleted file mode 100644
index 0f86fc6f..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/filter-invalidation-after-display-expected.html
+++ /dev/null
@@ -1,17 +0,0 @@
-<!DOCTYPE html>
-<style>
-.green {
-  background-color: green;
-}
-.box {
-  width: 200px;
-  height: 200px;
-  position: absolute;
-  left: 300px;
-}
-</style>
-<!--
-    This test checks that we correctly invalidate filters when they are removed.
-    There should be no red below.
--->
-<div class="green box" id="box"></div>
diff --git a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/filter-invalidation-positioned-child-expected.html b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/filter-invalidation-positioned-child-expected.html
deleted file mode 100644
index cfa86efe..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/filter-invalidation-positioned-child-expected.html
+++ /dev/null
@@ -1,24 +0,0 @@
-<!DOCTYPE html>
-<style>
-#box {
-  width: 100px;
-  height: 100px;
-  background-color: green;
-  filter: drop-shadow(300px 100px 10px green);
-}
-#positioned {
-  position: absolute;
-  top: 400px;
-  left: 400px;
-  width: 50px;
-  height: 50px;
-  background-color: blue;
-}
-</style>
-<!--
-Tests paint invalidation of positioned object when its ancestor changes filter.
-Passes if the all drop shadows change to green.
--->
-<div id="box">
-  <div id="positioned"></div>
-</div>
diff --git a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/filters/effect-reference-repaint-composite-1-expected.html b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/filters/effect-reference-repaint-composite-1-expected.html
deleted file mode 100644
index 3df7c65..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/filters/effect-reference-repaint-composite-1-expected.html
+++ /dev/null
@@ -1,17 +0,0 @@
-<!DOCTYPE html>
-<style>
-.box {
-  width: 200px;
-  height: 200px;
-  margin: 20px;
-  background-color: green;
-  filter: url(#composite);
-}
-</style>
-<div class="box"></div>
-<svg width="0" height="0">
-  <filter id="composite" x="-0.5" y="-0.5" width="2" height="2">
-    <feFlood x="100" y="100" width="200" height="200" flood-color="red"/>
-    <feComposite operator="in" in="SourceGraphic"/>
-  </filter>
-</svg>
diff --git a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/filters/effect-reference-repaint-composite-2-expected.html b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/filters/effect-reference-repaint-composite-2-expected.html
deleted file mode 100644
index 4e79271..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/filters/effect-reference-repaint-composite-2-expected.html
+++ /dev/null
@@ -1,17 +0,0 @@
-<!DOCTYPE html>
-<style>
-.box {
-  width: 200px;
-  height: 200px;
-  margin: 20px;
-  background-color: green;
-  filter: url(#composite);
-}
-</style>
-<div class="box"></div>
-<svg width="0" height="0">
-  <filter id="composite" x="-0.5" y="-0.5" width="2" height="2">
-    <feFlood x="100" y="100" width="200" height="200" flood-color="blue"/>
-    <feComposite operator="atop" in="SourceGraphic"/>
-  </filter>
-</svg>
diff --git a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/filters/effect-reference-repaint-composite-3-expected.html b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/filters/effect-reference-repaint-composite-3-expected.html
deleted file mode 100644
index d81abf99..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/filters/effect-reference-repaint-composite-3-expected.html
+++ /dev/null
@@ -1,18 +0,0 @@
-<!DOCTYPE html>
-<style>
-.box {
-  width: 200px;
-  height: 200px;
-  margin: 20px;
-  background-color: green;
-  filter: url(#composite);
-}
-</style>
-<div class="box"></div>
-<svg width="0" height="0">
-  <filter id="composite" x="-0.5" y="-0.5" width="2" height="2">
-    <feFlood x="100" y="100" width="200" height="200" flood-color="red"/>
-    <feComposite operator="arithmetic" k4="1" in="SourceGraphic"/>
-    <feColorMatrix values="0 0 0 0 0, 0 1 0 0 0, 0 0 0 0 0, 0 0 0 1 0"/>
-  </filter>
-</svg>
diff --git a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/filters/effect-reference-repaint-composite-4-expected.html b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/filters/effect-reference-repaint-composite-4-expected.html
deleted file mode 100644
index 3040299..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/filters/effect-reference-repaint-composite-4-expected.html
+++ /dev/null
@@ -1,17 +0,0 @@
-<!DOCTYPE html>
-<style>
-.box {
-  width: 200px;
-  height: 200px;
-  margin: 20px;
-  background-color: red;
-  filter: url(#composite);
-}
-</style>
-<div class="box"></div>
-<svg width="0" height="0">
-  <filter id="composite" x="-0.5" y="-0.5" width="2" height="2">
-    <feFlood x="100" y="100" width="200" height="200" flood-color="green"/>
-    <feComposite operator="arithmetic" k3="1" in="SourceGraphic"/>
-  </filter>
-</svg>
diff --git a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/filters/effect-reference-repaint-composite-5-expected.html b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/filters/effect-reference-repaint-composite-5-expected.html
deleted file mode 100644
index 25806ef..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/filters/effect-reference-repaint-composite-5-expected.html
+++ /dev/null
@@ -1,17 +0,0 @@
-<!DOCTYPE html>
-<style>
-.box {
-  width: 200px;
-  height: 200px;
-  margin: 20px;
-  background-color: green;
-  filter: url(#composite);
-}
-</style>
-<div class="box"></div>
-<svg width="0" height="0">
-  <filter id="composite" x="-0.5" y="-0.5" width="2" height="2">
-    <feFlood x="100" y="100" width="200" height="200" flood-color="white"/>
-    <feComposite operator="arithmetic" k1="1" in="SourceGraphic"/>
-  </filter>
-</svg>
diff --git a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/filters/effect-reference-repaint-composite-6-expected.html b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/filters/effect-reference-repaint-composite-6-expected.html
deleted file mode 100644
index 49f7400b..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/filters/effect-reference-repaint-composite-6-expected.html
+++ /dev/null
@@ -1,17 +0,0 @@
-<!DOCTYPE html>
-<style>
-.box {
-  width: 200px;
-  height: 200px;
-  margin: 20px;
-  background-color: green;
-  filter: url(#composite);
-}
-</style>
-<div class="box"></div>
-<svg width="0" height="0">
-  <filter id="composite" x="-0.5" y="-0.5" width="2" height="2">
-    <feFlood x="100" y="100" width="200" height="200" flood-color="blue"/>
-    <feComposite operator="arithmetic" k2="1" k3="1" in="SourceGraphic"/>
-  </filter>
-</svg>
diff --git a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/filters/effect-reference-repaint-displacement-expected.html b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/filters/effect-reference-repaint-displacement-expected.html
deleted file mode 100644
index 0ab5fc61..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/filters/effect-reference-repaint-displacement-expected.html
+++ /dev/null
@@ -1,18 +0,0 @@
-<!DOCTYPE html>
-<style>
-.box {
-  width: 200px;
-  height: 200px;
-  margin: 20px;
-  background-color: green;
-  filter: url(#displacement);
-}
-</style>
-<div class="box"></div>
-<svg width="0" height="0">
-  <filter id="displacement" x="-0.5" y="-0.5" width="2" height="2"
-          color-interpolation-filters="sRGB">
-    <feFlood/>
-    <feDisplacementMap in="SourceGraphic" scale="40"/>
-  </filter>
-</svg>
diff --git a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/filters/effect-reference-repaint-gaussianblur-expected.html b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/filters/effect-reference-repaint-gaussianblur-expected.html
deleted file mode 100644
index 48e5116..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/filters/effect-reference-repaint-gaussianblur-expected.html
+++ /dev/null
@@ -1,25 +0,0 @@
-<!DOCTYPE html>
-<html>
-  <head>
-    <style>
-      .box {
-        width: 200px;
-        height: 200px;
-        margin: 50px;
-        background-color: green;
-        -webkit-filter: url(#blur);
-        filter: url(#blur);
-      }
-    </style>
-  </head>
-  <body>
-    <div class="box"></div>
-    <svg xmlns="http://www.w3.org/2000/svg" width="0" height="0" version="1.1">
-      <defs>
-        <filter id="blur" x="-0.5" y="-0.5" width="2" height="2">
-          <feGaussianBlur stdDeviation="20 20"/>
-        </filter>
-      </defs>
-    </svg>
-  </body>
-</html>
diff --git a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/filters/effect-reference-repaint-gaussianblur-xonly-expected.html b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/filters/effect-reference-repaint-gaussianblur-xonly-expected.html
deleted file mode 100644
index 56f2ca1..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/filters/effect-reference-repaint-gaussianblur-xonly-expected.html
+++ /dev/null
@@ -1,25 +0,0 @@
-<!DOCTYPE html>
-<html>
-  <head>
-    <style>
-      .box {
-        width: 200px;
-        height: 200px;
-        margin: 50px;
-        background-color: green;
-        -webkit-filter: url(#blur);
-        filter: url(#blur);
-      }
-    </style>
-  </head>
-  <body>
-    <div class="box"></div>
-    <svg xmlns="http://www.w3.org/2000/svg" width="0" height="0" version="1.1">
-      <defs>
-        <filter id="blur" x="-0.5" y="-0.5" width="2" height="2">
-          <feGaussianBlur stdDeviation="20 0"/>
-        </filter>
-      </defs>
-    </svg>
-  </body>
-</html>
diff --git a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/filters/effect-reference-repaint-gaussianblur-yonly-expected.html b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/filters/effect-reference-repaint-gaussianblur-yonly-expected.html
deleted file mode 100644
index c091e17..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/filters/effect-reference-repaint-gaussianblur-yonly-expected.html
+++ /dev/null
@@ -1,25 +0,0 @@
-<!DOCTYPE html>
-<html>
-  <head>
-    <style>
-      .box {
-        width: 200px;
-        height: 200px;
-        margin: 50px;
-        background-color: green;
-        -webkit-filter: url(#blur);
-        filter: url(#blur);
-      }
-    </style>
-  </head>
-  <body>
-    <div class="box"></div>
-    <svg xmlns="http://www.w3.org/2000/svg" width="0" height="0" version="1.1">
-      <defs>
-        <filter id="blur" x="-0.5" y="-0.5" width="2" height="2">
-          <feGaussianBlur stdDeviation="0 20"/>
-        </filter>
-      </defs>
-    </svg>
-  </body>
-</html>
diff --git a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/filters/effect-reference-repaint-lighting-expected.html b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/filters/effect-reference-repaint-lighting-expected.html
deleted file mode 100644
index bb472e7e..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/filters/effect-reference-repaint-lighting-expected.html
+++ /dev/null
@@ -1,19 +0,0 @@
-<!DOCTYPE html>
-<style>
-.box {
-  width: 200px;
-  height: 200px;
-  margin: 20px;
-  background-image: radial-gradient(transparent, black);
-  filter: url(#lighting);
-}
-</style>
-<div class="box"></div>
-<svg width="0" height="0">
-  <filter id="lighting" x="-0.5" y="-0.5" width="2" height="2">
-    <feDiffuseLighting surfaceScale="200">
-      <feDistantLight azimuth="135"/>
-    </feDiffuseLighting>
-    <feComposite operator="in" x="50" y="50" width="100" height="100" in2="SourceGraphic"/>
-  </filter>
-</svg>
diff --git a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/filters/effect-reference-repaint-merge-expected.html b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/filters/effect-reference-repaint-merge-expected.html
deleted file mode 100644
index 87493c6..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/filters/effect-reference-repaint-merge-expected.html
+++ /dev/null
@@ -1,34 +0,0 @@
-<!DOCTYPE html>
-<html>
-  <head>
-    <style>
-      .box {
-        width: 200px;
-        height: 200px;
-        margin: 20px;
-        background-color: green;
-        -webkit-filter: url(#merge);
-        filter: url(#merge);
-      }
-    </style>
-  </head>
-  <body>
-    <div class="box"></div>
-    <svg xmlns="http://www.w3.org/2000/svg" width="0" height="0" version="1.1">
-      <defs>
-        <filter id="merge" x="-0.5" y="-0.5" width="2" height="2">
-          <feColorMatrix type="matrix" values="1 0 0 0 0  0 1 0 0 0  0 0 1 0 0  0 0 0 0.3 0"  result="trans"/>
-          <feOffset dx="40" dy="40"   in="trans" result="offset1"/>
-          <feOffset dx="80" dy="80"   in="trans" result="offset2"/>
-          <feOffset dx="120" dy="120" in="trans" result="offset3"/>
-          <feMerge>
-            <feMergeNode in="trans"/>
-            <feMergeNode in="offset1"/>
-            <feMergeNode in="offset2"/>
-            <feMergeNode in="offset3"/>
-          </feMerge>
-        </filter>
-      </defs>
-    </svg>
-  </body>
-</html>
diff --git a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/filters/effect-reference-repaint-morphology-expected.html b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/filters/effect-reference-repaint-morphology-expected.html
deleted file mode 100644
index 2b6d797..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/filters/effect-reference-repaint-morphology-expected.html
+++ /dev/null
@@ -1,25 +0,0 @@
-<!DOCTYPE html>
-<html>
-  <head>
-    <style>
-      .box {
-        width: 200px;
-        height: 200px;
-        margin: 50px;
-        background-color: green;
-        -webkit-filter: url(#morphology);
-        filter: url(#morphology);
-      }
-    </style>
-  </head>
-  <body>
-    <div class="box"></div>
-    <svg xmlns="http://www.w3.org/2000/svg" width="0" height="0" version="1.1">
-      <defs>
-        <filter id="morphology" x="-0.5" y="-0.5" width="2" height="2">
-          <feMorphology radius="25" operator="erode"/>
-        </filter>
-      </defs>
-    </svg>
-  </body>
-</html>
diff --git a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/filters/effect-reference-repaint-morphology-xonly-expected.html b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/filters/effect-reference-repaint-morphology-xonly-expected.html
deleted file mode 100644
index e981edb..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/filters/effect-reference-repaint-morphology-xonly-expected.html
+++ /dev/null
@@ -1,25 +0,0 @@
-<!DOCTYPE html>
-<html>
-  <head>
-    <style>
-      .box {
-        width: 200px;
-        height: 200px;
-        margin: 50px;
-        background-color: green;
-        -webkit-filter: url(#morphology);
-        filter: url(#morphology);
-      }
-    </style>
-  </head>
-  <body>
-    <div class="box"></div>
-    <svg xmlns="http://www.w3.org/2000/svg" width="0" height="0" version="1.1">
-      <defs>
-        <filter id="morphology" x="-0.5" y="-0.5" width="2" height="2">
-          <feMorphology radius="25 0" operator="erode"/>
-        </filter>
-      </defs>
-    </svg>
-  </body>
-</html>
diff --git a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/filters/effect-reference-repaint-morphology-yonly-expected.html b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/filters/effect-reference-repaint-morphology-yonly-expected.html
deleted file mode 100644
index e985c118..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/filters/effect-reference-repaint-morphology-yonly-expected.html
+++ /dev/null
@@ -1,25 +0,0 @@
-<!DOCTYPE html>
-<html>
-  <head>
-    <style>
-      .box {
-        width: 200px;
-        height: 200px;
-        margin: 50px;
-        background-color: green;
-        -webkit-filter: url(#morphology);
-        filter: url(#morphology);
-      }
-    </style>
-  </head>
-  <body>
-    <div class="box"></div>
-    <svg xmlns="http://www.w3.org/2000/svg" width="0" height="0" version="1.1">
-      <defs>
-        <filter id="morphology" x="-0.5" y="-0.5" width="2" height="2">
-          <feMorphology radius="0 25" operator="erode"/>
-        </filter>
-      </defs>
-    </svg>
-  </body>
-</html>
diff --git a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/filters/effect-reference-repaint-offset-expected.html b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/filters/effect-reference-repaint-offset-expected.html
deleted file mode 100644
index be9f8cc..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/filters/effect-reference-repaint-offset-expected.html
+++ /dev/null
@@ -1,24 +0,0 @@
-<!DOCTYPE html>
-<html>
-  <head>
-    <style>
-      .box {
-        width: 200px;
-        height: 200px;
-        background-color: green;
-        -webkit-filter: url(#offset);
-        filter: url(#offset);
-      }
-    </style>
-  </head>
-  <body>
-    <div class="box"></div>
-    <svg xmlns="http://www.w3.org/2000/svg" width="0" height="0" version="1.1">
-      <defs>
-        <filter id="offset" x="-0.5" y="-0.5" width="2" height="2">
-          <feOffset dx="190" dy="190"/>
-        </filter>
-      </defs>
-    </svg>
-  </body>
-</html>
diff --git a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/filters/effect-reference-repaint-primitive-attr-mutation-expected.txt b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/filters/effect-reference-repaint-primitive-attr-mutation-expected.txt
new file mode 100644
index 0000000..e3e1f13
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/filters/effect-reference-repaint-primitive-attr-mutation-expected.txt
@@ -0,0 +1,34 @@
+{
+  "layers": [
+    {
+      "name": "LayoutView #document",
+      "bounds": [800, 600],
+      "backgroundColor": "#FFFFFF"
+    },
+    {
+      "name": "Scrolling Layer",
+      "bounds": [800, 600],
+      "drawsContent": false
+    },
+    {
+      "name": "Scrolling Contents Layer",
+      "bounds": [800, 600],
+      "contentsOpaque": true,
+      "backgroundColor": "#FFFFFF",
+      "paintInvalidations": [
+        {
+          "object": "LayoutBlockFlow DIV class='target'",
+          "rect": [8, 8, 100, 100],
+          "reason": "full"
+        }
+      ]
+    }
+  ],
+  "objectPaintInvalidations": [
+    {
+      "object": "LayoutBlockFlow DIV class='target'",
+      "reason": "full"
+    }
+  ]
+}
+
diff --git a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/filters/effect-reference-repaint-primitive-attr-removal-expected.txt b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/filters/effect-reference-repaint-primitive-attr-removal-expected.txt
new file mode 100644
index 0000000..e3e1f13
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/filters/effect-reference-repaint-primitive-attr-removal-expected.txt
@@ -0,0 +1,34 @@
+{
+  "layers": [
+    {
+      "name": "LayoutView #document",
+      "bounds": [800, 600],
+      "backgroundColor": "#FFFFFF"
+    },
+    {
+      "name": "Scrolling Layer",
+      "bounds": [800, 600],
+      "drawsContent": false
+    },
+    {
+      "name": "Scrolling Contents Layer",
+      "bounds": [800, 600],
+      "contentsOpaque": true,
+      "backgroundColor": "#FFFFFF",
+      "paintInvalidations": [
+        {
+          "object": "LayoutBlockFlow DIV class='target'",
+          "rect": [8, 8, 100, 100],
+          "reason": "full"
+        }
+      ]
+    }
+  ],
+  "objectPaintInvalidations": [
+    {
+      "object": "LayoutBlockFlow DIV class='target'",
+      "reason": "full"
+    }
+  ]
+}
+
diff --git a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/filters/effect-reference-repaint-primitive-removed-expected.txt b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/filters/effect-reference-repaint-primitive-removed-expected.txt
new file mode 100644
index 0000000..e3e1f13
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/filters/effect-reference-repaint-primitive-removed-expected.txt
@@ -0,0 +1,34 @@
+{
+  "layers": [
+    {
+      "name": "LayoutView #document",
+      "bounds": [800, 600],
+      "backgroundColor": "#FFFFFF"
+    },
+    {
+      "name": "Scrolling Layer",
+      "bounds": [800, 600],
+      "drawsContent": false
+    },
+    {
+      "name": "Scrolling Contents Layer",
+      "bounds": [800, 600],
+      "contentsOpaque": true,
+      "backgroundColor": "#FFFFFF",
+      "paintInvalidations": [
+        {
+          "object": "LayoutBlockFlow DIV class='target'",
+          "rect": [8, 8, 100, 100],
+          "reason": "full"
+        }
+      ]
+    }
+  ],
+  "objectPaintInvalidations": [
+    {
+      "object": "LayoutBlockFlow DIV class='target'",
+      "reason": "full"
+    }
+  ]
+}
+
diff --git a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/fixed-element-repaint-after-compositing-update-expected.html b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/fixed-element-repaint-after-compositing-update-expected.html
deleted file mode 100644
index 584c123..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/fixed-element-repaint-after-compositing-update-expected.html
+++ /dev/null
@@ -1,20 +0,0 @@
-<!DOCTYPE html>
-<html>
-<head>
-<style>
-#moveMe {
-    position: fixed;
-    background: green;
-    width: 100px;
-    height: 100px;
-    top: 150px;
-    left: 150px;
-}
-</style>
-</head>
-
-<body>
-    <p>This test checks that we correctly invalidate a shifted fixed positioned element overlapping another fixed positioned element.</p>
-    <p>For this test, there should be only one green square below.</p>
-    <div id="moveMe"></div>
-</body>
diff --git a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/fixed-margin-change-repaint-expected.html b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/fixed-margin-change-repaint-expected.html
deleted file mode 100644
index 02cf75bc..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/fixed-margin-change-repaint-expected.html
+++ /dev/null
@@ -1,23 +0,0 @@
-<!DOCTYPE HTML>
-<style>
-    body {
-        margin: 0;
-    }
-    #container {
-        position: relative;
-        top: 40px;
-        width: 200px;
-        height: 400px;
-    }
-    #test {
-        position: fixed;
-        background-color: green;
-        width: 100px;
-        height: 100px;
-        margin-top: 20px;
-    }
-</style>
-<div id="container">
-    <div id="test"></div>
-</div>
-Tests the repainting of fixed element when margin-top changes.
diff --git a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/fixed-position-transparency-with-overflow-expected.html b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/fixed-position-transparency-with-overflow-expected.html
deleted file mode 100644
index e3689aa..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/fixed-position-transparency-with-overflow-expected.html
+++ /dev/null
@@ -1,9 +0,0 @@
-<html>
-<head>
-    <link rel="stylesheet" href="resources/default.css">
-</head>
-<body style="height:2000px;">
-    <!-- You should see 2 rectangles touching on one corner in the output: a green one (top left) and a green one. -->
-    <div id="container" style="top: 200px; opacity: 0.4" class="relative blue"><div style="top:100px; left:100px;" class="absolute green"></div></div>
-</body>
-</html>
diff --git a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/fixed-to-relative-position-with-absolute-child-expected.html b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/fixed-to-relative-position-with-absolute-child-expected.html
deleted file mode 100644
index b0490eb..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/fixed-to-relative-position-with-absolute-child-expected.html
+++ /dev/null
@@ -1,9 +0,0 @@
-<html>
-<head>
-    <link rel="stylesheet" href="resources/default.css">
-</head>
-<body style="height:2000px;">
-    <!-- You should see 2 rectangles touching on one corner in the output: a green one (top left) and a green one. -->
-    <div id="container" style="top: 200px; position: relative" class="blue"><div style="top:100px; left:100px;" class="absolute green"></div></div>
-</body>
-</html>
diff --git a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/fixed-under-composited-absolute-scrolled-expected.html b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/fixed-under-composited-absolute-scrolled-expected.html
deleted file mode 100644
index 15ec5ae..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/fixed-under-composited-absolute-scrolled-expected.html
+++ /dev/null
@@ -1,17 +0,0 @@
-<!DOCTYPE html>
-<script>
-onload = function() { window.scrollTo(0, 400); };
-</script>
-<style>
-body { height: 1985px; }
-#target {
-  position: absolute;
-  top: 400px;
-  left: 0;
-  width: 100px;
-  height: 200px;
-  /* Result of blended 99% green and 1% red */
-  background-color: rgb(3, 126, 0);
-}
-</style>
-<div id="target"></div>
diff --git a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/fixed-under-composited-fixed-scrolled-expected.html b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/fixed-under-composited-fixed-scrolled-expected.html
deleted file mode 100644
index 53b6595..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/fixed-under-composited-fixed-scrolled-expected.html
+++ /dev/null
@@ -1,10 +0,0 @@
-<!DOCTYPE html>
-<script>
-onload = function() { window.scrollTo(0, 400); }
-</script>
-<style>
-body {
-  height: 2000px;
-  background-color: green;
-}
-</style>
diff --git a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/fixed-with-border-under-composited-absolute-scrolled-expected.html b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/fixed-with-border-under-composited-absolute-scrolled-expected.html
deleted file mode 100644
index a020aa91..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/fixed-with-border-under-composited-absolute-scrolled-expected.html
+++ /dev/null
@@ -1,18 +0,0 @@
-<!DOCTYPE html>
-<script>
-onload = function() { window.scrollTo(0, 400); }
-</script>
-<style>
-body { height: 1985px; }
-#target {
-  position: absolute;
-  top: 400px;
-  left: 0;
-  width: 100px;
-  height: 200px; 
-  /* The colors are results of blended 99% green/blue and 1% red. */
-  border: 10px solid rgb(3, 0, 252);
-  background-color: rgb(3, 126, 0);
-}
-</style>
-<div id="target"></div>
diff --git a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/flexbox/repaint-expected.html b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/flexbox/repaint-expected.html
deleted file mode 100644
index 92b7699..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/flexbox/repaint-expected.html
+++ /dev/null
@@ -1,23 +0,0 @@
-<!DOCTYPE html>
-<html>
-<style>
-#flexbox {
-  display: flex;
-}
-
-#left {
-  flex: 1;
-  background-color: yellow;
-}
-
-#content {
-  flex: 5 0 0px;
-  background-color: grey;
-}
-</style>
-<br><br><br><br><br><br>
-<div id="flexbox">
-<div id="left"></div>
-<div id="content">
-<p style="margin: 0">Lorem ipsum dolor sit amet, consectetur adipiscing elit. Aenean laoreet dolor id urna eleifend aliquet. Nulla vel dolor ipsum. Aliquam ut turpis nisl, in vulputate sapien. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Sed congue magna vitae dolor feugiat vehicula. Sed volutpat, tellus vel varius vestibulum, purus quam mollis sapien, in condimentum leo neque sed nulla. Nunc quis porta elit. Pellentesque erat lectus, ultricies a lobortis id, faucibus id quam.</p>
-</div>
diff --git a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/flexbox/repaint-on-layout-expected.html b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/flexbox/repaint-on-layout-expected.html
deleted file mode 100644
index 94cd01b..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/flexbox/repaint-on-layout-expected.html
+++ /dev/null
@@ -1,39 +0,0 @@
-<!DOCTYPE html>
-<html>
-<head>
-    <title>Test for repaint on layout of flexbox</title>
-    <style>
-        html {
-            height: 100%
-        }
-
-        .nav-bar {
-            display: flex;
-            height: 100%;
-            position: fixed;
-            top: 0;
-            background-color: yellow;
-        }
-
-        .nav-right {
-            width: 200px;
-            background-color: green;
-        }
-
-        .state {
-            float: right;
-            line-height: 0;
-        }
-    </style>
-</head>
-<body>
-    <nav class="nav-bar">
-        <div class="nav-right"></div>
-    </nav>
-    <div class="item">
-        <div class="state">
-        </div>
-    </div>
-</body>
-</html>
-
diff --git a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/flexbox/repaint-on-margin-change-expected.html b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/flexbox/repaint-on-margin-change-expected.html
deleted file mode 100644
index b137506..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/flexbox/repaint-on-margin-change-expected.html
+++ /dev/null
@@ -1,22 +0,0 @@
-<!DOCTYPE html>
-<html>
-<head>
-    <title>Test for repaint on margin change</title>
-    <style>
-        .child {
-            height: 20px;
-            width: 20px;
-            background-color: green;
-        }
-    </style>
-</head>
-<body>
-    <div style="display: flex; flex-direction: column; height: 100%; background-color: blue">
-        <div style="flex: 1"></div>
-        <div class='nested-row-flexbox'>
-            <div class="child"></div>
-            <div class="child" id="child-to-grow" style="margin-left: 40px"></div>
-        </div>
-    </div>
-</body>
-</html>
diff --git a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/flexbox/repaint-opacity-change-expected.html b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/flexbox/repaint-opacity-change-expected.html
deleted file mode 100644
index f99f15c..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/flexbox/repaint-opacity-change-expected.html
+++ /dev/null
@@ -1,21 +0,0 @@
-<!DOCTYPE html>
-<html>
-<head>
-<style>
-.item {
-  margin: 10px;
-  padding: 10px;
-  opacity: 1;
-}
-.flex {
-  display: flex;
-  flex-direction: column;
-}
-</style>
-</head>
-<body>
-<div class="flex">
-    <div class="item" id="target"></div>
-    <div class="item"></div>
-</div>
-</body>
diff --git a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/flexbox/repaint-rtl-column-expected.html b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/flexbox/repaint-rtl-column-expected.html
deleted file mode 100644
index 7d24a118..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/flexbox/repaint-rtl-column-expected.html
+++ /dev/null
@@ -1,27 +0,0 @@
-<!DOCTYPE html>
-<style>
-#flexbox {
-    display: flex;
-    flex-flow: column;
-    height: 300px;
-    width: 200px;
-}
-#left {
-    flex: 1;
-    background-color: yellow;
-    min-height: 0;
-}
-#content {
-    flex: 5;
-    border: 5px solid blue;
-    min-height: 0;
-}
-#content > div {
-    height: 350px;
-    background-color: orange;
-}
-</style>
-<div style="height: 60px"></div>
-<div id="flexbox" dir="rtl">
-<div id="left"></div>
-<div id="content"><div></div></div>
diff --git a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/float-in-new-block-with-layout-delta-expected.html b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/float-in-new-block-with-layout-delta-expected.html
deleted file mode 100644
index 3bae818..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/float-in-new-block-with-layout-delta-expected.html
+++ /dev/null
@@ -1,6 +0,0 @@
-<body>
-    <div style="height: 100px;"></div>
-    <div id="target">
-        <div style="float: left; width: 100px; height: 100px; background-color: green;"></div>
-    </div>
-</body>
diff --git a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/float-move-during-layout-expected.html b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/float-move-during-layout-expected.html
deleted file mode 100644
index 878339d..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/float-move-during-layout-expected.html
+++ /dev/null
@@ -1,19 +0,0 @@
-<HTML>
-    <HEAD>
-        <TITLE></TITLE>
-    </HEAD>
-    <BODY>
-       <p>
-           This is a repaint test for <i><a href="https://bugs.webkit.org/show_bug.cgi?id=7204">http://bugzilla.opendarwin.org/show_bug.cgi?id=7204</a>
-           float inserted in fixed height block via DOM not repainted</i>.
-       </p>
-       <p>
-           There should be a green square below.
-       </p>
-       <hr>
-        <div id="t" style="height: 100px"></div>
-        <div id="s">
-            <div style="float:left; background: green; width: 100px; height: 100px;"></div>
-        </div>
-    </BODY>
-</HTML>
diff --git a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/float-new-in-block-expected.html b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/float-new-in-block-expected.html
deleted file mode 100644
index 228ffe8..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/float-new-in-block-expected.html
+++ /dev/null
@@ -1,5 +0,0 @@
-<body>
-    <div style="height: 20px; background-color: lightblue;">
-        <div id="target" style="float: left; width: 100px; height: 100px; background-color: green;"></div>
-    </div>
-</body>
diff --git a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/float-overflow-expected.html b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/float-overflow-expected.html
deleted file mode 100644
index d9a9e7ff..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/float-overflow-expected.html
+++ /dev/null
@@ -1,176 +0,0 @@
-<!DOCTYPE HTML>
-<html>
-<head>
-    <title>Repaint test for http://bugs.webkit.org/show_bug.cgi?id=12123</title>
-    <script src="../../resources/ahem.js"></script>
-    <style>
-        .spacer { width: 0; height: 6px; }
-        .test { border: thin dotted lightgray; margin: 2px; height: 35px; }
-        .outer { border: thin solid purple; padding: 5px; width: 50px; margin-left: 50px; }
-        .outer > div { height: 10px; background-color: pink; }
-        .outer > div > div { width: 40px; height: 10px; background-color: lightblue; }
-        span { font-family: Ahem; color: blue; }
-        .box { display: -webkit-box; }
-    </style>
-</head>
-<body>
-    <div class="test">
-        <div class="spacer" id="spacer1"></div>
-        <div class="outer">
-            <div>
-                <div style="float: left; margin-left: -2px;">
-                    <span style="margin-left: -2px;">x</span>
-                </div>
-            </div>
-        </div>
-    </div>
-
-    <div class="test">
-        <div class="spacer" id="spacer2"></div>
-        <div class="outer">
-            <div>
-                <div style="float: left; margin-left: -2px;">
-                    <span style="margin-left: -8px;">x</span>
-                </div>
-            </div>
-        </div>
-    </div>
-    
-    <div class="test">
-        <div class="spacer" id="spacer3"></div>
-        <div class="outer">
-            <div>
-                <div style="float: left; margin-left: -8px;">
-                    <span style="margin-left: -2px;">x</span>
-                </div>
-            </div>
-        </div>
-    </div>
-    
-    <div class="test">
-        <div class="spacer" id="spacer4"></div>
-        <div class="outer">
-            <div>
-                <div style="float: left;">
-                    <span style="margin-left: -8px;">x</span>
-                </div>
-            </div>
-        </div>
-    </div>
-    
-    <div class="test">
-        <div class="spacer" id="spacer5"></div>
-        <div class="outer">
-            <div>
-                <div style="float: left; margin-left: -8px;">
-                    <span>x</span>
-                </div>
-            </div>
-        </div>
-    </div>
-    
-    <div class="test">
-        <div class="spacer" id="spacer6"></div>
-        <div class="outer box" style="-webkit-box-orient: vertical;">
-            <div>
-                <div style="float: left; margin-left: -8px;">
-                    <span>x</span>
-                </div>
-            </div>
-        </div>
-    </div>
-    
-    <div class="test">
-        <div class="spacer" id="spacer12"></div>
-        <div class="outer box" style="-webkit-box-orient: horizontal;">
-            <div>
-                <div style="float: left; margin-left: -8px;">
-                    <span>x</span>
-                </div>
-            </div>
-        </div>
-    </div>
-    
-    <div class="test">
-        <div class="spacer" id="spacer7"></div>
-        <table class="outer">
-            <tr>
-                <td style="height: 10px; background-color: pink; width: 100%;">
-                    <div style="width: 40px; height: 10px; background-color: lightblue; float: left;">
-                        <span style="margin-left: -4px;">x</span>
-                    </div>
-                </td>
-            </tr>
-        </table>
-    </div>
-    
-    <div class="test">
-        <div class="spacer" id="spacer8"></div>
-        <table class="outer">
-            <tr>
-                <td style="height: 10px; background-color: pink; width: 100%;">
-                    <div style="width: 40px; height: 10px; background-color: lightblue; float: left;">
-                        <span style="margin-left: -12px;">x</span>
-                    </div>
-                </td>
-            </tr>
-        </table>
-    </div>
-    
-    <div class="test" style="height: 50px;">
-        <div class="spacer" id="spacer14"></div>
-        <table class="outer" style="display: inline-table;">
-            <tr>
-                <td style="height: 10px; background-color: pink; width: 100%;">
-                    <div style="width: 40px; height: 10px; background-color: lightblue; float: left;">
-                        <span style="margin-left: -12px;">x</span>
-                    </div>
-                </td>
-            </tr>
-        </table>
-    </div>
-    
-    <div class="test">
-        <div class="spacer" id="spacer9"></div>
-        <div class="outer">
-            <div>
-                <div style="opacity: 0.75; float: left; margin-left: -8px;">
-                    <span>x</span>
-                </div>
-            </div>
-        </div>
-    </div>
-    
-    <div class="test">
-        <div class="spacer" id="spacer10"></div>
-        <div class="outer">
-            <div style="opacity: 0.75;">
-                <div style="float: left; margin-left: -8px;">
-                    <span>x</span>
-                </div>
-            </div>
-        </div>
-    </div>
-    
-    <div class="test">
-        <div class="spacer" id="spacer11"></div>
-        <div class="outer" style="opacity: 0.75">
-            <div>
-                <div style="float: left; margin-left: -8px;">
-                    <span>x</span>
-                </div>
-            </div>
-        </div>
-    </div>
-    <div class="test" style="height: 48px">
-        <div class="spacer" id="spacer13"></div>
-        <div class="outer">
-            <div style="display: inline-block; height: 20px;">
-                <div style="float: left; margin-left: -8px;">
-                    <span>x</span>
-                </div>
-            </div>
-        </div>
-    </div>
-</body>
-</html>
diff --git a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/float-overflow-right-expected.html b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/float-overflow-right-expected.html
deleted file mode 100644
index 95f9c3e6..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/float-overflow-right-expected.html
+++ /dev/null
@@ -1,176 +0,0 @@
-<!DOCTYPE HTML>
-<html>
-<head>
-    <title>Repaint test for http://bugs.webkit.org/show_bug.cgi?id=12123</title>
-    <script src="../../resources/ahem.js"></script>
-    <style>
-        .spacer { width: 0; height: 6px; }
-        .test { direction: rtl; border: thin dotted lightgray; margin: 2px; height: 35px; }
-        .outer { border: thin solid purple; padding: 5px; width: 50px; margin-right: 50px; }
-        .outer > div { height: 10px; background-color: pink; }
-        .outer > div > div { width: 40px; height: 10px; background-color: lightblue; }
-        span { font-family: Ahem; color: blue; }
-        .box { display: -webkit-box; }
-    </style>
-</head>
-<body>
-    <div class="test">
-        <div class="spacer" id="spacer1"></div>
-        <div class="outer">
-            <div>
-                <div style="float: right; margin-right: -2px;">
-                    <span style="margin-right: -2px;">x</span>
-                </div>
-            </div>
-        </div>
-    </div>
-
-    <div class="test">
-        <div class="spacer" id="spacer2"></div>
-        <div class="outer">
-            <div>
-                <div style="float: right; margin-right: -2px;">
-                    <span style="margin-right: -8px;">x</span>
-                </div>
-            </div>
-        </div>
-    </div>
-    
-    <div class="test">
-        <div class="spacer" id="spacer3"></div>
-        <div class="outer">
-            <div>
-                <div style="float: right; margin-right: -8px;">
-                    <span style="margin-right: -2px;">x</span>
-                </div>
-            </div>
-        </div>
-    </div>
-    
-    <div class="test">
-        <div class="spacer" id="spacer4"></div>
-        <div class="outer">
-            <div>
-                <div style="float: right;">
-                    <span style="margin-right: -8px;">x</span>
-                </div>
-            </div>
-        </div>
-    </div>
-    
-    <div class="test">
-        <div class="spacer" id="spacer5"></div>
-        <div class="outer">
-            <div>
-                <div style="float: right; margin-right: -8px;">
-                    <span>x</span>
-                </div>
-            </div>
-        </div>
-    </div>
-    
-    <div class="test">
-        <div class="spacer" id="spacer6"></div>
-        <div class="outer box" style="-webkit-box-orient: vertical;">
-            <div>
-                <div style="float: right; margin-right: -8px;">
-                    <span>x</span>
-                </div>
-            </div>
-        </div>
-    </div>
-    
-    <div class="test">
-        <div class="spacer" id="spacer12"></div>
-        <div class="outer box" style="-webkit-box-orient: horizontal;">
-            <div>
-                <div style="float: right; margin-right: -8px;">
-                    <span>x</span>
-                </div>
-            </div>
-        </div>
-    </div>
-    
-    <div class="test">
-        <div class="spacer" id="spacer7"></div>
-        <table class="outer">
-            <tr>
-                <td style="height: 10px; background-color: pink; width: 100%;">
-                    <div style="width: 40px; height: 10px; background-color: lightblue; float: right;">
-                        <span style="margin-right: -4px;">x</span>
-                    </div>
-                </td>
-            </tr>
-        </table>
-    </div>
-    
-    <div class="test">
-        <div class="spacer" id="spacer8"></div>
-        <table class="outer">
-            <tr>
-                <td style="height: 10px; background-color: pink; width: 100%;">
-                    <div style="width: 40px; height: 10px; background-color: lightblue; float: right;">
-                        <span style="margin-right: -12px;">x</span>
-                    </div>
-                </td>
-            </tr>
-        </table>
-    </div>
-    
-    <div class="test" style="height: 50px;">
-        <div class="spacer" id="spacer14"></div>
-        <table class="outer" style="display: inline-table;">
-            <tr>
-                <td style="height: 10px; background-color: pink; width: 100%;">
-                    <div style="width: 40px; height: 10px; background-color: lightblue; float: right;">
-                        <span style="margin-right: -12px;">x</span>
-                    </div>
-                </td>
-            </tr>
-        </table>
-    </div>
-    
-    <div class="test">
-        <div class="spacer" id="spacer9"></div>
-        <div class="outer">
-            <div>
-                <div style="opacity: 0.75; float: right; margin-right: -8px;">
-                    <span>x</span>
-                </div>
-            </div>
-        </div>
-    </div>
-    
-    <div class="test">
-        <div class="spacer" id="spacer10"></div>
-        <div class="outer">
-            <div style="opacity: 0.75;">
-                <div style="float: right; margin-right: -8px;">
-                    <span>x</span>
-                </div>
-            </div>
-        </div>
-    </div>
-    
-    <div class="test">
-        <div class="spacer" id="spacer11"></div>
-        <div class="outer" style="opacity: 0.75">
-            <div>
-                <div style="float: right; margin-right: -8px;">
-                    <span>x</span>
-                </div>
-            </div>
-        </div>
-    </div>
-    <div class="test" style="height: 48px">
-        <div class="spacer" id="spacer13"></div>
-        <div class="outer">
-            <div style="display: inline-block; height: 20px;">
-                <div style="float: right; margin-right: -8px;">
-                    <span>x</span>
-                </div>
-            </div>
-        </div>
-    </div>
-</body>
-</html>
diff --git a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/focus-continuations-expected.html b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/focus-continuations-expected.html
deleted file mode 100644
index c13858c..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/focus-continuations-expected.html
+++ /dev/null
@@ -1,18 +0,0 @@
-<!DOCTYPE html>
-<style>
-body { height: 200px; }
-#container { position: absolute; }
-p, #inner { height: 20px; }
-</style>
-<p>
-  This test is verifying that when the focus is removed from an element we
-  correctly invalidate continuations and remove the focus ring.
-</p>
-<p>
-  If this test passes, you should see no focus ring.
-</p>
-<div id="container">
-  <span id="outer" tabindex="1">
-      <div id="inner">CONTENTS</div>
-  </span>
-</div>
diff --git a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/focus-ring-on-child-move-expected.html b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/focus-ring-on-child-move-expected.html
deleted file mode 100644
index 982bc48..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/focus-ring-on-child-move-expected.html
+++ /dev/null
@@ -1,5 +0,0 @@
-<!DOCTYPE html>
-Tests paint invalidation of focus ring when child moves. Passes if the focus ring is updated to contain the yellow areas.
-<div style="outline: auto; position: absolute; top: 100px; left: 100px; width: 300px; height: 20px; background-color: yellow">
-  <div id="child" style="position: absolute; top: -50px; left: 200px; width: 20px; height: 300px; background-color: yellow"></div>
-</div>
diff --git a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/focus-ring-on-continuation-move-expected.html b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/focus-ring-on-continuation-move-expected.html
deleted file mode 100644
index cf4221e..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/focus-ring-on-continuation-move-expected.html
+++ /dev/null
@@ -1,8 +0,0 @@
-<!DOCTYPE html>
-<p style="height: 200px">
-Tests paint invalidation of focus ring of an inline when a block content of the inline moves.
-Passes if the focus ring encloses the moved green rectangle.
-</p>
-<div style="outline: auto; position: relative; left: 200px; width: 100px; height: 100px">
-  <div style="position: relative; width: 100px; height: 100px; background-color: green"></div>
-</div>
diff --git a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/focus-ring-on-inline-continuation-move-expected.html b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/focus-ring-on-inline-continuation-move-expected.html
deleted file mode 100644
index 9a30ab0..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/focus-ring-on-inline-continuation-move-expected.html
+++ /dev/null
@@ -1,4 +0,0 @@
-<!DOCTYPE html>
-<div style="outline: auto; position: relative; top: 80px; width: 100px; height: 100px">
-  <div style="position: relative; width: 100px; height: 100px; background-color: green"></div>
-</div>
diff --git a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/gradients-em-stops-repaint-expected.html b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/gradients-em-stops-repaint-expected.html
deleted file mode 100644
index 2f40c14..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/gradients-em-stops-repaint-expected.html
+++ /dev/null
@@ -1,35 +0,0 @@
-<!DOCTYPE html>
-
-<html>
-<head>
-  <style type="text/css" media="screen">
-    .box {
-      display: inline-block;
-      height: 120px;
-      width: 300px;
-      margin: 10px;
-      border: 1px solid black;
-      background-repeat: no-repeat;
-      font-size: 12pt;
-    }
-    
-    .em-units > .box {
-      background-image: -webkit-linear-gradient(left, yellow, yellow 5em, green 5em);
-      background-image: -moz-linear-gradient(left, yellow, yellow 5em, green 5em);
-    }
-    
-    .indicator {
-      background-color: black;
-      height: 20px;
-    }
-  </style>
-</head>
-<body>
-
-  <div class="em-units">
-    <div id="box3" class="box"><div class="indicator" style="width: 5em;"></div></div>
-    <div id="box4" class="box" style="font-size: 36pt"><div class="indicator" style="width: 5em"></div></div>
-  </div>
-
-</body>
-</html>
diff --git a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/hover-pseudo-borders-expected.html b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/hover-pseudo-borders-expected.html
deleted file mode 100644
index 36e7952..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/hover-pseudo-borders-expected.html
+++ /dev/null
@@ -1,31 +0,0 @@
-<!DOCTYPE html>
-<html>
-<head>
-<style>
-.hitregion {
-  width: 100px;
-  height: 100px;
-  background-color: green;
-}
-.hitregion:after {
-  content: "";
-  border: 40px solid;
-  outline: 10px solid;
-  position: absolute;
-  width: 0;
-  height: 0;
-  margin-left: 140px;
-  margin-top: 10px;
-  color: green;
-}
-</style>
-</head>
-<body>
-<!--
-    REGRESSION: :hover doesn't work on :after content with borders or outlines.
-    To test this bug outside DRT, hover on the square below.
-    This test passes if there are two green squares.
--->
-<div class="hitregion"></div>
-</body>
-</html>
diff --git a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/hover-pseudo-borders-whitespace-expected.html b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/hover-pseudo-borders-whitespace-expected.html
deleted file mode 100644
index 6fc8de84..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/hover-pseudo-borders-whitespace-expected.html
+++ /dev/null
@@ -1,22 +0,0 @@
-<!doctype html>
-<style>
-
-div {
-    width: 100px;
-    height: 100px;
-    color: green;
-}
-
-#div_border {
-    border: 10px solid;
-}
-
-#div_outline {
-    outline: 10px solid;
-    margin: 20px 0 0 10px;
-    color: green;
-}
-
-</style>
-<div id="div_border"></div>
-<div id="div_outline"></div>
diff --git a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/iframe-rounding-expected.html b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/iframe-rounding-expected.html
deleted file mode 100644
index fa51b6f..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/iframe-rounding-expected.html
+++ /dev/null
@@ -1,8 +0,0 @@
-<!DOCTYPE html>
-<!-- The div within the iframe is at 0.5px from the iframe bounds, and the div containing the iframe is at 0.5px from the top-left of the screen.
-This test checks that the latter 0.5px is rounded to 1 before being added to the 0.5px and then rounded up again to an invalidation rect. This is
-because iframes are painted in rounded-int coordinates.
--->
-<div style="position: relative; left: 0.5px; margin: 0">
-  <iframe id='iframe' srcdoc="<div style='position: relative; background: lightgray; width: 100px; height: 100px; left: 0.5px'></div>"></iframe>
-</div>
diff --git a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/image-resize-expected.html b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/image-resize-expected.html
deleted file mode 100644
index 31302e5..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/image-resize-expected.html
+++ /dev/null
@@ -1,12 +0,0 @@
-<!DOCTYPE html>
-<style>
-img {
-  position: absolute;
-  top: 50px;
-  left: 0px;
-  width: 100px;
-  height: 200px;
-}
-</style>
-The image should be fully repainted on resize. Passes if there is a whole apple after resize.
-<img src="resources/apple.jpg">
diff --git a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/in-scaled-iframe-expected.html b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/in-scaled-iframe-expected.html
deleted file mode 100644
index 44fa63c..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/in-scaled-iframe-expected.html
+++ /dev/null
@@ -1,9 +0,0 @@
-<!DOCTYPE html>
-<div style="transform: scale(0.5); transform-origin: 0 0">
-  <iframe id="iframe" style="width: 800px; height: 800px"
-    srcdoc="<div id='div' style='position: absolute; top: 400px; left: 400px; width: 200px; height: 200px; background-color: green'></div>">
-  </iframe>
-</div>
-<p style="position: absolute; top: 400px">
-Tests paint invalidation in a scaled iframe. Passes if there is no red.
-</p>
diff --git a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/inline-block-resize-expected.html b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/inline-block-resize-expected.html
deleted file mode 100644
index ff2180a3..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/inline-block-resize-expected.html
+++ /dev/null
@@ -1,14 +0,0 @@
-<html>
-<head>
-    <title>Test for http://bugs.webkit.org/show_bug.cgi?id=12885</title>
-    <style type="text/css">
-      
-    </style>
-</head>
-<body>
-    <div style="position:absolute; height:100px; width:100px;background-color:red"></div>
-    <div style="padding-top:100px"></div>
-    <div style="position:absolute"><div id="target" style="display:inline-block; background-color:green; width: 100px; height: 100px; margin-top: -100px"></div></div>
-    </div>
-</body>
-</html>
diff --git a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/inline-color-change-expected.html b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/inline-color-change-expected.html
deleted file mode 100644
index bb4ada7..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/inline-color-change-expected.html
+++ /dev/null
@@ -1,11 +0,0 @@
-<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
-        "http://www.w3.org/TR/html4/strict.dtd">
-<html lang="en">
-<body>
-    <p>
-        Repaint test for <i><a href="rdar://problem/6518850">rdar://problem/6518850</a></i>
-        Make sure that an inline repaints using its line boxes and not using LayoutBox width()/height().
-    </p>
-    <p><span id="target" style="color:green">PASS</span></p>
-</body>
-</html>
diff --git a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/inline-outline-repaint-2-expected.html b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/inline-outline-repaint-2-expected.html
deleted file mode 100644
index c40bc1c..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/inline-outline-repaint-2-expected.html
+++ /dev/null
@@ -1,21 +0,0 @@
-<!DOCTYPE html>
-<script src="../../resources/ahem.js"></script>
-<style>
-body {
-  margin: 0;
-  padding: 0;
-}
-#container {
-  position: absolute;
-  width: 255px;
-  text-align: right;
-  font: 10px Ahem;
-  color: green;
-}
-#container > span {
-  outline: 5px solid blue;
-}
-</style>
-<div id=container>
-  <span>Test</span>
-</div>
diff --git a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/inline-overflow-expected.html b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/inline-overflow-expected.html
deleted file mode 100644
index 402ab97f..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/inline-overflow-expected.html
+++ /dev/null
@@ -1,4 +0,0 @@
-<script src="../../resources/ahem.js"></script>
-<body style="padding: 50px;">
-    <span id="target" style="font-family: Ahem; font-size: 50px; -webkit-text-stroke: 50px green;">A&nbsp;&nbsp;B</span>
-</body>
diff --git a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/inline-reflow-expected.html b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/inline-reflow-expected.html
deleted file mode 100644
index 835b4d2..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/inline-reflow-expected.html
+++ /dev/null
@@ -1,18 +0,0 @@
-<!DOCTYPE HTML>
-<script src="../../resources/ahem.js"></script>
-<style>
-body {
-    margin: 0;
-}
-.container {
-    font: 20px Ahem;
-    width: 200px;
-    position: absolute;
-}
-</style>
-<div class="container" id="div1" style="width: 300px">
-A A A A A AA AA AA AA AAA AAA AAA AAAA AAAA AAAAA AAAAA AAAAAA AAAAAAA AAAAAA AAAAA AAAAA AAAA AAAA AAA AAA AAA AA AA AA AA A A A A A
-</div>
-<div class="container" id="div2" style="top: 300px; width: 300px">
-A A A A A
-</div>
diff --git a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/inline-relative-positioned-expected.html b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/inline-relative-positioned-expected.html
deleted file mode 100644
index cd5ecb2b..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/inline-relative-positioned-expected.html
+++ /dev/null
@@ -1,5 +0,0 @@
-<script src="../../resources/ahem.js"></script>
-<body>
-<span style="position: relative; top: 80px;">
-    <div id="target" style="display: inline-block; width: 100px; height: 100px; overflow: hidden; font-family: Ahem; font-size: 100px; background: red; color: green;">a</div>
-</span>
diff --git a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/inline-vertical-lr-overflow-expected.html b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/inline-vertical-lr-overflow-expected.html
deleted file mode 100644
index 2d0fa09..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/inline-vertical-lr-overflow-expected.html
+++ /dev/null
@@ -1,4 +0,0 @@
-<html style="-webkit-writing-mode:vertical-lr">
-<body style="padding: 50px">
-    <div><span id="target" style="font-family: Ahem; font-size: 50px; -webkit-text-stroke: 50px green;">A&nbsp;&nbsp;B</span></div>
-</body>
diff --git a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/inline-vertical-rl-overflow-expected.html b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/inline-vertical-rl-overflow-expected.html
deleted file mode 100644
index 8a3e2eb..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/inline-vertical-rl-overflow-expected.html
+++ /dev/null
@@ -1,4 +0,0 @@
-<html style="-webkit-writing-mode:vertical-rl">
-<body style="padding: 50px">
-    <div><span id="target" style="font-family: Ahem; font-size: 50px; -webkit-text-stroke: 50px green;">A&nbsp;&nbsp;B</span></div>
-</body>
diff --git a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/input-overflow-in-table-expected.html b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/input-overflow-in-table-expected.html
deleted file mode 100644
index 191897c..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/input-overflow-in-table-expected.html
+++ /dev/null
@@ -1,9 +0,0 @@
-<!DOCTYPE html>
-<div style="display: table; position: relative;">
-    <div style="position: absolute;">
-            <div id="test" style="height: 20px; width: 100px; outline: 1px solid black;"></div>
-    </div>
-</div>
-<p>crbug.com/619510: Calculate overflow on the positioned descendants of tables.</p>
-
-
diff --git a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/intermediate-layout-position-expected.html b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/intermediate-layout-position-expected.html
deleted file mode 100644
index 1145c66..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/intermediate-layout-position-expected.html
+++ /dev/null
@@ -1,28 +0,0 @@
-<html>
-<head>
-    <title>Test for http://bugs.webkit.org/show_bug.cgi?id=10522</title>
-    <style type="text/css">
-        .float { float: right; height: 40px; width: 40px; }
-        .test { height: 100px; background-color: aliceblue }
-    </style>
-</head>
-<body>
-    <div class="test">
-        <div class="float"></div>
-        <div style="clear: right; background-color: purple; width: 40px; padding: 3px;">
-            <div style="height: 20px; width: 0;" id="target">
-            </div>
-        </div>
-    </div>
-    
-    <div class="test">
-        <div class="float"></div>
-        <table style="clear: both; background-color: purple;">
-            <tr>
-                <td id="cell" style="height: 20px; width: 40px;">
-                </td>
-            </tr>
-        </table>
-    </div>
-</body>
-</html>
diff --git a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/invalidate-box-shadow-currentColor-expected.html b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/invalidate-box-shadow-currentColor-expected.html
deleted file mode 100644
index a128466..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/invalidate-box-shadow-currentColor-expected.html
+++ /dev/null
@@ -1,9 +0,0 @@
-<!doctype HTML>
-<style>
-span {
-  color: green;
-  display: inline;
-  box-shadow: 0 5px 0 0 currentColor;
-}
-</style>
-<span id="target">Text</span>
diff --git a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/invalidate-descendants-when-receiving-paint-layer-expected.html b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/invalidate-descendants-when-receiving-paint-layer-expected.html
deleted file mode 100644
index 4f04c5f5..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/invalidate-descendants-when-receiving-paint-layer-expected.html
+++ /dev/null
@@ -1,6 +0,0 @@
-<!DOCTYPE html>
-<div style="position: relative; border: 1px solid black;">  
-  <div id="target" style="opacity: 0.2; height: 50px; width: 50px;">
-    <div id="child" style="width: 100px; height: 100px"></div>
-  </div>
-</div>
diff --git a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/invalidate-invisible-element-expected.html b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/invalidate-invisible-element-expected.html
deleted file mode 100644
index d41a36e..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/invalidate-invisible-element-expected.html
+++ /dev/null
@@ -1,10 +0,0 @@
-<!DOCTYPE html>
-<html>
-<body>
-    <div id="target"
-      style="position: absolute;
-             top: 300px; left: 200px;
-             width: 200px; height: 200px;
-             background-color: redl "></div>
-</body>
-</html>
diff --git a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/invalidate-paint-in-iframe-in-composited-layer-expected.html b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/invalidate-paint-in-iframe-in-composited-layer-expected.html
deleted file mode 100644
index 459062a..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/invalidate-paint-in-iframe-in-composited-layer-expected.html
+++ /dev/null
@@ -1,5 +0,0 @@
-<!DOCTYPE html>
-<div style="height: 400px"></div>
-<div style="height: 200px; width: 200px; transform: translateZ(0)">
-    <iframe srcdoc="<div style='height: 50px; width: 50px; background-color: green;'></div>"></iframe>
-</div>
diff --git a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/invalidation-with-zero-size-object-expected.html b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/invalidation-with-zero-size-object-expected.html
deleted file mode 100644
index c50eddd4..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/invalidation-with-zero-size-object-expected.html
+++ /dev/null
@@ -1 +0,0 @@
-<!doctype html>
diff --git a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/invisible-objects-expected.html b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/invisible-objects-expected.html
deleted file mode 100644
index c50d080..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/invisible-objects-expected.html
+++ /dev/null
@@ -1,10 +0,0 @@
-<html>
-<body>
-    <div style="visibility: hidden; position: relative;">
-        <span id="inline">is invisible</span>
-    </div>
-    <div style="visibility: hidden; position: relative;">
-        <div id="block" style="height: 100px;"></div>
-    </div>
-</body>
-</html>
diff --git a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/justify-content-change-expected.html b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/justify-content-change-expected.html
deleted file mode 100644
index 37cb227..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/justify-content-change-expected.html
+++ /dev/null
@@ -1,27 +0,0 @@
-<!DOCTYPE HTML>
-<style>
-body {
-  margin: 0;
-}
-#container {
-  display: flex;
-  justify-content: space-between;
-  width: 200px;
-  height: 300px;
-  background-color: orange;
-}
-.item {
-  background-color: green;
-  border: solid thin blue;
-  width: 50px;
-}
-</style>
-<p style="height: 20px">Tests invalidation on justify-content style change. Passes if only one big orange bar appear in the middle of the box.</p>
-<div id="container">
-  <div class="item">
-    <div style="height: 50px"></div>
-  </div>
-  <div class="item">
-    <div style="height: 50px"></div>
-  </div>
-</div>
diff --git a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/justify-content-distribution-change-grid-expected.html b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/justify-content-distribution-change-grid-expected.html
deleted file mode 100644
index 67f3de1..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/justify-content-distribution-change-grid-expected.html
+++ /dev/null
@@ -1,31 +0,0 @@
-<!DOCTYPE HTML>
-<style>
-body {
-  margin: 0;
-}
-#container {
-  display: grid;
-  grid-auto-columns: auto;
-  grid-auto-rows: 200px;
-  grid-auto-flow: column;
-  justify-content: stretch;
-  width: 300px;
-  height: 200px;
-  background-color: red;
-}
-.item {
-  background-color: green;
-}
-</style>
-<p style="height: 20px">Tests invalidation on justify-content style change (distribution). Passes if there is no red.</p>
-<div id="container">
-  <div class="item">
-    <div style="width: 50px"></div>
-  </div>
-  <div class="item">
-    <div style="width: 50px"></div>
-  </div>
-  <div class="item">
-    <div style="width: 50px"></div>
-  </div>
-</div>
diff --git a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/justify-content-position-change-expected.html b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/justify-content-position-change-expected.html
deleted file mode 100644
index 9cec3b1..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/justify-content-position-change-expected.html
+++ /dev/null
@@ -1,27 +0,0 @@
-<!DOCTYPE HTML>
-<style>
-body {
-  margin: 0;
-}
-#container {
-  display: flex;
-  justify-content: flex-start;
-  width: 200px;
-  height: 300px;
-  background-color: orange;
-}
-.item {
-  background-color: green;
-  border: solid thin blue;
-  width: 50px;
-}
-</style>
-<p style="height: 20px">Tests invalidation on justify-content style change. Passes if only one big orange bar appear aligned to the box's right edge.</p>
-<div id="container">
-  <div class="item">
-    <div style="height: 50px"></div>
-  </div>
-  <div class="item">
-    <div style="height: 50px"></div>
-  </div>
-</div>
diff --git a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/justify-content-position-change-grid-expected.html b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/justify-content-position-change-grid-expected.html
deleted file mode 100644
index 23f2c4c..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/justify-content-position-change-grid-expected.html
+++ /dev/null
@@ -1,31 +0,0 @@
-<!DOCTYPE HTML>
-<style>
-body {
-  margin: 0;
-}
-#container {
-  display: grid;
-  grid-auto-columns: auto;
-  grid-auto-rows: 200px;
-  grid-auto-flow: column;
-  justify-content: end;
-  width: 300px;
-  height: 200px;
-  background-color: red;
-}
-.item {
-  background-color: green;
-}
-</style>
-<p style="height: 20px">Tests invalidation on justify-content style change (position). Passes if the red half is on the left.</p>
-<div id="container">
-  <div class="item">
-    <div style="width: 50px"></div>
-  </div>
-  <div class="item">
-    <div style="width: 50px"></div>
-  </div>
-  <div class="item">
-    <div style="width: 50px"></div>
-  </div>
-</div>
diff --git a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/justify-items-change-expected.html b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/justify-items-change-expected.html
deleted file mode 100644
index 24cb3f1..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/justify-items-change-expected.html
+++ /dev/null
@@ -1,26 +0,0 @@
-<!DOCTYPE HTML>
-<style>
-body {
-  margin: 0;
-}
-#container {
-  display: grid;
-  grid: 300px / 200px;
-  justify-items: start;
-  width: 200px;
-  height: 300px;
-  background-color: red;
-}
-.item {
-  grid-row: 1;
-  grid-column: 1;
-  background-color: green;
-  width: 50px;
-}
-</style>
-<p style="height: 20px">Tests invalidation on justify-items style change. Passes if green bar is left aligned.</p>
-<div id="container">
-  <div class="item">
-    <div style="height: 50px"></div>
-  </div>
-</div>
diff --git a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/justify-items-legacy-change-expected.html b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/justify-items-legacy-change-expected.html
deleted file mode 100644
index 25cb07e2..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/justify-items-legacy-change-expected.html
+++ /dev/null
@@ -1,44 +0,0 @@
-<!DOCTYPE HTML>
-<style>
-body {
-  margin: 0;
-}
-#parentContainer {
-  justify-items: legacy center;
-  background-color: orange;
-  width: 300px;
-  height: 400px;
-}
-
-#container {
-  display: grid;
-  grid: 150px 150px / 100px 100px;
-  width: 200px;
-  height: 300px;
-  background-color: red;
-}
-.item1 {
-  grid-row: 1;
-  grid-column: 1;
-  background-color: green;
-  border: solid thin blue;
-  width: 50px;
-}
-.item2 {
-  grid-row: 1;
-  grid-column: 2;
-  background-color: green;
-  border: solid thin blue;
-  width: 50px;
-</style>
-<p style="height: 20px">Tests invalidation on justify-items style change (legacy value). Passes if green bars are centerd inside their red container.</p>
-<div id="parentContainer">
-    <div id="container">
-        <div class="item1">
-            <div style="height: 50px"></div>
-        </div>
-        <div class="item2">
-            <div style="height: 50px"></div>
-        </div>
-    </div>
-</div>
diff --git a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/justify-items-overflow-change-expected.html b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/justify-items-overflow-change-expected.html
deleted file mode 100644
index bb43348f..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/justify-items-overflow-change-expected.html
+++ /dev/null
@@ -1,34 +0,0 @@
-<!DOCTYPE HTML>
-<style>
-body {
-  margin: 0;
-}
-#container {
-  display: grid;
-  grid: 300px / 100px 100px;
-  justify-items: end safe;
-  width: 200px;
-  height: 300px;
-  background-color: red;
-}
-.item1 {
-  grid-row: 1;
-  grid-column: 1;
-  background-color: green;
-  width: 160px;
-}
-.item2 {
-  grid-row: 1;
-  grid-column: 2;
-  background-color: green;
-  width: 50px;
-</style>
-<p style="height: 20px">Tests invalidation on justify-items style change. Passes if there is no red.</p>
-<div id="container">
-  <div class="item1">
-    <div style="height: 50px"></div>
-  </div>
-  <div class="item2">
-    <div style="height: 50px"></div>
-  </div>
-</div>
diff --git a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/justify-self-change-expected.html b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/justify-self-change-expected.html
deleted file mode 100644
index 08a043a..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/justify-self-change-expected.html
+++ /dev/null
@@ -1,48 +0,0 @@
-<!DOCTYPE HTML>
-<style>
-body {
-  margin: 0;
-}
-#container {
-  display: grid;
-  grid: 150px 150px / 100px 100px;
-  width: 200px;
-  height: 300px;
-  background-color: red;
-}
-.item1 {
-  grid-row: 1;
-  grid-column: 1;
-  background-color: green;
-  justify-self: center;
-  height: 300px;
-  width: 100px;
-}
-.item2 {
-  grid-row: 1;
-  grid-column: 2;
-  background-color: green;
-  justify-self: start;
-  height: 300px;
-  width: 100px;
-}
-.item3 {
-  grid-row: 1;
-  grid-column: 2;
-  background-color: green;
-  justify-self: end;
-  height: 300px;
-}
-</style>
-<p style="height: 20px">Tests invalidation on justify-self style change. Passes if there is no red.</p>
-<div id="container">
-  <div class="item1">
-    <div style="width: 50px;"></div>
-  </div>
-  <div class="item2">
-    <div style="width: 50px;"></div>
-  </div>
-  <div class="item3">
-    <div style="width: 50px;"></div>
-  </div>
-</div>
diff --git a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/justify-self-change-keeping-geometry-expected.html b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/justify-self-change-keeping-geometry-expected.html
deleted file mode 100644
index ab83a01..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/justify-self-change-keeping-geometry-expected.html
+++ /dev/null
@@ -1,45 +0,0 @@
-<!DOCTYPE HTML>
-<style>
-body {
-  margin: 0;
-}
-#container {
-  display: grid;
-  grid: 300px / 100px 100px;
-  width: 200px;
-  height: 300px;
-  background-color: red;
-}
-.item1 {
-  grid-row: 1;
-  grid-column: 1;
-  justify-self: start;
-  background-color: green;
-  height: 300px;
-  width: 100px;
-}
-.item2 {
-  grid-row: 1;
-  grid-column: 2;
-  justify-self: start;
-  background-color: green;
-  height: 300px;
-  width: 50px;
-}
-.item3 {
-  grid-row: 1;
-  grid-column: 2;
-  background-color: green;
-  justify-self: end;
-  height: 300px;
-  width: 50px;
-}
-</style>
-<p style="height: 20px">There should be no invalidations because justify-self style change causes no visual change.</p>
-<div id="container">
-  <div class="item1">
-    <div style="width: 100px;"></div>
-  </div>
-  <div class="item2"></div>
-  <div class="item3"></div>
-</div>
diff --git a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/justify-self-overflow-change-expected.html b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/justify-self-overflow-change-expected.html
deleted file mode 100644
index b42b4aa..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/justify-self-overflow-change-expected.html
+++ /dev/null
@@ -1,34 +0,0 @@
-<!DOCTYPE HTML>
-<style>
-body {
-  margin: 0;
-}
-#container {
-  display: grid;
-  grid: 300px / 100px 100px;
-  width: 200px;
-  height: 300px;
-}
-.item1 {
-  grid-row: 1;
-  grid-column: 1;
-  justify-self: end safe;
-  background-color: green;
-  width: 150px;
-}
-.item2 {
-  grid-row: 1;
-  grid-column: 2;
-  background-color: green;
-  justify-self: end safe;
-  width: 50px;
-</style>
-<p style="height: 20px">Tests invalidation on justify-self style change. Passes if there is no red.</p>
-<div id="container">
-  <div class="item1">
-    <div style="height: 150px"></div>
-  </div>
-  <div class="item2">
-    <div style="height: 100px"></div>
-  </div>
-</div>
diff --git a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/layer-full-repaint-expected.html b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/layer-full-repaint-expected.html
deleted file mode 100644
index 19a8e78..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/layer-full-repaint-expected.html
+++ /dev/null
@@ -1,18 +0,0 @@
-<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
-<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
-<head>
-    <title>Test for http://bugs.webkit.org/show_bug.cgi?id=13655</title>
-    <style type="text/css">
-        div {
-            position: relative;
-            height: 100px;
-            width: 100px;
-            background-color: green;
-            text-shadow: red 5px 5px 0;
-        }
-    </style>
-</head>
-<body>
-        <div id="test"></div>
-</body>
-</html>
diff --git a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/layer-hide-when-needs-layout-expected.html b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/layer-hide-when-needs-layout-expected.html
deleted file mode 100644
index a8629a8e..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/layer-hide-when-needs-layout-expected.html
+++ /dev/null
@@ -1,11 +0,0 @@
-<html>
-<head>
-    <title>Test for http://bugs.webkit.org/show_bug.cgi?id=13544</title>
-</head>
-<body>
-    <div style="position: relative;">
-        <div style="background: green; width: 100px; height: 100px;">
-        </div>
-    </div>
-</body>
-</html>
diff --git a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/layer-visibility-expected.html b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/layer-visibility-expected.html
deleted file mode 100644
index 0d3d1120..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/layer-visibility-expected.html
+++ /dev/null
@@ -1,5 +0,0 @@
-<html>
-<body>
-    <div id="target" style="position: absolute; top: 0; left: 0; width: 100px; height: 100px; background-color: green;"></div>
-</body>
-</html>
diff --git a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/layout-state-only-positioned-expected.html b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/layout-state-only-positioned-expected.html
deleted file mode 100644
index 7d1ecbe3..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/layout-state-only-positioned-expected.html
+++ /dev/null
@@ -1,5 +0,0 @@
-<body>
-    <div style="position: absolute; top: 50px; left: 0; overflow: overlay; width: 100px; height: 100px; border: solid">
-        <div id="q" style="position: absolute; top: 0; height: 200px; width: 10px;"></div>
-    </div>
-</body>
diff --git a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/layout-state-relative-expected.html b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/layout-state-relative-expected.html
deleted file mode 100644
index 8163fe1..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/layout-state-relative-expected.html
+++ /dev/null
@@ -1,11 +0,0 @@
-<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
-        "http://www.w3.org/TR/html4/strict.dtd">
-<html lang="en">
-<body>
-    <p>
-        Repaint test for <i><a href="rdar://problem/6048566">rdar://problem/6048566</a>
-        Repaint original element's position, not its offset position</i>.
-    </p>
-    <div style="position: relative; top: 100px;" id="target">PASS</div>
-</body>
-</html>
diff --git a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/layoutstate-invalid-invalidation-inline-relative-positioned-expected.html b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/layoutstate-invalid-invalidation-inline-relative-positioned-expected.html
deleted file mode 100644
index fa3f503..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/layoutstate-invalid-invalidation-inline-relative-positioned-expected.html
+++ /dev/null
@@ -1,9 +0,0 @@
-<!DOCTYPE html>
-<script src="../../resources/ahem.js"></script>
-<body>
-<div style="font-family: Ahem;">This test passes if we correctly repaint the following relatively positioned inline.</div>
-<span style="position: relative; top: 80px;">
-    <span id="target" style="position: relative; top: 100px;">
-        <div style="display: inline-block; width: 100px; height: 100px; overflow: hidden; font-family: Ahem; font-size: 100px; color: green;">x</div>
-    </span>
-</span>
diff --git a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/line-overflow-expected.html b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/line-overflow-expected.html
deleted file mode 100644
index df3560b..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/line-overflow-expected.html
+++ /dev/null
@@ -1,19 +0,0 @@
-<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
-        "http://www.w3.org/TR/html4/strict.dtd">
-<html lang="en">
-<head>
-    <style type="text/css">
-       span#t { margin: 0; border-top: 30px solid blue; }
-    </style>
-</head>
-<body>
-    <p>
-        This is a test for <i><a href="https://bugs.webkit.org/show_bug.cgi?id=9669">http://bugzilla.opendarwin.org/show_bug.cgi?id=9669</a>
-        Incomplete repaint when changing an inline's border</i>.
-    </p>
-    <hr>
-    <div style="width: 200px; height: 200px;">
-        Cras faucibus. Nunc adipiscing, enim in scelerisque convallis,
-        augue <span id="t">purus</span> eleifend lacus, at sagittis eros leo pulvinar velit. Integer sollicitudin nisi ut urna blandit convallis.
-    </div>
-</body>
diff --git a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/lines-with-layout-delta-expected.html b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/lines-with-layout-delta-expected.html
deleted file mode 100644
index 511dd8d..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/lines-with-layout-delta-expected.html
+++ /dev/null
@@ -1,8 +0,0 @@
-<body>
-    <div style="float: left; height: 50px; width: 50px;"></div>
-    <div style="clear: left;">
-        <div id="target" style="overflow: hidden; float: left; width: 200px;">
-            PASS
-        </div>
-    </div>
-</body>
diff --git a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/list-marker-2-expected.html b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/list-marker-2-expected.html
deleted file mode 100644
index 31636a2..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/list-marker-2-expected.html
+++ /dev/null
@@ -1,13 +0,0 @@
-<html>
-<body>
-    <p>
-        This is a test for <i><a href="http://bugs.webkit.org/show_bug.cgi?id=13209">http://bugs.webkit.org/show_bug.cgi?id=13209</a>
-        REGRESSION (r18756-18765): Incomplete list marker repaint when resizing list item</i>.
-    </p>
-    <p>
-        There should be only one bullet, at the bottom left of the rectangle.
-    </p>
-    <ul>
-        <li><img id="target" style="width: 100px; height: 100px;"></li>
-    </ul>
-</body>
diff --git a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/make-children-non-inline-expected.html b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/make-children-non-inline-expected.html
deleted file mode 100644
index b2cb338..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/make-children-non-inline-expected.html
+++ /dev/null
@@ -1,22 +0,0 @@
-<html>
-<head>
-    <title></title>
-</head>
-<body>
-    <p>
-        Repaint test for <i><a href="http://bugs.webkit.org/show_bug.cgi?id=15838">http://bugs.webkit.org/show_bug.cgi?id=15838</a> Incomplete repaint toggling "How you know this person" on Facebook</i>.
-    </p>
-    <div>
-        Word,<br>
-        words,<br>
-        more words.<br>
-        I could<br>
-        write a book<br>
-        <div id="target" style="background-color: yellow; height: 100px; width: 10px;"></div>
-        about all the stuff<br>
-        that comes<br>
-        after<br>
-        the break.
-    </div>
-</body>
-</html>
diff --git a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/margin-expected.html b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/margin-expected.html
deleted file mode 100644
index baf43bfc..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/margin-expected.html
+++ /dev/null
@@ -1,14 +0,0 @@
-<!DOCTYPE HTML>
-<style>
-body {
-    margin: 0;
-}
-div {
-    width: 100px;
-    height: 100px;
-    position: absolute;
-    background-color: green;
-    margin: 20px;
-}
-</style>
-<div id="target"></div>
diff --git a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/mix-blend-mode-separate-stacking-context-expected.html b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/mix-blend-mode-separate-stacking-context-expected.html
deleted file mode 100644
index b04bea40..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/mix-blend-mode-separate-stacking-context-expected.html
+++ /dev/null
@@ -1,27 +0,0 @@
-<!DOCTYPE HTML>
-<html>
-<head>
-<style>
-    div {
-        margin: 20px;
-        width: 60px;
-        height: 60px;
-        float: left;
-    }
-</style>
-<!-- Repaint test to ensure that setting a blend mode dynamically triggers this operation
-    only with the contents of the nearest ancestor stacking context. -->
-<body>
-    <div style="background: green; position: relative; z-index: -1;">
-        <div id="first" style="mix-blend-mode: multiply; background-color: blue;"></div>
-    </div>
-    <div style="background: green; position: relative; z-index: -1;">
-        <div id="second" style="mix-blend-mode: normal; background-color: blue;"></div>
-    </div>
-    <div style="background: green; position: relative; z-index: -1;">
-        <div id="third" style="mix-blend-mode: multiply; background-color: blue;"></div>
-    </div>
-    <div id="fourth" style="background: green; position: relative; z-index: -1">
-        <div style="mix-blend-mode: hue; background-color: blue;"></div>
-    </div>
-</body>
diff --git a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/multi-layout-one-frame-expected.html b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/multi-layout-one-frame-expected.html
deleted file mode 100644
index 77ea756..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/multi-layout-one-frame-expected.html
+++ /dev/null
@@ -1,5 +0,0 @@
-<!DOCTYPE html>
-<body>
-    <input id="input1" value="PASSED"></input>
-    <input id="input2" value="PASSED"></input>
-</body>
diff --git a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/multicol-as-paint-container-expected.html b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/multicol-as-paint-container-expected.html
deleted file mode 100644
index 41e22c8..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/multicol-as-paint-container-expected.html
+++ /dev/null
@@ -1,9 +0,0 @@
-<!DOCTYPE html>
-<script src="../../resources/ahem.js"></script>
-<div id="target" style="-webkit-columns:2; backface-visibility:hidden; width:630px; font:20px/1 Ahem; color:green;">
-    Lorem ipsum dolor sit amet, consectetur adipiscing elit. Fusce
-    varius, metus eu fringilla pulvinar, ipsum sapien ultricies arcu,
-    non condimentum quam est eu purus. Ut nisl libero, suscipit ut leo
-    eget, dapibus ultrices dolor.
-</div>
-<p>All text above should be green (if tested manually, you need to click first).</p>
diff --git a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/multicol-relpos-with-abspos-expected.html b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/multicol-relpos-with-abspos-expected.html
deleted file mode 100644
index 2b210b6..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/multicol-relpos-with-abspos-expected.html
+++ /dev/null
@@ -1,5 +0,0 @@
-<!DOCTYPE html>
-<div style="position:relative; -webkit-columns:4; -webkit-column-gap:10px; width:630px; height:40px; column-fill:auto;">
-    <div id="target" style="position:absolute; width:20px; height:20px; right:0; bottom:0; background:green;"></div>
-</div>
-<p>A green square should be seen above (if tested manually, you need to click first).</p>
diff --git a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/multicol-repaint-expected.html b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/multicol-repaint-expected.html
deleted file mode 100644
index 5cda785c..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/multicol-repaint-expected.html
+++ /dev/null
@@ -1,30 +0,0 @@
-<!DOCTYPE html>
-
-<html lang="en">
-<head>
-  <script src="../../resources/ahem.js"></script>
-  <style type="text/css" media="screen">
-
-    .container {
-      width: 400px;
-      height: 100px;
-      border: 1px solid black;
-      font-size: 50px;
-      -webkit-column-count: 2;
-      column-count: 2;
-      column-fill: auto;
-    }
-
-    span {
-      font-family: Ahem;
-    }
-  </style>
-</head>
-<body>
-  
-  <div class="container">
-    &nbsp;<br>
-    <span id="a">XXXXXX</span>
-  </div>
-</body>
-</html>
diff --git a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/multicol-resize-with-rule-expected.html b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/multicol-resize-with-rule-expected.html
deleted file mode 100644
index 3632b5d..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/multicol-resize-with-rule-expected.html
+++ /dev/null
@@ -1,4 +0,0 @@
-<!DOCTYPE html>
-<div id="columns" style="columns: 8; column-rule: 2px solid green; width: 600px">
-<div style="height: 1600px"></div>
-</div>
diff --git a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/multicol-resize-with-rule-expected.txt b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/multicol-resize-with-rule-expected.txt
index a5c70eaf..7c7121a 100644
--- a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/multicol-resize-with-rule-expected.txt
+++ b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/multicol-resize-with-rule-expected.txt
@@ -26,6 +26,62 @@
   ],
   "objectPaintInvalidations": [
     {
+      "object": "LayoutMultiColumnFlowThread (anonymous)",
+      "reason": "geometry"
+    },
+    {
+      "object": "LayoutMultiColumnFlowThread (anonymous)",
+      "reason": "geometry"
+    },
+    {
+      "object": "LayoutMultiColumnFlowThread (anonymous)",
+      "reason": "geometry"
+    },
+    {
+      "object": "LayoutMultiColumnFlowThread (anonymous)",
+      "reason": "geometry"
+    },
+    {
+      "object": "LayoutMultiColumnFlowThread (anonymous)",
+      "reason": "geometry"
+    },
+    {
+      "object": "LayoutMultiColumnFlowThread (anonymous)",
+      "reason": "geometry"
+    },
+    {
+      "object": "LayoutBlockFlow DIV",
+      "reason": "geometry"
+    },
+    {
+      "object": "LayoutBlockFlow DIV",
+      "reason": "geometry"
+    },
+    {
+      "object": "LayoutBlockFlow DIV",
+      "reason": "geometry"
+    },
+    {
+      "object": "LayoutBlockFlow DIV",
+      "reason": "geometry"
+    },
+    {
+      "object": "LayoutBlockFlow DIV",
+      "reason": "geometry"
+    },
+    {
+      "object": "LayoutBlockFlow DIV",
+      "reason": "geometry"
+    },
+    {
+      "object": "LayoutBlockFlow DIV",
+      "reason": "geometry"
+    },
+    {
+      "object": "LayoutBlockFlow DIV",
+      "reason": "geometry"
+    },
+    {
       "object": "LayoutMultiColumnSet (anonymous)",
       "reason": "geometry"
     }
diff --git a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/multicol-with-abspos-expected.html b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/multicol-with-abspos-expected.html
deleted file mode 100644
index 4e43cf3..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/multicol-with-abspos-expected.html
+++ /dev/null
@@ -1,14 +0,0 @@
-<!DOCTYPE html>
-<script src="../../resources/ahem.js"></script>
-<p>A green rectangle should be seen below (if tested manually, you need to click first).</p>
-<div style="-webkit-columns:4; -webkit-column-gap:10px; column-fill:auto; width:630px; height:40px; font:20px/1 ahem; color:green;">
-    <br>
-    <br>
-    <br>
-    <br>
-    <br>
-    <br>
-    <!-- This absolutely positioned box is not part of the flow thread, since the nearest
-         non-statically positioned box is further up than that. -->
-    <div id="target" style="position:absolute; left:0; bottom:0">PASS</div>
-</div>
diff --git a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/multicol-with-abspos-in-relpos-expected.html b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/multicol-with-abspos-in-relpos-expected.html
deleted file mode 100644
index 999e1621..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/multicol-with-abspos-in-relpos-expected.html
+++ /dev/null
@@ -1,16 +0,0 @@
-<!DOCTYPE html>
-<script src="../../resources/ahem.js"></script>
-<div style="-webkit-columns:4; -webkit-column-gap:10px; column-fill:auto; width:630px; height:40px; font:20px/1 ahem; color:green;">
-    <br>
-    <br>
-    <br>
-    <br>
-    <br>
-    <br>
-    <div style="position:relative;">
-        <br>
-        <br>
-        <div id="target" style="position:absolute; left:20px; top:20px">PASS</div>
-    </div>
-</div>
-<p>A green rectangle should be seen above (if tested manually, you need to click first).</p>
diff --git a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/multicol-with-block-expected.html b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/multicol-with-block-expected.html
deleted file mode 100644
index fc175c7e..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/multicol-with-block-expected.html
+++ /dev/null
@@ -1,9 +0,0 @@
-<!DOCTYPE html>
-<script src="../../resources/ahem.js"></script>
-<div style="-webkit-columns:4; -webkit-column-gap:10px; column-fill:auto; width:630px; height:20px; font:20px/1 ahem; orphans:1; widows:1; color:green;">
-    <br>
-    <br>
-    <br>
-    <div id="target">PASS</div>
-</div>
-<p>A green rectangle should be seen above (if tested manually, you need to click first).</p>
diff --git a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/multicol-with-inline-expected.html b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/multicol-with-inline-expected.html
deleted file mode 100644
index 3ad1a19e..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/multicol-with-inline-expected.html
+++ /dev/null
@@ -1,9 +0,0 @@
-<!DOCTYPE html>
-<script src="../../resources/ahem.js"></script>
-<div style="-webkit-columns:4; -webkit-column-gap:10px; column-fill:auto; width:630px; height:20px; font:20px/1 ahem; color:green;">
-    <br>
-    <br>
-    <br>
-    <span id="target">PASS</span>
-</div>
-<p>A green rectangle should be seen above (if tested manually, you need to click first).</p>
diff --git a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/multicol-with-overflowing-block-rl-expected.html b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/multicol-with-overflowing-block-rl-expected.html
deleted file mode 100644
index 6c9a855d..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/multicol-with-overflowing-block-rl-expected.html
+++ /dev/null
@@ -1,8 +0,0 @@
-<!DOCTYPE html>
-<div id="container" style="-webkit-columns:3; -webkit-column-gap:0; column-fill:auto; width:500px; height:500px; -webkit-writing-mode:vertical-rl;">
-    <div style="width:100px;">
-        <div id="elm" style="width:1500px; background:green;"></div>
-    </div>
-</div>
-<p>Test changing the background color of a big block that overflows the flow thread.</p>
-<p>A green square should be seen above (if tested manually, you need to click first).</p>
diff --git a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/multicol-with-overflowing-block-rl-expected.txt b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/multicol-with-overflowing-block-rl-expected.txt
index 297fbc62..46be5f4 100644
--- a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/multicol-with-overflowing-block-rl-expected.txt
+++ b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/multicol-with-overflowing-block-rl-expected.txt
@@ -18,7 +18,17 @@
       "paintInvalidations": [
         {
           "object": "LayoutBlockFlow DIV id='elm'",
-          "rect": [8, 8, 500, 500],
+          "rect": [-492, 174, 1500, 168],
+          "reason": "style change"
+        },
+        {
+          "object": "LayoutBlockFlow DIV id='elm'",
+          "rect": [8, 341, 1500, 167],
+          "reason": "style change"
+        },
+        {
+          "object": "LayoutBlockFlow DIV id='elm'",
+          "rect": [-992, 8, 1500, 167],
           "reason": "style change"
         }
       ]
@@ -28,6 +38,14 @@
     {
       "object": "LayoutBlockFlow DIV id='elm'",
       "reason": "style change"
+    },
+    {
+      "object": "LayoutBlockFlow DIV id='elm'",
+      "reason": "style change"
+    },
+    {
+      "object": "LayoutBlockFlow DIV id='elm'",
+      "reason": "style change"
     }
   ]
 }
diff --git a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/multicol-with-relpos-expected.html b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/multicol-with-relpos-expected.html
deleted file mode 100644
index 4de4481..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/multicol-with-relpos-expected.html
+++ /dev/null
@@ -1,11 +0,0 @@
-<!DOCTYPE html>
-<div style="-webkit-columns:4; -webkit-column-gap:10px; column-fill:auto; width:630px; height:40px; font:20px/1 ahem; color:green;">
-    <br>
-    <br>
-    <br>
-    <br>
-    <br>
-    <br>
-    <div id="target" style="position:relative; left:20px; top:20px; height:20px; background:green;"></div>
-</div>
-<p>A green rectangle should be seen above (if tested manually, you need to click first).</p>
diff --git a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/multicol-with-text-expected.html b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/multicol-with-text-expected.html
deleted file mode 100644
index 1cac2a4..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/multicol-with-text-expected.html
+++ /dev/null
@@ -1,8 +0,0 @@
-<!DOCTYPE html>
-<script src="../../resources/ahem.js"></script>
-<div id="mc" style="-webkit-columns:4; -webkit-column-gap:10px; column-fill:auto; width:630px; height:20px; font:20px/1 ahem; color:green;">
-    <br>
-    <br>
-    <br>PASS
-</div>
-<p>A green rectangle should be seen above (if tested manually, you need to click first).</p>
diff --git a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/multiple-backgrounds-style-change-expected.html b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/multiple-backgrounds-style-change-expected.html
deleted file mode 100644
index 334d6eb..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/multiple-backgrounds-style-change-expected.html
+++ /dev/null
@@ -1,15 +0,0 @@
-<!DOCTYPE html>
-<style>
-    .box {
-        height: 200px;
-        width: 200px;
-        border: 1px solid black;
-        background-repeat: no-repeat;
-        background-size: 100px 100px;
-        background-position: 0 0, 100px 100px;
-        background-image: url('../../images/resources/green-256x256.jpg'), url('../../images/resources/dice.png');
-        transform: translate3d(50px, 50px, 0);
-    }
-</style>
-<div id="test" class="box">
-</div>
diff --git a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/negative-shadow-box-expand-expected.html b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/negative-shadow-box-expand-expected.html
deleted file mode 100644
index 3d14147..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/negative-shadow-box-expand-expected.html
+++ /dev/null
@@ -1,7 +0,0 @@
-<!DOCTYPE html>
-<body style="margin: 100px">
-    <div id="outer" style="box-shadow: 40px -40px #F00;">
-        <div id="inner1" style="height: 100px; background-color: blue"></div>
-        <div id="inner2" style="height: 100px; background-color: green"></div>
-    </div>
-</body>
diff --git a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/negative-shadow-box-shrink-expected.html b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/negative-shadow-box-shrink-expected.html
deleted file mode 100644
index 4c1bf32f..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/negative-shadow-box-shrink-expected.html
+++ /dev/null
@@ -1,6 +0,0 @@
-<!DOCTYPE html>
-<body style="margin: 100px">
-    <div id="outer" style="box-shadow: 40px -40px #F00;">
-        <div id="inner1" style="height: 100px; background-color: blue"></div>
-    </div>
-</body>
diff --git a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/negative-text-indent-with-overflow-hidden-expected.html b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/negative-text-indent-with-overflow-hidden-expected.html
deleted file mode 100644
index 295bbc0..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/negative-text-indent-with-overflow-hidden-expected.html
+++ /dev/null
@@ -1,26 +0,0 @@
-<!DOCTYPE html>
-<html>
-  <head>
-    <style>
-    .container {
-        position: absolute;
-        left: 550px;
-        height: 200px;
-        width: 200px;
-        background-color: silver;
-    }
-    #target {
-        text-indent: -300px;
-        width: 200px;
-        height: 50px;
-        overflow: hidden;
-        background-color: blue;
-    }
-    </style>
-</head>
-<body>
-    <div class="container">
-        <div id="target">Hidden Text</div>
-    </div>
-</body>
-</html>
diff --git a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/opacity-change-on-overflow-float-expected.html b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/opacity-change-on-overflow-float-expected.html
deleted file mode 100644
index da9e2ce..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/opacity-change-on-overflow-float-expected.html
+++ /dev/null
@@ -1,31 +0,0 @@
-<html>
-<head>
-<style>
-div {
-  width: 100px;
-  height:100px;
-  overflow:hidden;
-  float:left;
-}
-
-.green {
-  background-color:green
-}
-</style>
-</head>
-<body>
-<p>Repaint test for <rdar><!-- 
-An explanation as to why this is here.  In the beginning, there was an
-<rdar:://problem/6869687> link to rdar.  However, that link was invisible
-because it was enclosed in angle brackets.
-
-This was fine, until we implemented the HTML5 parsing algorithm, which changed
-the name of the rdar element to not include // charaters.  Rather than
-regenerate the expected results (which were platform specific), the rdar link
-was changed to an <rdar> element and the expected render tree was hand-edited.
---> REGRESSION (r41203): Facebook friend suggestions disappear on update.  Make sure when a layer switches
-from being self-painting to non-self-painting that a layout happens to fix up the floating objects lists.  You should see a 100x100 green square below.
-If you see any red, the test has failed.
-</p>
-<div class="green"></div>
-
diff --git a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/outline-add-repaint-expected.html b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/outline-add-repaint-expected.html
deleted file mode 100644
index ff48e14..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/outline-add-repaint-expected.html
+++ /dev/null
@@ -1,8 +0,0 @@
-<!DOCTYPE HTML>
-<style>
-    body {
-        margin: 0;
-    }
-</style>
-<div id="test" style="background-color: green; width: 100px; height: 100px; outline: solid black 10px"></div>
-<!-- Tests the repainting of outline when added. -->
diff --git a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/outline-change-continuations-expected.html b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/outline-change-continuations-expected.html
deleted file mode 100644
index 6c4318ca..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/outline-change-continuations-expected.html
+++ /dev/null
@@ -1,19 +0,0 @@
-<!DOCTYPE html>
-<style>
-body { height: 200px; }
-#container { position: absolute; }
-p, #inner { height: 20px; }
-#outer { outline: 2px solid green; }
-</style>
-<p>
-  This test is verifying that when the outline is modified on an element
-  that we correctly invalidate any continuations.
-</p>
-<p>
-  If this test passes, you should see a green border around the text contents.
-</p>
-<div id="container">
-  <span id="outer">
-      <div id="inner">CONTENTS</div>
-  </span>
-</div>
diff --git a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/outline-change-in-scrollers-expected.html b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/outline-change-in-scrollers-expected.html
deleted file mode 100644
index 4ba6db5..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/outline-change-in-scrollers-expected.html
+++ /dev/null
@@ -1,49 +0,0 @@
-<!DOCTYPE HTML>
-<style>
-.scroll {
-  position: relative;
-  width: 100px;
-  height: 100px;
-  display: inline-block;
-  border: 10px solid blue;
-  overflow: scroll;
-  padding: 5px;
-}
-.target {
-  width: 50px;
-  height: 50px;
-  outline: solid black 20px;
-}
-.space {
-  position: absolute;
-  top: 0;
-  left: 0;
-  width: 150px;
-  height: 150px;
-}
-</style>
-<div class="scroll">
-  <div class="target"></div>
-  <div class="space"></div>
-</div>
-<div class="scroll" style="writing-mode: vertical-rl">
-  <div class="target"></div>
-  <div class="space"></div>
-</div>
-<div class="scroll" style="writing-mode: vertical-lr">
-  <div class="target"></div>
-  <div class="space"></div>
-</div>
-<br>
-<div class="scroll" style="direction: rtl">
-  <div class="target"></div>
-  <div class="space"></div>
-</div>
-<div class="scroll" style="direction: rtl; writing-mode: vertical-rl">
-  <div class="target"></div>
-  <div class="space"></div>
-</div>
-<div class="scroll" style="direction: rtl; writing-mode: vertical-lr">
-  <div class="target"></div>
-  <div class="space"></div>
-</div>
diff --git a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/outline-change-invalidation-expected.html b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/outline-change-invalidation-expected.html
deleted file mode 100644
index 17ff29f..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/outline-change-invalidation-expected.html
+++ /dev/null
@@ -1,19 +0,0 @@
-<!DOCTYPE html>
-<html>
-<head>
-<style>
-a {
-    display: block;
-    outline: 5px dotted green;
-}
-</style>
-</head>
-<body>
-    <p>This test checks that an outline change is correctly repainted.</p>
-    <p>There should be a 5px green outline below.</p>
-    <ul>
-        <li><a id="link">Lorem Ipsum</a></li>
-    </ul>
-</body>
-</html>
-
diff --git a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/outline-change-offset-expected.html b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/outline-change-offset-expected.html
deleted file mode 100644
index 5ad302b..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/outline-change-offset-expected.html
+++ /dev/null
@@ -1,23 +0,0 @@
-<!DOCTYPE html>
-<style>
-div {
-  position: absolute;
-  top: 50px;
-  left: 50px;
-  width: 100px;
-  height: 100px;
-}
-
-#target {
-  outline: green solid 5px;
-  outline-offset: 10px;
-}
-
-#indicator {
-  outline: red solid 5px;
-  outline-offset: 10px;
-</style>
-
-Box should be repainted when outline-offset style changes. Passes if no red.
-<div id="indicator"></div>
-<div id="target"></div>
diff --git a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/outline-change-repaint-expected.html b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/outline-change-repaint-expected.html
deleted file mode 100644
index 5acb6eb2..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/outline-change-repaint-expected.html
+++ /dev/null
@@ -1,8 +0,0 @@
-<!DOCTYPE HTML>
-<style>
-    body {
-        margin: 0;
-    }
-</style>
-<div id="test" style="background-color: green; width: 100px; height: 100px; outline: solid black 10px;"></div>
-<!-- Tests the repainting of outline when changed. -->
diff --git a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/outline-change-scrollable-expected.html b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/outline-change-scrollable-expected.html
deleted file mode 100644
index 3ce4328..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/outline-change-scrollable-expected.html
+++ /dev/null
@@ -1,2 +0,0 @@
-<!DOCTYPE HTML>
-<div id="test" style="background-color: green; width: 1000px; height: 100px; outline: solid black 20px;"></div>
diff --git a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/outline-change-vertical-rl-expected.html b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/outline-change-vertical-rl-expected.html
deleted file mode 100644
index dbfe2a31..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/outline-change-vertical-rl-expected.html
+++ /dev/null
@@ -1,3 +0,0 @@
-<!DOCTYPE HTML>
-<style>body { writing-mode: vertical-rl; }</style>
-<div id="test" style="background-color: green; width: 1000px; height: 100px; outline: solid black 20px;"></div>
diff --git a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/outline-child-repaint-expected.html b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/outline-child-repaint-expected.html
deleted file mode 100644
index 533cc65..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/outline-child-repaint-expected.html
+++ /dev/null
@@ -1,42 +0,0 @@
-<html>
-<head>
-    <style type="text/css" media="screen">
-      #container {
-        position: absolute;
-        left: 10px;
-        top: 250px;
-        width: 200px;
-        height: 50px;
-      }
-      .outlined {
-        outline: 10px solid green;
-        height: 30px;
-        background-color: #DDD;
-      }
-
-      #underlay {
-        position: absolute;
-        top: 240px;
-        left: 0px;
-        width: 200px;
-        height: 30px;
-        border: 10px solid red;
-      }
-    </style>
-</head>
-<body>
-    <p>
-        This is a repaint test for <i><a href="https://bugs.webkit.org/show_bug.cgi?id=22159">https://bugs.webkit.org/show_bug.cgi?id=22159</a>
-        Repaint issue with outlines in child objects</i>.
-    </p>
-    <p>If the test passes, you should not see any red below</p>
-    <hr>
-
-    <div id="underlay">
-    </div>
-    <div id="container">
-      <div class="outlined">
-      </div>
-    </div>
-</body>
-</html>
diff --git a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/outline-clip-change-expected.html b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/outline-clip-change-expected.html
deleted file mode 100644
index a2e20db4..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/outline-clip-change-expected.html
+++ /dev/null
@@ -1,22 +0,0 @@
-<!DOCTYPE html>
-<html>
-<head>
-<style>
-a {
-    position: absolute;
-    display: block;
-    outline: thin dotted green;
-    outline-width: 5px;
-    clip: rect(0px, 100px, 100px, 0px);
-}
-</style>
-</head>
-<body>
-    <p>This test checks that an outline change is correctly repainted.</p>
-    <p>There should be a 5px green outline below.</p>
-    <ul>
-        <li><a id="link">Lorem Ipsum</a></li>
-    </ul>
-</body>
-</html>
-
diff --git a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/outline-containing-image-in-non-standard-mode-expected.html b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/outline-containing-image-in-non-standard-mode-expected.html
deleted file mode 100644
index b82cd951..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/outline-containing-image-in-non-standard-mode-expected.html
+++ /dev/null
@@ -1,3 +0,0 @@
-<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
-<!-- Almost Standards mode -->
-<span id="target" style="outline: 2px solid green"><img style="width: 200px; height: 50px"></span>
diff --git a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/outline-current-color-expected.html b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/outline-current-color-expected.html
deleted file mode 100644
index 9167306d..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/outline-current-color-expected.html
+++ /dev/null
@@ -1,12 +0,0 @@
-<!DOCTYPE html>
-<style>
-div {
-  margin: 50px;
-  outline-width: 10px;
-  outline-style: solid;
-  width: 100px;
-  height: 100px;
-}
-</style>
-<div style="outline-color: blue"></div>
-<div style="outline-color: green"></div>
diff --git a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/outline-inset-expected.html b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/outline-inset-expected.html
deleted file mode 100644
index 52a1640..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/outline-inset-expected.html
+++ /dev/null
@@ -1,22 +0,0 @@
-<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
-        "http://www.w3.org/TR/html4/strict.dtd">
-<html lang="en">
-<head>
-<style type="text/css">
-    div.test { width: 200px; height: 120px; border: 1px solid blue; padding: 10px; }
-</style>
-</head>
-<body>
-<div class="test">
-    <div style="background: teal; padding: 0; outline: solid red 4px; outline-offset: -5px;">
-        <div id="a" style="height: 40px; margin: 10px; background:silver;"></div>
-    </div>
-</div>
-<br>
-<div class="test">
-    <div style="background: teal; padding: 0; outline: solid red 4px; outline-offset: -5px;">
-        <div id="b" style="height: 60px; margin: 10px; background:silver;"></div>
-    </div>
-</div>
-</body>
-</html>
diff --git a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/outline-repaint-glitch-expected.html b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/outline-repaint-glitch-expected.html
deleted file mode 100644
index aeabbd2..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/outline-repaint-glitch-expected.html
+++ /dev/null
@@ -1,38 +0,0 @@
-<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
-        "http://www.w3.org/TR/html4/strict.dtd">
-<html lang="en">
-<head>
-<style type="text/css">
-    div.test { width: 200px; height: 120px; border: 1px solid blue; padding: 10px; }
-</style>
-</head>
-<body>
-<p><b>BUG ID:</b> <a href="https://bugs.webkit.org/show_bug.cgi?id=8032">Bugzilla bug 8032</a> REGRESSION: Focus ring not completely redrawn after a Delete changes its size</p>
-
-<p> Note that this bug (and the test) are just outline versions of <a href="https://bugs.webkit.org/show_bug.cgi?id=6301">Bugzilla bug 6301</a> and test <a href="border-repaint-glitch.html">border-repaint-glitch.html</a>
-
-<p id="success" style="background-color:palegreen; padding:3px;"><b>TEST PASS:</b>
-The boxes will resize, maintaining their solid red rectangular outlines.
-</p>
-
-<p id="failure" style="background-color:#FF3300; padding:3px;"><b>TEST FAIL:</b> 
-The boxes will resize, but the outlines will break. The first box will be missing
-small segments from either side of its bottom outline. The second box will have
-small red horizontal segments protruding inwards from both sides of the outline,
-where the bottom outline was before.
-</p>
-
-<div class="test">
-    <div style="background: teal; padding: 0; outline: solid red 4px;">
-        <div id="a" style="height: 40px; margin: 10px; background:silver;"></div>
-    </div>
-</div>
-<br>
-<div class="test">
-    <div style="background: teal; padding: 0; outline: solid red 4px;">
-        <div id="b" style="height: 60px; margin: 10px; background:silver;"></div>
-    </div>
-</div>
-
-</body>
-</html>
diff --git a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/outline-shrinking-expected.html b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/outline-shrinking-expected.html
deleted file mode 100644
index 37458ef..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/outline-shrinking-expected.html
+++ /dev/null
@@ -1,14 +0,0 @@
-<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
-        "http://www.w3.org/TR/html4/strict.dtd">
-<html lang="en">
-<body>
-    <p>
-        This is a test for <i><a href="https://bugs.webkit.org/show_bug.cgi?id=9388">http://bugzilla.opendarwin.org/show_bug.cgi?id=9388</a>
-        REGRESSION: outlines don't get erased when removed in some cases</i>.
-    </p>
-    <p>
-        There should be a green square and no trace of red.
-    </p>
-    <hr>
-    <div id="t" style="background: green; font-size: 20px; width: 100px; height: 100px;"></div>
-</body>
diff --git a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/overflow-changed-on-child-of-composited-layer-expected.html b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/overflow-changed-on-child-of-composited-layer-expected.html
deleted file mode 100644
index 887d9ca7..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/overflow-changed-on-child-of-composited-layer-expected.html
+++ /dev/null
@@ -1,5 +0,0 @@
-<!DOCTYPE html>
-<div id="parent" style="margin: 20px; transform: scale3d(1, 1, 1);">
-    <div id="test" style="height: 100px; width: 100px; outline: 1px solid black;"></div>
-</div>
-<p>crbug.com/621612: Change overflow on the child of a composited layer should allow the layer to resize and contain the overflow, just like it would in a layout. There should be a white box with black outline below.</p>
diff --git a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/overflow-clip-subtree-layout-expected.html b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/overflow-clip-subtree-layout-expected.html
deleted file mode 100644
index d885eee..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/overflow-clip-subtree-layout-expected.html
+++ /dev/null
@@ -1,9 +0,0 @@
-<head>
-    <title>Test for http://bugs.webkit.org/show_bug.cgi?id=15015 rdar://problem/5420308</title>
-</head>
-<body>
-    <div style="width: 400px; height: 400px; border: solid;">
-        <div id="float" style="float: left; width: 200px; height: 200px; overflow: hidden;">
-        </div>
-    </div>
-</body>
diff --git a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/overflow-delete-line-expected.html b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/overflow-delete-line-expected.html
deleted file mode 100644
index f24e8c4d..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/overflow-delete-line-expected.html
+++ /dev/null
@@ -1,12 +0,0 @@
-<html>
-<body>
-    <p>
-        This is a repaint test for <i><a href="http://bugs.webkit.org/show_bug.cgi?id=11277">http://bugs.webkit.org/show_bug.cgi?id=11277</a>
-        REGRESSION: Incomplete repaint of overflow areas when deleting</i>.
-    </p>
-    <hr>
-    <div contenteditable id="dv" style="overflow: hidden; outline: none; width: 80px; height: 36px">
-        Lorem ipsu
-    </div>
-</body>
-</html>
diff --git a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/overflow-flipped-writing-mode-block-expected.html b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/overflow-flipped-writing-mode-block-expected.html
deleted file mode 100644
index fcaa85f..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/overflow-flipped-writing-mode-block-expected.html
+++ /dev/null
@@ -1,5 +0,0 @@
-<div style="height: 100px; width: 100px; background-color: red; writing-mode: vertical-rl;">
-    <div style="width: 25px;">
-        <div style="width: 100px; background-color: green;"></div>
-    </div>
-</div>
diff --git a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/overflow-flipped-writing-mode-table-expected.html b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/overflow-flipped-writing-mode-table-expected.html
deleted file mode 100644
index 95ec910..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/overflow-flipped-writing-mode-table-expected.html
+++ /dev/null
@@ -1,7 +0,0 @@
-<div style="height: 100px; width: 100px; background-color: red; writing-mode: vertical-rl;">
-    <div style="display: table; height: 100px;">
-        <div style="width: 25px;">
-            <div style="width: 100px; background-color: green;"></div>
-        </div>
-    </div>
-</div>
diff --git a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/overflow-hide-expected.html b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/overflow-hide-expected.html
deleted file mode 100644
index 35a1c4b..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/overflow-hide-expected.html
+++ /dev/null
@@ -1,9 +0,0 @@
-<html>
-<head>
-    <link rel="stylesheet" href="resources/default.css">
-</head>
-<body style="height:2000px;">
-    <!-- You should see 2 green rectangle sharing one corner in the output. -->
-    <div id="overflowParent" class="absolute green" style="overflow: hidden"><div style="top:100px; left:100px;" class="relative red"></div></div>
-</body>
-</html>
diff --git a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/overflow-into-content-expected.html b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/overflow-into-content-expected.html
deleted file mode 100644
index ed3a02e..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/overflow-into-content-expected.html
+++ /dev/null
@@ -1,37 +0,0 @@
-<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
-<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
-<head>
-    <title>Test for http://bugs.webkit.org/show_bug.cgi?id=12885</title>
-    <style type="text/css">
-        div.wide { width: 100px; height: 50px; }
-        div.narrow { width: 50px; }
-        div.tall { width: 50px; height: 100px; }
-        div.short { height: 50px; width: 50px; }
-        #main-content { float: left; width: 100px; height: 80px; }
-        #target3 { display: none; clear: both; height: 20px; background: green; }
-    </style>
-</head>
-<body>
-    <div style="position: absolute; border: medium solid green; top: 8px; height: 100px;">
-        <div class="narrow" id="target1">
-            <div class="wide"></div>
-        </div>
-    </div>
-
-    <div style="position: absolute; border: medium solid green; top: 158px; width: 100px;">
-        <div class="short" id="target2">
-            <div class="tall"></div>
-        </div>
-    </div>
-
-    <div style="position: absolute; top: 308px;">
-        <div style="background: green;">
-            <div style="position: relative;">
-                <div id="main-content">
-                </div>
-            </div>
-            <div id="target3"></div>
-        </div>
-    </div>
-</body>
-</html>
diff --git a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/overflow-show-expected.html b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/overflow-show-expected.html
deleted file mode 100644
index 66f2c72..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/overflow-show-expected.html
+++ /dev/null
@@ -1,9 +0,0 @@
-<html>
-<head>
-    <link rel="stylesheet" href="resources/default.css">
-</head>
-<body style="height:2000px;">
-    <!-- You should see 2 green rectangle sharing one corner in the output. -->
-    <div id="overflowParent" style="overflow: visible" class="absolute green"><div style="top:100px; left:100px;" class="relative green"></div></div>
-</body>
-</html>
diff --git a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/overhanging-float-detach-repaint-expected.html b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/overhanging-float-detach-repaint-expected.html
deleted file mode 100644
index 4a4c030..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/overhanging-float-detach-repaint-expected.html
+++ /dev/null
@@ -1,21 +0,0 @@
-<!DOCTYPE HTML>
-<html>
-<head>
-    <style>
-    .floatWithHeight {
-        float: left;
-        height: 400px;
-    }
-    </style>
-</head>
-<body>
-<div>
-    <div style="opacity: 0;">
-        <a href="https://bugs.webkit.org/show_bug.cgi?id=105861">Bug 105861</a>: REGRESSION (r132591): Underpainting @ uofmchildrenshospital.org<br>
-        This test checks that overhanging floats are properly repainted when a renderer is detached.<br>
-        This test has PASSED if there is no RED below.
-    </div>
-    <div class="floatWithHeight"></div>
-</div>	
-</body> 
-</html> 
diff --git a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/padding-border-keeping-border-box-and-content-box-expected.html b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/padding-border-keeping-border-box-and-content-box-expected.html
deleted file mode 100644
index 07c9f9bc..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/padding-border-keeping-border-box-and-content-box-expected.html
+++ /dev/null
@@ -1,17 +0,0 @@
-<!DOCTYPE HTML>
-<style>
-body {
-    margin: 0;
-}
-div {
-    width: 100px;
-    height: 100px;
-    padding: 20px;
-    position: absolute;
-    background-color: green;
-    border-color: blue;
-    border-style: solid;
-    border-width: 20px;
-}
-</style>
-<div id="target"></div>
diff --git a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/padding-keeping-content-size-expected.html b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/padding-keeping-content-size-expected.html
deleted file mode 100644
index 6511a7d4..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/padding-keeping-content-size-expected.html
+++ /dev/null
@@ -1,23 +0,0 @@
-<!DOCTYPE HTML>
-<style>
-body {
-    margin: 0;
-}
-.outer {
-    width: 100px;
-    height: 100px;
-    position: absolute;
-    background-color: green;
-    padding: 20px;
-}
-#target2 {
-    top: 200px;
-}
-.inner {
-    width: 100%;
-    height: 100%;
-    background-color: yellow;
-}
-</style>
-<div id="target1" class="outer"></div>
-<div id="target2" class="outer"><div class="inner"></div></div>
diff --git a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/padding-keeping-visual-size-expected.html b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/padding-keeping-visual-size-expected.html
deleted file mode 100644
index e130d53..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/padding-keeping-visual-size-expected.html
+++ /dev/null
@@ -1,23 +0,0 @@
-<!DOCTYPE HTML>
-<style>
-body {
-    margin: 0;
-}
-.outer {
-    padding: 20px;
-    width: 60px;
-    height: 60px;
-    position: absolute;
-    background-color: green;
-}
-#target2 {
-    top: 200px;
-}
-.inner {
-    width: 100%;
-    height: 100%;
-    background-color: yellow;
-}
-</style>
-<div id="target1" class="outer"></div>
-<div id="target2" class="outer"><div class="inner"></div></div>
diff --git a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/paged-with-overflowing-block-rl-expected.txt b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/paged-with-overflowing-block-rl-expected.txt
index 775996b..4486c51 100644
--- a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/paged-with-overflowing-block-rl-expected.txt
+++ b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/paged-with-overflowing-block-rl-expected.txt
@@ -20,6 +20,11 @@
           "object": "LayoutBlockFlow DIV id='elm'",
           "rect": [8, 8, 500, 485],
           "reason": "style change"
+        },
+        {
+          "object": "LayoutBlockFlow DIV id='elm'",
+          "rect": [8, 8, 500, 485],
+          "reason": "style change"
         }
       ]
     }
@@ -28,6 +33,10 @@
     {
       "object": "LayoutBlockFlow DIV id='elm'",
       "reason": "style change"
+    },
+    {
+      "object": "LayoutBlockFlow DIV id='elm'",
+      "reason": "style change"
     }
   ]
 }
diff --git a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/paint-invalidation-with-opacity-expected.html b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/paint-invalidation-with-opacity-expected.html
deleted file mode 100644
index af02371..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/paint-invalidation-with-opacity-expected.html
+++ /dev/null
@@ -1,2 +0,0 @@
-<!DOCTYPE html>
-<div id="target" style="width: 100px; height: 100px; background: lightblue; opacity: 0.5"></div>
diff --git a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/percent-size-image-resize-container-expected.html b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/percent-size-image-resize-container-expected.html
deleted file mode 100644
index dbc3317..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/percent-size-image-resize-container-expected.html
+++ /dev/null
@@ -1,19 +0,0 @@
-<!DOCTYPE html>
-<style>
-div {
-  position: absolute;
-  top: 50px;
-  left: 0px;
-  width: 100px;
-  height: 200px;
-}
-img {
-  position: absolute;
-  width: 100%;
-  height: 100%;
-}
-</style>
-The percent-sized image should be fully repainted on container's resize. Passes if there is a whole apple after resize.
-<div>
-  <img src="resources/apple.jpg">
-</div>
diff --git a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/position-change-keeping-geometry-expected.html b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/position-change-keeping-geometry-expected.html
deleted file mode 100644
index c71e66b..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/position-change-keeping-geometry-expected.html
+++ /dev/null
@@ -1,36 +0,0 @@
-<!DOCTYPE html>
-<style>
-body {
-  margin: 0;
-}
-div {
-  width: 100px;
-  height: 100px;
-  top: 20px;
-  background-color: blue;
-}
-#target0 {
-  left: 20px;
-  position: relative;
-}
-#target1 {
-  left: 20px;
-  position: relative;
-}
-#target2 {
-  left: 220px;
-  position: fixed;
-  z-index: 0;
-}
-#target3 {
-  left: 420px;
-  position: absolute;
-  z-index: 0;
-}
-</style>
-There should be no invalildations on change of position without actual change of position and size.
-<!-- target0 ensures we don't strip anonymous wrappers (and trigger a layout) when the other elements change position. -->
-<div id="target0"></div>
-<div id="target1"></div>
-<div id="target2"></div>
-<div id="target3"></div>
diff --git a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/positioned-great-grandparent-change-location-expected.html b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/positioned-great-grandparent-change-location-expected.html
deleted file mode 100644
index 9152d5f..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/positioned-great-grandparent-change-location-expected.html
+++ /dev/null
@@ -1,11 +0,0 @@
-<!DOCTYPE html>
-Tests paint invalidation of the target when the great-grandparent changes location.
-Passes if there is only one green square.
-<div style="position: absolute; background-color: red; top: 100px; left: 100px; width: 100px; height: 100px">Indicator</div>
-<div id="great-grandparent" style="position: absolute; top: -100px; left: 0px">
-  <div style="position: absolute">
-    <div style="position: absolute">
-      <div style="position: absolute; background-color: green; top: 200px; left: 100px; width: 100px; height: 100px">Target</div>
-    </div>
-  </div>
-</div>
diff --git a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/push-block-with-first-line-expected.html b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/push-block-with-first-line-expected.html
deleted file mode 100644
index dcc1d26f..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/push-block-with-first-line-expected.html
+++ /dev/null
@@ -1,14 +0,0 @@
-<!DOCTYPE html>
-<!--
-    Test that the ::first-line background is repainted at the new position when its block is moved.
-    There should be no red below.
--->
-<script src="../../resources/ahem.js"></script>
-<script src="../../resources/run-after-layout-and-paint.js"></script>
-<style>
-    body { font:20px Ahem; }
-    .test { color:green; }
-    .test::first-line { background:red; }
-</style>
-<div id="spacer" style="height:3em;"></div>
-<div class="test">JOCULAR</div>
diff --git a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/quotes-expected.html b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/quotes-expected.html
deleted file mode 100644
index e1818da8..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/quotes-expected.html
+++ /dev/null
@@ -1,11 +0,0 @@
-<!DOCTYPE html>
-<style>
-.q-changed {
-    quotes: '{' '}';
-}
-.q-unchanged {
-    quotes: '<' '>';
-}
-</style>
-<div><q id="q1" class="q-unchanged">quote 1</q></div>
-<div><q id="q2" class="q-changed">quote 2</q></div>
diff --git a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/reflection-invalidation-after-display-expected.html b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/reflection-invalidation-after-display-expected.html
deleted file mode 100644
index f0337be..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/reflection-invalidation-after-display-expected.html
+++ /dev/null
@@ -1,17 +0,0 @@
-<!DOCTYPE html>
-<style>
-.green {
-  background-color: green;
-}
-.box {
-  width: 200px;
-  height: 200px;
-  position: absolute;
-  left: 300px;
-}
-</style>
-<!--
-    This test checks that we correctly invalidate reflection when they are removed.
-    There should be only one green box below.
--->
-<div class="green box" id="box"></div>
diff --git a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/reflection-invalidation-positioned-child-expected.html b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/reflection-invalidation-positioned-child-expected.html
deleted file mode 100644
index d07d555e..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/reflection-invalidation-positioned-child-expected.html
+++ /dev/null
@@ -1,27 +0,0 @@
-<!DOCTYPE html>
-<style>
-body {
-  margin: 0;
-}
-#box {
-  width: 100px;
-  height: 100px;
-  background-color: green;
-  -webkit-box-reflect: below 20px;
-}
-#positioned {
-  position: absolute;
-  top: 10px;
-  left: 400px;
-  width: 50px;
-  height: 50px;
-  background-color: blue;
-}
-</style>
-<!--
-Tests paint invalidation of positioned object when its ancestor changes reflection.
-Passes if there is no red.
--->
-<div id="box">
-  <div id="positioned"></div>
-</div>
diff --git a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/reflection-redraw-expected.html b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/reflection-redraw-expected.html
deleted file mode 100644
index bcab5a28..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/reflection-redraw-expected.html
+++ /dev/null
@@ -1,51 +0,0 @@
-<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
-  "http://www.w3.org/TR/html4/strict.dtd">
-<html>
-  <head>
-    <meta http-equiv="Content-type" content="text/html; charset=utf-8">
-    <title>Reflection Redraw</title>
-    <style type="text/css" media="screen">
-      #container {
-        position: absolute;
-        top: 120px;
-      }
-      .box {
-        position: absolute;
-        width: 150px;
-        height: 100px;
-        margin: 10px;
-        padding: 10px;
-        -webkit-box-sizing: border-box;
-        text-align: center;
-        border: 1px solid black;
-        background-color: gray;
-      }
-      .reflect {
-        background-color: gray;
-        -webkit-box-reflect: left 5px;
-      }
-      p {
-        color: green;
-      }
-    </style>
-  </head>
-<body>
-  <div id="container">
-    <div class="box reflect-top"  style="left: 275px; -webkit-box-reflect: above 10px;">
-      <p>The color of this text in the reflection should be green</p>
-    </div>
-
-    <div class="box reflect-left" style="top: 110px; left: 200px; -webkit-box-reflect: left 10px;">
-      <p>The color of this text in the reflection should be green</p>
-    </div>
-
-    <div class="box reflect-right"  style="top: 110px; left: 350px; -webkit-box-reflect: right 10px;">
-      <p>The color of this text in the reflection should be green</p>
-    </div>
-
-    <div class="box reflect-bottom"  style="top: 220px; left: 275px; -webkit-box-reflect: below 10px;">
-      <p>The color of this text in the reflection should be green</p>
-    </div>
-  </div>
-
-</html>
diff --git a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/reflection-repaint-test-expected.html b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/reflection-repaint-test-expected.html
deleted file mode 100644
index 342ebd98..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/reflection-repaint-test-expected.html
+++ /dev/null
@@ -1,24 +0,0 @@
-<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
-        "http://www.w3.org/TR/html4/strict.dtd">
-<html lang="en">
-<head>
-    <style type="text/css" media="screen">
-      div {
-        margin: 50px;
-        width: 200px;
-        height: 50px;
-        border: 1px solid black;
-        transform-origin: top left;
-        transform: rotate(20deg);
-        -webkit-box-reflect: below;
-      }
-      
-      div:hover {
-        background-color: orange;
-      }
-    </style>
-</head>
-<body>
-    <div id="target">PASS</div>
-</body>
-</html>
diff --git a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/rel-positioned-inline-with-overflow-expected.html b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/rel-positioned-inline-with-overflow-expected.html
deleted file mode 100644
index 4ed70f5..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/rel-positioned-inline-with-overflow-expected.html
+++ /dev/null
@@ -1,10 +0,0 @@
-<html>
-<head>
-  <title>Relative Positioned Inline Repaint Test</title>
-</head>
-<body>
-  <p>If you see any red or orange below then the test has failed.</p>
-  <span style="position:relative"><div style="vertical-align:top;display:inline-block; width:100px;height:100px; background-color:green"></div></span>
-  <br>
-</body>
-</html>
diff --git a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/relative-inline-positioned-movement-repaint-expected.html b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/relative-inline-positioned-movement-repaint-expected.html
deleted file mode 100644
index 55a7bb1..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/relative-inline-positioned-movement-repaint-expected.html
+++ /dev/null
@@ -1,14 +0,0 @@
-<!DOCTYPE html>
-<style>
-    #block {
-        display: inline;
-        margin: 10px;
-        width: 400px;
-        height: 60px;
-        border: 1px solid black;
-        backface-visibility: hidden;
-        position: relative;
-        left: 50px;
-    }
-</style>
-<div id="block">When this layer moves it shouldn't generate a repaint rect.</div>
diff --git a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/relative-margin-change-repaint-expected.html b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/relative-margin-change-repaint-expected.html
deleted file mode 100644
index 43215536..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/relative-margin-change-repaint-expected.html
+++ /dev/null
@@ -1,23 +0,0 @@
-<!DOCTYPE HTML>
-<style>
-    body {
-        margin: 0;
-    }
-    #container {
-        position: relative;
-        top: 40px;
-        width: 200px;
-        height: 400px;
-    }
-    #test {
-        position: relative;
-        background-color: green;
-        width: 100px;
-        height: 100px;
-        margin-top: 20px;
-    }
-</style>
-<div id="container">
-    <div id="test"></div>
-</div>
-<!-- Tests the repainting of relative element when margin-top changes. -->
diff --git a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/relative-positioned-movement-repaint-expected.html b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/relative-positioned-movement-repaint-expected.html
deleted file mode 100644
index fe1996bb..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/relative-positioned-movement-repaint-expected.html
+++ /dev/null
@@ -1,14 +0,0 @@
-<!DOCTYPE html>
-<style>
-    #block {
-        font-family: sans-serif;
-        display: block;
-        margin: 10px;
-        width: 400px;
-        height: 60px;
-        border: 1px solid black;
-        position: relative;
-        left: 50px;
-    }
-</style>
-<div id="block">When this layer moves it shouldn't generate a repaint rect.</div>
diff --git a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/remove-block-after-layout-expected.html b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/remove-block-after-layout-expected.html
deleted file mode 100644
index 91f3c549..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/remove-block-after-layout-expected.html
+++ /dev/null
@@ -1,4 +0,0 @@
-<!DOCTYPE html>
-<div style="height: 100px">
-Tests invalidation after layouting and then removing a div. The div should disappear without any residue.
-</div>
diff --git a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/remove-inline-after-layout-expected.html b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/remove-inline-after-layout-expected.html
deleted file mode 100644
index 2b20385f..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/remove-inline-after-layout-expected.html
+++ /dev/null
@@ -1,6 +0,0 @@
-<!DOCTYPE html>
-<div style="height: 100px">
-Tests invalidation after layouting and then removing a span. The span should disappear without any residue.
-</div>
-<div style="display: inline-block; width: 100px; height: 100px; background-color: green"></div>
-<div style="display: inline-block; width: 100px; height: 100px; background-color: green"></div>
diff --git a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/remove-inline-block-descendant-of-flex-expected.html b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/remove-inline-block-descendant-of-flex-expected.html
deleted file mode 100644
index ca907cc..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/remove-inline-block-descendant-of-flex-expected.html
+++ /dev/null
@@ -1,20 +0,0 @@
-<!DOCTYPE html>
-<style>
-body {
-  margin : 0;
-}
-.item {
-  display: inline-block;
-  height: 100px;
-  width: 100px;
-}
-</style>
-Tests paint invalidation of inline blocks following an inline-block that is removed.
-Passes if there is only one green square at the top-left corner of the window.
-<div style="display: flex; height: 300px; position: absolute; top: 100px">
-  <div style="display: flex">
-    <div style="width: 100px">
-      <div id="inline-block-2" class="item" style="background-color: green"><br></div>
-    </div>
-  </div>
-</div>
diff --git a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/remove-inline-layer-after-layout-expected.html b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/remove-inline-layer-after-layout-expected.html
deleted file mode 100644
index 5906a4d..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/remove-inline-layer-after-layout-expected.html
+++ /dev/null
@@ -1,6 +0,0 @@
-<!DOCTYPE html>
-<div style="height: 100px">
-Tests invalidation after layouting and then removing a layered span. The span should disappear without any residue.
-</div>
-<div style="display: inline-block; width: 100px; height: 100px; background-color: green"></div>
-<div style="display: inline-block; width: 100px; height: 100px; background-color: green"></div>
diff --git a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/repaint-descandant-on-ancestor-layer-move-expected.html b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/repaint-descandant-on-ancestor-layer-move-expected.html
deleted file mode 100644
index 5cbceeb..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/repaint-descandant-on-ancestor-layer-move-expected.html
+++ /dev/null
@@ -1,28 +0,0 @@
-<!DOCTYPE html>
-<style>
-body {
-    position: absolute;
-    left: 0px;
-    top: 0px;
-    right: 0px;
-    bottom: 0px;
-}
-body > div {
-    position: absolute;
-    left: 0; top: 10px;
-}
-div > div {
-    position: relative;
-    display: inline-block;
-    left: 20px;
-    top: 20px;
-    width: 300px;
-    background-color: papayawhip;
-}
-</style>
-<body>
-<div id="container">
-    <div>
-        There should only be one copy of this text.
-    </div>
-</div>
diff --git a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/repaint-in-iframe-expected.html b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/repaint-in-iframe-expected.html
deleted file mode 100644
index 9bdbea5..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/repaint-in-iframe-expected.html
+++ /dev/null
@@ -1,4 +0,0 @@
-<!DOCTYPE html>
-<html>
-<div style="height: 400px"></div>
-<iframe srcdoc="<div style='height: 50px; width: 50px; background-color: green;'></div>"></iframe>
diff --git a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/repaint-on-style-change-expected.html b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/repaint-on-style-change-expected.html
deleted file mode 100644
index fbd4eaa..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/repaint-on-style-change-expected.html
+++ /dev/null
@@ -1,21 +0,0 @@
-<!DOCTYPE html>
-<html>
-<head>
-    <title>Test for repaint on style change</title>
-    <style>
-    div {
-        background-color: green;
-        height: 100px;
-        width: 100px;
-
-        position: absolute;
-        top: 260px;
-        left: 260px;
-    }
-    </style>
-</head>
-<body>
-    <div id='box'> </div>
-</body>
-</html>
-
diff --git a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/repaint-resized-overflow-expected.html b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/repaint-resized-overflow-expected.html
deleted file mode 100644
index 8c7724a4..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/repaint-resized-overflow-expected.html
+++ /dev/null
@@ -1,23 +0,0 @@
-<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
-        "http://www.w3.org/TR/html4/strict.dtd">
-<html lang="en">
-<body>
-<p><b>BUG ID:</b> <a href="https://bugs.webkit.org/show_bug.cgi?id=6770">Bugzilla bug 6770</a> REGRESSION: Incomplete repaint when block with clipping grows</p>
-
-<p id="success" style="background-color:palegreen; padding:3px;"><b>TEST PASS:</b>
-There should be a white square with a blue border below, and no line running through
-the middle of the square.
-</p>
-
-<p id="failure" style="background-color:#FF3300; padding:3px;"><b>TEST FAIL:</b> 
-The white square will have a blue border and a blue horizontal line running through its middle.
-</p>
-
-<div style="overflow: hidden;">
-    <div id="s" style="border: 4px solid blue; width: 100px;">
-        <div id="t" style="width: 10px; height: 100px; margin-left: 120px;"></div>
-    </div>
-</div>
-
-</body>
-</html>
diff --git a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/repaint-table-row-in-composited-document-expected.html b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/repaint-table-row-in-composited-document-expected.html
deleted file mode 100644
index 787023b..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/repaint-table-row-in-composited-document-expected.html
+++ /dev/null
@@ -1,27 +0,0 @@
-<!DOCTYPE html>
-<html>
-<head>
-<style>
-td {
-  width: 200px;
-  height: 100px;
-}
-body {
-  margin: 50px;
-}
-</style>
-</head>
-<body>
-<table>
-  <tr>
-    <td id="target" style="height: 250px">
-    </td>
-  </tr>
-  <tr>
-    <td>
-    </td>
-    <td style="border: 1px solid black; background-color: green;">
-    </td>
-  </tr>
-</table>
-</body>
diff --git a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/replaced-clipped-positioned-not-wrong-incremental-repainting-expected.html b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/replaced-clipped-positioned-not-wrong-incremental-repainting-expected.html
deleted file mode 100644
index 69741c6..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/replaced-clipped-positioned-not-wrong-incremental-repainting-expected.html
+++ /dev/null
@@ -1,29 +0,0 @@
-<!DOCTYPE html>
-<html>
-<head>
-<style>
-#shiftMe {
-    position: relative;
-    left: -20px;
-}
-
-.container {
-    overflow: hidden;
-}
-
-.imgContainer {
-    position: relative;
-    float: left;
-}
-</style>
-</head>
-<body>
-<div class="container">
-    <div id="shiftMe">
-        <div class="imgContainer">
-            <img src="resources/apple.jpg">
-        </div>
-    </div>
-</div>
-</body>
-</html>
diff --git a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/requestAnimation-translation-leave-traces-expected.txt b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/requestAnimation-translation-leave-traces-expected.txt
new file mode 100644
index 0000000..3d5fa1b2
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/requestAnimation-translation-leave-traces-expected.txt
@@ -0,0 +1,74 @@
+This test checks that changing the transform on an element triggers a correct invalidation.
+The paint invalidations below should match the transformed element's coordinates.
+Tested locations: 1200,1500
+{
+  "layers": [
+    {
+      "name": "LayoutView #document",
+      "bounds": [800, 600],
+      "backgroundColor": "#FFFFFF"
+    },
+    {
+      "name": "Scrolling Layer",
+      "bounds": [800, 585],
+      "drawsContent": false
+    },
+    {
+      "name": "Scrolling Contents Layer",
+      "bounds": [1600, 585],
+      "contentsOpaque": true,
+      "backgroundColor": "#FFFFFF",
+      "paintInvalidations": [
+        {
+          "object": "LayoutView #document",
+          "rect": [1300, 0, 300, 585],
+          "reason": "background on scrolling contents layer"
+        },
+        {
+          "object": "LayoutView #document",
+          "rect": [1000, 0, 300, 585],
+          "reason": "background on scrolling contents layer"
+        },
+        {
+          "object": "LayoutBlockFlow DIV id='box'",
+          "rect": [1500, 0, 100, 100],
+          "reason": "subtree"
+        },
+        {
+          "object": "LayoutBlockFlow DIV id='box'",
+          "rect": [1200, 0, 100, 100],
+          "reason": "subtree"
+        },
+        {
+          "object": "LayoutBlockFlow DIV id='box'",
+          "rect": [1200, 0, 100, 100],
+          "reason": "subtree"
+        },
+        {
+          "object": "LayoutBlockFlow DIV id='box'",
+          "rect": [900, 0, 100, 100],
+          "reason": "subtree"
+        }
+      ]
+    }
+  ],
+  "objectPaintInvalidations": [
+    {
+      "object": "Scrolling Contents Layer",
+      "reason": "background on scrolling contents layer"
+    },
+    {
+      "object": "LayoutBlockFlow DIV id='box'",
+      "reason": "subtree"
+    },
+    {
+      "object": "Scrolling Contents Layer",
+      "reason": "background on scrolling contents layer"
+    },
+    {
+      "object": "LayoutBlockFlow DIV id='box'",
+      "reason": "subtree"
+    }
+  ]
+}
+
diff --git a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/resize-child-within-overflow-expected.html b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/resize-child-within-overflow-expected.html
deleted file mode 100644
index 708e9ec..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/resize-child-within-overflow-expected.html
+++ /dev/null
@@ -1,23 +0,0 @@
-<!DOCTYPE html>
-<style>
-body {
-    margin: 0;
-}
-.container {
-    position: absolute;
-    height: 1000px;
-    background-color: blue;
-}
-#child {
-    width: 600px;
-}
-.overflow {
-    width: 800px;
-    height: 50px;
-}
-</style>
-<div class="container">
-    <div id="child">
-        <div class="overflow"></div>
-    </div>
-</div>
diff --git a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/resize-skewed-expected.html b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/resize-skewed-expected.html
deleted file mode 100644
index 807c9bd..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/resize-skewed-expected.html
+++ /dev/null
@@ -1,23 +0,0 @@
-<!DOCTYPE html>
-<style>
-div {
-  position: absolute;
-  transform: skew(-45deg);
-  transform-origin: left top;
-  top: 50px;
-  left: 500px;
-  height: 500px;
-}
-#skewed {
-  width: 200px;
-  background-color: green;
-}
-#indicator {
-  width: 200px;
-  background-color: red;
-}
-</style>
-Tests paint invalidation when a skewed element is resized. Passes if there is no red. 
-<div id="indicator"></div>
-<div id="skewed"></div>
-
diff --git a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/resize-with-border-clipped-expected.html b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/resize-with-border-clipped-expected.html
deleted file mode 100644
index 870920da..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/resize-with-border-clipped-expected.html
+++ /dev/null
@@ -1,25 +0,0 @@
-<!DOCTYPE html>
-<style>
-body {
-  margin: 0;
-}
-#container {
-  position: absolute;
-  top: 100px;
-  left: 100px;
-  width: 200px;
-  height: 200px;
-  overflow: hidden;
-}
-#target {
-  width: 300px;
-  height: 300px;
-  border: green 10px solid;
-  background-color: blue;
-}
-</style>
-Tests invalidation when a box with border is resized within a clipping container.
-Passes if the result paint rects don't exceed the container.
-<div id="container">
-  <div id="target"></div>
-</div>
diff --git a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/resize-with-border-expected.html b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/resize-with-border-expected.html
deleted file mode 100644
index 3616472..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/resize-with-border-expected.html
+++ /dev/null
@@ -1,20 +0,0 @@
-<!DOCTYPE html>
-<style>
-body {
-    margin: 0;
-}
-#div {
-    position: absolute;
-    top: 100px;
-    left: 100px;
-    width: 400px;
-    height: 200px;
-    border: green 10px solid;
-}
-</style>
-<div>
-Tests repaint when a box with border is resized.
-Passes if the result paint rects cover all changed part,
-the new border is correctly drawn and there is no residue of the old border.
-</div>
-<div id="div"></div>
diff --git a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/scrolled-iframe-scrollbar-change-expected.txt b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/scrolled-iframe-scrollbar-change-expected.txt
new file mode 100644
index 0000000..b4f4e4e
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/scrolled-iframe-scrollbar-change-expected.txt
@@ -0,0 +1,29 @@
+{
+  "objectPaintInvalidations": [
+    {
+      "object": "VerticalScrollbar",
+      "reason": "scroll control"
+    },
+    {
+      "object": "LayoutView #document",
+      "reason": "style change"
+    },
+    {
+      "object": "LayoutView #document",
+      "reason": "geometry"
+    },
+    {
+      "object": "LayoutBlockFlow BODY class='noScroll'",
+      "reason": "style change"
+    },
+    {
+      "object": "LayoutBlockFlow DIV id='container'",
+      "reason": "geometry"
+    },
+    {
+      "object": "LayoutBlockFlow (positioned) DIV id='overlay'",
+      "reason": "appeared"
+    }
+  ]
+}
+
diff --git a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/search-field-cancel-expected.html b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/search-field-cancel-expected.html
deleted file mode 100644
index 182dba4..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/search-field-cancel-expected.html
+++ /dev/null
@@ -1,13 +0,0 @@
-<html>
-<head>
-  <title>Cancel button redraw</title>
-  <style type="text/css">
-    #searchfield {
-    }
-  </style>
-</head>
-<body>
-  <p>Test for <a href="https://bugs.webkit.org/show_bug.cgi?id=23093">https://bugs.webkit.org/show_bug.cgi?id=23093</a>. The cancel button in a search field fails to redraw.</p>
-  <input id="searchfield" type="search" value="some text">
-</body>
-</html>
diff --git a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/select-option-background-color-expected.html b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/select-option-background-color-expected.html
deleted file mode 100644
index 5764ceb..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/select-option-background-color-expected.html
+++ /dev/null
@@ -1,12 +0,0 @@
-<head>
-<title>This is a test for regression against https://bugs.webkit.org/show_bug.cgi?id=49790</title>
-</head>
-
-<body style="margin: 0;">
-    <p>This is a test for regression against <a href="https://bugs.webkit.org/show_bug.cgi?id=49790">https://bugs.webkit.org/show_bug.cgi?id=49790</a></p>
-
-    <select multiple="multiple">
-        <option id="option" value="A" style="background-color: green">A</option>
-        <option id="option" value="B">B</option>
-    </select>
-</body>
diff --git a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/selection-change-in-iframe-with-relative-parent-expected.txt b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/selection-change-in-iframe-with-relative-parent-expected.txt
index 6e04946f0f..d2cca7c 100644
--- a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/selection-change-in-iframe-with-relative-parent-expected.txt
+++ b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/selection-change-in-iframe-with-relative-parent-expected.txt
@@ -61,14 +61,6 @@
   ],
   "objectPaintInvalidations": [
     {
-      "object": "LayoutBlockFlow HTML",
-      "reason": "selection"
-    },
-    {
-      "object": "LayoutBlockFlow BODY",
-      "reason": "selection"
-    },
-    {
       "object": "LayoutText #text",
       "reason": "selection"
     },
diff --git a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/selection-clear-after-move-expected.txt b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/selection-clear-after-move-expected.txt
deleted file mode 100644
index 175df95..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/selection-clear-after-move-expected.txt
+++ /dev/null
@@ -1,38 +0,0 @@
-{
-  "layers": [
-    {
-      "name": "LayoutView #document",
-      "bounds": [800, 600],
-      "backgroundColor": "#FFFFFF"
-    },
-    {
-      "name": "Scrolling Layer",
-      "bounds": [800, 600],
-      "drawsContent": false
-    },
-    {
-      "name": "Scrolling Contents Layer",
-      "bounds": [800, 600],
-      "contentsOpaque": true,
-      "backgroundColor": "#FFFFFF",
-      "paintInvalidations": [
-        {
-          "object": "LayoutImage IMG",
-          "rect": [100, 300, 50, 50],
-          "reason": "selection"
-        }
-      ]
-    }
-  ],
-  "objectPaintInvalidations": [
-    {
-      "object": "LayoutImage IMG",
-      "reason": "selection"
-    },
-    {
-      "object": "LayoutText #text",
-      "reason": "selection"
-    }
-  ]
-}
-
diff --git a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/selection/invalidation-rect-includes-newline-for-vertical-lr-expected.txt b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/selection/invalidation-rect-includes-newline-for-vertical-lr-expected.txt
deleted file mode 100644
index c37aa6b5d..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/selection/invalidation-rect-includes-newline-for-vertical-lr-expected.txt
+++ /dev/null
@@ -1,54 +0,0 @@
-{
-  "layers": [
-    {
-      "name": "LayoutView #document",
-      "bounds": [800, 600],
-      "backgroundColor": "#FFFFFF"
-    },
-    {
-      "name": "Scrolling Layer",
-      "bounds": [800, 600],
-      "drawsContent": false
-    },
-    {
-      "name": "Scrolling Contents Layer",
-      "bounds": [800, 600],
-      "contentsOpaque": true,
-      "backgroundColor": "#FFFFFF",
-      "paintInvalidations": [
-        {
-          "object": "LayoutText #text",
-          "rect": [7, 8, 34, 48],
-          "reason": "geometry"
-        }
-      ]
-    }
-  ],
-  "objectPaintInvalidations": [
-    {
-      "object": "LayoutBlockFlow HTML",
-      "reason": "selection"
-    },
-    {
-      "object": "LayoutBlockFlow BODY",
-      "reason": "selection"
-    },
-    {
-      "object": "LayoutBlockFlow DIV id='container'",
-      "reason": "selection"
-    },
-    {
-      "object": "LayoutText #text",
-      "reason": "geometry"
-    },
-    {
-      "object": "InlineTextBox 'xx'",
-      "reason": "geometry"
-    },
-    {
-      "object": "InlineTextBox 'y'",
-      "reason": "geometry"
-    }
-  ]
-}
-
diff --git a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/set-text-content-same-expected.html b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/set-text-content-same-expected.html
deleted file mode 100644
index 5609c088..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/set-text-content-same-expected.html
+++ /dev/null
@@ -1,3 +0,0 @@
-<!DOCTYPE html>
-<body>
-<pre id="target">PASS if does not repaint.</pre>
diff --git a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/shadow-box-resize-expected.html b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/shadow-box-resize-expected.html
deleted file mode 100644
index cdd0289..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/shadow-box-resize-expected.html
+++ /dev/null
@@ -1,37 +0,0 @@
-<!DOCTYPE html>
-<style>
-body {
-    margin: 0;
-}
-div {
-    position: absolute;
-    width: 100px;
-    height: 100px;
-    background-color: green;
-    box-shadow: 40px 20px black;
-}
-#target1 {
-    top: 100px;
-    left: 100px;
-    width: 150px;
-}
-#target2 {
-    top: 100px;
-    left: 300px;
-    width: 50px;
-}
-#target3 {
-    top: 300px;
-    left: 100px;
-    height: 150px;
-}
-#target4 {
-    top: 300px;
-    left: 300px;
-    height: 50px;
-}
-</style>
-<div id="target1"></div>
-<div id="target2"></div>
-<div id="target3"></div>
-<div id="target4"></div>
diff --git a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/shadow-box-resize-writing-mode-expected.html b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/shadow-box-resize-writing-mode-expected.html
deleted file mode 100644
index 49c32490..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/shadow-box-resize-writing-mode-expected.html
+++ /dev/null
@@ -1,38 +0,0 @@
-<!DOCTYPE html>
-<style>
-body {
-    margin: 0;
-}
-div {
-    position: absolute;
-    width: 100px;
-    height: 100px;
-    background-color: green;
-    box-shadow: 40px 20px black;
-    -webkit-writing-mode: vertical-rl;
-}
-#target1 {
-    top: 100px;
-    left: 100px;
-    width: 150px;
-}
-#target2 {
-    top: 100px;
-    left: 300px;
-    width: 50px;
-}
-#target3 {
-    top: 300px;
-    left: 100px;
-    height: 150px;
-}
-#target4 {
-    top: 300px;
-    left: 300px;
-    height: 50px;
-}
-</style>
-<div id="target1"></div>
-<div id="target2"></div>
-<div id="target3"></div>
-<div id="target4"></div>
diff --git a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/shift-relative-positioned-container-with-image-addition-expected.html b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/shift-relative-positioned-container-with-image-addition-expected.html
deleted file mode 100644
index 973434f..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/shift-relative-positioned-container-with-image-addition-expected.html
+++ /dev/null
@@ -1,26 +0,0 @@
-<!DOCTYPE html>
-<html>
-<style>
-img {
-    max-width: 100%;
-}
-.relative {
-    position: relative;
-}
-/* Not needed but helps to see the bug. */
-.paddingTop {
-    padding: 50px;
-}
-</style>
-<body>
-    <p><a href="https://code.google.com/p/chromium/issues/detail?id=353933">issue 353933</a>: Pages missing invalidations<br>
-        The test checks that creating a new renderer correctly invalidate the existing shifted content.
-        The image should be correctly invalidated below.</p>
-    <iframe id="iframe" width="728" height="90" style="display: block"></iframe>
-    <div class="relative">
-        <div class="relative paddingTop">
-            <img src="resources/ducky.png"></img>
-        </div>
-    </div>
-</body>
-</html>
diff --git a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/shift-relative-positioned-container-with-image-removal-expected.html b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/shift-relative-positioned-container-with-image-removal-expected.html
deleted file mode 100644
index be78ad97..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/shift-relative-positioned-container-with-image-removal-expected.html
+++ /dev/null
@@ -1,25 +0,0 @@
-<!DOCTYPE html>
-<html>
-<style>
-img {
-    max-width: 100%;
-}
-.relative {
-    position: relative;
-}
-/* Not needed but helps to see the bug. */
-.paddingTop {
-    padding: 50px;
-}
-</style>
-<body>
-    <p><a href="https://code.google.com/p/chromium/issues/detail?id=353933">issue 353933</a>: Pages missing invalidations<br>
-        The test checks that removing a renderer correctly invalidate the existing shifted content.
-        The image should be correctly invalidated below.</p>
-    <div class="relative">
-        <div class="relative paddingTop">
-            <img src="resources/ducky.png"></img>
-        </div>
-    </div>
-</body>
-</html>
diff --git a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/stacked-diacritics-expected.html b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/stacked-diacritics-expected.html
deleted file mode 100644
index 972980e..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/stacked-diacritics-expected.html
+++ /dev/null
@@ -1,26 +0,0 @@
-<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
-        "http://www.w3.org/TR/html4/strict.dtd">
-<html lang="en">
-<head>
-<style type="text/css">
-    div.test { width: 200px; height: 120px; border: 1px solid blue; padding: 10px; }
-</style>
-</head>
-<body>
-<p><b>BUG ID:</b> <a href="https://bugs.webkit.org/show_bug.cgi?id=6274"> Bugzilla bug 6274</a>Text repainting does not account for glyphs which draw outside the typographic bounds of the font.</p>
-
-<p id="success" style="background-color:palegreen; padding:3px;"><b>TEST PASS:</b>
-The text will entirely disappear.
-</p>
-
-<p id="failure" style="background-color:#FF3300; padding:3px;"><b>TEST FAIL:</b> 
-Most of the text will be gone, but some artifacts will be left behind at the top of the page.
-</p>
-
-<div class="test">
-    <div style="font-size: 36px;" id="stacked"></div>
-</div>
-<br>
-
-</body>
-</html>
diff --git a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/stacking-context-lost-expected.html b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/stacking-context-lost-expected.html
deleted file mode 100644
index 495a8a3..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/stacking-context-lost-expected.html
+++ /dev/null
@@ -1,9 +0,0 @@
-<!DOCTYPE html>
-<div style="position: absolute; top: 10px; left: 10px; height: 100px;">
-    There should be one green box below. A red box may be seen briefly, but the page should settle
-    on showing only the one green box. Intent is to ensure that we accurately repaint the red box
-    region when (1) the green box containing the red box ceases to be a stacking context, and (2)
-    the red box is hidden.
-</div>
-<div id="outer" style="background-color: green; height: 100px; width: 100px; position: relative; top: 270px; left: 270px;">
-</div>
diff --git a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/static-to-positioned-expected.html b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/static-to-positioned-expected.html
deleted file mode 100644
index beb6661a..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/static-to-positioned-expected.html
+++ /dev/null
@@ -1,19 +0,0 @@
-<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
-        "http://www.w3.org/TR/html4/strict.dtd">
-<html lang="en">
-<body>
-    <p>
-        Repaint test for <i><a href="https://bugs.webkit.org/show_bug.cgi?id=9334">http://bugzilla.opendarwin.org/show_bug.cgi?id=9334</a>
-        Incomplete repaint when changing block from non-positioned to positioned</i>.
-    </p>
-    <hr>
-    <div style="position: relative; height: 200px;">
-        <div id="a" style="position: relative; width: 100px; height: 100px; background: blue; top: 50px; "></div>
-    </div>
-    <div style="position: relative; height: 150px; padding-top: 50px;">
-        <div style="height: 150px;">
-            <div id="t" style="position: absolute; width: 100px; height: 100px; background: blue; top: 0;"></div>
-        </div>
-    </div>
-</body>
-</html>
diff --git a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/subpixel-offset-scaled-transform-expected.html b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/subpixel-offset-scaled-transform-expected.html
deleted file mode 100644
index f37c7eef..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/subpixel-offset-scaled-transform-expected.html
+++ /dev/null
@@ -1,6 +0,0 @@
-<!DOCTYPE html>
-<style>
-.square { width: 40px; height: 40px; background: blue; position: relative; }
-</style>
-<div class="square"></div>
-<div class="square" style="top: 10px; left: 1px"></div>
diff --git a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/subtree-layoutstate-transform-expected.html b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/subtree-layoutstate-transform-expected.html
deleted file mode 100644
index dbebe29..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/subtree-layoutstate-transform-expected.html
+++ /dev/null
@@ -1,30 +0,0 @@
-<html>
-<head>
-  <style type="text/css" media="screen">
-    .transformed {
-      height: 100px;
-      width: 100px;
-      margin: 20px;
-      transform: scale(2);
-      transform-origin: top left;
-    }
-  
-    .layoutroot {
-      height: 100px;
-      width: 100px;
-      overflow: hidden;
-      background-color: red;
-    }
-  </style>
-</head>
-<body>
-
-  <p>Tests repaint after layout of a subtree, inside a transformed element. You should see a large green square below.</p>
-  <div class="transformed">
-    <div class="layoutroot">
-      <div id="target" style="height: 100px; width: 100px; background-color: green;"></div>
-    </div>
-  </div>
-
-</body>
-</html>
diff --git a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/subtree-root-clip-2-expected.html b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/subtree-root-clip-2-expected.html
deleted file mode 100644
index 8b01300..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/subtree-root-clip-2-expected.html
+++ /dev/null
@@ -1,12 +0,0 @@
-<html>
-<body>
-<div>
-    <span style="-position: relative; top: 25px; left: 25px;">
-        <div style="float: left; height: 100px; width: 100px; overflow: hidden; background-color: red;">
-            <div id="target" style="height: 100px; width: 100px; background-color: green;">
-            </div>
-        </div>
-    </span>
-</div>
-</body>
-</html>
diff --git a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/subtree-root-clip-3-expected.html b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/subtree-root-clip-3-expected.html
deleted file mode 100644
index f1f163e6..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/subtree-root-clip-3-expected.html
+++ /dev/null
@@ -1,14 +0,0 @@
-<html>
-<body>
-<table>
-    <tr>
-        <td style="height: 200px;"></td>
-        <td>
-            <div style="height: 100px; width: 100px; overflow: hidden;">
-                <div id="target" style="height: 100px; width: 100px; background-color: green;"></div>
-            </div>
-        </td>
-    </tr>
-</table>
-</body>
-</html>
diff --git a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/subtree-root-clip-expected.html b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/subtree-root-clip-expected.html
deleted file mode 100644
index 09545e84..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/subtree-root-clip-expected.html
+++ /dev/null
@@ -1,8 +0,0 @@
-<!DOCTYPE HTML>
-<html>
-<body>
-<div style="float: left; overflow: hidden; width: 100px; height: 100px; background-color: green;">
-    <div id="inner" style="width: 0; height: 100px;"></div>
-</div>
-</body>
-</html>
diff --git a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/svg/add-background-property-on-root-expected.html b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/svg/add-background-property-on-root-expected.html
deleted file mode 100644
index dfecc69..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/svg/add-background-property-on-root-expected.html
+++ /dev/null
@@ -1,4 +0,0 @@
-<!DOCTYPE html>
-<div style="width: 100px; height: 100px">
-  <svg width="100" height="100" style="background: green"></svg>
-</div>
diff --git a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/svg/add-border-property-on-root-expected.html b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/svg/add-border-property-on-root-expected.html
deleted file mode 100644
index 501dcf2..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/svg/add-border-property-on-root-expected.html
+++ /dev/null
@@ -1,3 +0,0 @@
-<!DOCTYPE html>
-<svg width="100" height="100" style="position: absolute; border: 10px solid green">
-</svg>
diff --git a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/svg/add-outline-property-on-root-expected.html b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/svg/add-outline-property-on-root-expected.html
deleted file mode 100644
index 17b74bf..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/svg/add-outline-property-on-root-expected.html
+++ /dev/null
@@ -1,5 +0,0 @@
-<!DOCTYPE html>
-<svg style="outline: 10px solid green" width="100" height="100">
-  <rect width="100" height="100" fill="blue"/>
-</svg>
-
diff --git a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/svg/change-background-color-expected.html b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/svg/change-background-color-expected.html
deleted file mode 100644
index 0c174b15..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/svg/change-background-color-expected.html
+++ /dev/null
@@ -1,4 +0,0 @@
-<!DOCTYPE HTML>
-<svg width="200px" height="100px" viewBox="0 0 100 100"
-     style="background-color: green">
-</svg>
diff --git a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/svg/modify-inserted-listitem-expected.html b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/svg/modify-inserted-listitem-expected.html
deleted file mode 100644
index efe084c..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/svg/modify-inserted-listitem-expected.html
+++ /dev/null
@@ -1,5 +0,0 @@
-<!DOCTYPE html>
-<svg width="100" height="100">
-  <rect id="ref" x="20" y="30" width="10" height="10" fill="red"></rect>
-  <rect id="move" x="10" y="10" width="10" height="10" fill="green" transform="matrix(1, 0, 0, 1, 10, 20)"></rect>
-</svg>
diff --git a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/svg/modify-transferred-listitem-different-attr-expected.html b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/svg/modify-transferred-listitem-different-attr-expected.html
deleted file mode 100644
index 8b9b514..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/svg/modify-transferred-listitem-different-attr-expected.html
+++ /dev/null
@@ -1,14 +0,0 @@
-<!DOCTYPE html>
-<style>
-  @font-face {
-    font-family: 'myahem';
-    src: url(../../../resources/Ahem.ttf);
-  }
-  text {
-    font-family: 'myahem';
-  }
-</style>
-<svg width="100" height="100">
-  <text id="target" x="15 65" y="10 20" fill="green">A B C</text>
-  <text id="source" x="50" y="50" fill="blue">X Y Z</text>
-</svg>
diff --git a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/svg/modify-transferred-listitem-expected.html b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/svg/modify-transferred-listitem-expected.html
deleted file mode 100644
index 4ee4ec6a..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/svg/modify-transferred-listitem-expected.html
+++ /dev/null
@@ -1,6 +0,0 @@
-<!DOCTYPE html>
-<svg width="100" height="100">
-  <polygon id="ref" points="20,10 10,30 30,30 40,10" fill="red"></polygon>
-  <polygon id="target" points="20,10 10,30 30,30 40,10" fill="green"></polygon>
-  <polygon id="source" fill="blue"></polygon>
-</svg>
diff --git a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/svg/outline-offset-shape-expected.html b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/svg/outline-offset-shape-expected.html
deleted file mode 100644
index 82e12b7..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/svg/outline-offset-shape-expected.html
+++ /dev/null
@@ -1,10 +0,0 @@
-<!DOCTYPE html>
-<style>
-rect {
-  outline: 5px solid blue;
-  outline-offset: 10px;
-}
-</style>
-<svg width="600">
-  <rect x="25" y="25" width="100" height="100" fill="green"/>
-</svg>
diff --git a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/svg/outline-offset-text-expected.html b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/svg/outline-offset-text-expected.html
deleted file mode 100644
index 3acff68d..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/svg/outline-offset-text-expected.html
+++ /dev/null
@@ -1,13 +0,0 @@
-<!DOCTYPE html>
-<style>
-text {
-  font-size: 75px;
-  font-family: sans-serif;
-  text-anchor: end;
-  outline: 5px solid blue;
-  outline-offset: 10px;
-}
-</style>
-<svg width="600">
-  <text x="200" y="100" width="100" height="100" fill="green">Foo</text>
-</svg>
diff --git a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/svg/overflow-repaint-expected.html b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/svg/overflow-repaint-expected.html
deleted file mode 100644
index abd2fcf..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/svg/overflow-repaint-expected.html
+++ /dev/null
@@ -1,17 +0,0 @@
-<!doctype html>
-<head>
-	<style>
-		div {
-			height:100px; width:100px;
-		}
-		div + div { background: green; }
-	</style>
-</head>
-<body>
-	<div>
-		<svg id="svg" height="100" width="100" viewbox="0 0 100 100">
-			<rect y="100" width="100" height="100" fill="red"/>
-		</svg>
-	</div>
-	<div></div>
-</body>
diff --git a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/svg/path-pathlength-change-expected.html b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/svg/path-pathlength-change-expected.html
deleted file mode 100644
index 35aeecbc..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/svg/path-pathlength-change-expected.html
+++ /dev/null
@@ -1,5 +0,0 @@
-<!DOCTYPE html>
-<svg width="400" height="400">
-  <path pathLength="200" d="M100,100h100v100h-100z" fill="none"
-        stroke="blue" stroke-width="20" stroke-dasharray="25"/>
-</svg>
diff --git a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/svg/relative-sized-document-scrollbars-expected.txt b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/svg/relative-sized-document-scrollbars-expected.txt
index b915a8b..ab0fcfe5 100644
--- a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/svg/relative-sized-document-scrollbars-expected.txt
+++ b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/svg/relative-sized-document-scrollbars-expected.txt
@@ -3,7 +3,14 @@
     {
       "name": "LayoutView #document",
       "bounds": [800, 600],
-      "backgroundColor": "#FFFFFF"
+      "backgroundColor": "#FFFFFF",
+      "paintInvalidations": [
+        {
+          "object": "LayoutView #document",
+          "rect": [0, 0, 800, 600],
+          "reason": "style change"
+        }
+      ]
     },
     {
       "name": "Scrolling Layer",
@@ -31,6 +38,10 @@
   ],
   "objectPaintInvalidations": [
     {
+      "object": "LayoutView #document",
+      "reason": "style change"
+    },
+    {
       "object": "LayoutSVGRoot svg",
       "reason": "style change"
     },
diff --git a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/svg/remove-background-property-on-root-expected.html b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/svg/remove-background-property-on-root-expected.html
deleted file mode 100644
index d7c24de..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/svg/remove-background-property-on-root-expected.html
+++ /dev/null
@@ -1,4 +0,0 @@
-<!DOCTYPE html>
-<div style="width: 100px; height: 100px; background: green">
-  <svg width="100" height="100"></svg>
-</div>
diff --git a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/svg/remove-border-property-on-root-expected.html b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/svg/remove-border-property-on-root-expected.html
deleted file mode 100644
index a5cb706..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/svg/remove-border-property-on-root-expected.html
+++ /dev/null
@@ -1,3 +0,0 @@
-<!DOCTYPE html>
-<svg style="position: absolute" width="100" height="100">
-</svg>
diff --git a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/svg/remove-outline-property-on-root-expected.html b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/svg/remove-outline-property-on-root-expected.html
deleted file mode 100644
index 9f4b5b46..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/svg/remove-outline-property-on-root-expected.html
+++ /dev/null
@@ -1,4 +0,0 @@
-<!DOCTYPE html>
-<svg width="100" height="100">
-  <rect width="100" height="100" fill="green"/>
-</svg>
diff --git a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/svg/repaint-non-scaling-stroke-text-decoration-expected.html b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/svg/repaint-non-scaling-stroke-text-decoration-expected.html
deleted file mode 100644
index 44f9eb1..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/svg/repaint-non-scaling-stroke-text-decoration-expected.html
+++ /dev/null
@@ -1,10 +0,0 @@
-<!DOCTYPE HTML>
-<html>
-<body>
-<svg>
-    <g transform="scale(0.5 0.5)">
-       <text id="t" x="10" y="50" stroke="blue" stroke-width="8" fill="none" font-size="36" vector-effect="non-scaling-stroke" text-decoration="underline">Hello</text>
-    </g>
-</svg>
-</body>
-</html>
diff --git a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/svg/repaint-non-scaling-stroke-text-expected.html b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/svg/repaint-non-scaling-stroke-text-expected.html
deleted file mode 100644
index d6b06e57..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/svg/repaint-non-scaling-stroke-text-expected.html
+++ /dev/null
@@ -1,10 +0,0 @@
-<!DOCTYPE HTML>
-<html>
-<body>
-<svg>
-    <g transform="scale(0.5 0.5)">
-       <text id="t" x="10" y="50" stroke="blue" stroke-width="8" fill="none" font-size="36" vector-effect="non-scaling-stroke">Hello</text>
-    </g>
-</svg>
-</body>
-</html>
diff --git a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/svg/resize-svg-invalidate-children-2-expected.html b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/svg/resize-svg-invalidate-children-2-expected.html
deleted file mode 100644
index b220a51..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/svg/resize-svg-invalidate-children-2-expected.html
+++ /dev/null
@@ -1,2 +0,0 @@
-<!DOCTYPE html>
-<div style="width: 500px; height: 400px; margin-left: 50px; background: green"></div>
diff --git a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/svg/resize-svg-invalidate-children-expected.html b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/svg/resize-svg-invalidate-children-expected.html
deleted file mode 100644
index c358cb9d..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/svg/resize-svg-invalidate-children-expected.html
+++ /dev/null
@@ -1,2 +0,0 @@
-<!DOCTYPE html>
-<div style="margin-left: 50px; margin-top: 58px; width: 100px; height: 100px; background: black"></div>
diff --git a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/svg/rounded-rect-height-change-expected.html b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/svg/rounded-rect-height-change-expected.html
deleted file mode 100644
index dcb63653..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/svg/rounded-rect-height-change-expected.html
+++ /dev/null
@@ -1,4 +0,0 @@
-<!DOCTYPE html>
-<svg width="200" height="200">
-  <rect width="100" height="100" fill="blue" rx="3"/>
-</svg>
diff --git a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/svg/shape-transform-change-expected.html b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/svg/shape-transform-change-expected.html
deleted file mode 100644
index 72b322e..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/svg/shape-transform-change-expected.html
+++ /dev/null
@@ -1,7 +0,0 @@
-<!DOCTYPE html>
-<svg width="200" height="200">
-  <rect width="200" height="200" fill="red"/>
-  <rect width="100" height="100" fill="green" transform="scale(2)"/>
-</svg>
-<p>Test if applying a transform to a &lt;rect> properly repaints the &lt;rect>.</p>
-<p>Pass if there's a green 200x200 (px) rectangle below, and no red visible.</p>
diff --git a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/svg/shape-with-nested-outline-expected.html b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/svg/shape-with-nested-outline-expected.html
deleted file mode 100644
index 2698d81..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/svg/shape-with-nested-outline-expected.html
+++ /dev/null
@@ -1,16 +0,0 @@
-<!DOCTYPE html>
-<style>
-g {
-  outline: 50px solid lightblue;
-}
-rect#r {
-  outline: 50px solid blue;
-}
-</style>
-<svg width="500" height="500">
-  <g transform="translate(50 50)">
-    <rect width="400" height="100"/>
-    <rect y="300" width="400" height="100"/>
-    <rect id="r" x="100" y="100" width="200" height="200" fill="green"/>
-  </g>
-</svg>
diff --git a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/svg/svg-image-par-resize-expected.html b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/svg/svg-image-par-resize-expected.html
deleted file mode 100644
index f586f935..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/svg/svg-image-par-resize-expected.html
+++ /dev/null
@@ -1,10 +0,0 @@
-<!DOCTYPE html>
-<script>
-window.testIsAsync = true;
-</script>
-<body>
-<svg width="300" height="200">
-  <image width="100" height="200" preserveAspectRatio="none"
-         xlink:href="data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' width='50' height='50'><rect width='100%' height='100%' fill='green'/></svg>"></image>
-</svg>
-</body>
diff --git a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/svg/text-pattern-update-2-expected.html b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/svg/text-pattern-update-2-expected.html
deleted file mode 100644
index 97262091..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/svg/text-pattern-update-2-expected.html
+++ /dev/null
@@ -1,9 +0,0 @@
-<!DOCTYPE html>
-<script src=../../../resources/ahem.js></script>
-<svg>
-  <pattern id="pat" patternUnits="userSpaceOnUse" width="200" height="200" y="100">
-    <rect width="200" height="100" fill="red"/>
-    <rect y="100" width="200" height="100" fill="green"/>
-  </pattern>
-  <text y="80" fill="url(#pat)" font-size="100" font-family="Ahem">X<tspan fill="green">Y</tspan>Z</text>
-</svg>
diff --git a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/svg/text-pattern-update-expected.html b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/svg/text-pattern-update-expected.html
deleted file mode 100644
index d17386f..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/svg/text-pattern-update-expected.html
+++ /dev/null
@@ -1,9 +0,0 @@
-<!DOCTYPE html>
-<script src=../../../resources/ahem.js></script>
-<svg>
-  <pattern id="pat" y="100" patternUnits="userSpaceOnUse" width="200" height="200">
-    <rect width="200" height="100" fill="red"/>
-    <rect y="100" width="200" height="100" fill="green"/>
-  </pattern>
-  <text y="80" fill="url(#pat)" font-size="100" font-family="Ahem">X</text>
-</svg>
diff --git a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/svg/transform-changed-state-expected.html b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/svg/transform-changed-state-expected.html
deleted file mode 100644
index e3a254e..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/svg/transform-changed-state-expected.html
+++ /dev/null
@@ -1,6 +0,0 @@
-<!DOCTYPE html>
-<svg width="400" height="400">
-  <g transform="scale(2)">
-    <rect x="50" y="50" width="50" height="50" fill="green"/>
-  </g>
-</svg>
diff --git a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/svg/transform-focus-ring-repaint-expected.html b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/svg/transform-focus-ring-repaint-expected.html
deleted file mode 100644
index 1057d64..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/svg/transform-focus-ring-repaint-expected.html
+++ /dev/null
@@ -1,9 +0,0 @@
-<!DOCTYPE html>
-<div style="height: 50px">
-Result repaint rects should cover the whole focus ring.
-</div>
-<div id="target" style="position: absolute; backface-visibility: hidden; width: 200px; height: 200px; background-color: yellow; outline: red auto thin">
-    <div style="transform: rotate(90deg); position: absolute; top: 100px; left: 100px; background-color: blue; width: 300px; height: 300px">
-        <div style="position: absolute; top: 100px; left: 40px; background-color: green; width: 400px; height: 100px"></div>
-    </div>
-</div>
diff --git a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/svg/transform-foreign-object-expected.html b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/svg/transform-foreign-object-expected.html
deleted file mode 100644
index e0cda58d..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/svg/transform-foreign-object-expected.html
+++ /dev/null
@@ -1,8 +0,0 @@
-<!DOCTYPE html>
-<body>
-<svg version="1.1" xmlns="http://www.w3.org/2000/svg">
-  <foreignObject width="100" height="100" style="transform: translate(100px, 0px)">
-    <div xmlns="http://www.w3.org/1999/xhtml" style="width: 100px; height: 100px; background-color: green;"></div>
-  </foreignObject>
-</svg>
-</body>
diff --git a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/svg/transform-text-element-expected.html b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/svg/transform-text-element-expected.html
deleted file mode 100644
index 2a83a27..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/svg/transform-text-element-expected.html
+++ /dev/null
@@ -1,7 +0,0 @@
-<!DOCTYPE html>
-<script src=../../../resources/ahem.js></script>
-<body>
-<svg width="400" height="400" version="1.1" xmlns="http://www.w3.org/2000/svg">
-  <text style="transform: translate(0px, 50px)" y="80" fill="green" font-size="100" font-family="Ahem">Test</text>
-</svg>
-</body>
diff --git a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/svg/tspan-pattern-update-expected.html b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/svg/tspan-pattern-update-expected.html
deleted file mode 100644
index 6263f67..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/svg/tspan-pattern-update-expected.html
+++ /dev/null
@@ -1,9 +0,0 @@
-<!DOCTYPE html>
-<script src=../../../resources/ahem.js></script>
-<svg>
-  <pattern id="pat" patternUnits="userSpaceOnUse" width="200" height="200" y="100">
-    <rect width="200" height="100" fill="red"/>
-    <rect y="100" width="200" height="100" fill="green"/>
-  </pattern>
-  <text y="80" fill="green" font-size="100" font-family="Ahem">X<tspan fill="url(#pat)">Y</tspan>Z</text>
-</svg>
diff --git a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/svg/use-detach-expected.txt b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/svg/use-detach-expected.txt
index 7362042b..9894423c 100644
--- a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/svg/use-detach-expected.txt
+++ b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/svg/use-detach-expected.txt
@@ -18,62 +18,62 @@
       "paintInvalidations": [
         {
           "object": "LayoutSVGContainer g id='use'",
-          "rect": [210, 58, 44, 64],
+          "rect": [210, 57, 44, 65],
           "reason": "appeared"
         },
         {
           "object": "LayoutSVGContainer g id='use'",
-          "rect": [210, 58, 44, 64],
+          "rect": [210, 57, 44, 65],
           "reason": "appeared"
         },
         {
           "object": "LayoutSVGContainer g id='use'",
-          "rect": [210, 58, 44, 64],
+          "rect": [210, 57, 44, 65],
           "reason": "disappeared"
         },
         {
           "object": "LayoutSVGContainer use",
-          "rect": [210, 58, 44, 38],
+          "rect": [210, 57, 44, 39],
           "reason": "appeared"
         },
         {
           "object": "LayoutSVGContainer use",
-          "rect": [210, 58, 44, 38],
+          "rect": [210, 57, 44, 39],
           "reason": "appeared"
         },
         {
           "object": "LayoutSVGContainer use",
-          "rect": [210, 58, 44, 38],
+          "rect": [210, 57, 44, 39],
           "reason": "disappeared"
         },
         {
           "object": "LayoutSVGInlineText #text",
-          "rect": [210, 58, 44, 38],
+          "rect": [210, 57, 44, 39],
           "reason": "appeared"
         },
         {
           "object": "LayoutSVGInlineText #text",
-          "rect": [210, 58, 44, 38],
+          "rect": [210, 57, 44, 39],
           "reason": "appeared"
         },
         {
           "object": "LayoutSVGInlineText #text",
-          "rect": [210, 58, 44, 38],
+          "rect": [210, 57, 44, 39],
           "reason": "disappeared"
         },
         {
           "object": "LayoutSVGText text id='use_text'",
-          "rect": [210, 58, 44, 38],
+          "rect": [210, 57, 44, 39],
           "reason": "appeared"
         },
         {
           "object": "LayoutSVGText text id='use_text'",
-          "rect": [210, 58, 44, 38],
+          "rect": [210, 57, 44, 39],
           "reason": "appeared"
         },
         {
           "object": "LayoutSVGText text id='use_text'",
-          "rect": [210, 58, 44, 38],
+          "rect": [210, 57, 44, 39],
           "reason": "disappeared"
         },
         {
diff --git a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/table-cell-collapsed-border-expected.html b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/table-cell-collapsed-border-expected.html
deleted file mode 100644
index a3d36a09f2..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/table-cell-collapsed-border-expected.html
+++ /dev/null
@@ -1,40 +0,0 @@
-<html>
-<head>
-    <style>
-        table { border-collapse: collapse; }
-        td { background: silver; width: 100px; height: 100px; }
-    </style>
-</head>
-<body>
-    <p>
-        Repaint test for <i><a href="http://bugs.webkit.org/show_bug.cgi?id=11359">http://bugs.webkit.org/show_bug.cgi?id=11359</a>
-        Incomplete repaint of table cell's collapsed border when changing only the cell</i>.
-    </p>
-    <table>
-        <tr>
-            <td></td>
-            <td style="border-bottom: 4px solid white; border-top: 10px solid white;"></td>
-            <td id="t1" style="border-left: 10px solid; border-right: 10px solid; border-color: green"></td>
-            <td style="border-bottom: 6px solid white; border-top: 10px solid white;"></td>
-        </tr>
-        <tr>
-            <td style="border-left: 10px solid white; border-right: 4px solid white;"></td>
-            <td></td>
-            <td></td>
-            <td></td>
-        </tr>
-        <tr>
-            <td id="t2" style="border-top: 10px solid; border-bottom: 10px solid; border-color: green"></td>
-            <td></td>
-            <td id="t3" style="border: 10px solid green;"></td>
-            <td></td>
-        </tr>
-        <tr>
-            <td style="border-left: 10px solid white; border-right: 6px solid white;"></td>
-            <td></td>
-            <td></td>
-            <td></td>
-        </tr>
-    </table>
-</body>
-</html>
diff --git a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/table-cell-move-expected.html b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/table-cell-move-expected.html
deleted file mode 100644
index 5c7dc07..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/table-cell-move-expected.html
+++ /dev/null
@@ -1,33 +0,0 @@
-<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
-        "http://www.w3.org/TR/html4/strict.dtd">
-<html>
-<body>
-<p><b>BUG ID:</b> <a href="https://bugs.webkit.org/show_bug.cgi?id=8449">Bugzilla bug 8449</a>
-REGRESSION: Incomplete repaint of table cell that moved
-<p id="success" style="background-color:palegreen; padding:3px;"><b>TEST PASS:</b>
-There should be only a green square below the line, and no red.
-</p>
-
-<p id="failure" style="background-color:#FF3300; padding:3px;"><b>TEST FAIL:</b> 
-There will be a red square and a green rectangle.
-</p>
-<hr>
-<table cellspacing="0" cellpadding="0">
-    <tr>
-        <td></td>
-        <td style="height: 60px;" id="t"></td>
-    </tr>
-    <tr>
-        <td style="width: 60px;">
-            <div style="background: green; height: 60px;"></div>
-        </td>
-        <td style="height: 180px;"></td>
-    </tr>
-    <tr>
-        <td style="background: red;"></td>
-        <td style="height: 0;" id="s"></td>
-    </tr>
-</table>
-
-</body>
-</html>
diff --git a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/table-cell-overflow-expected.html b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/table-cell-overflow-expected.html
deleted file mode 100644
index 84154b6c..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/table-cell-overflow-expected.html
+++ /dev/null
@@ -1,14 +0,0 @@
-<body>
-<table cellpadding=1 cellspacing=0>
-    <tr>
-        <td>
-            <div style="width: 100px;">
-                <div style="width: 100px; height: 100px; background-color: blue; margin-left: 50px;"></div>
-            </div>
-        </td>
-        <td>
-            <div style="width: 100px; height: 100px;" id="target"></div>
-        </td>
-    </tr>
-</table>
-</body>
diff --git a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/table-col-background-expected.html b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/table-col-background-expected.html
deleted file mode 100644
index 2f521ae..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/table-col-background-expected.html
+++ /dev/null
@@ -1,15 +0,0 @@
-<html>
-<head>
-    <title>Test for http://bugs.webkit.org/show_bug.cgi?id=5821</title>
-</head>
-<body>
-    <div style="height:100px"></div>
-    <table>
-        <col id="col" style="background-color: green;">
-        <tr>
-            <td style="width: 100px; height: 100px;">
-            </td>
-        </tr>
-    </table>
-</body>
-</html>
diff --git a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/table-col-background-offset-expected.html b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/table-col-background-offset-expected.html
deleted file mode 100644
index 0d8590d..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/table-col-background-offset-expected.html
+++ /dev/null
@@ -1,19 +0,0 @@
-<html>
-<head>
-    <title>Tests col background with offset</title>
-</head>
-<body>
-    <style>
-        td { width: 100px; height: 100px; }
-    </style>
-    <div style="height:100px"></div>
-    <table>
-        <col/>
-        <col id="col" style="background-color: green;">
-        <tr>
-            <td></td>
-            <td></td>
-        </tr>
-    </table>
-</body>
-</html>
diff --git a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/table-collapsed-border-expected.html b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/table-collapsed-border-expected.html
deleted file mode 100644
index 6a83c82..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/table-collapsed-border-expected.html
+++ /dev/null
@@ -1,87 +0,0 @@
-<head>
-    <style type="text/css">
-        table {
-            border-collapse: collapse;
-            border: 8px solid;
-            margin: 10px 0 10px 0;
-        }
-    </style>
-</head>
-<body>
-    <table id="t" style="border-color: green">
-        <tr>
-            <td>
-            </td>
-            <td>Lorem
-            </td>
-        </tr>
-        <tr>
-            <td>
-            </td>
-            <td>ipsum dolor
-            </td>
-        </tr>
-        <tr>
-            <td>
-            </td>
-            <td>sit amet
-            </td>
-        </tr>
-    </table>
-    <table>
-        <tr>
-            <td>
-            </td>
-            <td>Lorem
-            </td>
-        </tr>
-        <tr id="r">
-            <td>&nbsp;
-            </td>
-        </tr>
-        <tr>
-            <td>
-            </td>
-            <td>sit amet
-            </td>
-        </tr>
-    </table>
-    <table>
-        <tr>
-            <td>
-            </td>
-            <td>Lorem ipsum
-            </td>
-        </tr>
-        <tr id="r2">
-            <td>&nbsp;
-            </td>
-        </tr>
-        <tr>
-            <td>
-            </td>
-            <td>sit amet
-            </td>
-        </tr>
-    </table>
-    <table>
-        <tr>
-            <td>
-            </td>
-            <td>Lorem
-            </td>
-        </tr>
-        <tr>
-            <td>&nbsp;
-            </td>
-            <td id="d3">ipsum dolor
-            </td>
-        </tr>
-        <tr>
-            <td>
-            </td>
-            <td>sit amet
-            </td>
-        </tr>
-    </table>
-</body>
diff --git a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/table-extra-bottom-grow-expected.html b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/table-extra-bottom-grow-expected.html
deleted file mode 100644
index 7ab0743..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/table-extra-bottom-grow-expected.html
+++ /dev/null
@@ -1,26 +0,0 @@
-<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
-        "http://www.w3.org/TR/html4/strict.dtd">
-<html lang="en">
-<body>
-<p><b>BUG ID:</b> <a href="https://bugs.webkit.org/show_bug.cgi?id=6769">Bugzilla bug 6769</a> REGRESSION: Incomplete repaint when a cell's extra bottom margin grows</p>
-
-<p id="success" style="background-color:palegreen; padding:3px;"><b>TEST PASS:</b>
-There should be only a green square below, and no red.
-</p>
-
-<p id="failure" style="background-color:#FF3300; padding:3px;"><b>TEST FAIL:</b> 
-The lower-right quarter of the square will be red.
-</p>
-
-<table style="background: green;" cellspacing="0" cellpadding="0">
-    <tr>
-        <td style="height: 100px; width: 50px;" rowspan="2">
-        </td>
-        <td style="width: 50px; vertical-align: top; background: green; height: 100px;" id="t">
-        </td>
-    </tr>
-</table>
-
-</body>
-</html>
-
diff --git a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/table-outer-border-expected.html b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/table-outer-border-expected.html
deleted file mode 100644
index f57c6d8a..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/table-outer-border-expected.html
+++ /dev/null
@@ -1,30 +0,0 @@
-<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
-<html>
-<head>
-    <title>Test for http://bugs.webkit.org/show_bug.cgi?id=12817</title>
-    <style type="text/css" media="all">
-        table {
-            border-collapse: collapse;
-        }
-        
-        table td {
-            border: 15px solid green;
-            background-color: green;
-            height: 50px;
-            width: 100px;
-        }
-    </style>
-</head>
-<body>
-    <div id="container" style="width: 500px;">
-        <table id="table">
-            <tr>
-                <td></td>
-            </tr>
-            <tr>
-                <td></td>
-            </tr>
-        </table>
-    </div>
-</body>
-</html>
diff --git a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/table-row-bg-change-expected.html b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/table-row-bg-change-expected.html
deleted file mode 100644
index 7a4dd6f..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/table-row-bg-change-expected.html
+++ /dev/null
@@ -1,30 +0,0 @@
-<html>
-<head>
-    <title>Test for crbug.com/357291</title>
-    <style>
-      table {
-        height: 200px;
-        width: 200px;
-      }
-      #first {
-        background-color: green;
-      }
-    </style>
-
-</head>
-<body>
-    <table>
-        <tr id="first">
-            <td>A</td>
-            <td>A</td>
-            <td>A</td>
-        </tr>
-        <tr>
-            <td>A</td>
-            <td>A</td>
-            <td>A</td>
-        </tr>
-    </table>
-</body>
-</html>
-
diff --git a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/table-row-expected.html b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/table-row-expected.html
deleted file mode 100644
index 66c9dab..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/table-row-expected.html
+++ /dev/null
@@ -1,27 +0,0 @@
-<html>
-<head>
-    <title>Test for http://bugs.webkit.org/show_bug.cgi?id=14056</title>
-    <style>
-        tr {
-            background-color:green;
-            min-height: 500px; 
-        }
-
-        td {
-            width: 100px;
-            height: 100px;
-        }
-
-        .green {
-        }
-    </style>
-</head>
-<body>
-    <table>
-        <tr id="target">
-            <td>
-            </td>
-        </tr>
-    </table>
-</body>
-</html>
diff --git a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/table-section-overflow-expected.html b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/table-section-overflow-expected.html
deleted file mode 100644
index 38d5cbf..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/table-section-overflow-expected.html
+++ /dev/null
@@ -1,17 +0,0 @@
-<html>
-<head>
-    <title>Test for http://bugs.webkit.org/show_bug.cgi?id=12079</title>
-</head>
-<body>
-    <div id="spacer" style="width: 0; height: 50px"></div>
-    <table cellpadding="0" cellspacing="0" style="margin-left: 50px;">
-        <tr>
-            <td>
-                <div style="width: 50px;">
-                    <div style="background-color: green; width: 100px; height: 100px; margin-left: -25px;"></div>
-                </div>
-            </td>
-        </tr>
-    </table>
-</body>
-</html>
diff --git a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/table-section-repaint-expected.html b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/table-section-repaint-expected.html
deleted file mode 100644
index 69dcab94..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/table-section-repaint-expected.html
+++ /dev/null
@@ -1,73 +0,0 @@
-<html>
-<head>
-    <title>Test for http://bugs.webkit.org/show_bug.cgi?id=12079</title>
-    <style type="text/css">
-        div.playground { position: relative; width: 90px; height: 90px; }
-        .red { background-color: yellow; }
-        .blue { background-color: blue; }
-        .green { background-color: green; }
-        .zero { height: 0; width: 60px; }
-        .half { height: 30px; width: 60px; }
-        .full { height: 60px; width: 60px; }
-    </style>
-</head>
-<body>
-    <div class="playground">
-        <table cellpadding="0" cellspacing="0">
-            <caption id="caption1" class="blue zero"></caption>
-            <tbody>
-                <tr>
-                    <td class="red half"></td>
-                </tr>
-                <tr>
-                    <td class="green half"></td>
-                </tr>
-            </tbody>
-        </table>
-    </div>
-
-    <div class="playground">
-        <table cellpadding="0" cellspacing="0">
-            <tbody>
-                <tr>
-                    <td><div id="top" class="blue zero"></div></td>
-                </tr>
-            </tbody>
-            <tbody>
-                <tr>
-                    <td class="red half"></td>
-                </tr>
-                <tr>
-                    <td class="green half"></td>
-                </tr>
-            </tbody>
-        </table>
-    </div>
-
-    <div class="playground">
-        <table cellpadding="0" cellspacing="0">
-            <caption id="caption2" class="half"></caption>
-            <tbody>
-                <tr>
-                    <td class="green half"></td>
-                </tr>
-                <tr>
-                    <td class="red half"></td>
-                </tr>
-            </tbody>
-        </table>
-    </div>
-
-    <div class="playground" style="margin-top: 30px;">
-        <table cellpaddin="0" cellspacing="0" style="width: 60px; border-collapse: collapse; border: 8px solid green;">
-            <caption style="width: 10px; margin: auto;">
-                <div id="innerDiv" style="height: 15px"></div>
-            </caption>
-            <tbody>
-                <tr><td class="half"></td></tr>
-                <tr><td class="half" style="border-top: solid yellow 8px;"></td></tr>
-            </tbody>
-        </table>
-    </div>
-</body>
-</html>
diff --git a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/table-shrink-row-repaint-expected.html b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/table-shrink-row-repaint-expected.html
deleted file mode 100644
index 35e483b9..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/table-shrink-row-repaint-expected.html
+++ /dev/null
@@ -1,59 +0,0 @@
-<!DOCTYPE html>
-<html>
-<head>
-<style>
-td {
-    height: 50px;
-    border: 5px solid grey;
-}
-</style>
-</head>
-<body>
-<p>This test checks that changing the size of the middle row triggers an invalidation for the following rows.</p>
-<table border="0" cellpadding="0" cellspacing="0" width="100%">
-<tr>
-    <td>1</td>
-</tr>
-<tr>
-    <td id="resizeMe" style="height: 200px; height: 0"></td>
-</tr>
-<tr>
-    <td>2</td>
-</tr>
-<tr>
-    <td>3</td>
-</tr>
-<tr>
-    <td>4</td>
-</tr>
-<tr>
-    <td>5</td>
-</tr>
-<tr>
-    <td>6</td>
-</tr>
-<tr>
-    <td>7</td>
-</tr>
-<tr>
-    <td>8</td>
-</tr>
-<tr>
-    <td>9</td>
-</tr>
-<tr>
-    <td>10</td>
-</tr>
-<tr>
-    <td>11</td>
-</tr>
-<tr>
-    <td>12</td>
-</tr>
-<tr>
-    <td>13</td>
-</tr>
-</table>
-
-</body>
-</html>
diff --git a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/table-two-pass-layout-overpaint-expected.html b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/table-two-pass-layout-overpaint-expected.html
deleted file mode 100644
index 6c8da19..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/table-two-pass-layout-overpaint-expected.html
+++ /dev/null
@@ -1,24 +0,0 @@
-<html>
-<head>
-    <style>
-        table { background-color: lightblue; height: 100px; }
-        td { width: 100px; height: 50px; }
-        div#target { height: 25px; width: 50px; background-color: lightgreen; }
-    </style>
-</head>
-<body>
-<table>
-    <tr>
-        <td>
-            <div id="target"></div>
-            <div id="dummy"></div>
-        </td>
-    </tr>
-</table>
-</body>
-</html>
-<!-- crbug.com/690087: We do this to force a two-pass layout so that we get the same height on the table as the reference. -->
-<script>
-  document.body.offsetTop;
-  document.getElementById("dummy").style.display = "none";
-</script>
diff --git a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/table-with-padding-row-invalidation-expected.html b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/table-with-padding-row-invalidation-expected.html
deleted file mode 100644
index 3c380c1..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/table-with-padding-row-invalidation-expected.html
+++ /dev/null
@@ -1,29 +0,0 @@
-<!DOCTYPE html>
-<style>
-body {
-    margin: 0;
-}
-
-table {
-    border-collapse: collapse;
-    padding: 4px;
-}
-
-tr {
-    background: green;
-}
-
-td {
-    width: 260px;
-    height: 50px;
-    /* Disable the cell padding for output simplicity. */
-    padding: 0;
-}
-</style>
-<!--
-    This test checks that we correctly invalidate a row on a table with padding.
-    There should be no red below.
--->
-<table>
-    <td></td>
-</table>
diff --git a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/table/cached-69296-expected.html b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/table/cached-69296-expected.html
deleted file mode 100644
index a976d89..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/table/cached-69296-expected.html
+++ /dev/null
@@ -1,39 +0,0 @@
-<!--
-Test for bug69296.
-Collapsed borders should not disappear.
--->
-<html>
-    <head>
-        <style>
-            BODY {
-                margin: 20px;
-            }
-            TABLE {
-                border-collapse: collapse;
-            }
-            TD {
-                width: 50px;
-                height: 50px;
-                border: 1px solid #333333;
-            }
-        </style>
-    </head>
-    <body>
-        <table>
-            <tr id="row1">
-                <td valign="top"/>
-                <td/>
-                <td>
-                    <div>
-                        <div style="width: 20px; height: 20px; background: lime;"/>
-                    </div>
-                </td>
-            </tr>
-            <tr id="row2">
-                <td/>
-                <td/>
-                <td/>
-            </tr>
-        </table>
-    </body>
-</html>
diff --git a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/table/cached-cell-append-expected.html b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/table/cached-cell-append-expected.html
deleted file mode 100644
index bb1e0f7..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/table/cached-cell-append-expected.html
+++ /dev/null
@@ -1,19 +0,0 @@
-<!--
-Calculating collapsed borders for big tables is expensive, so we cache them and recalculate when needed.
-Here we append new cell, expect that cache is invalidated and paint produces expected image.
--->
-<html>
-    <head>
-        <title></title>
-        <link rel="stylesheet" href="../../../fast/table/border-collapsing/resources/cached.css">
-    </head>
-    <body>
-        <table style="border-collapse:collapse; border:2px solid blue">
-            <tr id="row">
-                <td style="border:4px solid lime"/>
-                <td style="border: 6px solid yellow"/>
-            </tr>
-        </table>
-    </body>
-</html>
-
diff --git a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/table/cached-change-cell-border-color-expected.html b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/table/cached-change-cell-border-color-expected.html
deleted file mode 100644
index bd8df01a..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/table/cached-change-cell-border-color-expected.html
+++ /dev/null
@@ -1,19 +0,0 @@
-<!--
-Calculating collapsed borders for big tables is expensive, so we cache them and recalculate when needed.
-Here we change cell border color, expect that cache is invalidated and paint produces expected image.
--->
-<html>
-    <head>
-        <title></title>
-        <link rel="stylesheet" href="../../../fast/table/border-collapsing/resources/cached.css">
-    </head>
-    <body>
-        <table style="border-collapse:collapse; border:2px solid blue">
-            <tr>
-                <td style="border:4px solid lime" id="foo"/>
-                <td style="border:1px solid black"/>
-            </tr>
-        </table>
-    </body>
-</html>
-
diff --git a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/table/cached-change-cell-border-width-expected.html b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/table/cached-change-cell-border-width-expected.html
deleted file mode 100644
index 07cf3ab..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/table/cached-change-cell-border-width-expected.html
+++ /dev/null
@@ -1,19 +0,0 @@
-<!--
-Calculating collapsed borders for big tables is expensive, so we cache them and recalculate when needed.
-Here we change cell border width, expect that cache is invalidated and paint produces expected image.
--->
-<html>
-    <head>
-        <title></title>
-        <link rel="stylesheet" href="../../../fast/table/border-collapsing/resources/cached.css">
-    </head>
-    <body>
-        <table style="border-collapse:collapse; border:2px solid blue">
-            <tr>
-                <td style="border:4px solid lime" id="foo"/>
-                <td style="border:1px solid black"/>
-            </tr>
-        </table>
-    </body>
-</html>
-
diff --git a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/table/cached-change-cell-sl-border-color-expected.html b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/table/cached-change-cell-sl-border-color-expected.html
deleted file mode 100644
index 03e401f..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/table/cached-change-cell-sl-border-color-expected.html
+++ /dev/null
@@ -1,21 +0,0 @@
-<!--
-Calculating collapsed borders for big tables is expensive, so we cache them and recalculate when needed.
-Here we:
-1. Remove DIV text, this requests layout for DIV, but only simplified layout for TABLE;
-2. Change cell border color, expect that cache is invalidated and paint produces expected image.
--->
-<html>
-    <head>
-        <title></title>
-        <link rel="stylesheet" href="../../../fast/table/border-collapsing/resources/cached.css">
-    </head>
-    <body>
-        <table style="border-collapse:collapse; border:2px solid blue; position: relative;">
-            <tr>
-                <td style="border:4px solid lime" id="foo"/>
-                <td style="border:1px solid black"/>
-                <div id="blockDiv"></div>
-            </tr>
-        </table>
-    </body>
-</html>
diff --git a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/table/cached-change-col-border-color-expected.html b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/table/cached-change-col-border-color-expected.html
deleted file mode 100644
index 05ed9ec..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/table/cached-change-col-border-color-expected.html
+++ /dev/null
@@ -1,29 +0,0 @@
-<!--
-Calculating collapsed borders for big tables is expensive, so we cache them and recalculate when needed.
-Here we change col border color, expect that cache is invalidated and paint produces expected image.
--->
-<html>
-    <head>
-        <title></title>
-        <link rel="stylesheet" href="../../../fast/table/border-collapsing/resources/cached.css">
-    </head>
-    <body>
-        <table style="border-collapse:collapse; border:1px solid blue">
-            <colgroup>
-                <col style="border:4px solid yellow" id="col">
-                <col>
-            </colgroup>
-            <tbody>
-                <tr>
-                    <td style="border:2px solid lime"/>
-                    <td/>
-                </tr>
-                <tr>
-                    <td/>
-                    <td/>
-                </tr>
-            </tbody>
-        </table>
-    </body>
-</html>
-
diff --git a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/table/cached-change-col-border-width-expected.html b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/table/cached-change-col-border-width-expected.html
deleted file mode 100644
index 1639890..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/table/cached-change-col-border-width-expected.html
+++ /dev/null
@@ -1,29 +0,0 @@
-<!--
-Calculating collapsed borders for big tables is expensive, so we cache them and recalculate when needed.
-Here we change col border width, expect that cache is invalidated and paint produces expected image.
--->
-<html>
-    <head>
-        <title></title>
-        <link rel="stylesheet" href="../../../fast/table/border-collapsing/resources/cached.css">
-    </head>
-    <body>
-        <table style="border-collapse:collapse; border:1px solid blue">
-            <colgroup>
-                <col style="border:4px solid yellow" id="col">
-                <col>
-            </colgroup>
-            <tbody>
-                <tr>
-                    <td style="border:2px solid lime"/>
-                    <td/>
-                </tr>
-                <tr>
-                    <td/>
-                    <td/>
-                </tr>
-            </tbody>
-        </table>
-    </body>
-</html>
-
diff --git a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/table/cached-change-colgroup-border-color-expected.html b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/table/cached-change-colgroup-border-color-expected.html
deleted file mode 100644
index 61f6852..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/table/cached-change-colgroup-border-color-expected.html
+++ /dev/null
@@ -1,34 +0,0 @@
-<!--
-Calculating collapsed borders for big tables is expensive, so we cache them and recalculate when needed.
-Here we change colgroup border color, expect that cache is invalidated and paint produces expected image.
--->
-<html>
-    <head>
-        <title></title>
-        <link rel="stylesheet" href="../../../fast/table/border-collapsing/resources/cached.css">
-    </head>
-    <body>
-        <table style="border-collapse:collapse; border:1px solid blue">
-            <colgroup style="border:4px solid yellow" id="colgroup">
-                <col>
-                <col>
-            </colgroup>
-            <colgroup>
-                <col>
-            </colgroup>
-            <tbody>
-                <tr>
-                    <td style="border:2px solid lime"/>
-                    <td/>
-                    <td/>
-                </tr>
-                <tr>
-                    <td/>
-                    <td/>
-                    <td/>
-                </tr>
-            </tbody>
-        </table>
-    </body>
-</html>
-
diff --git a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/table/cached-change-colgroup-border-width-expected.html b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/table/cached-change-colgroup-border-width-expected.html
deleted file mode 100644
index fd90d81..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/table/cached-change-colgroup-border-width-expected.html
+++ /dev/null
@@ -1,34 +0,0 @@
-<!--
-Calculating collapsed borders for big tables is expensive, so we cache them and recalculate when needed.
-Here we change colgroup border width, expect that cache is invalidated and paint produces expected image.
--->
-<html>
-    <head>
-        <title></title>
-        <link rel="stylesheet" href="../../../fast/table/border-collapsing/resources/cached.css">
-    </head>
-    <body>
-        <table style="border-collapse:collapse; border:1px solid blue">
-            <colgroup style="border:4px solid yellow" id="colgroup">
-                <col>
-                <col>
-            </colgroup>
-            <colgroup>
-                <col>
-            </colgroup>
-            <tbody>
-                <tr>
-                    <td style="border:2px solid lime"/>
-                    <td/>
-                    <td/>
-                </tr>
-                <tr>
-                    <td/>
-                    <td/>
-                    <td/>
-                </tr>
-            </tbody>
-        </table>
-    </body>
-</html>
-
diff --git a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/table/cached-change-row-border-color-expected.html b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/table/cached-change-row-border-color-expected.html
deleted file mode 100644
index fd1688098..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/table/cached-change-row-border-color-expected.html
+++ /dev/null
@@ -1,21 +0,0 @@
-<!--
-Calculating collapsed borders for big tables is expensive, so we cache them and recalculate when needed.
-Here we change row border color, expect that cache is invalidated and paint produces expected image.
--->
-<html>
-    <head>
-        <title></title>
-        <link rel="stylesheet" href="../../../fast/table/border-collapsing/resources/cached.css">
-    </head>
-    <body>
-        <table style="border-collapse:collapse; border:1px solid blue">
-            <tr style="border:4px solid yellow" id="row">
-                <td style="border:2px solid lime"/>
-            </tr>
-            <tr>
-                <td/>
-            </tr>
-        </table>
-    </body>
-</html>
-
diff --git a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/table/cached-change-row-border-width-expected.html b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/table/cached-change-row-border-width-expected.html
deleted file mode 100644
index 0f074717..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/table/cached-change-row-border-width-expected.html
+++ /dev/null
@@ -1,21 +0,0 @@
-<!--
-Calculating collapsed borders for big tables is expensive, so we cache them and recalculate when needed.
-Here we change row border width, expect that cache is invalidated and paint produces expected image.
--->
-<html>
-    <head>
-        <title></title>
-        <link rel="stylesheet" href="../../../fast/table/border-collapsing/resources/cached.css">
-    </head>
-    <body>
-        <table style="border-collapse:collapse; border:1px solid blue">
-            <tr style="border:4px solid yellow" id="row">
-                <td style="border:2px solid lime"/>
-            </tr>
-            <tr>
-                <td/>
-            </tr>
-        </table>
-    </body>
-</html>
-
diff --git a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/table/cached-change-table-border-color-expected.html b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/table/cached-change-table-border-color-expected.html
deleted file mode 100644
index e135358d..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/table/cached-change-table-border-color-expected.html
+++ /dev/null
@@ -1,18 +0,0 @@
-<!--
-Calculating collapsed borders for big tables is expensive, so we cache them and recalculate when needed.
-Here we change table border color, expect that cache is invalidated and paint produces expected image.
--->
-<html>
-    <head>
-        <title></title>
-        <link rel="stylesheet" href="../../../fast/table/border-collapsing/resources/cached.css">
-    </head>
-    <body>
-        <table style="border-collapse:collapse; border:4px solid yellow" id="tbl">
-            <tr>
-                <td style="border:2px solid lime"/>
-            </tr>
-        </table>
-    </body>
-</html>
-
diff --git a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/table/cached-change-table-border-width-expected.html b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/table/cached-change-table-border-width-expected.html
deleted file mode 100644
index ed9bd593..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/table/cached-change-table-border-width-expected.html
+++ /dev/null
@@ -1,18 +0,0 @@
-<!--
-Calculating collapsed borders for big tables is expensive, so we cache them and recalculate when needed.
-Here we change table border width, expect that cache is invalidated and paint produces expected image.
--->
-<html>
-    <head>
-        <title></title>
-        <link rel="stylesheet" href="../../../fast/table/border-collapsing/resources/cached.css">
-    </head>
-    <body>
-        <table style="border-collapse:collapse; border:4px solid blue" id="tbl">
-            <tr>
-                <td style="border:2px solid lime"/>
-            </tr>
-        </table>
-    </body>
-</html>
-
diff --git a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/table/cached-change-tbody-border-color-expected.html b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/table/cached-change-tbody-border-color-expected.html
deleted file mode 100644
index e439d5e7..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/table/cached-change-tbody-border-color-expected.html
+++ /dev/null
@@ -1,31 +0,0 @@
-<!--
-Calculating collapsed borders for big tables is expensive, so we cache them and recalculate when needed.
-Here we change tbody border color, expect that cache is invalidated and paint produces expected image.
--->
-<html>
-    <head>
-        <title></title>
-        <link rel="stylesheet" href="../../../fast/table/border-collapsing/resources/cached.css">
-    </head>
-    <body>
-        <table style="border-collapse:collapse; border:1px solid blue">
-            <tbody style="border:4px solid yellow" id="tbody">
-                <tr>
-                    <td style="border:2px solid lime"/>
-                    <td/>
-                </tr>
-                <tr>
-                    <td/>
-                    <td/>
-                </tr>
-            </tbody>
-            <tbody>
-                <tr>
-                    <td/>
-                    <td/>
-                </tr>
-            </tbody>
-        </table>
-    </body>
-</html>
-
diff --git a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/table/cached-change-tbody-border-width-expected.html b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/table/cached-change-tbody-border-width-expected.html
deleted file mode 100644
index 8638e917..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/table/cached-change-tbody-border-width-expected.html
+++ /dev/null
@@ -1,31 +0,0 @@
-<!--
-Calculating collapsed borders for big tables is expensive, so we cache them and recalculate when needed.
-Here we change tbody border width, expect that cache is invalidated and paint produces expected image.
--->
-<html>
-    <head>
-        <title></title>
-        <link rel="stylesheet" href="../../../fast/table/border-collapsing/resources/cached.css">
-    </head>
-    <body>
-        <table style="border-collapse:collapse; border:1px solid blue">
-            <tbody style="border:4px solid yellow" id="tbody">
-                <tr>
-                    <td style="border:2px solid lime"/>
-                    <td/>
-                </tr>
-                <tr>
-                    <td/>
-                    <td/>
-                </tr>
-            </tbody>
-            <tbody>
-                <tr>
-                    <td/>
-                    <td/>
-                </tr>
-            </tbody>
-        </table>
-    </body>
-</html>
-
diff --git a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/table/collapsed-border-cell-resize-expected.html b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/table/collapsed-border-cell-resize-expected.html
deleted file mode 100644
index ba2fc22d..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/table/collapsed-border-cell-resize-expected.html
+++ /dev/null
@@ -1,6 +0,0 @@
-<!DOCTYPE html>
-<table style="border-collapse: collapse">
-  <tr>
-    <td id="target" style="width: 100px; height: 200px; border: 1px solid blue"></td>
-  </tr>
-</table>
diff --git a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/table/invisible-col-visible-td-expected.html b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/table/invisible-col-visible-td-expected.html
deleted file mode 100644
index 082a28b..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/table/invisible-col-visible-td-expected.html
+++ /dev/null
@@ -1,12 +0,0 @@
-<!DOCTYPE html>
-<style>
-  td { border: 2px solid blue; background: green }
-</style>
-<table style="width: 200px; height: 200px; border-collapse: collapse">
-  <tr>
-    <td></td>
-  </tr>
-  <tr>
-    <td></td>
-  </tr>
-</table>
diff --git a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/table/invisible-tbody-visible-td-expected.html b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/table/invisible-tbody-visible-td-expected.html
deleted file mode 100644
index 6ac9b7f..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/table/invisible-tbody-visible-td-expected.html
+++ /dev/null
@@ -1,10 +0,0 @@
-<!DOCTYPE html>
-<style>
-  td { border: 2px solid blue; background: green }
-</style>
-<table style="width: 200px; height: 200px; border-collapse: collapse">
-  <tr>
-    <td></td>
-    <td style="visibility: hidden"></td>
-  </tr>
-</table>
diff --git a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/table/invisible-tr-visible-td-expected.html b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/table/invisible-tr-visible-td-expected.html
deleted file mode 100644
index 6ac9b7f..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/table/invisible-tr-visible-td-expected.html
+++ /dev/null
@@ -1,10 +0,0 @@
-<!DOCTYPE html>
-<style>
-  td { border: 2px solid blue; background: green }
-</style>
-<table style="width: 200px; height: 200px; border-collapse: collapse">
-  <tr>
-    <td></td>
-    <td style="visibility: hidden"></td>
-  </tr>
-</table>
diff --git a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/table/resize-table-repaint-percent-size-cell-expected.html b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/table/resize-table-repaint-percent-size-cell-expected.html
deleted file mode 100644
index 8609fa1..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/table/resize-table-repaint-percent-size-cell-expected.html
+++ /dev/null
@@ -1,29 +0,0 @@
-<!DOCTYPE html>
-<style>
-body {
-    margin: 0;
-}
-table {
-    position: absolute;
-    height: 80%;
-}
-tr {
-    height: 50%;
-    background-color: green;
-}
-td {
-    width: 100px;
-}
-</style>
-<div style="height: 50px">
-Tests repaint of percent-sized table cells when table changes size.
-The result repaint rects should cover the percent-sized table cells.
-</div>
-<table id="table">
-    <tr>
-        <td>ROW1</td>
-    </tr>
-    <tr>
-        <td>ROW2</td>
-    </tr>
-</table>
diff --git a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/table/resize-table-repaint-vertical-align-cell-expected.html b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/table/resize-table-repaint-vertical-align-cell-expected.html
deleted file mode 100644
index ae534290..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/table/resize-table-repaint-vertical-align-cell-expected.html
+++ /dev/null
@@ -1,23 +0,0 @@
-<!DOCTYPE html>
-<style>
-body {
-    margin: 0;
-}
-table {
-    position: absolute;
-    height: 80%;
-}
-td {
-    vertical-align: middle;
-    width: 100px;
-}
-</style>
-<div style="height: 50px">
-Tests repaint of middle-vertical-aligned table cells when table changes size.
-The result repaint rects should cover the middle-vertical-aligned table cells.
-</div>
-<table id="table">
-    <tr>
-        <td>MIDDLE</td>
-    </tr>
-</table>
diff --git a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/table/resize-table-row-repaint-expected.html b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/table/resize-table-row-repaint-expected.html
deleted file mode 100644
index 7e8d181..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/table/resize-table-row-repaint-expected.html
+++ /dev/null
@@ -1,21 +0,0 @@
-<!DOCTYPE html>
-<style>
-body {
-    margin: 0;
-}
-tr {
-    height: 200px;
-}
-td {
-    width: 100px;
-}
-</style>
-<div style="height: 100px">
-Tests repaint of table cells when the row changes size.
-The result repaint rects should cover the changed table cells.
-</div>
-<table>
-    <tr id="row">
-        <td>MIDDLE</td>
-    </tr>
-</table>
diff --git a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/table/row-change-background-rowspan-cell-expected.html b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/table/row-change-background-rowspan-cell-expected.html
deleted file mode 100644
index 6b3208a..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/table/row-change-background-rowspan-cell-expected.html
+++ /dev/null
@@ -1,27 +0,0 @@
-<!DOCTYPE html>
-<style>
-table {
-  position:relative;
-  top: 180px;
-}
-td {
-  width: 50px;
-  height: 50px;
-}
-</style>
-<table>
-  <tr>
-    <td rowspan="2">1,1</td>
-    <td>1,4</td>
-  </tr>
-  <tr>
-    <td>2,3</td>
-  </tr>
-  <tr>
-    <td rowspan="2" style="background-color: green">3,1</td>
-    <td style="background-color: green">3,4</td>
-  </tr>
-  <tr>
-    <td>4,4</td>
-  </tr>
-</table>
diff --git a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/text-append-dirty-lines-expected.html b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/text-append-dirty-lines-expected.html
deleted file mode 100644
index 2dec589b..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/text-append-dirty-lines-expected.html
+++ /dev/null
@@ -1,7 +0,0 @@
-<body>
-    <p>
-        Test for <i><a href="rdar://problem/6771547">rdar://problem/6771547</a> Appending to a LayoutText causes all its lines to be dirtied</i>.
-    </p>
-    <p id="target">
-        Lorem ipsum dolor sit amet, consectetur adipiscing elit. Suspendisse placerat. Morbi tristique. Mauris eu lacus sed felis pellentesque cursus. Proin vitae nulla. Vivamus in ipsum. Etiam mi. Nam malesuada purus in sem. Sed eget elit vel erat laoreet feugiat. Phasellus mollis pulvinar mi. Etiam ut neque sed eros egestas laoreet. Vestibulum ullamcorper, nulla non feugiat molestie, mi lorem bibendum leo, ac gravida orci nunc nec nulla. Nunc nunc lorem, rhoncus et, rutrum ac, fermentum ut, tortor. Sed rhoncus. Quisque enim metus, luctus tincidunt, vestibulum eu, vestibulum eu, libero. Mauris sagittis aliquam nunc. Nullam pharetra molestie eros. Donec tempus purus ut ligula. Phasellus non nisl. Etiam eu mauris. Curabitur a velit.</p>
-</body>
diff --git a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/text-in-relative-positioned-inline-expected.html b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/text-in-relative-positioned-inline-expected.html
deleted file mode 100644
index a7bf2da..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/text-in-relative-positioned-inline-expected.html
+++ /dev/null
@@ -1,8 +0,0 @@
-<head>
-    <script src="../../resources/ahem.js"></script>
-</head>
-<body>
-    <div style="margin-left: 100px; font: 100px Ahem; -webkit-font-smoothing: none; height: 100px;">
-    </div>
-    <div style="width: 100px; height: 100px; background-color: green; margin-top: -100px;"></div>
-</body>
diff --git a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/textarea-appearance-none-resize-handle-expected.html b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/textarea-appearance-none-resize-handle-expected.html
deleted file mode 100644
index e823144..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/textarea-appearance-none-resize-handle-expected.html
+++ /dev/null
@@ -1,12 +0,0 @@
-<!DOCTYPE html>
-Tests paint invalidation of resize handle when a textarea is resized.
-Passes if the resize handle is repainted correctly leaving no residue.
-<textarea id="textarea" style="
-  position: absolute;
-  top: 50px;
-  left: 0;
-  -webkit-appearance: none;
-  width: 100px;
-  height: 200px;
-  resize: auto">
-</textarea>
diff --git a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/textarea-resize-property-change-expected.html b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/textarea-resize-property-change-expected.html
deleted file mode 100644
index ebc705e..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/textarea-resize-property-change-expected.html
+++ /dev/null
@@ -1,11 +0,0 @@
-<!DOCTYPE html>
-Tests paint invalidation when a textarea's resize property changed.
-Passes if the resize handle is repainted correctly.
-<textarea id="textarea" style="
-  position: absolute;
-  top: 50px;
-  left: 0;
-  width: 100px;
-  height: 100px;
-  resize: auto">
-</textarea>
diff --git a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/textarea-set-disabled-expected.html b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/textarea-set-disabled-expected.html
deleted file mode 100644
index dc0ad45..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/textarea-set-disabled-expected.html
+++ /dev/null
@@ -1,9 +0,0 @@
-<!DOCTYPE html>
-<html>
-<script src="../../resources/ahem.js"></script>
-<body>
-<form>
-  <textarea disabled style="font: 10px Ahem; width: 100px; height: 100px;"></textarea>
-</form>
-</body>
-</html>
diff --git a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/trailing-floats-root-line-box-overflow-expected.html b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/trailing-floats-root-line-box-overflow-expected.html
deleted file mode 100644
index f2eb03a..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/trailing-floats-root-line-box-overflow-expected.html
+++ /dev/null
@@ -1,3 +0,0 @@
-<body>
-    <div style="background-color: yellow;"><div style="display: inline-block; width: 100px; height: 100px; background-color: green; margin-top: 50px; margin-bottom: -100px;"></div><br><div style="float: left;"></div></div>
-</body>
diff --git a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/transform-absolute-child-expected.html b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/transform-absolute-child-expected.html
deleted file mode 100644
index 5b5b557..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/transform-absolute-child-expected.html
+++ /dev/null
@@ -1,32 +0,0 @@
-<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
-   "http://www.w3.org/TR/html4/loose.dtd">
-<html lang="en">
-<head>
-  <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
-  <title>Transform with Abs. Pos child</title>
-  <style type="text/css" media="screen">
-     #box {
-        position: relative;
-        margin: 50px;
-        width: 200px;
-        height: 200px;
-        border: 2px solid black;
-        transform: rotate(40deg);
-     }
-     #child {
-        position: absolute;
-        width: 400px;
-        height: 50px;
-        top: 75px;
-        left: 75px;
-        background-color: gray;
-     }
-  </style>
-</head>
-<body>
-<div id="box">
-    <div id="child">
-    </div>
-</div>
-</body>
-</html>
diff --git a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/transform-absolute-in-positioned-container-expected.html b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/transform-absolute-in-positioned-container-expected.html
deleted file mode 100644
index eae260d..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/transform-absolute-in-positioned-container-expected.html
+++ /dev/null
@@ -1,34 +0,0 @@
-<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
-<html>
-<head>
-  <title>Relative Position Transform Redraw</title>
-  <meta http-equiv="content-type" content="text/html; charset=utf-8">
-  <style type="text/css">
-    #container {
-      position: relative;
-      left: 10px;
-      top: 60px;
-      padding: 20px;
-      background-color: #DDD;
-    }
-    #box {
-      position:relative;
-      top: 100px;
-      left: 100px;
-      height: 200px;
-      width: 200px;
-      background-color: #CCC;
-      border: 1px solid black;
-      transform: rotate(45deg);
-    }
-  </style>
-</head>
-<body>
-  <p>Test for <a href="https://bugs.webkit.org/show_bug.cgi?id=17840">https://bugs.webkit.org/show_bug.cgi?id=17840</a>. The rotated box should be correctly redrawn.</p>
-  
-  <span id="container">
-    Container
-    <div id="box"></div>
-  </span>
-</body>
-</html>
diff --git a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/transform-disable-layoutstate-expected.html b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/transform-disable-layoutstate-expected.html
deleted file mode 100644
index 4592e542..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/transform-disable-layoutstate-expected.html
+++ /dev/null
@@ -1,14 +0,0 @@
-<!DOCTYPE html>
-<html>
-<body>
-    <div id="container" style="width: 500px; transform: translate(50px, 80px)">
-      <div style="padding-bottom: 100px; background: silver;">
-          <div style="float: right; height: 50px; width: 50px; background: green;"></div>
-          <div style="clear: right; border: 4px solid blue;">
-                  <div style="height: 10px;" id="target">
-                  </div>
-          </div>
-      </div>
-    </div>
-</body>
-</html>
diff --git a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/transform-inline-layered-child-expected.html b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/transform-inline-layered-child-expected.html
deleted file mode 100644
index 60f04aa..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/transform-inline-layered-child-expected.html
+++ /dev/null
@@ -1,22 +0,0 @@
-<!DOCTYPE html>
-<script src="../../resources/ahem.js"></script>
-<style>
-#box {
-  position: absolute;
-  top: 100px;
-  left: 100px;
-  width: 100px;
-  transform: rotate(30deg);
-}
-#child {
-  position: relative;
-  left: 200px;
-  top: 200px;
-  font-family: Ahem;
-}
-</style>
-Tests if the inline layered child is correctly repainted when container's transform changes.
-Succeeds if the text is completely rotated leaving no residue at the original location.
-<div id="box">
-  <span id="child">A B C D E F G H I J K L M N O P Q R S T U V W X Y Z</span>
-</div>
diff --git a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/transform-layout-repaint-expected.html b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/transform-layout-repaint-expected.html
deleted file mode 100644
index 97c40d70..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/transform-layout-repaint-expected.html
+++ /dev/null
@@ -1,19 +0,0 @@
-<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
-        "http://www.w3.org/TR/html4/strict.dtd">
-<html lang="en">
-<head>
-    <style type="text/css" media="screen">
-      div {
-        margin: 50px;
-        width: 200px;
-        height: 50px;
-        border: 1px solid black;
-        transform-origin: top left;
-        transform: rotate(20deg);
-      }
-    </style>
-</head>
-<body>
-    <div id="target">PASS</div>
-</body>
-</html>
diff --git a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/transform-relative-position-expected.html b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/transform-relative-position-expected.html
deleted file mode 100644
index 2f5ca21..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/transform-relative-position-expected.html
+++ /dev/null
@@ -1,24 +0,0 @@
-<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
-<html>
-<head>
-  <title>Relative Position Transform Redraw</title>
-  <meta http-equiv="content-type" content="text/html; charset=utf-8">
-  <style type="text/css">
-    #box {
-      position:relative;
-      top: 100px;
-      left: 100px;
-      height: 200px;
-      width: 200px;
-      background-color: #CCC;
-      border: 1px solid black;
-      transform: rotate(45deg);
-    }
-  </style>
-</head>
-<body>
-  <p>Test for <a href="https://bugs.webkit.org/show_bug.cgi?id=17840">https://bugs.webkit.org/show_bug.cgi?id=17840</a>. The rotated box should be correctly redrawn.</p>
-  <div id="box">
-  </div>
-</body>
-</html>
diff --git a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/transform-repaint-descendants-expected.html b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/transform-repaint-descendants-expected.html
deleted file mode 100644
index 1fdfb7b..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/transform-repaint-descendants-expected.html
+++ /dev/null
@@ -1,32 +0,0 @@
-<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
-<html>
-<head>
-  <title>Transform Repaint Descendants</title>
-  <meta http-equiv="content-type" content="text/html; charset=utf-8">
-  <style type="text/css">
-    #box {
-      position:relative;
-      top: 100px;
-      left: 100px;
-      height: 200px;
-      width: 200px;
-      background-color: #CCC;
-      border: 1px solid black;
-      transform: rotate(23deg);
-    }
-    
-    #box > div {
-      position: absolute;
-      height: 50px;
-      width: 400px;
-      top: 75px;
-      left: 75px;
-      background-color: #555;
-    }
-  </style>
-</head>
-<body onload="startTest()">
-  <p>Test for <a href="https://bugs.webkit.org/show_bug.cgi?id=22088">https://bugs.webkit.org/show_bug.cgi?id=22088</a>. The rotated box should be correctly redrawn.</p>
-  <div id="box"><div></div></div>
-</body>
-</html>
diff --git a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/transform-replaced-shadows-expected.html b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/transform-replaced-shadows-expected.html
deleted file mode 100644
index 1c7d0c6..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/transform-replaced-shadows-expected.html
+++ /dev/null
@@ -1,20 +0,0 @@
-<html>
-<head>
-  <title>Scaling and box-shadow</title>
-  <style type="text/css" media="screen">
-    #box {
-      height: 100px;
-      width: 100px;
-      margin: 20px;
-      background-color: gray;
-      transform-origin: top left;
-      -webkit-box-shadow: 0px 20px 20px black;
-    }
-  </style>
-</head>
-<body>
-
-<img id="box">
-
-</body>
-</html>
diff --git a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/transform-rotate-and-remove-expected.html b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/transform-rotate-and-remove-expected.html
deleted file mode 100644
index 906365cba..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/transform-rotate-and-remove-expected.html
+++ /dev/null
@@ -1,15 +0,0 @@
-<!DOCTYPE html>
-<html>
-    <head>
-        <title>
-            Test case for https://bugs.webkit.org/show_bug.cgi?id=61338 
-        </title>
-    </head>
-    <body>
-        <!--
-        <p> Bug <a href="https://bugs.webkit.org/show_bug.cgi?id=61338">61338</a>: Element not fully repainted after application and removal of transform </p>
-        <p> The test PASSES only if all the four borders of the box are displayed in green</p>
-        -->
-        <div id="rel" style="height:50px; width:200px; background-color:yellow ; border:10px solid green;">  </div>
-    </body>
-</html>
diff --git a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/transform-translate-expected.html b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/transform-translate-expected.html
deleted file mode 100644
index be51ab76..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/transform-translate-expected.html
+++ /dev/null
@@ -1,6 +0,0 @@
-<head>
-<title>Repaint test for bug 15719</title>
-</head>
-<body>
-<h1>Repaint test for bug 15719</h1>
-<div id="target" style="transform: translate(20px, 0); width: 100px; height: 100px; background-color: yellow; border: solid;"></div>
diff --git a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/vertical-align-length1-expected.html b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/vertical-align-length1-expected.html
deleted file mode 100644
index f0b58c8e..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/vertical-align-length1-expected.html
+++ /dev/null
@@ -1,20 +0,0 @@
-<!DOCTYPE HTML>
-<style>
-body {
-    margin: 0;
-}
-.other {
-    width: 20px;
-    height: 20px;
-    background-color: blue;
-    display: inline-block;
-}
-#target {
-    width: 100px;
-    height: 100px;
-    background-color: green;
-    display: inline-block;
-    vertical-align: 50px;
-}
-</style>
-<div class="other"></div><div id="target"></div><div class="other"></div>
diff --git a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/vertical-align-length2-expected.html b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/vertical-align-length2-expected.html
deleted file mode 100644
index ba42ef82..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/vertical-align-length2-expected.html
+++ /dev/null
@@ -1,20 +0,0 @@
-<!DOCTYPE HTML>
-<style>
-body {
-    margin: 0;
-}
-.other {
-    width: 200px;
-    height: 200px;
-    background-color: blue;
-    display: inline-block;
-}
-#target {
-    width: 100px;
-    height: 100px;
-    background-color: green;
-    display: inline-block;
-    vertical-align: 50px;
-}
-</style>
-<div class="other"></div><div id="target"></div><div class="other"></div>
diff --git a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/vertical-align1-expected.html b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/vertical-align1-expected.html
deleted file mode 100644
index b8b46e6..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/vertical-align1-expected.html
+++ /dev/null
@@ -1,20 +0,0 @@
-<!DOCTYPE HTML>
-<style>
-body {
-    margin: 0;
-}
-.other {
-    width: 20px;
-    height: 20px;
-    background-color: blue;
-    display: inline-block;
-}
-#target {
-    width: 100px;
-    height: 100px;
-    background-color: green;
-    display: inline-block;
-    vertical-align: middle;
-}
-</style>
-<div class="other"></div><div id="target"></div><div class="other"></div>
diff --git a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/vertical-align2-expected.html b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/vertical-align2-expected.html
deleted file mode 100644
index c6cdb56..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/vertical-align2-expected.html
+++ /dev/null
@@ -1,20 +0,0 @@
-<!DOCTYPE HTML>
-<style>
-body {
-    margin: 0;
-}
-.other {
-    width: 200px;
-    height: 200px;
-    background-color: blue;
-    display: inline-block;
-}
-#target {
-    width: 100px;
-    height: 100px;
-    background-color: green;
-    display: inline-block;
-    vertical-align: middle;
-}
-</style>
-<div class="other"></div><div id="target"></div><div class="other"></div>
diff --git a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/vertical-rl-as-paint-container-expected.html b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/vertical-rl-as-paint-container-expected.html
deleted file mode 100644
index ff6de86..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/vertical-rl-as-paint-container-expected.html
+++ /dev/null
@@ -1,5 +0,0 @@
-<!DOCTYPE html>
-<div id="target" style="-webkit-writing-mode:vertical-rl; backface-visibility:hidden; width:600px; height:400px; font:20px/1 Ahem; color:green;">
-    Lorem ipsum dolor sit amet, consectetur adipiscing elit.
-</div>
-<p>All text above should be green (if tested manually, you need to click first).</p>
diff --git a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/vertical-rl-overflow-expected.html b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/vertical-rl-overflow-expected.html
deleted file mode 100644
index 1623234..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/vertical-rl-overflow-expected.html
+++ /dev/null
@@ -1,14 +0,0 @@
-<!DOCTYPE html>
-<style>
-#div {
-  box-shadow: -50px 0 green;
-  position: absolute;
-  top: 100px;
-  left: 100px;
-  width: 100px;
-  height: 100px;
-  background-color: blue;
-}
-</style>
-Tests paint invalidation of a verticle-rl div with overflow. Passes if no under-invalidation reported and shows no red.
-<div id="div"></div>
diff --git a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/view-background-from-body-2-expected.html b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/view-background-from-body-2-expected.html
deleted file mode 100644
index 529d3d9..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/view-background-from-body-2-expected.html
+++ /dev/null
@@ -1,2 +0,0 @@
-<body style="margin: 50px; background-color: blue;">
-</body>
diff --git a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/platform/linux/paint/invalidation/compositing/fixed-pos-with-abs-pos-child-scroll-expected.txt b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/platform/linux/paint/invalidation/compositing/fixed-pos-with-abs-pos-child-scroll-expected.txt
new file mode 100644
index 0000000..f27f796
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/platform/linux/paint/invalidation/compositing/fixed-pos-with-abs-pos-child-scroll-expected.txt
@@ -0,0 +1,106 @@
+Hi!
+{
+  "layers": [
+    {
+      "name": "LayoutView #document",
+      "bounds": [800, 600],
+      "backgroundColor": "#FFFFFF"
+    },
+    {
+      "name": "Scrolling Layer",
+      "bounds": [785, 600],
+      "drawsContent": false
+    },
+    {
+      "name": "Scrolling Contents Layer",
+      "bounds": [785, 4021],
+      "contentsOpaque": true,
+      "backgroundColor": "#FFFFFF",
+      "paintInvalidations": [
+        {
+          "object": "LayoutBlockFlow (positioned) DIV id='abs'",
+          "rect": [425, 980, 360, 90],
+          "reason": "subtree"
+        },
+        {
+          "object": "LayoutBlockFlow (positioned) DIV id='abs'",
+          "rect": [425, 980, 360, 90],
+          "reason": "subtree"
+        },
+        {
+          "object": "LayoutBlockFlow (positioned) DIV id='abs'",
+          "rect": [425, 480, 360, 90],
+          "reason": "subtree"
+        },
+        {
+          "object": "LayoutBlockFlow (positioned) DIV id='abs'",
+          "rect": [425, 480, 360, 90],
+          "reason": "subtree"
+        },
+        {
+          "object": "LayoutText #text",
+          "rect": [425, 980, 21, 19],
+          "reason": "subtree"
+        },
+        {
+          "object": "LayoutText #text",
+          "rect": [425, 980, 21, 19],
+          "reason": "subtree"
+        },
+        {
+          "object": "LayoutText #text",
+          "rect": [425, 480, 21, 19],
+          "reason": "subtree"
+        },
+        {
+          "object": "LayoutText #text",
+          "rect": [425, 480, 21, 19],
+          "reason": "subtree"
+        }
+      ]
+    }
+  ],
+  "objectPaintInvalidations": [
+    {
+      "object": "LayoutBlockFlow (positioned) DIV id='fixed'",
+      "reason": "subtree"
+    },
+    {
+      "object": "LayoutBlockFlow (positioned) DIV id='abs'",
+      "reason": "subtree"
+    },
+    {
+      "object": "RootInlineBox",
+      "reason": "subtree"
+    },
+    {
+      "object": "LayoutText #text",
+      "reason": "subtree"
+    },
+    {
+      "object": "InlineTextBox 'Hi!'",
+      "reason": "subtree"
+    },
+    {
+      "object": "LayoutBlockFlow (positioned) DIV id='fixed'",
+      "reason": "subtree"
+    },
+    {
+      "object": "LayoutBlockFlow (positioned) DIV id='abs'",
+      "reason": "subtree"
+    },
+    {
+      "object": "RootInlineBox",
+      "reason": "subtree"
+    },
+    {
+      "object": "LayoutText #text",
+      "reason": "subtree"
+    },
+    {
+      "object": "InlineTextBox 'Hi!'",
+      "reason": "subtree"
+    }
+  ]
+}
+
diff --git a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/platform/linux/paint/invalidation/japanese-rl-selection-repaint-expected.txt b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/platform/linux/paint/invalidation/japanese-rl-selection-repaint-expected.txt
index c048e53..f008b76 100644
--- a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/platform/linux/paint/invalidation/japanese-rl-selection-repaint-expected.txt
+++ b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/platform/linux/paint/invalidation/japanese-rl-selection-repaint-expected.txt
@@ -26,14 +26,6 @@
   ],
   "objectPaintInvalidations": [
     {
-      "object": "LayoutBlockFlow HTML",
-      "reason": "selection"
-    },
-    {
-      "object": "LayoutBlockFlow BODY",
-      "reason": "selection"
-    },
-    {
       "object": "LayoutText #text",
       "reason": "geometry"
     },
diff --git a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/platform/linux/paint/invalidation/multicol-repaint-expected.txt b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/platform/linux/paint/invalidation/multicol-repaint-expected.txt
index a456570..eee87584 100644
--- a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/platform/linux/paint/invalidation/multicol-repaint-expected.txt
+++ b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/platform/linux/paint/invalidation/multicol-repaint-expected.txt
@@ -17,13 +17,13 @@
       "backgroundColor": "#FFFFFF",
       "paintInvalidations": [
         {
-          "object": "LayoutMultiColumnFlowThread (anonymous)",
-          "rect": [9, 9, 400, 100],
+          "object": "LayoutInline SPAN id='a'",
+          "rect": [234, 10, 300, 57],
           "reason": "geometry"
         },
         {
           "object": "LayoutInline SPAN id='a'",
-          "rect": [234, 10, 300, 57],
+          "rect": [9, 110, 300, 57],
           "reason": "geometry"
         },
         {
@@ -33,10 +33,30 @@
         },
         {
           "object": "LayoutText #text",
-          "rect": [234, 15, 50, 50],
+          "rect": [9, 115, 300, 50],
+          "reason": "appeared"
+        },
+        {
+          "object": "LayoutText #text",
+          "rect": [9, 15, 275, 150],
           "reason": "disappeared"
         },
         {
+          "object": "LayoutMultiColumnFlowThread (anonymous)",
+          "rect": [234, -91, 175, 159],
+          "reason": "geometry"
+        },
+        {
+          "object": "LayoutMultiColumnFlowThread (anonymous)",
+          "rect": [9, 9, 175, 159],
+          "reason": "geometry"
+        },
+        {
+          "object": "LayoutText #text",
+          "rect": [234, -90, 13, 57],
+          "reason": "geometry"
+        },
+        {
           "object": "LayoutText #text",
           "rect": [9, 10, 13, 57],
           "reason": "geometry"
@@ -58,6 +78,14 @@
       "reason": "geometry"
     },
     {
+      "object": "LayoutMultiColumnFlowThread (anonymous)",
+      "reason": "geometry"
+    },
+    {
+      "object": "RootInlineBox",
+      "reason": "geometry"
+    },
+    {
       "object": "LayoutText #text",
       "reason": "geometry"
     },
@@ -66,6 +94,22 @@
       "reason": "geometry"
     },
     {
+      "object": "LayoutText #text",
+      "reason": "geometry"
+    },
+    {
+      "object": "InlineTextBox '\u00A0'",
+      "reason": "geometry"
+    },
+    {
+      "object": "LayoutBR BR",
+      "reason": "geometry"
+    },
+    {
+      "object": "InlineTextBox '\n'",
+      "reason": "geometry"
+    },
+    {
       "object": "LayoutBR BR",
       "reason": "geometry"
     },
@@ -82,6 +126,22 @@
       "reason": "geometry"
     },
     {
+      "object": "LayoutInline SPAN id='a'",
+      "reason": "geometry"
+    },
+    {
+      "object": "InlineFlowBox",
+      "reason": "geometry"
+    },
+    {
+      "object": "LayoutText #text",
+      "reason": "appeared"
+    },
+    {
+      "object": "InlineTextBox 'XXXXXX'",
+      "reason": "appeared"
+    },
+    {
       "object": "LayoutText #text",
       "reason": "appeared"
     },
diff --git a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/platform/linux/paint/invalidation/repaint-across-writing-mode-boundary-expected.txt b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/platform/linux/paint/invalidation/repaint-across-writing-mode-boundary-expected.txt
index 1aa8b99..74fb3b76 100644
--- a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/platform/linux/paint/invalidation/repaint-across-writing-mode-boundary-expected.txt
+++ b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/platform/linux/paint/invalidation/repaint-across-writing-mode-boundary-expected.txt
@@ -26,26 +26,6 @@
   ],
   "objectPaintInvalidations": [
     {
-      "object": "LayoutBlockFlow HTML",
-      "reason": "selection"
-    },
-    {
-      "object": "LayoutBlockFlow BODY",
-      "reason": "selection"
-    },
-    {
-      "object": "LayoutBlockFlow DIV class='lrblock'",
-      "reason": "selection"
-    },
-    {
-      "object": "LayoutBlockFlow DIV class='basic d1 vert'",
-      "reason": "selection"
-    },
-    {
-      "object": "LayoutBlockFlow P",
-      "reason": "selection"
-    },
-    {
       "object": "LayoutText #text",
       "reason": "selection"
     },
diff --git a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/platform/linux/paint/invalidation/scrollbar-damage-and-full-viewport-repaint-expected.txt b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/platform/linux/paint/invalidation/scrollbar-damage-and-full-viewport-repaint-expected.txt
new file mode 100644
index 0000000..c811469
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/platform/linux/paint/invalidation/scrollbar-damage-and-full-viewport-repaint-expected.txt
@@ -0,0 +1,34 @@
+{
+  "layers": [
+    {
+      "name": "LayoutView #document",
+      "bounds": [1000, 600],
+      "backgroundColor": "#FFFFFF"
+    },
+    {
+      "name": "Scrolling Layer",
+      "bounds": [1000, 600],
+      "drawsContent": false
+    },
+    {
+      "name": "Scrolling Contents Layer",
+      "bounds": [1000, 600],
+      "contentsOpaque": true,
+      "backgroundColor": "#FFFFFF",
+      "paintInvalidations": [
+        {
+          "object": "LayoutBlockFlow DIV id='container'",
+          "rect": [1, 236, 185, 15],
+          "reason": "scroll control"
+        }
+      ]
+    }
+  ],
+  "objectPaintInvalidations": [
+    {
+      "object": "HorizontalScrollbar",
+      "reason": "scroll control"
+    }
+  ]
+}
+
diff --git a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/platform/linux/paint/invalidation/selection-after-remove-expected.txt b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/platform/linux/paint/invalidation/selection-after-remove-expected.txt
index e74545e..1d05d4d 100644
--- a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/platform/linux/paint/invalidation/selection-after-remove-expected.txt
+++ b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/platform/linux/paint/invalidation/selection-after-remove-expected.txt
@@ -356,14 +356,6 @@
       "reason": "disappeared"
     },
     {
-      "object": "LayoutBlockFlow HTML",
-      "reason": "selection"
-    },
-    {
-      "object": "LayoutBlockFlow BODY",
-      "reason": "selection"
-    },
-    {
       "object": "LayoutBlockFlow DIV id='test'",
       "reason": "geometry"
     },
diff --git a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/platform/linux/paint/invalidation/selection-clear-expected.txt b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/platform/linux/paint/invalidation/selection-clear-expected.txt
index 7e085eb..36c3627 100644
--- a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/platform/linux/paint/invalidation/selection-clear-expected.txt
+++ b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/platform/linux/paint/invalidation/selection-clear-expected.txt
@@ -55,22 +55,10 @@
       "reason": "disappeared"
     },
     {
-      "object": "LayoutBlockFlow HTML",
-      "reason": "selection"
-    },
-    {
-      "object": "LayoutBlockFlow BODY",
-      "reason": "selection"
-    },
-    {
       "object": "LayoutBlockFlow DIV id='root'",
       "reason": "incremental"
     },
     {
-      "object": "LayoutBlockFlow DIV id='root'",
-      "reason": "selection"
-    },
-    {
       "object": "LayoutBlockFlow DIV id='firstLine'",
       "reason": "full"
     },
diff --git a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/platform/linux/paint/invalidation/selection-rl-expected.txt b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/platform/linux/paint/invalidation/selection-rl-expected.txt
index 9f9985f..fc8bb9fa 100644
--- a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/platform/linux/paint/invalidation/selection-rl-expected.txt
+++ b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/platform/linux/paint/invalidation/selection-rl-expected.txt
@@ -26,14 +26,6 @@
   ],
   "objectPaintInvalidations": [
     {
-      "object": "LayoutBlockFlow HTML",
-      "reason": "selection"
-    },
-    {
-      "object": "LayoutBlockFlow BODY",
-      "reason": "selection"
-    },
-    {
       "object": "LayoutText #text",
       "reason": "selection"
     },
diff --git a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/platform/linux/paint/invalidation/selection/invalidation-rect-includes-newline-expected.txt b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/platform/linux/paint/invalidation/selection/invalidation-rect-includes-newline-expected.txt
index 2431b62..e735349 100644
--- a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/platform/linux/paint/invalidation/selection/invalidation-rect-includes-newline-expected.txt
+++ b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/platform/linux/paint/invalidation/selection/invalidation-rect-includes-newline-expected.txt
@@ -26,18 +26,6 @@
   ],
   "objectPaintInvalidations": [
     {
-      "object": "LayoutBlockFlow HTML",
-      "reason": "selection"
-    },
-    {
-      "object": "LayoutBlockFlow BODY",
-      "reason": "selection"
-    },
-    {
-      "object": "LayoutBlockFlow DIV id='container'",
-      "reason": "selection"
-    },
-    {
       "object": "LayoutText #text",
       "reason": "geometry"
     },
diff --git a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/platform/linux/paint/invalidation/selection/invalidation-rect-includes-newline-for-rtl-expected.txt b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/platform/linux/paint/invalidation/selection/invalidation-rect-includes-newline-for-rtl-expected.txt
index 9d654b5..577fd29 100644
--- a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/platform/linux/paint/invalidation/selection/invalidation-rect-includes-newline-for-rtl-expected.txt
+++ b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/platform/linux/paint/invalidation/selection/invalidation-rect-includes-newline-for-rtl-expected.txt
@@ -26,18 +26,6 @@
   ],
   "objectPaintInvalidations": [
     {
-      "object": "LayoutBlockFlow HTML",
-      "reason": "selection"
-    },
-    {
-      "object": "LayoutBlockFlow BODY",
-      "reason": "selection"
-    },
-    {
-      "object": "LayoutBlockFlow DIV id='container'",
-      "reason": "selection"
-    },
-    {
       "object": "LayoutText #text",
       "reason": "geometry"
     },
diff --git a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/platform/linux/paint/invalidation/selection/invalidation-rect-includes-newline-for-vertical-lr-expected.txt b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/platform/linux/paint/invalidation/selection/invalidation-rect-includes-newline-for-vertical-lr-expected.txt
index 73837a3..4f82686 100644
--- a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/platform/linux/paint/invalidation/selection/invalidation-rect-includes-newline-for-vertical-lr-expected.txt
+++ b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/platform/linux/paint/invalidation/selection/invalidation-rect-includes-newline-for-vertical-lr-expected.txt
@@ -26,18 +26,6 @@
   ],
   "objectPaintInvalidations": [
     {
-      "object": "LayoutBlockFlow HTML",
-      "reason": "selection"
-    },
-    {
-      "object": "LayoutBlockFlow BODY",
-      "reason": "selection"
-    },
-    {
-      "object": "LayoutBlockFlow DIV id='container'",
-      "reason": "selection"
-    },
-    {
       "object": "LayoutText #text",
       "reason": "geometry"
     },
diff --git a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/platform/linux/paint/invalidation/selection/invalidation-rect-includes-newline-for-vertical-rl-expected.txt b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/platform/linux/paint/invalidation/selection/invalidation-rect-includes-newline-for-vertical-rl-expected.txt
index 7041887..eaceb9c0 100644
--- a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/platform/linux/paint/invalidation/selection/invalidation-rect-includes-newline-for-vertical-rl-expected.txt
+++ b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/platform/linux/paint/invalidation/selection/invalidation-rect-includes-newline-for-vertical-rl-expected.txt
@@ -26,18 +26,6 @@
   ],
   "objectPaintInvalidations": [
     {
-      "object": "LayoutBlockFlow HTML",
-      "reason": "selection"
-    },
-    {
-      "object": "LayoutBlockFlow BODY",
-      "reason": "selection"
-    },
-    {
-      "object": "LayoutBlockFlow DIV id='container'",
-      "reason": "selection"
-    },
-    {
       "object": "LayoutText #text",
       "reason": "geometry"
     },
diff --git a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/platform/linux/paint/invalidation/selection/invalidation-rect-with-br-includes-newline-expected.txt b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/platform/linux/paint/invalidation/selection/invalidation-rect-with-br-includes-newline-expected.txt
index f7be68eb..04cac2b 100644
--- a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/platform/linux/paint/invalidation/selection/invalidation-rect-with-br-includes-newline-expected.txt
+++ b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/platform/linux/paint/invalidation/selection/invalidation-rect-with-br-includes-newline-expected.txt
@@ -36,18 +36,6 @@
   ],
   "objectPaintInvalidations": [
     {
-      "object": "LayoutBlockFlow HTML",
-      "reason": "selection"
-    },
-    {
-      "object": "LayoutBlockFlow BODY",
-      "reason": "selection"
-    },
-    {
-      "object": "LayoutBlockFlow DIV id='container'",
-      "reason": "selection"
-    },
-    {
       "object": "LayoutText #text",
       "reason": "selection"
     },
diff --git a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/platform/linux/paint/invalidation/selection/repaint-rect-for-vertical-writing-mode-with-positioned-root-expected.txt b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/platform/linux/paint/invalidation/selection/repaint-rect-for-vertical-writing-mode-with-positioned-root-expected.txt
index c62c880a..62501fcc 100644
--- a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/platform/linux/paint/invalidation/selection/repaint-rect-for-vertical-writing-mode-with-positioned-root-expected.txt
+++ b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/platform/linux/paint/invalidation/selection/repaint-rect-for-vertical-writing-mode-with-positioned-root-expected.txt
@@ -26,14 +26,6 @@
   ],
   "objectPaintInvalidations": [
     {
-      "object": "LayoutBlockFlow (positioned) DIV id='test'",
-      "reason": "selection"
-    },
-    {
-      "object": "LayoutBlockFlow DIV",
-      "reason": "selection"
-    },
-    {
       "object": "LayoutText #text",
       "reason": "selection"
     },
diff --git a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/platform/linux/paint/invalidation/selection/selection-in-non-composited-scrolling-container-expected.txt b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/platform/linux/paint/invalidation/selection/selection-in-non-composited-scrolling-container-expected.txt
index e7eeecc..ccdf6ea 100644
--- a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/platform/linux/paint/invalidation/selection/selection-in-non-composited-scrolling-container-expected.txt
+++ b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/platform/linux/paint/invalidation/selection/selection-in-non-composited-scrolling-container-expected.txt
@@ -22,7 +22,7 @@
           "reason": "subtree"
         },
         {
-          "object": "LayoutBlockFlow DIV id='inner-editor'",
+          "object": "LayoutBlockFlow DIV",
           "rect": [10, 11, 60, 16],
           "reason": "subtree"
         },
@@ -36,19 +36,11 @@
   ],
   "objectPaintInvalidations": [
     {
-      "object": "LayoutBlockFlow HTML",
-      "reason": "selection"
-    },
-    {
-      "object": "LayoutBlockFlow BODY",
-      "reason": "selection"
-    },
-    {
       "object": "LayoutTextControl INPUT id='target'",
       "reason": "subtree"
     },
     {
-      "object": "LayoutBlockFlow DIV id='inner-editor'",
+      "object": "LayoutBlockFlow DIV",
       "reason": "subtree"
     },
     {
diff --git a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/platform/linux/paint/invalidation/svg/text-viewbox-rescale-expected.txt b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/platform/linux/paint/invalidation/svg/text-viewbox-rescale-expected.txt
index 949024b..be1ab30 100644
--- a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/platform/linux/paint/invalidation/svg/text-viewbox-rescale-expected.txt
+++ b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/platform/linux/paint/invalidation/svg/text-viewbox-rescale-expected.txt
@@ -18,57 +18,57 @@
       "paintInvalidations": [
         {
           "object": "LayoutSVGInlineText #text",
-          "rect": [59, 143, 95, 23],
+          "rect": [59, 140, 95, 23],
           "reason": "geometry"
         },
         {
           "object": "LayoutSVGInlineText #text",
-          "rect": [59, 143, 95, 23],
+          "rect": [59, 140, 95, 23],
           "reason": "geometry"
         },
         {
           "object": "LayoutSVGTSpan tspan",
-          "rect": [59, 143, 95, 23],
+          "rect": [59, 140, 95, 23],
           "reason": "full"
         },
         {
           "object": "LayoutSVGText text",
-          "rect": [59, 143, 95, 23],
+          "rect": [59, 140, 95, 23],
           "reason": "full"
         },
         {
           "object": "LayoutSVGViewportContainer svg id='inner2'",
-          "rect": [59, 143, 95, 23],
+          "rect": [59, 140, 95, 23],
           "reason": "full"
         },
         {
           "object": "LayoutSVGInlineText #text",
-          "rect": [59, 43, 95, 23],
+          "rect": [59, 40, 95, 23],
           "reason": "geometry"
         },
         {
           "object": "LayoutSVGInlineText #text",
-          "rect": [59, 43, 95, 23],
+          "rect": [59, 40, 95, 23],
           "reason": "geometry"
         },
         {
           "object": "LayoutSVGInlineText #text",
-          "rect": [59, 43, 95, 23],
+          "rect": [59, 40, 95, 23],
           "reason": "geometry"
         },
         {
           "object": "LayoutSVGTSpan tspan",
-          "rect": [59, 43, 95, 23],
+          "rect": [59, 40, 95, 23],
           "reason": "full"
         },
         {
           "object": "LayoutSVGText text",
-          "rect": [59, 43, 95, 23],
+          "rect": [59, 40, 95, 23],
           "reason": "full"
         },
         {
           "object": "LayoutSVGViewportContainer svg id='inner1'",
-          "rect": [59, 43, 95, 23],
+          "rect": [59, 40, 95, 23],
           "reason": "full"
         },
         {
diff --git a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/platform/linux/paint/invalidation/svg/window-expected.txt b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/platform/linux/paint/invalidation/svg/window-expected.txt
index fb77016..b1599f0d 100644
--- a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/platform/linux/paint/invalidation/svg/window-expected.txt
+++ b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/platform/linux/paint/invalidation/svg/window-expected.txt
@@ -458,12 +458,12 @@
         },
         {
           "object": "LayoutSVGInlineText #text",
-          "rect": [41, 524, 101, 11],
+          "rect": [41, 524, 101, 10],
           "reason": "appeared"
         },
         {
           "object": "LayoutSVGText text",
-          "rect": [41, 524, 101, 11],
+          "rect": [41, 524, 101, 10],
           "reason": "appeared"
         },
         {
@@ -538,12 +538,12 @@
         },
         {
           "object": "LayoutSVGInlineText #text",
-          "rect": [616, 153, 12, 81],
+          "rect": [615, 153, 13, 81],
           "reason": "appeared"
         },
         {
           "object": "LayoutSVGText text",
-          "rect": [616, 153, 12, 81],
+          "rect": [615, 153, 13, 81],
           "reason": "appeared"
         },
         {
diff --git a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/platform/mac-mac10.9/paint/invalidation/japanese-rl-selection-repaint-expected.txt b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/platform/mac-mac10.9/paint/invalidation/japanese-rl-selection-repaint-expected.txt
deleted file mode 100644
index 2c052ee2..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/platform/mac-mac10.9/paint/invalidation/japanese-rl-selection-repaint-expected.txt
+++ /dev/null
@@ -1,86 +0,0 @@
-{
-  "layers": [
-    {
-      "name": "LayoutView #document",
-      "bounds": [800, 600],
-      "backgroundColor": "#FFFFFF"
-    },
-    {
-      "name": "Scrolling Layer",
-      "bounds": [800, 600],
-      "drawsContent": false
-    },
-    {
-      "name": "Scrolling Contents Layer",
-      "bounds": [800, 600],
-      "contentsOpaque": true,
-      "backgroundColor": "#FFFFFF",
-      "paintInvalidations": [
-        {
-          "object": "LayoutText #text",
-          "rect": [420, 23, 352, 548],
-          "reason": "geometry"
-        }
-      ]
-    }
-  ],
-  "objectPaintInvalidations": [
-    {
-      "object": "LayoutBlockFlow HTML",
-      "reason": "selection"
-    },
-    {
-      "object": "LayoutBlockFlow BODY",
-      "reason": "selection"
-    },
-    {
-      "object": "LayoutText #text",
-      "reason": "geometry"
-    },
-    {
-      "object": "InlineTextBox '\u305B\u3063\u304B\u304F\u898B\u3064\u3051\u305F\u3059\u3070\u3089\u3057\u3044\u8A18\u4E8B\u304C\u3069\u3053\u306B\u3042\u3063\u305F\u304B\u5FD8\u308C'",
-      "reason": "geometry"
-    },
-    {
-      "object": "InlineTextBox '\u3066\u3057\u307E\u3063\u305F\u7D4C\u9A13\u306F\u3042\u308A\u307E\u3059\u304B\u306A\u3089\u30BF\u30A4\u30C8\u30EB\u3068\u30A2\u30C9\u30EC\u30B9\u3060'",
-      "reason": "geometry"
-    },
-    {
-      "object": "InlineTextBox '\u3051\u3067\u306A\u304F\u3001\u8A2A\u554F\u3057\u305F\u30A6\u30A7\u30D6\u30DA\u30FC\u30B8\u306E\u30B3\u30F3\u30C6\u30F3\u30C4\u304B\u3089\u3082\u691C'",
-      "reason": "geometry"
-    },
-    {
-      "object": "InlineTextBox '\u7D22\u3059\u308B\u3053\u3068\u304C\u3067\u304D\u307E\u3059\u3002\u305B\u3063\u304B\u304F\u898B\u3064\u3051\u305F\u3059\u3070\u3089\u3057\u3044\u8A18'",
-      "reason": "geometry"
-    },
-    {
-      "object": "InlineTextBox '\u4E8B\u304C\u3069\u3053\u306B\u3042\u3063\u305F\u304B\u5FD8\u308C\u3066\u3057\u307E\u3063\u305F\u7D4C\u9A13\u306F\u3042\u308A\u307E\u3059\u304B \u306A'",
-      "reason": "geometry"
-    },
-    {
-      "object": "InlineTextBox '\u3089\u30BF\u30A4\u30C8\u30EB\u3068\u30A2\u30C9\u30EC\u30B9\u3060\u3051\u3067\u306A\u304F\u3001\u8A2A\u554F\u3057\u305F\u30A6\u30A7\u30D6\u30DA\u30FC'",
-      "reason": "geometry"
-    },
-    {
-      "object": "InlineTextBox '\u30B8\u306E\u30B3\u30F3\u30C6\u30F3\u30C4\u304B\u3089\u3082\u691C\u7D22\u3059\u308B\u3053\u3068\u304C\u3067\u304D\u307E\u3059\u3002\u8A2A\u554F\u3057'",
-      "reason": "geometry"
-    },
-    {
-      "object": "InlineTextBox '\u305F\u30A6\u30A7\u30D6\u30DA\u30FC\u30B8\u306E\u30B3\u30F3\u30C6\u30F3\u30C4\u304B\u3089\u3082\u691C\u7D22\u3059\u308B\u3053\u3068\u304C\u3067\u304D'",
-      "reason": "geometry"
-    },
-    {
-      "object": "InlineTextBox '\u307E\u3059\u3002\u305B\u3063\u304B\u304F\u898B\u3064\u3051\u305F\u3059\u3070\u3089\u3057\u3044\u8A18\u4E8B\u304C\u3069\u3053\u306B\u3042\u3063\u305F'",
-      "reason": "geometry"
-    },
-    {
-      "object": "InlineTextBox '\u304B\u5FD8\u308C\u3066\u3057\u307E\u3063\u305F\u7D4C\u9A13\u306F\u3042\u308A\u307E\u3059\u304B \u306A\u3089\u30BF\u30A4\u30C8\u30EB\u3068\u30A2\u30C9'",
-      "reason": "geometry"
-    },
-    {
-      "object": "InlineTextBox '\u30EC\u30B9\u3060\u3051\u3067\u306A\u304F\u3001\u8A2A\u554F'",
-      "reason": "geometry"
-    }
-  ]
-}
-
diff --git a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/platform/mac-mac10.9/paint/invalidation/selection/selection-in-non-composited-scrolling-container-expected.txt b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/platform/mac-mac10.9/paint/invalidation/selection/selection-in-non-composited-scrolling-container-expected.txt
deleted file mode 100644
index 44de68b..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/platform/mac-mac10.9/paint/invalidation/selection/selection-in-non-composited-scrolling-container-expected.txt
+++ /dev/null
@@ -1,68 +0,0 @@
-{
-  "layers": [
-    {
-      "name": "LayoutView #document",
-      "bounds": [800, 600],
-      "backgroundColor": "#FFFFFF"
-    },
-    {
-      "name": "Scrolling Layer",
-      "bounds": [800, 600],
-      "drawsContent": false
-    },
-    {
-      "name": "Scrolling Contents Layer",
-      "bounds": [800, 600],
-      "contentsOpaque": true,
-      "backgroundColor": "#FFFFFF",
-      "paintInvalidations": [
-        {
-          "object": "LayoutTextControl INPUT id='target'",
-          "rect": [5, 5, 54, 25],
-          "reason": "subtree"
-        },
-        {
-          "object": "LayoutBlockFlow DIV id='inner-editor'",
-          "rect": [11, 11, 42, 13],
-          "reason": "subtree"
-        },
-        {
-          "object": "LayoutText #text",
-          "rect": [11, 11, 42, 13],
-          "reason": "subtree"
-        }
-      ]
-    }
-  ],
-  "objectPaintInvalidations": [
-    {
-      "object": "LayoutBlockFlow HTML",
-      "reason": "selection"
-    },
-    {
-      "object": "LayoutBlockFlow BODY",
-      "reason": "selection"
-    },
-    {
-      "object": "LayoutTextControl INPUT id='target'",
-      "reason": "subtree"
-    },
-    {
-      "object": "LayoutBlockFlow DIV id='inner-editor'",
-      "reason": "subtree"
-    },
-    {
-      "object": "RootInlineBox",
-      "reason": "subtree"
-    },
-    {
-      "object": "LayoutText #text",
-      "reason": "subtree"
-    },
-    {
-      "object": "InlineTextBox 'test test test'",
-      "reason": "subtree"
-    }
-  ]
-}
-
diff --git a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/platform/mac/css3/filters/composited-layer-child-bounds-after-composited-to-sw-shadow-change-expected.txt b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/platform/mac/css3/filters/composited-layer-child-bounds-after-composited-to-sw-shadow-change-expected.txt
new file mode 100644
index 0000000..2be56424
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/platform/mac/css3/filters/composited-layer-child-bounds-after-composited-to-sw-shadow-change-expected.txt
@@ -0,0 +1,91 @@
+{
+  "layers": [
+    {
+      "name": "LayoutView #document",
+      "bounds": [800, 600],
+      "backgroundColor": "#FFFFFF"
+    },
+    {
+      "name": "Scrolling Layer",
+      "bounds": [800, 600],
+      "drawsContent": false
+    },
+    {
+      "name": "Scrolling Contents Layer",
+      "bounds": [800, 600],
+      "contentsOpaque": true,
+      "backgroundColor": "#FFFFFF"
+    },
+    {
+      "name": "LayoutBlockFlow (positioned) DIV id='composited-parent' class='compositor-painted-shadow'",
+      "bounds": [100, 100],
+      "contentsOpaque": true,
+      "backgroundColor": "#FF0000",
+      "transform": 1
+    },
+    {
+      "name": "LayoutBlockFlow (positioned) DIV id='absolutely-positioned-composited-child'",
+      "bounds": [100, 100],
+      "contentsOpaque": true,
+      "backgroundColor": "#008000",
+      "transform": 1
+    }
+  ],
+  "transforms": [
+    {
+      "id": 1,
+      "transform": [
+        [1, 0, 0, 0],
+        [0, 1, 0, 0],
+        [0, 0, 1, 0],
+        [100, 100, 0, 1]
+      ]
+    }
+  ]
+}
+{
+  "layers": [
+    {
+      "name": "LayoutView #document",
+      "bounds": [800, 600],
+      "backgroundColor": "#FFFFFF"
+    },
+    {
+      "name": "Scrolling Layer",
+      "bounds": [785, 585],
+      "drawsContent": false
+    },
+    {
+      "name": "Scrolling Contents Layer",
+      "bounds": [835, 696],
+      "contentsOpaque": true,
+      "backgroundColor": "#FFFFFF"
+    },
+    {
+      "name": "LayoutBlockFlow (positioned) DIV id='composited-parent' class='software-painted-shadow'",
+      "bounds": [100, 100],
+      "contentsOpaque": true,
+      "backgroundColor": "#FF0000",
+      "transform": 1
+    },
+    {
+      "name": "LayoutBlockFlow (positioned) DIV id='absolutely-positioned-composited-child'",
+      "bounds": [100, 100],
+      "contentsOpaque": true,
+      "backgroundColor": "#008000",
+      "transform": 1
+    }
+  ],
+  "transforms": [
+    {
+      "id": 1,
+      "transform": [
+        [1, 0, 0, 0],
+        [0, 1, 0, 0],
+        [0, 0, 1, 0],
+        [100, 100, 0, 1]
+      ]
+    }
+  ]
+}
+
diff --git a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/platform/mac/css3/filters/composited-layer-promotion-after-outset-overlap-change-using-composited-shadow-expected.txt b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/platform/mac/css3/filters/composited-layer-promotion-after-outset-overlap-change-using-composited-shadow-expected.txt
new file mode 100644
index 0000000..94222ab
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/platform/mac/css3/filters/composited-layer-promotion-after-outset-overlap-change-using-composited-shadow-expected.txt
@@ -0,0 +1,84 @@
+{
+  "layers": [
+    {
+      "name": "LayoutView #document",
+      "bounds": [800, 600],
+      "backgroundColor": "#FFFFFF"
+    },
+    {
+      "name": "Scrolling Layer",
+      "bounds": [800, 600],
+      "drawsContent": false
+    },
+    {
+      "name": "Scrolling Contents Layer",
+      "bounds": [800, 600],
+      "contentsOpaque": true,
+      "backgroundColor": "#FFFFFF"
+    },
+    {
+      "name": "LayoutBlockFlow (positioned) DIV id='composited-layer-to-overlap'",
+      "bounds": [100, 100],
+      "contentsOpaque": true,
+      "backgroundColor": "#0000FF",
+      "transform": 1
+    }
+  ],
+  "transforms": [
+    {
+      "id": 1,
+      "transform": [
+        [1, 0, 0, 0],
+        [0, 1, 0, 0],
+        [0, 0, 1, 0],
+        [250, 250, 0, 1]
+      ]
+    }
+  ]
+}
+{
+  "layers": [
+    {
+      "name": "LayoutView #document",
+      "bounds": [800, 600],
+      "backgroundColor": "#FFFFFF"
+    },
+    {
+      "name": "Scrolling Layer",
+      "bounds": [800, 600],
+      "drawsContent": false
+    },
+    {
+      "name": "Scrolling Contents Layer",
+      "bounds": [800, 600],
+      "contentsOpaque": true,
+      "backgroundColor": "#FFFFFF"
+    },
+    {
+      "name": "LayoutBlockFlow (positioned) DIV id='composited-layer-to-overlap'",
+      "bounds": [100, 100],
+      "contentsOpaque": true,
+      "backgroundColor": "#0000FF",
+      "transform": 1
+    },
+    {
+      "name": "LayoutBlockFlow (positioned) DIV id='software-layer-to-promote' class='final-drop-shadow'",
+      "position": [100, 100],
+      "bounds": [100, 100],
+      "contentsOpaque": true,
+      "backgroundColor": "#000000"
+    }
+  ],
+  "transforms": [
+    {
+      "id": 1,
+      "transform": [
+        [1, 0, 0, 0],
+        [0, 1, 0, 0],
+        [0, 0, 1, 0],
+        [250, 250, 0, 1]
+      ]
+    }
+  ]
+}
+
diff --git a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/platform/mac/css3/filters/composited-layer-promotion-after-outset-overlap-change-using-sw-shadow-expected.txt b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/platform/mac/css3/filters/composited-layer-promotion-after-outset-overlap-change-using-sw-shadow-expected.txt
new file mode 100644
index 0000000..94222ab
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/platform/mac/css3/filters/composited-layer-promotion-after-outset-overlap-change-using-sw-shadow-expected.txt
@@ -0,0 +1,84 @@
+{
+  "layers": [
+    {
+      "name": "LayoutView #document",
+      "bounds": [800, 600],
+      "backgroundColor": "#FFFFFF"
+    },
+    {
+      "name": "Scrolling Layer",
+      "bounds": [800, 600],
+      "drawsContent": false
+    },
+    {
+      "name": "Scrolling Contents Layer",
+      "bounds": [800, 600],
+      "contentsOpaque": true,
+      "backgroundColor": "#FFFFFF"
+    },
+    {
+      "name": "LayoutBlockFlow (positioned) DIV id='composited-layer-to-overlap'",
+      "bounds": [100, 100],
+      "contentsOpaque": true,
+      "backgroundColor": "#0000FF",
+      "transform": 1
+    }
+  ],
+  "transforms": [
+    {
+      "id": 1,
+      "transform": [
+        [1, 0, 0, 0],
+        [0, 1, 0, 0],
+        [0, 0, 1, 0],
+        [250, 250, 0, 1]
+      ]
+    }
+  ]
+}
+{
+  "layers": [
+    {
+      "name": "LayoutView #document",
+      "bounds": [800, 600],
+      "backgroundColor": "#FFFFFF"
+    },
+    {
+      "name": "Scrolling Layer",
+      "bounds": [800, 600],
+      "drawsContent": false
+    },
+    {
+      "name": "Scrolling Contents Layer",
+      "bounds": [800, 600],
+      "contentsOpaque": true,
+      "backgroundColor": "#FFFFFF"
+    },
+    {
+      "name": "LayoutBlockFlow (positioned) DIV id='composited-layer-to-overlap'",
+      "bounds": [100, 100],
+      "contentsOpaque": true,
+      "backgroundColor": "#0000FF",
+      "transform": 1
+    },
+    {
+      "name": "LayoutBlockFlow (positioned) DIV id='software-layer-to-promote' class='final-drop-shadow'",
+      "position": [100, 100],
+      "bounds": [100, 100],
+      "contentsOpaque": true,
+      "backgroundColor": "#000000"
+    }
+  ],
+  "transforms": [
+    {
+      "id": 1,
+      "transform": [
+        [1, 0, 0, 0],
+        [0, 1, 0, 0],
+        [0, 0, 1, 0],
+        [250, 250, 0, 1]
+      ]
+    }
+  ]
+}
+
diff --git a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/platform/mac/paint/invalidation/background-image-paint-invalidation-large-abspos-div-expected.txt b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/platform/mac/paint/invalidation/background-image-paint-invalidation-large-abspos-div-expected.txt
new file mode 100644
index 0000000..001f21a
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/platform/mac/paint/invalidation/background-image-paint-invalidation-large-abspos-div-expected.txt
@@ -0,0 +1,10 @@
+layer at (0,0) size 800x600 clip at (0,0) size 785x600 scrollY 3000.00 scrollHeight 4008
+  LayoutView at (0,0) size 800x600
+layer at (0,-3000) size 785x557 backgroundClip at (0,0) size 785x600 clip at (0,0) size 785x600
+  LayoutBlockFlow {HTML} at (0,0) size 785x557
+    LayoutBlockFlow {BODY} at (8,8) size 769x541
+      LayoutImage {IMG} at (0,0) size 489x537
+      LayoutText {#text} at (0,0) size 0x0
+layer at (8,-2992) size 100x4000 backgroundClip at (0,0) size 785x600 clip at (0,0) size 785x600
+  LayoutBlockFlow (positioned) {DIV} at (8,8) size 100x4000
+scrolled to 0,3000
diff --git a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/platform/mac/paint/invalidation/body-background-image-expected.txt b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/platform/mac/paint/invalidation/body-background-image-expected.txt
index 8f7a95de..22510b3 100644
--- a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/platform/mac/paint/invalidation/body-background-image-expected.txt
+++ b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/platform/mac/paint/invalidation/body-background-image-expected.txt
@@ -3,7 +3,14 @@
     {
       "name": "LayoutView #document",
       "bounds": [800, 600],
-      "backgroundColor": "#FFFFFF"
+      "backgroundColor": "#FFFFFF",
+      "paintInvalidations": [
+        {
+          "object": "LayoutView #document",
+          "rect": [0, 0, 800, 600],
+          "reason": "style change"
+        }
+      ]
     },
     {
       "name": "Scrolling Layer",
@@ -26,6 +33,10 @@
   ],
   "objectPaintInvalidations": [
     {
+      "object": "LayoutView #document",
+      "reason": "style change"
+    },
+    {
       "object": "LayoutBlockFlow BODY",
       "reason": "style change"
     }
diff --git a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/platform/mac/paint/invalidation/compositing/fixed-pos-with-abs-pos-child-scroll-expected.txt b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/platform/mac/paint/invalidation/compositing/fixed-pos-with-abs-pos-child-scroll-expected.txt
new file mode 100644
index 0000000..c021b57
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/platform/mac/paint/invalidation/compositing/fixed-pos-with-abs-pos-child-scroll-expected.txt
@@ -0,0 +1,106 @@
+Hi!
+{
+  "layers": [
+    {
+      "name": "LayoutView #document",
+      "bounds": [800, 600],
+      "backgroundColor": "#FFFFFF"
+    },
+    {
+      "name": "Scrolling Layer",
+      "bounds": [785, 600],
+      "drawsContent": false
+    },
+    {
+      "name": "Scrolling Contents Layer",
+      "bounds": [785, 4021],
+      "contentsOpaque": true,
+      "backgroundColor": "#FFFFFF",
+      "paintInvalidations": [
+        {
+          "object": "LayoutBlockFlow (positioned) DIV id='abs'",
+          "rect": [425, 980, 360, 90],
+          "reason": "subtree"
+        },
+        {
+          "object": "LayoutBlockFlow (positioned) DIV id='abs'",
+          "rect": [425, 980, 360, 90],
+          "reason": "subtree"
+        },
+        {
+          "object": "LayoutBlockFlow (positioned) DIV id='abs'",
+          "rect": [425, 480, 360, 90],
+          "reason": "subtree"
+        },
+        {
+          "object": "LayoutBlockFlow (positioned) DIV id='abs'",
+          "rect": [425, 480, 360, 90],
+          "reason": "subtree"
+        },
+        {
+          "object": "LayoutText #text",
+          "rect": [425, 980, 22, 18],
+          "reason": "subtree"
+        },
+        {
+          "object": "LayoutText #text",
+          "rect": [425, 980, 22, 18],
+          "reason": "subtree"
+        },
+        {
+          "object": "LayoutText #text",
+          "rect": [425, 480, 22, 18],
+          "reason": "subtree"
+        },
+        {
+          "object": "LayoutText #text",
+          "rect": [425, 480, 22, 18],
+          "reason": "subtree"
+        }
+      ]
+    }
+  ],
+  "objectPaintInvalidations": [
+    {
+      "object": "LayoutBlockFlow (positioned) DIV id='fixed'",
+      "reason": "subtree"
+    },
+    {
+      "object": "LayoutBlockFlow (positioned) DIV id='abs'",
+      "reason": "subtree"
+    },
+    {
+      "object": "RootInlineBox",
+      "reason": "subtree"
+    },
+    {
+      "object": "LayoutText #text",
+      "reason": "subtree"
+    },
+    {
+      "object": "InlineTextBox 'Hi!'",
+      "reason": "subtree"
+    },
+    {
+      "object": "LayoutBlockFlow (positioned) DIV id='fixed'",
+      "reason": "subtree"
+    },
+    {
+      "object": "LayoutBlockFlow (positioned) DIV id='abs'",
+      "reason": "subtree"
+    },
+    {
+      "object": "RootInlineBox",
+      "reason": "subtree"
+    },
+    {
+      "object": "LayoutText #text",
+      "reason": "subtree"
+    },
+    {
+      "object": "InlineTextBox 'Hi!'",
+      "reason": "subtree"
+    }
+  ]
+}
+
diff --git a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/platform/mac/paint/invalidation/japanese-rl-selection-repaint-expected.txt b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/platform/mac/paint/invalidation/japanese-rl-selection-repaint-expected.txt
index b7e8f31..fd3c8db1 100644
--- a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/platform/mac/paint/invalidation/japanese-rl-selection-repaint-expected.txt
+++ b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/platform/mac/paint/invalidation/japanese-rl-selection-repaint-expected.txt
@@ -26,14 +26,6 @@
   ],
   "objectPaintInvalidations": [
     {
-      "object": "LayoutBlockFlow HTML",
-      "reason": "selection"
-    },
-    {
-      "object": "LayoutBlockFlow BODY",
-      "reason": "selection"
-    },
-    {
       "object": "LayoutText #text",
       "reason": "geometry"
     },
diff --git a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/platform/mac/paint/invalidation/multicol-as-paint-container-expected.txt b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/platform/mac/paint/invalidation/multicol-as-paint-container-expected.txt
index e9231e3..e6b74d7 100644
--- a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/platform/mac/paint/invalidation/multicol-as-paint-container-expected.txt
+++ b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/platform/mac/paint/invalidation/multicol-as-paint-container-expected.txt
@@ -29,7 +29,12 @@
         },
         {
           "object": "LayoutText #text",
-          "rect": [0, -1, 625, 181],
+          "rect": [325, -181, 300, 342],
+          "reason": "style change"
+        },
+        {
+          "object": "LayoutText #text",
+          "rect": [0, -1, 300, 342],
           "reason": "style change"
         }
       ]
@@ -109,6 +114,78 @@
       "reason": "style change"
     },
     {
+      "object": "LayoutText #text",
+      "reason": "style change"
+    },
+    {
+      "object": "InlineTextBox 'Lorem ipsum'",
+      "reason": "style change"
+    },
+    {
+      "object": "InlineTextBox 'dolor sit amet,'",
+      "reason": "style change"
+    },
+    {
+      "object": "InlineTextBox 'consectetur'",
+      "reason": "style change"
+    },
+    {
+      "object": "InlineTextBox 'adipiscing'",
+      "reason": "style change"
+    },
+    {
+      "object": "InlineTextBox 'elit. Fusce'",
+      "reason": "style change"
+    },
+    {
+      "object": "InlineTextBox 'varius, metus'",
+      "reason": "style change"
+    },
+    {
+      "object": "InlineTextBox 'eu fringilla'",
+      "reason": "style change"
+    },
+    {
+      "object": "InlineTextBox 'pulvinar, ipsum'",
+      "reason": "style change"
+    },
+    {
+      "object": "InlineTextBox 'sapien'",
+      "reason": "style change"
+    },
+    {
+      "object": "InlineTextBox 'ultricies arcu,'",
+      "reason": "style change"
+    },
+    {
+      "object": "InlineTextBox 'non condimentum'",
+      "reason": "style change"
+    },
+    {
+      "object": "InlineTextBox 'quam est eu'",
+      "reason": "style change"
+    },
+    {
+      "object": "InlineTextBox 'purus. Ut nisl'",
+      "reason": "style change"
+    },
+    {
+      "object": "InlineTextBox 'libero,'",
+      "reason": "style change"
+    },
+    {
+      "object": "InlineTextBox 'suscipit ut leo'",
+      "reason": "style change"
+    },
+    {
+      "object": "InlineTextBox 'eget, dapibus'",
+      "reason": "style change"
+    },
+    {
+      "object": "InlineTextBox 'ultrices dolor.'",
+      "reason": "style change"
+    },
+    {
       "object": "LayoutMultiColumnSet (anonymous)",
       "reason": "style change"
     }
diff --git a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/platform/mac/paint/invalidation/multicol-repaint-expected.txt b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/platform/mac/paint/invalidation/multicol-repaint-expected.txt
index 6688c196..545a7ff 100644
--- a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/platform/mac/paint/invalidation/multicol-repaint-expected.txt
+++ b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/platform/mac/paint/invalidation/multicol-repaint-expected.txt
@@ -17,13 +17,13 @@
       "backgroundColor": "#FFFFFF",
       "paintInvalidations": [
         {
-          "object": "LayoutMultiColumnFlowThread (anonymous)",
-          "rect": [9, 9, 400, 100],
+          "object": "LayoutInline SPAN id='a'",
+          "rect": [234, 9, 300, 59],
           "reason": "geometry"
         },
         {
           "object": "LayoutInline SPAN id='a'",
-          "rect": [234, 9, 300, 59],
+          "rect": [9, 109, 300, 59],
           "reason": "geometry"
         },
         {
@@ -33,10 +33,30 @@
         },
         {
           "object": "LayoutText #text",
-          "rect": [234, 14, 50, 52],
+          "rect": [9, 114, 300, 52],
+          "reason": "appeared"
+        },
+        {
+          "object": "LayoutText #text",
+          "rect": [9, 14, 275, 152],
           "reason": "disappeared"
         },
         {
+          "object": "LayoutMultiColumnFlowThread (anonymous)",
+          "rect": [234, -91, 175, 159],
+          "reason": "geometry"
+        },
+        {
+          "object": "LayoutMultiColumnFlowThread (anonymous)",
+          "rect": [9, 9, 175, 159],
+          "reason": "geometry"
+        },
+        {
+          "object": "LayoutText #text",
+          "rect": [234, -91, 13, 59],
+          "reason": "geometry"
+        },
+        {
           "object": "LayoutText #text",
           "rect": [9, 9, 13, 59],
           "reason": "geometry"
@@ -58,6 +78,14 @@
       "reason": "geometry"
     },
     {
+      "object": "LayoutMultiColumnFlowThread (anonymous)",
+      "reason": "geometry"
+    },
+    {
+      "object": "RootInlineBox",
+      "reason": "geometry"
+    },
+    {
       "object": "LayoutText #text",
       "reason": "geometry"
     },
@@ -66,6 +94,22 @@
       "reason": "geometry"
     },
     {
+      "object": "LayoutText #text",
+      "reason": "geometry"
+    },
+    {
+      "object": "InlineTextBox '\u00A0'",
+      "reason": "geometry"
+    },
+    {
+      "object": "LayoutBR BR",
+      "reason": "geometry"
+    },
+    {
+      "object": "InlineTextBox '\n'",
+      "reason": "geometry"
+    },
+    {
       "object": "LayoutBR BR",
       "reason": "geometry"
     },
@@ -82,6 +126,22 @@
       "reason": "geometry"
     },
     {
+      "object": "LayoutInline SPAN id='a'",
+      "reason": "geometry"
+    },
+    {
+      "object": "InlineFlowBox",
+      "reason": "geometry"
+    },
+    {
+      "object": "LayoutText #text",
+      "reason": "appeared"
+    },
+    {
+      "object": "InlineTextBox 'XXXXXX'",
+      "reason": "appeared"
+    },
+    {
       "object": "LayoutText #text",
       "reason": "appeared"
     },
diff --git a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/platform/mac/paint/invalidation/multicol-with-block-expected.txt b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/platform/mac/paint/invalidation/multicol-with-block-expected.txt
index ef72c728f..0a07531 100644
--- a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/platform/mac/paint/invalidation/multicol-with-block-expected.txt
+++ b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/platform/mac/paint/invalidation/multicol-with-block-expected.txt
@@ -17,13 +17,13 @@
       "backgroundColor": "#FFFFFF",
       "paintInvalidations": [
         {
-          "object": "LayoutText #text",
-          "rect": [328, 8, 240, 21],
+          "object": "LayoutBlockFlow DIV id='target'",
+          "rect": [488, 8, 150, 20],
           "reason": "style change"
         },
         {
-          "object": "LayoutBlockFlow DIV id='target'",
-          "rect": [488, 8, 150, 20],
+          "object": "LayoutText #text",
+          "rect": [488, 7, 80, 22],
           "reason": "style change"
         }
       ]
diff --git a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/platform/mac/paint/invalidation/multicol-with-inline-expected.txt b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/platform/mac/paint/invalidation/multicol-with-inline-expected.txt
index 1695efa6..97f4f4c 100644
--- a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/platform/mac/paint/invalidation/multicol-with-inline-expected.txt
+++ b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/platform/mac/paint/invalidation/multicol-with-inline-expected.txt
@@ -18,7 +18,22 @@
       "paintInvalidations": [
         {
           "object": "LayoutText #text",
-          "rect": [328, 8, 240, 21],
+          "rect": [488, 7, 80, 22],
+          "reason": "style change"
+        },
+        {
+          "object": "LayoutText #text",
+          "rect": [328, 27, 80, 22],
+          "reason": "style change"
+        },
+        {
+          "object": "LayoutText #text",
+          "rect": [168, 47, 80, 22],
+          "reason": "style change"
+        },
+        {
+          "object": "LayoutText #text",
+          "rect": [8, 67, 80, 22],
           "reason": "style change"
         }
       ]
@@ -30,6 +45,42 @@
       "reason": "style change"
     },
     {
+      "object": "LayoutInline SPAN id='target'",
+      "reason": "style change"
+    },
+    {
+      "object": "LayoutInline SPAN id='target'",
+      "reason": "style change"
+    },
+    {
+      "object": "LayoutInline SPAN id='target'",
+      "reason": "style change"
+    },
+    {
+      "object": "LayoutText #text",
+      "reason": "style change"
+    },
+    {
+      "object": "InlineTextBox 'PASS'",
+      "reason": "style change"
+    },
+    {
+      "object": "LayoutText #text",
+      "reason": "style change"
+    },
+    {
+      "object": "InlineTextBox 'PASS'",
+      "reason": "style change"
+    },
+    {
+      "object": "LayoutText #text",
+      "reason": "style change"
+    },
+    {
+      "object": "InlineTextBox 'PASS'",
+      "reason": "style change"
+    },
+    {
       "object": "LayoutText #text",
       "reason": "style change"
     },
diff --git a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/platform/mac/paint/invalidation/multicol-with-text-expected.txt b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/platform/mac/paint/invalidation/multicol-with-text-expected.txt
index 5d03cb54..6457196 100644
--- a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/platform/mac/paint/invalidation/multicol-with-text-expected.txt
+++ b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/platform/mac/paint/invalidation/multicol-with-text-expected.txt
@@ -17,18 +17,48 @@
       "backgroundColor": "#FFFFFF",
       "paintInvalidations": [
         {
-          "object": "LayoutMultiColumnFlowThread (anonymous)",
-          "rect": [8, 8, 630, 20],
-          "reason": "geometry"
-        },
-        {
           "object": "LayoutMultiColumnSet (anonymous)",
           "rect": [8, 8, 630, 20],
           "reason": "geometry"
         },
         {
+          "object": "LayoutMultiColumnFlowThread (anonymous)",
+          "rect": [488, -52, 150, 80],
+          "reason": "geometry"
+        },
+        {
+          "object": "LayoutMultiColumnFlowThread (anonymous)",
+          "rect": [328, -32, 150, 80],
+          "reason": "geometry"
+        },
+        {
+          "object": "LayoutMultiColumnFlowThread (anonymous)",
+          "rect": [168, -12, 150, 80],
+          "reason": "geometry"
+        },
+        {
+          "object": "LayoutMultiColumnFlowThread (anonymous)",
+          "rect": [8, 68, 150, 20],
+          "reason": "incremental"
+        },
+        {
           "object": "LayoutText #text",
-          "rect": [328, 8, 240, 21],
+          "rect": [488, 7, 80, 22],
+          "reason": "appeared"
+        },
+        {
+          "object": "LayoutText #text",
+          "rect": [328, 27, 80, 22],
+          "reason": "appeared"
+        },
+        {
+          "object": "LayoutText #text",
+          "rect": [168, 47, 80, 22],
+          "reason": "appeared"
+        },
+        {
+          "object": "LayoutText #text",
+          "rect": [8, 67, 80, 22],
           "reason": "appeared"
         }
       ]
@@ -37,6 +67,30 @@
   "objectPaintInvalidations": [
     {
       "object": "LayoutMultiColumnFlowThread (anonymous)",
+      "reason": "incremental"
+    },
+    {
+      "object": "RootInlineBox",
+      "reason": "incremental"
+    },
+    {
+      "object": "LayoutMultiColumnFlowThread (anonymous)",
+      "reason": "geometry"
+    },
+    {
+      "object": "RootInlineBox",
+      "reason": "geometry"
+    },
+    {
+      "object": "LayoutMultiColumnFlowThread (anonymous)",
+      "reason": "geometry"
+    },
+    {
+      "object": "RootInlineBox",
+      "reason": "geometry"
+    },
+    {
+      "object": "LayoutMultiColumnFlowThread (anonymous)",
       "reason": "geometry"
     },
     {
@@ -60,6 +114,110 @@
       "reason": "geometry"
     },
     {
+      "object": "LayoutBR BR",
+      "reason": "geometry"
+    },
+    {
+      "object": "InlineTextBox '\n'",
+      "reason": "geometry"
+    },
+    {
+      "object": "LayoutBR BR",
+      "reason": "geometry"
+    },
+    {
+      "object": "InlineTextBox '\n'",
+      "reason": "geometry"
+    },
+    {
+      "object": "LayoutBR BR",
+      "reason": "geometry"
+    },
+    {
+      "object": "InlineTextBox '\n'",
+      "reason": "geometry"
+    },
+    {
+      "object": "LayoutBR BR",
+      "reason": "geometry"
+    },
+    {
+      "object": "InlineTextBox '\n'",
+      "reason": "geometry"
+    },
+    {
+      "object": "LayoutBR BR",
+      "reason": "geometry"
+    },
+    {
+      "object": "InlineTextBox '\n'",
+      "reason": "geometry"
+    },
+    {
+      "object": "LayoutBR BR",
+      "reason": "geometry"
+    },
+    {
+      "object": "InlineTextBox '\n'",
+      "reason": "geometry"
+    },
+    {
+      "object": "LayoutBR BR",
+      "reason": "geometry"
+    },
+    {
+      "object": "InlineTextBox '\n'",
+      "reason": "geometry"
+    },
+    {
+      "object": "LayoutBR BR",
+      "reason": "geometry"
+    },
+    {
+      "object": "InlineTextBox '\n'",
+      "reason": "geometry"
+    },
+    {
+      "object": "LayoutBR BR",
+      "reason": "geometry"
+    },
+    {
+      "object": "InlineTextBox '\n'",
+      "reason": "geometry"
+    },
+    {
+      "object": "LayoutBR BR",
+      "reason": "geometry"
+    },
+    {
+      "object": "InlineTextBox '\n'",
+      "reason": "geometry"
+    },
+    {
+      "object": "LayoutText #text",
+      "reason": "appeared"
+    },
+    {
+      "object": "InlineTextBox 'PASS'",
+      "reason": "appeared"
+    },
+    {
+      "object": "LayoutText #text",
+      "reason": "appeared"
+    },
+    {
+      "object": "InlineTextBox 'PASS'",
+      "reason": "appeared"
+    },
+    {
+      "object": "LayoutText #text",
+      "reason": "appeared"
+    },
+    {
+      "object": "InlineTextBox 'PASS'",
+      "reason": "appeared"
+    },
+    {
       "object": "LayoutText #text",
       "reason": "appeared"
     },
diff --git a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/platform/mac/paint/invalidation/repaint-across-writing-mode-boundary-expected.txt b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/platform/mac/paint/invalidation/repaint-across-writing-mode-boundary-expected.txt
index e2d8b65..f0dcf919 100644
--- a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/platform/mac/paint/invalidation/repaint-across-writing-mode-boundary-expected.txt
+++ b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/platform/mac/paint/invalidation/repaint-across-writing-mode-boundary-expected.txt
@@ -26,26 +26,6 @@
   ],
   "objectPaintInvalidations": [
     {
-      "object": "LayoutBlockFlow HTML",
-      "reason": "selection"
-    },
-    {
-      "object": "LayoutBlockFlow BODY",
-      "reason": "selection"
-    },
-    {
-      "object": "LayoutBlockFlow DIV class='lrblock'",
-      "reason": "selection"
-    },
-    {
-      "object": "LayoutBlockFlow DIV class='basic d1 vert'",
-      "reason": "selection"
-    },
-    {
-      "object": "LayoutBlockFlow P",
-      "reason": "selection"
-    },
-    {
       "object": "LayoutText #text",
       "reason": "selection"
     },
diff --git a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/platform/mac/paint/invalidation/scrollbar-damage-and-full-viewport-repaint-expected.txt b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/platform/mac/paint/invalidation/scrollbar-damage-and-full-viewport-repaint-expected.txt
new file mode 100644
index 0000000..c811469
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/platform/mac/paint/invalidation/scrollbar-damage-and-full-viewport-repaint-expected.txt
@@ -0,0 +1,34 @@
+{
+  "layers": [
+    {
+      "name": "LayoutView #document",
+      "bounds": [1000, 600],
+      "backgroundColor": "#FFFFFF"
+    },
+    {
+      "name": "Scrolling Layer",
+      "bounds": [1000, 600],
+      "drawsContent": false
+    },
+    {
+      "name": "Scrolling Contents Layer",
+      "bounds": [1000, 600],
+      "contentsOpaque": true,
+      "backgroundColor": "#FFFFFF",
+      "paintInvalidations": [
+        {
+          "object": "LayoutBlockFlow DIV id='container'",
+          "rect": [1, 236, 185, 15],
+          "reason": "scroll control"
+        }
+      ]
+    }
+  ],
+  "objectPaintInvalidations": [
+    {
+      "object": "HorizontalScrollbar",
+      "reason": "scroll control"
+    }
+  ]
+}
+
diff --git a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/platform/mac/paint/invalidation/selection-after-remove-expected.txt b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/platform/mac/paint/invalidation/selection-after-remove-expected.txt
index 616cccea..5baba0b5 100644
--- a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/platform/mac/paint/invalidation/selection-after-remove-expected.txt
+++ b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/platform/mac/paint/invalidation/selection-after-remove-expected.txt
@@ -54,14 +54,6 @@
       "reason": "disappeared"
     },
     {
-      "object": "LayoutBlockFlow HTML",
-      "reason": "selection"
-    },
-    {
-      "object": "LayoutBlockFlow BODY",
-      "reason": "selection"
-    },
-    {
       "object": "LayoutBlockFlow DIV id='test'",
       "reason": "geometry"
     },
diff --git a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/platform/mac/paint/invalidation/selection-clear-expected.txt b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/platform/mac/paint/invalidation/selection-clear-expected.txt
index 84ed9ed..030f4e31 100644
--- a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/platform/mac/paint/invalidation/selection-clear-expected.txt
+++ b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/platform/mac/paint/invalidation/selection-clear-expected.txt
@@ -55,22 +55,10 @@
       "reason": "disappeared"
     },
     {
-      "object": "LayoutBlockFlow HTML",
-      "reason": "selection"
-    },
-    {
-      "object": "LayoutBlockFlow BODY",
-      "reason": "selection"
-    },
-    {
       "object": "LayoutBlockFlow DIV id='root'",
       "reason": "incremental"
     },
     {
-      "object": "LayoutBlockFlow DIV id='root'",
-      "reason": "selection"
-    },
-    {
       "object": "LayoutBlockFlow DIV id='firstLine'",
       "reason": "full"
     },
diff --git a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/platform/mac/paint/invalidation/selection-rl-expected.txt b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/platform/mac/paint/invalidation/selection-rl-expected.txt
index 3a0fcd2..6cd3ab43 100644
--- a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/platform/mac/paint/invalidation/selection-rl-expected.txt
+++ b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/platform/mac/paint/invalidation/selection-rl-expected.txt
@@ -26,14 +26,6 @@
   ],
   "objectPaintInvalidations": [
     {
-      "object": "LayoutBlockFlow HTML",
-      "reason": "selection"
-    },
-    {
-      "object": "LayoutBlockFlow BODY",
-      "reason": "selection"
-    },
-    {
       "object": "LayoutText #text",
       "reason": "selection"
     },
diff --git a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/platform/mac/paint/invalidation/selection/invalidation-rect-includes-newline-expected.txt b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/platform/mac/paint/invalidation/selection/invalidation-rect-includes-newline-expected.txt
index 5b8ba88..9894873 100644
--- a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/platform/mac/paint/invalidation/selection/invalidation-rect-includes-newline-expected.txt
+++ b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/platform/mac/paint/invalidation/selection/invalidation-rect-includes-newline-expected.txt
@@ -26,18 +26,6 @@
   ],
   "objectPaintInvalidations": [
     {
-      "object": "LayoutBlockFlow HTML",
-      "reason": "selection"
-    },
-    {
-      "object": "LayoutBlockFlow BODY",
-      "reason": "selection"
-    },
-    {
-      "object": "LayoutBlockFlow DIV id='container'",
-      "reason": "selection"
-    },
-    {
       "object": "LayoutText #text",
       "reason": "geometry"
     },
diff --git a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/platform/mac/paint/invalidation/selection/invalidation-rect-includes-newline-for-rtl-expected.txt b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/platform/mac/paint/invalidation/selection/invalidation-rect-includes-newline-for-rtl-expected.txt
index e4d0a97..66d8aab 100644
--- a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/platform/mac/paint/invalidation/selection/invalidation-rect-includes-newline-for-rtl-expected.txt
+++ b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/platform/mac/paint/invalidation/selection/invalidation-rect-includes-newline-for-rtl-expected.txt
@@ -26,18 +26,6 @@
   ],
   "objectPaintInvalidations": [
     {
-      "object": "LayoutBlockFlow HTML",
-      "reason": "selection"
-    },
-    {
-      "object": "LayoutBlockFlow BODY",
-      "reason": "selection"
-    },
-    {
-      "object": "LayoutBlockFlow DIV id='container'",
-      "reason": "selection"
-    },
-    {
       "object": "LayoutText #text",
       "reason": "geometry"
     },
diff --git a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/platform/mac/paint/invalidation/selection/invalidation-rect-includes-newline-for-vertical-lr-expected.txt b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/platform/mac/paint/invalidation/selection/invalidation-rect-includes-newline-for-vertical-lr-expected.txt
new file mode 100644
index 0000000..29a2c8d5
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/platform/mac/paint/invalidation/selection/invalidation-rect-includes-newline-for-vertical-lr-expected.txt
@@ -0,0 +1,42 @@
+{
+  "layers": [
+    {
+      "name": "LayoutView #document",
+      "bounds": [800, 600],
+      "backgroundColor": "#FFFFFF"
+    },
+    {
+      "name": "Scrolling Layer",
+      "bounds": [800, 600],
+      "drawsContent": false
+    },
+    {
+      "name": "Scrolling Contents Layer",
+      "bounds": [800, 600],
+      "contentsOpaque": true,
+      "backgroundColor": "#FFFFFF",
+      "paintInvalidations": [
+        {
+          "object": "LayoutText #text",
+          "rect": [7, 8, 34, 48],
+          "reason": "geometry"
+        }
+      ]
+    }
+  ],
+  "objectPaintInvalidations": [
+    {
+      "object": "LayoutText #text",
+      "reason": "geometry"
+    },
+    {
+      "object": "InlineTextBox 'xx'",
+      "reason": "geometry"
+    },
+    {
+      "object": "InlineTextBox 'y'",
+      "reason": "geometry"
+    }
+  ]
+}
+
diff --git a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/platform/mac/paint/invalidation/selection/invalidation-rect-includes-newline-for-vertical-rl-expected.txt b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/platform/mac/paint/invalidation/selection/invalidation-rect-includes-newline-for-vertical-rl-expected.txt
index 929842a5..d927d7a 100644
--- a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/platform/mac/paint/invalidation/selection/invalidation-rect-includes-newline-for-vertical-rl-expected.txt
+++ b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/platform/mac/paint/invalidation/selection/invalidation-rect-includes-newline-for-vertical-rl-expected.txt
@@ -26,18 +26,6 @@
   ],
   "objectPaintInvalidations": [
     {
-      "object": "LayoutBlockFlow HTML",
-      "reason": "selection"
-    },
-    {
-      "object": "LayoutBlockFlow BODY",
-      "reason": "selection"
-    },
-    {
-      "object": "LayoutBlockFlow DIV id='container'",
-      "reason": "selection"
-    },
-    {
       "object": "LayoutText #text",
       "reason": "geometry"
     },
diff --git a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/platform/mac/paint/invalidation/selection/invalidation-rect-with-br-includes-newline-expected.txt b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/platform/mac/paint/invalidation/selection/invalidation-rect-with-br-includes-newline-expected.txt
index 682030b..eee3ac19 100644
--- a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/platform/mac/paint/invalidation/selection/invalidation-rect-with-br-includes-newline-expected.txt
+++ b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/platform/mac/paint/invalidation/selection/invalidation-rect-with-br-includes-newline-expected.txt
@@ -36,18 +36,6 @@
   ],
   "objectPaintInvalidations": [
     {
-      "object": "LayoutBlockFlow HTML",
-      "reason": "selection"
-    },
-    {
-      "object": "LayoutBlockFlow BODY",
-      "reason": "selection"
-    },
-    {
-      "object": "LayoutBlockFlow DIV id='container'",
-      "reason": "selection"
-    },
-    {
       "object": "LayoutText #text",
       "reason": "selection"
     },
diff --git a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/platform/mac/paint/invalidation/selection/repaint-rect-for-vertical-writing-mode-with-positioned-root-expected.txt b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/platform/mac/paint/invalidation/selection/repaint-rect-for-vertical-writing-mode-with-positioned-root-expected.txt
index 4a1b94d..edadef5 100644
--- a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/platform/mac/paint/invalidation/selection/repaint-rect-for-vertical-writing-mode-with-positioned-root-expected.txt
+++ b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/platform/mac/paint/invalidation/selection/repaint-rect-for-vertical-writing-mode-with-positioned-root-expected.txt
@@ -26,14 +26,6 @@
   ],
   "objectPaintInvalidations": [
     {
-      "object": "LayoutBlockFlow (positioned) DIV id='test'",
-      "reason": "selection"
-    },
-    {
-      "object": "LayoutBlockFlow DIV",
-      "reason": "selection"
-    },
-    {
       "object": "LayoutText #text",
       "reason": "selection"
     },
diff --git a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/platform/mac/paint/invalidation/selection/selection-in-non-composited-scrolling-container-expected.txt b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/platform/mac/paint/invalidation/selection/selection-in-non-composited-scrolling-container-expected.txt
index 8a227f96..49b85eaa 100644
--- a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/platform/mac/paint/invalidation/selection/selection-in-non-composited-scrolling-container-expected.txt
+++ b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/platform/mac/paint/invalidation/selection/selection-in-non-composited-scrolling-container-expected.txt
@@ -22,7 +22,7 @@
           "reason": "subtree"
         },
         {
-          "object": "LayoutBlockFlow DIV id='inner-editor'",
+          "object": "LayoutBlockFlow DIV",
           "rect": [11, 11, 35, 13],
           "reason": "subtree"
         },
@@ -36,19 +36,11 @@
   ],
   "objectPaintInvalidations": [
     {
-      "object": "LayoutBlockFlow HTML",
-      "reason": "selection"
-    },
-    {
-      "object": "LayoutBlockFlow BODY",
-      "reason": "selection"
-    },
-    {
       "object": "LayoutTextControl INPUT id='target'",
       "reason": "subtree"
     },
     {
-      "object": "LayoutBlockFlow DIV id='inner-editor'",
+      "object": "LayoutBlockFlow DIV",
       "reason": "subtree"
     },
     {
diff --git a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/platform/mac/paint/invalidation/selection/selection-within-composited-scroller-expected.txt b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/platform/mac/paint/invalidation/selection/selection-within-composited-scroller-expected.txt
index 8a39ea4..ae51bebd 100644
--- a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/platform/mac/paint/invalidation/selection/selection-within-composited-scroller-expected.txt
+++ b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/platform/mac/paint/invalidation/selection/selection-within-composited-scroller-expected.txt
@@ -81,22 +81,6 @@
   ],
   "objectPaintInvalidations": [
     {
-      "object": "LayoutBlockFlow HTML",
-      "reason": "selection"
-    },
-    {
-      "object": "LayoutBlockFlow BODY",
-      "reason": "selection"
-    },
-    {
-      "object": "LayoutBlockFlow DIV id='scroller'",
-      "reason": "selection"
-    },
-    {
-      "object": "LayoutBlockFlow DIV id='target'",
-      "reason": "selection"
-    },
-    {
       "object": "LayoutText #text",
       "reason": "selection"
     },
diff --git a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/platform/mac/paint/invalidation/svg/append-text-node-to-tspan-expected.txt b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/platform/mac/paint/invalidation/svg/append-text-node-to-tspan-expected.txt
index 4bfd740..06db9dd 100644
--- a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/platform/mac/paint/invalidation/svg/append-text-node-to-tspan-expected.txt
+++ b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/platform/mac/paint/invalidation/svg/append-text-node-to-tspan-expected.txt
@@ -18,52 +18,52 @@
       "paintInvalidations": [
         {
           "object": "LayoutSVGInlineText #text",
-          "rect": [10, 62, 306, 378],
+          "rect": [10, 61, 306, 379],
           "reason": "geometry"
         },
         {
           "object": "LayoutSVGInlineText #text",
-          "rect": [10, 62, 306, 378],
+          "rect": [10, 61, 306, 379],
           "reason": "geometry"
         },
         {
           "object": "LayoutSVGInlineText #text",
-          "rect": [10, 62, 306, 378],
+          "rect": [10, 61, 306, 379],
           "reason": "geometry"
         },
         {
           "object": "LayoutSVGInlineText #text",
-          "rect": [10, 62, 306, 378],
+          "rect": [10, 61, 306, 379],
           "reason": "geometry"
         },
         {
           "object": "LayoutSVGInlineText #text",
-          "rect": [10, 62, 306, 378],
+          "rect": [10, 61, 306, 379],
           "reason": "geometry"
         },
         {
           "object": "LayoutSVGInlineText #text",
-          "rect": [10, 62, 306, 378],
+          "rect": [10, 61, 306, 379],
           "reason": "appeared"
         },
         {
           "object": "LayoutSVGTSpan tspan",
-          "rect": [10, 62, 306, 378],
+          "rect": [10, 61, 306, 379],
           "reason": "geometry"
         },
         {
           "object": "LayoutSVGTSpan tspan",
-          "rect": [10, 62, 306, 378],
+          "rect": [10, 61, 306, 379],
           "reason": "geometry"
         },
         {
           "object": "LayoutSVGTSpan tspan id='modify'",
-          "rect": [10, 62, 306, 378],
+          "rect": [10, 61, 306, 379],
           "reason": "geometry"
         },
         {
           "object": "LayoutSVGText text",
-          "rect": [10, 62, 306, 378],
+          "rect": [10, 61, 306, 379],
           "reason": "style change"
         }
       ]
diff --git a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/platform/mac/paint/invalidation/svg/js-late-gradient-and-object-creation-expected.txt b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/platform/mac/paint/invalidation/svg/js-late-gradient-and-object-creation-expected.txt
index e4aaaa48..0be7bbd 100644
--- a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/platform/mac/paint/invalidation/svg/js-late-gradient-and-object-creation-expected.txt
+++ b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/platform/mac/paint/invalidation/svg/js-late-gradient-and-object-creation-expected.txt
@@ -33,12 +33,12 @@
         },
         {
           "object": "LayoutSVGInlineText #text",
-          "rect": [0, 129, 596, 135],
+          "rect": [0, 129, 596, 134],
           "reason": "appeared"
         },
         {
           "object": "LayoutSVGText text",
-          "rect": [0, 129, 596, 135],
+          "rect": [0, 129, 596, 134],
           "reason": "appeared"
         },
         {
diff --git a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/platform/mac/paint/invalidation/svg/js-late-gradient-creation-expected.txt b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/platform/mac/paint/invalidation/svg/js-late-gradient-creation-expected.txt
index a4c3211b..59fe98c 100644
--- a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/platform/mac/paint/invalidation/svg/js-late-gradient-creation-expected.txt
+++ b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/platform/mac/paint/invalidation/svg/js-late-gradient-creation-expected.txt
@@ -18,12 +18,12 @@
       "paintInvalidations": [
         {
           "object": "LayoutSVGInlineText #text",
-          "rect": [33, 22, 693, 196],
+          "rect": [33, 21, 693, 197],
           "reason": "geometry"
         },
         {
           "object": "LayoutSVGText text",
-          "rect": [33, 22, 693, 196],
+          "rect": [33, 21, 693, 197],
           "reason": "style change"
         }
       ]
diff --git a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/platform/mac/paint/invalidation/svg/js-late-pattern-and-object-creation-expected.txt b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/platform/mac/paint/invalidation/svg/js-late-pattern-and-object-creation-expected.txt
index 074081f..80c806d 100644
--- a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/platform/mac/paint/invalidation/svg/js-late-pattern-and-object-creation-expected.txt
+++ b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/platform/mac/paint/invalidation/svg/js-late-pattern-and-object-creation-expected.txt
@@ -33,12 +33,12 @@
         },
         {
           "object": "LayoutSVGInlineText #text",
-          "rect": [0, 129, 520, 135],
+          "rect": [0, 129, 520, 134],
           "reason": "appeared"
         },
         {
           "object": "LayoutSVGText text",
-          "rect": [0, 129, 520, 135],
+          "rect": [0, 129, 520, 134],
           "reason": "appeared"
         },
         {
diff --git a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/platform/mac/paint/invalidation/svg/js-late-pattern-creation-expected.txt b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/platform/mac/paint/invalidation/svg/js-late-pattern-creation-expected.txt
index 50fb337..0662de79 100644
--- a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/platform/mac/paint/invalidation/svg/js-late-pattern-creation-expected.txt
+++ b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/platform/mac/paint/invalidation/svg/js-late-pattern-creation-expected.txt
@@ -18,12 +18,12 @@
       "paintInvalidations": [
         {
           "object": "LayoutSVGInlineText #text",
-          "rect": [33, 22, 618, 196],
+          "rect": [33, 21, 618, 197],
           "reason": "geometry"
         },
         {
           "object": "LayoutSVGText text",
-          "rect": [33, 22, 618, 196],
+          "rect": [33, 21, 618, 197],
           "reason": "style change"
         }
       ]
diff --git a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/platform/mac/paint/invalidation/svg/modify-text-node-in-tspan-expected.txt b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/platform/mac/paint/invalidation/svg/modify-text-node-in-tspan-expected.txt
index 46c7fc1..f55b365 100644
--- a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/platform/mac/paint/invalidation/svg/modify-text-node-in-tspan-expected.txt
+++ b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/platform/mac/paint/invalidation/svg/modify-text-node-in-tspan-expected.txt
@@ -18,47 +18,47 @@
       "paintInvalidations": [
         {
           "object": "LayoutSVGInlineText #text",
-          "rect": [10, 62, 306, 378],
+          "rect": [10, 61, 306, 379],
           "reason": "full"
         },
         {
           "object": "LayoutSVGInlineText #text",
-          "rect": [10, 62, 306, 378],
+          "rect": [10, 61, 306, 379],
           "reason": "geometry"
         },
         {
           "object": "LayoutSVGInlineText #text",
-          "rect": [10, 62, 306, 378],
+          "rect": [10, 61, 306, 379],
           "reason": "geometry"
         },
         {
           "object": "LayoutSVGInlineText #text",
-          "rect": [10, 62, 306, 378],
+          "rect": [10, 61, 306, 379],
           "reason": "geometry"
         },
         {
           "object": "LayoutSVGInlineText #text",
-          "rect": [10, 62, 306, 378],
+          "rect": [10, 61, 306, 379],
           "reason": "geometry"
         },
         {
           "object": "LayoutSVGTSpan tspan",
-          "rect": [10, 62, 306, 378],
+          "rect": [10, 61, 306, 379],
           "reason": "geometry"
         },
         {
           "object": "LayoutSVGTSpan tspan",
-          "rect": [10, 62, 306, 378],
+          "rect": [10, 61, 306, 379],
           "reason": "geometry"
         },
         {
           "object": "LayoutSVGTSpan tspan id='modify'",
-          "rect": [10, 62, 306, 378],
+          "rect": [10, 61, 306, 379],
           "reason": "geometry"
         },
         {
           "object": "LayoutSVGText text",
-          "rect": [10, 62, 306, 378],
+          "rect": [10, 61, 306, 379],
           "reason": "full"
         }
       ]
diff --git a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/platform/mac/paint/invalidation/svg/remove-text-node-from-tspan-expected.txt b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/platform/mac/paint/invalidation/svg/remove-text-node-from-tspan-expected.txt
index d52fe70..855d21911 100644
--- a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/platform/mac/paint/invalidation/svg/remove-text-node-from-tspan-expected.txt
+++ b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/platform/mac/paint/invalidation/svg/remove-text-node-from-tspan-expected.txt
@@ -18,52 +18,52 @@
       "paintInvalidations": [
         {
           "object": "LayoutSVGInlineText #text",
-          "rect": [10, 62, 306, 378],
+          "rect": [10, 61, 306, 379],
           "reason": "geometry"
         },
         {
           "object": "LayoutSVGInlineText #text",
-          "rect": [10, 62, 306, 378],
+          "rect": [10, 61, 306, 379],
           "reason": "geometry"
         },
         {
           "object": "LayoutSVGInlineText #text",
-          "rect": [10, 62, 306, 378],
+          "rect": [10, 61, 306, 379],
           "reason": "geometry"
         },
         {
           "object": "LayoutSVGInlineText #text",
-          "rect": [10, 62, 306, 378],
+          "rect": [10, 61, 306, 379],
           "reason": "geometry"
         },
         {
           "object": "LayoutSVGInlineText #text",
-          "rect": [10, 62, 306, 378],
+          "rect": [10, 61, 306, 379],
           "reason": "geometry"
         },
         {
           "object": "LayoutSVGInlineText #text",
-          "rect": [10, 62, 306, 378],
+          "rect": [10, 61, 306, 379],
           "reason": "disappeared"
         },
         {
           "object": "LayoutSVGTSpan tspan",
-          "rect": [10, 62, 306, 378],
+          "rect": [10, 61, 306, 379],
           "reason": "geometry"
         },
         {
           "object": "LayoutSVGTSpan tspan",
-          "rect": [10, 62, 306, 378],
+          "rect": [10, 61, 306, 379],
           "reason": "geometry"
         },
         {
           "object": "LayoutSVGTSpan tspan id='modify'",
-          "rect": [10, 62, 306, 378],
+          "rect": [10, 61, 306, 379],
           "reason": "geometry"
         },
         {
           "object": "LayoutSVGText text",
-          "rect": [10, 62, 306, 378],
+          "rect": [10, 61, 306, 379],
           "reason": "full"
         }
       ]
diff --git a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/platform/mac/paint/invalidation/svg/remove-tspan-from-text-expected.txt b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/platform/mac/paint/invalidation/svg/remove-tspan-from-text-expected.txt
index f7ed8f9..85c48b1 100644
--- a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/platform/mac/paint/invalidation/svg/remove-tspan-from-text-expected.txt
+++ b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/platform/mac/paint/invalidation/svg/remove-tspan-from-text-expected.txt
@@ -18,47 +18,47 @@
       "paintInvalidations": [
         {
           "object": "LayoutSVGInlineText #text",
-          "rect": [10, 62, 306, 258],
+          "rect": [10, 61, 306, 259],
           "reason": "geometry"
         },
         {
           "object": "LayoutSVGInlineText #text",
-          "rect": [10, 62, 306, 258],
+          "rect": [10, 61, 306, 259],
           "reason": "geometry"
         },
         {
           "object": "LayoutSVGInlineText #text",
-          "rect": [10, 62, 306, 258],
+          "rect": [10, 61, 306, 259],
           "reason": "geometry"
         },
         {
           "object": "LayoutSVGInlineText #text",
-          "rect": [10, 62, 306, 258],
+          "rect": [10, 61, 306, 259],
           "reason": "disappeared"
         },
         {
           "object": "LayoutSVGInlineText #text",
-          "rect": [10, 62, 306, 258],
+          "rect": [10, 61, 306, 259],
           "reason": "disappeared"
         },
         {
           "object": "LayoutSVGTSpan tspan",
-          "rect": [10, 62, 306, 258],
+          "rect": [10, 61, 306, 259],
           "reason": "geometry"
         },
         {
           "object": "LayoutSVGTSpan tspan",
-          "rect": [10, 62, 306, 258],
+          "rect": [10, 61, 306, 259],
           "reason": "geometry"
         },
         {
           "object": "LayoutSVGTSpan tspan id='remove'",
-          "rect": [10, 62, 306, 258],
+          "rect": [10, 61, 306, 259],
           "reason": "disappeared"
         },
         {
           "object": "LayoutSVGText text id='text'",
-          "rect": [10, 62, 306, 258],
+          "rect": [10, 61, 306, 259],
           "reason": "full"
         }
       ]
diff --git a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/platform/mac/paint/invalidation/svg/text-viewbox-rescale-expected.txt b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/platform/mac/paint/invalidation/svg/text-viewbox-rescale-expected.txt
index 6164f901f..3762833 100644
--- a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/platform/mac/paint/invalidation/svg/text-viewbox-rescale-expected.txt
+++ b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/platform/mac/paint/invalidation/svg/text-viewbox-rescale-expected.txt
@@ -18,57 +18,57 @@
       "paintInvalidations": [
         {
           "object": "LayoutSVGInlineText #text",
-          "rect": [59, 143, 95, 23],
+          "rect": [59, 140, 98, 23],
           "reason": "geometry"
         },
         {
           "object": "LayoutSVGInlineText #text",
-          "rect": [59, 143, 95, 23],
+          "rect": [59, 140, 98, 23],
           "reason": "geometry"
         },
         {
           "object": "LayoutSVGTSpan tspan",
-          "rect": [59, 143, 95, 23],
+          "rect": [59, 140, 98, 23],
           "reason": "full"
         },
         {
           "object": "LayoutSVGText text",
-          "rect": [59, 143, 95, 23],
+          "rect": [59, 140, 98, 23],
           "reason": "full"
         },
         {
           "object": "LayoutSVGViewportContainer svg id='inner2'",
-          "rect": [59, 143, 95, 23],
+          "rect": [59, 140, 98, 23],
           "reason": "full"
         },
         {
           "object": "LayoutSVGInlineText #text",
-          "rect": [59, 43, 95, 23],
+          "rect": [59, 40, 98, 23],
           "reason": "geometry"
         },
         {
           "object": "LayoutSVGInlineText #text",
-          "rect": [59, 43, 95, 23],
+          "rect": [59, 40, 98, 23],
           "reason": "geometry"
         },
         {
           "object": "LayoutSVGInlineText #text",
-          "rect": [59, 43, 95, 23],
+          "rect": [59, 40, 98, 23],
           "reason": "geometry"
         },
         {
           "object": "LayoutSVGTSpan tspan",
-          "rect": [59, 43, 95, 23],
+          "rect": [59, 40, 98, 23],
           "reason": "full"
         },
         {
           "object": "LayoutSVGText text",
-          "rect": [59, 43, 95, 23],
+          "rect": [59, 40, 98, 23],
           "reason": "full"
         },
         {
           "object": "LayoutSVGViewportContainer svg id='inner1'",
-          "rect": [59, 43, 95, 23],
+          "rect": [59, 40, 98, 23],
           "reason": "full"
         },
         {
diff --git a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/platform/mac/paint/invalidation/svg/window-expected.txt b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/platform/mac/paint/invalidation/svg/window-expected.txt
index 0b33d8ec..2dad79b 100644
--- a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/platform/mac/paint/invalidation/svg/window-expected.txt
+++ b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/platform/mac/paint/invalidation/svg/window-expected.txt
@@ -458,12 +458,12 @@
         },
         {
           "object": "LayoutSVGInlineText #text",
-          "rect": [41, 525, 102, 10],
+          "rect": [41, 525, 102, 9],
           "reason": "appeared"
         },
         {
           "object": "LayoutSVGText text",
-          "rect": [41, 525, 102, 10],
+          "rect": [41, 525, 102, 9],
           "reason": "appeared"
         },
         {
@@ -498,12 +498,12 @@
         },
         {
           "object": "LayoutSVGInlineText #text",
-          "rect": [80, 197, 67, 13],
+          "rect": [80, 197, 67, 12],
           "reason": "appeared"
         },
         {
           "object": "LayoutSVGText text",
-          "rect": [80, 197, 67, 13],
+          "rect": [80, 197, 67, 12],
           "reason": "appeared"
         },
         {
@@ -562,6 +562,16 @@
           "reason": "appeared"
         },
         {
+          "object": "LayoutSVGInlineText #text",
+          "rect": [616, 153, 11, 81],
+          "reason": "appeared"
+        },
+        {
+          "object": "LayoutSVGText text",
+          "rect": [616, 153, 11, 81],
+          "reason": "appeared"
+        },
+        {
           "object": "LayoutSVGPath line",
           "rect": [616, 83, 11, 12],
           "reason": "geometry"
@@ -732,16 +742,6 @@
           "reason": "appeared"
         },
         {
-          "object": "LayoutSVGInlineText #text",
-          "rect": [617, 153, 10, 81],
-          "reason": "appeared"
-        },
-        {
-          "object": "LayoutSVGText text",
-          "rect": [617, 153, 10, 81],
-          "reason": "appeared"
-        },
-        {
           "object": "LayoutSVGContainer use id='closeButtonnestedWindow'",
           "rect": [377, 184, 10, 11],
           "reason": "appeared"
diff --git a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/platform/win/css3/filters/composited-layer-child-bounds-after-composited-to-sw-shadow-change-expected.txt b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/platform/win/css3/filters/composited-layer-child-bounds-after-composited-to-sw-shadow-change-expected.txt
new file mode 100644
index 0000000..1be42ec
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/platform/win/css3/filters/composited-layer-child-bounds-after-composited-to-sw-shadow-change-expected.txt
@@ -0,0 +1,91 @@
+{
+  "layers": [
+    {
+      "name": "LayoutView #document",
+      "bounds": [800, 600],
+      "backgroundColor": "#FFFFFF"
+    },
+    {
+      "name": "Scrolling Layer",
+      "bounds": [800, 600],
+      "drawsContent": false
+    },
+    {
+      "name": "Scrolling Contents Layer",
+      "bounds": [800, 600],
+      "contentsOpaque": true,
+      "backgroundColor": "#FFFFFF"
+    },
+    {
+      "name": "LayoutBlockFlow (positioned) DIV id='composited-parent' class='compositor-painted-shadow'",
+      "bounds": [100, 100],
+      "contentsOpaque": true,
+      "backgroundColor": "#FF0000",
+      "transform": 1
+    },
+    {
+      "name": "LayoutBlockFlow (positioned) DIV id='absolutely-positioned-composited-child'",
+      "bounds": [100, 100],
+      "contentsOpaque": true,
+      "backgroundColor": "#008000",
+      "transform": 1
+    }
+  ],
+  "transforms": [
+    {
+      "id": 1,
+      "transform": [
+        [1, 0, 0, 0],
+        [0, 1, 0, 0],
+        [0, 0, 1, 0],
+        [100, 100, 0, 1]
+      ]
+    }
+  ]
+}
+{
+  "layers": [
+    {
+      "name": "LayoutView #document",
+      "bounds": [800, 600],
+      "backgroundColor": "#FFFFFF"
+    },
+    {
+      "name": "Scrolling Layer",
+      "bounds": [785, 585],
+      "drawsContent": false
+    },
+    {
+      "name": "Scrolling Contents Layer",
+      "bounds": [856, 741],
+      "contentsOpaque": true,
+      "backgroundColor": "#FFFFFF"
+    },
+    {
+      "name": "LayoutBlockFlow (positioned) DIV id='composited-parent' class='software-painted-shadow'",
+      "bounds": [100, 100],
+      "contentsOpaque": true,
+      "backgroundColor": "#FF0000",
+      "transform": 1
+    },
+    {
+      "name": "LayoutBlockFlow (positioned) DIV id='absolutely-positioned-composited-child'",
+      "bounds": [100, 100],
+      "contentsOpaque": true,
+      "backgroundColor": "#008000",
+      "transform": 1
+    }
+  ],
+  "transforms": [
+    {
+      "id": 1,
+      "transform": [
+        [1, 0, 0, 0],
+        [0, 1, 0, 0],
+        [0, 0, 1, 0],
+        [100, 100, 0, 1]
+      ]
+    }
+  ]
+}
+
diff --git a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/platform/win/css3/filters/composited-layer-promotion-after-outset-overlap-change-using-composited-shadow-expected.txt b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/platform/win/css3/filters/composited-layer-promotion-after-outset-overlap-change-using-composited-shadow-expected.txt
new file mode 100644
index 0000000..de45639
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/platform/win/css3/filters/composited-layer-promotion-after-outset-overlap-change-using-composited-shadow-expected.txt
@@ -0,0 +1,84 @@
+{
+  "layers": [
+    {
+      "name": "LayoutView #document",
+      "bounds": [800, 600],
+      "backgroundColor": "#FFFFFF"
+    },
+    {
+      "name": "Scrolling Layer",
+      "bounds": [800, 600],
+      "drawsContent": false
+    },
+    {
+      "name": "Scrolling Contents Layer",
+      "bounds": [800, 600],
+      "contentsOpaque": true,
+      "backgroundColor": "#FFFFFF"
+    },
+    {
+      "name": "LayoutBlockFlow (positioned) DIV id='composited-layer-to-overlap'",
+      "bounds": [100, 100],
+      "contentsOpaque": true,
+      "backgroundColor": "#0000FF",
+      "transform": 1
+    }
+  ],
+  "transforms": [
+    {
+      "id": 1,
+      "transform": [
+        [1, 0, 0, 0],
+        [0, 1, 0, 0],
+        [0, 0, 1, 0],
+        [250, 250, 0, 1]
+      ]
+    }
+  ]
+}
+{
+  "layers": [
+    {
+      "name": "LayoutView #document",
+      "bounds": [800, 600],
+      "backgroundColor": "#FFFFFF"
+    },
+    {
+      "name": "Scrolling Layer",
+      "bounds": [785, 600],
+      "drawsContent": false
+    },
+    {
+      "name": "Scrolling Contents Layer",
+      "bounds": [785, 629],
+      "contentsOpaque": true,
+      "backgroundColor": "#FFFFFF"
+    },
+    {
+      "name": "LayoutBlockFlow (positioned) DIV id='composited-layer-to-overlap'",
+      "bounds": [100, 100],
+      "contentsOpaque": true,
+      "backgroundColor": "#0000FF",
+      "transform": 1
+    },
+    {
+      "name": "LayoutBlockFlow (positioned) DIV id='software-layer-to-promote' class='final-drop-shadow'",
+      "position": [100, 100],
+      "bounds": [100, 100],
+      "contentsOpaque": true,
+      "backgroundColor": "#000000"
+    }
+  ],
+  "transforms": [
+    {
+      "id": 1,
+      "transform": [
+        [1, 0, 0, 0],
+        [0, 1, 0, 0],
+        [0, 0, 1, 0],
+        [250, 250, 0, 1]
+      ]
+    }
+  ]
+}
+
diff --git a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/platform/win/css3/filters/composited-layer-promotion-after-outset-overlap-change-using-sw-shadow-expected.txt b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/platform/win/css3/filters/composited-layer-promotion-after-outset-overlap-change-using-sw-shadow-expected.txt
new file mode 100644
index 0000000..de45639
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/platform/win/css3/filters/composited-layer-promotion-after-outset-overlap-change-using-sw-shadow-expected.txt
@@ -0,0 +1,84 @@
+{
+  "layers": [
+    {
+      "name": "LayoutView #document",
+      "bounds": [800, 600],
+      "backgroundColor": "#FFFFFF"
+    },
+    {
+      "name": "Scrolling Layer",
+      "bounds": [800, 600],
+      "drawsContent": false
+    },
+    {
+      "name": "Scrolling Contents Layer",
+      "bounds": [800, 600],
+      "contentsOpaque": true,
+      "backgroundColor": "#FFFFFF"
+    },
+    {
+      "name": "LayoutBlockFlow (positioned) DIV id='composited-layer-to-overlap'",
+      "bounds": [100, 100],
+      "contentsOpaque": true,
+      "backgroundColor": "#0000FF",
+      "transform": 1
+    }
+  ],
+  "transforms": [
+    {
+      "id": 1,
+      "transform": [
+        [1, 0, 0, 0],
+        [0, 1, 0, 0],
+        [0, 0, 1, 0],
+        [250, 250, 0, 1]
+      ]
+    }
+  ]
+}
+{
+  "layers": [
+    {
+      "name": "LayoutView #document",
+      "bounds": [800, 600],
+      "backgroundColor": "#FFFFFF"
+    },
+    {
+      "name": "Scrolling Layer",
+      "bounds": [785, 600],
+      "drawsContent": false
+    },
+    {
+      "name": "Scrolling Contents Layer",
+      "bounds": [785, 629],
+      "contentsOpaque": true,
+      "backgroundColor": "#FFFFFF"
+    },
+    {
+      "name": "LayoutBlockFlow (positioned) DIV id='composited-layer-to-overlap'",
+      "bounds": [100, 100],
+      "contentsOpaque": true,
+      "backgroundColor": "#0000FF",
+      "transform": 1
+    },
+    {
+      "name": "LayoutBlockFlow (positioned) DIV id='software-layer-to-promote' class='final-drop-shadow'",
+      "position": [100, 100],
+      "bounds": [100, 100],
+      "contentsOpaque": true,
+      "backgroundColor": "#000000"
+    }
+  ],
+  "transforms": [
+    {
+      "id": 1,
+      "transform": [
+        [1, 0, 0, 0],
+        [0, 1, 0, 0],
+        [0, 0, 1, 0],
+        [250, 250, 0, 1]
+      ]
+    }
+  ]
+}
+
diff --git a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/platform/win/paint/invalidation/background-image-paint-invalidation-large-abspos-div-expected.txt b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/platform/win/paint/invalidation/background-image-paint-invalidation-large-abspos-div-expected.txt
new file mode 100644
index 0000000..4cb443e
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/platform/win/paint/invalidation/background-image-paint-invalidation-large-abspos-div-expected.txt
@@ -0,0 +1,10 @@
+layer at (0,0) size 800x600 clip at (0,0) size 785x600 scrollY 3000.00 scrollHeight 4008
+  LayoutView at (0,0) size 800x600
+layer at (0,-3000) size 785x558 backgroundClip at (0,0) size 785x600 clip at (0,0) size 785x600
+  LayoutBlockFlow {HTML} at (0,0) size 785x558
+    LayoutBlockFlow {BODY} at (8,8) size 769x542
+      LayoutImage {IMG} at (0,0) size 489x537
+      LayoutText {#text} at (0,0) size 0x0
+layer at (8,-2992) size 100x4000 backgroundClip at (0,0) size 785x600 clip at (0,0) size 785x600
+  LayoutBlockFlow (positioned) {DIV} at (8,8) size 100x4000
+scrolled to 0,3000
diff --git a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/platform/win/paint/invalidation/body-background-image-expected.txt b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/platform/win/paint/invalidation/body-background-image-expected.txt
index 27570fa..cdbd30c5 100644
--- a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/platform/win/paint/invalidation/body-background-image-expected.txt
+++ b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/platform/win/paint/invalidation/body-background-image-expected.txt
@@ -3,7 +3,14 @@
     {
       "name": "LayoutView #document",
       "bounds": [800, 600],
-      "backgroundColor": "#FFFFFF"
+      "backgroundColor": "#FFFFFF",
+      "paintInvalidations": [
+        {
+          "object": "LayoutView #document",
+          "rect": [0, 0, 800, 600],
+          "reason": "style change"
+        }
+      ]
     },
     {
       "name": "Scrolling Layer",
@@ -26,6 +33,10 @@
   ],
   "objectPaintInvalidations": [
     {
+      "object": "LayoutView #document",
+      "reason": "style change"
+    },
+    {
       "object": "LayoutBlockFlow BODY",
       "reason": "style change"
     }
diff --git a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/platform/win/paint/invalidation/compositing/fixed-pos-with-abs-pos-child-scroll-expected.txt b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/platform/win/paint/invalidation/compositing/fixed-pos-with-abs-pos-child-scroll-expected.txt
new file mode 100644
index 0000000..57e8e09
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/platform/win/paint/invalidation/compositing/fixed-pos-with-abs-pos-child-scroll-expected.txt
@@ -0,0 +1,106 @@
+Hi!
+{
+  "layers": [
+    {
+      "name": "LayoutView #document",
+      "bounds": [800, 600],
+      "backgroundColor": "#FFFFFF"
+    },
+    {
+      "name": "Scrolling Layer",
+      "bounds": [785, 600],
+      "drawsContent": false
+    },
+    {
+      "name": "Scrolling Contents Layer",
+      "bounds": [785, 4021],
+      "contentsOpaque": true,
+      "backgroundColor": "#FFFFFF",
+      "paintInvalidations": [
+        {
+          "object": "LayoutBlockFlow (positioned) DIV id='abs'",
+          "rect": [425, 980, 360, 90],
+          "reason": "subtree"
+        },
+        {
+          "object": "LayoutBlockFlow (positioned) DIV id='abs'",
+          "rect": [425, 980, 360, 90],
+          "reason": "subtree"
+        },
+        {
+          "object": "LayoutBlockFlow (positioned) DIV id='abs'",
+          "rect": [425, 480, 360, 90],
+          "reason": "subtree"
+        },
+        {
+          "object": "LayoutBlockFlow (positioned) DIV id='abs'",
+          "rect": [425, 480, 360, 90],
+          "reason": "subtree"
+        },
+        {
+          "object": "LayoutText #text",
+          "rect": [425, 980, 19, 19],
+          "reason": "subtree"
+        },
+        {
+          "object": "LayoutText #text",
+          "rect": [425, 980, 19, 19],
+          "reason": "subtree"
+        },
+        {
+          "object": "LayoutText #text",
+          "rect": [425, 480, 19, 19],
+          "reason": "subtree"
+        },
+        {
+          "object": "LayoutText #text",
+          "rect": [425, 480, 19, 19],
+          "reason": "subtree"
+        }
+      ]
+    }
+  ],
+  "objectPaintInvalidations": [
+    {
+      "object": "LayoutBlockFlow (positioned) DIV id='fixed'",
+      "reason": "subtree"
+    },
+    {
+      "object": "LayoutBlockFlow (positioned) DIV id='abs'",
+      "reason": "subtree"
+    },
+    {
+      "object": "RootInlineBox",
+      "reason": "subtree"
+    },
+    {
+      "object": "LayoutText #text",
+      "reason": "subtree"
+    },
+    {
+      "object": "InlineTextBox 'Hi!'",
+      "reason": "subtree"
+    },
+    {
+      "object": "LayoutBlockFlow (positioned) DIV id='fixed'",
+      "reason": "subtree"
+    },
+    {
+      "object": "LayoutBlockFlow (positioned) DIV id='abs'",
+      "reason": "subtree"
+    },
+    {
+      "object": "RootInlineBox",
+      "reason": "subtree"
+    },
+    {
+      "object": "LayoutText #text",
+      "reason": "subtree"
+    },
+    {
+      "object": "InlineTextBox 'Hi!'",
+      "reason": "subtree"
+    }
+  ]
+}
+
diff --git a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/platform/win/paint/invalidation/japanese-rl-selection-repaint-expected.txt b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/platform/win/paint/invalidation/japanese-rl-selection-repaint-expected.txt
index 70ad7c7..7294184 100644
--- a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/platform/win/paint/invalidation/japanese-rl-selection-repaint-expected.txt
+++ b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/platform/win/paint/invalidation/japanese-rl-selection-repaint-expected.txt
@@ -18,7 +18,7 @@
       "paintInvalidations": [
         {
           "object": "LayoutText #text",
-          "rect": [378, 23, 394, 544],
+          "rect": [409, 23, 363, 544],
           "reason": "geometry"
         }
       ]
@@ -26,14 +26,6 @@
   ],
   "objectPaintInvalidations": [
     {
-      "object": "LayoutBlockFlow HTML",
-      "reason": "selection"
-    },
-    {
-      "object": "LayoutBlockFlow BODY",
-      "reason": "selection"
-    },
-    {
       "object": "LayoutText #text",
       "reason": "geometry"
     },
diff --git a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/platform/win/paint/invalidation/multicol-as-paint-container-expected.txt b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/platform/win/paint/invalidation/multicol-as-paint-container-expected.txt
index cf8cb254b..63aa244 100644
--- a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/platform/win/paint/invalidation/multicol-as-paint-container-expected.txt
+++ b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/platform/win/paint/invalidation/multicol-as-paint-container-expected.txt
@@ -29,7 +29,12 @@
         },
         {
           "object": "LayoutText #text",
-          "rect": [0, 0, 625, 180],
+          "rect": [325, -180, 300, 340],
+          "reason": "style change"
+        },
+        {
+          "object": "LayoutText #text",
+          "rect": [0, 0, 300, 340],
           "reason": "style change"
         }
       ]
@@ -109,6 +114,78 @@
       "reason": "style change"
     },
     {
+      "object": "LayoutText #text",
+      "reason": "style change"
+    },
+    {
+      "object": "InlineTextBox 'Lorem ipsum'",
+      "reason": "style change"
+    },
+    {
+      "object": "InlineTextBox 'dolor sit amet,'",
+      "reason": "style change"
+    },
+    {
+      "object": "InlineTextBox 'consectetur'",
+      "reason": "style change"
+    },
+    {
+      "object": "InlineTextBox 'adipiscing'",
+      "reason": "style change"
+    },
+    {
+      "object": "InlineTextBox 'elit. Fusce'",
+      "reason": "style change"
+    },
+    {
+      "object": "InlineTextBox 'varius, metus'",
+      "reason": "style change"
+    },
+    {
+      "object": "InlineTextBox 'eu fringilla'",
+      "reason": "style change"
+    },
+    {
+      "object": "InlineTextBox 'pulvinar, ipsum'",
+      "reason": "style change"
+    },
+    {
+      "object": "InlineTextBox 'sapien'",
+      "reason": "style change"
+    },
+    {
+      "object": "InlineTextBox 'ultricies arcu,'",
+      "reason": "style change"
+    },
+    {
+      "object": "InlineTextBox 'non condimentum'",
+      "reason": "style change"
+    },
+    {
+      "object": "InlineTextBox 'quam est eu'",
+      "reason": "style change"
+    },
+    {
+      "object": "InlineTextBox 'purus. Ut nisl'",
+      "reason": "style change"
+    },
+    {
+      "object": "InlineTextBox 'libero,'",
+      "reason": "style change"
+    },
+    {
+      "object": "InlineTextBox 'suscipit ut leo'",
+      "reason": "style change"
+    },
+    {
+      "object": "InlineTextBox 'eget, dapibus'",
+      "reason": "style change"
+    },
+    {
+      "object": "InlineTextBox 'ultrices dolor.'",
+      "reason": "style change"
+    },
+    {
       "object": "LayoutMultiColumnSet (anonymous)",
       "reason": "style change"
     }
diff --git a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/platform/win/paint/invalidation/multicol-repaint-expected.txt b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/platform/win/paint/invalidation/multicol-repaint-expected.txt
index 2f89d098..d263d54d 100644
--- a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/platform/win/paint/invalidation/multicol-repaint-expected.txt
+++ b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/platform/win/paint/invalidation/multicol-repaint-expected.txt
@@ -17,13 +17,13 @@
       "backgroundColor": "#FFFFFF",
       "paintInvalidations": [
         {
-          "object": "LayoutMultiColumnFlowThread (anonymous)",
-          "rect": [9, 9, 400, 100],
+          "object": "LayoutInline SPAN id='a'",
+          "rect": [234, 10, 300, 57],
           "reason": "geometry"
         },
         {
           "object": "LayoutInline SPAN id='a'",
-          "rect": [234, 10, 300, 57],
+          "rect": [9, 110, 300, 57],
           "reason": "geometry"
         },
         {
@@ -33,10 +33,30 @@
         },
         {
           "object": "LayoutText #text",
-          "rect": [234, 15, 50, 50],
+          "rect": [9, 115, 300, 50],
+          "reason": "appeared"
+        },
+        {
+          "object": "LayoutText #text",
+          "rect": [9, 15, 275, 150],
           "reason": "disappeared"
         },
         {
+          "object": "LayoutMultiColumnFlowThread (anonymous)",
+          "rect": [234, -91, 175, 159],
+          "reason": "geometry"
+        },
+        {
+          "object": "LayoutMultiColumnFlowThread (anonymous)",
+          "rect": [9, 9, 175, 159],
+          "reason": "geometry"
+        },
+        {
+          "object": "LayoutText #text",
+          "rect": [234, -90, 13, 58],
+          "reason": "geometry"
+        },
+        {
           "object": "LayoutText #text",
           "rect": [9, 10, 13, 58],
           "reason": "geometry"
@@ -58,6 +78,14 @@
       "reason": "geometry"
     },
     {
+      "object": "LayoutMultiColumnFlowThread (anonymous)",
+      "reason": "geometry"
+    },
+    {
+      "object": "RootInlineBox",
+      "reason": "geometry"
+    },
+    {
       "object": "LayoutText #text",
       "reason": "geometry"
     },
@@ -66,6 +94,22 @@
       "reason": "geometry"
     },
     {
+      "object": "LayoutText #text",
+      "reason": "geometry"
+    },
+    {
+      "object": "InlineTextBox '\u00A0'",
+      "reason": "geometry"
+    },
+    {
+      "object": "LayoutBR BR",
+      "reason": "geometry"
+    },
+    {
+      "object": "InlineTextBox '\n'",
+      "reason": "geometry"
+    },
+    {
       "object": "LayoutBR BR",
       "reason": "geometry"
     },
@@ -82,6 +126,22 @@
       "reason": "geometry"
     },
     {
+      "object": "LayoutInline SPAN id='a'",
+      "reason": "geometry"
+    },
+    {
+      "object": "InlineFlowBox",
+      "reason": "geometry"
+    },
+    {
+      "object": "LayoutText #text",
+      "reason": "appeared"
+    },
+    {
+      "object": "InlineTextBox 'XXXXXX'",
+      "reason": "appeared"
+    },
+    {
       "object": "LayoutText #text",
       "reason": "appeared"
     },
diff --git a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/platform/win/paint/invalidation/multicol-with-inline-expected.txt b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/platform/win/paint/invalidation/multicol-with-inline-expected.txt
index da4abef..5ae8a29b 100644
--- a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/platform/win/paint/invalidation/multicol-with-inline-expected.txt
+++ b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/platform/win/paint/invalidation/multicol-with-inline-expected.txt
@@ -20,6 +20,21 @@
           "object": "LayoutText #text",
           "rect": [488, 8, 80, 20],
           "reason": "style change"
+        },
+        {
+          "object": "LayoutText #text",
+          "rect": [328, 28, 80, 20],
+          "reason": "style change"
+        },
+        {
+          "object": "LayoutText #text",
+          "rect": [168, 48, 80, 20],
+          "reason": "style change"
+        },
+        {
+          "object": "LayoutText #text",
+          "rect": [8, 68, 80, 20],
+          "reason": "style change"
         }
       ]
     }
@@ -30,6 +45,42 @@
       "reason": "style change"
     },
     {
+      "object": "LayoutInline SPAN id='target'",
+      "reason": "style change"
+    },
+    {
+      "object": "LayoutInline SPAN id='target'",
+      "reason": "style change"
+    },
+    {
+      "object": "LayoutInline SPAN id='target'",
+      "reason": "style change"
+    },
+    {
+      "object": "LayoutText #text",
+      "reason": "style change"
+    },
+    {
+      "object": "InlineTextBox 'PASS'",
+      "reason": "style change"
+    },
+    {
+      "object": "LayoutText #text",
+      "reason": "style change"
+    },
+    {
+      "object": "InlineTextBox 'PASS'",
+      "reason": "style change"
+    },
+    {
+      "object": "LayoutText #text",
+      "reason": "style change"
+    },
+    {
+      "object": "InlineTextBox 'PASS'",
+      "reason": "style change"
+    },
+    {
       "object": "LayoutText #text",
       "reason": "style change"
     },
diff --git a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/platform/win/paint/invalidation/multicol-with-text-expected.txt b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/platform/win/paint/invalidation/multicol-with-text-expected.txt
index 063c7fef..8fd6a84b 100644
--- a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/platform/win/paint/invalidation/multicol-with-text-expected.txt
+++ b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/platform/win/paint/invalidation/multicol-with-text-expected.txt
@@ -17,19 +17,49 @@
       "backgroundColor": "#FFFFFF",
       "paintInvalidations": [
         {
-          "object": "LayoutMultiColumnFlowThread (anonymous)",
-          "rect": [8, 8, 630, 20],
-          "reason": "geometry"
-        },
-        {
           "object": "LayoutMultiColumnSet (anonymous)",
           "rect": [8, 8, 630, 20],
           "reason": "geometry"
         },
         {
+          "object": "LayoutMultiColumnFlowThread (anonymous)",
+          "rect": [488, -52, 150, 80],
+          "reason": "geometry"
+        },
+        {
+          "object": "LayoutMultiColumnFlowThread (anonymous)",
+          "rect": [328, -32, 150, 80],
+          "reason": "geometry"
+        },
+        {
+          "object": "LayoutMultiColumnFlowThread (anonymous)",
+          "rect": [168, -12, 150, 80],
+          "reason": "geometry"
+        },
+        {
+          "object": "LayoutMultiColumnFlowThread (anonymous)",
+          "rect": [8, 68, 150, 20],
+          "reason": "incremental"
+        },
+        {
           "object": "LayoutText #text",
           "rect": [488, 8, 80, 20],
           "reason": "appeared"
+        },
+        {
+          "object": "LayoutText #text",
+          "rect": [328, 28, 80, 20],
+          "reason": "appeared"
+        },
+        {
+          "object": "LayoutText #text",
+          "rect": [168, 48, 80, 20],
+          "reason": "appeared"
+        },
+        {
+          "object": "LayoutText #text",
+          "rect": [8, 68, 80, 20],
+          "reason": "appeared"
         }
       ]
     }
@@ -37,6 +67,30 @@
   "objectPaintInvalidations": [
     {
       "object": "LayoutMultiColumnFlowThread (anonymous)",
+      "reason": "incremental"
+    },
+    {
+      "object": "RootInlineBox",
+      "reason": "incremental"
+    },
+    {
+      "object": "LayoutMultiColumnFlowThread (anonymous)",
+      "reason": "geometry"
+    },
+    {
+      "object": "RootInlineBox",
+      "reason": "geometry"
+    },
+    {
+      "object": "LayoutMultiColumnFlowThread (anonymous)",
+      "reason": "geometry"
+    },
+    {
+      "object": "RootInlineBox",
+      "reason": "geometry"
+    },
+    {
+      "object": "LayoutMultiColumnFlowThread (anonymous)",
       "reason": "geometry"
     },
     {
@@ -60,6 +114,110 @@
       "reason": "geometry"
     },
     {
+      "object": "LayoutBR BR",
+      "reason": "geometry"
+    },
+    {
+      "object": "InlineTextBox '\n'",
+      "reason": "geometry"
+    },
+    {
+      "object": "LayoutBR BR",
+      "reason": "geometry"
+    },
+    {
+      "object": "InlineTextBox '\n'",
+      "reason": "geometry"
+    },
+    {
+      "object": "LayoutBR BR",
+      "reason": "geometry"
+    },
+    {
+      "object": "InlineTextBox '\n'",
+      "reason": "geometry"
+    },
+    {
+      "object": "LayoutBR BR",
+      "reason": "geometry"
+    },
+    {
+      "object": "InlineTextBox '\n'",
+      "reason": "geometry"
+    },
+    {
+      "object": "LayoutBR BR",
+      "reason": "geometry"
+    },
+    {
+      "object": "InlineTextBox '\n'",
+      "reason": "geometry"
+    },
+    {
+      "object": "LayoutBR BR",
+      "reason": "geometry"
+    },
+    {
+      "object": "InlineTextBox '\n'",
+      "reason": "geometry"
+    },
+    {
+      "object": "LayoutBR BR",
+      "reason": "geometry"
+    },
+    {
+      "object": "InlineTextBox '\n'",
+      "reason": "geometry"
+    },
+    {
+      "object": "LayoutBR BR",
+      "reason": "geometry"
+    },
+    {
+      "object": "InlineTextBox '\n'",
+      "reason": "geometry"
+    },
+    {
+      "object": "LayoutBR BR",
+      "reason": "geometry"
+    },
+    {
+      "object": "InlineTextBox '\n'",
+      "reason": "geometry"
+    },
+    {
+      "object": "LayoutBR BR",
+      "reason": "geometry"
+    },
+    {
+      "object": "InlineTextBox '\n'",
+      "reason": "geometry"
+    },
+    {
+      "object": "LayoutText #text",
+      "reason": "appeared"
+    },
+    {
+      "object": "InlineTextBox 'PASS'",
+      "reason": "appeared"
+    },
+    {
+      "object": "LayoutText #text",
+      "reason": "appeared"
+    },
+    {
+      "object": "InlineTextBox 'PASS'",
+      "reason": "appeared"
+    },
+    {
+      "object": "LayoutText #text",
+      "reason": "appeared"
+    },
+    {
+      "object": "InlineTextBox 'PASS'",
+      "reason": "appeared"
+    },
+    {
       "object": "LayoutText #text",
       "reason": "appeared"
     },
diff --git a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/platform/win/paint/invalidation/repaint-across-writing-mode-boundary-expected.txt b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/platform/win/paint/invalidation/repaint-across-writing-mode-boundary-expected.txt
index 8fed9eb..68ebe43 100644
--- a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/platform/win/paint/invalidation/repaint-across-writing-mode-boundary-expected.txt
+++ b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/platform/win/paint/invalidation/repaint-across-writing-mode-boundary-expected.txt
@@ -26,26 +26,6 @@
   ],
   "objectPaintInvalidations": [
     {
-      "object": "LayoutBlockFlow HTML",
-      "reason": "selection"
-    },
-    {
-      "object": "LayoutBlockFlow BODY",
-      "reason": "selection"
-    },
-    {
-      "object": "LayoutBlockFlow DIV class='lrblock'",
-      "reason": "selection"
-    },
-    {
-      "object": "LayoutBlockFlow DIV class='basic d1 vert'",
-      "reason": "selection"
-    },
-    {
-      "object": "LayoutBlockFlow P",
-      "reason": "selection"
-    },
-    {
       "object": "LayoutText #text",
       "reason": "selection"
     },
diff --git a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/platform/win/paint/invalidation/selection-after-remove-expected.txt b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/platform/win/paint/invalidation/selection-after-remove-expected.txt
index 9507a32..ee629b8d 100644
--- a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/platform/win/paint/invalidation/selection-after-remove-expected.txt
+++ b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/platform/win/paint/invalidation/selection-after-remove-expected.txt
@@ -54,14 +54,6 @@
       "reason": "disappeared"
     },
     {
-      "object": "LayoutBlockFlow HTML",
-      "reason": "selection"
-    },
-    {
-      "object": "LayoutBlockFlow BODY",
-      "reason": "selection"
-    },
-    {
       "object": "LayoutBlockFlow DIV id='test'",
       "reason": "geometry"
     },
diff --git a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/platform/win/paint/invalidation/selection-clear-expected.txt b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/platform/win/paint/invalidation/selection-clear-expected.txt
index f5ab1e7..8fb29713d 100644
--- a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/platform/win/paint/invalidation/selection-clear-expected.txt
+++ b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/platform/win/paint/invalidation/selection-clear-expected.txt
@@ -55,22 +55,10 @@
       "reason": "disappeared"
     },
     {
-      "object": "LayoutBlockFlow HTML",
-      "reason": "selection"
-    },
-    {
-      "object": "LayoutBlockFlow BODY",
-      "reason": "selection"
-    },
-    {
       "object": "LayoutBlockFlow DIV id='root'",
       "reason": "incremental"
     },
     {
-      "object": "LayoutBlockFlow DIV id='root'",
-      "reason": "selection"
-    },
-    {
       "object": "LayoutBlockFlow DIV id='firstLine'",
       "reason": "full"
     },
diff --git a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/platform/win/paint/invalidation/selection-rl-expected.txt b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/platform/win/paint/invalidation/selection-rl-expected.txt
index 9855bb0..0b202b5 100644
--- a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/platform/win/paint/invalidation/selection-rl-expected.txt
+++ b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/platform/win/paint/invalidation/selection-rl-expected.txt
@@ -26,14 +26,6 @@
   ],
   "objectPaintInvalidations": [
     {
-      "object": "LayoutBlockFlow HTML",
-      "reason": "selection"
-    },
-    {
-      "object": "LayoutBlockFlow BODY",
-      "reason": "selection"
-    },
-    {
       "object": "LayoutText #text",
       "reason": "selection"
     },
diff --git a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/platform/win/paint/invalidation/selection/invalidation-rect-includes-newline-expected.txt b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/platform/win/paint/invalidation/selection/invalidation-rect-includes-newline-expected.txt
index 056b0f55..50f69a7 100644
--- a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/platform/win/paint/invalidation/selection/invalidation-rect-includes-newline-expected.txt
+++ b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/platform/win/paint/invalidation/selection/invalidation-rect-includes-newline-expected.txt
@@ -26,18 +26,6 @@
   ],
   "objectPaintInvalidations": [
     {
-      "object": "LayoutBlockFlow HTML",
-      "reason": "selection"
-    },
-    {
-      "object": "LayoutBlockFlow BODY",
-      "reason": "selection"
-    },
-    {
-      "object": "LayoutBlockFlow DIV id='container'",
-      "reason": "selection"
-    },
-    {
       "object": "LayoutText #text",
       "reason": "geometry"
     },
diff --git a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/platform/win/paint/invalidation/selection/invalidation-rect-includes-newline-for-rtl-expected.txt b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/platform/win/paint/invalidation/selection/invalidation-rect-includes-newline-for-rtl-expected.txt
index 4f3b336..d2d2d01 100644
--- a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/platform/win/paint/invalidation/selection/invalidation-rect-includes-newline-for-rtl-expected.txt
+++ b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/platform/win/paint/invalidation/selection/invalidation-rect-includes-newline-for-rtl-expected.txt
@@ -26,18 +26,6 @@
   ],
   "objectPaintInvalidations": [
     {
-      "object": "LayoutBlockFlow HTML",
-      "reason": "selection"
-    },
-    {
-      "object": "LayoutBlockFlow BODY",
-      "reason": "selection"
-    },
-    {
-      "object": "LayoutBlockFlow DIV id='container'",
-      "reason": "selection"
-    },
-    {
       "object": "LayoutText #text",
       "reason": "geometry"
     },
diff --git a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/platform/win/paint/invalidation/selection/invalidation-rect-includes-newline-for-vertical-rl-expected.txt b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/platform/win/paint/invalidation/selection/invalidation-rect-includes-newline-for-vertical-rl-expected.txt
index c37aa6b5d..29a2c8d5 100644
--- a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/platform/win/paint/invalidation/selection/invalidation-rect-includes-newline-for-vertical-rl-expected.txt
+++ b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/platform/win/paint/invalidation/selection/invalidation-rect-includes-newline-for-vertical-rl-expected.txt
@@ -26,18 +26,6 @@
   ],
   "objectPaintInvalidations": [
     {
-      "object": "LayoutBlockFlow HTML",
-      "reason": "selection"
-    },
-    {
-      "object": "LayoutBlockFlow BODY",
-      "reason": "selection"
-    },
-    {
-      "object": "LayoutBlockFlow DIV id='container'",
-      "reason": "selection"
-    },
-    {
       "object": "LayoutText #text",
       "reason": "geometry"
     },
diff --git a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/platform/win/paint/invalidation/selection/invalidation-rect-with-br-includes-newline-expected.txt b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/platform/win/paint/invalidation/selection/invalidation-rect-with-br-includes-newline-expected.txt
index c19049b..adb91ea 100644
--- a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/platform/win/paint/invalidation/selection/invalidation-rect-with-br-includes-newline-expected.txt
+++ b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/platform/win/paint/invalidation/selection/invalidation-rect-with-br-includes-newline-expected.txt
@@ -36,18 +36,6 @@
   ],
   "objectPaintInvalidations": [
     {
-      "object": "LayoutBlockFlow HTML",
-      "reason": "selection"
-    },
-    {
-      "object": "LayoutBlockFlow BODY",
-      "reason": "selection"
-    },
-    {
-      "object": "LayoutBlockFlow DIV id='container'",
-      "reason": "selection"
-    },
-    {
       "object": "LayoutText #text",
       "reason": "selection"
     },
diff --git a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/platform/win/paint/invalidation/selection/repaint-rect-for-vertical-writing-mode-with-positioned-root-expected.txt b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/platform/win/paint/invalidation/selection/repaint-rect-for-vertical-writing-mode-with-positioned-root-expected.txt
index c93e584..ba0deaa4 100644
--- a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/platform/win/paint/invalidation/selection/repaint-rect-for-vertical-writing-mode-with-positioned-root-expected.txt
+++ b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/platform/win/paint/invalidation/selection/repaint-rect-for-vertical-writing-mode-with-positioned-root-expected.txt
@@ -26,14 +26,6 @@
   ],
   "objectPaintInvalidations": [
     {
-      "object": "LayoutBlockFlow (positioned) DIV id='test'",
-      "reason": "selection"
-    },
-    {
-      "object": "LayoutBlockFlow DIV",
-      "reason": "selection"
-    },
-    {
       "object": "LayoutText #text",
       "reason": "selection"
     },
diff --git a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/platform/win/paint/invalidation/selection/selection-in-non-composited-scrolling-container-expected.txt b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/platform/win/paint/invalidation/selection/selection-in-non-composited-scrolling-container-expected.txt
index 7b91e5ca..09c041d 100644
--- a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/platform/win/paint/invalidation/selection/selection-in-non-composited-scrolling-container-expected.txt
+++ b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/platform/win/paint/invalidation/selection/selection-in-non-composited-scrolling-container-expected.txt
@@ -22,7 +22,7 @@
           "reason": "subtree"
         },
         {
-          "object": "LayoutBlockFlow DIV id='inner-editor'",
+          "object": "LayoutBlockFlow DIV",
           "rect": [10, 11, 64, 16],
           "reason": "subtree"
         },
@@ -36,19 +36,11 @@
   ],
   "objectPaintInvalidations": [
     {
-      "object": "LayoutBlockFlow HTML",
-      "reason": "selection"
-    },
-    {
-      "object": "LayoutBlockFlow BODY",
-      "reason": "selection"
-    },
-    {
       "object": "LayoutTextControl INPUT id='target'",
       "reason": "subtree"
     },
     {
-      "object": "LayoutBlockFlow DIV id='inner-editor'",
+      "object": "LayoutBlockFlow DIV",
       "reason": "subtree"
     },
     {
diff --git a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/platform/win/paint/invalidation/selection/selection-within-composited-scroller-expected.txt b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/platform/win/paint/invalidation/selection/selection-within-composited-scroller-expected.txt
index c08233ad..d64ecc8 100644
--- a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/platform/win/paint/invalidation/selection/selection-within-composited-scroller-expected.txt
+++ b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/platform/win/paint/invalidation/selection/selection-within-composited-scroller-expected.txt
@@ -81,22 +81,6 @@
   ],
   "objectPaintInvalidations": [
     {
-      "object": "LayoutBlockFlow HTML",
-      "reason": "selection"
-    },
-    {
-      "object": "LayoutBlockFlow BODY",
-      "reason": "selection"
-    },
-    {
-      "object": "LayoutBlockFlow DIV id='scroller'",
-      "reason": "selection"
-    },
-    {
-      "object": "LayoutBlockFlow DIV id='target'",
-      "reason": "selection"
-    },
-    {
       "object": "LayoutText #text",
       "reason": "selection"
     },
diff --git a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/platform/win/paint/invalidation/svg/append-text-node-to-tspan-expected.txt b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/platform/win/paint/invalidation/svg/append-text-node-to-tspan-expected.txt
index b1d0030..0cddd57c 100644
--- a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/platform/win/paint/invalidation/svg/append-text-node-to-tspan-expected.txt
+++ b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/platform/win/paint/invalidation/svg/append-text-node-to-tspan-expected.txt
@@ -18,52 +18,52 @@
       "paintInvalidations": [
         {
           "object": "LayoutSVGInlineText #text",
-          "rect": [10, 63, 307, 377],
+          "rect": [10, 62, 307, 377],
           "reason": "geometry"
         },
         {
           "object": "LayoutSVGInlineText #text",
-          "rect": [10, 63, 307, 377],
+          "rect": [10, 62, 307, 377],
           "reason": "geometry"
         },
         {
           "object": "LayoutSVGInlineText #text",
-          "rect": [10, 63, 307, 377],
+          "rect": [10, 62, 307, 377],
           "reason": "geometry"
         },
         {
           "object": "LayoutSVGInlineText #text",
-          "rect": [10, 63, 307, 377],
+          "rect": [10, 62, 307, 377],
           "reason": "geometry"
         },
         {
           "object": "LayoutSVGInlineText #text",
-          "rect": [10, 63, 307, 377],
+          "rect": [10, 62, 307, 377],
           "reason": "geometry"
         },
         {
           "object": "LayoutSVGInlineText #text",
-          "rect": [10, 63, 307, 377],
+          "rect": [10, 62, 307, 377],
           "reason": "appeared"
         },
         {
           "object": "LayoutSVGTSpan tspan",
-          "rect": [10, 63, 307, 377],
+          "rect": [10, 62, 307, 377],
           "reason": "geometry"
         },
         {
           "object": "LayoutSVGTSpan tspan",
-          "rect": [10, 63, 307, 377],
+          "rect": [10, 62, 307, 377],
           "reason": "geometry"
         },
         {
           "object": "LayoutSVGTSpan tspan id='modify'",
-          "rect": [10, 63, 307, 377],
+          "rect": [10, 62, 307, 377],
           "reason": "geometry"
         },
         {
           "object": "LayoutSVGText text",
-          "rect": [10, 63, 307, 377],
+          "rect": [10, 62, 307, 377],
           "reason": "style change"
         }
       ]
diff --git a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/platform/win/paint/invalidation/svg/modify-text-node-in-tspan-expected.txt b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/platform/win/paint/invalidation/svg/modify-text-node-in-tspan-expected.txt
index 21fe31f9a..d1a5fb9 100644
--- a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/platform/win/paint/invalidation/svg/modify-text-node-in-tspan-expected.txt
+++ b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/platform/win/paint/invalidation/svg/modify-text-node-in-tspan-expected.txt
@@ -18,47 +18,47 @@
       "paintInvalidations": [
         {
           "object": "LayoutSVGInlineText #text",
-          "rect": [10, 63, 307, 377],
+          "rect": [10, 62, 307, 377],
           "reason": "full"
         },
         {
           "object": "LayoutSVGInlineText #text",
-          "rect": [10, 63, 307, 377],
+          "rect": [10, 62, 307, 377],
           "reason": "geometry"
         },
         {
           "object": "LayoutSVGInlineText #text",
-          "rect": [10, 63, 307, 377],
+          "rect": [10, 62, 307, 377],
           "reason": "geometry"
         },
         {
           "object": "LayoutSVGInlineText #text",
-          "rect": [10, 63, 307, 377],
+          "rect": [10, 62, 307, 377],
           "reason": "geometry"
         },
         {
           "object": "LayoutSVGInlineText #text",
-          "rect": [10, 63, 307, 377],
+          "rect": [10, 62, 307, 377],
           "reason": "geometry"
         },
         {
           "object": "LayoutSVGTSpan tspan",
-          "rect": [10, 63, 307, 377],
+          "rect": [10, 62, 307, 377],
           "reason": "geometry"
         },
         {
           "object": "LayoutSVGTSpan tspan",
-          "rect": [10, 63, 307, 377],
+          "rect": [10, 62, 307, 377],
           "reason": "geometry"
         },
         {
           "object": "LayoutSVGTSpan tspan id='modify'",
-          "rect": [10, 63, 307, 377],
+          "rect": [10, 62, 307, 377],
           "reason": "geometry"
         },
         {
           "object": "LayoutSVGText text",
-          "rect": [10, 63, 307, 377],
+          "rect": [10, 62, 307, 377],
           "reason": "full"
         }
       ]
diff --git a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/platform/win/paint/invalidation/svg/remove-text-node-from-tspan-expected.txt b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/platform/win/paint/invalidation/svg/remove-text-node-from-tspan-expected.txt
index 3258abc..2e718c3 100644
--- a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/platform/win/paint/invalidation/svg/remove-text-node-from-tspan-expected.txt
+++ b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/platform/win/paint/invalidation/svg/remove-text-node-from-tspan-expected.txt
@@ -18,52 +18,52 @@
       "paintInvalidations": [
         {
           "object": "LayoutSVGInlineText #text",
-          "rect": [10, 63, 307, 377],
+          "rect": [10, 62, 307, 377],
           "reason": "geometry"
         },
         {
           "object": "LayoutSVGInlineText #text",
-          "rect": [10, 63, 307, 377],
+          "rect": [10, 62, 307, 377],
           "reason": "geometry"
         },
         {
           "object": "LayoutSVGInlineText #text",
-          "rect": [10, 63, 307, 377],
+          "rect": [10, 62, 307, 377],
           "reason": "geometry"
         },
         {
           "object": "LayoutSVGInlineText #text",
-          "rect": [10, 63, 307, 377],
+          "rect": [10, 62, 307, 377],
           "reason": "geometry"
         },
         {
           "object": "LayoutSVGInlineText #text",
-          "rect": [10, 63, 307, 377],
+          "rect": [10, 62, 307, 377],
           "reason": "geometry"
         },
         {
           "object": "LayoutSVGInlineText #text",
-          "rect": [10, 63, 307, 377],
+          "rect": [10, 62, 307, 377],
           "reason": "disappeared"
         },
         {
           "object": "LayoutSVGTSpan tspan",
-          "rect": [10, 63, 307, 377],
+          "rect": [10, 62, 307, 377],
           "reason": "geometry"
         },
         {
           "object": "LayoutSVGTSpan tspan",
-          "rect": [10, 63, 307, 377],
+          "rect": [10, 62, 307, 377],
           "reason": "geometry"
         },
         {
           "object": "LayoutSVGTSpan tspan id='modify'",
-          "rect": [10, 63, 307, 377],
+          "rect": [10, 62, 307, 377],
           "reason": "geometry"
         },
         {
           "object": "LayoutSVGText text",
-          "rect": [10, 63, 307, 377],
+          "rect": [10, 62, 307, 377],
           "reason": "full"
         }
       ]
diff --git a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/platform/win/paint/invalidation/svg/remove-tspan-from-text-expected.txt b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/platform/win/paint/invalidation/svg/remove-tspan-from-text-expected.txt
index 3094f76..b9a77d9 100644
--- a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/platform/win/paint/invalidation/svg/remove-tspan-from-text-expected.txt
+++ b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/platform/win/paint/invalidation/svg/remove-tspan-from-text-expected.txt
@@ -18,47 +18,47 @@
       "paintInvalidations": [
         {
           "object": "LayoutSVGInlineText #text",
-          "rect": [10, 63, 307, 257],
+          "rect": [10, 62, 307, 257],
           "reason": "geometry"
         },
         {
           "object": "LayoutSVGInlineText #text",
-          "rect": [10, 63, 307, 257],
+          "rect": [10, 62, 307, 257],
           "reason": "geometry"
         },
         {
           "object": "LayoutSVGInlineText #text",
-          "rect": [10, 63, 307, 257],
+          "rect": [10, 62, 307, 257],
           "reason": "geometry"
         },
         {
           "object": "LayoutSVGInlineText #text",
-          "rect": [10, 63, 307, 257],
+          "rect": [10, 62, 307, 257],
           "reason": "disappeared"
         },
         {
           "object": "LayoutSVGInlineText #text",
-          "rect": [10, 63, 307, 257],
+          "rect": [10, 62, 307, 257],
           "reason": "disappeared"
         },
         {
           "object": "LayoutSVGTSpan tspan",
-          "rect": [10, 63, 307, 257],
+          "rect": [10, 62, 307, 257],
           "reason": "geometry"
         },
         {
           "object": "LayoutSVGTSpan tspan",
-          "rect": [10, 63, 307, 257],
+          "rect": [10, 62, 307, 257],
           "reason": "geometry"
         },
         {
           "object": "LayoutSVGTSpan tspan id='remove'",
-          "rect": [10, 63, 307, 257],
+          "rect": [10, 62, 307, 257],
           "reason": "disappeared"
         },
         {
           "object": "LayoutSVGText text id='text'",
-          "rect": [10, 63, 307, 257],
+          "rect": [10, 62, 307, 257],
           "reason": "full"
         }
       ]
diff --git a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/platform/win/paint/invalidation/svg/text-viewbox-rescale-expected.txt b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/platform/win/paint/invalidation/svg/text-viewbox-rescale-expected.txt
index 3910db3..b3afce8 100644
--- a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/platform/win/paint/invalidation/svg/text-viewbox-rescale-expected.txt
+++ b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/platform/win/paint/invalidation/svg/text-viewbox-rescale-expected.txt
@@ -18,57 +18,57 @@
       "paintInvalidations": [
         {
           "object": "LayoutSVGInlineText #text",
-          "rect": [59, 143, 95, 23],
+          "rect": [59, 140, 95, 23],
           "reason": "geometry"
         },
         {
           "object": "LayoutSVGInlineText #text",
-          "rect": [59, 143, 95, 23],
+          "rect": [59, 140, 95, 23],
           "reason": "geometry"
         },
         {
           "object": "LayoutSVGTSpan tspan",
-          "rect": [59, 143, 95, 23],
+          "rect": [59, 140, 95, 23],
           "reason": "full"
         },
         {
           "object": "LayoutSVGText text",
-          "rect": [59, 143, 95, 23],
+          "rect": [59, 140, 95, 23],
           "reason": "full"
         },
         {
           "object": "LayoutSVGViewportContainer svg id='inner2'",
-          "rect": [59, 143, 95, 23],
+          "rect": [59, 140, 95, 23],
           "reason": "full"
         },
         {
           "object": "LayoutSVGInlineText #text",
-          "rect": [59, 43, 95, 23],
+          "rect": [59, 40, 95, 23],
           "reason": "geometry"
         },
         {
           "object": "LayoutSVGInlineText #text",
-          "rect": [59, 43, 95, 23],
+          "rect": [59, 40, 95, 23],
           "reason": "geometry"
         },
         {
           "object": "LayoutSVGInlineText #text",
-          "rect": [59, 43, 95, 23],
+          "rect": [59, 40, 95, 23],
           "reason": "appeared"
         },
         {
           "object": "LayoutSVGTSpan tspan",
-          "rect": [59, 43, 95, 23],
+          "rect": [59, 40, 95, 23],
           "reason": "full"
         },
         {
           "object": "LayoutSVGText text",
-          "rect": [59, 43, 95, 23],
+          "rect": [59, 40, 95, 23],
           "reason": "full"
         },
         {
           "object": "LayoutSVGViewportContainer svg id='inner1'",
-          "rect": [59, 43, 95, 23],
+          "rect": [59, 40, 95, 23],
           "reason": "full"
         }
       ]
diff --git a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/platform/win/paint/invalidation/svg/window-expected.txt b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/platform/win/paint/invalidation/svg/window-expected.txt
index 9619e33..ebffa73 100644
--- a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/platform/win/paint/invalidation/svg/window-expected.txt
+++ b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/platform/win/paint/invalidation/svg/window-expected.txt
@@ -458,12 +458,12 @@
         },
         {
           "object": "LayoutSVGInlineText #text",
-          "rect": [41, 524, 98, 11],
+          "rect": [41, 524, 98, 10],
           "reason": "appeared"
         },
         {
           "object": "LayoutSVGText text",
-          "rect": [41, 524, 98, 11],
+          "rect": [41, 524, 98, 10],
           "reason": "appeared"
         },
         {
@@ -538,12 +538,12 @@
         },
         {
           "object": "LayoutSVGInlineText #text",
-          "rect": [616, 153, 12, 81],
+          "rect": [615, 153, 13, 81],
           "reason": "appeared"
         },
         {
           "object": "LayoutSVGText text",
-          "rect": [616, 153, 12, 81],
+          "rect": [615, 153, 13, 81],
           "reason": "appeared"
         },
         {
diff --git a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/platform/win7/paint/invalidation/japanese-rl-selection-repaint-expected.txt b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/platform/win7/paint/invalidation/japanese-rl-selection-repaint-expected.txt
index 496e0c9..bfa6bb3 100644
--- a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/platform/win7/paint/invalidation/japanese-rl-selection-repaint-expected.txt
+++ b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/platform/win7/paint/invalidation/japanese-rl-selection-repaint-expected.txt
@@ -26,14 +26,6 @@
   ],
   "objectPaintInvalidations": [
     {
-      "object": "LayoutBlockFlow HTML",
-      "reason": "selection"
-    },
-    {
-      "object": "LayoutBlockFlow BODY",
-      "reason": "selection"
-    },
-    {
       "object": "LayoutText #text",
       "reason": "geometry"
     },
diff --git a/third_party/WebKit/LayoutTests/fragmentation/border-radius-clip-above-fragmented-expected.html b/third_party/WebKit/LayoutTests/fragmentation/border-radius-clip-above-fragmented-expected.html
new file mode 100644
index 0000000..5fde4fb5
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/fragmentation/border-radius-clip-above-fragmented-expected.html
@@ -0,0 +1,26 @@
+<!doctype HTML>
+<style>
+.sized {
+    width: 100px;
+    height: 20px;
+}
+.blue {
+    background: lightblue;
+}
+.green {
+    background: green;
+}
+.secondcolumn {
+    position: relative;
+    left: 308px;
+    top: -60px
+}
+</style>
+<div id=target style="border-radius: 10px; overflow: hidden; height: 100px; width: 600px;">
+    <div class="sized blue"></div>
+    <div class="sized blue"></div>
+    <div class="sized blue"></div>
+    <div class="sized blue secondcolumn"></div>
+    <div class="sized blue secondcolumn"></div>
+    <div class="sized green secondcolumn"></div>
+</div>
diff --git a/third_party/WebKit/LayoutTests/fragmentation/border-radius-clip-above-fragmented.html b/third_party/WebKit/LayoutTests/fragmentation/border-radius-clip-above-fragmented.html
new file mode 100644
index 0000000..f7bf413
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/fragmentation/border-radius-clip-above-fragmented.html
@@ -0,0 +1,21 @@
+<!doctype HTML>
+<style>
+.sized {
+    width: 100px;
+    height: 20px;
+}
+.blue {
+    background: lightblue;
+}
+.green {
+    background: green;
+}
+</style>
+<div id=target style="border-radius: 10px; overflow: hidden; height: 100px; width: 600px; column-count: 2;">
+    <div class="sized blue"></div>
+    <div class="sized blue"></div>
+    <div class="sized blue"></div>
+    <div class="sized blue"></div>
+    <div class="sized blue"></div>
+    <div class="sized green"></div>
+</div>
diff --git a/third_party/WebKit/LayoutTests/fragmentation/table-cell-intrinsic-padding-pagination-strut-expected.html b/third_party/WebKit/LayoutTests/fragmentation/table-cell-intrinsic-padding-pagination-strut-expected.html
deleted file mode 100644
index 54439be..0000000
--- a/third_party/WebKit/LayoutTests/fragmentation/table-cell-intrinsic-padding-pagination-strut-expected.html
+++ /dev/null
@@ -1,35 +0,0 @@
-<!DOCTYPE html>
-<style>
-body {
-  width: 600px;
-}
-table{
-  width: 100%;
-  border-collapse: collapse;
-}
-td, th {
-  border: 1px solid black;
-  line-height: 20px;
-}
-</style>
-<p>crbug.com/768330: Don't let intrinsic padding in table cells skew pagination struts. The borders in the table should be properly aligned.</p>
-<div style="height:285px; column-fill: auto; column-width: 200px;background-color: yellow;">
-  <table id="table">
-    <tr>
-      <td>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Hic, enim.</td>
-      <td>Veritatis, dignissimos inventore quam repellendus fuga aliquid molestiae deserunt pariatur.</td>
-    </tr>
-    <tr>
-      <td>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Ab, in.</td>
-      <td>Expedita repellat, minus eius error, velit facilis! Doloribus reiciendis, praesentium.</td>
-    </tr>
-    <tr>
-      <td>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Ratione, aut!</td>
-      <td>Iusto optio deleniti sed dicta saepe mollitia illum deserunt fuga.</td>
-    </tr>
-    <tr>
-      <td>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Cum, nam.</td>
-      <td>Laudantium sint commodi explicabo voluptate non amet, totam nam dolorem.</td>
-    </tr>
-  </table>
-</div>
diff --git a/third_party/WebKit/LayoutTests/fragmentation/table-cell-intrinsic-padding-pagination-strut.html b/third_party/WebKit/LayoutTests/fragmentation/table-cell-intrinsic-padding-pagination-strut.html
deleted file mode 100644
index 71656e5..0000000
--- a/third_party/WebKit/LayoutTests/fragmentation/table-cell-intrinsic-padding-pagination-strut.html
+++ /dev/null
@@ -1,39 +0,0 @@
-<!DOCTYPE html>
-<style>
-body {
-  width: 600px;
-}
-table{
-  width: 50%;
-  border-collapse: collapse;
-}
-td, th {
-  border: 1px solid black;
-  line-height: 20px;
-}
-</style>
-<p>crbug.com/768330: Don't let intrinsic padding in table cells skew pagination struts. The borders in the table should be properly aligned.</p>
-<div style="height:285px; column-fill: auto; column-width: 200px;background-color: yellow;">
-  <table id="table">
-    <tr>
-      <td>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Hic, enim.</td>
-      <td>Veritatis, dignissimos inventore quam repellendus fuga aliquid molestiae deserunt pariatur.</td>
-    </tr>
-    <tr>
-      <td>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Ab, in.</td>
-      <td>Expedita repellat, minus eius error, velit facilis! Doloribus reiciendis, praesentium.</td>
-    </tr>
-    <tr>
-      <td>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Ratione, aut!</td>
-      <td>Iusto optio deleniti sed dicta saepe mollitia illum deserunt fuga.</td>
-    </tr>
-    <tr>
-      <td>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Cum, nam.</td>
-      <td>Laudantium sint commodi explicabo voluptate non amet, totam nam dolorem.</td>
-    </tr>
-  </table>
-</div>
-<script>
-document.body.offsetTop;
-table.style['width'] = "100%";
-</script>
diff --git a/third_party/WebKit/LayoutTests/http/tests/devtools/console/console-group-similar-expected.txt b/third_party/WebKit/LayoutTests/http/tests/devtools/console/console-group-similar-expected.txt
new file mode 100644
index 0000000..f01b9ba
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/http/tests/devtools/console/console-group-similar-expected.txt
@@ -0,0 +1,65 @@
+Tests that console correctly groups similar messages.
+
+5[Violation] Verbose-level violation
+5[Violation] Error-level violation
+ConsoleAPI log
+'evaluated command'
+"evaluated command"
+console-group-similar.js:19 Uncaught (in promise) undefined
+(anonymous) @ console-group-similar.js:19
+ConsoleAPI log
+'evaluated command'
+"evaluated command"
+console-group-similar.js:19 Uncaught (in promise) undefined
+(anonymous) @ console-group-similar.js:19
+ConsoleAPI log
+'evaluated command'
+"evaluated command"
+console-group-similar.js:19 Uncaught (in promise) undefined
+(anonymous) @ console-group-similar.js:19
+ConsoleAPI log
+'evaluated command'
+"evaluated command"
+console-group-similar.js:19 Uncaught (in promise) undefined
+(anonymous) @ console-group-similar.js:19
+ConsoleAPI log
+'evaluated command'
+"evaluated command"
+
+
+Stop grouping messages:
+
+[Violation] Verbose-level violation
+[Violation] Error-level violation
+ConsoleAPI log
+'evaluated command'
+"evaluated command"
+console-group-similar.js:19 Uncaught (in promise) undefined
+(anonymous) @ console-group-similar.js:19
+[Violation] Verbose-level violation
+[Violation] Error-level violation
+ConsoleAPI log
+'evaluated command'
+"evaluated command"
+console-group-similar.js:19 Uncaught (in promise) undefined
+(anonymous) @ console-group-similar.js:19
+[Violation] Verbose-level violation
+[Violation] Error-level violation
+ConsoleAPI log
+'evaluated command'
+"evaluated command"
+console-group-similar.js:19 Uncaught (in promise) undefined
+(anonymous) @ console-group-similar.js:19
+[Violation] Verbose-level violation
+[Violation] Error-level violation
+ConsoleAPI log
+'evaluated command'
+"evaluated command"
+console-group-similar.js:19 Uncaught (in promise) undefined
+(anonymous) @ console-group-similar.js:19
+[Violation] Verbose-level violation
+[Violation] Error-level violation
+ConsoleAPI log
+'evaluated command'
+"evaluated command"
+
diff --git a/third_party/WebKit/LayoutTests/http/tests/devtools/console/console-group-similar.js b/third_party/WebKit/LayoutTests/http/tests/devtools/console/console-group-similar.js
new file mode 100644
index 0000000..13b313e3
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/http/tests/devtools/console/console-group-similar.js
@@ -0,0 +1,51 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+(async function() {
+  TestRunner.addResult(`Tests that console correctly groups similar messages.\n`);
+
+  await TestRunner.loadModule('console_test_runner');
+  await TestRunner.showPanel('console');
+
+  // Show all messages, including verbose.
+  Console.ConsoleView.instance()._filter._currentFilter.levelsMask = Console.ConsoleFilter.allLevelsFilterValue();
+
+  for (var i = 0; i < 5; i++) {
+    addViolationMessage('Verbose-level violation', `script${i}.js`, ConsoleModel.ConsoleMessage.MessageLevel.Verbose);
+    addViolationMessage('Error-level violation', `script${i}.js`, ConsoleModel.ConsoleMessage.MessageLevel.Error);
+    addConsoleAPIMessage('ConsoleAPI log', `script${i}.js`);
+    await ConsoleTestRunner.evaluateInConsolePromise(`'evaluated command'`);
+    await TestRunner.evaluateInPagePromise(`Promise.reject()`);
+  }
+
+  ConsoleTestRunner.dumpConsoleMessages();
+
+  TestRunner.addResult('\n\nStop grouping messages:\n');
+  Console.ConsoleView.instance()._groupSimilarSetting.set(false);
+  ConsoleTestRunner.dumpConsoleMessages();
+  TestRunner.completeTest();
+
+  /**
+   * @param {string} text
+   * @param {string} url
+   * @param {string} level
+   */
+  function addViolationMessage(text, url, level) {
+    var message = new ConsoleModel.ConsoleMessage(
+        null, ConsoleModel.ConsoleMessage.MessageSource.Violation, level,
+        text, ConsoleModel.ConsoleMessage.MessageType.Log, url);
+    ConsoleModel.consoleModel.addMessage(message);
+  }
+
+  /**
+   * @param {string} text
+   * @param {string} url
+   */
+  function addConsoleAPIMessage(text,  url) {
+    var message = new ConsoleModel.ConsoleMessage(
+        null, ConsoleModel.ConsoleMessage.MessageSource.ConsoleAPI, ConsoleModel.ConsoleMessage.MessageLevel.Info,
+        text, ConsoleModel.ConsoleMessage.MessageType.Log, url);
+    ConsoleModel.consoleModel.addMessage(message);
+  }
+})();
diff --git a/third_party/WebKit/LayoutTests/http/tests/resources/feature-policy-permissions-test.js b/third_party/WebKit/LayoutTests/http/tests/resources/feature-policy-permissions-test.js
index e7212f9..47d22264 100644
--- a/third_party/WebKit/LayoutTests/http/tests/resources/feature-policy-permissions-test.js
+++ b/third_party/WebKit/LayoutTests/http/tests/resources/feature-policy-permissions-test.js
@@ -17,7 +17,8 @@
   window.addEventListener('message', test.step_func(evt => {
     if (evt.source == frame.contentWindow) {
       assert_equals(evt.data, expected);
-      document.body.removeChild(frame);
+      // TODO(raymes): Uncomment the below line once crbug.com/779433 is fixed.
+      // document.body.removeChild(frame);
       test.done();
     }
   }));
diff --git a/third_party/WebKit/LayoutTests/http/tests/security/cross-frame-access-put-expected.txt b/third_party/WebKit/LayoutTests/http/tests/security/cross-frame-access-put-expected.txt
index 6d2866f6..b44e74dc9e 100644
--- a/third_party/WebKit/LayoutTests/http/tests/security/cross-frame-access-put-expected.txt
+++ b/third_party/WebKit/LayoutTests/http/tests/security/cross-frame-access-put-expected.txt
@@ -165,7 +165,7 @@
 ALERT: PASS: window.find should be 'function find() { [native code] }' and is.
 ALERT: PASS: window.focus should be 'function () { [native code] }' and is.
 ALERT: PASS: window.getComputedStyle should be 'function getComputedStyle() { [native code] }' and is.
-ALERT: PASS: window.getMatchedCSSRules should be 'function getMatchedCSSRules() { [native code] }' and is.
+ALERT: PASS: window.getMatchedCSSRules should be 'undefined' and is.
 ALERT: PASS: window.getSelection should be 'function getSelection() { [native code] }' and is.
 ALERT: PASS: window.moveBy should be 'function moveBy() { [native code] }' and is.
 ALERT: PASS: window.moveTo should be 'function moveTo() { [native code] }' and is.
diff --git a/third_party/WebKit/LayoutTests/http/tests/worklet/webexposed/global-interface-listing-paint-worklet-expected.txt b/third_party/WebKit/LayoutTests/http/tests/worklet/webexposed/global-interface-listing-paint-worklet-expected.txt
index 43a2140..d825de84 100644
--- a/third_party/WebKit/LayoutTests/http/tests/worklet/webexposed/global-interface-listing-paint-worklet-expected.txt
+++ b/third_party/WebKit/LayoutTests/http/tests/worklet/webexposed/global-interface-listing-paint-worklet-expected.txt
@@ -11,10 +11,18 @@
 CONSOLE MESSAGE: line 147:     getter value
 CONSOLE MESSAGE: line 147:     method constructor
 CONSOLE MESSAGE: line 147:     setter value
+CONSOLE MESSAGE: line 147: interface CSSMathInvert : CSSMathValue
+CONSOLE MESSAGE: line 147:     getter value
+CONSOLE MESSAGE: line 147:     method constructor
+CONSOLE MESSAGE: line 147:     setter value
 CONSOLE MESSAGE: line 147: interface CSSMathMax : CSSMathValue
 CONSOLE MESSAGE: line 147:     method constructor
 CONSOLE MESSAGE: line 147: interface CSSMathMin : CSSMathValue
 CONSOLE MESSAGE: line 147:     method constructor
+CONSOLE MESSAGE: line 147: interface CSSMathNegate : CSSMathValue
+CONSOLE MESSAGE: line 147:     getter value
+CONSOLE MESSAGE: line 147:     method constructor
+CONSOLE MESSAGE: line 147:     setter value
 CONSOLE MESSAGE: line 147: interface CSSMathProduct : CSSMathValue
 CONSOLE MESSAGE: line 147:     method constructor
 CONSOLE MESSAGE: line 147: interface CSSMathSum : CSSMathValue
@@ -278,10 +286,18 @@
 CONSOLE MESSAGE: line 147:     getter value
 CONSOLE MESSAGE: line 147:     method constructor
 CONSOLE MESSAGE: line 147:     setter value
+CONSOLE MESSAGE: line 147: interface CSSMathInvert : CSSMathValue
+CONSOLE MESSAGE: line 147:     getter value
+CONSOLE MESSAGE: line 147:     method constructor
+CONSOLE MESSAGE: line 147:     setter value
 CONSOLE MESSAGE: line 147: interface CSSMathMax : CSSMathValue
 CONSOLE MESSAGE: line 147:     method constructor
 CONSOLE MESSAGE: line 147: interface CSSMathMin : CSSMathValue
 CONSOLE MESSAGE: line 147:     method constructor
+CONSOLE MESSAGE: line 147: interface CSSMathNegate : CSSMathValue
+CONSOLE MESSAGE: line 147:     getter value
+CONSOLE MESSAGE: line 147:     method constructor
+CONSOLE MESSAGE: line 147:     setter value
 CONSOLE MESSAGE: line 147: interface CSSMathProduct : CSSMathValue
 CONSOLE MESSAGE: line 147:     method constructor
 CONSOLE MESSAGE: line 147: interface CSSMathSum : CSSMathValue
diff --git a/third_party/WebKit/LayoutTests/platform/linux/editing/caret/caret-painting-low-dpi-expected.png b/third_party/WebKit/LayoutTests/platform/linux/editing/caret/caret-painting-low-dpi-expected.png
new file mode 100644
index 0000000..d539660
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/platform/linux/editing/caret/caret-painting-low-dpi-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/fast/text/sub-pixel/text-scaling-pixel-expected.png b/third_party/WebKit/LayoutTests/platform/linux/fast/text/sub-pixel/text-scaling-pixel-expected.png
index 13f80b7..4ca6bb3 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/fast/text/sub-pixel/text-scaling-pixel-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/linux/fast/text/sub-pixel/text-scaling-pixel-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac-mac10.10/editing/caret/caret-painting-low-dpi-expected.png b/third_party/WebKit/LayoutTests/platform/mac-mac10.10/editing/caret/caret-painting-low-dpi-expected.png
new file mode 100644
index 0000000..50584fc
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/platform/mac-mac10.10/editing/caret/caret-painting-low-dpi-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac-mac10.10/editing/caret/caret-painting-low-dpi-expected.txt b/third_party/WebKit/LayoutTests/platform/mac-mac10.10/editing/caret/caret-painting-low-dpi-expected.txt
new file mode 100644
index 0000000..ea89aaac
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/platform/mac-mac10.10/editing/caret/caret-painting-low-dpi-expected.txt
@@ -0,0 +1,12 @@
+layer at (0,0) size 800x600
+  LayoutView at (0,0) size 800x600
+layer at (0,0) size 800x68
+  LayoutBlockFlow {HTML} at (0,0) size 800x68
+    LayoutBlockFlow {BODY} at (8,8) size 784x52
+      LayoutText {#text} at (0,0) size 0x0
+layer at (8,8) size 208x48 clip at (10,10) size 204x44
+  LayoutTextControl {TEXTAREA} at (0,0) size 208x48 [bgcolor=#FFFFFF] [border: (2px solid #000000)]
+    LayoutBlockFlow {DIV} at (4,4) size 200x13
+      LayoutText {#text} at (0,0) size 52x13
+        text run at (0,0) width 52: "Some text"
+caret: position 0 of child 0 {#text} of child 0 {DIV} of {#document-fragment} of child 0 {TEXTAREA} of body
diff --git a/third_party/WebKit/LayoutTests/platform/mac-mac10.11/editing/caret/caret-painting-low-dpi-expected.png b/third_party/WebKit/LayoutTests/platform/mac-mac10.11/editing/caret/caret-painting-low-dpi-expected.png
new file mode 100644
index 0000000..676e3633
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/platform/mac-mac10.11/editing/caret/caret-painting-low-dpi-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac-retina/editing/caret/caret-painting-low-dpi-expected.png b/third_party/WebKit/LayoutTests/platform/mac-retina/editing/caret/caret-painting-low-dpi-expected.png
new file mode 100644
index 0000000..676e3633
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/platform/mac-retina/editing/caret/caret-painting-low-dpi-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac/editing/caret/caret-painting-low-dpi-expected.png b/third_party/WebKit/LayoutTests/platform/mac/editing/caret/caret-painting-low-dpi-expected.png
new file mode 100644
index 0000000..621289c1
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/platform/mac/editing/caret/caret-painting-low-dpi-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac/editing/caret/caret-painting-low-dpi-expected.txt b/third_party/WebKit/LayoutTests/platform/mac/editing/caret/caret-painting-low-dpi-expected.txt
new file mode 100644
index 0000000..0b724eaf
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/platform/mac/editing/caret/caret-painting-low-dpi-expected.txt
@@ -0,0 +1,12 @@
+layer at (0,0) size 800x600
+  LayoutView at (0,0) size 800x600
+layer at (0,0) size 800x68
+  LayoutBlockFlow {HTML} at (0,0) size 800x68
+    LayoutBlockFlow {BODY} at (8,8) size 784x52
+      LayoutText {#text} at (0,0) size 0x0
+layer at (8,8) size 208x48 clip at (10,10) size 204x44
+  LayoutTextControl {TEXTAREA} at (0,0) size 208x48 [bgcolor=#FFFFFF] [border: (2px solid #000000)]
+    LayoutBlockFlow {DIV} at (4,4) size 200x13
+      LayoutText {#text} at (0,0) size 53x13
+        text run at (0,0) width 53: "Some text"
+caret: position 0 of child 0 {#text} of child 0 {DIV} of {#document-fragment} of child 0 {TEXTAREA} of body
diff --git a/third_party/WebKit/LayoutTests/platform/win/editing/caret/caret-painting-low-dpi-expected.png b/third_party/WebKit/LayoutTests/platform/win/editing/caret/caret-painting-low-dpi-expected.png
new file mode 100644
index 0000000..1e738c4
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/platform/win/editing/caret/caret-painting-low-dpi-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win/editing/caret/caret-painting-low-dpi-expected.txt b/third_party/WebKit/LayoutTests/platform/win/editing/caret/caret-painting-low-dpi-expected.txt
new file mode 100644
index 0000000..b7d2a0e2
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/platform/win/editing/caret/caret-painting-low-dpi-expected.txt
@@ -0,0 +1,12 @@
+layer at (0,0) size 720x540
+  LayoutView at (0,0) size 720x540
+layer at (0,0) size 720x62
+  LayoutBlockFlow {HTML} at (0,0) size 720x61.56
+    LayoutBlockFlow {BODY} at (7.19,7.19) size 705.63x47.19
+      LayoutText {#text} at (0,0) size 0x0
+layer at (7,7) size 187x43 clip at (9,9) size 184x40
+  LayoutTextControl {TEXTAREA} at (0,0) size 187.19x43.19 [bgcolor=#FFFFFF] [border: (1.80px solid #000000)]
+    LayoutBlockFlow {DIV} at (3.59,3.59) size 180x15
+      LayoutText {#text} at (0,0) size 63x15
+        text run at (0,0) width 63: "Some text"
+caret: position 0 of child 0 {#text} of child 0 {DIV} of {#document-fragment} of child 0 {TEXTAREA} of body
diff --git a/third_party/WebKit/LayoutTests/platform/win7/fast/forms/suggested-value-expected.txt b/third_party/WebKit/LayoutTests/platform/win7/fast/forms/suggested-value-expected.txt
index 9f1eb3c..27a9c9d 100644
--- a/third_party/WebKit/LayoutTests/platform/win7/fast/forms/suggested-value-expected.txt
+++ b/third_party/WebKit/LayoutTests/platform/win7/fast/forms/suggested-value-expected.txt
@@ -9,9 +9,9 @@
 |   <shadow:root>
 |     <div>
 |       id="placeholder"
-|       pseudo="-webkit-input-suggested"
-|       style="display: none !important;"
-|       shadow:pseudoId="-webkit-input-suggested"
+|       pseudo="-internal-input-suggested"
+|       style="display: block !important;"
+|       shadow:pseudoId="-internal-input-suggested"
 |       "suggested value"
 |     <div>
 |       "suggested value"
@@ -70,9 +70,9 @@
 |   this.value="initial value"
 |   <shadow:root>
 |       id="placeholder"
-|       pseudo="-webkit-input-suggestedx"
+|       pseudo="-internal-input-suggestedx"
 |       style="display: none !important;"
-|       shadow:pseudoId="-webkit-input-suggested"
+|       shadow:pseudoId="-internal-input-suggested"
 |     <div>
 | <select>
 |   id="select"
diff --git a/third_party/WebKit/LayoutTests/sensor/orientation-sensor.html b/third_party/WebKit/LayoutTests/sensor/orientation-sensor.html
index bed0a22..1696f78 100644
--- a/third_party/WebKit/LayoutTests/sensor/orientation-sensor.html
+++ b/third_party/WebKit/LayoutTests/sensor/orientation-sensor.html
@@ -34,7 +34,7 @@
   return true;
 }
 
-function checkPopulateMatrix(sensor, sensorType) {
+async function checkPopulateMatrix(sensor, sensorType) {
   let sensorObject = new sensorType();
 
   // Throws with insufficient buffer space.
@@ -50,39 +50,37 @@
 
   sensorObject.start();
 
-  return sensor.mockSensorProvider.getCreatedSensor()
-    .then(mockSensor => mockSensor.setUpdateSensorReadingFunction(update_sensor_reading))
-    .then(mockSensor => {
-      return new Promise((resolve, reject) => {
-        let wrapper = new CallbackWrapper(() => {
-          // Works for all supported types.
-          let rotationMatrix32 = new Float32Array(16);
-          sensorObject.populateMatrix(rotationMatrix32);
-          assert_array_equals(rotationMatrix32, kRotationMatrix);
+  let mockSensor = await sensor.mockSensorProvider.getCreatedSensor();
+  await mockSensor.setUpdateSensorReadingFunction(update_sensor_reading);
+  await new Promise((resolve, reject) => {
+    let wrapper = new CallbackWrapper(() => {
+      // Works for all supported types.
+      let rotationMatrix32 = new Float32Array(16);
+      sensorObject.populateMatrix(rotationMatrix32);
+      assert_array_equals(rotationMatrix32, kRotationMatrix);
 
-          let rotationMatrix64 = new Float64Array(16);
-          sensorObject.populateMatrix(rotationMatrix64);
-          assert_array_equals(rotationMatrix64, kRotationMatrix);
+      let rotationMatrix64 = new Float64Array(16);
+      sensorObject.populateMatrix(rotationMatrix64);
+      assert_array_equals(rotationMatrix64, kRotationMatrix);
 
-          let rotationDOMMatrix = new DOMMatrix();
-          sensorObject.populateMatrix(rotationDOMMatrix);
-          assert_array_equals(rotationDOMMatrix.toFloat64Array(),
-                              kRotationMatrix);
+      let rotationDOMMatrix = new DOMMatrix();
+      sensorObject.populateMatrix(rotationDOMMatrix);
+      assert_array_equals(rotationDOMMatrix.toFloat64Array(),
+                          kRotationMatrix);
 
-          // Sets every matrix element.
-          rotationMatrix64.fill(123);
-          sensorObject.populateMatrix(rotationMatrix64);
-          assert_array_equals(rotationMatrix64, kRotationMatrix);
+      // Sets every matrix element.
+      rotationMatrix64.fill(123);
+      sensorObject.populateMatrix(rotationMatrix64);
+      assert_array_equals(rotationMatrix64, kRotationMatrix);
 
-          sensorObject.stop();
-          resolve(mockSensor);
-        }, reject);
+      sensorObject.stop();
+      resolve(mockSensor);
+    }, reject);
 
-        sensorObject.onreading = wrapper.callback;
-        sensorObject.onerror = reject;
-      });
-    })
-    .then(mockSensor => mockSensor.removeConfigurationCalled());
+    sensorObject.onreading = wrapper.callback;
+    sensorObject.onerror = reject;
+  });
+  return mockSensor.removeConfigurationCalled();
 }
 
 
diff --git a/third_party/WebKit/LayoutTests/sensor/resources/generic-sensor-tests.js b/third_party/WebKit/LayoutTests/sensor/resources/generic-sensor-tests.js
index 538e35b..d8a4757 100644
--- a/third_party/WebKit/LayoutTests/sensor/resources/generic-sensor-tests.js
+++ b/third_party/WebKit/LayoutTests/sensor/resources/generic-sensor-tests.js
@@ -21,212 +21,194 @@
     });
   }, `${sensorType.name}: Test that onerror is send when sensor is not supported.`);
 
-  sensor_test(sensor => {
-      let sensorObject = new sensorType({frequency: 560});
-      sensorObject.start();
+  sensor_test(async sensor => {
+    let sensorObject = new sensorType({frequency: 560});
+    sensorObject.start();
 
-      return sensor.mockSensorProvider.getCreatedSensor()
-        .then(mockSensor => {
-          mockSensor.setStartShouldFail(true);
-          return mockSensor.addConfigurationCalled(); })
-        .then(mockSensor => {
-          return new Promise((resolve, reject) => {
-            let wrapper = new CallbackWrapper(event => {
-              assert_false(sensorObject.activated);
-              assert_equals(event.error.name, 'NotReadableError');
-              sensorObject.onerror = null;
-              resolve();
-            }, reject);
+    let mockSensor = await sensor.mockSensorProvider.getCreatedSensor();
+    mockSensor.setStartShouldFail(true);
+    await mockSensor.addConfigurationCalled();
+    await new Promise((resolve, reject) => {
+      let wrapper = new CallbackWrapper(event => {
+        assert_false(sensorObject.activated);
+        assert_equals(event.error.name, 'NotReadableError');
+        sensorObject.onerror = null;
+        resolve();
+      }, reject);
 
-            sensorObject.onerror = wrapper.callback;
-          });
-        });
+      sensorObject.onerror = wrapper.callback;
+    });
   }, `${sensorType.name}: Test that onerror is send when start() call has failed.`);
 
-  sensor_test(sensor => {
+  sensor_test(async sensor => {
     let sensorObject = new sensorType();
     sensorObject.start();
 
-    return sensor.mockSensorProvider.getCreatedSensor()
-      .then(mockSensor => {
-        mockSensor.setStartShouldFail(true);
-        return mockSensor.addConfigurationCalled(); })
-      .then(mockSensor => mockSensor.removeConfigurationCalled());
+    let mockSensor = await sensor.mockSensorProvider.getCreatedSensor();
+    mockSensor.setStartShouldFail(true);
+    await mockSensor.addConfigurationCalled();
+    return mockSensor.removeConfigurationCalled();
   }, `${sensorType.name}: Test that no pending configuration left after start() failure.`);
 
-  sensor_test(sensor => {
-      let sensorObject = new sensorType({frequency: 560});
-      sensorObject.start();
+  sensor_test(async sensor => {
+    let sensorObject = new sensorType({frequency: 560});
+    sensorObject.start();
 
-      return sensor.mockSensorProvider.getCreatedSensor()
-          .then(mockSensor => mockSensor.addConfigurationCalled())
-          .then(mockSensor => {
-            return new Promise((resolve, reject) => {
-              let wrapper = new CallbackWrapper(() => {
-                assert_less_than_equal(mockSensor.getSamplingFrequency(), 60);
-                sensorObject.stop();
-                assert_false(sensorObject.activated);
-                resolve(mockSensor);
-              }, reject);
-              sensorObject.onactivate = wrapper.callback;
-              sensorObject.onerror = reject;
-            });
-          })
-          .then(mockSensor => mockSensor.removeConfigurationCalled());
+    let mockSensor = await sensor.mockSensorProvider.getCreatedSensor();
+    await mockSensor.addConfigurationCalled();
+    await new Promise((resolve, reject) => {
+      let wrapper = new CallbackWrapper(() => {
+        assert_less_than_equal(mockSensor.getSamplingFrequency(), 60);
+        sensorObject.stop();
+        assert_false(sensorObject.activated);
+        resolve(mockSensor);
+      }, reject);
+      sensorObject.onactivate = wrapper.callback;
+      sensorObject.onerror = reject;
+    });
+    return mockSensor.removeConfigurationCalled();
   }, `${sensorType.name}: Test that frequency is capped to allowed maximum.`);
 
-  sensor_test(sensor => {
+  sensor_test(async sensor => {
     let sensorObject = new sensorType();
     sensorObject.start();
-    return sensor.mockSensorProvider.getCreatedSensor()
-        .then(mockSensor => mockSensor.addConfigurationCalled())
-        .then(mockSensor => {
-            return new Promise((resolve, reject) => {
-              sensorObject.onactivate = () => {
-                // Now sensor proxy is initialized.
-                let anotherSensor = new sensorType({frequency: 21});
-                anotherSensor.start();
-                anotherSensor.stop();
-                resolve(mockSensor);
-              }
-            });
-          })
-        .then(mockSensor => mockSensor.removeConfigurationCalled())
-        .then(mockSensor => {
-          sensorObject.stop();
-          return mockSensor;
-        })
-        .then(mockSensor => mockSensor.removeConfigurationCalled());
+    let mockSensor = await sensor.mockSensorProvider.getCreatedSensor();
+    await mockSensor.addConfigurationCalled();
+    await new Promise((resolve, reject) => {
+      sensorObject.onactivate = () => {
+        // Now sensor proxy is initialized.
+        let anotherSensor = new sensorType({frequency: 21});
+        anotherSensor.start();
+        anotherSensor.stop();
+        resolve(mockSensor);
+      }
+    });
+    await mockSensor.removeConfigurationCalled();
+    sensorObject.stop();
+    return mockSensor.removeConfigurationCalled();
   }, `${sensorType.name}: Test that configuration is removed for a stopped sensor.`);
 
-  sensor_test(sensor => {
+  sensor_test(async sensor => {
     const maxSupportedFrequency = 5;
     sensor.mockSensorProvider.setMaximumSupportedFrequency(maxSupportedFrequency);
     let sensorObject = new sensorType({frequency: 50});
     sensorObject.start();
-    return sensor.mockSensorProvider.getCreatedSensor()
-        .then(mockSensor => mockSensor.addConfigurationCalled())
-        .then(mockSensor => {
-          return new Promise((resolve, reject) => {
-            let wrapper = new CallbackWrapper(() => {
-              assert_equals(mockSensor.getSamplingFrequency(), maxSupportedFrequency);
-              sensorObject.stop();
-              assert_false(sensorObject.activated);
-              resolve(mockSensor);
-           }, reject);
-           sensorObject.onactivate = wrapper.callback;
-           sensorObject.onerror = reject;
-          });
-        })
-        .then(mockSensor => mockSensor.removeConfigurationCalled());
+
+    let mockSensor = await sensor.mockSensorProvider.getCreatedSensor();
+    await mockSensor.addConfigurationCalled();
+    await new Promise((resolve, reject) => {
+      let wrapper = new CallbackWrapper(() => {
+        assert_equals(mockSensor.getSamplingFrequency(), maxSupportedFrequency);
+        sensorObject.stop();
+        assert_false(sensorObject.activated);
+        resolve(mockSensor);
+     }, reject);
+     sensorObject.onactivate = wrapper.callback;
+     sensorObject.onerror = reject;
+    });
+    return mockSensor.removeConfigurationCalled();
   }, `${sensorType.name}: Test that frequency is capped to the maximum supported from frequency.`);
 
-  sensor_test(sensor => {
+  sensor_test(async sensor => {
     const minSupportedFrequency = 2;
     sensor.mockSensorProvider.setMinimumSupportedFrequency(minSupportedFrequency);
     let sensorObject = new sensorType({frequency: -1});
     sensorObject.start();
-    return sensor.mockSensorProvider.getCreatedSensor()
-        .then(mockSensor => mockSensor.addConfigurationCalled())
-        .then(mockSensor => {
-          return new Promise((resolve, reject) => {
-            let wrapper = new CallbackWrapper(() => {
-              assert_equals(mockSensor.getSamplingFrequency(), minSupportedFrequency);
-              sensorObject.stop();
-              assert_false(sensorObject.activated);
-              resolve(mockSensor);
-           }, reject);
-           sensorObject.onactivate = wrapper.callback;
-           sensorObject.onerror = reject;
-          });
-        })
-        .then(mockSensor => mockSensor.removeConfigurationCalled());
+
+    let mockSensor = await sensor.mockSensorProvider.getCreatedSensor();
+    await mockSensor.addConfigurationCalled();
+    await new Promise((resolve, reject) => {
+      let wrapper = new CallbackWrapper(() => {
+        assert_equals(mockSensor.getSamplingFrequency(), minSupportedFrequency);
+        sensorObject.stop();
+        assert_false(sensorObject.activated);
+        resolve(mockSensor);
+     }, reject);
+     sensorObject.onactivate = wrapper.callback;
+     sensorObject.onerror = reject;
+    });
+    return mockSensor.removeConfigurationCalled();
   }, `${sensorType.name}: Test that frequency is limited to the minimum supported from frequency.`);
 
-  sensor_test(sensor => {
+  sensor_test(async sensor => {
     let sensorObject = new sensorType({frequency: 60});
     assert_false(sensorObject.activated);
     sensorObject.start();
     assert_false(sensorObject.activated);
-    return sensor.mockSensorProvider.getCreatedSensor()
-      .then((mockSensor) => {
-        return new Promise((resolve, reject) => {
-          let wrapper = new CallbackWrapper(() => {
-            assert_true(sensorObject.activated);
-            sensorObject.stop();
-            assert_false(sensorObject.activated);
-            resolve(mockSensor);
-          }, reject);
-          sensorObject.onactivate = wrapper.callback;
-          sensorObject.onerror = reject;
-        });
-      })
-      .then(mockSensor => mockSensor.removeConfigurationCalled());
+
+    let mockSensor = await sensor.mockSensorProvider.getCreatedSensor();
+    await new Promise((resolve, reject) => {
+      let wrapper = new CallbackWrapper(() => {
+        assert_true(sensorObject.activated);
+        sensorObject.stop();
+        assert_false(sensorObject.activated);
+        resolve(mockSensor);
+      }, reject);
+      sensorObject.onactivate = wrapper.callback;
+      sensorObject.onerror = reject;
+    });
+    return mockSensor.removeConfigurationCalled();
   }, `${sensorType.name}: Test that sensor can be successfully created and its states are correct.`);
 
-  sensor_test(sensor => {
+  sensor_test(async sensor => {
     let sensorObject = new sensorType();
     sensorObject.start();
-    return sensor.mockSensorProvider.getCreatedSensor()
-        .then((mockSensor) => {
-          return new Promise((resolve, reject) => {
-            let wrapper = new CallbackWrapper(() => {
-              assert_true(sensorObject.activated);
-              sensorObject.stop();
-              assert_false(sensorObject.activated);
-              resolve(mockSensor);
-            }, reject);
 
-            sensorObject.onactivate = wrapper.callback;
-            sensorObject.onerror = reject;
-          });
-        })
-        .then(mockSensor => mockSensor.removeConfigurationCalled());
+    let mockSensor = await sensor.mockSensorProvider.getCreatedSensor();
+    await new Promise((resolve, reject) => {
+      let wrapper = new CallbackWrapper(() => {
+        assert_true(sensorObject.activated);
+        sensorObject.stop();
+        assert_false(sensorObject.activated);
+        resolve(mockSensor);
+      }, reject);
+
+      sensorObject.onactivate = wrapper.callback;
+      sensorObject.onerror = reject;
+    });
+    return mockSensor.removeConfigurationCalled();
   }, `${sensorType.name}: Test that sensor can be constructed with default configuration.`);
 
-  sensor_test(sensor => {
+  sensor_test(async sensor => {
     let sensorObject = new sensorType({frequency: 60});
     sensorObject.start();
 
-    return sensor.mockSensorProvider.getCreatedSensor()
-        .then(mockSensor => mockSensor.addConfigurationCalled())
-        .then(mockSensor => {
-          return new Promise((resolve, reject) => {
-            let wrapper = new CallbackWrapper(() => {
-              assert_true(sensorObject.activated);
-              sensorObject.stop();
-              assert_false(sensorObject.activated);
-              resolve(mockSensor);
-           }, reject);
-           sensorObject.onactivate = wrapper.callback;
-           sensorObject.onerror = reject;
-          });
-        })
-        .then(mockSensor => mockSensor.removeConfigurationCalled());
+    let mockSensor = await sensor.mockSensorProvider.getCreatedSensor();
+    await mockSensor.addConfigurationCalled();
+    await new Promise((resolve, reject) => {
+      let wrapper = new CallbackWrapper(() => {
+        assert_true(sensorObject.activated);
+        sensorObject.stop();
+        assert_false(sensorObject.activated);
+        resolve(mockSensor);
+     }, reject);
+     sensorObject.onactivate = wrapper.callback;
+     sensorObject.onerror = reject;
+    });
+    return mockSensor.removeConfigurationCalled();
   }, `${sensorType.name}: Test that addConfiguration and removeConfiguration is called.`);
 
-  function checkOnReadingIsCalledAndReadingIsValid(sensor) {
+  async function checkOnReadingIsCalledAndReadingIsValid(sensor) {
     let sensorObject = new sensorType({frequency: 60});
     sensorObject.start();
     assert_false(sensorObject.hasReading);
-    return sensor.mockSensorProvider.getCreatedSensor()
-        .then(mockSensor => mockSensor.setUpdateSensorReadingFunction(updateReading))
-        .then(mockSensor => {
-          return new Promise((resolve, reject) => {
-            let wrapper = new CallbackWrapper(() => {
-              assert_true(verifyReading(sensorObject));
-              assert_true(sensorObject.hasReading);
-              sensorObject.stop();
-              assert_true(verifyReading(sensorObject, true /*should be null*/));
-              assert_false(sensorObject.hasReading);
-              resolve(mockSensor);
-            }, reject);
 
-            sensorObject.onreading = wrapper.callback;
-            sensorObject.onerror = reject;
-          });
-        })
-        .then(mockSensor => mockSensor.removeConfigurationCalled());
+    let mockSensor = await sensor.mockSensorProvider.getCreatedSensor();
+    await mockSensor.setUpdateSensorReadingFunction(updateReading);
+    await new Promise((resolve, reject) => {
+      let wrapper = new CallbackWrapper(() => {
+        assert_true(verifyReading(sensorObject));
+        assert_true(sensorObject.hasReading);
+        sensorObject.stop();
+        assert_true(verifyReading(sensorObject, true /*should be null*/));
+        assert_false(sensorObject.hasReading);
+        resolve(mockSensor);
+      }, reject);
+
+      sensorObject.onreading = wrapper.callback;
+      sensorObject.onerror = reject;
+    });
+    return mockSensor.removeConfigurationCalled();
   }
 
   sensor_test(sensor => checkOnReadingIsCalledAndReadingIsValid(sensor),
@@ -237,42 +219,33 @@
     return checkOnReadingIsCalledAndReadingIsValid(sensor);
   }, `${sensorType.name}: Test that onreading is called and sensor reading is valid (continuous reporting).`);
 
-  sensor_test(sensor => {
+  sensor_test(async sensor => {
     let sensorObject = new sensorType;
     sensorObject.start();
-    return sensor.mockSensorProvider.getCreatedSensor()
-        .then(mockSensor => mockSensor.setUpdateSensorReadingFunction(updateReading))
-        .then(mockSensor => {
-          return new Promise((resolve, reject) => {
-            let wrapper = new CallbackWrapper(() => {
-              assert_true(verifyReading(sensorObject));
-              resolve(mockSensor);
-            }, reject);
 
-            sensorObject.onreading = wrapper.callback;
-            sensorObject.onerror = reject;
-          });
-        })
-        .then(mockSensor => {
-          testRunner.setPageVisibility('hidden');
-          return mockSensor.suspendCalled();
-        })
-        .then(mockSensor => {
-          testRunner.setPageVisibility('visible');
-          return mockSensor.resumeCalled();
-        })
-        .then(mockSensor => {
-          return new Promise((resolve, reject) => {
-            sensorObject.stop();
-            resolve(mockSensor);
-            sensorObject.onerror = reject;
-          });
-        })
-        .then(mockSensor => mockSensor.removeConfigurationCalled());
+    let mockSensor = await sensor.mockSensorProvider.getCreatedSensor();
+    await mockSensor.setUpdateSensorReadingFunction(updateReading);
+    await new Promise((resolve, reject) => {
+      let wrapper = new CallbackWrapper(() => {
+        assert_true(verifyReading(sensorObject));
+        resolve(mockSensor);
+      }, reject);
+
+      sensorObject.onreading = wrapper.callback;
+      sensorObject.onerror = reject;
+    });
+    testRunner.setPageVisibility('hidden');
+    await mockSensor.suspendCalled();
+
+    testRunner.setPageVisibility('visible');
+    await mockSensor.resumeCalled();
+
+    sensorObject.stop();
+    await mockSensor.removeConfigurationCalled();
   }, `${sensorType.name}: Test that sensor receives suspend / resume notifications when page\
  visibility changes.`);
 
-  sensor_test(sensor => {
+  sensor_test(async sensor => {
     let sensorObject = new sensorType;
     sensorObject.start();
 
@@ -281,106 +254,99 @@
     let iframe = document.createElement('iframe');
     iframe.src = encodeURI(iframeSrc);
 
-    return sensor.mockSensorProvider.getCreatedSensor()
-        .then(mockSensor => mockSensor.setUpdateSensorReadingFunction(updateReading))
-        .then(mockSensor => new Promise((resolve, reject) => {
-          let wrapper = new CallbackWrapper(() => {
-            assert_true(verifyReading(sensorObject));
-            resolve(mockSensor);
-          }, reject);
+    let mockSensor = await sensor.mockSensorProvider.getCreatedSensor();
+    await mockSensor.setUpdateSensorReadingFunction(updateReading);
 
-          sensorObject.onreading = wrapper.callback;
-          sensorObject.onerror = reject;
-        }))
-        .then(mockSensor => {
-          document.body.appendChild(iframe);
-          return mockSensor.suspendCalled();
-        })
-        .then(mockSensor => {
-          window.focus();
-          return mockSensor.resumeCalled();
-        })
-        .then(mockSensor => new Promise((resolve, reject) => {
-          sensorObject.stop();
-          document.body.removeChild(iframe);
-          resolve(mockSensor);
-          sensorObject.onerror = reject;
-        }))
-        .then(mockSensor => mockSensor.removeConfigurationCalled());
+    await new Promise((resolve, reject) => {
+      let wrapper = new CallbackWrapper(() => {
+        assert_true(verifyReading(sensorObject));
+        resolve(mockSensor);
+      }, reject);
+
+      sensorObject.onreading = wrapper.callback;
+      sensorObject.onerror = reject;
+    });
+
+    document.body.appendChild(iframe);
+    await mockSensor.suspendCalled();
+
+    window.focus();
+    await mockSensor.resumeCalled();
+
+    sensorObject.stop();
+    document.body.removeChild(iframe);
+    return mockSensor.removeConfigurationCalled();
   }, `${sensorType.name}: Test that sensor receives suspend / resume notifications when\
  cross-origin subframe is focused`);
 
-  sensor_test(sensor => {
+  sensor_test(async sensor => {
     let sensor1 = new sensorType({frequency: 60});
     sensor1.start();
 
     let sensor2 = new sensorType({frequency: 20});
     sensor2.start();
-    return sensor.mockSensorProvider.getCreatedSensor()
-        .then(mockSensor => mockSensor.setUpdateSensorReadingFunction(updateReading))
-        .then(mockSensor => {
-          return new Promise((resolve, reject) => {
-            let wrapper = new CallbackWrapper(() => {
-              // Reading values are correct for both sensors.
-              assert_true(verifyReading(sensor1));
-              assert_true(verifyReading(sensor2));
 
-              // After first sensor stops its reading values are null,
-              // reading values for the second sensor sensor remain.
-              sensor1.stop();
-              assert_true(verifyReading(sensor1, true /*should be null*/));
-              assert_true(verifyReading(sensor2));
+    let mockSensor = await sensor.mockSensorProvider.getCreatedSensor();
+    await mockSensor.setUpdateSensorReadingFunction(updateReading);
+    await new Promise((resolve, reject) => {
+      let wrapper = new CallbackWrapper(() => {
+        // Reading values are correct for both sensors.
+        assert_true(verifyReading(sensor1));
+        assert_true(verifyReading(sensor2));
 
-              sensor2.stop();
-              assert_true(verifyReading(sensor2, true /*should be null*/));
+        // After first sensor stops its reading values are null,
+        // reading values for the second sensor sensor remain.
+        sensor1.stop();
+        assert_true(verifyReading(sensor1, true /*should be null*/));
+        assert_true(verifyReading(sensor2));
 
-              resolve(mockSensor);
-            }, reject);
+        sensor2.stop();
+        assert_true(verifyReading(sensor2, true /*should be null*/));
 
-            sensor1.onreading = wrapper.callback;
-            sensor1.onerror = reject;
-            sensor2.onerror = reject;
-          });
-        })
-        .then(mockSensor => mockSensor.removeConfigurationCalled());
+        resolve(mockSensor);
+      }, reject);
+
+      sensor1.onreading = wrapper.callback;
+      sensor1.onerror = reject;
+      sensor2.onerror = reject;
+    });
+    return mockSensor.removeConfigurationCalled();
   }, `${sensorType.name}: Test that sensor reading is correct.`);
 
-  function checkFrequencyHintWorks(sensor) {
+  async function checkFrequencyHintWorks(sensor) {
     let fastSensor = new sensorType({frequency: 30});
     let slowSensor = new sensorType({frequency: 5});
     slowSensor.start();
 
-    return sensor.mockSensorProvider.getCreatedSensor()
-        .then(mockSensor => mockSensor.setUpdateSensorReadingFunction(updateReading))
-        .then(mockSensor => {
-          return new Promise((resolve, reject) => {
-            let fastSensorNotifiedCounter = 0;
-            let slowSensorNotifiedCounter = 0;
+    let mockSensor = await sensor.mockSensorProvider.getCreatedSensor();
+    await mockSensor.setUpdateSensorReadingFunction(updateReading);
+    await new Promise((resolve, reject) => {
+      let fastSensorNotifiedCounter = 0;
+      let slowSensorNotifiedCounter = 0;
 
-            let fastSensorWrapper = new CallbackWrapper(() => {
-              fastSensorNotifiedCounter++;
-            }, reject);
+      let fastSensorWrapper = new CallbackWrapper(() => {
+        fastSensorNotifiedCounter++;
+      }, reject);
 
-            let slowSensorWrapper = new CallbackWrapper(() => {
-              slowSensorNotifiedCounter++;
-              if (slowSensorNotifiedCounter == 1) {
-                  fastSensor.start();
-              } else if (slowSensorNotifiedCounter == 3) {
-                assert_true(fastSensorNotifiedCounter > 2,
-                            "Fast sensor overtakes the slow one");
-                fastSensor.stop();
-                slowSensor.stop();
-                resolve(mockSensor);
-              }
-            }, reject);
+      let slowSensorWrapper = new CallbackWrapper(() => {
+        slowSensorNotifiedCounter++;
+        if (slowSensorNotifiedCounter == 1) {
+            fastSensor.start();
+        } else if (slowSensorNotifiedCounter == 3) {
+          assert_true(fastSensorNotifiedCounter > 2,
+                      "Fast sensor overtakes the slow one");
+          fastSensor.stop();
+          slowSensor.stop();
+          resolve(mockSensor);
+        }
+      }, reject);
 
-            fastSensor.onreading = fastSensorWrapper.callback;
-            slowSensor.onreading = slowSensorWrapper.callback;
-            fastSensor.onerror = reject;
-            slowSensor.onerror = reject;
-          });
-        })
-        .then(mockSensor => mockSensor.removeConfigurationCalled());
+      fastSensor.onreading = fastSensorWrapper.callback;
+      slowSensor.onreading = slowSensorWrapper.callback;
+      fastSensor.onerror = reject;
+      slowSensor.onerror = reject;
+    });
+    return mockSensor.removeConfigurationCalled();
   }
 
   sensor_test(sensor => checkFrequencyHintWorks(sensor),
@@ -426,29 +392,29 @@
     let mockSensor = await sensor.mockSensorProvider.getCreatedSensor();
     await mockSensor.setUpdateSensorReadingFunction(updateReading);
     await new Promise((resolve, reject) => {
-        let wrapper1 = new CallbackWrapper(() => {
-          assert_true(sensorObject.hasReading);
-          timestamp = sensorObject.timestamp;
-          sensorObject.stop();
+      let wrapper1 = new CallbackWrapper(() => {
+        assert_true(sensorObject.hasReading);
+        timestamp = sensorObject.timestamp;
+        sensorObject.stop();
 
-          assert_false(sensorObject.hasReading);
-          sensorObject.onreading = wrapper2.callback;
-          sensorObject.start();
-        }, reject);
+        assert_false(sensorObject.hasReading);
+        sensorObject.onreading = wrapper2.callback;
+        sensorObject.start();
+      }, reject);
 
-        let wrapper2 = new CallbackWrapper(() => {
-          assert_true(sensorObject.hasReading);
-          // Make sure that 'timestamp' is already initialized.
-          assert_greater_than(timestamp, 0);
-          // Check that the reading is updated.
-          assert_greater_than(sensorObject.timestamp, timestamp);
-          sensorObject.stop();
-          resolve(mockSensor);
-        }, reject);
+      let wrapper2 = new CallbackWrapper(() => {
+        assert_true(sensorObject.hasReading);
+        // Make sure that 'timestamp' is already initialized.
+        assert_greater_than(timestamp, 0);
+        // Check that the reading is updated.
+        assert_greater_than(sensorObject.timestamp, timestamp);
+        sensorObject.stop();
+        resolve(mockSensor);
+      }, reject);
 
-        sensorObject.onreading = wrapper1.callback;
-        sensorObject.onerror = reject;
-      });
+      sensorObject.onreading = wrapper1.callback;
+      sensorObject.onerror = reject;
+    });
     return mockSensor.removeConfigurationCalled();
   }, `${sensorType.name}: Test that fresh reading is fetched on start().`);
 }
diff --git a/third_party/WebKit/LayoutTests/typedcssom/stylevalue-objects/parse-parseAll-expected.txt b/third_party/WebKit/LayoutTests/typedcssom/stylevalue-objects/parse-parseAll-expected.txt
index e028bbb..072db6d 100644
--- a/third_party/WebKit/LayoutTests/typedcssom/stylevalue-objects/parse-parseAll-expected.txt
+++ b/third_party/WebKit/LayoutTests/typedcssom/stylevalue-objects/parse-parseAll-expected.txt
@@ -2,7 +2,7 @@
 PASS Calling CSSStyleValue.parse with an empty string throws a TypeError
 PASS Calling CSSStyleValue.parse with an unsupported CSS property throws a TypeError
 PASS Calling CSSStyleValue.parse with a CSS shorthand throws a TypeError
-FAIL Calling CSSStyleValue.parse with an invalid cssText for the given property throws a SyntaxError assert_throws: function "() => CSSStyleValue[parseMethod]('width', '10deg')" did not throw
+PASS Calling CSSStyleValue.parse with an invalid cssText for the given property throws a SyntaxError
 PASS Calling CSSStyleValue.parse with a valid cssText for the given property returns a valid CSSStyleValue
 PASS Calling CSSStyleValue.parse with a mixed case cssText returns a valid CSSStyleValue
 FAIL Calling CSSStyleValue.parse with a custom property returns a valid CSSStyleValue Failed to execute 'parse' on 'CSSStyleValue': Invalid property name
@@ -13,7 +13,7 @@
 FAIL Calling CSSStyleValue.parseAll with a valid cssText for the given property returns a valid CSSStyleValue CSSStyleValue[parseMethod] is not a function
 FAIL Calling CSSStyleValue.parseAll with a mixed case cssText returns a valid CSSStyleValue CSSStyleValue[parseMethod] is not a function
 FAIL Calling CSSStyleValue.parseAll with a custom property returns a valid CSSStyleValue CSSStyleValue[parseMethod] is not a function
-FAIL Calling CSSStyleValue.parse with a list-value property returns first list value Cannot read property 'constructor' of null
+PASS Calling CSSStyleValue.parse with a list-value property returns first list value
 FAIL Calling CSSStyleValue.parseAll with a list-value property returns a sequence of values CSSStyleValue.parseAll is not a function
 Harness: the test ran to completion.
 
diff --git a/third_party/WebKit/LayoutTests/typedcssom/stylevalue-subclasses/numeric-objects/cssMathValue.html b/third_party/WebKit/LayoutTests/typedcssom/stylevalue-subclasses/numeric-objects/cssMathValue.html
index 46eaf50a..44532fc7 100644
--- a/third_party/WebKit/LayoutTests/typedcssom/stylevalue-subclasses/numeric-objects/cssMathValue.html
+++ b/third_party/WebKit/LayoutTests/typedcssom/stylevalue-subclasses/numeric-objects/cssMathValue.html
@@ -8,14 +8,14 @@
 <script>
 'use strict';
 
-const gMathValueSubclasses = [
+const gVariadicMathValueSubclasses = [
   { subclass: CSSMathSum, operator: 'sum' },
   { subclass: CSSMathProduct, operator: 'product' },
   { subclass: CSSMathMin, operator: 'min' },
   { subclass: CSSMathMax, operator: 'max' },
 ];
 
-for (const {subclass, operator} of gMathValueSubclasses) {
+for (const {subclass, operator} of gVariadicMathValueSubclasses) {
   test(() => {
     assert_throws(new SyntaxError(), () => new subclass());
   }, 'Constructing a ' + subclass.name + ' with no arguments throws a SyntaxError');
@@ -36,4 +36,35 @@
   }, subclass.name + '.operator is readonly');
 }
 
+const gUnaryMathValueSubclasses = [
+  { subclass: CSSMathNegate, operator: 'negate' },
+  { subclass: CSSMathInvert, operator: 'invert' },
+]
+
+for (const {subclass, operator} of gUnaryMathValueSubclasses) {
+  test(() => {
+    const result1 = new subclass(CSS.number(0));
+    assert_equals(result1.operator, operator);
+    assert_style_value_equals(result1.value, CSS.number(0));
+
+    const result2 = new subclass(0);
+    assert_equals(result2.operator, operator);
+    assert_style_value_equals(result2.value, CSS.number(0));
+  }, subclass.name + ' can be constructed from a single numberish value');
+
+  test(() => {
+    let result = new subclass(CSS.number(1));
+    assert_throws(new TypeError(), () => result.operator = 'foo');
+  }, subclass.name + '.operator is readonly');
+
+  test(() => {
+    let result = new subclass(0);
+    result.value = CSS.number(1);
+    assert_style_value_equals(result.value, CSS.number(1));
+
+    result.value = 2;
+    assert_style_value_equals(result.value, CSS.number(2));
+  }, subclass.name + '.value can be updated with a numberish value');
+}
+
 </script>
diff --git a/third_party/WebKit/LayoutTests/virtual/color_space/fast/canvas/color-space/canvas-colorspace-arguments.html b/third_party/WebKit/LayoutTests/virtual/color_space/fast/canvas/color-space/canvas-colorspace-arguments.html
index 3abf07c..a518b2d7 100644
--- a/third_party/WebKit/LayoutTests/virtual/color_space/fast/canvas/color-space/canvas-colorspace-arguments.html
+++ b/third_party/WebKit/LayoutTests/virtual/color_space/fast/canvas/color-space/canvas-colorspace-arguments.html
@@ -4,55 +4,39 @@
 <script>
 
 var testScenarios = [
-    ["Test default context creation parameters", {}, {colorSpace: "srgb", pixelFormat: "8-8-8-8", linearPixelMath: false}],
+    ["Test default context creation parameters: srgb/8-8-8-8", {}, {colorSpace: "srgb", pixelFormat: "8-8-8-8"}],
 
-    ["Test CanvasColorSpace value srgb", {colorSpace: "srgb"}, {colorSpace: "srgb", pixelFormat: "8-8-8-8", linearPixelMath: false}],
-    ["Test CanvasColorSpace value rec2020", {colorSpace: "rec2020"},  {colorSpace: "srgb", pixelFormat: "8-8-8-8", linearPixelMath: false}],
-    ["Test CanvasColorSpace value p3", {colorSpace: "p3"}, {colorSpace: "srgb", pixelFormat: "8-8-8-8", linearPixelMath: false}],
+    ["Test CanvasColorSpace value srgb", {colorSpace: "srgb"}, {colorSpace: "srgb", pixelFormat: "8-8-8-8"}],
+    ["Test CanvasColorSpace value rec2020, no pixel format, falls back to srgb/8-8-8-8", {colorSpace: "rec2020"},  {colorSpace: "srgb", pixelFormat: "8-8-8-8"}],
+    ["Test CanvasColorSpace value p3, no pixel format, falls back to srgb/8-8-8-8", {colorSpace: "p3"},  {colorSpace: "srgb", pixelFormat: "8-8-8-8"}],
 
-    ["Test CanvasPixelFormat value 8-8-8-8", {pixelFormat: "8-8-8-8"}, {colorSpace: "srgb", pixelFormat: "8-8-8-8", linearPixelMath: false}],
-    ["Test CanvasPixelFormat value 10-10-10-2", {pixelFormat: "10-10-10-2"}, {colorSpace: "srgb", pixelFormat: "8-8-8-8", linearPixelMath: false}],
-    ["Test CanvasPixelFormat value 12-12-12-12", {pixelFormat: "12-12-12-12"}, {colorSpace: "srgb", pixelFormat: "8-8-8-8", linearPixelMath: false}],
-    ["Test CanvasPixelFormat value float16", {pixelFormat: "float16"}, {colorSpace: "srgb", pixelFormat: "float16", linearPixelMath: true}],
+    ["Test CanvasPixelFormat value 8-8-8-8", {pixelFormat: "8-8-8-8"}, {colorSpace: "srgb", pixelFormat: "8-8-8-8"}],
+    ["Test CanvasPixelFormat value 10-10-10-2, falls back to 8-8-8-8", {pixelFormat: "10-10-10-2"}, {colorSpace: "srgb", pixelFormat: "8-8-8-8"}],
+    ["Test CanvasPixelFormat value 12-12-12-12, falls back to 8-8-8-8", {pixelFormat: "12-12-12-12"}, {colorSpace: "srgb", pixelFormat: "8-8-8-8"}],
+    ["Test CanvasPixelFormat value float16", {pixelFormat: "float16"}, {colorSpace: "srgb", pixelFormat: "float16"}],
 
-    ["Test supported CanvasColorSpace and CanvasPixelFormat combination: srgb/8-8-8-8", {colorSpace: "srgb", pixelFormat: "8-8-8-8"}, {colorSpace: "srgb", pixelFormat: "8-8-8-8", linearPixelMath: false}],
-    ["Test not-supported CanvasColorSpace and CanvasPixelFormat combination: srgb/10-10-10-2", {colorSpace: "srgb", pixelFormat: "10-10-10-2"}, {colorSpace: "srgb", pixelFormat: "8-8-8-8", linearPixelMath: false}],
-    ["Test not-supported CanvasColorSpace and CanvasPixelFormat combination: srgb/12-12-12-12", {colorSpace: "srgb", pixelFormat: "12-12-12-12"}, {colorSpace: "srgb", pixelFormat: "8-8-8-8", linearPixelMath: false}],
-    ["Test supported CanvasColorSpace and CanvasPixelFormat combination: srgb/float16", {colorSpace: "srgb", pixelFormat: "float16"}, {colorSpace: "srgb", pixelFormat: "float16", linearPixelMath: true}],
+    ["Test supported CanvasColorSpace and CanvasPixelFormat combination: srgb/8-8-8-8", {colorSpace: "srgb", pixelFormat: "8-8-8-8"}, {colorSpace: "srgb", pixelFormat: "8-8-8-8"}],
+    ["Test not-supported CanvasColorSpace and CanvasPixelFormat combination: srgb/10-10-10-2", {colorSpace: "srgb", pixelFormat: "10-10-10-2"}, {colorSpace: "srgb", pixelFormat: "8-8-8-8"}],
+    ["Test not-supported CanvasColorSpace and CanvasPixelFormat combination: srgb/12-12-12-12", {colorSpace: "srgb", pixelFormat: "12-12-12-12"}, {colorSpace: "srgb", pixelFormat: "8-8-8-8"}],
+    ["Test supported CanvasColorSpace and CanvasPixelFormat combination: srgb/float16", {colorSpace: "srgb", pixelFormat: "float16"}, {colorSpace: "srgb", pixelFormat: "float16"}],
 
-    ["Test not-supported CanvasColorSpace and CanvasPixelFormat combination: rec2020/8-8-8-8", {colorSpace: "rec2020", pixelFormat: "8-8-8-8"}, {colorSpace: "srgb", pixelFormat: "8-8-8-8", linearPixelMath: false}],
-    ["Test not-supported CanvasColorSpace and CanvasPixelFormat combination: rec2020/10-10-10-2", {colorSpace: "rec2020", pixelFormat: "10-10-10-2"}, {colorSpace: "srgb", pixelFormat: "8-8-8-8", linearPixelMath: false}],
-    ["Test not-supported CanvasColorSpace and CanvasPixelFormat combination: rec2020/12-12-12-12", {colorSpace: "rec2020", pixelFormat: "12-12-12-12"}, {colorSpace: "srgb", pixelFormat: "8-8-8-8", linearPixelMath: false}],
-    ["Test supported CanvasColorSpace and CanvasPixelFormat combination: rec2020/float16", {colorSpace: "rec2020", pixelFormat: "float16"}, {colorSpace: "rec2020", pixelFormat: "float16", linearPixelMath: true}],
+    ["Test not-supported CanvasColorSpace and CanvasPixelFormat combination: rec2020/8-8-8-8, falls back to srgb/8-8-8-8", {colorSpace: "rec2020", pixelFormat: "8-8-8-8"}, {colorSpace: "srgb", pixelFormat: "8-8-8-8"}],
+    ["Test not-supported CanvasColorSpace and CanvasPixelFormat combination: rec2020/10-10-10-2, falls back to srgb/8-8-8-8", {colorSpace: "rec2020", pixelFormat: "10-10-10-2"}, {colorSpace: "srgb", pixelFormat: "8-8-8-8"}],
+    ["Test not-supported CanvasColorSpace and CanvasPixelFormat combination: rec2020/12-12-12-12, falls back to srgb/8-8-8-8", {colorSpace: "rec2020", pixelFormat: "12-12-12-12"}, {colorSpace: "srgb", pixelFormat: "8-8-8-8"}],
+    ["Test supported CanvasColorSpace and CanvasPixelFormat combination: rec2020/float16", {colorSpace: "rec2020", pixelFormat: "float16"}, {colorSpace: "rec2020", pixelFormat: "float16"}],
 
-    ["Test not-supported CanvasColorSpace and CanvasPixelFormat combination: p3/8-8-8-8", {colorSpace: "p3", pixelFormat: "8-8-8-8"}, {colorSpace: "srgb", pixelFormat: "8-8-8-8", linearPixelMath: false}],
-    ["Test not-supported CanvasColorSpace and CanvasPixelFormat combination: p3/10-10-10-2", {colorSpace: "p3", pixelFormat: "10-10-10-2"}, {colorSpace: "srgb", pixelFormat: "8-8-8-8", linearPixelMath: false}],
-    ["Test not-supported CanvasColorSpace and CanvasPixelFormat combination: p3/12-12-12-12", {colorSpace: "p3", pixelFormat: "12-12-12-12"}, {colorSpace: "srgb", pixelFormat: "8-8-8-8", linearPixelMath: false}],
-    ["Test supported CanvasColorSpace and CanvasPixelFormat combination: p3/float16", {colorSpace: "p3", pixelFormat: "float16"}, {colorSpace: "p3", pixelFormat: "float16", linearPixelMath: true}],
-
-    ["Test parameter linearPixelMath srgb/8-8-8-8/false", {colorSpace: "srgb", pixelFormat: "8-8-8-8", linearPixelMath: false}, {colorSpace: "srgb", pixelFormat: "8-8-8-8", linearPixelMath: false}],
-    ["Test parameter linearPixelMath srgb/8-8-8-8/true", {colorSpace: "srgb", pixelFormat: "8-8-8-8", linearPixelMath: true}, {colorSpace: "srgb", pixelFormat: "8-8-8-8", linearPixelMath: false}],
-    ["Test parameter linearPixelMath srgb/float16/false", {colorSpace: "srgb", pixelFormat: "float16", linearPixelMath: false}, {colorSpace: "srgb", pixelFormat: "float16", linearPixelMath: true}],
-    ["Test parameter linearPixelMath srgb/float16/true", {colorSpace: "srgb", pixelFormat: "float16", linearPixelMath: true}, {colorSpace: "srgb", pixelFormat: "float16", linearPixelMath: true}],
-
-    ["Test parameter linearPixelMath rec2020/float16/false", {colorSpace: "rec2020", pixelFormat: "float16", linearPixelMath: false}, {colorSpace: "rec2020", pixelFormat: "float16", linearPixelMath: true}],
-    ["Test parameter linearPixelMath rec2020/float16/true", {colorSpace: "rec2020", pixelFormat: "float16", linearPixelMath: true}, {colorSpace: "rec2020", pixelFormat: "float16", linearPixelMath: true}],
-
-    ["Test parameter linearPixelMath p3/float16/false", {colorSpace: "p3", pixelFormat: "float16", linearPixelMath: false}, {colorSpace: "p3", pixelFormat: "float16", linearPixelMath: true}],
-    ["Test parameter linearPixelMath p3/float16/true", {colorSpace: "p3", pixelFormat: "float16", linearPixelMath: true}, {colorSpace: "p3", pixelFormat: "float16", linearPixelMath: true}],
+    ["Test not-supported CanvasColorSpace and CanvasPixelFormat combination: p3/8-8-8-8, falls back to srgb/8-8-8-8", {colorSpace: "p3", pixelFormat: "8-8-8-8"}, {colorSpace: "srgb", pixelFormat: "8-8-8-8"}],
+    ["Test not-supported CanvasColorSpace and CanvasPixelFormat combination: p3/10-10-10-2, falls back to srgb/8-8-8-8", {colorSpace: "p3", pixelFormat: "10-10-10-2"}, {colorSpace: "srgb", pixelFormat: "8-8-8-8"}],
+    ["Test not-supported CanvasColorSpace and CanvasPixelFormat combination: p3/12-12-12-12, falls back to srgb/8-8-8-8", {colorSpace: "p3", pixelFormat: "12-12-12-12"}, {colorSpace: "srgb", pixelFormat: "8-8-8-8"}],
+    ["Test supported CanvasColorSpace and CanvasPixelFormat combination: p3/float16", {colorSpace: "p3", pixelFormat: "float16"}, {colorSpace: "p3", pixelFormat: "float16"}],
 ];
 
 function runTestScenario(contextCreationParameters, expectedContextAttributes) {
-    console.log(contextCreationParameters);
     var canvas = document. createElement('canvas');
     var ctx = canvas.getContext('2d', contextCreationParameters);
     var contextAttributes = ctx.getContextAttributes();
-    console.log(contextAttributes);
-    console.log(expectedContextAttributes);
     assert_equals(contextAttributes.colorSpace, expectedContextAttributes.colorSpace);
     assert_equals(contextAttributes.pixelFormat, expectedContextAttributes.pixelFormat);
-    // TODO(ccameron): linearPixelMath needs to be plumbed further.
-    // assert_equals(contextAttributes.linearPixelMath, expectedContextAttributes.linearPixelMath);
 }
 
 generate_tests(runTestScenario, testScenarios);
diff --git a/third_party/WebKit/LayoutTests/virtual/color_space/fast/canvas/color-space/canvas-createImageBitmap-linear-rgb.html b/third_party/WebKit/LayoutTests/virtual/color_space/fast/canvas/color-space/canvas-createImageBitmap-linear-rgb.html
index 6c80522..9cbe4a2 100644
--- a/third_party/WebKit/LayoutTests/virtual/color_space/fast/canvas/color-space/canvas-createImageBitmap-linear-rgb.html
+++ b/third_party/WebKit/LayoutTests/virtual/color_space/fast/canvas/color-space/canvas-createImageBitmap-linear-rgb.html
@@ -35,7 +35,7 @@
 {
     var actual, expected, tolerance = 0.01;
     if (sourceType === 'video')
-        tolerance = 0.02;
+        tolerance = 0.03;
     for (var i = 0; i < tests.length; i++) {
         actual = ctx.getImageData(tests[i][0], tests[i][1], 1, 1).dataUnion;
         expected = tests[i][2];
diff --git a/third_party/WebKit/LayoutTests/virtual/color_space/fast/canvas/color-space/canvas-createImageBitmap-p3.html b/third_party/WebKit/LayoutTests/virtual/color_space/fast/canvas/color-space/canvas-createImageBitmap-p3.html
index ee4a6ddb..d22d0db 100644
--- a/third_party/WebKit/LayoutTests/virtual/color_space/fast/canvas/color-space/canvas-createImageBitmap-p3.html
+++ b/third_party/WebKit/LayoutTests/virtual/color_space/fast/canvas/color-space/canvas-createImageBitmap-p3.html
@@ -31,7 +31,7 @@
 {
     var actual, expected, tolerance = 0.01;
     if (sourceType == 'video')
-        tolerance = 0.02;
+        tolerance = 0.03;
     for (var i = 0; i < tests.length; i++) {
         actual = ctx.getImageData(tests[i][0], tests[i][1], 1, 1).dataUnion;
         expected = tests[i][2];
diff --git a/third_party/WebKit/LayoutTests/virtual/color_space/fast/canvas/color-space/canvas-createImageBitmap-rec2020.html b/third_party/WebKit/LayoutTests/virtual/color_space/fast/canvas/color-space/canvas-createImageBitmap-rec2020.html
index 8abd8c5..d972ce8 100644
--- a/third_party/WebKit/LayoutTests/virtual/color_space/fast/canvas/color-space/canvas-createImageBitmap-rec2020.html
+++ b/third_party/WebKit/LayoutTests/virtual/color_space/fast/canvas/color-space/canvas-createImageBitmap-rec2020.html
@@ -35,7 +35,7 @@
 {
     var actual, expected, tolerance = 0.01;
     if (sourceType === 'video')
-        tolerance = 0.02;
+        tolerance = 0.03;
     for (var i = 0; i < tests.length; i++) {
         actual = ctx.getImageData(tests[i][0], tests[i][1], 1, 1).dataUnion;
         expected = tests[i][2];
diff --git a/third_party/WebKit/LayoutTests/virtual/color_space/fast/canvas/color-space/imageData-colorSpace.html b/third_party/WebKit/LayoutTests/virtual/color_space/fast/canvas/color-space/imageData-colorSpace.html
index 7b98c57..21a0aaa 100644
--- a/third_party/WebKit/LayoutTests/virtual/color_space/fast/canvas/color-space/imageData-colorSpace.html
+++ b/third_party/WebKit/LayoutTests/virtual/color_space/fast/canvas/color-space/imageData-colorSpace.html
@@ -18,8 +18,8 @@
 }
 
 function checkColorSettings(colorSettings, colorSpace, storageFormat) {
-  assert_equals(colorSpace, colorSettings.colorSpace);
-  assert_equals(storageFormat, colorSettings.storageFormat);
+  assert_equals(colorSettings.colorSpace, colorSpace);
+  assert_equals(colorSettings.storageFormat, storageFormat);
 }
 
 function runTest(colorSettings, expectedColorSettings) {
@@ -48,9 +48,9 @@
 }
 
 var testScenarios = [
-	["Test default color settings: {undefined, undefined} -> {legacy-srgb, uint8}", {}, {colorSpace: "legacy-srgb", storageFormat: "uint8"}],
+	["Test default color settings: {undefined, undefined} -> {srgb, uint8}", {}, {colorSpace: "srgb", storageFormat: "uint8"}],
   
-	["Test default color space: {undefined, float32} -> {legacy-srgb, float32}", {storageFormat: "float32"}, {colorSpace: "legacy-srgb", storageFormat: "float32"}],
+	["Test default color space: {undefined, float32} -> {srgb, float32}", {storageFormat: "float32"}, {colorSpace: "srgb", storageFormat: "float32"}],
 	["Test default storage format: {srgb, undefined} -> {srgb, uint8}", {colorSpace: "srgb"}, {colorSpace: "srgb", storageFormat: "uint8"}],
   
 	["Test color settings: {srgb, uint8}", {colorSpace: "srgb", storageFormat: "uint8"}, {colorSpace: "srgb", storageFormat: "uint8"}],
diff --git a/third_party/WebKit/LayoutTests/virtual/color_space/fast/canvas/color-space/imagedata-no-color-settings-crash.html b/third_party/WebKit/LayoutTests/virtual/color_space/fast/canvas/color-space/imagedata-no-color-settings-crash.html
new file mode 100644
index 0000000..fd60948
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/virtual/color_space/fast/canvas/color-space/imagedata-no-color-settings-crash.html
@@ -0,0 +1,26 @@
+<!DOCTYPE HTML>
+<script src="../../../../../resources/testharness.js"></script>
+<script src="../../../../../resources/testharnessreport.js"></script>
+<script>
+test(function() {
+    var canvas = document.createElement('canvas');
+    var ctx = canvas.getContext('2d',
+        {})
+    var dataLinearRGB = new Float32Array(4);
+    var imageData = ctx.createImageData(dataLinearRGB, 1, 1,
+        {});
+    ctx.putImageData(imageData, 5, 5);
+    var data = ctx.getImageData(5,5,1,1).dataUnion;
+}, "Putting a float-32 ImageData with no color settings on a context 2D should not crash.");
+
+test(function() {
+    var canvas = document.createElement('canvas');
+    var ctx = canvas.getContext('2d',
+        {})
+    var dataLinearRGB = new Uint16Array(4);
+    var imageData = ctx.createImageData(dataLinearRGB, 1, 1,
+        {});
+    ctx.putImageData(imageData, 5, 5);
+    var data = ctx.getImageData(5,5,1,1).dataUnion;
+}, "Putting a uint-16 ImageData with no color settings on a context 2D should not crash.");
+</script>
\ No newline at end of file
diff --git a/third_party/WebKit/LayoutTests/virtual/feature-policy-permissions/http/tests/webmidi/README.txt b/third_party/WebKit/LayoutTests/virtual/feature-policy-permissions/http/tests/webmidi/README.txt
deleted file mode 100644
index 72baed6..0000000
--- a/third_party/WebKit/LayoutTests/virtual/feature-policy-permissions/http/tests/webmidi/README.txt
+++ /dev/null
@@ -1 +0,0 @@
-# These tests run with --enable-features=UseFeaturePolicyForPermissions
diff --git a/third_party/WebKit/LayoutTests/virtual/stable/webexposed/global-interface-listing-expected.txt b/third_party/WebKit/LayoutTests/virtual/stable/webexposed/global-interface-listing-expected.txt
index 1bf5ffd..4428a6b 100644
--- a/third_party/WebKit/LayoutTests/virtual/stable/webexposed/global-interface-listing-expected.txt
+++ b/third_party/WebKit/LayoutTests/virtual/stable/webexposed/global-interface-listing-expected.txt
@@ -8075,7 +8075,6 @@
     method focus
     method gc
     method getComputedStyle
-    method getMatchedCSSRules
     method getSelection
     method matchMedia
     method moveBy
diff --git a/third_party/WebKit/LayoutTests/webexposed/global-interface-listing-expected.txt b/third_party/WebKit/LayoutTests/webexposed/global-interface-listing-expected.txt
index 143bfa0..13bbd3f 100644
--- a/third_party/WebKit/LayoutTests/webexposed/global-interface-listing-expected.txt
+++ b/third_party/WebKit/LayoutTests/webexposed/global-interface-listing-expected.txt
@@ -638,12 +638,22 @@
     getter value
     method constructor
     setter value
+interface CSSMathInvert : CSSMathValue
+    attribute @@toStringTag
+    getter value
+    method constructor
+    setter value
 interface CSSMathMax : CSSMathValue
     attribute @@toStringTag
     method constructor
 interface CSSMathMin : CSSMathValue
     attribute @@toStringTag
     method constructor
+interface CSSMathNegate : CSSMathValue
+    attribute @@toStringTag
+    getter value
+    method constructor
+    setter value
 interface CSSMathProduct : CSSMathValue
     attribute @@toStringTag
     method constructor
@@ -2044,6 +2054,7 @@
     getter mapping
     getter pose
     getter timestamp
+    getter vibrationActuator
     method constructor
 interface GamepadButton
     attribute @@toStringTag
@@ -2055,6 +2066,12 @@
     attribute @@toStringTag
     getter gamepad
     method constructor
+interface GamepadHapticActuator
+    attribute @@toStringTag
+    getter type
+    method constructor
+    method playEffect
+    method reset
 interface GamepadPose
     attribute @@toStringTag
     getter angularAcceleration
@@ -9258,7 +9275,6 @@
     method gc
     method getComputedStyle
     method getComputedStyleMap
-    method getMatchedCSSRules
     method getSelection
     method matchMedia
     method moveBy
diff --git a/third_party/WebKit/Source/bindings/core/v8/LocalWindowProxy.cpp b/third_party/WebKit/Source/bindings/core/v8/LocalWindowProxy.cpp
index b1c89c5..81bf5bd 100644
--- a/third_party/WebKit/Source/bindings/core/v8/LocalWindowProxy.cpp
+++ b/third_party/WebKit/Source/bindings/core/v8/LocalWindowProxy.cpp
@@ -194,6 +194,9 @@
   TRACE_EVENT1("v8", "LocalWindowProxy::CreateContext", "IsMainFrame",
                GetFrame()->IsMainFrame());
 
+  // TODO(yukishiino): Remove this CHECK once crbug.com/713699 gets fixed.
+  CHECK(IsMainThread());
+
   Vector<const char*> extension_names;
   // Dynamically tell v8 about our extensions now.
   if (GetFrame()->Client()->AllowScriptExtensions()) {
diff --git a/third_party/WebKit/Source/bindings/core/v8/V8ScriptRunner.cpp b/third_party/WebKit/Source/bindings/core/v8/V8ScriptRunner.cpp
index baf6ea0..17f71b78 100644
--- a/third_party/WebKit/Source/bindings/core/v8/V8ScriptRunner.cpp
+++ b/third_party/WebKit/Source/bindings/core/v8/V8ScriptRunner.cpp
@@ -555,8 +555,8 @@
 
   V8CompileHistogram::Cacheability cacheability_if_no_handler =
       V8CompileHistogram::Cacheability::kNoncacheable;
-  if (!cache_handler && (script_start_position.line_.ZeroBasedInt() == 0) &&
-      (script_start_position.column_.ZeroBasedInt() == 0))
+  if (!cache_handler && (script_start_position.line_.ZeroBasedInt() != 0 ||
+                         script_start_position.column_.ZeroBasedInt() != 0))
     cacheability_if_no_handler =
         V8CompileHistogram::Cacheability::kInlineScript;
 
diff --git a/third_party/WebKit/Source/bindings/core/v8/WindowProxyManager.cpp b/third_party/WebKit/Source/bindings/core/v8/WindowProxyManager.cpp
index 00fd985..e5c3365 100644
--- a/third_party/WebKit/Source/bindings/core/v8/WindowProxyManager.cpp
+++ b/third_party/WebKit/Source/bindings/core/v8/WindowProxyManager.cpp
@@ -61,7 +61,7 @@
   // All WindowProxyManagers must be created in the main thread.
   // Note that |isolate_| is initialized with
   // V8PerIsolateData::MainThreadIsolate().
-  DCHECK(IsMainThread());
+  CHECK(IsMainThread());
 }
 
 WindowProxy* WindowProxyManager::CreateWindowProxy(DOMWrapperWorld& world) {
diff --git a/third_party/WebKit/Source/build/scripts/core/css/properties/templates/CSSPropertyAPISubclass.h.tmpl b/third_party/WebKit/Source/build/scripts/core/css/properties/templates/CSSPropertyAPISubclass.h.tmpl
index d154c4c..402799d 100644
--- a/third_party/WebKit/Source/build/scripts/core/css/properties/templates/CSSPropertyAPISubclass.h.tmpl
+++ b/third_party/WebKit/Source/build/scripts/core/css/properties/templates/CSSPropertyAPISubclass.h.tmpl
@@ -65,11 +65,9 @@
 class {{api_classname}} : public CSSPropertyAPI {
  public:
   constexpr {{api_classname}}(CSSPropertyID id) : CSSPropertyAPI(id) {}
-
   {% for api_method in property.api_methods %}
   {{api_method.return_type}} {{api_method.name}}{{api_method.parameters}} const override;
   {% endfor %}
-
   {% if property.interpolable %}
   bool IsInterpolable() const override { return true; }
   {% endif %}
@@ -83,7 +81,6 @@
   {% if property.is_descriptor %}
   bool IsDescriptor() const override { return true; }
   {% endif %}
-
   {% if property.should_declare_application_functions %}
     {% if not property.api_custom_apply_functions_initial %}
   void ApplyInitial(StyleResolverState& state) const override {
@@ -100,7 +97,6 @@
   }
     {% endif %}
     {# TODO(meade): else emit function declaration only #}
-
     {% if not property.api_custom_apply_functions_inherit %}
   void ApplyInherit(StyleResolverState& state) const override {
       {% if property.svg %}
@@ -116,7 +112,6 @@
   }
     {% endif %}
     {# TODO(meade): else emit function declaration only #}
-
     {% if not property.api_custom_apply_functions_value %}
   void ApplyValue(StyleResolverState& state, const CSSValue& value) const override {
     {{convert_and_set_value(property)}}
@@ -143,7 +138,6 @@
   {% if not property.affected_by_all %}
   bool IsAffectedByAll() const override { return false; }
   {% endif %}
-
   {% if property.direction_aware_options %}
     {% if property.direction_aware_options.logical_side == "width" %}
   CSSPropertyID ResolveDirectionAwareProperty(
diff --git a/third_party/WebKit/Source/build/scripts/make_computed_style_base.py b/third_party/WebKit/Source/build/scripts/make_computed_style_base.py
index 20f8f26..3e99838 100755
--- a/third_party/WebKit/Source/build/scripts/make_computed_style_base.py
+++ b/third_party/WebKit/Source/build/scripts/make_computed_style_base.py
@@ -424,8 +424,8 @@
         "Length of rule and num_layers mismatch"
 
     layers_name = [
-        "rare-non-inherited-usage-less-than-{}".format(
-            str(int(round(partition_rule[i] * 100))) + "-percent")
+        "rare-non-inherited-usage-less-than-{}-percent".format(
+            int(round(partition_rule[i] * 100)))
         for i in range(num_layers)
     ]
     properties_ranking = _get_properties_ranking_using_partition_rule(
@@ -474,7 +474,8 @@
 
     layers_name = [
         "rare-inherited-usage-less-than-{}-percent".format(
-            str(int(round(partition_rule[i] * 100))) for i in range(num_layers))
+            int(round(partition_rule[i] * 100)))
+        for i in range(num_layers)
     ]
 
     properties_ranking = _get_properties_ranking_using_partition_rule(
diff --git a/third_party/WebKit/Source/build/scripts/make_instrumenting_probes.py b/third_party/WebKit/Source/build/scripts/make_instrumenting_probes.py
index 4d36961..aa345ad3 100644
--- a/third_party/WebKit/Source/build/scripts/make_instrumenting_probes.py
+++ b/third_party/WebKit/Source/build/scripts/make_instrumenting_probes.py
@@ -162,7 +162,7 @@
 
 
 def build_param_name(param_type):
-    return "param" + re.match(r"(const |RefPtr<)?(\w*)", param_type).group(2)
+    return "param" + re.match(r"(const |scoped_refptr<)?(\w*)", param_type).group(2)
 
 
 def load_config(file_name):
diff --git a/third_party/WebKit/Source/build/scripts/templates/fields/group.tmpl b/third_party/WebKit/Source/build/scripts/templates/fields/group.tmpl
index 35a2b46..9f17385 100644
--- a/third_party/WebKit/Source/build/scripts/templates/fields/group.tmpl
+++ b/third_party/WebKit/Source/build/scripts/templates/fields/group.tmpl
@@ -7,10 +7,10 @@
 {% endfor %}
 class {{group.type_name}} : public RefCounted<{{group.type_name}}> {
  public:
-  static RefPtr<{{group.type_name}}> Create() {
+  static scoped_refptr<{{group.type_name}}> Create() {
     return WTF::AdoptRef(new {{group.type_name}});
   }
-  RefPtr<{{group.type_name}}> Copy() const {
+  scoped_refptr<{{group.type_name}}> Copy() const {
     return WTF::AdoptRef(new {{group.type_name}}(*this));
   }
 
diff --git a/third_party/WebKit/Source/core/BUILD.gn b/third_party/WebKit/Source/core/BUILD.gn
index fd72688..d5867dc 100644
--- a/third_party/WebKit/Source/core/BUILD.gn
+++ b/third_party/WebKit/Source/core/BUILD.gn
@@ -1445,6 +1445,7 @@
     "dom/events/EventPathTest.cpp",
     "dom/events/EventTargetTest.cpp",
     "dom/events/ListenerLeakTest.cpp",
+    "dom/ng/flat_tree_traversal_ng_test.cc",
     "editing/CaretDisplayItemClientTest.cpp",
     "editing/KeyboardTest.cpp",
     "editing/LinkSelectionTest.cpp",
diff --git a/third_party/WebKit/Source/core/DEPS b/third_party/WebKit/Source/core/DEPS
index 689b9c7..342afac2 100644
--- a/third_party/WebKit/Source/core/DEPS
+++ b/third_party/WebKit/Source/core/DEPS
@@ -1,4 +1,5 @@
 include_rules = [
+    "+base/atomic_sequence_num.h",
     "+base/memory/scoped_refptr.h",
     "+bindings/core",
     "-bindings/modules",
diff --git a/third_party/WebKit/Source/core/animation/CSSRayInterpolationType.cpp b/third_party/WebKit/Source/core/animation/CSSRayInterpolationType.cpp
index 9046f6e..e4a2aae 100644
--- a/third_party/WebKit/Source/core/animation/CSSRayInterpolationType.cpp
+++ b/third_party/WebKit/Source/core/animation/CSSRayInterpolationType.cpp
@@ -40,7 +40,7 @@
 
 class CSSRayNonInterpolableValue : public NonInterpolableValue {
  public:
-  static RefPtr<CSSRayNonInterpolableValue> Create(const RayMode& mode) {
+  static scoped_refptr<CSSRayNonInterpolableValue> Create(const RayMode& mode) {
     return WTF::AdoptRef(new CSSRayNonInterpolableValue(mode));
   }
 
@@ -91,12 +91,12 @@
 class InheritedRayChecker : public CSSInterpolationType::CSSConversionChecker {
  public:
   static std::unique_ptr<InheritedRayChecker> Create(
-      RefPtr<StyleRay> style_ray) {
+      scoped_refptr<StyleRay> style_ray) {
     return WTF::WrapUnique(new InheritedRayChecker(std::move(style_ray)));
   }
 
  private:
-  InheritedRayChecker(RefPtr<StyleRay> style_ray)
+  InheritedRayChecker(scoped_refptr<StyleRay> style_ray)
       : style_ray_(std::move(style_ray)) {
     DCHECK(style_ray_);
   }
@@ -106,7 +106,7 @@
     return GetRay(*state.ParentStyle()) == style_ray_.get();
   }
 
-  const RefPtr<StyleRay> style_ray_;
+  const scoped_refptr<StyleRay> style_ray_;
 };
 
 InterpolationValue CreateValue(float angle, const RayMode& mode) {
diff --git a/third_party/WebKit/Source/core/clipboard/DataTransfer.cpp b/third_party/WebKit/Source/core/clipboard/DataTransfer.cpp
index be0b762..de74cb05 100644
--- a/third_party/WebKit/Source/core/clipboard/DataTransfer.cpp
+++ b/third_party/WebKit/Source/core/clipboard/DataTransfer.cpp
@@ -114,8 +114,7 @@
     PaintLayerFlags flags = kPaintLayerHaveTransparency |
                             kPaintLayerAppliedTransform |
                             kPaintLayerUncachedClipRects;
-    PaintRecordBuilder builder(
-        DataTransfer::DeviceSpaceRect(bounding_box, *local_frame_));
+    PaintRecordBuilder builder;
 
     dragged_layout_object->GetDocument().Lifecycle().AdvanceTo(
         DocumentLifecycle::kInPaint);
diff --git a/third_party/WebKit/Source/core/core_idl_files.gni b/third_party/WebKit/Source/core/core_idl_files.gni
index 59b55402..8cfd81ff 100644
--- a/third_party/WebKit/Source/core/core_idl_files.gni
+++ b/third_party/WebKit/Source/core/core_idl_files.gni
@@ -74,8 +74,10 @@
                     "css/cssom/CSSImageValue.idl",
                     "css/cssom/CSSKeywordValue.idl",
                     "css/cssom/CSSMatrixComponent.idl",
+                    "css/cssom/CSSMathInvert.idl",
                     "css/cssom/CSSMathMax.idl",
                     "css/cssom/CSSMathMin.idl",
+                    "css/cssom/CSSMathNegate.idl",
                     "css/cssom/CSSMathSum.idl",
                     "css/cssom/CSSMathProduct.idl",
                     "css/cssom/CSSMathValue.idl",
diff --git a/third_party/WebKit/Source/core/css/BUILD.gn b/third_party/WebKit/Source/core/css/BUILD.gn
index d414292..aa48e3b 100644
--- a/third_party/WebKit/Source/core/css/BUILD.gn
+++ b/third_party/WebKit/Source/core/css/BUILD.gn
@@ -374,8 +374,6 @@
     "parser/CSSParserLocalContext.h",
     "parser/CSSParserMode.h",
     "parser/CSSParserObserver.h",
-    "parser/CSSParserObserverWrapper.cpp",
-    "parser/CSSParserObserverWrapper.h",
     "parser/CSSParserScopedTokenBuffer.h",
     "parser/CSSParserSelector.cpp",
     "parser/CSSParserSelector.h",
diff --git a/third_party/WebKit/Source/core/css/CSSCrossfadeValue.cpp b/third_party/WebKit/Source/core/css/CSSCrossfadeValue.cpp
index 7aa94d8..5c4975d2 100644
--- a/third_party/WebKit/Source/core/css/CSSCrossfadeValue.cpp
+++ b/third_party/WebKit/Source/core/css/CSSCrossfadeValue.cpp
@@ -250,11 +250,13 @@
       FixedSize(document, FloatSize(size)), size);
 }
 
-void CSSCrossfadeValue::CrossfadeChanged(const IntRect&) {
+void CSSCrossfadeValue::CrossfadeChanged(
+    const IntRect&,
+    ImageResourceObserver::CanDeferInvalidation defer) {
   for (const auto& curr : Clients()) {
     ImageResourceObserver* client =
         const_cast<ImageResourceObserver*>(curr.key);
-    client->ImageChanged(static_cast<WrappedImagePtr>(this));
+    client->ImageChanged(static_cast<WrappedImagePtr>(this), defer);
   }
 }
 
@@ -268,9 +270,10 @@
 
 void CSSCrossfadeValue::CrossfadeSubimageObserverProxy::ImageChanged(
     ImageResourceContent*,
+    CanDeferInvalidation defer,
     const IntRect* rect) {
   if (ready_)
-    owner_value_->CrossfadeChanged(*rect);
+    owner_value_->CrossfadeChanged(*rect, defer);
 }
 
 bool CSSCrossfadeValue::CrossfadeSubimageObserverProxy::WillRenderImage() {
diff --git a/third_party/WebKit/Source/core/css/CSSCrossfadeValue.h b/third_party/WebKit/Source/core/css/CSSCrossfadeValue.h
index e521cd4..033f69c 100644
--- a/third_party/WebKit/Source/core/css/CSSCrossfadeValue.h
+++ b/third_party/WebKit/Source/core/css/CSSCrossfadeValue.h
@@ -91,7 +91,9 @@
     ~CrossfadeSubimageObserverProxy() override {}
     void Trace(blink::Visitor* visitor) { visitor->Trace(owner_value_); }
 
-    void ImageChanged(ImageResourceContent*, const IntRect* = nullptr) override;
+    void ImageChanged(ImageResourceContent*,
+                      CanDeferInvalidation,
+                      const IntRect* = nullptr) override;
     bool WillRenderImage() override;
     String DebugName() const override {
       return "CrossfadeSubimageObserverProxy";
@@ -104,7 +106,8 @@
   };
 
   bool WillRenderImage() const;
-  void CrossfadeChanged(const IntRect&);
+  void CrossfadeChanged(const IntRect&,
+                        ImageResourceObserver::CanDeferInvalidation);
 
   Member<CSSValue> from_value_;
   Member<CSSValue> to_value_;
diff --git a/third_party/WebKit/Source/core/css/CSSImageSetValue.cpp b/third_party/WebKit/Source/core/css/CSSImageSetValue.cpp
index 4902ab02..f93a6643 100644
--- a/third_party/WebKit/Source/core/css/CSSImageSetValue.cpp
+++ b/third_party/WebKit/Source/core/css/CSSImageSetValue.cpp
@@ -117,7 +117,9 @@
     ResourceRequest resource_request(document.CompleteURL(image.image_url));
     resource_request.SetHTTPReferrer(image.referrer);
     ResourceLoaderOptions options;
-    options.initiator_info.name = FetchInitiatorTypeNames::css;
+    options.initiator_info.name = parser_mode_ == kUASheetMode
+                                      ? FetchInitiatorTypeNames::uacss
+                                      : FetchInitiatorTypeNames::css;
     FetchParameters params(resource_request, options);
 
     if (cross_origin != kCrossOriginAttributeNotSet) {
diff --git a/third_party/WebKit/Source/core/css/CSSPaintValue.cpp b/third_party/WebKit/Source/core/css/CSSPaintValue.cpp
index 7aa2bf35..827bbbd6 100644
--- a/third_party/WebKit/Source/core/css/CSSPaintValue.cpp
+++ b/third_party/WebKit/Source/core/css/CSSPaintValue.cpp
@@ -104,7 +104,8 @@
     // TODO(ikilpatrick): We shouldn't be casting like this or mutate the layout
     // tree from a const pointer.
     const_cast<ImageResourceObserver*>(client)->ImageChanged(
-        static_cast<WrappedImagePtr>(this));
+        static_cast<WrappedImagePtr>(this),
+        ImageResourceObserver::CanDeferInvalidation::kNo);
   }
 }
 
diff --git a/third_party/WebKit/Source/core/css/StyleEngine.cpp b/third_party/WebKit/Source/core/css/StyleEngine.cpp
index f954cfd..7754bf0 100644
--- a/third_party/WebKit/Source/core/css/StyleEngine.cpp
+++ b/third_party/WebKit/Source/core/css/StyleEngine.cpp
@@ -1199,8 +1199,20 @@
   if (changed_rule_sets.IsEmpty())
     return;
 
-  if (changed_rule_flags & kKeyframesRules)
+  if (changed_rule_flags & kKeyframesRules) {
+    if (invalidation_scope == kInvalidateAllScopes) {
+      if (change == kActiveSheetsChanged)
+        ClearKeyframeRules();
+
+      for (auto it = new_style_sheets.begin();
+           it != new_style_sheets.end(); it++) {
+        DCHECK(it->second);
+        AddKeyframeRules(*it->second);
+      }
+    }
+
     ScopedStyleResolver::KeyframesRulesAdded(tree_scope);
+  }
 
   Node& invalidation_root =
       ScopedStyleResolver::InvalidationRootForTreeScope(tree_scope);
@@ -1328,10 +1340,44 @@
   }
 }
 
+void StyleEngine::AddKeyframeRules(const RuleSet& rule_set) {
+  const HeapVector<Member<StyleRuleKeyframes>> keyframes_rules =
+      rule_set.KeyframesRules();
+  for (unsigned i = 0; i < keyframes_rules.size(); ++i)
+    AddKeyframeStyle(keyframes_rules[i]);
+}
+
+void StyleEngine::AddKeyframeStyle(StyleRuleKeyframes* rule) {
+  AtomicString animation_name(rule->GetName());
+
+  if (rule->IsVendorPrefixed()) {
+    KeyframesRuleMap::iterator it = keyframes_rule_map_.find(animation_name);
+    if (it == keyframes_rule_map_.end())
+      keyframes_rule_map_.Set(animation_name, rule);
+    else if (it->value->IsVendorPrefixed())
+      keyframes_rule_map_.Set(animation_name, rule);
+  } else {
+    keyframes_rule_map_.Set(animation_name, rule);
+  }
+}
+
+StyleRuleKeyframes* StyleEngine::KeyframeStylesForAnimation(
+    const AtomicString& animation_name) {
+  if (keyframes_rule_map_.IsEmpty())
+    return nullptr;
+
+  KeyframesRuleMap::iterator it = keyframes_rule_map_.find(animation_name);
+  if (it == keyframes_rule_map_.end())
+    return nullptr;
+
+  return it->value.Get();
+}
+
 void StyleEngine::Trace(blink::Visitor* visitor) {
   visitor->Trace(document_);
   visitor->Trace(user_style_sheets_);
   visitor->Trace(active_user_style_sheets_);
+  visitor->Trace(keyframes_rule_map_);
   visitor->Trace(inspector_style_sheet_);
   visitor->Trace(document_style_sheet_collection_);
   visitor->Trace(style_sheet_collection_map_);
diff --git a/third_party/WebKit/Source/core/css/StyleEngine.h b/third_party/WebKit/Source/core/css/StyleEngine.h
index 42fa8de..4e91f56 100644
--- a/third_party/WebKit/Source/core/css/StyleEngine.h
+++ b/third_party/WebKit/Source/core/css/StyleEngine.h
@@ -284,6 +284,9 @@
   void ClearWhitespaceReattachSet() { whitespace_reattach_set_.clear(); }
   void MarkForWhitespaceReattachment();
 
+  StyleRuleKeyframes* KeyframeStylesForAnimation(
+      const AtomicString& animation_name);
+
   virtual void Trace(blink::Visitor*);
   void TraceWrappers(const ScriptWrappableVisitor*) const;
 
@@ -361,6 +364,11 @@
   const MediaQueryEvaluator& EnsureMediaQueryEvaluator();
   void UpdateStyleSheetList(TreeScope&);
 
+  void ClearKeyframeRules() { keyframes_rule_map_.clear(); }
+
+  void AddKeyframeRules(const RuleSet&);
+  void AddKeyframeStyle(StyleRuleKeyframes*);
+
   Member<Document> document_;
   bool is_master_;
 
@@ -372,10 +380,6 @@
   int pending_render_blocking_stylesheets_ = 0;
   int pending_body_stylesheets_ = 0;
 
-  HeapVector<std::pair<WebStyleSheetId, TraceWrapperMember<CSSStyleSheet>>>
-      user_style_sheets_;
-  ActiveStyleSheetVector active_user_style_sheets_;
-
   Member<CSSStyleSheet> inspector_style_sheet_;
 
   TraceWrapperMember<DocumentStyleSheetCollection>
@@ -424,8 +428,16 @@
   std::unique_ptr<StyleResolverStats> style_resolver_stats_;
   unsigned style_for_element_count_ = 0;
 
+  HeapVector<std::pair<WebStyleSheetId, TraceWrapperMember<CSSStyleSheet>>>
+      user_style_sheets_;
+  ActiveStyleSheetVector active_user_style_sheets_;
+
   WebStyleSheetId user_sheets_id_count_ = 0;
 
+  using KeyframesRuleMap =
+      HeapHashMap<AtomicString, Member<StyleRuleKeyframes>>;
+  KeyframesRuleMap keyframes_rule_map_;
+
   friend class StyleEngineTest;
 };
 
diff --git a/third_party/WebKit/Source/core/css/StyleEngineTest.cpp b/third_party/WebKit/Source/core/css/StyleEngineTest.cpp
index 3a16a44..919e9ae 100644
--- a/third_party/WebKit/Source/core/css/StyleEngineTest.cpp
+++ b/third_party/WebKit/Source/core/css/StyleEngineTest.cpp
@@ -84,10 +84,12 @@
       "<style>"
       " #t1 { color: red !important }"
       " #t2 { color: black }"
+      " #t4 { animation-name: dummy-animation }"
       "</style>"
       "<div id='t1'>Green</div>"
       "<div id='t2'>White</div>"
       "<div id='t3' style='color: black !important'>White</div>"
+      "<div id='t4'>I animate!</div>"
       "<div></div>");
   GetDocument().View()->UpdateAllLifecyclePhases();
 
@@ -187,6 +189,59 @@
             t2->GetComputedStyle()->VisitedDependentColor(CSSPropertyColor));
   EXPECT_EQ(MakeRGB(0, 0, 0),
             t3->GetComputedStyle()->VisitedDependentColor(CSSPropertyColor));
+
+  // @keyframes rules
+
+  Element* t4 = GetDocument().getElementById("t4");
+  ASSERT_TRUE(t4);
+
+  // There's no @keyframes rule named dummy-animation
+  ASSERT_FALSE(GetStyleEngine().Resolver()->FindKeyframesRule(
+      t4, AtomicString("dummy-animation")));
+
+  StyleSheetContents* keyframes_parsed_sheet =
+      StyleSheetContents::Create(CSSParserContext::Create(GetDocument()));
+  keyframes_parsed_sheet->ParseString("@keyframes dummy-animation { from {} }");
+  WebStyleSheetId keyframes_id =
+      GetStyleEngine().AddUserSheet(keyframes_parsed_sheet);
+  GetDocument().View()->UpdateAllLifecyclePhases();
+
+  // After injecting the style sheet, a @keyframes rule named dummy-animation
+  // is found with one keyframe.
+  StyleRuleKeyframes* keyframes =
+      GetStyleEngine().Resolver()->FindKeyframesRule(
+          t4, AtomicString("dummy-animation"));
+  ASSERT_TRUE(keyframes);
+  EXPECT_EQ(1u, keyframes->Keyframes().size());
+
+  HTMLStyleElement* style_element = HTMLStyleElement::Create(
+      GetDocument(), false);
+  style_element->SetInnerHTMLFromString(
+      "@keyframes dummy-animation { from {} to {} }");
+  GetDocument().body()->AppendChild(style_element);
+  GetDocument().View()->UpdateAllLifecyclePhases();
+
+  // Author @keyframes rules take precedence; now there are two keyframes (from
+  // and to).
+  keyframes = GetStyleEngine().Resolver()->FindKeyframesRule(
+      t4, AtomicString("dummy-animation"));
+  ASSERT_TRUE(keyframes);
+  EXPECT_EQ(2u, keyframes->Keyframes().size());
+
+  GetDocument().body()->RemoveChild(style_element);
+  GetDocument().View()->UpdateAllLifecyclePhases();
+
+  keyframes = GetStyleEngine().Resolver()->FindKeyframesRule(
+      t4, AtomicString("dummy-animation"));
+  ASSERT_TRUE(keyframes);
+  EXPECT_EQ(1u, keyframes->Keyframes().size());
+
+  GetStyleEngine().RemoveUserSheet(keyframes_id);
+  GetDocument().View()->UpdateAllLifecyclePhases();
+
+  // Injected @keyframes rules are no longer available once removed.
+  ASSERT_FALSE(GetStyleEngine().Resolver()->FindKeyframesRule(
+      t4, AtomicString("dummy-animation")));
 }
 
 TEST_F(StyleEngineTest, TextToSheetCache) {
diff --git a/third_party/WebKit/Source/core/css/cssom/CSSMathInvert.h b/third_party/WebKit/Source/core/css/cssom/CSSMathInvert.h
new file mode 100644
index 0000000..241c130f
--- /dev/null
+++ b/third_party/WebKit/Source/core/css/cssom/CSSMathInvert.h
@@ -0,0 +1,48 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CSSMathInvert_h
+#define CSSMathInvert_h
+
+#include "core/css/cssom/CSSMathValue.h"
+
+namespace blink {
+
+// Represents the inverse of a CSSNumericValue.
+// See CSSMathInvert.idl for more information about this class.
+class CORE_EXPORT CSSMathInvert : public CSSMathValue {
+  WTF_MAKE_NONCOPYABLE(CSSMathInvert);
+  DEFINE_WRAPPERTYPEINFO();
+
+ public:
+  // The constructor defined in the IDL.
+  static CSSMathInvert* Create(const CSSNumberish& arg) {
+    return new CSSMathInvert(CSSNumericValue::FromNumberish(arg));
+  }
+
+  String getOperator() const final { return "invert"; }
+
+  void value(CSSNumberish& value) { value.SetCSSNumericValue(value_); }
+  void setValue(const CSSNumberish& value) {
+    value_ = CSSNumericValue::FromNumberish(value);
+  }
+
+  // From CSSStyleValue.
+  StyleValueType GetType() const final { return CSSStyleValue::kInvertType; }
+
+  void Trace(Visitor* visitor) override {
+    visitor->Trace(value_);
+    CSSMathValue::Trace(visitor);
+  }
+
+ private:
+  explicit CSSMathInvert(CSSNumericValue* value)
+      : CSSMathValue(), value_(value) {}
+
+  Member<CSSNumericValue> value_;
+};
+
+}  // namespace blink
+
+#endif  // CSSMathInvert_h
diff --git a/third_party/WebKit/Source/core/css/cssom/CSSMathInvert.idl b/third_party/WebKit/Source/core/css/cssom/CSSMathInvert.idl
new file mode 100644
index 0000000..032e80a
--- /dev/null
+++ b/third_party/WebKit/Source/core/css/cssom/CSSMathInvert.idl
@@ -0,0 +1,13 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Represents the inverse a CSSNumericValue.
+// https://drafts.css-houdini.org/css-typed-om-1/#cssmathinvert
+[
+  Constructor(CSSNumberish arg),
+  Exposed=(Window,PaintWorklet),
+  RuntimeEnabled=CSSTypedOM
+] interface CSSMathInvert : CSSMathValue {
+  attribute CSSNumberish value;
+};
diff --git a/third_party/WebKit/Source/core/css/cssom/CSSMathNegate.h b/third_party/WebKit/Source/core/css/cssom/CSSMathNegate.h
new file mode 100644
index 0000000..e378051
--- /dev/null
+++ b/third_party/WebKit/Source/core/css/cssom/CSSMathNegate.h
@@ -0,0 +1,48 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CSSMathNegate_h
+#define CSSMathNegate_h
+
+#include "core/css/cssom/CSSMathValue.h"
+
+namespace blink {
+
+// Represents the negation of a CSSNumericValue.
+// See CSSMathNegate.idl for more information about this class.
+class CORE_EXPORT CSSMathNegate : public CSSMathValue {
+  WTF_MAKE_NONCOPYABLE(CSSMathNegate);
+  DEFINE_WRAPPERTYPEINFO();
+
+ public:
+  // The constructor defined in the IDL.
+  static CSSMathNegate* Create(const CSSNumberish& arg) {
+    return new CSSMathNegate(CSSNumericValue::FromNumberish(arg));
+  }
+
+  String getOperator() const final { return "negate"; }
+
+  void value(CSSNumberish& value) { value.SetCSSNumericValue(value_); }
+  void setValue(const CSSNumberish& value) {
+    value_ = CSSNumericValue::FromNumberish(value);
+  }
+
+  // From CSSStyleValue.
+  StyleValueType GetType() const final { return CSSStyleValue::kNegateType; }
+
+  void Trace(Visitor* visitor) override {
+    visitor->Trace(value_);
+    CSSMathValue::Trace(visitor);
+  }
+
+ private:
+  explicit CSSMathNegate(CSSNumericValue* value)
+      : CSSMathValue(), value_(value) {}
+
+  Member<CSSNumericValue> value_;
+};
+
+}  // namespace blink
+
+#endif  // CSSMathNegate_h
diff --git a/third_party/WebKit/Source/core/css/cssom/CSSMathNegate.idl b/third_party/WebKit/Source/core/css/cssom/CSSMathNegate.idl
new file mode 100644
index 0000000..1481462
--- /dev/null
+++ b/third_party/WebKit/Source/core/css/cssom/CSSMathNegate.idl
@@ -0,0 +1,13 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Represents the negation of a CSSNumericValue.
+// https://drafts.css-houdini.org/css-typed-om-1/#cssmathnegate
+[
+  Constructor(CSSNumberish arg),
+  Exposed=(Window,PaintWorklet),
+  RuntimeEnabled=CSSTypedOM
+] interface CSSMathNegate : CSSMathValue {
+  attribute CSSNumberish value;
+};
diff --git a/third_party/WebKit/Source/core/css/cssom/CSSNumericValue.cpp b/third_party/WebKit/Source/core/css/cssom/CSSNumericValue.cpp
index 376d29e..fb23367 100644
--- a/third_party/WebKit/Source/core/css/cssom/CSSNumericValue.cpp
+++ b/third_party/WebKit/Source/core/css/cssom/CSSNumericValue.cpp
@@ -45,6 +45,15 @@
   return CSSUnitValue::FromCSSValue(value);
 }
 
+/* static */
+CSSNumericValue* CSSNumericValue::FromNumberish(const CSSNumberish& value) {
+  if (value.IsDouble()) {
+    return CSSUnitValue::Create(value.GetAsDouble(),
+                                CSSPrimitiveValue::UnitType::kNumber);
+  }
+  return value.GetAsCSSNumericValue();
+}
+
 CSSNumericValue* CSSNumericValue::to(const String& unit_string,
                                      ExceptionState& exception_state) {
   CSSPrimitiveValue::UnitType unit = UnitFromName(unit_string);
diff --git a/third_party/WebKit/Source/core/css/cssom/CSSNumericValue.h b/third_party/WebKit/Source/core/css/cssom/CSSNumericValue.h
index 6e779df..bbaf2d6 100644
--- a/third_party/WebKit/Source/core/css/cssom/CSSNumericValue.h
+++ b/third_party/WebKit/Source/core/css/cssom/CSSNumericValue.h
@@ -27,6 +27,8 @@
   // Blink-internal ways of creating CSSNumericValues.
   static CSSNumericValue* parse(const String& css_text, ExceptionState&);
   static CSSNumericValue* FromCSSValue(const CSSPrimitiveValue&);
+  // https://drafts.css-houdini.org/css-typed-om-1/#rectify-a-numberish-value
+  static CSSNumericValue* FromNumberish(const CSSNumberish& value);
 
   // Methods defined in the IDL.
   virtual CSSNumericValue* add(const CSSNumericValue*, ExceptionState&) {
diff --git a/third_party/WebKit/Source/core/css/cssom/CSSStyleValue.cpp b/third_party/WebKit/Source/core/css/cssom/CSSStyleValue.cpp
index ee2657c..c21de49 100644
--- a/third_party/WebKit/Source/core/css/cssom/CSSStyleValue.cpp
+++ b/third_party/WebKit/Source/core/css/cssom/CSSStyleValue.cpp
@@ -36,16 +36,17 @@
 
   const CSSValue* css_value =
       CSSParser::ParseSingleValue(property_id, value, StrictCSSParserContext());
-  if (!css_value)
+  if (!css_value) {
+    exception_state.ThrowDOMException(
+        kSyntaxError, "The value provided ('" + value +
+                          "') could not be parsed as a '" + property_name +
+                          "'.");
     return ScriptValue::CreateNull(script_state);
+  }
 
   CSSStyleValueVector style_value_vector =
       StyleValueFactory::CssValueToStyleValueVector(property_id, *css_value);
-  if (style_value_vector.size() != 1) {
-    // TODO(meade): Support returning a CSSStyleValueOrCSSStyleValueSequence
-    // from this function.
-    return ScriptValue::CreateNull(script_state);
-  }
+  DCHECK(!style_value_vector.IsEmpty());
 
   v8::Local<v8::Value> wrapped_value =
       ToV8(style_value_vector[0], script_state->GetContext()->Global(),
diff --git a/third_party/WebKit/Source/core/css/cssom/CSSStyleValue.h b/third_party/WebKit/Source/core/css/cssom/CSSStyleValue.h
index fe3bd7f2..422dd9fa 100644
--- a/third_party/WebKit/Source/core/css/cssom/CSSStyleValue.h
+++ b/third_party/WebKit/Source/core/css/cssom/CSSStyleValue.h
@@ -29,10 +29,12 @@
     kAngleType,
     kFlexType,
     kFrequencyType,
+    kInvertType,
     kKeywordType,
     kLengthType,
     kMaxType,
     kMinType,
+    kNegateType,
     kNumberType,
     kPercentType,
     kPositionType,
diff --git a/third_party/WebKit/Source/core/css/html.css b/third_party/WebKit/Source/core/css/html.css
index 0542ecb..ef11631 100644
--- a/third_party/WebKit/Source/core/css/html.css
+++ b/third_party/WebKit/Source/core/css/html.css
@@ -521,7 +521,7 @@
     -webkit-text-security: disc !important;
 }
 
-input[type="password" i]::-webkit-input-suggested {
+input[type="password" i]::-internal-input-suggested {
     -webkit-text-security: disc !important;
 }
 
diff --git a/third_party/WebKit/Source/core/css/parser/CSS.proto b/third_party/WebKit/Source/core/css/parser/CSS.proto
index 08b5feb..b42a906 100644
--- a/third_party/WebKit/Source/core/css/parser/CSS.proto
+++ b/third_party/WebKit/Source/core/css/parser/CSS.proto
@@ -554,13 +554,13 @@
 // end tokens
 
 // rules
-// TODO(metzman): Add rules for @apply, @keyframes (including
-// -webkit-keyframes), @viewport, @supports.
+// TODO(metzman): Add rules for @keyframes (including
+// -webkit-keyframes), and @supports.
 message StyleSheet {
   optional CharsetDeclaration charset_declaration = 1;
   repeated Import imports = 2;
   repeated Namespace namespaces = 3;
-  repeated RulesetOrMediaOrPageOrFontFace ruleset_media_page_font_faces = 4;
+  repeated NestedAtRule nested_at_rules = 4;
 }
 
 // Not in grammar.
@@ -574,12 +574,55 @@
 }
 
 // Not in grammar.
-message RulesetOrMediaOrPageOrFontFace {
+message NestedAtRule {
   oneof rhs {
     Ruleset ruleset = 1;
     Media media = 2;
     Page page = 3;
     FontFace font_face = 4;
+    Viewport viewport = 5;
+  }
+}
+
+message Viewport {
+  repeated ViewportPropertyAndValue props_and_vals = 1;
+}
+
+message ViewportPropertyAndValue {
+  required ViewportProperty property = 1;
+  required ViewportValue value = 2;
+}
+
+message ViewportProperty {
+  enum PropertyId {
+    MIN_WIDTH = 1;
+    MAX_WIDTH = 2;
+    WIDTH = 3;
+    MIN_HEIGHT = 4;
+    MAX_HEIGHT = 5;
+    HEIGHT = 6;
+    ZOOM = 7;
+    MIN_ZOOM = 8;
+    USER_ZOOM = 9;
+    MAX_ZOOM = 10;
+    ORIENTATION = 11;
+  }
+  required PropertyId id = 1;
+}
+
+message ViewportValue {
+  enum ValueId {
+    LANDSCAPE = 1;
+    PORTRAIT = 2;
+    AUTO = 3;
+    ZOOM = 4;
+    FIXED = 5;
+    NONE = 6;
+  }
+  required ValueId value_id = 1;
+  oneof rhs {
+    Length length = 2;
+    Num num = 3;
   }
 }
 
@@ -677,8 +720,8 @@
 // TODO(metzman): implement <general-enclosed>
 
 message MfPlain {
-  required MfName mf_name = 1;
-  required MfValue mf_value = 2;
+  required MfName property = 1;
+  required MfValue value = 2;
 }
 
 message MfBool {
@@ -733,7 +776,7 @@
     SHAPE = 44;
     INVALID_NAME = 45;
   }
-  required ValueId value_id = 1;
+  required ValueId id = 1;
 }
 
 message MfValue {
diff --git a/third_party/WebKit/Source/core/css/parser/CSSParserImpl.cpp b/third_party/WebKit/Source/core/css/parser/CSSParserImpl.cpp
index 99c5030..260f01a 100644
--- a/third_party/WebKit/Source/core/css/parser/CSSParserImpl.cpp
+++ b/third_party/WebKit/Source/core/css/parser/CSSParserImpl.cpp
@@ -19,7 +19,6 @@
 #include "core/css/parser/CSSLazyParsingState.h"
 #include "core/css/parser/CSSLazyPropertyParserImpl.h"
 #include "core/css/parser/CSSParserObserver.h"
-#include "core/css/parser/CSSParserObserverWrapper.h"
 #include "core/css/parser/CSSParserScopedTokenBuffer.h"
 #include "core/css/parser/CSSParserSelector.h"
 #include "core/css/parser/CSSParserTokenStream.h"
@@ -63,9 +62,7 @@
 
 CSSParserImpl::CSSParserImpl(const CSSParserContext* context,
                              StyleSheetContents* style_sheet)
-    : context_(context),
-      style_sheet_(style_sheet),
-      observer_wrapper_(nullptr) {}
+    : context_(context), style_sheet_(style_sheet), observer_(nullptr) {}
 
 MutableStylePropertySet::SetResult CSSParserImpl::ParseValue(
     MutableStylePropertySet* declaration,
@@ -344,7 +341,7 @@
     CSSParserTokenRange range) {
   DCHECK(parsed_properties_.IsEmpty());
   DCHECK(RuntimeEnabledFeatures::CSSApplyAtRulesEnabled());
-  DCHECK(!observer_wrapper_);
+  DCHECK(!observer_);
 
   while (!range.AtEnd()) {
     switch (range.Peek().GetType()) {
@@ -401,8 +398,7 @@
     const CSSParserContext* context,
     CSSParserObserver& observer) {
   CSSParserImpl parser(context);
-  CSSParserObserverWrapper wrapper(observer);
-  parser.observer_wrapper_ = &wrapper;
+  parser.observer_ = &observer;
   CSSTokenizer tokenizer(declaration);
   observer.StartRuleHeader(StyleRule::kStyle, 0);
   observer.EndRuleHeader(1);
@@ -415,8 +411,7 @@
                                                 StyleSheetContents* style_sheet,
                                                 CSSParserObserver& observer) {
   CSSParserImpl parser(context, style_sheet);
-  CSSParserObserverWrapper wrapper(observer);
-  parser.observer_wrapper_ = &wrapper;
+  parser.observer_ = &observer;
   CSSTokenizer tokenizer(string);
   CSSParserTokenStream stream(tokenizer);
   bool first_rule_valid = parser.ConsumeRuleList(
@@ -656,12 +651,11 @@
   if (uri.IsNull())
     return nullptr;  // Parse error, expected string or URI
 
-  if (observer_wrapper_) {
-    observer_wrapper_->Observer().StartRuleHeader(StyleRule::kImport,
-                                                  prelude_offset.start);
-    observer_wrapper_->Observer().EndRuleHeader(prelude_offset.end);
-    observer_wrapper_->Observer().StartRuleBody(prelude_offset.end);
-    observer_wrapper_->Observer().EndRuleBody(prelude_offset.end);
+  if (observer_) {
+    observer_->StartRuleHeader(StyleRule::kImport, prelude_offset.start);
+    observer_->EndRuleHeader(prelude_offset.end);
+    observer_->StartRuleBody(prelude_offset.end);
+    observer_->EndRuleBody(prelude_offset.end);
   }
 
   return StyleRuleImport::Create(uri,
@@ -688,11 +682,10 @@
     CSSParserTokenStream& block) {
   HeapVector<Member<StyleRuleBase>> rules;
 
-  if (observer_wrapper_) {
-    observer_wrapper_->Observer().StartRuleHeader(StyleRule::kMedia,
-                                                  prelude_offset.start);
-    observer_wrapper_->Observer().EndRuleHeader(prelude_offset.end);
-    observer_wrapper_->Observer().StartRuleBody(block.Offset());
+  if (observer_) {
+    observer_->StartRuleHeader(StyleRule::kMedia, prelude_offset.start);
+    observer_->EndRuleHeader(prelude_offset.end);
+    observer_->StartRuleBody(block.Offset());
   }
 
   if (style_sheet_)
@@ -705,8 +698,8 @@
   ConsumeRuleList(block, kRegularRuleList,
                   [&rules](StyleRuleBase* rule) { rules.push_back(rule); });
 
-  if (observer_wrapper_)
-    observer_wrapper_->Observer().EndRuleBody(block.Offset());
+  if (observer_)
+    observer_->EndRuleBody(block.Offset());
 
   return StyleRuleMedia::Create(media, rules);
 }
@@ -722,11 +715,10 @@
   if (supported == CSSSupportsParser::kInvalid)
     return nullptr;  // Parse error, invalid @supports condition
 
-  if (observer_wrapper_) {
-    observer_wrapper_->Observer().StartRuleHeader(StyleRule::kSupports,
-                                                  prelude_offset.start);
-    observer_wrapper_->Observer().EndRuleHeader(prelude_offset.end);
-    observer_wrapper_->Observer().StartRuleBody(block.Offset());
+  if (observer_) {
+    observer_->StartRuleHeader(StyleRule::kSupports, prelude_offset.start);
+    observer_->EndRuleHeader(prelude_offset.end);
+    observer_->StartRuleBody(block.Offset());
   }
 
   const auto prelude_serialized = prelude.Serialize().StripWhiteSpace();
@@ -736,8 +728,8 @@
   ConsumeRuleList(block, kRegularRuleList,
                   [&rules](StyleRuleBase* rule) { rules.push_back(rule); });
 
-  if (observer_wrapper_)
-    observer_wrapper_->Observer().EndRuleBody(block.Offset());
+  if (observer_)
+    observer_->EndRuleBody(block.Offset());
 
   return StyleRuleSupports::Create(prelude_serialized, supported, rules);
 }
@@ -755,12 +747,11 @@
   if (!prelude.AtEnd())
     return nullptr;  // Parser error; @viewport prelude should be empty
 
-  if (observer_wrapper_) {
-    observer_wrapper_->Observer().StartRuleHeader(StyleRule::kViewport,
-                                                  prelude_offset.start);
-    observer_wrapper_->Observer().EndRuleHeader(prelude_offset.end);
-    observer_wrapper_->Observer().StartRuleBody(prelude_offset.end);
-    observer_wrapper_->Observer().EndRuleBody(prelude_offset.end);
+  if (observer_) {
+    observer_->StartRuleHeader(StyleRule::kViewport, prelude_offset.start);
+    observer_->EndRuleHeader(prelude_offset.end);
+    observer_->StartRuleBody(prelude_offset.end);
+    observer_->EndRuleBody(prelude_offset.end);
   }
 
   if (style_sheet_)
@@ -780,12 +771,11 @@
   if (!prelude.AtEnd())
     return nullptr;  // Parse error; @font-face prelude should be empty
 
-  if (observer_wrapper_) {
-    observer_wrapper_->Observer().StartRuleHeader(StyleRule::kFontFace,
-                                                  prelude_offset.start);
-    observer_wrapper_->Observer().EndRuleHeader(prelude_offset.end);
-    observer_wrapper_->Observer().StartRuleBody(prelude_offset.end);
-    observer_wrapper_->Observer().EndRuleBody(prelude_offset.end);
+  if (observer_) {
+    observer_->StartRuleHeader(StyleRule::kFontFace, prelude_offset.start);
+    observer_->EndRuleHeader(prelude_offset.end);
+    observer_->StartRuleBody(prelude_offset.end);
+    observer_->EndRuleBody(prelude_offset.end);
   }
 
   if (style_sheet_)
@@ -818,11 +808,10 @@
     return nullptr;  // Parse error; expected ident token in @keyframes header
   }
 
-  if (observer_wrapper_) {
-    observer_wrapper_->Observer().StartRuleHeader(StyleRule::kKeyframes,
-                                                  prelude_offset.start);
-    observer_wrapper_->Observer().EndRuleHeader(prelude_offset.end);
-    observer_wrapper_->Observer().StartRuleBody(block.Offset());
+  if (observer_) {
+    observer_->StartRuleHeader(StyleRule::kKeyframes, prelude_offset.start);
+    observer_->EndRuleHeader(prelude_offset.end);
+    observer_->StartRuleBody(block.Offset());
   }
 
   prelude_buffer.Release();
@@ -835,8 +824,8 @@
   keyframe_rule->SetName(name);
   keyframe_rule->SetVendorPrefixed(webkit_prefixed);
 
-  if (observer_wrapper_)
-    observer_wrapper_->Observer().EndRuleBody(block.Offset());
+  if (observer_)
+    observer_->EndRuleBody(block.Offset());
 
   return keyframe_rule;
 }
@@ -850,10 +839,9 @@
   if (!selector_list.IsValid())
     return nullptr;  // Parse error, invalid @page selector
 
-  if (observer_wrapper_) {
-    observer_wrapper_->Observer().StartRuleHeader(StyleRule::kPage,
-                                                  prelude_offset.start);
-    observer_wrapper_->Observer().EndRuleHeader(prelude_offset.end);
+  if (observer_) {
+    observer_->StartRuleHeader(StyleRule::kPage, prelude_offset.start);
+    observer_->EndRuleHeader(prelude_offset.end);
   }
 
   prelude_buffer.Release();
@@ -884,10 +872,9 @@
   if (!key_list)
     return nullptr;
 
-  if (observer_wrapper_) {
-    observer_wrapper_->Observer().StartRuleHeader(StyleRule::kKeyframe,
-                                                  prelude_offset.start);
-    observer_wrapper_->Observer().EndRuleHeader(prelude_offset.end);
+  if (observer_) {
+    observer_->StartRuleHeader(StyleRule::kKeyframe, prelude_offset.start);
+    observer_->EndRuleHeader(prelude_offset.end);
   }
 
   prelude_buffer.Release();
@@ -899,14 +886,12 @@
 }
 
 StyleRule* CSSParserImpl::ConsumeStyleRule(CSSParserTokenStream& stream) {
-  if (observer_wrapper_) {
-    observer_wrapper_->Observer().StartRuleHeader(StyleRule::kStyle,
-                                                  stream.LookAheadOffset());
-  }
+  if (observer_)
+    observer_->StartRuleHeader(StyleRule::kStyle, stream.LookAheadOffset());
 
   // Parse the prelude of the style rule
   CSSSelectorList selector_list = CSSSelectorParser::ConsumeSelector(
-      stream, context_, style_sheet_, observer_wrapper_);
+      stream, context_, style_sheet_, observer_);
 
   if (!selector_list.IsValid()) {
     // Read the rest of the prelude if there was an error
@@ -916,9 +901,8 @@
       stream.UncheckedConsumeComponentValue();
   }
 
-  if (observer_wrapper_) {
-    observer_wrapper_->Observer().EndRuleHeader(stream.LookAheadOffset());
-  }
+  if (observer_)
+    observer_->EndRuleHeader(stream.LookAheadOffset());
 
   if (stream.AtEnd())
     return nullptr;  // Parse error, EOF instead of qualified rule block
@@ -930,7 +914,7 @@
     return nullptr;  // Parse error, invalid selector list
 
   // TODO(csharrison): How should we lazily parse css that needs the observer?
-  if (!observer_wrapper_ && lazy_state_ &&
+  if (!observer_ && lazy_state_ &&
       lazy_state_->ShouldLazilyParseProperties(selector_list)) {
     DCHECK(style_sheet_);
     return StyleRule::CreateLazy(
@@ -948,10 +932,10 @@
                                            StyleRule::RuleType rule_type) {
   DCHECK(parsed_properties_.IsEmpty());
 
-  bool use_observer = observer_wrapper_ && (rule_type == StyleRule::kStyle ||
-                                            rule_type == StyleRule::kKeyframe);
+  bool use_observer = observer_ && (rule_type == StyleRule::kStyle ||
+                                    rule_type == StyleRule::kKeyframe);
   if (use_observer) {
-    observer_wrapper_->Observer().StartRuleBody(stream.Offset());
+    observer_->StartRuleBody(stream.Offset());
   }
 
   while (true) {
@@ -963,8 +947,7 @@
         size_t start_offset = stream.Offset();
         if (!stream.ConsumeCommentOrNothing())
           break;
-        observer_wrapper_->Observer().ObserveComment(start_offset,
-                                                     stream.Offset());
+        observer_->ObserveComment(start_offset, stream.Offset());
       }
     }
 
@@ -1021,7 +1004,7 @@
   }
 
   if (use_observer)
-    observer_wrapper_->Observer().EndRuleBody(stream.LookAheadOffset());
+    observer_->EndRuleBody(stream.LookAheadOffset());
 }
 
 void CSSParserImpl::ConsumeDeclaration(CSSParserTokenRange range,
@@ -1072,11 +1055,10 @@
         unresolved_property, important, rule_type);
   }
 
-  if (observer_wrapper_ &&
+  if (observer_ &&
       (rule_type == StyleRule::kStyle || rule_type == StyleRule::kKeyframe)) {
-    observer_wrapper_->Observer().ObserveProperty(
-        decl_offset.start, decl_offset.end, important,
-        parsed_properties_.size() != properties_count);
+    observer_->ObserveProperty(decl_offset.start, decl_offset.end, important,
+                               parsed_properties_.size() != properties_count);
   }
 }
 
diff --git a/third_party/WebKit/Source/core/css/parser/CSSParserImpl.h b/third_party/WebKit/Source/core/css/parser/CSSParserImpl.h
index c42d368..1e47822 100644
--- a/third_party/WebKit/Source/core/css/parser/CSSParserImpl.h
+++ b/third_party/WebKit/Source/core/css/parser/CSSParserImpl.h
@@ -20,7 +20,6 @@
 class CSSLazyParsingState;
 class CSSParserContext;
 class CSSParserObserver;
-class CSSParserObserverWrapper;
 class CSSParserScopedTokenBuffer;
 class CSSParserTokenStream;
 class StyleRule;
@@ -197,7 +196,7 @@
   Member<StyleSheetContents> style_sheet_;
 
   // For the inspector
-  CSSParserObserverWrapper* observer_wrapper_;
+  CSSParserObserver* observer_;
 
   Member<CSSLazyParsingState> lazy_state_;
 };
diff --git a/third_party/WebKit/Source/core/css/parser/CSSParserObserverWrapper.cpp b/third_party/WebKit/Source/core/css/parser/CSSParserObserverWrapper.cpp
deleted file mode 100644
index 030fb811..0000000
--- a/third_party/WebKit/Source/core/css/parser/CSSParserObserverWrapper.cpp
+++ /dev/null
@@ -1,24 +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 "core/css/parser/CSSParserObserverWrapper.h"
-
-#include "core/css/parser/CSSParserTokenRange.h"
-
-namespace blink {
-
-unsigned CSSParserObserverWrapper::StartOffset(
-    const CSSParserTokenRange& range) {
-  const size_t index = range.begin() - first_parser_token_;
-  DCHECK_LT(index, token_offsets_.size());
-  return token_offsets_[range.begin() - first_parser_token_];
-}
-
-unsigned CSSParserObserverWrapper::EndOffset(const CSSParserTokenRange& range) {
-  size_t index = range.end() - first_parser_token_;
-  DCHECK_LT(index, token_offsets_.size());
-  return token_offsets_[index];
-}
-
-}  // namespace blink
diff --git a/third_party/WebKit/Source/core/css/parser/CSSParserObserverWrapper.h b/third_party/WebKit/Source/core/css/parser/CSSParserObserverWrapper.h
deleted file mode 100644
index 2dd6b24..0000000
--- a/third_party/WebKit/Source/core/css/parser/CSSParserObserverWrapper.h
+++ /dev/null
@@ -1,51 +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.
-
-#ifndef CSSParserObserverWrapper_h
-#define CSSParserObserverWrapper_h
-
-#include "core/css/parser/CSSParserObserver.h"
-#include "core/css/parser/CSSParserTokenStream.h"
-#include "platform/wtf/Allocator.h"
-
-namespace blink {
-
-class CSSParserToken;
-class CSSParserTokenRange;
-
-// TODO(shend): Remove this class once we can use stream parsing directly
-// with CSSParserObserver.
-class CSSParserObserverWrapper {
-  STACK_ALLOCATED();
-
- public:
-  explicit CSSParserObserverWrapper(CSSParserObserver& observer)
-      : observer_(observer) {}
-
-  unsigned StartOffset(const CSSParserTokenRange&);
-  unsigned EndOffset(const CSSParserTokenRange&);
-
-  CSSParserObserver& Observer() { return observer_; }
-
-  void AddToken(unsigned start_offset) {
-    token_offsets_.push_back(start_offset);
-  }
-
-  void StartConstruction() {
-    token_offsets_.clear();
-    first_parser_token_ = nullptr;
-  }
-  void FinalizeConstruction(const CSSParserToken* first_parser_token) {
-    first_parser_token_ = first_parser_token;
-  }
-
- private:
-  CSSParserObserver& observer_;
-  Vector<unsigned> token_offsets_;
-  const CSSParserToken* first_parser_token_;
-};
-
-}  // namespace blink
-
-#endif  // CSSParserObserverWrapper_h
diff --git a/third_party/WebKit/Source/core/css/parser/CSSParserTokenStream.cpp b/third_party/WebKit/Source/core/css/parser/CSSParserTokenStream.cpp
index 1ed67fa..9da9eda 100644
--- a/third_party/WebKit/Source/core/css/parser/CSSParserTokenStream.cpp
+++ b/third_party/WebKit/Source/core/css/parser/CSSParserTokenStream.cpp
@@ -3,7 +3,6 @@
 // found in the LICENSE file.
 
 #include "core/css/parser/CSSParserTokenStream.h"
-#include "core/css/parser/CSSParserObserverWrapper.h"
 #include "core/css/parser/CSSParserScopedTokenBuffer.h"
 
 namespace blink {
@@ -63,25 +62,6 @@
   } while (!PeekInternal().IsEOF() && nesting_level);
 }
 
-void CSSParserTokenStream::UncheckedConsumeComponentValueWithOffsets(
-    CSSParserObserverWrapper& wrapper,
-    CSSParserScopedTokenBuffer& buffer) {
-  DCHECK(HasLookAhead());
-
-  // Have to use internal consume/peek in here because they can read past
-  // start/end of blocks
-  unsigned nesting_level = 0;
-  do {
-    wrapper.AddToken(LookAheadOffset());
-    const CSSParserToken& token = UncheckedConsumeInternal();
-    buffer.Append(token);
-    if (token.GetBlockType() == CSSParserToken::kBlockStart)
-      nesting_level++;
-    else if (token.GetBlockType() == CSSParserToken::kBlockEnd)
-      nesting_level--;
-  } while (!PeekInternal().IsEOF() && nesting_level);
-}
-
 void CSSParserTokenStream::UncheckedSkipToEndOfBlock() {
   DCHECK(HasLookAhead());
   // Have to use internal consume/peek in here because they can read past
diff --git a/third_party/WebKit/Source/core/css/parser/CSSParserTokenStream.h b/third_party/WebKit/Source/core/css/parser/CSSParserTokenStream.h
index 2d356e861..ac58d778 100644
--- a/third_party/WebKit/Source/core/css/parser/CSSParserTokenStream.h
+++ b/third_party/WebKit/Source/core/css/parser/CSSParserTokenStream.h
@@ -13,7 +13,6 @@
 namespace blink {
 
 class CSSParserScopedTokenBuffer;
-class CSSParserObserverWrapper;
 
 // A streaming interface to CSSTokenizer that tokenizes on demand.
 // Abstractly, the stream ends at either EOF or the beginning/end of a block.
@@ -122,8 +121,7 @@
   CSSParserToken ConsumeIncludingWhitespace();
   void UncheckedConsumeComponentValue();
   void UncheckedConsumeComponentValue(CSSParserScopedTokenBuffer&);
-  void UncheckedConsumeComponentValueWithOffsets(CSSParserObserverWrapper&,
-                                                 CSSParserScopedTokenBuffer&);
+
   // Either consumes a comment token and returns true, or peeks at the next
   // token and return false.
   bool ConsumeCommentOrNothing();
diff --git a/third_party/WebKit/Source/core/css/parser/CSSProtoConverter.cpp b/third_party/WebKit/Source/core/css/parser/CSSProtoConverter.cpp
index c726633..d3bfd3e 100644
--- a/third_party/WebKit/Source/core/css/parser/CSSProtoConverter.cpp
+++ b/third_party/WebKit/Source/core/css/parser/CSSProtoConverter.cpp
@@ -11,6 +11,18 @@
 
 namespace css_proto_converter {
 
+const std::string Converter::kViewportPropertyLookupTable[] = {
+    "",  // This is just to fill the zeroth spot. It should not be used.
+    "min-width",  "max-width", "width",       "min-height",
+    "max-height", "height",    "zoom",        "min-zoom",
+    "user-zoom",  "max-zoom",  "orientation",
+};
+
+const std::string Converter::kViewportValueLookupTable[] = {
+    "",  // This is just to fill the zeroth spot. It should not be used.
+    "landscape", "portrait", "auto", "zoom", "fixed", "none",
+};
+
 const std::string Converter::kPseudoLookupTable[] = {
     "",  // This is just to fill the zeroth spot. It should not be used.
     "-internal-list-box",
@@ -1606,9 +1618,24 @@
     Visit(import);
   for (auto& _namespace : style_sheet.namespaces())
     Visit(_namespace);
-  for (auto& ruleset_media_page_font_face :
-       style_sheet.ruleset_media_page_font_faces())
-    Visit(ruleset_media_page_font_face);
+  for (auto& nested_at_rule : style_sheet.nested_at_rules())
+    Visit(nested_at_rule);
+}
+
+void Converter::Visit(const ViewportValue& viewport_value) {
+  if (viewport_value.has_length())
+    Visit(viewport_value.length());
+  else if (viewport_value.has_num())
+    Visit(viewport_value.num());
+  else  // Default value.
+    AppendTableValue(viewport_value.value_id(), kViewportValueLookupTable);
+}
+
+void Converter::Visit(const Viewport& viewport) {
+  string_ += " @viewport {";
+  for (auto& prop_and_val : viewport.props_and_vals())
+    AppendPropertyAndValue(prop_and_val, kViewportPropertyLookupTable);
+  string_ += " } ";
 }
 
 void Converter::Visit(const CharsetDeclaration& charset_declaration) {
@@ -1618,12 +1645,14 @@
   string_ += "\"; ";
 }
 
-void Converter::Visit(
-    const RulesetOrMediaOrPageOrFontFace& ruleset_media_page_font_face) {
-  if (ruleset_media_page_font_face.has_ruleset())
-    Visit(ruleset_media_page_font_face.ruleset());
-  if (ruleset_media_page_font_face.has_media())
-    Visit(ruleset_media_page_font_face.media());
+void Converter::Visit(const NestedAtRule& nested_at_rule) {
+  if (nested_at_rule.has_ruleset())
+    Visit(nested_at_rule.ruleset());
+  else if (nested_at_rule.has_media())
+    Visit(nested_at_rule.media());
+  else if (nested_at_rule.has_viewport())
+    Visit(nested_at_rule.viewport());
+  // Else apppend nothing.
   // TODO(metzman): Support pages and font-faces.
 }
 
@@ -1734,23 +1763,17 @@
   if (media_feature.has_mf_bool()) {
     Visit(media_feature.mf_bool());
   } else if (media_feature.has_mf_plain()) {
-    Visit(media_feature.mf_plain());
+    AppendPropertyAndValue(media_feature.mf_plain(), kMfNameLookupTable, false);
   }
   string_ += ")";
 }
 
-void Converter::Visit(const MfPlain& mf_plain) {
-  Visit(mf_plain.mf_name());
-  string_ += " : ";
-  Visit(mf_plain.mf_value());
-}
-
 void Converter::Visit(const MfBool& mf_bool) {
   Visit(mf_bool.mf_name());
 }
 
 void Converter::Visit(const MfName& mf_name) {
-  AppendTableValue(mf_name.value_id(), kMfNameLookupTable);
+  AppendTableValue(mf_name.id(), kMfNameLookupTable);
 }
 
 void Converter::Visit(const MfValue& mf_value) {
@@ -2001,4 +2024,16 @@
   CHECK(id > 0 && static_cast<size_t>(id) < TableSize);
   string_ += lookup_table[id];
 }
+
+template <class T, size_t TableSize>
+void Converter::AppendPropertyAndValue(
+    T property_and_value,
+    const std::string (&lookup_table)[TableSize],
+    bool append_semicolon) {
+  AppendTableValue(property_and_value.property().id(), lookup_table);
+  string_ += " : ";
+  Visit(property_and_value.value());
+  if (append_semicolon)
+    string_ += "; ";
+}
 };  // namespace css_proto_converter
diff --git a/third_party/WebKit/Source/core/css/parser/CSSProtoConverter.h b/third_party/WebKit/Source/core/css/parser/CSSProtoConverter.h
index e41c822a..36f4b5dd 100644
--- a/third_party/WebKit/Source/core/css/parser/CSSProtoConverter.h
+++ b/third_party/WebKit/Source/core/css/parser/CSSProtoConverter.h
@@ -25,6 +25,8 @@
   static const std::string kEncodingLookupTable[];
   static const std::string kValueLookupTable[];
   static const std::string kPropertyLookupTable[];
+  static const std::string kViewportPropertyLookupTable[];
+  static const std::string kViewportValueLookupTable[];
 
   void Visit(const Unicode&);
   void Visit(const Escape&);
@@ -47,7 +49,7 @@
   void Visit(const FunctionToken&);
   void Visit(const StyleSheet&);
   void Visit(const CharsetDeclaration&);
-  void Visit(const RulesetOrMediaOrPageOrFontFace&);
+  void Visit(const NestedAtRule&);
   void Visit(const Import&);
   void Visit(const Namespace&);
   void Visit(const NamespacePrefix&);
@@ -78,7 +80,6 @@
   void Visit(const MediaOr&);
   void Visit(const MediaInParens&);
   void Visit(const MediaFeature&);
-  void Visit(const MfPlain&);
   void Visit(const MfBool&);
   void Visit(const MfName&);
   void Visit(const MfValue&);
@@ -86,7 +87,13 @@
   void Visit(const MediaConditionWithoutOr&);
   void Visit(const Selector&, bool is_first);
   void Visit(const PseudoPage&);
+  void Visit(const ViewportValue&);
+  void Visit(const Viewport&);
   void Reset();
+  template <class T, size_t TableSize>
+  void AppendPropertyAndValue(T property_and_value,
+                              const std::string (&lookup_table)[TableSize],
+                              bool append_semicolon = true);
   template <size_t TableSize>
   void AppendTableValue(int id, const std::string (&lookup_table)[TableSize]);
 };
diff --git a/third_party/WebKit/Source/core/css/parser/CSSSelectorParser.cpp b/third_party/WebKit/Source/core/css/parser/CSSSelectorParser.cpp
index ff47068..39129b0 100644
--- a/third_party/WebKit/Source/core/css/parser/CSSSelectorParser.cpp
+++ b/third_party/WebKit/Source/core/css/parser/CSSSelectorParser.cpp
@@ -8,7 +8,7 @@
 #include "core/css/CSSSelectorList.h"
 #include "core/css/StyleSheetContents.h"
 #include "core/css/parser/CSSParserContext.h"
-#include "core/css/parser/CSSParserObserverWrapper.h"
+#include "core/css/parser/CSSParserObserver.h"
 #include "core/css/parser/CSSParserScopedTokenBuffer.h"
 #include "core/css/parser/CSSParserTokenStream.h"
 #include "core/frame/Deprecation.h"
@@ -38,10 +38,10 @@
     CSSParserTokenStream& stream,
     const CSSParserContext* context,
     StyleSheetContents* style_sheet,
-    CSSParserObserverWrapper* wrapper) {
+    CSSParserObserver* observer) {
   CSSSelectorParser parser(context, style_sheet);
   stream.ConsumeWhitespace();
-  CSSSelectorList result = parser.ConsumeComplexSelectorList(stream, wrapper);
+  CSSSelectorList result = parser.ConsumeComplexSelectorList(stream, observer);
   parser.RecordUsageAndDeprecations(result);
   return result;
 }
@@ -73,7 +73,7 @@
 
 CSSSelectorList CSSSelectorParser::ConsumeComplexSelectorList(
     CSSParserTokenStream& stream,
-    CSSParserObserverWrapper* wrapper) {
+    CSSParserObserver* observer) {
   Vector<std::unique_ptr<CSSParserSelector>> selector_list;
 
   while (true) {
@@ -96,10 +96,8 @@
     if (!selector || failed_parsing_ || !complex_selector.AtEnd())
       return CSSSelectorList();
 
-    if (wrapper) {
-      wrapper->Observer().ObserveSelector(selector_offset_start,
-                                          selector_offset_end);
-    }
+    if (observer)
+      observer->ObserveSelector(selector_offset_start, selector_offset_end);
 
     selector_list.push_back(std::move(selector));
     if (stream.Peek().GetType() == kLeftBraceToken)
diff --git a/third_party/WebKit/Source/core/css/parser/CSSSelectorParser.h b/third_party/WebKit/Source/core/css/parser/CSSSelectorParser.h
index e63cd4e..28bc773 100644
--- a/third_party/WebKit/Source/core/css/parser/CSSSelectorParser.h
+++ b/third_party/WebKit/Source/core/css/parser/CSSSelectorParser.h
@@ -14,7 +14,7 @@
 
 class CSSParserContext;
 class CSSParserTokenStream;
-class CSSParserObserverWrapper;
+class CSSParserObserver;
 class CSSSelectorList;
 class StyleSheetContents;
 
@@ -30,7 +30,7 @@
   static CSSSelectorList ConsumeSelector(CSSParserTokenStream&,
                                          const CSSParserContext*,
                                          StyleSheetContents*,
-                                         CSSParserObserverWrapper*);
+                                         CSSParserObserver*);
 
   static bool ConsumeANPlusB(CSSParserTokenRange&, std::pair<int, int>&);
 
@@ -41,7 +41,7 @@
 
   CSSSelectorList ConsumeComplexSelectorList(CSSParserTokenRange&);
   CSSSelectorList ConsumeComplexSelectorList(CSSParserTokenStream&,
-                                             CSSParserObserverWrapper*);
+                                             CSSParserObserver*);
   CSSSelectorList ConsumeCompoundSelectorList(CSSParserTokenRange&);
 
   std::unique_ptr<CSSParserSelector> ConsumeComplexSelector(
diff --git a/third_party/WebKit/Source/core/css/parser/CSSTokenizer.cpp b/third_party/WebKit/Source/core/css/parser/CSSTokenizer.cpp
index 2b63b68e..42cfeb7 100644
--- a/third_party/WebKit/Source/core/css/parser/CSSTokenizer.cpp
+++ b/third_party/WebKit/Source/core/css/parser/CSSTokenizer.cpp
@@ -9,7 +9,6 @@
 }
 
 #include "core/css/parser/CSSParserIdioms.h"
-#include "core/css/parser/CSSParserObserverWrapper.h"
 #include "core/css/parser/CSSParserTokenRange.h"
 #include "core/html/parser/HTMLParserIdioms.h"
 #include "platform/wtf/text/CharacterNames.h"
diff --git a/third_party/WebKit/Source/core/css/resolver/StyleResolver.cpp b/third_party/WebKit/Source/core/css/resolver/StyleResolver.cpp
index 2ea313a..9efdddc 100644
--- a/third_party/WebKit/Source/core/css/resolver/StyleResolver.cpp
+++ b/third_party/WebKit/Source/core/css/resolver/StyleResolver.cpp
@@ -1241,6 +1241,11 @@
       return keyframes_rule;
   }
 
+  if (StyleRuleKeyframes* keyframes_rule =
+          GetDocument().GetStyleEngine().KeyframeStylesForAnimation(
+              animation_name))
+    return keyframes_rule;
+
   for (auto& resolver : resolvers)
     resolver->SetHasUnresolvedKeyframesRule();
   return nullptr;
diff --git a/third_party/WebKit/Source/core/dom/BUILD.gn b/third_party/WebKit/Source/core/dom/BUILD.gn
index 93f080f..b636bb42 100644
--- a/third_party/WebKit/Source/core/dom/BUILD.gn
+++ b/third_party/WebKit/Source/core/dom/BUILD.gn
@@ -344,6 +344,8 @@
     "events/TreeScopeEventContext.h",
     "events/WindowEventContext.cpp",
     "events/WindowEventContext.h",
+    "ng/flat_tree_traversal_ng.cc",
+    "ng/flat_tree_traversal_ng.h",
     "trustedtypes/TrustedHTML.cpp",
     "trustedtypes/TrustedHTML.h",
     "trustedtypes/TrustedScriptURL.cpp",
diff --git a/third_party/WebKit/Source/core/dom/ClassicPendingScript.cpp b/third_party/WebKit/Source/core/dom/ClassicPendingScript.cpp
index bae029c..00ca51c 100644
--- a/third_party/WebKit/Source/core/dom/ClassicPendingScript.cpp
+++ b/third_party/WebKit/Source/core/dom/ClassicPendingScript.cpp
@@ -19,9 +19,58 @@
 
 namespace blink {
 
-ClassicPendingScript* ClassicPendingScript::Fetch(ScriptElementBase* element,
-                                                  FetchParameters& params,
-                                                  Document& element_document) {
+ClassicPendingScript* ClassicPendingScript::Fetch(
+    const KURL& url,
+    Document& element_document,
+    const ScriptFetchOptions& options,
+    const WTF::TextEncoding& encoding,
+    ScriptElementBase* element,
+    FetchParameters::DeferOption defer) {
+  // Step 1. Let request be the result of creating a potential-CORS request
+  // given url, ... [spec text]
+  ResourceRequest resource_request(url);
+
+  // Step 1. ... "script", ... [spec text]
+  ResourceLoaderOptions resource_loader_options;
+  resource_loader_options.initiator_info.name = element->InitiatorName();
+  FetchParameters params(resource_request, resource_loader_options);
+
+  // Step 1. ... and CORS setting. [spec text]
+  //
+  // Instead of using CrossOriginAttributeValue that corresponds to |CORS
+  // setting|, we use ScriptFetchOptions::CredentialsMode().
+  // We shouldn't call SetCrossOriginAccessControl() if CredentialsMode() is
+  // kFetchCredentialsModeOmit, because in that case the request should be
+  // no-cors, while SetCrossOriginAccessControl(kFetchCredentialsModeOmit)
+  // would result in a cors request.
+  if (options.CredentialsMode() !=
+      network::mojom::FetchCredentialsMode::kOmit) {
+    params.SetCrossOriginAccessControl(element_document.GetSecurityOrigin(),
+                                       options.CredentialsMode());
+  }
+
+  // Step 3. Set up the classic script request given request and options. [spec
+  // text]
+  //
+  // https://html.spec.whatwg.org/multipage/webappapis.html#set-up-the-classic-script-request
+  // Set request's cryptographic nonce metadata to options's cryptographic
+  // nonce, [spec text]
+  params.SetContentSecurityPolicyNonce(options.Nonce());
+
+  // its integrity metadata to options's integrity metadata, [spec text]
+  params.SetIntegrityMetadata(options.GetIntegrityMetadata());
+  params.MutableResourceRequest().SetFetchIntegrity(
+      options.GetIntegrityAttributeValue());
+
+  // and its parser metadata to options's parser metadata. [spec text]
+  params.SetParserDisposition(options.ParserState());
+
+  params.SetCharset(encoding);
+
+  // This DeferOption logic is only for classic scripts, as we always set
+  // |kLazyLoad| for module scripts in ModuleScriptLoader.
+  params.SetDefer(defer);
+
   // [Intervention]
   // For users on slow connections, we want to avoid blocking the parser in
   // the main frame on script loads inserted via document.write, since it can
@@ -29,8 +78,8 @@
   auto* client_for_intervention =
       MaybeDisallowFetchForDocWrittenScript(params, element_document);
 
-  ClassicPendingScript* pending_script =
-      new ClassicPendingScript(element, TextPosition(), true /* is_external */);
+  ClassicPendingScript* pending_script = new ClassicPendingScript(
+      element, TextPosition(), options, true /* is_external */);
   ScriptResource* resource =
       ScriptResource::Fetch(params, element_document.Fetcher());
   if (!resource)
@@ -46,8 +95,8 @@
     ScriptElementBase* element,
     ScriptResource* resource) {
   DCHECK(resource);
-  ClassicPendingScript* pending_script =
-      new ClassicPendingScript(element, TextPosition(), true /* is_external */);
+  ClassicPendingScript* pending_script = new ClassicPendingScript(
+      element, TextPosition(), ScriptFetchOptions(), true /* is_external */);
   pending_script->SetResource(resource);
   pending_script->CheckState();
   return pending_script;
@@ -55,9 +104,10 @@
 
 ClassicPendingScript* ClassicPendingScript::CreateInline(
     ScriptElementBase* element,
-    const TextPosition& starting_position) {
+    const TextPosition& starting_position,
+    const ScriptFetchOptions& options) {
   ClassicPendingScript* pending_script = new ClassicPendingScript(
-      element, starting_position, false /* is_external */);
+      element, starting_position, options, false /* is_external */);
   pending_script->CheckState();
   return pending_script;
 }
@@ -65,8 +115,10 @@
 ClassicPendingScript::ClassicPendingScript(
     ScriptElementBase* element,
     const TextPosition& starting_position,
+    const ScriptFetchOptions& options,
     bool is_external)
     : PendingScript(element, starting_position),
+      options_(options),
       is_external_(is_external),
       ready_state_(is_external ? kWaitingForResource : kReady),
       integrity_failure_(false),
@@ -208,19 +260,10 @@
   DCHECK(IsReady());
 
   error_occurred = ErrorOccurred();
-  const ScriptLoader* loader = GetElement()->Loader();
-  // Here, we use the nonce snapshot at "#prepare-a-script".
-  // Note that |loader| may be nullptr if ScriptStreamerTest.
-  const String& nonce = loader ? loader->Nonce() : String();
-  const ParserDisposition parser_state = (loader && loader->IsParserInserted())
-                                             ? kParserInserted
-                                             : kNotParserInserted;
-  ScriptFetchOptions fetch_options(nonce, parser_state,
-                                   network::mojom::FetchCredentialsMode::kOmit);
   if (!is_external_) {
     ScriptSourceCode source_code(GetElement()->TextFromChildren(), document_url,
                                  StartingPosition());
-    return ClassicScript::Create(source_code, fetch_options);
+    return ClassicScript::Create(source_code, options_);
   }
 
   DCHECK(GetResource()->IsLoaded());
@@ -228,7 +271,7 @@
                         !streamer_->StreamingSuppressed();
   ScriptSourceCode source_code(streamer_ready ? streamer_ : nullptr,
                                GetResource());
-  return ClassicScript::Create(source_code, fetch_options);
+  return ClassicScript::Create(source_code, options_);
 }
 
 void ClassicPendingScript::SetStreamer(ScriptStreamer* streamer) {
diff --git a/third_party/WebKit/Source/core/dom/ClassicPendingScript.h b/third_party/WebKit/Source/core/dom/ClassicPendingScript.h
index c9048a09..697c917 100644
--- a/third_party/WebKit/Source/core/dom/ClassicPendingScript.h
+++ b/third_party/WebKit/Source/core/dom/ClassicPendingScript.h
@@ -10,6 +10,7 @@
 #include "core/dom/PendingScript.h"
 #include "core/loader/resource/ScriptResource.h"
 #include "platform/MemoryCoordinator.h"
+#include "platform/loader/fetch/FetchParameters.h"
 #include "platform/loader/fetch/ResourceOwner.h"
 
 namespace blink {
@@ -30,11 +31,16 @@
   USING_PRE_FINALIZER(ClassicPendingScript, Prefinalize);
 
  public:
+  // https://html.spec.whatwg.org/multipage/webappapis.html#fetch-a-classic-script
+  //
   // For a script from an external file, calls ScriptResource::Fetch() and
   // creates ClassicPendingScript. Returns nullptr if Fetch() returns nullptr.
-  static ClassicPendingScript* Fetch(ScriptElementBase*,
-                                     FetchParameters&,
-                                     Document&);
+  static ClassicPendingScript* Fetch(const KURL&,
+                                     Document&,
+                                     const ScriptFetchOptions&,
+                                     const WTF::TextEncoding&,
+                                     ScriptElementBase*,
+                                     FetchParameters::DeferOption);
 
   // For a script from an external file, with a supplied ScriptResource.
   static ClassicPendingScript* CreateExternalForTest(ScriptElementBase*,
@@ -42,7 +48,8 @@
 
   // For an inline script.
   static ClassicPendingScript* CreateInline(ScriptElementBase*,
-                                            const TextPosition&);
+                                            const TextPosition&,
+                                            const ScriptFetchOptions&);
 
   ~ClassicPendingScript() override;
 
@@ -83,6 +90,7 @@
 
   ClassicPendingScript(ScriptElementBase*,
                        const TextPosition&,
+                       const ScriptFetchOptions&,
                        bool is_external);
   ClassicPendingScript() = delete;
 
@@ -105,6 +113,8 @@
   // MemoryCoordinatorClient
   void OnPurgeMemory() override;
 
+  const ScriptFetchOptions options_;
+
   const bool is_external_;
   ReadyState ready_state_;
   bool integrity_failure_;
diff --git a/third_party/WebKit/Source/core/dom/DynamicModuleResolver.cpp b/third_party/WebKit/Source/core/dom/DynamicModuleResolver.cpp
index c3a6261..380c611 100644
--- a/third_party/WebKit/Source/core/dom/DynamicModuleResolver.cpp
+++ b/third_party/WebKit/Source/core/dom/DynamicModuleResolver.cpp
@@ -191,7 +191,8 @@
   // options are a new script fetch options whose items all have the same
   // values, except for the integrity metadata, which is instead the empty
   // string." [spec text]
-  ScriptFetchOptions options(referrer_info.Nonce(), referrer_info.ParserState(),
+  ScriptFetchOptions options(referrer_info.Nonce(), IntegrityMetadataSet(),
+                             String(), referrer_info.ParserState(),
                              referrer_info.CredentialsMode());
   ModuleScriptFetchRequest request(url, options);
 
diff --git a/third_party/WebKit/Source/core/dom/ModuleMapTest.cpp b/third_party/WebKit/Source/core/dom/ModuleMapTest.cpp
index 6f7efd4..ebcb96f 100644
--- a/third_party/WebKit/Source/core/dom/ModuleMapTest.cpp
+++ b/third_party/WebKit/Source/core/dom/ModuleMapTest.cpp
@@ -105,7 +105,11 @@
                             ModuleGraphLevel,
                             ModuleScriptLoaderClient*) override;
 
-  struct TestRequest : public GarbageCollectedFinalized<TestRequest> {
+  struct TestRequest final : public GarbageCollectedFinalized<TestRequest> {
+    TestRequest(const KURL& in_url,
+                const ScriptFetchOptions& in_options,
+                ModuleScriptLoaderClient* in_client)
+        : url(in_url), options(in_options), client(in_client) {}
     KURL url;
     ScriptFetchOptions options;
     Member<ModuleScriptLoaderClient> client;
@@ -130,10 +134,8 @@
     const ModuleScriptFetchRequest& request,
     ModuleGraphLevel,
     ModuleScriptLoaderClient* client) {
-  TestRequest* test_request = new TestRequest;
-  test_request->url = request.Url();
-  test_request->options = request.Options();
-  test_request->client = client;
+  TestRequest* test_request =
+      new TestRequest(request.Url(), request.Options(), client);
   test_requests_.push_back(test_request);
 }
 
diff --git a/third_party/WebKit/Source/core/dom/Node.cpp b/third_party/WebKit/Source/core/dom/Node.cpp
index 4295079..3ad33de3 100644
--- a/third_party/WebKit/Source/core/dom/Node.cpp
+++ b/third_party/WebKit/Source/core/dom/Node.cpp
@@ -1121,6 +1121,9 @@
 
 bool Node::CanParticipateInFlatTree() const {
   // TODO(hayato): Return false for pseudo elements.
+  if (RuntimeEnabledFeatures::IncrementalShadowDOMEnabled()) {
+    return !IsShadowRoot() && !IsActiveV0InsertionPoint(*this);
+  }
   return !IsShadowRoot() && !IsActiveSlotOrActiveV0InsertionPoint();
 }
 
diff --git a/third_party/WebKit/Source/core/dom/ScriptLoader.cpp b/third_party/WebKit/Source/core/dom/ScriptLoader.cpp
index 14bde4f..284abe8 100644
--- a/third_party/WebKit/Source/core/dom/ScriptLoader.cpp
+++ b/third_party/WebKit/Source/core/dom/ScriptLoader.cpp
@@ -338,9 +338,19 @@
   // 17. "If the script element has a nonce attribute,
   //      then let cryptographic nonce be that attribute's value.
   //      Otherwise, let cryptographic nonce be the empty string."
-  nonce_ = element_->GetNonceForElement();
+  String nonce = element_->GetNonceForElement();
 
-  // 18. is handled below.
+  // 18. "If the script element has an integrity attribute,
+  //      then let integrity metadata be that attribute's value.
+  //      Otherwise, let integrity metadata be the empty string."
+  String integrity_attr = element_->IntegrityAttributeValue();
+  IntegrityMetadataSet integrity_metadata;
+  if (!integrity_attr.IsEmpty()) {
+    SubresourceIntegrity::ReportInfo report_info;
+    SubresourceIntegrity::ParseIntegrityAttribute(
+        integrity_attr, integrity_metadata, &report_info);
+    SubresourceIntegrityHelper::DoReport(element_document, report_info);
+  }
 
   // 19. "Let parser state be "parser-inserted"
   //      if the script element has been flagged as "parser-inserted",
@@ -351,6 +361,20 @@
   if (GetScriptType() == ScriptType::kModule)
     UseCounter::Count(*context_document, WebFeature::kPrepareModuleScript);
 
+  DCHECK(!prepared_pending_script_);
+
+  // Reset line numbering for nested writes.
+  TextPosition position = element_document.IsInDocumentWrite()
+                              ? TextPosition()
+                              : script_start_position;
+
+  // 20. "Let options be a script fetch options whose cryptographic nonce is
+  //      cryptographic nonce, integrity metadata is integrity metadata,
+  //      parser metadata is parser metadata, and credentials mode is module
+  //      script credentials mode." [spec text]
+  ScriptFetchOptions options(nonce, integrity_metadata, integrity_attr,
+                             parser_state, credentials_mode);
+
   // 21. "If the element has a src content attribute, run these substeps:"
   if (element_->HasSourceAttribute()) {
     // 21.1. Let src be the value of the element's src attribute.
@@ -381,8 +405,6 @@
       return false;
     }
 
-    DCHECK(!prepared_pending_script_);
-
     // 21.6. "Switch on the script's type:"
     if (GetScriptType() == ScriptType::kClassic) {
       // - "classic":
@@ -401,21 +423,9 @@
       else
         encoding = element_document.Encoding();
 
-      // 18. "If the script element has an integrity attribute,
-      //      then let integrity metadata be that attribute's value.
-      //      Otherwise, let integrity metadata be the empty string."
-      String integrity_attr = element_->IntegrityAttributeValue();
-      IntegrityMetadataSet integrity_metadata;
-      if (!integrity_attr.IsEmpty()) {
-        SubresourceIntegrity::ReportInfo report_info;
-        SubresourceIntegrity::ParseIntegrityAttribute(
-            integrity_attr, integrity_metadata, &report_info);
-        SubresourceIntegrityHelper::DoReport(element_document, report_info);
-      }
-
-      if (!FetchClassicScript(url, element_document, nonce_, integrity_metadata,
-                              parser_state, cross_origin,
-                              element_document.GetSecurityOrigin(), encoding)) {
+      // "Fetch a classic script given url, settings object, options, CORS
+      // setting, and encoding." [spec text]
+      if (!FetchClassicScript(url, element_document, options, encoding)) {
         // TODO(hiroshige): Make this asynchronous. Currently we fire the error
         // event synchronously to keep the existing behavior.
         DispatchErrorEvent();
@@ -431,17 +441,8 @@
 
       Modulator* modulator = Modulator::From(
           ToScriptStateForMainWorld(context_document->GetFrame()));
-      // 20. "Let options be a script fetch options whose cryptographic nonce is
-      //      cryptographic nonce, integrity metadata is integrity metadata,
-      //      parser metadata is parser metadata, and credentials mode is module
-      //      script credentials mode." [spec text]
-      // TODO(kouhei,hiroshige): Move 20 higher up, when we modify
-      // FetchClassicScript to take |options| too.
-      ScriptFetchOptions options(nonce_, parser_state, credentials_mode);
       FetchModuleScriptTree(url, modulator, options);
     }
-    DCHECK(prepared_pending_script_);
-
     // "When the chosen algorithm asynchronously completes, set
     //  the script's script to the result. At that time, the script is ready."
     // When the script is ready, PendingScriptClient::pendingScriptFinished()
@@ -469,7 +470,17 @@
     switch (GetScriptType()) {
       // - "classic":
       case ScriptType::kClassic:
-        // TODO(hiroshige): Clarify how Step 22.2 is implemented for "classic".
+        // 1. Let script be the result of creating a classic script using source
+        // text, settings object, base URL, and options.
+        //
+        // TODO(hiroshige): Implement base URL and options.
+        prepared_pending_script_ =
+            ClassicPendingScript::CreateInline(element_, position, options);
+
+        // 2. Set the script's script to script.
+        // 3. The script is ready.
+        // Implemented by ClassicPendingScript.
+
         break;
 
       // - "module":
@@ -478,9 +489,6 @@
         //     base URL."
         KURL base_url = element_document.BaseURL();
 
-        TextPosition position = element_document.IsInDocumentWrite()
-                                    ? TextPosition()
-                                    : script_start_position;
         // 2. "Let script be the result of creating a module script using
         //     source text, settings, base URL, cryptographic nonce,
         //     parser state, and module script credentials mode."
@@ -488,8 +496,7 @@
         Modulator* modulator = Modulator::From(
             ToScriptStateForMainWorld(context_document->GetFrame()));
         ModuleScript* module_script = ModuleScript::Create(
-            element_->TextFromChildren(), modulator, base_url,
-            ScriptFetchOptions(nonce_, parser_state, credentials_mode),
+            element_->TextFromChildren(), modulator, base_url, options,
             kSharableCrossOrigin, position);
 
         // 3. "If this returns null, set the script's script to null and abort
@@ -510,6 +517,8 @@
     }
   }
 
+  DCHECK(prepared_pending_script_);
+
   // 23. "Then, follow the first of the following options that describes the
   //      situation:"
 
@@ -652,74 +661,26 @@
   // Note: this block is also duplicated in
   // HTMLParserScriptRunner::processScriptElementInternal().
   // TODO(hiroshige): Merge the duplicated code.
-
-  // Reset line numbering for nested writes.
-  TextPosition position = element_document.IsInDocumentWrite()
-                              ? TextPosition()
-                              : script_start_position;
   KURL script_url = (!element_document.IsInDocumentWrite() && parser_inserted_)
                         ? element_document.Url()
                         : KURL();
-
-  ExecuteScriptBlock(ClassicPendingScript::CreateInline(element_, position),
-                     script_url);
+  ExecuteScriptBlock(TakePendingScript(), script_url);
   return true;
 }
 
+// https://html.spec.whatwg.org/multipage/webappapis.html#fetch-a-classic-script
 bool ScriptLoader::FetchClassicScript(
     const KURL& url,
     Document& element_document,
-    const String& nonce,
-    const IntegrityMetadataSet& integrity_metadata,
-    ParserDisposition parser_state,
-    CrossOriginAttributeValue cross_origin,
-    SecurityOrigin* security_origin,
+    const ScriptFetchOptions& options,
     const WTF::TextEncoding& encoding) {
-  // TODO(hiroshige): remove nonce from the method argument.
-  DCHECK_EQ(nonce_, nonce);
-
-  // https://html.spec.whatwg.org/#prepare-a-script
-  // TODO(kouhei,hiroshige): Update to use ScriptFetchOptions
-  // 21.6, "classic":
-  // "Fetch a classic script given url, settings, ..."
-  ResourceRequest resource_request(url);
-
   FetchParameters::DeferOption defer = FetchParameters::kNoDefer;
   if (!parser_inserted_ || element_->AsyncAttributeValue() ||
       element_->DeferAttributeValue())
     defer = FetchParameters::kLazyLoad;
 
-  ResourceLoaderOptions options;
-  options.initiator_info.name = element_->InitiatorName();
-  FetchParameters params(resource_request, options);
-
-  // "... cryptographic nonce, ..."
-  params.SetContentSecurityPolicyNonce(nonce_);
-
-  // "... integrity metadata, ..."
-  params.SetIntegrityMetadata(integrity_metadata);
-
-  // "... integrity value, ..."
-  params.MutableResourceRequest().SetFetchIntegrity(
-      element_->IntegrityAttributeValue());
-
-  // "... parser state, ..."
-  params.SetParserDisposition(parser_state);
-
-  // "... CORS setting, ..."
-  if (cross_origin != kCrossOriginAttributeNotSet) {
-    params.SetCrossOriginAccessControl(security_origin, cross_origin);
-  }
-
-  // "... and encoding."
-  params.SetCharset(encoding);
-
-  // This DeferOption logic is only for classic scripts, as we always set
-  // |kLazyLoad| for module scripts in ModuleScriptLoader.
-  params.SetDefer(defer);
-
-  ClassicPendingScript* pending_script =
-      ClassicPendingScript::Fetch(element_, params, element_document);
+  ClassicPendingScript* pending_script = ClassicPendingScript::Fetch(
+      url, element_document, options, encoding, element_, defer);
 
   if (!pending_script)
     return false;
diff --git a/third_party/WebKit/Source/core/dom/ScriptLoader.h b/third_party/WebKit/Source/core/dom/ScriptLoader.h
index 96711b3..3cf0abb 100644
--- a/third_party/WebKit/Source/core/dom/ScriptLoader.h
+++ b/third_party/WebKit/Source/core/dom/ScriptLoader.h
@@ -122,8 +122,6 @@
 
   void SetFetchDocWrittenScriptDeferIdle();
 
-  const String& Nonce() const { return nonce_; }
-
   // To support script streaming, the ScriptRunner may need to access the
   // PendingScript. This breaks the intended layering, so please use with
   // care. (Method is virtual to support testing.)
@@ -146,11 +144,7 @@
   // https://html.spec.whatwg.org/#fetch-a-classic-script
   bool FetchClassicScript(const KURL&,
                           Document&,
-                          const String& nonce,
-                          const IntegrityMetadataSet&,
-                          ParserDisposition,
-                          CrossOriginAttributeValue,
-                          SecurityOrigin*,
+                          const ScriptFetchOptions&,
                           const WTF::TextEncoding&);
   // https://html.spec.whatwg.org/#fetch-a-module-script-tree
   void FetchModuleScriptTree(const KURL&,
@@ -235,8 +229,6 @@
   // as ScriptLoader is alive. crbug.com/778799
   Member<ScriptResource> resource_keep_alive_;
 
-  String nonce_;
-
   // The context document at the time when PrepareScript() is executed.
   // This is only used to check whether the script element is moved between
   // documents and thus doesn't retain a strong reference.
diff --git a/third_party/WebKit/Source/core/dom/ng/README.md b/third_party/WebKit/Source/core/dom/ng/README.md
new file mode 100644
index 0000000..ecd5eb9
--- /dev/null
+++ b/third_party/WebKit/Source/core/dom/ng/README.md
@@ -0,0 +1,10 @@
+# DOM experimental
+
+[Rendered](https://chromium.googlesource.com/chromium/src/+/master/third_party/WebKit/Source/core/dom/ng/README.md)
+
+Author: hayato@chromium.org
+
+This directory contains the implementation of **Incremental Shadow DOM**, which is in development behind "IncrementalShadowDOM" runtime flag.
+
+- [Design doc](https://docs.google.com/document/d/1R9J8CVaSub_nbaVQwwm3NjCoZye4feJ7ft7tVe5QerM/edit?usp=sharing)
+- [Tracking bug](http://crbug.com/776656)
diff --git a/third_party/WebKit/Source/core/dom/ng/flat_tree_traversal_ng.cc b/third_party/WebKit/Source/core/dom/ng/flat_tree_traversal_ng.cc
new file mode 100644
index 0000000..912ce0a
--- /dev/null
+++ b/third_party/WebKit/Source/core/dom/ng/flat_tree_traversal_ng.cc
@@ -0,0 +1,391 @@
+/*
+ * Copyright (C) 2012 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *     * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "core/dom/ng/flat_tree_traversal_ng.h"
+
+#include "core/dom/Element.h"
+#include "core/dom/ElementShadow.h"
+#include "core/html/HTMLShadowElement.h"
+#include "core/html/HTMLSlotElement.h"
+
+namespace blink {
+
+static inline ElementShadow* ShadowFor(const Node& node) {
+  return node.IsElementNode() ? ToElement(node).Shadow() : nullptr;
+}
+
+static inline bool CanBeDistributedToV0InsertionPoint(const Node& node) {
+  return node.IsInV0ShadowTree() || node.IsChildOfV0ShadowHost();
+}
+
+Node* FlatTreeTraversalNg::TraverseChild(const Node& node,
+                                         TraversalDirection direction) {
+  if (auto* slot = ToHTMLSlotElementOrNull(node)) {
+    if (slot->SupportsDistribution()) {
+      if (slot->AssignedNodes().IsEmpty()) {
+        return direction == kTraversalDirectionForward ? slot->firstChild()
+                                                       : slot->lastChild();
+      }
+      return direction == kTraversalDirectionForward ? slot->FirstAssignedNode()
+                                                     : slot->LastAssignedNode();
+    }
+  }
+
+  Node* child;
+  ElementShadow* shadow = ShadowFor(node);
+  if (shadow) {
+    ShadowRoot& shadow_root = shadow->YoungestShadowRoot();
+    child = direction == kTraversalDirectionForward ? shadow_root.firstChild()
+                                                    : shadow_root.lastChild();
+  } else {
+    child = direction == kTraversalDirectionForward ? node.firstChild()
+                                                    : node.lastChild();
+  }
+
+  if (!child)
+    return nullptr;
+
+  if (child->IsInV0ShadowTree()) {
+    return V0ResolveDistributionStartingAt(*child, direction);
+  }
+  return child;
+}
+
+// This needs only for v0
+// Node* FlatTreeTraversalNg::ResolveDistributionStartingAt(
+//     const Node* node,
+//     TraversalDirection direction) {
+//   if (!node)
+//     return nullptr;
+//   for (const Node* sibling = node; sibling;
+//        sibling = (direction == kTraversalDirectionForward
+//                       ? sibling->nextSibling()
+//                       : sibling->previousSibling())) {
+//     if (node->IsInV0ShadowTree())
+//       return V0ResolveDistributionStartingAt(*sibling, direction);
+//     return const_cast<Node*>(sibling);
+//   }
+//   return nullptr;
+// }
+
+Node* FlatTreeTraversalNg::V0ResolveDistributionStartingAt(
+    const Node& node,
+    TraversalDirection direction) {
+  DCHECK(!IsHTMLSlotElement(node) ||
+         !ToHTMLSlotElement(node).SupportsDistribution());
+  for (const Node* sibling = &node; sibling;
+       sibling = (direction == kTraversalDirectionForward
+                      ? sibling->nextSibling()
+                      : sibling->previousSibling())) {
+    if (!IsActiveV0InsertionPoint(*sibling))
+      return const_cast<Node*>(sibling);
+    const V0InsertionPoint& insertion_point = ToV0InsertionPoint(*sibling);
+    if (Node* found = (direction == kTraversalDirectionForward
+                           ? insertion_point.FirstDistributedNode()
+                           : insertion_point.LastDistributedNode()))
+      return found;
+    DCHECK(IsHTMLShadowElement(insertion_point) ||
+           (IsHTMLContentElement(insertion_point) &&
+            !insertion_point.HasChildren()));
+  }
+  return nullptr;
+}
+
+// TODO(hayato): This may return a wrong result for a node which is not in a
+// document flat tree.  See FlatTreeTraversalNgTest's redistribution test for
+// details.
+Node* FlatTreeTraversalNg::TraverseSiblings(const Node& node,
+                                            TraversalDirection direction) {
+  if (node.IsChildOfV1ShadowHost())
+    return TraverseSiblingsForV1HostChild(node, direction);
+
+  if (ShadowWhereNodeCanBeDistributedForV0(node))
+    return TraverseSiblingsForV0Distribution(node, direction);
+
+  Node* sibling = direction == kTraversalDirectionForward
+                      ? node.nextSibling()
+                      : node.previousSibling();
+
+  if (!node.IsInV0ShadowTree())
+    return sibling;
+
+  if (sibling) {
+    if (Node* found = V0ResolveDistributionStartingAt(*sibling, direction))
+      return found;
+  }
+
+  // // Slotted nodes are already handled in traverseSiblingsForV1HostChild()
+  // // above, here is for fallback contents.
+  // if (auto* slot = ToHTMLSlotElementOrNull(node.parentElement())) {
+  //   if (slot->SupportsDistribution() && slot->AssignedNodes().IsEmpty())
+  //     return TraverseSiblings(*slot, direction);
+  // }
+
+  // For v0 older shadow tree
+  if (node.parentNode() && node.parentNode()->IsShadowRoot()) {
+    ShadowRoot* parent_shadow_root = ToShadowRoot(node.parentNode());
+    if (!parent_shadow_root->IsYoungest()) {
+      HTMLShadowElement* assigned_insertion_point =
+          parent_shadow_root->ShadowInsertionPointOfYoungerShadowRoot();
+      DCHECK(assigned_insertion_point);
+      return TraverseSiblings(*assigned_insertion_point, direction);
+    }
+  }
+  return nullptr;
+}
+
+Node* FlatTreeTraversalNg::TraverseSiblingsForV1HostChild(
+    const Node& node,
+    TraversalDirection direction) {
+  HTMLSlotElement* slot = node.AssignedSlot();
+  if (!slot)
+    return nullptr;
+  return direction == kTraversalDirectionForward
+             ? slot->AssignedNodeNextTo(node)
+             : slot->AssignedNodePreviousTo(node);
+}
+
+Node* FlatTreeTraversalNg::TraverseSiblingsForV0Distribution(
+    const Node& node,
+    TraversalDirection direction) {
+  const V0InsertionPoint* final_destination = ResolveReprojection(&node);
+  if (!final_destination)
+    return nullptr;
+  if (Node* found = (direction == kTraversalDirectionForward
+                         ? final_destination->DistributedNodeNextTo(&node)
+                         : final_destination->DistributedNodePreviousTo(&node)))
+    return found;
+  return TraverseSiblings(*final_destination, direction);
+}
+
+ContainerNode* FlatTreeTraversalNg::TraverseParent(
+    const Node& node,
+    ParentTraversalDetails* details) {
+  // TODO(hayato): Stop this hack for a pseudo element because a pseudo element
+  // is not a child of its parentOrShadowHostNode() in a flat tree.
+  if (node.IsPseudoElement())
+    return node.ParentOrShadowHostNode();
+
+  if (node.IsChildOfV1ShadowHost())
+    return node.AssignedSlot();
+
+  if (auto* slot = ToHTMLSlotElementOrNull(node.parentElement())) {
+    if (slot->SupportsDistribution() && !slot->AssignedNodes().IsEmpty())
+      return nullptr;
+    return slot;
+  }
+
+  if (CanBeDistributedToV0InsertionPoint(node))
+    return TraverseParentForV0(node, details);
+
+  DCHECK(!ShadowWhereNodeCanBeDistributedForV0(node));
+  return TraverseParentOrHost(node);
+}
+
+ContainerNode* FlatTreeTraversalNg::TraverseParentForV0(
+    const Node& node,
+    ParentTraversalDetails* details) {
+  if (ShadowWhereNodeCanBeDistributedForV0(node)) {
+    if (const V0InsertionPoint* insertion_point = ResolveReprojection(&node)) {
+      if (details)
+        details->DidTraverseInsertionPoint(insertion_point);
+      // The node is distributed. But the distribution was stopped at this
+      // insertion point.
+      if (ShadowWhereNodeCanBeDistributedForV0(*insertion_point))
+        return nullptr;
+      return TraverseParent(*insertion_point);
+    }
+    return nullptr;
+  }
+  ContainerNode* parent = TraverseParentOrHost(node);
+  if (IsActiveV0InsertionPoint(*parent))
+    return nullptr;
+  return parent;
+}
+
+ContainerNode* FlatTreeTraversalNg::TraverseParentOrHost(const Node& node) {
+  ContainerNode* parent = node.parentNode();
+  if (!parent)
+    return nullptr;
+  if (!parent->IsShadowRoot())
+    return parent;
+  ShadowRoot* shadow_root = ToShadowRoot(parent);
+  DCHECK(!shadow_root->ShadowInsertionPointOfYoungerShadowRoot());
+  if (!shadow_root->IsYoungest())
+    return nullptr;
+  return &shadow_root->host();
+}
+
+Node* FlatTreeTraversalNg::ChildAt(const Node& node, unsigned index) {
+  AssertPrecondition(node);
+  Node* child = TraverseFirstChild(node);
+  while (child && index--)
+    child = NextSibling(*child);
+  AssertPostcondition(child);
+  return child;
+}
+
+Node* FlatTreeTraversalNg::NextSkippingChildren(const Node& node) {
+  if (Node* next_sibling = TraverseNextSibling(node))
+    return next_sibling;
+  return TraverseNextAncestorSibling(node);
+}
+
+bool FlatTreeTraversalNg::ContainsIncludingPseudoElement(
+    const ContainerNode& container,
+    const Node& node) {
+  AssertPrecondition(container);
+  AssertPrecondition(node);
+  // This can be slower than FlatTreeTraversalNg::contains() because we
+  // can't early exit even when container doesn't have children.
+  for (const Node* current = &node; current;
+       current = TraverseParent(*current)) {
+    if (current == &container)
+      return true;
+  }
+  return false;
+}
+
+Node* FlatTreeTraversalNg::PreviousSkippingChildren(const Node& node) {
+  if (Node* previous_sibling = TraversePreviousSibling(node))
+    return previous_sibling;
+  return TraversePreviousAncestorSibling(node);
+}
+
+Node* FlatTreeTraversalNg::PreviousAncestorSiblingPostOrder(
+    const Node& current,
+    const Node* stay_within) {
+  DCHECK(!FlatTreeTraversalNg::PreviousSibling(current));
+  for (Node* parent = FlatTreeTraversalNg::Parent(current); parent;
+       parent = FlatTreeTraversalNg::Parent(*parent)) {
+    if (parent == stay_within)
+      return nullptr;
+    if (Node* previous_sibling = FlatTreeTraversalNg::PreviousSibling(*parent))
+      return previous_sibling;
+  }
+  return nullptr;
+}
+
+// TODO(yosin) We should consider introducing template class to share code
+// between DOM tree traversal and flat tree tarversal.
+Node* FlatTreeTraversalNg::PreviousPostOrder(const Node& current,
+                                             const Node* stay_within) {
+  AssertPrecondition(current);
+  if (stay_within)
+    AssertPrecondition(*stay_within);
+  if (Node* last_child = TraverseLastChild(current)) {
+    AssertPostcondition(last_child);
+    return last_child;
+  }
+  if (current == stay_within)
+    return nullptr;
+  if (Node* previous_sibling = TraversePreviousSibling(current)) {
+    AssertPostcondition(previous_sibling);
+    return previous_sibling;
+  }
+  return PreviousAncestorSiblingPostOrder(current, stay_within);
+}
+
+bool FlatTreeTraversalNg::IsDescendantOf(const Node& node, const Node& other) {
+  AssertPrecondition(node);
+  AssertPrecondition(other);
+  if (!HasChildren(other) || node.isConnected() != other.isConnected())
+    return false;
+  for (const ContainerNode* n = TraverseParent(node); n;
+       n = TraverseParent(*n)) {
+    if (n == other)
+      return true;
+  }
+  return false;
+}
+
+Node* FlatTreeTraversalNg::CommonAncestor(const Node& node_a,
+                                          const Node& node_b) {
+  AssertPrecondition(node_a);
+  AssertPrecondition(node_b);
+  Node* result = node_a.CommonAncestor(node_b, [](const Node& node) {
+    return FlatTreeTraversalNg::Parent(node);
+  });
+  AssertPostcondition(result);
+  return result;
+}
+
+Node* FlatTreeTraversalNg::TraverseNextAncestorSibling(const Node& node) {
+  DCHECK(!TraverseNextSibling(node));
+  for (Node* parent = TraverseParent(node); parent;
+       parent = TraverseParent(*parent)) {
+    if (Node* next_sibling = TraverseNextSibling(*parent))
+      return next_sibling;
+  }
+  return nullptr;
+}
+
+Node* FlatTreeTraversalNg::TraversePreviousAncestorSibling(const Node& node) {
+  DCHECK(!TraversePreviousSibling(node));
+  for (Node* parent = TraverseParent(node); parent;
+       parent = TraverseParent(*parent)) {
+    if (Node* previous_sibling = TraversePreviousSibling(*parent))
+      return previous_sibling;
+  }
+  return nullptr;
+}
+
+unsigned FlatTreeTraversalNg::Index(const Node& node) {
+  AssertPrecondition(node);
+  unsigned count = 0;
+  for (Node* runner = TraversePreviousSibling(node); runner;
+       runner = PreviousSibling(*runner))
+    ++count;
+  return count;
+}
+
+unsigned FlatTreeTraversalNg::CountChildren(const Node& node) {
+  AssertPrecondition(node);
+  unsigned count = 0;
+  for (Node* runner = TraverseFirstChild(node); runner;
+       runner = TraverseNextSibling(*runner))
+    ++count;
+  return count;
+}
+
+Node* FlatTreeTraversalNg::LastWithin(const Node& node) {
+  AssertPrecondition(node);
+  Node* descendant = TraverseLastChild(node);
+  for (Node* child = descendant; child; child = LastChild(*child))
+    descendant = child;
+  AssertPostcondition(descendant);
+  return descendant;
+}
+
+Node& FlatTreeTraversalNg::LastWithinOrSelf(const Node& node) {
+  AssertPrecondition(node);
+  Node* last_descendant = LastWithin(node);
+  Node& result = last_descendant ? *last_descendant : const_cast<Node&>(node);
+  AssertPostcondition(&result);
+  return result;
+}
+
+}  // namespace blink
diff --git a/third_party/WebKit/Source/core/dom/ng/flat_tree_traversal_ng.h b/third_party/WebKit/Source/core/dom/ng/flat_tree_traversal_ng.h
new file mode 100644
index 0000000..ca433a6
--- /dev/null
+++ b/third_party/WebKit/Source/core/dom/ng/flat_tree_traversal_ng.h
@@ -0,0 +1,329 @@
+/*
+ * Copyright (C) 2012 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *     * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef FlatTreeTraversalNg_h
+#define FlatTreeTraversalNg_h
+
+#include "core/CoreExport.h"
+#include "core/dom/Document.h"
+#include "core/dom/LayoutTreeBuilderTraversal.h"
+#include "core/dom/NodeTraversal.h"
+#include "core/dom/ShadowRoot.h"
+#include "core/dom/V0InsertionPoint.h"
+#include "platform/wtf/Allocator.h"
+
+namespace blink {
+
+class ContainerNode;
+class Node;
+
+// Flat tree version of |NodeTraversal|.
+//
+// None of member functions takes a |ShadowRoot| or an active insertion point,
+// e.g. roughly speaking <content> and <shadow> in the shadow tree, see
+// |InsertionPoint::isActive()| for details of active insertion points, since
+// they aren't appeared in the flat tree. |assertPrecondition()| and
+// |assertPostCondition()| check this condition.
+//
+// FIXME: Make some functions inline to optimise the performance.
+// https://bugs.webkit.org/show_bug.cgi?id=82702
+class CORE_EXPORT FlatTreeTraversalNg {
+  STATIC_ONLY(FlatTreeTraversalNg);
+
+ public:
+  typedef LayoutTreeBuilderTraversal::ParentDetails ParentTraversalDetails;
+  using TraversalNodeType = Node;
+
+  static Node* Next(const Node&);
+  static Node* Next(const Node&, const Node* stay_within);
+  static Node* Previous(const Node&);
+
+  static Node* FirstChild(const Node&);
+  static Node* LastChild(const Node&);
+  static bool HasChildren(const Node&);
+
+  static ContainerNode* Parent(const Node&, ParentTraversalDetails* = nullptr);
+  static Element* ParentElement(const Node&);
+
+  static Node* NextSibling(const Node&);
+  static Node* PreviousSibling(const Node&);
+
+  // Returns a child node at |index|. If |index| is greater than or equal to
+  // the children, this function returns |nullptr|.
+  static Node* ChildAt(const Node&, unsigned index);
+
+  // Flat tree version of |NodeTraversal::nextSkippingChildren()|. This
+  // function is similar to |next()| but skips child nodes of a specified
+  // node.
+  static Node* NextSkippingChildren(const Node&);
+  static Node* NextSkippingChildren(const Node&, const Node* stay_within);
+
+  static Node* FirstWithin(const Node& current) { return FirstChild(current); }
+
+  // Flat tree version of |NodeTraversal::previousSkippingChildren()|
+  // similar to |previous()| but skipping child nodes of the specified node.
+  static Node* PreviousSkippingChildren(const Node&);
+
+  // Like previous, but visits parents before their children.
+  static Node* PreviousPostOrder(const Node&,
+                                 const Node* stay_within = nullptr);
+
+  // Flat tree version of |Node::isDescendantOf(other)|. This function
+  // returns true if |other| contains |node|, otherwise returns
+  // false. If |other| is |node|, this function returns false.
+  static bool IsDescendantOf(const Node& /*node*/, const Node& other);
+
+  static bool Contains(const ContainerNode& container, const Node& node) {
+    AssertPrecondition(container);
+    AssertPrecondition(node);
+    return container == node || IsDescendantOf(node, container);
+  }
+
+  static bool ContainsIncludingPseudoElement(const ContainerNode&, const Node&);
+
+  // Returns a common ancestor of |nodeA| and |nodeB| if exists, otherwise
+  // returns |nullptr|.
+  static Node* CommonAncestor(const Node& node_a, const Node& node_b);
+
+  // Flat tree version of |Node::nodeIndex()|. This function returns a
+  // zero base position number of the specified node in child nodes list, or
+  // zero if the specified node has no parent.
+  static unsigned Index(const Node&);
+
+  // Flat tree version of |ContainerNode::countChildren()|. This function
+  // returns the number of the child nodes of the specified node in the
+  // flat tree.
+  static unsigned CountChildren(const Node&);
+
+  static Node* LastWithin(const Node&);
+  static Node& LastWithinOrSelf(const Node&);
+
+  // Flat tree range helper functions for range based for statement.
+  // TODO(dom-team): We should have following functions to match with
+  // |NodeTraversal|:
+  //   - AncestorsOf()
+  //   - DescendantsOf()
+  //   - InclusiveAncestorsOf()
+  //   - InclusiveDescendantsOf()
+  //   - StartsAt()
+  //   - StartsAfter()
+  static TraversalRange<TraversalChildrenIterator<FlatTreeTraversalNg>>
+  ChildrenOf(const Node&);
+
+ private:
+  enum TraversalDirection {
+    kTraversalDirectionForward,
+    kTraversalDirectionBackward
+  };
+
+  static void AssertPrecondition(const Node& node) {
+    DCHECK(!node.NeedsDistributionRecalc());
+    DCHECK(node.CanParticipateInFlatTree());
+  }
+
+  static void AssertPostcondition(const Node* node) {
+#if DCHECK_IS_ON()
+    if (node)
+      AssertPrecondition(*node);
+#endif
+  }
+
+  // static Node* ResolveDistributionStartingAt(const Node*,
+  // TraversalDirection);
+  static Node* V0ResolveDistributionStartingAt(const Node&, TraversalDirection);
+
+  static Node* TraverseNext(const Node&);
+  static Node* TraverseNext(const Node&, const Node* stay_within);
+  static Node* TraverseNextSkippingChildren(const Node&,
+                                            const Node* stay_within);
+  static Node* TraversePrevious(const Node&);
+
+  static Node* TraverseFirstChild(const Node&);
+  static Node* TraverseLastChild(const Node&);
+  static Node* TraverseChild(const Node&, TraversalDirection);
+
+  static ContainerNode* TraverseParent(const Node&,
+                                       ParentTraversalDetails* = nullptr);
+  // TODO(hayato): Make ParentTraversalDetails be aware of slot elements too.
+  static ContainerNode* TraverseParentForV0(const Node&,
+                                            ParentTraversalDetails* = nullptr);
+  static ContainerNode* TraverseParentOrHost(const Node&);
+
+  static Node* TraverseNextSibling(const Node&);
+  static Node* TraversePreviousSibling(const Node&);
+
+  static Node* TraverseSiblings(const Node&, TraversalDirection);
+  static Node* TraverseSiblingsForV1HostChild(const Node&, TraversalDirection);
+  static Node* TraverseSiblingsForV0Distribution(const Node&,
+                                                 TraversalDirection);
+
+  static Node* TraverseNextAncestorSibling(const Node&);
+  static Node* TraversePreviousAncestorSibling(const Node&);
+  static Node* PreviousAncestorSiblingPostOrder(const Node& current,
+                                                const Node* stay_within);
+};
+
+inline ContainerNode* FlatTreeTraversalNg::Parent(
+    const Node& node,
+    ParentTraversalDetails* details) {
+  AssertPrecondition(node);
+  ContainerNode* result = TraverseParent(node, details);
+  AssertPostcondition(result);
+  return result;
+}
+
+inline Element* FlatTreeTraversalNg::ParentElement(const Node& node) {
+  ContainerNode* parent = FlatTreeTraversalNg::Parent(node);
+  return parent && parent->IsElementNode() ? ToElement(parent) : nullptr;
+}
+
+inline Node* FlatTreeTraversalNg::NextSibling(const Node& node) {
+  AssertPrecondition(node);
+  Node* result = TraverseSiblings(node, kTraversalDirectionForward);
+  AssertPostcondition(result);
+  return result;
+}
+
+inline Node* FlatTreeTraversalNg::PreviousSibling(const Node& node) {
+  AssertPrecondition(node);
+  Node* result = TraverseSiblings(node, kTraversalDirectionBackward);
+  AssertPostcondition(result);
+  return result;
+}
+
+inline Node* FlatTreeTraversalNg::Next(const Node& node) {
+  AssertPrecondition(node);
+  Node* result = TraverseNext(node);
+  AssertPostcondition(result);
+  return result;
+}
+
+inline Node* FlatTreeTraversalNg::Next(const Node& node,
+                                       const Node* stay_within) {
+  AssertPrecondition(node);
+  Node* result = TraverseNext(node, stay_within);
+  AssertPostcondition(result);
+  return result;
+}
+
+inline Node* FlatTreeTraversalNg::NextSkippingChildren(
+    const Node& node,
+    const Node* stay_within) {
+  AssertPrecondition(node);
+  Node* result = TraverseNextSkippingChildren(node, stay_within);
+  AssertPostcondition(result);
+  return result;
+}
+
+inline Node* FlatTreeTraversalNg::TraverseNext(const Node& node) {
+  if (Node* next = TraverseFirstChild(node))
+    return next;
+  for (const Node* next = &node; next; next = TraverseParent(*next)) {
+    if (Node* sibling = TraverseNextSibling(*next))
+      return sibling;
+  }
+  return nullptr;
+}
+
+inline Node* FlatTreeTraversalNg::TraverseNext(const Node& node,
+                                               const Node* stay_within) {
+  if (Node* next = TraverseFirstChild(node))
+    return next;
+  return TraverseNextSkippingChildren(node, stay_within);
+}
+
+inline Node* FlatTreeTraversalNg::TraverseNextSkippingChildren(
+    const Node& node,
+    const Node* stay_within) {
+  for (const Node* next = &node; next; next = TraverseParent(*next)) {
+    if (next == stay_within)
+      return nullptr;
+    if (Node* sibling = TraverseNextSibling(*next))
+      return sibling;
+  }
+  return nullptr;
+}
+
+inline Node* FlatTreeTraversalNg::Previous(const Node& node) {
+  AssertPrecondition(node);
+  Node* result = TraversePrevious(node);
+  AssertPostcondition(result);
+  return result;
+}
+
+inline Node* FlatTreeTraversalNg::TraversePrevious(const Node& node) {
+  if (Node* previous = TraversePreviousSibling(node)) {
+    while (Node* child = TraverseLastChild(*previous))
+      previous = child;
+    return previous;
+  }
+  return TraverseParent(node);
+}
+
+inline Node* FlatTreeTraversalNg::FirstChild(const Node& node) {
+  AssertPrecondition(node);
+  Node* result = TraverseChild(node, kTraversalDirectionForward);
+  AssertPostcondition(result);
+  return result;
+}
+
+inline Node* FlatTreeTraversalNg::LastChild(const Node& node) {
+  AssertPrecondition(node);
+  Node* result = TraverseLastChild(node);
+  AssertPostcondition(result);
+  return result;
+}
+
+inline bool FlatTreeTraversalNg::HasChildren(const Node& node) {
+  return FirstChild(node);
+}
+
+inline Node* FlatTreeTraversalNg::TraverseNextSibling(const Node& node) {
+  return TraverseSiblings(node, kTraversalDirectionForward);
+}
+
+inline Node* FlatTreeTraversalNg::TraversePreviousSibling(const Node& node) {
+  return TraverseSiblings(node, kTraversalDirectionBackward);
+}
+
+inline Node* FlatTreeTraversalNg::TraverseFirstChild(const Node& node) {
+  return TraverseChild(node, kTraversalDirectionForward);
+}
+
+inline Node* FlatTreeTraversalNg::TraverseLastChild(const Node& node) {
+  return TraverseChild(node, kTraversalDirectionBackward);
+}
+
+// TraverseRange<T> implementations
+inline TraversalRange<TraversalChildrenIterator<FlatTreeTraversalNg>>
+FlatTreeTraversalNg::ChildrenOf(const Node& parent) {
+  return TraversalRange<TraversalChildrenIterator<FlatTreeTraversalNg>>(
+      &parent);
+}
+
+}  // namespace blink
+
+#endif
diff --git a/third_party/WebKit/Source/core/dom/ng/flat_tree_traversal_ng_test.cc b/third_party/WebKit/Source/core/dom/ng/flat_tree_traversal_ng_test.cc
new file mode 100644
index 0000000..9579968
--- /dev/null
+++ b/third_party/WebKit/Source/core/dom/ng/flat_tree_traversal_ng_test.cc
@@ -0,0 +1,787 @@
+// 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 "core/dom/ng/flat_tree_traversal_ng.h"
+
+#include <memory>
+#include "bindings/core/v8/ExceptionState.h"
+#include "core/dom/Document.h"
+#include "core/dom/Element.h"
+#include "core/dom/Node.h"
+#include "core/dom/NodeTraversal.h"
+#include "core/dom/ShadowRoot.h"
+#include "core/frame/LocalFrameView.h"
+#include "core/html/HTMLElement.h"
+#include "core/testing/DummyPageHolder.h"
+#include "platform/geometry/IntSize.h"
+#include "platform/runtime_enabled_features.h"
+#include "platform/wtf/Compiler.h"
+#include "platform/wtf/StdLibExtras.h"
+#include "platform/wtf/Vector.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace blink {
+
+class FlatTreeTraversalNgTest : public ::testing::Test {
+ public:
+  FlatTreeTraversalNgTest() {
+    RuntimeEnabledFeatures::SetIncrementalShadowDOMEnabled(true);
+  }
+  ~FlatTreeTraversalNgTest() {
+    RuntimeEnabledFeatures::SetIncrementalShadowDOMEnabled(false);
+  }
+
+ protected:
+  Document& GetDocument() const;
+
+  // Sets |mainHTML| to BODY element with |innerHTML| property and attaches
+  // shadow root to child with |shadowHTML|, then update distribution for
+  // calling member functions in |FlatTreeTraversalNg|.
+  void SetupSampleHTML(const char* main_html,
+                       const char* shadow_html,
+                       unsigned);
+
+  void SetupDocumentTree(const char* main_html);
+
+  void AttachV0ShadowRoot(Element& shadow_host, const char* shadow_inner_html);
+  void AttachOpenShadowRoot(Element& shadow_host,
+                            const char* shadow_inner_html);
+
+ private:
+  void SetUp() override;
+
+  Persistent<Document> document_;
+  std::unique_ptr<DummyPageHolder> dummy_page_holder_;
+};
+
+void FlatTreeTraversalNgTest::SetUp() {
+  dummy_page_holder_ = DummyPageHolder::Create(IntSize(800, 600));
+  document_ = &dummy_page_holder_->GetDocument();
+  DCHECK(document_);
+}
+
+Document& FlatTreeTraversalNgTest::GetDocument() const {
+  return *document_;
+}
+
+void FlatTreeTraversalNgTest::SetupSampleHTML(const char* main_html,
+                                              const char* shadow_html,
+                                              unsigned index) {
+  Element* body = GetDocument().body();
+  body->SetInnerHTMLFromString(String::FromUTF8(main_html));
+  Element* shadow_host = ToElement(NodeTraversal::ChildAt(*body, index));
+  ShadowRoot& shadow_root = shadow_host->CreateShadowRootInternal();
+  shadow_root.SetInnerHTMLFromString(String::FromUTF8(shadow_html));
+  body->UpdateDistribution();
+}
+
+void FlatTreeTraversalNgTest::SetupDocumentTree(const char* main_html) {
+  Element* body = GetDocument().body();
+  body->SetInnerHTMLFromString(String::FromUTF8(main_html));
+}
+
+void FlatTreeTraversalNgTest::AttachV0ShadowRoot(
+    Element& shadow_host,
+    const char* shadow_inner_html) {
+  ShadowRoot& shadow_root = shadow_host.CreateShadowRootInternal();
+  shadow_root.SetInnerHTMLFromString(String::FromUTF8(shadow_inner_html));
+  GetDocument().body()->UpdateDistribution();
+}
+
+void FlatTreeTraversalNgTest::AttachOpenShadowRoot(
+    Element& shadow_host,
+    const char* shadow_inner_html) {
+  ShadowRoot& shadow_root =
+      shadow_host.AttachShadowRootInternal(ShadowRootType::kOpen);
+  shadow_root.SetInnerHTMLFromString(String::FromUTF8(shadow_inner_html));
+  GetDocument().body()->UpdateDistribution();
+}
+
+namespace {
+
+void TestCommonAncestor(Node* expected_result,
+                        const Node& node_a,
+                        const Node& node_b) {
+  Node* result1 = FlatTreeTraversalNg::CommonAncestor(node_a, node_b);
+  EXPECT_EQ(expected_result, result1)
+      << "commonAncestor(" << node_a.textContent() << ","
+      << node_b.textContent() << ")";
+  Node* result2 = FlatTreeTraversalNg::CommonAncestor(node_b, node_a);
+  EXPECT_EQ(expected_result, result2)
+      << "commonAncestor(" << node_b.textContent() << ","
+      << node_a.textContent() << ")";
+}
+
+}  // namespace
+
+// Test case for
+//  - childAt
+//  - countChildren
+//  - hasChildren
+//  - index
+//  - isDescendantOf
+TEST_F(FlatTreeTraversalNgTest, childAt) {
+  const char* main_html =
+      "<div id='m0'>"
+      "<span id='m00'>m00</span>"
+      "<span id='m01'>m01</span>"
+      "</div>";
+  const char* shadow_html =
+      "<a id='s00'>s00</a>"
+      "<content select='#m01'></content>"
+      "<a id='s02'>s02</a>"
+      "<a id='s03'><content select='#m00'></content></a>"
+      "<a id='s04'>s04</a>";
+  SetupSampleHTML(main_html, shadow_html, 0);
+
+  Element* body = GetDocument().body();
+  Element* m0 = body->QuerySelector("#m0");
+  Element* m00 = m0->QuerySelector("#m00");
+  Element* m01 = m0->QuerySelector("#m01");
+
+  Element* shadow_host = m0;
+  ShadowRoot* shadow_root = shadow_host->OpenShadowRoot();
+  Element* s00 = shadow_root->QuerySelector("#s00");
+  Element* s02 = shadow_root->QuerySelector("#s02");
+  Element* s03 = shadow_root->QuerySelector("#s03");
+  Element* s04 = shadow_root->QuerySelector("#s04");
+
+  const unsigned kNumberOfChildNodes = 5;
+  Node* expected_child_nodes[5] = {s00, m01, s02, s03, s04};
+
+  ASSERT_EQ(kNumberOfChildNodes,
+            FlatTreeTraversalNg::CountChildren(*shadow_host));
+  EXPECT_TRUE(FlatTreeTraversalNg::HasChildren(*shadow_host));
+
+  for (unsigned index = 0; index < kNumberOfChildNodes; ++index) {
+    Node* child = FlatTreeTraversalNg::ChildAt(*shadow_host, index);
+    EXPECT_EQ(expected_child_nodes[index], child)
+        << "FlatTreeTraversalNg::childAt(*shadowHost, " << index << ")";
+    EXPECT_EQ(index, FlatTreeTraversalNg::Index(*child))
+        << "FlatTreeTraversalNg::index(FlatTreeTraversalNg(*shadowHost, "
+        << index << "))";
+    EXPECT_TRUE(FlatTreeTraversalNg::IsDescendantOf(*child, *shadow_host))
+        << "FlatTreeTraversalNg::isDescendantOf(*FlatTreeTraversalNg(*"
+           "shadowHost, "
+        << index << "), *shadowHost)";
+  }
+  EXPECT_EQ(nullptr,
+            FlatTreeTraversalNg::ChildAt(*shadow_host, kNumberOfChildNodes + 1))
+      << "Out of bounds childAt() returns nullptr.";
+
+  // Distribute node |m00| is child of node in shadow tree |s03|.
+  EXPECT_EQ(m00, FlatTreeTraversalNg::ChildAt(*s03, 0));
+}
+
+TEST_F(FlatTreeTraversalNgTest, ChildrenOf) {
+  SetupSampleHTML(
+      "<p id=sample>ZERO<span slot=three>three</b><span "
+      "slot=one>one</b>FOUR</p>",
+      "zero<slot name=one></slot>two<slot name=three></slot>four", 0);
+  Element* const sample = GetDocument().getElementById("sample");
+
+  HeapVector<Member<Node>> expected_nodes;
+  for (Node* runner = FlatTreeTraversalNg::FirstChild(*sample); runner;
+       runner = FlatTreeTraversalNg::NextSibling(*runner)) {
+    expected_nodes.push_back(runner);
+  }
+
+  HeapVector<Member<Node>> actual_nodes;
+  for (Node& child : FlatTreeTraversalNg::ChildrenOf(*sample))
+    actual_nodes.push_back(&child);
+
+  EXPECT_EQ(expected_nodes, actual_nodes);
+}
+
+// Test case for
+//  - commonAncestor
+//  - isDescendantOf
+TEST_F(FlatTreeTraversalNgTest, commonAncestor) {
+  // We build following flat tree:
+  //             ____BODY___
+  //             |    |     |
+  //            m0    m1    m2       m1 is shadow host having m10, m11, m12.
+  //            _|_   |   __|__
+  //           |   |  |   |    |
+  //          m00 m01 |   m20 m21
+  //             _____|_____________
+  //             |  |   |    |     |
+  //            s10 s11 s12 s13  s14
+  //                         |
+  //                       __|__
+  //                |      |    |
+  //                m12    m10 m11 <-- distributed
+  // where: each symbol consists with prefix, child index, child-child index.
+  //  prefix "m" means node in main tree,
+  //  prefix "d" means node in main tree and distributed
+  //  prefix "s" means node in shadow tree
+  const char* main_html =
+      "<a id='m0'><b id='m00'>m00</b><b id='m01'>m01</b></a>"
+      "<a id='m1'>"
+      "<b id='m10'>m10</b>"
+      "<b id='m11'>m11</b>"
+      "<b id='m12'>m12</b>"
+      "</a>"
+      "<a id='m2'><b id='m20'>m20</b><b id='m21'>m21</b></a>";
+  const char* shadow_html =
+      "<a id='s10'>s10</a>"
+      "<a id='s11'><content select='#m12'></content></a>"
+      "<a id='s12'>s12</a>"
+      "<a id='s13'>"
+      "<content select='#m10'></content>"
+      "<content select='#m11'></content>"
+      "</a>"
+      "<a id='s14'>s14</a>";
+  SetupSampleHTML(main_html, shadow_html, 1);
+  Element* body = GetDocument().body();
+  Element* m0 = body->QuerySelector("#m0");
+  Element* m1 = body->QuerySelector("#m1");
+  Element* m2 = body->QuerySelector("#m2");
+
+  Element* m00 = body->QuerySelector("#m00");
+  Element* m01 = body->QuerySelector("#m01");
+  Element* m10 = body->QuerySelector("#m10");
+  Element* m11 = body->QuerySelector("#m11");
+  Element* m12 = body->QuerySelector("#m12");
+  Element* m20 = body->QuerySelector("#m20");
+  Element* m21 = body->QuerySelector("#m21");
+
+  ShadowRoot* shadow_root = m1->OpenShadowRoot();
+  Element* s10 = shadow_root->QuerySelector("#s10");
+  Element* s11 = shadow_root->QuerySelector("#s11");
+  Element* s12 = shadow_root->QuerySelector("#s12");
+  Element* s13 = shadow_root->QuerySelector("#s13");
+  Element* s14 = shadow_root->QuerySelector("#s14");
+
+  TestCommonAncestor(body, *m0, *m1);
+  TestCommonAncestor(body, *m1, *m2);
+  TestCommonAncestor(body, *m1, *m20);
+  TestCommonAncestor(body, *s14, *m21);
+
+  TestCommonAncestor(m0, *m0, *m0);
+  TestCommonAncestor(m0, *m00, *m01);
+
+  TestCommonAncestor(m1, *m1, *m1);
+  TestCommonAncestor(m1, *s10, *s14);
+  TestCommonAncestor(m1, *s10, *m12);
+  TestCommonAncestor(m1, *s12, *m12);
+  TestCommonAncestor(m1, *m10, *m12);
+
+  TestCommonAncestor(m01, *m01, *m01);
+  TestCommonAncestor(s11, *s11, *m12);
+  TestCommonAncestor(s13, *m10, *m11);
+
+  s12->remove(ASSERT_NO_EXCEPTION);
+  TestCommonAncestor(s12, *s12, *s12);
+  TestCommonAncestor(nullptr, *s12, *s11);
+  TestCommonAncestor(nullptr, *s12, *m01);
+  TestCommonAncestor(nullptr, *s12, *m20);
+
+  m20->remove(ASSERT_NO_EXCEPTION);
+  TestCommonAncestor(m20, *m20, *m20);
+  TestCommonAncestor(nullptr, *m20, *s12);
+  TestCommonAncestor(nullptr, *m20, *m1);
+}
+
+// Test case for
+//  - nextSkippingChildren
+//  - previousSkippingChildren
+TEST_F(FlatTreeTraversalNgTest, nextSkippingChildren) {
+  const char* main_html =
+      "<div id='m0'>m0</div>"
+      "<div id='m1'>"
+      "<span id='m10'>m10</span>"
+      "<span id='m11'>m11</span>"
+      "</div>"
+      "<div id='m2'>m2</div>";
+  const char* shadow_html =
+      "<content select='#m11'></content>"
+      "<a id='s11'>s11</a>"
+      "<a id='s12'>"
+      "<b id='s120'>s120</b>"
+      "<content select='#m10'></content>"
+      "</a>";
+  SetupSampleHTML(main_html, shadow_html, 1);
+
+  Element* body = GetDocument().body();
+  Element* m0 = body->QuerySelector("#m0");
+  Element* m1 = body->QuerySelector("#m1");
+  Element* m2 = body->QuerySelector("#m2");
+
+  Element* m10 = body->QuerySelector("#m10");
+  Element* m11 = body->QuerySelector("#m11");
+
+  ShadowRoot* shadow_root = m1->OpenShadowRoot();
+  Element* s11 = shadow_root->QuerySelector("#s11");
+  Element* s12 = shadow_root->QuerySelector("#s12");
+  Element* s120 = shadow_root->QuerySelector("#s120");
+
+  // Main tree node to main tree node
+  EXPECT_EQ(*m1, FlatTreeTraversalNg::NextSkippingChildren(*m0));
+  EXPECT_EQ(*m0, FlatTreeTraversalNg::PreviousSkippingChildren(*m1));
+
+  // Distribute node to main tree node
+  EXPECT_EQ(*m2, FlatTreeTraversalNg::NextSkippingChildren(*m10));
+  EXPECT_EQ(*m1, FlatTreeTraversalNg::PreviousSkippingChildren(*m2));
+
+  // Distribute node to node in shadow tree
+  EXPECT_EQ(*s11, FlatTreeTraversalNg::NextSkippingChildren(*m11));
+  EXPECT_EQ(*m11, FlatTreeTraversalNg::PreviousSkippingChildren(*s11));
+
+  // Node in shadow tree to distributed node
+  EXPECT_EQ(*s11, FlatTreeTraversalNg::NextSkippingChildren(*m11));
+  EXPECT_EQ(*m11, FlatTreeTraversalNg::PreviousSkippingChildren(*s11));
+
+  EXPECT_EQ(*m10, FlatTreeTraversalNg::NextSkippingChildren(*s120));
+  EXPECT_EQ(*s120, FlatTreeTraversalNg::PreviousSkippingChildren(*m10));
+
+  // Node in shadow tree to main tree
+  EXPECT_EQ(*m2, FlatTreeTraversalNg::NextSkippingChildren(*s12));
+  EXPECT_EQ(*m1, FlatTreeTraversalNg::PreviousSkippingChildren(*m2));
+}
+
+// Test case for
+//  - lastWithin
+//  - lastWithinOrSelf
+TEST_F(FlatTreeTraversalNgTest, lastWithin) {
+  const char* main_html =
+      "<div id='m0'>m0</div>"
+      "<div id='m1'>"
+      "<span id='m10'>m10</span>"
+      "<span id='m11'>m11</span>"
+      "<span id='m12'>m12</span>"  // #m12 is not distributed.
+      "</div>"
+      "<div id='m2'></div>";
+  const char* shadow_html =
+      "<content select='#m11'></content>"
+      "<a id='s11'>s11</a>"
+      "<a id='s12'>"
+      "<content select='#m10'></content>"
+      "</a>";
+  SetupSampleHTML(main_html, shadow_html, 1);
+
+  Element* body = GetDocument().body();
+  Element* m0 = body->QuerySelector("#m0");
+  Element* m1 = body->QuerySelector("#m1");
+  Element* m2 = body->QuerySelector("#m2");
+
+  Element* m10 = body->QuerySelector("#m10");
+
+  ShadowRoot* shadow_root = m1->OpenShadowRoot();
+  Element* s11 = shadow_root->QuerySelector("#s11");
+  Element* s12 = shadow_root->QuerySelector("#s12");
+
+  EXPECT_EQ(m0->firstChild(), FlatTreeTraversalNg::LastWithin(*m0));
+  EXPECT_EQ(*m0->firstChild(), FlatTreeTraversalNg::LastWithinOrSelf(*m0));
+
+  EXPECT_EQ(m10->firstChild(), FlatTreeTraversalNg::LastWithin(*m1));
+  EXPECT_EQ(*m10->firstChild(), FlatTreeTraversalNg::LastWithinOrSelf(*m1));
+
+  EXPECT_EQ(nullptr, FlatTreeTraversalNg::LastWithin(*m2));
+  EXPECT_EQ(*m2, FlatTreeTraversalNg::LastWithinOrSelf(*m2));
+
+  EXPECT_EQ(s11->firstChild(), FlatTreeTraversalNg::LastWithin(*s11));
+  EXPECT_EQ(*s11->firstChild(), FlatTreeTraversalNg::LastWithinOrSelf(*s11));
+
+  EXPECT_EQ(m10->firstChild(), FlatTreeTraversalNg::LastWithin(*s12));
+  EXPECT_EQ(*m10->firstChild(), FlatTreeTraversalNg::LastWithinOrSelf(*s12));
+}
+
+TEST_F(FlatTreeTraversalNgTest, previousPostOrder) {
+  const char* main_html =
+      "<div id='m0'>m0</div>"
+      "<div id='m1'>"
+      "<span id='m10'>m10</span>"
+      "<span id='m11'>m11</span>"
+      "</div>"
+      "<div id='m2'>m2</div>";
+  const char* shadow_html =
+      "<content select='#m11'></content>"
+      "<a id='s11'>s11</a>"
+      "<a id='s12'>"
+      "<b id='s120'>s120</b>"
+      "<content select='#m10'></content>"
+      "</a>";
+  SetupSampleHTML(main_html, shadow_html, 1);
+
+  Element* body = GetDocument().body();
+  Element* m0 = body->QuerySelector("#m0");
+  Element* m1 = body->QuerySelector("#m1");
+  Element* m2 = body->QuerySelector("#m2");
+
+  Element* m10 = body->QuerySelector("#m10");
+  Element* m11 = body->QuerySelector("#m11");
+
+  ShadowRoot* shadow_root = m1->OpenShadowRoot();
+  Element* s11 = shadow_root->QuerySelector("#s11");
+  Element* s12 = shadow_root->QuerySelector("#s12");
+  Element* s120 = shadow_root->QuerySelector("#s120");
+
+  EXPECT_EQ(*m0->firstChild(), FlatTreeTraversalNg::PreviousPostOrder(*m0));
+  EXPECT_EQ(*s12, FlatTreeTraversalNg::PreviousPostOrder(*m1));
+  EXPECT_EQ(*m10->firstChild(), FlatTreeTraversalNg::PreviousPostOrder(*m10));
+  EXPECT_EQ(*s120, FlatTreeTraversalNg::PreviousPostOrder(*m10->firstChild()));
+  EXPECT_EQ(*s120,
+            FlatTreeTraversalNg::PreviousPostOrder(*m10->firstChild(), s12));
+  EXPECT_EQ(*m11->firstChild(), FlatTreeTraversalNg::PreviousPostOrder(*m11));
+  EXPECT_EQ(*m0, FlatTreeTraversalNg::PreviousPostOrder(*m11->firstChild()));
+  EXPECT_EQ(nullptr,
+            FlatTreeTraversalNg::PreviousPostOrder(*m11->firstChild(), m11));
+  EXPECT_EQ(*m2->firstChild(), FlatTreeTraversalNg::PreviousPostOrder(*m2));
+
+  EXPECT_EQ(*s11->firstChild(), FlatTreeTraversalNg::PreviousPostOrder(*s11));
+  EXPECT_EQ(*m10, FlatTreeTraversalNg::PreviousPostOrder(*s12));
+  EXPECT_EQ(*s120->firstChild(), FlatTreeTraversalNg::PreviousPostOrder(*s120));
+  EXPECT_EQ(*s11, FlatTreeTraversalNg::PreviousPostOrder(*s120->firstChild()));
+  EXPECT_EQ(nullptr,
+            FlatTreeTraversalNg::PreviousPostOrder(*s120->firstChild(), s12));
+}
+
+TEST_F(FlatTreeTraversalNgTest, nextSiblingNotInDocumentFlatTree) {
+  const char* main_html =
+      "<div id='m0'>m0</div>"
+      "<div id='m1'>"
+      "<span id='m10'>m10</span>"
+      "<span id='m11'>m11</span>"
+      "</div>"
+      "<div id='m2'>m2</div>";
+  const char* shadow_html = "<content select='#m11'></content>";
+  SetupSampleHTML(main_html, shadow_html, 1);
+
+  Element* body = GetDocument().body();
+  Element* m10 = body->QuerySelector("#m10");
+
+  EXPECT_EQ(nullptr, FlatTreeTraversalNg::NextSibling(*m10));
+  EXPECT_EQ(nullptr, FlatTreeTraversalNg::PreviousSibling(*m10));
+}
+
+TEST_F(FlatTreeTraversalNgTest, redistribution) {
+  const char* main_html =
+      "<div id='m0'>m0</div>"
+      "<div id='m1'>"
+      "<span id='m10'>m10</span>"
+      "<span id='m11'>m11</span>"
+      "</div>"
+      "<div id='m2'>m2</div>";
+  const char* shadow_html1 =
+      "<div id='s1'>"
+      "<content></content>"
+      "</div>";
+
+  SetupSampleHTML(main_html, shadow_html1, 1);
+
+  const char* shadow_html2 =
+      "<div id='s2'>"
+      "<content select='#m10'></content>"
+      "<span id='s21'>s21</span>"
+      "</div>";
+
+  Element* body = GetDocument().body();
+  Element* m1 = body->QuerySelector("#m1");
+  Element* m10 = body->QuerySelector("#m10");
+
+  ShadowRoot* shadow_root1 = m1->OpenShadowRoot();
+  Element* s1 = shadow_root1->QuerySelector("#s1");
+
+  AttachV0ShadowRoot(*s1, shadow_html2);
+
+  ShadowRoot* shadow_root2 = s1->OpenShadowRoot();
+  Element* s21 = shadow_root2->QuerySelector("#s21");
+
+  EXPECT_EQ(s21, FlatTreeTraversalNg::NextSibling(*m10));
+  EXPECT_EQ(m10, FlatTreeTraversalNg::PreviousSibling(*s21));
+
+  // FlatTreeTraversalNg::traverseSiblings does not work for a node which is not
+  // in a document flat tree.
+  // e.g. The following test fails. The result of
+  // FlatTreeTraversalNg::previousSibling(*m11)) will be #m10, instead of
+  // nullptr. Element* m11 = body->querySelector("#m11"); EXPECT_EQ(nullptr,
+  // FlatTreeTraversalNg::previousSibling(*m11));
+}
+
+TEST_F(FlatTreeTraversalNgTest, v1Simple) {
+  const char* main_html =
+      "<div id='host'>"
+      "<div id='child1' slot='slot1'></div>"
+      "<div id='child2' slot='slot2'></div>"
+      "</div>";
+  const char* shadow_html =
+      "<div id='shadow-child1'></div>"
+      "<slot name='slot1'></slot>"
+      "<slot name='slot2'></slot>"
+      "<div id='shadow-child2'></div>";
+
+  SetupDocumentTree(main_html);
+  Element* body = GetDocument().body();
+  Element* host = body->QuerySelector("#host");
+  Element* child1 = body->QuerySelector("#child1");
+  Element* child2 = body->QuerySelector("#child2");
+
+  AttachOpenShadowRoot(*host, shadow_html);
+  ShadowRoot* shadow_root = host->OpenShadowRoot();
+  Element* slot1 = shadow_root->QuerySelector("[name=slot1]");
+  Element* slot2 = shadow_root->QuerySelector("[name=slot2]");
+  Element* shadow_child1 = shadow_root->QuerySelector("#shadow-child1");
+  Element* shadow_child2 = shadow_root->QuerySelector("#shadow-child2");
+
+  EXPECT_TRUE(slot1);
+  EXPECT_TRUE(slot2);
+  EXPECT_EQ(shadow_child1, FlatTreeTraversalNg::FirstChild(*host));
+  EXPECT_EQ(slot1, FlatTreeTraversalNg::NextSibling(*shadow_child1));
+  EXPECT_EQ(nullptr, FlatTreeTraversalNg::NextSibling(*child1));
+  EXPECT_EQ(nullptr, FlatTreeTraversalNg::NextSibling(*child2));
+  EXPECT_EQ(slot2, FlatTreeTraversalNg::NextSibling(*slot1));
+  EXPECT_EQ(shadow_child2, FlatTreeTraversalNg::NextSibling(*slot2));
+}
+
+TEST_F(FlatTreeTraversalNgTest, v1Redistribution) {
+  // composed tree:
+  // d1
+  // ├──/shadow-root
+  // │   └── d1-1
+  // │       ├──/shadow-root
+  // │       │   ├── d1-1-1
+  // │       │   ├── slot name=d1-1-s1
+  // │       │   ├── slot name=d1-1-s2
+  // │       │   └── d1-1-2
+  // │       ├── d1-2
+  // │       ├── slot id=d1-s0
+  // │       ├── slot name=d1-s1 slot=d1-1-s1
+  // │       ├── slot name=d1-s2
+  // │       ├── d1-3
+  // │       └── d1-4 slot=d1-1-s1
+  // ├── d2 slot=d1-s1
+  // ├── d3 slot=d1-s2
+  // ├── d4 slot=nonexistent
+  // └── d5
+
+  // flat tree:
+  // d1
+  // └── d1-1
+  //     ├── d1-1-1
+  //     ├── slot name=d1-1-s1
+  //     │   ├── slot name=d1-s1 slot=d1-1-s1
+  //     │   │   └── d2 slot=d1-s1
+  //     │   └── d1-4 slot=d1-1-s1
+  //     ├── slot name=d1-1-s2
+  //     └── d1-1-2
+  const char* main_html =
+      "<div id='d1'>"
+      "<div id='d2' slot='d1-s1'></div>"
+      "<div id='d3' slot='d1-s2'></div>"
+      "<div id='d4' slot='nonexistent'></div>"
+      "<div id='d5'></div>"
+      "</div>"
+      "<div id='d6'></div>";
+  const char* shadow_html1 =
+      "<div id='d1-1'>"
+      "<div id='d1-2'></div>"
+      "<slot id='d1-s0'></slot>"
+      "<slot name='d1-s1' slot='d1-1-s1'></slot>"
+      "<slot name='d1-s2'></slot>"
+      "<div id='d1-3'></div>"
+      "<div id='d1-4' slot='d1-1-s1'></div>"
+      "</div>";
+  const char* shadow_html2 =
+      "<div id='d1-1-1'></div>"
+      "<slot name='d1-1-s1'></slot>"
+      "<slot name='d1-1-s2'></slot>"
+      "<div id='d1-1-2'></div>";
+
+  SetupDocumentTree(main_html);
+
+  Element* body = GetDocument().body();
+  Element* d1 = body->QuerySelector("#d1");
+  Element* d2 = body->QuerySelector("#d2");
+  Element* d3 = body->QuerySelector("#d3");
+  Element* d4 = body->QuerySelector("#d4");
+  Element* d5 = body->QuerySelector("#d5");
+  Element* d6 = body->QuerySelector("#d6");
+
+  AttachOpenShadowRoot(*d1, shadow_html1);
+  ShadowRoot* shadow_root1 = d1->OpenShadowRoot();
+  Element* d11 = shadow_root1->QuerySelector("#d1-1");
+  Element* d12 = shadow_root1->QuerySelector("#d1-2");
+  Element* d13 = shadow_root1->QuerySelector("#d1-3");
+  Element* d14 = shadow_root1->QuerySelector("#d1-4");
+  Element* d1s0 = shadow_root1->QuerySelector("#d1-s0");
+  Element* d1s1 = shadow_root1->QuerySelector("[name=d1-s1]");
+  Element* d1s2 = shadow_root1->QuerySelector("[name=d1-s2]");
+
+  AttachOpenShadowRoot(*d11, shadow_html2);
+  ShadowRoot* shadow_root2 = d11->OpenShadowRoot();
+  Element* d111 = shadow_root2->QuerySelector("#d1-1-1");
+  Element* d112 = shadow_root2->QuerySelector("#d1-1-2");
+  Element* d11s1 = shadow_root2->QuerySelector("[name=d1-1-s1]");
+  Element* d11s2 = shadow_root2->QuerySelector("[name=d1-1-s2]");
+
+  EXPECT_TRUE(d5);
+  EXPECT_TRUE(d12);
+  EXPECT_TRUE(d13);
+  EXPECT_TRUE(d1s0);
+  EXPECT_TRUE(d1s1);
+  EXPECT_TRUE(d1s2);
+  EXPECT_TRUE(d11s1);
+  EXPECT_TRUE(d11s2);
+
+  EXPECT_EQ(d11, FlatTreeTraversalNg::Next(*d1));
+  EXPECT_EQ(d111, FlatTreeTraversalNg::Next(*d11));
+  EXPECT_EQ(d11s1, FlatTreeTraversalNg::Next(*d111));
+  EXPECT_EQ(d1s1, FlatTreeTraversalNg::Next(*d11s1));
+  EXPECT_EQ(d2, FlatTreeTraversalNg::Next(*d1s1));
+  EXPECT_EQ(d14, FlatTreeTraversalNg::Next(*d2));
+  EXPECT_EQ(d11s2, FlatTreeTraversalNg::Next(*d14));
+  EXPECT_EQ(d112, FlatTreeTraversalNg::Next(*d11s2));
+  EXPECT_EQ(d6, FlatTreeTraversalNg::Next(*d112));
+
+  EXPECT_EQ(d112, FlatTreeTraversalNg::Previous(*d6));
+
+  EXPECT_EQ(d11, FlatTreeTraversalNg::Parent(*d111));
+  EXPECT_EQ(d11, FlatTreeTraversalNg::Parent(*d112));
+  EXPECT_EQ(d1s1, FlatTreeTraversalNg::Parent(*d2));
+  EXPECT_EQ(d11s1, FlatTreeTraversalNg::Parent(*d14));
+  EXPECT_EQ(d1s2, FlatTreeTraversalNg::Parent(*d3));
+  EXPECT_EQ(nullptr, FlatTreeTraversalNg::Parent(*d4));
+}
+
+TEST_F(FlatTreeTraversalNgTest, v1SlotInDocumentTree) {
+  const char* main_html =
+      "<div id='parent'>"
+      "<slot>"
+      "<div id='child1'></div>"
+      "<div id='child2'></div>"
+      "</slot>"
+      "</div>";
+
+  SetupDocumentTree(main_html);
+  Element* body = GetDocument().body();
+  Element* parent = body->QuerySelector("#parent");
+  Element* slot = body->QuerySelector("slot");
+  Element* child1 = body->QuerySelector("#child1");
+  Element* child2 = body->QuerySelector("#child2");
+
+  EXPECT_EQ(slot, FlatTreeTraversalNg::FirstChild(*parent));
+  EXPECT_EQ(child1, FlatTreeTraversalNg::FirstChild(*slot));
+  EXPECT_EQ(child2, FlatTreeTraversalNg::NextSibling(*child1));
+  EXPECT_EQ(nullptr, FlatTreeTraversalNg::NextSibling(*child2));
+  EXPECT_EQ(slot, FlatTreeTraversalNg::Parent(*child1));
+  EXPECT_EQ(slot, FlatTreeTraversalNg::Parent(*child2));
+  EXPECT_EQ(parent, FlatTreeTraversalNg::Parent(*slot));
+}
+
+TEST_F(FlatTreeTraversalNgTest, v1FallbackContent) {
+  const char* main_html = "<div id='d1'></div>";
+  const char* shadow_html =
+      "<div id='before'></div>"
+      "<slot><p>fallback content</p></slot>"
+      "<div id='after'></div>";
+
+  SetupDocumentTree(main_html);
+
+  Element* body = GetDocument().body();
+  Element* d1 = body->QuerySelector("#d1");
+
+  AttachOpenShadowRoot(*d1, shadow_html);
+  ShadowRoot* shadow_root = d1->OpenShadowRoot();
+  Element* before = shadow_root->QuerySelector("#before");
+  Element* after = shadow_root->QuerySelector("#after");
+  Element* fallback_content = shadow_root->QuerySelector("p");
+  Element* slot = shadow_root->QuerySelector("slot");
+
+  EXPECT_EQ(before, FlatTreeTraversalNg::FirstChild(*d1));
+  EXPECT_EQ(after, FlatTreeTraversalNg::LastChild(*d1));
+  EXPECT_EQ(slot, FlatTreeTraversalNg::Parent(*fallback_content));
+
+  EXPECT_EQ(slot, FlatTreeTraversalNg::NextSibling(*before));
+  EXPECT_EQ(after, FlatTreeTraversalNg::NextSibling(*slot));
+  EXPECT_EQ(nullptr, FlatTreeTraversalNg::NextSibling(*fallback_content));
+  EXPECT_EQ(nullptr, FlatTreeTraversalNg::NextSibling(*after));
+
+  EXPECT_EQ(slot, FlatTreeTraversalNg::PreviousSibling(*after));
+  EXPECT_EQ(before, FlatTreeTraversalNg::PreviousSibling(*slot));
+  EXPECT_EQ(nullptr, FlatTreeTraversalNg::PreviousSibling(*fallback_content));
+  EXPECT_EQ(nullptr, FlatTreeTraversalNg::PreviousSibling(*before));
+}
+
+TEST_F(FlatTreeTraversalNgTest, v1FallbackContentSkippedInTraversal) {
+  const char* main_html = "<div id='d1'><span></span></div>";
+  const char* shadow_html =
+      "<div id='before'></div>"
+      "<slot><p>fallback content</p></slot>"
+      "<div id='after'></div>";
+
+  SetupDocumentTree(main_html);
+
+  Element* body = GetDocument().body();
+  Element* d1 = body->QuerySelector("#d1");
+  Element* span = body->QuerySelector("span");
+
+  AttachOpenShadowRoot(*d1, shadow_html);
+  ShadowRoot* shadow_root = d1->OpenShadowRoot();
+  Element* before = shadow_root->QuerySelector("#before");
+  Element* after = shadow_root->QuerySelector("#after");
+  Element* fallback_content = shadow_root->QuerySelector("p");
+  Element* slot = shadow_root->QuerySelector("slot");
+
+  EXPECT_EQ(before, FlatTreeTraversalNg::FirstChild(*d1));
+  EXPECT_EQ(after, FlatTreeTraversalNg::LastChild(*d1));
+  EXPECT_EQ(slot, FlatTreeTraversalNg::Parent(*span));
+  EXPECT_EQ(d1, FlatTreeTraversalNg::Parent(*slot));
+
+  EXPECT_EQ(slot, FlatTreeTraversalNg::NextSibling(*before));
+  EXPECT_EQ(after, FlatTreeTraversalNg::NextSibling(*slot));
+  EXPECT_EQ(nullptr, FlatTreeTraversalNg::NextSibling(*after));
+
+  EXPECT_EQ(slot, FlatTreeTraversalNg::PreviousSibling(*after));
+  EXPECT_EQ(before, FlatTreeTraversalNg::PreviousSibling(*slot));
+  EXPECT_EQ(nullptr, FlatTreeTraversalNg::PreviousSibling(*before));
+
+  EXPECT_EQ(nullptr, FlatTreeTraversalNg::Parent(*fallback_content));
+  EXPECT_EQ(nullptr, FlatTreeTraversalNg::NextSibling(*fallback_content));
+  EXPECT_EQ(nullptr, FlatTreeTraversalNg::PreviousSibling(*fallback_content));
+}
+
+TEST_F(FlatTreeTraversalNgTest, v1AllFallbackContent) {
+  const char* main_html = "<div id='d1'></div>";
+  const char* shadow_html =
+      "<slot name='a'><p id='x'>fallback content X</p></slot>"
+      "<slot name='b'><p id='y'>fallback content Y</p></slot>"
+      "<slot name='c'><p id='z'>fallback content Z</p></slot>";
+
+  SetupDocumentTree(main_html);
+
+  Element* body = GetDocument().body();
+  Element* d1 = body->QuerySelector("#d1");
+
+  AttachOpenShadowRoot(*d1, shadow_html);
+  ShadowRoot* shadow_root = d1->OpenShadowRoot();
+  Element* slot_a = shadow_root->QuerySelector("slot[name=a]");
+  Element* slot_b = shadow_root->QuerySelector("slot[name=b]");
+  Element* slot_c = shadow_root->QuerySelector("slot[name=c]");
+  Element* fallback_x = shadow_root->QuerySelector("#x");
+  Element* fallback_y = shadow_root->QuerySelector("#y");
+  Element* fallback_z = shadow_root->QuerySelector("#z");
+
+  EXPECT_EQ(slot_a, FlatTreeTraversalNg::FirstChild(*d1));
+  EXPECT_EQ(slot_c, FlatTreeTraversalNg::LastChild(*d1));
+
+  EXPECT_EQ(fallback_x, FlatTreeTraversalNg::FirstChild(*slot_a));
+  EXPECT_EQ(fallback_y, FlatTreeTraversalNg::FirstChild(*slot_b));
+  EXPECT_EQ(fallback_z, FlatTreeTraversalNg::FirstChild(*slot_c));
+
+  EXPECT_EQ(slot_a, FlatTreeTraversalNg::Parent(*fallback_x));
+  EXPECT_EQ(slot_b, FlatTreeTraversalNg::Parent(*fallback_y));
+  EXPECT_EQ(slot_c, FlatTreeTraversalNg::Parent(*fallback_z));
+  EXPECT_EQ(d1, FlatTreeTraversalNg::Parent(*slot_a));
+
+  EXPECT_EQ(nullptr, FlatTreeTraversalNg::NextSibling(*fallback_x));
+  EXPECT_EQ(nullptr, FlatTreeTraversalNg::NextSibling(*fallback_y));
+  EXPECT_EQ(nullptr, FlatTreeTraversalNg::NextSibling(*fallback_z));
+
+  EXPECT_EQ(nullptr, FlatTreeTraversalNg::PreviousSibling(*fallback_z));
+  EXPECT_EQ(nullptr, FlatTreeTraversalNg::PreviousSibling(*fallback_y));
+  EXPECT_EQ(nullptr, FlatTreeTraversalNg::PreviousSibling(*fallback_x));
+}
+
+}  // namespace blink
diff --git a/third_party/WebKit/Source/core/editing/EditingUtilities.cpp b/third_party/WebKit/Source/core/editing/EditingUtilities.cpp
index 22ee4df..5405880 100644
--- a/third_party/WebKit/Source/core/editing/EditingUtilities.cpp
+++ b/third_party/WebKit/Source/core/editing/EditingUtilities.cpp
@@ -1089,6 +1089,14 @@
   return non_breaking_space_string;
 }
 
+String RepeatString(const String& string, unsigned count) {
+  StringBuilder builder;
+  builder.ReserveCapacity(string.length() * count);
+  for (unsigned counter = 0; counter < count; ++counter)
+    builder.Append(string);
+  return builder.ToString();
+}
+
 // FIXME: need to dump this
 static bool IsSpecialHTMLElement(const Node& n) {
   if (!n.IsHTMLElement())
diff --git a/third_party/WebKit/Source/core/editing/EditingUtilities.h b/third_party/WebKit/Source/core/editing/EditingUtilities.h
index 8394e9d..471b4e9 100644
--- a/third_party/WebKit/Source/core/editing/EditingUtilities.h
+++ b/third_party/WebKit/Source/core/editing/EditingUtilities.h
@@ -424,6 +424,8 @@
                                       bool should_emit_nbs_pbefore_end);
 const String& NonBreakingSpaceString();
 
+CORE_EXPORT String RepeatString(const String&, unsigned);
+
 // -------------------------------------------------------------------------
 // Distance calculation functions
 // -------------------------------------------------------------------------
diff --git a/third_party/WebKit/Source/core/editing/EditingUtilitiesTest.cpp b/third_party/WebKit/Source/core/editing/EditingUtilitiesTest.cpp
index f88b38b0..588cb8a 100644
--- a/third_party/WebKit/Source/core/editing/EditingUtilitiesTest.cpp
+++ b/third_party/WebKit/Source/core/editing/EditingUtilitiesTest.cpp
@@ -121,6 +121,13 @@
   EXPECT_FALSE(IsEditablePosition(Position(table, 0)));
 }
 
+TEST_F(EditingUtilitiesTest, RepeatString) {
+  EXPECT_EQ("", RepeatString("xyz", 0));
+  EXPECT_EQ("xyz", RepeatString("xyz", 1));
+  EXPECT_EQ("xyzxyz", RepeatString("xyz", 2));
+  EXPECT_EQ("xyzxyzxyz", RepeatString("xyz", 3));
+}
+
 TEST_F(EditingUtilitiesTest, tableElementJustBefore) {
   const char* body_content =
       "<div contenteditable id=host><table "
diff --git a/third_party/WebKit/Source/core/editing/EphemeralRange.cpp b/third_party/WebKit/Source/core/editing/EphemeralRange.cpp
index 4e4dd1a5..a4611537 100644
--- a/third_party/WebKit/Source/core/editing/EphemeralRange.cpp
+++ b/third_party/WebKit/Source/core/editing/EphemeralRange.cpp
@@ -160,6 +160,30 @@
 }
 #endif
 
+#ifndef NDEBUG
+
+template <typename Strategy>
+void EphemeralRangeTemplate<Strategy>::ShowTreeForThis() const {
+  if (IsNull()) {
+    LOG(INFO) << "<null range>" << std::endl;
+    return;
+  }
+  LOG(INFO) << std::endl
+            << StartPosition()
+                   .AnchorNode()
+                   ->ToMarkedTreeString(StartPosition().AnchorNode(), "S",
+                                        EndPosition().AnchorNode(), "E")
+                   .Utf8()
+                   .data()
+            << "start: "
+            << StartPosition().ToAnchorTypeAndOffsetString().Utf8().data()
+            << std::endl
+            << "end: "
+            << EndPosition().ToAnchorTypeAndOffsetString().Utf8().data();
+}
+
+#endif
+
 Range* CreateRange(const EphemeralRange& range) {
   if (range.IsNull())
     return nullptr;
diff --git a/third_party/WebKit/Source/core/editing/EphemeralRange.h b/third_party/WebKit/Source/core/editing/EphemeralRange.h
index ae4b6a13..b3416eb 100644
--- a/third_party/WebKit/Source/core/editing/EphemeralRange.h
+++ b/third_party/WebKit/Source/core/editing/EphemeralRange.h
@@ -122,6 +122,10 @@
   static EphemeralRangeTemplate<Strategy> RangeOfContents(
       const Node& /* node */);
 
+#ifndef NDEBUG
+  void ShowTreeForThis() const;
+#endif
+
  private:
   bool IsValid() const;
 
diff --git a/third_party/WebKit/Source/core/editing/SelectionModifier.cpp b/third_party/WebKit/Source/core/editing/SelectionModifier.cpp
index 1018a73d..01485fec 100644
--- a/third_party/WebKit/Source/core/editing/SelectionModifier.cpp
+++ b/third_party/WebKit/Source/core/editing/SelectionModifier.cpp
@@ -139,7 +139,7 @@
 // handle base/extent don't match to start/end, e.g. granularity != character,
 // and start/end adjustment in |visibleSelection::validate()| for range
 // selection.
-static SelectionInDOMTree PrepareToExtendSeelction(
+static SelectionInDOMTree PrepareToExtendSelection(
     const VisibleSelection& visible_selection,
     SelectionModifyDirection direction) {
   if (visible_selection.Start().IsNull())
@@ -590,7 +590,7 @@
 
   if (alter == SelectionModifyAlteration::kExtend) {
     selection_ =
-        CreateVisibleSelection(PrepareToExtendSeelction(selection_, direction));
+        CreateVisibleSelection(PrepareToExtendSelection(selection_, direction));
   }
 
   bool was_range = selection_.IsRange();
@@ -719,7 +719,7 @@
       GetFrame()->GetDocument()->Lifecycle());
 
   if (alter == SelectionModifyAlteration::kExtend) {
-    selection_ = CreateVisibleSelection(PrepareToExtendSeelction(
+    selection_ = CreateVisibleSelection(PrepareToExtendSelection(
         selection_, direction == SelectionModifyVerticalDirection::kUp
                         ? SelectionModifyDirection::kBackward
                         : SelectionModifyDirection::kForward));
diff --git a/third_party/WebKit/Source/core/editing/iterators/SimplifiedBackwardsTextIterator.cpp b/third_party/WebKit/Source/core/editing/iterators/SimplifiedBackwardsTextIterator.cpp
index ea8ecdf5..e198c73 100644
--- a/third_party/WebKit/Source/core/editing/iterators/SimplifiedBackwardsTextIterator.cpp
+++ b/third_party/WebKit/Source/core/editing/iterators/SimplifiedBackwardsTextIterator.cpp
@@ -66,7 +66,8 @@
     SimplifiedBackwardsTextIteratorAlgorithm(
         const EphemeralRangeTemplate<Strategy>& range,
         const TextIteratorBehavior& behavior)
-    : node_(nullptr),
+    : behavior_(behavior),
+      node_(nullptr),
       offset_(0),
       handled_node_(false),
       handled_children_(false),
@@ -82,9 +83,7 @@
       single_character_buffer_(0),
       have_passed_start_node_(false),
       should_handle_first_letter_(false),
-      stops_on_form_controls_(behavior.StopsOnFormControls()),
-      should_stop_(false),
-      emits_original_text_(false) {
+      should_stop_(false) {
   Node* start_node = range.StartPosition().AnchorNode();
   if (!start_node)
     return;
@@ -147,7 +146,7 @@
   if (should_stop_)
     return;
 
-  if (stops_on_form_controls_ &&
+  if (behavior_.StopsOnFormControls() &&
       HTMLFormControlElement::EnclosingFormControlElement(node_)) {
     should_stop_ = true;
     return;
@@ -331,7 +330,7 @@
   // We can use a linefeed in place of a tab because this simple iterator is
   // only used to find boundaries, not actual content. A linefeed breaks words,
   // sentences, and paragraphs.
-  if (TextIterator::ShouldEmitNewlineForNode(node_, emits_original_text_) ||
+  if (TextIterator::ShouldEmitNewlineForNode(node_, false) ||
       TextIterator::ShouldEmitNewlineAfterNode(*node_) ||
       TextIterator::ShouldEmitTabBeforeNode(node_)) {
     unsigned index = Strategy::Index(*node_);
@@ -345,7 +344,7 @@
 
 template <typename Strategy>
 void SimplifiedBackwardsTextIteratorAlgorithm<Strategy>::ExitNode() {
-  if (TextIterator::ShouldEmitNewlineForNode(node_, emits_original_text_) ||
+  if (TextIterator::ShouldEmitNewlineForNode(node_, false) ||
       TextIterator::ShouldEmitNewlineBeforeNode(*node_) ||
       TextIterator::ShouldEmitTabBeforeNode(node_)) {
     // The start of this emitted range is wrong. Ensuring correctness would
diff --git a/third_party/WebKit/Source/core/editing/iterators/SimplifiedBackwardsTextIterator.h b/third_party/WebKit/Source/core/editing/iterators/SimplifiedBackwardsTextIterator.h
index c22e2b6..5953dbb4 100644
--- a/third_party/WebKit/Source/core/editing/iterators/SimplifiedBackwardsTextIterator.h
+++ b/third_party/WebKit/Source/core/editing/iterators/SimplifiedBackwardsTextIterator.h
@@ -97,6 +97,8 @@
                        int position,
                        int copy_length) const;
 
+  TextIteratorBehavior behavior_;
+
   // Current position, not necessarily of the text being returned, but position
   // as we walk through the DOM tree.
   Member<Node> node_;
@@ -134,15 +136,9 @@
   // Should handle first-letter layoutObject in the next call to handleTextNode.
   bool should_handle_first_letter_;
 
-  // Used when the iteration should stop if form controls are reached.
-  bool stops_on_form_controls_;
-
   // Used when m_stopsOnFormControls is set to determine if the iterator should
   // keep advancing.
   bool should_stop_;
-
-  // Used in pasting inside password field.
-  bool emits_original_text_;
 };
 
 extern template class CORE_EXTERN_TEMPLATE_EXPORT
diff --git a/third_party/WebKit/Source/core/editing/iterators/TextIteratorBehavior.cpp b/third_party/WebKit/Source/core/editing/iterators/TextIteratorBehavior.cpp
index 2e3db819..ecf598e 100644
--- a/third_party/WebKit/Source/core/editing/iterators/TextIteratorBehavior.cpp
+++ b/third_party/WebKit/Source/core/editing/iterators/TextIteratorBehavior.cpp
@@ -60,6 +60,12 @@
 }
 
 TextIteratorBehavior::Builder&
+TextIteratorBehavior::Builder::SetEmitsSmallXForTextSecurity(bool value) {
+  behavior_.values_.bits.emits_small_x_for_text_security = value;
+  return *this;
+}
+
+TextIteratorBehavior::Builder&
 TextIteratorBehavior::Builder::SetEntersOpenShadowRoots(bool value) {
   behavior_.values_.bits.enters_open_shadow_roots = value;
   return *this;
diff --git a/third_party/WebKit/Source/core/editing/iterators/TextIteratorBehavior.h b/third_party/WebKit/Source/core/editing/iterators/TextIteratorBehavior.h
index 6186eee0..bd8f268 100644
--- a/third_party/WebKit/Source/core/editing/iterators/TextIteratorBehavior.h
+++ b/third_party/WebKit/Source/core/editing/iterators/TextIteratorBehavior.h
@@ -39,6 +39,9 @@
   bool EntersOpenShadowRoots() const {
     return values_.bits.enters_open_shadow_roots;
   }
+  bool EmitsSmallXForTextSecurity() const {
+    return values_.bits.emits_small_x_for_text_security;
+  }
   bool EntersTextControls() const { return values_.bits.enters_text_controls; }
   bool ExcludeAutofilledValue() const {
     return values_.bits.exclude_autofilled_value;
@@ -75,6 +78,7 @@
       bool emits_space_for_nbsp : 1;
       bool emits_object_replacement_character : 1;
       bool emits_original_text : 1;
+      bool emits_small_x_for_text_security : 1;
       bool enters_open_shadow_roots : 1;
       bool enters_text_controls : 1;
       bool exclude_autofilled_value : 1;
@@ -103,6 +107,7 @@
   Builder& SetEmitsSpaceForNbsp(bool);
   Builder& SetEmitsObjectReplacementCharacter(bool);
   Builder& SetEmitsOriginalText(bool);
+  Builder& SetEmitsSmallXForTextSecurity(bool);
   Builder& SetEntersOpenShadowRoots(bool);
   Builder& SetEntersTextControls(bool);
   Builder& SetExcludeAutofilledValue(bool);
diff --git a/third_party/WebKit/Source/core/exported/WebAssociatedURLLoaderImpl.cpp b/third_party/WebKit/Source/core/exported/WebAssociatedURLLoaderImpl.cpp
index f8a0588..39b5c9f5 100644
--- a/third_party/WebKit/Source/core/exported/WebAssociatedURLLoaderImpl.cpp
+++ b/third_party/WebKit/Source/core/exported/WebAssociatedURLLoaderImpl.cpp
@@ -34,7 +34,6 @@
 #include <memory>
 #include "core/dom/ContextLifecycleObserver.h"
 #include "core/dom/Document.h"
-#include "core/dom/TaskRunnerHelper.h"
 #include "core/loader/DocumentThreadableLoader.h"
 #include "core/loader/DocumentThreadableLoaderClient.h"
 #include "core/loader/ThreadableLoadingContext.h"
@@ -49,6 +48,8 @@
 #include "platform/wtf/HashSet.h"
 #include "platform/wtf/PtrUtil.h"
 #include "platform/wtf/text/WTFString.h"
+#include "public/platform/Platform.h"
+#include "public/platform/TaskType.h"
 #include "public/platform/WebCORS.h"
 #include "public/platform/WebHTTPHeaderVisitor.h"
 #include "public/platform/WebString.h"
@@ -386,9 +387,13 @@
     }
   }
 
-  scoped_refptr<WebTaskRunner> task_runner = TaskRunnerHelper::Get(
-      TaskType::kUnspecedLoading,
-      observer_ ? ToDocument(observer_->LifecycleContext()) : nullptr);
+  scoped_refptr<WebTaskRunner> task_runner;
+  if (observer_) {
+    task_runner = ToDocument(observer_->LifecycleContext())
+                      ->GetTaskRunner(TaskType::kUnspecedLoading);
+  } else {
+    task_runner = Platform::Current()->CurrentThread()->GetWebTaskRunner();
+  }
   client_ = client;
   client_adapter_ = ClientAdapter::Create(this, client, options_,
                                           request.GetFetchRequestMode(),
diff --git a/third_party/WebKit/Source/core/exported/WebSharedWorkerImpl.cpp b/third_party/WebKit/Source/core/exported/WebSharedWorkerImpl.cpp
index 51943e7c..2a62448 100644
--- a/third_party/WebKit/Source/core/exported/WebSharedWorkerImpl.cpp
+++ b/third_party/WebKit/Source/core/exported/WebSharedWorkerImpl.cpp
@@ -60,6 +60,7 @@
 #include "platform/runtime_enabled_features.h"
 #include "platform/weborigin/KURL.h"
 #include "platform/weborigin/SecurityOrigin.h"
+#include "platform/weborigin/SecurityPolicy.h"
 #include "platform/wtf/Functional.h"
 #include "platform/wtf/PtrUtil.h"
 #include "public/platform/WebContentSettingsClient.h"
@@ -313,6 +314,12 @@
 
   ContentSecurityPolicy* content_security_policy =
       main_script_loader_->ReleaseContentSecurityPolicy();
+  ReferrerPolicy referrer_policy = kReferrerPolicyDefault;
+  if (!main_script_loader_->GetReferrerPolicy().IsNull()) {
+    SecurityPolicy::ReferrerPolicyFromHeaderValue(
+        main_script_loader_->GetReferrerPolicy(),
+        kDoNotSupportReferrerPolicyLegacyKeywords, &referrer_policy);
+  }
   auto worker_settings = std::make_unique<WorkerSettings>(
       shadow_page_->GetDocument()->GetFrame()->GetSettings());
   auto global_scope_creation_params =
@@ -321,8 +328,8 @@
           nullptr /* cached_meta_data */,
           content_security_policy ? content_security_policy->Headers().get()
                                   : nullptr,
-          main_script_loader_->GetReferrerPolicy(), starter_origin,
-          worker_clients, main_script_loader_->ResponseAddressSpace(),
+          referrer_policy, starter_origin, worker_clients,
+          main_script_loader_->ResponseAddressSpace(),
           main_script_loader_->OriginTrialTokens(), std::move(worker_settings),
           kV8CacheOptionsDefault, std::move(pending_interface_provider_));
 
diff --git a/third_party/WebKit/Source/core/exported/WebViewTest.cpp b/third_party/WebKit/Source/core/exported/WebViewTest.cpp
index b92f4e53..1fbf2ad 100644
--- a/third_party/WebKit/Source/core/exported/WebViewTest.cpp
+++ b/third_party/WebKit/Source/core/exported/WebViewTest.cpp
@@ -500,7 +500,7 @@
   SkCanvas canvas(bitmap);
   canvas.clear(kAlphaRed);
 
-  PaintRecordBuilder builder(FloatRect(0, 0, kWidth, kHeight));
+  PaintRecordBuilder builder;
 
   // Paint the root of the main frame in the way that CompositedLayerMapping
   // would.
@@ -4206,6 +4206,40 @@
   EXPECT_EQ(100, size.height);
 }
 
+TEST_P(WebViewTest, PreferredSizeWithGridMinWidth) {
+  WebViewImpl* web_view = web_view_helper_.Initialize();
+  WebURL base_url = URLTestHelpers::ToKURL("http://example.com/");
+  FrameTestHelpers::LoadHTMLString(web_view->MainFrameImpl(),
+                                   R"HTML(<!DOCTYPE html>
+    <body style="margin: 0px;">
+      <div style="display: inline-grid; min-width: 200px;">
+        <div>item</div>
+      </div>
+    </body>
+                                   )HTML",
+                                   base_url);
+
+  WebSize size = web_view->ContentsPreferredMinimumSize();
+  EXPECT_EQ(200, size.width);
+}
+
+TEST_P(WebViewTest, PreferredSizeWithGridMinWidthFlexibleTracks) {
+  WebViewImpl* web_view = web_view_helper_.Initialize();
+  WebURL base_url = URLTestHelpers::ToKURL("http://example.com/");
+  FrameTestHelpers::LoadHTMLString(web_view->MainFrameImpl(),
+                                   R"HTML(<!DOCTYPE html>
+    <body style="margin: 0px;">
+      <div style="display: inline-grid; min-width: 200px; grid-template-columns: 1fr;">
+        <div>item</div>
+      </div>
+    </body>
+                                   )HTML",
+                                   base_url);
+
+  WebSize size = web_view->ContentsPreferredMinimumSize();
+  EXPECT_EQ(200, size.width);
+}
+
 class UnhandledTapWebViewClient : public FrameTestHelpers::TestWebViewClient {
  public:
   void ShowUnhandledTapUIIfNeeded(const WebTappedInfo& tapped_info) override {
diff --git a/third_party/WebKit/Source/core/frame/Deprecation.cpp b/third_party/WebKit/Source/core/frame/Deprecation.cpp
index 9c017227..f3c73b2b 100644
--- a/third_party/WebKit/Source/core/frame/Deprecation.cpp
+++ b/third_party/WebKit/Source/core/frame/Deprecation.cpp
@@ -22,6 +22,20 @@
 
 namespace {
 
+const char chromeLoadTimesNavigationTiming[] =
+    "chrome.loadTimes() is deprecated, instead use standardized API: "
+    "Navigation Timing 2. "
+    "https://www.chromestatus.com/features/5637885046816768.";
+const char chromeLoadTimesNextHopProtocol[] =
+    "chrome.loadTimes() is deprecated, instead use standardized API: "
+    "nextHopProtocol in Navigation Timing 2. "
+    "https://www.chromestatus.com/features/5637885046816768.";
+
+const char chromeLoadTimesPaintTiming[] =
+    "chrome.loadTimes() is deprecated, instead use standardized API: "
+    "Paint Timing. "
+    "https://www.chromestatus.com/features/5637885046816768.";
+
 enum Milestone {
   M60,
   M61,
@@ -615,10 +629,36 @@
       return DeprecatedWebAudioDezippering("BiquadFilterNode.Q");
     case WebFeature::kWebAudioDezipperBiquadFilterNodeGain:
       return DeprecatedWebAudioDezippering("BiquadFilterNode.gain");
-
     case WebFeature::kWebAudioValueSetterIsSetValue:
       return DeprecatedWebAudioValueSetterBehavior();
 
+    case WebFeature::kChromeLoadTimesRequestTime:
+      return chromeLoadTimesNavigationTiming;
+    case WebFeature::kChromeLoadTimesStartLoadTime:
+      return chromeLoadTimesNavigationTiming;
+    case WebFeature::kChromeLoadTimesCommitLoadTime:
+      return chromeLoadTimesNavigationTiming;
+    case WebFeature::kChromeLoadTimesFinishDocumentLoadTime:
+      return chromeLoadTimesNavigationTiming;
+    case WebFeature::kChromeLoadTimesFinishLoadTime:
+      return chromeLoadTimesNavigationTiming;
+    case WebFeature::kChromeLoadTimesFirstPaintTime:
+      return chromeLoadTimesPaintTiming;
+    case WebFeature::kChromeLoadTimesFirstPaintAfterLoadTime:
+      return chromeLoadTimesPaintTiming;
+    case WebFeature::kChromeLoadTimesNavigationType:
+      return chromeLoadTimesNavigationTiming;
+    case WebFeature::kChromeLoadTimesWasFetchedViaSpdy:
+      return chromeLoadTimesNextHopProtocol;
+    case WebFeature::kChromeLoadTimesWasNpnNegotiated:
+      return chromeLoadTimesNextHopProtocol;
+    case WebFeature::kChromeLoadTimesNpnNegotiatedProtocol:
+      return chromeLoadTimesNextHopProtocol;
+    case WebFeature::kChromeLoadTimesWasAlternateProtocolAvailable:
+      return chromeLoadTimesNextHopProtocol;
+    case WebFeature::kChromeLoadTimesConnectionInfo:
+      return chromeLoadTimesNavigationTiming;
+
     // Features that aren't deprecated don't have a deprecation message.
     default:
       return String();
diff --git a/third_party/WebKit/Source/core/frame/LocalFrame.cpp b/third_party/WebKit/Source/core/frame/LocalFrame.cpp
index c24bc7b..ff971b6 100644
--- a/third_party/WebKit/Source/core/frame/LocalFrame.cpp
+++ b/third_party/WebKit/Source/core/frame/LocalFrame.cpp
@@ -787,6 +787,7 @@
 }
 
 scoped_refptr<WebTaskRunner> LocalFrame::GetTaskRunner(TaskType type) {
+  DCHECK(IsMainThread());
   return frame_scheduler_->GetTaskRunner(type);
 }
 
diff --git a/third_party/WebKit/Source/core/frame/LocalFrameView.cpp b/third_party/WebKit/Source/core/frame/LocalFrameView.cpp
index 89ed3b9..4dfd72e 100644
--- a/third_party/WebKit/Source/core/frame/LocalFrameView.cpp
+++ b/third_party/WebKit/Source/core/frame/LocalFrameView.cpp
@@ -5661,7 +5661,8 @@
 }
 
 LayoutUnit LocalFrameView::CaretWidth() const {
-  return LayoutUnit(GetChromeClient()->WindowToViewportScalar(1));
+  return LayoutUnit(
+      std::max<float>(1.0, GetChromeClient()->WindowToViewportScalar(1)));
 }
 
 ScrollbarTheme& LocalFrameView::GetPageScrollbarTheme() const {
diff --git a/third_party/WebKit/Source/core/frame/WebLocalFrameImpl.cpp b/third_party/WebKit/Source/core/frame/WebLocalFrameImpl.cpp
index 372a5bf..894e417 100644
--- a/third_party/WebKit/Source/core/frame/WebLocalFrameImpl.cpp
+++ b/third_party/WebKit/Source/core/frame/WebLocalFrameImpl.cpp
@@ -135,6 +135,7 @@
 #include "core/exported/WebPluginContainerImpl.h"
 #include "core/exported/WebRemoteFrameImpl.h"
 #include "core/exported/WebViewImpl.h"
+#include "core/frame/Deprecation.h"
 #include "core/frame/FrameConsole.h"
 #include "core/frame/LocalDOMWindow.h"
 #include "core/frame/LocalFrameView.h"
@@ -190,7 +191,6 @@
 #include "platform/graphics/GraphicsContext.h"
 #include "platform/graphics/GraphicsLayerClient.h"
 #include "platform/graphics/paint/ClipRecorder.h"
-#include "platform/graphics/paint/DisplayItemCacheSkipper.h"
 #include "platform/graphics/paint/DrawingRecorder.h"
 #include "platform/graphics/paint/PaintRecordBuilder.h"
 #include "platform/graphics/skia/SkiaUtils.h"
@@ -295,10 +295,10 @@
     // The page rect gets scaled and translated, so specify the entire
     // print content area here as the recording rect.
     IntRect bounds(0, 0, printed_page_height_, printed_page_width_);
-    PaintRecordBuilder builder(bounds, &canvas->getMetaData());
+    PaintRecordBuilder builder(&canvas->getMetaData());
     builder.Context().SetPrinting(true);
     builder.Context().BeginRecording(bounds);
-    float scale = SpoolPage(builder.Context(), page_number, bounds);
+    float scale = SpoolPage(builder.Context(), page_number);
     canvas->drawPicture(builder.Context().EndRecording());
     return scale;
   }
@@ -323,13 +323,13 @@
     int total_height = num_pages * (page_size_in_pixels.Height() + 1) - 1;
     IntRect all_pages_rect(0, 0, page_width, total_height);
 
-    PaintRecordBuilder builder(all_pages_rect, &canvas->getMetaData());
+    PaintRecordBuilder builder(&canvas->getMetaData());
     GraphicsContext& context = builder.Context();
     context.SetPrinting(true);
     context.BeginRecording(all_pages_rect);
 
     // Fill the whole background by white.
-    context.FillRect(FloatRect(0, 0, page_width, total_height), Color::kWhite);
+    context.FillRect(all_pages_rect, Color::kWhite);
 
     int current_height = 0;
     for (size_t page_index = 0; page_index < num_pages; page_index++) {
@@ -355,7 +355,7 @@
       context.Save();
       context.ConcatCTM(transform);
 
-      SpoolPage(context, page_index, all_pages_rect);
+      SpoolPage(context, page_index);
 
       context.Restore();
 
@@ -370,9 +370,7 @@
   // instead. Returns the scale to be applied.
   // On Linux, we don't have the problem with NativeTheme, hence we let WebKit
   // do the scaling and ignore the return value.
-  virtual float SpoolPage(GraphicsContext& context,
-                          int page_number,
-                          const IntRect& bounds) {
+  virtual float SpoolPage(GraphicsContext& context, int page_number) {
     IntRect page_rect = page_rects_[page_number];
     float scale = printed_page_width_ / page_rect.Width();
 
@@ -386,16 +384,10 @@
     context.ConcatCTM(transform);
     context.ClipRect(page_rect);
 
-    PaintRecordBuilder builder(bounds, &context.Canvas()->getMetaData(),
-                               &context);
-
-    // The local scope is so that the cache skipper is destroyed before
-    // we call endRecording().
+    PaintRecordBuilder builder(&context.Canvas()->getMetaData(), &context);
+    GetFrame()->View()->PaintContents(builder.Context(),
+                                      kGlobalPaintNormalPhase, page_rect);
     {
-      DisplayItemCacheSkipper skipper(builder.Context());
-      GetFrame()->View()->PaintContents(builder.Context(),
-                                        kGlobalPaintNormalPhase, page_rect);
-
       DrawingRecorder line_boundary_recorder(
           builder.Context(), builder,
           DisplayItem::kPrintedContentDestinationLocations);
@@ -469,16 +461,9 @@
   // Spools the printed page, a subrect of frame(). Skip the scale step.
   // NativeTheme doesn't play well with scaling. Scaling is done browser side
   // instead. Returns the scale to be applied.
-  float SpoolPage(GraphicsContext& context,
-                  int page_number,
-                  const IntRect& bounds) override {
-    PaintRecordBuilder builder(bounds, &context.Canvas()->getMetaData());
-    // The local scope is so that the cache skipper is destroyed before
-    // we call endRecording().
-    {
-      DisplayItemCacheSkipper skipper(builder.Context());
-      plugin_->PrintPage(page_number, builder.Context());
-    }
+  float SpoolPage(GraphicsContext& context, int page_number) override {
+    PaintRecordBuilder builder(&context.Canvas()->getMetaData());
+    plugin_->PrintPage(page_number, builder.Context());
     context.DrawRecord(builder.EndRecording());
 
     return 1.0;
@@ -2479,7 +2464,7 @@
   } else if (metric == "connectionInfo") {
     feature = WebFeature::kChromeLoadTimesConnectionInfo;
   }
-  UseCounter::Count(GetFrame(), feature);
+  Deprecation::CountDeprecation(GetFrame(), feature);
 }
 
 WebFrameScheduler* WebLocalFrameImpl::Scheduler() const {
diff --git a/third_party/WebKit/Source/core/frame/Window.idl b/third_party/WebKit/Source/core/frame/Window.idl
index 144bea7..ec32d77 100644
--- a/third_party/WebKit/Source/core/frame/Window.idl
+++ b/third_party/WebKit/Source/core/frame/Window.idl
@@ -190,8 +190,8 @@
     [MeasureAs=WindowDefaultStatus] attribute DOMString defaultStatus;
     [MeasureAs=WindowDefaultstatus, ImplementedAs=defaultStatus] attribute DOMString defaultstatus;
     [MeasureAs=StyleMedia] readonly attribute StyleMedia styleMedia;
-    [DeprecateAs=GetMatchedCSSRules, LegacyInterfaceTypeChecking] CSSRuleList getMatchedCSSRules([Default=Undefined] optional Element element,
-                                                                                                 [Default=Undefined] optional DOMString? pseudoElement);
+    [RuntimeEnabled=GetMatchedCSSRules, DeprecateAs=GetMatchedCSSRules, LegacyInterfaceTypeChecking] CSSRuleList getMatchedCSSRules([Default=Undefined] optional Element element,
+                                                                                                                                    [Default=Undefined] optional DOMString? pseudoElement);
     [DeprecateAs=PrefixedRequestAnimationFrame] long webkitRequestAnimationFrame(FrameRequestCallback callback);
     [DeprecateAs=PrefixedCancelAnimationFrame, ImplementedAs=cancelAnimationFrame] void webkitCancelAnimationFrame(long id);
     [MeasureAs=PrefixedTransitionEventConstructor] attribute TransitionEventConstructor WebKitTransitionEvent;
diff --git a/third_party/WebKit/Source/core/html/HTMLSlotElement.cpp b/third_party/WebKit/Source/core/html/HTMLSlotElement.cpp
index b8faed46..004b4652 100644
--- a/third_party/WebKit/Source/core/html/HTMLSlotElement.cpp
+++ b/third_party/WebKit/Source/core/html/HTMLSlotElement.cpp
@@ -66,7 +66,7 @@
   return (name.IsNull() || name.IsEmpty()) ? g_empty_atom : name;
 }
 
-const HeapVector<Member<Node>>& HTMLSlotElement::AssignedNodes() {
+const HeapVector<Member<Node>>& HTMLSlotElement::AssignedNodes() const {
   DCHECK(!NeedsDistributionRecalc());
   DCHECK(IsInShadowTree() || assigned_nodes_.IsEmpty());
   return assigned_nodes_;
@@ -135,6 +135,28 @@
   DispatchScopedEvent(event);
 }
 
+Node* HTMLSlotElement::AssignedNodeNextTo(const Node& node) const {
+  DCHECK(SupportsDistribution());
+  // TODO(crbug.com/776656): Assert that assigned_nodes_ is up-to-date.
+  // TODO(crbug.com/776656): Use {node -> index} map to avoid O(N) lookup
+  size_t index = assigned_nodes_.Find(&node);
+  DCHECK(index != WTF::kNotFound);
+  if (index + 1 == assigned_nodes_.size())
+    return nullptr;
+  return assigned_nodes_[index + 1].Get();
+}
+
+Node* HTMLSlotElement::AssignedNodePreviousTo(const Node& node) const {
+  DCHECK(SupportsDistribution());
+  // TODO(crbug.com/776656): Assert that assigned_nodes_ is up-to-date.
+  // TODO(crbug.com/776656): Use {node -> index} map to avoid O(N) lookup
+  size_t index = assigned_nodes_.Find(&node);
+  DCHECK(index != WTF::kNotFound);
+  if (index == 0)
+    return nullptr;
+  return assigned_nodes_[index - 1].Get();
+}
+
 Node* HTMLSlotElement::DistributedNodeNextTo(const Node& node) const {
   DCHECK(SupportsDistribution());
   const auto& it = distributed_indices_.find(&node);
diff --git a/third_party/WebKit/Source/core/html/HTMLSlotElement.h b/third_party/WebKit/Source/core/html/HTMLSlotElement.h
index 013f4f8..afab86d 100644
--- a/third_party/WebKit/Source/core/html/HTMLSlotElement.h
+++ b/third_party/WebKit/Source/core/html/HTMLSlotElement.h
@@ -44,11 +44,18 @@
  public:
   DECLARE_NODE_FACTORY(HTMLSlotElement);
 
-  const HeapVector<Member<Node>>& AssignedNodes();
+  const HeapVector<Member<Node>>& AssignedNodes() const;
   const HeapVector<Member<Node>>& GetDistributedNodes();
   const HeapVector<Member<Node>> assignedNodesForBinding(
       const AssignedNodesOptions&);
 
+  Node* FirstAssignedNode() const {
+    return assigned_nodes_.IsEmpty() ? nullptr : assigned_nodes_.front().Get();
+  }
+  Node* LastAssignedNode() const {
+    return assigned_nodes_.IsEmpty() ? nullptr : assigned_nodes_.back().Get();
+  }
+
   Node* FirstDistributedNode() const {
     DCHECK(SupportsDistribution());
     return distributed_nodes_.IsEmpty() ? nullptr
@@ -60,6 +67,9 @@
                                         : distributed_nodes_.back().Get();
   }
 
+  Node* AssignedNodeNextTo(const Node&) const;
+  Node* AssignedNodePreviousTo(const Node&) const;
+
   Node* DistributedNodeNextTo(const Node&) const;
   Node* DistributedNodePreviousTo(const Node&) const;
 
diff --git a/third_party/WebKit/Source/core/html/ImageData.cpp b/third_party/WebKit/Source/core/html/ImageData.cpp
index 94c8781..c1f33c3 100644
--- a/third_party/WebKit/Source/core/html/ImageData.cpp
+++ b/third_party/WebKit/Source/core/html/ImageData.cpp
@@ -406,6 +406,10 @@
 // intersection is empty or it cannot create the cropped ImageData it returns
 // nullptr. This function leaves the source ImageData intact. When crop_rect
 // covers all the ImageData, a copy of the ImageData is returned.
+// TODO (zakerinasab): crbug.com/774484: As a rule of thumb ImageData belongs to
+// the user and its state should not change unless directly modified by the
+// user. Therefore, we should be able to remove the extra copy and return a
+// "cropped view" on the source ImageData object.
 ImageData* ImageData::CropRect(const IntRect& crop_rect, bool flip_y) {
   IntRect src_rect(IntPoint(), size_);
   const IntRect dst_rect = Intersection(src_rect, crop_rect);
@@ -694,6 +698,13 @@
   return CanvasColorParams(color_space, pixel_format, kNonOpaque);
 }
 
+void ImageData::SwapU16EndiannessForSkColorSpaceXform() {
+  DCHECK(data_u16_);
+  uint16_t* buffer = static_cast<uint16_t*>(data_u16_->BufferBase()->Data());
+  for (unsigned i = 0; i < size_.Area() * 4; i++)
+    *(buffer + i) = WTF::Bswap16(*(buffer + i));
+};
+
 bool ImageData::ImageDataInCanvasColorSettings(
     CanvasColorSpace canvas_color_space,
     CanvasPixelFormat canvas_pixel_format,
@@ -701,72 +712,51 @@
   if (!data_ && !data_u16_ && !data_f32_)
     return false;
 
-  // If canvas and image data are both in the same color space and pixel format
-  // is 8-8-8-8, no conversion is needed.
-  CanvasColorSpace image_data_color_space =
-      ImageData::GetCanvasColorSpace(color_settings_.colorSpace());
-  if (canvas_pixel_format == kRGBA8CanvasPixelFormat &&
-      color_settings_.storageFormat() == kUint8ClampedArrayStorageFormatName) {
-    if (canvas_color_space == image_data_color_space ||
-        ((canvas_color_space == kLegacyCanvasColorSpace ||
-         canvas_color_space == kSRGBCanvasColorSpace) &&
-            (image_data_color_space == kLegacyCanvasColorSpace ||
-             image_data_color_space == kSRGBCanvasColorSpace))) {
-      memcpy(converted_pixels.get(), data_->Data(), data_->length());
-      return true;
-    }
-  }
+  CanvasColorParams dst_color_params =
+      CanvasColorParams(canvas_color_space, canvas_pixel_format, kNonOpaque);
 
-  // Otherwise, color convert the pixels.
   unsigned num_pixels = size_.Width() * size_.Height();
   void* src_data = this->BufferBase()->Data();
   SkColorSpaceXform::ColorFormat src_color_format =
       SkColorSpaceXform::ColorFormat::kRGBA_8888_ColorFormat;
-  if (data_u16_) {
-    // SkColorSpaceXform::apply expects U16 data to be in Big Endian byte
-    // order, while image data is always Little Endian.
-    uint16_t* src_data_u16 = static_cast<uint16_t*>(src_data);
-    for (unsigned i = 0; i < num_pixels * 4; i++)
-      *(src_data_u16 + i) = WTF::Bswap16(*(src_data_u16 + i));
+  if (data_u16_)
     src_color_format = SkColorSpaceXform::ColorFormat::kRGBA_U16_BE_ColorFormat;
-  } else if (data_f32_) {
+  else if (data_f32_)
     src_color_format = SkColorSpaceXform::ColorFormat::kRGBA_F32_ColorFormat;
-  }
 
   sk_sp<SkColorSpace> src_color_space =
-      CanvasColorParams(image_data_color_space,
-                        data_ ? kRGBA8CanvasPixelFormat : kF16CanvasPixelFormat,
-                        kNonOpaque)
-          .GetSkColorSpaceForSkSurfaces();
+      GetCanvasColorParams().GetSkColorSpaceForSkSurfaces();
   sk_sp<SkColorSpace> dst_color_space =
-      CanvasColorParams(canvas_color_space, canvas_pixel_format, kNonOpaque)
-          .GetSkColorSpaceForSkSurfaces();
+      dst_color_params.GetSkColorSpaceForSkSurfaces();
   SkColorSpaceXform::ColorFormat dst_color_format =
       SkColorSpaceXform::ColorFormat::kRGBA_8888_ColorFormat;
   if (canvas_pixel_format == kF16CanvasPixelFormat)
     dst_color_format = SkColorSpaceXform::ColorFormat::kRGBA_F16_ColorFormat;
+
+  if (!src_color_space.get() && !dst_color_space.get() && data_) {
+    memcpy(converted_pixels.get(), data_->Data(), data_->length());
+    return true;
+  }
+  bool conversion_result = false;
+  if (!src_color_space.get())
+    src_color_space = SkColorSpace::MakeSRGB();
+  if (!dst_color_space.get())
+    dst_color_space = SkColorSpace::MakeSRGB();
   std::unique_ptr<SkColorSpaceXform> xform =
       SkColorSpaceXform::New(src_color_space.get(), dst_color_space.get());
-
-  bool conversion_result =
+  // SkColorSpaceXform only accepts big-endian integers when source data is
+  // uint16. Since ImageData is always little-endian, we need to convert back
+  // and forth before passing uint16 data to SkColorSpaceXform::apply().
+  if (data_u16_)
+    this->SwapU16EndiannessForSkColorSpaceXform();
+  conversion_result =
       xform->apply(dst_color_format, converted_pixels.get(), src_color_format,
                    src_data, num_pixels, SkAlphaType::kUnpremul_SkAlphaType);
-  if (data_u16_) {
-    uint16_t* src_data_u16 = static_cast<uint16_t*>(src_data);
-    for (unsigned i = 0; i < num_pixels * 4; i++)
-      *(src_data_u16 + i) = WTF::Bswap16(*(src_data_u16 + i));
-  };
+  if (data_u16_)
+    this->SwapU16EndiannessForSkColorSpaceXform();
   return conversion_result;
 }
 
-bool ImageData::ImageDataInCanvasColorSettings(
-    const CanvasColorParams& canvas_color_params,
-    std::unique_ptr<uint8_t[]>& converted_pixels) {
-  return ImageDataInCanvasColorSettings(canvas_color_params.ColorSpace(),
-                                        canvas_color_params.PixelFormat(),
-                                        converted_pixels);
-}
-
 void ImageData::Trace(blink::Visitor* visitor) {
   visitor->Trace(data_);
   visitor->Trace(data_u16_);
@@ -795,6 +785,13 @@
   ImageDataStorageFormat storage_format =
       GetImageDataStorageFormat(color_settings_.storageFormat());
 
+  // TODO (zakerinasab): crbug.com/779570
+  // The default color space for ImageData with U16/F32 data should be
+  // extended-srgb color space. It is temporarily set to linear-rgb, which is
+  // not correct, but fixes crbug.com/779419.
+  if (color_settings_.colorSpace() == kLegacyCanvasColorSpaceName)
+    color_settings_.setColorSpace(kSRGBCanvasColorSpaceName);
+
   switch (storage_format) {
     case kUint8ClampedArrayStorageFormat:
       DCHECK(data->GetType() ==
diff --git a/third_party/WebKit/Source/core/html/ImageData.h b/third_party/WebKit/Source/core/html/ImageData.h
index 1ebbda9..50521ba7 100644
--- a/third_party/WebKit/Source/core/html/ImageData.h
+++ b/third_party/WebKit/Source/core/html/ImageData.h
@@ -60,12 +60,6 @@
   kParamData = 1 << 3,
 };
 
-enum ImageDataStorageFormat {
-  kUint8ClampedArrayStorageFormat,
-  kUint16ArrayStorageFormat,
-  kFloat32ArrayStorageFormat,
-};
-
 constexpr const char* kUint8ClampedArrayStorageFormatName = "uint8";
 constexpr const char* kUint16ArrayStorageFormatName = "uint16";
 constexpr const char* kFloat32ArrayStorageFormatName = "float32";
@@ -141,8 +135,6 @@
   bool ImageDataInCanvasColorSettings(CanvasColorSpace,
                                       CanvasPixelFormat,
                                       std::unique_ptr<uint8_t[]>&);
-  bool ImageDataInCanvasColorSettings(const CanvasColorParams&,
-                                      std::unique_ptr<uint8_t[]>&);
 
   // ImageBitmapSource implementation
   IntSize BitmapSourceSize() const override { return size_; }
@@ -198,6 +190,8 @@
 
   static DOMFloat32Array* ConvertFloat16ArrayToFloat32Array(const uint16_t*,
                                                             unsigned);
+
+  void SwapU16EndiannessForSkColorSpaceXform();
 };
 
 }  // namespace blink
diff --git a/third_party/WebKit/Source/core/html/ImageDataTest.cpp b/third_party/WebKit/Source/core/html/ImageDataTest.cpp
index eb26b54..4fb1742 100644
--- a/third_party/WebKit/Source/core/html/ImageDataTest.cpp
+++ b/third_party/WebKit/Source/core/html/ImageDataTest.cpp
@@ -7,6 +7,8 @@
 #include "core/dom/ExceptionCode.h"
 #include "platform/geometry/IntSize.h"
 #include "platform/graphics/ColorCorrectionTestUtils.h"
+#include "platform/testing/RuntimeEnabledFeaturesTestHelpers.h"
+#include "platform/wtf/ByteSwap.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "third_party/skia/include/core/SkColorSpaceXform.h"
 
@@ -43,12 +45,19 @@
 // format. This function is used in BaseRenderingContext2D::getImageData.
 TEST_F(ImageDataTest,
        TestConvertPixelsFromCanvasPixelFormatToImageDataStorageFormat) {
+  // Enable experimental canvas features for this test.
+  ScopedExperimentalCanvasFeaturesForTest experimental_canvas_features(true);
+
   // Source pixels in RGBA32
   unsigned char rgba32_pixels[] = {255, 0,   0,   255,  // Red
                                    0,   0,   0,   0,    // Transparent
                                    255, 192, 128, 64,   // Decreasing values
                                    93,  117, 205, 11};  // Random values
   const unsigned kNumColorComponents = 16;
+  float f32_pixels[kNumColorComponents];
+  for (unsigned i = 0; i < kNumColorComponents; i++)
+    f32_pixels[i] = rgba32_pixels[i] / 255.0;
+  const unsigned kNumPixels = kNumColorComponents / 4;
   // Source pixels in F16
   unsigned char f16_pixels[kNumColorComponents * 2];
 
@@ -81,158 +90,51 @@
 
   // Uint16 is not supported as the storage format for ImageData created from a
   // canvas, so this conversion is neither implemented nor tested here.
-  bool test_passed = true;
-  DOMArrayBufferView* data = nullptr;
-  DOMUint8ClampedArray* data_u8 = nullptr;
-  DOMFloat32Array* data_f32 = nullptr;
 
   // Testing kRGBA8CanvasPixelFormat -> kUint8ClampedArrayStorageFormat
-  data = ImageData::ConvertPixelsFromCanvasPixelFormatToImageDataStorageFormat(
-      contents_rgba32, kRGBA8CanvasPixelFormat,
-      kUint8ClampedArrayStorageFormat);
+  DOMArrayBufferView* data =
+      ImageData::ConvertPixelsFromCanvasPixelFormatToImageDataStorageFormat(
+          contents_rgba32, kRGBA8CanvasPixelFormat,
+          kUint8ClampedArrayStorageFormat);
   DCHECK(data->GetType() == DOMArrayBufferView::ViewType::kTypeUint8Clamped);
-  data_u8 = const_cast<DOMUint8ClampedArray*>(
-      static_cast<const DOMUint8ClampedArray*>(data));
-  DCHECK(data_u8);
-  for (unsigned i = 0; i < kNumColorComponents; i++) {
-    if (data_u8->Item(i) != rgba32_pixels[i]) {
-      test_passed = false;
-      break;
-    }
-  }
-  EXPECT_TRUE(test_passed);
+  ColorCorrectionTestUtils::CompareColorCorrectedPixels(
+      data->BaseAddress(), rgba32_pixels, kNumPixels,
+      kUint8ClampedArrayStorageFormat, kAlphaUnmultiplied,
+      kNoUnpremulRoundTripTolerance);
 
   // Testing kRGBA8CanvasPixelFormat -> kFloat32ArrayStorageFormat
   data = ImageData::ConvertPixelsFromCanvasPixelFormatToImageDataStorageFormat(
       contents2rgba32, kRGBA8CanvasPixelFormat, kFloat32ArrayStorageFormat);
   DCHECK(data->GetType() == DOMArrayBufferView::ViewType::kTypeFloat32);
-  data_f32 =
-      const_cast<DOMFloat32Array*>(static_cast<const DOMFloat32Array*>(data));
-  DCHECK(data_f32);
-  for (unsigned i = 0; i < kNumColorComponents; i++) {
-    if (!ColorCorrectionTestUtils::IsNearlyTheSame(data_f32->Item(i),
-                                                   rgba32_pixels[i] / 255.0)) {
-      test_passed = false;
-      break;
-    }
-  }
-  EXPECT_TRUE(test_passed);
+  ColorCorrectionTestUtils::CompareColorCorrectedPixels(
+      data->BaseAddress(), f32_pixels, kNumPixels, kFloat32ArrayStorageFormat,
+      kAlphaUnmultiplied, kUnpremulRoundTripTolerance);
 
   // Testing kF16CanvasPixelFormat -> kUint8ClampedArrayStorageFormat
   data = ImageData::ConvertPixelsFromCanvasPixelFormatToImageDataStorageFormat(
       contents_f16, kF16CanvasPixelFormat, kUint8ClampedArrayStorageFormat);
   DCHECK(data->GetType() == DOMArrayBufferView::ViewType::kTypeUint8Clamped);
-  data_u8 = const_cast<DOMUint8ClampedArray*>(
-      static_cast<const DOMUint8ClampedArray*>(data));
-  DCHECK(data_u8);
-  for (unsigned i = 0; i < kNumColorComponents; i++) {
-    if (!ColorCorrectionTestUtils::IsNearlyTheSame(data_u8->Item(i),
-                                                   rgba32_pixels[i])) {
-      test_passed = false;
-      break;
-    }
-  }
-  EXPECT_TRUE(test_passed);
+  ColorCorrectionTestUtils::CompareColorCorrectedPixels(
+      data->BaseAddress(), rgba32_pixels, kNumPixels,
+      kUint8ClampedArrayStorageFormat, kAlphaUnmultiplied,
+      kNoUnpremulRoundTripTolerance);
 
   // Testing kF16CanvasPixelFormat -> kFloat32ArrayStorageFormat
   data = ImageData::ConvertPixelsFromCanvasPixelFormatToImageDataStorageFormat(
       contents_f16, kF16CanvasPixelFormat, kFloat32ArrayStorageFormat);
   DCHECK(data->GetType() == DOMArrayBufferView::ViewType::kTypeFloat32);
-  data_f32 =
-      const_cast<DOMFloat32Array*>(static_cast<const DOMFloat32Array*>(data));
-  DCHECK(data_f32);
-  for (unsigned i = 0; i < kNumColorComponents; i++) {
-    if (!ColorCorrectionTestUtils::IsNearlyTheSame(data_f32->Item(i),
-                                                   rgba32_pixels[i] / 255.0)) {
-      test_passed = false;
-      break;
-    }
-  }
-  EXPECT_TRUE(test_passed);
-}
-
-bool ConvertPixelsToColorSpaceAndPixelFormatForTest(
-    DOMArrayBufferView* data_array,
-    CanvasColorSpace src_color_space,
-    CanvasColorSpace dst_color_space,
-    CanvasPixelFormat dst_pixel_format,
-    std::unique_ptr<uint8_t[]>& converted_pixels) {
-  // Setting SkColorSpaceXform::apply parameters
-  SkColorSpaceXform::ColorFormat src_color_format =
-      SkColorSpaceXform::kRGBA_8888_ColorFormat;
-
-  unsigned data_length = data_array->byteLength() / data_array->TypeSize();
-  unsigned num_pixels = data_length / 4;
-  DOMUint8ClampedArray* u8_array = nullptr;
-  DOMUint16Array* u16_array = nullptr;
-  DOMFloat32Array* f32_array = nullptr;
-  void* src_data = nullptr;
-
-  switch (data_array->GetType()) {
-    case ArrayBufferView::ViewType::kTypeUint8Clamped:
-      u8_array = const_cast<DOMUint8ClampedArray*>(
-          static_cast<const DOMUint8ClampedArray*>(data_array));
-      src_data = static_cast<void*>(u8_array->Data());
-      break;
-
-    case ArrayBufferView::ViewType::kTypeUint16:
-      u16_array = const_cast<DOMUint16Array*>(
-          static_cast<const DOMUint16Array*>(data_array));
-      src_color_format =
-          SkColorSpaceXform::ColorFormat::kRGBA_U16_BE_ColorFormat;
-      src_data = static_cast<void*>(u16_array->Data());
-      break;
-
-    case ArrayBufferView::ViewType::kTypeFloat32:
-      f32_array = const_cast<DOMFloat32Array*>(
-          static_cast<const DOMFloat32Array*>(data_array));
-      src_color_format = SkColorSpaceXform::kRGBA_F32_ColorFormat;
-      src_data = static_cast<void*>(f32_array->Data());
-      break;
-    default:
-      NOTREACHED();
-      return false;
-  }
-
-  SkColorSpaceXform::ColorFormat dst_color_format =
-      SkColorSpaceXform::ColorFormat::kRGBA_8888_ColorFormat;
-  if (dst_pixel_format == kF16CanvasPixelFormat)
-    dst_color_format = SkColorSpaceXform::ColorFormat::kRGBA_F16_ColorFormat;
-
-  sk_sp<SkColorSpace> src_sk_color_space = nullptr;
-  if (u8_array) {
-    src_sk_color_space =
-        CanvasColorParams(src_color_space, kRGBA8CanvasPixelFormat, kNonOpaque)
-            .GetSkColorSpaceForSkSurfaces();
-  } else {
-    src_sk_color_space =
-        CanvasColorParams(src_color_space, kF16CanvasPixelFormat, kNonOpaque)
-            .GetSkColorSpaceForSkSurfaces();
-  }
-
-  sk_sp<SkColorSpace> dst_sk_color_space =
-      CanvasColorParams(dst_color_space, dst_pixel_format, kNonOpaque)
-          .GetSkColorSpaceForSkSurfaces();
-
-  // When the input dataArray is in Uint16, we normally should convert the
-  // values from Little Endian to Big Endian before passing the buffer to
-  // SkColorSpaceXform::apply. However, in this test scenario we are creating
-  // the Uin16 dataArray by multiplying a Uint8Clamped array members by 257,
-  // hence the Big Endian and Little Endian representations are the same.
-
-  std::unique_ptr<SkColorSpaceXform> xform = SkColorSpaceXform::New(
-      src_sk_color_space.get(), dst_sk_color_space.get());
-
-  if (!xform->apply(dst_color_format, converted_pixels.get(), src_color_format,
-                    src_data, num_pixels, kUnpremul_SkAlphaType))
-    return false;
-  return true;
+  ColorCorrectionTestUtils::CompareColorCorrectedPixels(
+      data->BaseAddress(), f32_pixels, kNumPixels, kFloat32ArrayStorageFormat,
+      kAlphaUnmultiplied, kUnpremulRoundTripTolerance);
 }
 
 // This test verifies the correct behavior of ImageData member function used
 // to convert image data from image data storage format to canvas pixel format.
 // This function is used in BaseRenderingContext2D::putImageData.
 TEST_F(ImageDataTest, TestGetImageDataInCanvasColorSettings) {
+  // Enable experimental canvas features for this test.
+  ScopedExperimentalCanvasFeaturesForTest experimental_canvas_features(true);
+
   unsigned num_image_data_color_spaces = 3;
   CanvasColorSpace image_data_color_spaces[] = {
       kSRGBCanvasColorSpace, kRec2020CanvasColorSpace, kP3CanvasColorSpace,
@@ -249,6 +151,7 @@
       kSRGBCanvasColorSpace, kSRGBCanvasColorSpace, kRec2020CanvasColorSpace,
       kP3CanvasColorSpace,
   };
+
   CanvasPixelFormat canvas_pixel_formats[] = {
       kRGBA8CanvasPixelFormat, kF16CanvasPixelFormat, kF16CanvasPixelFormat,
       kF16CanvasPixelFormat,
@@ -263,7 +166,7 @@
   // ImageData::convertPixelsFromCanvasPixelFormatToImageDataStorageFormat().
   // We expect to get the same image data as we started with.
 
-  // Source pixels in RGBA32
+  // Source pixels in RGBA32, unpremul
   uint8_t u8_pixels[] = {255, 0,   0,   255,  // Red
                          0,   0,   0,   0,    // Transparent
                          255, 192, 128, 64,   // Decreasing values
@@ -328,15 +231,16 @@
           ImageData::CreateForTest(IntSize(2, 2), data_array, &color_settings);
 
       for (unsigned k = 0; k < num_canvas_color_settings; k++) {
-        unsigned output_length =
-            (canvas_pixel_formats[k] == kRGBA8CanvasPixelFormat)
-                ? data_length
-                : data_length * 2;
         // Convert the original data used to create ImageData to the
         // canvas color space and canvas pixel format.
-        EXPECT_TRUE(ConvertPixelsToColorSpaceAndPixelFormatForTest(
-            data_array, image_data_color_spaces[i], canvas_color_spaces[k],
-            canvas_pixel_formats[k], pixels_converted_manually));
+        EXPECT_TRUE(
+            ColorCorrectionTestUtils::
+                ConvertPixelsToColorSpaceAndPixelFormatForTest(
+                    data_array->BaseAddress(), data_length,
+                    image_data_color_spaces[i], image_data_storage_formats[j],
+                    canvas_color_spaces[k], canvas_pixel_formats[k],
+                    pixels_converted_manually,
+                    SkColorSpaceXform::ColorFormat::kRGBA_F16_ColorFormat));
 
         // Convert the image data to the color settings of the canvas.
         EXPECT_TRUE(image_data->ImageDataInCanvasColorSettings(
@@ -344,9 +248,13 @@
             pixels_converted_in_image_data));
 
         // Compare the converted pixels
-        EXPECT_EQ(0,
-                  memcmp(pixels_converted_manually.get(),
-                         pixels_converted_in_image_data.get(), output_length));
+        ColorCorrectionTestUtils::CompareColorCorrectedPixels(
+            pixels_converted_manually.get(),
+            pixels_converted_in_image_data.get(), image_data->Size().Area(),
+            (canvas_pixel_formats[k] == kRGBA8CanvasPixelFormat)
+                ? kUint8ClampedArrayStorageFormat
+                : kUint16ArrayStorageFormat,
+            kAlphaUnmultiplied, kUnpremulRoundTripTolerance);
       }
     }
   }
@@ -356,6 +264,9 @@
 
 // This test examines ImageData::CropRect()
 TEST_F(ImageDataTest, TestCropRect) {
+  // Enable experimental canvas features for this test.
+  ScopedExperimentalCanvasFeaturesForTest experimental_canvas_features(true);
+
   const int num_image_data_storage_formats = 3;
   ImageDataStorageFormat image_data_storage_formats[] = {
       kUint8ClampedArrayStorageFormat, kUint16ArrayStorageFormat,
diff --git a/third_party/WebKit/Source/core/html/TextMetrics.cpp b/third_party/WebKit/Source/core/html/TextMetrics.cpp
index 9088af5..32a870e 100644
--- a/third_party/WebKit/Source/core/html/TextMetrics.cpp
+++ b/third_party/WebKit/Source/core/html/TextMetrics.cpp
@@ -61,24 +61,21 @@
       TextRun::kAllowTrailingExpansion | TextRun::kForbidLeadingExpansion,
       direction, false);
   text_run.SetNormalizeSpace(true);
-  FloatRect text_bounds = font.SelectionRectForText(
-      text_run, FloatPoint(), font.GetFontDescription().ComputedSize(),
-      /* from */ 0, /* to */ -1);
-
+  FloatRect bbox = font.BoundingBox(text_run);
   const FontMetrics& font_metrics = font_data->GetFontMetrics();
 
   // x direction
-  width_ = font.Width(text_run);
+  width_ = bbox.Width();
 
   float dx = 0.0f;
   if (align == kCenterTextAlign)
     dx = -width_ / 2.0f;
   else if (align == kRightTextAlign ||
            (align == kStartTextAlign && direction == TextDirection::kRtl) ||
-           (align == kEndTextAlign && direction == TextDirection::kRtl))
+           (align == kEndTextAlign && direction != TextDirection::kRtl))
     dx = -width_;
-  actual_bounding_box_left_ = -text_bounds.X() - dx;
-  actual_bounding_box_right_ = text_bounds.MaxX() + dx;
+  actual_bounding_box_left_ = -bbox.X() - dx;
+  actual_bounding_box_right_ = bbox.MaxX() + dx;
 
   // y direction
   const float ascent = font_metrics.FloatAscent();
@@ -87,8 +84,8 @@
 
   font_bounding_box_ascent_ = ascent - baseline_y;
   font_bounding_box_descent_ = descent + baseline_y;
-  actual_bounding_box_ascent_ = ascent - baseline_y;
-  actual_bounding_box_descent_ = descent + baseline_y;
+  actual_bounding_box_ascent_ = -bbox.Y() - baseline_y;
+  actual_bounding_box_descent_ = bbox.MaxY() + baseline_y;
 
   // it's not clear where the baseline for the em rect is.
   // We could try to render a letter that has 1em height and try to figure out.
diff --git a/third_party/WebKit/Source/core/html/canvas/CanvasRenderingContext.cpp b/third_party/WebKit/Source/core/html/canvas/CanvasRenderingContext.cpp
index bc3034d..41ca265b 100644
--- a/third_party/WebKit/Source/core/html/canvas/CanvasRenderingContext.cpp
+++ b/third_party/WebKit/Source/core/html/canvas/CanvasRenderingContext.cpp
@@ -37,31 +37,26 @@
     CanvasRenderingContextHost* host,
     const CanvasContextCreationAttributes& attrs)
     : host_(host),
-      color_params_(kLegacyCanvasColorSpace,
-                    kRGBA8CanvasPixelFormat,
-                    kNonOpaque),
+      color_params_(kSRGBCanvasColorSpace, kRGBA8CanvasPixelFormat, kNonOpaque),
       creation_attributes_(attrs) {
-  color_params_.SetCanvasColorSpace(kLegacyCanvasColorSpace);
-
-  if (creation_attributes_.colorSpace() == kSRGBCanvasColorSpaceName) {
-    color_params_.SetCanvasColorSpace(kSRGBCanvasColorSpace);
-  } else if (creation_attributes_.colorSpace() ==
-             kRec2020CanvasColorSpaceName) {
-    color_params_.SetCanvasColorSpace(kRec2020CanvasColorSpace);
-  } else if (creation_attributes_.colorSpace() == kP3CanvasColorSpaceName) {
-    color_params_.SetCanvasColorSpace(kP3CanvasColorSpace);
-  }
-
+  // Supported color spaces: srgb-8888, srgb-f16, p3-f16, rec2020-f16. For wide
+  // gamut color spaces, user must explicitly request for float16 storage.
+  // Otherwise, we fall back to srgb-8888. Invalid requests fall back to
+  // srgb-8888 too.
   if (creation_attributes_.pixelFormat() == kF16CanvasPixelFormatName) {
     color_params_.SetCanvasPixelFormat(kF16CanvasPixelFormat);
+    if (creation_attributes_.colorSpace() == kRec2020CanvasColorSpaceName)
+      color_params_.SetCanvasColorSpace(kRec2020CanvasColorSpace);
+    else if (creation_attributes_.colorSpace() == kP3CanvasColorSpaceName)
+      color_params_.SetCanvasColorSpace(kP3CanvasColorSpace);
   }
 
   if (!creation_attributes_.alpha()) {
     color_params_.SetOpacityMode(kOpaque);
   }
 
-  // Make m_creationAttributes reflect the effective colorSpace, pixelFormat and
-  // linearPixelMath rather than the requested one.
+  // Make m_creationAttributes reflect the effective colorSpace and pixelFormat
+  // rather than the requested one.
   creation_attributes_.setColorSpace(ColorSpaceAsString());
   creation_attributes_.setPixelFormat(PixelFormatAsString());
 }
diff --git a/third_party/WebKit/Source/core/html/forms/FormData.cpp b/third_party/WebKit/Source/core/html/forms/FormData.cpp
index f80507c..8252df2 100644
--- a/third_party/WebKit/Source/core/html/forms/FormData.cpp
+++ b/third_party/WebKit/Source/core/html/forms/FormData.cpp
@@ -289,8 +289,6 @@
         // Do not add the file if the path is empty.
         if (!file->GetPath().IsEmpty())
           form_data->AppendFile(file->GetPath());
-        if (!file->FileSystemURL().IsEmpty())
-          form_data->AppendFileSystemURL(file->FileSystemURL());
       } else {
         form_data->AppendBlob(entry->GetBlob()->Uuid(),
                               entry->GetBlob()->GetBlobDataHandle());
diff --git a/third_party/WebKit/Source/core/html/forms/TextControlElement.cpp b/third_party/WebKit/Source/core/html/forms/TextControlElement.cpp
index a220592..b8bd149 100644
--- a/third_party/WebKit/Source/core/html/forms/TextControlElement.cpp
+++ b/third_party/WebKit/Source/core/html/forms/TextControlElement.cpp
@@ -998,9 +998,9 @@
 
   // Change the pseudo-id to set the style for suggested values or reset the
   // placeholder style depending on if there is a suggested value.
-  placeholder->SetShadowPseudoId(AtomicString(suggested_value_.IsEmpty()
-                                                  ? "-webkit-input-placeholder"
-                                                  : "-webkit-input-suggested"));
+  placeholder->SetShadowPseudoId(
+      AtomicString(suggested_value_.IsEmpty() ? "-webkit-input-placeholder"
+                                              : "-internal-input-suggested"));
 }
 
 HTMLElement* TextControlElement::CreateInnerEditorElement() {
diff --git a/third_party/WebKit/Source/core/html/forms/TextFieldInputType.cpp b/third_party/WebKit/Source/core/html/forms/TextFieldInputType.cpp
index 6e2b668..ed5c6e1 100644
--- a/third_party/WebKit/Source/core/html/forms/TextFieldInputType.cpp
+++ b/third_party/WebKit/Source/core/html/forms/TextFieldInputType.cpp
@@ -524,8 +524,6 @@
 }
 
 void TextFieldInputType::UpdateView() {
-  // The suggested values are now shown using placeholder elements, so there is
-  // nothing to do here for the suggested values.
   if (GetElement().SuggestedValue().IsEmpty() &&
       GetElement().NeedsToUpdateViewValue()) {
     // Update the view only if needsToUpdateViewValue is true. It protects
@@ -535,8 +533,8 @@
     // updated. In this case, updateView() is called but we should not
     // update the view value.
     GetElement().SetInnerEditorValue(VisibleValue());
-    GetElement().UpdatePlaceholderVisibility();
   }
+  GetElement().UpdatePlaceholderVisibility();
 }
 
 void TextFieldInputType::FocusAndSelectSpinButtonOwner() {
diff --git a/third_party/WebKit/Source/core/html/parser/HTMLParserScriptRunner.cpp b/third_party/WebKit/Source/core/html/parser/HTMLParserScriptRunner.cpp
index 1d35b0fc..8415ae2 100644
--- a/third_party/WebKit/Source/core/html/parser/HTMLParserScriptRunner.cpp
+++ b/third_party/WebKit/Source/core/html/parser/HTMLParserScriptRunner.cpp
@@ -27,21 +27,15 @@
 
 #include <inttypes.h>
 #include <memory>
-#include "bindings/core/v8/ScriptSourceCode.h"
-#include "bindings/core/v8/V8BindingForCore.h"
-#include "core/dom/ClassicPendingScript.h"
-#include "core/dom/ClassicScript.h"
 #include "core/dom/DocumentParserTiming.h"
 #include "core/dom/Element.h"
 #include "core/dom/IgnoreDestructiveWriteCountIncrementer.h"
 #include "core/dom/ScriptLoader.h"
 #include "core/dom/TaskRunnerHelper.h"
-#include "core/dom/events/Event.h"
 #include "core/frame/LocalFrame.h"
 #include "core/html/parser/HTMLInputStream.h"
 #include "core/html/parser/HTMLParserScriptRunnerHost.h"
 #include "core/html/parser/NestingLevelIncrementer.h"
-#include "core/loader/resource/ScriptResource.h"
 #include "platform/Histogram.h"
 #include "platform/WebFrameScheduler.h"
 #include "platform/bindings/Microtask.h"
@@ -533,8 +527,7 @@
         //  Document of the parser that created the element.
         //  (There can only be one such script per Document at a time.)"
         CHECK(!parser_blocking_script_);
-        parser_blocking_script_ =
-            ClassicPendingScript::CreateInline(element, script_start_position);
+        parser_blocking_script_ = script_loader->TakePendingScript();
       } else {
         // 6th Clause of Step 23.
         // "Immediately execute the script block,
@@ -544,9 +537,8 @@
         if (parser_blocking_script_)
           parser_blocking_script_->Dispose();
         parser_blocking_script_ = nullptr;
-        DoExecuteScript(
-            ClassicPendingScript::CreateInline(element, script_start_position),
-            DocumentURLForScriptExecution(document_));
+        DoExecuteScript(script_loader->TakePendingScript(),
+                        DocumentURLForScriptExecution(document_));
       }
     } else {
       // 2nd Clause of Step 23.
diff --git a/third_party/WebKit/Source/core/imagebitmap/ImageBitmap.cpp b/third_party/WebKit/Source/core/imagebitmap/ImageBitmap.cpp
index 7441ae25..89ee0f23 100644
--- a/third_party/WebKit/Source/core/imagebitmap/ImageBitmap.cpp
+++ b/third_party/WebKit/Source/core/imagebitmap/ImageBitmap.cpp
@@ -66,6 +66,8 @@
            options.premultiplyAlpha() == kImageBitmapOptionPremultiply);
   }
 
+  parsed_options.has_color_space_conversion =
+      (options.colorSpaceConversion() != kImageBitmapOptionNone);
   parsed_options.color_params.SetCanvasColorSpace(kLegacyCanvasColorSpace);
   if (options.colorSpaceConversion() == kSRGBImageBitmapColorSpaceConversion) {
     parsed_options.color_params.SetCanvasColorSpace(kSRGBCanvasColorSpace);
@@ -237,7 +239,8 @@
 
   SkImageInfo info = GetSkImageInfo(image.get());
   info = info.makeAlphaType(alpha_type);
-  scoped_refptr<Uint8Array> dst_pixels = CopyImageData(image, info);
+  scoped_refptr<Uint8Array> dst_pixels =
+      CopyImageData(image, info.makeColorSpace(nullptr));
   if (!dst_pixels)
     return nullptr;
   return NewImageFromRaster(info, std::move(dst_pixels));
@@ -248,65 +251,59 @@
     unsigned resize_width,
     unsigned resize_height,
     SkFilterQuality resize_quality) {
-  sk_sp<SkImage> skia_image = image->PaintImageForCurrentFrame().GetSkImage();
-  SkAlphaType original_alpha = skia_image->alphaType();
-  auto pm_image = skia_image;
-  auto pm_info = GetSkImageInfo(image);
-  if (original_alpha == kUnpremul_SkAlphaType) {
-    pm_info = pm_info.makeAlphaType(kPremul_SkAlphaType);
-    SkPixmap pm_pixmap;
-    if (!skia_image->peekPixels(&pm_pixmap))
-      return nullptr;
-    pm_pixmap.reset(pm_info, pm_pixmap.addr(), pm_pixmap.rowBytes());
-    pm_image = SkImage::MakeFromRaster(pm_pixmap, nullptr, nullptr);
+  auto sk_image = image->PaintImageForCurrentFrame().GetSkImage();
+  // SkImage::scalePixels() only works in premul. If the input is unpremul, we
+  // convert it to premul.
+  bool converted_to_premul = false;
+  if (sk_image->alphaType() == kUnpremul_SkAlphaType) {
+    image = GetImageWithAlphaDisposition(std::move(image), kPremultiplyAlpha);
+    sk_image = image->PaintImageForCurrentFrame().GetSkImage();
+    converted_to_premul = true;
   }
-
-  scoped_refptr<ArrayBuffer> dst_buffer = ArrayBuffer::CreateOrNull(
-      resize_width * resize_height, pm_info.bytesPerPixel());
-  if (!dst_buffer)
+  auto image_info = GetSkImageInfo(image);
+  // Avoid sRGB transfer function by setting the color space to nullptr.
+  if (SkColorSpace::Equals(image_info.colorSpace(),
+                           SkColorSpace::MakeSRGB().get()))
+    image_info = image_info.makeColorSpace(nullptr);
+  SkImageInfo resized_info = image_info.makeWH(resize_width, resize_height);
+  auto resized_data =
+      SkData::MakeUninitialized(resized_info.computeMinByteSize());
+  if (!resized_data)
     return nullptr;
-  scoped_refptr<Uint8Array> resized_pixels =
-      Uint8Array::Create(dst_buffer, 0, dst_buffer->ByteLength());
-  SkImageInfo pm_resized_info = pm_info.makeWH(resize_width, resize_height);
-  SkPixmap pm_resized_pixmap(pm_resized_info, resized_pixels->Data(),
-                             resize_width * pm_info.bytesPerPixel());
+  SkPixmap resized_pixmap(resized_info, resized_data->writable_data(),
+                          resized_info.minRowBytes());
+  sk_image->scalePixels(resized_pixmap, resize_quality);
+  // Tag the resized Pixmap with the correct color space.
+  resized_pixmap.setColorSpace(GetSkImageInfo(image).refColorSpace());
+  auto resized_sk_image = SkImage::MakeRasterCopy(resized_pixmap);
+  scoped_refptr<StaticBitmapImage> resized_image = StaticBitmapImage::Create(
+      resized_sk_image, image->ContextProviderWrapper());
 
-  // When the original image is unpremul and is tagged as premul, calling
-  // SkImage::scalePixels() with parameter kHigh_SkFilterQuality clamps RGB
-  // components to alpha (bugs.chromium.org/p/skia/issues/detail?id=6855).
-  // As a workaround, we downgrade kHigh_SkFilterQuality to kMedium_ for
-  // unpremul images. This does not affect the quality of down-scaling,
-  // but should be fixed to get the highest upscaling quality.
-  // Bug: 744636.
-  if (original_alpha == kUnpremul_SkAlphaType &&
-      resize_quality == kHigh_SkFilterQuality)
-    resize_quality = kMedium_SkFilterQuality;
-
-  // Only scale in premul
-  pm_image->scalePixels(pm_resized_pixmap, resize_quality);
-  sk_sp<SkImage> resized_image;
-  if (original_alpha == kPremul_SkAlphaType) {
-    resized_pixels->AddRef();
-    resized_image = SkImage::MakeFromRaster(pm_resized_pixmap, freePixels,
-                                            resized_pixels.get());
-  } else {
-    SkPixmap upm_resized_pixmap(
-        pm_resized_info.makeAlphaType(kUnpremul_SkAlphaType),
-        resized_pixels->Data(), resize_width * pm_info.bytesPerPixel());
-    resized_pixels->AddRef();
-    resized_image = SkImage::MakeFromRaster(upm_resized_pixmap, freePixels,
-                                            resized_pixels.get());
+  // If the source image was unpremul, unpremul the resized image.
+  if (converted_to_premul) {
+    resized_image = GetImageWithAlphaDisposition(std::move(resized_image),
+                                                 kDontPremultiplyAlpha);
   }
-  return StaticBitmapImage::Create(resized_image,
-                                   image->ContextProviderWrapper());
+  return resized_image;
 }
 
 scoped_refptr<StaticBitmapImage> ApplyColorSpaceConversion(
     scoped_refptr<StaticBitmapImage>&& image,
     ImageBitmap::ParsedOptions& options) {
+  SkTransferFunctionBehavior transfer_function_behavior =
+      SkTransferFunctionBehavior::kRespect;
+  // We normally expect to respect transfer function. However, in two scenarios
+  // we have to ignore the transfer function. First, when the source image is
+  // unpremul. Second, when the source image is drawn using a
+  // SkColorSpaceXformCanvas.
+  sk_sp<SkImage> skia_image = image->PaintImageForCurrentFrame().GetSkImage();
+  if (!skia_image->colorSpace() ||
+      skia_image->alphaType() == kUnpremul_SkAlphaType)
+    transfer_function_behavior = SkTransferFunctionBehavior::kIgnore;
+
   return image->ConvertToColorSpace(
       options.color_params.GetSkColorSpaceForSkSurfaces(),
-      SkTransferFunctionBehavior::kRespect);
+      transfer_function_behavior);
 }
 
 scoped_refptr<StaticBitmapImage> MakeBlankImage(
@@ -340,8 +337,7 @@
 
 static scoped_refptr<StaticBitmapImage> CropImageAndApplyColorSpaceConversion(
     scoped_refptr<Image>&& image,
-    ImageBitmap::ParsedOptions& parsed_options,
-    ColorBehavior color_behavior = ColorBehavior::TransformToSRGB()) {
+    ImageBitmap::ParsedOptions& parsed_options) {
   DCHECK(image);
   IntRect img_rect(IntPoint(), IntSize(image->width(), image->height()));
   const IntRect src_rect = Intersection(img_rect, parsed_options.crop_rect);
@@ -354,14 +350,14 @@
   sk_sp<SkImage> skia_image = image->PaintImageForCurrentFrame().GetSkImage();
   // Attempt to get raw unpremultiplied image data, executed only when
   // skia_image is premultiplied.
-  if ((((!image->IsSVGImage() && !skia_image->isOpaque()) || !skia_image) &&
-       image->Data() && skia_image->alphaType() == kPremul_SkAlphaType) ||
-      color_behavior.IsIgnore()) {
+  if (!skia_image->isOpaque() && image->Data() &&
+      skia_image->alphaType() == kPremul_SkAlphaType) {
     std::unique_ptr<ImageDecoder> decoder(ImageDecoder::Create(
         image->Data(), true,
         parsed_options.premultiply_alpha ? ImageDecoder::kAlphaPremultiplied
                                          : ImageDecoder::kAlphaNotPremultiplied,
-        color_behavior));
+        parsed_options.has_color_space_conversion ? ColorBehavior::Tag()
+                                                  : ColorBehavior::Ignore()));
     if (!decoder)
       return nullptr;
     skia_image = ImageBitmap::GetSkImageFromDecoder(std::move(decoder));
@@ -392,8 +388,8 @@
                    parsed_options.resize_height, parsed_options.resize_quality);
   }
 
-  // color correct the image
-  result = ApplyColorSpaceConversion(std::move(result), parsed_options);
+  if (parsed_options.has_color_space_conversion)
+    result = ApplyColorSpaceConversion(std::move(result), parsed_options);
   return result;
 }
 
@@ -407,11 +403,8 @@
   if (DstBufferSizeHasOverflow(parsed_options))
     return;
 
-  image_ = CropImageAndApplyColorSpaceConversion(
-      std::move(input), parsed_options,
-      options.colorSpaceConversion() == kImageBitmapOptionNone
-          ? ColorBehavior::Ignore()
-          : ColorBehavior::TransformToSRGB());
+  image_ =
+      CropImageAndApplyColorSpaceConversion(std::move(input), parsed_options);
   if (!image_)
     return;
 
diff --git a/third_party/WebKit/Source/core/imagebitmap/ImageBitmap.h b/third_party/WebKit/Source/core/imagebitmap/ImageBitmap.h
index 5188767..ddd5a72 100644
--- a/third_party/WebKit/Source/core/imagebitmap/ImageBitmap.h
+++ b/third_party/WebKit/Source/core/imagebitmap/ImageBitmap.h
@@ -136,6 +136,7 @@
     bool flip_y = false;
     bool premultiply_alpha = true;
     bool should_scale_input = false;
+    bool has_color_space_conversion = false;
     unsigned resize_width = 0;
     unsigned resize_height = 0;
     IntRect crop_rect;
diff --git a/third_party/WebKit/Source/core/imagebitmap/ImageBitmapFactories.cpp b/third_party/WebKit/Source/core/imagebitmap/ImageBitmapFactories.cpp
index 771ef54..8773677d 100644
--- a/third_party/WebKit/Source/core/imagebitmap/ImageBitmapFactories.cpp
+++ b/third_party/WebKit/Source/core/imagebitmap/ImageBitmapFactories.cpp
@@ -324,8 +324,7 @@
       SegmentReader::CreateFromSkData(SkData::MakeWithoutCopy(
           array_buffer->Data(), array_buffer->ByteLength())),
       true, alpha_op,
-      ignore_color_space ? ColorBehavior::Ignore()
-                         : ColorBehavior::TransformToSRGB()));
+      ignore_color_space ? ColorBehavior::Ignore() : ColorBehavior::Tag()));
   sk_sp<SkImage> frame;
   if (decoder) {
     frame = ImageBitmap::GetSkImageFromDecoder(std::move(decoder));
diff --git a/third_party/WebKit/Source/core/imagebitmap/ImageBitmapTest.cpp b/third_party/WebKit/Source/core/imagebitmap/ImageBitmapTest.cpp
index 555b985..e561228 100644
--- a/third_party/WebKit/Source/core/imagebitmap/ImageBitmapTest.cpp
+++ b/third_party/WebKit/Source/core/imagebitmap/ImageBitmapTest.cpp
@@ -223,8 +223,6 @@
   }
 }
 
-constexpr float kWideGamutColorCorrectionTolerance = 0.01;
-
 enum class ColorSpaceConversion : uint8_t {
   NONE = 0,
   DEFAULT_COLOR_CORRECTED = 1,
@@ -241,10 +239,9 @@
   // Set the color space conversion in ImageBitmapOptions
   ImageBitmapOptions options;
   static const Vector<String> kConversions = {
-      "none", "default", "default", "srgb", "linear-rgb", "p3", "rec2020"};
+      "none", "default", "srgb", "linear-rgb", "p3", "rec2020"};
   options.setColorSpaceConversion(
       kConversions[static_cast<uint8_t>(color_space_conversion)]);
-
   return options;
 }
 
@@ -259,8 +256,7 @@
 #endif
 
 TEST_F(ImageBitmapTest, MAYBE_ImageBitmapColorSpaceConversionHTMLImageElement) {
-  // Enable experimental canvas features and color canvas extensions for this
-  // test.
+  // Enable experimental canvas features for this test.
   ScopedExperimentalCanvasFeaturesForTest experimental_canvas_features(true);
 
   HTMLImageElement* image_element =
@@ -278,8 +274,9 @@
 
   std::unique_ptr<uint8_t[]> src_pixel(
       new uint8_t[raster_image_info.bytesPerPixel()]());
-  image->readPixels(raster_image_info.makeWH(1, 1), src_pixel.get(),
-                    image->width() * raster_image_info.bytesPerPixel(), 5, 5);
+  SkImageInfo src_pixel_image_info = raster_image_info.makeWH(1, 1);
+  image->readPixels(src_pixel_image_info, src_pixel.get(),
+                    src_pixel_image_info.minRowBytes(), 5, 5);
 
   ImageResourceContent* original_image_resource =
       ImageResourceContent::CreateLoaded(
@@ -352,9 +349,8 @@
         1, 1, color_type, SkAlphaType::kPremul_SkAlphaType, color_space);
     std::unique_ptr<uint8_t[]> converted_pixel(
         new uint8_t[image_info.bytesPerPixel()]());
-    converted_image->readPixels(
-        image_info, converted_pixel.get(),
-        converted_image->width() * image_info.bytesPerPixel(), 5, 5);
+    converted_image->readPixels(image_info, converted_pixel.get(),
+                                image_info.minRowBytes(), 5, 5);
 
     // Transform the source pixel and check if the image bitmap color conversion
     // is done correctly.
@@ -367,8 +363,10 @@
                              SkAlphaType::kPremul_SkAlphaType);
 
     ColorCorrectionTestUtils::CompareColorCorrectedPixels(
-        converted_pixel, transformed_pixel, image_info.bytesPerPixel(),
-        kWideGamutColorCorrectionTolerance);
+        converted_pixel.get(), transformed_pixel.get(), 1,
+        (color_type == kBGRA_8888_SkColorType) ? kUint8ClampedArrayStorageFormat
+                                               : kUint16ArrayStorageFormat,
+        kAlphaMultiplied, kUnpremulRoundTripTolerance);
   }
 }
 
@@ -383,8 +381,7 @@
 #endif
 
 TEST_F(ImageBitmapTest, MAYBE_ImageBitmapColorSpaceConversionImageBitmap) {
-  // Enable experimental canvas features and color canvas extensions for this
-  // test.
+  // Enable experimental canvas features for this test.
   ScopedExperimentalCanvasFeaturesForTest experimental_canvas_features(true);
 
   HTMLImageElement* image_element =
@@ -488,8 +485,10 @@
                              SkAlphaType::kPremul_SkAlphaType);
 
     ColorCorrectionTestUtils::CompareColorCorrectedPixels(
-        converted_pixel, transformed_pixel, image_info.bytesPerPixel(),
-        kWideGamutColorCorrectionTolerance);
+        converted_pixel.get(), transformed_pixel.get(), 1,
+        (color_type == kBGRA_8888_SkColorType) ? kUint8ClampedArrayStorageFormat
+                                               : kUint16ArrayStorageFormat,
+        kAlphaMultiplied, kUnpremulRoundTripTolerance);
   }
 }
 
@@ -505,8 +504,7 @@
 
 TEST_F(ImageBitmapTest,
        MAYBE_ImageBitmapColorSpaceConversionStaticBitmapImage) {
-  // Enable experimental canvas features and color canvas extensions for this
-  // test.
+  // Enable experimental canvas features for this test.
   ScopedExperimentalCanvasFeaturesForTest experimental_canvas_features(true);
 
   SkPaint p;
@@ -549,6 +547,8 @@
                                    .GetSkImage()
                                    .get();
 
+    UnpremulRoundTripTolerance unpremul_round_trip_tolerance =
+        kUnpremulRoundTripTolerance;
     switch (color_space_conversion) {
       case ColorSpaceConversion::NONE:
         NOTREACHED();
@@ -557,6 +557,7 @@
       case ColorSpaceConversion::SRGB:
         color_space = SkColorSpace::MakeSRGB();
         color_format = color_format32;
+        unpremul_round_trip_tolerance = kUnpremulRoundTripTolerance;
         break;
       case ColorSpaceConversion::LINEAR_RGB:
         color_space = SkColorSpace::MakeSRGBLinear();
@@ -600,21 +601,21 @@
                              SkAlphaType::kPremul_SkAlphaType);
 
     ColorCorrectionTestUtils::CompareColorCorrectedPixels(
-        converted_pixel, transformed_pixel, image_info.bytesPerPixel(),
-        kWideGamutColorCorrectionTolerance);
+        converted_pixel.get(), transformed_pixel.get(), 1,
+        (color_type == kBGRA_8888_SkColorType) ? kUint8ClampedArrayStorageFormat
+                                               : kUint16ArrayStorageFormat,
+        kAlphaMultiplied, unpremul_round_trip_tolerance);
   }
 }
 
 TEST_F(ImageBitmapTest, ImageBitmapColorSpaceConversionImageData) {
-  // Enable experimental canvas features and color canvas extensions for this
-  // test.
+  // Enable experimental canvas features for this test.
   ScopedExperimentalCanvasFeaturesForTest experimental_canvas_features(true);
 
   sk_sp<SkColorSpace> src_rgb_color_space = SkColorSpace::MakeSRGB();
-  unsigned char data_buffer[4] = {32, 96, 160, 255};
+  unsigned char data_buffer[4] = {32, 96, 160, 128};
   DOMUint8ClampedArray* data = DOMUint8ClampedArray::Create(data_buffer, 4);
   ImageDataColorSettings color_settings;
-  color_settings.setColorSpace("srgb");
   ImageData* image_data = ImageData::Create(
       IntSize(1, 1), NotShared<DOMUint8ClampedArray>(data), &color_settings);
   std::unique_ptr<uint8_t[]> src_pixel(new uint8_t[4]());
@@ -623,10 +624,11 @@
   Optional<IntRect> crop_rect = IntRect(0, 0, 1, 1);
   sk_sp<SkColorSpace> color_space = nullptr;
   SkColorType color_type = SkColorType::kN32_SkColorType;
-  SkColorSpaceXform::ColorFormat color_format =
-      kN32_SkColorType == kRGBA_8888_SkColorType
-          ? SkColorSpaceXform::ColorFormat::kRGBA_8888_ColorFormat
-          : SkColorSpaceXform::ColorFormat::kBGRA_8888_ColorFormat;
+  SkColorSpaceXform::ColorFormat color_format32 =
+      (color_type == kBGRA_8888_SkColorType)
+          ? SkColorSpaceXform::ColorFormat::kBGRA_8888_ColorFormat
+          : SkColorSpaceXform::ColorFormat::kRGBA_8888_ColorFormat;
+  SkColorSpaceXform::ColorFormat color_format = color_format32;
 
   for (uint8_t i =
            static_cast<uint8_t>(ColorSpaceConversion::DEFAULT_COLOR_CORRECTED);
@@ -650,6 +652,7 @@
       case ColorSpaceConversion::DEFAULT_COLOR_CORRECTED:
       case ColorSpaceConversion::SRGB:
         color_space = SkColorSpace::MakeSRGB();
+        color_format = color_format32;
         break;
       case ColorSpaceConversion::LINEAR_RGB:
         color_space = SkColorSpace::MakeSRGBLinear();
@@ -674,8 +677,8 @@
         NOTREACHED();
     }
 
-    SkImageInfo image_info = SkImageInfo::Make(
-        1, 1, color_type, SkAlphaType::kPremul_SkAlphaType, color_space);
+    SkImageInfo image_info =
+        SkImageInfo::Make(1, 1, color_type, SkAlphaType::kUnpremul_SkAlphaType);
     std::unique_ptr<uint8_t[]> converted_pixel(
         new uint8_t[image_info.bytesPerPixel()]());
     converted_image->readPixels(
@@ -691,11 +694,13 @@
     color_space_xform->apply(
         color_format, transformed_pixel.get(),
         SkColorSpaceXform::ColorFormat::kRGBA_8888_ColorFormat, src_pixel.get(),
-        1, SkAlphaType::kPremul_SkAlphaType);
+        1, kUnpremul_SkAlphaType);
 
     ColorCorrectionTestUtils::CompareColorCorrectedPixels(
-        converted_pixel, transformed_pixel, image_info.bytesPerPixel(),
-        kWideGamutColorCorrectionTolerance);
+        converted_pixel.get(), transformed_pixel.get(), 1,
+        (color_type == kBGRA_8888_SkColorType) ? kUint8ClampedArrayStorageFormat
+                                               : kUint16ArrayStorageFormat,
+        kAlphaUnmultiplied, kUnpremulRoundTripTolerance);
   }
 }
 
diff --git a/third_party/WebKit/Source/core/layout/GridTrackSizingAlgorithm.cpp b/third_party/WebKit/Source/core/layout/GridTrackSizingAlgorithm.cpp
index 70cee28..105b47d 100644
--- a/third_party/WebKit/Source/core/layout/GridTrackSizingAlgorithm.cpp
+++ b/third_party/WebKit/Source/core/layout/GridTrackSizingAlgorithm.cpp
@@ -544,25 +544,11 @@
 
 LayoutUnit IndefiniteSizeStrategy::FreeSpaceForStretchAutoTracksStep() const {
   DCHECK(!algorithm_.FreeSpace(Direction()));
-  LayoutUnit min_size;
+  if (Direction() == kForColumns)
+    return LayoutUnit();
 
-  if (Direction() == kForColumns) {
-    // TODO(rego): Review intrinsic sizes in follow-up patches. For flexible
-    // tracks we will need to do something similar if we want to have accurate
-    // intrinsic sizes. Even in ComputeGridContainerIntrinsicSizes() we should
-    // consider this.
-    Length min_width = GetLayoutGrid()->StyleRef().LogicalMinWidth();
-    if (min_width.IsFixed() && min_width.Value() > 0) {
-      min_size = GetLayoutGrid()->AdjustContentBoxLogicalWidthForBoxSizing(
-          LayoutUnit(min_width.Value()));
-    } else {
-      return LayoutUnit();
-    }
-  } else {
-    min_size = GetLayoutGrid()->ComputeContentLogicalHeight(
-        kMinSize, GetLayoutGrid()->StyleRef().LogicalMinHeight(),
-        LayoutUnit(-1));
-  }
+  LayoutUnit min_size = GetLayoutGrid()->ComputeContentLogicalHeight(
+      kMinSize, GetLayoutGrid()->StyleRef().LogicalMinHeight(), LayoutUnit(-1));
   return min_size - ComputeTrackBasedSize();
 }
 
diff --git a/third_party/WebKit/Source/core/layout/LayoutBlock.cpp b/third_party/WebKit/Source/core/layout/LayoutBlock.cpp
index c61b95b..84f066f 100644
--- a/third_party/WebKit/Source/core/layout/LayoutBlock.cpp
+++ b/third_party/WebKit/Source/core/layout/LayoutBlock.cpp
@@ -1420,6 +1420,11 @@
                      LayoutUnit(style_to_use.LogicalMinWidth().Value())));
   }
 
+  LayoutUnit border_and_padding = BorderAndPaddingLogicalWidth();
+  DCHECK_GE(border_and_padding, LayoutUnit());
+  min_preferred_logical_width_ += border_and_padding;
+  max_preferred_logical_width_ += border_and_padding;
+
   // Table layout uses integers, ceil the preferred widths to ensure that they
   // can contain the contents.
   if (IsTableCell()) {
@@ -1429,11 +1434,6 @@
         LayoutUnit(max_preferred_logical_width_.Ceil());
   }
 
-  LayoutUnit border_and_padding = BorderAndPaddingLogicalWidth();
-  DCHECK_GE(border_and_padding, LayoutUnit());
-  min_preferred_logical_width_ += border_and_padding;
-  max_preferred_logical_width_ += border_and_padding;
-
   ClearPreferredLogicalWidthsDirty();
 }
 
diff --git a/third_party/WebKit/Source/core/layout/LayoutBox.cpp b/third_party/WebKit/Source/core/layout/LayoutBox.cpp
index 4c2d745..7fb3db1 100644
--- a/third_party/WebKit/Source/core/layout/LayoutBox.cpp
+++ b/third_party/WebKit/Source/core/layout/LayoutBox.cpp
@@ -1787,7 +1787,9 @@
   BoxPainter(*this).PaintMask(paint_info, paint_offset);
 }
 
-void LayoutBox::ImageChanged(WrappedImagePtr image, const IntRect*) {
+void LayoutBox::ImageChanged(WrappedImagePtr image,
+                             CanDeferInvalidation defer,
+                             const IntRect*) {
   // TODO(chrishtr): support PaintInvalidationReason::kDelayedFull for animated
   // border images.
   if ((StyleRef().BorderImage().GetImage() &&
@@ -1818,7 +1820,7 @@
             layer->GetImage()->CachedImage() &&
             layer->GetImage()->CachedImage()->GetImage() &&
             layer->GetImage()->CachedImage()->GetImage()->MaybeAnimated();
-        if (maybe_animated) {
+        if (defer == CanDeferInvalidation::kYes && maybe_animated) {
           SetMayNeedPaintInvalidationAnimatedBackgroundImage();
         } else {
           SetShouldDoFullPaintInvalidationWithoutGeometryChange(
diff --git a/third_party/WebKit/Source/core/layout/LayoutBox.h b/third_party/WebKit/Source/core/layout/LayoutBox.h
index c45572b5..d8159eba 100644
--- a/third_party/WebKit/Source/core/layout/LayoutBox.h
+++ b/third_party/WebKit/Source/core/layout/LayoutBox.h
@@ -1073,7 +1073,9 @@
   virtual void PaintBoxDecorationBackground(const PaintInfo&,
                                             const LayoutPoint&) const;
   virtual void PaintMask(const PaintInfo&, const LayoutPoint&) const;
-  void ImageChanged(WrappedImagePtr, const IntRect* = nullptr) override;
+  void ImageChanged(WrappedImagePtr,
+                    CanDeferInvalidation,
+                    const IntRect* = nullptr) override;
   ResourcePriority ComputeResourcePriority() const final;
 
   void LogicalExtentAfterUpdatingLogicalWidth(const LayoutUnit& logical_top,
diff --git a/third_party/WebKit/Source/core/layout/LayoutBoxTest.cpp b/third_party/WebKit/Source/core/layout/LayoutBoxTest.cpp
index 8798a4f..efba67f 100644
--- a/third_party/WebKit/Source/core/layout/LayoutBoxTest.cpp
+++ b/third_party/WebKit/Source/core/layout/LayoutBoxTest.cpp
@@ -6,7 +6,9 @@
 
 #include "build/build_config.h"
 #include "core/html/HTMLElement.h"
+#include "core/layout/LayoutImage.h"
 #include "core/layout/LayoutTestHelper.h"
+#include "platform/graphics/test/StubImage.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
 namespace blink {
@@ -350,4 +352,36 @@
   EXPECT_EQ(LayoutRect(-70, 0, 230, 210), a->VisualOverflowRect());
 }
 
+class AnimatedImage : public StubImage {
+ public:
+  bool MaybeAnimated() override { return true; }
+};
+
+TEST_F(LayoutBoxTest, DeferredInvalidation) {
+  SetBodyInnerHTML("<img id='image' style='width: 100px; height: 100px;'/>");
+  auto* obj = ToLayoutBox(GetLayoutObjectByElementId("image"));
+  ASSERT_TRUE(obj);
+
+  // Inject an animated image since deferred invalidations are only done for
+  // animated images.
+  auto* image =
+      ImageResourceContent::CreateLoaded(WTF::AdoptRef(new AnimatedImage()));
+  ToLayoutImage(obj)->ImageResource()->SetImageResource(image);
+  ASSERT_TRUE(ToLayoutImage(obj)->CachedImage()->GetImage()->MaybeAnimated());
+
+  // CanDeferInvalidation::kYes results in a deferred invalidation.
+  obj->ClearPaintInvalidationFlags();
+  EXPECT_EQ(obj->FullPaintInvalidationReason(), PaintInvalidationReason::kNone);
+  obj->ImageChanged(image, ImageResourceObserver::CanDeferInvalidation::kYes);
+  EXPECT_EQ(obj->FullPaintInvalidationReason(),
+            PaintInvalidationReason::kDelayedFull);
+
+  // CanDeferInvalidation::kNo results in a immediate invalidation.
+  obj->ClearPaintInvalidationFlags();
+  EXPECT_EQ(obj->FullPaintInvalidationReason(), PaintInvalidationReason::kNone);
+  obj->ImageChanged(image, ImageResourceObserver::CanDeferInvalidation::kNo);
+  EXPECT_EQ(obj->FullPaintInvalidationReason(),
+            PaintInvalidationReason::kImage);
+}
+
 }  // namespace blink
diff --git a/third_party/WebKit/Source/core/layout/LayoutFrame.cpp b/third_party/WebKit/Source/core/layout/LayoutFrame.cpp
index 30a84173..da4a82e 100644
--- a/third_party/WebKit/Source/core/layout/LayoutFrame.cpp
+++ b/third_party/WebKit/Source/core/layout/LayoutFrame.cpp
@@ -41,7 +41,9 @@
   return FrameEdgeInfo(element->NoResize(), element->HasFrameBorder());
 }
 
-void LayoutFrame::ImageChanged(WrappedImagePtr image, const IntRect*) {
+void LayoutFrame::ImageChanged(WrappedImagePtr image,
+                               CanDeferInvalidation,
+                               const IntRect*) {
   if (const CursorList* cursors = Style()->Cursors()) {
     for (const CursorData& cursor : *cursors) {
       if (cursor.GetImage() && cursor.GetImage()->CachedImage() == image) {
diff --git a/third_party/WebKit/Source/core/layout/LayoutFrame.h b/third_party/WebKit/Source/core/layout/LayoutFrame.h
index 5a00f48..957ea08 100644
--- a/third_party/WebKit/Source/core/layout/LayoutFrame.h
+++ b/third_party/WebKit/Source/core/layout/LayoutFrame.h
@@ -36,7 +36,9 @@
 
   FrameEdgeInfo EdgeInfo() const;
 
-  void ImageChanged(WrappedImagePtr, const IntRect* = nullptr) override;
+  void ImageChanged(WrappedImagePtr,
+                    CanDeferInvalidation,
+                    const IntRect* = nullptr) override;
 
   const char* GetName() const override { return "LayoutFrame"; }
 
diff --git a/third_party/WebKit/Source/core/layout/LayoutImage.cpp b/third_party/WebKit/Source/core/layout/LayoutImage.cpp
index 7362691..6a85e22 100644
--- a/third_party/WebKit/Source/core/layout/LayoutImage.cpp
+++ b/third_party/WebKit/Source/core/layout/LayoutImage.cpp
@@ -82,7 +82,9 @@
   image_resource_->Initialize(this);
 }
 
-void LayoutImage::ImageChanged(WrappedImagePtr new_image, const IntRect* rect) {
+void LayoutImage::ImageChanged(WrappedImagePtr new_image,
+                               CanDeferInvalidation defer,
+                               const IntRect* rect) {
   DCHECK(View());
   DCHECK(View()->GetFrameView());
   if (DocumentBeingDestroyed())
@@ -90,7 +92,7 @@
 
   if (HasBoxDecorationBackground() || HasMask() || HasShapeOutside() ||
       HasReflection())
-    LayoutReplaced::ImageChanged(new_image, rect);
+    LayoutReplaced::ImageChanged(new_image, defer, rect);
 
   if (!image_resource_)
     return;
@@ -122,7 +124,7 @@
     did_increment_visually_non_empty_pixel_count_ = true;
   }
 
-  InvalidatePaintAndMarkForLayoutIfNeeded();
+  InvalidatePaintAndMarkForLayoutIfNeeded(defer);
 }
 
 void LayoutImage::UpdateIntrinsicSizeIfNeeded(const LayoutSize& new_size) {
@@ -131,7 +133,8 @@
   SetIntrinsicSize(new_size);
 }
 
-void LayoutImage::InvalidatePaintAndMarkForLayoutIfNeeded() {
+void LayoutImage::InvalidatePaintAndMarkForLayoutIfNeeded(
+    CanDeferInvalidation defer) {
   LayoutSize old_intrinsic_size = IntrinsicSize();
   LayoutSize new_intrinsic_size =
       image_resource_->ImageSize(Style()->EffectiveZoom());
@@ -171,7 +174,8 @@
   }
 
   SetShouldDoFullPaintInvalidationWithoutGeometryChange(
-      ImageResource() && ImageResource()->MaybeAnimated()
+      defer == CanDeferInvalidation::kYes && ImageResource() &&
+              ImageResource()->MaybeAnimated()
           ? PaintInvalidationReason::kDelayedFull
           : PaintInvalidationReason::kImage);
 
@@ -211,7 +215,7 @@
   if (area_element->GetPath(this).IsEmpty())
     return;
 
-  InvalidatePaintAndMarkForLayoutIfNeeded();
+  InvalidatePaintAndMarkForLayoutIfNeeded(CanDeferInvalidation::kYes);
 }
 
 bool LayoutImage::ForegroundIsKnownToBeOpaqueInRect(
diff --git a/third_party/WebKit/Source/core/layout/LayoutImage.h b/third_party/WebKit/Source/core/layout/LayoutImage.h
index 49d8bdd..8bc2e5b12 100644
--- a/third_party/WebKit/Source/core/layout/LayoutImage.h
+++ b/third_party/WebKit/Source/core/layout/LayoutImage.h
@@ -82,7 +82,7 @@
 
   void IntrinsicSizeChanged() override {
     if (image_resource_)
-      ImageChanged(image_resource_->ImagePtr());
+      ImageChanged(image_resource_->ImagePtr(), CanDeferInvalidation::kNo);
   }
 
   const char* GetName() const override { return "LayoutImage"; }
@@ -92,7 +92,9 @@
   LayoutReplaced* EmbeddedReplacedContent() const final;
   void ComputeIntrinsicSizingInfo(IntrinsicSizingInfo&) const final;
 
-  void ImageChanged(WrappedImagePtr, const IntRect* = nullptr) override;
+  void ImageChanged(WrappedImagePtr,
+                    CanDeferInvalidation,
+                    const IntRect* = nullptr) override;
 
   void Paint(const PaintInfo&, const LayoutPoint&) const final;
 
@@ -126,7 +128,7 @@
                    const LayoutPoint& accumulated_offset,
                    HitTestAction) final;
 
-  void InvalidatePaintAndMarkForLayoutIfNeeded();
+  void InvalidatePaintAndMarkForLayoutIfNeeded(CanDeferInvalidation);
   void UpdateIntrinsicSizeIfNeeded(const LayoutSize&);
 
   // This member wraps the associated decoded image.
diff --git a/third_party/WebKit/Source/core/layout/LayoutImageResource.cpp b/third_party/WebKit/Source/core/layout/LayoutImageResource.cpp
index e085c6d3..b8c51a10 100644
--- a/third_party/WebKit/Source/core/layout/LayoutImageResource.cpp
+++ b/third_party/WebKit/Source/core/layout/LayoutImageResource.cpp
@@ -66,10 +66,14 @@
   cached_image_ = new_image;
   if (cached_image_) {
     cached_image_->AddObserver(layout_object_);
-    if (cached_image_->ErrorOccurred())
-      layout_object_->ImageChanged(cached_image_.Get());
+    if (cached_image_->ErrorOccurred()) {
+      layout_object_->ImageChanged(
+          cached_image_.Get(),
+          ImageResourceObserver::CanDeferInvalidation::kNo);
+    }
   } else {
-    layout_object_->ImageChanged(cached_image_.Get());
+    layout_object_->ImageChanged(
+        cached_image_.Get(), ImageResourceObserver::CanDeferInvalidation::kNo);
   }
 }
 
diff --git a/third_party/WebKit/Source/core/layout/LayoutImageResource.h b/third_party/WebKit/Source/core/layout/LayoutImageResource.h
index 8e862cf..879ba7c 100644
--- a/third_party/WebKit/Source/core/layout/LayoutImageResource.h
+++ b/third_party/WebKit/Source/core/layout/LayoutImageResource.h
@@ -27,6 +27,7 @@
 #ifndef LayoutImageResource_h
 #define LayoutImageResource_h
 
+#include "core/CoreExport.h"
 #include "core/loader/resource/ImageResourceContent.h"
 #include "core/style/StyleImage.h"
 
@@ -34,7 +35,7 @@
 
 class LayoutObject;
 
-class LayoutImageResource
+class CORE_EXPORT LayoutImageResource
     : public GarbageCollectedFinalized<LayoutImageResource> {
   WTF_MAKE_NONCOPYABLE(LayoutImageResource);
 
diff --git a/third_party/WebKit/Source/core/layout/LayoutInline.cpp b/third_party/WebKit/Source/core/layout/LayoutInline.cpp
index be9a0da9..d4256d3a 100644
--- a/third_party/WebKit/Source/core/layout/LayoutInline.cpp
+++ b/third_party/WebKit/Source/core/layout/LayoutInline.cpp
@@ -1420,7 +1420,9 @@
                                             : logical_offset.TransposedSize();
 }
 
-void LayoutInline::ImageChanged(WrappedImagePtr, const IntRect*) {
+void LayoutInline::ImageChanged(WrappedImagePtr,
+                                CanDeferInvalidation,
+                                const IntRect*) {
   if (!Parent())
     return;
 
diff --git a/third_party/WebKit/Source/core/layout/LayoutInline.h b/third_party/WebKit/Source/core/layout/LayoutInline.h
index 1f61858..5c89674 100644
--- a/third_party/WebKit/Source/core/layout/LayoutInline.h
+++ b/third_party/WebKit/Source/core/layout/LayoutInline.h
@@ -329,7 +329,9 @@
 
   void UpdateHitTestResult(HitTestResult&, const LayoutPoint&) final;
 
-  void ImageChanged(WrappedImagePtr, const IntRect* = nullptr) final;
+  void ImageChanged(WrappedImagePtr,
+                    CanDeferInvalidation,
+                    const IntRect* = nullptr) final;
 
   void AddAnnotatedRegions(Vector<AnnotatedRegionValue>&) final;
 
diff --git a/third_party/WebKit/Source/core/layout/LayoutListMarker.cpp b/third_party/WebKit/Source/core/layout/LayoutListMarker.cpp
index b4ec120..c6597dd 100644
--- a/third_party/WebKit/Source/core/layout/LayoutListMarker.cpp
+++ b/third_party/WebKit/Source/core/layout/LayoutListMarker.cpp
@@ -176,7 +176,9 @@
   ClearNeedsLayout();
 }
 
-void LayoutListMarker::ImageChanged(WrappedImagePtr o, const IntRect*) {
+void LayoutListMarker::ImageChanged(WrappedImagePtr o,
+                                    CanDeferInvalidation,
+                                    const IntRect*) {
   // A list marker can't have a background or border image, so no need to call
   // the base class method.
   if (!image_ || o != image_->Data())
diff --git a/third_party/WebKit/Source/core/layout/LayoutListMarker.h b/third_party/WebKit/Source/core/layout/LayoutListMarker.h
index e44cd86..8fc5a72c 100644
--- a/third_party/WebKit/Source/core/layout/LayoutListMarker.h
+++ b/third_party/WebKit/Source/core/layout/LayoutListMarker.h
@@ -95,7 +95,9 @@
 
   void UpdateLayout() override;
 
-  void ImageChanged(WrappedImagePtr, const IntRect* = nullptr) override;
+  void ImageChanged(WrappedImagePtr,
+                    CanDeferInvalidation,
+                    const IntRect* = nullptr) override;
 
   InlineBox* CreateInlineBox() override;
 
diff --git a/third_party/WebKit/Source/core/layout/LayoutObject.cpp b/third_party/WebKit/Source/core/layout/LayoutObject.cpp
index 376442d..dd93ed00 100644
--- a/third_party/WebKit/Source/core/layout/LayoutObject.cpp
+++ b/third_party/WebKit/Source/core/layout/LayoutObject.cpp
@@ -3179,6 +3179,7 @@
 }
 
 void LayoutObject::ImageChanged(ImageResourceContent* image,
+                                CanDeferInvalidation defer,
                                 const IntRect* rect) {
   DCHECK(node_);
 
@@ -3188,7 +3189,7 @@
   DCHECK_NE(GetDocument().Lifecycle().GetState(),
             DocumentLifecycle::LifecycleState::kInPaint);
 
-  ImageChanged(static_cast<WrappedImagePtr>(image), rect);
+  ImageChanged(static_cast<WrappedImagePtr>(image), defer, rect);
 }
 
 Element* LayoutObject::OffsetParent(const Element* base) const {
diff --git a/third_party/WebKit/Source/core/layout/LayoutObject.h b/third_party/WebKit/Source/core/layout/LayoutObject.h
index df5c310..09dc4ec25 100644
--- a/third_party/WebKit/Source/core/layout/LayoutObject.h
+++ b/third_party/WebKit/Source/core/layout/LayoutObject.h
@@ -1540,8 +1540,12 @@
   virtual int CaretMaxOffset() const;
 
   // ImageResourceClient override.
-  void ImageChanged(ImageResourceContent*, const IntRect* = nullptr) final;
-  void ImageChanged(WrappedImagePtr, const IntRect* = nullptr) override {}
+  void ImageChanged(ImageResourceContent*,
+                    CanDeferInvalidation,
+                    const IntRect* = nullptr) final;
+  void ImageChanged(WrappedImagePtr,
+                    CanDeferInvalidation,
+                    const IntRect* = nullptr) override {}
   bool WillRenderImage() final;
   bool GetImageAnimationPolicy(ImageAnimationPolicy&) final;
 
diff --git a/third_party/WebKit/Source/core/layout/LayoutScrollbarPart.cpp b/third_party/WebKit/Source/core/layout/LayoutScrollbarPart.cpp
index 82cec743..1638a3b 100644
--- a/third_party/WebKit/Source/core/layout/LayoutScrollbarPart.cpp
+++ b/third_party/WebKit/Source/core/layout/LayoutScrollbarPart.cpp
@@ -209,9 +209,10 @@
 }
 
 void LayoutScrollbarPart::ImageChanged(WrappedImagePtr image,
+                                       CanDeferInvalidation defer,
                                        const IntRect* rect) {
   SetNeedsPaintInvalidation();
-  LayoutBlock::ImageChanged(image, rect);
+  LayoutBlock::ImageChanged(image, defer, rect);
 }
 
 LayoutObject* LayoutScrollbarPart::ScrollbarStyleSource() const {
diff --git a/third_party/WebKit/Source/core/layout/LayoutScrollbarPart.h b/third_party/WebKit/Source/core/layout/LayoutScrollbarPart.h
index 652758e6..068976d1 100644
--- a/third_party/WebKit/Source/core/layout/LayoutScrollbarPart.h
+++ b/third_party/WebKit/Source/core/layout/LayoutScrollbarPart.h
@@ -78,7 +78,9 @@
   void StyleWillChange(StyleDifference,
                        const ComputedStyle& new_style) override;
   void StyleDidChange(StyleDifference, const ComputedStyle* old_style) override;
-  void ImageChanged(WrappedImagePtr, const IntRect* = nullptr) override;
+  void ImageChanged(WrappedImagePtr,
+                    CanDeferInvalidation,
+                    const IntRect* = nullptr) override;
 
  private:
   LayoutScrollbarPart(ScrollableArea*, LayoutScrollbar*, ScrollbarPart);
diff --git a/third_party/WebKit/Source/core/layout/LayoutTableRow.cpp b/third_party/WebKit/Source/core/layout/LayoutTableRow.cpp
index 080f66c..b000498 100644
--- a/third_party/WebKit/Source/core/layout/LayoutTableRow.cpp
+++ b/third_party/WebKit/Source/core/layout/LayoutTableRow.cpp
@@ -194,10 +194,8 @@
     cell->SetLogicalTop(LogicalTop());
     if (!cell->NeedsLayout())
       Section()->MarkChildForPaginationRelayoutIfNeeded(*cell, layouter);
-    if (cell->NeedsLayout()) {
-      cell->ClearIntrinsicPadding();
+    if (cell->NeedsLayout())
       cell->UpdateLayout();
-    }
     if (paginated)
       Section()->UpdateFragmentationInfoForChild(*cell);
   }
diff --git a/third_party/WebKit/Source/core/layout/LayoutTextFragment.h b/third_party/WebKit/Source/core/layout/LayoutTextFragment.h
index 29f5135..cdf10f87 100644
--- a/third_party/WebKit/Source/core/layout/LayoutTextFragment.h
+++ b/third_party/WebKit/Source/core/layout/LayoutTextFragment.h
@@ -80,7 +80,6 @@
 
   void TransformText() override;
 
-  // FIXME: Rename to LayoutTextFragment
   const char* GetName() const override { return "LayoutTextFragment"; }
 
   void SetFirstLetterPseudoElement(FirstLetterPseudoElement* element) {
diff --git a/third_party/WebKit/Source/core/layout/LayoutVideo.cpp b/third_party/WebKit/Source/core/layout/LayoutVideo.cpp
index 22f7cb4..34473ab 100644
--- a/third_party/WebKit/Source/core/layout/LayoutVideo.cpp
+++ b/third_party/WebKit/Source/core/layout/LayoutVideo.cpp
@@ -108,8 +108,10 @@
   return DefaultSize();
 }
 
-void LayoutVideo::ImageChanged(WrappedImagePtr new_image, const IntRect* rect) {
-  LayoutMedia::ImageChanged(new_image, rect);
+void LayoutVideo::ImageChanged(WrappedImagePtr new_image,
+                               CanDeferInvalidation defer,
+                               const IntRect* rect) {
+  LayoutMedia::ImageChanged(new_image, defer, rect);
 
   // Cache the image intrinsic size so we can continue to use it to draw the
   // image correctly even if we know the video intrinsic size but aren't able to
diff --git a/third_party/WebKit/Source/core/layout/LayoutVideo.h b/third_party/WebKit/Source/core/layout/LayoutVideo.h
index 625a3d6..5ede5ae 100644
--- a/third_party/WebKit/Source/core/layout/LayoutVideo.h
+++ b/third_party/WebKit/Source/core/layout/LayoutVideo.h
@@ -55,7 +55,9 @@
   LayoutSize CalculateIntrinsicSize();
   void UpdateIntrinsicSize();
 
-  void ImageChanged(WrappedImagePtr, const IntRect*) override;
+  void ImageChanged(WrappedImagePtr,
+                    CanDeferInvalidation,
+                    const IntRect*) override;
 
   bool IsOfType(LayoutObjectType type) const override {
     return type == kLayoutObjectVideo || LayoutMedia::IsOfType(type);
diff --git a/third_party/WebKit/Source/core/layout/ng/README.md b/third_party/WebKit/Source/core/layout/ng/README.md
index d7f1b273..85da73a 100644
--- a/third_party/WebKit/Source/core/layout/ng/README.md
+++ b/third_party/WebKit/Source/core/layout/ng/README.md
@@ -55,8 +55,7 @@
 
 ## Block Flow Algorithm ##
 
-This section contains details specific to the
-[NGBlockLayoutAlgorithm](ng_block_layout_algorithm.h).
+Please refer to the [block flow layout docs](BlockLayout.md).
 
 ### Collapsing Margins ###
 
diff --git a/third_party/WebKit/Source/core/layout/ng/inline/ng_inline_node.cc b/third_party/WebKit/Source/core/layout/ng/inline/ng_inline_node.cc
index 5b17629..40473c64 100644
--- a/third_party/WebKit/Source/core/layout/ng/inline/ng_inline_node.cc
+++ b/third_party/WebKit/Source/core/layout/ng/inline/ng_inline_node.cc
@@ -422,7 +422,7 @@
   return Data();
 }
 
-const NGOffsetMapping& NGInlineNode::ComputeOffsetMappingIfNeeded() {
+const NGOffsetMapping* NGInlineNode::ComputeOffsetMappingIfNeeded() {
   DCHECK(!GetLayoutBlockFlow()->GetDocument().NeedsLayoutTreeUpdate());
 
   if (!Data().offset_mapping_) {
@@ -443,7 +443,7 @@
         WTF::MakeUnique<NGOffsetMapping>(mapping_builder.Build());
   }
 
-  return *Data().offset_mapping_;
+  return Data().offset_mapping_.get();
 }
 
 // Depth-first-scan of all LayoutInline and LayoutText nodes that make up this
diff --git a/third_party/WebKit/Source/core/layout/ng/inline/ng_inline_node.h b/third_party/WebKit/Source/core/layout/ng/inline/ng_inline_node.h
index 53b454d..9216fd5 100644
--- a/third_party/WebKit/Source/core/layout/ng/inline/ng_inline_node.h
+++ b/third_party/WebKit/Source/core/layout/ng/inline/ng_inline_node.h
@@ -69,7 +69,7 @@
   // Returns the DOM to text content offset mapping of this block. If it is not
   // computed before, compute and store it in NGInlineNodeData.
   // This funciton must be called with clean layout.
-  const NGOffsetMapping& ComputeOffsetMappingIfNeeded();
+  const NGOffsetMapping* ComputeOffsetMappingIfNeeded();
 
   bool IsBidiEnabled() const { return Data().is_bidi_enabled_; }
   TextDirection BaseDirection() const { return Data().BaseDirection(); }
diff --git a/third_party/WebKit/Source/core/layout/ng/inline/ng_offset_mapping.cc b/third_party/WebKit/Source/core/layout/ng/inline/ng_offset_mapping.cc
index 5d14f26..bab0dda 100644
--- a/third_party/WebKit/Source/core/layout/ng/inline/ng_offset_mapping.cc
+++ b/third_party/WebKit/Source/core/layout/ng/inline/ng_offset_mapping.cc
@@ -129,11 +129,13 @@
   if (!block_flow)
     return nullptr;
   DCHECK(block_flow->ChildrenInline());
-  // Note: We are assuming that every LayoutNGBlockFlow with inline children is
-  // laid out with NG, and hence, has offset mapping. If any change breaks this
-  // assumption (e.g., disabling NG on contenteditable), extra checking is
-  // needed here.
-  return &NGInlineNode(block_flow).ComputeOffsetMappingIfNeeded();
+  NGBlockNode block_node = NGBlockNode(block_flow);
+  if (!block_node.CanUseNewLayout())
+    return nullptr;
+  NGLayoutInputNode node = block_node.FirstChild();
+  if (node && node.IsInline())
+    return ToNGInlineNode(node).ComputeOffsetMappingIfNeeded();
+  return nullptr;
 }
 
 NGOffsetMapping::NGOffsetMapping(NGOffsetMapping&& other)
diff --git a/third_party/WebKit/Source/core/layout/ng/inline/ng_offset_mapping_test.cc b/third_party/WebKit/Source/core/layout/ng/inline/ng_offset_mapping_test.cc
index c06ab27..de00c266 100644
--- a/third_party/WebKit/Source/core/layout/ng/inline/ng_offset_mapping_test.cc
+++ b/third_party/WebKit/Source/core/layout/ng/inline/ng_offset_mapping_test.cc
@@ -37,7 +37,10 @@
   }
 
   const NGOffsetMapping& GetOffsetMapping() const {
-    return NGInlineNode(layout_block_flow_).ComputeOffsetMappingIfNeeded();
+    const NGOffsetMapping* map =
+        NGInlineNode(layout_block_flow_).ComputeOffsetMappingIfNeeded();
+    CHECK(map);
+    return *map;
   }
 
   bool IsOffsetMappingStored() const {
diff --git a/third_party/WebKit/Source/core/layout/ng/ng_block_layout_algorithm.h b/third_party/WebKit/Source/core/layout/ng/ng_block_layout_algorithm.h
index 33b7989..f2067c0 100644
--- a/third_party/WebKit/Source/core/layout/ng/ng_block_layout_algorithm.h
+++ b/third_party/WebKit/Source/core/layout/ng/ng_block_layout_algorithm.h
@@ -126,7 +126,7 @@
       NGLayoutInputNode child,
       NGBreakToken* child_break_token,
       NGPreviousInflowPosition*,
-      RefPtr<NGBreakToken>* previous_inline_break_token);
+      scoped_refptr<NGBreakToken>* previous_inline_break_token);
 
   // Performs the actual layout of a new formatting context. This may be called
   // multiple times from HandleNewFormattingContext.
@@ -143,7 +143,7 @@
   bool HandleInflow(NGLayoutInputNode child,
                     NGBreakToken* child_break_token,
                     NGPreviousInflowPosition*,
-                    RefPtr<NGBreakToken>* previous_inline_break_token);
+                    scoped_refptr<NGBreakToken>* previous_inline_break_token);
 
   // Return the amount of block space available in the current fragmentainer
   // for the node being laid out by this algorithm.
diff --git a/third_party/WebKit/Source/core/layout/svg/LayoutSVGImage.cpp b/third_party/WebKit/Source/core/layout/svg/LayoutSVGImage.cpp
index 06cce25..a70e461 100644
--- a/third_party/WebKit/Source/core/layout/svg/LayoutSVGImage.cpp
+++ b/third_party/WebKit/Source/core/layout/svg/LayoutSVGImage.cpp
@@ -185,7 +185,9 @@
   return false;
 }
 
-void LayoutSVGImage::ImageChanged(WrappedImagePtr, const IntRect*) {
+void LayoutSVGImage::ImageChanged(WrappedImagePtr,
+                                  CanDeferInvalidation defer,
+                                  const IntRect*) {
   // Notify parent resources that we've changed. This also invalidates
   // references from resources (filters) that may have a cached
   // representation of this image/layout object.
diff --git a/third_party/WebKit/Source/core/layout/svg/LayoutSVGImage.h b/third_party/WebKit/Source/core/layout/svg/LayoutSVGImage.h
index d9c13a8..fdb4613 100644
--- a/third_party/WebKit/Source/core/layout/svg/LayoutSVGImage.h
+++ b/third_party/WebKit/Source/core/layout/svg/LayoutSVGImage.h
@@ -62,7 +62,9 @@
                        const LayoutPoint& additional_offset,
                        IncludeBlockVisualOverflowOrNot) const override;
 
-  void ImageChanged(WrappedImagePtr, const IntRect* = nullptr) override;
+  void ImageChanged(WrappedImagePtr,
+                    CanDeferInvalidation,
+                    const IntRect* = nullptr) override;
 
   void UpdateLayout() override;
   void Paint(const PaintInfo&, const LayoutPoint&) const override;
diff --git a/third_party/WebKit/Source/core/layout/svg/LayoutSVGResourceClipper.cpp b/third_party/WebKit/Source/core/layout/svg/LayoutSVGResourceClipper.cpp
index 07179f2..2ed15e4 100644
--- a/third_party/WebKit/Source/core/layout/svg/LayoutSVGResourceClipper.cpp
+++ b/third_party/WebKit/Source/core/layout/svg/LayoutSVGResourceClipper.cpp
@@ -210,13 +210,7 @@
   if (cached_paint_record_)
     return cached_paint_record_;
 
-  // Using strokeBoundingBox (instead of visualRectInLocalSVGCoordinates) to
-  // avoid the intersection with local clips/mask, which may yield incorrect
-  // results when mixing objectBoundingBox and userSpaceOnUse units
-  // (http://crbug.com/294900).
-  FloatRect bounds = StrokeBoundingBox();
-
-  PaintRecordBuilder builder(bounds, nullptr, nullptr);
+  PaintRecordBuilder builder(nullptr, nullptr);
   // Switch to a paint behavior where all children of this <clipPath> will be
   // laid out using special constraints:
   // - fill-opacity/stroke-opacity/opacity set to 1
diff --git a/third_party/WebKit/Source/core/layout/svg/LayoutSVGResourceMasker.cpp b/third_party/WebKit/Source/core/layout/svg/LayoutSVGResourceMasker.cpp
index ac9a7205..f5c44c7 100644
--- a/third_party/WebKit/Source/core/layout/svg/LayoutSVGResourceMasker.cpp
+++ b/third_party/WebKit/Source/core/layout/svg/LayoutSVGResourceMasker.cpp
@@ -71,14 +71,7 @@
     return cached_paint_record_;
 
   SubtreeContentTransformScope content_transform_scope(content_transformation);
-
-  // Using strokeBoundingBox instead of visualRectInLocalCoordinates
-  // to avoid the intersection with local clips/mask, which may yield incorrect
-  // results when mixing objectBoundingBox and userSpaceOnUse units.
-  // http://crbug.com/294900
-  FloatRect bounds = StrokeBoundingBox();
-
-  PaintRecordBuilder builder(bounds, nullptr, &context);
+  PaintRecordBuilder builder(nullptr, &context);
 
   ColorFilter mask_content_filter =
       Style()->SvgStyle().ColorInterpolation() == CI_LINEARRGB
diff --git a/third_party/WebKit/Source/core/layout/svg/LayoutSVGResourcePattern.cpp b/third_party/WebKit/Source/core/layout/svg/LayoutSVGResourcePattern.cpp
index 855718b..952642ef 100644
--- a/third_party/WebKit/Source/core/layout/svg/LayoutSVGResourcePattern.cpp
+++ b/third_party/WebKit/Source/core/layout/svg/LayoutSVGResourcePattern.cpp
@@ -214,7 +214,7 @@
 
   SubtreeContentTransformScope content_transform_scope(content_transform);
 
-  PaintRecordBuilder builder(bounds);
+  PaintRecordBuilder builder;
   for (LayoutObject* child = pattern_layout_object->FirstChild(); child;
        child = child->NextSibling())
     SVGPaintContext::PaintResourceSubtree(builder.Context(), child);
diff --git a/third_party/WebKit/Source/core/loader/BaseFetchContext.cpp b/third_party/WebKit/Source/core/loader/BaseFetchContext.cpp
index 6e19feb5..be32da2 100644
--- a/third_party/WebKit/Source/core/loader/BaseFetchContext.cpp
+++ b/third_party/WebKit/Source/core/loader/BaseFetchContext.cpp
@@ -211,6 +211,15 @@
       break;
   }
 
+  // User Agent CSS stylesheets should only support loading images and should be
+  // restricted to data urls.
+  if (options.initiator_info.name == FetchInitiatorTypeNames::uacss) {
+    if (type == Resource::kImage && url.ProtocolIsData()) {
+      return ResourceRequestBlockedReason::kNone;
+    }
+    return ResourceRequestBlockedReason::kOther;
+  }
+
   WebURLRequest::RequestContext request_context =
       resource_request.GetRequestContext();
 
diff --git a/third_party/WebKit/Source/core/loader/BaseFetchContextTest.cpp b/third_party/WebKit/Source/core/loader/BaseFetchContextTest.cpp
index 1be4a98..ec952cd0 100644
--- a/third_party/WebKit/Source/core/loader/BaseFetchContextTest.cpp
+++ b/third_party/WebKit/Source/core/loader/BaseFetchContextTest.cpp
@@ -31,6 +31,7 @@
 #include "core/loader/BaseFetchContext.h"
 
 #include "core/testing/NullExecutionContext.h"
+#include "platform/loader/fetch/fetch_initiator_type_names.h"
 #include "platform/testing/RuntimeEnabledFeaturesTestHelpers.h"
 #include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
@@ -387,4 +388,57 @@
                 ResourceRequest::RedirectStatus::kFollowedRedirect));
 }
 
+// Test that User Agent CSS can only load images with data urls.
+TEST_F(BaseFetchContextTest, UACSSTest) {
+  KURL test_url("https://example.com");
+  KURL data_url("data:image/png;base64,test");
+
+  ResourceRequest resource_request(test_url);
+  ResourceLoaderOptions options;
+  options.initiator_info.name = FetchInitiatorTypeNames::uacss;
+
+  EXPECT_EQ(ResourceRequestBlockedReason::kOther,
+            fetch_context_->CanRequest(
+                Resource::kScript, resource_request, test_url, options,
+                SecurityViolationReportingPolicy::kReport,
+                FetchParameters::kUseDefaultOriginRestrictionForType,
+                ResourceRequest::RedirectStatus::kFollowedRedirect));
+
+  EXPECT_EQ(ResourceRequestBlockedReason::kOther,
+            fetch_context_->CanRequest(
+                Resource::kImage, resource_request, test_url, options,
+                SecurityViolationReportingPolicy::kReport,
+                FetchParameters::kUseDefaultOriginRestrictionForType,
+                ResourceRequest::RedirectStatus::kFollowedRedirect));
+
+  EXPECT_EQ(ResourceRequestBlockedReason::kNone,
+            fetch_context_->CanRequest(
+                Resource::kImage, resource_request, data_url, options,
+                SecurityViolationReportingPolicy::kReport,
+                FetchParameters::kUseDefaultOriginRestrictionForType,
+                ResourceRequest::RedirectStatus::kFollowedRedirect));
+}
+
+// Test that User Agent CSS can bypass CSP to load embedded images.
+TEST_F(BaseFetchContextTest, UACSSTest_BypassCSP) {
+  ContentSecurityPolicy* policy =
+      execution_context_->GetContentSecurityPolicy();
+  policy->DidReceiveHeader("default-src 'self'",
+                           kContentSecurityPolicyHeaderTypeEnforce,
+                           kContentSecurityPolicyHeaderSourceHTTP);
+
+  KURL data_url("data:image/png;base64,test");
+
+  ResourceRequest resource_request(data_url);
+  ResourceLoaderOptions options;
+  options.initiator_info.name = FetchInitiatorTypeNames::uacss;
+
+  EXPECT_EQ(ResourceRequestBlockedReason::kNone,
+            fetch_context_->CanRequest(
+                Resource::kImage, resource_request, data_url, options,
+                SecurityViolationReportingPolicy::kReport,
+                FetchParameters::kUseDefaultOriginRestrictionForType,
+                ResourceRequest::RedirectStatus::kFollowedRedirect));
+}
+
 }  // namespace blink
diff --git a/third_party/WebKit/Source/core/loader/ImageLoader.cpp b/third_party/WebKit/Source/core/loader/ImageLoader.cpp
index 6cf7864..11a39eec 100644
--- a/third_party/WebKit/Source/core/loader/ImageLoader.cpp
+++ b/third_party/WebKit/Source/core/loader/ImageLoader.cpp
@@ -569,7 +569,9 @@
   return (IsHTMLObjectElement(element_) || IsHTMLEmbedElement(element_));
 }
 
-void ImageLoader::ImageChanged(ImageResourceContent* content, const IntRect*) {
+void ImageLoader::ImageChanged(ImageResourceContent* content,
+                               CanDeferInvalidation,
+                               const IntRect*) {
   DCHECK_EQ(content, image_content_.Get());
   if (image_complete_ || !content->IsLoading() ||
       delay_until_image_notify_finished_)
diff --git a/third_party/WebKit/Source/core/loader/ImageLoader.h b/third_party/WebKit/Source/core/loader/ImageLoader.h
index 90c264dd..86ef281 100644
--- a/third_party/WebKit/Source/core/loader/ImageLoader.h
+++ b/third_party/WebKit/Source/core/loader/ImageLoader.h
@@ -122,7 +122,9 @@
   ScriptPromise Decode(ScriptState*, ExceptionState&);
 
  protected:
-  void ImageChanged(ImageResourceContent*, const IntRect*) override;
+  void ImageChanged(ImageResourceContent*,
+                    CanDeferInvalidation,
+                    const IntRect*) override;
   void ImageNotifyFinished(ImageResourceContent*) override;
 
  private:
diff --git a/third_party/WebKit/Source/core/loader/SubresourceIntegrityHelper.cpp b/third_party/WebKit/Source/core/loader/SubresourceIntegrityHelper.cpp
index a5781d7..6187fe8 100644
--- a/third_party/WebKit/Source/core/loader/SubresourceIntegrityHelper.cpp
+++ b/third_party/WebKit/Source/core/loader/SubresourceIntegrityHelper.cpp
@@ -6,7 +6,6 @@
 
 #include "core/dom/ExecutionContext.h"
 #include "core/frame/UseCounter.h"
-#include "core/inspector/ConsoleMessage.h"
 #include "core/inspector/ConsoleTypes.h"
 
 namespace blink {
@@ -37,9 +36,20 @@
   for (auto feature : report_info.UseCounts()) {
     UseCounter::Count(&execution_context, GetWebFeature(feature));
   }
+  HeapVector<Member<ConsoleMessage>> messages;
+  GetConsoleMessages(report_info, &messages);
+  for (const auto& message : messages) {
+    execution_context.AddConsoleMessage(message);
+  }
+}
+
+void SubresourceIntegrityHelper::GetConsoleMessages(
+    const SubresourceIntegrity::ReportInfo& report_info,
+    HeapVector<Member<ConsoleMessage>>* messages) {
+  DCHECK(messages);
   for (const auto& message : report_info.ConsoleErrorMessages()) {
-    execution_context.AddConsoleMessage(ConsoleMessage::Create(
-        kSecurityMessageSource, kErrorMessageLevel, message));
+    messages->push_back(ConsoleMessage::Create(kSecurityMessageSource,
+                                               kErrorMessageLevel, message));
   }
 }
 
diff --git a/third_party/WebKit/Source/core/loader/SubresourceIntegrityHelper.h b/third_party/WebKit/Source/core/loader/SubresourceIntegrityHelper.h
index 566843f..d8f1daa 100644
--- a/third_party/WebKit/Source/core/loader/SubresourceIntegrityHelper.h
+++ b/third_party/WebKit/Source/core/loader/SubresourceIntegrityHelper.h
@@ -6,6 +6,7 @@
 #define SubresourceIntegrityHelper_h
 
 #include "core/CoreExport.h"
+#include "core/inspector/ConsoleMessage.h"
 #include "platform/loader/SubresourceIntegrity.h"
 #include "platform/wtf/Allocator.h"
 
@@ -19,6 +20,9 @@
  public:
   static void DoReport(ExecutionContext&,
                        const SubresourceIntegrity::ReportInfo&);
+
+  static void GetConsoleMessages(const SubresourceIntegrity::ReportInfo&,
+                                 HeapVector<Member<ConsoleMessage>>*);
 };
 
 }  // namespace blink
diff --git a/third_party/WebKit/Source/core/loader/modulescript/DocumentModuleScriptFetcher.cpp b/third_party/WebKit/Source/core/loader/modulescript/DocumentModuleScriptFetcher.cpp
index d1e76be..000b9da 100644
--- a/third_party/WebKit/Source/core/loader/modulescript/DocumentModuleScriptFetcher.cpp
+++ b/third_party/WebKit/Source/core/loader/modulescript/DocumentModuleScriptFetcher.cpp
@@ -6,6 +6,7 @@
 
 #include "core/dom/ExecutionContext.h"
 #include "core/inspector/ConsoleMessage.h"
+#include "core/loader/SubresourceIntegrityHelper.h"
 #include "platform/loader/fetch/FetchUtils.h"
 #include "platform/network/mime/MIMETypeRegistry.h"
 
@@ -21,8 +22,15 @@
 
   DCHECK(error_messages);
 
+  if (resource) {
+    SubresourceIntegrityHelper::GetConsoleMessages(
+        resource->IntegrityReportInfo(), error_messages);
+  }
+
   // - response's type is "error"
-  if (!resource || resource->ErrorOccurred()) {
+  if (!resource || resource->ErrorOccurred() ||
+      resource->IntegrityDisposition() !=
+          ResourceIntegrityDisposition::kPassed) {
     return false;
   }
 
diff --git a/third_party/WebKit/Source/core/loader/modulescript/ModuleScriptLoader.cpp b/third_party/WebKit/Source/core/loader/modulescript/ModuleScriptLoader.cpp
index 8ddb6655..b068692 100644
--- a/third_party/WebKit/Source/core/loader/modulescript/ModuleScriptLoader.cpp
+++ b/third_party/WebKit/Source/core/loader/modulescript/ModuleScriptLoader.cpp
@@ -23,9 +23,13 @@
 namespace blink {
 
 ModuleScriptLoader::ModuleScriptLoader(Modulator* modulator,
+                                       const ScriptFetchOptions& options,
                                        ModuleScriptLoaderRegistry* registry,
                                        ModuleScriptLoaderClient* client)
-    : modulator_(modulator), registry_(registry), client_(client) {
+    : modulator_(modulator),
+      options_(options),
+      registry_(registry),
+      client_(client) {
   DCHECK(modulator);
   DCHECK(registry);
   DCHECK(client);
@@ -78,9 +82,6 @@
                                ModuleGraphLevel level) {
   // https://html.spec.whatwg.org/#fetch-a-single-module-script
 
-  // Save "options" for its use in Step 8-.
-  options_ = module_request.Options();
-
   // Step 4. "Set moduleMap[url] to "fetching"." [spec text]
   AdvanceState(State::kFetching);
 
@@ -99,10 +100,6 @@
   // [SMSR]
   // https://html.spec.whatwg.org/multipage/webappapis.html#set-up-the-module-script-request
 
-  // [SMSR] "... its integrity metadata to options's integrity metadata, ..."
-  // [spec text]
-  // TODO(kouhei): Implement.
-
   // [SMSR] "... its parser metadata to options's parser metadata, ..."
   // [spec text]
   options.parser_disposition = options_.ParserState();
@@ -121,6 +118,12 @@
   // Note: |options| should not be modified after here.
   FetchParameters fetch_params(resource_request, options);
 
+  // [SMSR] "... its integrity metadata to options's integrity metadata, ..."
+  // [spec text]
+  fetch_params.SetIntegrityMetadata(options_.GetIntegrityMetadata());
+  fetch_params.MutableResourceRequest().SetFetchIntegrity(
+      options_.GetIntegrityAttributeValue());
+
   // [SMSR] "Set request's cryptographic nonce metadata to options's
   // cryptographic nonce, ..." [spec text]
   fetch_params.SetContentSecurityPolicyNonce(options_.Nonce());
diff --git a/third_party/WebKit/Source/core/loader/modulescript/ModuleScriptLoader.h b/third_party/WebKit/Source/core/loader/modulescript/ModuleScriptLoader.h
index 48e72ab..ae79ffd 100644
--- a/third_party/WebKit/Source/core/loader/modulescript/ModuleScriptLoader.h
+++ b/third_party/WebKit/Source/core/loader/modulescript/ModuleScriptLoader.h
@@ -45,9 +45,10 @@
 
  public:
   static ModuleScriptLoader* Create(Modulator* modulator,
+                                    const ScriptFetchOptions& options,
                                     ModuleScriptLoaderRegistry* registry,
                                     ModuleScriptLoaderClient* client) {
-    return new ModuleScriptLoader(modulator, registry, client);
+    return new ModuleScriptLoader(modulator, options, registry, client);
   }
 
   ~ModuleScriptLoader();
@@ -67,6 +68,7 @@
 
  private:
   ModuleScriptLoader(Modulator*,
+                     const ScriptFetchOptions&,
                      ModuleScriptLoaderRegistry*,
                      ModuleScriptLoaderClient*);
 
@@ -77,7 +79,7 @@
 
   Member<Modulator> modulator_;
   State state_ = State::kInitial;
-  ScriptFetchOptions options_;
+  const ScriptFetchOptions options_;
   Member<ModuleScript> module_script_;
   Member<ModuleScriptLoaderRegistry> registry_;
   Member<ModuleScriptLoaderClient> client_;
diff --git a/third_party/WebKit/Source/core/loader/modulescript/ModuleScriptLoaderRegistry.cpp b/third_party/WebKit/Source/core/loader/modulescript/ModuleScriptLoaderRegistry.cpp
index 48ee64b..cf8344f 100644
--- a/third_party/WebKit/Source/core/loader/modulescript/ModuleScriptLoaderRegistry.cpp
+++ b/third_party/WebKit/Source/core/loader/modulescript/ModuleScriptLoaderRegistry.cpp
@@ -18,7 +18,7 @@
     Modulator* modulator,
     ModuleScriptLoaderClient* client) {
   ModuleScriptLoader* loader =
-      ModuleScriptLoader::Create(modulator, this, client);
+      ModuleScriptLoader::Create(modulator, request.Options(), this, client);
   DCHECK(loader->IsInitialState());
   active_loaders_.insert(loader);
   loader->Fetch(request, level);
diff --git a/third_party/WebKit/Source/core/loader/modulescript/ModuleScriptLoaderTest.cpp b/third_party/WebKit/Source/core/loader/modulescript/ModuleScriptLoaderTest.cpp
index ee37b7a..46962dd 100644
--- a/third_party/WebKit/Source/core/loader/modulescript/ModuleScriptLoaderTest.cpp
+++ b/third_party/WebKit/Source/core/loader/modulescript/ModuleScriptLoaderTest.cpp
@@ -182,7 +182,7 @@
       GetDocument().Url(), GetDocument().UserAgent(),
       String() /* source_code */, nullptr /* cached_meta_data */,
       nullptr /* content_security_policy_parsed_headers */,
-      String() /* referrer_policy */, GetDocument().GetSecurityOrigin(),
+      GetDocument().GetReferrerPolicy(), GetDocument().GetSecurityOrigin(),
       nullptr /* worker_clients */, GetDocument().AddressSpace(),
       OriginTrialContext::GetTokens(&GetDocument()).get(),
       nullptr /* worker_settings */, kV8CacheOptionsDefault);
diff --git a/third_party/WebKit/Source/core/loader/modulescript/ModuleTreeLinker.cpp b/third_party/WebKit/Source/core/loader/modulescript/ModuleTreeLinker.cpp
index ef2122f..44bbbf9f 100644
--- a/third_party/WebKit/Source/core/loader/modulescript/ModuleTreeLinker.cpp
+++ b/third_party/WebKit/Source/core/loader/modulescript/ModuleTreeLinker.cpp
@@ -344,16 +344,26 @@
     return;
   }
 
-  // [FD] Step 6. For each url in urls, ...
+  // [FD] Step 6. Let options be the descendant script fetch options for module
+  // script's fetch options.
+  // https://html.spec.whatwg.org/multipage/webappapis.html#descendant-script-fetch-options
+  // the descendant script fetch options are a new script fetch options whose
+  // items all have the same values, except for the integrity metadata, which is
+  // instead the empty string.
+  ScriptFetchOptions options(module_script->FetchOptions().Nonce(),
+                             IntegrityMetadataSet(), String(),
+                             module_script->FetchOptions().ParserState(),
+                             module_script->FetchOptions().CredentialsMode());
+
+  // [FD] Step 7. For each url in urls, ...
   //
-  // [FD] Step 6. These invocations of the internal module script graph fetching
+  // [FD] Step 7. These invocations of the internal module script graph fetching
   // procedure should be performed in parallel to each other.
   for (size_t i = 0; i < urls.size(); ++i) {
-    // [FD] Step 6. ... perform the internal module script graph fetching
+    // [FD] Step 7. ... perform the internal module script graph fetching
     // procedure given ... with the top-level module fetch flag unset. ...
-    ModuleScriptFetchRequest request(urls[i], module_script->FetchOptions(),
-                                     module_script->BaseURL().GetString(),
-                                     positions[i]);
+    ModuleScriptFetchRequest request(
+        urls[i], options, module_script->BaseURL().GetString(), positions[i]);
     InitiateInternalModuleScriptGraphFetching(
         request, ModuleGraphLevel::kDependentModuleFetch);
   }
diff --git a/third_party/WebKit/Source/core/loader/resource/ImageResourceContent.cpp b/third_party/WebKit/Source/core/loader/resource/ImageResourceContent.cpp
index 9c43443e..85071a9 100644
--- a/third_party/WebKit/Source/core/loader/resource/ImageResourceContent.cpp
+++ b/third_party/WebKit/Source/core/loader/resource/ImageResourceContent.cpp
@@ -128,7 +128,7 @@
     return;
 
   if (image_ && !image_->IsNull()) {
-    observer->ImageChanged(this);
+    observer->ImageChanged(this, CanDeferInvalidation::kNo);
   }
 
   if (IsLoaded() && observers_.Contains(observer) &&
@@ -235,6 +235,7 @@
 
 void ImageResourceContent::NotifyObservers(
     NotifyFinishOption notifying_finish_option,
+    CanDeferInvalidation defer,
     const IntRect* change_rect) {
   {
     Vector<ImageResourceObserver*> finished_observers_as_vector;
@@ -246,7 +247,7 @@
 
     for (auto* observer : finished_observers_as_vector) {
       if (finished_observers_.Contains(observer))
-        observer->ImageChanged(this, change_rect);
+        observer->ImageChanged(this, defer, change_rect);
     }
   }
   {
@@ -259,7 +260,7 @@
 
     for (auto* observer : observers_as_vector) {
       if (observers_.Contains(observer)) {
-        observer->ImageChanged(this, change_rect);
+        observer->ImageChanged(this, defer, change_rect);
         if (notifying_finish_option == kShouldNotifyFinish &&
             observers_.Contains(observer) &&
             !info_->SchedulingReloadOrShouldReloadBrokenPlaceholder()) {
@@ -368,7 +369,7 @@
   CHECK_EQ(size_available_, Image::kSizeAvailableAndLoadingAsynchronously);
   size_available_ = Image::kSizeAvailable;
   UpdateToLoadedContentStatus(ResourceStatus::kCached);
-  NotifyObservers(kShouldNotifyFinish);
+  NotifyObservers(kShouldNotifyFinish, CanDeferInvalidation::kNo);
 }
 
 ImageResourceContent::UpdateImageResult ImageResourceContent::UpdateImage(
@@ -448,12 +449,16 @@
   // In the case of kSizeAvailableAndLoadingAsynchronously, we are waiting for
   // SVG image completion, and thus we notify observers of kDoNotNotifyFinish
   // here, and will notify observers of finish later in AsyncLoadCompleted().
+  //
+  // Don't allow defering of invalidation if it resulted from a data update.
+  // This is necessary to ensure that all PaintImages in a recording committed
+  // to the compositor have the same data.
   if (all_data_received &&
       size_available_ != Image::kSizeAvailableAndLoadingAsynchronously) {
     UpdateToLoadedContentStatus(status);
-    NotifyObservers(kShouldNotifyFinish);
+    NotifyObservers(kShouldNotifyFinish, CanDeferInvalidation::kNo);
   } else {
-    NotifyObservers(kDoNotNotifyFinish);
+    NotifyObservers(kDoNotNotifyFinish, CanDeferInvalidation::kNo);
   }
 
   return UpdateImageResult::kNoDecodeError;
@@ -489,7 +494,7 @@
 void ImageResourceContent::AnimationAdvanced(const blink::Image* image) {
   if (!image || image != image_)
     return;
-  NotifyObservers(kDoNotNotifyFinish);
+  NotifyObservers(kDoNotNotifyFinish, CanDeferInvalidation::kYes);
 }
 
 void ImageResourceContent::UpdateImageAnimationPolicy() {
@@ -517,7 +522,7 @@
                                          const IntRect& rect) {
   if (!image || image != image_)
     return;
-  NotifyObservers(kDoNotNotifyFinish, &rect);
+  NotifyObservers(kDoNotNotifyFinish, CanDeferInvalidation::kYes, &rect);
 }
 
 bool ImageResourceContent::IsAccessAllowed(SecurityOrigin* security_origin) {
diff --git a/third_party/WebKit/Source/core/loader/resource/ImageResourceContent.h b/third_party/WebKit/Source/core/loader/resource/ImageResourceContent.h
index 8bc5924..d5e6650 100644
--- a/third_party/WebKit/Source/core/loader/resource/ImageResourceContent.h
+++ b/third_party/WebKit/Source/core/loader/resource/ImageResourceContent.h
@@ -7,6 +7,7 @@
 
 #include <memory>
 #include "core/CoreExport.h"
+#include "core/loader/resource/ImageResourceObserver.h"
 #include "platform/geometry/IntRect.h"
 #include "platform/graphics/Image.h"
 #include "platform/graphics/ImageObserver.h"
@@ -173,6 +174,8 @@
   }
 
  private:
+  using CanDeferInvalidation = ImageResourceObserver::CanDeferInvalidation;
+
   explicit ImageResourceContent(scoped_refptr<blink::Image> = nullptr);
 
   // ImageObserver
@@ -189,6 +192,7 @@
 
   // If not null, changeRect is the changed part of the image.
   void NotifyObservers(NotifyFinishOption,
+                       CanDeferInvalidation,
                        const IntRect* change_rect = nullptr);
   void MarkObserverFinished(ImageResourceObserver*);
   void UpdateToLoadedContentStatus(ResourceStatus);
diff --git a/third_party/WebKit/Source/core/loader/resource/ImageResourceObserver.h b/third_party/WebKit/Source/core/loader/resource/ImageResourceObserver.h
index d7f9739c..7d014cd 100644
--- a/third_party/WebKit/Source/core/loader/resource/ImageResourceObserver.h
+++ b/third_party/WebKit/Source/core/loader/resource/ImageResourceObserver.h
@@ -36,16 +36,29 @@
 
 class CORE_EXPORT ImageResourceObserver {
  public:
+  // Used to notify the observers whether the invalidation resulting from an
+  // image change notification can be deferred. In cases where the image is
+  // changing as a result of an animation, its performant to avoid continuous
+  // invalidations of offscreen content.
+  // Note that the observer can ignore kYes and perform an immediate
+  // invalidation, but kNo must be strictly enforced, i.e., if specified the
+  // invalidation can not be deferred.
+  enum class CanDeferInvalidation { kYes, kNo };
+
   virtual ~ImageResourceObserver() {}
 
   // Called whenever a frame of an image changes, either because we got more
   // data from the network or because we are animating. If not null, the IntRect
   // is the changed rect of the image.
-  virtual void ImageChanged(ImageResourceContent*, const IntRect* = nullptr) {}
+  virtual void ImageChanged(ImageResourceContent*,
+                            CanDeferInvalidation,
+                            const IntRect* = nullptr) {}
 
   // Sub-classes that have an associated image need to override this function
   // to get notified of any image change.
-  virtual void ImageChanged(WrappedImagePtr, const IntRect* = nullptr) {}
+  virtual void ImageChanged(WrappedImagePtr,
+                            CanDeferInvalidation,
+                            const IntRect* = nullptr) {}
 
   // Called just after imageChanged() if all image data is received or errored.
   // TODO(hiroshige): Merge imageNotifyFinished() into imageChanged().
diff --git a/third_party/WebKit/Source/core/loader/resource/ImageResourceTest.cpp b/third_party/WebKit/Source/core/loader/resource/ImageResourceTest.cpp
index 914713c..7d95fa81 100644
--- a/third_party/WebKit/Source/core/loader/resource/ImageResourceTest.cpp
+++ b/third_party/WebKit/Source/core/loader/resource/ImageResourceTest.cpp
@@ -1924,5 +1924,24 @@
   WTF::SetTimeFunctionsForTesting(nullptr);
 }
 
+TEST(ImageResourceTest, DeferredInvalidation) {
+  ImageResource* image_resource = ImageResource::CreateForTest(NullURL());
+  std::unique_ptr<MockImageResourceObserver> obs =
+      MockImageResourceObserver::Create(image_resource->GetContent());
+
+  // Image loaded.
+  ReceiveResponse(image_resource, NullURL(), "image/jpeg",
+                  reinterpret_cast<const char*>(kJpegImage),
+                  sizeof(kJpegImage));
+  EXPECT_EQ(obs->ImageChangedCount(), 2);
+  EXPECT_EQ(obs->Defer(), ImageResourceObserver::CanDeferInvalidation::kNo);
+
+  // Image animated.
+  static_cast<ImageObserver*>(image_resource->GetContent())
+      ->AnimationAdvanced(image_resource->GetContent()->GetImage());
+  EXPECT_EQ(obs->ImageChangedCount(), 3);
+  EXPECT_EQ(obs->Defer(), ImageResourceObserver::CanDeferInvalidation::kYes);
+}
+
 }  // namespace
 }  // namespace blink
diff --git a/third_party/WebKit/Source/core/loader/resource/MockImageResourceObserver.cpp b/third_party/WebKit/Source/core/loader/resource/MockImageResourceObserver.cpp
index 4f9ff90..bcece60 100644
--- a/third_party/WebKit/Source/core/loader/resource/MockImageResourceObserver.cpp
+++ b/third_party/WebKit/Source/core/loader/resource/MockImageResourceObserver.cpp
@@ -32,10 +32,12 @@
 }
 
 void MockImageResourceObserver::ImageChanged(ImageResourceContent* image,
+                                             CanDeferInvalidation defer,
                                              const IntRect*) {
   image_changed_count_++;
   image_width_on_last_image_changed_ =
       content_->HasImage() ? content_->GetImage()->width() : 0;
+  defer_ = defer;
 }
 
 void MockImageResourceObserver::ImageNotifyFinished(
diff --git a/third_party/WebKit/Source/core/loader/resource/MockImageResourceObserver.h b/third_party/WebKit/Source/core/loader/resource/MockImageResourceObserver.h
index 6b3918dc..7bef757 100644
--- a/third_party/WebKit/Source/core/loader/resource/MockImageResourceObserver.h
+++ b/third_party/WebKit/Source/core/loader/resource/MockImageResourceObserver.h
@@ -36,16 +36,21 @@
     return status_on_image_notify_finished_;
   }
 
+  CanDeferInvalidation Defer() const { return defer_; }
+
  private:
   explicit MockImageResourceObserver(ImageResourceContent*);
 
   // ImageResourceObserver overrides.
   void ImageNotifyFinished(ImageResourceContent*) override;
-  void ImageChanged(ImageResourceContent*, const IntRect*) override;
+  void ImageChanged(ImageResourceContent*,
+                    CanDeferInvalidation,
+                    const IntRect*) override;
   String DebugName() const override { return "MockImageResourceObserver"; }
 
   Persistent<ImageResourceContent> content_;
   int image_changed_count_;
+  CanDeferInvalidation defer_;
   int image_width_on_last_image_changed_;
   int image_notify_finished_count_;
   int image_width_on_image_notify_finished_;
diff --git a/third_party/WebKit/Source/core/page/ContextMenuClient.cpp b/third_party/WebKit/Source/core/page/ContextMenuClient.cpp
index 1cb6169..90d5561 100644
--- a/third_party/WebKit/Source/core/page/ContextMenuClient.cpp
+++ b/third_party/WebKit/Source/core/page/ContextMenuClient.cpp
@@ -30,6 +30,9 @@
 
 #include "core/page/ContextMenuClient.h"
 
+#include <algorithm>
+#include <utility>
+
 #include "bindings/core/v8/ExceptionState.h"
 #include "core/CSSPropertyNames.h"
 #include "core/css/CSSStyleDeclaration.h"
@@ -361,13 +364,8 @@
         UrlFromFrame(ToLocalFrame(web_view_->GetPage()->MainFrame()));
   }
 
-  if (selected_frame != web_view_->GetPage()->MainFrame()) {
+  if (selected_frame != web_view_->GetPage()->MainFrame())
     data.frame_url = UrlFromFrame(selected_frame);
-    HistoryItem* history_item =
-        selected_frame->Loader().GetDocumentLoader()->GetHistoryItem();
-    if (history_item)
-      data.frame_history_item = WebHistoryItem(history_item);
-  }
 
   // HitTestResult::isSelected() ensures clean layout by performing a hit test.
   if (r.IsSelected())
diff --git a/third_party/WebKit/Source/core/page/DragController.cpp b/third_party/WebKit/Source/core/page/DragController.cpp
index d269b8e..af7145c3 100644
--- a/third_party/WebKit/Source/core/page/DragController.cpp
+++ b/third_party/WebKit/Source/core/page/DragController.cpp
@@ -1138,8 +1138,7 @@
   GlobalPaintFlags paint_flags =
       kGlobalPaintSelectionOnly | kGlobalPaintFlattenCompositingLayers;
 
-  PaintRecordBuilder builder(
-      DataTransfer::DeviceSpaceRect(painting_rect, frame));
+  PaintRecordBuilder builder;
   frame.View()->PaintContents(builder.Context(), paint_flags,
                               EnclosingIntRect(painting_rect));
   return DataTransfer::CreateDragImageForFrame(
diff --git a/third_party/WebKit/Source/core/page/PageWidgetDelegate.cpp b/third_party/WebKit/Source/core/page/PageWidgetDelegate.cpp
index 9fa399b7..99a27c2 100644
--- a/third_party/WebKit/Source/core/page/PageWidgetDelegate.cpp
+++ b/third_party/WebKit/Source/core/page/PageWidgetDelegate.cpp
@@ -69,9 +69,7 @@
   if (rect.IsEmpty())
     return;
 
-  IntRect int_rect(rect);
-  // TODO(enne): intRect is not correct: http://crbug.com/703231
-  PaintRecordBuilder builder(int_rect);
+  PaintRecordBuilder builder;
   {
     GraphicsContext& paint_context = builder.Context();
 
diff --git a/third_party/WebKit/Source/core/page/PrintContextTest.cpp b/third_party/WebKit/Source/core/page/PrintContextTest.cpp
index cf5877c..f60bfdc9 100644
--- a/third_party/WebKit/Source/core/page/PrintContextTest.cpp
+++ b/third_party/WebKit/Source/core/page/PrintContextTest.cpp
@@ -84,7 +84,7 @@
     IntRect page_rect(0, 0, kPageWidth, kPageHeight);
     GetPrintContext().BeginPrintMode(page_rect.Width(), page_rect.Height());
     GetDocument().View()->UpdateAllLifecyclePhases();
-    PaintRecordBuilder builder(page_rect);
+    PaintRecordBuilder builder;
     GraphicsContext& context = builder.Context();
     context.SetPrinting(true);
     GetDocument().View()->PaintContents(context, kGlobalPaintPrinting,
diff --git a/third_party/WebKit/Source/core/paint/BlockPainterTest.cpp b/third_party/WebKit/Source/core/paint/BlockPainterTest.cpp
index 971f2575..b05cfe9 100644
--- a/third_party/WebKit/Source/core/paint/BlockPainterTest.cpp
+++ b/third_party/WebKit/Source/core/paint/BlockPainterTest.cpp
@@ -64,15 +64,18 @@
   EXPECT_EQ(nullptr, root_transform->ScrollNode());
 
   // The container's background chunk should not scroll and therefore should use
-  // the root transform.
+  // the root transform. Its local transform is actually a paint offset
+  // transform.
   auto* container_transform =
-      container_chunk.properties.property_tree_state.Transform();
+      container_chunk.properties.property_tree_state.Transform()->Parent();
   EXPECT_EQ(root_transform, container_transform);
   EXPECT_EQ(nullptr, container_transform->ScrollNode());
 
   // The scroll hit test should not be scrolled and should not be clipped.
+  // Its local transform is actually a paint offset transform.
   auto* scroll_hit_test_transform =
-      scroll_hit_test_chunk.properties.property_tree_state.Transform();
+      scroll_hit_test_chunk.properties.property_tree_state.Transform()
+          ->Parent();
   EXPECT_EQ(nullptr, scroll_hit_test_transform->ScrollNode());
   EXPECT_EQ(root_transform, scroll_hit_test_transform);
   auto* scroll_hit_test_clip =
diff --git a/third_party/WebKit/Source/core/paint/BoxReflectionUtils.cpp b/third_party/WebKit/Source/core/paint/BoxReflectionUtils.cpp
index 67bb16d..c925835 100644
--- a/third_party/WebKit/Source/core/paint/BoxReflectionUtils.cpp
+++ b/third_party/WebKit/Source/core/paint/BoxReflectionUtils.cpp
@@ -58,12 +58,8 @@
   LayoutRect mask_rect(LayoutPoint(), frame_layout_rect.Size());
   LayoutRect mask_bounding_rect(mask_rect);
   mask_bounding_rect.Expand(style.ImageOutsets(mask_nine_piece));
-  FloatRect mask_bounding_float_rect(mask_bounding_rect);
 
-  // TODO(jbroman): PaintRecordBuilder + DrawingRecorder seems excessive.
-  // If NinePieceImagePainter operated on SkCanvas, we'd only need a
-  // PictureRecorder here.
-  PaintRecordBuilder builder(mask_bounding_float_rect);
+  PaintRecordBuilder builder;
   {
     GraphicsContext& context = builder.Context();
     DrawingRecorder recorder(context, layer.GetLayoutObject(),
@@ -78,7 +74,7 @@
                                  SkBlendMode::kSrcOver);
   }
   return BoxReflection(direction, offset, builder.EndRecording(),
-                       mask_bounding_float_rect);
+                       FloatRect(mask_bounding_rect));
 }
 
 }  // namespace blink
diff --git a/third_party/WebKit/Source/core/paint/ClipPathClipper.cpp b/third_party/WebKit/Source/core/paint/ClipPathClipper.cpp
index 7961d98..3a84f47 100644
--- a/third_party/WebKit/Source/core/paint/ClipPathClipper.cpp
+++ b/third_party/WebKit/Source/core/paint/ClipPathClipper.cpp
@@ -159,8 +159,8 @@
   mask_clip_recorder_.emplace(context_, layout_object_, SkBlendMode::kSrcOver,
                               1, &visual_rect);
   {
-    if (!DrawClipAsMask(target_bounding_box, visual_rect,
-                        animated_local_transform, layer_position_offset)) {
+    if (!DrawClipAsMask(target_bounding_box, animated_local_transform,
+                        layer_position_offset)) {
       // End the clip mask's compositor.
       mask_clip_recorder_.reset();
       return false;
@@ -175,14 +175,13 @@
 }
 
 bool ClipPathClipper::DrawClipAsMask(const FloatRect& target_bounding_box,
-                                     const FloatRect& target_visual_rect,
                                      const AffineTransform& local_transform,
                                      const FloatPoint& layer_position_offset) {
   if (DrawingRecorder::UseCachedDrawingIfPossible(context_, layout_object_,
                                                   DisplayItem::kSVGClip))
     return true;
 
-  PaintRecordBuilder mask_builder(target_visual_rect, nullptr, &context_);
+  PaintRecordBuilder mask_builder(nullptr, &context_);
   GraphicsContext& mask_context = mask_builder.Context();
   {
     TransformRecorder recorder(mask_context, layout_object_, local_transform);
diff --git a/third_party/WebKit/Source/core/paint/ClipPathClipper.h b/third_party/WebKit/Source/core/paint/ClipPathClipper.h
index 41bc897..e7504f6e 100644
--- a/third_party/WebKit/Source/core/paint/ClipPathClipper.h
+++ b/third_party/WebKit/Source/core/paint/ClipPathClipper.h
@@ -41,7 +41,6 @@
                      const FloatRect& visual_rect,
                      const FloatPoint& layer_position_offset);
   bool DrawClipAsMask(const FloatRect& target_bounding_box,
-                      const FloatRect& target_visual_rect,
                       const AffineTransform&,
                       const FloatPoint&);
   void FinishEffect();
diff --git a/third_party/WebKit/Source/core/paint/LayerClipRecorder.cpp b/third_party/WebKit/Source/core/paint/LayerClipRecorder.cpp
index 6356d30..d261a3e 100644
--- a/third_party/WebKit/Source/core/paint/LayerClipRecorder.cpp
+++ b/third_party/WebKit/Source/core/paint/LayerClipRecorder.cpp
@@ -63,7 +63,7 @@
 void LayerClipRecorder::CollectRoundedRectClips(
     const PaintLayer& paint_layer,
     const PaintLayer* clip_root,
-    const LayoutPoint& offset_within_layer,
+    const LayoutPoint& fragment_offset,
     bool cross_composited_scrollers,
     BorderRadiusClippingRule rule,
     Vector<FloatRoundedRect>& rounded_rect_clips) {
@@ -87,7 +87,10 @@
     if (layer->GetLayoutObject().HasOverflowClip() &&
         layer->GetLayoutObject().Style()->HasBorderRadius() &&
         InContainingBlockChain(&paint_layer, layer)) {
-      LayoutPoint delta(offset_within_layer);
+      LayoutPoint delta;
+      if (layer->EnclosingPaginationLayer() ==
+          paint_layer.EnclosingPaginationLayer())
+        delta.MoveBy(fragment_offset);
       layer->ConvertToLayerCoords(clip_root, delta);
 
       // The PaintLayer's size is pixel-snapped if it is a LayoutBox. We can't
diff --git a/third_party/WebKit/Source/core/paint/LayerClipRecorder.h b/third_party/WebKit/Source/core/paint/LayerClipRecorder.h
index 62f33fd..bfe8b24a 100644
--- a/third_party/WebKit/Source/core/paint/LayerClipRecorder.h
+++ b/third_party/WebKit/Source/core/paint/LayerClipRecorder.h
@@ -55,7 +55,7 @@
 
   // Build a vector of the border radius clips that should be applied to
   // the given PaintLayer, walking up the paint layer tree to the clip_root.
-  // The offset_within_layer is an offset to apply to the clip to position it
+  // The fragment_offset is an offset to apply to the clip to position it
   // in the required clipping coordinates (for cases when the painting
   // coordinate system is offset from the layer coordinate system).
   // cross_composited_scrollers should be true when the search for clips should
@@ -66,7 +66,7 @@
   static void CollectRoundedRectClips(
       const PaintLayer&,
       const PaintLayer* clip_root,
-      const LayoutPoint& offset_within_layer,
+      const LayoutPoint& fragment_offset,
       bool cross_composited_scrollers,
       BorderRadiusClippingRule,
       Vector<FloatRoundedRect>& rounded_rect_clips);
diff --git a/third_party/WebKit/Source/core/paint/PaintPropertyTreeBuilder.cpp b/third_party/WebKit/Source/core/paint/PaintPropertyTreeBuilder.cpp
index 0868dc37..9ed0048 100644
--- a/third_party/WebKit/Source/core/paint/PaintPropertyTreeBuilder.cpp
+++ b/third_party/WebKit/Source/core/paint/PaintPropertyTreeBuilder.cpp
@@ -316,13 +316,7 @@
     const LayoutObject& object,
     PaintPropertyTreeBuilderFragmentContext& context) {
   Optional<IntPoint> paint_offset_translation;
-  if (NeedsPaintOffsetTranslation(object) &&
-      // As an optimization, skip these paint offset translation nodes when
-      // the offset is an identity. An exception is the layout view because root
-      // layer scrolling needs a transform node to ensure fixed and absolute
-      // descendants use the correct transform space.
-      (object.IsLayoutView() ||
-       context.current.paint_offset != LayoutPoint())) {
+  if (NeedsPaintOffsetTranslation(object)) {
     paint_offset_translation =
         ApplyPaintOffsetTranslation(object, context.current.paint_offset);
 
diff --git a/third_party/WebKit/Source/core/paint/PaintPropertyTreeBuilderTest.cpp b/third_party/WebKit/Source/core/paint/PaintPropertyTreeBuilderTest.cpp
index a775509..bc247cdc 100644
--- a/third_party/WebKit/Source/core/paint/PaintPropertyTreeBuilderTest.cpp
+++ b/third_party/WebKit/Source/core/paint/PaintPropertyTreeBuilderTest.cpp
@@ -1137,7 +1137,7 @@
             div_with_transform_properties->Transform()->Matrix());
   // Ensure the div's transform node is a child of the svg's transform node.
   EXPECT_EQ(svg_with_transform_properties->Transform(),
-            div_with_transform_properties->Transform()->Parent());
+            div_with_transform_properties->Transform()->Parent()->Parent());
 }
 
 TEST_P(PaintPropertyTreeBuilderTest, PaintOffsetTranslationSVGHTMLBoundary) {
@@ -1400,12 +1400,16 @@
   // ...
   //   Transform transform=translation=1.000000,2.000000,3.000000
   //     PreTranslation transform=translation=7.000000,7.000000,0.000000
-  //       ScrollTranslation transform=translation=0.000000,0.000000,0.000000
-  //         Transform transform=translation=4.000000,5.000000,6.000000
+  //       PaintOffsetTranslation transform=Identity
+  //         ScrollTranslation transform=translation=0.000000,0.000000,0.000000
+  //           Transform transform=translation=4.000000,5.000000,6.000000
   auto* inner_document_scroll_translation = inner_div_transform->Parent();
   EXPECT_EQ(TransformationMatrix().Translate3d(0, 0, 0),
             inner_document_scroll_translation->Matrix());
-  auto* iframe_pre_translation = inner_document_scroll_translation->Parent();
+  auto* paint_offset_translation = inner_document_scroll_translation->Parent();
+  auto* iframe_pre_translation =
+      inner_document_scroll_translation->Parent()->Parent();
+  EXPECT_EQ(FloatSize(), paint_offset_translation->Matrix().To2DTranslation());
   EXPECT_EQ(TransformationMatrix().Translate3d(7, 7, 0),
             iframe_pre_translation->Matrix());
   EXPECT_EQ(div_with_transform_properties->Transform(),
@@ -1782,7 +1786,7 @@
   // content).
   EXPECT_TRUE(!FrameScrollTranslation());
   EXPECT_EQ(FramePreTranslation(),
-            overflow_properties->ScrollTranslation()->Parent());
+            overflow_properties->ScrollTranslation()->Parent()->Parent());
   CHECK_EXACT_VISUAL_RECT(LayoutRect(0, 0, 50, 50), &overflow,
                           GetDocument().View()->GetLayoutView());
 
@@ -2625,12 +2629,12 @@
   b_transform_node = b_properties->Transform();
   EXPECT_EQ(TransformationMatrix().Translate(111, 222),
             b_transform_node->Matrix());
-  EXPECT_EQ(a_transform_node, b_transform_node->Parent());
+  EXPECT_EQ(a_transform_node, b_transform_node->Parent()->Parent());
 
   EXPECT_EQ(c_properties,
             c->GetLayoutObject()->FirstFragment().PaintProperties());
   EXPECT_EQ(c_transform_node, c_properties->Transform());
-  EXPECT_EQ(b_transform_node, c_transform_node->Parent());
+  EXPECT_EQ(b_transform_node, c_transform_node->Parent()->Parent());
 
   CHECK_EXACT_VISUAL_RECT(LayoutRect(33, 44, 50, 60), a->GetLayoutObject(),
                           frame_view->GetLayoutView());
@@ -2654,7 +2658,7 @@
   EXPECT_EQ(c_properties,
             c->GetLayoutObject()->FirstFragment().PaintProperties());
   EXPECT_EQ(c_transform_node, c_properties->Transform());
-  EXPECT_EQ(a_transform_node, c_transform_node->Parent());
+  EXPECT_EQ(a_transform_node, c_transform_node->Parent()->Parent());
 
   CHECK_EXACT_VISUAL_RECT(LayoutRect(33, 44, 50, 60), a->GetLayoutObject(),
                           frame_view->GetLayoutView());
@@ -2678,12 +2682,12 @@
             b->GetLayoutObject()->FirstFragment().PaintProperties());
   b_transform_node = b_properties->Transform();
   EXPECT_EQ(TransformationMatrix().Translate(4, 5), b_transform_node->Matrix());
-  EXPECT_EQ(a_transform_node, b_transform_node->Parent());
+  EXPECT_EQ(a_transform_node, b_transform_node->Parent()->Parent());
 
   EXPECT_EQ(c_properties,
             c->GetLayoutObject()->FirstFragment().PaintProperties());
   EXPECT_EQ(c_transform_node, c_properties->Transform());
-  EXPECT_EQ(b_transform_node, c_transform_node->Parent());
+  EXPECT_EQ(b_transform_node, c_transform_node->Parent()->Parent());
 
   CHECK_EXACT_VISUAL_RECT(LayoutRect(33, 44, 50, 60), a->GetLayoutObject(),
                           frame_view->GetLayoutView());
diff --git a/third_party/WebKit/Source/core/paint/SVGShapePainter.cpp b/third_party/WebKit/Source/core/paint/SVGShapePainter.cpp
index 764a7503..d9c0dbac 100644
--- a/third_party/WebKit/Source/core/paint/SVGShapePainter.cpp
+++ b/third_party/WebKit/Source/core/paint/SVGShapePainter.cpp
@@ -243,13 +243,12 @@
   if (SVGLayoutSupport::IsOverflowHidden(&marker))
     canvas->clipRect(marker.Viewport());
 
+  PaintRecordBuilder builder(nullptr, &paint_info.context);
+  PaintInfo marker_paint_info(builder.Context(), paint_info);
   // It's expensive to track the transformed paint cull rect for each
   // marker so just disable culling. The shape paint call will already
   // be culled if it is outside the paint info cull rect.
-  IntRect bounds(LayoutRect::InfiniteIntRect());
-  PaintRecordBuilder builder(FloatRect(bounds), nullptr, &paint_info.context);
-  PaintInfo marker_paint_info(builder.Context(), paint_info);
-  marker_paint_info.cull_rect_.rect_ = bounds;
+  marker_paint_info.cull_rect_.rect_ = LayoutRect::InfiniteIntRect();
 
   SVGContainerPainter(marker).Paint(marker_paint_info);
   builder.EndRecording(*canvas);
diff --git a/third_party/WebKit/Source/core/paint/ScrollableAreaPainter.cpp b/third_party/WebKit/Source/core/paint/ScrollableAreaPainter.cpp
index 1f899c57..99ce6d2 100644
--- a/third_party/WebKit/Source/core/paint/ScrollableAreaPainter.cpp
+++ b/third_party/WebKit/Source/core/paint/ScrollableAreaPainter.cpp
@@ -279,19 +279,19 @@
   context.FillRect(abs_rect, Color::kWhite);
 }
 
-void ScrollableAreaPainter::PaintScrollbar(const Scrollbar& scrollbar,
-                                           GraphicsContext& context,
-                                           const IntRect& clip) {
-  // Frame scrollbars are painted in the space of the containing frame, not the
-  // local space of the scrollbar.
+void ScrollableAreaPainter::PaintCompositedScrollbar(
+    const Scrollbar& scrollbar,
+    GraphicsContext& context,
+    const CullRect& cull_rect_arg) {
+  // Map context and cull_rect which are in the local space of the scrollbar
+  // to the space of the containing scrollable area in which Scrollbar::Paint()
+  // will paint the scrollbar.
   const IntRect& scrollbar_rect = scrollbar.FrameRect();
-  IntRect transformed_clip = clip;
-  transformed_clip.MoveBy(scrollbar_rect.Location());
-
+  CullRect cull_rect(cull_rect_arg, scrollbar_rect.Location());
   AffineTransform translation =
       AffineTransform::Translation(-scrollbar_rect.X(), -scrollbar_rect.Y());
   TransformRecorder transform_recorder(context, scrollbar, translation);
-  scrollbar.Paint(context, CullRect(transformed_clip));
+  scrollbar.Paint(context, cull_rect);
 }
 
 PaintLayerScrollableArea& ScrollableAreaPainter::GetScrollableArea() const {
diff --git a/third_party/WebKit/Source/core/paint/ScrollableAreaPainter.h b/third_party/WebKit/Source/core/paint/ScrollableAreaPainter.h
index 936ad11..91e81da 100644
--- a/third_party/WebKit/Source/core/paint/ScrollableAreaPainter.h
+++ b/third_party/WebKit/Source/core/paint/ScrollableAreaPainter.h
@@ -36,9 +36,11 @@
   void PaintScrollCorner(GraphicsContext&,
                          const IntPoint& paint_offset,
                          const CullRect&);
-  static void PaintScrollbar(const Scrollbar&,
-                             GraphicsContext&,
-                             const IntRect& clip);
+
+  // GraphicsContext and CullRect are in the local space of the scrollbar.
+  static void PaintCompositedScrollbar(const Scrollbar&,
+                                       GraphicsContext&,
+                                       const CullRect&);
 
  private:
   void DrawPlatformResizerImage(GraphicsContext&, IntRect resizer_corner_rect);
diff --git a/third_party/WebKit/Source/core/paint/compositing/CompositedLayerMapping.cpp b/third_party/WebKit/Source/core/paint/compositing/CompositedLayerMapping.cpp
index 68586a7b..93e7b9d 100644
--- a/third_party/WebKit/Source/core/paint/compositing/CompositedLayerMapping.cpp
+++ b/third_party/WebKit/Source/core/paint/compositing/CompositedLayerMapping.cpp
@@ -3492,11 +3492,15 @@
 
   PaintLayerScrollableArea* scrollable_area = owning_layer_.GetScrollableArea();
   if (graphics_layer == LayerForHorizontalScrollbar()) {
-    if (const Scrollbar* scrollbar = scrollable_area->HorizontalScrollbar())
-      ScrollableAreaPainter::PaintScrollbar(*scrollbar, context, interest_rect);
+    if (const Scrollbar* scrollbar = scrollable_area->HorizontalScrollbar()) {
+      ScrollableAreaPainter::PaintCompositedScrollbar(*scrollbar, context,
+                                                      CullRect(interest_rect));
+    }
   } else if (graphics_layer == LayerForVerticalScrollbar()) {
-    if (const Scrollbar* scrollbar = scrollable_area->VerticalScrollbar())
-      ScrollableAreaPainter::PaintScrollbar(*scrollbar, context, interest_rect);
+    if (const Scrollbar* scrollbar = scrollable_area->VerticalScrollbar()) {
+      ScrollableAreaPainter::PaintCompositedScrollbar(*scrollbar, context,
+                                                      CullRect(interest_rect));
+    }
   } else if (graphics_layer == LayerForScrollCorner()) {
     // Note that scroll corners always paint into local space, whereas
     // scrollbars paint in the space of their containing frame.
diff --git a/third_party/WebKit/Source/core/paint/compositing/PaintLayerCompositor.cpp b/third_party/WebKit/Source/core/paint/compositing/PaintLayerCompositor.cpp
index 29b0a3f..047ee05 100644
--- a/third_party/WebKit/Source/core/paint/compositing/PaintLayerCompositor.cpp
+++ b/third_party/WebKit/Source/core/paint/compositing/PaintLayerCompositor.cpp
@@ -962,7 +962,8 @@
     return;
 
   if (scrollbar) {
-    ScrollableAreaPainter::PaintScrollbar(*scrollbar, context, interest_rect);
+    ScrollableAreaPainter::PaintCompositedScrollbar(*scrollbar, context,
+                                                    CullRect(interest_rect));
   } else {
     FramePainter(*layout_view_.GetFrameView())
         .PaintScrollCorner(context, interest_rect);
diff --git a/third_party/WebKit/Source/core/svg/graphics/SVGImage.cpp b/third_party/WebKit/Source/core/svg/graphics/SVGImage.cpp
index bc27790..f02b3063 100644
--- a/third_party/WebKit/Source/core/svg/graphics/SVGImage.cpp
+++ b/third_party/WebKit/Source/core/svg/graphics/SVGImage.cpp
@@ -340,8 +340,7 @@
   FloatRect spaced_tile(tile);
   spaced_tile.Expand(FloatSize(repeat_spacing));
 
-  PaintRecordBuilder builder(spaced_tile, nullptr, &context);
-
+  PaintRecordBuilder builder(nullptr, &context);
   {
     DrawingRecorder recorder(builder.Context(), builder,
                              DisplayItem::Type::kSVGImage);
@@ -493,7 +492,7 @@
   // avoid setting timers from the latter.
   FlushPendingTimelineRewind();
 
-  PaintRecordBuilder builder(bounds, nullptr, nullptr, paint_controller_.get());
+  PaintRecordBuilder builder(nullptr, nullptr, paint_controller_.get());
 
   view->UpdateAllLifecyclePhasesExceptPaint();
   view->PaintWithLifecycleUpdate(builder.Context(), kGlobalPaintNormalPhase,
diff --git a/third_party/WebKit/Source/core/svg/graphics/filters/SVGFEImage.cpp b/third_party/WebKit/Source/core/svg/graphics/filters/SVGFEImage.cpp
index 1338c69..47d34bf 100644
--- a/third_party/WebKit/Source/core/svg/graphics/filters/SVGFEImage.cpp
+++ b/third_party/WebKit/Source/core/svg/graphics/filters/SVGFEImage.cpp
@@ -180,9 +180,7 @@
     transform.Translate(dst_rect.X(), dst_rect.Y());
   }
 
-  // TODO(chrishtr): use tighter bounds for this.
-  FloatRect bounds(LayoutRect::InfiniteIntRect());
-  PaintRecordBuilder builder(bounds);
+  PaintRecordBuilder builder;
   SVGPaintContext::PaintResourceSubtree(builder.Context(), &layout_object);
 
   PaintRecorder paint_recorder;
diff --git a/third_party/WebKit/Source/core/timing/PerformanceEntry.cpp b/third_party/WebKit/Source/core/timing/PerformanceEntry.cpp
index 64df0a78..183b210 100644
--- a/third_party/WebKit/Source/core/timing/PerformanceEntry.cpp
+++ b/third_party/WebKit/Source/core/timing/PerformanceEntry.cpp
@@ -30,13 +30,14 @@
 
 #include "core/timing/PerformanceEntry.h"
 
+#include "base/atomic_sequence_num.h"
 #include "bindings/core/v8/ScriptValue.h"
 #include "bindings/core/v8/V8ObjectBuilder.h"
 
 namespace blink {
 
 namespace {
-static size_t max_index = 0;
+static base::AtomicSequenceNumber index_seq;
 }
 
 PerformanceEntry::PerformanceEntry(const String& name,
@@ -47,9 +48,8 @@
       entry_type_(entry_type),
       start_time_(start_time),
       duration_(finish_time - start_time),
-      entry_type_enum_(ToEntryTypeEnum(entry_type)) {
-  index_ = ++max_index;
-}
+      entry_type_enum_(ToEntryTypeEnum(entry_type)),
+      index_(index_seq.GetNext()) {}
 
 PerformanceEntry::~PerformanceEntry() {}
 
diff --git a/third_party/WebKit/Source/core/timing/PerformanceEntry.h b/third_party/WebKit/Source/core/timing/PerformanceEntry.h
index 12f3d6f..31218e2 100644
--- a/third_party/WebKit/Source/core/timing/PerformanceEntry.h
+++ b/third_party/WebKit/Source/core/timing/PerformanceEntry.h
@@ -107,7 +107,7 @@
   const double start_time_;
   const double duration_;
   const PerformanceEntryType entry_type_enum_;
-  size_t index_;
+  const int index_;
 };
 
 }  // namespace blink
diff --git a/third_party/WebKit/Source/core/workers/DedicatedWorker.cpp b/third_party/WebKit/Source/core/workers/DedicatedWorker.cpp
index 33bf542..60d27dd 100644
--- a/third_party/WebKit/Source/core/workers/DedicatedWorker.cpp
+++ b/third_party/WebKit/Source/core/workers/DedicatedWorker.cpp
@@ -20,6 +20,7 @@
 #include "core/workers/WorkerScriptLoader.h"
 #include "platform/bindings/ScriptState.h"
 #include "platform/loader/fetch/ResourceFetcher.h"
+#include "platform/weborigin/SecurityPolicy.h"
 #include "public/platform/WebContentSettingsClient.h"
 #include "public/web/WebFrameClient.h"
 #include "services/network/public/interfaces/fetch_api.mojom-blink.h"
@@ -146,9 +147,15 @@
   } else if (script_loader_->Failed()) {
     DispatchEvent(Event::CreateCancelable(EventTypeNames::error));
   } else {
+    ReferrerPolicy referrer_policy = kReferrerPolicyDefault;
+    if (!script_loader_->GetReferrerPolicy().IsNull()) {
+      SecurityPolicy::ReferrerPolicyFromHeaderValue(
+          script_loader_->GetReferrerPolicy(),
+          kDoNotSupportReferrerPolicyLegacyKeywords, &referrer_policy);
+    }
     context_proxy_->StartWorkerGlobalScope(
         script_loader_->Url(), GetExecutionContext()->UserAgent(),
-        script_loader_->SourceText(), script_loader_->GetReferrerPolicy());
+        script_loader_->SourceText(), referrer_policy);
     probe::scriptImported(GetExecutionContext(), script_loader_->Identifier(),
                           script_loader_->SourceText());
   }
diff --git a/third_party/WebKit/Source/core/workers/DedicatedWorkerMessagingProxy.cpp b/third_party/WebKit/Source/core/workers/DedicatedWorkerMessagingProxy.cpp
index f81f9a0..320c940e 100644
--- a/third_party/WebKit/Source/core/workers/DedicatedWorkerMessagingProxy.cpp
+++ b/third_party/WebKit/Source/core/workers/DedicatedWorkerMessagingProxy.cpp
@@ -63,7 +63,7 @@
     const KURL& script_url,
     const String& user_agent,
     const String& source_code,
-    const String& referrer_policy) {
+    ReferrerPolicy referrer_policy) {
   DCHECK(IsParentContextThread());
   if (AskedToTerminate()) {
     // Worker.terminate() could be called from JS before the thread was
diff --git a/third_party/WebKit/Source/core/workers/DedicatedWorkerMessagingProxy.h b/third_party/WebKit/Source/core/workers/DedicatedWorkerMessagingProxy.h
index f599ffb5..aab67eca 100644
--- a/third_party/WebKit/Source/core/workers/DedicatedWorkerMessagingProxy.h
+++ b/third_party/WebKit/Source/core/workers/DedicatedWorkerMessagingProxy.h
@@ -11,6 +11,7 @@
 #include "core/workers/ThreadedMessagingProxyBase.h"
 #include "core/workers/WorkerBackingThreadStartupData.h"
 #include "platform/heap/Handle.h"
+#include "platform/weborigin/ReferrerPolicy.h"
 #include "platform/wtf/Noncopyable.h"
 #include "platform/wtf/Optional.h"
 #include "platform/wtf/RefPtr.h"
@@ -39,7 +40,7 @@
   void StartWorkerGlobalScope(const KURL& script_url,
                               const String& user_agent,
                               const String& source_code,
-                              const String& referrer_policy);
+                              ReferrerPolicy);
   void PostMessageToWorkerGlobalScope(scoped_refptr<SerializedScriptValue>,
                                       Vector<MessagePortChannel>);
 
diff --git a/third_party/WebKit/Source/core/workers/DedicatedWorkerTest.cpp b/third_party/WebKit/Source/core/workers/DedicatedWorkerTest.cpp
index 6d6ce9d..a057ff29 100644
--- a/third_party/WebKit/Source/core/workers/DedicatedWorkerTest.cpp
+++ b/third_party/WebKit/Source/core/workers/DedicatedWorkerTest.cpp
@@ -18,6 +18,7 @@
 #include "core/workers/WorkerThreadTestHelper.h"
 #include "platform/CrossThreadFunctional.h"
 #include "platform/testing/UnitTestHelpers.h"
+#include "platform/weborigin/SecurityPolicy.h"
 #include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
@@ -120,8 +121,7 @@
   void StartWithSourceCode(const String& source) {
     KURL script_url("http://fake.url/");
     security_origin_ = SecurityOrigin::Create(script_url);
-    std::unique_ptr<Vector<CSPHeaderAndType>> headers =
-        WTF::MakeUnique<Vector<CSPHeaderAndType>>();
+    auto headers = std::make_unique<Vector<CSPHeaderAndType>>();
     CSPHeaderAndType header_and_type("contentSecurityPolicy",
                                      kContentSecurityPolicyHeaderTypeReport);
     headers->push_back(header_and_type);
@@ -131,7 +131,7 @@
         std::make_unique<GlobalScopeCreationParams>(
             script_url, "fake user agent", source,
             nullptr /* cached_meta_data */, headers.get(),
-            "" /* referrer_policy */, security_origin_.get(),
+            kReferrerPolicyDefault, security_origin_.get(),
             nullptr /* worker_clients */, kWebAddressSpaceLocal,
             nullptr /* origin_trial_tokens */, std::move(worker_settings),
             kV8CacheOptionsDefault),
diff --git a/third_party/WebKit/Source/core/workers/GlobalScopeCreationParams.cpp b/third_party/WebKit/Source/core/workers/GlobalScopeCreationParams.cpp
index e4e537a..4cb26f9b 100644
--- a/third_party/WebKit/Source/core/workers/GlobalScopeCreationParams.cpp
+++ b/third_party/WebKit/Source/core/workers/GlobalScopeCreationParams.cpp
@@ -16,7 +16,7 @@
     const String& source_code,
     std::unique_ptr<Vector<char>> cached_meta_data,
     const Vector<CSPHeaderAndType>* content_security_policy_parsed_headers,
-    const String& referrer_policy,
+    ReferrerPolicy referrer_policy,
     const SecurityOrigin* starter_origin,
     WorkerClients* worker_clients,
     WebAddressSpace address_space,
@@ -29,7 +29,7 @@
       user_agent(user_agent.IsolatedCopy()),
       source_code(source_code.IsolatedCopy()),
       cached_meta_data(std::move(cached_meta_data)),
-      referrer_policy(referrer_policy.IsolatedCopy()),
+      referrer_policy(referrer_policy),
       starter_origin(starter_origin ? starter_origin->IsolatedCopy() : nullptr),
       worker_clients(worker_clients),
       address_space(address_space),
diff --git a/third_party/WebKit/Source/core/workers/GlobalScopeCreationParams.h b/third_party/WebKit/Source/core/workers/GlobalScopeCreationParams.h
index b5bc693..c5ea77c 100644
--- a/third_party/WebKit/Source/core/workers/GlobalScopeCreationParams.h
+++ b/third_party/WebKit/Source/core/workers/GlobalScopeCreationParams.h
@@ -14,6 +14,7 @@
 #include "platform/network/ContentSecurityPolicyParsers.h"
 #include "platform/network/ContentSecurityPolicyResponseHeaders.h"
 #include "platform/weborigin/KURL.h"
+#include "platform/weborigin/ReferrerPolicy.h"
 #include "platform/wtf/Forward.h"
 #include "platform/wtf/Noncopyable.h"
 #include "platform/wtf/Optional.h"
@@ -38,7 +39,7 @@
       const String& source_code,
       std::unique_ptr<Vector<char>> cached_meta_data,
       const Vector<CSPHeaderAndType>* content_security_policy_parsed_headers,
-      const String& referrer_policy,
+      ReferrerPolicy referrer_policy,
       const SecurityOrigin*,
       WorkerClients*,
       WebAddressSpace,
@@ -63,7 +64,7 @@
   WTF::Optional<ContentSecurityPolicyResponseHeaders>
       content_security_policy_raw_headers;
 
-  String referrer_policy;
+  ReferrerPolicy referrer_policy;
   std::unique_ptr<Vector<String>> origin_trial_tokens;
 
   // The SecurityOrigin of the Document creating a Worker/Worklet.
diff --git a/third_party/WebKit/Source/core/workers/MainThreadWorkletTest.cpp b/third_party/WebKit/Source/core/workers/MainThreadWorkletTest.cpp
index 543a6c44..b7227e3 100644
--- a/third_party/WebKit/Source/core/workers/MainThreadWorkletTest.cpp
+++ b/third_party/WebKit/Source/core/workers/MainThreadWorkletTest.cpp
@@ -53,7 +53,7 @@
         document->Url(), document->UserAgent(), String() /* source_code */,
         nullptr /* cached_meta_data */,
         nullptr /* content_security_policy_parsed_headers */,
-        String() /* referrer_policy */, document->GetSecurityOrigin(),
+        document->GetReferrerPolicy(), document->GetSecurityOrigin(),
         nullptr /* worker_clients */, document->AddressSpace(),
         OriginTrialContext::GetTokens(document).get(),
         nullptr /* worker_settings */, kV8CacheOptionsDefault);
diff --git a/third_party/WebKit/Source/core/workers/ThreadedWorkletMessagingProxy.cpp b/third_party/WebKit/Source/core/workers/ThreadedWorkletMessagingProxy.cpp
index 3880637..f97ddfc 100644
--- a/third_party/WebKit/Source/core/workers/ThreadedWorkletMessagingProxy.cpp
+++ b/third_party/WebKit/Source/core/workers/ThreadedWorkletMessagingProxy.cpp
@@ -37,13 +37,11 @@
   ContentSecurityPolicy* csp = document->GetContentSecurityPolicy();
   DCHECK(csp);
 
-  // TODO(nhiroki): Inherit a referrer policy from owner's document.
-  // (https://crbug.com/773921)
   auto global_scope_creation_params =
       std::make_unique<GlobalScopeCreationParams>(
           document->Url(), document->UserAgent(), String() /* source_code */,
           nullptr /* cached_meta_data */, csp->Headers().get(),
-          String() /* referrer_policy */, document->GetSecurityOrigin(),
+          document->GetReferrerPolicy(), document->GetSecurityOrigin(),
           ReleaseWorkerClients(), document->AddressSpace(),
           OriginTrialContext::GetTokens(document).get(),
           std::make_unique<WorkerSettings>(document->GetSettings()),
diff --git a/third_party/WebKit/Source/core/workers/ThreadedWorkletTest.cpp b/third_party/WebKit/Source/core/workers/ThreadedWorkletTest.cpp
index 01782897..6d29f76 100644
--- a/third_party/WebKit/Source/core/workers/ThreadedWorkletTest.cpp
+++ b/third_party/WebKit/Source/core/workers/ThreadedWorkletTest.cpp
@@ -5,6 +5,7 @@
 #include "bindings/core/v8/V8CacheOptions.h"
 #include "core/dom/TaskRunnerHelper.h"
 #include "core/inspector/ConsoleMessageStorage.h"
+#include "core/origin_trials/OriginTrialContext.h"
 #include "core/testing/DummyPageHolder.h"
 #include "core/workers/GlobalScopeCreationParams.h"
 #include "core/workers/ThreadedWorkletGlobalScope.h"
@@ -143,22 +144,20 @@
   ~ThreadedWorkletMessagingProxyForTest() override {}
 
   void Start() {
-    KURL script_url("http://fake.url/");
+    Document* document = ToDocument(GetExecutionContext());
     std::unique_ptr<Vector<char>> cached_meta_data = nullptr;
     Vector<CSPHeaderAndType> content_security_policy_headers;
-    String referrer_policy = "";
-    security_origin_ = SecurityOrigin::Create(script_url);
     WorkerClients* worker_clients = nullptr;
-    Vector<String> origin_trial_tokens;
     std::unique_ptr<WorkerSettings> worker_settings = nullptr;
     InitializeWorkerThread(
         std::make_unique<GlobalScopeCreationParams>(
-            script_url, "fake user agent", "// fake source code",
+            document->Url(), document->UserAgent(), "" /* source_code */,
             std::move(cached_meta_data), &content_security_policy_headers,
-            referrer_policy, security_origin_.get(), worker_clients,
-            kWebAddressSpaceLocal, &origin_trial_tokens,
+            document->GetReferrerPolicy(), document->GetSecurityOrigin(),
+            worker_clients, document->AddressSpace(),
+            OriginTrialContext::GetTokens(document).get(),
             std::move(worker_settings), kV8CacheOptionsDefault),
-        WTF::nullopt, script_url);
+        WTF::nullopt, document->Url());
   }
 
  private:
@@ -167,14 +166,15 @@
   std::unique_ptr<WorkerThread> CreateWorkerThread() final {
     return WTF::MakeUnique<ThreadedWorkletThreadForTest>(WorkletObjectProxy());
   }
-
-  scoped_refptr<SecurityOrigin> security_origin_;
 };
 
 class ThreadedWorkletTest : public ::testing::Test {
  public:
   void SetUp() override {
     page_ = DummyPageHolder::Create();
+    Document* document = page_->GetFrame().GetDocument();
+    document->SetURL(KURL("https://example.com/"));
+    document->UpdateSecurityOrigin(SecurityOrigin::Create(document->Url()));
     messaging_proxy_ = new ThreadedWorkletMessagingProxyForTest(
         &page_->GetDocument(), WorkerClients::Create());
     ThreadedWorkletThreadForTest::EnsureSharedBackingThread();
diff --git a/third_party/WebKit/Source/core/workers/WorkerGlobalScope.cpp b/third_party/WebKit/Source/core/workers/WorkerGlobalScope.cpp
index 226415ac..c555dc0a 100644
--- a/third_party/WebKit/Source/core/workers/WorkerGlobalScope.cpp
+++ b/third_party/WebKit/Source/core/workers/WorkerGlobalScope.cpp
@@ -390,8 +390,7 @@
   ApplyContentSecurityPolicyFromVector(
       *creation_params->content_security_policy_parsed_headers);
   SetWorkerSettings(std::move(creation_params->worker_settings));
-  if (!creation_params->referrer_policy.IsNull())
-    ParseAndSetReferrerPolicy(creation_params->referrer_policy);
+  SetReferrerPolicy(creation_params->referrer_policy);
   SetAddressSpace(creation_params->address_space);
   OriginTrialContext::AddTokens(this,
                                 creation_params->origin_trial_tokens.get());
diff --git a/third_party/WebKit/Source/core/workers/WorkerScriptLoader.h b/third_party/WebKit/Source/core/workers/WorkerScriptLoader.h
index 5dc0d94..64f83442 100644
--- a/third_party/WebKit/Source/core/workers/WorkerScriptLoader.h
+++ b/third_party/WebKit/Source/core/workers/WorkerScriptLoader.h
@@ -100,7 +100,7 @@
     return content_security_policy_.Release();
   }
 
-  String GetReferrerPolicy() { return referrer_policy_; }
+  const String& GetReferrerPolicy() const { return referrer_policy_; }
 
   WebAddressSpace ResponseAddressSpace() const {
     return response_address_space_;
diff --git a/third_party/WebKit/Source/core/workers/WorkerThreadTest.cpp b/third_party/WebKit/Source/core/workers/WorkerThreadTest.cpp
index 47b5730..d9de139 100644
--- a/third_party/WebKit/Source/core/workers/WorkerThreadTest.cpp
+++ b/third_party/WebKit/Source/core/workers/WorkerThreadTest.cpp
@@ -299,7 +299,7 @@
   auto global_scope_creation_params =
       std::make_unique<GlobalScopeCreationParams>(
           KURL("http://fake.url/"), "fake user agent", "// fake source code",
-          nullptr /* cachedMetaData */, headers.get(), "" /* referrer_policy */,
+          nullptr /* cachedMetaData */, headers.get(), kReferrerPolicyDefault,
           security_origin_.get(), nullptr /* workerClients */,
           kWebAddressSpaceLocal, nullptr /* originTrialToken */,
           std::make_unique<WorkerSettings>(Settings::Create().get()),
diff --git a/third_party/WebKit/Source/core/workers/WorkerThreadTestHelper.h b/third_party/WebKit/Source/core/workers/WorkerThreadTestHelper.h
index 3015d9d..0dc7b3ab 100644
--- a/third_party/WebKit/Source/core/workers/WorkerThreadTestHelper.h
+++ b/third_party/WebKit/Source/core/workers/WorkerThreadTestHelper.h
@@ -98,7 +98,7 @@
 
     auto creation_params = WTF::MakeUnique<GlobalScopeCreationParams>(
         KURL("http://fake.url/"), "fake user agent", source, nullptr,
-        headers.get(), "", security_origin, worker_clients,
+        headers.get(), kReferrerPolicyDefault, security_origin, worker_clients,
         kWebAddressSpaceLocal, nullptr,
         std::make_unique<WorkerSettings>(Settings::Create().get()),
         kV8CacheOptionsDefault);
diff --git a/third_party/WebKit/Source/core/workers/WorkletGlobalScope.cpp b/third_party/WebKit/Source/core/workers/WorkletGlobalScope.cpp
index b44f396..ad981abd 100644
--- a/third_party/WebKit/Source/core/workers/WorkletGlobalScope.cpp
+++ b/third_party/WebKit/Source/core/workers/WorkletGlobalScope.cpp
@@ -118,11 +118,23 @@
   // Step 2: "Let script by the result of fetch a worklet script given
   // moduleURLRecord, moduleResponsesMap, credentialOptions, outsideSettings,
   // and insideSettings when it asynchronously completes."
+
+  // [FMWST]
+  // https://html.spec.whatwg.org/multipage/webappapis.html#fetch-a-module-worker-script-tree
+  // [FMWST] Step 2: "Let options be a script fetch options whose cryptographic
+  // nonce is the empty string,
   String nonce;
+  // integrity metadata is the empty string,
+  String integrity_attribute;
+  // parser metadata is "not-parser-inserted",
   ParserDisposition parser_state = kNotParserInserted;
+  // and credentials mode is credentials mode.
+  ScriptFetchOptions options(nonce, IntegrityMetadataSet(), integrity_attribute,
+                             parser_state, credentials_mode);
+
   Modulator* modulator = Modulator::From(ScriptController()->GetScriptState());
-  // TODO(nhiroki, ikilpatrick): Update spec to use #script-fetch-options.
-  ScriptFetchOptions options(nonce, parser_state, credentials_mode);
+  // [FMWST] Step 3. "Perform the internal module script graph fetching
+  // procedure ..."
   ModuleScriptFetchRequest module_request(module_url_record, options);
 
   // Step 3 to 5 are implemented in
diff --git a/third_party/WebKit/Source/core/xml/parser/XMLParserScriptRunner.cpp b/third_party/WebKit/Source/core/xml/parser/XMLParserScriptRunner.cpp
index be437f50..43eb199 100644
--- a/third_party/WebKit/Source/core/xml/parser/XMLParserScriptRunner.cpp
+++ b/third_party/WebKit/Source/core/xml/parser/XMLParserScriptRunner.cpp
@@ -85,10 +85,8 @@
 
   if (script_loader->ReadyToBeParserExecuted()) {
     // 5th Clause, Step 23 of https://html.spec.whatwg.org/#prepare-a-script
-    script_loader->ExecuteScriptBlock(
-        ClassicPendingScript::CreateInline(script_element_base,
-                                           script_start_position),
-        document.Url());
+    script_loader->ExecuteScriptBlock(script_loader->TakePendingScript(),
+                                      document.Url());
   } else if (script_loader->WillBeParserExecuted()) {
     // 1st/2nd Clauses, Step 23 of
     // https://html.spec.whatwg.org/#prepare-a-script
diff --git a/third_party/WebKit/Source/core/xmlhttprequest/XMLHttpRequest.cpp b/third_party/WebKit/Source/core/xmlhttprequest/XMLHttpRequest.cpp
index e1e04c2..c16b0d8 100644
--- a/third_party/WebKit/Source/core/xmlhttprequest/XMLHttpRequest.cpp
+++ b/third_party/WebKit/Source/core/xmlhttprequest/XMLHttpRequest.cpp
@@ -904,8 +904,6 @@
       File* file = ToFile(body);
       if (!file->GetPath().IsEmpty())
         http_body->AppendFile(file->GetPath());
-      else if (!file->FileSystemURL().IsEmpty())
-        http_body->AppendFileSystemURL(file->FileSystemURL());
       else
         NOTREACHED();
     } else {
diff --git a/third_party/WebKit/Source/devtools/front_end/cm/PRESUBMIT.py b/third_party/WebKit/Source/devtools/front_end/cm/PRESUBMIT.py
index 6e4973c4c..354b013 100644
--- a/third_party/WebKit/Source/devtools/front_end/cm/PRESUBMIT.py
+++ b/third_party/WebKit/Source/devtools/front_end/cm/PRESUBMIT.py
@@ -32,7 +32,7 @@
                  "rolls from the upstream (http://codemirror.net). If this is a roll, "
                  "make sure you mention 'roll CodeMirror' (no quotes) in the change description.\n"
                  "CodeMirror rolling instructions:\n"
-                 "    https://sites.google.com/a/chromium.org/devtools-codemirror-rolling")
+                 "    src/third_party/WebKit/Source/devtools/front_end/cm/README.md")
     changeDescription = input_api.change.DescriptionText()
     errors = []
     if not "roll codemirror" in changeDescription.lower():
diff --git a/third_party/WebKit/Source/devtools/front_end/cm/README.md b/third_party/WebKit/Source/devtools/front_end/cm/README.md
new file mode 100644
index 0000000..68f5303
--- /dev/null
+++ b/third_party/WebKit/Source/devtools/front_end/cm/README.md
@@ -0,0 +1,36 @@
+# Rolling CodeMirror
+
+## What's this about?
+CodeMirror is a third-party library, which supports editing experience in Chrome DevTools. DevTools does not fork CodeMirror, thus all CodeMirror patches should go upstream to http://codemirror.net.
+Every once in a while, the CodeMirror dependency (which is located in Source/devtools/front_end/cm/ folder) should be updated to a newer version.
+
+## Updating CodeMirror
+This requires the following steps to be done:
+1. File `headlesscodemirror.js` is a `runmode-standalone.js` file from CodeMirror distribution, but wrapped in `(function(window) { ... }(this))`
+construction. This is needed to support in web workers.
+2. File `markselection.js` is a `mark-selection.js` from CodeMirror distribution. The "dash" is removed due to the restriction on the chromium grd generator.
+4. File codemirror.css contains both the default theme of CodeMirror and structural css required for it to work. Discard everything in the file up to the word `/* STOP */`.
+3. All other files in front_end/cm/ folder should be substituted with their newer versions from the upstream.
+
+## Testing
+DevTools wrap CodeMirror via `CodeMirrorTextEditor.js` and `cmdevtools.css` files.
+Although there are a couple of automated tests (LayoutTests/inspector/editor/) to verify overall sanity of the setup, a manual testing is mandatory before
+landing a roll. Here is a rough testing scenario outline:
+1. Create a new snippet and type in a small function with a few nested for-loops. (The author suggests a bubble-sort). Make sure that:
+   * Words `function`, `for`, `var` are highlighted
+   * "Smart braces" behavior works
+   * "Enter" after opening curly brace adds correct indent
+   * Autocompletion works
+   * Multiple cursors functionality works as intended - Ctrl+D/Ctrl+U shortcuts
+   * Set a breakpoint inside a function, select some text and summon a context menu over it.
+2. Make sure there are items such as "Add to Watch", "Evaluate in Console" and "Copy/Paste"
+Make sure minified jquery opens nicely in the editor (minified jquery could be found as a resource on http://jquery.com)
+   * Verify `jquery.min.js` is formatted via "Pretty print" action
+3. Go to the Elements panel, select a node and verify the "Edit it as HTML" command works.
+
+## Committing
+The only changes allowed to front_end/cm/ folder are CodeMirror rolls. There's a presubmit check that enforces this, so make sure you include the phrase "roll CodeMirror" into
+your patch description.
+
+## Example
+Example CodeMirror roll patchset: https://codereview.chromium.org/273763003
diff --git a/third_party/WebKit/Source/devtools/front_end/cm/codemirror.css b/third_party/WebKit/Source/devtools/front_end/cm/codemirror.css
index b962b383..7eabf5d 100644
--- a/third_party/WebKit/Source/devtools/front_end/cm/codemirror.css
+++ b/third_party/WebKit/Source/devtools/front_end/cm/codemirror.css
@@ -1,149 +1,3 @@
-/* BASICS */
-
-.CodeMirror {
-  /* Set height, width, borders, and global font properties here */
-  font-family: monospace;
-  height: 300px;
-  color: black;
-}
-
-/* PADDING */
-
-.CodeMirror-lines {
-  padding: 4px 0; /* Vertical padding around content */
-}
-.CodeMirror pre {
-  padding: 0 4px; /* Horizontal padding of content */
-}
-
-.CodeMirror-scrollbar-filler, .CodeMirror-gutter-filler {
-  background-color: white; /* The little square between H and V scrollbars */
-}
-
-/* GUTTER */
-
-.CodeMirror-gutters {
-  border-right: 1px solid #ddd;
-  background-color: #f7f7f7;
-  white-space: nowrap;
-}
-.CodeMirror-linenumbers {}
-.CodeMirror-linenumber {
-  padding: 0 3px 0 5px;
-  min-width: 20px;
-  text-align: right;
-  color: #999;
-  white-space: nowrap;
-}
-
-.CodeMirror-guttermarker { color: black; }
-.CodeMirror-guttermarker-subtle { color: #999; }
-
-/* CURSOR */
-
-.CodeMirror-cursor {
-  border-left: 1px solid black;
-  border-right: none;
-  width: 0;
-}
-/* Shown when moving in bi-directional text */
-.CodeMirror div.CodeMirror-secondarycursor {
-  border-left: 1px solid silver;
-}
-.cm-fat-cursor .CodeMirror-cursor {
-  width: auto;
-  border: 0 !important;
-  background: #7e7;
-}
-.cm-fat-cursor div.CodeMirror-cursors {
-  z-index: 1;
-}
-
-.cm-animate-fat-cursor {
-  width: auto;
-  border: 0;
-  -webkit-animation: blink 1.06s steps(1) infinite;
-  -moz-animation: blink 1.06s steps(1) infinite;
-  animation: blink 1.06s steps(1) infinite;
-  background-color: #7e7;
-}
-@-moz-keyframes blink {
-  0% {}
-  50% { background-color: transparent; }
-  100% {}
-}
-@-webkit-keyframes blink {
-  0% {}
-  50% { background-color: transparent; }
-  100% {}
-}
-@keyframes blink {
-  0% {}
-  50% { background-color: transparent; }
-  100% {}
-}
-
-/* Can style cursor different in overwrite (non-insert) mode */
-.CodeMirror-overwrite .CodeMirror-cursor {}
-
-.cm-tab { display: inline-block; text-decoration: inherit; }
-
-.CodeMirror-rulers {
-  position: absolute;
-  left: 0; right: 0; top: -50px; bottom: -20px;
-  overflow: hidden;
-}
-.CodeMirror-ruler {
-  border-left: 1px solid #ccc;
-  top: 0; bottom: 0;
-  position: absolute;
-}
-
-/* DEFAULT THEME */
-
-.cm-s-default .cm-header {color: blue;}
-.cm-s-default .cm-quote {color: #090;}
-.cm-negative {color: #d44;}
-.cm-positive {color: #292;}
-.cm-header, .cm-strong {font-weight: bold;}
-.cm-em {font-style: italic;}
-.cm-link {text-decoration: underline;}
-.cm-strikethrough {text-decoration: line-through;}
-
-.cm-s-default .cm-keyword {color: #708;}
-.cm-s-default .cm-atom {color: #219;}
-.cm-s-default .cm-number {color: #164;}
-.cm-s-default .cm-def {color: #00f;}
-.cm-s-default .cm-variable,
-.cm-s-default .cm-punctuation,
-.cm-s-default .cm-property,
-.cm-s-default .cm-operator {}
-.cm-s-default .cm-variable-2 {color: #05a;}
-.cm-s-default .cm-variable-3 {color: #085;}
-.cm-s-default .cm-comment {color: #a50;}
-.cm-s-default .cm-string {color: #a11;}
-.cm-s-default .cm-string-2 {color: #f50;}
-.cm-s-default .cm-meta {color: #555;}
-.cm-s-default .cm-qualifier {color: #555;}
-.cm-s-default .cm-builtin {color: #30a;}
-.cm-s-default .cm-bracket {color: #997;}
-.cm-s-default .cm-tag {color: #170;}
-.cm-s-default .cm-attribute {color: #00c;}
-.cm-s-default .cm-hr {color: #999;}
-.cm-s-default .cm-link {color: #00c;}
-
-.cm-s-default .cm-error {color: #f00;}
-.cm-invalidchar {color: #f00;}
-
-.CodeMirror-composing { border-bottom: 2px solid; }
-
-/* Default styles for common addons */
-
-div.CodeMirror span.CodeMirror-matchingbracket {color: #0f0;}
-div.CodeMirror span.CodeMirror-nonmatchingbracket {color: #f22;}
-.CodeMirror-matchingtag { background: rgba(255, 150, 0, .3); }
-.CodeMirror-activeline-background {background: #e8f2ff;}
-
 /* STOP */
 
 /* The rest of this file contains styles related to the mechanics of
diff --git a/third_party/WebKit/Source/devtools/front_end/cm_modes/PRESUBMIT.py b/third_party/WebKit/Source/devtools/front_end/cm_modes/PRESUBMIT.py
index a769412..57ab9d0 100644
--- a/third_party/WebKit/Source/devtools/front_end/cm_modes/PRESUBMIT.py
+++ b/third_party/WebKit/Source/devtools/front_end/cm_modes/PRESUBMIT.py
@@ -8,7 +8,7 @@
                  "rolls from the upstream (http://codemirror.net). If this is a roll, "
                  "make sure you mention 'roll CodeMirror' (no quotes) in the change description.\n"
                  "CodeMirror rolling instructions:\n"
-                 "    https://sites.google.com/a/chromium.org/devtools-codemirror-rolling")
+                 "    src/third_party/WebKit/Source/devtools/front_end/cm/README.md")
     changeDescription = input_api.change.DescriptionText()
     errors = []
     if "roll codemirror" not in changeDescription.lower():
diff --git a/third_party/WebKit/Source/devtools/front_end/console/ConsoleView.js b/third_party/WebKit/Source/devtools/front_end/console/ConsoleView.js
index c3191fc..5c0d57b0 100644
--- a/third_party/WebKit/Source/devtools/front_end/console/ConsoleView.js
+++ b/third_party/WebKit/Source/devtools/front_end/console/ConsoleView.js
@@ -1240,7 +1240,9 @@
     var setting = this._messageLevelFiltersSetting;
     var levels = setting.get();
 
-    var contextMenu = new UI.ContextMenu(mouseEvent, true);
+    var contextMenu = new UI.ContextMenu(
+        mouseEvent, true /* useSoftMenu */, this._levelMenuButton.element.totalOffsetLeft(),
+        this._levelMenuButton.element.totalOffsetTop() + this._levelMenuButton.element.offsetHeight);
     contextMenu.headerSection().appendItem(
         Common.UIString('Default'), () => setting.set(Console.ConsoleFilter.defaultLevelsFilterValue()));
     for (var level in this._levelLabels) {
diff --git a/third_party/WebKit/Source/devtools/front_end/console/ConsoleViewMessage.js b/third_party/WebKit/Source/devtools/front_end/console/ConsoleViewMessage.js
index d0bef2c..a43d6e6 100644
--- a/third_party/WebKit/Source/devtools/front_end/console/ConsoleViewMessage.js
+++ b/third_party/WebKit/Source/devtools/front_end/console/ConsoleViewMessage.js
@@ -1385,7 +1385,7 @@
       else if (token.type === 'event')
         text = Common.UIString('<some> event');
       else if (token.type === 'milestone')
-        text = Common.UIString('M<XX>');
+        text = Common.UIString(' M<XX>');
       else if (token.type === 'autofill')
         text = Common.UIString('<attribute>');
       return acc + text;
diff --git a/third_party/WebKit/Source/devtools/front_end/console_model/ConsoleModel.js b/third_party/WebKit/Source/devtools/front_end/console_model/ConsoleModel.js
index 9186511..a35b2dd 100644
--- a/third_party/WebKit/Source/devtools/front_end/console_model/ConsoleModel.js
+++ b/third_party/WebKit/Source/devtools/front_end/console_model/ConsoleModel.js
@@ -561,11 +561,13 @@
    * @return {boolean}
    */
   isGroupable() {
+    var isJSError = this.source === ConsoleModel.ConsoleMessage.MessageSource.JS &&
+        this.level === ConsoleModel.ConsoleMessage.MessageLevel.Error;
     return (
         this.source !== ConsoleModel.ConsoleMessage.MessageSource.ConsoleAPI &&
         this.type !== ConsoleModel.ConsoleMessage.MessageType.Command &&
         this.type !== ConsoleModel.ConsoleMessage.MessageType.Result &&
-        this.type !== ConsoleModel.ConsoleMessage.MessageType.System);
+        this.type !== ConsoleModel.ConsoleMessage.MessageType.System && !isJSError);
   }
 
   /**
diff --git a/third_party/WebKit/Source/devtools/front_end/emulation/DevicesSettingsTab.js b/third_party/WebKit/Source/devtools/front_end/emulation/DevicesSettingsTab.js
index 2c0a283b..7f534d4 100644
--- a/third_party/WebKit/Source/devtools/front_end/emulation/DevicesSettingsTab.js
+++ b/third_party/WebKit/Source/devtools/front_end/emulation/DevicesSettingsTab.js
@@ -105,6 +105,7 @@
     var checkbox = element.createChild('input', 'devices-list-checkbox');
     checkbox.type = 'checkbox';
     checkbox.checked = device.show();
+    checkbox.addEventListener('click', event => event.consume(), false);
     element.createChild('div', 'devices-list-title').textContent = device.title;
     element.addEventListener('click', onItemClicked.bind(this), false);
     return element;
diff --git a/third_party/WebKit/Source/devtools/front_end/emulation/devicesSettingsTab.css b/third_party/WebKit/Source/devtools/front_end/emulation/devicesSettingsTab.css
index 2317db75..fd05063 100644
--- a/third_party/WebKit/Source/devtools/front_end/emulation/devicesSettingsTab.css
+++ b/third_party/WebKit/Source/devtools/front_end/emulation/devicesSettingsTab.css
@@ -51,6 +51,10 @@
     pointer-events: none;
 }
 
+.devices-list-checkbox:focus {
+    outline: auto 5px -webkit-focus-ring-color;
+}
+
 .devices-list-title {
     overflow: hidden;
     white-space: nowrap;
diff --git a/third_party/WebKit/Source/devtools/front_end/object_ui/objectValue.css b/third_party/WebKit/Source/devtools/front_end/object_ui/objectValue.css
index 488511d..45c8ff35 100644
--- a/third_party/WebKit/Source/devtools/front_end/object_ui/objectValue.css
+++ b/third_party/WebKit/Source/devtools/front_end/object_ui/objectValue.css
@@ -19,7 +19,7 @@
     display: flex !important;
 }
 
-.object-value-node:hover {
+.value.object-value-node:hover {
     background-color: rgba(56, 121, 217, 0.1);
 }
 
diff --git a/third_party/WebKit/Source/devtools/front_end/text_editor/cmdevtools.css b/third_party/WebKit/Source/devtools/front_end/text_editor/cmdevtools.css
index de84ee1..a7a7b1c6 100644
--- a/third_party/WebKit/Source/devtools/front_end/text_editor/cmdevtools.css
+++ b/third_party/WebKit/Source/devtools/front_end/text_editor/cmdevtools.css
@@ -2,6 +2,7 @@
     line-height: 1.2em !important;
     background-color: transparent !important;
     color: #222;
+    height: 300px;
 }
 
 .CodeMirror-linewidget {
@@ -90,17 +91,18 @@
     display: none;
 }
 
-.CodeMirror .CodeMirror-gutters {
+.CodeMirror-gutters {
     border-right: 1px solid rgb(187, 187, 187);
     background-color: #eee;
-}
-
-.CodeMirror .CodeMirror-linenumber {
-    color: rgb(128, 128, 128);
+    white-space: nowrap;
 }
 
 .CodeMirror-linenumber {
-    min-width: 22px !important;
+    color: rgb(128, 128, 128);
+    padding: 0 3px 0 5px;
+    min-width: 22px;
+    text-align: right;
+    white-space: nowrap;
 }
 
 .cm-highlight {
@@ -222,13 +224,11 @@
 div.CodeMirror span.CodeMirror-matchingbracket {
     background-color: rgba(0, 0, 0, 0.07);
     border-bottom: 1px solid rgba(0, 0, 0, 0.5);
-    color: unset;
 }
 
 div.CodeMirror span.CodeMirror-nonmatchingbracket {
     background-color: rgba(255, 0, 0, 0.07);
     border-bottom: 1px solid rgba(255, 0, 0, 0.5);
-    color: unset;
 }
 
 .-theme-with-dark-background div.CodeMirror span.CodeMirror-matchingbracket {
@@ -248,6 +248,8 @@
 }
 
 .cm-tab {
+    display: inline-block;
+    text-decoration: inherit;
     position: relative;
 }
 
@@ -463,10 +465,6 @@
     transform: translateZ(0);
 }
 
-.CodeMirror .CodeMirror-activeline-background {
-    background-color: transparent;
-}
-
 .cm-trailing-whitespace {
     background-color: rgba(255, 0, 0, 0.05);
 }
@@ -487,4 +485,31 @@
 .CodeMirror textarea {
     resize: none;
     overflow: hidden;
-}
\ No newline at end of file
+}
+
+.CodeMirror-lines {
+    padding: 4px 0; /* Vertical padding around content */
+}
+
+.CodeMirror pre {
+    padding: 0 4px; /* Horizontal padding of content */
+}
+
+.CodeMirror-scrollbar-filler, .CodeMirror-gutter-filler {
+    background-color: white; /* The little square between H and V scrollbars */
+}
+
+.CodeMirror-cursor {
+    border-left: 1px solid black;
+    border-right: none;
+    width: 0;
+}
+
+/* Shown when moving in bi-directional text */
+.CodeMirror div.CodeMirror-secondarycursor {
+    border-left: 1px solid silver;
+}
+
+.CodeMirror-composing {
+    border-bottom: 2px solid;
+}
diff --git a/third_party/WebKit/Source/devtools/front_end/ui/TextPrompt.js b/third_party/WebKit/Source/devtools/front_end/ui/TextPrompt.js
index 6f447eb9..d54d9fc 100644
--- a/third_party/WebKit/Source/devtools/front_end/ui/TextPrompt.js
+++ b/third_party/WebKit/Source/devtools/front_end/ui/TextPrompt.js
@@ -210,6 +210,7 @@
       this._element.setAttribute('contenteditable', 'plaintext-only');
     else
       this._element.removeAttribute('contenteditable');
+    this._element.classList.toggle('disabled', !enabled);
   }
 
   _removeFromElement() {
diff --git a/third_party/WebKit/Source/devtools/front_end/ui/inspectorSyntaxHighlight.css b/third_party/WebKit/Source/devtools/front_end/ui/inspectorSyntaxHighlight.css
index 6823b53..fb08a90 100644
--- a/third_party/WebKit/Source/devtools/front_end/ui/inspectorSyntaxHighlight.css
+++ b/third_party/WebKit/Source/devtools/front_end/ui/inspectorSyntaxHighlight.css
@@ -27,9 +27,9 @@
  */
 .cm-js-keyword {color: hsl(310, 86%, 36%);}
 .cm-js-number {color: hsl(248, 100%, 41%);}
-.cm-js-comment {color: hsl(120, 100%, 23%) !important; font-style: italic;}
-.cm-js-string {color: hsl(1, 80%, 43%) !important;}
-.cm-js-string-2 {color: hsl(1, 99%, 39%) !important;}
+.cm-js-comment {color: hsl(120, 100%, 23%); font-style: italic;}
+.cm-js-string {color: hsl(1, 80%, 43%);}
+.cm-js-string-2 {color: hsl(1, 99%, 39%);}
 .cm-js-atom {color: hsl(310, 86%, 36%);}
 .cm-js-def {color: hsl(240, 73%, 38%);}
 .cm-js-operator {color: hsl(27, 100%, 30%);}
@@ -38,23 +38,23 @@
 
 .cm-css-keyword { color: rgb(7, 144, 154);}
 .cm-css-number {color: rgb(50, 0, 255);}
-.cm-css-comment {color: rgb(0, 116, 0) !important;}
+.cm-css-comment {color: rgb(0, 116, 0);}
 .cm-css-def {color: rgb(200, 0, 0);}
 .cm-css-meta {color: rgb(200, 0, 0);}
 .cm-css-atom {color: rgb(7, 144, 154);}
-.cm-css-string {color: rgb(7, 144, 154) !important;}
-.cm-css-string-2 {color: rgb(7, 144, 154) !important;}
-.cm-css-link {color: rgb(7, 144, 154) !important;}
+.cm-css-string {color: rgb(7, 144, 154);}
+.cm-css-string-2 {color: rgb(7, 144, 154);}
+.cm-css-link {color: rgb(7, 144, 154);}
 .cm-css-variable {color: rgb(200, 0, 0);}
 .cm-css-variable-2 {color: rgb(0, 0, 128);}
 .cm-css-property, .webkit-css-property {color: rgb(200, 0, 0);}
 
 .cm-xml-meta {color: rgb(192, 192, 192);}
-.cm-xml-comment {color: rgb(35, 110, 37) !important;}
-.cm-xml-string {color: rgb(26, 26, 166) !important;}
+.cm-xml-comment {color: rgb(35, 110, 37);}
+.cm-xml-string {color: rgb(26, 26, 166);}
 .cm-xml-tag {color: rgb(136, 18, 128);}
 .cm-xml-attribute {color: rgb(153, 69, 0);}
-.cm-xml-link {color: #00e !important;}
+.cm-xml-link {color: #00e;}
 
 .webkit-html-comment {
     /* Keep this in sync with view-source.css (.webkit-html-comment) */
@@ -130,3 +130,13 @@
     color: rgb(255, 0, 0);
     font-weight: bold;
 }
+
+/* Default CodeMirror Theme */
+.cm-negative {color: #d44;}
+.cm-positive {color: #292;}
+.cm-header, .cm-strong {font-weight: bold;}
+.cm-em {font-style: italic;}
+.cm-link {text-decoration: underline;}
+.cm-strikethrough {text-decoration: line-through;}
+
+.cm-invalidchar {color: #f00;}
diff --git a/third_party/WebKit/Source/devtools/front_end/ui/inspectorSyntaxHighlightDark.css b/third_party/WebKit/Source/devtools/front_end/ui/inspectorSyntaxHighlightDark.css
index 6595310..782ae591 100644
--- a/third_party/WebKit/Source/devtools/front_end/ui/inspectorSyntaxHighlightDark.css
+++ b/third_party/WebKit/Source/devtools/front_end/ui/inspectorSyntaxHighlightDark.css
@@ -7,7 +7,7 @@
 .cm-js-atom{color:rgb(161, 247, 181);}
 .cm-js-attribute{color:rgb(97, 148, 198);}
 .cm-js-builtin{color:rgb(159, 180, 214);}
-.cm-js-comment{color:rgb(116, 116, 116) !important;}
+.cm-js-comment{color:rgb(116, 116, 116);}
 .cm-js-def{color:rgb(93, 176, 215);}
 .cm-js-keyword{color:rgb(154, 127, 213);}
 .cm-js-link{color:rgb(159, 180, 214);}
@@ -15,42 +15,42 @@
 .cm-js-number{color:rgb(161, 247, 181);}
 .cm-js-operator{color:rgb(210, 192, 87);}
 .cm-js-property{color:rgb(210, 192, 87);}
-.cm-js-string{color:rgb(242, 139, 84) !important;}
-.cm-js-string-2{color:rgb(242, 139, 84) !important;}
+.cm-js-string{color:rgb(242, 139, 84);}
+.cm-js-string-2{color:rgb(242, 139, 84);}
 .cm-js-tag{color:rgb(93, 176, 215);}
 .cm-js-variable{color:rgb(217, 217, 217);}
 .cm-js-variable-2{color:rgb(217, 217, 217);}
 .cm-atom{color:rgb(161, 247, 181);}
-.cm-comment{color:rgb(116, 116, 116) !important;}
+.cm-comment{color:rgb(116, 116, 116);}
 .cm-variable{color:rgb(217, 217, 217);}
-.cm-string{color:rgb(242, 139, 84) !important;}
+.cm-string{color:rgb(242, 139, 84);}
 .cm-keyword{color:rgb(154, 127, 213);}
 .cm-number{color:rgb(161, 247, 181);}
 .cm-operator{color:rgb(210, 192, 87);}
 .cm-css-atom{color:rgb(217, 217, 217);}
 .cm-css-builtin{color:rgb(255, 163, 79);}
 .cm-css-def{color:rgb(255, 163, 79);}
-.cm-css-comment{color:rgb(116, 116, 116) !important;}
+.cm-css-comment{color:rgb(116, 116, 116);}
 .cm-css-meta{color:rgb(132, 240, 255);}
 .cm-css-number{color:rgb(217, 217, 217);}
 .cm-css-operator{color:rgb(217, 217, 217);}
 .cm-css-property{color:rgb(132, 240, 255);}
 .cm-css-qualifier{color:rgb(255, 163, 79);}
-.cm-css-string{color:rgb(231, 194, 111) !important;}
-.cm-css-string-2{color:rgb(217, 217, 217) !important;}
+.cm-css-string{color:rgb(231, 194, 111);}
+.cm-css-string-2{color:rgb(217, 217, 217);}
 .cm-css-tag{color:rgb(255, 163, 79);}
 .cm-css-variable{color:rgb(255, 163, 79);}
 .cm-css-variable-2{color:rgb(255, 163, 79);}
-.cm-xml-comment{color:rgb(137, 137, 137) !important;}
+.cm-xml-comment{color:rgb(137, 137, 137);}
 .cm-xml-error{color:rgb(198, 95, 95);}
-.cm-xml-string{color:rgb(242, 151, 102) !important;}
+.cm-xml-string{color:rgb(242, 151, 102);}
 .cm-xml-tag{color:rgb(93, 176, 215);}
 .cm-xml-attribute{color:rgb(155, 187, 220);}
 .cm-xml-link{color:rgb(231, 194, 111);}
 
 .webkit-html-attribute-name{color:rgb(155, 187, 220);}
 .webkit-html-attribute-value{color:rgb(242, 151, 102);}
-.webkit-html-comment{color:rgb(137, 137, 137) !important;}
+.webkit-html-comment{color:rgb(137, 137, 137);}
 .devtools-link{color:rgb(231, 194, 111);}
 .webkit-html-tag{color:rgb(93, 176, 215);}
 .webkit-html-tag-name{color:rgb(93, 176, 215);}
@@ -67,5 +67,5 @@
 .webkit-css-keyword{color:rgb(255, 163, 79);}
 .webkit-css-number{color:rgb(217, 217, 217);}
 .webkit-css-property{color: rgb(53, 212, 199);}
-.webkit-css-string{color:rgb(231, 194, 111) !important;}
+.webkit-css-string{color:rgb(231, 194, 111);}
 .webkit-css-url{color:rgb(231, 194, 111);}
diff --git a/third_party/WebKit/Source/devtools/front_end/ui/textPrompt.css b/third_party/WebKit/Source/devtools/front_end/ui/textPrompt.css
index 9cb04edc..a1cdc70 100644
--- a/third_party/WebKit/Source/devtools/front_end/ui/textPrompt.css
+++ b/third_party/WebKit/Source/devtools/front_end/ui/textPrompt.css
@@ -46,6 +46,15 @@
     display: block;
 }
 
+::content .text-prompt {
+    cursor: text;
+}
+
+::content .text-prompt.disabled {
+    opacity: 0.5;
+    cursor: default;
+}
+
 .text-prompt-editing ::content br {
     display: none;
 }
diff --git a/third_party/WebKit/Source/modules/animationworklet/AnimationWorkletGlobalScopeTest.cpp b/third_party/WebKit/Source/modules/animationworklet/AnimationWorkletGlobalScopeTest.cpp
index a0efbff0..84d22085 100644
--- a/third_party/WebKit/Source/modules/animationworklet/AnimationWorkletGlobalScopeTest.cpp
+++ b/third_party/WebKit/Source/modules/animationworklet/AnimationWorkletGlobalScopeTest.cpp
@@ -10,7 +10,10 @@
 #include "bindings/core/v8/V8BindingForCore.h"
 #include "bindings/core/v8/V8CacheOptions.h"
 #include "bindings/core/v8/WorkerOrWorkletScriptController.h"
+#include "core/dom/Document.h"
 #include "core/dom/TaskRunnerHelper.h"
+#include "core/origin_trials/OriginTrialContext.h"
+#include "core/testing/DummyPageHolder.h"
 #include "core/workers/GlobalScopeCreationParams.h"
 #include "core/workers/WorkerReportingProxy.h"
 #include "modules/animationworklet/AnimationWorklet.h"
@@ -35,8 +38,11 @@
 
   void SetUp() override {
     AnimationWorkletThread::CreateSharedBackingThreadForTest();
-    reporting_proxy_ = WTF::MakeUnique<WorkerReportingProxy>();
-    security_origin_ = SecurityOrigin::Create(KURL("http://fake.url/"));
+    page_ = DummyPageHolder::Create();
+    Document* document = page_->GetFrame().GetDocument();
+    document->SetURL(KURL("https://example.com/"));
+    document->UpdateSecurityOrigin(SecurityOrigin::Create(document->Url()));
+    reporting_proxy_ = std::make_unique<WorkerReportingProxy>();
   }
 
   void TearDown() override {
@@ -49,16 +55,18 @@
 
     WorkerClients* clients = WorkerClients::Create();
 
-    thread->Start(std::make_unique<GlobalScopeCreationParams>(
-                      KURL("http://fake.url/"), "fake user agent",
-                      "" /* source_code */, nullptr /* cached_meta_data */,
-                      nullptr /* content_security_policy_parsed_headers */,
-                      "" /* referrer_policy */, security_origin_.get(), clients,
-                      kWebAddressSpaceLocal, nullptr /* origin_trial_tokens */,
-                      nullptr /* worker_settings */, kV8CacheOptionsDefault),
-                  WTF::nullopt,
-                  WorkerInspectorProxy::PauseOnWorkerStart::kDontPause,
-                  ParentFrameTaskRunners::Create());
+    Document* document = page_->GetFrame().GetDocument();
+    thread->Start(
+        std::make_unique<GlobalScopeCreationParams>(
+            document->Url(), document->UserAgent(), "" /* source_code */,
+            nullptr /* cached_meta_data */,
+            nullptr /* content_security_policy_parsed_headers */,
+            document->GetReferrerPolicy(), document->GetSecurityOrigin(),
+            clients, document->AddressSpace(),
+            OriginTrialContext::GetTokens(document).get(),
+            nullptr /* worker_settings */, kV8CacheOptionsDefault),
+        WTF::nullopt, WorkerInspectorProxy::PauseOnWorkerStart::kDontPause,
+        ParentFrameTaskRunners::Create());
     return thread;
   }
 
@@ -268,7 +276,7 @@
     return value.IsEmpty();
   }
 
-  scoped_refptr<SecurityOrigin> security_origin_;
+  std::unique_ptr<DummyPageHolder> page_;
   std::unique_ptr<WorkerReportingProxy> reporting_proxy_;
 };
 
diff --git a/third_party/WebKit/Source/modules/animationworklet/AnimationWorkletThreadTest.cpp b/third_party/WebKit/Source/modules/animationworklet/AnimationWorkletThreadTest.cpp
index 3032d0f..1b7aa33 100644
--- a/third_party/WebKit/Source/modules/animationworklet/AnimationWorkletThreadTest.cpp
+++ b/third_party/WebKit/Source/modules/animationworklet/AnimationWorkletThreadTest.cpp
@@ -12,6 +12,8 @@
 #include "bindings/core/v8/WorkerOrWorkletScriptController.h"
 #include "core/dom/AnimationWorkletProxyClient.h"
 #include "core/inspector/ConsoleMessage.h"
+#include "core/origin_trials/OriginTrialContext.h"
+#include "core/testing/DummyPageHolder.h"
 #include "core/workers/GlobalScopeCreationParams.h"
 #include "core/workers/ParentFrameTaskRunners.h"
 #include "core/workers/WorkerBackingThread.h"
@@ -69,8 +71,11 @@
  public:
   void SetUp() override {
     AnimationWorkletThread::CreateSharedBackingThreadForTest();
-    reporting_proxy_ = WTF::MakeUnique<WorkerReportingProxy>();
-    security_origin_ = SecurityOrigin::Create(KURL("http://fake.url/"));
+    page_ = DummyPageHolder::Create();
+    Document* document = page_->GetFrame().GetDocument();
+    document->SetURL(KURL("https://example.com/"));
+    document->UpdateSecurityOrigin(SecurityOrigin::Create(document->Url()));
+    reporting_proxy_ = std::make_unique<WorkerReportingProxy>();
   }
 
   void TearDown() override {
@@ -84,17 +89,18 @@
 
     std::unique_ptr<AnimationWorkletThread> thread =
         AnimationWorkletThread::Create(nullptr, *reporting_proxy_);
-
-    thread->Start(std::make_unique<GlobalScopeCreationParams>(
-                      KURL("http://fake.url/"), "fake user agent",
-                      "" /* source_code */, nullptr /* cached_meta_data */,
-                      nullptr /* content_security_policy_parsed_headers */,
-                      "" /* referrer_policy */, security_origin_.get(), clients,
-                      kWebAddressSpaceLocal, nullptr /* origin_trial_tokens */,
-                      nullptr /* worker_settings */, kV8CacheOptionsDefault),
-                  WTF::nullopt,
-                  WorkerInspectorProxy::PauseOnWorkerStart::kDontPause,
-                  ParentFrameTaskRunners::Create());
+    Document* document = page_->GetFrame().GetDocument();
+    thread->Start(
+        std::make_unique<GlobalScopeCreationParams>(
+            document->Url(), document->UserAgent(), "" /* source_code */,
+            nullptr /* cached_meta_data */,
+            nullptr /* content_security_policy_parsed_headers */,
+            document->GetReferrerPolicy(), document->GetSecurityOrigin(),
+            clients, document->AddressSpace(),
+            OriginTrialContext::GetTokens(document).get(),
+            nullptr /* worker_settings */, kV8CacheOptionsDefault),
+        WTF::nullopt, WorkerInspectorProxy::PauseOnWorkerStart::kDontPause,
+        ParentFrameTaskRunners::Create());
     return thread;
   }
 
@@ -131,7 +137,7 @@
     wait_event->Signal();
   }
 
-  scoped_refptr<SecurityOrigin> security_origin_;
+  std::unique_ptr<DummyPageHolder> page_;
   std::unique_ptr<WorkerReportingProxy> reporting_proxy_;
   ScopedTestingPlatformSupport<AnimationWorkletTestPlatform> platform_;
 };
diff --git a/third_party/WebKit/Source/modules/canvas/canvas2d/CanvasRenderingContext2DSettings.idl b/third_party/WebKit/Source/modules/canvas/canvas2d/CanvasRenderingContext2DSettings.idl
index 283cb92a..d953c69 100644
--- a/third_party/WebKit/Source/modules/canvas/canvas2d/CanvasRenderingContext2DSettings.idl
+++ b/third_party/WebKit/Source/modules/canvas/canvas2d/CanvasRenderingContext2DSettings.idl
@@ -12,6 +12,5 @@
     // Must decide before shipping.
     [RuntimeEnabled=ExperimentalCanvasFeatures] CanvasColorSpace colorSpace = "legacy-srgb";
     [RuntimeEnabled=ExperimentalCanvasFeatures] CanvasPixelFormat pixelFormat = "8-8-8-8";
-    [RuntimeEnabled=ExperimentalCanvasFeatures] boolean linearPixelMath = false;
 };
 
diff --git a/third_party/WebKit/Source/modules/canvas/canvas2d/CanvasRenderingContext2DTest.cpp b/third_party/WebKit/Source/modules/canvas/canvas2d/CanvasRenderingContext2DTest.cpp
index 0bb3f22e..bb8f35569 100644
--- a/third_party/WebKit/Source/modules/canvas/canvas2d/CanvasRenderingContext2DTest.cpp
+++ b/third_party/WebKit/Source/modules/canvas/canvas2d/CanvasRenderingContext2DTest.cpp
@@ -32,6 +32,7 @@
 #include "platform/loader/fetch/MemoryCache.h"
 #include "platform/testing/RuntimeEnabledFeaturesTestHelpers.h"
 #include "platform/testing/TestingPlatformSupport.h"
+#include "platform/wtf/ByteSwap.h"
 #include "platform/wtf/PtrUtil.h"
 #include "public/platform/scheduler/test/renderer_scheduler_test_support.h"
 #include "testing/gmock/include/gmock/gmock.h"
@@ -1072,17 +1073,16 @@
   // Set the color space conversion in ImageBitmapOptions
   ImageBitmapOptions options;
   static const Vector<String> kConversions = {
-      "none", "default", "default", "srgb", "linear-rgb", "p3", "rec2020"};
+      "none", "default", "srgb", "linear-rgb", "p3", "rec2020"};
   options.setColorSpaceConversion(
       kConversions[static_cast<uint8_t>(color_space_conversion)]);
 
   return options;
 }
 
-constexpr int kSRGBColorCorrectionTolerance = 1;
-constexpr float kWideGamutColorCorrectionTolerance = 0.01;
-
 TEST_F(CanvasRenderingContext2DTest, ImageBitmapColorSpaceConversion) {
+  ScopedExperimentalCanvasFeaturesForTest experimental_canvas_features(true);
+
   Persistent<HTMLCanvasElement> canvas =
       Persistent<HTMLCanvasElement>(CanvasElement());
   CanvasContextCreationAttributes attributes;
@@ -1091,24 +1091,19 @@
   CanvasRenderingContext2D* context = static_cast<CanvasRenderingContext2D*>(
       canvas->GetCanvasRenderingContext("2d", attributes));
   StringOrCanvasGradientOrCanvasPattern fill_style;
-  fill_style.SetString("#FF0000");
+  fill_style.SetString("#FFC08040");  // 255,192,128,64
   context->setFillStyle(fill_style);
-  context->fillRect(0, 0, 10, 10);
+  context->fillRect(0, 0, 4, 4);
   NonThrowableExceptionState exception_state;
   uint8_t* src_pixel =
-      context->getImageData(5, 5, 1, 1, exception_state)->data()->Data();
-  // Swizzle if needed
-  if (kN32_SkColorType == kBGRA_8888_SkColorType)
-    std::swap(src_pixel[0], src_pixel[2]);
+      context->getImageData(2, 2, 1, 1, exception_state)->data()->Data();
 
   // Create and test the ImageBitmap objects.
-  Optional<IntRect> crop_rect = IntRect(0, 0, 10, 10);
+  Optional<IntRect> crop_rect = IntRect(0, 0, 4, 4);
   sk_sp<SkColorSpace> color_space = nullptr;
-  SkColorType color_type = SkColorType::kN32_SkColorType;
+  SkColorType color_type = SkColorType::kRGBA_8888_SkColorType;
   SkColorSpaceXform::ColorFormat color_format32 =
-      (color_type == kBGRA_8888_SkColorType)
-          ? SkColorSpaceXform::ColorFormat::kBGRA_8888_ColorFormat
-          : SkColorSpaceXform::ColorFormat::kRGBA_8888_ColorFormat;
+      SkColorSpaceXform::ColorFormat::kRGBA_8888_ColorFormat;
   SkColorSpaceXform::ColorFormat color_format = color_format32;
   sk_sp<SkColorSpace> src_rgb_color_space = SkColorSpace::MakeSRGB();
 
@@ -1117,11 +1112,6 @@
        i <= static_cast<uint8_t>(ColorSpaceConversion::LAST); i++) {
     ColorSpaceConversion color_space_conversion =
         static_cast<ColorSpaceConversion>(i);
-    ImageBitmapOptions options =
-        PrepareBitmapOptionsAndSetRuntimeFlags(color_space_conversion);
-    ImageBitmap* image_bitmap = ImageBitmap::Create(canvas, crop_rect, options);
-    sk_sp<SkImage> converted_image =
-        image_bitmap->BitmapImage()->PaintImageForCurrentFrame().GetSkImage();
 
     switch (color_space_conversion) {
       case ColorSpaceConversion::NONE:
@@ -1155,13 +1145,19 @@
         NOTREACHED();
     }
 
-    SkImageInfo image_info = SkImageInfo::Make(
-        1, 1, color_type, SkAlphaType::kPremul_SkAlphaType, color_space);
+    // Color convert using ImageBitmap
+    ImageBitmapOptions options =
+        PrepareBitmapOptionsAndSetRuntimeFlags(color_space_conversion);
+    ImageBitmap* image_bitmap = ImageBitmap::Create(canvas, crop_rect, options);
+    sk_sp<SkImage> converted_image =
+        image_bitmap->BitmapImage()->PaintImageForCurrentFrame().GetSkImage();
+    SkImageInfo image_info =
+        SkImageInfo::Make(1, 1, color_type, SkAlphaType::kUnpremul_SkAlphaType,
+                          converted_image->refColorSpace());
     std::unique_ptr<uint8_t[]> converted_pixel(
         new uint8_t[image_info.bytesPerPixel()]());
-    converted_image->readPixels(
-        image_info, converted_pixel.get(),
-        converted_image->width() * image_info.bytesPerPixel(), 5, 5);
+    converted_image->readPixels(image_info, converted_pixel.get(),
+                                image_info.minRowBytes(), 2, 2);
 
     // Transform the source pixel and check if the image bitmap color conversion
     // is done correctly.
@@ -1171,92 +1167,16 @@
         new uint8_t[image_info.bytesPerPixel()]());
     color_space_xform->apply(color_format, transformed_pixel.get(),
                              color_format32, src_pixel, 1,
-                             SkAlphaType::kPremul_SkAlphaType);
+                             SkAlphaType::kUnpremul_SkAlphaType);
 
     ColorCorrectionTestUtils::CompareColorCorrectedPixels(
-        converted_pixel, transformed_pixel, image_info.bytesPerPixel(),
-        kWideGamutColorCorrectionTolerance);
+        converted_pixel.get(), transformed_pixel.get(), 1,
+        (color_type == kRGBA_8888_SkColorType) ? kUint8ClampedArrayStorageFormat
+                                               : kUint16ArrayStorageFormat,
+        kAlphaUnmultiplied, kUnpremulRoundTripTolerance);
   }
 }
 
-bool ConvertPixelsToColorSpaceAndPixelFormatForTest(
-    DOMArrayBufferView* data_array,
-    CanvasColorSpace src_color_space,
-    CanvasColorSpace dst_color_space,
-    CanvasPixelFormat dst_pixel_format,
-    std::unique_ptr<uint8_t[]>& converted_pixels) {
-  // Setting SkColorSpaceXform::apply parameters
-  SkColorSpaceXform::ColorFormat src_color_format =
-      SkColorSpaceXform::kRGBA_8888_ColorFormat;
-
-  unsigned data_length = data_array->byteLength() / data_array->TypeSize();
-  unsigned num_pixels = data_length / 4;
-  DOMUint8ClampedArray* u8_array = nullptr;
-  DOMUint16Array* u16_array = nullptr;
-  DOMFloat32Array* f32_array = nullptr;
-  void* src_data = nullptr;
-
-  switch (data_array->GetType()) {
-    case ArrayBufferView::ViewType::kTypeUint8Clamped:
-      u8_array = const_cast<DOMUint8ClampedArray*>(
-          static_cast<const DOMUint8ClampedArray*>(data_array));
-      src_data = static_cast<void*>(u8_array->Data());
-      break;
-
-    case ArrayBufferView::ViewType::kTypeUint16:
-      u16_array = const_cast<DOMUint16Array*>(
-          static_cast<const DOMUint16Array*>(data_array));
-      src_color_format =
-          SkColorSpaceXform::ColorFormat::kRGBA_U16_BE_ColorFormat;
-      src_data = static_cast<void*>(u16_array->Data());
-      break;
-
-    case ArrayBufferView::ViewType::kTypeFloat32:
-      f32_array = const_cast<DOMFloat32Array*>(
-          static_cast<const DOMFloat32Array*>(data_array));
-      src_color_format = SkColorSpaceXform::kRGBA_F32_ColorFormat;
-      src_data = static_cast<void*>(f32_array->Data());
-      break;
-    default:
-      NOTREACHED();
-      return false;
-  }
-
-  SkColorSpaceXform::ColorFormat dst_color_format =
-      SkColorSpaceXform::ColorFormat::kRGBA_8888_ColorFormat;
-  if (dst_pixel_format == kF16CanvasPixelFormat)
-    dst_color_format = SkColorSpaceXform::ColorFormat::kRGBA_F32_ColorFormat;
-
-  sk_sp<SkColorSpace> src_sk_color_space = nullptr;
-  if (u8_array) {
-    src_sk_color_space =
-        CanvasColorParams(src_color_space, kRGBA8CanvasPixelFormat, kNonOpaque)
-            .GetSkColorSpaceForSkSurfaces();
-  } else {
-    src_sk_color_space =
-        CanvasColorParams(src_color_space, kF16CanvasPixelFormat, kNonOpaque)
-            .GetSkColorSpaceForSkSurfaces();
-  }
-
-  sk_sp<SkColorSpace> dst_sk_color_space =
-      CanvasColorParams(dst_color_space, dst_pixel_format, kNonOpaque)
-          .GetSkColorSpaceForSkSurfaces();
-
-  // When the input dataArray is in Uint16, we normally should convert the
-  // values from Little Endian to Big Endian before passing the buffer to
-  // SkColorSpaceXform::apply. However, in this test scenario we are creating
-  // the Uin16 dataArray by multiplying a Uint8Clamped array members by 257,
-  // hence the Big Endian and Little Endian representations are the same.
-
-  std::unique_ptr<SkColorSpaceXform> xform = SkColorSpaceXform::New(
-      src_sk_color_space.get(), dst_sk_color_space.get());
-
-  if (!xform->apply(dst_color_format, converted_pixels.get(), src_color_format,
-                    src_data, num_pixels, kUnpremul_SkAlphaType))
-    return false;
-  return true;
-}
-
 // The color settings of the surface of the canvas always remaines loyal to the
 // first created context 2D. Therefore, we have to test different canvas color
 // space settings for CanvasRenderingContext2D::putImageData() in different
@@ -1334,6 +1254,7 @@
 
   ImageData* image_data = nullptr;
   ImageDataColorSettings color_settings;
+  int num_pixels = data_length / 4;
 
   // At most four bytes are needed for Float32 output per color component.
   std::unique_ptr<uint8_t[]> pixels_converted_manually(
@@ -1369,9 +1290,14 @@
       unsigned k = (unsigned)(canvas_colorspace_setting);
       // Convert the original data used to create ImageData to the
       // canvas color space and canvas pixel format.
-      EXPECT_TRUE(ConvertPixelsToColorSpaceAndPixelFormatForTest(
-          data_array, image_data_color_spaces[i], canvas_color_spaces[k],
-          canvas_pixel_formats[k], pixels_converted_manually));
+      EXPECT_TRUE(
+          ColorCorrectionTestUtils::
+              ConvertPixelsToColorSpaceAndPixelFormatForTest(
+                  data_array->BaseAddress(), data_length,
+                  image_data_color_spaces[i], image_data_storage_formats[j],
+                  canvas_color_spaces[k], canvas_pixel_formats[k],
+                  pixels_converted_manually,
+                  SkColorSpaceXform::ColorFormat::kRGBA_F32_ColorFormat));
 
       // Create a canvas and call putImageData and getImageData to make sure
       // the conversion is done correctly.
@@ -1385,26 +1311,17 @@
       NonThrowableExceptionState exception_state;
       context->putImageData(image_data, 0, 0, exception_state);
 
-      void* pixels_from_get_image_data = nullptr;
-      if (canvas_pixel_formats[k] == kRGBA8CanvasPixelFormat) {
-        pixels_from_get_image_data =
-            context->getImageData(0, 0, 2, 2, exception_state)->data()->Data();
-        ColorCorrectionTestUtils::CompareColorCorrectedPixels(
-            static_cast<uint8_t*>((void*)(pixels_converted_manually.get())),
-            static_cast<uint8_t*>(pixels_from_get_image_data), data_length,
-            kSRGBColorCorrectionTolerance);
-      } else {
-        pixels_from_get_image_data =
-            context->getImageData(0, 0, 2, 2, exception_state)
-                ->dataUnion()
-                .GetAsFloat32Array()
-                .View()
-                ->Data();
-        ColorCorrectionTestUtils::CompareColorCorrectedPixels(
-            static_cast<float*>((void*)(pixels_converted_manually.get())),
-            static_cast<float*>(pixels_from_get_image_data), data_length,
-            kWideGamutColorCorrectionTolerance);
-      }
+      void* pixels_from_get_image_data =
+          context->getImageData(0, 0, 2, 2, exception_state)
+              ->BufferBase()
+              ->Data();
+      ColorCorrectionTestUtils::CompareColorCorrectedPixels(
+          pixels_from_get_image_data, pixels_converted_manually.get(),
+          num_pixels,
+          (canvas_pixel_formats[k] == kRGBA8CanvasPixelFormat)
+              ? kUint8ClampedArrayStorageFormat
+              : kFloat32ArrayStorageFormat,
+          kAlphaUnmultiplied, kUnpremulRoundTripTolerance);
     }
   }
   delete[] u16_pixels;
@@ -1416,10 +1333,8 @@
       CanvasElement(), CanvasColorSpaceSettings::CANVAS_SRGB);
 }
 
-// This test crashes when canvas color parameters are set correctly.
-// http://crbug.com/772189
 TEST_F(CanvasRenderingContext2DTest,
-       DISABLED_ColorManagedPutImageDataOnLinearSRGBCanvas) {
+       ColorManagedPutImageDataOnLinearSRGBCanvas) {
   TestPutImageDataOnCanvasWithColorSpaceSettings(
       CanvasElement(), CanvasColorSpaceSettings::CANVAS_LINEARSRGB);
 }
diff --git a/third_party/WebKit/Source/modules/csspaint/PaintWorkletGlobalScopeProxy.cpp b/third_party/WebKit/Source/modules/csspaint/PaintWorkletGlobalScopeProxy.cpp
index d81850f3..0087da7 100644
--- a/third_party/WebKit/Source/modules/csspaint/PaintWorkletGlobalScopeProxy.cpp
+++ b/third_party/WebKit/Source/modules/csspaint/PaintWorkletGlobalScopeProxy.cpp
@@ -26,16 +26,15 @@
     size_t global_scope_number) {
   DCHECK(IsMainThread());
   Document* document = frame->GetDocument();
-  reporting_proxy_ = WTF::MakeUnique<MainThreadWorkletReportingProxy>(document);
+  reporting_proxy_ =
+      std::make_unique<MainThreadWorkletReportingProxy>(document);
 
   // TODO(nhiroki): Set CSP headers (https://crbug.com/773786).
-  // TODO(nhiroki): Inherit a referrer policy from owner's document.
-  // (https://crbug.com/773921)
   auto creation_params = std::make_unique<GlobalScopeCreationParams>(
       document->Url(), document->UserAgent(), String() /* source_code */,
       nullptr /* cached_meta_data */,
       nullptr /* content_security_policy_parsed_headers */,
-      String() /* referrer_policy */, document->GetSecurityOrigin(),
+      document->GetReferrerPolicy(), document->GetSecurityOrigin(),
       nullptr /* worker_clients */, document->AddressSpace(),
       OriginTrialContext::GetTokens(document).get(),
       nullptr /* worker_settings */, kV8CacheOptionsDefault);
diff --git a/third_party/WebKit/Source/modules/exported/WebEmbeddedWorkerImpl.cpp b/third_party/WebKit/Source/modules/exported/WebEmbeddedWorkerImpl.cpp
index 03c51aa..bfae55d 100644
--- a/third_party/WebKit/Source/modules/exported/WebEmbeddedWorkerImpl.cpp
+++ b/third_party/WebKit/Source/modules/exported/WebEmbeddedWorkerImpl.cpp
@@ -403,8 +403,8 @@
         main_script_loader_->SourceText(),
         main_script_loader_->ReleaseCachedMetadata(),
         document->GetContentSecurityPolicy()->Headers().get(),
-        main_script_loader_->GetReferrerPolicy(), starter_origin,
-        worker_clients, main_script_loader_->ResponseAddressSpace(),
+        document->GetReferrerPolicy(), starter_origin, worker_clients,
+        main_script_loader_->ResponseAddressSpace(),
         main_script_loader_->OriginTrialTokens(), std::move(worker_settings),
         static_cast<V8CacheOptions>(worker_start_data_.v8_cache_options),
         std::move(interface_provider_info_));
@@ -416,7 +416,7 @@
     global_scope_creation_params = WTF::MakeUnique<GlobalScopeCreationParams>(
         worker_start_data_.script_url, worker_start_data_.user_agent,
         "" /* SourceText */, nullptr /* CachedMetadata */,
-        nullptr /* ContentSecurityPolicy */, "" /* ReferrerPolicy */,
+        nullptr /* ContentSecurityPolicy */, kReferrerPolicyDefault,
         starter_origin, worker_clients, worker_start_data_.address_space,
         nullptr /* OriginTrialTokens */, std::move(worker_settings),
         static_cast<V8CacheOptions>(worker_start_data_.v8_cache_options),
diff --git a/third_party/WebKit/Source/modules/gamepad/BUILD.gn b/third_party/WebKit/Source/modules/gamepad/BUILD.gn
index 027b327d..4cb4ecd 100644
--- a/third_party/WebKit/Source/modules/gamepad/BUILD.gn
+++ b/third_party/WebKit/Source/modules/gamepad/BUILD.gn
@@ -14,6 +14,8 @@
     "GamepadDispatcher.h",
     "GamepadEvent.cpp",
     "GamepadEvent.h",
+    "GamepadHapticActuator.cpp",
+    "GamepadHapticActuator.h",
     "GamepadList.cpp",
     "GamepadList.h",
     "GamepadPose.cpp",
@@ -24,5 +26,7 @@
 
   deps = [
     "//device/gamepad/public/cpp:shared_with_blink",
+    "//device/gamepad/public/interfaces:interfaces_blink",
+    "//third_party/WebKit/public:blink_headers",
   ]
 }
diff --git a/third_party/WebKit/Source/modules/gamepad/DEPS b/third_party/WebKit/Source/modules/gamepad/DEPS
index c1ba0f0..fb586b4 100644
--- a/third_party/WebKit/Source/modules/gamepad/DEPS
+++ b/third_party/WebKit/Source/modules/gamepad/DEPS
@@ -4,6 +4,8 @@
     "+device/gamepad/public/cpp/gamepad.h",
     "+device/gamepad/public/cpp/gamepads.h",
 
+    "+device/gamepad/public/interfaces/gamepad.mojom-blink.h",
+
     "-modules",
     "+modules/EventModules.h",
     "+modules/ModulesExport.h",
diff --git a/third_party/WebKit/Source/modules/gamepad/Gamepad.cpp b/third_party/WebKit/Source/modules/gamepad/Gamepad.cpp
index 5c02a2b..fea7a05 100644
--- a/third_party/WebKit/Source/modules/gamepad/Gamepad.cpp
+++ b/third_party/WebKit/Source/modules/gamepad/Gamepad.cpp
@@ -81,6 +81,20 @@
   is_button_data_dirty_ = true;
 }
 
+void Gamepad::SetVibrationActuator(
+    const device::GamepadHapticActuator& actuator) {
+  if (!actuator.not_null) {
+    if (vibration_actuator_)
+      vibration_actuator_ = nullptr;
+    return;
+  }
+
+  if (!vibration_actuator_)
+    vibration_actuator_ = GamepadHapticActuator::Create(index_);
+
+  vibration_actuator_->SetType(actuator.type);
+}
+
 void Gamepad::SetPose(const device::GamepadPose& pose) {
   if (!pose.not_null) {
     if (pose_)
@@ -112,6 +126,7 @@
 
 void Gamepad::Trace(blink::Visitor* visitor) {
   visitor->Trace(buttons_);
+  visitor->Trace(vibration_actuator_);
   visitor->Trace(pose_);
   ScriptWrappable::Trace(visitor);
 }
diff --git a/third_party/WebKit/Source/modules/gamepad/Gamepad.h b/third_party/WebKit/Source/modules/gamepad/Gamepad.h
index 6ae9f97..53f77ae 100644
--- a/third_party/WebKit/Source/modules/gamepad/Gamepad.h
+++ b/third_party/WebKit/Source/modules/gamepad/Gamepad.h
@@ -28,6 +28,7 @@
 
 #include "device/gamepad/public/cpp/gamepad.h"
 #include "modules/gamepad/GamepadButton.h"
+#include "modules/gamepad/GamepadHapticActuator.h"
 #include "modules/gamepad/GamepadPose.h"
 #include "platform/bindings/ScriptWrappable.h"
 #include "platform/heap/Handle.h"
@@ -68,6 +69,11 @@
   void SetButtons(unsigned count, const device::GamepadButton* data);
   bool isButtonDataDirty() const { return is_button_data_dirty_; }
 
+  GamepadHapticActuator* vibrationActuator() const {
+    return vibration_actuator_;
+  }
+  void SetVibrationActuator(const device::GamepadHapticActuator&);
+
   GamepadPose* pose() const { return pose_; }
   void SetPose(const device::GamepadPose&);
 
@@ -89,6 +95,7 @@
   String mapping_;
   DoubleVector axes_;
   GamepadButtonVector buttons_;
+  Member<GamepadHapticActuator> vibration_actuator_;
   Member<GamepadPose> pose_;
   String hand_;
   unsigned display_id_;
diff --git a/third_party/WebKit/Source/modules/gamepad/Gamepad.idl b/third_party/WebKit/Source/modules/gamepad/Gamepad.idl
index 73e64de1..47353f6d 100644
--- a/third_party/WebKit/Source/modules/gamepad/Gamepad.idl
+++ b/third_party/WebKit/Source/modules/gamepad/Gamepad.idl
@@ -39,6 +39,11 @@
     [CachedAttribute=isAxisDataDirty, MeasureAs=GamepadAxes] readonly attribute FrozenArray<double> axes;
     [CachedAttribute=isButtonDataDirty, MeasureAs=GamepadButtons] readonly attribute FrozenArray<GamepadButton> buttons;
 
+    // Gamepad vibration is proposed as an extension to the Gamepad API.
+    // https://docs.google.com/document/d/1jPKzVRNzzU4dUsvLpSXm1VXPQZ8FP-0lKMT-R_p-s6g
+    // TODO(mattreynolds): Replace this with a link to w3c.github.io/gamepad
+    [OriginTrialEnabled=GamepadExtensions, MeasureAs=GamepadVibrationActuator] readonly attribute GamepadHapticActuator? vibrationActuator;
+
     [OriginTrialEnabled=GamepadExtensions, MeasureAs=GamepadPose] readonly attribute GamepadPose? pose;
     [OriginTrialEnabled=GamepadExtensions, MeasureAs=GamepadHand] readonly attribute GamepadHand hand;
 
diff --git a/third_party/WebKit/Source/modules/gamepad/GamepadDispatcher.cpp b/third_party/WebKit/Source/modules/gamepad/GamepadDispatcher.cpp
index 06e5a07..2a072d8 100644
--- a/third_party/WebKit/Source/modules/gamepad/GamepadDispatcher.cpp
+++ b/third_party/WebKit/Source/modules/gamepad/GamepadDispatcher.cpp
@@ -6,9 +6,12 @@
 
 #include "modules/gamepad/NavigatorGamepad.h"
 #include "public/platform/Platform.h"
+#include "third_party/WebKit/public/platform/InterfaceProvider.h"
 
 namespace blink {
 
+using device::mojom::blink::GamepadHapticsManager;
+
 GamepadDispatcher& GamepadDispatcher::Instance() {
   DEFINE_STATIC_LOCAL(GamepadDispatcher, gamepad_dispatcher,
                       (new GamepadDispatcher));
@@ -19,9 +22,34 @@
   Platform::Current()->SampleGamepads(gamepads);
 }
 
-GamepadDispatcher::GamepadDispatcher() {}
+void GamepadDispatcher::PlayVibrationEffectOnce(
+    int pad_index,
+    device::mojom::blink::GamepadHapticEffectType type,
+    device::mojom::blink::GamepadEffectParametersPtr params,
+    GamepadHapticsManager::PlayVibrationEffectOnceCallback callback) {
+  InitializeHaptics();
+  gamepad_haptics_manager_->PlayVibrationEffectOnce(
+      pad_index, type, std::move(params), std::move(callback));
+}
 
-GamepadDispatcher::~GamepadDispatcher() {}
+void GamepadDispatcher::ResetVibrationActuator(
+    int pad_index,
+    GamepadHapticsManager::ResetVibrationActuatorCallback callback) {
+  InitializeHaptics();
+  gamepad_haptics_manager_->ResetVibrationActuator(pad_index,
+                                                   std::move(callback));
+}
+
+GamepadDispatcher::GamepadDispatcher() = default;
+
+GamepadDispatcher::~GamepadDispatcher() = default;
+
+void GamepadDispatcher::InitializeHaptics() {
+  if (!gamepad_haptics_manager_) {
+    Platform::Current()->GetInterfaceProvider()->GetInterface(
+        mojo::MakeRequest(&gamepad_haptics_manager_));
+  }
+}
 
 void GamepadDispatcher::Trace(blink::Visitor* visitor) {
   PlatformEventDispatcher::Trace(visitor);
diff --git a/third_party/WebKit/Source/modules/gamepad/GamepadDispatcher.h b/third_party/WebKit/Source/modules/gamepad/GamepadDispatcher.h
index 5dde741..856ab1d 100644
--- a/third_party/WebKit/Source/modules/gamepad/GamepadDispatcher.h
+++ b/third_party/WebKit/Source/modules/gamepad/GamepadDispatcher.h
@@ -7,6 +7,7 @@
 
 #include "core/frame/PlatformEventDispatcher.h"
 #include "device/gamepad/public/cpp/gamepads.h"
+#include "device/gamepad/public/interfaces/gamepad.mojom-blink.h"
 #include "platform/heap/Handle.h"
 #include "public/platform/WebGamepadListener.h"
 
@@ -24,6 +25,15 @@
 
   void SampleGamepads(device::Gamepads&);
 
+  void PlayVibrationEffectOnce(int pad_index,
+                               device::mojom::blink::GamepadHapticEffectType,
+                               device::mojom::blink::GamepadEffectParametersPtr,
+                               device::mojom::blink::GamepadHapticsManager::
+                                   PlayVibrationEffectOnceCallback);
+  void ResetVibrationActuator(int pad_index,
+                              device::mojom::blink::GamepadHapticsManager::
+                                  ResetVibrationActuatorCallback);
+
   struct ConnectionChange {
     DISALLOW_NEW();
     device::Gamepad pad;
@@ -39,6 +49,8 @@
  private:
   GamepadDispatcher();
 
+  void InitializeHaptics();
+
   // WebGamepadListener
   void DidConnectGamepad(unsigned index, const device::Gamepad&) override;
   void DidDisconnectGamepad(unsigned index, const device::Gamepad&) override;
@@ -52,6 +64,8 @@
                                              bool connected);
 
   ConnectionChange latest_change_;
+
+  device::mojom::blink::GamepadHapticsManagerPtr gamepad_haptics_manager_;
 };
 
 }  // namespace blink
diff --git a/third_party/WebKit/Source/modules/gamepad/GamepadEffectParameters.idl b/third_party/WebKit/Source/modules/gamepad/GamepadEffectParameters.idl
new file mode 100644
index 0000000..6d81895
--- /dev/null
+++ b/third_party/WebKit/Source/modules/gamepad/GamepadEffectParameters.idl
@@ -0,0 +1,13 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Gamepad vibration is proposed as an extension to the Gamepad API.
+// https://docs.google.com/document/d/1jPKzVRNzzU4dUsvLpSXm1VXPQZ8FP-0lKMT-R_p-s6g
+// TODO(mattreynolds): Replace this with a link to w3c.github.io/gamepad
+dictionary GamepadEffectParameters {
+    double duration = 0.0;
+    double startDelay = 0.0;
+    double strongMagnitude = 0.0;
+    double weakMagnitude = 0.0;
+};
diff --git a/third_party/WebKit/Source/modules/gamepad/GamepadHapticActuator.cpp b/third_party/WebKit/Source/modules/gamepad/GamepadHapticActuator.cpp
new file mode 100644
index 0000000..b64ebd7
--- /dev/null
+++ b/third_party/WebKit/Source/modules/gamepad/GamepadHapticActuator.cpp
@@ -0,0 +1,72 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "modules/gamepad/GamepadHapticActuator.h"
+
+#include "bindings/core/v8/ScriptPromiseResolver.h"
+
+namespace {
+
+const char kGamepadHapticActuatorTypeVibration[] = "vibration";
+const char kGamepadHapticActuatorTypeDualRumble[] = "dual-rumble";
+
+const char kGamepadHapticsResultNotSupported[] = "not-supported";
+
+}  // namespace
+
+namespace blink {
+
+// static
+GamepadHapticActuator* GamepadHapticActuator::Create(int pad_index) {
+  return new GamepadHapticActuator(
+      pad_index, device::GamepadHapticActuatorType::kDualRumble);
+}
+
+GamepadHapticActuator::GamepadHapticActuator(
+    int pad_index,
+    device::GamepadHapticActuatorType type) {
+  SetType(type);
+}
+
+GamepadHapticActuator::~GamepadHapticActuator() = default;
+
+void GamepadHapticActuator::SetType(device::GamepadHapticActuatorType type) {
+  switch (type) {
+    case device::GamepadHapticActuatorType::kVibration:
+      type_ = kGamepadHapticActuatorTypeVibration;
+      break;
+    case device::GamepadHapticActuatorType::kDualRumble:
+      type_ = kGamepadHapticActuatorTypeDualRumble;
+      break;
+    default:
+      NOTREACHED();
+  }
+}
+
+ScriptPromise GamepadHapticActuator::playEffect(
+    ScriptState* script_state,
+    const String& type,
+    const GamepadEffectParameters& params) {
+  ScriptPromiseResolver* resolver = ScriptPromiseResolver::Create(script_state);
+  ScriptPromise promise = resolver->Promise();
+  resolver->Resolve(kGamepadHapticsResultNotSupported);
+
+  NOTIMPLEMENTED();
+  return promise;
+}
+
+ScriptPromise GamepadHapticActuator::reset(ScriptState* script_state) {
+  ScriptPromiseResolver* resolver = ScriptPromiseResolver::Create(script_state);
+  ScriptPromise promise = resolver->Promise();
+  resolver->Resolve(kGamepadHapticsResultNotSupported);
+
+  NOTIMPLEMENTED();
+  return promise;
+}
+
+void GamepadHapticActuator::Trace(blink::Visitor* visitor) {
+  ScriptWrappable::Trace(visitor);
+}
+
+}  // namespace blink
diff --git a/third_party/WebKit/Source/modules/gamepad/GamepadHapticActuator.h b/third_party/WebKit/Source/modules/gamepad/GamepadHapticActuator.h
new file mode 100644
index 0000000..ac7dde8
--- /dev/null
+++ b/third_party/WebKit/Source/modules/gamepad/GamepadHapticActuator.h
@@ -0,0 +1,46 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef GamepadHapticActuator_h
+#define GamepadHapticActuator_h
+
+#include "bindings/core/v8/ScriptPromise.h"
+#include "device/gamepad/public/cpp/gamepad.h"
+#include "modules/gamepad/GamepadEffectParameters.h"
+#include "platform/bindings/ScriptWrappable.h"
+#include "platform/heap/Handle.h"
+#include "platform/wtf/Vector.h"
+#include "platform/wtf/text/WTFString.h"
+
+namespace blink {
+
+class GamepadHapticActuator final : public ScriptWrappable {
+  DEFINE_WRAPPERTYPEINFO();
+
+ public:
+  static GamepadHapticActuator* Create(int pad_index);
+  ~GamepadHapticActuator();
+
+  const String& type() const { return type_; }
+  void SetType(device::GamepadHapticActuatorType);
+
+  ScriptPromise playEffect(ScriptState*,
+                           const String&,
+                           const GamepadEffectParameters&);
+
+  ScriptPromise reset(ScriptState*);
+
+  void Trace(blink::Visitor*);
+
+ private:
+  GamepadHapticActuator(int pad_index, device::GamepadHapticActuatorType);
+
+  String type_;
+};
+
+typedef HeapVector<Member<GamepadHapticActuator>> GamepadHapticActuatorVector;
+
+}  // namespace blink
+
+#endif  // GamepadHapticActuator_h
diff --git a/third_party/WebKit/Source/modules/gamepad/GamepadHapticActuator.idl b/third_party/WebKit/Source/modules/gamepad/GamepadHapticActuator.idl
new file mode 100644
index 0000000..58ce26c
--- /dev/null
+++ b/third_party/WebKit/Source/modules/gamepad/GamepadHapticActuator.idl
@@ -0,0 +1,33 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// https://w3c.github.io/gamepad/extensions.html#gamepadhapticactuatortype-enum
+enum GamepadHapticActuatorType {
+    "vibration",
+    "dual-rumble"
+};
+
+enum GamepadHapticEffectType {
+    "dual-rumble"
+};
+
+enum GamepadHapticsResult {
+    "complete",
+    "preempted",
+    "invalid-parameter",
+    "not-supported"
+};
+
+// Gamepad vibration is proposed as an extension to the Gamepad API.
+// https://docs.google.com/document/d/1jPKzVRNzzU4dUsvLpSXm1VXPQZ8FP-0lKMT-R_p-s6g
+// TODO(mattreynolds): Replace this with a link to w3c.github.io/gamepad
+[
+    OriginTrialEnabled=GamepadExtensions
+] interface GamepadHapticActuator {
+    readonly attribute GamepadHapticActuatorType type;
+    [CallWith=ScriptState] Promise<GamepadHapticsResult> playEffect(
+        GamepadHapticEffectType type,
+        GamepadEffectParameters params);
+    [CallWith=ScriptState] Promise<GamepadHapticsResult> reset();
+};
diff --git a/third_party/WebKit/Source/modules/gamepad/NavigatorGamepad.cpp b/third_party/WebKit/Source/modules/gamepad/NavigatorGamepad.cpp
index d2ddbb9..8c9231f 100644
--- a/third_party/WebKit/Source/modules/gamepad/NavigatorGamepad.cpp
+++ b/third_party/WebKit/Source/modules/gamepad/NavigatorGamepad.cpp
@@ -34,22 +34,54 @@
 #include "modules/gamepad/GamepadEvent.h"
 #include "modules/gamepad/GamepadList.h"
 
+namespace {
+
+void HasGamepadConnectionChanged(const String& old_id,
+                                 const String& new_id,
+                                 bool old_connected,
+                                 bool new_connected,
+                                 bool* gamepad_found,
+                                 bool* gamepad_lost) {
+  // If the gamepad ID changes, treat it as a disconnection and connection.
+  bool id_changed = old_connected && new_connected && old_id != new_id;
+
+  if (gamepad_found)
+    *gamepad_found = id_changed || (!old_connected && new_connected);
+  if (gamepad_lost)
+    *gamepad_lost = id_changed || (old_connected && !new_connected);
+}
+
+}  // namespace
+
 namespace blink {
 
 template <typename T>
 static void SampleGamepad(unsigned index,
                           T& gamepad,
                           const device::Gamepad& device_gamepad) {
+  String old_id = gamepad.id();
+  bool old_was_connected = gamepad.connected();
+
   gamepad.SetId(device_gamepad.id);
-  gamepad.SetIndex(index);
   gamepad.SetConnected(device_gamepad.connected);
   gamepad.SetTimestamp(device_gamepad.timestamp);
-  gamepad.SetMapping(device_gamepad.mapping);
   gamepad.SetAxes(device_gamepad.axes_length, device_gamepad.axes);
   gamepad.SetButtons(device_gamepad.buttons_length, device_gamepad.buttons);
   gamepad.SetPose(device_gamepad.pose);
   gamepad.SetHand(device_gamepad.hand);
-  gamepad.SetDisplayId(device_gamepad.display_id);
+
+  bool newly_connected;
+  HasGamepadConnectionChanged(old_id, gamepad.id(), old_was_connected,
+                              gamepad.connected(), &newly_connected, nullptr);
+
+  // These fields are not expected to change and will only be written when the
+  // gamepad is newly connected.
+  if (newly_connected) {
+    gamepad.SetIndex(index);
+    gamepad.SetMapping(device_gamepad.mapping);
+    gamepad.SetVibrationActuator(device_gamepad.vibration_actuator);
+    gamepad.SetDisplayId(device_gamepad.display_id);
+  }
 }
 
 template <typename GamepadType, typename ListType>
@@ -249,22 +281,40 @@
   for (unsigned i = 0; i < device::Gamepads::kItemsLengthCap; ++i) {
     Gamepad* old_gamepad = old_gamepads ? old_gamepads->item(i) : nullptr;
     Gamepad* new_gamepad = new_gamepads->item(i);
-    bool old_was_connected = old_gamepad && old_gamepad->connected();
-    bool new_is_connected = new_gamepad && new_gamepad->connected();
-    bool connected_gamepad_changed = old_was_connected && new_is_connected &&
-                                     old_gamepad->id() != new_gamepad->id();
-    if (connected_gamepad_changed || (old_was_connected && !new_is_connected)) {
+    bool connected, disconnected;
+    CheckConnectedGamepad(old_gamepad, new_gamepad, &connected, &disconnected);
+
+    if (disconnected) {
       old_gamepad->SetConnected(false);
       pending_events_.push_back(old_gamepad);
       disconnection_count++;
     }
-    if (connected_gamepad_changed || (!old_was_connected && new_is_connected)) {
+    if (connected) {
       pending_events_.push_back(new_gamepad);
     }
   }
   return disconnection_count > 0;
 }
 
+void NavigatorGamepad::CheckConnectedGamepad(Gamepad* old_gamepad,
+                                             Gamepad* new_gamepad,
+                                             bool* gamepad_found,
+                                             bool* gamepad_lost) {
+  bool old_connected = old_gamepad && old_gamepad->connected();
+  bool new_connected = new_gamepad && new_gamepad->connected();
+  if (old_gamepad && new_gamepad) {
+    HasGamepadConnectionChanged(old_gamepad->id(), new_gamepad->id(),
+                                old_connected, new_connected, gamepad_found,
+                                gamepad_lost);
+    return;
+  }
+
+  if (gamepad_found)
+    *gamepad_found = new_connected;
+  if (gamepad_lost)
+    *gamepad_lost = old_connected;
+}
+
 void NavigatorGamepad::PageVisibilityChanged() {
   // Inform the embedder whether it needs to provide gamepad data for us.
   bool visible = GetPage()->IsPageVisible();
diff --git a/third_party/WebKit/Source/modules/gamepad/NavigatorGamepad.h b/third_party/WebKit/Source/modules/gamepad/NavigatorGamepad.h
index d714da9..743c76da 100644
--- a/third_party/WebKit/Source/modules/gamepad/NavigatorGamepad.h
+++ b/third_party/WebKit/Source/modules/gamepad/NavigatorGamepad.h
@@ -70,6 +70,7 @@
   bool StartUpdatingIfAttached();
   void SampleAndCheckConnectedGamepads();
   bool CheckConnectedGamepads(GamepadList*, GamepadList*);
+  void CheckConnectedGamepad(Gamepad*, Gamepad*, bool*, bool*);
 
   // PageVisibilityObserver
   void PageVisibilityChanged() override;
diff --git a/third_party/WebKit/Source/modules/media_controls/MediaControlsImpl.cpp b/third_party/WebKit/Source/modules/media_controls/MediaControlsImpl.cpp
index 90c3b7b..695ee9f 100644
--- a/third_party/WebKit/Source/modules/media_controls/MediaControlsImpl.cpp
+++ b/third_party/WebKit/Source/modules/media_controls/MediaControlsImpl.cpp
@@ -79,6 +79,7 @@
 #include "modules/remoteplayback/RemotePlayback.h"
 #include "platform/EventDispatchForbiddenScope.h"
 #include "platform/runtime_enabled_features.h"
+#include "public/platform/WebSize.h"
 
 namespace blink {
 
@@ -110,6 +111,10 @@
     "phase-ready state-buffering",        // kBuffering
 };
 
+// The padding in pixels inside the button panel.
+constexpr int kModernControlsAudioButtonPadding = 20;
+constexpr int kModernControlsVideoButtonPadding = 26;
+
 bool ShouldShowFullscreenButton(const HTMLMediaElement& media_element) {
   // Unconditionally allow the user to exit fullscreen if we are in it
   // now.  Especially on android, when we might not yet know if
@@ -865,6 +870,102 @@
   overlay_cast_button_->UpdateDisplayType();
 }
 
+void MediaControlsImpl::UpdateOverflowMenuWanted() const {
+  // If the bool is true then the element is "sticky" this means that we will
+  // always try and show it unless there is not room for it.
+  std::pair<MediaControlElementBase*, bool> row_elements[] = {
+      std::make_pair(play_button_.Get(), true),
+      std::make_pair(mute_button_.Get(), true),
+      std::make_pair(fullscreen_button_.Get(), true),
+      std::make_pair(current_time_display_.Get(), true),
+      std::make_pair(duration_display_.Get(), true),
+      std::make_pair(cast_button_.Get(), false),
+      std::make_pair(download_button_.Get(), false),
+      std::make_pair(toggle_closed_captions_button_.Get(), false),
+  };
+
+  // Get the size of the media controls.
+  WebSize controls_size =
+      MediaControlElementsHelper::GetSizeOrDefault(*this, WebSize(0, 0));
+
+  // The video controls are more than one row so we need to allocate vertical
+  // room and hide the overlay play button if there is not enough room.
+  if (MediaElement().IsHTMLVideoElement()) {
+    // These are the elements in order of priority that take up vertical room.
+    MediaControlElementBase* column_elements[] = {
+        overlay_play_button_.Get(), media_button_panel_.Get(), timeline_.Get(),
+    };
+
+    controls_size.width -= kModernControlsVideoButtonPadding;
+
+    // Allocate vertical room for the column elements.
+    for (MediaControlElementBase* element : column_elements) {
+      WebSize element_size = element->GetSizeOrDefault();
+      if (controls_size.height - element_size.height >= 0) {
+        element->SetDoesFit(true);
+        controls_size.height -= element_size.height;
+      } else {
+        element->SetDoesFit(false);
+      }
+    }
+
+    // If we cannot show the overlay play button, show the normal one.
+    play_button_->SetIsWanted(!overlay_play_button_->DoesFit());
+  } else {
+    controls_size.width -= kModernControlsAudioButtonPadding;
+  }
+
+  // Go through the elements and if they are sticky allocate them to the panel
+  // if we have enough room. If not (or they are not sticky) then add them to
+  // the overflow menu. Once we have run out of room add_elements will be
+  // made false and no more elements will be added.
+  MediaControlElementBase* last_element = nullptr;
+  bool add_elements = true;
+  bool overflow_wanted = false;
+  for (std::pair<MediaControlElementBase*, bool> pair : row_elements) {
+    MediaControlElementBase* element = pair.first;
+
+    // If the element is wanted then it should take up space, otherwise skip it.
+    element->SetOverflowElementIsWanted(false);
+    if (!element->IsWanted())
+      continue;
+
+    // Get the size of the element and see if we should allocate space to it.
+    WebSize element_size = element->GetSizeOrDefault();
+    bool does_fit = add_elements && pair.second &&
+                    ((controls_size.width - element_size.width) >= 0);
+    element->SetDoesFit(does_fit);
+
+    // The element does fit and is sticky so we should allocate space for it. If
+    // we cannot fit this element we should stop allocating space for other
+    // elements.
+    if (does_fit) {
+      controls_size.width -= element_size.width;
+      last_element = element;
+    } else {
+      add_elements = false;
+      if (element->HasOverflowButton()) {
+        overflow_wanted = true;
+        element->SetOverflowElementIsWanted(true);
+      }
+    }
+  }
+
+  overflow_menu_->SetDoesFit(overflow_wanted);
+  overflow_menu_->SetIsWanted(overflow_wanted);
+
+  // If we want to show the overflow button and we do not have any space to show
+  // it then we should hide the last shown element.
+  int overflow_icon_width = overflow_menu_->GetSizeOrDefault().width;
+  if (overflow_wanted && last_element &&
+      controls_size.width < overflow_icon_width) {
+    last_element->SetDoesFit(false);
+    last_element->SetOverflowElementIsWanted(true);
+  }
+
+  MaybeRecordElementsDisplayed();
+}
+
 void MediaControlsImpl::DefaultEventHandler(Event* event) {
   HTMLDivElement::DefaultEventHandler(event);
 
@@ -1166,10 +1267,10 @@
   // Hide all controls that don't fit, and show the ones that do.
   // This might be better suited for a layout, but since JS media controls
   // won't benefit from that anwyay, we just do it here like JS will.
-
-  // TODO(beccahughes): Update this for modern controls.
-  if (IsModern())
+  if (IsModern()) {
+    UpdateOverflowMenuWanted();
     return;
+  }
 
   // Controls that we'll hide / show, in order of decreasing priority.
   MediaControlElementBase* elements[] = {
@@ -1282,15 +1383,36 @@
     overlay_play_button_->SetDoesFit(does_fit);
   }
 
+  MaybeRecordElementsDisplayed();
+}
+
+void MediaControlsImpl::MaybeRecordElementsDisplayed() const {
   // Record the display state when needed. It is only recorded when the media
   // element is in a state that allows it in order to reduce noise in the
   // metrics.
-  if (MediaControlInputElement::ShouldRecordDisplayStates(MediaElement())) {
-    // Record which controls are used.
-    for (const auto& element : elements)
+  if (!MediaControlInputElement::ShouldRecordDisplayStates(MediaElement()))
+    return;
+
+  MediaControlElementBase* elements[] = {
+      play_button_.Get(),
+      fullscreen_button_.Get(),
+      download_button_.Get(),
+      timeline_.Get(),
+      mute_button_.Get(),
+      volume_slider_.Get(),
+      toggle_closed_captions_button_.Get(),
+      cast_button_.Get(),
+      current_time_display_.Get(),
+      duration_display_.Get(),
+      overlay_play_button_.Get(),
+  };
+
+  // Record which controls are used.
+  for (const auto& element : elements) {
+    if (element)
       element->MaybeRecordDisplayed();
-    overflow_menu_->MaybeRecordDisplayed();
   }
+  overflow_menu_->MaybeRecordDisplayed();
 
   if (download_iph_manager_)
     download_iph_manager_->UpdateInProductHelp();
@@ -1306,7 +1428,12 @@
   DCHECK(GetDocument().domWindow());
   DCHECK(GetDocument().domWindow()->visualViewport());
 
-  DOMRect* bounding_client_rect = MediaElement().getBoundingClientRect();
+  // The legacy text tracks have their own button so they should position
+  // themselves based on that button.
+  DOMRect* bounding_client_rect =
+      (popup_menu == text_track_list_ && !IsModern())
+          ? toggle_closed_captions_button_->getBoundingClientRect()
+          : overflow_menu_->getBoundingClientRect();
   DOMVisualViewport* viewport = GetDocument().domWindow()->visualViewport();
 
   WTF::String bottom_str_value = WTF::String::Number(
diff --git a/third_party/WebKit/Source/modules/media_controls/MediaControlsImpl.h b/third_party/WebKit/Source/modules/media_controls/MediaControlsImpl.h
index b7b31bd..9d7a4be0 100644
--- a/third_party/WebKit/Source/modules/media_controls/MediaControlsImpl.h
+++ b/third_party/WebKit/Source/modules/media_controls/MediaControlsImpl.h
@@ -222,6 +222,9 @@
   // current.
   void ComputeWhichControlsFit();
 
+  void UpdateOverflowMenuWanted() const;
+  void MaybeRecordElementsDisplayed() const;
+
   // Takes a popup menu (caption, overflow) and position on the screen. This is
   // used because these menus use a fixed position in order to appear over all
   // content.
diff --git a/third_party/WebKit/Source/modules/media_controls/elements/MediaControlDivElement.cpp b/third_party/WebKit/Source/modules/media_controls/elements/MediaControlDivElement.cpp
index ed80922..22338fe 100644
--- a/third_party/WebKit/Source/modules/media_controls/elements/MediaControlDivElement.cpp
+++ b/third_party/WebKit/Source/modules/media_controls/elements/MediaControlDivElement.cpp
@@ -5,6 +5,8 @@
 #include "modules/media_controls/elements/MediaControlDivElement.h"
 
 #include "modules/media_controls/MediaControlsImpl.h"
+#include "modules/media_controls/elements/MediaControlElementsHelper.h"
+#include "public/platform/WebSize.h"
 
 namespace blink {
 
@@ -26,6 +28,10 @@
   return true;
 }
 
+WebSize MediaControlDivElement::GetSizeOrDefault() const {
+  return MediaControlElementsHelper::GetSizeOrDefault(*this, WebSize(0, 0));
+}
+
 void MediaControlDivElement::Trace(blink::Visitor* visitor) {
   HTMLDivElement::Trace(visitor);
   MediaControlElementBase::Trace(visitor);
diff --git a/third_party/WebKit/Source/modules/media_controls/elements/MediaControlDivElement.h b/third_party/WebKit/Source/modules/media_controls/elements/MediaControlDivElement.h
index df925592..f888426b 100644
--- a/third_party/WebKit/Source/modules/media_controls/elements/MediaControlDivElement.h
+++ b/third_party/WebKit/Source/modules/media_controls/elements/MediaControlDivElement.h
@@ -23,6 +23,10 @@
   void SetOverflowElementIsWanted(bool) final;
   void MaybeRecordDisplayed() final;
 
+  // Get the size of the element in pixels or the default if we cannot get the
+  // size because the element has not been layed out yet.
+  WebSize GetSizeOrDefault() const override;
+
   virtual void Trace(blink::Visitor*);
 
  protected:
diff --git a/third_party/WebKit/Source/modules/media_controls/elements/MediaControlElementBase.h b/third_party/WebKit/Source/modules/media_controls/elements/MediaControlElementBase.h
index 45ec00a..36e8429 100644
--- a/third_party/WebKit/Source/modules/media_controls/elements/MediaControlElementBase.h
+++ b/third_party/WebKit/Source/modules/media_controls/elements/MediaControlElementBase.h
@@ -18,6 +18,7 @@
 class HTMLElement;
 class HTMLMediaElement;
 class MediaControlsImpl;
+struct WebSize;
 
 // MediaControlElementBase is the base class for all the media control elements.
 // It is sub-classed by MediaControlInputElement and MediaControlDivElement
@@ -51,6 +52,10 @@
   // function and return true.
   virtual bool HasOverflowButton() const;
 
+  // Get the size of the element in pixels or the default if we cannot get the
+  // size because the element has not been layed out yet.
+  virtual WebSize GetSizeOrDefault() const = 0;
+
   virtual void Trace(blink::Visitor*);
 
  protected:
diff --git a/third_party/WebKit/Source/modules/media_controls/elements/MediaControlElementsHelper.cpp b/third_party/WebKit/Source/modules/media_controls/elements/MediaControlElementsHelper.cpp
index 2a5725ab..b586321b 100644
--- a/third_party/WebKit/Source/modules/media_controls/elements/MediaControlElementsHelper.cpp
+++ b/third_party/WebKit/Source/modules/media_controls/elements/MediaControlElementsHelper.cpp
@@ -8,9 +8,11 @@
 #include "core/html/HTMLDivElement.h"
 #include "core/html/media/HTMLMediaElement.h"
 #include "core/layout/LayoutSlider.h"
+#include "core/layout/LayoutView.h"
 #include "core/layout/api/LayoutSliderItem.h"
 #include "modules/media_controls/elements/MediaControlDivElement.h"
 #include "modules/media_controls/elements/MediaControlInputElement.h"
+#include "public/platform/WebSize.h"
 
 namespace blink {
 
@@ -85,4 +87,23 @@
   return element;
 }
 
+// static
+WebSize MediaControlElementsHelper::GetSizeOrDefault(
+    const Element& element,
+    const WebSize& default_size) {
+  float zoom_factor = 1.0f;
+  int width = default_size.width;
+  int height = default_size.height;
+
+  if (LayoutBox* box = element.GetLayoutBox()) {
+    width = box->LogicalWidth().Round();
+    height = box->LogicalHeight().Round();
+  }
+
+  if (element.GetDocument().GetLayoutView())
+    zoom_factor = element.GetDocument().GetLayoutView()->ZoomFactor();
+
+  return WebSize(round(width / zoom_factor), round(height / zoom_factor));
+}
+
 }  // namespace blink
diff --git a/third_party/WebKit/Source/modules/media_controls/elements/MediaControlElementsHelper.h b/third_party/WebKit/Source/modules/media_controls/elements/MediaControlElementsHelper.h
index afc043e..b0720b6 100644
--- a/third_party/WebKit/Source/modules/media_controls/elements/MediaControlElementsHelper.h
+++ b/third_party/WebKit/Source/modules/media_controls/elements/MediaControlElementsHelper.h
@@ -16,11 +16,13 @@
 namespace blink {
 
 class ContainerNode;
+class Element;
 class Event;
 class HTMLDivElement;
 class HTMLMediaElement;
 class LayoutObject;
 class Node;
+struct WebSize;
 
 // Helper class for media control elements. It contains methods, constants or
 // concepts shared by more than one element.
@@ -48,6 +50,10 @@
   // Utility function for quickly creating div elements.
   static HTMLDivElement* CreateDiv(const WTF::AtomicString& id,
                                    ContainerNode* parent);
+
+  // Utility function for getting the size in pixels of an element. If the
+  // element has not been layed out then returns the supplied default.
+  static WebSize GetSizeOrDefault(const Element&, const WebSize&);
 };
 
 }  // namespace blink
diff --git a/third_party/WebKit/Source/modules/media_controls/elements/MediaControlInputElement.cpp b/third_party/WebKit/Source/modules/media_controls/elements/MediaControlInputElement.cpp
index 7cc1af1..a6f6931 100644
--- a/third_party/WebKit/Source/modules/media_controls/elements/MediaControlInputElement.cpp
+++ b/third_party/WebKit/Source/modules/media_controls/elements/MediaControlInputElement.cpp
@@ -9,9 +9,18 @@
 #include "core/html/forms/HTMLLabelElement.h"
 #include "core/html/media/HTMLMediaElement.h"
 #include "modules/media_controls/MediaControlsImpl.h"
+#include "modules/media_controls/elements/MediaControlElementsHelper.h"
 #include "platform/Histogram.h"
 #include "platform/runtime_enabled_features.h"
 #include "platform/text/PlatformLocale.h"
+#include "public/platform/WebSize.h"
+
+namespace {
+
+// The default size of an overflow button in pixels.
+constexpr int kDefaultButtonSize = 36;
+
+}  // namespace
 
 namespace blink {
 
@@ -193,6 +202,16 @@
     overflow_element_->UpdateDisplayType();
 }
 
+WebSize MediaControlInputElement::GetSizeOrDefault() const {
+  if (HasOverflowButton()) {
+    // If this has an overflow button then it is a button control and therefore
+    // has a default size of kDefaultButtonSize.
+    return MediaControlElementsHelper::GetSizeOrDefault(
+        *this, WebSize(kDefaultButtonSize, kDefaultButtonSize));
+  }
+  return MediaControlElementsHelper::GetSizeOrDefault(*this, WebSize(0, 0));
+}
+
 void MediaControlInputElement::Trace(blink::Visitor* visitor) {
   HTMLInputElement::Trace(visitor);
   MediaControlElementBase::Trace(visitor);
diff --git a/third_party/WebKit/Source/modules/media_controls/elements/MediaControlInputElement.h b/third_party/WebKit/Source/modules/media_controls/elements/MediaControlInputElement.h
index 6206cb2..83214ef 100644
--- a/third_party/WebKit/Source/modules/media_controls/elements/MediaControlInputElement.h
+++ b/third_party/WebKit/Source/modules/media_controls/elements/MediaControlInputElement.h
@@ -35,6 +35,10 @@
     return overflow_element_;
   }
 
+  // Get the size of the element in pixels or the default if we cannot get the
+  // size because the element has not been layed out yet.
+  WebSize GetSizeOrDefault() const override;
+
  protected:
   MediaControlInputElement(MediaControlsImpl&, MediaControlElementType);
 
diff --git a/third_party/WebKit/Source/modules/media_controls/elements/MediaControlOverlayPlayButtonElement.cpp b/third_party/WebKit/Source/modules/media_controls/elements/MediaControlOverlayPlayButtonElement.cpp
index e03a3e3..9df9a0e 100644
--- a/third_party/WebKit/Source/modules/media_controls/elements/MediaControlOverlayPlayButtonElement.cpp
+++ b/third_party/WebKit/Source/modules/media_controls/elements/MediaControlOverlayPlayButtonElement.cpp
@@ -13,6 +13,14 @@
 #include "modules/media_controls/elements/MediaControlElementsHelper.h"
 #include "platform/runtime_enabled_features.h"
 #include "public/platform/Platform.h"
+#include "public/platform/WebSize.h"
+
+namespace {
+
+// The size of the inner circle button in pixels.
+constexpr int kInnerButtonSize = 56;
+
+}  // namespace.
 
 namespace blink {
 
@@ -25,14 +33,15 @@
 //   This contains the inner circle with the actual play/pause icon.
 MediaControlOverlayPlayButtonElement::MediaControlOverlayPlayButtonElement(
     MediaControlsImpl& media_controls)
-    : MediaControlInputElement(media_controls, kMediaOverlayPlayButton) {
+    : MediaControlInputElement(media_controls, kMediaOverlayPlayButton),
+      internal_button_(nullptr) {
   EnsureUserAgentShadowRoot();
   setType(InputTypeNames::button);
   SetShadowPseudoId(AtomicString("-webkit-media-controls-overlay-play-button"));
 
   if (MediaControlsImpl::IsModern()) {
     ShadowRoot& shadow_root = Shadow()->OldestShadowRoot();
-    MediaControlElementsHelper::CreateDiv(
+    internal_button_ = MediaControlElementsHelper::CreateDiv(
         "-internal-media-controls-overlay-play-button-internal", &shadow_root);
   }
 }
@@ -77,4 +86,16 @@
   return MediaControlElementsHelper::IsUserInteractionEvent(event);
 }
 
+WebSize MediaControlOverlayPlayButtonElement::GetSizeOrDefault() const {
+  // The size should come from the internal button which actually displays the
+  // button.
+  return MediaControlElementsHelper::GetSizeOrDefault(
+      *internal_button_, WebSize(kInnerButtonSize, kInnerButtonSize));
+}
+
+void MediaControlOverlayPlayButtonElement::Trace(blink::Visitor* visitor) {
+  MediaControlInputElement::Trace(visitor);
+  visitor->Trace(internal_button_);
+}
+
 }  // namespace blink
diff --git a/third_party/WebKit/Source/modules/media_controls/elements/MediaControlOverlayPlayButtonElement.h b/third_party/WebKit/Source/modules/media_controls/elements/MediaControlOverlayPlayButtonElement.h
index cb35a6f..9572452 100644
--- a/third_party/WebKit/Source/modules/media_controls/elements/MediaControlOverlayPlayButtonElement.h
+++ b/third_party/WebKit/Source/modules/media_controls/elements/MediaControlOverlayPlayButtonElement.h
@@ -10,6 +10,7 @@
 namespace blink {
 
 class Event;
+class HTMLDivElement;
 class MediaControlsImpl;
 
 class MediaControlOverlayPlayButtonElement final
@@ -20,12 +21,18 @@
   // MediaControlInputElement overrides.
   void UpdateDisplayType() override;
 
+  WebSize GetSizeOrDefault() const final;
+
+  void Trace(blink::Visitor*) override;
+
  protected:
   const char* GetNameForHistograms() const override;
 
  private:
   void DefaultEventHandler(Event*) override;
   bool KeepEventInNode(Event*) override;
+
+  Member<HTMLDivElement> internal_button_;
 };
 
 }  // namespace blink
diff --git a/third_party/WebKit/Source/modules/media_controls/elements/MediaControlTextTrackListElement.cpp b/third_party/WebKit/Source/modules/media_controls/elements/MediaControlTextTrackListElement.cpp
index a09f3e0..da64535 100644
--- a/third_party/WebKit/Source/modules/media_controls/elements/MediaControlTextTrackListElement.cpp
+++ b/third_party/WebKit/Source/modules/media_controls/elements/MediaControlTextTrackListElement.cpp
@@ -68,7 +68,12 @@
 }
 
 void MediaControlTextTrackListElement::DefaultEventHandler(Event* event) {
-  if (event->type() == EventTypeNames::change) {
+  if (event->type() == EventTypeNames::click) {
+    // This handles the back button click. Clicking on a menu item triggers the
+    // change event instead.
+    GetMediaControls().ToggleOverflowMenu();
+    event->SetDefaultHandled();
+  } else if (event->type() == EventTypeNames::change) {
     // Identify which input element was selected and set track to showing
     Node* target = event->target()->ToNode();
     if (!target || !target->IsElementNode())
@@ -132,9 +137,15 @@
       track_item_input->setChecked(true);
   }
 
-  track_item->AppendChild(track_item_input);
+  // Modern media controls should have the checkbox after the text instead of
+  // the other way around.
+  if (!MediaControlsImpl::IsModern())
+    track_item->AppendChild(track_item_input);
   String track_label = GetTextTrackLabel(track);
   track_item->AppendChild(Text::Create(GetDocument(), track_label));
+  if (MediaControlsImpl::IsModern())
+    track_item->AppendChild(track_item_input);
+
   // Add a track kind marker icon if there are multiple tracks with the same
   // label or if the track has no label.
   if (track && (track->label().IsEmpty() || HasDuplicateLabel(track))) {
@@ -152,6 +163,17 @@
   return track_item;
 }
 
+Element* MediaControlTextTrackListElement::CreateTextTrackHeaderItem() {
+  HTMLLabelElement* header_item = HTMLLabelElement::Create(GetDocument());
+  header_item->SetShadowPseudoId(
+      "-internal-media-controls-text-track-list-header");
+  header_item->AppendChild(
+      Text::Create(GetDocument(),
+                   GetLocale().QueryString(
+                       WebLocalizedString::kOverflowMenuCaptionsSubmenuTitle)));
+  return header_item;
+}
+
 void MediaControlTextTrackListElement::RefreshTextTrackListMenu() {
   if (!MediaElement().HasClosedCaptions() ||
       !MediaElement().TextTracksAreReady()) {
@@ -161,6 +183,9 @@
   EventDispatchForbiddenScope::AllowUserAgentEvents allow_events;
   RemoveChildren(kOmitSubtreeModifiedEvent);
 
+  if (MediaControlsImpl::IsModern())
+    AppendChild(CreateTextTrackHeaderItem());
+
   // Construct a menu for subtitles and captions.  Pass in a nullptr to
   // createTextTrackListItem to create the "Off" track item.
   AppendChild(CreateTextTrackListItem(nullptr));
diff --git a/third_party/WebKit/Source/modules/media_controls/elements/MediaControlTextTrackListElement.h b/third_party/WebKit/Source/modules/media_controls/elements/MediaControlTextTrackListElement.h
index 7f168a7..65348784 100644
--- a/third_party/WebKit/Source/modules/media_controls/elements/MediaControlTextTrackListElement.h
+++ b/third_party/WebKit/Source/modules/media_controls/elements/MediaControlTextTrackListElement.h
@@ -35,6 +35,9 @@
   // Creates the track element in the list when a valid track is passed in and
   // the "Off" item when the parameter is null.
   Element* CreateTextTrackListItem(TextTrack*);
+
+  // Creates the header element of the text track list (modern only).
+  Element* CreateTextTrackHeaderItem();
 };
 
 }  // namespace blink
diff --git a/third_party/WebKit/Source/modules/media_controls/resources/default_100_percent/modern/ic_arrow_back.png b/third_party/WebKit/Source/modules/media_controls/resources/default_100_percent/modern/ic_arrow_back.png
new file mode 100644
index 0000000..497a35b
--- /dev/null
+++ b/third_party/WebKit/Source/modules/media_controls/resources/default_100_percent/modern/ic_arrow_back.png
Binary files differ
diff --git a/third_party/WebKit/Source/modules/media_controls/resources/default_100_percent/modern/ic_check_blue.png b/third_party/WebKit/Source/modules/media_controls/resources/default_100_percent/modern/ic_check_blue.png
new file mode 100644
index 0000000..c7f44f49
--- /dev/null
+++ b/third_party/WebKit/Source/modules/media_controls/resources/default_100_percent/modern/ic_check_blue.png
Binary files differ
diff --git a/third_party/WebKit/Source/modules/media_controls/resources/default_200_percent/modern/ic_arrow_back.png b/third_party/WebKit/Source/modules/media_controls/resources/default_200_percent/modern/ic_arrow_back.png
new file mode 100644
index 0000000..73f1dda9
--- /dev/null
+++ b/third_party/WebKit/Source/modules/media_controls/resources/default_200_percent/modern/ic_arrow_back.png
Binary files differ
diff --git a/third_party/WebKit/Source/modules/media_controls/resources/default_200_percent/modern/ic_check_blue.png b/third_party/WebKit/Source/modules/media_controls/resources/default_200_percent/modern/ic_check_blue.png
new file mode 100644
index 0000000..e379780
--- /dev/null
+++ b/third_party/WebKit/Source/modules/media_controls/resources/default_200_percent/modern/ic_check_blue.png
Binary files differ
diff --git a/third_party/WebKit/Source/modules/media_controls/resources/modernMediaControls.css b/third_party/WebKit/Source/modules/media_controls/resources/modernMediaControls.css
index 2e6d0b0a0..aed3e98 100644
--- a/third_party/WebKit/Source/modules/media_controls/resources/modernMediaControls.css
+++ b/third_party/WebKit/Source/modules/media_controls/resources/modernMediaControls.css
@@ -351,8 +351,10 @@
  * Overflow Menu
  */
 
-video::-internal-media-controls-overflow-menu-list,
-audio::-internal-media-controls-overflow-menu-list {
+audio::-internal-media-controls-text-track-list,
+video::-internal-media-controls-text-track-list,
+audio::-internal-media-controls-overflow-menu-list,
+video::-internal-media-controls-overflow-menu-list {
   position: fixed;
   max-width: 50%;
   max-height: 250px;
@@ -366,8 +368,12 @@
   border-radius: 2px;
 }
 
-video::-internal-media-controls-overflow-menu-list-item,
-audio::-internal-media-controls-overflow-menu-list-item {
+audio::-internal-media-controls-text-track-list-header,
+video::-internal-media-controls-text-track-list-header,
+audio::-internal-media-controls-text-track-list-item,
+video::-internal-media-controls-text-track-list-item,
+audio::-internal-media-controls-overflow-menu-list-item,
+video::-internal-media-controls-overflow-menu-list-item {
   display: flex;
   align-items: center;
   justify-content: flex-start;
@@ -386,20 +392,63 @@
   margin-right: 2px;
 }
 
+audio::-internal-media-controls-text-track-list-header:hover,
+video::-internal-media-controls-text-track-list-header:hover,
+audio::-internal-media-controls-overflow-menu-list-item:hover,
 video::-internal-media-controls-overflow-menu-list-item:hover,
-audio::-internal-media-controls-overflow-menu-list-item:hover {
+audio::-internal-media-controls-text-track-list-item:hover,
+video::-internal-media-controls-text-track-list-item:hover {
   background-color: #e0e0e0;
 }
 
+audio::-internal-media-controls-text-track-list-header,
+video::-internal-media-controls-text-track-list-header,
+audio::-internal-media-controls-text-track-list-item,
+video::-internal-media-controls-text-track-list-item {
+  padding-left: 58px;
+  display: block;
+}
+
+audio::-internal-media-controls-text-track-list-header,
+video::-internal-media-controls-text-track-list-header {
+  background-size: 18px;
+  background-position: 20px center;
+  background-repeat: no-repeat;
+  background-image: -webkit-image-set(
+    url(default_100_percent/modern/ic_arrow_back.png) 1x,
+    url(default_200_percent/modern/ic_arrow_back.png) 2x);
+}
+
+label[pseudo="-internal-media-controls-text-track-list-item"] input {
+  -webkit-appearance: none;
+  width: 18px;
+  height: 18px;
+  margin: 15px;
+  float: right;
+}
+
+label[pseudo="-internal-media-controls-text-track-list-item"] input:checked {
+  background-image: -webkit-image-set(
+    url(default_100_percent/modern/ic_check_blue.png) 1x,
+    url(default_200_percent/modern/ic_check_blue.png) 2x);
+}
+
 /**
  * Audio Controls
  */
 
 audio::-webkit-media-controls {
   min-width: 240px;
+  display: flex;
+  align-items: center;
+  justify-content: center;
 }
 
-audio::-webkit-media-controls {
+audio::-webkit-media-controls-overlay-enclosure {
+  display: none;
+}
+
+audio::-webkit-media-controls-enclosure {
   max-height: 54px;
   flex-direction: row;
   background: #F1F3F4;
@@ -407,10 +456,6 @@
   overflow: hidden;
 }
 
-audio::-webkit-media-controls-overlay-enclosure {
-  display: none;
-}
-
 audio::-webkit-media-controls-panel {
   flex-direction: row;
   background: none;
diff --git a/third_party/WebKit/Source/modules/mediastream/UserMediaRequest.cpp b/third_party/WebKit/Source/modules/mediastream/UserMediaRequest.cpp
index 0c5a5ca..45d56923 100644
--- a/third_party/WebKit/Source/modules/mediastream/UserMediaRequest.cpp
+++ b/third_party/WebKit/Source/modules/mediastream/UserMediaRequest.cpp
@@ -403,13 +403,31 @@
                       WebFeature::kGetUserMediaSecureOrigin);
     UseCounter::CountCrossOriginIframe(
         *document, WebFeature::kGetUserMediaSecureOriginIframe);
+
+    // Feature policy deprecation messages.
     if (Audio()) {
-      Deprecation::CountDeprecationFeaturePolicy(
-          *document, WebFeaturePolicyFeature::kMicrophone);
+      if (RuntimeEnabledFeatures::FeaturePolicyForPermissionsEnabled()) {
+        if (!document->GetFrame()->IsFeatureEnabled(
+                WebFeaturePolicyFeature::kMicrophone)) {
+          UseCounter::Count(
+              document, WebFeature::kMicrophoneDisabledByFeaturePolicyEstimate);
+        }
+      } else {
+        Deprecation::CountDeprecationFeaturePolicy(
+            *document, WebFeaturePolicyFeature::kMicrophone);
+      }
     }
     if (Video()) {
-      Deprecation::CountDeprecationFeaturePolicy(
-          *document, WebFeaturePolicyFeature::kCamera);
+      if (RuntimeEnabledFeatures::FeaturePolicyForPermissionsEnabled()) {
+        if (!document->GetFrame()->IsFeatureEnabled(
+                WebFeaturePolicyFeature::kCamera)) {
+          UseCounter::Count(document,
+                            WebFeature::kCameraDisabledByFeaturePolicyEstimate);
+        }
+      } else {
+        Deprecation::CountDeprecationFeaturePolicy(
+            *document, WebFeaturePolicyFeature::kCamera);
+      }
     }
 
     HostsUsingFeatures::CountAnyWorld(
diff --git a/third_party/WebKit/Source/modules/modules_idl_files.gni b/third_party/WebKit/Source/modules/modules_idl_files.gni
index f5919141..461a7c6 100644
--- a/third_party/WebKit/Source/modules/modules_idl_files.gni
+++ b/third_party/WebKit/Source/modules/modules_idl_files.gni
@@ -142,6 +142,7 @@
           "gamepad/Gamepad.idl",
           "gamepad/GamepadButton.idl",
           "gamepad/GamepadEvent.idl",
+          "gamepad/GamepadHapticActuator.idl",
           "gamepad/GamepadList.idl",
           "gamepad/GamepadPose.idl",
           "geolocation/Coordinates.idl",
@@ -486,6 +487,7 @@
                     "eventsource/EventSourceInit.idl",
                     "fetch/ResponseInit.idl",
                     "filesystem/FileSystemFlags.idl",
+                    "gamepad/GamepadEffectParameters.idl",
                     "gamepad/GamepadEventInit.idl",
                     "geolocation/PositionOptions.idl",
                     "imagecapture/ConstrainPoint2DParameters.idl",
diff --git a/third_party/WebKit/Source/modules/serviceworkers/ServiceWorkerGlobalScope.cpp b/third_party/WebKit/Source/modules/serviceworkers/ServiceWorkerGlobalScope.cpp
index 2c0430ef..37145b6 100644
--- a/third_party/WebKit/Source/modules/serviceworkers/ServiceWorkerGlobalScope.cpp
+++ b/third_party/WebKit/Source/modules/serviceworkers/ServiceWorkerGlobalScope.cpp
@@ -85,7 +85,7 @@
     // CSP headers, referrer policy, and origin trial tokens will be provided by
     // the InstalledScriptsManager in EvaluateClassicScript().
     DCHECK(creation_params->content_security_policy_parsed_headers->IsEmpty());
-    DCHECK(creation_params->referrer_policy.IsEmpty());
+    DCHECK_EQ(kReferrerPolicyDefault, creation_params->referrer_policy);
     DCHECK(creation_params->origin_trial_tokens->IsEmpty());
   }
   return new ServiceWorkerGlobalScope(std::move(creation_params), thread,
diff --git a/third_party/WebKit/Source/modules/webaudio/AudioWorkletGlobalScopeTest.cpp b/third_party/WebKit/Source/modules/webaudio/AudioWorkletGlobalScopeTest.cpp
index 38f6f91..b0034771 100644
--- a/third_party/WebKit/Source/modules/webaudio/AudioWorkletGlobalScopeTest.cpp
+++ b/third_party/WebKit/Source/modules/webaudio/AudioWorkletGlobalScopeTest.cpp
@@ -14,7 +14,10 @@
 #include "bindings/core/v8/V8CacheOptions.h"
 #include "bindings/core/v8/V8GCController.h"
 #include "bindings/core/v8/WorkerOrWorkletScriptController.h"
+#include "core/dom/Document.h"
 #include "core/dom/TaskRunnerHelper.h"
+#include "core/origin_trials/OriginTrialContext.h"
+#include "core/testing/DummyPageHolder.h"
 #include "core/workers/GlobalScopeCreationParams.h"
 #include "core/workers/WorkerBackingThread.h"
 #include "core/workers/WorkerInspectorProxy.h"
@@ -49,24 +52,28 @@
  public:
   void SetUp() override {
     AudioWorkletThread::CreateSharedBackingThreadForTest();
+    page_ = DummyPageHolder::Create();
+    Document* document = page_->GetFrame().GetDocument();
+    document->SetURL(KURL("https://example.com/"));
+    document->UpdateSecurityOrigin(SecurityOrigin::Create(document->Url()));
     reporting_proxy_ = WTF::MakeUnique<WorkerReportingProxy>();
-    security_origin_ = SecurityOrigin::Create(KURL("http://fake.url/"));
   }
 
   std::unique_ptr<AudioWorkletThread> CreateAudioWorkletThread() {
     std::unique_ptr<AudioWorkletThread> thread =
         AudioWorkletThread::Create(nullptr, *reporting_proxy_);
-    thread->Start(std::make_unique<GlobalScopeCreationParams>(
-                      KURL("http://fake.url/"), "fake user agent",
-                      "" /* source_code */, nullptr /* cached_meta_data */,
-                      nullptr /* content_security_policy_parsed_headers */,
-                      "" /* referrer_policy */, security_origin_.get(),
-                      nullptr /* worker_clients */, kWebAddressSpaceLocal,
-                      nullptr /* origin_trial_tokens */,
-                      nullptr /* worker_settings */, kV8CacheOptionsDefault),
-                  WTF::nullopt,
-                  WorkerInspectorProxy::PauseOnWorkerStart::kDontPause,
-                  ParentFrameTaskRunners::Create());
+    Document* document = page_->GetFrame().GetDocument();
+    thread->Start(
+        std::make_unique<GlobalScopeCreationParams>(
+            document->Url(), document->UserAgent(), "" /* source_code */,
+            nullptr /* cached_meta_data */,
+            nullptr /* content_security_policy_parsed_headers */,
+            document->GetReferrerPolicy(), document->GetSecurityOrigin(),
+            nullptr /* worker_clients */, document->AddressSpace(),
+            OriginTrialContext::GetTokens(document).get(),
+            nullptr /* worker_settings */, kV8CacheOptionsDefault),
+        WTF::nullopt, WorkerInspectorProxy::PauseOnWorkerStart::kDontPause,
+        ParentFrameTaskRunners::Create());
     return thread;
   }
 
@@ -345,7 +352,7 @@
     wait_event->Signal();
   }
 
-  scoped_refptr<SecurityOrigin> security_origin_;
+  std::unique_ptr<DummyPageHolder> page_;
   std::unique_ptr<WorkerReportingProxy> reporting_proxy_;
 };
 
diff --git a/third_party/WebKit/Source/modules/webaudio/AudioWorkletThreadTest.cpp b/third_party/WebKit/Source/modules/webaudio/AudioWorkletThreadTest.cpp
index 2e3b068..2c9a1a9e 100644
--- a/third_party/WebKit/Source/modules/webaudio/AudioWorkletThreadTest.cpp
+++ b/third_party/WebKit/Source/modules/webaudio/AudioWorkletThreadTest.cpp
@@ -12,6 +12,8 @@
 #include "bindings/core/v8/V8GCController.h"
 #include "bindings/core/v8/WorkerOrWorkletScriptController.h"
 #include "core/inspector/ConsoleMessage.h"
+#include "core/origin_trials/OriginTrialContext.h"
+#include "core/testing/DummyPageHolder.h"
 #include "core/workers/GlobalScopeCreationParams.h"
 #include "core/workers/WorkerBackingThread.h"
 #include "core/workers/WorkerInspectorProxy.h"
@@ -38,24 +40,28 @@
  public:
   void SetUp() override {
     AudioWorkletThread::CreateSharedBackingThreadForTest();
+    page_ = DummyPageHolder::Create();
+    Document* document = page_->GetFrame().GetDocument();
+    document->SetURL(KURL("https://example.com/"));
+    document->UpdateSecurityOrigin(SecurityOrigin::Create(document->Url()));
     reporting_proxy_ = WTF::MakeUnique<WorkerReportingProxy>();
-    security_origin_ = SecurityOrigin::Create(KURL("http://fake.url/"));
   }
 
   std::unique_ptr<AudioWorkletThread> CreateAudioWorkletThread() {
     std::unique_ptr<AudioWorkletThread> thread =
         AudioWorkletThread::Create(nullptr, *reporting_proxy_);
-    thread->Start(std::make_unique<GlobalScopeCreationParams>(
-                      KURL("http://fake.url/"), "fake user agent",
-                      "" /* source_code */, nullptr /* cached_meta_data */,
-                      nullptr /* content_security_policy_parsed_headers */,
-                      "" /* referrer_policy */, security_origin_.get(),
-                      nullptr /* worker_clients */, kWebAddressSpaceLocal,
-                      nullptr /* origin_trial_tokens */,
-                      nullptr /* worker_settings */, kV8CacheOptionsDefault),
-                  WTF::nullopt,
-                  WorkerInspectorProxy::PauseOnWorkerStart::kDontPause,
-                  ParentFrameTaskRunners::Create());
+    Document* document = page_->GetFrame().GetDocument();
+    thread->Start(
+        std::make_unique<GlobalScopeCreationParams>(
+            document->Url(), document->UserAgent(), "" /* source_code */,
+            nullptr /* cached_meta_data */,
+            nullptr /* content_security_policy_parsed_headers */,
+            document->GetReferrerPolicy(), document->GetSecurityOrigin(),
+            nullptr /* worker_clients */, document->AddressSpace(),
+            OriginTrialContext::GetTokens(document).get(),
+            nullptr /* worker_settings */, kV8CacheOptionsDefault),
+        WTF::nullopt, WorkerInspectorProxy::PauseOnWorkerStart::kDontPause,
+        ParentFrameTaskRunners::Create());
     return thread;
   }
 
@@ -91,7 +97,7 @@
     wait_event->Signal();
   }
 
-  scoped_refptr<SecurityOrigin> security_origin_;
+  std::unique_ptr<DummyPageHolder> page_;
   std::unique_ptr<WorkerReportingProxy> reporting_proxy_;
 };
 
diff --git a/third_party/WebKit/Source/modules/webmidi/NavigatorWebMIDI.cpp b/third_party/WebKit/Source/modules/webmidi/NavigatorWebMIDI.cpp
index d38b5cf..8ca97e9 100644
--- a/third_party/WebKit/Source/modules/webmidi/NavigatorWebMIDI.cpp
+++ b/third_party/WebKit/Source/modules/webmidi/NavigatorWebMIDI.cpp
@@ -39,11 +39,21 @@
 #include "core/frame/LocalFrame.h"
 #include "core/frame/Navigator.h"
 #include "core/frame/UseCounter.h"
+#include "core/inspector/ConsoleMessage.h"
 #include "modules/webmidi/MIDIAccessInitializer.h"
 #include "modules/webmidi/MIDIOptions.h"
 #include "public/platform/WebFeaturePolicyFeature.h"
 
 namespace blink {
+namespace {
+
+const char kFeaturePolicyErrorMessage[] =
+    "Midi has been disabled in this document by Feature Policy.";
+const char kFeaturePolicyConsoleWarning[] =
+    "Midi access has been blocked because of a Feature Policy applied to the "
+    "current document. See https://goo.gl/EuHzyv for more details.";
+
+}  // namespace
 
 NavigatorWebMIDI::NavigatorWebMIDI(Navigator& navigator)
     : Supplement<Navigator>(navigator) {}
@@ -93,8 +103,22 @@
   }
   UseCounter::CountCrossOriginIframe(
       document, WebFeature::kRequestMIDIAccessIframe_ObscuredByFootprinting);
-  Deprecation::CountDeprecationFeaturePolicy(
-      document, WebFeaturePolicyFeature::kMidiFeature);
+
+  if (RuntimeEnabledFeatures::FeaturePolicyForPermissionsEnabled()) {
+    if (!document.GetFrame()->IsFeatureEnabled(
+            WebFeaturePolicyFeature::kMidiFeature)) {
+      UseCounter::Count(document, WebFeature::kMidiDisabledByFeaturePolicy);
+      document.AddConsoleMessage(
+          ConsoleMessage::Create(kJSMessageSource, kWarningMessageLevel,
+                                 kFeaturePolicyConsoleWarning));
+      return ScriptPromise::RejectWithDOMException(
+          script_state,
+          DOMException::Create(kSecurityError, kFeaturePolicyErrorMessage));
+    }
+  } else {
+    Deprecation::CountDeprecationFeaturePolicy(
+        document, WebFeaturePolicyFeature::kMidiFeature);
+  }
 
   return MIDIAccessInitializer::Start(script_state, options);
 }
diff --git a/third_party/WebKit/Source/platform/AsyncFileSystemCallbacks.h b/third_party/WebKit/Source/platform/AsyncFileSystemCallbacks.h
index e570a6d6..1d4499f 100644
--- a/third_party/WebKit/Source/platform/AsyncFileSystemCallbacks.h
+++ b/third_party/WebKit/Source/platform/AsyncFileSystemCallbacks.h
@@ -72,7 +72,7 @@
 
   // Called when a snapshot file is created successfully.
   virtual void DidCreateSnapshotFile(const FileMetadata&,
-                                     RefPtr<BlobDataHandle> snapshot) {
+                                     scoped_refptr<BlobDataHandle> snapshot) {
     NOTREACHED();
   }
 
diff --git a/third_party/WebKit/Source/platform/BUILD.gn b/third_party/WebKit/Source/platform/BUILD.gn
index 87b3953..343f75a 100644
--- a/third_party/WebKit/Source/platform/BUILD.gn
+++ b/third_party/WebKit/Source/platform/BUILD.gn
@@ -1736,6 +1736,7 @@
     "animation/CompositorFloatAnimationCurveTest.cpp",
     "animation/TimingFunctionTest.cpp",
     "audio/PushPullFIFOTest.cpp",
+    "audio/VectorMathTest.cpp",
     "bindings/RuntimeCallStatsTest.cpp",
     "exported/FilePathConversionTest.cpp",
     "exported/WebCORSPreflightResultCacheTest.cpp",
@@ -2164,6 +2165,7 @@
     "graphics/test/FakeWebGraphicsContext3DProvider.h",
     "graphics/test/MockImageDecoder.h",
     "graphics/test/MockPaintCanvas.h",
+    "graphics/test/StubImage.h",
 
     # Tests migrated from the web/tests directory.
     "TimerPerfTest.cpp",
diff --git a/third_party/WebKit/Source/platform/CalculationValue.h b/third_party/WebKit/Source/platform/CalculationValue.h
index 05a0dad0..ba3114fe 100644
--- a/third_party/WebKit/Source/platform/CalculationValue.h
+++ b/third_party/WebKit/Source/platform/CalculationValue.h
@@ -40,8 +40,8 @@
 
 class PLATFORM_EXPORT CalculationValue : public RefCounted<CalculationValue> {
  public:
-  static RefPtr<CalculationValue> Create(PixelsAndPercent value,
-                                         ValueRange range) {
+  static scoped_refptr<CalculationValue> Create(PixelsAndPercent value,
+                                                ValueRange range) {
     return WTF::AdoptRef(new CalculationValue(value, range));
   }
 
diff --git a/third_party/WebKit/Source/platform/CrossThreadCopier.cpp b/third_party/WebKit/Source/platform/CrossThreadCopier.cpp
index ea339285..ef2b6c7 100644
--- a/third_party/WebKit/Source/platform/CrossThreadCopier.cpp
+++ b/third_party/WebKit/Source/platform/CrossThreadCopier.cpp
@@ -76,11 +76,10 @@
   typedef int Type;
 };
 
-static_assert(
-    (std::is_same<RefPtr<CopierThreadSafeRefCountedTest>,
-                  CrossThreadCopier<
-                      RefPtr<CopierThreadSafeRefCountedTest>>::Type>::value),
-    "RefPtr + ThreadSafeRefCounted should pass CrossThreadCopier");
+static_assert((std::is_same<scoped_refptr<CopierThreadSafeRefCountedTest>,
+                            CrossThreadCopier<scoped_refptr<
+                                CopierThreadSafeRefCountedTest>>::Type>::value),
+              "RefPtr + ThreadSafeRefCounted should pass CrossThreadCopier");
 static_assert(
     (std::is_same<
         int,
diff --git a/third_party/WebKit/Source/platform/CrossThreadCopier.h b/third_party/WebKit/Source/platform/CrossThreadCopier.h
index eefca21..975adf0 100644
--- a/third_party/WebKit/Source/platform/CrossThreadCopier.h
+++ b/third_party/WebKit/Source/platform/CrossThreadCopier.h
@@ -98,19 +98,19 @@
 struct CrossThreadCopier<WTF::RetainedRefWrapper<T>> {
   STATIC_ONLY(CrossThreadCopier);
   static_assert(WTF::IsSubclassOfTemplate<T, ThreadSafeRefCounted>::value,
-                "RefPtr<T> can be passed across threads only if T is "
+                "scoped_refptr<T> can be passed across threads only if T is "
                 "ThreadSafeRefCounted.");
   using Type = WTF::RetainedRefWrapper<T>;
   static Type Copy(Type pointer) { return pointer; }
 };
 template <typename T>
-struct CrossThreadCopier<RefPtr<T>> {
+struct CrossThreadCopier<scoped_refptr<T>> {
   STATIC_ONLY(CrossThreadCopier);
   static_assert(WTF::IsSubclassOfTemplate<T, ThreadSafeRefCounted>::value,
-                "RefPtr<T> can be passed across threads only if T is "
+                "scoped_refptr<T> can be passed across threads only if T is "
                 "ThreadSafeRefCounted.");
-  using Type = RefPtr<T>;
-  static RefPtr<T> Copy(RefPtr<T> pointer) { return pointer; }
+  using Type = scoped_refptr<T>;
+  static scoped_refptr<T> Copy(scoped_refptr<T> pointer) { return pointer; }
 };
 template <typename T>
 struct CrossThreadCopier<sk_sp<T>>
diff --git a/third_party/WebKit/Source/platform/Cursor.h b/third_party/WebKit/Source/platform/Cursor.h
index a5fa6a11..c4013915 100644
--- a/third_party/WebKit/Source/platform/Cursor.h
+++ b/third_party/WebKit/Source/platform/Cursor.h
@@ -117,7 +117,7 @@
 
  private:
   Type type_;
-  RefPtr<Image> image_;
+  scoped_refptr<Image> image_;
   IntPoint hot_spot_;
   float image_scale_factor_;
 };
diff --git a/third_party/WebKit/Source/platform/DragImage.cpp b/third_party/WebKit/Source/platform/DragImage.cpp
index cd514f38c..fa21b50 100644
--- a/third_party/WebKit/Source/platform/DragImage.cpp
+++ b/third_party/WebKit/Source/platform/DragImage.cpp
@@ -309,7 +309,7 @@
                           FloatPoint(text_pos), Font::kDoNotPaintIfFontNotReady,
                           device_scale_factor, text_paint);
 
-  RefPtr<StaticBitmapImage> image = buffer->NewImageSnapshot();
+  scoped_refptr<StaticBitmapImage> image = buffer->NewImageSnapshot();
   return DragImage::Create(image.get(), kDoNotRespectImageOrientation,
                            device_scale_factor);
 }
diff --git a/third_party/WebKit/Source/platform/DragImageTest.cpp b/third_party/WebKit/Source/platform/DragImageTest.cpp
index 01339e6..7dfa7b2 100644
--- a/third_party/WebKit/Source/platform/DragImageTest.cpp
+++ b/third_party/WebKit/Source/platform/DragImageTest.cpp
@@ -49,11 +49,11 @@
 
 class TestImage : public Image {
  public:
-  static RefPtr<TestImage> Create(sk_sp<SkImage> image) {
+  static scoped_refptr<TestImage> Create(sk_sp<SkImage> image) {
     return WTF::AdoptRef(new TestImage(image));
   }
 
-  static RefPtr<TestImage> Create(const IntSize& size) {
+  static scoped_refptr<TestImage> Create(const IntSize& size) {
     return WTF::AdoptRef(new TestImage(size));
   }
 
@@ -109,12 +109,12 @@
 TEST(DragImageTest, NullHandling) {
   EXPECT_FALSE(DragImage::Create(nullptr));
 
-  RefPtr<TestImage> null_test_image(TestImage::Create(IntSize()));
+  scoped_refptr<TestImage> null_test_image(TestImage::Create(IntSize()));
   EXPECT_FALSE(DragImage::Create(null_test_image.get()));
 }
 
 TEST(DragImageTest, NonNullHandling) {
-  RefPtr<TestImage> test_image(TestImage::Create(IntSize(2, 2)));
+  scoped_refptr<TestImage> test_image(TestImage::Create(IntSize(2, 2)));
   std::unique_ptr<DragImage> drag_image = DragImage::Create(test_image.get());
   ASSERT_TRUE(drag_image);
 
@@ -128,7 +128,7 @@
   // Tests that the DrageImage implementation doesn't choke on null values
   // of imageForCurrentFrame().
   // FIXME: how is this test any different from test NullHandling?
-  RefPtr<TestImage> test_image(TestImage::Create(IntSize()));
+  scoped_refptr<TestImage> test_image(TestImage::Create(IntSize()));
   EXPECT_FALSE(DragImage::Create(test_image.get()));
 }
 
@@ -169,7 +169,7 @@
   test_bitmap.eraseArea(SkIRect::MakeXYWH(1, 0, 1, 1), 0xFF000000);
   test_bitmap.eraseArea(SkIRect::MakeXYWH(1, 1, 1, 1), 0xFFFFFFFF);
 
-  RefPtr<TestImage> test_image =
+  scoped_refptr<TestImage> test_image =
       TestImage::Create(SkImage::MakeFromBitmap(test_bitmap));
   std::unique_ptr<DragImage> drag_image = DragImage::Create(
       test_image.get(), kDoNotRespectImageOrientation, 1, kInterpolationNone);
diff --git a/third_party/WebKit/Source/platform/LayoutLocale.cpp b/third_party/WebKit/Source/platform/LayoutLocale.cpp
index 7ae5a86e..118ffd0 100644
--- a/third_party/WebKit/Source/platform/LayoutLocale.cpp
+++ b/third_party/WebKit/Source/platform/LayoutLocale.cpp
@@ -146,7 +146,7 @@
   return *locale;
 }
 
-RefPtr<LayoutLocale> LayoutLocale::CreateForTesting(
+scoped_refptr<LayoutLocale> LayoutLocale::CreateForTesting(
     const AtomicString& locale) {
   return WTF::AdoptRef(new LayoutLocale(locale));
 }
@@ -160,8 +160,9 @@
   return hyphenation_.get();
 }
 
-void LayoutLocale::SetHyphenationForTesting(const AtomicString& locale_string,
-                                            RefPtr<Hyphenation> hyphenation) {
+void LayoutLocale::SetHyphenationForTesting(
+    const AtomicString& locale_string,
+    scoped_refptr<Hyphenation> hyphenation) {
   const LayoutLocale& locale = ValueOrDefault(Get(locale_string));
   locale.hyphenation_computed_ = true;
   locale.hyphenation_ = std::move(hyphenation);
diff --git a/third_party/WebKit/Source/platform/LayoutLocale.h b/third_party/WebKit/Source/platform/LayoutLocale.h
index 2743c33..b6aec3be 100644
--- a/third_party/WebKit/Source/platform/LayoutLocale.h
+++ b/third_party/WebKit/Source/platform/LayoutLocale.h
@@ -60,9 +60,9 @@
 
   AtomicString LocaleWithBreakKeyword(LineBreakIteratorMode) const;
 
-  static RefPtr<LayoutLocale> CreateForTesting(const AtomicString&);
+  static scoped_refptr<LayoutLocale> CreateForTesting(const AtomicString&);
   static void SetHyphenationForTesting(const AtomicString&,
-                                       RefPtr<Hyphenation>);
+                                       scoped_refptr<Hyphenation>);
 
  private:
   explicit LayoutLocale(const AtomicString&);
@@ -71,7 +71,7 @@
 
   AtomicString string_;
   mutable CString string_for_sk_font_mgr_;
-  mutable RefPtr<Hyphenation> hyphenation_;
+  mutable scoped_refptr<Hyphenation> hyphenation_;
 
   // hb_language_t is defined in hb.h, which not all files can include.
   const hb_language_impl_t* harfbuzz_language_;
diff --git a/third_party/WebKit/Source/platform/LayoutLocaleTest.cpp b/third_party/WebKit/Source/platform/LayoutLocaleTest.cpp
index b2ddf65..5368088 100644
--- a/third_party/WebKit/Source/platform/LayoutLocaleTest.cpp
+++ b/third_party/WebKit/Source/platform/LayoutLocaleTest.cpp
@@ -101,7 +101,8 @@
   };
 
   for (const auto& test : tests) {
-    RefPtr<LayoutLocale> locale = LayoutLocale::CreateForTesting(test.locale);
+    scoped_refptr<LayoutLocale> locale =
+        LayoutLocale::CreateForTesting(test.locale);
     EXPECT_EQ(test.script, locale->GetScript()) << test.locale;
     EXPECT_EQ(test.has_script_for_han, locale->HasScriptForHan())
         << test.locale;
@@ -132,7 +133,8 @@
       {"ja@lb=loose", "ja", LineBreakIteratorMode::kLoose},
   };
   for (const auto& test : tests) {
-    RefPtr<LayoutLocale> locale = LayoutLocale::CreateForTesting(test.locale);
+    scoped_refptr<LayoutLocale> locale =
+        LayoutLocale::CreateForTesting(test.locale);
     EXPECT_EQ(test.expected, locale->LocaleWithBreakKeyword(test.mode))
         << String::Format("'%s' with line-break %d should be '%s'", test.locale,
                           static_cast<int>(test.mode), test.expected);
@@ -144,7 +146,7 @@
       "en@x=", "en@lb=xyz", "en@ =",
   };
   for (const auto& test : tests) {
-    RefPtr<LayoutLocale> locale = LayoutLocale::CreateForTesting(test);
+    scoped_refptr<LayoutLocale> locale = LayoutLocale::CreateForTesting(test);
     EXPECT_EQ(test,
               locale->LocaleWithBreakKeyword(LineBreakIteratorMode::kNormal));
   }
diff --git a/third_party/WebKit/Source/platform/Length.cpp b/third_party/WebKit/Source/platform/Length.cpp
index 216bb13..1dbf38a8 100644
--- a/third_party/WebKit/Source/platform/Length.cpp
+++ b/third_party/WebKit/Source/platform/Length.cpp
@@ -38,7 +38,7 @@
  public:
   CalculationValueHandleMap() : index_(1) {}
 
-  int insert(RefPtr<CalculationValue> calc_value) {
+  int insert(scoped_refptr<CalculationValue> calc_value) {
     DCHECK(index_);
     // FIXME calc(): https://bugs.webkit.org/show_bug.cgi?id=80489
     // This monotonically increasing handle generation scheme is potentially
@@ -76,7 +76,7 @@
 
  private:
   int index_;
-  HashMap<int, RefPtr<CalculationValue>> map_;
+  HashMap<int, scoped_refptr<CalculationValue>> map_;
 };
 
 static CalculationValueHandleMap& CalcHandles() {
@@ -84,7 +84,7 @@
   return handle_map;
 }
 
-Length::Length(RefPtr<CalculationValue> calc)
+Length::Length(scoped_refptr<CalculationValue> calc)
     : quirk_(false), type_(kCalculated), is_float_(false) {
   int_value_ = CalcHandles().insert(std::move(calc));
 }
diff --git a/third_party/WebKit/Source/platform/Length.h b/third_party/WebKit/Source/platform/Length.h
index 516bd224..56feb05 100644
--- a/third_party/WebKit/Source/platform/Length.h
+++ b/third_party/WebKit/Source/platform/Length.h
@@ -89,7 +89,7 @@
     float_value_ = static_cast<float>(v);
   }
 
-  explicit Length(RefPtr<CalculationValue>);
+  explicit Length(scoped_refptr<CalculationValue>);
 
   Length(const Length& length) {
     memcpy(this, &length, sizeof(Length));
diff --git a/third_party/WebKit/Source/platform/PODArena.h b/third_party/WebKit/Source/platform/PODArena.h
index 2538aa1a..09b3cd4 100644
--- a/third_party/WebKit/Source/platform/PODArena.h
+++ b/third_party/WebKit/Source/platform/PODArena.h
@@ -61,7 +61,7 @@
   // fastFree to allocate chunks of storage.
   class FastMallocAllocator : public Allocator {
    public:
-    static RefPtr<FastMallocAllocator> Create() {
+    static scoped_refptr<FastMallocAllocator> Create() {
       return WTF::AdoptRef(new FastMallocAllocator);
     }
 
@@ -76,10 +76,12 @@
   };
 
   // Creates a new PODArena configured with a FastMallocAllocator.
-  static RefPtr<PODArena> Create() { return WTF::AdoptRef(new PODArena); }
+  static scoped_refptr<PODArena> Create() {
+    return WTF::AdoptRef(new PODArena);
+  }
 
   // Creates a new PODArena configured with the given Allocator.
-  static RefPtr<PODArena> Create(RefPtr<Allocator> allocator) {
+  static scoped_refptr<PODArena> Create(scoped_refptr<Allocator> allocator) {
     return WTF::AdoptRef(new PODArena(std::move(allocator)));
   }
 
@@ -107,7 +109,7 @@
         current_(0),
         current_chunk_size_(kDefaultChunkSize) {}
 
-  explicit PODArena(RefPtr<Allocator> allocator)
+  explicit PODArena(scoped_refptr<Allocator> allocator)
       : allocator_(std::move(allocator)),
         current_(0),
         current_chunk_size_(kDefaultChunkSize) {}
@@ -182,7 +184,7 @@
     size_t current_offset_;
   };
 
-  RefPtr<Allocator> allocator_;
+  scoped_refptr<Allocator> allocator_;
   Chunk* current_;
   size_t current_chunk_size_;
   Vector<std::unique_ptr<Chunk>> chunks_;
diff --git a/third_party/WebKit/Source/platform/PODArenaTest.cpp b/third_party/WebKit/Source/platform/PODArenaTest.cpp
index 1a3ef66..9f23f1a 100644
--- a/third_party/WebKit/Source/platform/PODArenaTest.cpp
+++ b/third_party/WebKit/Source/platform/PODArenaTest.cpp
@@ -56,8 +56,8 @@
 // Make sure the arena can successfully allocate from more than one
 // region.
 TEST_F(PODArenaTest, CanAllocateFromMoreThanOneRegion) {
-  RefPtr<TrackedAllocator> allocator = TrackedAllocator::Create();
-  RefPtr<PODArena> arena = PODArena::Create(allocator);
+  scoped_refptr<TrackedAllocator> allocator = TrackedAllocator::Create();
+  scoped_refptr<PODArena> arena = PODArena::Create(allocator);
   int num_iterations = 10 * PODArena::kDefaultChunkSize / sizeof(TestClassXYZW);
   for (int i = 0; i < num_iterations; ++i)
     arena->AllocateObject<TestClassXYZW>();
@@ -66,9 +66,9 @@
 
 // Make sure the arena frees all allocated regions during destruction.
 TEST_F(PODArenaTest, FreesAllAllocatedRegions) {
-  RefPtr<TrackedAllocator> allocator = TrackedAllocator::Create();
+  scoped_refptr<TrackedAllocator> allocator = TrackedAllocator::Create();
   {
-    RefPtr<PODArena> arena = PODArena::Create(allocator);
+    scoped_refptr<PODArena> arena = PODArena::Create(allocator);
     for (int i = 0; i < 3; i++)
       arena->AllocateObject<TestClassXYZW>();
     EXPECT_GT(allocator->NumRegions(), 0);
@@ -78,7 +78,7 @@
 
 // Make sure the arena runs constructors of the objects allocated within.
 TEST_F(PODArenaTest, RunsConstructors) {
-  RefPtr<PODArena> arena = PODArena::Create();
+  scoped_refptr<PODArena> arena = PODArena::Create();
   for (int i = 0; i < 10000; i++) {
     TestClassXYZW* tc1 = arena->AllocateObject<TestClassXYZW>();
     EXPECT_EQ(0, tc1->x);
diff --git a/third_party/WebKit/Source/platform/PODFreeListArena.h b/third_party/WebKit/Source/platform/PODFreeListArena.h
index 9239597..452f31a 100644
--- a/third_party/WebKit/Source/platform/PODFreeListArena.h
+++ b/third_party/WebKit/Source/platform/PODFreeListArena.h
@@ -35,13 +35,13 @@
 template <class T>
 class PODFreeListArena : public RefCounted<PODFreeListArena<T>> {
  public:
-  static RefPtr<PODFreeListArena> Create() {
+  static scoped_refptr<PODFreeListArena> Create() {
     return WTF::AdoptRef(new PODFreeListArena);
   }
 
   // Creates a new PODFreeListArena configured with the given Allocator.
-  static RefPtr<PODFreeListArena> Create(
-      RefPtr<PODArena::Allocator> allocator) {
+  static scoped_refptr<PODFreeListArena> Create(
+      scoped_refptr<PODArena::Allocator> allocator) {
     return WTF::AdoptRef(new PODFreeListArena(std::move(allocator)));
   }
 
@@ -83,7 +83,7 @@
  private:
   PODFreeListArena() : arena_(PODArena::Create()), free_list_(0) {}
 
-  explicit PODFreeListArena(RefPtr<PODArena::Allocator> allocator)
+  explicit PODFreeListArena(scoped_refptr<PODArena::Allocator> allocator)
       : arena_(PODArena::Create(std::move(allocator))), free_list_(0) {}
 
   ~PODFreeListArena() {}
@@ -105,7 +105,7 @@
     return total;
   }
 
-  RefPtr<PODArena> arena_;
+  scoped_refptr<PODArena> arena_;
 
   // This free list contains pointers within every chunk that's been allocated
   // so far. None of the individual chunks can be freed until the arena is
diff --git a/third_party/WebKit/Source/platform/PODFreeListArenaTest.cpp b/third_party/WebKit/Source/platform/PODFreeListArenaTest.cpp
index caf65d984..3967578c 100644
--- a/third_party/WebKit/Source/platform/PODFreeListArenaTest.cpp
+++ b/third_party/WebKit/Source/platform/PODFreeListArenaTest.cpp
@@ -56,7 +56,7 @@
 
 class PODFreeListArenaTest : public ::testing::Test {
  protected:
-  int GetFreeListSize(RefPtr<PODFreeListArena<TestClass1>> arena) const {
+  int GetFreeListSize(scoped_refptr<PODFreeListArena<TestClass1>> arena) const {
     return arena->GetFreeListSizeForTesting();
   }
 };
@@ -64,8 +64,8 @@
 // Make sure the arena can successfully allocate from more than one
 // region.
 TEST_F(PODFreeListArenaTest, CanAllocateFromMoreThanOneRegion) {
-  RefPtr<TrackedAllocator> allocator = TrackedAllocator::Create();
-  RefPtr<PODFreeListArena<TestClass1>> arena =
+  scoped_refptr<TrackedAllocator> allocator = TrackedAllocator::Create();
+  scoped_refptr<PODFreeListArena<TestClass1>> arena =
       PODFreeListArena<TestClass1>::Create(allocator);
   int num_iterations = 10 * PODArena::kDefaultChunkSize / sizeof(TestClass1);
   for (int i = 0; i < num_iterations; ++i)
@@ -75,9 +75,9 @@
 
 // Make sure the arena frees all allocated regions during destruction.
 TEST_F(PODFreeListArenaTest, FreesAllAllocatedRegions) {
-  RefPtr<TrackedAllocator> allocator = TrackedAllocator::Create();
+  scoped_refptr<TrackedAllocator> allocator = TrackedAllocator::Create();
   {
-    RefPtr<PODFreeListArena<TestClass1>> arena =
+    scoped_refptr<PODFreeListArena<TestClass1>> arena =
         PODFreeListArena<TestClass1>::Create(allocator);
     for (int i = 0; i < 3; i++)
       arena->AllocateObject();
@@ -88,7 +88,7 @@
 
 // Make sure the arena runs constructors of the objects allocated within.
 TEST_F(PODFreeListArenaTest, RunsConstructorsOnNewObjects) {
-  RefPtr<PODFreeListArena<TestClass1>> arena =
+  scoped_refptr<PODFreeListArena<TestClass1>> arena =
       PODFreeListArena<TestClass1>::Create();
   for (int i = 0; i < 10000; i++) {
     TestClass1* tc1 = arena->AllocateObject();
@@ -102,7 +102,7 @@
 // Make sure the arena runs constructors of the objects allocated within.
 TEST_F(PODFreeListArenaTest, RunsConstructorsOnReusedObjects) {
   std::set<TestClass1*> objects;
-  RefPtr<PODFreeListArena<TestClass1>> arena =
+  scoped_refptr<PODFreeListArena<TestClass1>> arena =
       PODFreeListArena<TestClass1>::Create();
   for (int i = 0; i < 100; i++) {
     TestClass1* tc1 = arena->AllocateObject();
@@ -132,7 +132,7 @@
 // Make sure freeObject puts the object in the free list.
 TEST_F(PODFreeListArenaTest, AddsFreedObjectsToFreedList) {
   Vector<TestClass1*, 100> objects;
-  RefPtr<PODFreeListArena<TestClass1>> arena =
+  scoped_refptr<PODFreeListArena<TestClass1>> arena =
       PODFreeListArena<TestClass1>::Create();
   for (int i = 0; i < 100; i++) {
     objects.push_back(arena->AllocateObject());
@@ -146,7 +146,7 @@
 // Make sure allocations use previously freed memory.
 TEST_F(PODFreeListArenaTest, ReusesPreviouslyFreedObjects) {
   std::set<TestClass2*> objects;
-  RefPtr<PODFreeListArena<TestClass2>> arena =
+  scoped_refptr<PODFreeListArena<TestClass2>> arena =
       PODFreeListArena<TestClass2>::Create();
   for (int i = 0; i < 100; i++) {
     objects.insert(arena->AllocateObject());
diff --git a/third_party/WebKit/Source/platform/PODIntervalTree.h b/third_party/WebKit/Source/platform/PODIntervalTree.h
index 97a2c68..6f4aa4c6 100644
--- a/third_party/WebKit/Source/platform/PODIntervalTree.h
+++ b/third_party/WebKit/Source/platform/PODIntervalTree.h
@@ -85,7 +85,7 @@
 
   PODIntervalTree() : PODRedBlackTree<IntervalType>() { Init(); }
 
-  explicit PODIntervalTree(RefPtr<PODArena> arena)
+  explicit PODIntervalTree(scoped_refptr<PODArena> arena)
       : PODRedBlackTree<IntervalType>(arena) {
     Init();
   }
diff --git a/third_party/WebKit/Source/platform/PODRedBlackTree.h b/third_party/WebKit/Source/platform/PODRedBlackTree.h
index 16f9793..660d4c1 100644
--- a/third_party/WebKit/Source/platform/PODRedBlackTree.h
+++ b/third_party/WebKit/Source/platform/PODRedBlackTree.h
@@ -137,7 +137,7 @@
 
   // Constructs a new red-black tree, allocating temporary objects
   // from the given PODArena.
-  explicit PODRedBlackTree(RefPtr<PODFreeListArena<Node>> arena)
+  explicit PODRedBlackTree(scoped_refptr<PODFreeListArena<Node>> arena)
       : arena_(std::move(arena)),
         root_(0),
         needs_full_ordering_comparisons_(false)
@@ -782,7 +782,7 @@
   //----------------------------------------------------------------------
   // Data members
 
-  RefPtr<PODFreeListArena<Node>> arena_;
+  scoped_refptr<PODFreeListArena<Node>> arena_;
   Node* root_;
   bool needs_full_ordering_comparisons_;
 #ifndef NDEBUG
diff --git a/third_party/WebKit/Source/platform/PODRedBlackTreeTest.cpp b/third_party/WebKit/Source/platform/PODRedBlackTreeTest.cpp
index 6d30ca07..02d54aa 100644
--- a/third_party/WebKit/Source/platform/PODRedBlackTreeTest.cpp
+++ b/third_party/WebKit/Source/platform/PODRedBlackTreeTest.cpp
@@ -39,10 +39,10 @@
 using TreeTestHelpers::NextRandom;
 
 TEST(PODRedBlackTreeTest, TestTreeAllocatesFromArena) {
-  RefPtr<TrackedAllocator> allocator = TrackedAllocator::Create();
+  scoped_refptr<TrackedAllocator> allocator = TrackedAllocator::Create();
   {
     typedef PODFreeListArena<PODRedBlackTree<int>::Node> PODIntegerArena;
-    RefPtr<PODIntegerArena> arena = PODIntegerArena::Create(allocator);
+    scoped_refptr<PODIntegerArena> arena = PODIntegerArena::Create(allocator);
     PODRedBlackTree<int> tree(arena);
     int num_additions = 2 * PODArena::kDefaultChunkSize / sizeof(int);
     for (int i = 0; i < num_additions; ++i)
diff --git a/third_party/WebKit/Source/platform/Prerender.h b/third_party/WebKit/Source/platform/Prerender.h
index 0076b4ac..1e92935 100644
--- a/third_party/WebKit/Source/platform/Prerender.h
+++ b/third_party/WebKit/Source/platform/Prerender.h
@@ -75,7 +75,7 @@
   const String& GetReferrer() const { return referrer_.referrer; }
   ReferrerPolicy GetReferrerPolicy() const { return referrer_.referrer_policy; }
 
-  void SetExtraData(RefPtr<ExtraData> extra_data) {
+  void SetExtraData(scoped_refptr<ExtraData> extra_data) {
     extra_data_ = std::move(extra_data);
   }
   ExtraData* GetExtraData() { return extra_data_.get(); }
@@ -98,7 +98,7 @@
   const unsigned rel_types_;
   const Referrer referrer_;
 
-  RefPtr<ExtraData> extra_data_;
+  scoped_refptr<ExtraData> extra_data_;
 };
 
 }  // namespace blink
diff --git a/third_party/WebKit/Source/platform/SerializedResource.h b/third_party/WebKit/Source/platform/SerializedResource.h
index f164dcd6..e6b0027 100644
--- a/third_party/WebKit/Source/platform/SerializedResource.h
+++ b/third_party/WebKit/Source/platform/SerializedResource.h
@@ -42,11 +42,11 @@
   DISALLOW_NEW_EXCEPT_PLACEMENT_NEW();
   KURL url;
   String mime_type;
-  RefPtr<const SharedBuffer> data;
+  scoped_refptr<const SharedBuffer> data;
 
   SerializedResource(const KURL& url,
                      const String& mime_type,
-                     RefPtr<const SharedBuffer> data)
+                     scoped_refptr<const SharedBuffer> data)
       : url(url), mime_type(mime_type), data(std::move(data)) {}
 };
 
diff --git a/third_party/WebKit/Source/platform/SharedBuffer.cpp b/third_party/WebKit/Source/platform/SharedBuffer.cpp
index 8213867..1804a886 100644
--- a/third_party/WebKit/Source/platform/SharedBuffer.cpp
+++ b/third_party/WebKit/Source/platform/SharedBuffer.cpp
@@ -66,8 +66,8 @@
   Clear();
 }
 
-RefPtr<SharedBuffer> SharedBuffer::AdoptVector(Vector<char>& vector) {
-  RefPtr<SharedBuffer> buffer = Create();
+scoped_refptr<SharedBuffer> SharedBuffer::AdoptVector(Vector<char>& vector) {
+  scoped_refptr<SharedBuffer> buffer = Create();
   buffer->buffer_.swap(vector);
   buffer->size_ = buffer->buffer_.size();
   return buffer;
@@ -264,7 +264,7 @@
 }
 
 SharedBuffer::DeprecatedFlatData::DeprecatedFlatData(
-    RefPtr<const SharedBuffer> buffer)
+    scoped_refptr<const SharedBuffer> buffer)
     : buffer_(std::move(buffer)) {
   DCHECK(buffer_);
 
diff --git a/third_party/WebKit/Source/platform/SharedBuffer.h b/third_party/WebKit/Source/platform/SharedBuffer.h
index 33885b3..c18d6c6e 100644
--- a/third_party/WebKit/Source/platform/SharedBuffer.h
+++ b/third_party/WebKit/Source/platform/SharedBuffer.h
@@ -45,31 +45,31 @@
  public:
   enum : unsigned { kSegmentSize = 0x1000 };
 
-  static RefPtr<SharedBuffer> Create() {
+  static scoped_refptr<SharedBuffer> Create() {
     return WTF::AdoptRef(new SharedBuffer);
   }
 
   HAS_STRICTLY_TYPED_ARG
-  static RefPtr<SharedBuffer> Create(STRICTLY_TYPED_ARG(size)) {
+  static scoped_refptr<SharedBuffer> Create(STRICTLY_TYPED_ARG(size)) {
     STRICT_ARG_TYPE(size_t);
     return WTF::AdoptRef(new SharedBuffer(size));
   }
 
   HAS_STRICTLY_TYPED_ARG
-  static RefPtr<SharedBuffer> Create(const char* data,
-                                     STRICTLY_TYPED_ARG(size)) {
+  static scoped_refptr<SharedBuffer> Create(const char* data,
+                                            STRICTLY_TYPED_ARG(size)) {
     STRICT_ARG_TYPE(size_t);
     return WTF::AdoptRef(new SharedBuffer(data, size));
   }
 
   HAS_STRICTLY_TYPED_ARG
-  static RefPtr<SharedBuffer> Create(const unsigned char* data,
-                                     STRICTLY_TYPED_ARG(size)) {
+  static scoped_refptr<SharedBuffer> Create(const unsigned char* data,
+                                            STRICTLY_TYPED_ARG(size)) {
     STRICT_ARG_TYPE(size_t);
     return WTF::AdoptRef(new SharedBuffer(data, size));
   }
 
-  static RefPtr<SharedBuffer> AdoptVector(Vector<char>&);
+  static scoped_refptr<SharedBuffer> AdoptVector(Vector<char>&);
 
   ~SharedBuffer();
 
@@ -161,13 +161,13 @@
     STACK_ALLOCATED();
 
    public:
-    explicit DeprecatedFlatData(RefPtr<const SharedBuffer>);
+    explicit DeprecatedFlatData(scoped_refptr<const SharedBuffer>);
 
     const char* Data() const { return data_; }
     size_t size() const { return buffer_->size(); }
 
    private:
-    RefPtr<const SharedBuffer> buffer_;
+    scoped_refptr<const SharedBuffer> buffer_;
     Vector<char> flat_buffer_;
     const char* data_;
   };
diff --git a/third_party/WebKit/Source/platform/SharedBufferChunkReader.cpp b/third_party/WebKit/Source/platform/SharedBufferChunkReader.cpp
index 15006111..5b67d1f 100644
--- a/third_party/WebKit/Source/platform/SharedBufferChunkReader.cpp
+++ b/third_party/WebKit/Source/platform/SharedBufferChunkReader.cpp
@@ -35,7 +35,7 @@
 namespace blink {
 
 SharedBufferChunkReader::SharedBufferChunkReader(
-    RefPtr<const SharedBuffer> buffer,
+    scoped_refptr<const SharedBuffer> buffer,
     const Vector<char>& separator)
     : buffer_(std::move(buffer)),
       buffer_position_(0),
@@ -47,7 +47,7 @@
       separator_index_(0) {}
 
 SharedBufferChunkReader::SharedBufferChunkReader(
-    RefPtr<const SharedBuffer> buffer,
+    scoped_refptr<const SharedBuffer> buffer,
     const char* separator)
     : buffer_(std::move(buffer)),
       buffer_position_(0),
diff --git a/third_party/WebKit/Source/platform/SharedBufferChunkReader.h b/third_party/WebKit/Source/platform/SharedBufferChunkReader.h
index e5040ad1..be6780fc 100644
--- a/third_party/WebKit/Source/platform/SharedBufferChunkReader.h
+++ b/third_party/WebKit/Source/platform/SharedBufferChunkReader.h
@@ -46,9 +46,10 @@
   WTF_MAKE_NONCOPYABLE(SharedBufferChunkReader);
 
  public:
-  SharedBufferChunkReader(RefPtr<const SharedBuffer>,
+  SharedBufferChunkReader(scoped_refptr<const SharedBuffer>,
                           const Vector<char>& separator);
-  SharedBufferChunkReader(RefPtr<const SharedBuffer>, const char* separator);
+  SharedBufferChunkReader(scoped_refptr<const SharedBuffer>,
+                          const char* separator);
 
   void SetSeparator(const Vector<char>&);
   void SetSeparator(const char*);
@@ -67,7 +68,7 @@
   size_t Peek(Vector<char>&, size_t);
 
  private:
-  RefPtr<const SharedBuffer> buffer_;
+  scoped_refptr<const SharedBuffer> buffer_;
   size_t buffer_position_;
   const char* segment_;
   size_t segment_length_;
diff --git a/third_party/WebKit/Source/platform/SharedBufferTest.cpp b/third_party/WebKit/Source/platform/SharedBufferTest.cpp
index 7db3b08ca..200d795 100644
--- a/third_party/WebKit/Source/platform/SharedBufferTest.cpp
+++ b/third_party/WebKit/Source/platform/SharedBufferTest.cpp
@@ -45,7 +45,7 @@
   char test_data1[] = "World";
   char test_data2[] = "Goodbye";
 
-  RefPtr<SharedBuffer> shared_buffer =
+  scoped_refptr<SharedBuffer> shared_buffer =
       SharedBuffer::Create(test_data0, strlen(test_data0));
   shared_buffer->Append(test_data1, strlen(test_data1));
   shared_buffer->Append(test_data2, strlen(test_data2));
@@ -65,7 +65,7 @@
   char test_data1[] = "World";
   char test_data2[] = "Goodbye";
 
-  RefPtr<SharedBuffer> shared_buffer =
+  scoped_refptr<SharedBuffer> shared_buffer =
       SharedBuffer::Create(test_data0, strlen(test_data0));
   shared_buffer->Append(test_data1, strlen(test_data1));
   shared_buffer->Append(test_data2, strlen(test_data2));
@@ -94,7 +94,8 @@
   for (size_t i = 0; i < vector2.size(); ++i)
     vector2[i] = 'c';
 
-  RefPtr<SharedBuffer> shared_buffer = SharedBuffer::AdoptVector(vector0);
+  scoped_refptr<SharedBuffer> shared_buffer =
+      SharedBuffer::AdoptVector(vector0);
   shared_buffer->Append(vector1);
   shared_buffer->Append(vector2);
 
@@ -123,7 +124,7 @@
   std::generate(test_data.begin(), test_data.end(), &std::rand);
 
   size_t length = test_data.size();
-  RefPtr<SharedBuffer> shared_buffer =
+  scoped_refptr<SharedBuffer> shared_buffer =
       SharedBuffer::Create(test_data.data(), length);
   shared_buffer->Append(test_data.data(), length);
   shared_buffer->Append(test_data.data(), length);
@@ -144,7 +145,7 @@
 
 TEST(SharedBufferTest, constructorWithSizeOnly) {
   size_t length = 10000;
-  RefPtr<SharedBuffer> shared_buffer = SharedBuffer::Create(length);
+  scoped_refptr<SharedBuffer> shared_buffer = SharedBuffer::Create(length);
   ASSERT_EQ(length, shared_buffer->size());
 
   // The internal flat buffer should have been resized to |length| therefore
@@ -154,7 +155,7 @@
 }
 
 TEST(SharedBufferTest, FlatData) {
-  auto check_flat_data = [](RefPtr<const SharedBuffer> shared_buffer) {
+  auto check_flat_data = [](scoped_refptr<const SharedBuffer> shared_buffer) {
     const SharedBuffer::DeprecatedFlatData flat_buffer(shared_buffer);
 
     EXPECT_EQ(shared_buffer->size(), flat_buffer.size());
@@ -172,7 +173,7 @@
     });
   };
 
-  RefPtr<SharedBuffer> shared_buffer = SharedBuffer::Create();
+  scoped_refptr<SharedBuffer> shared_buffer = SharedBuffer::Create();
 
   // Add enough data to hit a couple of segments.
   while (shared_buffer->size() < 10000) {
diff --git a/third_party/WebKit/Source/platform/Timer.cpp b/third_party/WebKit/Source/platform/Timer.cpp
index e3a80b98..409f4a32 100644
--- a/third_party/WebKit/Source/platform/Timer.cpp
+++ b/third_party/WebKit/Source/platform/Timer.cpp
@@ -40,7 +40,7 @@
 
 namespace blink {
 
-TimerBase::TimerBase(RefPtr<WebTaskRunner> web_task_runner)
+TimerBase::TimerBase(scoped_refptr<WebTaskRunner> web_task_runner)
     : next_fire_time_(0),
       repeat_interval_(0),
       web_task_runner_(std::move(web_task_runner)),
@@ -85,7 +85,7 @@
   return next_fire_time_ - current;
 }
 
-void TimerBase::MoveToNewTaskRunner(RefPtr<WebTaskRunner> task_runner) {
+void TimerBase::MoveToNewTaskRunner(scoped_refptr<WebTaskRunner> task_runner) {
 #if DCHECK_IS_ON()
   DCHECK_EQ(thread_, CurrentThread());
   DCHECK(task_runner->RunsTasksInCurrentSequence());
@@ -111,11 +111,11 @@
 }
 
 // static
-RefPtr<WebTaskRunner> TimerBase::GetTimerTaskRunner() {
+scoped_refptr<WebTaskRunner> TimerBase::GetTimerTaskRunner() {
   return Platform::Current()->CurrentThread()->Scheduler()->TimerTaskRunner();
 }
 
-RefPtr<WebTaskRunner> TimerBase::TimerTaskRunner() const {
+scoped_refptr<WebTaskRunner> TimerBase::TimerTaskRunner() const {
   return web_task_runner_;
 }
 
diff --git a/third_party/WebKit/Source/platform/Timer.h b/third_party/WebKit/Source/platform/Timer.h
index c246af7..2d65428 100644
--- a/third_party/WebKit/Source/platform/Timer.h
+++ b/third_party/WebKit/Source/platform/Timer.h
@@ -47,7 +47,7 @@
   WTF_MAKE_NONCOPYABLE(TimerBase);
 
  public:
-  explicit TimerBase(RefPtr<WebTaskRunner>);
+  explicit TimerBase(scoped_refptr<WebTaskRunner>);
   virtual ~TimerBase();
 
   void Start(double next_fire_interval,
@@ -83,19 +83,19 @@
     repeat_interval_ += delta;
   }
 
-  void MoveToNewTaskRunner(RefPtr<WebTaskRunner>);
+  void MoveToNewTaskRunner(scoped_refptr<WebTaskRunner>);
 
   struct PLATFORM_EXPORT Comparator {
     bool operator()(const TimerBase* a, const TimerBase* b) const;
   };
 
  protected:
-  static RefPtr<WebTaskRunner> GetTimerTaskRunner();
+  static scoped_refptr<WebTaskRunner> GetTimerTaskRunner();
 
  private:
   virtual void Fired() = 0;
 
-  virtual RefPtr<WebTaskRunner> TimerTaskRunner() const;
+  virtual scoped_refptr<WebTaskRunner> TimerTaskRunner() const;
 
   NO_SANITIZE_ADDRESS
   virtual bool CanFire() const { return true; }
@@ -109,7 +109,7 @@
   double next_fire_time_;   // 0 if inactive
   double repeat_interval_;  // 0 if not repeating
   WebTraceLocation location_;
-  RefPtr<WebTaskRunner> web_task_runner_;
+  scoped_refptr<WebTaskRunner> web_task_runner_;
 
 #if DCHECK_IS_ON()
   ThreadIdentifier thread_;
@@ -140,7 +140,7 @@
  public:
   using TimerFiredFunction = void (TimerFiredClass::*)(TimerBase*);
 
-  TaskRunnerTimer(RefPtr<WebTaskRunner> web_task_runner,
+  TaskRunnerTimer(scoped_refptr<WebTaskRunner> web_task_runner,
                   TimerFiredClass* o,
                   TimerFiredFunction f)
       : TimerBase(std::move(web_task_runner)), object_(o), function_(f) {}
diff --git a/third_party/WebKit/Source/platform/TimerTest.cpp b/third_party/WebKit/Source/platform/TimerTest.cpp
index 5be9697e..1e765ae6 100644
--- a/third_party/WebKit/Source/platform/TimerTest.cpp
+++ b/third_party/WebKit/Source/platform/TimerTest.cpp
@@ -81,7 +81,7 @@
  public:
   class Record final : public RefCounted<Record> {
    public:
-    static RefPtr<Record> Create() { return WTF::AdoptRef(new Record); }
+    static scoped_refptr<Record> Create() { return WTF::AdoptRef(new Record); }
 
     bool TimerHasFired() const { return timer_has_fired_; }
     bool IsDisposed() const { return is_disposed_; }
@@ -98,7 +98,7 @@
     bool owner_is_destructed_ = false;
   };
 
-  explicit OnHeapTimerOwner(RefPtr<Record> record)
+  explicit OnHeapTimerOwner(scoped_refptr<Record> record)
       : timer_(this, &OnHeapTimerOwner::Fired), record_(std::move(record)) {}
   ~OnHeapTimerOwner() { record_->SetOwnerIsDestructed(); }
 
@@ -115,7 +115,7 @@
   }
 
   Timer<OnHeapTimerOwner> timer_;
-  RefPtr<Record> record_;
+  scoped_refptr<Record> record_;
 };
 
 class GCForbiddenScope final {
@@ -528,7 +528,7 @@
 
   ~TimerForTest() override {}
 
-  TimerForTest(RefPtr<WebTaskRunner> web_task_runner,
+  TimerForTest(scoped_refptr<WebTaskRunner> web_task_runner,
                TimerFiredClass* timer_fired_class,
                TimerFiredFunction timer_fired_function)
       : TaskRunnerTimer<TimerFiredClass>(std::move(web_task_runner),
@@ -540,7 +540,7 @@
   scoped_refptr<scheduler::TaskQueue> task_runner(
       platform_->GetRendererScheduler()->NewTimerTaskQueue(
           scheduler::MainThreadTaskQueue::QueueType::FRAME_THROTTLEABLE));
-  RefPtr<scheduler::WebTaskRunnerImpl> web_task_runner =
+  scoped_refptr<scheduler::WebTaskRunnerImpl> web_task_runner =
       scheduler::WebTaskRunnerImpl::Create(task_runner);
   TimerForTest<TimerTest> timer(web_task_runner, this,
                                 &TimerTest::CountingTask);
@@ -551,7 +551,8 @@
 }
 
 TEST_F(TimerTest, RunOnHeapTimer) {
-  RefPtr<OnHeapTimerOwner::Record> record = OnHeapTimerOwner::Record::Create();
+  scoped_refptr<OnHeapTimerOwner::Record> record =
+      OnHeapTimerOwner::Record::Create();
   Persistent<OnHeapTimerOwner> owner = new OnHeapTimerOwner(record);
 
   owner->StartOneShot(0, BLINK_FROM_HERE);
@@ -562,7 +563,8 @@
 }
 
 TEST_F(TimerTest, DestructOnHeapTimer) {
-  RefPtr<OnHeapTimerOwner::Record> record = OnHeapTimerOwner::Record::Create();
+  scoped_refptr<OnHeapTimerOwner::Record> record =
+      OnHeapTimerOwner::Record::Create();
   Persistent<OnHeapTimerOwner> owner = new OnHeapTimerOwner(record);
 
   record->Dispose();
@@ -580,7 +582,8 @@
 }
 
 TEST_F(TimerTest, MarkOnHeapTimerAsUnreachable) {
-  RefPtr<OnHeapTimerOwner::Record> record = OnHeapTimerOwner::Record::Create();
+  scoped_refptr<OnHeapTimerOwner::Record> record =
+      OnHeapTimerOwner::Record::Create();
   Persistent<OnHeapTimerOwner> owner = new OnHeapTimerOwner(record);
 
   record->Dispose();
@@ -605,8 +608,8 @@
 
 class TaskObserver : public base::MessageLoop::TaskObserver {
  public:
-  TaskObserver(RefPtr<WebTaskRunner> task_runner,
-               std::vector<RefPtr<WebTaskRunner>>* run_order)
+  TaskObserver(scoped_refptr<WebTaskRunner> task_runner,
+               std::vector<scoped_refptr<WebTaskRunner>>* run_order)
       : task_runner_(std::move(task_runner)), run_order_(run_order) {}
 
   void WillProcessTask(const base::PendingTask&) {}
@@ -616,19 +619,19 @@
   }
 
  private:
-  RefPtr<WebTaskRunner> task_runner_;
-  std::vector<RefPtr<WebTaskRunner>>* run_order_;
+  scoped_refptr<WebTaskRunner> task_runner_;
+  std::vector<scoped_refptr<WebTaskRunner>>* run_order_;
 };
 
 }  // namespace
 
 TEST_F(TimerTest, MoveToNewTaskRunnerOneShot) {
-  std::vector<RefPtr<WebTaskRunner>> run_order;
+  std::vector<scoped_refptr<WebTaskRunner>> run_order;
 
   scoped_refptr<scheduler::TaskQueue> task_runner1(
       platform_->GetRendererScheduler()->NewTimerTaskQueue(
           scheduler::MainThreadTaskQueue::QueueType::FRAME_THROTTLEABLE));
-  RefPtr<scheduler::WebTaskRunnerImpl> web_task_runner1 =
+  scoped_refptr<scheduler::WebTaskRunnerImpl> web_task_runner1 =
       scheduler::WebTaskRunnerImpl::Create(task_runner1);
   TaskObserver task_observer1(web_task_runner1, &run_order);
   task_runner1->AddTaskObserver(&task_observer1);
@@ -636,7 +639,7 @@
   scoped_refptr<scheduler::TaskQueue> task_runner2(
       platform_->GetRendererScheduler()->NewTimerTaskQueue(
           scheduler::MainThreadTaskQueue::QueueType::FRAME_THROTTLEABLE));
-  RefPtr<scheduler::WebTaskRunnerImpl> web_task_runner2 =
+  scoped_refptr<scheduler::WebTaskRunnerImpl> web_task_runner2 =
       scheduler::WebTaskRunnerImpl::Create(task_runner2);
   TaskObserver task_observer2(web_task_runner2, &run_order);
   task_runner2->AddTaskObserver(&task_observer2);
@@ -663,12 +666,12 @@
 }
 
 TEST_F(TimerTest, MoveToNewTaskRunnerRepeating) {
-  std::vector<RefPtr<WebTaskRunner>> run_order;
+  std::vector<scoped_refptr<WebTaskRunner>> run_order;
 
   scoped_refptr<scheduler::TaskQueue> task_runner1(
       platform_->GetRendererScheduler()->NewTimerTaskQueue(
           scheduler::MainThreadTaskQueue::QueueType::FRAME_THROTTLEABLE));
-  RefPtr<scheduler::WebTaskRunnerImpl> web_task_runner1 =
+  scoped_refptr<scheduler::WebTaskRunnerImpl> web_task_runner1 =
       scheduler::WebTaskRunnerImpl::Create(task_runner1);
   TaskObserver task_observer1(web_task_runner1, &run_order);
   task_runner1->AddTaskObserver(&task_observer1);
@@ -676,7 +679,7 @@
   scoped_refptr<scheduler::TaskQueue> task_runner2(
       platform_->GetRendererScheduler()->NewTimerTaskQueue(
           scheduler::MainThreadTaskQueue::QueueType::FRAME_THROTTLEABLE));
-  RefPtr<scheduler::WebTaskRunnerImpl> web_task_runner2 =
+  scoped_refptr<scheduler::WebTaskRunnerImpl> web_task_runner2 =
       scheduler::WebTaskRunnerImpl::Create(task_runner2);
   TaskObserver task_observer2(web_task_runner2, &run_order);
   task_runner2->AddTaskObserver(&task_observer2);
@@ -710,13 +713,13 @@
   scoped_refptr<scheduler::TaskQueue> task_runner1(
       platform_->GetRendererScheduler()->NewTimerTaskQueue(
           scheduler::MainThreadTaskQueue::QueueType::FRAME_THROTTLEABLE));
-  RefPtr<scheduler::WebTaskRunnerImpl> web_task_runner1 =
+  scoped_refptr<scheduler::WebTaskRunnerImpl> web_task_runner1 =
       scheduler::WebTaskRunnerImpl::Create(task_runner1);
 
   scoped_refptr<scheduler::TaskQueue> task_runner2(
       platform_->GetRendererScheduler()->NewTimerTaskQueue(
           scheduler::MainThreadTaskQueue::QueueType::FRAME_THROTTLEABLE));
-  RefPtr<scheduler::WebTaskRunnerImpl> web_task_runner2 =
+  scoped_refptr<scheduler::WebTaskRunnerImpl> web_task_runner2 =
       scheduler::WebTaskRunnerImpl::Create(task_runner2);
 
   TimerForTest<TimerTest> timer(web_task_runner1, this,
diff --git a/third_party/WebKit/Source/platform/WebFrameScheduler.h b/third_party/WebKit/Source/platform/WebFrameScheduler.h
index 1f35ec5..04ff36e9 100644
--- a/third_party/WebKit/Source/platform/WebFrameScheduler.h
+++ b/third_party/WebKit/Source/platform/WebFrameScheduler.h
@@ -116,7 +116,7 @@
   // and unthrottled task runner corresponds to pausable task runner.
 
   // Returns a WebTaskRunner that is suitable with the given task type.
-  virtual RefPtr<WebTaskRunner> GetTaskRunner(TaskType) = 0;
+  virtual scoped_refptr<WebTaskRunner> GetTaskRunner(TaskType) = 0;
 
   // Returns the parent WebViewScheduler.
   virtual WebViewScheduler* GetWebViewScheduler() = 0;
diff --git a/third_party/WebKit/Source/platform/WebTaskRunner.cpp b/third_party/WebKit/Source/platform/WebTaskRunner.cpp
index 7dd8c0b5..b2d228ee 100644
--- a/third_party/WebKit/Source/platform/WebTaskRunner.cpp
+++ b/third_party/WebKit/Source/platform/WebTaskRunner.cpp
@@ -107,7 +107,8 @@
   return *this;
 }
 
-TaskHandle::TaskHandle(RefPtr<Runner> runner) : runner_(std::move(runner)) {
+TaskHandle::TaskHandle(scoped_refptr<Runner> runner)
+    : runner_(std::move(runner)) {
   DCHECK(runner_);
 }
 
@@ -144,7 +145,7 @@
 TaskHandle WebTaskRunner::PostCancellableTask(const WebTraceLocation& location,
                                               WTF::Closure task) {
   DCHECK(RunsTasksInCurrentSequence());
-  RefPtr<TaskHandle::Runner> runner =
+  scoped_refptr<TaskHandle::Runner> runner =
       WTF::AdoptRef(new TaskHandle::Runner(std::move(task)));
   PostTask(location, WTF::Bind(&TaskHandle::Runner::Run, runner->AsWeakPtr(),
                                TaskHandle(runner)));
@@ -156,7 +157,7 @@
     WTF::Closure task,
     TimeDelta delay) {
   DCHECK(RunsTasksInCurrentSequence());
-  RefPtr<TaskHandle::Runner> runner =
+  scoped_refptr<TaskHandle::Runner> runner =
       WTF::AdoptRef(new TaskHandle::Runner(std::move(task)));
   PostDelayedTask(location,
                   WTF::Bind(&TaskHandle::Runner::Run, runner->AsWeakPtr(),
diff --git a/third_party/WebKit/Source/platform/WebTaskRunner.h b/third_party/WebKit/Source/platform/WebTaskRunner.h
index c083952..0982c5a 100644
--- a/third_party/WebKit/Source/platform/WebTaskRunner.h
+++ b/third_party/WebKit/Source/platform/WebTaskRunner.h
@@ -47,8 +47,8 @@
  private:
   friend class WebTaskRunner;
 
-  explicit TaskHandle(RefPtr<Runner>);
-  RefPtr<Runner> runner_;
+  explicit TaskHandle(scoped_refptr<Runner>);
+  scoped_refptr<Runner> runner_;
 };
 
 // The blink representation of a chromium SingleThreadTaskRunner.
diff --git a/third_party/WebKit/Source/platform/WebTaskRunnerTest.cpp b/third_party/WebKit/Source/platform/WebTaskRunnerTest.cpp
index 9662994..39848ed 100644
--- a/third_party/WebKit/Source/platform/WebTaskRunnerTest.cpp
+++ b/third_party/WebKit/Source/platform/WebTaskRunnerTest.cpp
@@ -38,7 +38,7 @@
 }  // namespace
 
 TEST(WebTaskRunnerTest, PostCancellableTaskTest) {
-  RefPtr<scheduler::FakeWebTaskRunner> task_runner =
+  scoped_refptr<scheduler::FakeWebTaskRunner> task_runner =
       WTF::AdoptRef(new scheduler::FakeWebTaskRunner);
 
   // Run without cancellation.
@@ -119,7 +119,7 @@
 }
 
 TEST(WebTaskRunnerTest, CancellationCheckerTest) {
-  RefPtr<scheduler::FakeWebTaskRunner> task_runner =
+  scoped_refptr<scheduler::FakeWebTaskRunner> task_runner =
       WTF::AdoptRef(new scheduler::FakeWebTaskRunner);
 
   int count = 0;
diff --git a/third_party/WebKit/Source/platform/audio/AudioBus.cpp b/third_party/WebKit/Source/platform/audio/AudioBus.cpp
index ce6f7d21..6bb6357 100644
--- a/third_party/WebKit/Source/platform/audio/AudioBus.cpp
+++ b/third_party/WebKit/Source/platform/audio/AudioBus.cpp
@@ -46,9 +46,9 @@
 
 const unsigned kMaxBusChannels = 32;
 
-RefPtr<AudioBus> AudioBus::Create(unsigned number_of_channels,
-                                  size_t length,
-                                  bool allocate) {
+scoped_refptr<AudioBus> AudioBus::Create(unsigned number_of_channels,
+                                         size_t length,
+                                         bool allocate) {
   DCHECK_LE(number_of_channels, kMaxBusChannels);
   if (number_of_channels > kMaxBusChannels)
     return nullptr;
@@ -184,9 +184,10 @@
   return true;
 }
 
-RefPtr<AudioBus> AudioBus::CreateBufferFromRange(const AudioBus* source_buffer,
-                                                 unsigned start_frame,
-                                                 unsigned end_frame) {
+scoped_refptr<AudioBus> AudioBus::CreateBufferFromRange(
+    const AudioBus* source_buffer,
+    unsigned start_frame,
+    unsigned end_frame) {
   size_t number_of_source_frames = source_buffer->length();
   unsigned number_of_channels = source_buffer->NumberOfChannels();
 
@@ -199,7 +200,7 @@
 
   size_t range_length = end_frame - start_frame;
 
-  RefPtr<AudioBus> audio_bus = Create(number_of_channels, range_length);
+  scoped_refptr<AudioBus> audio_bus = Create(number_of_channels, range_length);
   audio_bus->SetSampleRate(source_buffer->SampleRate());
 
   for (unsigned i = 0; i < number_of_channels; ++i)
@@ -624,7 +625,7 @@
   }
 }
 
-RefPtr<AudioBus> AudioBus::CreateBySampleRateConverting(
+scoped_refptr<AudioBus> AudioBus::CreateBySampleRateConverting(
     const AudioBus* source_bus,
     bool mix_to_mono,
     double new_sample_rate) {
@@ -652,7 +653,7 @@
   }
 
   if (source_bus->IsSilent()) {
-    RefPtr<AudioBus> silent_bus = Create(
+    scoped_refptr<AudioBus> silent_bus = Create(
         number_of_source_channels, source_bus->length() / sample_rate_ratio);
     silent_bus->SetSampleRate(new_sample_rate);
     return silent_bus;
@@ -660,7 +661,7 @@
 
   // First, mix to mono (if necessary) then sample-rate convert.
   const AudioBus* resampler_source_bus;
-  RefPtr<AudioBus> mixed_mono_bus;
+  scoped_refptr<AudioBus> mixed_mono_bus;
   if (mix_to_mono) {
     mixed_mono_bus = AudioBus::CreateByMixingToMono(source_bus);
     resampler_source_bus = mixed_mono_bus.get();
@@ -676,7 +677,7 @@
   // Create destination bus with same number of channels.
   unsigned number_of_destination_channels =
       resampler_source_bus->NumberOfChannels();
-  RefPtr<AudioBus> destination_bus =
+  scoped_refptr<AudioBus> destination_bus =
       Create(number_of_destination_channels, destination_length);
 
   // Sample-rate convert each channel.
@@ -693,7 +694,8 @@
   return destination_bus;
 }
 
-RefPtr<AudioBus> AudioBus::CreateByMixingToMono(const AudioBus* source_bus) {
+scoped_refptr<AudioBus> AudioBus::CreateByMixingToMono(
+    const AudioBus* source_bus) {
   if (source_bus->IsSilent())
     return Create(1, source_bus->length());
 
@@ -704,7 +706,7 @@
                                              source_bus->length());
     case 2: {
       unsigned n = source_bus->length();
-      RefPtr<AudioBus> destination_bus = Create(1, n);
+      scoped_refptr<AudioBus> destination_bus = Create(1, n);
 
       const float* source_l = source_bus->Channel(0)->Data();
       const float* source_r = source_bus->Channel(1)->Data();
@@ -737,15 +739,15 @@
     channels_[i]->ClearSilentFlag();
 }
 
-RefPtr<AudioBus> DecodeAudioFileData(const char* data, size_t size) {
+scoped_refptr<AudioBus> DecodeAudioFileData(const char* data, size_t size) {
   WebAudioBus web_audio_bus;
   if (Platform::Current()->DecodeAudioFileData(&web_audio_bus, data, size))
     return web_audio_bus.Release();
   return nullptr;
 }
 
-RefPtr<AudioBus> AudioBus::GetDataResource(const char* name,
-                                           float sample_rate) {
+scoped_refptr<AudioBus> AudioBus::GetDataResource(const char* name,
+                                                  float sample_rate) {
   const WebData& resource = Platform::Current()->GetDataResource(name);
   if (resource.IsEmpty())
     return nullptr;
@@ -755,8 +757,8 @@
   // If this becomes problematic, we'll have the refactor DecodeAudioFileData
   // to take WebData and use segmented access.
   SharedBuffer::DeprecatedFlatData flat_data(
-      resource.operator RefPtr<SharedBuffer>());
-  RefPtr<AudioBus> audio_bus =
+      resource.operator scoped_refptr<SharedBuffer>());
+  scoped_refptr<AudioBus> audio_bus =
       DecodeAudioFileData(flat_data.Data(), flat_data.size());
 
   if (!audio_bus.get())
@@ -770,11 +772,11 @@
                                                 sample_rate);
 }
 
-RefPtr<AudioBus> CreateBusFromInMemoryAudioFile(const void* data,
-                                                size_t data_size,
-                                                bool mix_to_mono,
-                                                float sample_rate) {
-  RefPtr<AudioBus> audio_bus =
+scoped_refptr<AudioBus> CreateBusFromInMemoryAudioFile(const void* data,
+                                                       size_t data_size,
+                                                       bool mix_to_mono,
+                                                       float sample_rate) {
+  scoped_refptr<AudioBus> audio_bus =
       DecodeAudioFileData(static_cast<const char*>(data), data_size);
   if (!audio_bus.get())
     return nullptr;
diff --git a/third_party/WebKit/Source/platform/audio/AudioBus.h b/third_party/WebKit/Source/platform/audio/AudioBus.h
index ccd2722..29e817b6 100644
--- a/third_party/WebKit/Source/platform/audio/AudioBus.h
+++ b/third_party/WebKit/Source/platform/audio/AudioBus.h
@@ -69,9 +69,9 @@
   // case the AudioChannels will memory-manage their own storage.  If allocate
   // is false then setChannelMemory() has to be called later on for each
   // channel before the AudioBus is useable...
-  static RefPtr<AudioBus> Create(unsigned number_of_channels,
-                                 size_t length,
-                                 bool allocate = true);
+  static scoped_refptr<AudioBus> Create(unsigned number_of_channels,
+                                        size_t length,
+                                        bool allocate = true);
 
   // Tells the given channel to use an externally allocated buffer.
   void SetChannelMemory(unsigned channel_index, float* storage, size_t length);
@@ -111,16 +111,17 @@
 
   // Creates a new buffer from a range in the source buffer.
   // 0 may be returned if the range does not fit in the sourceBuffer
-  static RefPtr<AudioBus> CreateBufferFromRange(const AudioBus* source_buffer,
-                                                unsigned start_frame,
-                                                unsigned end_frame);
+  static scoped_refptr<AudioBus> CreateBufferFromRange(
+      const AudioBus* source_buffer,
+      unsigned start_frame,
+      unsigned end_frame);
 
   // Creates a new AudioBus by sample-rate converting sourceBus to the
   // newSampleRate.
   // setSampleRate() must have been previously called on sourceBus.
   // Note: sample-rate conversion is already handled in the file-reading code
   // for the mac port, so we don't need this.
-  static RefPtr<AudioBus> CreateBySampleRateConverting(
+  static scoped_refptr<AudioBus> CreateBySampleRateConverting(
       const AudioBus* source_bus,
       bool mix_to_mono,
       double new_sample_rate);
@@ -128,7 +129,8 @@
   // Creates a new AudioBus by mixing all the channels down to mono.
   // If sourceBus is already mono, then the returned AudioBus will simply be a
   // copy.
-  static RefPtr<AudioBus> CreateByMixingToMono(const AudioBus* source_bus);
+  static scoped_refptr<AudioBus> CreateByMixingToMono(
+      const AudioBus* source_bus);
 
   // Scales all samples by the same amount.
   void Scale(float scale);
@@ -168,7 +170,8 @@
   // Makes maximum absolute value == 1.0 (if possible).
   void Normalize();
 
-  static RefPtr<AudioBus> GetDataResource(const char* name, float sample_rate);
+  static scoped_refptr<AudioBus> GetDataResource(const char* name,
+                                                 float sample_rate);
 
  protected:
   AudioBus() {}
diff --git a/third_party/WebKit/Source/platform/audio/AudioDestination.cpp b/third_party/WebKit/Source/platform/audio/AudioDestination.cpp
index 0425ce0..8b81e72 100644
--- a/third_party/WebKit/Source/platform/audio/AudioDestination.cpp
+++ b/third_party/WebKit/Source/platform/audio/AudioDestination.cpp
@@ -58,20 +58,21 @@
 // value and not a buffer size in the latencyHint. See: crbug.com/737047
 const size_t kFIFOSize = 8192;
 
-RefPtr<AudioDestination> AudioDestination::Create(
+scoped_refptr<AudioDestination> AudioDestination::Create(
     AudioIOCallback& callback,
     unsigned number_of_output_channels,
     const WebAudioLatencyHint& latency_hint,
-    RefPtr<SecurityOrigin> security_origin) {
+    scoped_refptr<SecurityOrigin> security_origin) {
   return WTF::AdoptRef(new AudioDestination(callback, number_of_output_channels,
                                             latency_hint,
                                             std::move(security_origin)));
 }
 
-AudioDestination::AudioDestination(AudioIOCallback& callback,
-                                   unsigned number_of_output_channels,
-                                   const WebAudioLatencyHint& latency_hint,
-                                   RefPtr<SecurityOrigin> security_origin)
+AudioDestination::AudioDestination(
+    AudioIOCallback& callback,
+    unsigned number_of_output_channels,
+    const WebAudioLatencyHint& latency_hint,
+    scoped_refptr<SecurityOrigin> security_origin)
     : number_of_output_channels_(number_of_output_channels),
       is_playing_(false),
       fifo_(WTF::WrapUnique(
diff --git a/third_party/WebKit/Source/platform/audio/AudioDestination.h b/third_party/WebKit/Source/platform/audio/AudioDestination.h
index 5ff5d45..601c65e 100644
--- a/third_party/WebKit/Source/platform/audio/AudioDestination.h
+++ b/third_party/WebKit/Source/platform/audio/AudioDestination.h
@@ -65,14 +65,14 @@
   AudioDestination(AudioIOCallback&,
                    unsigned number_of_output_channels,
                    const WebAudioLatencyHint&,
-                   RefPtr<SecurityOrigin>);
+                   scoped_refptr<SecurityOrigin>);
   ~AudioDestination() override;
 
-  static RefPtr<AudioDestination> Create(
+  static scoped_refptr<AudioDestination> Create(
       AudioIOCallback&,
       unsigned number_of_output_channels,
       const WebAudioLatencyHint&,
-      RefPtr<SecurityOrigin>);
+      scoped_refptr<SecurityOrigin>);
 
   // The actual render function (WebAudioDevice::RenderCallback) isochronously
   // invoked by the media renderer. This is never called after Stop() is called.
@@ -133,11 +133,11 @@
   std::unique_ptr<PushPullFIFO> fifo_;
 
   // Accessed by device thread: to pass the data from FIFO to the device.
-  RefPtr<AudioBus> output_bus_;
+  scoped_refptr<AudioBus> output_bus_;
 
   // Accessed by rendering thread: to push the rendered result from WebAudio
   // graph into the FIFO.
-  RefPtr<AudioBus> render_bus_;
+  scoped_refptr<AudioBus> render_bus_;
 
   // Accessed by rendering thread: the render callback function of WebAudio
   // engine. (i.e. DestinationNode)
diff --git a/third_party/WebKit/Source/platform/audio/AudioFileReader.h b/third_party/WebKit/Source/platform/audio/AudioFileReader.h
index a2d8993..5fa3731 100644
--- a/third_party/WebKit/Source/platform/audio/AudioFileReader.h
+++ b/third_party/WebKit/Source/platform/audio/AudioFileReader.h
@@ -42,15 +42,16 @@
 // doesn't already match the file's sample-rate).  The created buffer will have
 // its sample-rate set correctly to the result.
 
-PLATFORM_EXPORT RefPtr<AudioBus> CreateBusFromInMemoryAudioFile(
+PLATFORM_EXPORT scoped_refptr<AudioBus> CreateBusFromInMemoryAudioFile(
     const void* data,
     size_t data_size,
     bool mix_to_mono,
     float sample_rate);
 
-PLATFORM_EXPORT RefPtr<AudioBus> CreateBusFromAudioFile(const char* file_path,
-                                                        bool mix_to_mono,
-                                                        float sample_rate);
+PLATFORM_EXPORT scoped_refptr<AudioBus> CreateBusFromAudioFile(
+    const char* file_path,
+    bool mix_to_mono,
+    float sample_rate);
 
 // May pass in 0.0 for sampleRate in which case it will use the AudioBus's
 // sampleRate
diff --git a/third_party/WebKit/Source/platform/audio/AudioResampler.h b/third_party/WebKit/Source/platform/audio/AudioResampler.h
index 7dc4237..fe817b0 100644
--- a/third_party/WebKit/Source/platform/audio/AudioResampler.h
+++ b/third_party/WebKit/Source/platform/audio/AudioResampler.h
@@ -69,7 +69,7 @@
  private:
   double rate_;
   Vector<std::unique_ptr<AudioResamplerKernel>> kernels_;
-  RefPtr<AudioBus> source_bus_;
+  scoped_refptr<AudioBus> source_bus_;
 };
 
 }  // namespace blink
diff --git a/third_party/WebKit/Source/platform/audio/HRTFDatabaseLoader.cpp b/third_party/WebKit/Source/platform/audio/HRTFDatabaseLoader.cpp
index abd8cef..cb595f1 100644
--- a/third_party/WebKit/Source/platform/audio/HRTFDatabaseLoader.cpp
+++ b/third_party/WebKit/Source/platform/audio/HRTFDatabaseLoader.cpp
@@ -46,11 +46,11 @@
   return *map;
 }
 
-RefPtr<HRTFDatabaseLoader>
+scoped_refptr<HRTFDatabaseLoader>
 HRTFDatabaseLoader::CreateAndLoadAsynchronouslyIfNecessary(float sample_rate) {
   DCHECK(IsMainThread());
 
-  RefPtr<HRTFDatabaseLoader> loader = GetLoaderMap().at(sample_rate);
+  scoped_refptr<HRTFDatabaseLoader> loader = GetLoaderMap().at(sample_rate);
   if (loader) {
     DCHECK_EQ(sample_rate, loader->DatabaseSampleRate());
     return loader;
diff --git a/third_party/WebKit/Source/platform/audio/HRTFDatabaseLoader.h b/third_party/WebKit/Source/platform/audio/HRTFDatabaseLoader.h
index 6d3a8ec..cf7c9a0 100644
--- a/third_party/WebKit/Source/platform/audio/HRTFDatabaseLoader.h
+++ b/third_party/WebKit/Source/platform/audio/HRTFDatabaseLoader.h
@@ -50,8 +50,8 @@
   // time).
   // Returns the HRTFDatabaseLoader.
   // Must be called from the main thread.
-  static RefPtr<HRTFDatabaseLoader> CreateAndLoadAsynchronouslyIfNecessary(
-      float sample_rate);
+  static scoped_refptr<HRTFDatabaseLoader>
+  CreateAndLoadAsynchronouslyIfNecessary(float sample_rate);
 
   // Both constructor and destructor must be called from the main thread.
   ~HRTFDatabaseLoader();
diff --git a/third_party/WebKit/Source/platform/audio/HRTFElevation.cpp b/third_party/WebKit/Source/platform/audio/HRTFElevation.cpp
index 09c6f2f..3e01f62 100644
--- a/third_party/WebKit/Source/platform/audio/HRTFElevation.cpp
+++ b/third_party/WebKit/Source/platform/audio/HRTFElevation.cpp
@@ -64,18 +64,19 @@
 
 // Lazily load a concatenated HRTF database for given subject and store it in a
 // local hash table to ensure quick efficient future retrievals.
-static RefPtr<AudioBus> GetConcatenatedImpulseResponsesForSubject(
+static scoped_refptr<AudioBus> GetConcatenatedImpulseResponsesForSubject(
     const String& subject_name) {
-  typedef HashMap<String, RefPtr<AudioBus>> AudioBusMap;
+  typedef HashMap<String, scoped_refptr<AudioBus>> AudioBusMap;
   DEFINE_THREAD_SAFE_STATIC_LOCAL(AudioBusMap, audio_bus_map, ());
   DEFINE_THREAD_SAFE_STATIC_LOCAL(Mutex, mutex, ());
 
   MutexLocker locker(mutex);
-  RefPtr<AudioBus> bus;
+  scoped_refptr<AudioBus> bus;
   AudioBusMap::iterator iterator = audio_bus_map.find(subject_name);
   if (iterator == audio_bus_map.end()) {
-    RefPtr<AudioBus> concatenated_impulse_responses(AudioBus::GetDataResource(
-        subject_name.Utf8().data(), kResponseSampleRate));
+    scoped_refptr<AudioBus> concatenated_impulse_responses(
+        AudioBus::GetDataResource(subject_name.Utf8().data(),
+                                  kResponseSampleRate));
     DCHECK(concatenated_impulse_responses);
     if (!concatenated_impulse_responses)
       return nullptr;
@@ -129,7 +130,8 @@
   // implementation detail.
   int positive_elevation = elevation < 0 ? elevation + 360 : elevation;
 
-  RefPtr<AudioBus> bus(GetConcatenatedImpulseResponsesForSubject(subject_name));
+  scoped_refptr<AudioBus> bus(
+      GetConcatenatedImpulseResponsesForSubject(subject_name));
 
   if (!bus)
     return false;
@@ -167,9 +169,9 @@
   // (hardware) sample-rate.
   unsigned start_frame = index * kResponseFrameSize;
   unsigned stop_frame = start_frame + kResponseFrameSize;
-  RefPtr<AudioBus> pre_sample_rate_converted_response(
+  scoped_refptr<AudioBus> pre_sample_rate_converted_response(
       AudioBus::CreateBufferFromRange(bus.get(), start_frame, stop_frame));
-  RefPtr<AudioBus> response(AudioBus::CreateBySampleRateConverting(
+  scoped_refptr<AudioBus> response(AudioBus::CreateBySampleRateConverting(
       pre_sample_rate_converted_response.get(), false, sample_rate));
   AudioChannel* left_ear_impulse_response =
       response->Channel(AudioBus::kChannelLeft);
diff --git a/third_party/WebKit/Source/platform/audio/HRTFPanner.h b/third_party/WebKit/Source/platform/audio/HRTFPanner.h
index f0d32cb..5756660 100644
--- a/third_party/WebKit/Source/platform/audio/HRTFPanner.h
+++ b/third_party/WebKit/Source/platform/audio/HRTFPanner.h
@@ -69,7 +69,7 @@
   int CalculateDesiredAzimuthIndexAndBlend(double azimuth,
                                            double& azimuth_blend);
 
-  RefPtr<HRTFDatabaseLoader> database_loader_;
+  scoped_refptr<HRTFDatabaseLoader> database_loader_;
 
   float sample_rate_;
 
diff --git a/third_party/WebKit/Source/platform/audio/MultiChannelResampler.cpp b/third_party/WebKit/Source/platform/audio/MultiChannelResampler.cpp
index 61b6b24..7558327 100644
--- a/third_party/WebKit/Source/platform/audio/MultiChannelResampler.cpp
+++ b/third_party/WebKit/Source/platform/audio/MultiChannelResampler.cpp
@@ -87,7 +87,7 @@
 
  private:
   AudioSourceProvider* multi_channel_provider_;
-  RefPtr<AudioBus> multi_channel_bus_;
+  scoped_refptr<AudioBus> multi_channel_bus_;
   unsigned number_of_channels_;
   unsigned current_channel_;
   // Used to verify that all channels ask for the same amount.
diff --git a/third_party/WebKit/Source/platform/audio/PushPullFIFO.h b/third_party/WebKit/Source/platform/audio/PushPullFIFO.h
index 63b347b8..f680240 100644
--- a/third_party/WebKit/Source/platform/audio/PushPullFIFO.h
+++ b/third_party/WebKit/Source/platform/audio/PushPullFIFO.h
@@ -93,7 +93,7 @@
   size_t frames_available_ = 0;
   size_t index_read_ = 0;
   size_t index_write_ = 0;
-  RefPtr<AudioBus> fifo_bus_;
+  scoped_refptr<AudioBus> fifo_bus_;
 };
 
 }  // namespace blink
diff --git a/third_party/WebKit/Source/platform/audio/PushPullFIFOMultithreadTest.cpp b/third_party/WebKit/Source/platform/audio/PushPullFIFOMultithreadTest.cpp
index 4545a4d..ad5ece815 100644
--- a/third_party/WebKit/Source/platform/audio/PushPullFIFOMultithreadTest.cpp
+++ b/third_party/WebKit/Source/platform/audio/PushPullFIFOMultithreadTest.cpp
@@ -68,7 +68,7 @@
   }
 
   PushPullFIFO* fifo_;
-  RefPtr<AudioBus> bus_;
+  scoped_refptr<AudioBus> bus_;
   std::unique_ptr<WebThread> client_thread_;
   std::unique_ptr<WaitableEvent> done_event_;
 
diff --git a/third_party/WebKit/Source/platform/audio/PushPullFIFOTest.cpp b/third_party/WebKit/Source/platform/audio/PushPullFIFOTest.cpp
index 4e71bbd..b945d33 100644
--- a/third_party/WebKit/Source/platform/audio/PushPullFIFOTest.cpp
+++ b/third_party/WebKit/Source/platform/audio/PushPullFIFOTest.cpp
@@ -36,21 +36,21 @@
 
   // The input bus length must be |AudioUtilities::kRenderQuantumFrames|.
   // i.e.) input_bus->length() == kRenderQuantumFrames
-  RefPtr<AudioBus> input_bus_129_frames =
+  scoped_refptr<AudioBus> input_bus_129_frames =
       AudioBus::Create(2, AudioUtilities::kRenderQuantumFrames + 1);
   EXPECT_DEATH(test_fifo->Push(input_bus_129_frames.get()), "");
-  RefPtr<AudioBus> input_bus_127_frames =
+  scoped_refptr<AudioBus> input_bus_127_frames =
       AudioBus::Create(2, AudioUtilities::kRenderQuantumFrames - 1);
   EXPECT_DEATH(test_fifo->Push(input_bus_127_frames.get()), "");
 
   // Pull request frames cannot exceed the length of output bus.
   // i.e.) frames_requested <= output_bus->length()
-  RefPtr<AudioBus> output_bus_512_frames = AudioBus::Create(2, 512);
+  scoped_refptr<AudioBus> output_bus_512_frames = AudioBus::Create(2, 512);
   EXPECT_DEATH(test_fifo->Pull(output_bus_512_frames.get(), 513), "");
 
   // Pull request frames cannot exceed the length of FIFO.
   // i.e.) frames_requested <= fifo_length_
-  RefPtr<AudioBus> output_bus_1025_frames = AudioBus::Create(2, 1025);
+  scoped_refptr<AudioBus> output_bus_1025_frames = AudioBus::Create(2, 1025);
   EXPECT_DEATH(test_fifo->Pull(output_bus_1025_frames.get(), 1025), "");
 }
 
@@ -144,13 +144,13 @@
   std::unique_ptr<PushPullFIFO> fifo = WTF::WrapUnique(
       new PushPullFIFO(setup.number_of_channels, setup.fifo_length));
 
-  RefPtr<AudioBus> output_bus;
+  scoped_refptr<AudioBus> output_bus;
 
   // Iterate all the scheduled push/pull actions.
   size_t frame_counter = 0;
   for (const auto& action : setup.fifo_actions) {
     if (strcmp(action.action, "PUSH") == 0) {
-      RefPtr<AudioBus> input_bus =
+      scoped_refptr<AudioBus> input_bus =
           AudioBus::Create(setup.number_of_channels, action.number_of_frames);
       frame_counter = FillBusWithLinearRamp(input_bus.get(), frame_counter);
       fifo->Push(input_bus.get());
diff --git a/third_party/WebKit/Source/platform/audio/Reverb.h b/third_party/WebKit/Source/platform/audio/Reverb.h
index 447abde..1846e3e4 100644
--- a/third_party/WebKit/Source/platform/audio/Reverb.h
+++ b/third_party/WebKit/Source/platform/audio/Reverb.h
@@ -79,7 +79,7 @@
   Vector<std::unique_ptr<ReverbConvolver>> convolvers_;
 
   // For "True" stereo processing
-  RefPtr<AudioBus> temp_buffer_;
+  scoped_refptr<AudioBus> temp_buffer_;
 };
 
 }  // namespace blink
diff --git a/third_party/WebKit/Source/platform/audio/SincResampler.cpp b/third_party/WebKit/Source/platform/audio/SincResampler.cpp
index a1285a1..a07d97e7 100644
--- a/third_party/WebKit/Source/platform/audio/SincResampler.cpp
+++ b/third_party/WebKit/Source/platform/audio/SincResampler.cpp
@@ -139,7 +139,8 @@
     return;
 
   // Wrap the provided buffer by an AudioBus for use by the source provider.
-  RefPtr<AudioBus> bus = AudioBus::Create(1, number_of_source_frames, false);
+  scoped_refptr<AudioBus> bus =
+      AudioBus::Create(1, number_of_source_frames, false);
 
   // FIXME: Find a way to make the following const-correct:
   bus->SetChannelMemory(0, buffer, number_of_source_frames);
diff --git a/third_party/WebKit/Source/platform/audio/VectorMathTest.cpp b/third_party/WebKit/Source/platform/audio/VectorMathTest.cpp
new file mode 100644
index 0000000..119b585
--- /dev/null
+++ b/third_party/WebKit/Source/platform/audio/VectorMathTest.cpp
@@ -0,0 +1,399 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "platform/audio/VectorMath.h"
+
+#include <algorithm>
+#include <array>
+#include <cmath>
+#include <limits>
+#include <numeric>
+#include <random>
+#include <vector>
+
+#include "platform/wtf/MathExtras.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace blink {
+namespace VectorMath {
+namespace {
+
+struct MemoryLayout {
+  size_t byte_alignment;
+  size_t stride;
+};
+
+// This is the minimum aligned needed by AVX on x86 family architectures.
+constexpr size_t kMaxBitAlignment = 256u;
+constexpr size_t kMaxByteAlignment = kMaxBitAlignment / 8u;
+
+constexpr size_t kMaxStride = 2u;
+
+constexpr MemoryLayout kMemoryLayouts[] = {
+    {kMaxByteAlignment / 2u - kMaxByteAlignment / 4u, 1u},
+    {kMaxByteAlignment / 2u, 1u},
+    {kMaxByteAlignment / 2u + kMaxByteAlignment / 4u, 1u},
+    {kMaxByteAlignment, 1u},
+    {0u, kMaxStride}};
+constexpr size_t kMemoryLayoutCount =
+    sizeof(kMemoryLayouts) / sizeof(*kMemoryLayouts);
+
+// This is the minimum vector size in bytes needed for MSA instructions on
+// MIPS.
+constexpr size_t kMaxVectorSizeInBytes = 1024u;
+constexpr size_t kVectorSizesInBytes[] = {
+    kMaxVectorSizeInBytes,
+    // This vector size in bytes is chosen so that the following optimization
+    // paths can be tested on x86 family architectures using different memory
+    // layouts:
+    //  * AVX + SSE + scalar
+    //  * scalar + SSE + AVX
+    //  * SSE + AVX + scalar
+    //  * scalar + AVX + SSE
+    // On other architectures, this vector size in bytes results in either
+    // optimization + scalar path or scalar path to be tested.
+    kMaxByteAlignment + kMaxByteAlignment / 2u + kMaxByteAlignment / 4u};
+constexpr size_t kVectorSizeCount =
+    sizeof(kVectorSizesInBytes) / sizeof(*kVectorSizesInBytes);
+
+// Compare two floats and consider all NaNs to be equal.
+bool Equal(float a, float b) {
+  if (std::isnan(a))
+    return std::isnan(b);
+  return a == b;
+}
+
+// This represents a real source or destination vector which is aligned, can be
+// non-contiguous and can be used as a source or destination vector for
+// blink::VectorMath functions.
+template <typename T>
+class TestVector {
+  class Iterator {
+   public:
+    // These types are used by std::iterator_traits used by std::equal used by
+    // TestVector::operator==.
+    using difference_type = ptrdiff_t;
+    using iterator_category = std::input_iterator_tag;
+    using pointer = T*;
+    using reference = T&;
+    using value_type = T;
+
+    Iterator(T* p, int stride) : p_(p), stride_(stride) {}
+
+    Iterator& operator++() {
+      p_ += stride_;
+      return *this;
+    }
+    Iterator operator++(int) {
+      Iterator iter = *this;
+      ++(*this);
+      return iter;
+    }
+    bool operator==(const Iterator& other) const { return p_ == other.p_; }
+    bool operator!=(const Iterator& other) const { return !(*this == other); }
+    T& operator*() const { return *p_; }
+
+   private:
+    T* p_;
+    size_t stride_;
+  };
+
+ public:
+  // These types are used internally by Google Test.
+  using const_iterator = Iterator;
+  using iterator = Iterator;
+
+  TestVector() = default;
+  TestVector(T* base, const MemoryLayout* memory_layout, size_t size)
+      : p_(GetAligned(base, memory_layout->byte_alignment)),
+        memory_layout_(memory_layout),
+        size_(size) {}
+  TestVector(T* base, const TestVector<const T>& primary_vector)
+      : TestVector(base,
+                   primary_vector.memory_layout(),
+                   primary_vector.size()) {}
+
+  Iterator begin() const { return Iterator(p_, stride()); }
+  Iterator end() const { return Iterator(p_ + size() * stride(), stride()); }
+  const MemoryLayout* memory_layout() const { return memory_layout_; }
+  T* p() const { return p_; }
+  size_t size() const { return size_; }
+  int stride() const { return static_cast<int>(memory_layout()->stride); }
+
+  bool operator==(const TestVector& other) const {
+    return std::equal(begin(), end(), other.begin(), other.end(), Equal);
+  }
+  T& operator[](size_t i) const { return p_[i * stride()]; }
+
+ private:
+  static T* GetAligned(T* base, size_t byte_alignment) {
+    size_t base_byte_alignment = GetByteAlignment(base);
+    size_t byte_offset =
+        (byte_alignment - base_byte_alignment + kMaxByteAlignment) %
+        kMaxByteAlignment;
+    T* p = base + byte_offset / sizeof(T);
+    size_t p_byte_alignment = GetByteAlignment(p);
+    CHECK_EQ(byte_alignment % kMaxByteAlignment, p_byte_alignment);
+    return p;
+  }
+  static size_t GetByteAlignment(T* p) {
+    return reinterpret_cast<size_t>(p) % kMaxByteAlignment;
+  }
+
+  T* p_;
+  const MemoryLayout* memory_layout_;
+  size_t size_;
+};
+
+// Get primary input vectors with difference memory layout and size
+// combinations.
+template <typename T>
+std::array<TestVector<const T>, kVectorSizeCount * kMemoryLayoutCount>
+GetPrimaryVectors(const T* base) {
+  std::array<TestVector<const T>, kVectorSizeCount * kMemoryLayoutCount>
+      vectors;
+  for (auto& vector : vectors) {
+    ptrdiff_t i = &vector - &vectors[0];
+    ptrdiff_t memory_layout_index = i % kMemoryLayoutCount;
+    ptrdiff_t size_index = i / kMemoryLayoutCount;
+    vector = TestVector<const T>(base, &kMemoryLayouts[memory_layout_index],
+                                 kVectorSizesInBytes[size_index] / sizeof(T));
+  }
+  return vectors;
+}
+
+// Get secondary input or output vectors. As the size of a secondary vector
+// must always be the same as the size of the primary input vector, there are
+// only  two interesting secondary vectors:
+//  - A vector with the same memory layout as the primary input vector has and
+//    which therefore is aligned whenever the primary input vector is aligned.
+//  - A vector with a different memory layout than the primary input vector has
+//  - and which therefore is not aligned when the primary input vector is
+//    aligned.
+template <typename T>
+std::array<TestVector<T>, 2u> GetSecondaryVectors(
+    T* base,
+    const TestVector<const float>& primary_vector) {
+  std::array<TestVector<T>, 2u> vectors;
+  const MemoryLayout* primary_memory_layout = primary_vector.memory_layout();
+  const MemoryLayout* other_memory_layout =
+      &kMemoryLayouts[primary_memory_layout == &kMemoryLayouts[0]];
+  CHECK_NE(primary_memory_layout, other_memory_layout);
+  vectors[0] = TestVector<T>(base, primary_vector);
+  vectors[1] = TestVector<T>(base, other_memory_layout, primary_vector.size());
+  return vectors;
+}
+
+class VectorMathTest : public testing::Test {
+ protected:
+  enum {
+    kDestinationCount = 4u,
+    kFloatArraySize =
+        (kMaxStride * kMaxVectorSizeInBytes + kMaxByteAlignment - 1u) /
+        sizeof(float),
+    kFullyFiniteSource = 4u,
+    kFullyNonNanSource = 5u,
+    kSourceCount = 6u
+  };
+
+  // Get a destination buffer containing initially uninitialized floats.
+  float* GetDestination(size_t i) {
+    CHECK_LT(i, kDestinationCount);
+    return destinations_[i];
+  }
+  // Get a source buffer containing random floats.
+  const float* GetSource(size_t i) {
+    CHECK_LT(i, kSourceCount);
+    return sources_[i];
+  }
+
+  static void SetUpTestCase() {
+    std::minstd_rand generator(99);
+    // Fill in source buffers with finite random floats.
+    std::uniform_real_distribution<float> float_distribution(-10.0f, 10.0f);
+    std::generate_n(&**sources_, sizeof(sources_) / sizeof(**sources_),
+                    [&]() { return float_distribution(generator); });
+    // Add INFINITYs and NANs to most source buffers.
+    std::uniform_int_distribution<size_t> index_distribution(
+        0u, kFloatArraySize / 2u - 1u);
+    for (size_t i = 0u; i < kSourceCount; ++i) {
+      if (i == kFullyFiniteSource)
+        continue;
+      sources_[i][index_distribution(generator)] = INFINITY;
+      sources_[i][index_distribution(generator)] = -INFINITY;
+      if (i != kFullyNonNanSource)
+        sources_[i][index_distribution(generator)] = NAN;
+    }
+  };
+
+ private:
+  static float destinations_[kDestinationCount][kFloatArraySize];
+  static float sources_[kSourceCount][kFloatArraySize];
+};
+
+float VectorMathTest::destinations_[kDestinationCount][kFloatArraySize];
+float VectorMathTest::sources_[kSourceCount][kFloatArraySize];
+
+TEST_F(VectorMathTest, Vadd) {
+  for (const auto& source1 : GetPrimaryVectors(GetSource(0u))) {
+    for (const auto& source2 : GetSecondaryVectors(GetSource(1u), source1)) {
+      TestVector<float> expected_dest(GetDestination(0u), source1);
+      for (size_t i = 0u; i < source1.size(); ++i)
+        expected_dest[i] = source1[i] + source2[i];
+      for (auto& dest : GetSecondaryVectors(GetDestination(1u), source1)) {
+        Vadd(source1.p(), source1.stride(), source2.p(), source2.stride(),
+             dest.p(), dest.stride(), source1.size());
+        EXPECT_EQ(expected_dest, dest);
+      }
+    }
+  }
+}
+
+TEST_F(VectorMathTest, Vclip) {
+  // Vclip does not accept NaNs thus let's use only sources without NaNs.
+  for (const auto& source : GetPrimaryVectors(GetSource(kFullyNonNanSource))) {
+    const float* thresholds = GetSource(kFullyFiniteSource);
+    const float low_threshold = std::min(thresholds[0], thresholds[1]);
+    const float high_threshold = std::max(thresholds[0], thresholds[1]);
+    TestVector<float> expected_dest(GetDestination(0u), source);
+    for (size_t i = 0u; i < source.size(); ++i)
+      expected_dest[i] = clampTo(source[i], low_threshold, high_threshold);
+    for (auto& dest : GetSecondaryVectors(GetDestination(1u), source)) {
+      Vclip(source.p(), source.stride(), &low_threshold, &high_threshold,
+            dest.p(), dest.stride(), source.size());
+      EXPECT_EQ(expected_dest, dest);
+    }
+  }
+}
+
+TEST_F(VectorMathTest, Vmaxmgv) {
+  const auto maxmg = [](float init, float x) {
+    return std::max(init, std::abs(x));
+  };
+  // Vmaxmgv does not accept NaNs thus let's use only sources without NaNs.
+  for (const float* source_base :
+       {GetSource(kFullyFiniteSource), GetSource(kFullyNonNanSource)}) {
+    for (const auto& source : GetPrimaryVectors(source_base)) {
+      const float expected_max =
+          std::accumulate(source.begin(), source.end(), 0.0f, maxmg);
+      float max;
+      Vmaxmgv(source.p(), source.stride(), &max, source.size());
+      EXPECT_EQ(expected_max, max) << testing::PrintToString(source);
+    }
+  }
+}
+
+TEST_F(VectorMathTest, Vmul) {
+  for (const auto& source1 : GetPrimaryVectors(GetSource(0u))) {
+    for (const auto& source2 : GetSecondaryVectors(GetSource(1u), source1)) {
+      TestVector<float> expected_dest(GetDestination(0u), source1);
+      for (size_t i = 0u; i < source1.size(); ++i)
+        expected_dest[i] = source1[i] * source2[i];
+      for (auto& dest : GetSecondaryVectors(GetDestination(1u), source1)) {
+        Vmul(source1.p(), source1.stride(), source2.p(), source2.stride(),
+             dest.p(), dest.stride(), source1.size());
+        EXPECT_EQ(expected_dest, dest);
+      }
+    }
+  }
+}
+
+TEST_F(VectorMathTest, Vsma) {
+  for (const auto& source : GetPrimaryVectors(GetSource(0u))) {
+    const float scale = *GetSource(1u);
+    const TestVector<const float> dest_source(GetSource(2u), source);
+    TestVector<float> expected_dest(GetDestination(0u), source);
+    for (size_t i = 0u; i < source.size(); ++i)
+      expected_dest[i] = dest_source[i] + scale * source[i];
+    for (auto& dest : GetSecondaryVectors(GetDestination(1u), source)) {
+      std::copy(dest_source.begin(), dest_source.end(), dest.begin());
+      Vsma(source.p(), source.stride(), &scale, dest.p(), dest.stride(),
+           source.size());
+      EXPECT_EQ(expected_dest, dest);
+    }
+  }
+}
+
+TEST_F(VectorMathTest, Vsmul) {
+  for (const auto& source : GetPrimaryVectors(GetSource(0u))) {
+    const float scale = *GetSource(1u);
+    TestVector<float> expected_dest(GetDestination(0u), source);
+    for (size_t i = 0u; i < source.size(); ++i)
+      expected_dest[i] = scale * source[i];
+    for (auto& dest : GetSecondaryVectors(GetDestination(1u), source)) {
+      Vsmul(source.p(), source.stride(), &scale, dest.p(), dest.stride(),
+            source.size());
+      EXPECT_EQ(expected_dest, dest);
+    }
+  }
+}
+
+TEST_F(VectorMathTest, Vsvesq) {
+  const auto sqsum = [](float init, float x) { return init + x * x; };
+  for (const float* source_base :
+       {GetSource(0u), GetSource(kFullyFiniteSource)}) {
+    for (const auto& source : GetPrimaryVectors(source_base)) {
+      const float expected_sum =
+          std::accumulate(source.begin(), source.end(), 0.0f, sqsum);
+      float sum;
+      Vsvesq(source.p(), source.stride(), &sum, source.size());
+      if (std::isfinite(expected_sum)) {
+        // Optimized paths in Vsvesq use parallel partial sums which may result
+        // in different rounding errors than the non-partial sum algorithm used
+        // here and in non-optimized paths in Vsvesq.
+        EXPECT_NEAR(expected_sum, sum, 1e-6f * expected_sum);
+      } else if (std::isnan(expected_sum)) {
+        EXPECT_TRUE(std::isnan(sum));
+      } else {  // +INFINITY or -INFINITY
+        EXPECT_EQ(expected_sum, sum);
+      }
+    }
+  }
+}
+
+TEST_F(VectorMathTest, Zvmul) {
+  constexpr float kMax = std::numeric_limits<float>::max();
+  std::vector<std::array<float, kFloatArraySize + 1u>> sources(4u);
+  for (size_t i = 0u; i < sources.size(); ++i) {
+    // Initialize a local source with a randomized test case source.
+    std::copy_n(GetSource(i), kFloatArraySize, sources[i].begin());
+    // Put +FLT_MAX and -FLT_MAX in the middle of the source. Use a different
+    // sequence for each source in order to get 16 different combinations.
+    for (size_t j = 0u; j < 16u; ++j)
+      sources[i][kFloatArraySize / 2u + j] = ((j >> i) & 1) ? -kMax : kMax;
+  }
+  for (const auto& real1 : GetPrimaryVectors(sources[0u].data())) {
+    if (real1.stride() != 1)
+      continue;
+    const TestVector<const float> imag1(sources[1u].data(), real1);
+    const TestVector<const float> real2(sources[2u].data(), real1);
+    const TestVector<const float> imag2(sources[3u].data(), real1);
+    TestVector<float> expected_dest_real(GetDestination(0u), real1);
+    TestVector<float> expected_dest_imag(GetDestination(1u), real1);
+    for (size_t i = 0u; i < real1.size(); ++i) {
+      expected_dest_real[i] = real1[i] * real2[i] - imag1[i] * imag2[i];
+      expected_dest_imag[i] = real1[i] * imag2[i] + imag1[i] * real2[i];
+      if (&real1[i] >= &sources[0u][kFloatArraySize / 2u] &&
+          &real1[i] < &sources[0u][kFloatArraySize / 2u] + 16u) {
+        // FLT_MAX products should have overflowed.
+        EXPECT_TRUE(std::isinf(expected_dest_real[i]) ||
+                    std::isinf(expected_dest_imag[i]));
+        EXPECT_TRUE(std::isnan(expected_dest_real[i]) ||
+                    std::isnan(expected_dest_imag[i]));
+      }
+    }
+    for (auto& dest_real : GetSecondaryVectors(GetDestination(2u), real1)) {
+      TestVector<float> dest_imag(GetDestination(3u), real1);
+      ASSERT_EQ(1, dest_real.stride());
+      Zvmul(real1.p(), imag1.p(), real2.p(), imag2.p(), dest_real.p(),
+            dest_imag.p(), real1.size());
+      EXPECT_EQ(expected_dest_real, dest_real);
+      EXPECT_EQ(expected_dest_imag, dest_imag);
+    }
+  }
+}
+
+}  // namespace
+}  // namespace VectorMath
+}  // namespace blink
diff --git a/third_party/WebKit/Source/platform/bindings/CallbackFunctionBase.h b/third_party/WebKit/Source/platform/bindings/CallbackFunctionBase.h
index 55dec40..ec974ad 100644
--- a/third_party/WebKit/Source/platform/bindings/CallbackFunctionBase.h
+++ b/third_party/WebKit/Source/platform/bindings/CallbackFunctionBase.h
@@ -31,7 +31,7 @@
 
  protected:
   CallbackFunctionBase(ScriptState*, v8::Local<v8::Function>);
-  RefPtr<ScriptState> script_state_;
+  scoped_refptr<ScriptState> script_state_;
   TraceWrapperV8Reference<v8::Function> callback_;
 };
 
diff --git a/third_party/WebKit/Source/platform/bindings/DOMWrapperWorld.cpp b/third_party/WebKit/Source/platform/bindings/DOMWrapperWorld.cpp
index bb64de39..a256ac9 100644
--- a/third_party/WebKit/Source/platform/bindings/DOMWrapperWorld.cpp
+++ b/third_party/WebKit/Source/platform/bindings/DOMWrapperWorld.cpp
@@ -63,8 +63,8 @@
 }
 #endif
 
-RefPtr<DOMWrapperWorld> DOMWrapperWorld::Create(v8::Isolate* isolate,
-                                                WorldType world_type) {
+scoped_refptr<DOMWrapperWorld> DOMWrapperWorld::Create(v8::Isolate* isolate,
+                                                       WorldType world_type) {
   DCHECK_NE(WorldType::kIsolated, world_type);
   int world_id = GenerateWorldIdForType(world_type);
   if (world_id == kInvalidWorldId)
@@ -109,7 +109,7 @@
 }
 
 void DOMWrapperWorld::AllWorldsInCurrentThread(
-    Vector<RefPtr<DOMWrapperWorld>>& worlds) {
+    Vector<scoped_refptr<DOMWrapperWorld>>& worlds) {
   if (IsMainThread())
     worlds.push_back(&MainWorld());
   for (DOMWrapperWorld* world : GetWorldMap().Values())
@@ -150,7 +150,7 @@
   GetWorldMap().erase(world_id_);
 }
 
-RefPtr<DOMWrapperWorld> DOMWrapperWorld::EnsureIsolatedWorld(
+scoped_refptr<DOMWrapperWorld> DOMWrapperWorld::EnsureIsolatedWorld(
     v8::Isolate* isolate,
     int world_id) {
 #if DCHECK_IS_ON()
@@ -160,7 +160,7 @@
   WorldMap& map = GetWorldMap();
   auto it = map.find(world_id);
   if (it != map.end()) {
-    RefPtr<DOMWrapperWorld> world = it->value;
+    scoped_refptr<DOMWrapperWorld> world = it->value;
     DCHECK(world->IsIsolatedWorld());
     DCHECK_EQ(world_id, world->GetWorldId());
     return world;
@@ -170,7 +170,8 @@
       new DOMWrapperWorld(isolate, WorldType::kIsolated, world_id));
 }
 
-typedef HashMap<int, RefPtr<SecurityOrigin>> IsolatedWorldSecurityOriginMap;
+typedef HashMap<int, scoped_refptr<SecurityOrigin>>
+    IsolatedWorldSecurityOriginMap;
 static IsolatedWorldSecurityOriginMap& IsolatedWorldSecurityOrigins() {
   DCHECK(IsMainThread());
   DEFINE_STATIC_LOCAL(IsolatedWorldSecurityOriginMap, map, ());
@@ -186,7 +187,7 @@
 
 void DOMWrapperWorld::SetIsolatedWorldSecurityOrigin(
     int world_id,
-    RefPtr<SecurityOrigin> security_origin) {
+    scoped_refptr<SecurityOrigin> security_origin) {
 #if DCHECK_IS_ON()
   DCHECK(IsIsolatedWorldId(world_id));
 #endif
@@ -317,7 +318,7 @@
     ScriptWrappable* script_wrappable) {
   DCHECK(IsMainThread());
 
-  Vector<RefPtr<DOMWrapperWorld>> worlds;
+  Vector<scoped_refptr<DOMWrapperWorld>> worlds;
   DOMWrapperWorld::AllWorldsInCurrentThread(worlds);
   for (const auto& world : worlds) {
     DOMDataStore& dom_data_store = world->DomDataStore();
diff --git a/third_party/WebKit/Source/platform/bindings/DOMWrapperWorld.h b/third_party/WebKit/Source/platform/bindings/DOMWrapperWorld.h
index e2fc062..df2a3e0c 100644
--- a/third_party/WebKit/Source/platform/bindings/DOMWrapperWorld.h
+++ b/third_party/WebKit/Source/platform/bindings/DOMWrapperWorld.h
@@ -77,11 +77,11 @@
 
   // Creates a world other than IsolatedWorld. Note this can return nullptr if
   // GenerateWorldIdForType fails to allocate a valid id.
-  static RefPtr<DOMWrapperWorld> Create(v8::Isolate*, WorldType);
+  static scoped_refptr<DOMWrapperWorld> Create(v8::Isolate*, WorldType);
 
   // Ensures an IsolatedWorld for |worldId|.
-  static RefPtr<DOMWrapperWorld> EnsureIsolatedWorld(v8::Isolate*,
-                                                     int world_id);
+  static scoped_refptr<DOMWrapperWorld> EnsureIsolatedWorld(v8::Isolate*,
+                                                            int world_id);
   ~DOMWrapperWorld();
   void Dispose();
 
@@ -91,7 +91,8 @@
     return number_of_non_main_worlds_in_main_thread_;
   }
 
-  static void AllWorldsInCurrentThread(Vector<RefPtr<DOMWrapperWorld>>& worlds);
+  static void AllWorldsInCurrentThread(
+      Vector<scoped_refptr<DOMWrapperWorld>>& worlds);
   static void MarkWrappersInAllWorlds(ScriptWrappable*,
                                       const ScriptWrappableVisitor*);
 
@@ -112,7 +113,7 @@
   // origin. XMLHttpRequest instances used in that world will be considered
   // to come from that origin, not the frame's.
   static void SetIsolatedWorldSecurityOrigin(int world_id,
-                                             RefPtr<SecurityOrigin>);
+                                             scoped_refptr<SecurityOrigin>);
   SecurityOrigin* IsolatedWorldSecurityOrigin();
 
   // Associated an isolated world with a Content Security Policy. Resources
diff --git a/third_party/WebKit/Source/platform/bindings/ScriptState.cpp b/third_party/WebKit/Source/platform/bindings/ScriptState.cpp
index 94aea17a0..cffb3be 100644
--- a/third_party/WebKit/Source/platform/bindings/ScriptState.cpp
+++ b/third_party/WebKit/Source/platform/bindings/ScriptState.cpp
@@ -8,9 +8,10 @@
 
 namespace blink {
 
-RefPtr<ScriptState> ScriptState::Create(v8::Local<v8::Context> context,
-                                        RefPtr<DOMWrapperWorld> world) {
-  RefPtr<ScriptState> script_state =
+scoped_refptr<ScriptState> ScriptState::Create(
+    v8::Local<v8::Context> context,
+    scoped_refptr<DOMWrapperWorld> world) {
+  scoped_refptr<ScriptState> script_state =
       WTF::AdoptRef(new ScriptState(context, std::move(world)));
   // This AddRef() is for keeping this ScriptState alive as long as the
   // v8::Context is alive.  This is Release()d in the weak callback of the
@@ -30,7 +31,7 @@
 }
 
 ScriptState::ScriptState(v8::Local<v8::Context> context,
-                         RefPtr<DOMWrapperWorld> world)
+                         scoped_refptr<DOMWrapperWorld> world)
     : isolate_(context->GetIsolate()),
       context_(isolate_, context),
       world_(std::move(world)),
diff --git a/third_party/WebKit/Source/platform/bindings/ScriptState.h b/third_party/WebKit/Source/platform/bindings/ScriptState.h
index 2baf97d3..d809dca8 100644
--- a/third_party/WebKit/Source/platform/bindings/ScriptState.h
+++ b/third_party/WebKit/Source/platform/bindings/ScriptState.h
@@ -30,7 +30,7 @@
 //
 // In some cases, you need ScriptState in code that doesn't have any JavaScript
 // on the stack. Then you can store ScriptState on a C++ object using
-// RefPtr<ScriptState>.
+// scoped_refptr<ScriptState>.
 //
 // class SomeObject {
 //   void someMethod(ScriptState* scriptState) {
@@ -48,7 +48,7 @@
 //     // Do V8 related things.
 //     ToV8(...);
 //   }
-//   RefPtr<ScriptState> script_state_;
+//   scoped_refptr<ScriptState> script_state_;
 // };
 //
 // You should not store ScriptState on a C++ object that can be accessed
@@ -88,8 +88,8 @@
     v8::Local<v8::Context> context_;
   };
 
-  static RefPtr<ScriptState> Create(v8::Local<v8::Context>,
-                                    RefPtr<DOMWrapperWorld>);
+  static scoped_refptr<ScriptState> Create(v8::Local<v8::Context>,
+                                           scoped_refptr<DOMWrapperWorld>);
   virtual ~ScriptState();
 
   static ScriptState* Current(v8::Isolate* isolate)  // DEPRECATED
@@ -146,7 +146,7 @@
   void DisposePerContextData();
 
  protected:
-  ScriptState(v8::Local<v8::Context>, RefPtr<DOMWrapperWorld>);
+  ScriptState(v8::Local<v8::Context>, scoped_refptr<DOMWrapperWorld>);
 
  private:
   v8::Isolate* isolate_;
@@ -155,7 +155,7 @@
 
   // This RefPtr doesn't cause a cycle because all persistent handles that
   // DOMWrapperWorld holds are weak.
-  RefPtr<DOMWrapperWorld> world_;
+  scoped_refptr<DOMWrapperWorld> world_;
 
   // This std::unique_ptr causes a cycle:
   // V8PerContextData --(Persistent)--> v8::Context --(RefPtr)--> ScriptState
@@ -188,7 +188,7 @@
   }
 
  private:
-  RefPtr<ScriptState> script_state_;
+  scoped_refptr<ScriptState> script_state_;
   ScopedPersistent<v8::Context> context_;
 };
 
diff --git a/third_party/WebKit/Source/platform/bindings/SharedPersistent.h b/third_party/WebKit/Source/platform/bindings/SharedPersistent.h
index 0c14681c..d8a43e7 100644
--- a/third_party/WebKit/Source/platform/bindings/SharedPersistent.h
+++ b/third_party/WebKit/Source/platform/bindings/SharedPersistent.h
@@ -46,8 +46,8 @@
   WTF_MAKE_NONCOPYABLE(SharedPersistent);
 
  public:
-  static RefPtr<SharedPersistent<T>> Create(v8::Local<T> value,
-                                            v8::Isolate* isolate) {
+  static scoped_refptr<SharedPersistent<T>> Create(v8::Local<T> value,
+                                                   v8::Isolate* isolate) {
     return WTF::AdoptRef(new SharedPersistent<T>(value, isolate));
   }
 
diff --git a/third_party/WebKit/Source/platform/bindings/V8PerIsolateData.h b/third_party/WebKit/Source/platform/bindings/V8PerIsolateData.h
index 7ee8909..ef1005b 100644
--- a/third_party/WebKit/Source/platform/bindings/V8PerIsolateData.h
+++ b/third_party/WebKit/Source/platform/bindings/V8PerIsolateData.h
@@ -298,7 +298,7 @@
 
   std::unique_ptr<StringCache> string_cache_;
   std::unique_ptr<V8PrivateProperty> private_property_;
-  RefPtr<ScriptState> script_regexp_script_state_;
+  scoped_refptr<ScriptState> script_regexp_script_state_;
 
   bool constructor_mode_;
   friend class ConstructorMode;
diff --git a/third_party/WebKit/Source/platform/bindings/V8ValueCache.h b/third_party/WebKit/Source/platform/bindings/V8ValueCache.h
index fa3b7d8..6cb55bda 100644
--- a/third_party/WebKit/Source/platform/bindings/V8ValueCache.h
+++ b/third_party/WebKit/Source/platform/bindings/V8ValueCache.h
@@ -120,7 +120,7 @@
   // Note: RefPtr is a must as we cache by StringImpl* equality, not identity
   // hence lastStringImpl might be not a key of the cache (in sense of identity)
   // and hence it's not refed on addition.
-  RefPtr<StringImpl> last_string_impl_;
+  scoped_refptr<StringImpl> last_string_impl_;
 };
 
 }  // namespace blink
diff --git a/third_party/WebKit/Source/platform/credentialmanager/PlatformFederatedCredential.cpp b/third_party/WebKit/Source/platform/credentialmanager/PlatformFederatedCredential.cpp
index c047b32..9e71e6e2 100644
--- a/third_party/WebKit/Source/platform/credentialmanager/PlatformFederatedCredential.cpp
+++ b/third_party/WebKit/Source/platform/credentialmanager/PlatformFederatedCredential.cpp
@@ -8,7 +8,7 @@
 
 PlatformFederatedCredential* PlatformFederatedCredential::Create(
     const String& id,
-    RefPtr<SecurityOrigin> provider,
+    scoped_refptr<SecurityOrigin> provider,
     const String& name,
     const KURL& icon_url) {
   return new PlatformFederatedCredential(id, std::move(provider), name,
@@ -17,7 +17,7 @@
 
 PlatformFederatedCredential::PlatformFederatedCredential(
     const String& id,
-    RefPtr<SecurityOrigin> provider,
+    scoped_refptr<SecurityOrigin> provider,
     const String& name,
     const KURL& icon_url)
     : PlatformCredential(id),
diff --git a/third_party/WebKit/Source/platform/credentialmanager/PlatformFederatedCredential.h b/third_party/WebKit/Source/platform/credentialmanager/PlatformFederatedCredential.h
index f650e74b..bbdeaf9 100644
--- a/third_party/WebKit/Source/platform/credentialmanager/PlatformFederatedCredential.h
+++ b/third_party/WebKit/Source/platform/credentialmanager/PlatformFederatedCredential.h
@@ -18,13 +18,14 @@
   WTF_MAKE_NONCOPYABLE(PlatformFederatedCredential);
 
  public:
-  static PlatformFederatedCredential* Create(const String& id,
-                                             RefPtr<SecurityOrigin> provider,
-                                             const String& name,
-                                             const KURL& icon_url);
+  static PlatformFederatedCredential* Create(
+      const String& id,
+      scoped_refptr<SecurityOrigin> provider,
+      const String& name,
+      const KURL& icon_url);
   ~PlatformFederatedCredential() override;
 
-  RefPtr<SecurityOrigin> Provider() const { return provider_; }
+  scoped_refptr<SecurityOrigin> Provider() const { return provider_; }
 
   bool IsFederated() override { return true; }
   const String& Name() const { return name_; }
@@ -32,12 +33,12 @@
 
  private:
   PlatformFederatedCredential(const String& id,
-                              RefPtr<SecurityOrigin> provider,
+                              scoped_refptr<SecurityOrigin> provider,
                               const String& name,
                               const KURL& icon_url);
   String name_;
   KURL icon_url_;
-  RefPtr<SecurityOrigin> provider_;
+  scoped_refptr<SecurityOrigin> provider_;
 };
 
 }  // namespace blink
diff --git a/third_party/WebKit/Source/platform/exported/WebFont.cpp b/third_party/WebKit/Source/platform/exported/WebFont.cpp
index d24e9fb..fee8027c 100644
--- a/third_party/WebKit/Source/platform/exported/WebFont.cpp
+++ b/third_party/WebKit/Source/platform/exported/WebFont.cpp
@@ -87,8 +87,7 @@
   TextRunPaintInfo run_info(text_run);
   run_info.bounds = text_clip_rect;
 
-  IntRect int_rect(clip);
-  PaintRecordBuilder builder(int_rect);
+  PaintRecordBuilder builder;
   GraphicsContext& context = builder.Context();
 
   {
diff --git a/third_party/WebKit/Source/platform/exported/WebScrollbarThemePainter.cpp b/third_party/WebKit/Source/platform/exported/WebScrollbarThemePainter.cpp
index c7b162c..b15be4d 100644
--- a/third_party/WebKit/Source/platform/exported/WebScrollbarThemePainter.cpp
+++ b/third_party/WebKit/Source/platform/exported/WebScrollbarThemePainter.cpp
@@ -43,7 +43,6 @@
                          WebCanvas* canvas,
                          const WebRect& rect)
       : int_rect_(IntRect(IntPoint(), IntSize(rect.width, rect.height))),
-        builder_(int_rect_),
         canvas_(canvas),
         rect_(rect) {
     builder_.Context().SetDeviceScaleFactor(painter->DeviceScaleFactor());
diff --git a/third_party/WebKit/Source/platform/feature_policy/FeaturePolicy.cpp b/third_party/WebKit/Source/platform/feature_policy/FeaturePolicy.cpp
index 9d4e6c9..363dc9f 100644
--- a/third_party/WebKit/Source/platform/feature_policy/FeaturePolicy.cpp
+++ b/third_party/WebKit/Source/platform/feature_policy/FeaturePolicy.cpp
@@ -18,7 +18,7 @@
 // TODO(loonybear): Deprecate the methods in this namesapce when deprecating old
 // allow syntax.
 bool IsValidOldAllowSyntax(const String& policy,
-                           RefPtr<SecurityOrigin> src_origin) {
+                           scoped_refptr<SecurityOrigin> src_origin) {
   // Old syntax enable all features on src_origin, If src_origin does not exist
   // (example, http header does not have a src_origin), then the syntax cannot
   // be valid.
@@ -54,7 +54,7 @@
 
 Vector<WebParsedFeaturePolicyDeclaration> ParseOldAllowSyntax(
     const String& policy,
-    RefPtr<SecurityOrigin> origin,
+    scoped_refptr<SecurityOrigin> origin,
     Vector<String>* messages,
     const FeatureNameMap& feature_names) {
   Vector<WebParsedFeaturePolicyDeclaration> whitelists;
@@ -81,17 +81,18 @@
 
 }  // namespace
 
-WebParsedFeaturePolicy ParseFeaturePolicyHeader(const String& policy,
-                                                RefPtr<SecurityOrigin> origin,
-                                                Vector<String>* messages) {
-  return ParseFeaturePolicy(policy, origin, RefPtr<SecurityOrigin>(), messages,
-                            GetDefaultFeatureNameMap());
+WebParsedFeaturePolicy ParseFeaturePolicyHeader(
+    const String& policy,
+    scoped_refptr<SecurityOrigin> origin,
+    Vector<String>* messages) {
+  return ParseFeaturePolicy(policy, origin, scoped_refptr<SecurityOrigin>(),
+                            messages, GetDefaultFeatureNameMap());
 }
 
 Vector<WebParsedFeaturePolicyDeclaration> ParseFeaturePolicyAttribute(
     const String& policy,
-    RefPtr<SecurityOrigin> self_origin,
-    RefPtr<SecurityOrigin> src_origin,
+    scoped_refptr<SecurityOrigin> self_origin,
+    scoped_refptr<SecurityOrigin> src_origin,
     Vector<String>* messages,
     bool* old_syntax) {
   return ParseFeaturePolicy(policy, self_origin, src_origin, messages,
@@ -100,8 +101,8 @@
 
 Vector<WebParsedFeaturePolicyDeclaration> ParseFeaturePolicy(
     const String& policy,
-    RefPtr<SecurityOrigin> self_origin,
-    RefPtr<SecurityOrigin> src_origin,
+    scoped_refptr<SecurityOrigin> self_origin,
+    scoped_refptr<SecurityOrigin> src_origin,
     Vector<String>* messages,
     const FeatureNameMap& feature_names,
     bool* old_syntax) {
diff --git a/third_party/WebKit/Source/platform/feature_policy/FeaturePolicy.h b/third_party/WebKit/Source/platform/feature_policy/FeaturePolicy.h
index 30c0c7a4..9e55629 100644
--- a/third_party/WebKit/Source/platform/feature_policy/FeaturePolicy.h
+++ b/third_party/WebKit/Source/platform/feature_policy/FeaturePolicy.h
@@ -31,7 +31,7 @@
 //     "vibrate a.com b.com; fullscreen 'none'; payment 'self', payment *".
 PLATFORM_EXPORT WebParsedFeaturePolicy
 ParseFeaturePolicyHeader(const String& policy,
-                         RefPtr<SecurityOrigin>,
+                         scoped_refptr<SecurityOrigin>,
                          Vector<String>* messages);
 
 // Converts a container policy string into a vector of whitelists, given self
@@ -47,8 +47,8 @@
 // https://crbug.com/761009.
 PLATFORM_EXPORT Vector<WebParsedFeaturePolicyDeclaration>
 ParseFeaturePolicyAttribute(const String& policy,
-                            RefPtr<SecurityOrigin> self_origin,
-                            RefPtr<SecurityOrigin> src_origin,
+                            scoped_refptr<SecurityOrigin> self_origin,
+                            scoped_refptr<SecurityOrigin> src_origin,
                             Vector<String>* messages,
                             bool* old_syntax);
 
@@ -63,8 +63,8 @@
 // https://crbug.com/761009.
 PLATFORM_EXPORT Vector<WebParsedFeaturePolicyDeclaration> ParseFeaturePolicy(
     const String& policy,
-    RefPtr<SecurityOrigin> self_origin,
-    RefPtr<SecurityOrigin> src_origin,
+    scoped_refptr<SecurityOrigin> self_origin,
+    scoped_refptr<SecurityOrigin> src_origin,
     Vector<String>* messages,
     const FeatureNameMap& feature_names,
     bool* old_syntax = nullptr);
diff --git a/third_party/WebKit/Source/platform/feature_policy/FeaturePolicyFuzzer.cpp b/third_party/WebKit/Source/platform/feature_policy/FeaturePolicyFuzzer.cpp
index 152911bf..4dd41a6c5 100644
--- a/third_party/WebKit/Source/platform/feature_policy/FeaturePolicyFuzzer.cpp
+++ b/third_party/WebKit/Source/platform/feature_policy/FeaturePolicyFuzzer.cpp
@@ -18,7 +18,7 @@
       blink::BlinkFuzzerTestSupport();
   WTF::Vector<WTF::String> messages;
   // TODO(csharrison): Be smarter about parsing this origin for performance.
-  RefPtr<blink::SecurityOrigin> origin =
+  scoped_refptr<blink::SecurityOrigin> origin =
       blink::SecurityOrigin::CreateFromString("https://example.com/");
   blink::ParseFeaturePolicyHeader(WTF::String(data, size), origin.get(),
                                   &messages);
diff --git a/third_party/WebKit/Source/platform/feature_policy/FeaturePolicyTest.cpp b/third_party/WebKit/Source/platform/feature_policy/FeaturePolicyTest.cpp
index 9f7cd4e..1f871e9 100644
--- a/third_party/WebKit/Source/platform/feature_policy/FeaturePolicyTest.cpp
+++ b/third_party/WebKit/Source/platform/feature_policy/FeaturePolicyTest.cpp
@@ -58,9 +58,12 @@
   ~FeaturePolicyTest() {
   }
 
-  RefPtr<SecurityOrigin> origin_a_ = SecurityOrigin::CreateFromString(ORIGIN_A);
-  RefPtr<SecurityOrigin> origin_b_ = SecurityOrigin::CreateFromString(ORIGIN_B);
-  RefPtr<SecurityOrigin> origin_c_ = SecurityOrigin::CreateFromString(ORIGIN_C);
+  scoped_refptr<SecurityOrigin> origin_a_ =
+      SecurityOrigin::CreateFromString(ORIGIN_A);
+  scoped_refptr<SecurityOrigin> origin_b_ =
+      SecurityOrigin::CreateFromString(ORIGIN_B);
+  scoped_refptr<SecurityOrigin> origin_c_ =
+      SecurityOrigin::CreateFromString(ORIGIN_C);
 
   const FeatureNameMap test_feature_name_map = {
       {"fullscreen", blink::WebFeaturePolicyFeature::kFullscreen},
diff --git a/third_party/WebKit/Source/platform/fonts/CharacterRange.h b/third_party/WebKit/Source/platform/fonts/CharacterRange.h
index e441747..e3b7ab2 100644
--- a/third_party/WebKit/Source/platform/fonts/CharacterRange.h
+++ b/third_party/WebKit/Source/platform/fonts/CharacterRange.h
@@ -8,14 +8,19 @@
 namespace blink {
 
 struct CharacterRange {
-  CharacterRange(float from, float to) : start(from), end(to) {
+  CharacterRange(float from, float to, float ascent, float descent)
+      : start(from), end(to), ascent(ascent), descent(descent) {
     DCHECK_LE(start, end);
   }
 
   float Width() const { return end - start; }
+  float Height() const { return ascent + descent; }
 
   float start;
   float end;
+
+  float ascent;
+  float descent;
 };
 
 }  // namespace blink
diff --git a/third_party/WebKit/Source/platform/fonts/Font.cpp b/third_party/WebKit/Source/platform/fonts/Font.cpp
index b149c4f..33a589a 100644
--- a/third_party/WebKit/Source/platform/fonts/Font.cpp
+++ b/third_party/WebKit/Source/platform/fonts/Font.cpp
@@ -380,6 +380,13 @@
       FloatRect(point.X() + range.start, point.Y(), range.Width(), height));
 }
 
+FloatRect Font::BoundingBox(const TextRun& run) const {
+  FontCachePurgePreventer purge_preventer;
+  CachingWordShaper shaper(*this);
+  CharacterRange range = shaper.GetCharacterRange(run, 0, run.length());
+  return FloatRect(range.start, -range.ascent, range.Width(), range.Height());
+}
+
 int Font::OffsetForPosition(const TextRun& run,
                             float x_float,
                             bool include_partial_glyphs) const {
diff --git a/third_party/WebKit/Source/platform/fonts/Font.h b/third_party/WebKit/Source/platform/fonts/Font.h
index 2d627df7..78789056 100644
--- a/third_party/WebKit/Source/platform/fonts/Font.h
+++ b/third_party/WebKit/Source/platform/fonts/Font.h
@@ -147,6 +147,7 @@
                                  int h,
                                  int from = 0,
                                  int to = -1) const;
+  FloatRect BoundingBox(const TextRun&) const;
   CharacterRange GetCharacterRange(const TextRun&,
                                    unsigned from,
                                    unsigned to) const;
diff --git a/third_party/WebKit/Source/platform/fonts/shaping/CachingWordShaper.cpp b/third_party/WebKit/Source/platform/fonts/shaping/CachingWordShaper.cpp
index b658d7f..eedb61cb 100644
--- a/third_party/WebKit/Source/platform/fonts/shaping/CachingWordShaper.cpp
+++ b/third_party/WebKit/Source/platform/fonts/shaping/CachingWordShaper.cpp
@@ -113,7 +113,7 @@
   // crbug.com/613915 and crbug.com/615661) so add empty ranges to ensure all
   // characters have an associated range.
   while (ranges.size() < static_cast<unsigned>(run.length()))
-    ranges.push_back(CharacterRange(0, 0));
+    ranges.push_back(CharacterRange(0, 0, 0, 0));
   return ranges;
 }
 
diff --git a/third_party/WebKit/Source/platform/fonts/shaping/ShapeResultBuffer.cpp b/third_party/WebKit/Source/platform/fonts/shaping/ShapeResultBuffer.cpp
index e49914d..abde58d 100644
--- a/third_party/WebKit/Source/platform/fonts/shaping/ShapeResultBuffer.cpp
+++ b/third_party/WebKit/Source/platform/fonts/shaping/ShapeResultBuffer.cpp
@@ -38,6 +38,8 @@
   float to_x = 0;
   bool found_from_x = false;
   bool found_to_x = false;
+  float min_y = 0;
+  float max_y = 0;
 
   if (direction == TextDirection::kRtl)
     current_x = total_width;
@@ -84,6 +86,11 @@
         to -= num_characters;
       }
 
+      if (found_from_x || found_to_x) {
+        min_y = std::min(min_y, result->Bounds().Y());
+        max_y = std::max(max_y, result->Bounds().MaxY());
+      }
+
       if (found_from_x && found_to_x)
         break;
       current_x += result->runs_[i]->width_;
@@ -111,8 +118,8 @@
   if (!found_to_x && !found_from_x)
     from_x = to_x = 0;
   if (from_x < to_x)
-    return CharacterRange(from_x, to_x);
-  return CharacterRange(to_x, from_x);
+    return CharacterRange(from_x, to_x, -min_y, max_y);
+  return CharacterRange(to_x, from_x, -min_y, max_y);
 }
 
 CharacterRange ShapeResultBuffer::GetCharacterRange(TextDirection direction,
@@ -137,9 +144,9 @@
 
     // To match getCharacterRange we flip ranges to ensure start <= end.
     if (end < start)
-      ranges.push_back(CharacterRange(end, start));
+      ranges.push_back(CharacterRange(end, start, 0, 0));
     else
-      ranges.push_back(CharacterRange(start, end));
+      ranges.push_back(CharacterRange(start, end, 0, 0));
   }
 }
 
diff --git a/third_party/WebKit/Source/platform/graphics/Canvas2DLayerBridge.cpp b/third_party/WebKit/Source/platform/graphics/Canvas2DLayerBridge.cpp
index 49f52a5d..c103027 100644
--- a/third_party/WebKit/Source/platform/graphics/Canvas2DLayerBridge.cpp
+++ b/third_party/WebKit/Source/platform/graphics/Canvas2DLayerBridge.cpp
@@ -333,7 +333,7 @@
   *out_mailbox = viz::TextureMailbox(mailbox, sync_token, texture_target,
                                      gfx::Size(size_), is_overlay_candidate);
   out_mailbox->set_color_space(color_params_.GetSamplerGfxColorSpace());
-  image_info->gpu_memory_buffer_->SetColorSpaceForScanout(
+  image_info->gpu_memory_buffer_->SetColorSpace(
       color_params_.GetStorageGfxColorSpace());
 
   gl->BindTexture(GC3D_TEXTURE_RECTANGLE_ARB, 0);
diff --git a/third_party/WebKit/Source/platform/graphics/CanvasColorParams.cpp b/third_party/WebKit/Source/platform/graphics/CanvasColorParams.cpp
index 3de2775..d9e3290 100644
--- a/third_party/WebKit/Source/platform/graphics/CanvasColorParams.cpp
+++ b/third_party/WebKit/Source/platform/graphics/CanvasColorParams.cpp
@@ -80,9 +80,9 @@
 }
 
 bool CanvasColorParams::NeedsSkColorSpaceXformCanvas() const {
-  // TODO: To unify legacy and srgb spaces, return
-  // color_space_ == kSRGBCanvasColorSpace
-  return color_space_ == kLegacyCanvasColorSpace;
+  return color_space_ == kLegacyCanvasColorSpace ||
+         (color_space_ == kSRGBCanvasColorSpace &&
+          pixel_format_ == kRGBA8CanvasPixelFormat);
 }
 
 std::unique_ptr<cc::PaintCanvas> CanvasColorParams::WrapCanvas(
@@ -97,24 +97,17 @@
 sk_sp<SkColorSpace> CanvasColorParams::GetSkColorSpaceForSkSurfaces() const {
   if (NeedsSkColorSpaceXformCanvas())
     return nullptr;
-  switch (color_space_) {
-    case kLegacyCanvasColorSpace:
-      NOTREACHED();
-    case kSRGBCanvasColorSpace:
-      if (pixel_format_ == kF16CanvasPixelFormat)
-        return SkColorSpace::MakeSRGBLinear();
-      return SkColorSpace::MakeSRGB();
-    case kRec2020CanvasColorSpace:
-      return SkColorSpace::MakeRGB(SkColorSpace::kLinear_RenderTargetGamma,
-                                   SkColorSpace::kRec2020_Gamut);
-    case kP3CanvasColorSpace:
-      return SkColorSpace::MakeRGB(SkColorSpace::kLinear_RenderTargetGamma,
-                                   SkColorSpace::kDCIP3_D65_Gamut);
-  }
-  return nullptr;
+  return GetSkColorSpace();
+}
 
-  // TODO(ccameron): This should return GetSkColorSpace if linear pixel math was
-  // requested, and nullptr otherwise.
+bool CanvasColorParams::NeedsColorConversion(
+    const CanvasColorParams& dest_color_params) const {
+  if ((color_space_ == dest_color_params.ColorSpace() &&
+       pixel_format_ == dest_color_params.PixelFormat()) ||
+      (NeedsSkColorSpaceXformCanvas() &&
+       dest_color_params.NeedsSkColorSpaceXformCanvas()))
+    return false;
+  return true;
 }
 
 SkColorType CanvasColorParams::GetSkColorType() const {
@@ -166,23 +159,22 @@
 
 sk_sp<SkColorSpace> CanvasColorParams::GetSkColorSpace() const {
   SkColorSpace::Gamut gamut = SkColorSpace::kSRGB_Gamut;
+  SkColorSpace::RenderTargetGamma gamma = SkColorSpace::kSRGB_RenderTargetGamma;
   switch (color_space_) {
     case kLegacyCanvasColorSpace:
     case kSRGBCanvasColorSpace:
-      gamut = SkColorSpace::kSRGB_Gamut;
+      if (pixel_format_ == kF16CanvasPixelFormat)
+        gamma = SkColorSpace::kLinear_RenderTargetGamma;
       break;
     case kRec2020CanvasColorSpace:
       gamut = SkColorSpace::kRec2020_Gamut;
+      gamma = SkColorSpace::kLinear_RenderTargetGamma;
       break;
     case kP3CanvasColorSpace:
       gamut = SkColorSpace::kDCIP3_D65_Gamut;
+      gamma = SkColorSpace::kLinear_RenderTargetGamma;
       break;
   }
-
-  SkColorSpace::RenderTargetGamma gamma = SkColorSpace::kSRGB_RenderTargetGamma;
-  if (pixel_format_ == kF16CanvasPixelFormat)
-    gamma = SkColorSpace::kLinear_RenderTargetGamma;
-
   return SkColorSpace::MakeRGB(gamma, gamut);
 }
 
diff --git a/third_party/WebKit/Source/platform/graphics/CanvasColorParams.h b/third_party/WebKit/Source/platform/graphics/CanvasColorParams.h
index 3246575..8819398 100644
--- a/third_party/WebKit/Source/platform/graphics/CanvasColorParams.h
+++ b/third_party/WebKit/Source/platform/graphics/CanvasColorParams.h
@@ -54,6 +54,10 @@
   // in order to enforce non-gamma-aware pixel math behaviour.
   bool NeedsSkColorSpaceXformCanvas() const;
 
+  // Indicates if pixels in this canvas color settings require any color
+  // conversion to be used in the passed canvas color settings.
+  bool NeedsColorConversion(const CanvasColorParams&) const;
+
   // The SkColorSpace to use in the SkImageInfo for allocated SkSurfaces. This
   // is nullptr in legacy rendering mode.
   sk_sp<SkColorSpace> GetSkColorSpaceForSkSurfaces() const;
diff --git a/third_party/WebKit/Source/platform/graphics/CanvasColorParamsTest.cpp b/third_party/WebKit/Source/platform/graphics/CanvasColorParamsTest.cpp
index 7c607d69..911c3c7 100644
--- a/third_party/WebKit/Source/platform/graphics/CanvasColorParamsTest.cpp
+++ b/third_party/WebKit/Source/platform/graphics/CanvasColorParamsTest.cpp
@@ -5,6 +5,7 @@
 #include "platform/graphics/CanvasColorParams.h"
 
 #include "platform/graphics/ColorCorrectionTestUtils.h"
+#include "platform/testing/RuntimeEnabledFeaturesTestHelpers.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "third_party/skia/include/core/SkColorSpaceXform.h"
 #include "ui/gfx/color_space.h"
@@ -14,13 +15,17 @@
 // When drawing a color managed canvas, the target SkColorSpace is obtained by
 // calling CanvasColorParams::GetSkColorSpaceForSkSurfaces(). When drawing media
 // to the canvas, the target gfx::ColorSpace is returned by CanvasColorParams::
-// GfxColorSpace(). This test verifies that the two different color spaces
-// are approximately the same for different CanvasColorParam objects.
+// GetStorageGfxColorSpace(). This test verifies that the two different color
+// spaces are approximately the same for different CanvasColorParam objects.
 // This test does not use SkColorSpace::Equals() since it is sensitive to
 // rounding issues (floats don't round-trip perfectly through ICC fixed point).
-// Instead, it color converts a pixel and compares the result.
+// Instead, it color converts a pixel and compares the result. Furthermore, this
+// test does not include sRGB as target color space since we use
+// SkColorSpaceXformCanvas for sRGB targets and GetSkColorSpaceForSkSurfaces()
+// returns nullptr for the surface.
 TEST(CanvasColorParamsTest, MatchSkColorSpaceWithGfxColorSpace) {
-  const float wide_gamut_color_correction_tolerance = 0.001;
+  ScopedExperimentalCanvasFeaturesForTest experimental_canvas_features(true);
+
   sk_sp<SkColorSpace> src_rgb_color_space = SkColorSpace::MakeSRGB();
   std::unique_ptr<uint8_t[]> src_pixel(new uint8_t[4]{32, 96, 160, 255});
 
@@ -28,48 +33,41 @@
       kSRGBCanvasColorSpace, kRec2020CanvasColorSpace, kP3CanvasColorSpace,
   };
 
-  CanvasPixelFormat canvas_pixel_formats[] = {
-      kRGBA8CanvasPixelFormat, kRGB10A2CanvasPixelFormat,
-      kRGBA12CanvasPixelFormat, kF16CanvasPixelFormat,
-  };
+  for (int iter_color_space = 0; iter_color_space < 3; iter_color_space++) {
+    CanvasColorParams color_params(canvas_color_spaces[iter_color_space],
+                                   kF16CanvasPixelFormat, kNonOpaque);
 
-  for (int iter_color_space = 0; iter_color_space < 3; iter_color_space++)
-    for (int iter_pixel_format = 0; iter_pixel_format < 4;
-         iter_pixel_format++) {
-      CanvasColorParams color_params(canvas_color_spaces[iter_color_space],
-                                     canvas_pixel_formats[iter_pixel_format],
-                                     kNonOpaque);
+    std::unique_ptr<SkColorSpaceXform> color_space_xform_canvas =
+        SkColorSpaceXform::New(src_rgb_color_space.get(),
+                               color_params.GetSkColorSpace().get());
+    std::unique_ptr<SkColorSpaceXform> color_space_xform_media =
+        SkColorSpaceXform::New(
+            src_rgb_color_space.get(),
+            color_params.GetStorageGfxColorSpace().ToSkColorSpace().get());
 
-      std::unique_ptr<SkColorSpaceXform> color_space_xform_canvas =
-          SkColorSpaceXform::New(src_rgb_color_space.get(),
-                                 color_params.GetSkColorSpace().get());
-      std::unique_ptr<SkColorSpaceXform> color_space_xform_media =
-          SkColorSpaceXform::New(
-              src_rgb_color_space.get(),
-              color_params.GetStorageGfxColorSpace().ToSkColorSpace().get());
+    std::unique_ptr<uint8_t[]> transformed_pixel_canvas(
+        new uint8_t[color_params.BytesPerPixel()]());
+    std::unique_ptr<uint8_t[]> transformed_pixel_media(
+        new uint8_t[color_params.BytesPerPixel()]());
 
-      std::unique_ptr<uint8_t[]> transformed_pixel_canvas(
-          new uint8_t[color_params.BytesPerPixel()]());
-      std::unique_ptr<uint8_t[]> transformed_pixel_media(
-          new uint8_t[color_params.BytesPerPixel()]());
+    SkColorSpaceXform::ColorFormat transformed_color_format =
+        color_params.BytesPerPixel() == 4
+            ? SkColorSpaceXform::ColorFormat::kRGBA_8888_ColorFormat
+            : SkColorSpaceXform::ColorFormat::kRGBA_F16_ColorFormat;
 
-      SkColorSpaceXform::ColorFormat transformed_color_format =
-          color_params.BytesPerPixel() == 4
-              ? SkColorSpaceXform::ColorFormat::kRGBA_8888_ColorFormat
-              : SkColorSpaceXform::ColorFormat::kRGBA_F16_ColorFormat;
+    color_space_xform_canvas->apply(
+        transformed_color_format, transformed_pixel_canvas.get(),
+        SkColorSpaceXform::ColorFormat::kRGBA_8888_ColorFormat, src_pixel.get(),
+        1, SkAlphaType::kPremul_SkAlphaType);
+    color_space_xform_media->apply(
+        transformed_color_format, transformed_pixel_media.get(),
+        SkColorSpaceXform::ColorFormat::kRGBA_8888_ColorFormat, src_pixel.get(),
+        1, SkAlphaType::kPremul_SkAlphaType);
 
-      color_space_xform_canvas->apply(
-          transformed_color_format, transformed_pixel_canvas.get(),
-          SkColorSpaceXform::ColorFormat::kRGBA_8888_ColorFormat,
-          src_pixel.get(), 1, SkAlphaType::kPremul_SkAlphaType);
-      color_space_xform_media->apply(
-          transformed_color_format, transformed_pixel_media.get(),
-          SkColorSpaceXform::ColorFormat::kRGBA_8888_ColorFormat,
-          src_pixel.get(), 1, SkAlphaType::kPremul_SkAlphaType);
-
-      ColorCorrectionTestUtils::CompareColorCorrectedPixels(
-          transformed_pixel_canvas, transformed_pixel_media,
-          color_params.BytesPerPixel(), wide_gamut_color_correction_tolerance);
+    ColorCorrectionTestUtils::CompareColorCorrectedPixels(
+        transformed_pixel_canvas.get(), transformed_pixel_media.get(), 1,
+        kUint16ArrayStorageFormat, kAlphaMultiplied,
+        kUnpremulRoundTripTolerance);
     }
 }
 
diff --git a/third_party/WebKit/Source/platform/graphics/ColorCorrectionTestUtils.cpp b/third_party/WebKit/Source/platform/graphics/ColorCorrectionTestUtils.cpp
index a21063b5..95632c0 100644
--- a/third_party/WebKit/Source/platform/graphics/ColorCorrectionTestUtils.cpp
+++ b/third_party/WebKit/Source/platform/graphics/ColorCorrectionTestUtils.cpp
@@ -4,12 +4,15 @@
 
 #include "platform/graphics/ColorCorrectionTestUtils.h"
 
+#include "platform/wtf/ByteSwap.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
 namespace blink {
 
-// This function is a compact version of SkHalfToFloat.
-float ColorCorrectionTestUtils::Float16ToFloat(const uint16_t& f16) {
+// This function is a compact version of SkHalfToFloat from Skia. If many
+// color correction tests fail at the same time, please check if SkHalf format
+// has changed.
+static float Float16ToFloat(const uint16_t& f16) {
   union FloatUIntUnion {
     uint32_t fUInt;
     float fFloat;
@@ -39,61 +42,153 @@
 }
 
 void ColorCorrectionTestUtils::CompareColorCorrectedPixels(
-    std::unique_ptr<uint8_t[]>& converted_pixel,
-    std::unique_ptr<uint8_t[]>& transformed_pixel,
-    int bytes_per_pixel,
-    float color_correction_tolerance) {
-  if (bytes_per_pixel == 4) {
-    EXPECT_EQ(std::memcmp(converted_pixel.get(), transformed_pixel.get(), 4),
-              0);
-  } else {
-    uint16_t *f16_converted =
-                 static_cast<uint16_t*>((void*)(converted_pixel.get())),
-             *f16_trnasformed =
-                 static_cast<uint16_t*>((void*)(transformed_pixel.get()));
-    bool test_passed = true;
-    for (int p = 0; p < 4; p++) {
-      if (!IsNearlyTheSame(Float16ToFloat(f16_converted[p]),
-                           Float16ToFloat(f16_trnasformed[p]),
-                           color_correction_tolerance)) {
-        test_passed = false;
-        break;
+    const void* actual_pixels,
+    const void* expected_pixels,
+    int num_pixels,
+    ImageDataStorageFormat src_storage_format,
+    PixelsAlphaMultiply alpha_multiplied,
+    UnpremulRoundTripTolerance premul_unpremul_tolerance) {
+  bool test_passed = true;
+  int srgb_color_correction_tolerance = 3;
+  float wide_gamut_color_correction_tolerance = 0.01;
+  if (premul_unpremul_tolerance == kNoUnpremulRoundTripTolerance)
+    wide_gamut_color_correction_tolerance = 0;
+
+  switch (src_storage_format) {
+    case kUint8ClampedArrayStorageFormat: {
+      if (premul_unpremul_tolerance == kUnpremulRoundTripTolerance) {
+        // Premul->unpremul->premul round trip does not introduce any error when
+        // rounding intermediate results. However, we still might see some error
+        // introduced in consecutive color correction operations (error <= 3).
+        // For unpremul->premul->unpremul round trip, we do premul and compare
+        // the result.
+        const uint8_t* actual_pixels_u8 =
+            static_cast<const uint8_t*>(actual_pixels);
+        const uint8_t* expected_pixels_u8 =
+            static_cast<const uint8_t*>(expected_pixels);
+        for (int i = 0; test_passed && i < num_pixels; i++) {
+          test_passed &=
+              (actual_pixels_u8[i * 4 + 3] == expected_pixels_u8[i * 4 + 3]);
+          int alpha_multiplier =
+              alpha_multiplied ? 1 : expected_pixels_u8[i * 4 + 3];
+          for (int j = 0; j < 3; j++) {
+            test_passed &= IsNearlyTheSame(
+                actual_pixels_u8[i * 4 + j] * alpha_multiplier,
+                expected_pixels_u8[i * 4 + j] * alpha_multiplier,
+                srgb_color_correction_tolerance);
+          }
+        }
+      } else {
+        EXPECT_EQ(std::memcmp(actual_pixels, expected_pixels, num_pixels * 4),
+                  0);
       }
-    }
-    EXPECT_EQ(test_passed, true);
-  }
-}
-
-void ColorCorrectionTestUtils::CompareColorCorrectedPixels(
-    uint8_t* color_components_1,
-    uint8_t* color_components_2,
-    int num_components,
-    int color_correction_tolerance) {
-  bool test_passed = true;
-  for (int i = 0; i < num_components; i++) {
-    if (!IsNearlyTheSame(color_components_1[i], color_components_2[i],
-                         color_correction_tolerance)) {
-      test_passed = false;
       break;
     }
+
+    case kUint16ArrayStorageFormat: {
+      const uint16_t* actual_pixels_u16 =
+          static_cast<const uint16_t*>(actual_pixels);
+      const uint16_t* expected_pixels_u16 =
+          static_cast<const uint16_t*>(expected_pixels);
+      for (int i = 0; test_passed && i < num_pixels; i++) {
+        for (int j = 0; j < 4; j++) {
+          test_passed &=
+              IsNearlyTheSame(Float16ToFloat(actual_pixels_u16[i * 4 + j]),
+                              Float16ToFloat(expected_pixels_u16[i * 4 + j]),
+                              wide_gamut_color_correction_tolerance);
+        }
+      }
+      break;
+    }
+
+    case kFloat32ArrayStorageFormat: {
+      const float* actual_pixels_f32 = static_cast<const float*>(actual_pixels);
+      const float* expected_pixels_f32 =
+          static_cast<const float*>(expected_pixels);
+      for (int i = 0; test_passed && i < num_pixels; i++) {
+        for (int j = 0; j < 4; j++) {
+          test_passed &= IsNearlyTheSame(actual_pixels_f32[i * 4 + j],
+                                         expected_pixels_f32[i * 4 + j],
+                                         wide_gamut_color_correction_tolerance);
+        }
+      }
+      break;
+    }
+
+    default:
+      NOTREACHED();
   }
   EXPECT_EQ(test_passed, true);
 }
 
-void ColorCorrectionTestUtils::CompareColorCorrectedPixels(
-    float* color_components_1,
-    float* color_components_2,
-    int num_components,
-    float color_correction_tolerance) {
-  bool test_passed = true;
-  for (int i = 0; i < num_components; i++) {
-    if (!IsNearlyTheSame(color_components_1[i], color_components_2[i],
-                         color_correction_tolerance)) {
-      test_passed = false;
+bool ColorCorrectionTestUtils::ConvertPixelsToColorSpaceAndPixelFormatForTest(
+    void* src_data,
+    int num_elements,
+    CanvasColorSpace src_color_space,
+    ImageDataStorageFormat src_storage_format,
+    CanvasColorSpace dst_color_space,
+    CanvasPixelFormat dst_pixel_format,
+    std::unique_ptr<uint8_t[]>& converted_pixels,
+    SkColorSpaceXform::ColorFormat color_format_for_f16_canvas) {
+  unsigned num_pixels = num_elements / 4;
+  // Setting SkColorSpaceXform::apply parameters
+  SkColorSpaceXform::ColorFormat src_color_format =
+      SkColorSpaceXform::kRGBA_8888_ColorFormat;
+
+  uint16_t* u16_buffer = static_cast<uint16_t*>(src_data);
+  switch (src_storage_format) {
+    case kUint8ClampedArrayStorageFormat:
       break;
-    }
+
+    case kUint16ArrayStorageFormat:
+      src_color_format =
+          SkColorSpaceXform::ColorFormat::kRGBA_U16_BE_ColorFormat;
+      for (int i = 0; i < num_elements; i++)
+        *(u16_buffer + i) = WTF::Bswap16(*(u16_buffer + i));
+      break;
+
+    case kFloat32ArrayStorageFormat:
+      src_color_format = SkColorSpaceXform::kRGBA_F32_ColorFormat;
+      break;
+
+    default:
+      NOTREACHED();
+      return false;
   }
-  EXPECT_EQ(test_passed, true);
+
+  SkColorSpaceXform::ColorFormat dst_color_format =
+      SkColorSpaceXform::ColorFormat::kRGBA_8888_ColorFormat;
+  if (dst_pixel_format == kF16CanvasPixelFormat)
+    dst_color_format = color_format_for_f16_canvas;
+
+  sk_sp<SkColorSpace> src_sk_color_space = nullptr;
+  src_sk_color_space =
+      CanvasColorParams(src_color_space,
+                        (src_storage_format == kUint8ClampedArrayStorageFormat)
+                            ? kRGBA8CanvasPixelFormat
+                            : kF16CanvasPixelFormat,
+                        kNonOpaque)
+          .GetSkColorSpaceForSkSurfaces();
+  if (!src_sk_color_space.get())
+    src_sk_color_space = SkColorSpace::MakeSRGB();
+
+  sk_sp<SkColorSpace> dst_sk_color_space =
+      CanvasColorParams(dst_color_space, dst_pixel_format, kNonOpaque)
+          .GetSkColorSpaceForSkSurfaces();
+  if (!dst_sk_color_space.get())
+    dst_sk_color_space = SkColorSpace::MakeSRGB();
+
+  std::unique_ptr<SkColorSpaceXform> xform = SkColorSpaceXform::New(
+      src_sk_color_space.get(), dst_sk_color_space.get());
+  bool conversion_result =
+      xform->apply(dst_color_format, converted_pixels.get(), src_color_format,
+                   src_data, num_pixels, kUnpremul_SkAlphaType);
+
+  if (src_storage_format == kUint16ArrayStorageFormat) {
+    for (int i = 0; i < num_elements; i++)
+      *(u16_buffer + i) = WTF::Bswap16(*(u16_buffer + i));
+  }
+  return conversion_result;
 }
 
 }  // namespace blink
diff --git a/third_party/WebKit/Source/platform/graphics/ColorCorrectionTestUtils.h b/third_party/WebKit/Source/platform/graphics/ColorCorrectionTestUtils.h
index 6f8a631..6a1b181 100644
--- a/third_party/WebKit/Source/platform/graphics/ColorCorrectionTestUtils.h
+++ b/third_party/WebKit/Source/platform/graphics/ColorCorrectionTestUtils.h
@@ -5,39 +5,46 @@
 #ifndef ColorCorrectionTestUtils_h
 #define ColorCorrectionTestUtils_h
 
+#include "platform/graphics/CanvasColorParams.h"
+
+#include "platform/graphics/GraphicsTypes.h"
 #include "platform/runtime_enabled_features.h"
+#include "third_party/skia/include/core/SkColorSpaceXform.h"
 
 namespace blink {
 
+enum PixelsAlphaMultiply {
+  kAlphaMultiplied,
+  kAlphaUnmultiplied,
+};
+
+enum UnpremulRoundTripTolerance {
+  kNoUnpremulRoundTripTolerance,
+  kUnpremulRoundTripTolerance,
+};
+
 class ColorCorrectionTestUtils {
  public:
-  static bool IsNearlyTheSame(
-      float expected,
-      float actual,
-      float tolerance = wide_gamut_color_correction_tolerance_);
   static void CompareColorCorrectedPixels(
-      std::unique_ptr<uint8_t[]>& converted_pixel,
-      std::unique_ptr<uint8_t[]>& transformed_pixel,
-      int bytes_per_pixel = 4,
-      float color_correction_tolerance =
-          wide_gamut_color_correction_tolerance_);
-  static void CompareColorCorrectedPixels(uint8_t* color_components_1,
-                                          uint8_t* color_components_2,
-                                          int,
-                                          int);
-  static void CompareColorCorrectedPixels(
-      float* color_components_1,
-      float* color_components_2,
-      int num_components,
-      float color_correction_tolerance =
-          wide_gamut_color_correction_tolerance_);
+      const void* actual_pixels,
+      const void* expected_pixels,
+      int num_pixels,
+      ImageDataStorageFormat src_storage_format,
+      PixelsAlphaMultiply alpha_multiplied,
+      UnpremulRoundTripTolerance premul_unpremul_tolerance);
+
+  static bool ConvertPixelsToColorSpaceAndPixelFormatForTest(
+      void* src_data,
+      int num_elements,
+      CanvasColorSpace src_color_space,
+      ImageDataStorageFormat src_storage_format,
+      CanvasColorSpace dst_color_space,
+      CanvasPixelFormat dst_pixel_format,
+      std::unique_ptr<uint8_t[]>& converted_pixels,
+      SkColorSpaceXform::ColorFormat color_format_for_f16_canvas);
 
  private:
-  static constexpr float wide_gamut_color_correction_tolerance_ = 0.01;
-  // This function is a compact version of SkHalfToFloat from Skia. If many
-  // color correction tests fail at the same time, please check if SkHalf format
-  // has changed.
-  static float Float16ToFloat(const uint16_t& f16);
+  static bool IsNearlyTheSame(float expected, float actual, float tolerance);
 };
 
 }  // namespace blink
diff --git a/third_party/WebKit/Source/platform/graphics/GraphicsTypes.h b/third_party/WebKit/Source/platform/graphics/GraphicsTypes.h
index 13bf1e23..a16e321 100644
--- a/third_party/WebKit/Source/platform/graphics/GraphicsTypes.h
+++ b/third_party/WebKit/Source/platform/graphics/GraphicsTypes.h
@@ -35,6 +35,12 @@
 
 namespace blink {
 
+enum ImageDataStorageFormat {
+  kUint8ClampedArrayStorageFormat,
+  kUint16ArrayStorageFormat,
+  kFloat32ArrayStorageFormat,
+};
+
 enum StrokeStyle {
   kNoStroke,
   kSolidStroke,
diff --git a/third_party/WebKit/Source/platform/graphics/HighContrastImageClassifier.cpp b/third_party/WebKit/Source/platform/graphics/HighContrastImageClassifier.cpp
index 8b63a13..8258d59 100644
--- a/third_party/WebKit/Source/platform/graphics/HighContrastImageClassifier.cpp
+++ b/third_party/WebKit/Source/platform/graphics/HighContrastImageClassifier.cpp
@@ -4,6 +4,8 @@
 
 #include "platform/graphics/HighContrastImageClassifier.h"
 
+#include "base/rand_util.h"
+#include "third_party/WebKit/Source/platform/geometry/IntRect.h"
 #include "third_party/skia/include/utils/SkNullCanvas.h"
 
 namespace {
@@ -16,25 +18,63 @@
          8;
 }
 
-enum class ColorMode { kColor = 0, kGrayscale = 1 };
+void RGBAdd(const SkColor& new_pixel, SkColor4f* sink) {
+  sink->fR += SkColorGetR(new_pixel);
+  sink->fG += SkColorGetG(new_pixel);
+  sink->fB += SkColorGetB(new_pixel);
+}
 
-const int kOneDimensionalPixelsToSample = 34;
+void RGBDivide(SkColor4f* sink, int divisor) {
+  sink->fR /= divisor;
+  sink->fG /= divisor;
+  sink->fB /= divisor;
+}
+
+float ColorDifference(const SkColor& color1, const SkColor4f& color2) {
+  return sqrt((pow(static_cast<float>(SkColorGetR(color1)) - color2.fR, 2.0) +
+               pow(static_cast<float>(SkColorGetG(color1)) - color2.fG, 2.0) +
+               pow(static_cast<float>(SkColorGetB(color1)) - color2.fB, 2.0)) /
+              3.0);
+}
+
+const int kPixelsToSample = 1000;
+const int kBlocksCount1D = 10;
+const int kMinImageSizeForClassification1D = 24;
 
 }  // namespace
 
 namespace blink {
 
+HighContrastImageClassifier::HighContrastImageClassifier()
+    : use_testing_random_generator_(false), testing_random_generator_seed_(0) {}
+
+int HighContrastImageClassifier::GetRandomInt(const int min, const int max) {
+  if (use_testing_random_generator_) {
+    testing_random_generator_seed_ *= 7;
+    testing_random_generator_seed_ += 15485863;
+    testing_random_generator_seed_ %= 256205689;
+    return min + testing_random_generator_seed_ % (max - min);
+  }
+
+  return base::RandInt(min, max - 1);
+}
+
 bool HighContrastImageClassifier::ShouldApplyHighContrastFilterToImage(
     Image& image) {
   HighContrastClassification result = image.GetHighContrastClassification();
   if (result != HighContrastClassification::kNotClassified)
     return result == HighContrastClassification::kApplyHighContrastFilter;
 
-  std::vector<float> features;
-  if (!ComputeImageFeatures(image, &features))
-    result = HighContrastClassification::kDoNotApplyHighContrastFilter;
-  else
-    result = ClassifyImage(features);
+  if (image.width() < kMinImageSizeForClassification1D ||
+      image.height() < kMinImageSizeForClassification1D) {
+    result = HighContrastClassification::kApplyHighContrastFilter;
+  } else {
+    std::vector<float> features;
+    if (!ComputeImageFeatures(image, &features))
+      result = HighContrastClassification::kDoNotApplyHighContrastFilter;
+    else
+      result = ClassifyImage(features);
+  }
 
   image.SetHighContrastClassification(result);
   return result == HighContrastClassification::kApplyHighContrastFilter;
@@ -50,11 +90,15 @@
   if (!GetBitmap(image, &bitmap))
     return false;
 
+  if (use_testing_random_generator_)
+    testing_random_generator_seed_ = 0;
+
   std::vector<SkColor> sampled_pixels;
   float transparency_ratio;
-  GetSamples(bitmap, &sampled_pixels, &transparency_ratio);
+  float background_ratio;
+  GetSamples(bitmap, &sampled_pixels, &transparency_ratio, &background_ratio);
 
-  GetFeatures(sampled_pixels, transparency_ratio, features);
+  GetFeatures(sampled_pixels, transparency_ratio, background_ratio, features);
   return true;
 }
 
@@ -71,32 +115,136 @@
   return true;
 }
 
-// This function selects a set of sample pixels from an image, and returns them
-// along with ratio of transparent pixels to all pixels.
-// Sampling is done uniformly along the width and height of the image.
+// Extracts sample pixels from the image, focusing on the foreground and
+// ignoring static background. The image is separated into uniformly distributed
+// blocks through its width and height, each block is sampled, and checked to
+// see if it seem to be background or foreground (See IsBlockBackground for
+// details). Samples from foreground blocks are collected, and if they are less
+// than 50% of requested samples, the foreground blocks are resampled to get
+// more points.
 void HighContrastImageClassifier::GetSamples(
     const SkBitmap& bitmap,
     std::vector<SkColor>* sampled_pixels,
-    float* transparency_ratio) {
-  int cx = static_cast<int>(
-      ceil(bitmap.width() / static_cast<float>(kOneDimensionalPixelsToSample)));
-  int cy = static_cast<int>(ceil(
-      bitmap.height() / static_cast<float>(kOneDimensionalPixelsToSample)));
+    float* transparency_ratio,
+    float* background_ratio) {
+  int pixels_per_block = kPixelsToSample / (kBlocksCount1D * kBlocksCount1D);
+
+  int transparent_pixels = 0;
+  int opaque_pixels = 0;
+  int blocks_count = 0;
+
+  std::vector<int> horizontal_grid(kBlocksCount1D + 1);
+  std::vector<int> vertical_grid(kBlocksCount1D + 1);
+  for (int block = 0; block <= kBlocksCount1D; block++) {
+    horizontal_grid[block] = static_cast<int>(
+        round(block * bitmap.width() / static_cast<float>(kBlocksCount1D)));
+    vertical_grid[block] = static_cast<int>(
+        round(block * bitmap.height() / static_cast<float>(kBlocksCount1D)));
+  }
 
   sampled_pixels->clear();
-  int transparent_pixels = 0;
-  for (int y = 0; y < bitmap.height(); y += cy) {
-    for (int x = 0; x < bitmap.width(); x += cx) {
-      SkColor new_sample = bitmap.getColor(x, y);
-      if (SkColorGetA(new_sample) < 128)
-        transparent_pixels++;
-      else
-        sampled_pixels->push_back(new_sample);
+  std::vector<IntRect> foreground_blocks;
+
+  for (int y = 0; y < kBlocksCount1D; y++) {
+    for (int x = 0; x < kBlocksCount1D; x++) {
+      IntRect block(horizontal_grid[x], vertical_grid[y],
+                    horizontal_grid[x + 1] - horizontal_grid[x],
+                    vertical_grid[y + 1] - vertical_grid[y]);
+
+      std::vector<SkColor> block_samples;
+      int block_transparent_pixels;
+      GetBlockSamples(bitmap, block, pixels_per_block, &block_samples,
+                      &block_transparent_pixels);
+      opaque_pixels += static_cast<int>(block_samples.size());
+      transparent_pixels += block_transparent_pixels;
+
+      if (!IsBlockBackground(block_samples, block_transparent_pixels)) {
+        sampled_pixels->insert(sampled_pixels->end(), block_samples.begin(),
+                               block_samples.end());
+        foreground_blocks.push_back(block);
+      }
+      blocks_count++;
     }
   }
 
-  *transparency_ratio = (transparent_pixels * 1.0) /
-                        (transparent_pixels + sampled_pixels->size());
+  *transparency_ratio = static_cast<float>(transparent_pixels) /
+                        (transparent_pixels + opaque_pixels);
+  *background_ratio =
+      1.0 - static_cast<float>(foreground_blocks.size()) / blocks_count;
+
+  // If samples are too few, resample foreground blocks.
+  if (sampled_pixels->size() < kPixelsToSample / 2 &&
+      foreground_blocks.size()) {
+    pixels_per_block = static_cast<int>(
+        ceil((kPixelsToSample - static_cast<float>(sampled_pixels->size())) /
+             static_cast<float>(foreground_blocks.size())));
+    for (const IntRect& block : foreground_blocks) {
+      std::vector<SkColor> block_samples;
+      int unused;
+      GetBlockSamples(bitmap, block, pixels_per_block, &block_samples, &unused);
+      sampled_pixels->insert(sampled_pixels->end(), block_samples.begin(),
+                             block_samples.end());
+    }
+  }
+}
+
+// Selects random samples from a block of the image. Returns the opaque sampled
+// pixels, and the number of transparent sampled pixels.
+void HighContrastImageClassifier::GetBlockSamples(
+    const SkBitmap& bitmap,
+    const IntRect& block,
+    const int required_samples_count,
+    std::vector<SkColor>* sampled_pixels,
+    int* transparent_pixels_count) {
+  *transparent_pixels_count = 0;
+
+  int x1 = block.X();
+  int y1 = block.Y();
+  int x2 = block.MaxX();
+  int y2 = block.MaxY();
+  DCHECK(x1 < bitmap.width());
+  DCHECK(y1 < bitmap.height());
+  DCHECK(x2 <= bitmap.width());
+  DCHECK(y2 <= bitmap.height());
+
+  sampled_pixels->clear();
+  for (int i = 0; i < required_samples_count; i++) {
+    int x = GetRandomInt(x1, x2);
+    int y = GetRandomInt(y1, y2);
+    SkColor new_sample = bitmap.getColor(x, y);
+    if (SkColorGetA(new_sample) < 128)
+      (*transparent_pixels_count)++;
+    else
+      sampled_pixels->push_back(new_sample);
+  }
+}
+
+// Given sampled pixels and transparent pixels count of a block of the image,
+// decides if that block is background or not. If more than 80% of the block is
+// transparent, or the divergence of colors in the block is less than 5%, the
+// block is considered background.
+bool HighContrastImageClassifier::IsBlockBackground(
+    const std::vector<SkColor>& sampled_pixels,
+    const int transparent_pixels) {
+  if (static_cast<int>(sampled_pixels.size()) <= transparent_pixels / 4)
+    return true;
+
+  SkColor4f average;
+  average.fR = 0;
+  average.fG = 0;
+  average.fB = 0;
+
+  for (const SkColor& sample : sampled_pixels)
+    RGBAdd(sample, &average);
+
+  RGBDivide(&average, sampled_pixels.size());
+
+  float sum = 0;
+  for (const auto& sample : sampled_pixels)
+    sum += ColorDifference(sample, average);
+  sum /= 128;  // Normalize to 0..1 range.
+  float divergence = sum / sampled_pixels.size();
+  return divergence < 0.05;
 }
 
 // This function computes a single feature vector from a sample set of image
@@ -104,9 +252,12 @@
 // 0: 1 if color, 0 if grayscale.
 // 1: Ratio of the number of bucketed colors used in the image to all
 //    possiblities. Color buckets are represented with 4 bits per color channel.
+// 2: Ratio of transparent area to the whole image.
+// 3: Ratio of the brackground area to the whole image.
 void HighContrastImageClassifier::GetFeatures(
     const std::vector<SkColor>& sampled_pixels,
     const float transparency_ratio,
+    const float background_ratio,
     std::vector<float>* features) {
   int samples_count = static_cast<int>(sampled_pixels.size());
 
@@ -120,30 +271,49 @@
                              ? ColorMode::kColor
                              : ColorMode::kGrayscale;
 
-  features->resize(2);
+  features->resize(4);
 
   // Feature 0: Is Colorful?
   (*features)[0] = color_mode == ColorMode::kColor;
 
-  // Feature 1: Color Buckets Ratio
+  // Feature 1: Color Buckets Ratio.
+  (*features)[1] = ComputeColorBucketsRatio(sampled_pixels, color_mode);
+
+  // Feature 2: Transparency Ratio
+  (*features)[2] = transparency_ratio;
+
+  // Feature 3: Background Ratio.
+  (*features)[3] = background_ratio;
+}
+
+float HighContrastImageClassifier::ComputeColorBucketsRatio(
+    const std::vector<SkColor>& sampled_pixels,
+    const ColorMode color_mode) {
+  std::set<unsigned> buckets;
+  // If image is in color, use 4 bits per color channel, otherwise 4 bits for
+  // illumination.
+  if (color_mode == ColorMode::kColor) {
+    for (const SkColor& sample : sampled_pixels) {
+      unsigned bucket = ((SkColorGetR(sample) >> 4) << 8) +
+                        ((SkColorGetG(sample) >> 4) << 4) +
+                        ((SkColorGetB(sample) >> 4));
+      buckets.insert(bucket);
+    }
+  } else {
+    for (const SkColor& sample : sampled_pixels) {
+      unsigned illumination =
+          (SkColorGetR(sample) * 5 + SkColorGetG(sample) * 3 +
+           SkColorGetB(sample) * 2) /
+          10;
+      buckets.insert(illumination / 16);
+    }
+  }
+
   // Using 4 bit per channel representation of each color bucket, there would be
   // 2^4 buckets for grayscale images and 2^12 for color images.
   const float max_buckets[] = {16, 4096};
-  (*features)[1] = CountColorBuckets(sampled_pixels) /
-                   max_buckets[color_mode == ColorMode::kColor];
-}
-
-int HighContrastImageClassifier::CountColorBuckets(
-    const std::vector<SkColor>& sampled_pixels) {
-  std::set<unsigned> buckets;
-  for (const SkColor& sample : sampled_pixels) {
-    unsigned bucket = ((SkColorGetR(sample) >> 4) << 8) +
-                      ((SkColorGetG(sample) >> 4) << 4) +
-                      ((SkColorGetB(sample) >> 4));
-    buckets.insert(bucket);
-  }
-
-  return static_cast<int>(buckets.size());
+  return static_cast<float>(buckets.size()) /
+         max_buckets[color_mode == ColorMode::kColor];
 }
 
 HighContrastClassification HighContrastImageClassifier::ClassifyImage(
@@ -151,11 +321,9 @@
   bool result = false;
 
   // Shallow decision tree trained by C4.5.
-  if (features.size() == 2) {
-    if (features[1] < 0.016)
-      result = true;
-    else
-      result = (features[0] == 0);
+  if (features.size() >= 2) {
+    float threshold = (features[0] == 0) ? 0.8125 : 0.0166;
+    result = features[1] < threshold;
   }
 
   return result ? HighContrastClassification::kApplyHighContrastFilter
diff --git a/third_party/WebKit/Source/platform/graphics/HighContrastImageClassifier.h b/third_party/WebKit/Source/platform/graphics/HighContrastImageClassifier.h
index 0034623d..29a901a 100644
--- a/third_party/WebKit/Source/platform/graphics/HighContrastImageClassifier.h
+++ b/third_party/WebKit/Source/platform/graphics/HighContrastImageClassifier.h
@@ -12,9 +12,11 @@
 
 namespace blink {
 
+class IntRect;
+
 class PLATFORM_EXPORT HighContrastImageClassifier {
  public:
-  HighContrastImageClassifier() = default;
+  HighContrastImageClassifier();
   ~HighContrastImageClassifier() = default;
 
   // Decides if a high contrast filter should be applied to the image or not.
@@ -25,26 +27,57 @@
     return ComputeImageFeatures(image, features);
   }
 
+  void SetRandomGeneratorForTesting() { use_testing_random_generator_ = true; }
+
  private:
+  enum class ColorMode { kColor = 0, kGrayscale = 1 };
+
   // Computes the features vector for a given image.
   bool ComputeImageFeatures(Image&, std::vector<float>*);
 
   // Converts image to SkBitmap and returns true if successful.
   bool GetBitmap(Image&, SkBitmap*);
 
-  // Extracts sample pixels and transparency ratio from the given bitmap.
-  void GetSamples(const SkBitmap&, std::vector<SkColor>*, float*);
+  // Given a SkBitmap, extracts a sample set of pixels (|sampled_pixels|),
+  // |transparency_ratio|, and |background_ratio|.
+  void GetSamples(const SkBitmap&,
+                  std::vector<SkColor>* sampled_pixels,
+                  float* transparency_ratio,
+                  float* background_ratio);
 
-  // Computes the features, given sampled pixels and transparency ratio.
-  void GetFeatures(const std::vector<SkColor>&,
-                   const float,
-                   std::vector<float>*);
+  // Given |sampled_pixels|, |transparency_ratio|, and |background_ratio| for an
+  // image, computes the required |features| for classification.
+  void GetFeatures(const std::vector<SkColor>& sampled_pixels,
+                   const float transparency_ratio,
+                   const float background_ratio,
+                   std::vector<float>* features);
 
-  // Makes a decision about image given its features.
+  // Makes a decision about the image given its features.
   HighContrastClassification ClassifyImage(const std::vector<float>&);
 
-  // Receives sampled pixels, and returns the number of color buckets.
-  int CountColorBuckets(const std::vector<SkColor>&);
+  // Receives sampled pixels and color mode, and returns the ratio of color
+  // buckets count to all possible color buckets. If image is in color, a color
+  // bucket is a 4 bit per channel representation of each RGB color, and if it
+  // is grayscale, each bucket is a 4 bit representation of luminance.
+  float ComputeColorBucketsRatio(const std::vector<SkColor>&, const ColorMode);
+
+  // Gets the |required_samples_count| for a specific |block| of the given
+  // SkBitmap, and returns |sampled_pixels| and |transparent_pixels_count|.
+  void GetBlockSamples(const SkBitmap&,
+                       const IntRect& block,
+                       const int required_samples_count,
+                       std::vector<SkColor>* sampled_pixels,
+                       int* transparent_pixels_count);
+
+  // Given sampled pixels from a block of image and the number of transparent
+  // pixels, decides if a block is part of background or or not.
+  bool IsBlockBackground(const std::vector<SkColor>&, const int);
+
+  // Returns a random number in range [min, max).
+  int GetRandomInt(const int min, const int max);
+
+  bool use_testing_random_generator_;
+  int testing_random_generator_seed_;
 };
 
 }  // namespace blink
diff --git a/third_party/WebKit/Source/platform/graphics/HighContrastImageClassifierTest.cpp b/third_party/WebKit/Source/platform/graphics/HighContrastImageClassifierTest.cpp
index 5b7a9d1ff..1e2c7458 100644
--- a/third_party/WebKit/Source/platform/graphics/HighContrastImageClassifierTest.cpp
+++ b/third_party/WebKit/Source/platform/graphics/HighContrastImageClassifierTest.cpp
@@ -10,6 +10,11 @@
 #include "platform/testing/UnitTestHelpers.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
+namespace {
+const float kEpsilon = 0.00001;
+
+}  // namespace
+
 namespace blink {
 
 class HighContrastImageClassifierTest : public ::testing::Test {
@@ -20,26 +25,18 @@
                                     std::vector<float>* features) {
     SCOPED_TRACE(file_name);
     scoped_refptr<BitmapImage> image = LoadImage(file_name);
+    classifier_.SetRandomGeneratorForTesting();
     classifier_.ComputeImageFeaturesForTesting(*image.get(), features);
     return classifier_.ShouldApplyHighContrastFilterToImage(*image.get());
   }
 
-  // Compares two vectors of computed features and expected ones. Comparison is
-  // done with 0.000001 precision to ignore minor, negligible differences.
-  bool AreFeaturesEqual(const std::vector<float>& features,
-                        const std::vector<float>& expected_features) {
-    if (features.size() != expected_features.size()) {
-      LOG(ERROR) << "Different sized vectors.";
-      return false;
-    }
+  void AssertFeaturesEqual(const std::vector<float>& features,
+                           const std::vector<float>& expected_features) {
+    EXPECT_EQ(features.size(), expected_features.size());
     for (unsigned i = 0; i < features.size(); i++) {
-      if (fabs(features[i] - expected_features[i]) > 0.000001) {
-        LOG(ERROR) << "Different values at index " << i << ", " << features[i]
-                   << " vs " << expected_features[i];
-        return false;
-      }
+      EXPECT_NEAR(features[i], expected_features[i], kEpsilon)
+          << "Feature " << i;
     }
-    return true;
   }
 
  protected:
@@ -66,12 +63,12 @@
   EXPECT_FALSE(GetFeaturesAndClassification(
       "/LayoutTests/images/resources/blue-wheel-srgb-color-profile.png",
       &features));
-  EXPECT_TRUE(AreFeaturesEqual(features, {1.0f, 0.0336914f}));
+  AssertFeaturesEqual(features, {1.0f, 0.03027f, 0.0f, 0.24f});
 
   // Test Case 2:
   EXPECT_TRUE(GetFeaturesAndClassification(
       "/LayoutTests/images/resources/grid-large.png", &features));
-  EXPECT_TRUE(AreFeaturesEqual(features, {0.0f, 0.1875f}));
+  AssertFeaturesEqual(features, {0.0f, 0.1875f, 0.0f, 0.1f});
 }
 
 }  // namespace blink
diff --git a/third_party/WebKit/Source/platform/graphics/ImageBuffer.cpp b/third_party/WebKit/Source/platform/graphics/ImageBuffer.cpp
index bb8ad3b8..9cc39e6 100644
--- a/third_party/WebKit/Source/platform/graphics/ImageBuffer.cpp
+++ b/third_party/WebKit/Source/platform/graphics/ImageBuffer.cpp
@@ -371,9 +371,8 @@
       (surface_->ColorParams().GetSkColorType() == kRGBA_F16_SkColorType)
           ? kRGBA_F16_SkColorType
           : kRGBA_8888_SkColorType;
-  SkImageInfo info = SkImageInfo::Make(
-      rect.Width(), rect.Height(), color_type, kUnpremul_SkAlphaType,
-      surface_->ColorParams().GetSkColorSpaceForSkSurfaces());
+  SkImageInfo info = SkImageInfo::Make(rect.Width(), rect.Height(), color_type,
+                                       kUnpremul_SkAlphaType);
   snapshot->PaintImageForCurrentFrame().GetSkImage()->readPixels(
       info, result.Data(), bytes_per_pixel * rect.Width(), rect.X(), rect.Y());
   gpu_readback_invoked_in_current_frame_ = true;
diff --git a/third_party/WebKit/Source/platform/graphics/StaticBitmapImage.cpp b/third_party/WebKit/Source/platform/graphics/StaticBitmapImage.cpp
index 37d175f..09b9681 100644
--- a/third_party/WebKit/Source/platform/graphics/StaticBitmapImage.cpp
+++ b/third_party/WebKit/Source/platform/graphics/StaticBitmapImage.cpp
@@ -49,17 +49,23 @@
 
 scoped_refptr<StaticBitmapImage> StaticBitmapImage::ConvertToColorSpace(
     sk_sp<SkColorSpace> target,
-    SkTransferFunctionBehavior premulBehavior) {
-  if (!target)
-    return this;
-
+    SkTransferFunctionBehavior transfer_function_behavior) {
   sk_sp<SkImage> skia_image = PaintImageForCurrentFrame().GetSkImage();
-  sk_sp<SkImage> converted_skia_image =
-      skia_image->makeColorSpace(target, premulBehavior);
-
-  if (skia_image == converted_skia_image)
+  sk_sp<SkColorSpace> src_color_space = skia_image->refColorSpace();
+  if (!src_color_space.get())
+    src_color_space = SkColorSpace::MakeSRGB();
+  sk_sp<SkColorSpace> dst_color_space = target;
+  if (!dst_color_space.get())
+    dst_color_space = SkColorSpace::MakeSRGB();
+  if (SkColorSpace::Equals(src_color_space.get(), dst_color_space.get()))
     return this;
 
+  // transfer_function_behavior = SkTransferFunctionBehavior::kIgnore;
+  sk_sp<SkImage> converted_skia_image =
+      skia_image->makeColorSpace(dst_color_space, transfer_function_behavior);
+  DCHECK(converted_skia_image.get());
+  DCHECK(skia_image.get() != converted_skia_image.get());
+
   return StaticBitmapImage::Create(converted_skia_image,
                                    ContextProviderWrapper());
 }
diff --git a/third_party/WebKit/Source/platform/graphics/gpu/AcceleratedImageBufferSurface.cpp b/third_party/WebKit/Source/platform/graphics/gpu/AcceleratedImageBufferSurface.cpp
index b91d56ab..cb64ddd7 100644
--- a/third_party/WebKit/Source/platform/graphics/gpu/AcceleratedImageBufferSurface.cpp
+++ b/third_party/WebKit/Source/platform/graphics/gpu/AcceleratedImageBufferSurface.cpp
@@ -63,7 +63,6 @@
   if (!surface_)
     return;
 
-  sk_sp<SkColorSpace> xform_canvas_color_space = nullptr;
   canvas_ = color_params.WrapCanvas(surface_->getCanvas());
   Clear();
 
diff --git a/third_party/WebKit/Source/platform/graphics/gpu/DrawingBuffer.cpp b/third_party/WebKit/Source/platform/graphics/gpu/DrawingBuffer.cpp
index 53e7f40..a903e61 100644
--- a/third_party/WebKit/Source/platform/graphics/gpu/DrawingBuffer.cpp
+++ b/third_party/WebKit/Source/platform/graphics/gpu/DrawingBuffer.cpp
@@ -1206,7 +1206,7 @@
         gfx::Size(size), buffer_format, gfx::BufferUsage::SCANOUT,
         gpu::kNullSurfaceHandle);
     if (gpu_memory_buffer) {
-      gpu_memory_buffer->SetColorSpaceForScanout(storage_color_space_);
+      gpu_memory_buffer->SetColorSpace(storage_color_space_);
       image_id =
           gl_->CreateImageCHROMIUM(gpu_memory_buffer->AsClientBuffer(),
                                    size.Width(), size.Height(), gl_format);
diff --git a/third_party/WebKit/Source/platform/graphics/paint/PaintRecordBuilder.cpp b/third_party/WebKit/Source/platform/graphics/paint/PaintRecordBuilder.cpp
index edfef4d..a5c05cc8 100644
--- a/third_party/WebKit/Source/platform/graphics/paint/PaintRecordBuilder.cpp
+++ b/third_party/WebKit/Source/platform/graphics/paint/PaintRecordBuilder.cpp
@@ -11,11 +11,10 @@
 
 namespace blink {
 
-PaintRecordBuilder::PaintRecordBuilder(const FloatRect& bounds,
-                                       SkMetaData* meta_data,
+PaintRecordBuilder::PaintRecordBuilder(SkMetaData* meta_data,
                                        GraphicsContext* containing_context,
                                        PaintController* paint_controller)
-    : paint_controller_(nullptr), bounds_(bounds) {
+    : paint_controller_(nullptr) {
   GraphicsContext::DisabledMode disabled_mode =
       GraphicsContext::kNothingDisabled;
   if (containing_context && containing_context->ContextDisabled())
@@ -52,7 +51,7 @@
 
 sk_sp<PaintRecord> PaintRecordBuilder::EndRecording(
     const PropertyTreeState& replay_state) {
-  context_->BeginRecording(bounds_);
+  context_->BeginRecording(FloatRect());
   paint_controller_->CommitNewDisplayItems();
   paint_controller_->GetPaintArtifact().Replay(*context_, replay_state);
   return context_->EndRecording();
diff --git a/third_party/WebKit/Source/platform/graphics/paint/PaintRecordBuilder.h b/third_party/WebKit/Source/platform/graphics/paint/PaintRecordBuilder.h
index 61abbe2..21902260 100644
--- a/third_party/WebKit/Source/platform/graphics/paint/PaintRecordBuilder.h
+++ b/third_party/WebKit/Source/platform/graphics/paint/PaintRecordBuilder.h
@@ -31,19 +31,17 @@
   WTF_MAKE_NONCOPYABLE(PaintRecordBuilder);
 
  public:
-  // Constructs a new builder with the given bounds for the resulting recorded
-  // picture. If |metadata| is specified, that metadata is propagated to the
-  // builder's internal canvas. If |containingContext| is specified, the device
-  // scale factor, printing, and disabled state are propagated to the builder's
-  // internal context.
+  // Constructs a new builder for the resulting recorded picture. If |metadata|
+  // is specified, that metadata is propagated to the builder's internal canvas.
+  // If |containing_context| is specified, the device scale factor, printing,
+  // and disabled state are propagated to the builder's internal context.
   // If a PaintController is passed, it is used as the PaintController for
   // painting the picture (and hence we can use its cache). Otherwise, a new
   // PaintController is used for the duration of the picture building, which
   // therefore has no caching.
-  // In SPv175+ mode, resets paint chunks to PropertyTreeState::root()
+  // In SPv175+ mode, resets paint chunks to PropertyTreeState::Root()
   // before beginning to record.
-  PaintRecordBuilder(const FloatRect& bounds,
-                     SkMetaData* = nullptr,
+  PaintRecordBuilder(SkMetaData* = nullptr,
                      GraphicsContext* containing_context = nullptr,
                      PaintController* = nullptr);
 
@@ -69,7 +67,6 @@
   PaintController* paint_controller_;
   std::unique_ptr<PaintController> own_paint_controller_;
   std::unique_ptr<GraphicsContext> context_;
-  FloatRect bounds_;
   Optional<DisplayItemCacheSkipper> cache_skipper_;
 };
 
diff --git a/third_party/WebKit/Source/platform/graphics/paint/PaintRecordBuilderTest.cpp b/third_party/WebKit/Source/platform/graphics/paint/PaintRecordBuilderTest.cpp
index 5f13af7..5f585a4 100644
--- a/third_party/WebKit/Source/platform/graphics/paint/PaintRecordBuilderTest.cpp
+++ b/third_party/WebKit/Source/platform/graphics/paint/PaintRecordBuilderTest.cpp
@@ -15,7 +15,7 @@
 using PaintRecordBuilderTest = PaintControllerTestBase;
 
 TEST_F(PaintRecordBuilderTest, TransientPaintController) {
-  PaintRecordBuilder builder(FloatRect(10, 10, 20, 20));
+  PaintRecordBuilder builder;
   auto& context = builder.Context();
   FakeDisplayItemClient client("client", LayoutRect(10, 10, 20, 20));
   DrawRect(context, client, kBackgroundType, FloatRect(10, 10, 20, 20));
@@ -34,8 +34,7 @@
 }
 
 TEST_F(PaintRecordBuilderTest, LastingPaintController) {
-  PaintRecordBuilder builder(FloatRect(10, 10, 20, 20), nullptr, nullptr,
-                             &GetPaintController());
+  PaintRecordBuilder builder(nullptr, nullptr, &GetPaintController());
   auto& context = builder.Context();
   EXPECT_EQ(&context.GetPaintController(), &GetPaintController());
 
@@ -79,7 +78,7 @@
                       TestDisplayItem(client, kForegroundType));
   EXPECT_TRUE(GetPaintController().ClientCacheIsValid(client));
 
-  PaintRecordBuilder builder(FloatRect(10, 10, 20, 20));
+  PaintRecordBuilder builder;
   EXPECT_NE(&builder.Context().GetPaintController(), &GetPaintController());
   DrawRect(builder.Context(), client, kBackgroundType,
            FloatRect(10, 10, 20, 20));
diff --git a/third_party/WebKit/Source/platform/graphics/test/StubImage.h b/third_party/WebKit/Source/platform/graphics/test/StubImage.h
new file mode 100644
index 0000000..b16421f7
--- /dev/null
+++ b/third_party/WebKit/Source/platform/graphics/test/StubImage.h
@@ -0,0 +1,31 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef StubImage_h
+#define StubImage_h
+
+#include "platform/graphics/Image.h"
+
+namespace blink {
+
+class StubImage : public Image {
+ public:
+  StubImage() {}
+
+  bool CurrentFrameKnownToBeOpaque(MetadataMode) override { return false; }
+  IntSize Size() const override { return IntSize(10, 10); }
+  void DestroyDecodedData() override {}
+  PaintImage PaintImageForCurrentFrame() override { return PaintImage(); }
+  void Draw(PaintCanvas*,
+            const PaintFlags&,
+            const FloatRect& dst_rect,
+            const FloatRect& src_rect,
+            RespectImageOrientationEnum,
+            ImageClampingMode,
+            ImageDecodingMode) override {}
+};
+
+}  // namespace blink
+
+#endif  // StubImage_h
diff --git a/third_party/WebKit/Source/platform/heap/BlinkGCAPIReference.md b/third_party/WebKit/Source/platform/heap/BlinkGCAPIReference.md
index 2229196..2e8f504 100644
--- a/third_party/WebKit/Source/platform/heap/BlinkGCAPIReference.md
+++ b/third_party/WebKit/Source/platform/heap/BlinkGCAPIReference.md
@@ -91,7 +91,7 @@
     ~YourClass() { ... } // Non-empty destructor means finalization is needed.
 
 private:
-    RefPtr<Something> m_something; // RefPtr<> has non-empty destructor, so finalization is needed.
+    scoped_refptr<Something> m_something; // scoped_refptr<> has non-empty destructor, so finalization is needed.
 };
 ```
 
@@ -247,7 +247,7 @@
 
 ## Handles
 
-Class templates in this section are smart pointers, each carrying a pointer to an on-heap object (think of `RefPtr<T>`
+Class templates in this section are smart pointers, each carrying a pointer to an on-heap object (think of `scoped_refptr<T>`
 for `RefCounted<T>`). Collectively, they are called *handles*.
 
 On-heap objects must be retained by any of these, depending on the situation.
@@ -271,7 +271,7 @@
 the desired semantics.
 
 `Member<T>` represents a *strong* reference to an object of type `T`, which means that the referred object is kept
-alive as long as the owner class instance is alive. Unlike `RefPtr<T>`, it is okay to form a reference cycle with
+alive as long as the owner class instance is alive. Unlike `scoped_refptr<T>`, it is okay to form a reference cycle with
 members (in on-heap objects) and raw pointers (on stack).
 
 `WeakMember<T>` is a *weak* reference to an object of type `T`. Unlike `Member<T>`, `WeakMember<T>` does not keep
diff --git a/third_party/WebKit/Source/platform/heap/HeapTest.cpp b/third_party/WebKit/Source/platform/heap/HeapTest.cpp
index 7437fc0..585e763 100644
--- a/third_party/WebKit/Source/platform/heap/HeapTest.cpp
+++ b/third_party/WebKit/Source/platform/heap/HeapTest.cpp
@@ -422,7 +422,7 @@
 
 class OffHeapInt : public RefCounted<OffHeapInt> {
  public:
-  static RefPtr<OffHeapInt> Create(int x) {
+  static scoped_refptr<OffHeapInt> Create(int x) {
     return WTF::AdoptRef(new OffHeapInt(x));
   }
 
@@ -661,7 +661,7 @@
       ref_counted_chain_ = WTF::AdoptRef(RefCountedChain::Create(count));
     }
 
-    RefPtr<RefCountedChain> ref_counted_chain_;
+    scoped_refptr<RefCountedChain> ref_counted_chain_;
   };
 
   void RunThread() override {
@@ -3793,7 +3793,7 @@
 TEST(HeapTest, RefCountedGarbageCollected) {
   RefCountedAndGarbageCollected::destructor_calls_ = 0;
   {
-    RefPtr<RefCountedAndGarbageCollected> ref_ptr3;
+    scoped_refptr<RefCountedAndGarbageCollected> ref_ptr3;
     {
       Persistent<RefCountedAndGarbageCollected> persistent;
       {
@@ -4889,7 +4889,7 @@
 }
 
 TEST(HeapTest, MapWithCustomWeaknessHandling) {
-  typedef HeapHashMap<PairWithWeakHandling, RefPtr<OffHeapInt>> Map;
+  typedef HeapHashMap<PairWithWeakHandling, scoped_refptr<OffHeapInt>> Map;
   typedef Map::iterator Iterator;
   ClearOutOldGarbage();
   OffHeapInt::destructor_calls_ = 0;
@@ -4949,7 +4949,7 @@
   map1->insert(
       PairWithWeakHandling(IntWrapper::Create(103), IntWrapper::Create(103)),
       OffHeapInt::Create(2002));  // This one gets zapped too.
-  RefPtr<OffHeapInt> dupe_int(OffHeapInt::Create(2003));
+  scoped_refptr<OffHeapInt> dupe_int(OffHeapInt::Create(2003));
   map1->insert(PairWithWeakHandling(living_int, living_int), dupe_int);
   map1->insert(
       PairWithWeakHandling(living_int, living_int),
@@ -4971,7 +4971,7 @@
 }
 
 TEST(HeapTest, MapWithCustomWeaknessHandling2) {
-  typedef HeapHashMap<RefPtr<OffHeapInt>, PairWithWeakHandling> Map;
+  typedef HeapHashMap<scoped_refptr<OffHeapInt>, PairWithWeakHandling> Map;
   typedef Map::iterator Iterator;
   ClearOutOldGarbage();
   OffHeapInt::destructor_calls_ = 0;
@@ -5033,7 +5033,7 @@
                PairWithWeakHandling(
                    IntWrapper::Create(103),
                    IntWrapper::Create(103)));  // This one gets zapped too.
-  RefPtr<OffHeapInt> dupe_int(OffHeapInt::Create(2003));
+  scoped_refptr<OffHeapInt> dupe_int(OffHeapInt::Create(2003));
   map1->insert(dupe_int, PairWithWeakHandling(living_int, living_int));
   // This one is identical to the previous and doesn't add anything.
   map1->insert(dupe_int, PairWithWeakHandling(living_int, living_int));
@@ -5138,7 +5138,7 @@
 
   Persistent<IntWrapper> living_int(IntWrapper::Create(42));
 
-  typedef RefPtr<OffHeapInt> Key;
+  typedef scoped_refptr<OffHeapInt> Key;
   typedef HeapHashMap<Key, WeakSet, WTF::DefaultHash<Key>::Hash,
                       HashTraits<Key>, EmptyClearingHashSetTraits>
       Map;
@@ -6089,7 +6089,7 @@
 
 class SimpleRefValue : public RefCounted<SimpleRefValue> {
  public:
-  static RefPtr<SimpleRefValue> Create(int i) {
+  static scoped_refptr<SimpleRefValue> Create(int i) {
     return WTF::AdoptRef(new SimpleRefValue(i));
   }
 
@@ -6112,7 +6112,7 @@
   int Value() const { return value_->Value(); }
 
  private:
-  RefPtr<SimpleRefValue> value_;
+  scoped_refptr<SimpleRefValue> value_;
 };
 
 }  // namespace blink
diff --git a/third_party/WebKit/Source/platform/image-decoders/ImageDecoder.cpp b/third_party/WebKit/Source/platform/image-decoders/ImageDecoder.cpp
index 178c1e3..02295e6 100644
--- a/third_party/WebKit/Source/platform/image-decoders/ImageDecoder.cpp
+++ b/third_party/WebKit/Source/platform/image-decoders/ImageDecoder.cpp
@@ -487,14 +487,6 @@
   return row_bytes_[i];
 }
 
-void ImageDecoder::SetEmbeddedColorProfile(const char* icc_data,
-                                           unsigned icc_length) {
-  sk_sp<SkColorSpace> color_space = SkColorSpace::MakeICC(icc_data, icc_length);
-  if (!color_space)
-    DLOG(ERROR) << "Failed to parse image ICC profile";
-  SetEmbeddedColorSpace(std::move(color_space));
-}
-
 void ImageDecoder::SetEmbeddedColorSpace(sk_sp<SkColorSpace> color_space) {
   DCHECK(!IgnoresColorSpace());
   DCHECK(!has_histogrammed_color_space_);
diff --git a/third_party/WebKit/Source/platform/image-decoders/ImageDecoder.h b/third_party/WebKit/Source/platform/image-decoders/ImageDecoder.h
index 55b1e96..c801a801 100644
--- a/third_party/WebKit/Source/platform/image-decoders/ImageDecoder.h
+++ b/third_party/WebKit/Source/platform/image-decoders/ImageDecoder.h
@@ -225,8 +225,6 @@
   // has been baked into the pixel values.
   bool HasEmbeddedColorSpace() const { return embedded_color_space_.get(); }
 
-  // Set the embedded color space directly or via ICC profile.
-  void SetEmbeddedColorProfile(const char* icc_data, unsigned icc_length);
   void SetEmbeddedColorSpace(sk_sp<SkColorSpace> src_space);
 
   // Transformation from embedded color space to target color space.
diff --git a/third_party/WebKit/Source/platform/image-decoders/jpeg/JPEGImageDecoder.cpp b/third_party/WebKit/Source/platform/image-decoders/jpeg/JPEGImageDecoder.cpp
index 69ed974..41d5c4d6 100644
--- a/third_party/WebKit/Source/platform/image-decoders/jpeg/JPEGImageDecoder.cpp
+++ b/third_party/WebKit/Source/platform/image-decoders/jpeg/JPEGImageDecoder.cpp
@@ -469,8 +469,30 @@
           JOCTET* profile = nullptr;
           unsigned profile_length = 0;
           if (read_icc_profile(Info(), &profile, &profile_length)) {
-            Decoder()->SetEmbeddedColorProfile(reinterpret_cast<char*>(profile),
-                                               profile_length);
+            sk_sp<SkColorSpace> color_space =
+                SkColorSpace::MakeICC(profile, profile_length);
+            if (color_space) {
+              const SkColorSpace::Type type = color_space->type();
+              switch (info_.jpeg_color_space) {
+                case JCS_CMYK:
+                case JCS_YCCK:
+                  if (type != SkColorSpace::kCMYK_Type)
+                    color_space = nullptr;
+                  break;
+                case JCS_GRAYSCALE:
+                  if (type != SkColorSpace::kGray_Type &&
+                      type != SkColorSpace::kRGB_Type)
+                    color_space = nullptr;
+                  break;
+                default:
+                  if (type != SkColorSpace::kRGB_Type)
+                    color_space = nullptr;
+                  break;
+              }
+              Decoder()->SetEmbeddedColorSpace(std::move(color_space));
+            } else {
+              DLOG(ERROR) << "Failed to parse image ICC profile";
+            }
             free(profile);
           }
           if (Decoder()->ColorTransform()) {
@@ -881,7 +903,7 @@
       SetPixel<colorSpace>(pixel, samples, x);
 
     SkColorSpaceXform* xform = reader->Decoder()->ColorTransform();
-    if (JCS_RGB == colorSpace && xform) {
+    if (xform) {
       ImageFrame::PixelData* row = buffer.GetAddr(0, y);
       xform->apply(XformColorFormat(), row, XformColorFormat(), row, width,
                    kOpaque_SkAlphaType);
diff --git a/third_party/WebKit/Source/platform/image-decoders/webp/WEBPImageDecoder.cpp b/third_party/WebKit/Source/platform/image-decoders/webp/WEBPImageDecoder.cpp
index 4dbd4af..0bb867fe 100644
--- a/third_party/WebKit/Source/platform/image-decoders/webp/WEBPImageDecoder.cpp
+++ b/third_party/WebKit/Source/platform/image-decoders/webp/WEBPImageDecoder.cpp
@@ -313,7 +313,14 @@
       reinterpret_cast<const char*>(chunk_iterator.chunk.bytes);
   size_t profile_size = chunk_iterator.chunk.size;
 
-  SetEmbeddedColorProfile(profile_data, profile_size);
+  sk_sp<SkColorSpace> color_space =
+      SkColorSpace::MakeICC(profile_data, profile_size);
+  if (color_space) {
+    if (color_space->type() == SkColorSpace::kRGB_Type)
+      SetEmbeddedColorSpace(std::move(color_space));
+  } else {
+    DLOG(ERROR) << "Failed to parse image ICC profile";
+  }
 
   WebPDemuxReleaseChunkIterator(&chunk_iterator);
 }
diff --git a/third_party/WebKit/Source/platform/loader/fetch/Resource.cpp b/third_party/WebKit/Source/platform/loader/fetch/Resource.cpp
index 93cf2180..273db5e 100644
--- a/third_party/WebKit/Source/platform/loader/fetch/Resource.cpp
+++ b/third_party/WebKit/Source/platform/loader/fetch/Resource.cpp
@@ -1163,13 +1163,15 @@
     return "Processing instruction";
   if (initiator_type_name == FetchInitiatorTypeNames::texttrack)
     return "Text track";
+  if (initiator_type_name == FetchInitiatorTypeNames::uacss)
+    return "User Agent CSS resource";
   if (initiator_type_name == FetchInitiatorTypeNames::xml)
     return "XML resource";
   if (initiator_type_name == FetchInitiatorTypeNames::xmlhttprequest)
     return "XMLHttpRequest";
 
   static_assert(
-      FetchInitiatorTypeNames::FetchInitiatorTypeNamesCount == 12,
+      FetchInitiatorTypeNames::FetchInitiatorTypeNamesCount == 13,
       "New FetchInitiatorTypeNames should be handled correctly here.");
 
   return "Resource";
diff --git a/third_party/WebKit/Source/platform/loader/fetch/ResourceLoader.cpp b/third_party/WebKit/Source/platform/loader/fetch/ResourceLoader.cpp
index 7bb30e43..8644427 100644
--- a/third_party/WebKit/Source/platform/loader/fetch/ResourceLoader.cpp
+++ b/third_party/WebKit/Source/platform/loader/fetch/ResourceLoader.cpp
@@ -166,6 +166,17 @@
 void ResourceLoader::SetDefersLoading(bool defers) {
   DCHECK(loader_);
   loader_->SetDefersLoading(defers);
+
+  // Inform the scheduler if the resource load is deferred / undeferred. Note
+  // duplicate calls don't matter.
+  WebFrameScheduler* scheduler = fetcher_->Context().GetFrameScheduler();
+  if (scheduler) {
+    if (defers) {
+      scheduler->DidStopLoading(resource_->Identifier());
+    } else {
+      scheduler->DidStartLoading(resource_->Identifier());
+    }
+  }
 }
 
 void ResourceLoader::DidChangePriority(ResourceLoadPriority load_priority,
diff --git a/third_party/WebKit/Source/platform/loader/fetch/ScriptFetchOptions.h b/third_party/WebKit/Source/platform/loader/fetch/ScriptFetchOptions.h
index 5890cbf6..5eaa2fc 100644
--- a/third_party/WebKit/Source/platform/loader/fetch/ScriptFetchOptions.h
+++ b/third_party/WebKit/Source/platform/loader/fetch/ScriptFetchOptions.h
@@ -5,6 +5,7 @@
 #ifndef ScriptFetchOptions_h
 #define ScriptFetchOptions_h
 
+#include "platform/loader/fetch/IntegrityMetadata.h"
 #include "platform/loader/fetch/ResourceLoaderOptions.h"
 #include "platform/wtf/text/WTFString.h"
 #include "public/platform/WebURLRequest.h"
@@ -25,14 +26,24 @@
         credentials_mode_(network::mojom::FetchCredentialsMode::kOmit) {}
 
   ScriptFetchOptions(const String& nonce,
+                     const IntegrityMetadataSet& integrity_metadata,
+                     const String& integrity_attribute,
                      ParserDisposition parser_state,
                      network::mojom::FetchCredentialsMode credentials_mode)
       : nonce_(nonce),
+        integrity_metadata_(integrity_metadata),
+        integrity_attribute_(integrity_attribute),
         parser_state_(parser_state),
         credentials_mode_(credentials_mode) {}
   ~ScriptFetchOptions() = default;
 
   const String& Nonce() const { return nonce_; }
+  const IntegrityMetadataSet& GetIntegrityMetadata() const {
+    return integrity_metadata_;
+  }
+  const String& GetIntegrityAttributeValue() const {
+    return integrity_attribute_;
+  }
   const ParserDisposition& ParserState() const { return parser_state_; }
   network::mojom::FetchCredentialsMode CredentialsMode() const {
     return credentials_mode_;
@@ -40,16 +51,17 @@
 
  private:
   // https://html.spec.whatwg.org/multipage/webappapis.html#concept-script-fetch-options-nonce
-  String nonce_;
+  const String nonce_;
 
   // https://html.spec.whatwg.org/multipage/webappapis.html#concept-script-fetch-options-integrity
-  // TODO(kouhei): const IntegrityMetadata integrity_metadata_;
+  const IntegrityMetadataSet integrity_metadata_;
+  const String integrity_attribute_;
 
   // https://html.spec.whatwg.org/multipage/webappapis.html#concept-script-fetch-options-parser
-  ParserDisposition parser_state_;
+  const ParserDisposition parser_state_;
 
   // https://html.spec.whatwg.org/multipage/webappapis.html#concept-script-fetch-options-credentials
-  network::mojom::FetchCredentialsMode credentials_mode_;
+  const network::mojom::FetchCredentialsMode credentials_mode_;
 };
 
 }  // namespace blink
diff --git a/third_party/WebKit/Source/platform/loader/fetch/fetch_initiator_type_names.json5 b/third_party/WebKit/Source/platform/loader/fetch/fetch_initiator_type_names.json5
index 6db167be..d2d2aac 100644
--- a/third_party/WebKit/Source/platform/loader/fetch/fetch_initiator_type_names.json5
+++ b/third_party/WebKit/Source/platform/loader/fetch/fetch_initiator_type_names.json5
@@ -14,6 +14,7 @@
     "ping",
     "processinginstruction",
     "texttrack",
+    "uacss",
     "violationreport",
     "xml",
     "xmlhttprequest",
diff --git a/third_party/WebKit/Source/platform/mac/ScrollAnimatorMac.h b/third_party/WebKit/Source/platform/mac/ScrollAnimatorMac.h
index 3001a9f8..1b612bb 100644
--- a/third_party/WebKit/Source/platform/mac/ScrollAnimatorMac.h
+++ b/third_party/WebKit/Source/platform/mac/ScrollAnimatorMac.h
@@ -135,7 +135,7 @@
 
   void SendContentAreaScrolledTask();
   TaskHandle send_content_area_scrolled_task_handle_;
-  RefPtr<WebTaskRunner> task_runner_;
+  scoped_refptr<WebTaskRunner> task_runner_;
   ScrollOffset content_area_scrolled_timer_scroll_delta_;
 
   ScrollResult UserScroll(ScrollGranularity,
diff --git a/third_party/WebKit/Source/platform/mac/ScrollAnimatorMac.mm b/third_party/WebKit/Source/platform/mac/ScrollAnimatorMac.mm
index bcb9ed61..7500183 100644
--- a/third_party/WebKit/Source/platform/mac/ScrollAnimatorMac.mm
+++ b/third_party/WebKit/Source/platform/mac/ScrollAnimatorMac.mm
@@ -337,7 +337,7 @@
   double start_time_;                       // In seconds.
   double duration_;                         // In seconds.
   BlinkScrollbarPartAnimation* animation_;  // Weak, owns this.
-  RefPtr<CubicBezierTimingFunction> timing_function_;
+  scoped_refptr<CubicBezierTimingFunction> timing_function_;
 };
 
 }  // namespace blink
diff --git a/third_party/WebKit/Source/platform/mhtml/ArchiveResource.cpp b/third_party/WebKit/Source/platform/mhtml/ArchiveResource.cpp
index 6c389f7d..378b3cc 100644
--- a/third_party/WebKit/Source/platform/mhtml/ArchiveResource.cpp
+++ b/third_party/WebKit/Source/platform/mhtml/ArchiveResource.cpp
@@ -30,7 +30,7 @@
 
 namespace blink {
 
-ArchiveResource::ArchiveResource(RefPtr<SharedBuffer> data,
+ArchiveResource::ArchiveResource(scoped_refptr<SharedBuffer> data,
                                  const KURL& url,
                                  const String& content_id,
                                  const AtomicString& mime_type,
@@ -45,7 +45,7 @@
 
 ArchiveResource::~ArchiveResource() {}
 
-ArchiveResource* ArchiveResource::Create(RefPtr<SharedBuffer> data,
+ArchiveResource* ArchiveResource::Create(scoped_refptr<SharedBuffer> data,
                                          const KURL& url,
                                          const String& content_id,
                                          const AtomicString& mime_type,
diff --git a/third_party/WebKit/Source/platform/mhtml/ArchiveResource.h b/third_party/WebKit/Source/platform/mhtml/ArchiveResource.h
index ccc4715..4b2ebea 100644
--- a/third_party/WebKit/Source/platform/mhtml/ArchiveResource.h
+++ b/third_party/WebKit/Source/platform/mhtml/ArchiveResource.h
@@ -40,7 +40,7 @@
 class PLATFORM_EXPORT ArchiveResource final
     : public GarbageCollectedFinalized<ArchiveResource> {
  public:
-  static ArchiveResource* Create(RefPtr<SharedBuffer>,
+  static ArchiveResource* Create(scoped_refptr<SharedBuffer>,
                                  const KURL&,
                                  const String& content_id,
                                  const AtomicString& mime_type,
@@ -57,7 +57,7 @@
   void Trace(blink::Visitor* visitor) {}
 
  private:
-  ArchiveResource(RefPtr<SharedBuffer>,
+  ArchiveResource(scoped_refptr<SharedBuffer>,
                   const KURL&,
                   const String& content_id,
                   const AtomicString& mime_type,
@@ -65,7 +65,7 @@
 
   KURL url_;
   String content_id_;
-  RefPtr<SharedBuffer> data_;
+  scoped_refptr<SharedBuffer> data_;
   AtomicString mime_type_;
   AtomicString text_encoding_;
 };
diff --git a/third_party/WebKit/Source/platform/mhtml/MHTMLArchive.cpp b/third_party/WebKit/Source/platform/mhtml/MHTMLArchive.cpp
index fde6a46..112e2b81 100644
--- a/third_party/WebKit/Source/platform/mhtml/MHTMLArchive.cpp
+++ b/third_party/WebKit/Source/platform/mhtml/MHTMLArchive.cpp
@@ -78,7 +78,7 @@
 MHTMLArchive::MHTMLArchive() {}
 
 MHTMLArchive* MHTMLArchive::Create(const KURL& url,
-                                   RefPtr<const SharedBuffer> data) {
+                                   scoped_refptr<const SharedBuffer> data) {
   // MHTML pages can only be loaded from local URLs, http/https URLs, and
   // content URLs(Android specific).  The latter is now allowed due to full
   // sandboxing enforcement on MHTML pages.
diff --git a/third_party/WebKit/Source/platform/mhtml/MHTMLArchive.h b/third_party/WebKit/Source/platform/mhtml/MHTMLArchive.h
index 66d794d..4774c92 100644
--- a/third_party/WebKit/Source/platform/mhtml/MHTMLArchive.h
+++ b/third_party/WebKit/Source/platform/mhtml/MHTMLArchive.h
@@ -52,7 +52,7 @@
 class PLATFORM_EXPORT MHTMLArchive final
     : public GarbageCollected<MHTMLArchive> {
  public:
-  static MHTMLArchive* Create(const KURL&, RefPtr<const SharedBuffer>);
+  static MHTMLArchive* Create(const KURL&, scoped_refptr<const SharedBuffer>);
 
   // Binary encoding results in smaller MHTML files but they might not work in
   // other browsers.
diff --git a/third_party/WebKit/Source/platform/mhtml/MHTMLParser.cpp b/third_party/WebKit/Source/platform/mhtml/MHTMLParser.cpp
index 8966f3b..fe33fa8 100644
--- a/third_party/WebKit/Source/platform/mhtml/MHTMLParser.cpp
+++ b/third_party/WebKit/Source/platform/mhtml/MHTMLParser.cpp
@@ -205,7 +205,7 @@
   return false;
 }
 
-MHTMLParser::MHTMLParser(RefPtr<const SharedBuffer> data)
+MHTMLParser::MHTMLParser(scoped_refptr<const SharedBuffer> data)
     : line_reader_(std::move(data), "\r\n") {}
 
 HeapVector<Member<ArchiveResource>> MHTMLParser::ParseArchive() {
@@ -356,7 +356,7 @@
       DVLOG(1) << "Invalid encoding for MHTML part.";
       return nullptr;
   }
-  RefPtr<SharedBuffer> content_buffer = SharedBuffer::AdoptVector(data);
+  scoped_refptr<SharedBuffer> content_buffer = SharedBuffer::AdoptVector(data);
   // FIXME: the URL in the MIME header could be relative, we should resolve it
   // if it is.  The specs mentions 5 ways to resolve a URL:
   // http://tools.ietf.org/html/rfc2557#section-5
diff --git a/third_party/WebKit/Source/platform/mhtml/MHTMLParser.h b/third_party/WebKit/Source/platform/mhtml/MHTMLParser.h
index 040e4c7..10d91bc 100644
--- a/third_party/WebKit/Source/platform/mhtml/MHTMLParser.h
+++ b/third_party/WebKit/Source/platform/mhtml/MHTMLParser.h
@@ -51,7 +51,7 @@
   STACK_ALLOCATED();
 
  public:
-  explicit MHTMLParser(RefPtr<const SharedBuffer>);
+  explicit MHTMLParser(scoped_refptr<const SharedBuffer>);
 
   HeapVector<Member<ArchiveResource>> ParseArchive();
 
diff --git a/third_party/WebKit/Source/platform/mojo/KURLSecurityOriginTest.cpp b/third_party/WebKit/Source/platform/mojo/KURLSecurityOriginTest.cpp
index ba6d825..ba066dd 100644
--- a/third_party/WebKit/Source/platform/mojo/KURLSecurityOriginTest.cpp
+++ b/third_party/WebKit/Source/platform/mojo/KURLSecurityOriginTest.cpp
@@ -22,7 +22,7 @@
     std::move(callback).Run(in);
   }
 
-  void BounceOrigin(const RefPtr<SecurityOrigin>& in,
+  void BounceOrigin(const scoped_refptr<SecurityOrigin>& in,
                     BounceOriginCallback callback) override {
     std::move(callback).Run(in);
   }
@@ -74,20 +74,20 @@
   }
 
   // Test basic Origin serialization.
-  RefPtr<SecurityOrigin> non_unique =
+  scoped_refptr<SecurityOrigin> non_unique =
       SecurityOrigin::Create("http", "www.google.com", 80);
-  RefPtr<SecurityOrigin> output;
+  scoped_refptr<SecurityOrigin> output;
   EXPECT_TRUE(proxy->BounceOrigin(non_unique, &output));
   EXPECT_TRUE(non_unique->IsSameSchemeHostPortAndSuborigin(output.get()));
   EXPECT_TRUE(non_unique->IsSameSchemeHostPort(output.get()));
   EXPECT_FALSE(output->HasSuborigin());
   EXPECT_FALSE(output->IsUnique());
 
-  RefPtr<SecurityOrigin> unique = SecurityOrigin::CreateUnique();
+  scoped_refptr<SecurityOrigin> unique = SecurityOrigin::CreateUnique();
   EXPECT_TRUE(proxy->BounceOrigin(unique, &output));
   EXPECT_TRUE(output->IsUnique());
 
-  RefPtr<SecurityOrigin> with_sub_origin =
+  scoped_refptr<SecurityOrigin> with_sub_origin =
       SecurityOrigin::Create("http", "www.google.com", 80, "suborigin");
   EXPECT_TRUE(proxy->BounceOrigin(with_sub_origin, &output));
   EXPECT_TRUE(with_sub_origin->IsSameSchemeHostPortAndSuborigin(output.get()));
diff --git a/third_party/WebKit/Source/platform/mojo/SecurityOrigin.typemap b/third_party/WebKit/Source/platform/mojo/SecurityOrigin.typemap
index 2be13c41..40fbdff 100644
--- a/third_party/WebKit/Source/platform/mojo/SecurityOrigin.typemap
+++ b/third_party/WebKit/Source/platform/mojo/SecurityOrigin.typemap
@@ -13,4 +13,4 @@
   "//mojo/public/cpp/bindings",
   "//url",
 ]
-type_mappings = [ "url.mojom.Origin=RefPtr<::blink::SecurityOrigin>" ]
+type_mappings = [ "url.mojom.Origin=scoped_refptr<::blink::SecurityOrigin>" ]
diff --git a/third_party/WebKit/Source/platform/mojo/SecurityOriginStructTraits.h b/third_party/WebKit/Source/platform/mojo/SecurityOriginStructTraits.h
index 88551da..b0843d5 100644
--- a/third_party/WebKit/Source/platform/mojo/SecurityOriginStructTraits.h
+++ b/third_party/WebKit/Source/platform/mojo/SecurityOriginStructTraits.h
@@ -13,25 +13,28 @@
 
 template <>
 struct StructTraits<url::mojom::blink::Origin::DataView,
-                    RefPtr<::blink::SecurityOrigin>> {
-  static WTF::String scheme(const RefPtr<::blink::SecurityOrigin>& origin) {
+                    scoped_refptr<::blink::SecurityOrigin>> {
+  static WTF::String scheme(
+      const scoped_refptr<::blink::SecurityOrigin>& origin) {
     return origin->Protocol();
   }
-  static WTF::String host(const RefPtr<::blink::SecurityOrigin>& origin) {
+  static WTF::String host(
+      const scoped_refptr<::blink::SecurityOrigin>& origin) {
     return origin->Host();
   }
-  static uint16_t port(const RefPtr<::blink::SecurityOrigin>& origin) {
+  static uint16_t port(const scoped_refptr<::blink::SecurityOrigin>& origin) {
     return origin->EffectivePort();
   }
-  static WTF::String suborigin(const RefPtr<::blink::SecurityOrigin>& origin) {
+  static WTF::String suborigin(
+      const scoped_refptr<::blink::SecurityOrigin>& origin) {
     WTF::String suborigin = origin->GetSuborigin()->GetName();
     return suborigin.IsNull() ? "" : suborigin;
   }
-  static bool unique(const RefPtr<::blink::SecurityOrigin>& origin) {
+  static bool unique(const scoped_refptr<::blink::SecurityOrigin>& origin) {
     return origin->IsUnique();
   }
   static bool Read(url::mojom::blink::Origin::DataView data,
-                   RefPtr<::blink::SecurityOrigin>* out) {
+                   scoped_refptr<::blink::SecurityOrigin>* out) {
     if (data.unique()) {
       *out = ::blink::SecurityOrigin::CreateUnique();
     } else {
diff --git a/third_party/WebKit/Source/platform/network/EncodedFormData.cpp b/third_party/WebKit/Source/platform/network/EncodedFormData.cpp
index b94d6f1..d13fcd00 100644
--- a/third_party/WebKit/Source/platform/network/EncodedFormData.cpp
+++ b/third_party/WebKit/Source/platform/network/EncodedFormData.cpp
@@ -45,34 +45,36 @@
 
 EncodedFormData::~EncodedFormData() {}
 
-RefPtr<EncodedFormData> EncodedFormData::Create() {
+scoped_refptr<EncodedFormData> EncodedFormData::Create() {
   return WTF::AdoptRef(new EncodedFormData);
 }
 
-RefPtr<EncodedFormData> EncodedFormData::Create(const void* data, size_t size) {
-  RefPtr<EncodedFormData> result = Create();
+scoped_refptr<EncodedFormData> EncodedFormData::Create(const void* data,
+                                                       size_t size) {
+  scoped_refptr<EncodedFormData> result = Create();
   result->AppendData(data, size);
   return result;
 }
 
-RefPtr<EncodedFormData> EncodedFormData::Create(const CString& string) {
-  RefPtr<EncodedFormData> result = Create();
+scoped_refptr<EncodedFormData> EncodedFormData::Create(const CString& string) {
+  scoped_refptr<EncodedFormData> result = Create();
   result->AppendData(string.data(), string.length());
   return result;
 }
 
-RefPtr<EncodedFormData> EncodedFormData::Create(const Vector<char>& vector) {
-  RefPtr<EncodedFormData> result = Create();
+scoped_refptr<EncodedFormData> EncodedFormData::Create(
+    const Vector<char>& vector) {
+  scoped_refptr<EncodedFormData> result = Create();
   result->AppendData(vector.data(), vector.size());
   return result;
 }
 
-RefPtr<EncodedFormData> EncodedFormData::Copy() const {
+scoped_refptr<EncodedFormData> EncodedFormData::Copy() const {
   return WTF::AdoptRef(new EncodedFormData(*this));
 }
 
-RefPtr<EncodedFormData> EncodedFormData::DeepCopy() const {
-  RefPtr<EncodedFormData> form_data(Create());
+scoped_refptr<EncodedFormData> EncodedFormData::DeepCopy() const {
+  scoped_refptr<EncodedFormData> form_data(Create());
 
   form_data->identifier_ = identifier_;
   form_data->boundary_ = boundary_;
@@ -127,8 +129,9 @@
       FormDataElement(filename, start, length, expected_modification_time));
 }
 
-void EncodedFormData::AppendBlob(const String& uuid,
-                                 RefPtr<BlobDataHandle> optional_handle) {
+void EncodedFormData::AppendBlob(
+    const String& uuid,
+    scoped_refptr<BlobDataHandle> optional_handle) {
   elements_.push_back(FormDataElement(uuid, std::move(optional_handle)));
 }
 
diff --git a/third_party/WebKit/Source/platform/network/EncodedFormData.h b/third_party/WebKit/Source/platform/network/EncodedFormData.h
index 9394a71..c0a060d 100644
--- a/third_party/WebKit/Source/platform/network/EncodedFormData.h
+++ b/third_party/WebKit/Source/platform/network/EncodedFormData.h
@@ -50,7 +50,7 @@
         file_length_(file_length),
         expected_file_modification_time_(expected_file_modification_time) {}
   explicit FormDataElement(const String& blob_uuid,
-                           RefPtr<BlobDataHandle> optional_handle)
+                           scoped_refptr<BlobDataHandle> optional_handle)
       : type_(kEncodedBlob),
         blob_uuid_(blob_uuid),
         optional_blob_data_handle_(std::move(optional_handle)) {}
@@ -70,7 +70,7 @@
   Vector<char> data_;
   String filename_;
   String blob_uuid_;
-  RefPtr<BlobDataHandle> optional_blob_data_handle_;
+  scoped_refptr<BlobDataHandle> optional_blob_data_handle_;
   KURL file_system_url_;
   long long file_start_;
   long long file_length_;
@@ -110,12 +110,12 @@
     kMultipartFormData  // for multipart/form-data
   };
 
-  static RefPtr<EncodedFormData> Create();
-  static RefPtr<EncodedFormData> Create(const void*, size_t);
-  static RefPtr<EncodedFormData> Create(const CString&);
-  static RefPtr<EncodedFormData> Create(const Vector<char>&);
-  RefPtr<EncodedFormData> Copy() const;
-  RefPtr<EncodedFormData> DeepCopy() const;
+  static scoped_refptr<EncodedFormData> Create();
+  static scoped_refptr<EncodedFormData> Create(const void*, size_t);
+  static scoped_refptr<EncodedFormData> Create(const CString&);
+  static scoped_refptr<EncodedFormData> Create(const Vector<char>&);
+  scoped_refptr<EncodedFormData> Copy() const;
+  scoped_refptr<EncodedFormData> DeepCopy() const;
   ~EncodedFormData();
 
   void AppendData(const void* data, size_t);
@@ -125,7 +125,7 @@
                        long long length,
                        double expected_modification_time);
   void AppendBlob(const String& blob_uuid,
-                  RefPtr<BlobDataHandle> optional_handle);
+                  scoped_refptr<BlobDataHandle> optional_handle);
   void AppendFileSystemURL(const KURL&);
   void AppendFileSystemURLRange(const KURL&,
                                 long long start,
diff --git a/third_party/WebKit/Source/platform/network/EncodedFormDataTest.cpp b/third_party/WebKit/Source/platform/network/EncodedFormDataTest.cpp
index 3b0e6a2..a469bdc0 100644
--- a/third_party/WebKit/Source/platform/network/EncodedFormDataTest.cpp
+++ b/third_party/WebKit/Source/platform/network/EncodedFormDataTest.cpp
@@ -34,7 +34,7 @@
 };
 
 TEST_F(EncodedFormDataTest, DeepCopy) {
-  RefPtr<EncodedFormData> original(EncodedFormData::Create());
+  scoped_refptr<EncodedFormData> original(EncodedFormData::Create());
   original->AppendData("Foo", 3);
   original->AppendFileRange("example.txt", 12345, 56789, 9999.0);
   original->AppendBlob("originalUUID", nullptr);
@@ -47,7 +47,7 @@
   original->SetBoundary(boundary_vector);
   original->SetContainsPasswordData(true);
 
-  RefPtr<EncodedFormData> copy = original->DeepCopy();
+  scoped_refptr<EncodedFormData> copy = original->DeepCopy();
 
   // Check that contents are copied (compare the copy with expected values).
   const Vector<FormDataElement>& original_elements = original->Elements();
diff --git a/third_party/WebKit/Source/platform/network/NetworkStateNotifier.cpp b/third_party/WebKit/Source/platform/network/NetworkStateNotifier.cpp
index 3eba504..c1c53ab7 100644
--- a/third_party/WebKit/Source/platform/network/NetworkStateNotifier.cpp
+++ b/third_party/WebKit/Source/platform/network/NetworkStateNotifier.cpp
@@ -77,7 +77,7 @@
     NetworkStateNotifier* notifier,
     NetworkStateNotifier::ObserverType type,
     NetworkStateNotifier::NetworkStateObserver* observer,
-    RefPtr<WebTaskRunner> task_runner)
+    scoped_refptr<WebTaskRunner> task_runner)
     : notifier_(notifier),
       type_(type),
       observer_(observer),
@@ -138,16 +138,18 @@
 }
 
 std::unique_ptr<NetworkStateNotifier::NetworkStateObserverHandle>
-NetworkStateNotifier::AddConnectionObserver(NetworkStateObserver* observer,
-                                            RefPtr<WebTaskRunner> task_runner) {
+NetworkStateNotifier::AddConnectionObserver(
+    NetworkStateObserver* observer,
+    scoped_refptr<WebTaskRunner> task_runner) {
   AddObserverToMap(connection_observers_, observer, task_runner);
   return std::make_unique<NetworkStateNotifier::NetworkStateObserverHandle>(
       this, ObserverType::kConnectionType, observer, task_runner);
 }
 
 std::unique_ptr<NetworkStateNotifier::NetworkStateObserverHandle>
-NetworkStateNotifier::AddOnLineObserver(NetworkStateObserver* observer,
-                                        RefPtr<WebTaskRunner> task_runner) {
+NetworkStateNotifier::AddOnLineObserver(
+    NetworkStateObserver* observer,
+    scoped_refptr<WebTaskRunner> task_runner) {
   AddObserverToMap(on_line_state_observers_, observer, task_runner);
   return std::make_unique<NetworkStateNotifier::NetworkStateObserverHandle>(
       this, ObserverType::kOnLineState, observer, task_runner);
@@ -204,7 +206,7 @@
   DCHECK(IsMainThread());
   MutexLocker locker(mutex_);
   for (const auto& entry : map) {
-    RefPtr<WebTaskRunner> task_runner = entry.key;
+    scoped_refptr<WebTaskRunner> task_runner = entry.key;
     task_runner->PostTask(
         BLINK_FROM_HERE,
         CrossThreadBind(&NetworkStateNotifier::NotifyObserversOnTaskRunner,
@@ -216,7 +218,7 @@
 void NetworkStateNotifier::NotifyObserversOnTaskRunner(
     ObserverListMap* map,
     ObserverType type,
-    RefPtr<WebTaskRunner> task_runner,
+    scoped_refptr<WebTaskRunner> task_runner,
     const NetworkState& state) {
   ObserverList* observer_list = LockAndFindObserverList(*map, task_runner);
 
@@ -253,9 +255,10 @@
     CollectZeroedObservers(*map, observer_list, std::move(task_runner));
 }
 
-void NetworkStateNotifier::AddObserverToMap(ObserverListMap& map,
-                                            NetworkStateObserver* observer,
-                                            RefPtr<WebTaskRunner> task_runner) {
+void NetworkStateNotifier::AddObserverToMap(
+    ObserverListMap& map,
+    NetworkStateObserver* observer,
+    scoped_refptr<WebTaskRunner> task_runner) {
   DCHECK(task_runner->RunsTasksInCurrentSequence());
   DCHECK(observer);
 
@@ -269,9 +272,10 @@
   result.stored_value->value->observers.push_back(observer);
 }
 
-void NetworkStateNotifier::RemoveObserver(ObserverType type,
-                                          NetworkStateObserver* observer,
-                                          RefPtr<WebTaskRunner> task_runner) {
+void NetworkStateNotifier::RemoveObserver(
+    ObserverType type,
+    NetworkStateObserver* observer,
+    scoped_refptr<WebTaskRunner> task_runner) {
   switch (type) {
     case ObserverType::kConnectionType:
       RemoveObserverFromMap(connection_observers_, observer,
@@ -287,7 +291,7 @@
 void NetworkStateNotifier::RemoveObserverFromMap(
     ObserverListMap& map,
     NetworkStateObserver* observer,
-    RefPtr<WebTaskRunner> task_runner) {
+    scoped_refptr<WebTaskRunner> task_runner) {
   DCHECK(task_runner->RunsTasksInCurrentSequence());
   DCHECK(observer);
 
@@ -309,7 +313,7 @@
 NetworkStateNotifier::ObserverList*
 NetworkStateNotifier::LockAndFindObserverList(
     ObserverListMap& map,
-    RefPtr<WebTaskRunner> task_runner) {
+    scoped_refptr<WebTaskRunner> task_runner) {
   MutexLocker locker(mutex_);
   ObserverListMap::iterator it = map.find(task_runner);
   return it == map.end() ? nullptr : it->value.get();
@@ -318,7 +322,7 @@
 void NetworkStateNotifier::CollectZeroedObservers(
     ObserverListMap& map,
     ObserverList* list,
-    RefPtr<WebTaskRunner> task_runner) {
+    scoped_refptr<WebTaskRunner> task_runner) {
   DCHECK(task_runner->RunsTasksInCurrentSequence());
   DCHECK(!list->iterating);
 
diff --git a/third_party/WebKit/Source/platform/network/NetworkStateNotifier.h b/third_party/WebKit/Source/platform/network/NetworkStateNotifier.h
index 9903d0d..944847b 100644
--- a/third_party/WebKit/Source/platform/network/NetworkStateNotifier.h
+++ b/third_party/WebKit/Source/platform/network/NetworkStateNotifier.h
@@ -88,14 +88,14 @@
     NetworkStateObserverHandle(NetworkStateNotifier*,
                                ObserverType,
                                NetworkStateObserver*,
-                               RefPtr<WebTaskRunner>);
+                               scoped_refptr<WebTaskRunner>);
     ~NetworkStateObserverHandle();
 
    private:
     NetworkStateNotifier* notifier_;
     ObserverType type_;
     NetworkStateObserver* observer_;
-    RefPtr<WebTaskRunner> task_runner_;
+    scoped_refptr<WebTaskRunner> task_runner_;
 
     DISALLOW_COPY_AND_ASSIGN(NetworkStateObserverHandle);
   };
@@ -217,10 +217,10 @@
   // and then added during notification.
   std::unique_ptr<NetworkStateObserverHandle> AddConnectionObserver(
       NetworkStateObserver*,
-      RefPtr<WebTaskRunner>);
+      scoped_refptr<WebTaskRunner>);
   std::unique_ptr<NetworkStateObserverHandle> AddOnLineObserver(
       NetworkStateObserver*,
-      RefPtr<WebTaskRunner>);
+      scoped_refptr<WebTaskRunner>);
 
   // Returns the randomization salt (weak and insecure) that should be used when
   // adding noise to the network quality metrics. This is known only to the
@@ -255,33 +255,33 @@
   // The ObserverListMap is cross-thread accessed, adding/removing Observers
   // running on a task runner.
   using ObserverListMap =
-      HashMap<RefPtr<WebTaskRunner>, std::unique_ptr<ObserverList>>;
+      HashMap<scoped_refptr<WebTaskRunner>, std::unique_ptr<ObserverList>>;
 
   void NotifyObservers(ObserverListMap&, ObserverType, const NetworkState&);
   void NotifyObserversOnTaskRunner(ObserverListMap*,
                                    ObserverType,
-                                   RefPtr<WebTaskRunner>,
+                                   scoped_refptr<WebTaskRunner>,
                                    const NetworkState&);
 
   void AddObserverToMap(ObserverListMap&,
                         NetworkStateObserver*,
-                        RefPtr<WebTaskRunner>);
+                        scoped_refptr<WebTaskRunner>);
   void RemoveObserver(ObserverType,
                       NetworkStateObserver*,
-                      RefPtr<WebTaskRunner>);
+                      scoped_refptr<WebTaskRunner>);
   void RemoveObserverFromMap(ObserverListMap&,
                              NetworkStateObserver*,
-                             RefPtr<WebTaskRunner>);
+                             scoped_refptr<WebTaskRunner>);
 
   ObserverList* LockAndFindObserverList(ObserverListMap&,
-                                        RefPtr<WebTaskRunner>);
+                                        scoped_refptr<WebTaskRunner>);
 
   // Removed observers are nulled out in the list in case the list is being
   // iterated over. Once done iterating, call this to clean up nulled
   // observers.
   void CollectZeroedObservers(ObserverListMap&,
                               ObserverList*,
-                              RefPtr<WebTaskRunner>);
+                              scoped_refptr<WebTaskRunner>);
 
   mutable Mutex mutex_;
   NetworkState state_;
diff --git a/third_party/WebKit/Source/platform/network/NetworkStateNotifierTest.cpp b/third_party/WebKit/Source/platform/network/NetworkStateNotifierTest.cpp
index 1d7f3bf47..db70659c 100644
--- a/third_party/WebKit/Source/platform/network/NetworkStateNotifierTest.cpp
+++ b/third_party/WebKit/Source/platform/network/NetworkStateNotifierTest.cpp
@@ -113,10 +113,11 @@
 
   void AddObserverOnNotification(NetworkStateNotifier* notifier,
                                  StateObserver* observer_to_add,
-                                 RefPtr<WebTaskRunner> task_runner) {
+                                 scoped_refptr<WebTaskRunner> task_runner) {
     closure_ = base::BindOnce(
         [](StateObserver* observer, NetworkStateNotifier* notifier,
-           StateObserver* observer_to_add, RefPtr<WebTaskRunner> task_runner) {
+           StateObserver* observer_to_add,
+           scoped_refptr<WebTaskRunner> task_runner) {
           observer->added_handle_ =
               notifier->AddConnectionObserver(observer_to_add, task_runner);
         },
@@ -221,8 +222,8 @@
                downlink_throughput_mbps;
   }
 
-  RefPtr<FakeWebTaskRunner> task_runner_;
-  RefPtr<FakeWebTaskRunner> task_runner2_;
+  scoped_refptr<FakeWebTaskRunner> task_runner_;
+  scoped_refptr<FakeWebTaskRunner> task_runner2_;
   NetworkStateNotifier notifier_;
 };
 
diff --git a/third_party/WebKit/Source/platform/network/NetworkUtils.cpp b/third_party/WebKit/Source/platform/network/NetworkUtils.cpp
index 6960388..84c7076 100644
--- a/third_party/WebKit/Source/platform/network/NetworkUtils.cpp
+++ b/third_party/WebKit/Source/platform/network/NetworkUtils.cpp
@@ -64,7 +64,7 @@
   return String(domain.data(), domain.length());
 }
 
-RefPtr<SharedBuffer> ParseDataURLAndPopulateResponse(
+scoped_refptr<SharedBuffer> ParseDataURLAndPopulateResponse(
     const KURL& url,
     ResourceResponse& response) {
   // The following code contains duplication of GetInfoFromDataURL() and
@@ -86,7 +86,7 @@
   if (!blink::IsSupportedMimeType(utf8_mime_type))
     return nullptr;
 
-  RefPtr<SharedBuffer> data =
+  scoped_refptr<SharedBuffer> data =
       SharedBuffer::Create(data_string.data(), data_string.size());
   response.SetHTTPStatusCode(200);
   response.SetHTTPStatusText("OK");
diff --git a/third_party/WebKit/Source/platform/network/NetworkUtils.h b/third_party/WebKit/Source/platform/network/NetworkUtils.h
index ec33256..e12876d 100644
--- a/third_party/WebKit/Source/platform/network/NetworkUtils.h
+++ b/third_party/WebKit/Source/platform/network/NetworkUtils.h
@@ -30,7 +30,7 @@
 
 // Returns the decoded data url as ResourceResponse and SharedBuffer
 // if url had a supported mimetype and parsing was successful.
-PLATFORM_EXPORT RefPtr<SharedBuffer> ParseDataURLAndPopulateResponse(
+PLATFORM_EXPORT scoped_refptr<SharedBuffer> ParseDataURLAndPopulateResponse(
     const KURL&,
     ResourceResponse&);
 
diff --git a/third_party/WebKit/Source/platform/network/WebSocketHandshakeRequest.h b/third_party/WebKit/Source/platform/network/WebSocketHandshakeRequest.h
index 83e3e98..44c8d4c 100644
--- a/third_party/WebKit/Source/platform/network/WebSocketHandshakeRequest.h
+++ b/third_party/WebKit/Source/platform/network/WebSocketHandshakeRequest.h
@@ -45,13 +45,13 @@
 class PLATFORM_EXPORT WebSocketHandshakeRequest final
     : public RefCounted<WebSocketHandshakeRequest> {
  public:
-  static RefPtr<WebSocketHandshakeRequest> Create(const KURL& url) {
+  static scoped_refptr<WebSocketHandshakeRequest> Create(const KURL& url) {
     return WTF::AdoptRef(new WebSocketHandshakeRequest(url));
   }
-  static RefPtr<WebSocketHandshakeRequest> Create() {
+  static scoped_refptr<WebSocketHandshakeRequest> Create() {
     return WTF::AdoptRef(new WebSocketHandshakeRequest);
   }
-  static RefPtr<WebSocketHandshakeRequest> Create(
+  static scoped_refptr<WebSocketHandshakeRequest> Create(
       const WebSocketHandshakeRequest& request) {
     return WTF::AdoptRef(new WebSocketHandshakeRequest(request));
   }
diff --git a/third_party/WebKit/Source/platform/plugins/PluginData.h b/third_party/WebKit/Source/platform/plugins/PluginData.h
index 5adede1..c2bdba5 100644
--- a/third_party/WebKit/Source/platform/plugins/PluginData.h
+++ b/third_party/WebKit/Source/platform/plugins/PluginData.h
@@ -1,3 +1,4 @@
+
 /*
     Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies)
 
@@ -109,7 +110,7 @@
 
   HeapVector<Member<PluginInfo>> plugins_;
   HeapVector<Member<MimeClassInfo>> mimes_;
-  RefPtr<SecurityOrigin> main_frame_origin_;
+  scoped_refptr<SecurityOrigin> main_frame_origin_;
 };
 
 }  // namespace blink
diff --git a/third_party/WebKit/Source/platform/runtime_enabled_features.json5 b/third_party/WebKit/Source/platform/runtime_enabled_features.json5
index ef70c01..802ea02 100644
--- a/third_party/WebKit/Source/platform/runtime_enabled_features.json5
+++ b/third_party/WebKit/Source/platform/runtime_enabled_features.json5
@@ -458,6 +458,9 @@
       status: "stable",
     },
     {
+      name: "GetMatchedCSSRules",
+    },
+    {
       name: "HeapCompaction",
       status: "stable",
     },
@@ -487,7 +490,6 @@
     },
     {
       name: "IncrementalShadowDOM",
-      status: "test",
     },
     {
       name: "InertAttribute",
diff --git a/third_party/WebKit/Source/platform/scheduler/renderer/renderer_scheduler_impl.cc b/third_party/WebKit/Source/platform/scheduler/renderer/renderer_scheduler_impl.cc
index 6a13ca4..e7ffd7a 100644
--- a/third_party/WebKit/Source/platform/scheduler/renderer/renderer_scheduler_impl.cc
+++ b/third_party/WebKit/Source/platform/scheduler/renderer/renderer_scheduler_impl.cc
@@ -1058,6 +1058,8 @@
                          &new_policy_duration);
   }
 
+  bool previously_stopped_when_backgrounded =
+      main_thread_only().stopped_when_backgrounded;
   bool newly_stopped = false;
   if (main_thread_only().renderer_backgrounded &&
       main_thread_only().stopping_when_backgrounded_enabled) {
@@ -1270,9 +1272,11 @@
 
   // TODO(skyostil): send these notifications after releasing the scheduler
   // lock.
-  if (new_policy.loading_queue_policy().is_stopped !=
-      main_thread_only().current_policy.loading_queue_policy().is_stopped) {
-    SetStoppedInBackground(new_policy.loading_queue_policy().is_stopped);
+  if (main_thread_only().stopping_when_backgrounded_enabled) {
+    if (main_thread_only().stopped_when_backgrounded !=
+        previously_stopped_when_backgrounded) {
+      SetStoppedInBackground(main_thread_only().stopped_when_backgrounded);
+    }
   }
 
   if (new_policy.should_disable_throttling() !=
@@ -2037,6 +2041,13 @@
   TRACE_COUNTER1(TRACE_DISABLED_BY_DEFAULT("renderer.scheduler"),
                  "estimated_queueing_time_for_window",
                  queueing_time.InMillisecondsF());
+
+  if (BlinkResourceCoordinatorBase::IsEnabled()) {
+    RendererResourceCoordinator::Get().SetProperty(
+        resource_coordinator::mojom::PropertyType::
+            kExpectedTaskQueueingDuration,
+        queueing_time.InMilliseconds());
+  }
 }
 
 void RendererSchedulerImpl::OnReportSplitExpectedQueueingTime(
diff --git a/third_party/WebKit/Source/platform/scheduler/renderer/web_frame_scheduler_impl.cc b/third_party/WebKit/Source/platform/scheduler/renderer/web_frame_scheduler_impl.cc
index 7549c73a..1e2d058a 100644
--- a/third_party/WebKit/Source/platform/scheduler/renderer/web_frame_scheduler_impl.cc
+++ b/third_party/WebKit/Source/platform/scheduler/renderer/web_frame_scheduler_impl.cc
@@ -528,7 +528,8 @@
 
 WebFrameScheduler::ThrottlingState
 WebFrameSchedulerImpl::CalculateThrottlingState() const {
-  if (page_stopped_) {
+  if (RuntimeEnabledFeatures::StopLoadingInBackgroundAndroidEnabled() &&
+      page_stopped_) {
     DCHECK(!page_visible_);
     return WebFrameScheduler::ThrottlingState::kStopped;
   }
diff --git a/third_party/WebKit/Source/platform/scroll/ScrollAnimatorTest.cpp b/third_party/WebKit/Source/platform/scroll/ScrollAnimatorTest.cpp
index 1983a1b..80d3281 100644
--- a/third_party/WebKit/Source/platform/scroll/ScrollAnimatorTest.cpp
+++ b/third_party/WebKit/Source/platform/scroll/ScrollAnimatorTest.cpp
@@ -118,7 +118,7 @@
     ScrollableArea::SetScrollOffset(offset, type, behavior);
   }
 
-  RefPtr<WebTaskRunner> GetTimerTaskRunner() const final {
+  scoped_refptr<WebTaskRunner> GetTimerTaskRunner() const final {
     return Platform::Current()->CurrentThread()->Scheduler()->TimerTaskRunner();
   }
 
diff --git a/third_party/WebKit/Source/platform/scroll/ScrollableArea.h b/third_party/WebKit/Source/platform/scroll/ScrollableArea.h
index 3159ebe..9316180 100644
--- a/third_party/WebKit/Source/platform/scroll/ScrollableArea.h
+++ b/third_party/WebKit/Source/platform/scroll/ScrollableArea.h
@@ -374,7 +374,7 @@
 
   // Returns the task runner to be used for scrollable area timers.
   // Ideally a frame-specific throttled one can be used.
-  virtual RefPtr<WebTaskRunner> GetTimerTaskRunner() const = 0;
+  virtual scoped_refptr<WebTaskRunner> GetTimerTaskRunner() const = 0;
 
   // Callback for compositor-side scrolling.
   virtual void DidScroll(const gfx::ScrollOffset&);
diff --git a/third_party/WebKit/Source/platform/scroll/ScrollbarTestSuite.h b/third_party/WebKit/Source/platform/scroll/ScrollbarTestSuite.h
index d9ab46d..e62a9441 100644
--- a/third_party/WebKit/Source/platform/scroll/ScrollbarTestSuite.h
+++ b/third_party/WebKit/Source/platform/scroll/ScrollbarTestSuite.h
@@ -95,7 +95,7 @@
     ScrollableArea::SetScrollOrigin(origin);
   }
 
-  RefPtr<WebTaskRunner> GetTimerTaskRunner() const final {
+  scoped_refptr<WebTaskRunner> GetTimerTaskRunner() const final {
     return Platform::Current()->CurrentThread()->Scheduler()->TimerTaskRunner();
   }
 
diff --git a/third_party/WebKit/Source/platform/scroll/ScrollbarThemeMac.h b/third_party/WebKit/Source/platform/scroll/ScrollbarThemeMac.h
index b0d0f580..aaa59440d 100644
--- a/third_party/WebKit/Source/platform/scroll/ScrollbarThemeMac.h
+++ b/third_party/WebKit/Source/platform/scroll/ScrollbarThemeMac.h
@@ -112,7 +112,7 @@
 
   int TickmarkBorderWidth() override { return 1; }
 
-  RefPtr<Pattern> overhang_pattern_;
+  scoped_refptr<Pattern> overhang_pattern_;
 };
 }
 
diff --git a/third_party/WebKit/Source/platform/speech/PlatformSpeechSynthesisUtterance.h b/third_party/WebKit/Source/platform/speech/PlatformSpeechSynthesisUtterance.h
index bc28abc..a5c4b5d0 100644
--- a/third_party/WebKit/Source/platform/speech/PlatformSpeechSynthesisUtterance.h
+++ b/third_party/WebKit/Source/platform/speech/PlatformSpeechSynthesisUtterance.h
@@ -82,7 +82,7 @@
   Member<PlatformSpeechSynthesisUtteranceClient> client_;
   String text_;
   String lang_;
-  RefPtr<PlatformSpeechSynthesisVoice> voice_;
+  scoped_refptr<PlatformSpeechSynthesisVoice> voice_;
   float volume_;
   float rate_;
   float pitch_;
diff --git a/third_party/WebKit/Source/platform/speech/PlatformSpeechSynthesisVoice.cpp b/third_party/WebKit/Source/platform/speech/PlatformSpeechSynthesisVoice.cpp
index 677b23e..59492f9 100644
--- a/third_party/WebKit/Source/platform/speech/PlatformSpeechSynthesisVoice.cpp
+++ b/third_party/WebKit/Source/platform/speech/PlatformSpeechSynthesisVoice.cpp
@@ -27,17 +27,18 @@
 
 namespace blink {
 
-RefPtr<PlatformSpeechSynthesisVoice> PlatformSpeechSynthesisVoice::Create(
-    const String& voice_uri,
-    const String& name,
-    const String& lang,
-    bool local_service,
-    bool is_default) {
+scoped_refptr<PlatformSpeechSynthesisVoice>
+PlatformSpeechSynthesisVoice::Create(const String& voice_uri,
+                                     const String& name,
+                                     const String& lang,
+                                     bool local_service,
+                                     bool is_default) {
   return WTF::AdoptRef(new PlatformSpeechSynthesisVoice(
       voice_uri, name, lang, local_service, is_default));
 }
 
-RefPtr<PlatformSpeechSynthesisVoice> PlatformSpeechSynthesisVoice::Create() {
+scoped_refptr<PlatformSpeechSynthesisVoice>
+PlatformSpeechSynthesisVoice::Create() {
   return WTF::AdoptRef(new PlatformSpeechSynthesisVoice);
 }
 
diff --git a/third_party/WebKit/Source/platform/speech/PlatformSpeechSynthesisVoice.h b/third_party/WebKit/Source/platform/speech/PlatformSpeechSynthesisVoice.h
index 1813c321..ce27c5a 100644
--- a/third_party/WebKit/Source/platform/speech/PlatformSpeechSynthesisVoice.h
+++ b/third_party/WebKit/Source/platform/speech/PlatformSpeechSynthesisVoice.h
@@ -36,12 +36,13 @@
 class PLATFORM_EXPORT PlatformSpeechSynthesisVoice final
     : public RefCounted<PlatformSpeechSynthesisVoice> {
  public:
-  static RefPtr<PlatformSpeechSynthesisVoice> Create(const String& voice_uri,
-                                                     const String& name,
-                                                     const String& lang,
-                                                     bool local_service,
-                                                     bool is_default);
-  static RefPtr<PlatformSpeechSynthesisVoice> Create();
+  static scoped_refptr<PlatformSpeechSynthesisVoice> Create(
+      const String& voice_uri,
+      const String& name,
+      const String& lang,
+      bool local_service,
+      bool is_default);
+  static scoped_refptr<PlatformSpeechSynthesisVoice> Create();
 
   const String& VoiceURI() const { return voice_uri_; }
   void SetVoiceURI(const String& voice_uri) { voice_uri_ = voice_uri; }
diff --git a/third_party/WebKit/Source/platform/speech/PlatformSpeechSynthesizer.cpp b/third_party/WebKit/Source/platform/speech/PlatformSpeechSynthesizer.cpp
index 10e6a38d..a3f8907 100644
--- a/third_party/WebKit/Source/platform/speech/PlatformSpeechSynthesizer.cpp
+++ b/third_party/WebKit/Source/platform/speech/PlatformSpeechSynthesizer.cpp
@@ -76,7 +76,7 @@
 }
 
 void PlatformSpeechSynthesizer::SetVoiceList(
-    Vector<RefPtr<PlatformSpeechSynthesisVoice>>& voices) {
+    Vector<scoped_refptr<PlatformSpeechSynthesisVoice>>& voices) {
   voice_list_ = voices;
 }
 
diff --git a/third_party/WebKit/Source/platform/speech/PlatformSpeechSynthesizer.h b/third_party/WebKit/Source/platform/speech/PlatformSpeechSynthesizer.h
index 207227f..03ac0bd3 100644
--- a/third_party/WebKit/Source/platform/speech/PlatformSpeechSynthesizer.h
+++ b/third_party/WebKit/Source/platform/speech/PlatformSpeechSynthesizer.h
@@ -66,7 +66,7 @@
 
   virtual ~PlatformSpeechSynthesizer();
 
-  const Vector<RefPtr<PlatformSpeechSynthesisVoice>>& VoiceList() const {
+  const Vector<scoped_refptr<PlatformSpeechSynthesisVoice>>& VoiceList() const {
     return voice_list_;
   }
   virtual void Speak(PlatformSpeechSynthesisUtterance*);
@@ -78,7 +78,7 @@
     return speech_synthesizer_client_;
   }
 
-  void SetVoiceList(Vector<RefPtr<PlatformSpeechSynthesisVoice>>&);
+  void SetVoiceList(Vector<scoped_refptr<PlatformSpeechSynthesisVoice>>&);
 
   // Eager finalization is required to promptly release the owned
   // WebSpeechSynthesizer.
@@ -98,7 +98,7 @@
 
   virtual void InitializeVoiceList();
 
-  Vector<RefPtr<PlatformSpeechSynthesisVoice>> voice_list_;
+  Vector<scoped_refptr<PlatformSpeechSynthesisVoice>> voice_list_;
 
  private:
   Member<PlatformSpeechSynthesizerClient> speech_synthesizer_client_;
diff --git a/third_party/WebKit/Source/platform/testing/ArenaTestHelpers.h b/third_party/WebKit/Source/platform/testing/ArenaTestHelpers.h
index e2da983..1f8f8f25 100644
--- a/third_party/WebKit/Source/platform/testing/ArenaTestHelpers.h
+++ b/third_party/WebKit/Source/platform/testing/ArenaTestHelpers.h
@@ -39,7 +39,7 @@
 // been allocated.
 class TrackedAllocator final : public PODArena::FastMallocAllocator {
  public:
-  static RefPtr<TrackedAllocator> Create() {
+  static scoped_refptr<TrackedAllocator> Create() {
     return WTF::AdoptRef(new TrackedAllocator);
   }
 
diff --git a/third_party/WebKit/Source/platform/testing/FontTestHelpers.cpp b/third_party/WebKit/Source/platform/testing/FontTestHelpers.cpp
index 2148824..762dde0f 100644
--- a/third_party/WebKit/Source/platform/testing/FontTestHelpers.cpp
+++ b/third_party/WebKit/Source/platform/testing/FontTestHelpers.cpp
@@ -19,7 +19,7 @@
 class TestFontSelector : public FontSelector {
  public:
   static TestFontSelector* Create(const String& path) {
-    RefPtr<SharedBuffer> font_buffer = testing::ReadFromFile(path);
+    scoped_refptr<SharedBuffer> font_buffer = testing::ReadFromFile(path);
     String ots_parse_message;
     return new TestFontSelector(
         FontCustomPlatformData::Create(font_buffer.get(), ots_parse_message));
@@ -27,8 +27,9 @@
 
   ~TestFontSelector() override {}
 
-  RefPtr<FontData> GetFontData(const FontDescription& font_description,
-                               const AtomicString& family_name) override {
+  scoped_refptr<FontData> GetFontData(
+      const FontDescription& font_description,
+      const AtomicString& family_name) override {
     FontSelectionCapabilities normal_capabilities(
         {NormalWidthValue(), NormalWidthValue()},
         {NormalSlopeValue(), NormalSlopeValue()},
@@ -58,12 +59,12 @@
   void UnregisterForInvalidationCallbacks(FontSelectorClient*) override {}
 
  private:
-  TestFontSelector(RefPtr<FontCustomPlatformData> custom_platform_data)
+  TestFontSelector(scoped_refptr<FontCustomPlatformData> custom_platform_data)
       : custom_platform_data_(std::move(custom_platform_data)) {
     DCHECK(custom_platform_data_);
   }
 
-  RefPtr<FontCustomPlatformData> custom_platform_data_;
+  scoped_refptr<FontCustomPlatformData> custom_platform_data_;
 };
 
 }  // namespace
diff --git a/third_party/WebKit/Source/platform/testing/ImageDecodeBench.cpp b/third_party/WebKit/Source/platform/testing/ImageDecodeBench.cpp
index dfe0531d25b..2218ba2 100644
--- a/third_party/WebKit/Source/platform/testing/ImageDecodeBench.cpp
+++ b/third_party/WebKit/Source/platform/testing/ImageDecodeBench.cpp
@@ -182,7 +182,7 @@
 
 #endif
 
-RefPtr<SharedBuffer> ReadFile(const char* file_name) {
+scoped_refptr<SharedBuffer> ReadFile(const char* file_name) {
   FILE* fp = fopen(file_name, "rb");
   if (!fp) {
     fprintf(stderr, "Can't open file %s\n", file_name);
@@ -226,7 +226,7 @@
     return !decoder->Failed();
   }
 
-  RefPtr<SharedBuffer> packet_data = SharedBuffer::Create();
+  scoped_refptr<SharedBuffer> packet_data = SharedBuffer::Create();
   size_t position = 0;
   size_t next_frame_to_decode = 0;
   while (true) {
@@ -314,7 +314,7 @@
   // Read entire file content to data, and consolidate the SharedBuffer data
   // segments into one, contiguous block of memory.
 
-  RefPtr<SharedBuffer> data = ReadFile(argv[1]);
+  scoped_refptr<SharedBuffer> data = ReadFile(argv[1]);
   if (!data.get() || !data->size()) {
     fprintf(stderr, "Error reading image data from [%s]\n", argv[1]);
     exit(2);
diff --git a/third_party/WebKit/Source/platform/testing/PaintPropertyTestHelpers.h b/third_party/WebKit/Source/platform/testing/PaintPropertyTestHelpers.h
index 89dc6e5..1e4640c0 100644
--- a/third_party/WebKit/Source/platform/testing/PaintPropertyTestHelpers.h
+++ b/third_party/WebKit/Source/platform/testing/PaintPropertyTestHelpers.h
@@ -13,12 +13,12 @@
 namespace blink {
 namespace testing {
 
-static inline RefPtr<EffectPaintPropertyNode> CreateOpacityOnlyEffect(
-    RefPtr<const EffectPaintPropertyNode> parent,
+static inline scoped_refptr<EffectPaintPropertyNode> CreateOpacityOnlyEffect(
+    scoped_refptr<const EffectPaintPropertyNode> parent,
     float opacity) {
-  RefPtr<TransformPaintPropertyNode> local_transform_space =
+  scoped_refptr<TransformPaintPropertyNode> local_transform_space =
       const_cast<TransformPaintPropertyNode*>(parent->LocalTransformSpace());
-  RefPtr<ClipPaintPropertyNode> output_clip =
+  scoped_refptr<ClipPaintPropertyNode> output_clip =
       const_cast<ClipPaintPropertyNode*>(parent->OutputClip());
   return EffectPaintPropertyNode::Create(
       std::move(parent), std::move(local_transform_space),
diff --git a/third_party/WebKit/Source/platform/testing/TestPaintArtifact.cpp b/third_party/WebKit/Source/platform/testing/TestPaintArtifact.cpp
index de2cf1a6..f93f859 100644
--- a/third_party/WebKit/Source/platform/testing/TestPaintArtifact.cpp
+++ b/third_party/WebKit/Source/platform/testing/TestPaintArtifact.cpp
@@ -44,17 +44,17 @@
 TestPaintArtifact::~TestPaintArtifact() {}
 
 TestPaintArtifact& TestPaintArtifact::Chunk(
-    RefPtr<const TransformPaintPropertyNode> transform,
-    RefPtr<const ClipPaintPropertyNode> clip,
-    RefPtr<const EffectPaintPropertyNode> effect) {
+    scoped_refptr<const TransformPaintPropertyNode> transform,
+    scoped_refptr<const ClipPaintPropertyNode> clip,
+    scoped_refptr<const EffectPaintPropertyNode> effect) {
   return Chunk(NewClient(), transform, clip, effect);
 }
 
 TestPaintArtifact& TestPaintArtifact::Chunk(
     DisplayItemClient& client,
-    RefPtr<const TransformPaintPropertyNode> transform,
-    RefPtr<const ClipPaintPropertyNode> clip,
-    RefPtr<const EffectPaintPropertyNode> effect) {
+    scoped_refptr<const TransformPaintPropertyNode> transform,
+    scoped_refptr<const ClipPaintPropertyNode> clip,
+    scoped_refptr<const EffectPaintPropertyNode> effect) {
   PropertyTreeState property_tree_state(transform.get(), clip.get(),
                                         effect.get());
   PaintChunkProperties properties(property_tree_state);
@@ -114,13 +114,13 @@
 }
 
 TestPaintArtifact& TestPaintArtifact::ScrollHitTest(
-    RefPtr<const TransformPaintPropertyNode> scroll_offset) {
+    scoped_refptr<const TransformPaintPropertyNode> scroll_offset) {
   return ScrollHitTest(NewClient(), scroll_offset);
 }
 
 TestPaintArtifact& TestPaintArtifact::ScrollHitTest(
     DisplayItemClient& client,
-    RefPtr<const TransformPaintPropertyNode> scroll_offset) {
+    scoped_refptr<const TransformPaintPropertyNode> scroll_offset) {
   display_item_list_.AllocateAndConstruct<ScrollHitTestDisplayItem>(
       client, DisplayItem::kScrollHitTest, std::move(scroll_offset));
   return *this;
diff --git a/third_party/WebKit/Source/platform/testing/TestPaintArtifact.h b/third_party/WebKit/Source/platform/testing/TestPaintArtifact.h
index a70d058..ec339a50 100644
--- a/third_party/WebKit/Source/platform/testing/TestPaintArtifact.h
+++ b/third_party/WebKit/Source/platform/testing/TestPaintArtifact.h
@@ -47,24 +47,24 @@
   ~TestPaintArtifact();
 
   // Add to the artifact.
-  TestPaintArtifact& Chunk(RefPtr<const TransformPaintPropertyNode>,
-                           RefPtr<const ClipPaintPropertyNode>,
-                           RefPtr<const EffectPaintPropertyNode>);
+  TestPaintArtifact& Chunk(scoped_refptr<const TransformPaintPropertyNode>,
+                           scoped_refptr<const ClipPaintPropertyNode>,
+                           scoped_refptr<const EffectPaintPropertyNode>);
   TestPaintArtifact& Chunk(const PaintChunkProperties&);
   TestPaintArtifact& RectDrawing(const FloatRect& bounds, Color);
   TestPaintArtifact& ForeignLayer(const FloatPoint&,
                                   const IntSize&,
                                   scoped_refptr<cc::Layer>);
   TestPaintArtifact& ScrollHitTest(
-      RefPtr<const TransformPaintPropertyNode> scroll_offset);
+      scoped_refptr<const TransformPaintPropertyNode> scroll_offset);
   TestPaintArtifact& KnownToBeOpaque();
 
   // Add to the artifact, with specified display item client. These are used
   // to test incremental paint artifact updates.
   TestPaintArtifact& Chunk(DisplayItemClient&,
-                           RefPtr<const TransformPaintPropertyNode>,
-                           RefPtr<const ClipPaintPropertyNode>,
-                           RefPtr<const EffectPaintPropertyNode>);
+                           scoped_refptr<const TransformPaintPropertyNode>,
+                           scoped_refptr<const ClipPaintPropertyNode>,
+                           scoped_refptr<const EffectPaintPropertyNode>);
   TestPaintArtifact& Chunk(DisplayItemClient&, const PaintChunkProperties&);
   TestPaintArtifact& RectDrawing(DisplayItemClient&,
                                  const FloatRect& bounds,
@@ -75,7 +75,7 @@
                                   scoped_refptr<cc::Layer>);
   TestPaintArtifact& ScrollHitTest(
       DisplayItemClient&,
-      RefPtr<const TransformPaintPropertyNode> scroll_offset);
+      scoped_refptr<const TransformPaintPropertyNode> scroll_offset);
 
   // Can't add more things once this is called.
   const PaintArtifact& Build();
diff --git a/third_party/WebKit/Source/platform/testing/UnitTestHelpers.cpp b/third_party/WebKit/Source/platform/testing/UnitTestHelpers.cpp
index 1882564..7e7a321 100644
--- a/third_party/WebKit/Source/platform/testing/UnitTestHelpers.cpp
+++ b/third_party/WebKit/Source/platform/testing/UnitTestHelpers.cpp
@@ -106,7 +106,7 @@
           .Append(WebStringToFilePath(relative_path)));
 }
 
-RefPtr<SharedBuffer> ReadFromFile(const String& path) {
+scoped_refptr<SharedBuffer> ReadFromFile(const String& path) {
   base::FilePath file_path = blink::WebStringToFilePath(path);
   std::string buffer;
   base::ReadFileToString(file_path, &buffer);
diff --git a/third_party/WebKit/Source/platform/testing/UnitTestHelpers.h b/third_party/WebKit/Source/platform/testing/UnitTestHelpers.h
index f96d6398..407a396 100644
--- a/third_party/WebKit/Source/platform/testing/UnitTestHelpers.h
+++ b/third_party/WebKit/Source/platform/testing/UnitTestHelpers.h
@@ -66,7 +66,7 @@
 // specified.
 String PlatformTestDataPath(const String& relative_path = String());
 
-RefPtr<SharedBuffer> ReadFromFile(const String& path);
+scoped_refptr<SharedBuffer> ReadFromFile(const String& path);
 
 }  // namespace testing
 }  // namespace blink
diff --git a/third_party/WebKit/Source/platform/text/BidiContext.cpp b/third_party/WebKit/Source/platform/text/BidiContext.cpp
index c796fc9..f115c89 100644
--- a/third_party/WebKit/Source/platform/text/BidiContext.cpp
+++ b/third_party/WebKit/Source/platform/text/BidiContext.cpp
@@ -38,7 +38,7 @@
 static_assert(sizeof(BidiContext) == sizeof(SameSizeAsBidiContext),
               "BidiContext should stay small");
 
-inline RefPtr<BidiContext> BidiContext::CreateUncached(
+inline scoped_refptr<BidiContext> BidiContext::CreateUncached(
     unsigned char level,
     CharDirection direction,
     bool override,
@@ -48,11 +48,11 @@
       new BidiContext(level, direction, override, source, parent));
 }
 
-RefPtr<BidiContext> BidiContext::Create(unsigned char level,
-                                        CharDirection direction,
-                                        bool override,
-                                        BidiEmbeddingSource source,
-                                        BidiContext* parent) {
+scoped_refptr<BidiContext> BidiContext::Create(unsigned char level,
+                                               CharDirection direction,
+                                               bool override,
+                                               BidiEmbeddingSource source,
+                                               BidiContext* parent) {
   DCHECK_EQ(direction, (level % 2 ? kRightToLeft : kLeftToRight));
 
   if (parent || level >= 2)
@@ -86,7 +86,7 @@
   return rtl_override_context;
 }
 
-static inline RefPtr<BidiContext> CopyContextAndRebaselineLevel(
+static inline scoped_refptr<BidiContext> CopyContextAndRebaselineLevel(
     BidiContext* context,
     BidiContext* parent) {
   DCHECK(context);
@@ -103,7 +103,8 @@
 // The BidiContext stack must be immutable -- they're re-used for re-layout
 // after DOM modification/editing -- so we copy all the non-unicode contexts,
 // and recalculate their levels.
-RefPtr<BidiContext> BidiContext::CopyStackRemovingUnicodeEmbeddingContexts() {
+scoped_refptr<BidiContext>
+BidiContext::CopyStackRemovingUnicodeEmbeddingContexts() {
   Vector<BidiContext*, 64> contexts;
   for (BidiContext* iter = this; iter; iter = iter->Parent()) {
     if (iter->Source() != kFromUnicode)
@@ -111,7 +112,7 @@
   }
   DCHECK(contexts.size());
 
-  RefPtr<BidiContext> top_context =
+  scoped_refptr<BidiContext> top_context =
       CopyContextAndRebaselineLevel(contexts.back(), nullptr);
   for (int i = contexts.size() - 1; i > 0; --i) {
     top_context =
diff --git a/third_party/WebKit/Source/platform/text/BidiContext.h b/third_party/WebKit/Source/platform/text/BidiContext.h
index 583e23be..3bfa5aa58 100644
--- a/third_party/WebKit/Source/platform/text/BidiContext.h
+++ b/third_party/WebKit/Source/platform/text/BidiContext.h
@@ -36,11 +36,12 @@
 // Used to keep track of explicit embeddings.
 class PLATFORM_EXPORT BidiContext : public ThreadSafeRefCounted<BidiContext> {
  public:
-  static RefPtr<BidiContext> Create(unsigned char level,
-                                    WTF::Unicode::CharDirection,
-                                    bool override = false,
-                                    BidiEmbeddingSource = kFromStyleOrDOM,
-                                    BidiContext* parent = 0);
+  static scoped_refptr<BidiContext> Create(
+      unsigned char level,
+      WTF::Unicode::CharDirection,
+      bool override = false,
+      BidiEmbeddingSource = kFromStyleOrDOM,
+      BidiContext* parent = 0);
 
   BidiContext* Parent() const { return parent_.get(); }
   unsigned char Level() const { return level_; }
@@ -52,7 +53,7 @@
     return static_cast<BidiEmbeddingSource>(source_);
   }
 
-  RefPtr<BidiContext> CopyStackRemovingUnicodeEmbeddingContexts();
+  scoped_refptr<BidiContext> CopyStackRemovingUnicodeEmbeddingContexts();
 
   // http://www.unicode.org/reports/tr9/#Modifications
   // 6.3 raised the limit from 61 to 125.
@@ -73,11 +74,11 @@
     DCHECK(level <= kMaxLevel);
   }
 
-  static RefPtr<BidiContext> CreateUncached(unsigned char level,
-                                            WTF::Unicode::CharDirection,
-                                            bool override,
-                                            BidiEmbeddingSource,
-                                            BidiContext* parent);
+  static scoped_refptr<BidiContext> CreateUncached(unsigned char level,
+                                                   WTF::Unicode::CharDirection,
+                                                   bool override,
+                                                   BidiEmbeddingSource,
+                                                   BidiContext* parent);
 
   // The maximium bidi level is 125:
   // http://unicode.org/reports/tr9/#Explicit_Levels_and_Directions
@@ -85,7 +86,7 @@
   unsigned direction_ : 5;  // Direction
   unsigned override_ : 1;
   unsigned source_ : 1;  // BidiEmbeddingSource
-  RefPtr<BidiContext> parent_;
+  scoped_refptr<BidiContext> parent_;
 };
 
 inline unsigned char NextGreaterOddLevel(unsigned char level) {
diff --git a/third_party/WebKit/Source/platform/text/BidiResolver.h b/third_party/WebKit/Source/platform/text/BidiResolver.h
index 3ae9aa0c..1e8bd9c 100644
--- a/third_party/WebKit/Source/platform/text/BidiResolver.h
+++ b/third_party/WebKit/Source/platform/text/BidiResolver.h
@@ -142,7 +142,7 @@
   BidiStatus(WTF::Unicode::CharDirection eor_dir,
              WTF::Unicode::CharDirection last_strong_dir,
              WTF::Unicode::CharDirection last_dir,
-             RefPtr<BidiContext> bidi_context)
+             scoped_refptr<BidiContext> bidi_context)
       : eor(eor_dir),
         last_strong(last_strong_dir),
         last(last_dir),
@@ -161,7 +161,7 @@
       level = NextGreaterEvenLevel(level);
       direction = WTF::Unicode::kLeftToRight;
     }
-    RefPtr<BidiContext> context =
+    scoped_refptr<BidiContext> context =
         BidiContext::Create(level, direction, is_override, kFromStyleOrDOM);
 
     // This copies BidiStatus and may churn the ref on BidiContext.
@@ -172,7 +172,7 @@
   WTF::Unicode::CharDirection eor;
   WTF::Unicode::CharDirection last_strong;
   WTF::Unicode::CharDirection last;
-  RefPtr<BidiContext> context;
+  scoped_refptr<BidiContext> context;
 };
 
 class BidiEmbedding final {
@@ -240,7 +240,9 @@
   }
 
   BidiContext* Context() const { return status_.context.get(); }
-  void SetContext(RefPtr<BidiContext> c) { status_.context = std::move(c); }
+  void SetContext(scoped_refptr<BidiContext> c) {
+    status_.context = std::move(c);
+  }
 
   void SetLastDir(WTF::Unicode::CharDirection last_dir) {
     status_.last = last_dir;
@@ -599,7 +601,7 @@
   DCHECK(!InIsolate() || current_explicit_embedding_sequence_.IsEmpty());
 
   unsigned char from_level = Context()->Level();
-  RefPtr<BidiContext> to_context = Context();
+  scoped_refptr<BidiContext> to_context = Context();
 
   for (size_t i = 0; i < current_explicit_embedding_sequence_.size(); ++i) {
     BidiEmbedding embedding = current_explicit_embedding_sequence_[i];
diff --git a/third_party/WebKit/Source/platform/text/Hyphenation.h b/third_party/WebKit/Source/platform/text/Hyphenation.h
index 8fd2be4..9b2739b 100644
--- a/third_party/WebKit/Source/platform/text/Hyphenation.h
+++ b/third_party/WebKit/Source/platform/text/Hyphenation.h
@@ -39,7 +39,8 @@
 
  private:
   friend class LayoutLocale;
-  static RefPtr<Hyphenation> PlatformGetHyphenation(const AtomicString& locale);
+  static scoped_refptr<Hyphenation> PlatformGetHyphenation(
+      const AtomicString& locale);
 };
 
 }  // namespace blink
diff --git a/third_party/WebKit/Source/platform/text/HyphenationTest.cpp b/third_party/WebKit/Source/platform/text/HyphenationTest.cpp
index 10397caa..a94db4f 100644
--- a/third_party/WebKit/Source/platform/text/HyphenationTest.cpp
+++ b/third_party/WebKit/Source/platform/text/HyphenationTest.cpp
@@ -31,7 +31,7 @@
 };
 
 TEST(HyphenationTest, Get) {
-  RefPtr<Hyphenation> hyphenation = WTF::AdoptRef(new NoHyphenation);
+  scoped_refptr<Hyphenation> hyphenation = WTF::AdoptRef(new NoHyphenation);
   LayoutLocale::SetHyphenationForTesting("en-US", hyphenation);
   EXPECT_EQ(hyphenation.get(), LayoutLocale::Get("en-US")->GetHyphenation());
 
@@ -52,7 +52,7 @@
     // Ignore this test on platforms without hyphenation dictionaries.
     return;
   }
-  RefPtr<Hyphenation> hyphenation =
+  scoped_refptr<Hyphenation> hyphenation =
       HyphenationMinikin::FromFileForTesting(std::move(file));
 #else
   const LayoutLocale* locale = LayoutLocale::Get("en-us");
diff --git a/third_party/WebKit/Source/platform/text/TextDecoration.h b/third_party/WebKit/Source/platform/text/TextDecoration.h
index 7a48b67b..27c69ab 100644
--- a/third_party/WebKit/Source/platform/text/TextDecoration.h
+++ b/third_party/WebKit/Source/platform/text/TextDecoration.h
@@ -34,8 +34,8 @@
 namespace blink {
 
 enum TextDecorationType {
-  kTextDecorationTypeSpelling = 1 << 1,
-  kTextDecorationTypeGrammar = 1 << 2,
+  kTextDecorationTypeSpelling,
+  kTextDecorationTypeGrammar,
 };
 }
 
diff --git a/third_party/WebKit/Source/platform/text/fuchsia/HyphenationFuchsia.cpp b/third_party/WebKit/Source/platform/text/fuchsia/HyphenationFuchsia.cpp
index 04bfe317..355b108 100644
--- a/third_party/WebKit/Source/platform/text/fuchsia/HyphenationFuchsia.cpp
+++ b/third_party/WebKit/Source/platform/text/fuchsia/HyphenationFuchsia.cpp
@@ -6,7 +6,8 @@
 
 namespace blink {
 
-RefPtr<Hyphenation> Hyphenation::PlatformGetHyphenation(const AtomicString&) {
+scoped_refptr<Hyphenation> Hyphenation::PlatformGetHyphenation(
+    const AtomicString&) {
   // TODO(fuchsia): Implement this when UI support is ready. crbug.com/750946
   return nullptr;
 }
diff --git a/third_party/WebKit/Source/platform/text/hyphenation/HyphenationMinikin.cpp b/third_party/WebKit/Source/platform/text/hyphenation/HyphenationMinikin.cpp
index b96b4b0..52d9c9f 100644
--- a/third_party/WebKit/Source/platform/text/hyphenation/HyphenationMinikin.cpp
+++ b/third_party/WebKit/Source/platform/text/hyphenation/HyphenationMinikin.cpp
@@ -141,9 +141,10 @@
   return map;
 }
 
-RefPtr<Hyphenation> Hyphenation::PlatformGetHyphenation(
+scoped_refptr<Hyphenation> Hyphenation::PlatformGetHyphenation(
     const AtomicString& locale) {
-  RefPtr<HyphenationMinikin> hyphenation(WTF::AdoptRef(new HyphenationMinikin));
+  scoped_refptr<HyphenationMinikin> hyphenation(
+      WTF::AdoptRef(new HyphenationMinikin));
   if (hyphenation->OpenDictionary(locale.LowerASCII()))
     return hyphenation;
   hyphenation = nullptr;
@@ -156,9 +157,10 @@
   return nullptr;
 }
 
-RefPtr<HyphenationMinikin> HyphenationMinikin::FromFileForTesting(
+scoped_refptr<HyphenationMinikin> HyphenationMinikin::FromFileForTesting(
     base::File file) {
-  RefPtr<HyphenationMinikin> hyphenation(WTF::AdoptRef(new HyphenationMinikin));
+  scoped_refptr<HyphenationMinikin> hyphenation(
+      WTF::AdoptRef(new HyphenationMinikin));
   if (hyphenation->OpenDictionary(std::move(file)))
     return hyphenation;
   return nullptr;
diff --git a/third_party/WebKit/Source/platform/text/hyphenation/HyphenationMinikin.h b/third_party/WebKit/Source/platform/text/hyphenation/HyphenationMinikin.h
index d09d8fc..81a259a 100644
--- a/third_party/WebKit/Source/platform/text/hyphenation/HyphenationMinikin.h
+++ b/third_party/WebKit/Source/platform/text/hyphenation/HyphenationMinikin.h
@@ -28,7 +28,7 @@
                             size_t before_index) const override;
   Vector<size_t, 8> HyphenLocations(const StringView&) const override;
 
-  static RefPtr<HyphenationMinikin> FromFileForTesting(base::File);
+  static scoped_refptr<HyphenationMinikin> FromFileForTesting(base::File);
 
  private:
   bool OpenDictionary(base::File);
diff --git a/third_party/WebKit/Source/platform/text/linux/HyphenationLinux.cpp b/third_party/WebKit/Source/platform/text/linux/HyphenationLinux.cpp
index f41cb869..92fa833 100644
--- a/third_party/WebKit/Source/platform/text/linux/HyphenationLinux.cpp
+++ b/third_party/WebKit/Source/platform/text/linux/HyphenationLinux.cpp
@@ -6,7 +6,8 @@
 
 namespace blink {
 
-RefPtr<Hyphenation> Hyphenation::PlatformGetHyphenation(const AtomicString&) {
+scoped_refptr<Hyphenation> Hyphenation::PlatformGetHyphenation(
+    const AtomicString&) {
   return nullptr;
 }
 
diff --git a/third_party/WebKit/Source/platform/text/mac/HyphenationMac.cpp b/third_party/WebKit/Source/platform/text/mac/HyphenationMac.cpp
index 2a82cba..112c951 100644
--- a/third_party/WebKit/Source/platform/text/mac/HyphenationMac.cpp
+++ b/third_party/WebKit/Source/platform/text/mac/HyphenationMac.cpp
@@ -49,7 +49,7 @@
   RetainPtr<CFLocaleRef> locale_cf_;
 };
 
-RefPtr<Hyphenation> Hyphenation::PlatformGetHyphenation(
+scoped_refptr<Hyphenation> Hyphenation::PlatformGetHyphenation(
     const AtomicString& locale) {
   RetainPtr<CFStringRef> locale_cf_string = locale.Impl()->CreateCFString();
   RetainPtr<CFLocaleRef> locale_cf =
diff --git a/third_party/WebKit/Source/platform/text/win/HyphenationWin.cpp b/third_party/WebKit/Source/platform/text/win/HyphenationWin.cpp
index f41cb869..92fa833 100644
--- a/third_party/WebKit/Source/platform/text/win/HyphenationWin.cpp
+++ b/third_party/WebKit/Source/platform/text/win/HyphenationWin.cpp
@@ -6,7 +6,8 @@
 
 namespace blink {
 
-RefPtr<Hyphenation> Hyphenation::PlatformGetHyphenation(const AtomicString&) {
+scoped_refptr<Hyphenation> Hyphenation::PlatformGetHyphenation(
+    const AtomicString&) {
   return nullptr;
 }
 
diff --git a/third_party/WebKit/Source/platform/weborigin/OriginAccessEntryTest.cpp b/third_party/WebKit/Source/platform/weborigin/OriginAccessEntryTest.cpp
index b8c10eec..0faf6a0 100644
--- a/third_party/WebKit/Source/platform/weborigin/OriginAccessEntryTest.cpp
+++ b/third_party/WebKit/Source/platform/weborigin/OriginAccessEntryTest.cpp
@@ -71,7 +71,7 @@
   ScopedTestingPlatformSupport<OriginAccessEntryTestPlatform> platform;
   platform->SetPublicSuffix("com");
 
-  RefPtr<SecurityOrigin> origin =
+  scoped_refptr<SecurityOrigin> origin =
       SecurityOrigin::CreateFromString("http://www.google.com");
   OriginAccessEntry entry1("http", "google.com",
                            OriginAccessEntry::kAllowSubdomains);
@@ -145,7 +145,7 @@
   for (const auto& test : inputs) {
     SCOPED_TRACE(::testing::Message()
                  << "Host: " << test.host << ", Origin: " << test.origin);
-    RefPtr<SecurityOrigin> origin_to_test =
+    scoped_refptr<SecurityOrigin> origin_to_test =
         SecurityOrigin::CreateFromString(test.origin);
     OriginAccessEntry entry1(test.protocol, test.host,
                              OriginAccessEntry::kAllowSubdomains);
@@ -197,7 +197,7 @@
   platform->SetPublicSuffix("com");
 
   for (const auto& test : inputs) {
-    RefPtr<SecurityOrigin> origin_to_test =
+    scoped_refptr<SecurityOrigin> origin_to_test =
         SecurityOrigin::CreateFromString(test.origin);
     OriginAccessEntry entry1(test.protocol, test.host,
                              OriginAccessEntry::kAllowRegisterableDomains);
@@ -253,7 +253,7 @@
   platform->SetPublicSuffix("appspot.com");
 
   for (const auto& test : inputs) {
-    RefPtr<SecurityOrigin> origin_to_test =
+    scoped_refptr<SecurityOrigin> origin_to_test =
         SecurityOrigin::CreateFromString(test.origin);
     OriginAccessEntry entry1(test.protocol, test.host,
                              OriginAccessEntry::kAllowRegisterableDomains);
@@ -306,7 +306,7 @@
   for (const auto& test : inputs) {
     SCOPED_TRACE(::testing::Message()
                  << "Host: " << test.host << ", Origin: " << test.origin);
-    RefPtr<SecurityOrigin> origin_to_test =
+    scoped_refptr<SecurityOrigin> origin_to_test =
         SecurityOrigin::CreateFromString(test.origin);
     OriginAccessEntry entry1(test.protocol, test.host,
                              OriginAccessEntry::kDisallowSubdomains);
@@ -365,7 +365,7 @@
   for (const auto& test : inputs) {
     SCOPED_TRACE(::testing::Message()
                  << "Host: " << test.host << ", Origin: " << test.origin);
-    RefPtr<SecurityOrigin> origin_to_test =
+    scoped_refptr<SecurityOrigin> origin_to_test =
         SecurityOrigin::CreateFromString(test.origin);
     OriginAccessEntry entry1(test.protocol, test.host,
                              OriginAccessEntry::kAllowSubdomains);
diff --git a/third_party/WebKit/Source/platform/weborigin/SecurityOrigin.cpp b/third_party/WebKit/Source/platform/weborigin/SecurityOrigin.cpp
index 1d5072b..dc10d12 100644
--- a/third_party/WebKit/Source/platform/weborigin/SecurityOrigin.cpp
+++ b/third_party/WebKit/Source/platform/weborigin/SecurityOrigin.cpp
@@ -177,8 +177,8 @@
       is_unique_origin_potentially_trustworthy_(
           other->is_unique_origin_potentially_trustworthy_) {}
 
-RefPtr<SecurityOrigin> SecurityOrigin::Create(const KURL& url) {
-  if (RefPtr<SecurityOrigin> origin = GetOriginFromMap(url))
+scoped_refptr<SecurityOrigin> SecurityOrigin::Create(const KURL& url) {
+  if (scoped_refptr<SecurityOrigin> origin = GetOriginFromMap(url))
     return origin;
 
   if (ShouldTreatAsUniqueOrigin(url))
@@ -190,13 +190,13 @@
   return WTF::AdoptRef(new SecurityOrigin(url));
 }
 
-RefPtr<SecurityOrigin> SecurityOrigin::CreateUnique() {
-  RefPtr<SecurityOrigin> origin = WTF::AdoptRef(new SecurityOrigin());
+scoped_refptr<SecurityOrigin> SecurityOrigin::CreateUnique() {
+  scoped_refptr<SecurityOrigin> origin = WTF::AdoptRef(new SecurityOrigin());
   DCHECK(origin->IsUnique());
   return origin;
 }
 
-RefPtr<SecurityOrigin> SecurityOrigin::IsolatedCopy() const {
+scoped_refptr<SecurityOrigin> SecurityOrigin::IsolatedCopy() const {
   return WTF::AdoptRef(new SecurityOrigin(this));
 }
 
@@ -292,7 +292,7 @@
   if (IsUnique())
     return false;
 
-  RefPtr<SecurityOrigin> target_origin = SecurityOrigin::Create(url);
+  scoped_refptr<SecurityOrigin> target_origin = SecurityOrigin::Create(url);
 
   if (target_origin->IsUnique())
     return false;
@@ -503,14 +503,14 @@
   }
 }
 
-RefPtr<SecurityOrigin> SecurityOrigin::CreateFromString(
+scoped_refptr<SecurityOrigin> SecurityOrigin::CreateFromString(
     const String& origin_string) {
   return SecurityOrigin::Create(KURL(NullURL(), origin_string));
 }
 
-RefPtr<SecurityOrigin> SecurityOrigin::Create(const String& protocol,
-                                              const String& host,
-                                              int port) {
+scoped_refptr<SecurityOrigin> SecurityOrigin::Create(const String& protocol,
+                                                     const String& host,
+                                                     int port) {
   if (port < 0 || port > kMaxAllowedPort)
     return CreateUnique();
 
@@ -520,11 +520,11 @@
   return Create(KURL(NullURL(), protocol + "://" + host + port_part + "/"));
 }
 
-RefPtr<SecurityOrigin> SecurityOrigin::Create(const String& protocol,
-                                              const String& host,
-                                              int port,
-                                              const String& suborigin) {
-  RefPtr<SecurityOrigin> origin = Create(protocol, host, port);
+scoped_refptr<SecurityOrigin> SecurityOrigin::Create(const String& protocol,
+                                                     const String& host,
+                                                     int port,
+                                                     const String& suborigin) {
+  scoped_refptr<SecurityOrigin> origin = Create(protocol, host, port);
   if (!suborigin.IsEmpty())
     origin->suborigin_.SetName(suborigin);
   return origin;
@@ -569,13 +569,13 @@
           Suborigin::SuboriginPolicyOptions::kUnsafeCredentials))
     return false;
 
-  RefPtr<SecurityOrigin> other = SecurityOrigin::Create(url);
+  scoped_refptr<SecurityOrigin> other = SecurityOrigin::Create(url);
   return IsSameSchemeHostPort(other.get());
 }
 
 bool SecurityOrigin::AreSameSchemeHostPort(const KURL& a, const KURL& b) {
-  RefPtr<SecurityOrigin> origin_a = SecurityOrigin::Create(a);
-  RefPtr<SecurityOrigin> origin_b = SecurityOrigin::Create(b);
+  scoped_refptr<SecurityOrigin> origin_a = SecurityOrigin::Create(a);
+  scoped_refptr<SecurityOrigin> origin_b = SecurityOrigin::Create(b);
   return origin_b->IsSameSchemeHostPort(origin_a.get());
 }
 
diff --git a/third_party/WebKit/Source/platform/weborigin/SecurityOrigin.h b/third_party/WebKit/Source/platform/weborigin/SecurityOrigin.h
index e2b8099..e29b8c45 100644
--- a/third_party/WebKit/Source/platform/weborigin/SecurityOrigin.h
+++ b/third_party/WebKit/Source/platform/weborigin/SecurityOrigin.h
@@ -46,17 +46,17 @@
   WTF_MAKE_NONCOPYABLE(SecurityOrigin);
 
  public:
-  static RefPtr<SecurityOrigin> Create(const KURL&);
-  static RefPtr<SecurityOrigin> CreateUnique();
+  static scoped_refptr<SecurityOrigin> Create(const KURL&);
+  static scoped_refptr<SecurityOrigin> CreateUnique();
 
-  static RefPtr<SecurityOrigin> CreateFromString(const String&);
-  static RefPtr<SecurityOrigin> Create(const String& protocol,
-                                       const String& host,
-                                       int port);
-  static RefPtr<SecurityOrigin> Create(const String& protocol,
-                                       const String& host,
-                                       int port,
-                                       const String& suborigin);
+  static scoped_refptr<SecurityOrigin> CreateFromString(const String&);
+  static scoped_refptr<SecurityOrigin> Create(const String& protocol,
+                                              const String& host,
+                                              int port);
+  static scoped_refptr<SecurityOrigin> Create(const String& protocol,
+                                              const String& host,
+                                              int port,
+                                              const String& suborigin);
 
   static void SetMap(URLSecurityOriginMap*);
 
@@ -75,7 +75,7 @@
 
   // Create a deep copy of this SecurityOrigin. This method is useful
   // when marshalling a SecurityOrigin to another thread.
-  RefPtr<SecurityOrigin> IsolatedCopy() const;
+  scoped_refptr<SecurityOrigin> IsolatedCopy() const;
 
   // Set the domain property of this security origin to newDomain. This
   // function does not check whether newDomain is a suffix of the current
diff --git a/third_party/WebKit/Source/platform/weborigin/SecurityOriginHash.h b/third_party/WebKit/Source/platform/weborigin/SecurityOriginHash.h
index 446b33b5..4d2bdb3 100644
--- a/third_party/WebKit/Source/platform/weborigin/SecurityOriginHash.h
+++ b/third_party/WebKit/Source/platform/weborigin/SecurityOriginHash.h
@@ -48,7 +48,7 @@
             : 0};
     return StringHasher::HashMemory<sizeof(hash_codes)>(hash_codes);
   }
-  static unsigned GetHash(const RefPtr<SecurityOrigin>& origin) {
+  static unsigned GetHash(const scoped_refptr<SecurityOrigin>& origin) {
     return GetHash(origin.get());
   }
 
@@ -70,14 +70,14 @@
 
     return true;
   }
-  static bool Equal(SecurityOrigin* a, const RefPtr<SecurityOrigin>& b) {
+  static bool Equal(SecurityOrigin* a, const scoped_refptr<SecurityOrigin>& b) {
     return Equal(a, b.get());
   }
-  static bool Equal(const RefPtr<SecurityOrigin>& a, SecurityOrigin* b) {
+  static bool Equal(const scoped_refptr<SecurityOrigin>& a, SecurityOrigin* b) {
     return Equal(a.get(), b);
   }
-  static bool Equal(const RefPtr<SecurityOrigin>& a,
-                    const RefPtr<SecurityOrigin>& b) {
+  static bool Equal(const scoped_refptr<SecurityOrigin>& a,
+                    const scoped_refptr<SecurityOrigin>& b) {
     return Equal(a.get(), b.get());
   }
 
@@ -89,7 +89,7 @@
 namespace WTF {
 
 template <>
-struct DefaultHash<RefPtr<blink::SecurityOrigin>> {
+struct DefaultHash<scoped_refptr<blink::SecurityOrigin>> {
   typedef blink::SecurityOriginHash Hash;
 };
 
diff --git a/third_party/WebKit/Source/platform/weborigin/SecurityOriginTest.cpp b/third_party/WebKit/Source/platform/weborigin/SecurityOriginTest.cpp
index e8b0dfa..a7d9b1b1 100644
--- a/third_party/WebKit/Source/platform/weborigin/SecurityOriginTest.cpp
+++ b/third_party/WebKit/Source/platform/weborigin/SecurityOriginTest.cpp
@@ -56,7 +56,7 @@
   int ports[] = {-100, -1, kMaxAllowedPort + 1, 1000000};
 
   for (size_t i = 0; i < WTF_ARRAY_LENGTH(ports); ++i) {
-    RefPtr<SecurityOrigin> origin =
+    scoped_refptr<SecurityOrigin> origin =
         SecurityOrigin::Create("http", "example.com", ports[i]);
     EXPECT_TRUE(origin->IsUnique())
         << "Port " << ports[i] << " should have generated a unique origin.";
@@ -67,7 +67,7 @@
   int ports[] = {0, 80, 443, 5000, kMaxAllowedPort};
 
   for (size_t i = 0; i < WTF_ARRAY_LENGTH(ports); ++i) {
-    RefPtr<SecurityOrigin> origin =
+    scoped_refptr<SecurityOrigin> origin =
         SecurityOrigin::Create("http", "example.com", ports[i]);
     EXPECT_FALSE(origin->IsUnique())
         << "Port " << ports[i] << " should not have generated a unique origin.";
@@ -75,9 +75,9 @@
 }
 
 TEST_F(SecurityOriginTest, LocalAccess) {
-  RefPtr<SecurityOrigin> file1 =
+  scoped_refptr<SecurityOrigin> file1 =
       SecurityOrigin::CreateFromString("file:///etc/passwd");
-  RefPtr<SecurityOrigin> file2 =
+  scoped_refptr<SecurityOrigin> file2 =
       SecurityOrigin::CreateFromString("file:///etc/shadow");
 
   EXPECT_TRUE(file1->IsSameSchemeHostPort(file1.get()));
@@ -165,14 +165,14 @@
 
   for (size_t i = 0; i < WTF_ARRAY_LENGTH(inputs); ++i) {
     SCOPED_TRACE(inputs[i].url);
-    RefPtr<SecurityOrigin> origin =
+    scoped_refptr<SecurityOrigin> origin =
         SecurityOrigin::CreateFromString(inputs[i].url);
     String error_message;
     EXPECT_EQ(inputs[i].access_granted, origin->IsPotentiallyTrustworthy());
   }
 
   // Unique origins are not considered secure.
-  RefPtr<SecurityOrigin> unique_origin = SecurityOrigin::CreateUnique();
+  scoped_refptr<SecurityOrigin> unique_origin = SecurityOrigin::CreateUnique();
   EXPECT_FALSE(unique_origin->IsPotentiallyTrustworthy());
   // ... unless they are specially marked as such.
   unique_origin->SetUniqueOriginIsPotentiallyTrustworthy(true);
@@ -224,7 +224,7 @@
 TEST_F(SecurityOriginTest, Suborigins) {
   ScopedSuboriginsForTest suborigins(true);
 
-  RefPtr<SecurityOrigin> origin =
+  scoped_refptr<SecurityOrigin> origin =
       SecurityOrigin::CreateFromString("https://test.com");
   Suborigin suborigin;
   suborigin.SetName("foobar");
@@ -282,7 +282,7 @@
   EXPECT_EQ("test.com", real_host);
   EXPECT_EQ("foobar", suborigin);
 
-  RefPtr<SecurityOrigin> origin;
+  scoped_refptr<SecurityOrigin> origin;
   StringBuilder builder;
 
   origin = SecurityOrigin::CreateFromString("https-so://foobar.test.com");
@@ -310,15 +310,15 @@
 
 TEST_F(SecurityOriginTest, SuboriginsIsSameSchemeHostPortAndSuborigin) {
   ScopedSuboriginsForTest suborigins(true);
-  RefPtr<SecurityOrigin> origin =
+  scoped_refptr<SecurityOrigin> origin =
       SecurityOrigin::CreateFromString("https-so://foobar.test.com");
-  RefPtr<SecurityOrigin> other1 =
+  scoped_refptr<SecurityOrigin> other1 =
       SecurityOrigin::CreateFromString("https-so://bazbar.test.com");
-  RefPtr<SecurityOrigin> other2 =
+  scoped_refptr<SecurityOrigin> other2 =
       SecurityOrigin::CreateFromString("http-so://foobar.test.com");
-  RefPtr<SecurityOrigin> other3 =
+  scoped_refptr<SecurityOrigin> other3 =
       SecurityOrigin::CreateFromString("https-so://foobar.test.com:1234");
-  RefPtr<SecurityOrigin> other4 =
+  scoped_refptr<SecurityOrigin> other4 =
       SecurityOrigin::CreateFromString("https://test.com");
 
   EXPECT_TRUE(origin->IsSameSchemeHostPortAndSuborigin(origin.get()));
@@ -346,9 +346,9 @@
   };
 
   for (size_t i = 0; i < WTF_ARRAY_LENGTH(tests); ++i) {
-    RefPtr<SecurityOrigin> origin1 =
+    scoped_refptr<SecurityOrigin> origin1 =
         SecurityOrigin::CreateFromString(tests[i].origin1);
-    RefPtr<SecurityOrigin> origin2 =
+    scoped_refptr<SecurityOrigin> origin2 =
         SecurityOrigin::CreateFromString(tests[i].origin2);
     EXPECT_EQ(tests[i].can_access, origin1->CanAccess(origin2.get()));
   }
@@ -372,7 +372,7 @@
   };
 
   for (size_t i = 0; i < WTF_ARRAY_LENGTH(tests); ++i) {
-    RefPtr<SecurityOrigin> origin =
+    scoped_refptr<SecurityOrigin> origin =
         SecurityOrigin::CreateFromString(tests[i].origin);
     blink::KURL url(tests[i].url);
     EXPECT_EQ(tests[i].can_request, origin->CanRequest(url));
@@ -396,7 +396,7 @@
   };
 
   for (const auto& test : cases) {
-    RefPtr<SecurityOrigin> origin =
+    scoped_refptr<SecurityOrigin> origin =
         SecurityOrigin::CreateFromString(test.origin);
     EXPECT_EQ(test.port, origin->Port());
     EXPECT_EQ(test.effective_port, origin->EffectivePort());
@@ -419,7 +419,7 @@
   };
 
   for (const auto& test : cases) {
-    RefPtr<SecurityOrigin> origin =
+    scoped_refptr<SecurityOrigin> origin =
         SecurityOrigin::Create(test.scheme, test.host, test.port);
     EXPECT_EQ(test.origin, origin->ToString()) << test.origin;
   }
@@ -449,7 +449,7 @@
   };
 
   for (const auto& test : cases) {
-    RefPtr<SecurityOrigin> origin = SecurityOrigin::Create(
+    scoped_refptr<SecurityOrigin> origin = SecurityOrigin::Create(
         test.scheme, test.host, test.port, test.suborigin);
     EXPECT_EQ(test.origin, origin->ToString()) << test.origin;
   }
@@ -474,12 +474,14 @@
   };
 
   for (const TestCase& test : cases) {
-    RefPtr<SecurityOrigin> origin = SecurityOrigin::CreateFromString(test.url);
+    scoped_refptr<SecurityOrigin> origin =
+        SecurityOrigin::CreateFromString(test.url);
     EXPECT_EQ(test.expected_uniqueness, origin->IsUnique());
     EXPECT_EQ(test.expected_origin_string, origin->ToString());
 
     KURL blob_url = BlobURL::CreatePublicURL(origin.get());
-    RefPtr<SecurityOrigin> blob_url_origin = SecurityOrigin::Create(blob_url);
+    scoped_refptr<SecurityOrigin> blob_url_origin =
+        SecurityOrigin::Create(blob_url);
     EXPECT_EQ(blob_url_origin->IsUnique(), origin->IsUnique());
     EXPECT_EQ(blob_url_origin->ToString(), origin->ToString());
     EXPECT_EQ(blob_url_origin->ToRawString(), origin->ToRawString());
@@ -487,8 +489,8 @@
 }
 
 TEST_F(SecurityOriginTest, UniqueOriginIsSameSchemeHostPort) {
-  RefPtr<SecurityOrigin> unique_origin = SecurityOrigin::CreateUnique();
-  RefPtr<SecurityOrigin> tuple_origin =
+  scoped_refptr<SecurityOrigin> unique_origin = SecurityOrigin::CreateUnique();
+  scoped_refptr<SecurityOrigin> tuple_origin =
       SecurityOrigin::CreateFromString("http://example.com");
 
   EXPECT_TRUE(unique_origin->IsSameSchemeHostPort(unique_origin.get()));
diff --git a/third_party/WebKit/Source/platform/weborigin/SecurityPolicy.cpp b/third_party/WebKit/Source/platform/weborigin/SecurityPolicy.cpp
index 18dbbb38..6109129 100644
--- a/third_party/WebKit/Source/platform/weborigin/SecurityPolicy.cpp
+++ b/third_party/WebKit/Source/platform/weborigin/SecurityPolicy.cpp
@@ -116,9 +116,9 @@
       return Referrer(origin + "/", referrer_policy_no_default);
     }
     case kReferrerPolicyOriginWhenCrossOrigin: {
-      RefPtr<SecurityOrigin> referrer_origin =
+      scoped_refptr<SecurityOrigin> referrer_origin =
           SecurityOrigin::Create(referrer_url);
-      RefPtr<SecurityOrigin> url_origin = SecurityOrigin::Create(url);
+      scoped_refptr<SecurityOrigin> url_origin = SecurityOrigin::Create(url);
       if (!url_origin->IsSameSchemeHostPort(referrer_origin.get())) {
         String origin = referrer_origin->ToString();
         return Referrer(origin + "/", referrer_policy_no_default);
@@ -126,9 +126,9 @@
       break;
     }
     case kReferrerPolicySameOrigin: {
-      RefPtr<SecurityOrigin> referrer_origin =
+      scoped_refptr<SecurityOrigin> referrer_origin =
           SecurityOrigin::Create(referrer_url);
-      RefPtr<SecurityOrigin> url_origin = SecurityOrigin::Create(url);
+      scoped_refptr<SecurityOrigin> url_origin = SecurityOrigin::Create(url);
       if (!url_origin->IsSameSchemeHostPort(referrer_origin.get())) {
         return Referrer(Referrer::NoReferrer(), referrer_policy_no_default);
       }
@@ -142,9 +142,9 @@
                       referrer_policy_no_default);
     }
     case kReferrerPolicyNoReferrerWhenDowngradeOriginWhenCrossOrigin: {
-      RefPtr<SecurityOrigin> referrer_origin =
+      scoped_refptr<SecurityOrigin> referrer_origin =
           SecurityOrigin::Create(referrer_url);
-      RefPtr<SecurityOrigin> url_origin = SecurityOrigin::Create(url);
+      scoped_refptr<SecurityOrigin> url_origin = SecurityOrigin::Create(url);
       if (!url_origin->IsSameSchemeHostPort(referrer_origin.get())) {
         String origin = referrer_origin->ToString();
         return Referrer(ShouldHideReferrer(url, referrer_url)
@@ -211,7 +211,7 @@
 bool SecurityPolicy::IsAccessToURLWhiteListed(
     const SecurityOrigin* active_origin,
     const KURL& url) {
-  RefPtr<SecurityOrigin> target_origin = SecurityOrigin::Create(url);
+  scoped_refptr<SecurityOrigin> target_origin = SecurityOrigin::Create(url);
   return IsAccessWhiteListed(active_origin, target_origin.get());
 }
 
diff --git a/third_party/WebKit/Source/platform/weborigin/SecurityPolicyTest.cpp b/third_party/WebKit/Source/platform/weborigin/SecurityPolicyTest.cpp
index 14a0ec2..d13e089 100644
--- a/third_party/WebKit/Source/platform/weborigin/SecurityPolicyTest.cpp
+++ b/third_party/WebKit/Source/platform/weborigin/SecurityPolicyTest.cpp
@@ -217,7 +217,8 @@
   };
 
   for (const char* url : insecure_urls) {
-    RefPtr<SecurityOrigin> origin = SecurityOrigin::CreateFromString(url);
+    scoped_refptr<SecurityOrigin> origin =
+        SecurityOrigin::CreateFromString(url);
     EXPECT_FALSE(origin->IsPotentiallyTrustworthy());
     SecurityPolicy::AddOriginTrustworthyWhiteList(*origin);
     EXPECT_TRUE(origin->IsPotentiallyTrustworthy());
@@ -239,8 +240,9 @@
   };
   for (const TestCase& test : insecure_urls_with_inner_origin) {
     // Actually origins of both URLs should be same.
-    RefPtr<SecurityOrigin> origin1 = SecurityOrigin::CreateFromString(test.url);
-    RefPtr<SecurityOrigin> origin2 =
+    scoped_refptr<SecurityOrigin> origin1 =
+        SecurityOrigin::CreateFromString(test.url);
+    scoped_refptr<SecurityOrigin> origin2 =
         SecurityOrigin::CreateFromString(test.another_url_in_origin);
 
     EXPECT_FALSE(origin1->IsPotentiallyTrustworthy());
diff --git a/third_party/WebKit/Tools/Scripts/webkitpy/w3c/test_importer.py b/third_party/WebKit/Tools/Scripts/webkitpy/w3c/test_importer.py
index b6de169..e5480548 100644
--- a/third_party/WebKit/Tools/Scripts/webkitpy/w3c/test_importer.py
+++ b/third_party/WebKit/Tools/Scripts/webkitpy/w3c/test_importer.py
@@ -488,23 +488,20 @@
         return '\n'.join(message_lines)
 
     def tbr_reviewer(self):
-        """Returns the email address to use as the reviewer.
+        """Returns the user name or email address to use as the reviewer.
 
-        This tries to fetch the current ecosystem infra sheriff,
-        but falls back in case of error.
+        This tries to fetch the current ecosystem infra sheriff, but falls back
+        in case of error.
+
+        Either a user name (which is assumed to have a chromium.org email
+        address) or a full email address (for other cases) is returned.
         """
-        username = ''
+        username = 'qyearsley'  # Fallback in case of failure.
         try:
             username = self._fetch_ecosystem_infra_sheriff_username()
         except (IOError, KeyError, ValueError) as error:
             _log.error('Exception while fetching current sheriff: %s', error)
-        if not username:
-            username = 'qyearsley'  # Fallback in case of failure.
-        # Users with an email address other than chromium.org have a full email
-        # address in the JSON file.
-        if '@' in username:
-            return username
-        return username + '@chromium.org'
+        return username
 
     def _fetch_ecosystem_infra_sheriff_username(self):
         content = self.host.web.get_binary(ROTATIONS_URL)
diff --git a/third_party/WebKit/Tools/Scripts/webkitpy/w3c/test_importer_unittest.py b/third_party/WebKit/Tools/Scripts/webkitpy/w3c/test_importer_unittest.py
index d2bcd63..0015fc6 100644
--- a/third_party/WebKit/Tools/Scripts/webkitpy/w3c/test_importer_unittest.py
+++ b/third_party/WebKit/Tools/Scripts/webkitpy/w3c/test_importer_unittest.py
@@ -318,7 +318,7 @@
     def test_tbr_reviewer_no_response_uses_backup(self):
         host = MockHost()
         importer = TestImporter(host)
-        self.assertEqual('qyearsley@chromium.org', importer.tbr_reviewer())
+        self.assertEqual('qyearsley', importer.tbr_reviewer())
         self.assertLog([
             'ERROR: Exception while fetching current sheriff: '
             'No JSON object could be decoded\n'
@@ -341,7 +341,7 @@
             'rotations': ['other-rotation', 'ecosystem_infra']
         })
         importer = TestImporter(host)
-        self.assertEqual('current-sheriff@chromium.org', importer.tbr_reviewer())
+        self.assertEqual('current-sheriff', importer.tbr_reviewer())
         self.assertLog([])
 
     def test_tbr_reviewer_with_full_email_address(self):
diff --git a/third_party/WebKit/public/platform/WebLocalizedString.h b/third_party/WebKit/public/platform/WebLocalizedString.h
index b162eea..38d50637 100644
--- a/third_party/WebKit/public/platform/WebLocalizedString.h
+++ b/third_party/WebKit/public/platform/WebLocalizedString.h
@@ -100,6 +100,7 @@
     kOtherMonthLabel,
     kOtherWeekLabel,
     kOverflowMenuCaptions,
+    kOverflowMenuCaptionsSubmenuTitle,
     kOverflowMenuCast,
     kOverflowMenuEnterFullscreen,
     kOverflowMenuExitFullscreen,
diff --git a/third_party/WebKit/public/platform/referrer.mojom b/third_party/WebKit/public/platform/referrer.mojom
index 003ba32..83be35c 100644
--- a/third_party/WebKit/public/platform/referrer.mojom
+++ b/third_party/WebKit/public/platform/referrer.mojom
@@ -11,6 +11,10 @@
 //
 // TODO(rockot): Update all WebReferrerPolicy consumers to use this type
 // instead, and remove the typemap.
+// Don't make backwards-incompatible changes to this definition!
+// It's used in PageState serialization, so backwards incompatible changes
+// would cause stored PageState objects to be un-parseable. Please contact the
+// page state serialization owners before making such a change.
 enum ReferrerPolicy {
     ALWAYS,
     DEFAULT,
diff --git a/third_party/WebKit/public/platform/web_feature.mojom b/third_party/WebKit/public/platform/web_feature.mojom
index 2ae3978..45474c8 100644
--- a/third_party/WebKit/public/platform/web_feature.mojom
+++ b/third_party/WebKit/public/platform/web_feature.mojom
@@ -1736,6 +1736,11 @@
   kHasBeforeOrAfterPseudoElement = 2204,
   kShapeOutsideMaybeAffectedInlineSize = 2205,
   kShapeOutsideMaybeAffectedInlinePosition = 2206,
+  kGamepadVibrationActuator = 2207,
+  kMicrophoneDisabledByFeaturePolicyEstimate = 2208,
+  kCameraDisabledByFeaturePolicyEstimate = 2209,
+  kMidiDisabledByFeaturePolicy = 2210,
+
   // Add new features immediately above this line. Don't change assigned
   // numbers of any item, and don't reuse removed slots.
   // Also, run update_use_counter_feature_enum.py in
diff --git a/third_party/WebKit/public/web/WebContextMenuData.h b/third_party/WebKit/public/web/WebContextMenuData.h
index ec8190c..abfcb586 100644
--- a/third_party/WebKit/public/web/WebContextMenuData.h
+++ b/third_party/WebKit/public/web/WebContextMenuData.h
@@ -31,7 +31,6 @@
 #ifndef WebContextMenuData_h
 #define WebContextMenuData_h
 
-#include "WebHistoryItem.h"
 #include "WebMenuItemInfo.h"
 #include "public/platform/WebMenuSourceType.h"
 #include "public/platform/WebPoint.h"
@@ -103,9 +102,6 @@
   // The encoding for the frame in context.
   WebString frame_encoding;
 
-  // History state of the subframe in context.
-  WebHistoryItem frame_history_item;
-
   enum MediaFlags {
     kMediaNone = 0x0,
     kMediaInError = 0x1,
diff --git a/third_party/WebKit/public/web/WebInputElement.h b/third_party/WebKit/public/web/WebInputElement.h
index fc1061d0..e8de3cf2 100644
--- a/third_party/WebKit/public/web/WebInputElement.h
+++ b/third_party/WebKit/public/web/WebInputElement.h
@@ -73,6 +73,8 @@
   // Sets the value inside the text field without being sanitized. Can't be
   // used if a renderer doesn't exist or on a non text field type. Caret will
   // be moved to the end.
+  // TODO(crbug.com/777850): Remove all references to SetEditingValue, as it's
+  // not used anymore.
   void SetEditingValue(const WebString&);
   bool IsValidValue(const WebString&) const;
   bool IsChecked() const;
diff --git a/third_party/WebKit/public/web/WebTextDecorationType.h b/third_party/WebKit/public/web/WebTextDecorationType.h
index 9c0ef555..f306956 100644
--- a/third_party/WebKit/public/web/WebTextDecorationType.h
+++ b/third_party/WebKit/public/web/WebTextDecorationType.h
@@ -34,8 +34,8 @@
 namespace blink {
 
 enum WebTextDecorationType {
-  kWebTextDecorationTypeSpelling = 1 << 1,
-  kWebTextDecorationTypeGrammar = 1 << 2,
+  kWebTextDecorationTypeSpelling,
+  kWebTextDecorationTypeGrammar,
 };
 
 }  // namespace blink
diff --git a/third_party/crashpad/README.chromium b/third_party/crashpad/README.chromium
index f1bb0e68..6eede7f 100644
--- a/third_party/crashpad/README.chromium
+++ b/third_party/crashpad/README.chromium
@@ -2,7 +2,7 @@
 Short Name: crashpad
 URL: https://crashpad.chromium.org/
 Version: unknown
-Revision: 6d5bd1d04d5f50d9f4a58d528ccfb38c46423f23
+Revision: 3fae8ff07c097da6d0042510bdbe5b16c67a8e12
 License: Apache 2.0
 License File: crashpad/LICENSE
 Security Critical: yes
diff --git a/third_party/crashpad/crashpad/build/run_tests.py b/third_party/crashpad/crashpad/build/run_tests.py
index c5cbb03..3eae77a 100755
--- a/third_party/crashpad/crashpad/build/run_tests.py
+++ b/third_party/crashpad/crashpad/build/run_tests.py
@@ -1,4 +1,5 @@
 #!/usr/bin/env python
+# coding: utf-8
 
 # Copyright 2014 The Crashpad Authors. All rights reserved.
 #
@@ -31,6 +32,18 @@
       os.path.join(os.path.dirname(os.path.abspath(__file__)), os.pardir)
   binary_dir = args[0]
 
+  # Tell 64-bit Windows tests where to find 32-bit test executables, for
+  # cross-bitted testing. This relies on the fact that the GYP build by default
+  # uses {Debug,Release} for the 32-bit build and {Debug,Release}_x64 for the
+  # 64-bit build. This is not a universally valid assumption, and if it’s not
+  # met, 64-bit tests that require 32-bit build output will disable themselves
+  # dynamically.
+  if (sys.platform == 'win32' and binary_dir.endswith('_x64') and
+      'CRASHPAD_TEST_32_BIT_OUTPUT' not in os.environ):
+    binary_dir_32 = binary_dir[:-4]
+    if os.path.isdir(binary_dir_32):
+      os.environ['CRASHPAD_TEST_32_BIT_OUTPUT'] = binary_dir_32
+
   tests = [
       'crashpad_client_test',
       'crashpad_minidump_test',
diff --git a/third_party/crashpad/crashpad/client/annotation.cc b/third_party/crashpad/crashpad/client/annotation.cc
new file mode 100644
index 0000000..22c7395
--- /dev/null
+++ b/third_party/crashpad/crashpad/client/annotation.cc
@@ -0,0 +1,40 @@
+// Copyright 2017 The Crashpad Authors. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "client/annotation.h"
+
+#include <type_traits>
+
+#include "client/annotation_list.h"
+
+namespace crashpad {
+
+static_assert(std::is_standard_layout<Annotation>::value,
+              "Annotation must be POD");
+
+// static
+constexpr size_t Annotation::kNameMaxLength;
+constexpr size_t Annotation::kValueMaxSize;
+
+void Annotation::SetSize(ValueSizeType size) {
+  DCHECK_LT(size, kValueMaxSize);
+  size_ = size;
+  AnnotationList::Get()->Add(this);
+}
+
+void Annotation::Clear() {
+  size_ = 0;
+}
+
+}  // namespace crashpad
diff --git a/third_party/crashpad/crashpad/client/annotation.h b/third_party/crashpad/crashpad/client/annotation.h
new file mode 100644
index 0000000..141aa12
--- /dev/null
+++ b/third_party/crashpad/crashpad/client/annotation.h
@@ -0,0 +1,223 @@
+// Copyright 2017 The Crashpad Authors. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#ifndef CRASHPAD_CLIENT_ANNOTATION_H_
+#define CRASHPAD_CLIENT_ANNOTATION_H_
+
+#include <algorithm>
+#include <atomic>
+
+#include <stdint.h>
+#include <string.h>
+#include <sys/types.h>
+
+#include "base/logging.h"
+#include "base/macros.h"
+#include "base/numerics/safe_conversions.h"
+#include "build/build_config.h"
+
+namespace crashpad {
+
+class AnnotationList;
+
+//! \brief Base class for an annotation, which records a name-value pair of
+//!     arbitrary data when set.
+//!
+//! After an annotation is declared, its `value_ptr_` will not be captured in a
+//! crash report until a call to \a SetSize() specifies how much data from the
+//! value should be recorded.
+//!
+//! Annotations should be declared with static storage duration.
+//!
+//! An example declaration and usage:
+//!
+//! \code
+//!   // foo.cc:
+//!
+//!   namespace {
+//!   char g_buffer[1024];
+//!   crashpad::Annotation g_buffer_annotation(
+//!       crashpad::Annotation::Type::kString, "buffer_head", g_buffer);
+//!   }  // namespace
+//!
+//!   void OnBufferProduced(size_t n) {
+//!     // Capture the head of the buffer, in case we crash when parsing it.
+//!     g_buffer_annotation.SetSize(std::min(64, n));
+//!
+//!     // Start parsing the header.
+//!     Frobinate(g_buffer, n);
+//!   }
+//! \endcode
+//!
+//! Annotation objects are not inherently thread-safe. To manipulate them
+//! from multiple threads, external synchronization must be used.
+//!
+//! Annotation objects should never be destroyed. Once they are Set(), they
+//! are permanently referenced by a global object.
+class Annotation {
+ public:
+  //! \brief The maximum length of the #name field in bytes.
+  static constexpr size_t kNameMaxLength = 64;
+
+  //! \brief The maximum size of the #value field in bytes.
+  static constexpr size_t kValueMaxSize = 2048;
+
+  //! \brief The type used for \a SetSize().
+  using ValueSizeType = uint32_t;
+
+  //! \brief The type of data stored in the annotation.
+  enum class Type : uint16_t {
+    //! \brief An invalid annotation. Reserved for internal use.
+    kInvalid = 0,
+
+    //! \brief A `NUL`-terminated C-string.
+    kString = 1,
+
+    //! \brief Clients may declare their own custom types by using values
+    //!     greater than this.
+    kUserDefinedStart = 0x8000,
+  };
+
+  //! \brief Creates a user-defined Annotation::Type.
+  //!
+  //! This exists to remove the casting overhead of `enum class`.
+  //!
+  //! \param[in] value A value used to create a user-defined type.
+  //!
+  //! \returns The value added to Type::kUserDefinedStart and casted.
+  constexpr static Type UserDefinedType(uint16_t value) {
+    using UnderlyingType = std::underlying_type<Type>::type;
+    // MSVS 2015 doesn't have full C++14 support and complains about local
+    // variables defined in a constexpr function, which is valid. Avoid them
+    // and the also-problematic DCHECK until all the infrastructure is updated:
+    // https://crbug.com/crashpad/201.
+#if !defined(OS_WIN) || (defined(_MSC_VER) && _MSC_VER >= 1910)
+    const UnderlyingType start =
+        static_cast<UnderlyingType>(Type::kUserDefinedStart);
+    const UnderlyingType user_type = start + value;
+    DCHECK(user_type > start) << "User-defined Type is 0 or overflows";
+    return static_cast<Type>(user_type);
+#else
+    return static_cast<Type>(
+        static_cast<UnderlyingType>(Type::kUserDefinedStart) + value);
+#endif
+  }
+
+  //! \brief Constructs a new annotation.
+  //!
+  //! Upon construction, the annotation will not be included in any crash
+  //! reports until \sa SetSize() is called with a value greater than `0`.
+  //!
+  //! \param[in] type The data type of the value of the annotation.
+  //! \param[in] name A `NUL`-terminated C-string name for the annotation. Names
+  //!     do not have to be unique, though not all crash processors may handle
+  //!     Annotations with the same name. Names should be constexpr data with
+  //!     static storage duration.
+  //! \param[in] value_ptr A pointer to the value for the annotation. The
+  //!     pointer may not be changed once associated with an annotation, but
+  //!     the data may be mutated.
+  constexpr Annotation(Type type, const char name[], void* const value_ptr)
+      : link_node_(nullptr),
+        name_(name),
+        value_ptr_(value_ptr),
+        size_(0),
+        type_(type) {}
+
+  //! \brief Specifies the number of bytes in \a value_ptr_ to include when
+  //!     generating a crash report.
+  //!
+  //! A size of `0` indicates that no value should be recorded and is the
+  //! equivalent of calling \sa Clear().
+  //!
+  //! This method does not mutate the data referenced by the annotation, it
+  //! merely updates the annotation system's bookkeeping.
+  //!
+  //! Subclasses of this base class that provide additional Set methods to
+  //! mutate the value of the annotation must call always call this method.
+  //!
+  //! \param[in] size The number of bytes.
+  void SetSize(ValueSizeType size);
+
+  //! \brief Marks the annotation as cleared, indicating the \a value_ptr_
+  //!     should not be included in a crash report.
+  //!
+  //! This method does not mutate the data referenced by the annotation, it
+  //! merely updates the annotation system's bookkeeping.
+  void Clear();
+
+  //! \brief Tests whether the annotation has been set.
+  bool is_set() const { return size_ > 0; }
+
+  Type type() const { return type_; }
+  ValueSizeType size() const { return size_; }
+  const char* name() const { return name_; }
+  const void* value() const { return value_ptr_; }
+
+ protected:
+  friend class AnnotationList;
+
+  std::atomic<Annotation*>& link_node() { return link_node_; }
+
+ private:
+  //! \brief Linked list next-node pointer. Accessed only by \sa AnnotationList.
+  //!
+  //! This will be null until the first call to \sa SetSize(), after which the
+  //! presence of the pointer will prevent the node from being added to the
+  //! list again.
+  std::atomic<Annotation*> link_node_;
+
+  const char* const name_;
+  void* const value_ptr_;
+  ValueSizeType size_;
+  const Type type_;
+
+  DISALLOW_COPY_AND_ASSIGN(Annotation);
+};
+
+//! \brief An \sa Annotation that stores a `NUL`-terminated C-string value.
+//!
+//! The storage for the value is allocated by the annotation and the template
+//! parameter \a MaxSize controls the maxmium length for the value.
+//!
+//! It is expected that the string value be valid UTF-8, although this is not
+//! validated.
+template <Annotation::ValueSizeType MaxSize>
+class StringAnnotation : public Annotation {
+ public:
+  //! \brief Constructs a new StringAnnotation with the given \a name.
+  //!
+  //! \param[in] name The Annotation name.
+  constexpr explicit StringAnnotation(const char name[])
+      : Annotation(Type::kString, name, value_), value_() {}
+
+  //! \brief Sets the Annotation's string value.
+  //!
+  //! \param[in] value The `NUL`-terminated C-string value.
+  void Set(const char* value) {
+    strncpy(value_, value, MaxSize);
+    SetSize(
+        std::min(MaxSize, base::saturated_cast<ValueSizeType>(strlen(value))));
+  }
+
+ private:
+  // This value is not `NUL`-terminated, since the size is stored by the base
+  // annotation.
+  char value_[MaxSize];
+
+  DISALLOW_COPY_AND_ASSIGN(StringAnnotation);
+};
+
+}  // namespace crashpad
+
+#endif  // CRASHPAD_CLIENT_ANNOTATION_H_
diff --git a/third_party/crashpad/crashpad/client/annotation_list.cc b/third_party/crashpad/crashpad/client/annotation_list.cc
new file mode 100644
index 0000000..10f5ea49
--- /dev/null
+++ b/third_party/crashpad/crashpad/client/annotation_list.cc
@@ -0,0 +1,97 @@
+// Copyright 2017 The Crashpad Authors. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "client/annotation_list.h"
+
+#include "base/logging.h"
+#include "client/crashpad_info.h"
+
+namespace crashpad {
+
+AnnotationList::AnnotationList()
+    : tail_pointer_(&tail_),
+      head_(Annotation::Type::kInvalid, nullptr, nullptr),
+      tail_(Annotation::Type::kInvalid, nullptr, nullptr) {
+  head_.link_node().store(&tail_);
+}
+
+AnnotationList::~AnnotationList() {}
+
+// static
+AnnotationList* AnnotationList::Get() {
+  return CrashpadInfo::GetCrashpadInfo()->annotations_list();
+}
+
+// static
+AnnotationList* AnnotationList::Register() {
+  AnnotationList* list = Get();
+  if (!list) {
+    list = new AnnotationList();
+    CrashpadInfo::GetCrashpadInfo()->set_annotations_list(list);
+  }
+  return list;
+}
+
+void AnnotationList::Add(Annotation* annotation) {
+  Annotation* null = nullptr;
+  Annotation* head_next = head_.link_node().load(std::memory_order_relaxed);
+  if (!annotation->link_node().compare_exchange_strong(null, head_next)) {
+    // If |annotation|'s link node is not null, then it has been added to the
+    // list already and no work needs to be done.
+    return;
+  }
+
+  // Check that the annotation's name is less than the maximum size. This is
+  // done here, since the Annotation constructor must be constexpr and this
+  // path is taken once per annotation.
+  DCHECK_LT(strlen(annotation->name_), Annotation::kNameMaxLength);
+
+  // Update the head link to point to the new |annotation|.
+  while (!head_.link_node().compare_exchange_weak(head_next, annotation)) {
+    // Another thread has updated the head-next pointer, so try again with the
+    // re-loaded |head_next|.
+    annotation->link_node().store(head_next, std::memory_order_relaxed);
+  }
+}
+
+AnnotationList::Iterator::Iterator(Annotation* head, const Annotation* tail)
+    : curr_(head), tail_(tail) {}
+
+AnnotationList::Iterator::~Iterator() = default;
+
+Annotation* AnnotationList::Iterator::operator*() const {
+  CHECK_NE(curr_, tail_);
+  return curr_;
+}
+
+AnnotationList::Iterator& AnnotationList::Iterator::operator++() {
+  CHECK_NE(curr_, tail_);
+  curr_ = curr_->link_node();
+  return *this;
+}
+
+bool AnnotationList::Iterator::operator==(
+    const AnnotationList::Iterator& other) const {
+  return curr_ == other.curr_;
+}
+
+AnnotationList::Iterator AnnotationList::begin() {
+  return Iterator(head_.link_node(), tail_pointer_);
+}
+
+AnnotationList::Iterator AnnotationList::end() {
+  return Iterator(&tail_, tail_pointer_);
+}
+
+}  // namespace crashpad
diff --git a/third_party/crashpad/crashpad/client/annotation_list.h b/third_party/crashpad/crashpad/client/annotation_list.h
new file mode 100644
index 0000000..9485c46c
--- /dev/null
+++ b/third_party/crashpad/crashpad/client/annotation_list.h
@@ -0,0 +1,94 @@
+// Copyright 2017 The Crashpad Authors. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#ifndef CRASHPAD_CLIENT_ANNOTATION_LIST_H_
+#define CRASHPAD_CLIENT_ANNOTATION_LIST_H_
+
+#include "base/macros.h"
+#include "client/annotation.h"
+
+namespace crashpad {
+
+//! \brief A list that contains all the currently set annotations.
+//!
+//! An instance of this class must be registered on the \a CrashpadInfo
+//! structure in order to use the annotations system. Once a list object has
+//! been registered on the CrashpadInfo, a different instance should not
+//! be used instead.
+class AnnotationList {
+ public:
+  AnnotationList();
+  ~AnnotationList();
+
+  //! \brief Returns the instance of the list that has been registered on the
+  //!     CrashapdInfo structure.
+  static AnnotationList* Get();
+
+  //! \brief Returns the instace of the list, creating and registering
+  //!     it if one is not already set on the CrashapdInfo structure.
+  static AnnotationList* Register();
+
+  //! \brief Adds \a annotation to the global list. This method does not need
+  //!     to be called by clients directly. The Annotation object will do so
+  //!     automatically.
+  //!
+  //! Once an annotation is added to the list, it is not removed. This is
+  //! because the AnnotationList avoids the use of locks/mutexes, in case it is
+  //! being manipulated in a compromised context. Instead, an Annotation keeps
+  //! track of when it has been cleared, which excludes it from a crash report.
+  //! This design also avoids linear scans of the list when repeatedly setting
+  //! and/or clearing the value.
+  void Add(Annotation* annotation);
+
+  //! \brief An InputIterator for the AnnotationList.
+  class Iterator {
+   public:
+    ~Iterator();
+
+    Annotation* operator*() const;
+    Iterator& operator++();
+    bool operator==(const Iterator& other) const;
+    bool operator!=(const Iterator& other) const { return !(*this == other); }
+
+   private:
+    friend class AnnotationList;
+    Iterator(Annotation* head, const Annotation* tail);
+
+    Annotation* curr_;
+    const Annotation* const tail_;
+
+    // Copy and assign are required.
+  };
+
+  //! \brief Returns an iterator to the first element of the annotation list.
+  Iterator begin();
+
+  //! \brief Returns an iterator past the last element of the annotation list.
+  Iterator end();
+
+ private:
+  // To make it easier for the handler to locate the dummy tail node, store the
+  // pointer. Placed first for packing.
+  const Annotation* const tail_pointer_;
+
+  // Dummy linked-list head and tail elements of \a Annotation::Type::kInvalid.
+  Annotation head_;
+  Annotation tail_;
+
+  DISALLOW_COPY_AND_ASSIGN(AnnotationList);
+};
+
+}  // namespace crashpad
+
+#endif  // CRASHPAD_CLIENT_ANNOTATION_LIST_H_
diff --git a/third_party/crashpad/crashpad/client/annotation_list_test.cc b/third_party/crashpad/crashpad/client/annotation_list_test.cc
new file mode 100644
index 0000000..ef3039c
--- /dev/null
+++ b/third_party/crashpad/crashpad/client/annotation_list_test.cc
@@ -0,0 +1,183 @@
+// Copyright 2017 The Crashpad Authors. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "client/annotation.h"
+
+#include <string>
+#include <vector>
+
+#include "base/rand_util.h"
+#include "client/crashpad_info.h"
+#include "gtest/gtest.h"
+#include "util/misc/clock.h"
+#include "util/thread/thread.h"
+
+namespace crashpad {
+namespace test {
+namespace {
+
+TEST(AnnotationListStatic, Register) {
+  ASSERT_FALSE(AnnotationList::Get());
+  EXPECT_TRUE(AnnotationList::Register());
+  EXPECT_TRUE(AnnotationList::Get());
+  EXPECT_EQ(AnnotationList::Get(), AnnotationList::Register());
+
+  // This isn't expected usage of the AnnotationList API, but it is necessary
+  // for testing.
+  AnnotationList* list = AnnotationList::Get();
+  CrashpadInfo::GetCrashpadInfo()->set_annotations_list(nullptr);
+  delete list;
+
+  EXPECT_FALSE(AnnotationList::Get());
+}
+
+class AnnotationList : public testing::Test {
+ public:
+  void SetUp() override {
+    CrashpadInfo::GetCrashpadInfo()->set_annotations_list(&annotations_);
+  }
+
+  void TearDown() override {
+    CrashpadInfo::GetCrashpadInfo()->set_annotations_list(nullptr);
+  }
+
+  // NOTE: Annotations should be declared at file-scope, but in order to test
+  // them, they are declared as part of the test. These members are public so
+  // they are accessible from global helpers.
+  crashpad::StringAnnotation<8> one_{"First"};
+  crashpad::StringAnnotation<256> two_{"Second"};
+  crashpad::StringAnnotation<101> three_{"First"};
+
+ protected:
+  using AllAnnotations = std::vector<std::pair<std::string, std::string>>;
+
+  AllAnnotations CollectAnnotations() {
+    AllAnnotations annotations;
+
+    for (Annotation* curr : annotations_) {
+      if (!curr->is_set())
+        continue;
+      std::string value(static_cast<const char*>(curr->value()), curr->size());
+      annotations.push_back(std::make_pair(curr->name(), value));
+    }
+
+    return annotations;
+  }
+
+  bool ContainsNameValue(const AllAnnotations& annotations,
+                         const std::string& name,
+                         const std::string& value) {
+    return std::find(annotations.begin(),
+                     annotations.end(),
+                     std::make_pair(name, value)) != annotations.end();
+  }
+
+  crashpad::AnnotationList annotations_;
+};
+
+TEST_F(AnnotationList, SetAndClear) {
+  one_.Set("this is a value longer than 8 bytes");
+  AllAnnotations annotations = CollectAnnotations();
+
+  EXPECT_EQ(1u, annotations.size());
+  EXPECT_TRUE(ContainsNameValue(annotations, "First", "this is "));
+
+  one_.Clear();
+
+  EXPECT_EQ(0u, CollectAnnotations().size());
+
+  one_.Set("short");
+  two_.Set(std::string(500, 'A').data());
+
+  annotations = CollectAnnotations();
+  EXPECT_EQ(2u, annotations.size());
+
+  EXPECT_EQ(5u, one_.size());
+  EXPECT_EQ(256u, two_.size());
+
+  EXPECT_TRUE(ContainsNameValue(annotations, "First", "short"));
+  EXPECT_TRUE(ContainsNameValue(annotations, "Second", std::string(256, 'A')));
+}
+
+TEST_F(AnnotationList, DuplicateKeys) {
+  ASSERT_EQ(0u, CollectAnnotations().size());
+
+  one_.Set("1");
+  three_.Set("2");
+
+  AllAnnotations annotations = CollectAnnotations();
+  EXPECT_EQ(2u, annotations.size());
+
+  EXPECT_TRUE(ContainsNameValue(annotations, "First", "1"));
+  EXPECT_TRUE(ContainsNameValue(annotations, "First", "2"));
+
+  one_.Clear();
+
+  annotations = CollectAnnotations();
+  EXPECT_EQ(1u, annotations.size());
+}
+
+class RaceThread : public Thread {
+ public:
+  explicit RaceThread(test::AnnotationList* test) : Thread(), test_(test) {}
+
+ private:
+  void ThreadMain() override {
+    for (int i = 0; i <= 50; ++i) {
+      if (i % 2 == 0) {
+        test_->three_.Set("three");
+        test_->two_.Clear();
+      } else {
+        test_->three_.Clear();
+      }
+      SleepNanoseconds(base::RandInt(1, 1000));
+    }
+  }
+
+  test::AnnotationList* test_;
+};
+
+TEST_F(AnnotationList, MultipleThreads) {
+  ASSERT_EQ(0u, CollectAnnotations().size());
+
+  RaceThread other_thread(this);
+  other_thread.Start();
+
+  for (int i = 0; i <= 50; ++i) {
+    if (i % 2 == 0) {
+      one_.Set("one");
+      two_.Set("two");
+    } else {
+      one_.Clear();
+    }
+    SleepNanoseconds(base::RandInt(1, 1000));
+  }
+
+  other_thread.Join();
+
+  AllAnnotations annotations = CollectAnnotations();
+  EXPECT_GE(annotations.size(), 2u);
+  EXPECT_LE(annotations.size(), 3u);
+
+  EXPECT_TRUE(ContainsNameValue(annotations, "First", "one"));
+  EXPECT_TRUE(ContainsNameValue(annotations, "First", "three"));
+
+  if (annotations.size() == 3) {
+    EXPECT_TRUE(ContainsNameValue(annotations, "Second", "two"));
+  }
+}
+
+}  // namespace
+}  // namespace test
+}  // namespace crashpad
diff --git a/third_party/crashpad/crashpad/client/annotation_test.cc b/third_party/crashpad/crashpad/client/annotation_test.cc
new file mode 100644
index 0000000..2553071
--- /dev/null
+++ b/third_party/crashpad/crashpad/client/annotation_test.cc
@@ -0,0 +1,112 @@
+// Copyright 2017 The Crashpad Authors. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "client/annotation.h"
+
+#include <string>
+
+#include "client/annotation_list.h"
+#include "client/crashpad_info.h"
+#include "gtest/gtest.h"
+
+namespace crashpad {
+namespace test {
+namespace {
+
+class Annotation : public testing::Test {
+ public:
+  void SetUp() override {
+    CrashpadInfo::GetCrashpadInfo()->set_annotations_list(&annotations_);
+  }
+
+  void TearDown() override {
+    CrashpadInfo::GetCrashpadInfo()->set_annotations_list(nullptr);
+  }
+
+  size_t AnnotationsCount() {
+    size_t result = 0;
+    for (auto* annotation : annotations_) {
+      if (annotation->is_set())
+        ++result;
+    }
+    return result;
+  }
+
+ protected:
+  crashpad::AnnotationList annotations_;
+};
+
+TEST_F(Annotation, Basics) {
+  constexpr crashpad::Annotation::Type kType =
+      crashpad::Annotation::UserDefinedType(1);
+
+  const char kName[] = "annotation 1";
+  char buffer[1024];
+  crashpad::Annotation annotation(kType, kName, buffer);
+
+  EXPECT_FALSE(annotation.is_set());
+  EXPECT_EQ(0u, AnnotationsCount());
+
+  EXPECT_EQ(kType, annotation.type());
+  EXPECT_EQ(0u, annotation.size());
+  EXPECT_EQ(std::string(kName), annotation.name());
+  EXPECT_EQ(buffer, annotation.value());
+
+  annotation.SetSize(10);
+
+  EXPECT_TRUE(annotation.is_set());
+  EXPECT_EQ(1u, AnnotationsCount());
+
+  EXPECT_EQ(10u, annotation.size());
+  EXPECT_EQ(&annotation, *annotations_.begin());
+
+  annotation.Clear();
+
+  EXPECT_FALSE(annotation.is_set());
+  EXPECT_EQ(0u, AnnotationsCount());
+
+  EXPECT_EQ(0u, annotation.size());
+}
+
+TEST_F(Annotation, StringType) {
+  crashpad::StringAnnotation<5> annotation("name");
+  const char* value_ptr = static_cast<const char*>(annotation.value());
+
+  EXPECT_FALSE(annotation.is_set());
+
+  EXPECT_EQ(crashpad::Annotation::Type::kString, annotation.type());
+  EXPECT_EQ(0u, annotation.size());
+  EXPECT_EQ(std::string("name"), annotation.name());
+  EXPECT_EQ(0u, strlen(value_ptr));
+
+  annotation.Set("test");
+
+  EXPECT_TRUE(annotation.is_set());
+  EXPECT_EQ(1u, AnnotationsCount());
+
+  EXPECT_EQ(4u, annotation.size());
+  EXPECT_EQ(std::string("test"), value_ptr);
+
+  annotation.Set("loooooooooooong");
+
+  EXPECT_TRUE(annotation.is_set());
+  EXPECT_EQ(1u, AnnotationsCount());
+
+  EXPECT_EQ(5u, annotation.size());
+  EXPECT_EQ(std::string("loooo"), std::string(value_ptr, annotation.size()));
+}
+
+}  // namespace
+}  // namespace test
+}  // namespace crashpad
diff --git a/third_party/crashpad/crashpad/client/client.gyp b/third_party/crashpad/crashpad/client/client.gyp
index 0e4a89d8..4b14c4bf 100644
--- a/third_party/crashpad/crashpad/client/client.gyp
+++ b/third_party/crashpad/crashpad/client/client.gyp
@@ -29,6 +29,10 @@
         '..',
       ],
       'sources': [
+        'annotation.cc',
+        'annotation.h',
+        'annotation_list.cc',
+        'annotation_list.h',
         'capture_context_mac.S',
         'capture_context_mac.h',
         'crash_report_database.cc',
diff --git a/third_party/crashpad/crashpad/client/client_test.gyp b/third_party/crashpad/crashpad/client/client_test.gyp
index 03cde2c..4ea4ef2 100644
--- a/third_party/crashpad/crashpad/client/client_test.gyp
+++ b/third_party/crashpad/crashpad/client/client_test.gyp
@@ -35,6 +35,8 @@
         '..',
       ],
       'sources': [
+        'annotation_test.cc',
+        'annotation_list_test.cc',
         'capture_context_mac_test.cc',
         'crash_report_database_test.cc',
         'crashpad_client_win_test.cc',
diff --git a/third_party/crashpad/crashpad/client/crashpad_info.cc b/third_party/crashpad/crashpad/client/crashpad_info.cc
index 18866ba..9452382b 100644
--- a/third_party/crashpad/crashpad/client/crashpad_info.cc
+++ b/third_party/crashpad/crashpad/client/crashpad_info.cc
@@ -105,7 +105,8 @@
       padding_1_(0),
       extra_memory_ranges_(nullptr),
       simple_annotations_(nullptr),
-      user_data_minidump_stream_head_(nullptr)
+      user_data_minidump_stream_head_(nullptr),
+      annotations_list_(nullptr)
 #if !defined(NDEBUG) && defined(OS_WIN)
       ,
       invalid_read_detection_(0xbadc0de)
diff --git a/third_party/crashpad/crashpad/client/crashpad_info.h b/third_party/crashpad/crashpad/client/crashpad_info.h
index 77c9097..7ce55ed 100644
--- a/third_party/crashpad/crashpad/client/crashpad_info.h
+++ b/third_party/crashpad/crashpad/client/crashpad_info.h
@@ -19,6 +19,7 @@
 
 #include "base/macros.h"
 #include "build/build_config.h"
+#include "client/annotation_list.h"
 #include "client/simple_address_range_bag.h"
 #include "client/simple_string_dictionary.h"
 #include "util/misc/tri_state.h"
@@ -109,6 +110,33 @@
     return simple_annotations_;
   }
 
+  //! \brief Sets the annotations list.
+  //!
+  //! Unlike the \a simple_annotations structure, the \a annotations can
+  //! typed data and it is not limited to a dictionary form. Annotations are
+  //! interpreted by Crashpad as module-level annotations.
+  //!
+  //! Annotations may exist in \a annotations_list at the time that this
+  //! method is called, or they may be added, removed, or modified in \a
+  //! annotations_list after this method is called.
+  //!
+  //! \param[in] annotations_list A list of set Annotation objects that maintain
+  //!     arbitrary, typed key-value state. The CrashpadInfo object does not
+  //!     take ownership of the AnnotationsList object. It is the caller’s
+  //!     responsibility to ensure that this pointer remains valid while it is
+  //!     in effect for a CrashpadInfo object.
+  //!
+  //! \sa annotations_list()
+  //! \sa AnnotationList::Register()
+  void set_annotations_list(AnnotationList* list) { annotations_list_ = list; }
+
+  //! \return The annotations list.
+  //!
+  //! \sa set_annotations_list()
+  //! \sa AnnotationList::Get()
+  //! \sa AnnotationList::Register()
+  AnnotationList* annotations_list() const { return annotations_list_; }
+
   //! \brief Enables or disables Crashpad handler processing.
   //!
   //! When handling an exception, the Crashpad handler will scan all modules in
@@ -218,6 +246,7 @@
   SimpleAddressRangeBag* extra_memory_ranges_;  // weak
   SimpleStringDictionary* simple_annotations_;  // weak
   internal::UserDataMinidumpStreamListEntry* user_data_minidump_stream_head_;
+  AnnotationList* annotations_list_;  // weak
 
 #if !defined(NDEBUG) && defined(OS_WIN)
   uint32_t invalid_read_detection_;
diff --git a/third_party/crashpad/crashpad/compat/compat.gyp b/third_party/crashpad/crashpad/compat/compat.gyp
index 52cca46..b0aec0af 100644
--- a/third_party/crashpad/crashpad/compat/compat.gyp
+++ b/third_party/crashpad/crashpad/compat/compat.gyp
@@ -54,6 +54,7 @@
         'win/sys/types.h',
         'win/time.cc',
         'win/time.h',
+        'win/winbase.h',
         'win/winnt.h',
         'win/winternl.h',
       ],
diff --git a/third_party/crashpad/crashpad/compat/win/winbase.h b/third_party/crashpad/crashpad/compat/win/winbase.h
new file mode 100644
index 0000000..ffd850b
--- /dev/null
+++ b/third_party/crashpad/crashpad/compat/win/winbase.h
@@ -0,0 +1,27 @@
+// Copyright 2017 The Crashpad Authors. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#ifndef CRASHPAD_COMPAT_WIN_WINBASE_H_
+#define CRASHPAD_COMPAT_WIN_WINBASE_H_
+
+// include_next <winbase.h>
+#include <../um/winbase.h>
+
+// 10.0.15063.0 SDK
+
+#ifndef SYMBOLIC_LINK_FLAG_ALLOW_UNPRIVILEGED_CREATE
+#define SYMBOLIC_LINK_FLAG_ALLOW_UNPRIVILEGED_CREATE (0x2)
+#endif
+
+#endif  // CRASHPAD_COMPAT_WIN_WINBASE_H_
diff --git a/third_party/crashpad/crashpad/handler/crashpad_handler_test.cc b/third_party/crashpad/crashpad/handler/crashpad_handler_test.cc
index 125157ff..1534443 100644
--- a/third_party/crashpad/crashpad/handler/crashpad_handler_test.cc
+++ b/third_party/crashpad/crashpad/handler/crashpad_handler_test.cc
@@ -28,11 +28,14 @@
 #include "test/test_paths.h"
 #include "test/win/win_multiprocess_with_temp_dir.h"
 #include "util/file/file_reader.h"
+#include "util/win/capture_context.h"
 
 namespace crashpad {
 namespace test {
 namespace {
 
+constexpr DWORD kExpectedExitCode = 0x1CEB00DA;
+
 void StartAndCrashWithExtendedHandler(const base::FilePath& temp_dir) {
   base::FilePath handler_path = TestPaths::Executable().DirName().Append(
       FILE_PATH_LITERAL("crashpad_handler_test_extended_handler.exe"));
@@ -47,7 +50,14 @@
                                   false,
                                   false));
 
-  __debugbreak();
+  // It appears that the GoogleTest fixture will catch and handle exceptions
+  // from here. Hence the fabricated crash in favor of raising an exception.
+  EXCEPTION_RECORD exception_record = {kExpectedExitCode,
+                                       EXCEPTION_NONCONTINUABLE};
+  CONTEXT context;
+  CaptureContext(&context);
+  EXCEPTION_POINTERS exception_pointers = {&exception_record, &context};
+  CrashpadClient::DumpAndCrash(&exception_pointers);
 }
 
 class CrashWithExtendedHandler final : public WinMultiprocessWithTempDir {
@@ -59,7 +69,7 @@
   void ValidateGeneratedDump();
 
   void WinMultiprocessParent() override {
-    SetExpectedChildExitCode(EXCEPTION_BREAKPOINT);
+    SetExpectedChildExitCode(kExpectedExitCode);
   }
 
   void WinMultiprocessChild() override {
diff --git a/third_party/crashpad/crashpad/snapshot/linux/process_reader.cc b/third_party/crashpad/crashpad/snapshot/linux/process_reader.cc
index 904fdce..c9a5a382 100644
--- a/third_party/crashpad/crashpad/snapshot/linux/process_reader.cc
+++ b/third_party/crashpad/crashpad/snapshot/linux/process_reader.cc
@@ -192,8 +192,7 @@
     return false;
   }
 
-  process_memory_.reset(new ProcessMemoryLinux());
-  if (!process_memory_->Initialize(pid)) {
+  if (!process_memory_.Initialize(pid)) {
     return false;
   }
 
diff --git a/third_party/crashpad/crashpad/snapshot/linux/process_reader.h b/third_party/crashpad/crashpad/snapshot/linux/process_reader.h
index 8570838..26d777e4 100644
--- a/third_party/crashpad/crashpad/snapshot/linux/process_reader.h
+++ b/third_party/crashpad/crashpad/snapshot/linux/process_reader.h
@@ -18,7 +18,6 @@
 #include <sys/time.h>
 #include <sys/types.h>
 
-#include <memory>
 #include <vector>
 
 #include "base/macros.h"
@@ -79,7 +78,7 @@
   pid_t ParentProcessID() const { return process_info_.ParentProcessID(); }
 
   //! \brief Return a memory reader for the target process.
-  ProcessMemory* Memory() { return process_memory_.get(); }
+  ProcessMemory* Memory() { return &process_memory_; }
 
   //! \brief Return a memory map of the target process.
   MemoryMap* GetMemoryMap() { return &memory_map_; }
@@ -113,9 +112,9 @@
 
   PtraceConnection* connection_;  // weak
   ProcessInfo process_info_;
-  class MemoryMap memory_map_;
+  MemoryMap memory_map_;
   std::vector<Thread> threads_;
-  std::unique_ptr<ProcessMemoryLinux> process_memory_;
+  ProcessMemoryLinux process_memory_;
   bool is_64_bit_;
   bool initialized_threads_;
   InitializationStateDcheck initialized_;
diff --git a/third_party/crashpad/crashpad/snapshot/linux/process_reader_test.cc b/third_party/crashpad/crashpad/snapshot/linux/process_reader_test.cc
index 5c8b8cb..08edf02 100644
--- a/third_party/crashpad/crashpad/snapshot/linux/process_reader_test.cc
+++ b/third_party/crashpad/crashpad/snapshot/linux/process_reader_test.cc
@@ -24,6 +24,7 @@
 #include <unistd.h>
 
 #include <map>
+#include <memory>
 #include <string>
 #include <utility>
 
diff --git a/third_party/crashpad/crashpad/snapshot/mac/process_types/crashpad_info.proctype b/third_party/crashpad/crashpad/snapshot/mac/process_types/crashpad_info.proctype
index 713bb09..41af5fc9 100644
--- a/third_party/crashpad/crashpad/snapshot/mac/process_types/crashpad_info.proctype
+++ b/third_party/crashpad/crashpad/snapshot/mac/process_types/crashpad_info.proctype
@@ -47,4 +47,7 @@
 
   // UserDataStreamListEntry*
   PROCESS_TYPE_STRUCT_MEMBER(Pointer, user_data_minidump_stream_head)
+
+  // AnnotationList*
+  PROCESS_TYPE_STRUCT_MEMBER(Pointer, annotations_list)
 PROCESS_TYPE_STRUCT_END(CrashpadInfo)
diff --git a/third_party/crashpad/crashpad/snapshot/win/end_to_end_test.py b/third_party/crashpad/crashpad/snapshot/win/end_to_end_test.py
index e6df56e9..c640a548 100755
--- a/third_party/crashpad/crashpad/snapshot/win/end_to_end_test.py
+++ b/third_party/crashpad/crashpad/snapshot/win/end_to_end_test.py
@@ -462,7 +462,7 @@
       return 1
 
     z7_dump_path = None
-    if not args[0].endswith('x64'):
+    if not args[0].endswith('_x64'):
       z7_dump_path = GetDumpFromZ7Program(args[0], pipe_name)
       if not z7_dump_path:
         return 1
diff --git a/third_party/crashpad/crashpad/snapshot/win/exception_snapshot_win_test.cc b/third_party/crashpad/crashpad/snapshot/win/exception_snapshot_win_test.cc
index cc8dd9d..a782ae6 100644
--- a/third_party/crashpad/crashpad/snapshot/win/exception_snapshot_win_test.cc
+++ b/third_party/crashpad/crashpad/snapshot/win/exception_snapshot_win_test.cc
@@ -23,6 +23,7 @@
 #include "gtest/gtest.h"
 #include "snapshot/win/process_snapshot_win.h"
 #include "test/errors.h"
+#include "test/gtest_disabled.h"
 #include "test/test_paths.h"
 #include "test/win/child_launcher.h"
 #include "util/file/file_io.h"
@@ -120,7 +121,7 @@
   DISALLOW_COPY_AND_ASSIGN(CrashingDelegate);
 };
 
-void TestCrashingChild(const base::string16& directory_modification) {
+void TestCrashingChild(const base::FilePath& directory) {
   // Set up the registration server on a background thread.
   ScopedKernelHANDLE server_ready(CreateEvent(nullptr, false, false, nullptr));
   ASSERT_TRUE(server_ready.is_valid()) << ErrorMessage("CreateEvent");
@@ -140,13 +141,13 @@
       << ErrorMessage("WaitForSingleObject");
 
   // Spawn a child process, passing it the pipe name to connect to.
-  base::FilePath test_executable = TestPaths::Executable();
-  std::wstring child_test_executable =
-      test_executable.DirName()
-          .Append(directory_modification)
-          .Append(test_executable.BaseName().RemoveFinalExtension().value() +
-                  L"_crashing_child.exe")
-          .value();
+  std::wstring child_test_executable = directory
+                                           .Append(TestPaths::Executable()
+                                                       .BaseName()
+                                                       .RemoveFinalExtension()
+                                                       .value() +
+                                                   L"_crashing_child.exe")
+                                           .value();
   ChildLauncher child(child_test_executable, pipe_name);
   ASSERT_NO_FATAL_FAILURE(child.Start());
 
@@ -165,16 +166,17 @@
 }
 
 TEST(ExceptionSnapshotWinTest, ChildCrash) {
-  TestCrashingChild(FILE_PATH_LITERAL("."));
+  TestCrashingChild(TestPaths::Executable().DirName());
 }
 
 #if defined(ARCH_CPU_64_BITS)
 TEST(ExceptionSnapshotWinTest, ChildCrashWOW64) {
-#ifndef NDEBUG
-  TestCrashingChild(FILE_PATH_LITERAL("..\\..\\out\\Debug"));
-#else
-  TestCrashingChild(FILE_PATH_LITERAL("..\\..\\out\\Release"));
-#endif
+  base::FilePath output_32_bit_directory = TestPaths::Output32BitDirectory();
+  if (output_32_bit_directory.empty()) {
+    DISABLED_TEST();
+  }
+
+  TestCrashingChild(output_32_bit_directory);
 }
 #endif  // ARCH_CPU_64_BITS
 
@@ -227,8 +229,7 @@
   DISALLOW_COPY_AND_ASSIGN(SimulateDelegate);
 };
 
-void TestDumpWithoutCrashingChild(
-    const base::string16& directory_modification) {
+void TestDumpWithoutCrashingChild(const base::FilePath& directory) {
   // Set up the registration server on a background thread.
   ScopedKernelHANDLE server_ready(CreateEvent(nullptr, false, false, nullptr));
   ASSERT_TRUE(server_ready.is_valid()) << ErrorMessage("CreateEvent");
@@ -248,11 +249,12 @@
       << ErrorMessage("WaitForSingleObject");
 
   // Spawn a child process, passing it the pipe name to connect to.
-  base::FilePath test_executable = TestPaths::Executable();
   std::wstring child_test_executable =
-      test_executable.DirName()
-          .Append(directory_modification)
-          .Append(test_executable.BaseName().RemoveFinalExtension().value() +
+      directory
+          .Append(TestPaths::Executable()
+                      .BaseName()
+                      .RemoveFinalExtension()
+                      .value() +
                   L"_dump_without_crashing.exe")
           .value();
   ChildLauncher child(child_test_executable, pipe_name);
@@ -273,16 +275,17 @@
 }
 
 TEST(SimulateCrash, ChildDumpWithoutCrashing) {
-  TestDumpWithoutCrashingChild(FILE_PATH_LITERAL("."));
+  TestDumpWithoutCrashingChild(TestPaths::Executable().DirName());
 }
 
 #if defined(ARCH_CPU_64_BITS)
 TEST(SimulateCrash, ChildDumpWithoutCrashingWOW64) {
-#ifndef NDEBUG
-  TestDumpWithoutCrashingChild(FILE_PATH_LITERAL("..\\..\\out\\Debug"));
-#else
-  TestDumpWithoutCrashingChild(FILE_PATH_LITERAL("..\\..\\out\\Release"));
-#endif
+  base::FilePath output_32_bit_directory = TestPaths::Output32BitDirectory();
+  if (output_32_bit_directory.empty()) {
+    DISABLED_TEST();
+  }
+
+  TestDumpWithoutCrashingChild(output_32_bit_directory);
 }
 #endif  // ARCH_CPU_64_BITS
 
diff --git a/third_party/crashpad/crashpad/snapshot/win/extra_memory_ranges_test.cc b/third_party/crashpad/crashpad/snapshot/win/extra_memory_ranges_test.cc
index a012027b..d0820a0 100644
--- a/third_party/crashpad/crashpad/snapshot/win/extra_memory_ranges_test.cc
+++ b/third_party/crashpad/crashpad/snapshot/win/extra_memory_ranges_test.cc
@@ -25,6 +25,7 @@
 #include "client/simple_address_range_bag.h"
 #include "gtest/gtest.h"
 #include "snapshot/win/process_snapshot_win.h"
+#include "test/gtest_disabled.h"
 #include "test/test_paths.h"
 #include "test/win/child_launcher.h"
 #include "util/file/file_io.h"
@@ -42,16 +43,15 @@
   kCrashDebugBreak,
 };
 
-void TestExtraMemoryRanges(TestType type,
-                           const base::string16& directory_modification) {
+void TestExtraMemoryRanges(TestType type, const base::FilePath& directory) {
   // Spawn a child process, passing it the pipe name to connect to.
-  base::FilePath test_executable = TestPaths::Executable();
-  std::wstring child_test_executable =
-      test_executable.DirName()
-          .Append(directory_modification)
-          .Append(test_executable.BaseName().RemoveFinalExtension().value() +
-                  L"_extra_memory_ranges.exe")
-          .value();
+  std::wstring child_test_executable = directory
+                                           .Append(TestPaths::Executable()
+                                                       .BaseName()
+                                                       .RemoveFinalExtension()
+                                                       .value() +
+                                                   L"_extra_memory_ranges.exe")
+                                           .value();
   ChildLauncher child(child_test_executable, L"");
   ASSERT_NO_FATAL_FAILURE(child.Start());
 
@@ -101,30 +101,30 @@
 }
 
 TEST(ExtraMemoryRanges, DontCrash) {
-  TestExtraMemoryRanges(kDontCrash, FILE_PATH_LITERAL("."));
+  TestExtraMemoryRanges(kDontCrash, TestPaths::Executable().DirName());
 }
 
 TEST(ExtraMemoryRanges, CrashDebugBreak) {
-  TestExtraMemoryRanges(kCrashDebugBreak, FILE_PATH_LITERAL("."));
+  TestExtraMemoryRanges(kCrashDebugBreak, TestPaths::Executable().DirName());
 }
 
 #if defined(ARCH_CPU_64_BITS)
 TEST(ExtraMemoryRanges, DontCrashWOW64) {
-#ifndef NDEBUG
-  TestExtraMemoryRanges(kDontCrash, FILE_PATH_LITERAL("..\\..\\out\\Debug"));
-#else
-  TestExtraMemoryRanges(kDontCrash, FILE_PATH_LITERAL("..\\..\\out\\Release"));
-#endif
+  base::FilePath output_32_bit_directory = TestPaths::Output32BitDirectory();
+  if (output_32_bit_directory.empty()) {
+    DISABLED_TEST();
+  }
+
+  TestExtraMemoryRanges(kDontCrash, output_32_bit_directory);
 }
 
 TEST(ExtraMemoryRanges, CrashDebugBreakWOW64) {
-#ifndef NDEBUG
-  TestExtraMemoryRanges(kCrashDebugBreak,
-                        FILE_PATH_LITERAL("..\\..\\out\\Debug"));
-#else
-  TestExtraMemoryRanges(kCrashDebugBreak,
-                        FILE_PATH_LITERAL("..\\..\\out\\Release"));
-#endif
+  base::FilePath output_32_bit_directory = TestPaths::Output32BitDirectory();
+  if (output_32_bit_directory.empty()) {
+    DISABLED_TEST();
+  }
+
+  TestExtraMemoryRanges(kCrashDebugBreak, output_32_bit_directory);
 }
 #endif  // ARCH_CPU_64_BITS
 
diff --git a/third_party/crashpad/crashpad/snapshot/win/pe_image_annotations_reader_test.cc b/third_party/crashpad/crashpad/snapshot/win/pe_image_annotations_reader_test.cc
index a20e986..f69f5ab 100644
--- a/third_party/crashpad/crashpad/snapshot/win/pe_image_annotations_reader_test.cc
+++ b/third_party/crashpad/crashpad/snapshot/win/pe_image_annotations_reader_test.cc
@@ -29,6 +29,7 @@
 #include "gtest/gtest.h"
 #include "snapshot/win/pe_image_reader.h"
 #include "snapshot/win/process_reader_win.h"
+#include "test/gtest_disabled.h"
 #include "test/test_paths.h"
 #include "test/win/child_launcher.h"
 #include "util/file/file_io.h"
@@ -46,16 +47,15 @@
   kCrashDebugBreak,
 };
 
-void TestAnnotationsOnCrash(TestType type,
-                            const base::string16& directory_modification) {
+void TestAnnotationsOnCrash(TestType type, const base::FilePath& directory) {
   // Spawn a child process, passing it the pipe name to connect to.
-  base::FilePath test_executable = TestPaths::Executable();
-  std::wstring child_test_executable =
-      test_executable.DirName()
-          .Append(directory_modification)
-          .Append(test_executable.BaseName().RemoveFinalExtension().value() +
-                  L"_simple_annotations.exe")
-          .value();
+  std::wstring child_test_executable = directory
+                                           .Append(TestPaths::Executable()
+                                                       .BaseName()
+                                                       .RemoveFinalExtension()
+                                                       .value() +
+                                                   L"_simple_annotations.exe")
+                                           .value();
   ChildLauncher child(child_test_executable, L"");
   ASSERT_NO_FATAL_FAILURE(child.Start());
 
@@ -112,30 +112,30 @@
 }
 
 TEST(PEImageAnnotationsReader, DontCrash) {
-  TestAnnotationsOnCrash(kDontCrash, FILE_PATH_LITERAL("."));
+  TestAnnotationsOnCrash(kDontCrash, TestPaths::Executable().DirName());
 }
 
 TEST(PEImageAnnotationsReader, CrashDebugBreak) {
-  TestAnnotationsOnCrash(kCrashDebugBreak, FILE_PATH_LITERAL("."));
+  TestAnnotationsOnCrash(kCrashDebugBreak, TestPaths::Executable().DirName());
 }
 
 #if defined(ARCH_CPU_64_BITS)
 TEST(PEImageAnnotationsReader, DontCrashWOW64) {
-#ifndef NDEBUG
-  TestAnnotationsOnCrash(kDontCrash, FILE_PATH_LITERAL("..\\..\\out\\Debug"));
-#else
-  TestAnnotationsOnCrash(kDontCrash, FILE_PATH_LITERAL("..\\..\\out\\Release"));
-#endif
+  base::FilePath output_32_bit_directory = TestPaths::Output32BitDirectory();
+  if (output_32_bit_directory.empty()) {
+    DISABLED_TEST();
+  }
+
+  TestAnnotationsOnCrash(kDontCrash, output_32_bit_directory);
 }
 
 TEST(PEImageAnnotationsReader, CrashDebugBreakWOW64) {
-#ifndef NDEBUG
-  TestAnnotationsOnCrash(kCrashDebugBreak,
-                         FILE_PATH_LITERAL("..\\..\\out\\Debug"));
-#else
-  TestAnnotationsOnCrash(kCrashDebugBreak,
-                         FILE_PATH_LITERAL("..\\..\\out\\Release"));
-#endif
+  base::FilePath output_32_bit_directory = TestPaths::Output32BitDirectory();
+  if (output_32_bit_directory.empty()) {
+    DISABLED_TEST();
+  }
+
+  TestAnnotationsOnCrash(kCrashDebugBreak, output_32_bit_directory);
 }
 #endif  // ARCH_CPU_64_BITS
 
diff --git a/third_party/crashpad/crashpad/snapshot/win/pe_image_reader.h b/third_party/crashpad/crashpad/snapshot/win/pe_image_reader.h
index be18541..56a991b 100644
--- a/third_party/crashpad/crashpad/snapshot/win/pe_image_reader.h
+++ b/third_party/crashpad/crashpad/snapshot/win/pe_image_reader.h
@@ -48,6 +48,7 @@
   typename Traits::Pointer extra_address_ranges;
   typename Traits::Pointer simple_annotations;
   typename Traits::Pointer user_data_minidump_stream_head;
+  typename Traits::Pointer annotations_list;
 };
 
 }  // namespace process_types
diff --git a/third_party/crashpad/crashpad/snapshot/win/process_snapshot_win_test.cc b/third_party/crashpad/crashpad/snapshot/win/process_snapshot_win_test.cc
index 1bb2027..839ba48 100644
--- a/third_party/crashpad/crashpad/snapshot/win/process_snapshot_win_test.cc
+++ b/third_party/crashpad/crashpad/snapshot/win/process_snapshot_win_test.cc
@@ -20,6 +20,7 @@
 #include "snapshot/win/pe_image_reader.h"
 #include "snapshot/win/process_reader_win.h"
 #include "test/errors.h"
+#include "test/gtest_disabled.h"
 #include "test/test_paths.h"
 #include "test/win/child_launcher.h"
 #include "util/file/file_io.h"
@@ -30,20 +31,20 @@
 namespace test {
 namespace {
 
-void TestImageReaderChild(const base::string16& directory_modification) {
+void TestImageReaderChild(const base::FilePath& directory) {
   UUID done_uuid;
   done_uuid.InitializeWithNew();
   ScopedKernelHANDLE done(
       CreateEvent(nullptr, true, false, done_uuid.ToString16().c_str()));
   ASSERT_TRUE(done.is_valid()) << ErrorMessage("CreateEvent");
 
-  base::FilePath test_executable = TestPaths::Executable();
-  std::wstring child_test_executable =
-      test_executable.DirName()
-          .Append(directory_modification)
-          .Append(test_executable.BaseName().RemoveFinalExtension().value() +
-                  L"_image_reader.exe")
-          .value();
+  std::wstring child_test_executable = directory
+                                           .Append(TestPaths::Executable()
+                                                       .BaseName()
+                                                       .RemoveFinalExtension()
+                                                       .value() +
+                                                   L"_image_reader.exe")
+                                           .value();
   ChildLauncher child(child_test_executable, done_uuid.ToString16());
   ASSERT_NO_FATAL_FAILURE(child.Start());
 
@@ -112,16 +113,17 @@
 }
 
 TEST(ProcessSnapshotTest, CrashpadInfoChild) {
-  TestImageReaderChild(FILE_PATH_LITERAL("."));
+  TestImageReaderChild(TestPaths::Executable().DirName());
 }
 
 #if defined(ARCH_CPU_64_BITS)
 TEST(ProcessSnapshotTest, CrashpadInfoChildWOW64) {
-#ifndef NDEBUG
-  TestImageReaderChild(FILE_PATH_LITERAL("..\\..\\out\\Debug"));
-#else
-  TestImageReaderChild(FILE_PATH_LITERAL("..\\..\\out\\Release"));
-#endif
+  base::FilePath output_32_bit_directory = TestPaths::Output32BitDirectory();
+  if (output_32_bit_directory.empty()) {
+    DISABLED_TEST();
+  }
+
+  TestImageReaderChild(output_32_bit_directory);
 }
 #endif
 
diff --git a/third_party/crashpad/crashpad/test/gmock_main.cc b/third_party/crashpad/crashpad/test/gmock_main.cc
deleted file mode 100644
index 7f7bc93..0000000
--- a/third_party/crashpad/crashpad/test/gmock_main.cc
+++ /dev/null
@@ -1,38 +0,0 @@
-// Copyright 2017 The Crashpad Authors. All rights reserved.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//     http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-#include "gmock/gmock.h"
-#include "gtest/gtest.h"
-#include "test/main_arguments.h"
-
-#if defined(CRASHPAD_IN_CHROMIUM)
-#include "base/bind.h"
-#include "base/test/launcher/unit_test_launcher.h"
-#include "base/test/test_suite.h"
-#endif
-
-int main(int argc, char* argv[]) {
-  crashpad::test::InitializeMainArguments(argc, argv);
-#if defined(CRASHPAD_IN_CHROMIUM)
-  // Writes a json file with test details which is needed by swarming.
-  base::TestSuite test_suite(argc, argv);
-  return base::LaunchUnitTests(
-      argc,
-      argv,
-      base::Bind(&base::TestSuite::Run, base::Unretained(&test_suite)));
-#else
-  testing::InitGoogleMock(&argc, argv);
-  return RUN_ALL_TESTS();
-#endif
-}
diff --git a/third_party/crashpad/crashpad/test/gtest_disabled.cc b/third_party/crashpad/crashpad/test/gtest_disabled.cc
new file mode 100644
index 0000000..fab6802
--- /dev/null
+++ b/third_party/crashpad/crashpad/test/gtest_disabled.cc
@@ -0,0 +1,83 @@
+// Copyright 2017 The Crashpad Authors. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "test/gtest_disabled.h"
+
+#include <stdio.h>
+
+#include "base/format_macros.h"
+#include "base/logging.h"
+#include "base/strings/stringprintf.h"
+
+namespace crashpad {
+namespace test {
+
+namespace {
+
+DisabledTestGtestEnvironment* g_instance;
+
+}  // namespace
+
+// static
+DisabledTestGtestEnvironment* DisabledTestGtestEnvironment::Get() {
+  if (!g_instance) {
+    g_instance = new DisabledTestGtestEnvironment();
+  }
+  return g_instance;
+}
+
+void DisabledTestGtestEnvironment::DisabledTest() {
+  const testing::TestInfo* test_info =
+      testing::UnitTest::GetInstance()->current_test_info();
+  std::string disabled_test = base::StringPrintf(
+      "%s.%s", test_info->test_case_name(), test_info->name());
+
+  // Show a DISABLED message using a format similar to gtest, along with a hint
+  // explaining that OK or FAILED will also appear.
+  printf(
+      "This test has been disabled dynamically.\n"
+      "It will appear as both DISABLED and OK or FAILED.\n"
+      "[ DISABLED ] %s\n",
+      disabled_test.c_str());
+
+  disabled_tests_.push_back(disabled_test);
+}
+
+DisabledTestGtestEnvironment::DisabledTestGtestEnvironment()
+    : testing::Environment(),
+      disabled_tests_() {
+  DCHECK(!g_instance);
+}
+
+DisabledTestGtestEnvironment::~DisabledTestGtestEnvironment() {
+  DCHECK_EQ(this, g_instance);
+  g_instance = nullptr;
+}
+
+void DisabledTestGtestEnvironment::TearDown() {
+  if (!disabled_tests_.empty()) {
+    printf(
+        "[ DISABLED ] %" PRIuS " dynamically disabled test%s, listed below:\n"
+        "[ DISABLED ] %s also counted in PASSED or FAILED below.\n",
+        disabled_tests_.size(),
+        disabled_tests_.size() == 1 ? "" : "s",
+        disabled_tests_.size() == 1 ? "This test is" : "These tests are");
+    for (const std::string& disabled_test : disabled_tests_) {
+      printf("[ DISABLED ] %s\n", disabled_test.c_str());
+    }
+  }
+}
+
+}  // namespace test
+}  // namespace crashpad
diff --git a/third_party/crashpad/crashpad/test/gtest_disabled.h b/third_party/crashpad/crashpad/test/gtest_disabled.h
new file mode 100644
index 0000000..9415cba
--- /dev/null
+++ b/third_party/crashpad/crashpad/test/gtest_disabled.h
@@ -0,0 +1,87 @@
+// Copyright 2017 The Crashpad Authors. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#ifndef CRASHPAD_TEST_GTEST_DISABLED_H_
+#define CRASHPAD_TEST_GTEST_DISABLED_H_
+
+#include <string>
+#include <vector>
+
+#include "base/macros.h"
+#include "gtest/gtest.h"
+
+//! \file
+
+namespace crashpad {
+namespace test {
+
+//! \brief Provides support for dynamically disabled gtest tests.
+//!
+//! A test runner must register this with gtest as follows prior to calling
+//! `RUN_ALL_TESTS()`:
+//! \code
+//!   testing::AddGlobalTestEnvironment(
+//!       crashpad::test::DisabledTestGtestEnvironment::Get());
+//! \endcode
+class DisabledTestGtestEnvironment final : public testing::Environment {
+ public:
+  //! \brief Returns the DisabledTestGtestEnvironment singleton instance,
+  //!     creating it if necessary.
+  static DisabledTestGtestEnvironment* Get();
+
+  //! \brief Displays a message about a test being disabled, and arranges for
+  //!     this information to be duplicated in TearDown().
+  //!
+  //! This method is for the internal use of the DISABLED_TEST() macro. Do not
+  //! call it directly, use the macro instead.
+  void DisabledTest();
+
+ private:
+  DisabledTestGtestEnvironment();
+  ~DisabledTestGtestEnvironment() override;
+
+  // testing::Environment:
+  void TearDown() override;
+
+  std::vector<std::string> disabled_tests_;
+
+  DISALLOW_COPY_AND_ASSIGN(DisabledTestGtestEnvironment);
+};
+
+}  // namespace test
+}  // namespace crashpad
+
+//! \brief Displays a message about a test being disabled, and returns early.
+//!
+//! gtest only provides a mechanism for tests to be disabled statically, by
+//! prefixing test case names or test names with `DISABLED_`. When it is
+//! necessary to disable tests dynamically, gtest provides no assistance. This
+//! macro displays a message about the disabled test and returns early. The
+//! dynamically disabled test will also be displayed during gtest global test
+//! environment tear-down before the test executable exits.
+//!
+//! This macro may only be invoked from the context of a gtest test.
+//!
+//! There’s a long-standing <a
+//! href="https://groups.google.com/d/topic/googletestframework/Nwh3u7YFuN4">gtest
+//! feature request</a> to provide this functionality directly in gtest, but
+//! since it hasn’t been implemented, this macro provides a local mechanism to
+//! achieve it.
+#define DISABLED_TEST()                                                    \
+  do {                                                                     \
+    ::crashpad::test::DisabledTestGtestEnvironment::Get()->DisabledTest(); \
+    return;                                                                \
+  } while (false)
+
+#endif  // CRASHPAD_TEST_GTEST_DISABLED_H_
diff --git a/third_party/crashpad/crashpad/test/gtest_main.cc b/third_party/crashpad/crashpad/test/gtest_main.cc
index c3f6899c..6e082828 100644
--- a/third_party/crashpad/crashpad/test/gtest_main.cc
+++ b/third_party/crashpad/crashpad/test/gtest_main.cc
@@ -12,26 +12,62 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
+#include "build/build_config.h"
 #include "gtest/gtest.h"
+#include "test/gtest_disabled.h"
 #include "test/main_arguments.h"
 
+#if defined(CRASHPAD_TEST_LAUNCHER_GMOCK)
+#include "gmock/gmock.h"
+#endif  // CRASHPAD_TEST_LAUNCHER_GMOCK
+
+#if defined(OS_WIN)
+#include "test/win/win_child_process.h"
+#endif  // OS_WIN
+
 #if defined(CRASHPAD_IN_CHROMIUM)
 #include "base/bind.h"
 #include "base/test/launcher/unit_test_launcher.h"
 #include "base/test/test_suite.h"
-#endif
+#endif  // CRASHPAD_IN_CHROMIUM
 
 int main(int argc, char* argv[]) {
   crashpad::test::InitializeMainArguments(argc, argv);
-#if defined(CRASHPAD_IN_CHROMIUM)
-  // Writes a json file with test details which is needed by swarming.
-  base::TestSuite test_suite(argc, argv);
-  return base::LaunchUnitTests(
-      argc,
-      argv,
-      base::Bind(&base::TestSuite::Run, base::Unretained(&test_suite)));
-#else
+
+#if defined(CRASHPAD_TEST_LAUNCHER_GMOCK)
+  testing::InitGoogleMock(&argc, argv);
+#elif defined(CRASHPAD_TEST_LAUNCHER_GTEST)
   testing::InitGoogleTest(&argc, argv);
+#else  // CRASHPAD_TEST_LAUNCHER_GTEST
+#error #define CRASHPAD_TEST_LAUNCHER_GTEST or CRASHPAD_TEST_LAUNCHER_GMOCK
+#endif  // CRASHPAD_TEST_LAUNCHER_GTEST
+
+  testing::AddGlobalTestEnvironment(
+      crashpad::test::DisabledTestGtestEnvironment::Get());
+
+#if defined(CRASHPAD_IN_CHROMIUM)
+
+#if defined(OS_WIN)
+  // Chromium’s test launcher interferes with WinMultiprocess-based tests. Allow
+  // their child processes to be launched by the standard gtest-based test
+  // runner.
+  const bool use_chromium_test_launcher =
+      !crashpad::test::WinChildProcess::IsChildProcess();
+#else  // OS_WIN
+  constexpr bool use_chromium_test_launcher = true;
+#endif  // OS_WIN
+
+  if (use_chromium_test_launcher) {
+    // This supports --test-launcher-summary-output, which writes a JSON file
+    // containing test details needed by Swarming.
+    base::TestSuite test_suite(argc, argv);
+    return base::LaunchUnitTests(
+        argc,
+        argv,
+        base::Bind(&base::TestSuite::Run, base::Unretained(&test_suite)));
+  }
+
+#endif  // CRASHPAD_IN_CHROMIUM
+
   return RUN_ALL_TESTS();
-#endif
 }
diff --git a/third_party/crashpad/crashpad/test/test.gyp b/third_party/crashpad/crashpad/test/test.gyp
index 31a8381..931d948 100644
--- a/third_party/crashpad/crashpad/test/test.gyp
+++ b/third_party/crashpad/crashpad/test/test.gyp
@@ -36,6 +36,8 @@
         'file.cc',
         'file.h',
         'gtest_death_check.h',
+        'gtest_disabled.cc',
+        'gtest_disabled.h',
         'hex_string.cc',
         'hex_string.h',
         'linux/fake_ptrace_connection.cc',
@@ -100,26 +102,40 @@
       ],
     },
     {
-      'target_name': 'crashpad_gtest_main',
-      'type': 'static_library',
-      'dependencies': [
-        'crashpad_test',
-        '../third_party/gtest/gtest.gyp:gtest',
-      ],
-      'sources': [
-        'gtest_main.cc',
-      ],
-    },
-    {
       'target_name': 'crashpad_gmock_main',
       'type': 'static_library',
       'dependencies': [
         'crashpad_test',
         '../third_party/gtest/gmock.gyp:gmock',
         '../third_party/gtest/gtest.gyp:gtest',
+        '../third_party/mini_chromium/mini_chromium.gyp:base',
+      ],
+      'include_dirs': [
+        '..',
+      ],
+      'defines': [
+        'CRASHPAD_TEST_LAUNCHER_GMOCK=1',
       ],
       'sources': [
-        'gmock_main.cc',
+        'gtest_main.cc',
+      ],
+    },
+    {
+      'target_name': 'crashpad_gtest_main',
+      'type': 'static_library',
+      'dependencies': [
+        'crashpad_test',
+        '../third_party/gtest/gtest.gyp:gtest',
+        '../third_party/mini_chromium/mini_chromium.gyp:base',
+      ],
+      'include_dirs': [
+        '..',
+      ],
+      'defines': [
+        'CRASHPAD_TEST_LAUNCHER_GTEST=1',
+      ],
+      'sources': [
+        'gtest_main.cc',
       ],
     },
   ],
diff --git a/third_party/crashpad/crashpad/test/test_paths.cc b/third_party/crashpad/crashpad/test/test_paths.cc
index 4c256030..a601208 100644
--- a/third_party/crashpad/crashpad/test/test_paths.cc
+++ b/third_party/crashpad/crashpad/test/test_paths.cc
@@ -106,5 +106,19 @@
   return *test_data_root;
 }
 
+#if defined(OS_WIN) && defined(ARCH_CPU_64_BITS)
+
+// static
+base::FilePath TestPaths::Output32BitDirectory() {
+  const wchar_t* environment_value = _wgetenv(L"CRASHPAD_TEST_32_BIT_OUTPUT");
+  if (!environment_value) {
+    return base::FilePath();
+  }
+
+  return base::FilePath(environment_value);
+}
+
+#endif  // defined(OS_WIN) && defined(ARCH_CPU_64_BITS)
+
 }  // namespace test
 }  // namespace crashpad
diff --git a/third_party/crashpad/crashpad/test/test_paths.h b/third_party/crashpad/crashpad/test/test_paths.h
index 261ab91..f5629ed 100644
--- a/third_party/crashpad/crashpad/test/test_paths.h
+++ b/third_party/crashpad/crashpad/test/test_paths.h
@@ -17,6 +17,7 @@
 
 #include "base/files/file_path.h"
 #include "base/macros.h"
+#include "build/build_config.h"
 
 namespace crashpad {
 namespace test {
@@ -42,6 +43,22 @@
   //! files.
   static base::FilePath TestDataRoot();
 
+#if (defined(OS_WIN) && defined(ARCH_CPU_64_BITS)) || DOXYGEN
+  //! \brief Returns the pathname of a directory containing 32-bit test build
+  //!     output.
+  //!
+  //! Tests that require the use of 32-bit build output should call this
+  //! function to locate that output. This function is only provided to allow
+  //! 64-bit test code to locate 32-bit output. 32-bit test code can find 32-bit
+  //! output in its own directory, the parent of Executable().
+  //!
+  //! If the `CRASHPAD_TEST_32_BIT_OUTPUT` environment variable is set, its
+  //! value will be returned. Otherwise, this function will return an empty
+  //! path, and tests that require the use of 32-bit build output should disable
+  //! themselves. The DISABLED_TEST() macro may be useful for this purpose.
+  static base::FilePath Output32BitDirectory();
+#endif
+
   DISALLOW_IMPLICIT_CONSTRUCTORS(TestPaths);
 };
 
diff --git a/third_party/crashpad/crashpad/test/win/child_launcher.cc b/third_party/crashpad/crashpad/test/win/child_launcher.cc
index 4ab1c816..c5f897c3 100644
--- a/third_party/crashpad/crashpad/test/win/child_launcher.cc
+++ b/third_party/crashpad/crashpad/test/win/child_launcher.cc
@@ -15,6 +15,7 @@
 #include "test/win/child_launcher.h"
 
 #include "gtest/gtest.h"
+#include "test/errors.h"
 #include "util/win/command_line.h"
 
 namespace crashpad {
@@ -47,25 +48,31 @@
 
   HANDLE stdout_read;
   HANDLE stdout_write;
-  ASSERT_TRUE(CreatePipe(&stdout_read, &stdout_write, &security_attributes, 0));
+  ASSERT_TRUE(CreatePipe(&stdout_read, &stdout_write, &security_attributes, 0))
+      << ErrorMessage("CreatePipe");
   stdout_read_handle_.reset(stdout_read);
   ScopedFileHANDLE write_handle(stdout_write);
   ASSERT_TRUE(
-      SetHandleInformation(stdout_read_handle_.get(), HANDLE_FLAG_INHERIT, 0));
+      SetHandleInformation(stdout_read_handle_.get(), HANDLE_FLAG_INHERIT, 0))
+      << ErrorMessage("SetHandleInformation");
 
   HANDLE stdin_read;
   HANDLE stdin_write;
-  ASSERT_TRUE(CreatePipe(&stdin_read, &stdin_write, &security_attributes, 0));
+  ASSERT_TRUE(CreatePipe(&stdin_read, &stdin_write, &security_attributes, 0))
+      << ErrorMessage("CreatePipe");
   stdin_write_handle_.reset(stdin_write);
   ScopedFileHANDLE read_handle(stdin_read);
   ASSERT_TRUE(
-      SetHandleInformation(stdin_write_handle_.get(), HANDLE_FLAG_INHERIT, 0));
+      SetHandleInformation(stdin_write_handle_.get(), HANDLE_FLAG_INHERIT, 0))
+      << ErrorMessage("SetHandleInformation");
 
   STARTUPINFO startup_info = {0};
   startup_info.cb = sizeof(startup_info);
   startup_info.hStdInput = read_handle.get();
   startup_info.hStdOutput = write_handle.get();
   startup_info.hStdError = GetStdHandle(STD_ERROR_HANDLE);
+  EXPECT_NE(startup_info.hStdError, INVALID_HANDLE_VALUE)
+      << ErrorMessage("GetStdHandle");
   startup_info.dwFlags = STARTF_USESTDHANDLES;
   PROCESS_INFORMATION process_information;
   std::wstring command_line;
@@ -81,7 +88,8 @@
                             nullptr,
                             nullptr,
                             &startup_info,
-                            &process_information));
+                            &process_information))
+      << ErrorMessage("CreateProcess");
   // Take ownership of the two process handles returned.
   main_thread_handle_.reset(process_information.hThread);
   process_handle_.reset(process_information.hProcess);
@@ -89,10 +97,11 @@
 
 DWORD ChildLauncher::WaitForExit() {
   EXPECT_TRUE(process_handle_.is_valid());
-  EXPECT_EQ(WaitForSingleObject(process_handle_.get(), INFINITE),
-            WAIT_OBJECT_0);
+  EXPECT_EQ(WaitForSingleObject(process_handle_.get(), INFINITE), WAIT_OBJECT_0)
+      << ErrorMessage("WaitForSingleObject");
   DWORD exit_code = 0;
-  EXPECT_TRUE(GetExitCodeProcess(process_handle_.get(), &exit_code));
+  EXPECT_TRUE(GetExitCodeProcess(process_handle_.get(), &exit_code))
+      << ErrorMessage("GetExitCodeProcess");
   process_handle_.reset();
   return exit_code;
 }
diff --git a/third_party/crashpad/crashpad/test/win/win_child_process.cc b/third_party/crashpad/crashpad/test/win/win_child_process.cc
index 74687ee..14299e6 100644
--- a/third_party/crashpad/crashpad/test/win/win_child_process.cc
+++ b/third_party/crashpad/crashpad/test/win/win_child_process.cc
@@ -182,17 +182,20 @@
   }
 
   // Build a command line for the child process that tells it only to run the
-  // current test, and to pass down the values of the pipe handles.
+  // current test, and to pass down the values of the pipe handles. Use
+  // --gtest_also_run_disabled_tests because the test may be DISABLED_, but if
+  // it managed to run in the parent, disabled tests must be running.
   const ::testing::TestInfo* const test_info =
       ::testing::UnitTest::GetInstance()->current_test_info();
   std::wstring command_line =
-      TestPaths::Executable().value() + L" " +
-      base::UTF8ToUTF16(base::StringPrintf("--gtest_filter=%s.%s %s=0x%x|0x%x",
-                                           test_info->test_case_name(),
-                                           test_info->name(),
-                                           kIsMultiprocessChild,
-                                           HandleToInt(write_for_child.get()),
-                                           HandleToInt(read_for_child.get())));
+      TestPaths::Executable().value() +
+      base::UTF8ToUTF16(base::StringPrintf(
+          " --gtest_filter=%s.%s %s=0x%x|0x%x --gtest_also_run_disabled_tests",
+          test_info->test_case_name(),
+          test_info->name(),
+          kIsMultiprocessChild,
+          HandleToInt(write_for_child.get()),
+          HandleToInt(read_for_child.get())));
 
   // Command-line buffer cannot be constant, per CreateProcess signature.
   handles_for_parent->process = LaunchCommandLine(&command_line[0]);
diff --git a/third_party/crashpad/crashpad/util/file/directory_reader_test.cc b/third_party/crashpad/crashpad/util/file/directory_reader_test.cc
index da4bfb7..640b850 100644
--- a/third_party/crashpad/crashpad/util/file/directory_reader_test.cc
+++ b/third_party/crashpad/crashpad/util/file/directory_reader_test.cc
@@ -21,6 +21,7 @@
 #include "base/strings/stringprintf.h"
 #include "base/strings/utf_string_conversions.h"
 #include "gtest/gtest.h"
+#include "test/gtest_disabled.h"
 #include "test/scoped_temp_dir.h"
 #include "util/file/file_io.h"
 #include "util/file/filesystem.h"
@@ -30,6 +31,51 @@
 namespace test {
 namespace {
 
+TEST(DirectoryReader, BadPaths) {
+  DirectoryReader reader;
+  EXPECT_FALSE(reader.Open(base::FilePath()));
+
+  ScopedTempDir temp_dir;
+  base::FilePath file(temp_dir.path().Append(FILE_PATH_LITERAL("file")));
+  ASSERT_TRUE(CreateFile(file));
+  EXPECT_FALSE(reader.Open(file));
+
+  EXPECT_FALSE(
+      reader.Open(temp_dir.path().Append(FILE_PATH_LITERAL("doesntexist"))));
+}
+
+#if !defined(OS_FUCHSIA)
+
+TEST(DirectoryReader, BadPaths_SymbolicLinks) {
+  if (!CanCreateSymbolicLinks()) {
+    DISABLED_TEST();
+  }
+
+  ScopedTempDir temp_dir;
+  base::FilePath file(temp_dir.path().Append(FILE_PATH_LITERAL("file")));
+  ASSERT_TRUE(CreateFile(file));
+
+  base::FilePath link(temp_dir.path().Append(FILE_PATH_LITERAL("link")));
+  ASSERT_TRUE(CreateSymbolicLink(file, link));
+
+  DirectoryReader reader;
+  EXPECT_FALSE(reader.Open(link));
+
+  ASSERT_TRUE(LoggingRemoveFile(file));
+  EXPECT_FALSE(reader.Open(link));
+}
+
+#endif  // !OS_FUCHSIA
+
+TEST(DirectoryReader, EmptyDirectory) {
+  ScopedTempDir temp_dir;
+  DirectoryReader reader;
+
+  ASSERT_TRUE(reader.Open(temp_dir.path()));
+  base::FilePath filename;
+  EXPECT_EQ(reader.NextFile(&filename), DirectoryReader::Result::kNoMoreFiles);
+}
+
 void ExpectFiles(const std::set<base::FilePath>& files,
                  const std::set<base::FilePath>& expected) {
   EXPECT_EQ(files.size(), expected.size());
@@ -41,36 +87,7 @@
   }
 }
 
-TEST(DirectoryReader, BadPaths) {
-  DirectoryReader reader;
-  EXPECT_FALSE(reader.Open(base::FilePath()));
-
-  ScopedTempDir temp_dir;
-  base::FilePath file(temp_dir.path().Append(FILE_PATH_LITERAL("file")));
-  ASSERT_TRUE(CreateFile(file));
-  EXPECT_FALSE(reader.Open(file));
-
-  base::FilePath link(temp_dir.path().Append(FILE_PATH_LITERAL("link")));
-  ASSERT_TRUE(CreateSymbolicLink(file, link));
-  EXPECT_FALSE(reader.Open(link));
-
-  ASSERT_TRUE(LoggingRemoveFile(file));
-  EXPECT_FALSE(reader.Open(link));
-
-  EXPECT_FALSE(
-      reader.Open(temp_dir.path().Append(FILE_PATH_LITERAL("doesntexist"))));
-}
-
-TEST(DirectoryReader, EmptyDirectory) {
-  ScopedTempDir temp_dir;
-  DirectoryReader reader;
-
-  ASSERT_TRUE(reader.Open(temp_dir.path()));
-  base::FilePath filename;
-  EXPECT_EQ(reader.NextFile(&filename), DirectoryReader::Result::kNoMoreFiles);
-}
-
-TEST(DirectoryReader, FilesAndDirectories) {
+void TestFilesAndDirectories(bool symbolic_links) {
   ScopedTempDir temp_dir;
   std::set<base::FilePath> expected_files;
 
@@ -78,17 +95,6 @@
   ASSERT_TRUE(CreateFile(temp_dir.path().Append(file)));
   EXPECT_TRUE(expected_files.insert(file).second);
 
-  base::FilePath link(FILE_PATH_LITERAL("link"));
-  ASSERT_TRUE(CreateSymbolicLink(temp_dir.path().Append(file),
-                                 temp_dir.path().Append(link)));
-  EXPECT_TRUE(expected_files.insert(link).second);
-
-  base::FilePath dangling(FILE_PATH_LITERAL("dangling"));
-  ASSERT_TRUE(
-      CreateSymbolicLink(base::FilePath(FILE_PATH_LITERAL("not_a_file")),
-                         temp_dir.path().Append(dangling)));
-  EXPECT_TRUE(expected_files.insert(dangling).second);
-
   base::FilePath directory(FILE_PATH_LITERAL("directory"));
   ASSERT_TRUE(LoggingCreateDirectory(temp_dir.path().Append(directory),
                                      FilePermissions::kWorldReadable,
@@ -99,6 +105,23 @@
   ASSERT_TRUE(
       CreateFile(temp_dir.path().Append(directory).Append(nested_file)));
 
+#if !defined(OS_FUCHSIA)
+
+  if (symbolic_links) {
+    base::FilePath link(FILE_PATH_LITERAL("link"));
+    ASSERT_TRUE(CreateSymbolicLink(temp_dir.path().Append(file),
+                                   temp_dir.path().Append(link)));
+    EXPECT_TRUE(expected_files.insert(link).second);
+
+    base::FilePath dangling(FILE_PATH_LITERAL("dangling"));
+    ASSERT_TRUE(
+        CreateSymbolicLink(base::FilePath(FILE_PATH_LITERAL("not_a_file")),
+                           temp_dir.path().Append(dangling)));
+    EXPECT_TRUE(expected_files.insert(dangling).second);
+  }
+
+#endif  // !OS_FUCHSIA
+
   std::set<base::FilePath> files;
   DirectoryReader reader;
   ASSERT_TRUE(reader.Open(temp_dir.path()));
@@ -113,6 +136,22 @@
   ExpectFiles(files, expected_files);
 }
 
+TEST(DirectoryReader, FilesAndDirectories) {
+  TestFilesAndDirectories(false);
+}
+
+#if !defined(OS_FUCHSIA)
+
+TEST(DirectoryReader, FilesAndDirectories_SymbolicLinks) {
+  if (!CanCreateSymbolicLinks()) {
+    DISABLED_TEST();
+  }
+
+  TestFilesAndDirectories(true);
+}
+
+#endif  // !OS_FUCHSIA
+
 }  // namespace
 }  // namespace test
 }  // namespace crashpad
diff --git a/third_party/crashpad/crashpad/util/file/filesystem_posix.cc b/third_party/crashpad/crashpad/util/file/filesystem_posix.cc
index 802c3fc..a35db1c 100644
--- a/third_party/crashpad/crashpad/util/file/filesystem_posix.cc
+++ b/third_party/crashpad/crashpad/util/file/filesystem_posix.cc
@@ -56,7 +56,7 @@
 bool IsRegularFile(const base::FilePath& path) {
   struct stat st;
   if (lstat(path.value().c_str(), &st) != 0) {
-    PLOG_IF(ERROR, errno != ENOENT) << "stat " << path.value();
+    PLOG(ERROR) << "stat " << path.value();
     return false;
   }
   return S_ISREG(st.st_mode);
@@ -69,11 +69,9 @@
       PLOG(ERROR) << "stat " << path.value();
       return false;
     }
-  } else {
-    if (lstat(path.value().c_str(), &st) != 0) {
-      PLOG(ERROR) << "lstat " << path.value();
-      return false;
-    }
+  } else if (lstat(path.value().c_str(), &st) != 0) {
+    PLOG(ERROR) << "lstat " << path.value();
+    return false;
   }
   return S_ISDIR(st.st_mode);
 }
diff --git a/third_party/crashpad/crashpad/util/file/filesystem_test.cc b/third_party/crashpad/crashpad/util/file/filesystem_test.cc
index 4fc856a..8657e5b 100644
--- a/third_party/crashpad/crashpad/util/file/filesystem_test.cc
+++ b/third_party/crashpad/crashpad/util/file/filesystem_test.cc
@@ -15,7 +15,9 @@
 #include "util/file/filesystem.h"
 
 #include "base/logging.h"
+#include "build/build_config.h"
 #include "gtest/gtest.h"
+#include "test/gtest_disabled.h"
 #include "test/scoped_temp_dir.h"
 #include "util/file/filesystem_test_util.h"
 
@@ -60,16 +62,16 @@
   base::FilePath file2(temp_dir.path().Append(FILE_PATH_LITERAL("file2")));
   EXPECT_TRUE(MoveFileOrDirectory(file, file2));
   EXPECT_TRUE(IsRegularFile(file2));
-  EXPECT_FALSE(IsRegularFile(file));
+  EXPECT_FALSE(PathExists(file));
 
   EXPECT_FALSE(MoveFileOrDirectory(file, file2));
   EXPECT_TRUE(IsRegularFile(file2));
-  EXPECT_FALSE(IsRegularFile(file));
+  EXPECT_FALSE(PathExists(file));
 
   ASSERT_TRUE(CreateFile(file));
   EXPECT_TRUE(MoveFileOrDirectory(file2, file));
   EXPECT_TRUE(IsRegularFile(file));
-  EXPECT_FALSE(IsRegularFile(file2));
+  EXPECT_FALSE(PathExists(file2));
 
   // directories
   base::FilePath dir(temp_dir.path().Append(FILE_PATH_LITERAL("dir")));
@@ -100,6 +102,19 @@
   EXPECT_FALSE(MoveFileOrDirectory(dir2, file));
   EXPECT_TRUE(IsDirectory(dir2, false));
   EXPECT_TRUE(IsRegularFile(file));
+}
+
+#if !defined(OS_FUCHSIA)
+
+TEST(Filesystem, MoveFileOrDirectory_SymbolicLinks) {
+  if (!CanCreateSymbolicLinks()) {
+    DISABLED_TEST();
+  }
+
+  ScopedTempDir temp_dir;
+
+  base::FilePath file(temp_dir.path().Append(FILE_PATH_LITERAL("file")));
+  ASSERT_TRUE(CreateFile(file));
 
   // file links
   base::FilePath link(temp_dir.path().Append(FILE_PATH_LITERAL("link")));
@@ -135,6 +150,10 @@
   EXPECT_FALSE(PathExists(link));
 
   // directory links
+  base::FilePath dir(temp_dir.path().Append(FILE_PATH_LITERAL("dir")));
+  ASSERT_TRUE(
+      LoggingCreateDirectory(dir, FilePermissions::kWorldReadable, false));
+
   ASSERT_TRUE(CreateSymbolicLink(dir, link));
 
   EXPECT_TRUE(MoveFileOrDirectory(link, link2));
@@ -148,6 +167,8 @@
   EXPECT_FALSE(PathExists(link2));
 }
 
+#endif  // !OS_FUCHSIA
+
 TEST(Filesystem, IsRegularFile) {
   EXPECT_FALSE(IsRegularFile(base::FilePath()));
 
@@ -159,6 +180,18 @@
 
   ASSERT_TRUE(CreateFile(file));
   EXPECT_TRUE(IsRegularFile(file));
+}
+
+#if !defined(OS_FUCHSIA)
+
+TEST(Filesystem, IsRegularFile_SymbolicLinks) {
+  if (!CanCreateSymbolicLinks()) {
+    DISABLED_TEST();
+  }
+
+  ScopedTempDir temp_dir;
+  base::FilePath file(temp_dir.path().Append(FILE_PATH_LITERAL("file")));
+  ASSERT_TRUE(CreateFile(file));
 
   base::FilePath link(temp_dir.path().Append(FILE_PATH_LITERAL("link")));
   ASSERT_TRUE(CreateSymbolicLink(file, link));
@@ -173,6 +206,8 @@
   EXPECT_FALSE(IsRegularFile(dir_link));
 }
 
+#endif  // !OS_FUCHSIA
+
 TEST(Filesystem, IsDirectory) {
   EXPECT_FALSE(IsDirectory(base::FilePath(), false));
   EXPECT_FALSE(IsDirectory(base::FilePath(), true));
@@ -187,6 +222,18 @@
   ASSERT_TRUE(CreateFile(file));
   EXPECT_FALSE(IsDirectory(file, false));
   EXPECT_FALSE(IsDirectory(file, true));
+}
+
+#if !defined(OS_FUCHSIA)
+
+TEST(Filesystem, IsDirectory_SymbolicLinks) {
+  if (!CanCreateSymbolicLinks()) {
+    DISABLED_TEST();
+  }
+
+  ScopedTempDir temp_dir;
+  base::FilePath file(temp_dir.path().Append(FILE_PATH_LITERAL("file")));
+  ASSERT_TRUE(CreateFile(file));
 
   base::FilePath link(temp_dir.path().Append(FILE_PATH_LITERAL("link")));
   ASSERT_TRUE(CreateSymbolicLink(file, link));
@@ -204,6 +251,8 @@
   EXPECT_TRUE(IsDirectory(dir_link, true));
 }
 
+#endif  // !OS_FUCHSIA
+
 TEST(Filesystem, RemoveFile) {
   EXPECT_FALSE(LoggingRemoveFile(base::FilePath()));
 
@@ -216,27 +265,45 @@
   ASSERT_TRUE(CreateFile(file));
   EXPECT_TRUE(IsRegularFile(file));
 
+  base::FilePath dir(temp_dir.path().Append(FILE_PATH_LITERAL("dir")));
+  ASSERT_TRUE(
+      LoggingCreateDirectory(dir, FilePermissions::kWorldReadable, false));
+  EXPECT_FALSE(LoggingRemoveFile(dir));
+
+  EXPECT_TRUE(LoggingRemoveFile(file));
+  EXPECT_FALSE(PathExists(file));
+  EXPECT_FALSE(LoggingRemoveFile(file));
+}
+
+#if !defined(OS_FUCHSIA)
+
+TEST(Filesystem, RemoveFile_SymbolicLinks) {
+  if (!CanCreateSymbolicLinks()) {
+    DISABLED_TEST();
+  }
+
+  ScopedTempDir temp_dir;
+  base::FilePath file(temp_dir.path().Append(FILE_PATH_LITERAL("file")));
+  ASSERT_TRUE(CreateFile(file));
+
+  base::FilePath dir(temp_dir.path().Append(FILE_PATH_LITERAL("dir")));
+  ASSERT_TRUE(
+      LoggingCreateDirectory(dir, FilePermissions::kWorldReadable, false));
+
   base::FilePath link(temp_dir.path().Append(FILE_PATH_LITERAL("link")));
   ASSERT_TRUE(CreateSymbolicLink(file, link));
   EXPECT_TRUE(LoggingRemoveFile(link));
   EXPECT_FALSE(PathExists(link));
   EXPECT_TRUE(PathExists(file));
 
-  base::FilePath dir(temp_dir.path().Append(FILE_PATH_LITERAL("dir")));
-  ASSERT_TRUE(
-      LoggingCreateDirectory(dir, FilePermissions::kWorldReadable, false));
-  EXPECT_FALSE(LoggingRemoveFile(dir));
-
   ASSERT_TRUE(CreateSymbolicLink(dir, link));
   EXPECT_TRUE(LoggingRemoveFile(link));
   EXPECT_FALSE(PathExists(link));
   EXPECT_TRUE(PathExists(dir));
-
-  EXPECT_TRUE(LoggingRemoveFile(file));
-  EXPECT_FALSE(IsRegularFile(file));
-  EXPECT_FALSE(LoggingRemoveFile(file));
 }
 
+#endif  // !OS_FUCHSIA
+
 TEST(Filesystem, RemoveDirectory) {
   EXPECT_FALSE(LoggingRemoveDirectory(base::FilePath()));
 
@@ -253,6 +320,25 @@
   EXPECT_FALSE(LoggingRemoveDirectory(file));
   EXPECT_FALSE(LoggingRemoveDirectory(dir));
 
+  ASSERT_TRUE(LoggingRemoveFile(file));
+  EXPECT_TRUE(LoggingRemoveDirectory(dir));
+}
+
+#if !defined(OS_FUCHSIA)
+
+TEST(Filesystem, RemoveDirectory_SymbolicLinks) {
+  if (!CanCreateSymbolicLinks()) {
+    DISABLED_TEST();
+  }
+
+  ScopedTempDir temp_dir;
+  base::FilePath dir(temp_dir.path().Append(FILE_PATH_LITERAL("dir")));
+  ASSERT_TRUE(
+      LoggingCreateDirectory(dir, FilePermissions::kWorldReadable, false));
+
+  base::FilePath file(dir.Append(FILE_PATH_LITERAL("file")));
+  EXPECT_FALSE(LoggingRemoveDirectory(file));
+
   base::FilePath link(temp_dir.path().Append(FILE_PATH_LITERAL("link")));
   ASSERT_TRUE(CreateSymbolicLink(file, link));
   EXPECT_FALSE(LoggingRemoveDirectory(link));
@@ -261,11 +347,10 @@
   ASSERT_TRUE(CreateSymbolicLink(dir, link));
   EXPECT_FALSE(LoggingRemoveDirectory(link));
   EXPECT_TRUE(LoggingRemoveFile(link));
-
-  ASSERT_TRUE(LoggingRemoveFile(file));
-  EXPECT_TRUE(LoggingRemoveDirectory(dir));
 }
 
+#endif  // !OS_FUCHSIA
+
 }  // namespace
 }  // namespace test
 }  // namespace crashpad
diff --git a/third_party/crashpad/crashpad/util/file/filesystem_test_util.cc b/third_party/crashpad/crashpad/util/file/filesystem_test_util.cc
index 49e13ec..5d991ee7 100644
--- a/third_party/crashpad/crashpad/util/file/filesystem_test_util.cc
+++ b/third_party/crashpad/crashpad/util/file/filesystem_test_util.cc
@@ -20,9 +20,9 @@
 
 #include "base/logging.h"
 #include "base/strings/utf_string_conversions.h"
-#include "build/build_config.h"
 #include "gtest/gtest.h"
 #include "test/errors.h"
+#include "test/scoped_temp_dir.h"
 #include "util/file/file_io.h"
 #include "util/file/filesystem.h"
 
@@ -37,6 +37,59 @@
 namespace crashpad {
 namespace test {
 
+namespace {
+
+#if defined(OS_WIN)
+
+// Detects the flags necessary to create symbolic links and stores them in
+// |flags| if non-nullptr, and returns true on success. If symbolic links can’t
+// be created, returns false.
+bool SymbolicLinkFlags(DWORD* flags) {
+  static DWORD symbolic_link_flags = []() {
+    ScopedTempDir temp_dir_;
+
+    base::FilePath target_path = temp_dir_.path().Append(L"target");
+    base::FilePath symlink_path = temp_dir_.path().Append(L"symlink");
+    if (::CreateSymbolicLink(
+            symlink_path.value().c_str(), target_path.value().c_str(), 0)) {
+      return 0;
+    }
+
+    DWORD error = GetLastError();
+    if (error == ERROR_PRIVILEGE_NOT_HELD) {
+      if (::CreateSymbolicLink(symlink_path.value().c_str(),
+                               target_path.value().c_str(),
+                               SYMBOLIC_LINK_FLAG_ALLOW_UNPRIVILEGED_CREATE)) {
+        return SYMBOLIC_LINK_FLAG_ALLOW_UNPRIVILEGED_CREATE;
+      }
+
+      // This may fail with ERROR_INVALID_PARAMETER if the OS is too old to
+      // understand SYMBOLIC_LINK_FLAG_ALLOW_UNPRIVILEGED_CREATE, so keep
+      // ERROR_PRIVILEGE_NOT_HELD for |error|.
+    }
+
+    // Don’t use ErrorMessage() here because the second CreateSymbolicLink() may
+    // have scrambled it. Use the saved |error| value instead.
+    EXPECT_EQ(error, static_cast<DWORD>(ERROR_PRIVILEGE_NOT_HELD))
+        << "CreateSymbolicLink: " << logging::SystemErrorCodeToString(error);
+    return -1;
+  }();
+
+  if (symbolic_link_flags == static_cast<DWORD>(-1)) {
+    return false;
+  }
+
+  if (flags) {
+    *flags = symbolic_link_flags;
+  }
+
+  return true;
+}
+
+#endif  // OS_WIN
+
+}  // namespace
+
 bool CreateFile(const base::FilePath& file) {
   ScopedFileHandle fd(LoggingOpenFileForWrite(
       file, FileWriteMode::kCreateOrFail, FilePermissions::kOwnerOnly));
@@ -44,6 +97,35 @@
   return fd.is_valid();
 }
 
+bool PathExists(const base::FilePath& path) {
+#if defined(OS_POSIX)
+  struct stat st;
+  if (lstat(path.value().c_str(), &st) != 0) {
+    EXPECT_EQ(errno, ENOENT) << ErrnoMessage("lstat ") << path.value();
+    return false;
+  }
+  return true;
+#elif defined(OS_WIN)
+  if (GetFileAttributes(path.value().c_str()) == INVALID_FILE_ATTRIBUTES) {
+    EXPECT_EQ(GetLastError(), static_cast<DWORD>(ERROR_FILE_NOT_FOUND))
+        << ErrorMessage("GetFileAttributes ")
+        << base::UTF16ToUTF8(path.value());
+    return false;
+  }
+  return true;
+#endif
+}
+
+#if !defined(OS_FUCHSIA)
+
+bool CanCreateSymbolicLinks() {
+#if defined(OS_POSIX)
+  return true;
+#elif defined(OS_WIN)
+  return SymbolicLinkFlags(nullptr);
+#endif  // OS_POSIX
+}
+
 bool CreateSymbolicLink(const base::FilePath& target_path,
                         const base::FilePath& symlink_path) {
 #if defined(OS_POSIX)
@@ -53,35 +135,24 @@
     PLOG(ERROR) << "symlink";
     return false;
   }
+  return true;
 #elif defined(OS_WIN)
+  DWORD symbolic_link_flags = 0;
+  SymbolicLinkFlags(&symbolic_link_flags);
   if (!::CreateSymbolicLink(
           symlink_path.value().c_str(),
           target_path.value().c_str(),
-          IsDirectory(target_path, true) ? SYMBOLIC_LINK_FLAG_DIRECTORY : 0)) {
+          symbolic_link_flags |
+              (IsDirectory(target_path, true) ? SYMBOLIC_LINK_FLAG_DIRECTORY
+                                              : 0))) {
     PLOG(ERROR) << "CreateSymbolicLink";
     return false;
   }
-#endif  // OS_POSIX
   return true;
+#endif  // OS_POSIX
 }
 
-bool PathExists(const base::FilePath& path) {
-#if defined(OS_POSIX)
-  struct stat st;
-  if (lstat(path.value().c_str(), &st) != 0) {
-    EXPECT_EQ(errno, ENOENT) << ErrnoMessage("lstat ") << path.value();
-    return false;
-  }
-#elif defined(OS_WIN)
-  if (GetFileAttributes(path.value().c_str()) == INVALID_FILE_ATTRIBUTES) {
-    EXPECT_EQ(GetLastError(), ERROR_FILE_NOT_FOUND)
-        << ErrorMessage("GetFileAttributes ")
-        << base::UTF16ToUTF8(path.value());
-    return false;
-  }
-#endif
-  return true;
-}
+#endif  // !OS_FUCHSIA
 
 }  // namespace test
 }  // namespace crashpad
diff --git a/third_party/crashpad/crashpad/util/file/filesystem_test_util.h b/third_party/crashpad/crashpad/util/file/filesystem_test_util.h
index 393bc8b..b74653f 100644
--- a/third_party/crashpad/crashpad/util/file/filesystem_test_util.h
+++ b/third_party/crashpad/crashpad/util/file/filesystem_test_util.h
@@ -17,15 +17,41 @@
 
 #include "base/files/file_path.h"
 
+#include "build/build_config.h"
+
 namespace crashpad {
 namespace test {
 
 bool CreateFile(const base::FilePath& file);
 
+bool PathExists(const base::FilePath& path);
+
+#if !defined(OS_FUCHSIA) || DOXYGEN
+// There are no symbolic links on Fuchsia. Don’t bother declaring or defining
+// symbolic link-related functions at all, because it’s an error to even pretend
+// that symbolic links might be available on Fuchsia.
+
+//! \brief Determines whether it should be possible to create symbolic links.
+//!
+//! It is always possible to create symbolic links on POSIX.
+//!
+//! On Windows, it is only possible to create symbolic links when running as an
+//! administrator, or as a non-administrator when running Windows 10 build 15063
+//! (1703, Creators Update) or later, provided that developer mode is enabled
+//! and `SYMBOLIC_LINK_FLAG_ALLOW_UNPRIVILEGED_CREATE` is used. This function
+//! tests the creation of a symbolic link and returns true on success, and false
+//! on failure. If the symbolic link could not be created for a reason other
+//! than the expected lack of privilege, a message is logged.
+//!
+//! Additional background: <a
+//! href="https://blogs.windows.com/buildingapps/2016/12/02/symlinks-windows-10/">Symlinks
+//! in Windows 10!</a>
+bool CanCreateSymbolicLinks();
+
 bool CreateSymbolicLink(const base::FilePath& target_path,
                         const base::FilePath& symlink_path);
 
-bool PathExists(const base::FilePath& path);
+#endif  // !OS_FUCHSIA || DOXYGEN
 
 }  // namespace test
 }  // namespace crashpad
diff --git a/third_party/crashpad/crashpad/util/file/filesystem_win.cc b/third_party/crashpad/crashpad/util/file/filesystem_win.cc
index 5a1242ec0..b874ed8 100644
--- a/third_party/crashpad/crashpad/util/file/filesystem_win.cc
+++ b/third_party/crashpad/crashpad/util/file/filesystem_win.cc
@@ -82,8 +82,7 @@
 bool IsRegularFile(const base::FilePath& path) {
   DWORD fileattr = GetFileAttributes(path.value().c_str());
   if (fileattr == INVALID_FILE_ATTRIBUTES) {
-    PLOG_IF(ERROR, GetLastError() != ERROR_FILE_NOT_FOUND)
-        << "GetFileAttributes " << base::UTF16ToUTF8(path.value());
+    PLOG(ERROR) << "GetFileAttributes " << base::UTF16ToUTF8(path.value());
     return false;
   }
   if ((fileattr & FILE_ATTRIBUTE_DIRECTORY) != 0 ||
diff --git a/third_party/crashpad/crashpad/util/misc/from_pointer_cast.h b/third_party/crashpad/crashpad/util/misc/from_pointer_cast.h
index f1b3734..89a9941 100644
--- a/third_party/crashpad/crashpad/util/misc/from_pointer_cast.h
+++ b/third_party/crashpad/crashpad/util/misc/from_pointer_cast.h
@@ -21,6 +21,7 @@
 #include <type_traits>
 
 #include "base/numerics/safe_conversions.h"
+#include "build/build_config.h"
 
 namespace crashpad {
 
@@ -56,6 +57,20 @@
   return To();
 }
 
+// FromPointerCast<>() with a function pointer “From” type raises
+// -Wnoexcept-type in GCC 7.2 if the function pointer type has a throw() or
+// noexcept specification. This is the case for all standard C library functions
+// provided by glibc. Various tests make use of FromPointerCast<>() with
+// pointers to standard C library functions.
+//
+// Clang has the similar -Wc++1z-compat-mangling, which is not triggered by this
+// pattern.
+#if defined(COMPILER_GCC) && !defined(__clang__) && \
+    (__GNUC__ > 7 || (__GNUC__ == 7 && __GNUC_MINOR__ >= 2))
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wnoexcept-type"
+#endif
+
 // Cast a pointer to any other pointer type.
 template <typename To, typename From>
 typename std::enable_if<std::is_pointer<From>::value &&
@@ -88,6 +103,11 @@
   return base::checked_cast<To>(intermediate);
 }
 
+#if defined(COMPILER_GCC) && !defined(__clang__) && \
+    (__GNUC__ > 7 || (__GNUC__ == 7 && __GNUC_MINOR__ >= 2))
+#pragma GCC diagnostic pop
+#endif
+
 #endif  // DOXYGEN
 
 }  // namespace crashpad
diff --git a/third_party/crashpad/crashpad/util/process/process_memory_linux.h b/third_party/crashpad/crashpad/util/process/process_memory_linux.h
index 95e93f5..e03e251 100644
--- a/third_party/crashpad/crashpad/util/process/process_memory_linux.h
+++ b/third_party/crashpad/crashpad/util/process/process_memory_linux.h
@@ -27,7 +27,7 @@
 namespace crashpad {
 
 //! \brief Accesses the memory of another Linux process.
-class ProcessMemoryLinux : public ProcessMemory {
+class ProcessMemoryLinux final : public ProcessMemory {
  public:
   ProcessMemoryLinux();
   ~ProcessMemoryLinux();
diff --git a/third_party/crashpad/crashpad/util/win/exception_handler_server_test.cc b/third_party/crashpad/crashpad/util/win/exception_handler_server_test.cc
index 6f9ffc3..6f880516 100644
--- a/third_party/crashpad/crashpad/util/win/exception_handler_server_test.cc
+++ b/third_party/crashpad/crashpad/util/win/exception_handler_server_test.cc
@@ -180,13 +180,7 @@
   DISALLOW_COPY_AND_ASSIGN(TestClient);
 };
 
-// https://crashpad.chromium.org/bug/205
-#if defined(CRASHPAD_IN_CHROMIUM)
-#define MAYBE_MultipleConnections DISABLED_MultipleConnections
-#else
-#define MAYBE_MultipleConnections MultipleConnections
-#endif
-TEST_F(ExceptionHandlerServerTest, MAYBE_MultipleConnections) {
+TEST_F(ExceptionHandlerServerTest, MultipleConnections) {
   WinChildProcess::EntryPoint<TestClient>();
 
   std::unique_ptr<WinChildProcess::Handles> handles_1 =
diff --git a/third_party/crashpad/crashpad/util/win/process_info_test.cc b/third_party/crashpad/crashpad/util/win/process_info_test.cc
index 590ef15..051479d 100644
--- a/third_party/crashpad/crashpad/util/win/process_info_test.cc
+++ b/third_party/crashpad/crashpad/util/win/process_info_test.cc
@@ -26,6 +26,7 @@
 #include "build/build_config.h"
 #include "gtest/gtest.h"
 #include "test/errors.h"
+#include "test/gtest_disabled.h"
 #include "test/scoped_temp_dir.h"
 #include "test/test_paths.h"
 #include "test/win/child_launcher.h"
@@ -131,7 +132,7 @@
                             FromPointerCast<WinVMAddress>(_ReturnAddress()));
 }
 
-void TestOtherProcess(const base::string16& directory_modification) {
+void TestOtherProcess(const base::FilePath& directory) {
   ProcessInfo process_info;
 
   UUID done_uuid;
@@ -141,12 +142,12 @@
       CreateEvent(nullptr, true, false, done_uuid.ToString16().c_str()));
   ASSERT_TRUE(done.get()) << ErrorMessage("CreateEvent");
 
-  base::FilePath test_executable = TestPaths::Executable();
-
   std::wstring child_test_executable =
-      test_executable.DirName()
-          .Append(directory_modification)
-          .Append(test_executable.BaseName().RemoveFinalExtension().value() +
+      directory
+          .Append(TestPaths::Executable()
+                      .BaseName()
+                      .RemoveFinalExtension()
+                      .value() +
                   L"_process_info_test_child.exe")
           .value();
 
@@ -189,19 +190,18 @@
   VerifyAddressInInCodePage(process_info, code_address);
 }
 
-// https://crashpad.chromium.org/bug/204
-TEST(ProcessInfo, DISABLED_OtherProcess) {
-  TestOtherProcess(FILE_PATH_LITERAL("."));
+TEST(ProcessInfo, OtherProcess) {
+  TestOtherProcess(TestPaths::Executable().DirName());
 }
 
 #if defined(ARCH_CPU_64_BITS)
-// https://crashpad.chromium.org/bug/203
-TEST(ProcessInfo, DISABLED_OtherProcessWOW64) {
-#ifndef NDEBUG
-  TestOtherProcess(FILE_PATH_LITERAL("..\\..\\out\\Debug"));
-#else
-  TestOtherProcess(FILE_PATH_LITERAL("..\\..\\out\\Release"));
-#endif
+TEST(ProcessInfo, OtherProcessWOW64) {
+  base::FilePath output_32_bit_directory = TestPaths::Output32BitDirectory();
+  if (output_32_bit_directory.empty()) {
+    DISABLED_TEST();
+  }
+
+  TestOtherProcess(output_32_bit_directory);
 }
 #endif  // ARCH_CPU_64_BITS
 
diff --git a/third_party/crashpad/crashpad/util/win/scoped_process_suspend_test.cc b/third_party/crashpad/crashpad/util/win/scoped_process_suspend_test.cc
index 7dfcdf29..2d0f5a0b 100644
--- a/third_party/crashpad/crashpad/util/win/scoped_process_suspend_test.cc
+++ b/third_party/crashpad/crashpad/util/win/scoped_process_suspend_test.cc
@@ -89,13 +89,7 @@
   DISALLOW_COPY_AND_ASSIGN(ScopedProcessSuspendTest);
 };
 
-// https://crashpad.chromium.org/bug/205
-#if defined(CRASHPAD_IN_CHROMIUM)
-#define MAYBE_ScopedProcessSuspend DISABLED_ScopedProcessSuspend
-#else
-#define MAYBE_ScopedProcessSuspend ScopedProcessSuspend
-#endif
-TEST(ScopedProcessSuspend, MAYBE_ScopedProcessSuspend) {
+TEST(ScopedProcessSuspend, ScopedProcessSuspend) {
   WinChildProcess::EntryPoint<ScopedProcessSuspendTest>();
   std::unique_ptr<WinChildProcess::Handles> handles = WinChildProcess::Launch();
 
diff --git a/third_party/libaom/OWNERS b/third_party/libaom/OWNERS
new file mode 100644
index 0000000..1579e8a
--- /dev/null
+++ b/third_party/libaom/OWNERS
@@ -0,0 +1,3 @@
+tomfinegan@chromium.org
+johannkoenig@google.com
+jzern@chromium.org
diff --git a/third_party/libaom/README.chromium b/third_party/libaom/README.chromium
new file mode 100644
index 0000000..1b533dd
--- /dev/null
+++ b/third_party/libaom/README.chromium
@@ -0,0 +1,15 @@
+Name: Alliance for Open Media Video Codec
+Short Name: libaom
+URL: https://aomedia.googlesource.com/aom/
+Version: 0
+Date: 15 September 2017
+License: BSD
+License File: source/libaom/LICENSE
+Security Critical: yes
+
+Description:
+Provides tools for:
+ - creating AV1 bitstreams for storage and transmission.
+ - decoding AV1 bitstreams for display.
+
+Local Modifications:
diff --git a/third_party/libdrm/BUILD.gn b/third_party/libdrm/BUILD.gn
index 9f048b06..fb663a43 100644
--- a/third_party/libdrm/BUILD.gn
+++ b/third_party/libdrm/BUILD.gn
@@ -15,6 +15,8 @@
 
 if (!use_system_libdrm) {
   config("libdrm_config") {
+    # Define _GNU_SOURCE for vasprintf use in xf86drm.c
+    defines = [ "_GNU_SOURCE" ]
     include_dirs = [
       "src",
       "src/include",
diff --git a/third_party/libdrm/README.chromium b/third_party/libdrm/README.chromium
index 678d4bee..ea366011 100644
--- a/third_party/libdrm/README.chromium
+++ b/third_party/libdrm/README.chromium
@@ -1,7 +1,7 @@
 Name: libdrm
 Short Name: libdrm
 URL: https://chromium.googlesource.com/chromiumos/third_party/libdrm
-Version: 2.4.70
+Version: 2.4.85
 License: MIT, GPL
 License File: NOT_SHIPPED
 Security Critical: yes
diff --git a/third_party/polymer/README.chromium b/third_party/polymer/README.chromium
index 40a1a74..b7d6e9f 100644
--- a/third_party/polymer/README.chromium
+++ b/third_party/polymer/README.chromium
@@ -38,6 +38,8 @@
 - Re-implemented <paper-ripple> using Web Animations API (which, as of
   2/21/2017 does not work in Safari or IE). This is a complete fork from
   Polymer's <paper-ripple>.
+- Removed CSS properties that are not needed in Chromium using
+  css_strip_prefixes.py script.
 
 To restore a content of the 'components-chromium' directory from scratch, run
 ./v1_0/reproduce.sh on a Linux machine.
diff --git a/third_party/polymer/v1_0/components-chromium/iron-autogrow-textarea/iron-autogrow-textarea.html b/third_party/polymer/v1_0/components-chromium/iron-autogrow-textarea/iron-autogrow-textarea.html
index aac2019e..5c634ae 100644
--- a/third_party/polymer/v1_0/components-chromium/iron-autogrow-textarea/iron-autogrow-textarea.html
+++ b/third_party/polymer/v1_0/components-chromium/iron-autogrow-textarea/iron-autogrow-textarea.html
@@ -44,7 +44,6 @@
         width: 400px;
         border: 1px solid;
         padding: 2px;
-        -moz-appearance: textarea;
         -webkit-appearance: textarea;
         overflow: hidden;
       }
diff --git a/third_party/polymer/v1_0/components-chromium/iron-flex-layout/iron-flex-layout-classes.html b/third_party/polymer/v1_0/components-chromium/iron-flex-layout/iron-flex-layout-classes.html
index d382652..aebe1a2 100644
--- a/third_party/polymer/v1_0/components-chromium/iron-flex-layout/iron-flex-layout-classes.html
+++ b/third_party/polymer/v1_0/components-chromium/iron-flex-layout/iron-flex-layout-classes.html
@@ -37,66 +37,45 @@
     <style>
       .layout.horizontal,
       .layout.vertical {
-        display: -ms-flexbox;
-        display: -webkit-flex;
         display: flex;
       }
 
       .layout.inline {
-        display: -ms-inline-flexbox;
-        display: -webkit-inline-flex;
         display: inline-flex;
       }
 
       .layout.horizontal {
-        -ms-flex-direction: row;
-        -webkit-flex-direction: row;
         flex-direction: row;
       }
 
       .layout.vertical {
-        -ms-flex-direction: column;
-        -webkit-flex-direction: column;
         flex-direction: column;
       }
 
       .layout.wrap {
-        -ms-flex-wrap: wrap;
-        -webkit-flex-wrap: wrap;
         flex-wrap: wrap;
       }
 
       .layout.center,
       .layout.center-center {
-        -ms-flex-align: center;
-        -webkit-align-items: center;
         align-items: center;
       }
 
       .layout.center-justified,
       .layout.center-center {
-        -ms-flex-pack: center;
-        -webkit-justify-content: center;
         justify-content: center;
       }
 
       .flex {
-        -ms-flex: 1 1 0.000000001px;
-        -webkit-flex: 1;
         flex: 1;
-        -webkit-flex-basis: 0.000000001px;
         flex-basis: 0.000000001px;
       }
 
       .flex-auto {
-        -ms-flex: 1 1 auto;
-        -webkit-flex: 1 1 auto;
         flex: 1 1 auto;
       }
 
       .flex-none {
-        -ms-flex: none;
-        -webkit-flex: none;
         flex: none;
       }
     </style>
@@ -109,26 +88,18 @@
     <style>
       .layout.horizontal-reverse,
       .layout.vertical-reverse {
-        display: -ms-flexbox;
-        display: -webkit-flex;
         display: flex;
       }
 
       .layout.horizontal-reverse {
-        -ms-flex-direction: row-reverse;
-        -webkit-flex-direction: row-reverse;
         flex-direction: row-reverse;
       }
 
       .layout.vertical-reverse {
-        -ms-flex-direction: column-reverse;
-        -webkit-flex-direction: column-reverse;
         flex-direction: column-reverse;
       }
 
       .layout.wrap-reverse {
-        -ms-flex-wrap: wrap-reverse;
-        -webkit-flex-wrap: wrap-reverse;
         flex-wrap: wrap-reverse;
       }
     </style>
@@ -143,27 +114,19 @@
        * Alignment in cross axis.
        */
       .layout.start {
-        -ms-flex-align: start;
-        -webkit-align-items: flex-start;
         align-items: flex-start;
       }
 
       .layout.center,
       .layout.center-center {
-        -ms-flex-align: center;
-        -webkit-align-items: center;
         align-items: center;
       }
 
       .layout.end {
-        -ms-flex-align: end;
-        -webkit-align-items: flex-end;
         align-items: flex-end;
       }
 
       .layout.baseline {
-        -ms-flex-align: baseline;
-        -webkit-align-items: baseline;
         align-items: baseline;
       }
 
@@ -171,33 +134,23 @@
        * Alignment in main axis.
        */
       .layout.start-justified {
-        -ms-flex-pack: start;
-        -webkit-justify-content: flex-start;
         justify-content: flex-start;
       }
 
       .layout.center-justified,
       .layout.center-center {
-        -ms-flex-pack: center;
-        -webkit-justify-content: center;
         justify-content: center;
       }
 
       .layout.end-justified {
-        -ms-flex-pack: end;
-        -webkit-justify-content: flex-end;
         justify-content: flex-end;
       }
 
       .layout.around-justified {
-        -ms-flex-pack: distribute;
-        -webkit-justify-content: space-around;
         justify-content: space-around;
       }
 
       .layout.justified {
-        -ms-flex-pack: justify;
-        -webkit-justify-content: space-between;
         justify-content: space-between;
       }
 
@@ -205,32 +158,22 @@
        * Self alignment.
        */
       .self-start {
-        -ms-align-self: flex-start;
-        -webkit-align-self: flex-start;
         align-self: flex-start;
       }
 
       .self-center {
-        -ms-align-self: center;
-        -webkit-align-self: center;
         align-self: center;
       }
 
       .self-end {
-        -ms-align-self: flex-end;
-        -webkit-align-self: flex-end;
         align-self: flex-end;
       }
 
       .self-stretch {
-        -ms-align-self: stretch;
-        -webkit-align-self: stretch;
         align-self: stretch;
       }
 
       .self-baseline {
-        -ms-align-self: baseline;
-        -webkit-align-self: baseline;
         align-self: baseline;
       };
 
@@ -238,37 +181,22 @@
        * multi-line alignment in main axis.
        */
       .layout.start-aligned {
-        -ms-flex-line-pack: start;  /* IE10 */
-        -ms-align-content: flex-start;
-        -webkit-align-content: flex-start;
         align-content: flex-start;
       }
 
       .layout.end-aligned {
-        -ms-flex-line-pack: end;  /* IE10 */
-        -ms-align-content: flex-end;
-        -webkit-align-content: flex-end;
         align-content: flex-end;
       }
 
       .layout.center-aligned {
-        -ms-flex-line-pack: center;  /* IE10 */
-        -ms-align-content: center;
-        -webkit-align-content: center;
         align-content: center;
       }
 
       .layout.between-aligned {
-        -ms-flex-line-pack: justify;  /* IE10 */
-        -ms-align-content: space-between;
-        -webkit-align-content: space-between;
         align-content: space-between;
       }
 
       .layout.around-aligned {
-        -ms-flex-line-pack: distribute;  /* IE10 */
-        -ms-align-content: space-around;
-        -webkit-align-content: space-around;
         align-content: space-around;
       }
     </style>
@@ -280,76 +208,51 @@
     <style>
       .flex,
       .flex-1 {
-        -ms-flex: 1 1 0.000000001px;
-        -webkit-flex: 1;
         flex: 1;
-        -webkit-flex-basis: 0.000000001px;
         flex-basis: 0.000000001px;
       }
 
       .flex-2 {
-        -ms-flex: 2;
-        -webkit-flex: 2;
         flex: 2;
       }
 
       .flex-3 {
-        -ms-flex: 3;
-        -webkit-flex: 3;
         flex: 3;
       }
 
       .flex-4 {
-        -ms-flex: 4;
-        -webkit-flex: 4;
         flex: 4;
       }
 
       .flex-5 {
-        -ms-flex: 5;
-        -webkit-flex: 5;
         flex: 5;
       }
 
       .flex-6 {
-        -ms-flex: 6;
-        -webkit-flex: 6;
         flex: 6;
       }
 
       .flex-7 {
-        -ms-flex: 7;
-        -webkit-flex: 7;
         flex: 7;
       }
 
       .flex-8 {
-        -ms-flex: 8;
-        -webkit-flex: 8;
         flex: 8;
       }
 
       .flex-9 {
-        -ms-flex: 9;
-        -webkit-flex: 9;
         flex: 9;
       }
 
       .flex-10 {
-        -ms-flex: 10;
-        -webkit-flex: 10;
         flex: 10;
       }
 
       .flex-11 {
-        -ms-flex: 11;
-        -webkit-flex: 11;
         flex: 11;
       }
 
       .flex-12 {
-        -ms-flex: 12;
-        -webkit-flex: 12;
         flex: 12;
       }
     </style>
diff --git a/third_party/polymer/v1_0/components-chromium/iron-flex-layout/iron-flex-layout.html b/third_party/polymer/v1_0/components-chromium/iron-flex-layout/iron-flex-layout.html
index d98e9d0..66714bb 100644
--- a/third_party/polymer/v1_0/components-chromium/iron-flex-layout/iron-flex-layout.html
+++ b/third_party/polymer/v1_0/components-chromium/iron-flex-layout/iron-flex-layout.html
@@ -57,202 +57,139 @@
   :root {
 
     --layout: {
-      display: -ms-flexbox;
-      display: -webkit-flex;
       display: flex;
     };
 
     --layout-inline: {
-      display: -ms-inline-flexbox;
-      display: -webkit-inline-flex;
       display: inline-flex;
     };
 
     --layout-horizontal: {
       @apply(--layout);
 
-      -ms-flex-direction: row;
-      -webkit-flex-direction: row;
       flex-direction: row;
     };
 
     --layout-horizontal-reverse: {
       @apply(--layout);
 
-      -ms-flex-direction: row-reverse;
-      -webkit-flex-direction: row-reverse;
       flex-direction: row-reverse;
     };
 
     --layout-vertical: {
       @apply(--layout);
 
-      -ms-flex-direction: column;
-      -webkit-flex-direction: column;
       flex-direction: column;
     };
 
     --layout-vertical-reverse: {
       @apply(--layout);
 
-      -ms-flex-direction: column-reverse;
-      -webkit-flex-direction: column-reverse;
       flex-direction: column-reverse;
     };
 
     --layout-wrap: {
-      -ms-flex-wrap: wrap;
-      -webkit-flex-wrap: wrap;
       flex-wrap: wrap;
     };
 
     --layout-wrap-reverse: {
-      -ms-flex-wrap: wrap-reverse;
-      -webkit-flex-wrap: wrap-reverse;
       flex-wrap: wrap-reverse;
     };
 
     --layout-flex-auto: {
-      -ms-flex: 1 1 auto;
-      -webkit-flex: 1 1 auto;
       flex: 1 1 auto;
     };
 
     --layout-flex-none: {
-      -ms-flex: none;
-      -webkit-flex: none;
       flex: none;
     };
 
     --layout-flex: {
-      -ms-flex: 1 1 0.000000001px;
-      -webkit-flex: 1;
       flex: 1;
-      -webkit-flex-basis: 0.000000001px;
       flex-basis: 0.000000001px;
     };
 
     --layout-flex-2: {
-      -ms-flex: 2;
-      -webkit-flex: 2;
       flex: 2;
     };
 
     --layout-flex-3: {
-      -ms-flex: 3;
-      -webkit-flex: 3;
       flex: 3;
     };
 
     --layout-flex-4: {
-      -ms-flex: 4;
-      -webkit-flex: 4;
       flex: 4;
     };
 
     --layout-flex-5: {
-      -ms-flex: 5;
-      -webkit-flex: 5;
       flex: 5;
     };
 
     --layout-flex-6: {
-      -ms-flex: 6;
-      -webkit-flex: 6;
       flex: 6;
     };
 
     --layout-flex-7: {
-      -ms-flex: 7;
-      -webkit-flex: 7;
       flex: 7;
     };
 
     --layout-flex-8: {
-      -ms-flex: 8;
-      -webkit-flex: 8;
       flex: 8;
     };
 
     --layout-flex-9: {
-      -ms-flex: 9;
-      -webkit-flex: 9;
       flex: 9;
     };
 
     --layout-flex-10: {
-      -ms-flex: 10;
-      -webkit-flex: 10;
       flex: 10;
     };
 
     --layout-flex-11: {
-      -ms-flex: 11;
-      -webkit-flex: 11;
       flex: 11;
     };
 
     --layout-flex-12: {
-      -ms-flex: 12;
-      -webkit-flex: 12;
       flex: 12;
     };
 
     /* alignment in cross axis */
 
     --layout-start: {
-      -ms-flex-align: start;
-      -webkit-align-items: flex-start;
       align-items: flex-start;
     };
 
     --layout-center: {
-      -ms-flex-align: center;
-      -webkit-align-items: center;
       align-items: center;
     };
 
     --layout-end: {
-      -ms-flex-align: end;
-      -webkit-align-items: flex-end;
       align-items: flex-end;
     };
 
     --layout-baseline: {
-      -ms-flex-align: baseline;
-      -webkit-align-items: baseline;
       align-items: baseline;
     };
 
     /* alignment in main axis */
 
     --layout-start-justified: {
-      -ms-flex-pack: start;
-      -webkit-justify-content: flex-start;
       justify-content: flex-start;
     };
 
     --layout-center-justified: {
-      -ms-flex-pack: center;
-      -webkit-justify-content: center;
       justify-content: center;
     };
 
     --layout-end-justified: {
-      -ms-flex-pack: end;
-      -webkit-justify-content: flex-end;
       justify-content: flex-end;
     };
 
     --layout-around-justified: {
-      -ms-flex-pack: distribute;
-      -webkit-justify-content: space-around;
       justify-content: space-around;
     };
 
     --layout-justified: {
-      -ms-flex-pack: justify;
-      -webkit-justify-content: space-between;
       justify-content: space-between;
     };
 
@@ -264,69 +201,44 @@
     /* self alignment */
 
     --layout-self-start: {
-      -ms-align-self: flex-start;
-      -webkit-align-self: flex-start;
       align-self: flex-start;
     };
 
     --layout-self-center: {
-      -ms-align-self: center;
-      -webkit-align-self: center;
       align-self: center;
     };
 
     --layout-self-end: {
-      -ms-align-self: flex-end;
-      -webkit-align-self: flex-end;
       align-self: flex-end;
     };
 
     --layout-self-stretch: {
-      -ms-align-self: stretch;
-      -webkit-align-self: stretch;
       align-self: stretch;
     };
 
     --layout-self-baseline: {
-      -ms-align-self: baseline;
-      -webkit-align-self: baseline;
       align-self: baseline;
     };
 
     /* multi-line alignment in main axis */
 
     --layout-start-aligned: {
-      -ms-flex-line-pack: start;  /* IE10 */
-      -ms-align-content: flex-start;
-      -webkit-align-content: flex-start;
       align-content: flex-start;
     };
 
     --layout-end-aligned: {
-      -ms-flex-line-pack: end;  /* IE10 */
-      -ms-align-content: flex-end;
-      -webkit-align-content: flex-end;
       align-content: flex-end;
     };
 
     --layout-center-aligned: {
-      -ms-flex-line-pack: center;  /* IE10 */
-      -ms-align-content: center;
-      -webkit-align-content: center;
       align-content: center;
     };
 
     --layout-between-aligned: {
-      -ms-flex-line-pack: justify;  /* IE10 */
-      -ms-align-content: space-between;
-      -webkit-align-content: space-between;
       align-content: space-between;
     };
 
     --layout-around-aligned: {
-      -ms-flex-line-pack: distribute;  /* IE10 */
-      -ms-align-content: space-around;
-      -webkit-align-content: space-around;
       align-content: space-around;
     };
 
diff --git a/third_party/polymer/v1_0/components-chromium/paper-button/paper-button.html b/third_party/polymer/v1_0/components-chromium/paper-button/paper-button.html
index 1e5bf28..c5bda980 100644
--- a/third_party/polymer/v1_0/components-chromium/paper-button/paper-button.html
+++ b/third_party/polymer/v1_0/components-chromium/paper-button/paper-button.html
@@ -96,9 +96,6 @@
         text-transform: uppercase;
         outline-width: 0;
         border-radius: 3px;
-        -moz-user-select: none;
-        -ms-user-select: none;
-        -webkit-user-select: none;
         user-select: none;
         cursor: pointer;
         z-index: 0;
diff --git a/third_party/polymer/v1_0/components-chromium/paper-checkbox/paper-checkbox.html b/third_party/polymer/v1_0/components-chromium/paper-checkbox/paper-checkbox.html
index 1bfc1b55..47eebb72 100644
--- a/third_party/polymer/v1_0/components-chromium/paper-checkbox/paper-checkbox.html
+++ b/third_party/polymer/v1_0/components-chromium/paper-checkbox/paper-checkbox.html
@@ -123,22 +123,18 @@
         border-color: var(--paper-checkbox-unchecked-color, var(--primary-text-color));
         border-radius: 2px;
         pointer-events: none;
-        -webkit-transition: background-color 140ms, border-color 140ms;
         transition: background-color 140ms, border-color 140ms;
       }
 
       /* checkbox checked animations */
       #checkbox.checked #checkmark {
-        -webkit-animation: checkmark-expand 140ms ease-out forwards;
         animation: checkmark-expand 140ms ease-out forwards;
       }
 
       @-webkit-keyframes checkmark-expand {
         0% {
-          -webkit-transform: scale(0, 0) rotate(45deg);
         }
         100% {
-          -webkit-transform: scale(1, 1) rotate(45deg);
         }
       }
 
@@ -166,13 +162,11 @@
         border-right-width: calc(2/15 * var(--calculated-paper-checkbox-size));
         border-bottom-width: calc(2/15 * var(--calculated-paper-checkbox-size));
         border-color: var(--paper-checkbox-checkmark-color, white);
-        -webkit-transform-origin: 97% 86%;
         transform-origin: 97% 86%;
         box-sizing: content-box; /* protect against page-level box-sizing */
       }
 
       :host-context([dir="rtl"]) #checkmark {
-        -webkit-transform-origin: 50% 14%;
         transform-origin: 50% 14%;
       }
 
diff --git a/third_party/polymer/v1_0/components-chromium/paper-fab/paper-fab.html b/third_party/polymer/v1_0/components-chromium/paper-fab/paper-fab.html
index 546614e..d386257e 100644
--- a/third_party/polymer/v1_0/components-chromium/paper-fab/paper-fab.html
+++ b/third_party/polymer/v1_0/components-chromium/paper-fab/paper-fab.html
@@ -69,9 +69,6 @@
         outline: none;
         padding: 16px;
         position: relative;
-        -moz-user-select: none;
-        -ms-user-select: none;
-        -webkit-user-select: none;
         user-select: none;
         width: 56px;
         z-index: 0;
diff --git a/third_party/polymer/v1_0/components-chromium/paper-icon-button/paper-icon-button.html b/third_party/polymer/v1_0/components-chromium/paper-icon-button/paper-icon-button.html
index 3d82fc5..50334df 100644
--- a/third_party/polymer/v1_0/components-chromium/paper-icon-button/paper-icon-button.html
+++ b/third_party/polymer/v1_0/components-chromium/paper-icon-button/paper-icon-button.html
@@ -74,9 +74,6 @@
         position: relative;
         padding: 8px;
         outline: none;
-        -webkit-user-select: none;
-        -moz-user-select: none;
-        -ms-user-select: none;
         user-select: none;
         cursor: pointer;
         z-index: 0;
diff --git a/third_party/polymer/v1_0/components-chromium/paper-input/paper-input-container.html b/third_party/polymer/v1_0/components-chromium/paper-input/paper-input-container.html
index a5199956..7e999a4d 100644
--- a/third_party/polymer/v1_0/components-chromium/paper-input/paper-input-container.html
+++ b/third_party/polymer/v1_0/components-chromium/paper-input/paper-input-container.html
@@ -138,18 +138,14 @@
 
         border-bottom: 2px solid var(--paper-input-container-focus-color, --primary-color);
 
-        -webkit-transform-origin: center center;
         transform-origin: center center;
-        -webkit-transform: scale3d(0,1,1);
         transform: scale3d(0,1,1);
 
         @apply(--paper-input-container-underline-focus);
       }
 
       .underline.is-highlighted .focused-line {
-        -webkit-transform: none;
         transform: none;
-        -webkit-transition: -webkit-transform 0.25s;
         transition: transform 0.25s;
 
         @apply(--paper-transition-easing);
@@ -157,9 +153,7 @@
 
       .underline.is-invalid .focused-line {
         border-color: var(--paper-input-container-invalid-color, --error-color);
-        -webkit-transform: none;
         transform: none;
-        -webkit-transition: -webkit-transform 0.25s;
         transition: transform 0.25s;
 
         @apply(--paper-transition-easing);
@@ -204,9 +198,7 @@
         width: 100%;
         font: inherit;
         color: var(--paper-input-container-color, --secondary-text-color);
-        -webkit-transition: -webkit-transform 0.25s, width 0.25s;
         transition: transform 0.25s, width 0.25s;
-        -webkit-transform-origin: left top;
         transform-origin: left top;
 
         @apply(--paper-font-common-nowrap);
@@ -217,7 +209,6 @@
 
       .input-content.label-is-floating ::content label,
       .input-content.label-is-floating ::content .paper-input-label {
-        -webkit-transform: translateY(-75%) scale(0.75);
         transform: translateY(-75%) scale(0.75);
 
         /* Since we scale to 75/100 of the size, we actually have 100/75 of the
@@ -233,7 +224,6 @@
          * actually makes
          * it wider on the right side, not left side, as you would expect in RTL */
         width: 100%;
-        -webkit-transform-origin: right top;
         transform-origin: right top;
       }
 
diff --git a/third_party/polymer/v1_0/components-chromium/paper-progress/paper-progress.html b/third_party/polymer/v1_0/components-chromium/paper-progress/paper-progress.html
index 5a2a3a8..f4c0884 100644
--- a/third_party/polymer/v1_0/components-chromium/paper-progress/paper-progress.html
+++ b/third_party/polymer/v1_0/components-chromium/paper-progress/paper-progress.html
@@ -124,28 +124,22 @@
 
       :host(.transiting) #primaryProgress,
       :host(.transiting) #secondaryProgress {
-        -webkit-transition-property: -webkit-transform;
         transition-property: transform;
 
         /* Duration */
-        -webkit-transition-duration: var(--paper-progress-transition-duration, 0.08s);
         transition-duration: var(--paper-progress-transition-duration, 0.08s);
 
         /* Timing function */
-        -webkit-transition-timing-function: var(--paper-progress-transition-timing-function, ease);
         transition-timing-function: var(--paper-progress-transition-timing-function, ease);
 
         /* Delay */
-        -webkit-transition-delay: var(--paper-progress-transition-delay, 0s);
         transition-delay: var(--paper-progress-transition-delay, 0s);
       }
 
       #primaryProgress,
       #secondaryProgress {
         @apply(--layout-fit);
-        -webkit-transform-origin: left center;
         transform-origin: left center;
-        -webkit-transform: scaleX(0);
         transform: scaleX(0);
         will-change: transform;
       }
@@ -167,50 +161,36 @@
       }
 
       :host(:not([disabled])) #primaryProgress.indeterminate {
-        -webkit-transform-origin: right center;
         transform-origin: right center;
-        -webkit-animation: indeterminate-bar var(--paper-progress-indeterminate-cycle-duration, 2s) linear infinite;
         animation: indeterminate-bar var(--paper-progress-indeterminate-cycle-duration, 2s) linear infinite;
       }
 
       :host(:not([disabled])) #primaryProgress.indeterminate::after {
         content: "";
-        -webkit-transform-origin: center center;
         transform-origin: center center;
 
-        -webkit-animation: indeterminate-splitter var(--paper-progress-indeterminate-cycle-duration, 2s) linear infinite;
         animation: indeterminate-splitter var(--paper-progress-indeterminate-cycle-duration, 2s) linear infinite;
       }
 
       @-webkit-keyframes indeterminate-bar {
         0% {
-          -webkit-transform: scaleX(1) translateX(-100%);
         }
         50% {
-          -webkit-transform: scaleX(1) translateX(0%);
         }
         75% {
-          -webkit-transform: scaleX(1) translateX(0%);
-          -webkit-animation-timing-function: cubic-bezier(.28,.62,.37,.91);
         }
         100% {
-          -webkit-transform: scaleX(0) translateX(0%);
         }
       }
 
       @-webkit-keyframes indeterminate-splitter {
         0% {
-          -webkit-transform: scaleX(.75) translateX(-125%);
         }
         30% {
-          -webkit-transform: scaleX(.75) translateX(-125%);
-          -webkit-animation-timing-function: cubic-bezier(.42,0,.6,.8);
         }
         90% {
-          -webkit-transform: scaleX(.75) translateX(125%);
         }
         100% {
-          -webkit-transform: scaleX(.75) translateX(125%);
         }
       }
 
diff --git a/third_party/polymer/v1_0/components-chromium/paper-radio-button/paper-radio-button.html b/third_party/polymer/v1_0/components-chromium/paper-radio-button/paper-radio-button.html
index e3f0c13c..38fe78c 100644
--- a/third_party/polymer/v1_0/components-chromium/paper-radio-button/paper-radio-button.html
+++ b/third_party/polymer/v1_0/components-chromium/paper-radio-button/paper-radio-button.html
@@ -93,7 +93,6 @@
         color: var(--paper-radio-button-unchecked-ink-color, --primary-text-color);
         opacity: 0.6;
         pointer-events: none;
-        -webkit-transform: translate(-50%, -50%);
         transform: translate(-50%, -50%);
       }
 
@@ -119,9 +118,7 @@
 
       #onRadio {
         background-color: var(--paper-radio-button-checked-color, --primary-color);
-        -webkit-transform: scale(0);
         transform: scale(0);
-        transition: -webkit-transform ease 0.28s;
         transition: transform ease 0.28s;
         will-change: transform;
       }
@@ -131,7 +128,6 @@
       }
 
       :host([checked]) #onRadio {
-        -webkit-transform: scale(0.5);
         transform: scale(0.5);
       }
 
diff --git a/third_party/polymer/v1_0/components-chromium/paper-slider/paper-slider.html b/third_party/polymer/v1_0/components-chromium/paper-slider/paper-slider.html
index 364fb01..646c22c 100644
--- a/third_party/polymer/v1_0/components-chromium/paper-slider/paper-slider.html
+++ b/third_party/polymer/v1_0/components-chromium/paper-slider/paper-slider.html
@@ -72,9 +72,6 @@
         @apply --layout-center;
         width: 200px;
         cursor: default;
-        -webkit-user-select: none;
-        -moz-user-select: none;
-        -ms-user-select: none;
         user-select: none;
         -webkit-tap-highlight-color: rgba(0, 0, 0, 0);
         --paper-progress-active-color: var(--paper-slider-active-color, var(--google-blue-700));
@@ -95,7 +92,6 @@
        * compatability, dir="rtl" must be explicitly set on paper-slider.
        */
       :host-context([dir="rtl"]) #sliderContainer {
-        -webkit-transform: scaleX(-1);
         transform: scaleX(-1);
       }
 
@@ -104,7 +100,6 @@
        * not be recognized.
        */
       :host([dir="rtl"]) #sliderContainer {
-        -webkit-transform: scaleX(-1);
         transform: scaleX(-1);
       }
 
@@ -113,7 +108,6 @@
        * to support LTR sliders in RTL pages.
        */
       :host([dir="ltr"]) #sliderContainer {
-        -webkit-transform: scaleX(1);
         transform: scaleX(1);
       }
 
@@ -211,7 +205,6 @@
       }
 
       .snaps > .slider-knob.dragging {
-        transition: -webkit-transform 0.08s ease;
         transition: transform 0.08s ease;
       }
 
@@ -223,17 +216,14 @@
         border: 2px solid var(--paper-slider-knob-color, var(--google-blue-700));
         border-radius: 50%;
 
-        -moz-box-sizing: border-box;
         box-sizing: border-box;
 
-        transition-property: -webkit-transform, background-color, border;
         transition-property: transform, background-color, border;
         transition-duration: 0.18s;
         transition-timing-function: ease;
       }
 
       .expand:not(.pin) > .slider-knob > .slider-knob-inner {
-        -webkit-transform: scale(1.5);
         transform: scale(1.5);
       }
 
@@ -256,13 +246,11 @@
         height: 26px;
         border-radius: 50% 50% 50% 0;
 
-        -webkit-transform: rotate(-45deg) scale(0) translate(0);
         transform: rotate(-45deg) scale(0) translate(0);
       }
 
       .slider-knob-inner::before,
       .slider-knob-inner::after {
-        transition: -webkit-transform .18s ease, background-color .18s ease;
         transition: transform .18s ease, background-color .18s ease;
       }
 
@@ -271,7 +259,6 @@
       }
 
       .pin.expand > .slider-knob > .slider-knob-inner::before {
-        -webkit-transform: rotate(-45deg) scale(1) translate(17px, -17px);
         transform: rotate(-45deg) scale(1) translate(17px, -17px);
       }
 
@@ -287,12 +274,10 @@
         color: var(--paper-slider-font-color, #fff);
         font-size: 10px;
 
-        -webkit-transform: scale(0) translate(0);
         transform: scale(0) translate(0);
       }
 
       .pin.expand > .slider-knob > .slider-knob-inner::after {
-        -webkit-transform: scale(1) translate(0, -17px);
         transform: scale(1) translate(0, -17px);
       }
 
@@ -314,7 +299,6 @@
       .disabled > .slider-knob > .slider-knob-inner {
         background-color: var(--paper-slider-disabled-knob-color, var(--paper-grey-400));
         border: 2px solid var(--paper-slider-disabled-knob-color, var(--paper-grey-400));
-        -webkit-transform: scale3d(0.75, 0.75, 1);
         transform: scale3d(0.75, 0.75, 1);
       }
 
diff --git a/third_party/polymer/v1_0/components-chromium/paper-spinner/paper-spinner-styles.html b/third_party/polymer/v1_0/components-chromium/paper-spinner/paper-spinner-styles.html
index 0832929..923b5d87 100644
--- a/third_party/polymer/v1_0/components-chromium/paper-spinner/paper-spinner-styles.html
+++ b/third_party/polymer/v1_0/components-chromium/paper-spinner/paper-spinner-styles.html
@@ -58,7 +58,6 @@
       }
 
       #spinnerContainer.active {
-        -webkit-animation: container-rotate var(--paper-spinner-container-rotation-duration) linear infinite;
         animation: container-rotate var(--paper-spinner-container-rotation-duration) linear infinite;
       }
 
@@ -104,10 +103,6 @@
        * seems).
        */
       .active .spinner-layer {
-        -webkit-animation-name: fill-unfill-rotate;
-        -webkit-animation-duration: var(--paper-spinner-full-cycle-duration);
-        -webkit-animation-timing-function: cubic-bezier(0.4, 0.0, 0.2, 1);
-        -webkit-animation-iteration-count: infinite;
         animation-name: fill-unfill-rotate;
         animation-duration: var(--paper-spinner-full-cycle-duration);
         animation-timing-function: cubic-bezier(0.4, 0.0, 0.2, 1);
@@ -116,22 +111,18 @@
       }
 
       .active .spinner-layer.layer-1 {
-        -webkit-animation-name: fill-unfill-rotate, layer-1-fade-in-out;
         animation-name: fill-unfill-rotate, layer-1-fade-in-out;
       }
 
       .active .spinner-layer.layer-2 {
-        -webkit-animation-name: fill-unfill-rotate, layer-2-fade-in-out;
         animation-name: fill-unfill-rotate, layer-2-fade-in-out;
       }
 
       .active .spinner-layer.layer-3 {
-        -webkit-animation-name: fill-unfill-rotate, layer-3-fade-in-out;
         animation-name: fill-unfill-rotate, layer-3-fade-in-out;
       }
 
       .active .spinner-layer.layer-4 {
-        -webkit-animation-name: fill-unfill-rotate, layer-4-fade-in-out;
         animation-name: fill-unfill-rotate, layer-4-fade-in-out;
       }
 
@@ -267,34 +258,27 @@
       .circle-clipper.left::after {
         left: 0;
         border-right-color: transparent !important;
-        -webkit-transform: rotate(129deg);
         transform: rotate(129deg);
       }
 
       .circle-clipper.right::after {
         left: -100%;
         border-left-color: transparent !important;
-        -webkit-transform: rotate(-129deg);
         transform: rotate(-129deg);
       }
 
       .active .gap-patch::after,
       .active .circle-clipper::after {
-        -webkit-animation-duration: var(--paper-spinner-expand-contract-duration);
-        -webkit-animation-timing-function: cubic-bezier(0.4, 0.0, 0.2, 1);
-        -webkit-animation-iteration-count: infinite;
         animation-duration: var(--paper-spinner-expand-contract-duration);
         animation-timing-function: cubic-bezier(0.4, 0.0, 0.2, 1);
         animation-iteration-count: infinite;
       }
 
       .active .circle-clipper.left::after {
-        -webkit-animation-name: left-spin;
         animation-name: left-spin;
       }
 
       .active .circle-clipper.right::after {
-        -webkit-animation-name: right-spin;
         animation-name: right-spin;
       }
 
@@ -323,7 +307,6 @@
       }
 
       #spinnerContainer.cooldown {
-        -webkit-animation: container-rotate var(--paper-spinner-container-rotation-duration) linear infinite, fade-out var(--paper-spinner-cooldown-duration) cubic-bezier(0.4, 0.0, 0.2, 1);
         animation: container-rotate var(--paper-spinner-container-rotation-duration) linear infinite, fade-out var(--paper-spinner-cooldown-duration) cubic-bezier(0.4, 0.0, 0.2, 1);
       }
 
diff --git a/third_party/polymer/v1_0/components-chromium/paper-styles/classes/shadow-layout.html b/third_party/polymer/v1_0/components-chromium/paper-styles/classes/shadow-layout.html
index fe55ec8..cae7154 100644
--- a/third_party/polymer/v1_0/components-chromium/paper-styles/classes/shadow-layout.html
+++ b/third_party/polymer/v1_0/components-chromium/paper-styles/classes/shadow-layout.html
@@ -17,215 +17,147 @@
   html /deep/ .layout.horizontal-reverse,
   html /deep/ .layout.vertical,
   html /deep/ .layout.vertical-reverse {
-    display: -ms-flexbox;
-    display: -webkit-flex;
     display: flex;
   }
 
   html /deep/ .layout.inline {
-    display: -ms-inline-flexbox;
-    display: -webkit-inline-flex;
     display: inline-flex;
   }
 
   html /deep/ .layout.horizontal {
-    -ms-flex-direction: row;
-    -webkit-flex-direction: row;
     flex-direction: row;
   }
 
   html /deep/ .layout.horizontal-reverse {
-    -ms-flex-direction: row-reverse;
-    -webkit-flex-direction: row-reverse;
     flex-direction: row-reverse;
   }
 
   html /deep/ .layout.vertical {
-    -ms-flex-direction: column;
-    -webkit-flex-direction: column;
     flex-direction: column;
   }
 
   html /deep/ .layout.vertical-reverse {
-    -ms-flex-direction: column-reverse;
-    -webkit-flex-direction: column-reverse;
     flex-direction: column-reverse;
   }
 
   html /deep/ .layout.wrap {
-    -ms-flex-wrap: wrap;
-    -webkit-flex-wrap: wrap;
     flex-wrap: wrap;
   }
 
   html /deep/ .layout.wrap-reverse {
-    -ms-flex-wrap: wrap-reverse;
-    -webkit-flex-wrap: wrap-reverse;
     flex-wrap: wrap-reverse;
   }
 
   html /deep/ .flex-auto {
-    -ms-flex: 1 1 auto;
-    -webkit-flex: 1 1 auto;
     flex: 1 1 auto;
   }
 
   html /deep/ .flex-none {
-    -ms-flex: none;
-    -webkit-flex: none;
     flex: none;
   }
 
   html /deep/ .flex,
   html /deep/ .flex-1 {
-    -ms-flex: 1;
-    -webkit-flex: 1;
     flex: 1;
   }
 
   html /deep/ .flex-2 {
-    -ms-flex: 2;
-    -webkit-flex: 2;
     flex: 2;
   }
 
   html /deep/ .flex-3 {
-    -ms-flex: 3;
-    -webkit-flex: 3;
     flex: 3;
   }
 
   html /deep/ .flex-4 {
-    -ms-flex: 4;
-    -webkit-flex: 4;
     flex: 4;
   }
 
   html /deep/ .flex-5 {
-    -ms-flex: 5;
-    -webkit-flex: 5;
     flex: 5;
   }
 
   html /deep/ .flex-6 {
-    -ms-flex: 6;
-    -webkit-flex: 6;
     flex: 6;
   }
 
   html /deep/ .flex-7 {
-    -ms-flex: 7;
-    -webkit-flex: 7;
     flex: 7;
   }
 
   html /deep/ .flex-8 {
-    -ms-flex: 8;
-    -webkit-flex: 8;
     flex: 8;
   }
 
   html /deep/ .flex-9 {
-    -ms-flex: 9;
-    -webkit-flex: 9;
     flex: 9;
   }
 
   html /deep/ .flex-10 {
-    -ms-flex: 10;
-    -webkit-flex: 10;
     flex: 10;
   }
 
   html /deep/ .flex-11 {
-    -ms-flex: 11;
-    -webkit-flex: 11;
     flex: 11;
   }
 
   html /deep/ .flex-12 {
-    -ms-flex: 12;
-    -webkit-flex: 12;
     flex: 12;
   }
 
   /* alignment in cross axis */
 
   html /deep/ .layout.start {
-    -ms-flex-align: start;
-    -webkit-align-items: flex-start;
     align-items: flex-start;
   }
 
   html /deep/ .layout.center,
   html /deep/ .layout.center-center {
-    -ms-flex-align: center;
-    -webkit-align-items: center;
     align-items: center;
   }
 
   html /deep/ .layout.end {
-    -ms-flex-align: end;
-    -webkit-align-items: flex-end;
     align-items: flex-end;
   }
 
   /* alignment in main axis */
 
   html /deep/ .layout.start-justified {
-    -ms-flex-pack: start;
-    -webkit-justify-content: flex-start;
     justify-content: flex-start;
   }
 
   html /deep/ .layout.center-justified,
   html /deep/ .layout.center-center {
-    -ms-flex-pack: center;
-    -webkit-justify-content: center;
     justify-content: center;
   }
 
   html /deep/ .layout.end-justified {
-    -ms-flex-pack: end;
-    -webkit-justify-content: flex-end;
     justify-content: flex-end;
   }
 
   html /deep/ .layout.around-justified {
-    -ms-flex-pack: around;
-    -webkit-justify-content: space-around;
     justify-content: space-around;
   }
 
   html /deep/ .layout.justified {
-    -ms-flex-pack: justify;
-    -webkit-justify-content: space-between;
     justify-content: space-between;
   }
 
   /* self alignment */
 
   html /deep/ .self-start {
-    -ms-align-self: flex-start;
-    -webkit-align-self: flex-start;
     align-self: flex-start;
   }
 
   html /deep/ .self-center {
-    -ms-align-self: center;
-    -webkit-align-self: center;
     align-self: center;
   }
 
   html /deep/ .self-end {
-    -ms-align-self: flex-end;
-    -webkit-align-self: flex-end;
     align-self: flex-end;
   }
 
   html /deep/ .self-stretch {
-    -ms-align-self: stretch;
-    -webkit-align-self: stretch;
     align-self: stretch;
   }
 
diff --git a/third_party/polymer/v1_0/components-chromium/paper-tabs/paper-tab.html b/third_party/polymer/v1_0/components-chromium/paper-tabs/paper-tab.html
index 1b9446c..b60ba68 100644
--- a/third_party/polymer/v1_0/components-chromium/paper-tabs/paper-tab.html
+++ b/third_party/polymer/v1_0/components-chromium/paper-tabs/paper-tab.html
@@ -70,7 +70,6 @@
       .tab-content {
         height: 100%;
         transform: translateZ(0);
-          -webkit-transform: translateZ(0);
         transition: opacity 0.1s cubic-bezier(0.4, 0.0, 1, 1);
         @apply(--layout-horizontal);
         @apply(--layout-center-center);
diff --git a/third_party/polymer/v1_0/components-chromium/paper-tabs/paper-tabs.html b/third_party/polymer/v1_0/components-chromium/paper-tabs/paper-tabs.html
index 31aded7a..3d7df92 100644
--- a/third_party/polymer/v1_0/components-chromium/paper-tabs/paper-tabs.html
+++ b/third_party/polymer/v1_0/components-chromium/paper-tabs/paper-tabs.html
@@ -102,9 +102,6 @@
         font-size: 14px;
         font-weight: 500;
         overflow: hidden;
-        -moz-user-select: none;
-        -ms-user-select: none;
-        -webkit-user-select: none;
         user-select: none;
 
         /* NOTE: Both values are needed, since some phones require the value to be `transparent`. */
@@ -128,8 +125,6 @@
 
       #tabsContent {
         height: 100%;
-        -moz-flex-basis: auto;
-        -ms-flex-basis: auto;
         flex-basis: auto;
       }
 
@@ -149,8 +144,6 @@
 
       #tabsContent.scrollable.fit-container > ::content > * {
         /* IE - prevent tabs from compressing when they should scroll. */
-        -ms-flex: 1 0 auto;
-        -webkit-flex: 1 0 auto;
         flex: 1 0 auto;
       }
 
@@ -177,11 +170,8 @@
         left: 0;
         right: 0;
         background-color: var(--paper-tabs-selection-bar-color, --paper-yellow-a100);
-          -webkit-transform: scale(0);
         transform: scale(0);
-          -webkit-transform-origin: left center;
         transform-origin: left center;
-          transition: -webkit-transform;
         transition: transform;
 
         @apply(--paper-tabs-selection-bar);
diff --git a/third_party/polymer/v1_0/components-chromium/paper-toggle-button/paper-toggle-button.html b/third_party/polymer/v1_0/components-chromium/paper-toggle-button/paper-toggle-button.html
index e4204650..749c5ac5 100644
--- a/third_party/polymer/v1_0/components-chromium/paper-toggle-button/paper-toggle-button.html
+++ b/third_party/polymer/v1_0/components-chromium/paper-toggle-button/paper-toggle-button.html
@@ -95,7 +95,6 @@
         width: 20px;
         border-radius: 50%;
         box-shadow: 0 1px 5px 0 rgba(0, 0, 0, 0.6);
-        transition: -webkit-transform linear .08s, background-color linear .08s;
         transition: transform linear .08s, background-color linear .08s;
         will-change: transform;
         background-color: var(--paper-toggle-button-unchecked-button-color, --paper-grey-50);
@@ -104,7 +103,6 @@
       }
 
       .toggle-button.dragging {
-        -webkit-transition: none;
         transition: none;
       }
 
@@ -121,7 +119,6 @@
       }
 
       :host([checked]) .toggle-button {
-        -webkit-transform: translate(16px, 0);
         transform: translate(16px, 0);
       }
 
diff --git a/third_party/polymer/v1_0/components-chromium/paper-tooltip/paper-tooltip.html b/third_party/polymer/v1_0/components-chromium/paper-tooltip/paper-tooltip.html
index 5464b0e..7093029 100644
--- a/third_party/polymer/v1_0/components-chromium/paper-tooltip/paper-tooltip.html
+++ b/third_party/polymer/v1_0/components-chromium/paper-tooltip/paper-tooltip.html
@@ -61,9 +61,6 @@
         position: absolute;
         outline: none;
         z-index: 1002;
-        -moz-user-select: none;
-        -ms-user-select: none;
-        -webkit-user-select: none;
         user-select: none;
         cursor: default;
       }
diff --git a/third_party/polymer/v1_0/css_strip_prefixes.py b/third_party/polymer/v1_0/css_strip_prefixes.py
new file mode 100644
index 0000000..868b93f
--- /dev/null
+++ b/third_party/polymer/v1_0/css_strip_prefixes.py
@@ -0,0 +1,97 @@
+# Copyright 2017 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import fnmatch
+import os
+import re
+
+# List of CSS properties to be removed.
+CSS_PROPERTIES_TO_REMOVE = [
+  '-moz-appearance',
+  '-moz-box-sizing',
+  '-moz-flex-basis',
+  '-moz-user-select',
+
+  '-ms-align-content',
+  '-ms-align-self',
+  '-ms-flex',
+  '-ms-flex-align',
+  '-ms-flex-basis',
+  '-ms-flex-line-pack',
+  '-ms-flexbox',
+  '-ms-flex-direction',
+  '-ms-flex-pack',
+  '-ms-flex-wrap',
+  '-ms-inline-flexbox',
+  '-ms-user-select',
+
+  '-webkit-align-content',
+  '-webkit-align-items',
+  '-webkit-align-self',
+  '-webkit-animation',
+  '-webkit-animation-duration',
+  '-webkit-animation-iteration-count',
+  '-webkit-animation-name',
+  '-webkit-animation-timing-function',
+  '-webkit-flex',
+  '-webkit-flex-basis',
+  '-webkit-flex-direction',
+  '-webkit-flex-wrap',
+  '-webkit-inline-flex',
+  '-webkit-justify-content',
+  '-webkit-transform',
+  '-webkit-transform-origin',
+  '-webkit-transition',
+  '-webkit-transition-delay',
+  '-webkit-transition-property',
+  '-webkit-user-select',
+]
+
+
+# Regex to detect a CSS line of interest (helps avoiding edge cases, like
+# removing the 1st line of a multi-line CSS rule).
+CSS_LINE_REGEX = '^\s*[^;\s]+:\s*[^;]+;\s*(/\*.+/*/)*\s*$';
+
+
+def ProcessFile(filename):
+  # Gather indices of lines to be removed.
+  indices_to_remove = [];
+  with open(filename) as f:
+    lines = f.readlines()
+    for i, line in enumerate(lines):
+      if ShouldRemoveLine(line):
+        indices_to_remove.append(i)
+
+  if len(indices_to_remove):
+    print 'stripping CSS from: ' + filename
+
+  # Process line numbers in descinding order, such that the array can be
+  # modified in-place.
+  indices_to_remove.reverse()
+  for i in indices_to_remove:
+    del lines[i]
+
+  # Reconstruct file.
+  with open(filename, 'w') as f:
+    for l in lines:
+      f.write(l)
+  return
+
+
+def ShouldRemoveLine(line):
+  pred = lambda p: re.search(CSS_LINE_REGEX, line) and re.search(p, line)
+  return any(pred(p) for p in CSS_PROPERTIES_TO_REMOVE)
+
+
+def main():
+  html_files = [os.path.join(dirpath, f)
+    for dirpath, dirnames, files in os.walk('components-chromium')
+    for f in fnmatch.filter(files, '*.html')]
+
+  for f in html_files:
+    ProcessFile(f)
+
+
+if __name__ == '__main__':
+  main()
diff --git a/third_party/polymer/v1_0/css_strip_prefixes_test.py b/third_party/polymer/v1_0/css_strip_prefixes_test.py
new file mode 100755
index 0000000..e23e8df
--- /dev/null
+++ b/third_party/polymer/v1_0/css_strip_prefixes_test.py
@@ -0,0 +1,50 @@
+#!/usr/bin/env python
+# Copyright 2017 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import css_strip_prefixes
+import unittest
+
+
+class CssStripPrefixesTest(unittest.TestCase):
+  def testShouldRemoveLineTrue(self):
+    # Test case where the prefixed property is before the the colon.
+    self.assertTrue(css_strip_prefixes.ShouldRemoveLine('-ms-flex: bar;'))
+    self.assertTrue(css_strip_prefixes.ShouldRemoveLine('-ms-flex:bar;'))
+    self.assertTrue(css_strip_prefixes.ShouldRemoveLine('  -ms-flex: bar; '))
+    self.assertTrue(css_strip_prefixes.ShouldRemoveLine('  -ms-flex: bar ;'))
+
+    # Test case where the prefixed property is after the the colon.
+    self.assertTrue(
+        css_strip_prefixes.ShouldRemoveLine(' display: -ms-inline-flexbox;'))
+
+    # Test lines with comments also get removed.
+    self.assertTrue(css_strip_prefixes.ShouldRemoveLine(
+        ' display: -ms-inline-flexbox; /* */'))
+    self.assertTrue(css_strip_prefixes.ShouldRemoveLine(
+        ' -ms-flex: bar; /* foo */ '))
+
+  def testShouldRemoveLineFalse(self):
+    # Test cases where the line is not considered a CSS line.
+    self.assertFalse(css_strip_prefixes.ShouldRemoveLine(''))
+    self.assertFalse(css_strip_prefixes.ShouldRemoveLine(' -ms-flex'))
+    self.assertFalse(css_strip_prefixes.ShouldRemoveLine('/* -ms-flex */'))
+    self.assertFalse(css_strip_prefixes.ShouldRemoveLine(': -ms-flex; '))
+    self.assertFalse(css_strip_prefixes.ShouldRemoveLine(' : -ms-flex; '))
+    self.assertFalse(css_strip_prefixes.ShouldRemoveLine('-ms-flex {'))
+
+    # Test cases where prefixed CSS rules should be unaffected.
+    css_to_preserve = [
+      '-webkit-appearance',
+      '-webkit-box-reflect',
+      '-webkit-font-smoothing',
+      '-webkit-overflow-scrolling',
+      '-webkit-tap-highlight',
+    ]
+    for p in css_to_preserve:
+      self.assertFalse(css_strip_prefixes.ShouldRemoveLine(p + ': bar;'))
+
+
+if __name__ == '__main__':
+  unittest.main()
diff --git a/third_party/polymer/v1_0/reproduce.sh b/third_party/polymer/v1_0/reproduce.sh
index 5faf7ab..fd2010be 100755
--- a/third_party/polymer/v1_0/reproduce.sh
+++ b/third_party/polymer/v1_0/reproduce.sh
@@ -111,6 +111,9 @@
   echo
 fi
 
+echo 'Stripping unnecessary prefixed CSS rules...'
+python css_strip_prefixes.py
+
 echo 'Creating a summary of components...'
 python create_components_summary.py > components_summary.txt
 
diff --git a/third_party/zlib/BUILD.gn b/third_party/zlib/BUILD.gn
index 11f57ef..3b56e450 100644
--- a/third_party/zlib/BUILD.gn
+++ b/third_party/zlib/BUILD.gn
@@ -8,6 +8,11 @@
 
 config("zlib_config") {
   include_dirs = [ "." ]
+  if (current_cpu == "arm" || current_cpu == "arm64") {
+    if (arm_use_neon) {
+      include_dirs += [ "contrib/optimizations/arm" ]
+    }
+  }
 }
 
 config("zlib_adler32_simd_config") {
@@ -130,9 +135,10 @@
         "inflate.c",
       ]
       sources += [
-        "contrib/arm/chunkcopy.h",
-        "contrib/arm/inffast.c",
-        "contrib/arm/inflate.c",
+        "contrib/optimizations/arm/chunkcopy_arm.h",
+        "contrib/optimizations/chunkcopy.h",
+        "contrib/optimizations/inffast_chunky.c",
+        "contrib/optimizations/inflate.c",
       ]
     }
   }
@@ -162,9 +168,7 @@
 
   public_configs = [ ":zlib_config" ]
 
-  deps += [
-    ":zlib_x86_simd"
-  ]
+  deps += [ ":zlib_x86_simd" ]
 }
 
 config("minizip_warnings") {
diff --git a/third_party/zlib/contrib/arm/chunkcopy.h b/third_party/zlib/contrib/arm/chunkcopy.h
deleted file mode 100644
index bc8a77d..0000000
--- a/third_party/zlib/contrib/arm/chunkcopy.h
+++ /dev/null
@@ -1,297 +0,0 @@
-/* chunkcopy.h -- fast copies and sets
- * Copyright (C) 2017 ARM, Inc.
- * For conditions of distribution and use, see copyright notice in zlib.h
- */
-
-#ifndef CHUNKCOPY_H
-#define CHUNKCOPY_H
-
-#include <arm_neon.h>
-#include "zutil.h"
-
-#if __STDC_VERSION__ >= 199901L
-#define Z_RESTRICT restrict
-#else
-#define Z_RESTRICT
-#endif
-
-typedef uint8x16_t chunkcopy_chunk_t;
-#define CHUNKCOPY_CHUNK_SIZE sizeof(chunkcopy_chunk_t)
-
-/*
-   Ask the compiler to perform a wide, unaligned load with an machine
-   instruction appropriate for the chunkcopy_chunk_t type.
- */
-static inline chunkcopy_chunk_t loadchunk(const unsigned char FAR* s) {
-  chunkcopy_chunk_t c;
-  __builtin_memcpy(&c, s, sizeof(c));
-  return c;
-}
-
-/*
-   Ask the compiler to perform a wide, unaligned store with an machine
-   instruction appropriate for the chunkcopy_chunk_t type.
- */
-static inline void storechunk(unsigned char FAR* d, chunkcopy_chunk_t c) {
-  __builtin_memcpy(d, &c, sizeof(c));
-}
-
-/*
-   Perform a memcpy-like operation, but assume that length is non-zero and that
-   it's OK to overwrite at least CHUNKCOPY_CHUNK_SIZE bytes of output even if
-   the length is shorter than this.
-
-   It also guarantees that it will properly unroll the data if the distance
-   between `out` and `from` is at least CHUNKCOPY_CHUNK_SIZE, which we rely on
-   in chunkcopy_relaxed().
-
-   Aside from better memory bus utilisation, this means that short copies
-   (CHUNKCOPY_CHUNK_SIZE bytes or fewer) will fall straight through the loop
-   without iteration, which will hopefully make the branch prediction more
-   reliable.
- */
-static inline unsigned char FAR* chunkcopy_core(unsigned char FAR* out,
-                                                const unsigned char FAR* from,
-                                                unsigned len) {
-  int bump = (--len % CHUNKCOPY_CHUNK_SIZE) + 1;
-  storechunk(out, loadchunk(from));
-  out += bump;
-  from += bump;
-  len /= CHUNKCOPY_CHUNK_SIZE;
-  while (len-- > 0) {
-    storechunk(out, loadchunk(from));
-    out += CHUNKCOPY_CHUNK_SIZE;
-    from += CHUNKCOPY_CHUNK_SIZE;
-  }
-  return out;
-}
-
-/*
-   Like chunkcopy_core, but avoid writing beyond of legal output.
-
-   Accepts an additional pointer to the end of safe output.  A generic safe
-   copy would use (out + len), but it's normally the case that the end of the
-   output buffer is beyond the end of the current copy, and this can still be
-   exploited.
- */
-static inline unsigned char FAR* chunkcopy_core_safe(
-    unsigned char FAR* out,
-    const unsigned char FAR* from,
-    unsigned len,
-    unsigned char FAR* limit) {
-  Assert(out + len <= limit, "chunk copy exceeds safety limit");
-  if (limit - out < CHUNKCOPY_CHUNK_SIZE) {
-    const unsigned char FAR* Z_RESTRICT rfrom = from;
-    if (len & 8) {
-      __builtin_memcpy(out, rfrom, 8);
-      out += 8;
-      rfrom += 8;
-    }
-    if (len & 4) {
-      __builtin_memcpy(out, rfrom, 4);
-      out += 4;
-      rfrom += 4;
-    }
-    if (len & 2) {
-      __builtin_memcpy(out, rfrom, 2);
-      out += 2;
-      rfrom += 2;
-    }
-    if (len & 1) {
-      *out++ = *rfrom++;
-    }
-    return out;
-  }
-  return chunkcopy_core(out, from, len);
-}
-
-/*
-   Perform short copies until distance can be rewritten as being at least
-   CHUNKCOPY_CHUNK_SIZE.
-
-   This assumes that it's OK to overwrite at least the first
-   2*CHUNKCOPY_CHUNK_SIZE bytes of output even if the copy is shorter than
-   this.  This assumption holds within inflate_fast() which starts every
-   iteration with at least 258 bytes of output space available (258 being the
-   maximum length output from a single token; see inffast.c).
- */
-static inline unsigned char FAR* chunkunroll_relaxed(unsigned char FAR* out,
-                                                     unsigned FAR* dist,
-                                                     unsigned FAR* len) {
-  const unsigned char FAR* from = out - *dist;
-  while (*dist < *len && *dist < CHUNKCOPY_CHUNK_SIZE) {
-    storechunk(out, loadchunk(from));
-    out += *dist;
-    *len -= *dist;
-    *dist += *dist;
-  }
-  return out;
-}
-
-static inline uint8x16_t chunkset_vld1q_dup_u8x8(
-    const unsigned char FAR* Z_RESTRICT from) {
-#if defined(__clang__) || defined(__aarch64__)
-  return vreinterpretq_u8_u64(vld1q_dup_u64((void*)from));
-#else
-  /* 32-bit GCC uses an alignment hint for vld1q_dup_u64, even when given a
-   * void pointer, so here's an alternate implementation.
-   */
-  uint8x8_t h = vld1_u8(from);
-  return vcombine_u8(h, h);
-#endif
-}
-
-/*
-   Perform an overlapping copy which behaves as a memset() operation, but
-   supporting periods other than one, and assume that length is non-zero and
-   that it's OK to overwrite at least CHUNKCOPY_CHUNK_SIZE*3 bytes of output
-   even if the length is shorter than this.
- */
-static inline unsigned char FAR* chunkset_core(unsigned char FAR* out,
-                                               unsigned period,
-                                               unsigned len) {
-  uint8x16_t f;
-  int bump = ((len - 1) % sizeof(f)) + 1;
-
-  switch (period) {
-    case 1:
-      f = vld1q_dup_u8(out - 1);
-      vst1q_u8(out, f);
-      out += bump;
-      len -= bump;
-      while (len > 0) {
-        vst1q_u8(out, f);
-        out += sizeof(f);
-        len -= sizeof(f);
-      }
-      return out;
-    case 2:
-      f = vreinterpretq_u8_u16(vld1q_dup_u16((void*)(out - 2)));
-      vst1q_u8(out, f);
-      out += bump;
-      len -= bump;
-      if (len > 0) {
-        f = vreinterpretq_u8_u16(vld1q_dup_u16((void*)(out - 2)));
-        do {
-          vst1q_u8(out, f);
-          out += sizeof(f);
-          len -= sizeof(f);
-        } while (len > 0);
-      }
-      return out;
-    case 4:
-      f = vreinterpretq_u8_u32(vld1q_dup_u32((void*)(out - 4)));
-      vst1q_u8(out, f);
-      out += bump;
-      len -= bump;
-      if (len > 0) {
-        f = vreinterpretq_u8_u32(vld1q_dup_u32((void*)(out - 4)));
-        do {
-          vst1q_u8(out, f);
-          out += sizeof(f);
-          len -= sizeof(f);
-        } while (len > 0);
-      }
-      return out;
-    case 8:
-      f = chunkset_vld1q_dup_u8x8(out - 8);
-      vst1q_u8(out, f);
-      out += bump;
-      len -= bump;
-      if (len > 0) {
-        f = chunkset_vld1q_dup_u8x8(out - 8);
-        do {
-          vst1q_u8(out, f);
-          out += sizeof(f);
-          len -= sizeof(f);
-        } while (len > 0);
-      }
-      return out;
-  }
-  out = chunkunroll_relaxed(out, &period, &len);
-  return chunkcopy_core(out, out - period, len);
-}
-
-/*
-   Perform a memcpy-like operation, but assume that length is non-zero and that
-   it's OK to overwrite at least CHUNKCOPY_CHUNK_SIZE bytes of output even if
-   the length is shorter than this.
-
-   Unlike chunkcopy_core() above, no guarantee is made regarding the behaviour
-   of overlapping buffers, regardless of the distance between the pointers.
-   This is reflected in the `restrict`-qualified pointers, allowing the
-   compiler to reorder loads and stores.
- */
-static inline unsigned char FAR* chunkcopy_relaxed(
-    unsigned char FAR* Z_RESTRICT out,
-    const unsigned char FAR* Z_RESTRICT from,
-    unsigned len) {
-  return chunkcopy_core(out, from, len);
-}
-
-/*
-   Like chunkcopy_relaxed, but avoid writing beyond of legal output.
-
-   Unlike chunkcopy_core_safe() above, no guarantee is made regarding the
-   behaviour of overlapping buffers, regardless of the distance between the
-   pointers.  This is reflected in the `restrict`-qualified pointers, allowing
-   the compiler to reorder loads and stores.
-
-   Accepts an additional pointer to the end of safe output.  A generic safe
-   copy would use (out + len), but it's normally the case that the end of the
-   output buffer is beyond the end of the current copy, and this can still be
-   exploited.
- */
-static inline unsigned char FAR* chunkcopy_safe(
-    unsigned char FAR* out,
-    const unsigned char FAR* Z_RESTRICT from,
-    unsigned len,
-    unsigned char FAR* limit) {
-  Assert(out + len <= limit, "chunk copy exceeds safety limit");
-  return chunkcopy_core_safe(out, from, len, limit);
-}
-
-/*
-   Perform chunky copy within the same buffer, where the source and destination
-   may potentially overlap.
-
-   Assumes that len > 0 on entry, and that it's safe to write at least
-   CHUNKCOPY_CHUNK_SIZE*3 bytes to the output.
- */
-static inline unsigned char FAR*
-chunkcopy_lapped_relaxed(unsigned char FAR* out, unsigned dist, unsigned len) {
-  if (dist < len && dist < CHUNKCOPY_CHUNK_SIZE) {
-    return chunkset_core(out, dist, len);
-  }
-  return chunkcopy_core(out, out - dist, len);
-}
-
-/*
-   Behave like chunkcopy_lapped_relaxed, but avoid writing beyond of legal
-   output.
-
-   Accepts an additional pointer to the end of safe output.  A generic safe
-   copy would use (out + len), but it's normally the case that the end of the
-   output buffer is beyond the end of the current copy, and this can still be
-   exploited.
- */
-static inline unsigned char FAR* chunkcopy_lapped_safe(
-    unsigned char FAR* out,
-    unsigned dist,
-    unsigned len,
-    unsigned char FAR* limit) {
-  Assert(out + len <= limit, "chunk copy exceeds safety limit");
-  if (limit - out < CHUNKCOPY_CHUNK_SIZE * 3) {
-    /* TODO: try harder to optimise this */
-    while (len-- > 0) {
-      *out = *(out - dist);
-      out++;
-    }
-    return out;
-  }
-  return chunkcopy_lapped_relaxed(out, dist, len);
-}
-
-#undef Z_RESTRICT
-
-#endif /* CHUNKCOPY_H */
diff --git a/third_party/zlib/contrib/arm/inffast.c b/third_party/zlib/contrib/arm/inffast.c
deleted file mode 100644
index f7f5007..0000000
--- a/third_party/zlib/contrib/arm/inffast.c
+++ /dev/null
@@ -1,307 +0,0 @@
-/* inffast.c -- fast decoding
- * Copyright (C) 1995-2017 Mark Adler
- * For conditions of distribution and use, see copyright notice in zlib.h
- */
-
-#include "zutil.h"
-#include "inftrees.h"
-#include "inflate.h"
-#include "inffast.h"
-#include "chunkcopy.h"
-
-#ifdef ASMINF
-#  pragma message("Assembler code may have bugs -- use at your own risk")
-#else
-
-/*
-   Decode literal, length, and distance codes and write out the resulting
-   literal and match bytes until either not enough input or output is
-   available, an end-of-block is encountered, or a data error is encountered.
-   When large enough input and output buffers are supplied to inflate(), for
-   example, a 16K input buffer and a 64K output buffer, more than 95% of the
-   inflate execution time is spent in this routine.
-
-   Entry assumptions:
-
-        state->mode == LEN
-        strm->avail_in >= 6
-        strm->avail_out >= 258
-        start >= strm->avail_out
-        state->bits < 8
-
-   On return, state->mode is one of:
-
-        LEN -- ran out of enough output space or enough available input
-        TYPE -- reached end of block code, inflate() to interpret next block
-        BAD -- error in block data
-
-   Notes:
-
-    - The maximum input bits used by a length/distance pair is 15 bits for the
-      length code, 5 bits for the length extra, 15 bits for the distance code,
-      and 13 bits for the distance extra.  This totals 48 bits, or six bytes.
-      Therefore if strm->avail_in >= 6, then there is enough input to avoid
-      checking for available input while decoding.
-
-    - The maximum bytes that a single length/distance pair can output is 258
-      bytes, which is the maximum length that can be coded.  inflate_fast()
-      requires strm->avail_out >= 258 for each loop to avoid checking for
-      output space.
- */
-void ZLIB_INTERNAL inflate_fast(strm, start)
-z_streamp strm;
-unsigned start;         /* inflate()'s starting value for strm->avail_out */
-{
-    struct inflate_state FAR *state;
-    z_const unsigned char FAR *in;      /* local strm->next_in */
-    z_const unsigned char FAR *last;    /* have enough input while in < last */
-    unsigned char FAR *out;     /* local strm->next_out */
-    unsigned char FAR *beg;     /* inflate()'s initial strm->next_out */
-    unsigned char FAR *end;     /* while out < end, enough space available */
-    unsigned char FAR *limit;   /* safety limit for chunky copies */
-#ifdef INFLATE_STRICT
-    unsigned dmax;              /* maximum distance from zlib header */
-#endif
-    unsigned wsize;             /* window size or zero if not using window */
-    unsigned whave;             /* valid bytes in the window */
-    unsigned wnext;             /* window write index */
-    unsigned char FAR *window;  /* allocated sliding window, if wsize != 0 */
-    unsigned long hold;         /* local strm->hold */
-    unsigned bits;              /* local strm->bits */
-    code const FAR *lcode;      /* local strm->lencode */
-    code const FAR *dcode;      /* local strm->distcode */
-    unsigned lmask;             /* mask for first level of length codes */
-    unsigned dmask;             /* mask for first level of distance codes */
-    code here;                  /* retrieved table entry */
-    unsigned op;                /* code bits, operation, extra bits, or */
-                                /*  window position, window bytes to copy */
-    unsigned len;               /* match length, unused bytes */
-    unsigned dist;              /* match distance */
-    unsigned char FAR *from;    /* where to copy match from */
-
-    /* copy state to local variables */
-    state = (struct inflate_state FAR *)strm->state;
-    in = strm->next_in;
-    last = in + (strm->avail_in - 5);
-    out = strm->next_out;
-    beg = out - (start - strm->avail_out);
-    end = out + (strm->avail_out - 257);
-    limit = out + strm->avail_out;
-#ifdef INFLATE_STRICT
-    dmax = state->dmax;
-#endif
-    wsize = state->wsize;
-    whave = state->whave;
-    wnext = (state->wnext == 0 && whave >= wsize) ? wsize : state->wnext;
-    window = state->window;
-    hold = state->hold;
-    bits = state->bits;
-    lcode = state->lencode;
-    dcode = state->distcode;
-    lmask = (1U << state->lenbits) - 1;
-    dmask = (1U << state->distbits) - 1;
-
-    /* decode literals and length/distances until end-of-block or not enough
-       input data or output space */
-    do {
-        if (bits < 15) {
-            hold += (unsigned long)(*in++) << bits;
-            bits += 8;
-            hold += (unsigned long)(*in++) << bits;
-            bits += 8;
-        }
-        here = lcode[hold & lmask];
-      dolen:
-        op = (unsigned)(here.bits);
-        hold >>= op;
-        bits -= op;
-        op = (unsigned)(here.op);
-        if (op == 0) {                          /* literal */
-            Tracevv((stderr, here.val >= 0x20 && here.val < 0x7f ?
-                    "inflate:         literal '%c'\n" :
-                    "inflate:         literal 0x%02x\n", here.val));
-            *out++ = (unsigned char)(here.val);
-        }
-        else if (op & 16) {                     /* length base */
-            len = (unsigned)(here.val);
-            op &= 15;                           /* number of extra bits */
-            if (op) {
-                if (bits < op) {
-                    hold += (unsigned long)(*in++) << bits;
-                    bits += 8;
-                }
-                len += (unsigned)hold & ((1U << op) - 1);
-                hold >>= op;
-                bits -= op;
-            }
-            Tracevv((stderr, "inflate:         length %u\n", len));
-            if (bits < 15) {
-                hold += (unsigned long)(*in++) << bits;
-                bits += 8;
-                hold += (unsigned long)(*in++) << bits;
-                bits += 8;
-            }
-            here = dcode[hold & dmask];
-          dodist:
-            op = (unsigned)(here.bits);
-            hold >>= op;
-            bits -= op;
-            op = (unsigned)(here.op);
-            if (op & 16) {                      /* distance base */
-                dist = (unsigned)(here.val);
-                op &= 15;                       /* number of extra bits */
-                if (bits < op) {
-                    hold += (unsigned long)(*in++) << bits;
-                    bits += 8;
-                    if (bits < op) {
-                        hold += (unsigned long)(*in++) << bits;
-                        bits += 8;
-                    }
-                }
-                dist += (unsigned)hold & ((1U << op) - 1);
-#ifdef INFLATE_STRICT
-                if (dist > dmax) {
-                    strm->msg = (char *)"invalid distance too far back";
-                    state->mode = BAD;
-                    break;
-                }
-#endif
-                hold >>= op;
-                bits -= op;
-                Tracevv((stderr, "inflate:         distance %u\n", dist));
-                op = (unsigned)(out - beg);     /* max distance in output */
-                if (dist > op) {                /* see if copy from window */
-                    op = dist - op;             /* distance back in window */
-                    if (op > whave) {
-                        if (state->sane) {
-                            strm->msg =
-                                (char *)"invalid distance too far back";
-                            state->mode = BAD;
-                            break;
-                        }
-#ifdef INFLATE_ALLOW_INVALID_DISTANCE_TOOFAR_ARRR
-                        if (len <= op - whave) {
-                            do {
-                                *out++ = 0;
-                            } while (--len);
-                            continue;
-                        }
-                        len -= op - whave;
-                        do {
-                            *out++ = 0;
-                        } while (--op > whave);
-                        if (op == 0) {
-                            from = out - dist;
-                            do {
-                                *out++ = *from++;
-                            } while (--len);
-                            continue;
-                        }
-#endif
-                    }
-                    from = window;
-                    if (wnext >= op) {          /* contiguous in window */
-                        from += wnext - op;
-                    }
-                    else {                      /* wrap around window */
-                        op -= wnext;
-                        from += wsize - op;
-                        if (op < len) {         /* some from end of window */
-                            len -= op;
-                            out = chunkcopy_safe(out, from, op, limit);
-                            from = window;      /* more from start of window */
-                            op = wnext;
-                            /* This (rare) case can create a situation where
-                               the first chunkcopy below must be checked.
-                             */
-                        }
-                    }
-                    if (op < len) {             /* still need some from output */
-                        out = chunkcopy_safe(out, from, op, limit);
-                        len -= op;
-                        /* When dist is small the amount of data that can be
-                           copied from the window is also small, and progress
-                           towards the dangerous end of the output buffer is
-                           also small.  This means that for trivial memsets and
-                           for chunkunroll_relaxed() a safety check is
-                           unnecessary.  However, these conditions may not be
-                           entered at all, and in that case it's possible that
-                           the main copy is near the end.
-                          */
-                        out = chunkunroll_relaxed(out, &dist, &len);
-                        out = chunkcopy_safe(out, out - dist, len, limit);
-                    } else {
-                        /* from points to window, so there is no risk of
-                           overlapping pointers requiring memset-like behaviour
-                         */
-                        out = chunkcopy_safe(out, from, len, limit);
-                    }
-                }
-                else {
-                    /* Whole reference is in range of current output.  No
-                       range checks are necessary because we start with room
-                       for at least 258 bytes of output, so unroll and roundoff
-                       operations can write beyond `out+len` so long as they
-                       stay within 258 bytes of `out`.
-                     */
-                    out = chunkcopy_lapped_relaxed(out, dist, len);
-                }
-            }
-            else if ((op & 64) == 0) {          /* 2nd level distance code */
-                here = dcode[here.val + (hold & ((1U << op) - 1))];
-                goto dodist;
-            }
-            else {
-                strm->msg = (char *)"invalid distance code";
-                state->mode = BAD;
-                break;
-            }
-        }
-        else if ((op & 64) == 0) {              /* 2nd level length code */
-            here = lcode[here.val + (hold & ((1U << op) - 1))];
-            goto dolen;
-        }
-        else if (op & 32) {                     /* end-of-block */
-            Tracevv((stderr, "inflate:         end of block\n"));
-            state->mode = TYPE;
-            break;
-        }
-        else {
-            strm->msg = (char *)"invalid literal/length code";
-            state->mode = BAD;
-            break;
-        }
-    } while (in < last && out < end);
-
-    /* return unused bytes (on entry, bits < 8, so in won't go too far back) */
-    len = bits >> 3;
-    in -= len;
-    bits -= len << 3;
-    hold &= (1U << bits) - 1;
-
-    /* update state and return */
-    strm->next_in = in;
-    strm->next_out = out;
-    strm->avail_in = (unsigned)(in < last ? 5 + (last - in) : 5 - (in - last));
-    strm->avail_out = (unsigned)(out < end ?
-                                 257 + (end - out) : 257 - (out - end));
-    state->hold = hold;
-    state->bits = bits;
-    return;
-}
-
-/*
-   inflate_fast() speedups that turned out slower (on a PowerPC G3 750CXe):
-   - Using bit fields for code structure
-   - Different op definition to avoid & for extra bits (do & for table bits)
-   - Three separate decoding do-loops for direct, window, and wnext == 0
-   - Special case for distance > 1 copies to do overlapped load and store copy
-   - Explicit branch predictions (based on measured branch probabilities)
-   - Deferring match copy and interspersed it with decoding subsequent codes
-   - Swapping literal/length else
-   - Swapping window/direct else
-   - Larger unrolled copy loops (three is about right)
-   - Moving len -= 3 statement into middle of loop
- */
-
-#endif /* !ASMINF */
diff --git a/third_party/zlib/contrib/arm/inflate.c b/third_party/zlib/contrib/arm/inflate.c
deleted file mode 100644
index 23e95f1f..0000000
--- a/third_party/zlib/contrib/arm/inflate.c
+++ /dev/null
@@ -1,1572 +0,0 @@
-/* inflate.c -- zlib decompression
- * Copyright (C) 1995-2016 Mark Adler
- * For conditions of distribution and use, see copyright notice in zlib.h
- */
-
-/*
- * Change history:
- *
- * 1.2.beta0    24 Nov 2002
- * - First version -- complete rewrite of inflate to simplify code, avoid
- *   creation of window when not needed, minimize use of window when it is
- *   needed, make inffast.c even faster, implement gzip decoding, and to
- *   improve code readability and style over the previous zlib inflate code
- *
- * 1.2.beta1    25 Nov 2002
- * - Use pointers for available input and output checking in inffast.c
- * - Remove input and output counters in inffast.c
- * - Change inffast.c entry and loop from avail_in >= 7 to >= 6
- * - Remove unnecessary second byte pull from length extra in inffast.c
- * - Unroll direct copy to three copies per loop in inffast.c
- *
- * 1.2.beta2    4 Dec 2002
- * - Change external routine names to reduce potential conflicts
- * - Correct filename to inffixed.h for fixed tables in inflate.c
- * - Make hbuf[] unsigned char to match parameter type in inflate.c
- * - Change strm->next_out[-state->offset] to *(strm->next_out - state->offset)
- *   to avoid negation problem on Alphas (64 bit) in inflate.c
- *
- * 1.2.beta3    22 Dec 2002
- * - Add comments on state->bits assertion in inffast.c
- * - Add comments on op field in inftrees.h
- * - Fix bug in reuse of allocated window after inflateReset()
- * - Remove bit fields--back to byte structure for speed
- * - Remove distance extra == 0 check in inflate_fast()--only helps for lengths
- * - Change post-increments to pre-increments in inflate_fast(), PPC biased?
- * - Add compile time option, POSTINC, to use post-increments instead (Intel?)
- * - Make MATCH copy in inflate() much faster for when inflate_fast() not used
- * - Use local copies of stream next and avail values, as well as local bit
- *   buffer and bit count in inflate()--for speed when inflate_fast() not used
- *
- * 1.2.beta4    1 Jan 2003
- * - Split ptr - 257 statements in inflate_table() to avoid compiler warnings
- * - Move a comment on output buffer sizes from inffast.c to inflate.c
- * - Add comments in inffast.c to introduce the inflate_fast() routine
- * - Rearrange window copies in inflate_fast() for speed and simplification
- * - Unroll last copy for window match in inflate_fast()
- * - Use local copies of window variables in inflate_fast() for speed
- * - Pull out common wnext == 0 case for speed in inflate_fast()
- * - Make op and len in inflate_fast() unsigned for consistency
- * - Add FAR to lcode and dcode declarations in inflate_fast()
- * - Simplified bad distance check in inflate_fast()
- * - Added inflateBackInit(), inflateBack(), and inflateBackEnd() in new
- *   source file infback.c to provide a call-back interface to inflate for
- *   programs like gzip and unzip -- uses window as output buffer to avoid
- *   window copying
- *
- * 1.2.beta5    1 Jan 2003
- * - Improved inflateBack() interface to allow the caller to provide initial
- *   input in strm.
- * - Fixed stored blocks bug in inflateBack()
- *
- * 1.2.beta6    4 Jan 2003
- * - Added comments in inffast.c on effectiveness of POSTINC
- * - Typecasting all around to reduce compiler warnings
- * - Changed loops from while (1) or do {} while (1) to for (;;), again to
- *   make compilers happy
- * - Changed type of window in inflateBackInit() to unsigned char *
- *
- * 1.2.beta7    27 Jan 2003
- * - Changed many types to unsigned or unsigned short to avoid warnings
- * - Added inflateCopy() function
- *
- * 1.2.0        9 Mar 2003
- * - Changed inflateBack() interface to provide separate opaque descriptors
- *   for the in() and out() functions
- * - Changed inflateBack() argument and in_func typedef to swap the length
- *   and buffer address return values for the input function
- * - Check next_in and next_out for Z_NULL on entry to inflate()
- *
- * The history for versions after 1.2.0 are in ChangeLog in zlib distribution.
- */
-
-#include "zutil.h"
-#include "inftrees.h"
-#include "inflate.h"
-#include "inffast.h"
-#include "contrib/arm/chunkcopy.h"
-
-#ifdef MAKEFIXED
-#  ifndef BUILDFIXED
-#    define BUILDFIXED
-#  endif
-#endif
-
-/* function prototypes */
-local int inflateStateCheck OF((z_streamp strm));
-local void fixedtables OF((struct inflate_state FAR *state));
-local int updatewindow OF((z_streamp strm, const unsigned char FAR *end,
-                           unsigned copy));
-#ifdef BUILDFIXED
-   void makefixed OF((void));
-#endif
-local unsigned syncsearch OF((unsigned FAR *have, const unsigned char FAR *buf,
-                              unsigned len));
-
-local int inflateStateCheck(strm)
-z_streamp strm;
-{
-    struct inflate_state FAR *state;
-    if (strm == Z_NULL ||
-        strm->zalloc == (alloc_func)0 || strm->zfree == (free_func)0)
-        return 1;
-    state = (struct inflate_state FAR *)strm->state;
-    if (state == Z_NULL || state->strm != strm ||
-        state->mode < HEAD || state->mode > SYNC)
-        return 1;
-    return 0;
-}
-
-int ZEXPORT inflateResetKeep(strm)
-z_streamp strm;
-{
-    struct inflate_state FAR *state;
-
-    if (inflateStateCheck(strm)) return Z_STREAM_ERROR;
-    state = (struct inflate_state FAR *)strm->state;
-    strm->total_in = strm->total_out = state->total = 0;
-    strm->msg = Z_NULL;
-    if (state->wrap)        /* to support ill-conceived Java test suite */
-        strm->adler = state->wrap & 1;
-    state->mode = HEAD;
-    state->last = 0;
-    state->havedict = 0;
-    state->dmax = 32768U;
-    state->head = Z_NULL;
-    state->hold = 0;
-    state->bits = 0;
-    state->lencode = state->distcode = state->next = state->codes;
-    state->sane = 1;
-    state->back = -1;
-    Tracev((stderr, "inflate: reset\n"));
-    return Z_OK;
-}
-
-int ZEXPORT inflateReset(strm)
-z_streamp strm;
-{
-    struct inflate_state FAR *state;
-
-    if (inflateStateCheck(strm)) return Z_STREAM_ERROR;
-    state = (struct inflate_state FAR *)strm->state;
-    state->wsize = 0;
-    state->whave = 0;
-    state->wnext = 0;
-    return inflateResetKeep(strm);
-}
-
-int ZEXPORT inflateReset2(strm, windowBits)
-z_streamp strm;
-int windowBits;
-{
-    int wrap;
-    struct inflate_state FAR *state;
-
-    /* get the state */
-    if (inflateStateCheck(strm)) return Z_STREAM_ERROR;
-    state = (struct inflate_state FAR *)strm->state;
-
-    /* extract wrap request from windowBits parameter */
-    if (windowBits < 0) {
-        wrap = 0;
-        windowBits = -windowBits;
-    }
-    else {
-        wrap = (windowBits >> 4) + 5;
-#ifdef GUNZIP
-        if (windowBits < 48)
-            windowBits &= 15;
-#endif
-    }
-
-    /* set number of window bits, free window if different */
-    if (windowBits && (windowBits < 8 || windowBits > 15))
-        return Z_STREAM_ERROR;
-    if (state->window != Z_NULL && state->wbits != (unsigned)windowBits) {
-        ZFREE(strm, state->window);
-        state->window = Z_NULL;
-    }
-
-    /* update state and reset the rest of it */
-    state->wrap = wrap;
-    state->wbits = (unsigned)windowBits;
-    return inflateReset(strm);
-}
-
-int ZEXPORT inflateInit2_(strm, windowBits, version, stream_size)
-z_streamp strm;
-int windowBits;
-const char *version;
-int stream_size;
-{
-    int ret;
-    struct inflate_state FAR *state;
-
-    if (version == Z_NULL || version[0] != ZLIB_VERSION[0] ||
-        stream_size != (int)(sizeof(z_stream)))
-        return Z_VERSION_ERROR;
-    if (strm == Z_NULL) return Z_STREAM_ERROR;
-    strm->msg = Z_NULL;                 /* in case we return an error */
-    if (strm->zalloc == (alloc_func)0) {
-#ifdef Z_SOLO
-        return Z_STREAM_ERROR;
-#else
-        strm->zalloc = zcalloc;
-        strm->opaque = (voidpf)0;
-#endif
-    }
-    if (strm->zfree == (free_func)0)
-#ifdef Z_SOLO
-        return Z_STREAM_ERROR;
-#else
-        strm->zfree = zcfree;
-#endif
-    state = (struct inflate_state FAR *)
-            ZALLOC(strm, 1, sizeof(struct inflate_state));
-    if (state == Z_NULL) return Z_MEM_ERROR;
-    Tracev((stderr, "inflate: allocated\n"));
-    strm->state = (struct internal_state FAR *)state;
-    state->strm = strm;
-    state->window = Z_NULL;
-    state->mode = HEAD;     /* to pass state test in inflateReset2() */
-    state->check = 1L;      /* 1L is the result of adler32() zero length data */
-    ret = inflateReset2(strm, windowBits);
-    if (ret != Z_OK) {
-        ZFREE(strm, state);
-        strm->state = Z_NULL;
-    }
-    return ret;
-}
-
-int ZEXPORT inflateInit_(strm, version, stream_size)
-z_streamp strm;
-const char *version;
-int stream_size;
-{
-    return inflateInit2_(strm, DEF_WBITS, version, stream_size);
-}
-
-int ZEXPORT inflatePrime(strm, bits, value)
-z_streamp strm;
-int bits;
-int value;
-{
-    struct inflate_state FAR *state;
-
-    if (inflateStateCheck(strm)) return Z_STREAM_ERROR;
-    state = (struct inflate_state FAR *)strm->state;
-    if (bits < 0) {
-        state->hold = 0;
-        state->bits = 0;
-        return Z_OK;
-    }
-    if (bits > 16 || state->bits + (uInt)bits > 32) return Z_STREAM_ERROR;
-    value &= (1L << bits) - 1;
-    state->hold += (unsigned)value << state->bits;
-    state->bits += (uInt)bits;
-    return Z_OK;
-}
-
-/*
-   Return state with length and distance decoding tables and index sizes set to
-   fixed code decoding.  Normally this returns fixed tables from inffixed.h.
-   If BUILDFIXED is defined, then instead this routine builds the tables the
-   first time it's called, and returns those tables the first time and
-   thereafter.  This reduces the size of the code by about 2K bytes, in
-   exchange for a little execution time.  However, BUILDFIXED should not be
-   used for threaded applications, since the rewriting of the tables and virgin
-   may not be thread-safe.
- */
-local void fixedtables(state)
-struct inflate_state FAR *state;
-{
-#ifdef BUILDFIXED
-    static int virgin = 1;
-    static code *lenfix, *distfix;
-    static code fixed[544];
-
-    /* build fixed huffman tables if first call (may not be thread safe) */
-    if (virgin) {
-        unsigned sym, bits;
-        static code *next;
-
-        /* literal/length table */
-        sym = 0;
-        while (sym < 144) state->lens[sym++] = 8;
-        while (sym < 256) state->lens[sym++] = 9;
-        while (sym < 280) state->lens[sym++] = 7;
-        while (sym < 288) state->lens[sym++] = 8;
-        next = fixed;
-        lenfix = next;
-        bits = 9;
-        inflate_table(LENS, state->lens, 288, &(next), &(bits), state->work);
-
-        /* distance table */
-        sym = 0;
-        while (sym < 32) state->lens[sym++] = 5;
-        distfix = next;
-        bits = 5;
-        inflate_table(DISTS, state->lens, 32, &(next), &(bits), state->work);
-
-        /* do this just once */
-        virgin = 0;
-    }
-#else /* !BUILDFIXED */
-#   include "inffixed.h"
-#endif /* BUILDFIXED */
-    state->lencode = lenfix;
-    state->lenbits = 9;
-    state->distcode = distfix;
-    state->distbits = 5;
-}
-
-#ifdef MAKEFIXED
-#include <stdio.h>
-
-/*
-   Write out the inffixed.h that is #include'd above.  Defining MAKEFIXED also
-   defines BUILDFIXED, so the tables are built on the fly.  makefixed() writes
-   those tables to stdout, which would be piped to inffixed.h.  A small program
-   can simply call makefixed to do this:
-
-    void makefixed(void);
-
-    int main(void)
-    {
-        makefixed();
-        return 0;
-    }
-
-   Then that can be linked with zlib built with MAKEFIXED defined and run:
-
-    a.out > inffixed.h
- */
-void makefixed()
-{
-    unsigned low, size;
-    struct inflate_state state;
-
-    fixedtables(&state);
-    puts("    /* inffixed.h -- table for decoding fixed codes");
-    puts("     * Generated automatically by makefixed().");
-    puts("     */");
-    puts("");
-    puts("    /* WARNING: this file should *not* be used by applications.");
-    puts("       It is part of the implementation of this library and is");
-    puts("       subject to change. Applications should only use zlib.h.");
-    puts("     */");
-    puts("");
-    size = 1U << 9;
-    printf("    static const code lenfix[%u] = {", size);
-    low = 0;
-    for (;;) {
-        if ((low % 7) == 0) printf("\n        ");
-        printf("{%u,%u,%d}", (low & 127) == 99 ? 64 : state.lencode[low].op,
-               state.lencode[low].bits, state.lencode[low].val);
-        if (++low == size) break;
-        putchar(',');
-    }
-    puts("\n    };");
-    size = 1U << 5;
-    printf("\n    static const code distfix[%u] = {", size);
-    low = 0;
-    for (;;) {
-        if ((low % 6) == 0) printf("\n        ");
-        printf("{%u,%u,%d}", state.distcode[low].op, state.distcode[low].bits,
-               state.distcode[low].val);
-        if (++low == size) break;
-        putchar(',');
-    }
-    puts("\n    };");
-}
-#endif /* MAKEFIXED */
-
-/*
-   Update the window with the last wsize (normally 32K) bytes written before
-   returning.  If window does not exist yet, create it.  This is only called
-   when a window is already in use, or when output has been written during this
-   inflate call, but the end of the deflate stream has not been reached yet.
-   It is also called to create a window for dictionary data when a dictionary
-   is loaded.
-
-   Providing output buffers larger than 32K to inflate() should provide a speed
-   advantage, since only the last 32K of output is copied to the sliding window
-   upon return from inflate(), and since all distances after the first 32K of
-   output will fall in the output data, making match copies simpler and faster.
-   The advantage may be dependent on the size of the processor's data caches.
- */
-local int updatewindow(strm, end, copy)
-z_streamp strm;
-const Bytef *end;
-unsigned copy;
-{
-    struct inflate_state FAR *state;
-    unsigned dist;
-
-    state = (struct inflate_state FAR *)strm->state;
-
-    /* if it hasn't been done already, allocate space for the window */
-    if (state->window == Z_NULL) {
-        unsigned wsize = 1U << state->wbits;
-        state->window = (unsigned char FAR *)
-                        ZALLOC(strm, wsize + CHUNKCOPY_CHUNK_SIZE,
-                               sizeof(unsigned char));
-        if (state->window == Z_NULL) return 1;
-#ifdef INFLATE_CLEAR_UNUSED_UNDEFINED
-        /* Copies from the overflow portion of this buffer are undefined and
-           may cause analysis tools to raise a warning if we don't initialize
-           it.  However, this undefined data overwrites other undefined data
-           and is subsequently either overwritten or left deliberately
-           undefined at the end of decode; so there's really no point.
-         */
-        memset(state->window + wsize, 0, CHUNKCOPY_CHUNK_SIZE);
-#endif
-    }
-
-    /* if window not in use yet, initialize */
-    if (state->wsize == 0) {
-        state->wsize = 1U << state->wbits;
-        state->wnext = 0;
-        state->whave = 0;
-    }
-
-    /* copy state->wsize or less output bytes into the circular window */
-    if (copy >= state->wsize) {
-        zmemcpy(state->window, end - state->wsize, state->wsize);
-        state->wnext = 0;
-        state->whave = state->wsize;
-    }
-    else {
-        dist = state->wsize - state->wnext;
-        if (dist > copy) dist = copy;
-        zmemcpy(state->window + state->wnext, end - copy, dist);
-        copy -= dist;
-        if (copy) {
-            zmemcpy(state->window, end - copy, copy);
-            state->wnext = copy;
-            state->whave = state->wsize;
-        }
-        else {
-            state->wnext += dist;
-            if (state->wnext == state->wsize) state->wnext = 0;
-            if (state->whave < state->wsize) state->whave += dist;
-        }
-    }
-    return 0;
-}
-
-/* Macros for inflate(): */
-
-/* check function to use adler32() for zlib or crc32() for gzip */
-#ifdef GUNZIP
-#  define UPDATE(check, buf, len) \
-    (state->flags ? crc32(check, buf, len) : adler32(check, buf, len))
-#else
-#  define UPDATE(check, buf, len) adler32(check, buf, len)
-#endif
-
-/* check macros for header crc */
-#ifdef GUNZIP
-#  define CRC2(check, word) \
-    do { \
-        hbuf[0] = (unsigned char)(word); \
-        hbuf[1] = (unsigned char)((word) >> 8); \
-        check = crc32(check, hbuf, 2); \
-    } while (0)
-
-#  define CRC4(check, word) \
-    do { \
-        hbuf[0] = (unsigned char)(word); \
-        hbuf[1] = (unsigned char)((word) >> 8); \
-        hbuf[2] = (unsigned char)((word) >> 16); \
-        hbuf[3] = (unsigned char)((word) >> 24); \
-        check = crc32(check, hbuf, 4); \
-    } while (0)
-#endif
-
-/* Load registers with state in inflate() for speed */
-#define LOAD() \
-    do { \
-        put = strm->next_out; \
-        left = strm->avail_out; \
-        next = strm->next_in; \
-        have = strm->avail_in; \
-        hold = state->hold; \
-        bits = state->bits; \
-    } while (0)
-
-/* Restore state from registers in inflate() */
-#define RESTORE() \
-    do { \
-        strm->next_out = put; \
-        strm->avail_out = left; \
-        strm->next_in = next; \
-        strm->avail_in = have; \
-        state->hold = hold; \
-        state->bits = bits; \
-    } while (0)
-
-/* Clear the input bit accumulator */
-#define INITBITS() \
-    do { \
-        hold = 0; \
-        bits = 0; \
-    } while (0)
-
-/* Get a byte of input into the bit accumulator, or return from inflate()
-   if there is no input available. */
-#define PULLBYTE() \
-    do { \
-        if (have == 0) goto inf_leave; \
-        have--; \
-        hold += (unsigned long)(*next++) << bits; \
-        bits += 8; \
-    } while (0)
-
-/* Assure that there are at least n bits in the bit accumulator.  If there is
-   not enough available input to do that, then return from inflate(). */
-#define NEEDBITS(n) \
-    do { \
-        while (bits < (unsigned)(n)) \
-            PULLBYTE(); \
-    } while (0)
-
-/* Return the low n bits of the bit accumulator (n < 16) */
-#define BITS(n) \
-    ((unsigned)hold & ((1U << (n)) - 1))
-
-/* Remove n bits from the bit accumulator */
-#define DROPBITS(n) \
-    do { \
-        hold >>= (n); \
-        bits -= (unsigned)(n); \
-    } while (0)
-
-/* Remove zero to seven bits as needed to go to a byte boundary */
-#define BYTEBITS() \
-    do { \
-        hold >>= bits & 7; \
-        bits -= bits & 7; \
-    } while (0)
-
-/*
-   inflate() uses a state machine to process as much input data and generate as
-   much output data as possible before returning.  The state machine is
-   structured roughly as follows:
-
-    for (;;) switch (state) {
-    ...
-    case STATEn:
-        if (not enough input data or output space to make progress)
-            return;
-        ... make progress ...
-        state = STATEm;
-        break;
-    ...
-    }
-
-   so when inflate() is called again, the same case is attempted again, and
-   if the appropriate resources are provided, the machine proceeds to the
-   next state.  The NEEDBITS() macro is usually the way the state evaluates
-   whether it can proceed or should return.  NEEDBITS() does the return if
-   the requested bits are not available.  The typical use of the BITS macros
-   is:
-
-        NEEDBITS(n);
-        ... do something with BITS(n) ...
-        DROPBITS(n);
-
-   where NEEDBITS(n) either returns from inflate() if there isn't enough
-   input left to load n bits into the accumulator, or it continues.  BITS(n)
-   gives the low n bits in the accumulator.  When done, DROPBITS(n) drops
-   the low n bits off the accumulator.  INITBITS() clears the accumulator
-   and sets the number of available bits to zero.  BYTEBITS() discards just
-   enough bits to put the accumulator on a byte boundary.  After BYTEBITS()
-   and a NEEDBITS(8), then BITS(8) would return the next byte in the stream.
-
-   NEEDBITS(n) uses PULLBYTE() to get an available byte of input, or to return
-   if there is no input available.  The decoding of variable length codes uses
-   PULLBYTE() directly in order to pull just enough bytes to decode the next
-   code, and no more.
-
-   Some states loop until they get enough input, making sure that enough
-   state information is maintained to continue the loop where it left off
-   if NEEDBITS() returns in the loop.  For example, want, need, and keep
-   would all have to actually be part of the saved state in case NEEDBITS()
-   returns:
-
-    case STATEw:
-        while (want < need) {
-            NEEDBITS(n);
-            keep[want++] = BITS(n);
-            DROPBITS(n);
-        }
-        state = STATEx;
-    case STATEx:
-
-   As shown above, if the next state is also the next case, then the break
-   is omitted.
-
-   A state may also return if there is not enough output space available to
-   complete that state.  Those states are copying stored data, writing a
-   literal byte, and copying a matching string.
-
-   When returning, a "goto inf_leave" is used to update the total counters,
-   update the check value, and determine whether any progress has been made
-   during that inflate() call in order to return the proper return code.
-   Progress is defined as a change in either strm->avail_in or strm->avail_out.
-   When there is a window, goto inf_leave will update the window with the last
-   output written.  If a goto inf_leave occurs in the middle of decompression
-   and there is no window currently, goto inf_leave will create one and copy
-   output to the window for the next call of inflate().
-
-   In this implementation, the flush parameter of inflate() only affects the
-   return code (per zlib.h).  inflate() always writes as much as possible to
-   strm->next_out, given the space available and the provided input--the effect
-   documented in zlib.h of Z_SYNC_FLUSH.  Furthermore, inflate() always defers
-   the allocation of and copying into a sliding window until necessary, which
-   provides the effect documented in zlib.h for Z_FINISH when the entire input
-   stream available.  So the only thing the flush parameter actually does is:
-   when flush is set to Z_FINISH, inflate() cannot return Z_OK.  Instead it
-   will return Z_BUF_ERROR if it has not reached the end of the stream.
- */
-
-int ZEXPORT inflate(strm, flush)
-z_streamp strm;
-int flush;
-{
-    struct inflate_state FAR *state;
-    z_const unsigned char FAR *next;    /* next input */
-    unsigned char FAR *put;     /* next output */
-    unsigned have, left;        /* available input and output */
-    unsigned long hold;         /* bit buffer */
-    unsigned bits;              /* bits in bit buffer */
-    unsigned in, out;           /* save starting available input and output */
-    unsigned copy;              /* number of stored or match bytes to copy */
-    unsigned char FAR *from;    /* where to copy match bytes from */
-    code here;                  /* current decoding table entry */
-    code last;                  /* parent table entry */
-    unsigned len;               /* length to copy for repeats, bits to drop */
-    int ret;                    /* return code */
-#ifdef GUNZIP
-    unsigned char hbuf[4];      /* buffer for gzip header crc calculation */
-#endif
-    static const unsigned short order[19] = /* permutation of code lengths */
-        {16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15};
-
-    if (inflateStateCheck(strm) || strm->next_out == Z_NULL ||
-        (strm->next_in == Z_NULL && strm->avail_in != 0))
-        return Z_STREAM_ERROR;
-
-    state = (struct inflate_state FAR *)strm->state;
-    if (state->mode == TYPE) state->mode = TYPEDO;      /* skip check */
-    LOAD();
-    in = have;
-    out = left;
-    ret = Z_OK;
-    for (;;)
-        switch (state->mode) {
-        case HEAD:
-            if (state->wrap == 0) {
-                state->mode = TYPEDO;
-                break;
-            }
-            NEEDBITS(16);
-#ifdef GUNZIP
-            if ((state->wrap & 2) && hold == 0x8b1f) {  /* gzip header */
-                if (state->wbits == 0)
-                    state->wbits = 15;
-                state->check = crc32(0L, Z_NULL, 0);
-                CRC2(state->check, hold);
-                INITBITS();
-                state->mode = FLAGS;
-                break;
-            }
-            state->flags = 0;           /* expect zlib header */
-            if (state->head != Z_NULL)
-                state->head->done = -1;
-            if (!(state->wrap & 1) ||   /* check if zlib header allowed */
-#else
-            if (
-#endif
-                ((BITS(8) << 8) + (hold >> 8)) % 31) {
-                strm->msg = (char *)"incorrect header check";
-                state->mode = BAD;
-                break;
-            }
-            if (BITS(4) != Z_DEFLATED) {
-                strm->msg = (char *)"unknown compression method";
-                state->mode = BAD;
-                break;
-            }
-            DROPBITS(4);
-            len = BITS(4) + 8;
-            if (state->wbits == 0)
-                state->wbits = len;
-            if (len > 15 || len > state->wbits) {
-                strm->msg = (char *)"invalid window size";
-                state->mode = BAD;
-                break;
-            }
-            state->dmax = 1U << len;
-            Tracev((stderr, "inflate:   zlib header ok\n"));
-            strm->adler = state->check = adler32(0L, Z_NULL, 0);
-            state->mode = hold & 0x200 ? DICTID : TYPE;
-            INITBITS();
-            break;
-#ifdef GUNZIP
-        case FLAGS:
-            NEEDBITS(16);
-            state->flags = (int)(hold);
-            if ((state->flags & 0xff) != Z_DEFLATED) {
-                strm->msg = (char *)"unknown compression method";
-                state->mode = BAD;
-                break;
-            }
-            if (state->flags & 0xe000) {
-                strm->msg = (char *)"unknown header flags set";
-                state->mode = BAD;
-                break;
-            }
-            if (state->head != Z_NULL)
-                state->head->text = (int)((hold >> 8) & 1);
-            if ((state->flags & 0x0200) && (state->wrap & 4))
-                CRC2(state->check, hold);
-            INITBITS();
-            state->mode = TIME;
-        case TIME:
-            NEEDBITS(32);
-            if (state->head != Z_NULL)
-                state->head->time = hold;
-            if ((state->flags & 0x0200) && (state->wrap & 4))
-                CRC4(state->check, hold);
-            INITBITS();
-            state->mode = OS;
-        case OS:
-            NEEDBITS(16);
-            if (state->head != Z_NULL) {
-                state->head->xflags = (int)(hold & 0xff);
-                state->head->os = (int)(hold >> 8);
-            }
-            if ((state->flags & 0x0200) && (state->wrap & 4))
-                CRC2(state->check, hold);
-            INITBITS();
-            state->mode = EXLEN;
-        case EXLEN:
-            if (state->flags & 0x0400) {
-                NEEDBITS(16);
-                state->length = (unsigned)(hold);
-                if (state->head != Z_NULL)
-                    state->head->extra_len = (unsigned)hold;
-                if ((state->flags & 0x0200) && (state->wrap & 4))
-                    CRC2(state->check, hold);
-                INITBITS();
-            }
-            else if (state->head != Z_NULL)
-                state->head->extra = Z_NULL;
-            state->mode = EXTRA;
-        case EXTRA:
-            if (state->flags & 0x0400) {
-                copy = state->length;
-                if (copy > have) copy = have;
-                if (copy) {
-                    if (state->head != Z_NULL &&
-                        state->head->extra != Z_NULL) {
-                        len = state->head->extra_len - state->length;
-                        zmemcpy(state->head->extra + len, next,
-                                len + copy > state->head->extra_max ?
-                                state->head->extra_max - len : copy);
-                    }
-                    if ((state->flags & 0x0200) && (state->wrap & 4))
-                        state->check = crc32(state->check, next, copy);
-                    have -= copy;
-                    next += copy;
-                    state->length -= copy;
-                }
-                if (state->length) goto inf_leave;
-            }
-            state->length = 0;
-            state->mode = NAME;
-        case NAME:
-            if (state->flags & 0x0800) {
-                if (have == 0) goto inf_leave;
-                copy = 0;
-                do {
-                    len = (unsigned)(next[copy++]);
-                    if (state->head != Z_NULL &&
-                            state->head->name != Z_NULL &&
-                            state->length < state->head->name_max)
-                        state->head->name[state->length++] = (Bytef)len;
-                } while (len && copy < have);
-                if ((state->flags & 0x0200) && (state->wrap & 4))
-                    state->check = crc32(state->check, next, copy);
-                have -= copy;
-                next += copy;
-                if (len) goto inf_leave;
-            }
-            else if (state->head != Z_NULL)
-                state->head->name = Z_NULL;
-            state->length = 0;
-            state->mode = COMMENT;
-        case COMMENT:
-            if (state->flags & 0x1000) {
-                if (have == 0) goto inf_leave;
-                copy = 0;
-                do {
-                    len = (unsigned)(next[copy++]);
-                    if (state->head != Z_NULL &&
-                            state->head->comment != Z_NULL &&
-                            state->length < state->head->comm_max)
-                        state->head->comment[state->length++] = (Bytef)len;
-                } while (len && copy < have);
-                if ((state->flags & 0x0200) && (state->wrap & 4))
-                    state->check = crc32(state->check, next, copy);
-                have -= copy;
-                next += copy;
-                if (len) goto inf_leave;
-            }
-            else if (state->head != Z_NULL)
-                state->head->comment = Z_NULL;
-            state->mode = HCRC;
-        case HCRC:
-            if (state->flags & 0x0200) {
-                NEEDBITS(16);
-                if ((state->wrap & 4) && hold != (state->check & 0xffff)) {
-                    strm->msg = (char *)"header crc mismatch";
-                    state->mode = BAD;
-                    break;
-                }
-                INITBITS();
-            }
-            if (state->head != Z_NULL) {
-                state->head->hcrc = (int)((state->flags >> 9) & 1);
-                state->head->done = 1;
-            }
-            strm->adler = state->check = crc32(0L, Z_NULL, 0);
-            state->mode = TYPE;
-            break;
-#endif
-        case DICTID:
-            NEEDBITS(32);
-            strm->adler = state->check = ZSWAP32(hold);
-            INITBITS();
-            state->mode = DICT;
-        case DICT:
-            if (state->havedict == 0) {
-                RESTORE();
-                return Z_NEED_DICT;
-            }
-            strm->adler = state->check = adler32(0L, Z_NULL, 0);
-            state->mode = TYPE;
-        case TYPE:
-            if (flush == Z_BLOCK || flush == Z_TREES) goto inf_leave;
-        case TYPEDO:
-            if (state->last) {
-                BYTEBITS();
-                state->mode = CHECK;
-                break;
-            }
-            NEEDBITS(3);
-            state->last = BITS(1);
-            DROPBITS(1);
-            switch (BITS(2)) {
-            case 0:                             /* stored block */
-                Tracev((stderr, "inflate:     stored block%s\n",
-                        state->last ? " (last)" : ""));
-                state->mode = STORED;
-                break;
-            case 1:                             /* fixed block */
-                fixedtables(state);
-                Tracev((stderr, "inflate:     fixed codes block%s\n",
-                        state->last ? " (last)" : ""));
-                state->mode = LEN_;             /* decode codes */
-                if (flush == Z_TREES) {
-                    DROPBITS(2);
-                    goto inf_leave;
-                }
-                break;
-            case 2:                             /* dynamic block */
-                Tracev((stderr, "inflate:     dynamic codes block%s\n",
-                        state->last ? " (last)" : ""));
-                state->mode = TABLE;
-                break;
-            case 3:
-                strm->msg = (char *)"invalid block type";
-                state->mode = BAD;
-            }
-            DROPBITS(2);
-            break;
-        case STORED:
-            BYTEBITS();                         /* go to byte boundary */
-            NEEDBITS(32);
-            if ((hold & 0xffff) != ((hold >> 16) ^ 0xffff)) {
-                strm->msg = (char *)"invalid stored block lengths";
-                state->mode = BAD;
-                break;
-            }
-            state->length = (unsigned)hold & 0xffff;
-            Tracev((stderr, "inflate:       stored length %u\n",
-                    state->length));
-            INITBITS();
-            state->mode = COPY_;
-            if (flush == Z_TREES) goto inf_leave;
-        case COPY_:
-            state->mode = COPY;
-        case COPY:
-            copy = state->length;
-            if (copy) {
-                if (copy > have) copy = have;
-                if (copy > left) copy = left;
-                if (copy == 0) goto inf_leave;
-                zmemcpy(put, next, copy);
-                have -= copy;
-                next += copy;
-                left -= copy;
-                put += copy;
-                state->length -= copy;
-                break;
-            }
-            Tracev((stderr, "inflate:       stored end\n"));
-            state->mode = TYPE;
-            break;
-        case TABLE:
-            NEEDBITS(14);
-            state->nlen = BITS(5) + 257;
-            DROPBITS(5);
-            state->ndist = BITS(5) + 1;
-            DROPBITS(5);
-            state->ncode = BITS(4) + 4;
-            DROPBITS(4);
-#ifndef PKZIP_BUG_WORKAROUND
-            if (state->nlen > 286 || state->ndist > 30) {
-                strm->msg = (char *)"too many length or distance symbols";
-                state->mode = BAD;
-                break;
-            }
-#endif
-            Tracev((stderr, "inflate:       table sizes ok\n"));
-            state->have = 0;
-            state->mode = LENLENS;
-        case LENLENS:
-            while (state->have < state->ncode) {
-                NEEDBITS(3);
-                state->lens[order[state->have++]] = (unsigned short)BITS(3);
-                DROPBITS(3);
-            }
-            while (state->have < 19)
-                state->lens[order[state->have++]] = 0;
-            state->next = state->codes;
-            state->lencode = (const code FAR *)(state->next);
-            state->lenbits = 7;
-            ret = inflate_table(CODES, state->lens, 19, &(state->next),
-                                &(state->lenbits), state->work);
-            if (ret) {
-                strm->msg = (char *)"invalid code lengths set";
-                state->mode = BAD;
-                break;
-            }
-            Tracev((stderr, "inflate:       code lengths ok\n"));
-            state->have = 0;
-            state->mode = CODELENS;
-        case CODELENS:
-            while (state->have < state->nlen + state->ndist) {
-                for (;;) {
-                    here = state->lencode[BITS(state->lenbits)];
-                    if ((unsigned)(here.bits) <= bits) break;
-                    PULLBYTE();
-                }
-                if (here.val < 16) {
-                    DROPBITS(here.bits);
-                    state->lens[state->have++] = here.val;
-                }
-                else {
-                    if (here.val == 16) {
-                        NEEDBITS(here.bits + 2);
-                        DROPBITS(here.bits);
-                        if (state->have == 0) {
-                            strm->msg = (char *)"invalid bit length repeat";
-                            state->mode = BAD;
-                            break;
-                        }
-                        len = state->lens[state->have - 1];
-                        copy = 3 + BITS(2);
-                        DROPBITS(2);
-                    }
-                    else if (here.val == 17) {
-                        NEEDBITS(here.bits + 3);
-                        DROPBITS(here.bits);
-                        len = 0;
-                        copy = 3 + BITS(3);
-                        DROPBITS(3);
-                    }
-                    else {
-                        NEEDBITS(here.bits + 7);
-                        DROPBITS(here.bits);
-                        len = 0;
-                        copy = 11 + BITS(7);
-                        DROPBITS(7);
-                    }
-                    if (state->have + copy > state->nlen + state->ndist) {
-                        strm->msg = (char *)"invalid bit length repeat";
-                        state->mode = BAD;
-                        break;
-                    }
-                    while (copy--)
-                        state->lens[state->have++] = (unsigned short)len;
-                }
-            }
-
-            /* handle error breaks in while */
-            if (state->mode == BAD) break;
-
-            /* check for end-of-block code (better have one) */
-            if (state->lens[256] == 0) {
-                strm->msg = (char *)"invalid code -- missing end-of-block";
-                state->mode = BAD;
-                break;
-            }
-
-            /* build code tables -- note: do not change the lenbits or distbits
-               values here (9 and 6) without reading the comments in inftrees.h
-               concerning the ENOUGH constants, which depend on those values */
-            state->next = state->codes;
-            state->lencode = (const code FAR *)(state->next);
-            state->lenbits = 9;
-            ret = inflate_table(LENS, state->lens, state->nlen, &(state->next),
-                                &(state->lenbits), state->work);
-            if (ret) {
-                strm->msg = (char *)"invalid literal/lengths set";
-                state->mode = BAD;
-                break;
-            }
-            state->distcode = (const code FAR *)(state->next);
-            state->distbits = 6;
-            ret = inflate_table(DISTS, state->lens + state->nlen, state->ndist,
-                            &(state->next), &(state->distbits), state->work);
-            if (ret) {
-                strm->msg = (char *)"invalid distances set";
-                state->mode = BAD;
-                break;
-            }
-            Tracev((stderr, "inflate:       codes ok\n"));
-            state->mode = LEN_;
-            if (flush == Z_TREES) goto inf_leave;
-        case LEN_:
-            state->mode = LEN;
-        case LEN:
-            if (have >= 6 && left >= 258) {
-                RESTORE();
-                inflate_fast(strm, out);
-                LOAD();
-                if (state->mode == TYPE)
-                    state->back = -1;
-                break;
-            }
-            state->back = 0;
-            for (;;) {
-                here = state->lencode[BITS(state->lenbits)];
-                if ((unsigned)(here.bits) <= bits) break;
-                PULLBYTE();
-            }
-            if (here.op && (here.op & 0xf0) == 0) {
-                last = here;
-                for (;;) {
-                    here = state->lencode[last.val +
-                            (BITS(last.bits + last.op) >> last.bits)];
-                    if ((unsigned)(last.bits + here.bits) <= bits) break;
-                    PULLBYTE();
-                }
-                DROPBITS(last.bits);
-                state->back += last.bits;
-            }
-            DROPBITS(here.bits);
-            state->back += here.bits;
-            state->length = (unsigned)here.val;
-            if ((int)(here.op) == 0) {
-                Tracevv((stderr, here.val >= 0x20 && here.val < 0x7f ?
-                        "inflate:         literal '%c'\n" :
-                        "inflate:         literal 0x%02x\n", here.val));
-                state->mode = LIT;
-                break;
-            }
-            if (here.op & 32) {
-                Tracevv((stderr, "inflate:         end of block\n"));
-                state->back = -1;
-                state->mode = TYPE;
-                break;
-            }
-            if (here.op & 64) {
-                strm->msg = (char *)"invalid literal/length code";
-                state->mode = BAD;
-                break;
-            }
-            state->extra = (unsigned)(here.op) & 15;
-            state->mode = LENEXT;
-        case LENEXT:
-            if (state->extra) {
-                NEEDBITS(state->extra);
-                state->length += BITS(state->extra);
-                DROPBITS(state->extra);
-                state->back += state->extra;
-            }
-            Tracevv((stderr, "inflate:         length %u\n", state->length));
-            state->was = state->length;
-            state->mode = DIST;
-        case DIST:
-            for (;;) {
-                here = state->distcode[BITS(state->distbits)];
-                if ((unsigned)(here.bits) <= bits) break;
-                PULLBYTE();
-            }
-            if ((here.op & 0xf0) == 0) {
-                last = here;
-                for (;;) {
-                    here = state->distcode[last.val +
-                            (BITS(last.bits + last.op) >> last.bits)];
-                    if ((unsigned)(last.bits + here.bits) <= bits) break;
-                    PULLBYTE();
-                }
-                DROPBITS(last.bits);
-                state->back += last.bits;
-            }
-            DROPBITS(here.bits);
-            state->back += here.bits;
-            if (here.op & 64) {
-                strm->msg = (char *)"invalid distance code";
-                state->mode = BAD;
-                break;
-            }
-            state->offset = (unsigned)here.val;
-            state->extra = (unsigned)(here.op) & 15;
-            state->mode = DISTEXT;
-        case DISTEXT:
-            if (state->extra) {
-                NEEDBITS(state->extra);
-                state->offset += BITS(state->extra);
-                DROPBITS(state->extra);
-                state->back += state->extra;
-            }
-#ifdef INFLATE_STRICT
-            if (state->offset > state->dmax) {
-                strm->msg = (char *)"invalid distance too far back";
-                state->mode = BAD;
-                break;
-            }
-#endif
-            Tracevv((stderr, "inflate:         distance %u\n", state->offset));
-            state->mode = MATCH;
-        case MATCH:
-            if (left == 0) goto inf_leave;
-            copy = out - left;
-            if (state->offset > copy) {         /* copy from window */
-                copy = state->offset - copy;
-                if (copy > state->whave) {
-                    if (state->sane) {
-                        strm->msg = (char *)"invalid distance too far back";
-                        state->mode = BAD;
-                        break;
-                    }
-#ifdef INFLATE_ALLOW_INVALID_DISTANCE_TOOFAR_ARRR
-                    Trace((stderr, "inflate.c too far\n"));
-                    copy -= state->whave;
-                    if (copy > state->length) copy = state->length;
-                    if (copy > left) copy = left;
-                    left -= copy;
-                    state->length -= copy;
-                    do {
-                        *put++ = 0;
-                    } while (--copy);
-                    if (state->length == 0) state->mode = LEN;
-                    break;
-#endif
-                }
-                if (copy > state->wnext) {
-                    copy -= state->wnext;
-                    from = state->window + (state->wsize - copy);
-                }
-                else
-                    from = state->window + (state->wnext - copy);
-                if (copy > state->length) copy = state->length;
-                if (copy > left) copy = left;
-                put = chunkcopy_safe(put, from, copy, put + left);
-            }
-            else {                              /* copy from output */
-                copy = state->length;
-                if (copy > left) copy = left;
-                put = chunkcopy_lapped_safe(put, state->offset, copy, put + left);
-            }
-            left -= copy;
-            state->length -= copy;
-            if (state->length == 0) state->mode = LEN;
-            break;
-        case LIT:
-            if (left == 0) goto inf_leave;
-            *put++ = (unsigned char)(state->length);
-            left--;
-            state->mode = LEN;
-            break;
-        case CHECK:
-            if (state->wrap) {
-                NEEDBITS(32);
-                out -= left;
-                strm->total_out += out;
-                state->total += out;
-                if ((state->wrap & 4) && out)
-                    strm->adler = state->check =
-                        UPDATE(state->check, put - out, out);
-                out = left;
-                if ((state->wrap & 4) && (
-#ifdef GUNZIP
-                     state->flags ? hold :
-#endif
-                     ZSWAP32(hold)) != state->check) {
-                    strm->msg = (char *)"incorrect data check";
-                    state->mode = BAD;
-                    break;
-                }
-                INITBITS();
-                Tracev((stderr, "inflate:   check matches trailer\n"));
-            }
-#ifdef GUNZIP
-            state->mode = LENGTH;
-        case LENGTH:
-            if (state->wrap && state->flags) {
-                NEEDBITS(32);
-                if (hold != (state->total & 0xffffffffUL)) {
-                    strm->msg = (char *)"incorrect length check";
-                    state->mode = BAD;
-                    break;
-                }
-                INITBITS();
-                Tracev((stderr, "inflate:   length matches trailer\n"));
-            }
-#endif
-            state->mode = DONE;
-        case DONE:
-            ret = Z_STREAM_END;
-            goto inf_leave;
-        case BAD:
-            ret = Z_DATA_ERROR;
-            goto inf_leave;
-        case MEM:
-            return Z_MEM_ERROR;
-        case SYNC:
-        default:
-            return Z_STREAM_ERROR;
-        }
-
-    /*
-       Return from inflate(), updating the total counts and the check value.
-       If there was no progress during the inflate() call, return a buffer
-       error.  Call updatewindow() to create and/or update the window state.
-       Note: a memory error from inflate() is non-recoverable.
-     */
-  inf_leave:
-    RESTORE();
-    if (state->wsize || (out != strm->avail_out && state->mode < BAD &&
-            (state->mode < CHECK || flush != Z_FINISH)))
-        if (updatewindow(strm, strm->next_out, out - strm->avail_out)) {
-            state->mode = MEM;
-            return Z_MEM_ERROR;
-        }
-    in -= strm->avail_in;
-    out -= strm->avail_out;
-    strm->total_in += in;
-    strm->total_out += out;
-    state->total += out;
-    if ((state->wrap & 4) && out)
-        strm->adler = state->check =
-            UPDATE(state->check, strm->next_out - out, out);
-    strm->data_type = (int)state->bits + (state->last ? 64 : 0) +
-                      (state->mode == TYPE ? 128 : 0) +
-                      (state->mode == LEN_ || state->mode == COPY_ ? 256 : 0);
-    if (((in == 0 && out == 0) || flush == Z_FINISH) && ret == Z_OK)
-        ret = Z_BUF_ERROR;
-    return ret;
-}
-
-int ZEXPORT inflateEnd(strm)
-z_streamp strm;
-{
-    struct inflate_state FAR *state;
-    if (inflateStateCheck(strm))
-        return Z_STREAM_ERROR;
-    state = (struct inflate_state FAR *)strm->state;
-    if (state->window != Z_NULL) ZFREE(strm, state->window);
-    ZFREE(strm, strm->state);
-    strm->state = Z_NULL;
-    Tracev((stderr, "inflate: end\n"));
-    return Z_OK;
-}
-
-int ZEXPORT inflateGetDictionary(strm, dictionary, dictLength)
-z_streamp strm;
-Bytef *dictionary;
-uInt *dictLength;
-{
-    struct inflate_state FAR *state;
-
-    /* check state */
-    if (inflateStateCheck(strm)) return Z_STREAM_ERROR;
-    state = (struct inflate_state FAR *)strm->state;
-
-    /* copy dictionary */
-    if (state->whave && dictionary != Z_NULL) {
-        zmemcpy(dictionary, state->window + state->wnext,
-                state->whave - state->wnext);
-        zmemcpy(dictionary + state->whave - state->wnext,
-                state->window, state->wnext);
-    }
-    if (dictLength != Z_NULL)
-        *dictLength = state->whave;
-    return Z_OK;
-}
-
-int ZEXPORT inflateSetDictionary(strm, dictionary, dictLength)
-z_streamp strm;
-const Bytef *dictionary;
-uInt dictLength;
-{
-    struct inflate_state FAR *state;
-    unsigned long dictid;
-    int ret;
-
-    /* check state */
-    if (inflateStateCheck(strm)) return Z_STREAM_ERROR;
-    state = (struct inflate_state FAR *)strm->state;
-    if (state->wrap != 0 && state->mode != DICT)
-        return Z_STREAM_ERROR;
-
-    /* check for correct dictionary identifier */
-    if (state->mode == DICT) {
-        dictid = adler32(0L, Z_NULL, 0);
-        dictid = adler32(dictid, dictionary, dictLength);
-        if (dictid != state->check)
-            return Z_DATA_ERROR;
-    }
-
-    /* copy dictionary to window using updatewindow(), which will amend the
-       existing dictionary if appropriate */
-    ret = updatewindow(strm, dictionary + dictLength, dictLength);
-    if (ret) {
-        state->mode = MEM;
-        return Z_MEM_ERROR;
-    }
-    state->havedict = 1;
-    Tracev((stderr, "inflate:   dictionary set\n"));
-    return Z_OK;
-}
-
-int ZEXPORT inflateGetHeader(strm, head)
-z_streamp strm;
-gz_headerp head;
-{
-    struct inflate_state FAR *state;
-
-    /* check state */
-    if (inflateStateCheck(strm)) return Z_STREAM_ERROR;
-    state = (struct inflate_state FAR *)strm->state;
-    if ((state->wrap & 2) == 0) return Z_STREAM_ERROR;
-
-    /* save header structure */
-    state->head = head;
-    head->done = 0;
-    return Z_OK;
-}
-
-/*
-   Search buf[0..len-1] for the pattern: 0, 0, 0xff, 0xff.  Return when found
-   or when out of input.  When called, *have is the number of pattern bytes
-   found in order so far, in 0..3.  On return *have is updated to the new
-   state.  If on return *have equals four, then the pattern was found and the
-   return value is how many bytes were read including the last byte of the
-   pattern.  If *have is less than four, then the pattern has not been found
-   yet and the return value is len.  In the latter case, syncsearch() can be
-   called again with more data and the *have state.  *have is initialized to
-   zero for the first call.
- */
-local unsigned syncsearch(have, buf, len)
-unsigned FAR *have;
-const unsigned char FAR *buf;
-unsigned len;
-{
-    unsigned got;
-    unsigned next;
-
-    got = *have;
-    next = 0;
-    while (next < len && got < 4) {
-        if ((int)(buf[next]) == (got < 2 ? 0 : 0xff))
-            got++;
-        else if (buf[next])
-            got = 0;
-        else
-            got = 4 - got;
-        next++;
-    }
-    *have = got;
-    return next;
-}
-
-int ZEXPORT inflateSync(strm)
-z_streamp strm;
-{
-    unsigned len;               /* number of bytes to look at or looked at */
-    unsigned long in, out;      /* temporary to save total_in and total_out */
-    unsigned char buf[4];       /* to restore bit buffer to byte string */
-    struct inflate_state FAR *state;
-
-    /* check parameters */
-    if (inflateStateCheck(strm)) return Z_STREAM_ERROR;
-    state = (struct inflate_state FAR *)strm->state;
-    if (strm->avail_in == 0 && state->bits < 8) return Z_BUF_ERROR;
-
-    /* if first time, start search in bit buffer */
-    if (state->mode != SYNC) {
-        state->mode = SYNC;
-        state->hold <<= state->bits & 7;
-        state->bits -= state->bits & 7;
-        len = 0;
-        while (state->bits >= 8) {
-            buf[len++] = (unsigned char)(state->hold);
-            state->hold >>= 8;
-            state->bits -= 8;
-        }
-        state->have = 0;
-        syncsearch(&(state->have), buf, len);
-    }
-
-    /* search available input */
-    len = syncsearch(&(state->have), strm->next_in, strm->avail_in);
-    strm->avail_in -= len;
-    strm->next_in += len;
-    strm->total_in += len;
-
-    /* return no joy or set up to restart inflate() on a new block */
-    if (state->have != 4) return Z_DATA_ERROR;
-    in = strm->total_in;  out = strm->total_out;
-    inflateReset(strm);
-    strm->total_in = in;  strm->total_out = out;
-    state->mode = TYPE;
-    return Z_OK;
-}
-
-/*
-   Returns true if inflate is currently at the end of a block generated by
-   Z_SYNC_FLUSH or Z_FULL_FLUSH. This function is used by one PPP
-   implementation to provide an additional safety check. PPP uses
-   Z_SYNC_FLUSH but removes the length bytes of the resulting empty stored
-   block. When decompressing, PPP checks that at the end of input packet,
-   inflate is waiting for these length bytes.
- */
-int ZEXPORT inflateSyncPoint(strm)
-z_streamp strm;
-{
-    struct inflate_state FAR *state;
-
-    if (inflateStateCheck(strm)) return Z_STREAM_ERROR;
-    state = (struct inflate_state FAR *)strm->state;
-    return state->mode == STORED && state->bits == 0;
-}
-
-int ZEXPORT inflateCopy(dest, source)
-z_streamp dest;
-z_streamp source;
-{
-    struct inflate_state FAR *state;
-    struct inflate_state FAR *copy;
-    unsigned char FAR *window;
-    unsigned wsize;
-
-    /* check input */
-    if (inflateStateCheck(source) || dest == Z_NULL)
-        return Z_STREAM_ERROR;
-    state = (struct inflate_state FAR *)source->state;
-
-    /* allocate space */
-    copy = (struct inflate_state FAR *)
-           ZALLOC(source, 1, sizeof(struct inflate_state));
-    if (copy == Z_NULL) return Z_MEM_ERROR;
-    window = Z_NULL;
-    if (state->window != Z_NULL) {
-        window = (unsigned char FAR *)
-                 ZALLOC(source, 1U << state->wbits, sizeof(unsigned char));
-        if (window == Z_NULL) {
-            ZFREE(source, copy);
-            return Z_MEM_ERROR;
-        }
-    }
-
-    /* copy state */
-    zmemcpy((voidpf)dest, (voidpf)source, sizeof(z_stream));
-    zmemcpy((voidpf)copy, (voidpf)state, sizeof(struct inflate_state));
-    copy->strm = dest;
-    if (state->lencode >= state->codes &&
-        state->lencode <= state->codes + ENOUGH - 1) {
-        copy->lencode = copy->codes + (state->lencode - state->codes);
-        copy->distcode = copy->codes + (state->distcode - state->codes);
-    }
-    copy->next = copy->codes + (state->next - state->codes);
-    if (window != Z_NULL) {
-        wsize = 1U << state->wbits;
-        zmemcpy(window, state->window, wsize);
-    }
-    copy->window = window;
-    dest->state = (struct internal_state FAR *)copy;
-    return Z_OK;
-}
-
-int ZEXPORT inflateUndermine(strm, subvert)
-z_streamp strm;
-int subvert;
-{
-    struct inflate_state FAR *state;
-
-    if (inflateStateCheck(strm)) return Z_STREAM_ERROR;
-    state = (struct inflate_state FAR *)strm->state;
-#ifdef INFLATE_ALLOW_INVALID_DISTANCE_TOOFAR_ARRR
-    state->sane = !subvert;
-    return Z_OK;
-#else
-    (void)subvert;
-    state->sane = 1;
-    return Z_DATA_ERROR;
-#endif
-}
-
-int ZEXPORT inflateValidate(strm, check)
-z_streamp strm;
-int check;
-{
-    struct inflate_state FAR *state;
-
-    if (inflateStateCheck(strm)) return Z_STREAM_ERROR;
-    state = (struct inflate_state FAR *)strm->state;
-    if (check)
-        state->wrap |= 4;
-    else
-        state->wrap &= ~4;
-    return Z_OK;
-}
-
-long ZEXPORT inflateMark(strm)
-z_streamp strm;
-{
-    struct inflate_state FAR *state;
-
-    if (inflateStateCheck(strm))
-        return -(1L << 16);
-    state = (struct inflate_state FAR *)strm->state;
-    return (long)(((unsigned long)((long)state->back)) << 16) +
-        (state->mode == COPY ? state->length :
-            (state->mode == MATCH ? state->was - state->length : 0));
-}
-
-unsigned long ZEXPORT inflateCodesUsed(strm)
-z_streamp strm;
-{
-    struct inflate_state FAR *state;
-    if (inflateStateCheck(strm)) return (unsigned long)-1;
-    state = (struct inflate_state FAR *)strm->state;
-    return (unsigned long)(state->next - state->codes);
-}
diff --git a/third_party/zlib/contrib/optimizations/arm/chunkcopy_arm.h b/third_party/zlib/contrib/optimizations/arm/chunkcopy_arm.h
new file mode 100644
index 0000000..41474c8a
--- /dev/null
+++ b/third_party/zlib/contrib/optimizations/arm/chunkcopy_arm.h
@@ -0,0 +1,122 @@
+/* chunkcopy_arm.h -- fast copies and sets
+ * Copyright (C) 2017 ARM, Inc.
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+#ifndef CHUNKCOPY_ARM_H
+#define CHUNKCOPY_ARM_H
+
+#include <arm_neon.h>
+#include "zutil.h"
+
+#if __STDC_VERSION__ >= 199901L
+#define Z_RESTRICT restrict
+#else
+#define Z_RESTRICT
+#endif
+
+/* A port to a new arch only requires to implement 2 functions
+  (vld_dup and chunkset_core) and the chunk type.
+*/
+
+typedef uint8x16_t chunkcopy_chunk_t;
+#define CHUNKCOPY_CHUNK_SIZE sizeof(chunkcopy_chunk_t)
+
+/* Forward declarations. */
+static inline unsigned char FAR* chunkunroll_relaxed(unsigned char FAR* out,
+                                                     unsigned FAR* dist,
+                                                     unsigned FAR* len);
+
+static inline unsigned char FAR* chunkcopy_core(unsigned char FAR* out,
+                                                const unsigned char FAR* from,
+                                                unsigned len);
+
+/* Architecture specific code starts here. */
+static inline uint8x16_t chunkset_vld1q_dup_u8x8(
+    const unsigned char FAR* Z_RESTRICT from) {
+#if defined(__clang__) || defined(__aarch64__)
+  return vreinterpretq_u8_u64(vld1q_dup_u64((void*)from));
+#else
+  /* 32-bit GCC uses an alignment hint for vld1q_dup_u64, even when given a
+   * void pointer, so here's an alternate implementation.
+   */
+  uint8x8_t h = vld1_u8(from);
+  return vcombine_u8(h, h);
+#endif
+}
+
+/*
+   Perform an overlapping copy which behaves as a memset() operation, but
+   supporting periods other than one, and assume that length is non-zero and
+   that it's OK to overwrite at least CHUNKCOPY_CHUNK_SIZE*3 bytes of output
+   even if the length is shorter than this.
+   TODO(cavalcantii): maybe rename vreinterpretq and chunkset_vld to make it
+                      generic and move this code to chunkcopy.h (plus we
+                      won't need the forward declarations).
+ */
+static inline unsigned char FAR* chunkset_core(unsigned char FAR* out,
+                                               unsigned period,
+                                               unsigned len) {
+  uint8x16_t f;
+  int bump = ((len - 1) % sizeof(f)) + 1;
+
+  switch (period) {
+    case 1:
+      f = vld1q_dup_u8(out - 1);
+      vst1q_u8(out, f);
+      out += bump;
+      len -= bump;
+      while (len > 0) {
+        vst1q_u8(out, f);
+        out += sizeof(f);
+        len -= sizeof(f);
+      }
+      return out;
+    case 2:
+      f = vreinterpretq_u8_u16(vld1q_dup_u16((void*)(out - 2)));
+      vst1q_u8(out, f);
+      out += bump;
+      len -= bump;
+      if (len > 0) {
+        f = vreinterpretq_u8_u16(vld1q_dup_u16((void*)(out - 2)));
+        do {
+          vst1q_u8(out, f);
+          out += sizeof(f);
+          len -= sizeof(f);
+        } while (len > 0);
+      }
+      return out;
+    case 4:
+      f = vreinterpretq_u8_u32(vld1q_dup_u32((void*)(out - 4)));
+      vst1q_u8(out, f);
+      out += bump;
+      len -= bump;
+      if (len > 0) {
+        f = vreinterpretq_u8_u32(vld1q_dup_u32((void*)(out - 4)));
+        do {
+          vst1q_u8(out, f);
+          out += sizeof(f);
+          len -= sizeof(f);
+        } while (len > 0);
+      }
+      return out;
+    case 8:
+      f = chunkset_vld1q_dup_u8x8(out - 8);
+      vst1q_u8(out, f);
+      out += bump;
+      len -= bump;
+      if (len > 0) {
+        f = chunkset_vld1q_dup_u8x8(out - 8);
+        do {
+          vst1q_u8(out, f);
+          out += sizeof(f);
+          len -= sizeof(f);
+        } while (len > 0);
+      }
+      return out;
+  }
+  out = chunkunroll_relaxed(out, &period, &len);
+  return chunkcopy_core(out, out - period, len);
+}
+
+#endif /* CHUNKCOPY_ARM_H */
diff --git a/third_party/zlib/contrib/optimizations/chunkcopy.h b/third_party/zlib/contrib/optimizations/chunkcopy.h
new file mode 100644
index 0000000..2080643
--- /dev/null
+++ b/third_party/zlib/contrib/optimizations/chunkcopy.h
@@ -0,0 +1,204 @@
+/* chunkcopy.h -- fast copies and sets
+ * Copyright (C) 2017 ARM, Inc.
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+#ifndef CHUNKCOPY_H
+#define CHUNKCOPY_H
+
+// TODO(cavalcantii): add the Intel code next.
+#include "chunkcopy_arm.h"
+
+/*
+   Ask the compiler to perform a wide, unaligned load with an machine
+   instruction appropriate for the chunkcopy_chunk_t type.
+ */
+static inline chunkcopy_chunk_t loadchunk(const unsigned char FAR* s) {
+  chunkcopy_chunk_t c;
+  __builtin_memcpy(&c, s, sizeof(c));
+  return c;
+}
+
+/*
+   Ask the compiler to perform a wide, unaligned store with an machine
+   instruction appropriate for the chunkcopy_chunk_t type.
+ */
+static inline void storechunk(unsigned char FAR* d, chunkcopy_chunk_t c) {
+  __builtin_memcpy(d, &c, sizeof(c));
+}
+
+/*
+   Perform a memcpy-like operation, but assume that length is non-zero and that
+   it's OK to overwrite at least CHUNKCOPY_CHUNK_SIZE bytes of output even if
+   the length is shorter than this.
+
+   It also guarantees that it will properly unroll the data if the distance
+   between `out` and `from` is at least CHUNKCOPY_CHUNK_SIZE, which we rely on
+   in chunkcopy_relaxed().
+
+   Aside from better memory bus utilisation, this means that short copies
+   (CHUNKCOPY_CHUNK_SIZE bytes or fewer) will fall straight through the loop
+   without iteration, which will hopefully make the branch prediction more
+   reliable.
+ */
+static inline unsigned char FAR* chunkcopy_core(unsigned char FAR* out,
+                                                const unsigned char FAR* from,
+                                                unsigned len) {
+  int bump = (--len % CHUNKCOPY_CHUNK_SIZE) + 1;
+  storechunk(out, loadchunk(from));
+  out += bump;
+  from += bump;
+  len /= CHUNKCOPY_CHUNK_SIZE;
+  while (len-- > 0) {
+    storechunk(out, loadchunk(from));
+    out += CHUNKCOPY_CHUNK_SIZE;
+    from += CHUNKCOPY_CHUNK_SIZE;
+  }
+  return out;
+}
+
+/*
+   Like chunkcopy_core, but avoid writing beyond of legal output.
+
+   Accepts an additional pointer to the end of safe output.  A generic safe
+   copy would use (out + len), but it's normally the case that the end of the
+   output buffer is beyond the end of the current copy, and this can still be
+   exploited.
+ */
+static inline unsigned char FAR* chunkcopy_core_safe(
+    unsigned char FAR* out,
+    const unsigned char FAR* from,
+    unsigned len,
+    unsigned char FAR* limit) {
+  Assert(out + len <= limit, "chunk copy exceeds safety limit");
+  if (limit - out < CHUNKCOPY_CHUNK_SIZE) {
+    const unsigned char FAR* Z_RESTRICT rfrom = from;
+    if (len & 8) {
+      __builtin_memcpy(out, rfrom, 8);
+      out += 8;
+      rfrom += 8;
+    }
+    if (len & 4) {
+      __builtin_memcpy(out, rfrom, 4);
+      out += 4;
+      rfrom += 4;
+    }
+    if (len & 2) {
+      __builtin_memcpy(out, rfrom, 2);
+      out += 2;
+      rfrom += 2;
+    }
+    if (len & 1) {
+      *out++ = *rfrom++;
+    }
+    return out;
+  }
+  return chunkcopy_core(out, from, len);
+}
+
+/*
+   Perform short copies until distance can be rewritten as being at least
+   CHUNKCOPY_CHUNK_SIZE.
+
+   This assumes that it's OK to overwrite at least the first
+   2*CHUNKCOPY_CHUNK_SIZE bytes of output even if the copy is shorter than
+   this.  This assumption holds within inflate_fast() which starts every
+   iteration with at least 258 bytes of output space available (258 being the
+   maximum length output from a single token; see inffast.c).
+ */
+static inline unsigned char FAR* chunkunroll_relaxed(unsigned char FAR* out,
+                                                     unsigned FAR* dist,
+                                                     unsigned FAR* len) {
+  const unsigned char FAR* from = out - *dist;
+  while (*dist < *len && *dist < CHUNKCOPY_CHUNK_SIZE) {
+    storechunk(out, loadchunk(from));
+    out += *dist;
+    *len -= *dist;
+    *dist += *dist;
+  }
+  return out;
+}
+
+/*
+   Perform a memcpy-like operation, but assume that length is non-zero and that
+   it's OK to overwrite at least CHUNKCOPY_CHUNK_SIZE bytes of output even if
+   the length is shorter than this.
+
+   Unlike chunkcopy_core() above, no guarantee is made regarding the behaviour
+   of overlapping buffers, regardless of the distance between the pointers.
+   This is reflected in the `restrict`-qualified pointers, allowing the
+   compiler to reorder loads and stores.
+ */
+static inline unsigned char FAR* chunkcopy_relaxed(
+    unsigned char FAR* Z_RESTRICT out,
+    const unsigned char FAR* Z_RESTRICT from,
+    unsigned len) {
+  return chunkcopy_core(out, from, len);
+}
+
+/*
+   Like chunkcopy_relaxed, but avoid writing beyond of legal output.
+
+   Unlike chunkcopy_core_safe() above, no guarantee is made regarding the
+   behaviour of overlapping buffers, regardless of the distance between the
+   pointers.  This is reflected in the `restrict`-qualified pointers, allowing
+   the compiler to reorder loads and stores.
+
+   Accepts an additional pointer to the end of safe output.  A generic safe
+   copy would use (out + len), but it's normally the case that the end of the
+   output buffer is beyond the end of the current copy, and this can still be
+   exploited.
+ */
+static inline unsigned char FAR* chunkcopy_safe(
+    unsigned char FAR* out,
+    const unsigned char FAR* Z_RESTRICT from,
+    unsigned len,
+    unsigned char FAR* limit) {
+  Assert(out + len <= limit, "chunk copy exceeds safety limit");
+  return chunkcopy_core_safe(out, from, len, limit);
+}
+
+/*
+   Perform chunky copy within the same buffer, where the source and destination
+   may potentially overlap.
+
+   Assumes that len > 0 on entry, and that it's safe to write at least
+   CHUNKCOPY_CHUNK_SIZE*3 bytes to the output.
+ */
+static inline unsigned char FAR*
+chunkcopy_lapped_relaxed(unsigned char FAR* out, unsigned dist, unsigned len) {
+  if (dist < len && dist < CHUNKCOPY_CHUNK_SIZE) {
+    return chunkset_core(out, dist, len);
+  }
+  return chunkcopy_core(out, out - dist, len);
+}
+
+/*
+   Behave like chunkcopy_lapped_relaxed, but avoid writing beyond of legal
+   output.
+
+   Accepts an additional pointer to the end of safe output.  A generic safe
+   copy would use (out + len), but it's normally the case that the end of the
+   output buffer is beyond the end of the current copy, and this can still be
+   exploited.
+ */
+static inline unsigned char FAR* chunkcopy_lapped_safe(
+    unsigned char FAR* out,
+    unsigned dist,
+    unsigned len,
+    unsigned char FAR* limit) {
+  Assert(out + len <= limit, "chunk copy exceeds safety limit");
+  if (limit - out < CHUNKCOPY_CHUNK_SIZE * 3) {
+    /* TODO(cavalcantii): try harder to optimise this */
+    while (len-- > 0) {
+      *out = *(out - dist);
+      out++;
+    }
+    return out;
+  }
+  return chunkcopy_lapped_relaxed(out, dist, len);
+}
+
+#undef Z_RESTRICT
+
+#endif /* CHUNKCOPY_H */
diff --git a/third_party/zlib/contrib/optimizations/inffast_chunky.c b/third_party/zlib/contrib/optimizations/inffast_chunky.c
new file mode 100644
index 0000000..9170d33
--- /dev/null
+++ b/third_party/zlib/contrib/optimizations/inffast_chunky.c
@@ -0,0 +1,307 @@
+/* inffast_chunky.c -- fast decoding
+ * Copyright (C) 1995-2017 Mark Adler
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+#include "zutil.h"
+#include "inftrees.h"
+#include "inflate.h"
+#include "inffast.h"
+#include "contrib/optimizations/chunkcopy.h"
+
+#ifdef ASMINF
+#  pragma message("Assembler code may have bugs -- use at your own risk")
+#else
+
+/*
+   Decode literal, length, and distance codes and write out the resulting
+   literal and match bytes until either not enough input or output is
+   available, an end-of-block is encountered, or a data error is encountered.
+   When large enough input and output buffers are supplied to inflate(), for
+   example, a 16K input buffer and a 64K output buffer, more than 95% of the
+   inflate execution time is spent in this routine.
+
+   Entry assumptions:
+
+        state->mode == LEN
+        strm->avail_in >= 6
+        strm->avail_out >= 258
+        start >= strm->avail_out
+        state->bits < 8
+
+   On return, state->mode is one of:
+
+        LEN -- ran out of enough output space or enough available input
+        TYPE -- reached end of block code, inflate() to interpret next block
+        BAD -- error in block data
+
+   Notes:
+
+    - The maximum input bits used by a length/distance pair is 15 bits for the
+      length code, 5 bits for the length extra, 15 bits for the distance code,
+      and 13 bits for the distance extra.  This totals 48 bits, or six bytes.
+      Therefore if strm->avail_in >= 6, then there is enough input to avoid
+      checking for available input while decoding.
+
+    - The maximum bytes that a single length/distance pair can output is 258
+      bytes, which is the maximum length that can be coded.  inflate_fast()
+      requires strm->avail_out >= 258 for each loop to avoid checking for
+      output space.
+ */
+void ZLIB_INTERNAL inflate_fast(strm, start)
+z_streamp strm;
+unsigned start;         /* inflate()'s starting value for strm->avail_out */
+{
+    struct inflate_state FAR *state;
+    z_const unsigned char FAR *in;      /* local strm->next_in */
+    z_const unsigned char FAR *last;    /* have enough input while in < last */
+    unsigned char FAR *out;     /* local strm->next_out */
+    unsigned char FAR *beg;     /* inflate()'s initial strm->next_out */
+    unsigned char FAR *end;     /* while out < end, enough space available */
+    unsigned char FAR *limit;   /* safety limit for chunky copies */
+#ifdef INFLATE_STRICT
+    unsigned dmax;              /* maximum distance from zlib header */
+#endif
+    unsigned wsize;             /* window size or zero if not using window */
+    unsigned whave;             /* valid bytes in the window */
+    unsigned wnext;             /* window write index */
+    unsigned char FAR *window;  /* allocated sliding window, if wsize != 0 */
+    unsigned long hold;         /* local strm->hold */
+    unsigned bits;              /* local strm->bits */
+    code const FAR *lcode;      /* local strm->lencode */
+    code const FAR *dcode;      /* local strm->distcode */
+    unsigned lmask;             /* mask for first level of length codes */
+    unsigned dmask;             /* mask for first level of distance codes */
+    code here;                  /* retrieved table entry */
+    unsigned op;                /* code bits, operation, extra bits, or */
+                                /*  window position, window bytes to copy */
+    unsigned len;               /* match length, unused bytes */
+    unsigned dist;              /* match distance */
+    unsigned char FAR *from;    /* where to copy match from */
+
+    /* copy state to local variables */
+    state = (struct inflate_state FAR *)strm->state;
+    in = strm->next_in;
+    last = in + (strm->avail_in - 5);
+    out = strm->next_out;
+    beg = out - (start - strm->avail_out);
+    end = out + (strm->avail_out - 257);
+    limit = out + strm->avail_out;
+#ifdef INFLATE_STRICT
+    dmax = state->dmax;
+#endif
+    wsize = state->wsize;
+    whave = state->whave;
+    wnext = (state->wnext == 0 && whave >= wsize) ? wsize : state->wnext;
+    window = state->window;
+    hold = state->hold;
+    bits = state->bits;
+    lcode = state->lencode;
+    dcode = state->distcode;
+    lmask = (1U << state->lenbits) - 1;
+    dmask = (1U << state->distbits) - 1;
+
+    /* decode literals and length/distances until end-of-block or not enough
+       input data or output space */
+    do {
+        if (bits < 15) {
+            hold += (unsigned long)(*in++) << bits;
+            bits += 8;
+            hold += (unsigned long)(*in++) << bits;
+            bits += 8;
+        }
+        here = lcode[hold & lmask];
+      dolen:
+        op = (unsigned)(here.bits);
+        hold >>= op;
+        bits -= op;
+        op = (unsigned)(here.op);
+        if (op == 0) {                          /* literal */
+            Tracevv((stderr, here.val >= 0x20 && here.val < 0x7f ?
+                    "inflate:         literal '%c'\n" :
+                    "inflate:         literal 0x%02x\n", here.val));
+            *out++ = (unsigned char)(here.val);
+        }
+        else if (op & 16) {                     /* length base */
+            len = (unsigned)(here.val);
+            op &= 15;                           /* number of extra bits */
+            if (op) {
+                if (bits < op) {
+                    hold += (unsigned long)(*in++) << bits;
+                    bits += 8;
+                }
+                len += (unsigned)hold & ((1U << op) - 1);
+                hold >>= op;
+                bits -= op;
+            }
+            Tracevv((stderr, "inflate:         length %u\n", len));
+            if (bits < 15) {
+                hold += (unsigned long)(*in++) << bits;
+                bits += 8;
+                hold += (unsigned long)(*in++) << bits;
+                bits += 8;
+            }
+            here = dcode[hold & dmask];
+          dodist:
+            op = (unsigned)(here.bits);
+            hold >>= op;
+            bits -= op;
+            op = (unsigned)(here.op);
+            if (op & 16) {                      /* distance base */
+                dist = (unsigned)(here.val);
+                op &= 15;                       /* number of extra bits */
+                if (bits < op) {
+                    hold += (unsigned long)(*in++) << bits;
+                    bits += 8;
+                    if (bits < op) {
+                        hold += (unsigned long)(*in++) << bits;
+                        bits += 8;
+                    }
+                }
+                dist += (unsigned)hold & ((1U << op) - 1);
+#ifdef INFLATE_STRICT
+                if (dist > dmax) {
+                    strm->msg = (char *)"invalid distance too far back";
+                    state->mode = BAD;
+                    break;
+                }
+#endif
+                hold >>= op;
+                bits -= op;
+                Tracevv((stderr, "inflate:         distance %u\n", dist));
+                op = (unsigned)(out - beg);     /* max distance in output */
+                if (dist > op) {                /* see if copy from window */
+                    op = dist - op;             /* distance back in window */
+                    if (op > whave) {
+                        if (state->sane) {
+                            strm->msg =
+                                (char *)"invalid distance too far back";
+                            state->mode = BAD;
+                            break;
+                        }
+#ifdef INFLATE_ALLOW_INVALID_DISTANCE_TOOFAR_ARRR
+                        if (len <= op - whave) {
+                            do {
+                                *out++ = 0;
+                            } while (--len);
+                            continue;
+                        }
+                        len -= op - whave;
+                        do {
+                            *out++ = 0;
+                        } while (--op > whave);
+                        if (op == 0) {
+                            from = out - dist;
+                            do {
+                                *out++ = *from++;
+                            } while (--len);
+                            continue;
+                        }
+#endif
+                    }
+                    from = window;
+                    if (wnext >= op) {          /* contiguous in window */
+                        from += wnext - op;
+                    }
+                    else {                      /* wrap around window */
+                        op -= wnext;
+                        from += wsize - op;
+                        if (op < len) {         /* some from end of window */
+                            len -= op;
+                            out = chunkcopy_safe(out, from, op, limit);
+                            from = window;      /* more from start of window */
+                            op = wnext;
+                            /* This (rare) case can create a situation where
+                               the first chunkcopy below must be checked.
+                             */
+                        }
+                    }
+                    if (op < len) {             /* still need some from output */
+                        out = chunkcopy_safe(out, from, op, limit);
+                        len -= op;
+                        /* When dist is small the amount of data that can be
+                           copied from the window is also small, and progress
+                           towards the dangerous end of the output buffer is
+                           also small.  This means that for trivial memsets and
+                           for chunkunroll_relaxed() a safety check is
+                           unnecessary.  However, these conditions may not be
+                           entered at all, and in that case it's possible that
+                           the main copy is near the end.
+                          */
+                        out = chunkunroll_relaxed(out, &dist, &len);
+                        out = chunkcopy_safe(out, out - dist, len, limit);
+                    } else {
+                        /* from points to window, so there is no risk of
+                           overlapping pointers requiring memset-like behaviour
+                         */
+                        out = chunkcopy_safe(out, from, len, limit);
+                    }
+                }
+                else {
+                    /* Whole reference is in range of current output.  No
+                       range checks are necessary because we start with room
+                       for at least 258 bytes of output, so unroll and roundoff
+                       operations can write beyond `out+len` so long as they
+                       stay within 258 bytes of `out`.
+                     */
+                    out = chunkcopy_lapped_relaxed(out, dist, len);
+                }
+            }
+            else if ((op & 64) == 0) {          /* 2nd level distance code */
+                here = dcode[here.val + (hold & ((1U << op) - 1))];
+                goto dodist;
+            }
+            else {
+                strm->msg = (char *)"invalid distance code";
+                state->mode = BAD;
+                break;
+            }
+        }
+        else if ((op & 64) == 0) {              /* 2nd level length code */
+            here = lcode[here.val + (hold & ((1U << op) - 1))];
+            goto dolen;
+        }
+        else if (op & 32) {                     /* end-of-block */
+            Tracevv((stderr, "inflate:         end of block\n"));
+            state->mode = TYPE;
+            break;
+        }
+        else {
+            strm->msg = (char *)"invalid literal/length code";
+            state->mode = BAD;
+            break;
+        }
+    } while (in < last && out < end);
+
+    /* return unused bytes (on entry, bits < 8, so in won't go too far back) */
+    len = bits >> 3;
+    in -= len;
+    bits -= len << 3;
+    hold &= (1U << bits) - 1;
+
+    /* update state and return */
+    strm->next_in = in;
+    strm->next_out = out;
+    strm->avail_in = (unsigned)(in < last ? 5 + (last - in) : 5 - (in - last));
+    strm->avail_out = (unsigned)(out < end ?
+                                 257 + (end - out) : 257 - (out - end));
+    state->hold = hold;
+    state->bits = bits;
+    return;
+}
+
+/*
+   inflate_fast() speedups that turned out slower (on a PowerPC G3 750CXe):
+   - Using bit fields for code structure
+   - Different op definition to avoid & for extra bits (do & for table bits)
+   - Three separate decoding do-loops for direct, window, and wnext == 0
+   - Special case for distance > 1 copies to do overlapped load and store copy
+   - Explicit branch predictions (based on measured branch probabilities)
+   - Deferring match copy and interspersed it with decoding subsequent codes
+   - Swapping literal/length else
+   - Swapping window/direct else
+   - Larger unrolled copy loops (three is about right)
+   - Moving len -= 3 statement into middle of loop
+ */
+
+#endif /* !ASMINF */
diff --git a/third_party/zlib/contrib/optimizations/inflate.c b/third_party/zlib/contrib/optimizations/inflate.c
new file mode 100644
index 0000000..0451d74
--- /dev/null
+++ b/third_party/zlib/contrib/optimizations/inflate.c
@@ -0,0 +1,1572 @@
+/* inflate.c -- zlib decompression
+ * Copyright (C) 1995-2016 Mark Adler
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+/*
+ * Change history:
+ *
+ * 1.2.beta0    24 Nov 2002
+ * - First version -- complete rewrite of inflate to simplify code, avoid
+ *   creation of window when not needed, minimize use of window when it is
+ *   needed, make inffast.c even faster, implement gzip decoding, and to
+ *   improve code readability and style over the previous zlib inflate code
+ *
+ * 1.2.beta1    25 Nov 2002
+ * - Use pointers for available input and output checking in inffast.c
+ * - Remove input and output counters in inffast.c
+ * - Change inffast.c entry and loop from avail_in >= 7 to >= 6
+ * - Remove unnecessary second byte pull from length extra in inffast.c
+ * - Unroll direct copy to three copies per loop in inffast.c
+ *
+ * 1.2.beta2    4 Dec 2002
+ * - Change external routine names to reduce potential conflicts
+ * - Correct filename to inffixed.h for fixed tables in inflate.c
+ * - Make hbuf[] unsigned char to match parameter type in inflate.c
+ * - Change strm->next_out[-state->offset] to *(strm->next_out - state->offset)
+ *   to avoid negation problem on Alphas (64 bit) in inflate.c
+ *
+ * 1.2.beta3    22 Dec 2002
+ * - Add comments on state->bits assertion in inffast.c
+ * - Add comments on op field in inftrees.h
+ * - Fix bug in reuse of allocated window after inflateReset()
+ * - Remove bit fields--back to byte structure for speed
+ * - Remove distance extra == 0 check in inflate_fast()--only helps for lengths
+ * - Change post-increments to pre-increments in inflate_fast(), PPC biased?
+ * - Add compile time option, POSTINC, to use post-increments instead (Intel?)
+ * - Make MATCH copy in inflate() much faster for when inflate_fast() not used
+ * - Use local copies of stream next and avail values, as well as local bit
+ *   buffer and bit count in inflate()--for speed when inflate_fast() not used
+ *
+ * 1.2.beta4    1 Jan 2003
+ * - Split ptr - 257 statements in inflate_table() to avoid compiler warnings
+ * - Move a comment on output buffer sizes from inffast.c to inflate.c
+ * - Add comments in inffast.c to introduce the inflate_fast() routine
+ * - Rearrange window copies in inflate_fast() for speed and simplification
+ * - Unroll last copy for window match in inflate_fast()
+ * - Use local copies of window variables in inflate_fast() for speed
+ * - Pull out common wnext == 0 case for speed in inflate_fast()
+ * - Make op and len in inflate_fast() unsigned for consistency
+ * - Add FAR to lcode and dcode declarations in inflate_fast()
+ * - Simplified bad distance check in inflate_fast()
+ * - Added inflateBackInit(), inflateBack(), and inflateBackEnd() in new
+ *   source file infback.c to provide a call-back interface to inflate for
+ *   programs like gzip and unzip -- uses window as output buffer to avoid
+ *   window copying
+ *
+ * 1.2.beta5    1 Jan 2003
+ * - Improved inflateBack() interface to allow the caller to provide initial
+ *   input in strm.
+ * - Fixed stored blocks bug in inflateBack()
+ *
+ * 1.2.beta6    4 Jan 2003
+ * - Added comments in inffast.c on effectiveness of POSTINC
+ * - Typecasting all around to reduce compiler warnings
+ * - Changed loops from while (1) or do {} while (1) to for (;;), again to
+ *   make compilers happy
+ * - Changed type of window in inflateBackInit() to unsigned char *
+ *
+ * 1.2.beta7    27 Jan 2003
+ * - Changed many types to unsigned or unsigned short to avoid warnings
+ * - Added inflateCopy() function
+ *
+ * 1.2.0        9 Mar 2003
+ * - Changed inflateBack() interface to provide separate opaque descriptors
+ *   for the in() and out() functions
+ * - Changed inflateBack() argument and in_func typedef to swap the length
+ *   and buffer address return values for the input function
+ * - Check next_in and next_out for Z_NULL on entry to inflate()
+ *
+ * The history for versions after 1.2.0 are in ChangeLog in zlib distribution.
+ */
+
+#include "zutil.h"
+#include "inftrees.h"
+#include "inflate.h"
+#include "inffast.h"
+#include "contrib/optimizations/chunkcopy.h"
+
+#ifdef MAKEFIXED
+#  ifndef BUILDFIXED
+#    define BUILDFIXED
+#  endif
+#endif
+
+/* function prototypes */
+local int inflateStateCheck OF((z_streamp strm));
+local void fixedtables OF((struct inflate_state FAR *state));
+local int updatewindow OF((z_streamp strm, const unsigned char FAR *end,
+                           unsigned copy));
+#ifdef BUILDFIXED
+   void makefixed OF((void));
+#endif
+local unsigned syncsearch OF((unsigned FAR *have, const unsigned char FAR *buf,
+                              unsigned len));
+
+local int inflateStateCheck(strm)
+z_streamp strm;
+{
+    struct inflate_state FAR *state;
+    if (strm == Z_NULL ||
+        strm->zalloc == (alloc_func)0 || strm->zfree == (free_func)0)
+        return 1;
+    state = (struct inflate_state FAR *)strm->state;
+    if (state == Z_NULL || state->strm != strm ||
+        state->mode < HEAD || state->mode > SYNC)
+        return 1;
+    return 0;
+}
+
+int ZEXPORT inflateResetKeep(strm)
+z_streamp strm;
+{
+    struct inflate_state FAR *state;
+
+    if (inflateStateCheck(strm)) return Z_STREAM_ERROR;
+    state = (struct inflate_state FAR *)strm->state;
+    strm->total_in = strm->total_out = state->total = 0;
+    strm->msg = Z_NULL;
+    if (state->wrap)        /* to support ill-conceived Java test suite */
+        strm->adler = state->wrap & 1;
+    state->mode = HEAD;
+    state->last = 0;
+    state->havedict = 0;
+    state->dmax = 32768U;
+    state->head = Z_NULL;
+    state->hold = 0;
+    state->bits = 0;
+    state->lencode = state->distcode = state->next = state->codes;
+    state->sane = 1;
+    state->back = -1;
+    Tracev((stderr, "inflate: reset\n"));
+    return Z_OK;
+}
+
+int ZEXPORT inflateReset(strm)
+z_streamp strm;
+{
+    struct inflate_state FAR *state;
+
+    if (inflateStateCheck(strm)) return Z_STREAM_ERROR;
+    state = (struct inflate_state FAR *)strm->state;
+    state->wsize = 0;
+    state->whave = 0;
+    state->wnext = 0;
+    return inflateResetKeep(strm);
+}
+
+int ZEXPORT inflateReset2(strm, windowBits)
+z_streamp strm;
+int windowBits;
+{
+    int wrap;
+    struct inflate_state FAR *state;
+
+    /* get the state */
+    if (inflateStateCheck(strm)) return Z_STREAM_ERROR;
+    state = (struct inflate_state FAR *)strm->state;
+
+    /* extract wrap request from windowBits parameter */
+    if (windowBits < 0) {
+        wrap = 0;
+        windowBits = -windowBits;
+    }
+    else {
+        wrap = (windowBits >> 4) + 5;
+#ifdef GUNZIP
+        if (windowBits < 48)
+            windowBits &= 15;
+#endif
+    }
+
+    /* set number of window bits, free window if different */
+    if (windowBits && (windowBits < 8 || windowBits > 15))
+        return Z_STREAM_ERROR;
+    if (state->window != Z_NULL && state->wbits != (unsigned)windowBits) {
+        ZFREE(strm, state->window);
+        state->window = Z_NULL;
+    }
+
+    /* update state and reset the rest of it */
+    state->wrap = wrap;
+    state->wbits = (unsigned)windowBits;
+    return inflateReset(strm);
+}
+
+int ZEXPORT inflateInit2_(strm, windowBits, version, stream_size)
+z_streamp strm;
+int windowBits;
+const char *version;
+int stream_size;
+{
+    int ret;
+    struct inflate_state FAR *state;
+
+    if (version == Z_NULL || version[0] != ZLIB_VERSION[0] ||
+        stream_size != (int)(sizeof(z_stream)))
+        return Z_VERSION_ERROR;
+    if (strm == Z_NULL) return Z_STREAM_ERROR;
+    strm->msg = Z_NULL;                 /* in case we return an error */
+    if (strm->zalloc == (alloc_func)0) {
+#ifdef Z_SOLO
+        return Z_STREAM_ERROR;
+#else
+        strm->zalloc = zcalloc;
+        strm->opaque = (voidpf)0;
+#endif
+    }
+    if (strm->zfree == (free_func)0)
+#ifdef Z_SOLO
+        return Z_STREAM_ERROR;
+#else
+        strm->zfree = zcfree;
+#endif
+    state = (struct inflate_state FAR *)
+            ZALLOC(strm, 1, sizeof(struct inflate_state));
+    if (state == Z_NULL) return Z_MEM_ERROR;
+    Tracev((stderr, "inflate: allocated\n"));
+    strm->state = (struct internal_state FAR *)state;
+    state->strm = strm;
+    state->window = Z_NULL;
+    state->mode = HEAD;     /* to pass state test in inflateReset2() */
+    state->check = 1L;      /* 1L is the result of adler32() zero length data */
+    ret = inflateReset2(strm, windowBits);
+    if (ret != Z_OK) {
+        ZFREE(strm, state);
+        strm->state = Z_NULL;
+    }
+    return ret;
+}
+
+int ZEXPORT inflateInit_(strm, version, stream_size)
+z_streamp strm;
+const char *version;
+int stream_size;
+{
+    return inflateInit2_(strm, DEF_WBITS, version, stream_size);
+}
+
+int ZEXPORT inflatePrime(strm, bits, value)
+z_streamp strm;
+int bits;
+int value;
+{
+    struct inflate_state FAR *state;
+
+    if (inflateStateCheck(strm)) return Z_STREAM_ERROR;
+    state = (struct inflate_state FAR *)strm->state;
+    if (bits < 0) {
+        state->hold = 0;
+        state->bits = 0;
+        return Z_OK;
+    }
+    if (bits > 16 || state->bits + (uInt)bits > 32) return Z_STREAM_ERROR;
+    value &= (1L << bits) - 1;
+    state->hold += (unsigned)value << state->bits;
+    state->bits += (uInt)bits;
+    return Z_OK;
+}
+
+/*
+   Return state with length and distance decoding tables and index sizes set to
+   fixed code decoding.  Normally this returns fixed tables from inffixed.h.
+   If BUILDFIXED is defined, then instead this routine builds the tables the
+   first time it's called, and returns those tables the first time and
+   thereafter.  This reduces the size of the code by about 2K bytes, in
+   exchange for a little execution time.  However, BUILDFIXED should not be
+   used for threaded applications, since the rewriting of the tables and virgin
+   may not be thread-safe.
+ */
+local void fixedtables(state)
+struct inflate_state FAR *state;
+{
+#ifdef BUILDFIXED
+    static int virgin = 1;
+    static code *lenfix, *distfix;
+    static code fixed[544];
+
+    /* build fixed huffman tables if first call (may not be thread safe) */
+    if (virgin) {
+        unsigned sym, bits;
+        static code *next;
+
+        /* literal/length table */
+        sym = 0;
+        while (sym < 144) state->lens[sym++] = 8;
+        while (sym < 256) state->lens[sym++] = 9;
+        while (sym < 280) state->lens[sym++] = 7;
+        while (sym < 288) state->lens[sym++] = 8;
+        next = fixed;
+        lenfix = next;
+        bits = 9;
+        inflate_table(LENS, state->lens, 288, &(next), &(bits), state->work);
+
+        /* distance table */
+        sym = 0;
+        while (sym < 32) state->lens[sym++] = 5;
+        distfix = next;
+        bits = 5;
+        inflate_table(DISTS, state->lens, 32, &(next), &(bits), state->work);
+
+        /* do this just once */
+        virgin = 0;
+    }
+#else /* !BUILDFIXED */
+#   include "inffixed.h"
+#endif /* BUILDFIXED */
+    state->lencode = lenfix;
+    state->lenbits = 9;
+    state->distcode = distfix;
+    state->distbits = 5;
+}
+
+#ifdef MAKEFIXED
+#include <stdio.h>
+
+/*
+   Write out the inffixed.h that is #include'd above.  Defining MAKEFIXED also
+   defines BUILDFIXED, so the tables are built on the fly.  makefixed() writes
+   those tables to stdout, which would be piped to inffixed.h.  A small program
+   can simply call makefixed to do this:
+
+    void makefixed(void);
+
+    int main(void)
+    {
+        makefixed();
+        return 0;
+    }
+
+   Then that can be linked with zlib built with MAKEFIXED defined and run:
+
+    a.out > inffixed.h
+ */
+void makefixed()
+{
+    unsigned low, size;
+    struct inflate_state state;
+
+    fixedtables(&state);
+    puts("    /* inffixed.h -- table for decoding fixed codes");
+    puts("     * Generated automatically by makefixed().");
+    puts("     */");
+    puts("");
+    puts("    /* WARNING: this file should *not* be used by applications.");
+    puts("       It is part of the implementation of this library and is");
+    puts("       subject to change. Applications should only use zlib.h.");
+    puts("     */");
+    puts("");
+    size = 1U << 9;
+    printf("    static const code lenfix[%u] = {", size);
+    low = 0;
+    for (;;) {
+        if ((low % 7) == 0) printf("\n        ");
+        printf("{%u,%u,%d}", (low & 127) == 99 ? 64 : state.lencode[low].op,
+               state.lencode[low].bits, state.lencode[low].val);
+        if (++low == size) break;
+        putchar(',');
+    }
+    puts("\n    };");
+    size = 1U << 5;
+    printf("\n    static const code distfix[%u] = {", size);
+    low = 0;
+    for (;;) {
+        if ((low % 6) == 0) printf("\n        ");
+        printf("{%u,%u,%d}", state.distcode[low].op, state.distcode[low].bits,
+               state.distcode[low].val);
+        if (++low == size) break;
+        putchar(',');
+    }
+    puts("\n    };");
+}
+#endif /* MAKEFIXED */
+
+/*
+   Update the window with the last wsize (normally 32K) bytes written before
+   returning.  If window does not exist yet, create it.  This is only called
+   when a window is already in use, or when output has been written during this
+   inflate call, but the end of the deflate stream has not been reached yet.
+   It is also called to create a window for dictionary data when a dictionary
+   is loaded.
+
+   Providing output buffers larger than 32K to inflate() should provide a speed
+   advantage, since only the last 32K of output is copied to the sliding window
+   upon return from inflate(), and since all distances after the first 32K of
+   output will fall in the output data, making match copies simpler and faster.
+   The advantage may be dependent on the size of the processor's data caches.
+ */
+local int updatewindow(strm, end, copy)
+z_streamp strm;
+const Bytef *end;
+unsigned copy;
+{
+    struct inflate_state FAR *state;
+    unsigned dist;
+
+    state = (struct inflate_state FAR *)strm->state;
+
+    /* if it hasn't been done already, allocate space for the window */
+    if (state->window == Z_NULL) {
+        unsigned wsize = 1U << state->wbits;
+        state->window = (unsigned char FAR *)
+                        ZALLOC(strm, wsize + CHUNKCOPY_CHUNK_SIZE,
+                               sizeof(unsigned char));
+        if (state->window == Z_NULL) return 1;
+#ifdef INFLATE_CLEAR_UNUSED_UNDEFINED
+        /* Copies from the overflow portion of this buffer are undefined and
+           may cause analysis tools to raise a warning if we don't initialize
+           it.  However, this undefined data overwrites other undefined data
+           and is subsequently either overwritten or left deliberately
+           undefined at the end of decode; so there's really no point.
+         */
+        memset(state->window + wsize, 0, CHUNKCOPY_CHUNK_SIZE);
+#endif
+    }
+
+    /* if window not in use yet, initialize */
+    if (state->wsize == 0) {
+        state->wsize = 1U << state->wbits;
+        state->wnext = 0;
+        state->whave = 0;
+    }
+
+    /* copy state->wsize or less output bytes into the circular window */
+    if (copy >= state->wsize) {
+        zmemcpy(state->window, end - state->wsize, state->wsize);
+        state->wnext = 0;
+        state->whave = state->wsize;
+    }
+    else {
+        dist = state->wsize - state->wnext;
+        if (dist > copy) dist = copy;
+        zmemcpy(state->window + state->wnext, end - copy, dist);
+        copy -= dist;
+        if (copy) {
+            zmemcpy(state->window, end - copy, copy);
+            state->wnext = copy;
+            state->whave = state->wsize;
+        }
+        else {
+            state->wnext += dist;
+            if (state->wnext == state->wsize) state->wnext = 0;
+            if (state->whave < state->wsize) state->whave += dist;
+        }
+    }
+    return 0;
+}
+
+/* Macros for inflate(): */
+
+/* check function to use adler32() for zlib or crc32() for gzip */
+#ifdef GUNZIP
+#  define UPDATE(check, buf, len) \
+    (state->flags ? crc32(check, buf, len) : adler32(check, buf, len))
+#else
+#  define UPDATE(check, buf, len) adler32(check, buf, len)
+#endif
+
+/* check macros for header crc */
+#ifdef GUNZIP
+#  define CRC2(check, word) \
+    do { \
+        hbuf[0] = (unsigned char)(word); \
+        hbuf[1] = (unsigned char)((word) >> 8); \
+        check = crc32(check, hbuf, 2); \
+    } while (0)
+
+#  define CRC4(check, word) \
+    do { \
+        hbuf[0] = (unsigned char)(word); \
+        hbuf[1] = (unsigned char)((word) >> 8); \
+        hbuf[2] = (unsigned char)((word) >> 16); \
+        hbuf[3] = (unsigned char)((word) >> 24); \
+        check = crc32(check, hbuf, 4); \
+    } while (0)
+#endif
+
+/* Load registers with state in inflate() for speed */
+#define LOAD() \
+    do { \
+        put = strm->next_out; \
+        left = strm->avail_out; \
+        next = strm->next_in; \
+        have = strm->avail_in; \
+        hold = state->hold; \
+        bits = state->bits; \
+    } while (0)
+
+/* Restore state from registers in inflate() */
+#define RESTORE() \
+    do { \
+        strm->next_out = put; \
+        strm->avail_out = left; \
+        strm->next_in = next; \
+        strm->avail_in = have; \
+        state->hold = hold; \
+        state->bits = bits; \
+    } while (0)
+
+/* Clear the input bit accumulator */
+#define INITBITS() \
+    do { \
+        hold = 0; \
+        bits = 0; \
+    } while (0)
+
+/* Get a byte of input into the bit accumulator, or return from inflate()
+   if there is no input available. */
+#define PULLBYTE() \
+    do { \
+        if (have == 0) goto inf_leave; \
+        have--; \
+        hold += (unsigned long)(*next++) << bits; \
+        bits += 8; \
+    } while (0)
+
+/* Assure that there are at least n bits in the bit accumulator.  If there is
+   not enough available input to do that, then return from inflate(). */
+#define NEEDBITS(n) \
+    do { \
+        while (bits < (unsigned)(n)) \
+            PULLBYTE(); \
+    } while (0)
+
+/* Return the low n bits of the bit accumulator (n < 16) */
+#define BITS(n) \
+    ((unsigned)hold & ((1U << (n)) - 1))
+
+/* Remove n bits from the bit accumulator */
+#define DROPBITS(n) \
+    do { \
+        hold >>= (n); \
+        bits -= (unsigned)(n); \
+    } while (0)
+
+/* Remove zero to seven bits as needed to go to a byte boundary */
+#define BYTEBITS() \
+    do { \
+        hold >>= bits & 7; \
+        bits -= bits & 7; \
+    } while (0)
+
+/*
+   inflate() uses a state machine to process as much input data and generate as
+   much output data as possible before returning.  The state machine is
+   structured roughly as follows:
+
+    for (;;) switch (state) {
+    ...
+    case STATEn:
+        if (not enough input data or output space to make progress)
+            return;
+        ... make progress ...
+        state = STATEm;
+        break;
+    ...
+    }
+
+   so when inflate() is called again, the same case is attempted again, and
+   if the appropriate resources are provided, the machine proceeds to the
+   next state.  The NEEDBITS() macro is usually the way the state evaluates
+   whether it can proceed or should return.  NEEDBITS() does the return if
+   the requested bits are not available.  The typical use of the BITS macros
+   is:
+
+        NEEDBITS(n);
+        ... do something with BITS(n) ...
+        DROPBITS(n);
+
+   where NEEDBITS(n) either returns from inflate() if there isn't enough
+   input left to load n bits into the accumulator, or it continues.  BITS(n)
+   gives the low n bits in the accumulator.  When done, DROPBITS(n) drops
+   the low n bits off the accumulator.  INITBITS() clears the accumulator
+   and sets the number of available bits to zero.  BYTEBITS() discards just
+   enough bits to put the accumulator on a byte boundary.  After BYTEBITS()
+   and a NEEDBITS(8), then BITS(8) would return the next byte in the stream.
+
+   NEEDBITS(n) uses PULLBYTE() to get an available byte of input, or to return
+   if there is no input available.  The decoding of variable length codes uses
+   PULLBYTE() directly in order to pull just enough bytes to decode the next
+   code, and no more.
+
+   Some states loop until they get enough input, making sure that enough
+   state information is maintained to continue the loop where it left off
+   if NEEDBITS() returns in the loop.  For example, want, need, and keep
+   would all have to actually be part of the saved state in case NEEDBITS()
+   returns:
+
+    case STATEw:
+        while (want < need) {
+            NEEDBITS(n);
+            keep[want++] = BITS(n);
+            DROPBITS(n);
+        }
+        state = STATEx;
+    case STATEx:
+
+   As shown above, if the next state is also the next case, then the break
+   is omitted.
+
+   A state may also return if there is not enough output space available to
+   complete that state.  Those states are copying stored data, writing a
+   literal byte, and copying a matching string.
+
+   When returning, a "goto inf_leave" is used to update the total counters,
+   update the check value, and determine whether any progress has been made
+   during that inflate() call in order to return the proper return code.
+   Progress is defined as a change in either strm->avail_in or strm->avail_out.
+   When there is a window, goto inf_leave will update the window with the last
+   output written.  If a goto inf_leave occurs in the middle of decompression
+   and there is no window currently, goto inf_leave will create one and copy
+   output to the window for the next call of inflate().
+
+   In this implementation, the flush parameter of inflate() only affects the
+   return code (per zlib.h).  inflate() always writes as much as possible to
+   strm->next_out, given the space available and the provided input--the effect
+   documented in zlib.h of Z_SYNC_FLUSH.  Furthermore, inflate() always defers
+   the allocation of and copying into a sliding window until necessary, which
+   provides the effect documented in zlib.h for Z_FINISH when the entire input
+   stream available.  So the only thing the flush parameter actually does is:
+   when flush is set to Z_FINISH, inflate() cannot return Z_OK.  Instead it
+   will return Z_BUF_ERROR if it has not reached the end of the stream.
+ */
+
+int ZEXPORT inflate(strm, flush)
+z_streamp strm;
+int flush;
+{
+    struct inflate_state FAR *state;
+    z_const unsigned char FAR *next;    /* next input */
+    unsigned char FAR *put;     /* next output */
+    unsigned have, left;        /* available input and output */
+    unsigned long hold;         /* bit buffer */
+    unsigned bits;              /* bits in bit buffer */
+    unsigned in, out;           /* save starting available input and output */
+    unsigned copy;              /* number of stored or match bytes to copy */
+    unsigned char FAR *from;    /* where to copy match bytes from */
+    code here;                  /* current decoding table entry */
+    code last;                  /* parent table entry */
+    unsigned len;               /* length to copy for repeats, bits to drop */
+    int ret;                    /* return code */
+#ifdef GUNZIP
+    unsigned char hbuf[4];      /* buffer for gzip header crc calculation */
+#endif
+    static const unsigned short order[19] = /* permutation of code lengths */
+        {16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15};
+
+    if (inflateStateCheck(strm) || strm->next_out == Z_NULL ||
+        (strm->next_in == Z_NULL && strm->avail_in != 0))
+        return Z_STREAM_ERROR;
+
+    state = (struct inflate_state FAR *)strm->state;
+    if (state->mode == TYPE) state->mode = TYPEDO;      /* skip check */
+    LOAD();
+    in = have;
+    out = left;
+    ret = Z_OK;
+    for (;;)
+        switch (state->mode) {
+        case HEAD:
+            if (state->wrap == 0) {
+                state->mode = TYPEDO;
+                break;
+            }
+            NEEDBITS(16);
+#ifdef GUNZIP
+            if ((state->wrap & 2) && hold == 0x8b1f) {  /* gzip header */
+                if (state->wbits == 0)
+                    state->wbits = 15;
+                state->check = crc32(0L, Z_NULL, 0);
+                CRC2(state->check, hold);
+                INITBITS();
+                state->mode = FLAGS;
+                break;
+            }
+            state->flags = 0;           /* expect zlib header */
+            if (state->head != Z_NULL)
+                state->head->done = -1;
+            if (!(state->wrap & 1) ||   /* check if zlib header allowed */
+#else
+            if (
+#endif
+                ((BITS(8) << 8) + (hold >> 8)) % 31) {
+                strm->msg = (char *)"incorrect header check";
+                state->mode = BAD;
+                break;
+            }
+            if (BITS(4) != Z_DEFLATED) {
+                strm->msg = (char *)"unknown compression method";
+                state->mode = BAD;
+                break;
+            }
+            DROPBITS(4);
+            len = BITS(4) + 8;
+            if (state->wbits == 0)
+                state->wbits = len;
+            if (len > 15 || len > state->wbits) {
+                strm->msg = (char *)"invalid window size";
+                state->mode = BAD;
+                break;
+            }
+            state->dmax = 1U << len;
+            Tracev((stderr, "inflate:   zlib header ok\n"));
+            strm->adler = state->check = adler32(0L, Z_NULL, 0);
+            state->mode = hold & 0x200 ? DICTID : TYPE;
+            INITBITS();
+            break;
+#ifdef GUNZIP
+        case FLAGS:
+            NEEDBITS(16);
+            state->flags = (int)(hold);
+            if ((state->flags & 0xff) != Z_DEFLATED) {
+                strm->msg = (char *)"unknown compression method";
+                state->mode = BAD;
+                break;
+            }
+            if (state->flags & 0xe000) {
+                strm->msg = (char *)"unknown header flags set";
+                state->mode = BAD;
+                break;
+            }
+            if (state->head != Z_NULL)
+                state->head->text = (int)((hold >> 8) & 1);
+            if ((state->flags & 0x0200) && (state->wrap & 4))
+                CRC2(state->check, hold);
+            INITBITS();
+            state->mode = TIME;
+        case TIME:
+            NEEDBITS(32);
+            if (state->head != Z_NULL)
+                state->head->time = hold;
+            if ((state->flags & 0x0200) && (state->wrap & 4))
+                CRC4(state->check, hold);
+            INITBITS();
+            state->mode = OS;
+        case OS:
+            NEEDBITS(16);
+            if (state->head != Z_NULL) {
+                state->head->xflags = (int)(hold & 0xff);
+                state->head->os = (int)(hold >> 8);
+            }
+            if ((state->flags & 0x0200) && (state->wrap & 4))
+                CRC2(state->check, hold);
+            INITBITS();
+            state->mode = EXLEN;
+        case EXLEN:
+            if (state->flags & 0x0400) {
+                NEEDBITS(16);
+                state->length = (unsigned)(hold);
+                if (state->head != Z_NULL)
+                    state->head->extra_len = (unsigned)hold;
+                if ((state->flags & 0x0200) && (state->wrap & 4))
+                    CRC2(state->check, hold);
+                INITBITS();
+            }
+            else if (state->head != Z_NULL)
+                state->head->extra = Z_NULL;
+            state->mode = EXTRA;
+        case EXTRA:
+            if (state->flags & 0x0400) {
+                copy = state->length;
+                if (copy > have) copy = have;
+                if (copy) {
+                    if (state->head != Z_NULL &&
+                        state->head->extra != Z_NULL) {
+                        len = state->head->extra_len - state->length;
+                        zmemcpy(state->head->extra + len, next,
+                                len + copy > state->head->extra_max ?
+                                state->head->extra_max - len : copy);
+                    }
+                    if ((state->flags & 0x0200) && (state->wrap & 4))
+                        state->check = crc32(state->check, next, copy);
+                    have -= copy;
+                    next += copy;
+                    state->length -= copy;
+                }
+                if (state->length) goto inf_leave;
+            }
+            state->length = 0;
+            state->mode = NAME;
+        case NAME:
+            if (state->flags & 0x0800) {
+                if (have == 0) goto inf_leave;
+                copy = 0;
+                do {
+                    len = (unsigned)(next[copy++]);
+                    if (state->head != Z_NULL &&
+                            state->head->name != Z_NULL &&
+                            state->length < state->head->name_max)
+                        state->head->name[state->length++] = (Bytef)len;
+                } while (len && copy < have);
+                if ((state->flags & 0x0200) && (state->wrap & 4))
+                    state->check = crc32(state->check, next, copy);
+                have -= copy;
+                next += copy;
+                if (len) goto inf_leave;
+            }
+            else if (state->head != Z_NULL)
+                state->head->name = Z_NULL;
+            state->length = 0;
+            state->mode = COMMENT;
+        case COMMENT:
+            if (state->flags & 0x1000) {
+                if (have == 0) goto inf_leave;
+                copy = 0;
+                do {
+                    len = (unsigned)(next[copy++]);
+                    if (state->head != Z_NULL &&
+                            state->head->comment != Z_NULL &&
+                            state->length < state->head->comm_max)
+                        state->head->comment[state->length++] = (Bytef)len;
+                } while (len && copy < have);
+                if ((state->flags & 0x0200) && (state->wrap & 4))
+                    state->check = crc32(state->check, next, copy);
+                have -= copy;
+                next += copy;
+                if (len) goto inf_leave;
+            }
+            else if (state->head != Z_NULL)
+                state->head->comment = Z_NULL;
+            state->mode = HCRC;
+        case HCRC:
+            if (state->flags & 0x0200) {
+                NEEDBITS(16);
+                if ((state->wrap & 4) && hold != (state->check & 0xffff)) {
+                    strm->msg = (char *)"header crc mismatch";
+                    state->mode = BAD;
+                    break;
+                }
+                INITBITS();
+            }
+            if (state->head != Z_NULL) {
+                state->head->hcrc = (int)((state->flags >> 9) & 1);
+                state->head->done = 1;
+            }
+            strm->adler = state->check = crc32(0L, Z_NULL, 0);
+            state->mode = TYPE;
+            break;
+#endif
+        case DICTID:
+            NEEDBITS(32);
+            strm->adler = state->check = ZSWAP32(hold);
+            INITBITS();
+            state->mode = DICT;
+        case DICT:
+            if (state->havedict == 0) {
+                RESTORE();
+                return Z_NEED_DICT;
+            }
+            strm->adler = state->check = adler32(0L, Z_NULL, 0);
+            state->mode = TYPE;
+        case TYPE:
+            if (flush == Z_BLOCK || flush == Z_TREES) goto inf_leave;
+        case TYPEDO:
+            if (state->last) {
+                BYTEBITS();
+                state->mode = CHECK;
+                break;
+            }
+            NEEDBITS(3);
+            state->last = BITS(1);
+            DROPBITS(1);
+            switch (BITS(2)) {
+            case 0:                             /* stored block */
+                Tracev((stderr, "inflate:     stored block%s\n",
+                        state->last ? " (last)" : ""));
+                state->mode = STORED;
+                break;
+            case 1:                             /* fixed block */
+                fixedtables(state);
+                Tracev((stderr, "inflate:     fixed codes block%s\n",
+                        state->last ? " (last)" : ""));
+                state->mode = LEN_;             /* decode codes */
+                if (flush == Z_TREES) {
+                    DROPBITS(2);
+                    goto inf_leave;
+                }
+                break;
+            case 2:                             /* dynamic block */
+                Tracev((stderr, "inflate:     dynamic codes block%s\n",
+                        state->last ? " (last)" : ""));
+                state->mode = TABLE;
+                break;
+            case 3:
+                strm->msg = (char *)"invalid block type";
+                state->mode = BAD;
+            }
+            DROPBITS(2);
+            break;
+        case STORED:
+            BYTEBITS();                         /* go to byte boundary */
+            NEEDBITS(32);
+            if ((hold & 0xffff) != ((hold >> 16) ^ 0xffff)) {
+                strm->msg = (char *)"invalid stored block lengths";
+                state->mode = BAD;
+                break;
+            }
+            state->length = (unsigned)hold & 0xffff;
+            Tracev((stderr, "inflate:       stored length %u\n",
+                    state->length));
+            INITBITS();
+            state->mode = COPY_;
+            if (flush == Z_TREES) goto inf_leave;
+        case COPY_:
+            state->mode = COPY;
+        case COPY:
+            copy = state->length;
+            if (copy) {
+                if (copy > have) copy = have;
+                if (copy > left) copy = left;
+                if (copy == 0) goto inf_leave;
+                zmemcpy(put, next, copy);
+                have -= copy;
+                next += copy;
+                left -= copy;
+                put += copy;
+                state->length -= copy;
+                break;
+            }
+            Tracev((stderr, "inflate:       stored end\n"));
+            state->mode = TYPE;
+            break;
+        case TABLE:
+            NEEDBITS(14);
+            state->nlen = BITS(5) + 257;
+            DROPBITS(5);
+            state->ndist = BITS(5) + 1;
+            DROPBITS(5);
+            state->ncode = BITS(4) + 4;
+            DROPBITS(4);
+#ifndef PKZIP_BUG_WORKAROUND
+            if (state->nlen > 286 || state->ndist > 30) {
+                strm->msg = (char *)"too many length or distance symbols";
+                state->mode = BAD;
+                break;
+            }
+#endif
+            Tracev((stderr, "inflate:       table sizes ok\n"));
+            state->have = 0;
+            state->mode = LENLENS;
+        case LENLENS:
+            while (state->have < state->ncode) {
+                NEEDBITS(3);
+                state->lens[order[state->have++]] = (unsigned short)BITS(3);
+                DROPBITS(3);
+            }
+            while (state->have < 19)
+                state->lens[order[state->have++]] = 0;
+            state->next = state->codes;
+            state->lencode = (const code FAR *)(state->next);
+            state->lenbits = 7;
+            ret = inflate_table(CODES, state->lens, 19, &(state->next),
+                                &(state->lenbits), state->work);
+            if (ret) {
+                strm->msg = (char *)"invalid code lengths set";
+                state->mode = BAD;
+                break;
+            }
+            Tracev((stderr, "inflate:       code lengths ok\n"));
+            state->have = 0;
+            state->mode = CODELENS;
+        case CODELENS:
+            while (state->have < state->nlen + state->ndist) {
+                for (;;) {
+                    here = state->lencode[BITS(state->lenbits)];
+                    if ((unsigned)(here.bits) <= bits) break;
+                    PULLBYTE();
+                }
+                if (here.val < 16) {
+                    DROPBITS(here.bits);
+                    state->lens[state->have++] = here.val;
+                }
+                else {
+                    if (here.val == 16) {
+                        NEEDBITS(here.bits + 2);
+                        DROPBITS(here.bits);
+                        if (state->have == 0) {
+                            strm->msg = (char *)"invalid bit length repeat";
+                            state->mode = BAD;
+                            break;
+                        }
+                        len = state->lens[state->have - 1];
+                        copy = 3 + BITS(2);
+                        DROPBITS(2);
+                    }
+                    else if (here.val == 17) {
+                        NEEDBITS(here.bits + 3);
+                        DROPBITS(here.bits);
+                        len = 0;
+                        copy = 3 + BITS(3);
+                        DROPBITS(3);
+                    }
+                    else {
+                        NEEDBITS(here.bits + 7);
+                        DROPBITS(here.bits);
+                        len = 0;
+                        copy = 11 + BITS(7);
+                        DROPBITS(7);
+                    }
+                    if (state->have + copy > state->nlen + state->ndist) {
+                        strm->msg = (char *)"invalid bit length repeat";
+                        state->mode = BAD;
+                        break;
+                    }
+                    while (copy--)
+                        state->lens[state->have++] = (unsigned short)len;
+                }
+            }
+
+            /* handle error breaks in while */
+            if (state->mode == BAD) break;
+
+            /* check for end-of-block code (better have one) */
+            if (state->lens[256] == 0) {
+                strm->msg = (char *)"invalid code -- missing end-of-block";
+                state->mode = BAD;
+                break;
+            }
+
+            /* build code tables -- note: do not change the lenbits or distbits
+               values here (9 and 6) without reading the comments in inftrees.h
+               concerning the ENOUGH constants, which depend on those values */
+            state->next = state->codes;
+            state->lencode = (const code FAR *)(state->next);
+            state->lenbits = 9;
+            ret = inflate_table(LENS, state->lens, state->nlen, &(state->next),
+                                &(state->lenbits), state->work);
+            if (ret) {
+                strm->msg = (char *)"invalid literal/lengths set";
+                state->mode = BAD;
+                break;
+            }
+            state->distcode = (const code FAR *)(state->next);
+            state->distbits = 6;
+            ret = inflate_table(DISTS, state->lens + state->nlen, state->ndist,
+                            &(state->next), &(state->distbits), state->work);
+            if (ret) {
+                strm->msg = (char *)"invalid distances set";
+                state->mode = BAD;
+                break;
+            }
+            Tracev((stderr, "inflate:       codes ok\n"));
+            state->mode = LEN_;
+            if (flush == Z_TREES) goto inf_leave;
+        case LEN_:
+            state->mode = LEN;
+        case LEN:
+            if (have >= 6 && left >= 258) {
+                RESTORE();
+                inflate_fast(strm, out);
+                LOAD();
+                if (state->mode == TYPE)
+                    state->back = -1;
+                break;
+            }
+            state->back = 0;
+            for (;;) {
+                here = state->lencode[BITS(state->lenbits)];
+                if ((unsigned)(here.bits) <= bits) break;
+                PULLBYTE();
+            }
+            if (here.op && (here.op & 0xf0) == 0) {
+                last = here;
+                for (;;) {
+                    here = state->lencode[last.val +
+                            (BITS(last.bits + last.op) >> last.bits)];
+                    if ((unsigned)(last.bits + here.bits) <= bits) break;
+                    PULLBYTE();
+                }
+                DROPBITS(last.bits);
+                state->back += last.bits;
+            }
+            DROPBITS(here.bits);
+            state->back += here.bits;
+            state->length = (unsigned)here.val;
+            if ((int)(here.op) == 0) {
+                Tracevv((stderr, here.val >= 0x20 && here.val < 0x7f ?
+                        "inflate:         literal '%c'\n" :
+                        "inflate:         literal 0x%02x\n", here.val));
+                state->mode = LIT;
+                break;
+            }
+            if (here.op & 32) {
+                Tracevv((stderr, "inflate:         end of block\n"));
+                state->back = -1;
+                state->mode = TYPE;
+                break;
+            }
+            if (here.op & 64) {
+                strm->msg = (char *)"invalid literal/length code";
+                state->mode = BAD;
+                break;
+            }
+            state->extra = (unsigned)(here.op) & 15;
+            state->mode = LENEXT;
+        case LENEXT:
+            if (state->extra) {
+                NEEDBITS(state->extra);
+                state->length += BITS(state->extra);
+                DROPBITS(state->extra);
+                state->back += state->extra;
+            }
+            Tracevv((stderr, "inflate:         length %u\n", state->length));
+            state->was = state->length;
+            state->mode = DIST;
+        case DIST:
+            for (;;) {
+                here = state->distcode[BITS(state->distbits)];
+                if ((unsigned)(here.bits) <= bits) break;
+                PULLBYTE();
+            }
+            if ((here.op & 0xf0) == 0) {
+                last = here;
+                for (;;) {
+                    here = state->distcode[last.val +
+                            (BITS(last.bits + last.op) >> last.bits)];
+                    if ((unsigned)(last.bits + here.bits) <= bits) break;
+                    PULLBYTE();
+                }
+                DROPBITS(last.bits);
+                state->back += last.bits;
+            }
+            DROPBITS(here.bits);
+            state->back += here.bits;
+            if (here.op & 64) {
+                strm->msg = (char *)"invalid distance code";
+                state->mode = BAD;
+                break;
+            }
+            state->offset = (unsigned)here.val;
+            state->extra = (unsigned)(here.op) & 15;
+            state->mode = DISTEXT;
+        case DISTEXT:
+            if (state->extra) {
+                NEEDBITS(state->extra);
+                state->offset += BITS(state->extra);
+                DROPBITS(state->extra);
+                state->back += state->extra;
+            }
+#ifdef INFLATE_STRICT
+            if (state->offset > state->dmax) {
+                strm->msg = (char *)"invalid distance too far back";
+                state->mode = BAD;
+                break;
+            }
+#endif
+            Tracevv((stderr, "inflate:         distance %u\n", state->offset));
+            state->mode = MATCH;
+        case MATCH:
+            if (left == 0) goto inf_leave;
+            copy = out - left;
+            if (state->offset > copy) {         /* copy from window */
+                copy = state->offset - copy;
+                if (copy > state->whave) {
+                    if (state->sane) {
+                        strm->msg = (char *)"invalid distance too far back";
+                        state->mode = BAD;
+                        break;
+                    }
+#ifdef INFLATE_ALLOW_INVALID_DISTANCE_TOOFAR_ARRR
+                    Trace((stderr, "inflate.c too far\n"));
+                    copy -= state->whave;
+                    if (copy > state->length) copy = state->length;
+                    if (copy > left) copy = left;
+                    left -= copy;
+                    state->length -= copy;
+                    do {
+                        *put++ = 0;
+                    } while (--copy);
+                    if (state->length == 0) state->mode = LEN;
+                    break;
+#endif
+                }
+                if (copy > state->wnext) {
+                    copy -= state->wnext;
+                    from = state->window + (state->wsize - copy);
+                }
+                else
+                    from = state->window + (state->wnext - copy);
+                if (copy > state->length) copy = state->length;
+                if (copy > left) copy = left;
+                put = chunkcopy_safe(put, from, copy, put + left);
+            }
+            else {                              /* copy from output */
+                copy = state->length;
+                if (copy > left) copy = left;
+                put = chunkcopy_lapped_safe(put, state->offset, copy, put + left);
+            }
+            left -= copy;
+            state->length -= copy;
+            if (state->length == 0) state->mode = LEN;
+            break;
+        case LIT:
+            if (left == 0) goto inf_leave;
+            *put++ = (unsigned char)(state->length);
+            left--;
+            state->mode = LEN;
+            break;
+        case CHECK:
+            if (state->wrap) {
+                NEEDBITS(32);
+                out -= left;
+                strm->total_out += out;
+                state->total += out;
+                if ((state->wrap & 4) && out)
+                    strm->adler = state->check =
+                        UPDATE(state->check, put - out, out);
+                out = left;
+                if ((state->wrap & 4) && (
+#ifdef GUNZIP
+                     state->flags ? hold :
+#endif
+                     ZSWAP32(hold)) != state->check) {
+                    strm->msg = (char *)"incorrect data check";
+                    state->mode = BAD;
+                    break;
+                }
+                INITBITS();
+                Tracev((stderr, "inflate:   check matches trailer\n"));
+            }
+#ifdef GUNZIP
+            state->mode = LENGTH;
+        case LENGTH:
+            if (state->wrap && state->flags) {
+                NEEDBITS(32);
+                if (hold != (state->total & 0xffffffffUL)) {
+                    strm->msg = (char *)"incorrect length check";
+                    state->mode = BAD;
+                    break;
+                }
+                INITBITS();
+                Tracev((stderr, "inflate:   length matches trailer\n"));
+            }
+#endif
+            state->mode = DONE;
+        case DONE:
+            ret = Z_STREAM_END;
+            goto inf_leave;
+        case BAD:
+            ret = Z_DATA_ERROR;
+            goto inf_leave;
+        case MEM:
+            return Z_MEM_ERROR;
+        case SYNC:
+        default:
+            return Z_STREAM_ERROR;
+        }
+
+    /*
+       Return from inflate(), updating the total counts and the check value.
+       If there was no progress during the inflate() call, return a buffer
+       error.  Call updatewindow() to create and/or update the window state.
+       Note: a memory error from inflate() is non-recoverable.
+     */
+  inf_leave:
+    RESTORE();
+    if (state->wsize || (out != strm->avail_out && state->mode < BAD &&
+            (state->mode < CHECK || flush != Z_FINISH)))
+        if (updatewindow(strm, strm->next_out, out - strm->avail_out)) {
+            state->mode = MEM;
+            return Z_MEM_ERROR;
+        }
+    in -= strm->avail_in;
+    out -= strm->avail_out;
+    strm->total_in += in;
+    strm->total_out += out;
+    state->total += out;
+    if ((state->wrap & 4) && out)
+        strm->adler = state->check =
+            UPDATE(state->check, strm->next_out - out, out);
+    strm->data_type = (int)state->bits + (state->last ? 64 : 0) +
+                      (state->mode == TYPE ? 128 : 0) +
+                      (state->mode == LEN_ || state->mode == COPY_ ? 256 : 0);
+    if (((in == 0 && out == 0) || flush == Z_FINISH) && ret == Z_OK)
+        ret = Z_BUF_ERROR;
+    return ret;
+}
+
+int ZEXPORT inflateEnd(strm)
+z_streamp strm;
+{
+    struct inflate_state FAR *state;
+    if (inflateStateCheck(strm))
+        return Z_STREAM_ERROR;
+    state = (struct inflate_state FAR *)strm->state;
+    if (state->window != Z_NULL) ZFREE(strm, state->window);
+    ZFREE(strm, strm->state);
+    strm->state = Z_NULL;
+    Tracev((stderr, "inflate: end\n"));
+    return Z_OK;
+}
+
+int ZEXPORT inflateGetDictionary(strm, dictionary, dictLength)
+z_streamp strm;
+Bytef *dictionary;
+uInt *dictLength;
+{
+    struct inflate_state FAR *state;
+
+    /* check state */
+    if (inflateStateCheck(strm)) return Z_STREAM_ERROR;
+    state = (struct inflate_state FAR *)strm->state;
+
+    /* copy dictionary */
+    if (state->whave && dictionary != Z_NULL) {
+        zmemcpy(dictionary, state->window + state->wnext,
+                state->whave - state->wnext);
+        zmemcpy(dictionary + state->whave - state->wnext,
+                state->window, state->wnext);
+    }
+    if (dictLength != Z_NULL)
+        *dictLength = state->whave;
+    return Z_OK;
+}
+
+int ZEXPORT inflateSetDictionary(strm, dictionary, dictLength)
+z_streamp strm;
+const Bytef *dictionary;
+uInt dictLength;
+{
+    struct inflate_state FAR *state;
+    unsigned long dictid;
+    int ret;
+
+    /* check state */
+    if (inflateStateCheck(strm)) return Z_STREAM_ERROR;
+    state = (struct inflate_state FAR *)strm->state;
+    if (state->wrap != 0 && state->mode != DICT)
+        return Z_STREAM_ERROR;
+
+    /* check for correct dictionary identifier */
+    if (state->mode == DICT) {
+        dictid = adler32(0L, Z_NULL, 0);
+        dictid = adler32(dictid, dictionary, dictLength);
+        if (dictid != state->check)
+            return Z_DATA_ERROR;
+    }
+
+    /* copy dictionary to window using updatewindow(), which will amend the
+       existing dictionary if appropriate */
+    ret = updatewindow(strm, dictionary + dictLength, dictLength);
+    if (ret) {
+        state->mode = MEM;
+        return Z_MEM_ERROR;
+    }
+    state->havedict = 1;
+    Tracev((stderr, "inflate:   dictionary set\n"));
+    return Z_OK;
+}
+
+int ZEXPORT inflateGetHeader(strm, head)
+z_streamp strm;
+gz_headerp head;
+{
+    struct inflate_state FAR *state;
+
+    /* check state */
+    if (inflateStateCheck(strm)) return Z_STREAM_ERROR;
+    state = (struct inflate_state FAR *)strm->state;
+    if ((state->wrap & 2) == 0) return Z_STREAM_ERROR;
+
+    /* save header structure */
+    state->head = head;
+    head->done = 0;
+    return Z_OK;
+}
+
+/*
+   Search buf[0..len-1] for the pattern: 0, 0, 0xff, 0xff.  Return when found
+   or when out of input.  When called, *have is the number of pattern bytes
+   found in order so far, in 0..3.  On return *have is updated to the new
+   state.  If on return *have equals four, then the pattern was found and the
+   return value is how many bytes were read including the last byte of the
+   pattern.  If *have is less than four, then the pattern has not been found
+   yet and the return value is len.  In the latter case, syncsearch() can be
+   called again with more data and the *have state.  *have is initialized to
+   zero for the first call.
+ */
+local unsigned syncsearch(have, buf, len)
+unsigned FAR *have;
+const unsigned char FAR *buf;
+unsigned len;
+{
+    unsigned got;
+    unsigned next;
+
+    got = *have;
+    next = 0;
+    while (next < len && got < 4) {
+        if ((int)(buf[next]) == (got < 2 ? 0 : 0xff))
+            got++;
+        else if (buf[next])
+            got = 0;
+        else
+            got = 4 - got;
+        next++;
+    }
+    *have = got;
+    return next;
+}
+
+int ZEXPORT inflateSync(strm)
+z_streamp strm;
+{
+    unsigned len;               /* number of bytes to look at or looked at */
+    unsigned long in, out;      /* temporary to save total_in and total_out */
+    unsigned char buf[4];       /* to restore bit buffer to byte string */
+    struct inflate_state FAR *state;
+
+    /* check parameters */
+    if (inflateStateCheck(strm)) return Z_STREAM_ERROR;
+    state = (struct inflate_state FAR *)strm->state;
+    if (strm->avail_in == 0 && state->bits < 8) return Z_BUF_ERROR;
+
+    /* if first time, start search in bit buffer */
+    if (state->mode != SYNC) {
+        state->mode = SYNC;
+        state->hold <<= state->bits & 7;
+        state->bits -= state->bits & 7;
+        len = 0;
+        while (state->bits >= 8) {
+            buf[len++] = (unsigned char)(state->hold);
+            state->hold >>= 8;
+            state->bits -= 8;
+        }
+        state->have = 0;
+        syncsearch(&(state->have), buf, len);
+    }
+
+    /* search available input */
+    len = syncsearch(&(state->have), strm->next_in, strm->avail_in);
+    strm->avail_in -= len;
+    strm->next_in += len;
+    strm->total_in += len;
+
+    /* return no joy or set up to restart inflate() on a new block */
+    if (state->have != 4) return Z_DATA_ERROR;
+    in = strm->total_in;  out = strm->total_out;
+    inflateReset(strm);
+    strm->total_in = in;  strm->total_out = out;
+    state->mode = TYPE;
+    return Z_OK;
+}
+
+/*
+   Returns true if inflate is currently at the end of a block generated by
+   Z_SYNC_FLUSH or Z_FULL_FLUSH. This function is used by one PPP
+   implementation to provide an additional safety check. PPP uses
+   Z_SYNC_FLUSH but removes the length bytes of the resulting empty stored
+   block. When decompressing, PPP checks that at the end of input packet,
+   inflate is waiting for these length bytes.
+ */
+int ZEXPORT inflateSyncPoint(strm)
+z_streamp strm;
+{
+    struct inflate_state FAR *state;
+
+    if (inflateStateCheck(strm)) return Z_STREAM_ERROR;
+    state = (struct inflate_state FAR *)strm->state;
+    return state->mode == STORED && state->bits == 0;
+}
+
+int ZEXPORT inflateCopy(dest, source)
+z_streamp dest;
+z_streamp source;
+{
+    struct inflate_state FAR *state;
+    struct inflate_state FAR *copy;
+    unsigned char FAR *window;
+    unsigned wsize;
+
+    /* check input */
+    if (inflateStateCheck(source) || dest == Z_NULL)
+        return Z_STREAM_ERROR;
+    state = (struct inflate_state FAR *)source->state;
+
+    /* allocate space */
+    copy = (struct inflate_state FAR *)
+           ZALLOC(source, 1, sizeof(struct inflate_state));
+    if (copy == Z_NULL) return Z_MEM_ERROR;
+    window = Z_NULL;
+    if (state->window != Z_NULL) {
+        window = (unsigned char FAR *)
+                 ZALLOC(source, 1U << state->wbits, sizeof(unsigned char));
+        if (window == Z_NULL) {
+            ZFREE(source, copy);
+            return Z_MEM_ERROR;
+        }
+    }
+
+    /* copy state */
+    zmemcpy((voidpf)dest, (voidpf)source, sizeof(z_stream));
+    zmemcpy((voidpf)copy, (voidpf)state, sizeof(struct inflate_state));
+    copy->strm = dest;
+    if (state->lencode >= state->codes &&
+        state->lencode <= state->codes + ENOUGH - 1) {
+        copy->lencode = copy->codes + (state->lencode - state->codes);
+        copy->distcode = copy->codes + (state->distcode - state->codes);
+    }
+    copy->next = copy->codes + (state->next - state->codes);
+    if (window != Z_NULL) {
+        wsize = 1U << state->wbits;
+        zmemcpy(window, state->window, wsize);
+    }
+    copy->window = window;
+    dest->state = (struct internal_state FAR *)copy;
+    return Z_OK;
+}
+
+int ZEXPORT inflateUndermine(strm, subvert)
+z_streamp strm;
+int subvert;
+{
+    struct inflate_state FAR *state;
+
+    if (inflateStateCheck(strm)) return Z_STREAM_ERROR;
+    state = (struct inflate_state FAR *)strm->state;
+#ifdef INFLATE_ALLOW_INVALID_DISTANCE_TOOFAR_ARRR
+    state->sane = !subvert;
+    return Z_OK;
+#else
+    (void)subvert;
+    state->sane = 1;
+    return Z_DATA_ERROR;
+#endif
+}
+
+int ZEXPORT inflateValidate(strm, check)
+z_streamp strm;
+int check;
+{
+    struct inflate_state FAR *state;
+
+    if (inflateStateCheck(strm)) return Z_STREAM_ERROR;
+    state = (struct inflate_state FAR *)strm->state;
+    if (check)
+        state->wrap |= 4;
+    else
+        state->wrap &= ~4;
+    return Z_OK;
+}
+
+long ZEXPORT inflateMark(strm)
+z_streamp strm;
+{
+    struct inflate_state FAR *state;
+
+    if (inflateStateCheck(strm))
+        return -(1L << 16);
+    state = (struct inflate_state FAR *)strm->state;
+    return (long)(((unsigned long)((long)state->back)) << 16) +
+        (state->mode == COPY ? state->length :
+            (state->mode == MATCH ? state->was - state->length : 0));
+}
+
+unsigned long ZEXPORT inflateCodesUsed(strm)
+z_streamp strm;
+{
+    struct inflate_state FAR *state;
+    if (inflateStateCheck(strm)) return (unsigned long)-1;
+    state = (struct inflate_state FAR *)strm->state;
+    return (unsigned long)(state->next - state->codes);
+}
diff --git a/tools/OWNERS b/tools/OWNERS
index 00b74ece..c7709de 100644
--- a/tools/OWNERS
+++ b/tools/OWNERS
@@ -46,6 +46,8 @@
 
 per-file roll_angle.py=kbr@chromium.org
 per-file roll_angle.py=geofflang@chromium.org
+per-file roll_swiftshader.py=capn@chromium.org
+per-file roll_swiftshader.py=sugoi@chromium.org
 per-file roll_webgl_conformance.py=bajones@chromium.org
 per-file roll_webgl_conformance.py=kbr@chromium.org
 per-file roll_webgl_conformance.py=geofflang@chromium.org
diff --git a/tools/android/native_lib_memory/extract_symbols.py b/tools/android/native_lib_memory/extract_symbols.py
index d21ca6a..ce9860e 100755
--- a/tools/android/native_lib_memory/extract_symbols.py
+++ b/tools/android/native_lib_memory/extract_symbols.py
@@ -57,23 +57,22 @@
   return result
 
 
-def CodePagesToMangledSymbols(native_library_filename):
-  """From the native library, groups the symbol per code page.
+def CodePagesToMangledSymbols(symbol_infos):
+  """Groups a list of symbol per code page.
 
   Args:
-    native_library_filename: (str) Native library path.
+    symbol_infos: (symbol_extractor.SymbolInfo) List of symbols.
 
   Returns:
     {offset: [(mangled_name, size_in_page), ...]}
   """
-  symbols = symbol_extractor.SymbolInfosFromBinary(native_library_filename)
   # Different symbols can be at the same address, through identical code folding
   # for instance. In this case, only keep the first one. This is not ideal, as
   # file attribution will be incorrect in this case. However ICF mostly works
   # with small symbols, so it shouldn't impact numbers too much.
   result = collections.defaultdict(set)
   known_offsets = set()
-  for s in symbols:
+  for s in symbol_infos:
     assert s.offset % 2 == 0, 'Wrong alignment'
     if s.offset in known_offsets:
       continue
@@ -90,11 +89,62 @@
   for page in result:
     total_size = sum(s[1] for s in result[page])
     if total_size > _PAGE_SIZE:
-      logging.warning('Too many symbols in page (%d * 4k)! Total size: %d' %
-                      (page / _PAGE_SIZE, total_size))
+      logging.warning('Too many symbols in page (%d * 4k)! Total size: %d',
+                      page / _PAGE_SIZE, total_size)
   return result
 
 
+def ReadReachedSymbols(filename):
+  """Reads a list of reached symbols from a file.
+
+  Args:
+    filename: (str) File to read.
+
+  Returns:
+    [str] List of symbol names.
+  """
+  with open(filename, 'r') as f:
+    return [line.strip() for line in f.readlines()]
+
+
+def WriteReachedData(filename, page_to_reached_data):
+  """Writes the page to reached fraction to a JSON file.
+
+  The output format is suited for visualize.html.
+
+  Args:
+    filename: (str) Output filename.
+    page_to_reached_data: (dict) As returned by CodePagesToReachedSize().
+  """
+  json_object = []
+  for (offset, data) in page_to_reached_data.items():
+    json_object.append({'offset': offset, 'total': data['total'],
+                        'reached': data['reached']})
+  with open(filename, 'w') as f:
+    json.dump(json_object, f)
+
+
+def CodePagesToReachedSize(reached_symbol_names, page_to_symbols):
+  """From page offset -> [all_symbols], return the reached portion per page.
+
+  Args:
+    reached_symbol_names: ([str]) List of reached symbol names.
+    page_to_symbols: (dict) As returned by CodePagesToMangledSymbols().
+
+  Returns:
+    {page offset (int) -> {'total': int, 'reached': int}}
+  """
+  reached_symbol_names = set(reached_symbol_names)
+  page_to_reached = {}
+  for offset in page_to_symbols:
+    total_size = sum(x[1] for x in page_to_symbols[offset])
+    reached_size = sum(
+        size_in_page for (name, size_in_page) in page_to_symbols[offset]
+        if name in reached_symbol_names)
+    page_to_reached[offset] = {'total': total_size, 'reached': reached_size}
+  return page_to_reached
+
+
 def CodePagesToObjectFiles(symbols_to_object_files, code_pages_to_symbols):
   """From symbols in object files and symbols in pages, gives code page to
   object files.
@@ -118,7 +168,7 @@
       if object_filename not in result[page_address]:
         result[page_address][object_filename] = 0
       result[page_address][object_filename] += size_in_page
-  logging.warning('%d unmatched symbols.' % unmatched_symbols_count)
+  logging.warning('%d unmatched symbols.', unmatched_symbols_count)
   return result
 
 
@@ -149,12 +199,20 @@
 
 
 def CreateArgumentParser():
+  """Creates and returns the argument parser."""
   parser = argparse.ArgumentParser(description='Map code pages to paths')
-  parser.add_argument('--build_directory', type=str, help='Build directory',
+  parser.add_argument('--native-library', type=str, default='libchrome.so',
+                      help=('Native Library, e.g. libchrome.so or '
+                            'libmonochrome.so'))
+  parser.add_argument('--reached-symbols-file', type=str,
+                      help='Path to the list of reached symbols, as generated '
+                      'by tools/cygprofile/process_profiles.py',
+                      required=False)
+  parser.add_argument('--build-directory', type=str, help='Build directory',
                       required=True)
-  parser.add_argument('--output_directory', type=str, help='Output directory',
+  parser.add_argument('--output-directory', type=str, help='Output directory',
                       required=True)
-  parser.add_argument('--start_server', action='store_true', default=False,
+  parser.add_argument('--start-server', action='store_true', default=False,
                       help='Run an HTTP server in the output directory')
   parser.add_argument('--port', type=int, default=8000,
                       help='Port to use for the HTTP server.')
@@ -164,14 +222,30 @@
 def main():
   parser = CreateArgumentParser()
   args = parser.parse_args()
-  symbols = GetSymbolNameToFilename(args.build_directory)
+  logging.basicConfig(level=logging.INFO)
+
+  logging.info('Parsing object files in %s', args.build_directory)
+  object_files_symbols = GetSymbolNameToFilename(args.build_directory)
   native_lib_filename = os.path.join(
-      args.build_directory, 'lib.unstripped', 'libmonochrome.so')
+      args.build_directory, 'lib.unstripped', args.native_library)
   if not os.path.exists(native_lib_filename):
-    logging.error('Native library not found. Did you build monochrome_apk?')
+    logging.error('Native library not found. Did you build the APK?')
     return 1
-  page_to_symbols = CodePagesToMangledSymbols(native_lib_filename)
-  page_to_object_files = CodePagesToObjectFiles(symbols, page_to_symbols)
+
+  logging.info('Extracting symbols from %s', native_lib_filename)
+  native_lib_symbols = symbol_extractor.SymbolInfosFromBinary(
+      native_lib_filename)
+  logging.info('Mapping symbols and object files to code pages')
+  page_to_symbols = CodePagesToMangledSymbols(native_lib_symbols)
+  page_to_object_files = CodePagesToObjectFiles(object_files_symbols,
+                                                page_to_symbols)
+
+  if args.reached_symbols_file:
+    logging.info('Mapping reached symbols to code pages')
+    reached_symbol_names = ReadReachedSymbols(args.reached_symbols_file)
+    reached_data = CodePagesToReachedSize(reached_symbol_names, page_to_symbols)
+    WriteReachedData(os.path.join(args.output_directory, 'reached.json'),
+                     reached_data)
 
   if not os.path.exists(args.output_directory):
     os.makedirs(args.output_directory)
@@ -180,6 +254,7 @@
   WriteCodePageAttribution(
       page_to_object_files, text_output_filename, json_output_filename)
   directory = os.path.dirname(__file__)
+
   for filename in ['visualize.html', 'visualize.js', 'visualize.css']:
     shutil.copy(os.path.join(directory, filename),
                 os.path.join(args.output_directory, filename))
@@ -187,8 +262,8 @@
   if args.start_server:
     os.chdir(args.output_directory)
     httpd = SocketServer.TCPServer(
-        ("", args.port), SimpleHTTPServer.SimpleHTTPRequestHandler)
-    logging.warning('Serving on port %d' % args.port)
+        ('', args.port), SimpleHTTPServer.SimpleHTTPRequestHandler)
+    logging.warning('Serving on port %d', args.port)
     httpd.serve_forever()
 
   return 0
diff --git a/tools/android/native_lib_memory/visualize.css b/tools/android/native_lib_memory/visualize.css
index 84cb884..d66a8880 100644
--- a/tools/android/native_lib_memory/visualize.css
+++ b/tools/android/native_lib_memory/visualize.css
@@ -3,6 +3,10 @@
  * found in the LICENSE file.
  */
 
+html, html * {
+  font-family: "Roboto", sans-serif;
+}
+
 .chart {
     shape-rendering: crispEdges;
 }
diff --git a/tools/android/native_lib_memory/visualize.html b/tools/android/native_lib_memory/visualize.html
index c8e32fd..2bb4fe6 100644
--- a/tools/android/native_lib_memory/visualize.html
+++ b/tools/android/native_lib_memory/visualize.html
@@ -20,7 +20,8 @@
         <script src="https://d3js.org/d3.v3.min.js"></script>
         <script src="visualize.js"></script>
         <script type="text/javascript">
-         readFileXhr("map.json");
+          fetchAllAndCreateGraph(["map.json", "reached.json"]);
+          buildColorLegend();
         </script>
     </body>
 </html>
diff --git a/tools/android/native_lib_memory/visualize.js b/tools/android/native_lib_memory/visualize.js
index cdbc228..f9f72b63 100644
--- a/tools/android/native_lib_memory/visualize.js
+++ b/tools/android/native_lib_memory/visualize.js
@@ -2,46 +2,55 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-function readFileXhr(filename) {
-  let xhr = new XMLHttpRequest();
-  xhr.open("GET", filename, true);
-  xhr.onreadystatechange = function() {
-    if (xhr.readyState == 4 && xhr.status == 200) {
-      let contents = xhr.responseText;
-      let jsonData = JSON.parse(contents);
-      go(jsonData);
-    }
-  }
-  xhr.send(null);
+/**
+ * Fetches all the urls, and calls {@link createGraph} with the JSON contents.
+ */
+function fetchAllAndCreateGraph(urls) {
+  Promise.all(
+      urls.map(url => fetch(url)
+               .then(response => response.ok ? response.json() : undefined)))
+      .then(jsonContents => createGraph.apply(this, jsonContents));
 }
 
-function go(codePages) {
-  createGraph(codePages);
-}
+const CODE_PAGE = "code_page";
+const REACHED_PAGE = "reached_page";
 
-// Returns the fill color for an item.
+/**
+ * @return {string} the fill color for a given page slice.
+ */
 function getFillColor(d) {
-  if (d.type == "code_page") return pageToFillColor(d.data);
+  switch (d.type) {
+    case CODE_PAGE:
+      return pageFillColor(d.data);
+    case REACHED_PAGE:
+      return reachedPageFillColor(d.data);
+  }
 }
 
 // Prefixes, color, description.
+const colors = d3.scale.category20();
+let colorIndex = 1;
 const COLOR_MAPPING = [
-  [["third_party/WebKit"], "darksalmon", "Blink"],
-  [["v8"], "green", "V8"],
-  [["base"], "purple", "//base"],
-  [["content"], "blue", "//content"],
-  [["components"], "pink", "//components"],
-  [["chrome/android"], "lightgreen", "//chrome/android"],
-  [["chrome"], "darkblue", "//chrome"],
-  [["net", "third_party/boringssl"], "black", "Net"],
+  [["third_party/WebKit"], colors(colorIndex++), "Blink"],
+  [["v8"], colors(colorIndex++), "V8"],
+  [["base"], colors(colorIndex++), "//base"],
+  [["content"], colors(colorIndex++), "//content"],
+  [["components"], colors(colorIndex++), "//components"],
+  [["chrome/android"], colors(colorIndex++), "//chrome/android"],
+  [["chrome"], colors(colorIndex++), "//chrome"],
+  [["net", "third_party/boringssl"], colors(colorIndex++), "Net"],
   [["third_party/webrtc", "third_party/opus", "third_party/usrsctp"],
-   "orange", "WebRTC"],
-  [["third_party/ffmpeg", "third_party/libvpx"], "darkred", "Media"],
-  [["third_party/icu"], "yellow", "ICU"],
-  [["skia"], "red", "Skia"]];
+   colors(colorIndex++), "WebRTC"],
+  [["third_party/ffmpeg", "third_party/libvpx"], colors(colorIndex++), "Media"],
+  [["third_party/icu"], colors(colorIndex++), "ICU"],
+  [["skia"], colors(colorIndex++), "Skia"],
+  [["ui"], colors(colorIndex++), "UI"],
+  [["cc"], colors(colorIndex++), "CC"]];
 
-// Returns the fill color for a code page item.
-function pageToFillColor(page) {
+/**
+ * @return the fill color for an item representing a code page.
+ */
+function pageFillColor(page) {
   const sizeAndFilename = page.size_and_filenames[0];
   if (!sizeAndFilename) return "lightgrey";
 
@@ -56,6 +65,22 @@
   return "darkgrey";
 }
 
+const reachedColorScale = d3.scale.linear()
+      .domain([0, 100])
+      .range(["black", "green"]);
+/**
+ * @return the fill color for an item reprensting reached data.
+ */
+function reachedPageFillColor(page) {
+  if (page.total == 0) return "white";
+  if (page.reached == 0) return "red";
+  const percentage = 100 * page.reached / page.total;
+  return reachedColorScale(percentage);
+}
+
+/**
+ * Adds the color legend to the document.
+ */
 function buildColorLegend() {
   let table = document.getElementById("colors-legend-table");
   for (let i = 0; i < COLOR_MAPPING.length; i++) {
@@ -73,15 +98,20 @@
     table.appendChild(row);
   }
 }
-buildColorLegend();
 
-// Returns the legend for a page item.
-function getLegend(d) {
-  if (d.type == "code_page") pageLegend(d.data);
-}
+/**
+ * Updates the legend.
+ *
+ * @param offset Offset of the item to label in the legend.
+ * @param offsetToData {offset: data} map.
+ */
+function updateLegend(offset, offsetToData) {
+  let data = offsetToData[offset];
+  if (!data) return;
 
-// Returns the legend for a code page item.
-function pageLegend(page) {
+  let page = data[CODE_PAGE];
+  let reached = data[REACHED_PAGE];
+
   let legend = document.getElementById("legend");
   legend.style.display = "block";
 
@@ -90,11 +120,15 @@
   let filename = "";
   if (sizeAndFilename) filename = sizeAndFilename[1];
 
+  let reachedSize = reached ? reached.reached : 0;
+  let reachedPercentage = reachedSize ? 100 * reachedSize / reached.total : 0;
   title.innerHTML = `
     <b>Page offset:</b> ${page.offset}
     <br/>
     <b>Accounted for:</b> ${page.accounted_for}
     <br/>
+    <b>Reached: </b> ${reachedSize} (${reachedPercentage.toFixed(2)}%)
+    <br/>
     <b>Dominant filename:</b> ${filename}`;
 
   let table = document.getElementById("legend-table");
@@ -112,21 +146,59 @@
   }
 }
 
-// Returns the lane index (from 0) for an item.
+
+/**
+ * @return {int} the lane index for a given data item.
+ */
 function typeToLane(d) {
-  return d.type == "code_page" ? 0 : 1;
+  switch (d.type) {
+    case CODE_PAGE:
+      return 0;
+    case REACHED_PAGE:
+      return 1;
+  }
 }
 
-// Takes the json data and displays it.
-function createGraph(codePages, residencyData) {
+/**
+ * Returns: offset -> {"code_page": codeData, "reached": reachedData}
+ */
+function getOffsetToData(flatData) {
+  let result = [];
+  for (let i = 0; i < flatData.length; i++) {
+    let data = flatData[i].data;
+    let type = flatData[i].type;
+    let offset = data["offset"];
+    if (!result[offset]) result[offset] = {};
+    result[offset][type] = data;
+  }
+  return result;
+}
+
+/**
+ * Creates the graph, and adds it to the DOM.
+ *
+ * reachedData can be undefined. In this case, only the code page data is shown.
+ *
+ * @param codePages data relative to code pages and their content.
+ * @param reachedData data relative to which fraction of code pages is reached.
+ */
+function createGraph(codePages, reachedPerPage) {
   const PAGE_SIZE = 4096;
 
   let offsets = codePages.map((x) => x.offset).sort((a, b) => a - b);
   let minOffset = +offsets[0];
   let maxOffset = +offsets[offsets.length - 1] + PAGE_SIZE;
 
-  let lanes = 1;  // Number of data tracks.
-  let flatData = codePages.map((page) => ({"type": "code_page", "data": page}));
+  let lanes = reachedPerPage ? 2 : 1;
+
+  // [{type: REACHED_PAGE | CODE_PAGE, data: pageData}]
+  let flatData = codePages.map((page) => ({"type": CODE_PAGE, "data": page}));
+  if (reachedPerPage) {
+    let typedReachedPerPage = reachedPerPage.map(
+        (page) => ({"type": REACHED_PAGE, "data": page}));
+    flatData = flatData.concat(typedReachedPerPage);
+  }
+  const offsetToData = getOffsetToData(flatData);
 
   let margins = [20, 15, 15, 120]  // top right bottom left
   let width = window.innerWidth - margins[1] - margins[3]
@@ -184,10 +256,10 @@
   let mainAxis = d3.svg.axis().scale(mainAxisScale).orient("bottom");
   let mainXAxis = main.append("g")
       .attr("class", "x axis")
-      .attr("transform", `translate(0, ${mainHeight})`)
+      .attr("transform", `translate(0, -10)`)
       .call(mainAxis);
 
-  const labels = ["Component"];
+  const labels = ["Component", "Reached"].slice(0, lanes);
   main.append("g").selectAll(".laneLines")
       .data(labels)
       .enter().append("line")
@@ -276,7 +348,7 @@
         .attr("width", (d) => zoomedXScalePageWidth)
         .attr("height", (d) => .8 * mainYScale(1))
         .style("fill", getFillColor)
-        .on("mouseover", getLegend);
+        .on("mouseover", (d) => updateLegend(d.data.offset, offsetToData));
 
     rects.exit().remove();
   }
diff --git a/tools/gn/command_gen.cc b/tools/gn/command_gen.cc
index 9c08a84..5775f78 100644
--- a/tools/gn/command_gen.cc
+++ b/tools/gn/command_gen.cc
@@ -211,10 +211,14 @@
     std::string win_kit;
     if (command_line->HasSwitch(kSwitchIdeValueWinSdk))
       win_kit = command_line->GetSwitchValueASCII(kSwitchIdeValueWinSdk);
+    std::string ninja_extra_args;
+    if (command_line->HasSwitch(kSwitchNinjaExtraArgs))
+      ninja_extra_args =
+          command_line->GetSwitchValueASCII(kSwitchNinjaExtraArgs);
     bool no_deps = command_line->HasSwitch(kSwitchNoDeps);
-    bool res = VisualStudioWriter::RunAndWriteFiles(build_settings, builder,
-                                                    version, sln_name, filters,
-                                                    win_kit, no_deps, err);
+    bool res = VisualStudioWriter::RunAndWriteFiles(
+        build_settings, builder, version, sln_name, filters, win_kit,
+        ninja_extra_args, no_deps, err);
     if (res && !quiet) {
       OutputString("Generating Visual Studio projects took " +
                    base::Int64ToString(timer.Elapsed().InMilliseconds()) +
@@ -329,6 +333,10 @@
       As an example, "10.0.15063.0" can be specified to use Creators Update SDK
       instead of the default one.
 
+  --ninja-extra-args=<string>
+      This string is passed without any quoting to the ninja invocation
+      command-line. Can be used to configure ninja flags, like "-j".
+
 Xcode Flags
 
   --workspace=<file_name>
@@ -337,8 +345,7 @@
 
   --ninja-extra-args=<string>
       This string is passed without any quoting to the ninja invocation
-      command-line. Can be used to configure ninja flags, like "-j" if using
-      goma for example.
+      command-line. Can be used to configure ninja flags, like "-j".
 
   --root-target=<target_name>
       Name of the target corresponding to "All" target in Xcode. If unset,
diff --git a/tools/gn/docs/reference.md b/tools/gn/docs/reference.md
index d5fe229a..733588a 100644
--- a/tools/gn/docs/reference.md
+++ b/tools/gn/docs/reference.md
@@ -663,6 +663,10 @@
       Use the specified Windows 10 SDK version to generate project files.
       As an example, "10.0.15063.0" can be specified to use Creators Update SDK
       instead of the default one.
+
+  --ninja-extra-args=<string>
+      This string is passed without any quoting to the ninja invocation
+      command-line. Can be used to configure ninja flags, like "-j".
 ```
 
 #### **Xcode Flags**
@@ -674,8 +678,7 @@
 
   --ninja-extra-args=<string>
       This string is passed without any quoting to the ninja invocation
-      command-line. Can be used to configure ninja flags, like "-j" if using
-      goma for example.
+      command-line. Can be used to configure ninja flags, like "-j".
 
   --root-target=<target_name>
       Name of the target corresponding to "All" target in Xcode. If unset,
diff --git a/tools/gn/parser_fuzzer.cc b/tools/gn/parser_fuzzer.cc
index c7b43255..e40da78 100644
--- a/tools/gn/parser_fuzzer.cc
+++ b/tools/gn/parser_fuzzer.cc
@@ -9,6 +9,51 @@
 #include "tools/gn/source_file.h"
 #include "tools/gn/tokenizer.h"
 
+namespace {
+
+enum { kMaxContentDepth = 256, kMaxDodgy = 256 };
+
+// Some auto generated input is too unreasonable for fuzzing GN.
+// We see stack overflow when the parser hits really deeply "nested" input.
+// (I.E.: certain input that causes nested parsing function calls).
+//
+// Abstract max limits are undesirable in the release GN code, so some sanity
+// checks in the fuzzer to prevent stack overflow are done here.
+// - 1) Too many opening bracket, paren, or brace in a row.
+// - 2) Too many '!', '<' or '>' operators in a row.
+bool SanityCheckContent(const std::vector<Token>& tokens) {
+  int depth = 0;
+  int dodgy_count = 0;
+  for (const auto& token : tokens) {
+    switch (token.type()) {
+      case Token::LEFT_PAREN:
+      case Token::LEFT_BRACKET:
+      case Token::LEFT_BRACE:
+        ++depth;
+        break;
+      case Token::RIGHT_PAREN:
+      case Token::RIGHT_BRACKET:
+      case Token::RIGHT_BRACE:
+        --depth;
+        break;
+      case Token::BANG:
+      case Token::LESS_THAN:
+      case Token::GREATER_THAN:
+        ++dodgy_count;
+        break;
+      default:
+        break;
+    }
+    // Bail out as soon as a boundary is hit, inside the loop.
+    if (depth >= kMaxContentDepth || dodgy_count >= kMaxDodgy)
+      return false;
+  }
+
+  return true;
+}
+
+}  // namespace
+
 extern "C" int LLVMFuzzerTestOneInput(const unsigned char* data, size_t size) {
   SourceFile source;
   InputFile input(source);
@@ -16,6 +61,8 @@
 
   Err err;
   std::vector<Token> tokens = Tokenizer::Tokenize(&input, &err);
+  if (!SanityCheckContent(tokens))
+    return 0;
 
   if (!err.has_error())
     Parser::Parse(tokens, &err);
diff --git a/tools/gn/visual_studio_writer.cc b/tools/gn/visual_studio_writer.cc
index ad821a7..bbb99c6f 100644
--- a/tools/gn/visual_studio_writer.cc
+++ b/tools/gn/visual_studio_writer.cc
@@ -316,6 +316,7 @@
                                           const std::string& sln_name,
                                           const std::string& filters,
                                           const std::string& win_sdk,
+                                          const std::string& ninja_extra_args,
                                           bool no_deps,
                                           Err* err) {
   std::vector<const Target*> targets;
@@ -351,7 +352,7 @@
       continue;
     }
 
-    if (!writer.WriteProjectFiles(target, err))
+    if (!writer.WriteProjectFiles(target, ninja_extra_args, err))
       return false;
   }
 
@@ -372,7 +373,9 @@
   return writer.WriteSolutionFile(sln_name, err);
 }
 
-bool VisualStudioWriter::WriteProjectFiles(const Target* target, Err* err) {
+bool VisualStudioWriter::WriteProjectFiles(const Target* target,
+                                           const std::string& ninja_extra_args,
+                                           Err* err) {
   std::string project_name = target->label().name();
   const char* project_config_platform = config_platform_;
   if (!target->settings()->is_default()) {
@@ -403,7 +406,7 @@
   std::stringstream vcxproj_string_out;
   SourceFileCompileTypePairs source_types;
   if (!WriteProjectFileContents(vcxproj_string_out, *projects_.back(), target,
-                                &source_types, err)) {
+                                ninja_extra_args, &source_types, err)) {
     projects_.pop_back();
     return false;
   }
@@ -424,6 +427,7 @@
     std::ostream& out,
     const SolutionProject& solution_project,
     const Target* target,
+    const std::string& ninja_extra_args,
     SourceFileCompileTypePairs* source_types,
     Err* err) {
   PathOutput path_output(
@@ -611,6 +615,7 @@
         std::unique_ptr<XmlElementWriter> build = group->SubElement(
             compile_type, "Include", SourceFileWriter(path_output, file));
         build->SubElement("Command")->Text("call ninja.exe -C $(OutDir) " +
+                                           ninja_extra_args + " " +
                                            tool_outputs[0].value());
         build->SubElement("Outputs")->Text("$(OutDir)" +
                                            tool_outputs[0].value());
@@ -638,8 +643,9 @@
     std::unique_ptr<XmlElementWriter> build =
         project.SubElement("Target", XmlAttributes("Name", "Build"));
     build->SubElement(
-        "Exec", XmlAttributes("Command",
-                              "call ninja.exe -C $(OutDir) " + ninja_target));
+        "Exec",
+        XmlAttributes("Command", "call ninja.exe -C $(OutDir) " +
+                                     ninja_extra_args + " " + ninja_target));
   }
 
   {
diff --git a/tools/gn/visual_studio_writer.h b/tools/gn/visual_studio_writer.h
index db2f3ea..d9bb883 100644
--- a/tools/gn/visual_studio_writer.h
+++ b/tools/gn/visual_studio_writer.h
@@ -45,6 +45,7 @@
                                const std::string& sln_name,
                                const std::string& filters,
                                const std::string& win_sdk,
+                               const std::string& ninja_extra_args,
                                bool no_deps,
                                Err* err);
 
@@ -104,10 +105,13 @@
                      const std::string& win_kit);
   ~VisualStudioWriter();
 
-  bool WriteProjectFiles(const Target* target, Err* err);
+  bool WriteProjectFiles(const Target* target,
+                         const std::string& ninja_extra_args,
+                         Err* err);
   bool WriteProjectFileContents(std::ostream& out,
                                 const SolutionProject& solution_project,
                                 const Target* target,
+                                const std::string& ninja_extra_args,
                                 SourceFileCompileTypePairs* source_types,
                                 Err* err);
   void WriteFiltersFileContents(std::ostream& out,
diff --git a/tools/mb/mb_config.pyl b/tools/mb/mb_config.pyl
index a6eb178..5b04aea 100644
--- a/tools/mb/mb_config.pyl
+++ b/tools/mb/mb_config.pyl
@@ -204,6 +204,7 @@
       'CrWinGoma': 'release_bot_x86_minimal_symbols',
       'CrWinGoma(dll)': 'shared_release_bot_x86',
       'CrWinGoma(loc)': 'shared_release_bot_x86',
+      'CrWinClexeGoma': 'shared_release_bot_x86_no_clang',
       'CrWinClangGoma': 'clang_official_optimize_release_bot_minimal_symbols_x86',
 
       'EarlGreyiOS': 'ios',
@@ -618,7 +619,6 @@
       'linux_chromium_headless_rel': 'headless_linux_release_trybot',
       'linux_chromium_ozone_compile_only_ng': 'ozone_linux_release_trybot',
       'linux_chromium_ozone_ng': 'ozone_linux_release_trybot',
-      'linux_layout_tests_slimming_paint_v2': 'release_trybot',
 
       # This is intentionally a release_bot and not a release_trybot;
       # enabling DCHECKs seems to cause flaky failures that don't show up
@@ -629,6 +629,8 @@
       'linux_chromium_tsan_rel_ng': 'tsan_disable_nacl_release_trybot',
       'linux_chromium_ubsan_rel_ng': 'ubsan_vptr_release_trybot',
       'linux_layout_tests_layout_ng': 'release_trybot',
+      'linux_layout_tests_root_layer_scrolls': 'release_trybot',
+      'linux_layout_tests_slimming_paint_v2': 'release_trybot',
       'linux_mojo': 'release_trybot',
       'linux_mojo_chromeos': 'chromeos_with_codecs_release_trybot',
       'linux_nacl_sdk_build': 'release_bot',
@@ -1620,6 +1622,10 @@
       'shared_release_bot', 'x86',
     ],
 
+    'shared_release_bot_x86_no_clang': [
+      'shared_release_bot', 'x86', 'no_clang',
+    ],
+
     'syzyasan_no_pch_release_x86': [
       'syzyasan', 'no_pch', 'release', 'x86',
       # The SyzyASAN build may default dcheck_always_on to true to produce
diff --git a/tools/metrics/histograms/README.md b/tools/metrics/histograms/README.md
index dd469dc..a48e281 100644
--- a/tools/metrics/histograms/README.md
+++ b/tools/metrics/histograms/README.md
@@ -80,11 +80,12 @@
 To add a new entry:
 
 1. Edit [enums.xml](./enums.xml), adding the feature to the `LoginCustomFlags`
-   enum section, with any unique value (just make one up).
+   enum section, with any unique value (just make one up, although whatever it
+   is needs to appear in sorted order; `pretty-print.py` will do this for you).
 2. Build `unit_tests`, then run `unit_tests
    --gtest_filter='AboutFlagsHistogramTest.*'` to compute the correct value.
 3. Update the entry in [enums.xml](./enums.xml) with the correct value, and move
-   it so the list is sorted by value.
+   it so the list is sorted by value (`pretty_print.py` will do this for you).
 4. Re-run the test to ensure the value and ordering are correct.
 
 You can also use `tools/metrics/histograms/validate_format.py` to check the
diff --git a/tools/metrics/histograms/enums.xml b/tools/metrics/histograms/enums.xml
index 477d8ee..db575a8 100644
--- a/tools/metrics/histograms/enums.xml
+++ b/tools/metrics/histograms/enums.xml
@@ -4058,6 +4058,15 @@
   <int value="36" label="UNREACHABLE_6"/>
 </enum>
 
+<enum name="BrowserActionsMenuOption">
+  <int value="0" label="Open in new Chrome tab"/>
+  <int value="1" label="Open in incognito tab"/>
+  <int value="2" label="Download page"/>
+  <int value="3" label="Copy link"/>
+  <int value="4" label="Share link"/>
+  <int value="5" label="App provided items"/>
+</enum>
+
 <enum name="BubbleType">
   <int value="0" label="Unknown Bubble"/>
   <int value="1" label="Mock Bubble"/>
@@ -4368,6 +4377,13 @@
   <int value="4" label="Init Verification Failed"/>
 </enum>
 
+<enum name="CdmLoadResult">
+  <int value="0" label="Success"/>
+  <int value="1" label="CDM file missing"/>
+  <int value="2" label="CDM file exists but load failed"/>
+  <int value="3" label="CDM loaded but entry point missing"/>
+</enum>
+
 <enum name="CdmPromiseResult">
   <int value="0" label="Success"/>
   <int value="1" label="NotSupportedError"/>
@@ -9436,7 +9452,52 @@
   <int value="260" label="toast"/>
   <int value="261" label="udif"/>
   <int value="262" label="run"/>
-  <int value="263" label="ad"/>
+  <int value="263" label="mpkg"/>
+  <int value="264" label="as"/>
+  <int value="265" label="cpgz"/>
+  <int value="266" label="pax"/>
+  <int value="267" label="xip"/>
+  <int value="268" label="docx"/>
+  <int value="269" label="docm"/>
+  <int value="270" label="dott"/>
+  <int value="271" label="dotm"/>
+  <int value="272" label="docb"/>
+  <int value="273" label="xlsx"/>
+  <int value="274" label="xlsm"/>
+  <int value="275" label="xltx"/>
+  <int value="276" label="xltm"/>
+  <int value="277" label="pptx"/>
+  <int value="278" label="pptm"/>
+  <int value="279" label="potx"/>
+  <int value="280" label="ppam"/>
+  <int value="281" label="ppsx"/>
+  <int value="282" label="sldx"/>
+  <int value="283" label="sldm"/>
+  <int value="284" label="htm"/>
+  <int value="285" label="html"/>
+  <int value="286" label="xht"/>
+  <int value="287" label="xhtm"/>
+  <int value="288" label="xhtml"/>
+  <int value="289" label="vdx"/>
+  <int value="290" label="vsx"/>
+  <int value="291" label="vtx"/>
+  <int value="292" label="vsdx"/>
+  <int value="293" label="vssx"/>
+  <int value="294" label="vstx"/>
+  <int value="295" label="vsdm"/>
+  <int value="296" label="vssm"/>
+  <int value="297" label="vstm"/>
+  <int value="298" label="btapp"/>
+  <int value="299" label="btbtskin"/>
+  <int value="300" label="btinstall"/>
+  <int value="301" label="btkey"/>
+  <int value="302" label="btsearch"/>
+  <int value="303" label="dhtml"/>
+  <int value="304" label="dhtm"/>
+  <int value="305" label="dht"/>
+  <int value="306" label="shtml"/>
+  <int value="307" label="shtm"/>
+  <int value="308" label="sht"/>
 </enum>
 
 <enum name="DownloadItem.DangerType">
@@ -16790,6 +16851,10 @@
   <int value="2204" label="HasBeforeOrAfterPseudoElement"/>
   <int value="2205" label="ShapeOutsideMaybeAffectedInlineSize"/>
   <int value="2206" label="ShapeOutsideMaybeAffectedInlinePosition"/>
+  <int value="2207" label="GamepadVibrationActuator"/>
+  <int value="2208" label="MicrophoneDisabledByFeaturePolicyEstimate"/>
+  <int value="2209" label="CameraDisabledByFeaturePolicyEstimate"/>
+  <int value="2210" label="MidiDisabledByFeaturePolicy"/>
 </enum>
 
 <enum name="FeedbackSource">
@@ -17951,6 +18016,8 @@
       label="Anki OVERDRIVE cars; be15bee0-6186-407e-8381-0bd89c4d8df4"/>
   <int value="40437408" label="gender"/>
   <int value="42833873" label="42833873 (Unknown; not a 16bit UUID)"/>
+  <int value="46607535"
+      label="PocketLab 1; f000aa14-0451-4000-b000-000000000000"/>
   <int value="61502349"
       label="PocketLab; f000aa2c-0452-4000-b000-000000000000"/>
   <int value="64893984" label="local_east_coordinate.xml"/>
@@ -17963,6 +18030,8 @@
              a3c8750a-8ed3-4bdf-8a39-a01bebede295"/>
   <int value="87432554"
       label="Parrot Drone; 9a66fd54-0800-9191-11e4-012d1540cb8e"/>
+  <int value="87889094"
+      label="PocketLab 1; f000aa21-0451-4000-b000-000000000000"/>
   <int value="89070880" label="blood_pressure_measurement"/>
   <int value="102699400" label="cycling_power_feature"/>
   <int value="107355463"
@@ -17982,6 +18051,8 @@
   <int value="177223896" label="report_map"/>
   <int value="193202136"
       label="Anki OVERDRIVE cars; be15bee1-6186-407e-8381-0bd89c4d8df4"/>
+  <int value="197745578"
+      label="PocketLab 1; f000aa13-0451-4000-b000-000000000000"/>
   <int value="203698195"
       label="micro:bit event; e95d9775-251d-470a-a062-fa1922dfa9a8"/>
   <int value="203846063" label="ff0c"/>
@@ -18003,6 +18074,8 @@
       label="Wahoo Kickr trainer; a026e005-0a7d-4ab3-97fa-f1500f9feb8b"/>
   <int value="296670902" label="heart_rate_control_point"/>
   <int value="298186521" label="alert_category_id"/>
+  <int value="305375377"
+      label="PocketLab 1; f000aa62-0451-4000-b000-000000000000"/>
   <int value="307449363" label="plx_features"/>
   <int value="310983691" label="cycling_power_measurement"/>
   <int value="312578485" label="navigation"/>
@@ -18045,6 +18118,8 @@
   <int value="448606809" label="448606809 (Unknown; not a 16bit UUID)"/>
   <int value="449334956"
       label="PocketLab; f000aa3d-0452-4000-b000-000000000000"/>
+  <int value="450021248"
+      label="PocketLab 1; f000aa34-0451-4000-b000-000000000000"/>
   <int value="469191968" label="Playbulb Candle Color; fffc"/>
   <int value="473092981"
       label="Eddystone Config Advertising Interval;
@@ -18133,8 +18208,12 @@
   <int value="797118889" label="time_source"/>
   <int value="806223105"
       label="PocketLab; f000aa1c-0452-4000-b000-000000000000"/>
+  <int value="827298832"
+      label="PocketLab 1; f000aa41-0451-4000-b000-000000000000"/>
   <int value="827651216"
       label="PocketLab; f000aa20-0452-4000-b000-000000000000"/>
+  <int value="837013645"
+      label="PocketLab 1; f000aa64-0451-4000-b000-000000000000"/>
   <int value="839366223" label="user_index"/>
   <int value="842908520" label="rsc_measurement"/>
   <int value="845003775"
@@ -18162,6 +18241,8 @@
   <int value="922434244" label="ln_feature"/>
   <int value="928099812" label="system_id"/>
   <int value="928491064" label="last_name"/>
+  <int value="936278868"
+      label="PocketLab 1; f000aa53-0451-4000-b000-000000000000"/>
   <int value="941113050"
       label="konashi i2cReadParameter; 229b300e-03fb-40da-98a7-b0def65c2d4b"/>
   <int value="947971228" label="temperature_type"/>
@@ -18172,8 +18253,12 @@
       label="Eddystone Config Public ECDH Key;
              a3c87508-8ed3-4bdf-8a39-a01bebede295"/>
   <int value="976761505" label="local_time_information"/>
+  <int value="981442423"
+      label="PocketLab 1; f000aa63-0451-4000-b000-000000000000"/>
   <int value="987658962" label="glucose_measurement"/>
   <int value="1002619180" label="exact_time_256"/>
+  <int value="1005198408"
+      label="PocketLab 1; f000aa51-0451-4000-b000-000000000000"/>
   <int value="1018346218"
       label="PocketLab; f000aa03-0452-4000-b000-000000000000"/>
   <int value="1025676359" label="dst_offset"/>
@@ -18192,6 +18277,10 @@
   <int value="1097514018"
       label="PocketLab; f000aa06-0452-4000-b000-000000000000"/>
   <int value="1100640868" label="day_of_week"/>
+  <int value="1102386988"
+      label="PocketLab 1; f000aa42-0451-4000-b000-000000000000"/>
+  <int value="1108268178"
+      label="PocketLab 1; f000aa23-0451-4000-b000-000000000000"/>
   <int value="1115558005"
       label="konashi hardwareReset; 229b3014-03fb-40da-98a7-b0def65c2d4b"/>
   <int value="1117053056"
@@ -18203,6 +18292,8 @@
   <int value="1134538374" label="hip_circumference"/>
   <int value="1136624215" label="maximum_recommended_heart_rate"/>
   <int value="1136682523" label="date_time"/>
+  <int value="1142216738"
+      label="PocketLab 1; f000aa22-0451-4000-b000-000000000000"/>
   <int value="1154699367"
       label="konashi uartTx; 229b3012-03fb-40da-98a7-b0def65c2d4b"/>
   <int value="1161713439" label="Playbulb Candle Effect; fffb"/>
@@ -18218,6 +18309,8 @@
   <int value="1193066711" label="uv_index"/>
   <int value="1211834643"
       label="PocketLab; f000aa02-0452-4000-b000-000000000000"/>
+  <int value="1212625023"
+      label="PocketLab 1; f000aa52-0451-4000-b000-000000000000"/>
   <int value="1214133688" label="vo2_max"/>
   <int value="1217613737" label="three_zone_heart_rate_limits"/>
   <int value="1225369773"
@@ -18232,17 +18325,23 @@
   <int value="1254532025" label="user_control_point"/>
   <int value="1266038031" label="1266038031 (Unknown; not a 16bit UUID)"/>
   <int value="1288236137" label="hid_control_point"/>
+  <int value="1293962119"
+      label="PocketLab 1; f000aa61-0451-4000-b000-000000000000"/>
   <int value="1307935876"
       label="Tacx trainer; 6e40fec3-b5a3-f393-e0a9-e50e24dcca9e"/>
   <int value="1320278204"
       label="Eddystone Config Radio Tx Power;
              a3c87504-8ed3-4bdf-8a39-a01bebede295"/>
+  <int value="1324040850"
+      label="PocketLab 1; f000aa11-0451-4000-b000-000000000000"/>
   <int value="1329901812"
       label="Eddystone Config Lock State;
              a3c87506-8ed3-4bdf-8a39-a01bebede295"/>
   <int value="1333242790" label="longitude"/>
   <int value="1334750659"
       label="konashi i2cWrite; 229b300d-03fb-40da-98a7-b0def65c2d4b"/>
+  <int value="1345855767"
+      label="PocketLab 1; f000aa24-0451-4000-b000-000000000000"/>
   <int value="1352512695" label="1352512695 (Unknown; not a 16bit UUID)"/>
   <int value="1358488787"
       label="sport_type_for_aerobic_and_anaerobic_thresholds"/>
@@ -18299,6 +18398,8 @@
   <int value="1547112406"
       label="Eddystone Config Active Slot;
              a3c87502-8ed3-4bdf-8a39-a01bebede295"/>
+  <int value="1547439596"
+      label="PocketLab 1; f000aa31-0451-4000-b000-000000000000"/>
   <int value="1548291582"
       label="konashi analogRead1; 229b3009-03fb-40da-98a7-b0def65c2d4b"/>
   <int value="1551090056"
@@ -18314,14 +18415,20 @@
   <int value="1599786113" label="sensor_location"/>
   <int value="1611458228"
       label="PocketLab; f000aa34-0452-4000-b000-000000000000"/>
+  <int value="1620145835"
+      label="PocketLab 1; f000aa54-0451-4000-b000-000000000000"/>
   <int value="1650767660" label="protocol_mode"/>
   <int value="1655824245" label="pressure"/>
   <int value="1658559118" label="digital"/>
+  <int value="1667674937"
+      label="PocketLab 1; f000aa33-0451-4000-b000-000000000000"/>
   <int value="1669829174"
       label="Purple Eye; 00005200-0000-1000-8000-00805f9b34fb"/>
   <int value="1676607014"
       label="konashi i2cConfig; 229b300b-03fb-40da-98a7-b0def65c2d4b"/>
   <int value="1704141710" label="true_wind_direction"/>
+  <int value="1717192545"
+      label="PocketLab 1; f000aa12-0451-4000-b000-000000000000"/>
   <int value="1719495127"
       label="PocketLab; f000aa00-0452-4000-b000-000000000000"/>
   <int value="1732815395" label="alert_level"/>
@@ -18376,6 +18483,8 @@
   <int value="1995515788"
       label="PocketLab (from service 11);
              f000aa1b-0452-4000-b000-000000000000"/>
+  <int value="1995890588"
+      label="PocketLab 1; f000aa43-0451-4000-b000-000000000000"/>
   <int value="1999174392" label="glucose_measurement_context"/>
   <int value="2000824522" label="waist_circumference"/>
   <int value="2010182602" label="csc_feature"/>
@@ -18388,6 +18497,8 @@
   <int value="2025816471"
       label="Eddystone Config Unlock; a3c87507-8ed3-4bdf-8a39-a01bebede295"/>
   <int value="2031294873" label="uncertainty"/>
+  <int value="2040106786"
+      label="PocketLab 1; f000aa44-0451-4000-b000-000000000000"/>
   <int value="2041423305" label="email_address"/>
   <int value="2042267197" label="age"/>
   <int value="2047173546" label="boot_keyboard_input_report"/>
@@ -18415,6 +18526,8 @@
   <int value="2105952193" label="heart_rate_max"/>
   <int value="2110830087"
       label="Printer; 00002af1-0000-1000-8000-00805f9b34fb"/>
+  <int value="2118241351"
+      label="PocketLab 1; f000aa32-0451-4000-b000-000000000000"/>
   <int value="2118566262" label="database_change_increment"/>
   <int value="2122016879"
       label="PocketLab (from service 11);
@@ -18492,6 +18605,8 @@
   <int value="81699382"
       label="PocketLab; f000aa1d-0452-4000-b000-000000000000"/>
   <int value="85709298" label="fe38"/>
+  <int value="87242598"
+      label="PocketLab 1; f000aa40-0451-4000-b000-000000000000"/>
   <int value="91953454" label="fe7b"/>
   <int value="107684477"
       label="PocketLab; f000aa2d-0452-4000-b000-000000000000"/>
@@ -18526,12 +18641,16 @@
   <int value="253001319" label="fe84"/>
   <int value="267848299" label="fe3e"/>
   <int value="270670950" label="fe62"/>
+  <int value="272049750"
+      label="PocketLab 1; f000aa30-0451-4000-b000-000000000000"/>
   <int value="272218751" label="automation_io"/>
   <int value="273356483" label="fe68"/>
   <int value="278860884" label="fe5c"/>
   <int value="289754407" label="fe01"/>
   <int value="291870040" label="fe6d"/>
   <int value="295205583" label="fe27"/>
+  <int value="298938019"
+      label="PocketLab 1; f000aa20-0451-4000-b000-000000000000"/>
   <int value="310654399" label="fe54"/>
   <int value="314884784" label="fe65"/>
   <int value="315044617" label="fea9"/>
@@ -18569,6 +18688,8 @@
   <int value="501361244"
       label="PocketLab; f000aa21-0452-4000-b000-000000000000"/>
   <int value="517314925" label="fe0e"/>
+  <int value="525609715"
+      label="PocketLab 1; f000aa10-0451-4000-b000-000000000000"/>
   <int value="534472233" label="feea"/>
   <int value="535574137" label="feb1"/>
   <int value="540487861"
@@ -18675,6 +18796,8 @@
   <int value="963656436" label="fe77"/>
   <int value="978815669"
       label="CoolBeans Serial; a495ff10-c5b1-4b44-b512-1370f02d74de"/>
+  <int value="988476177"
+      label="PocketLab 1; f000aa50-0451-4000-b000-000000000000"/>
   <int value="1001310815" label="fe75"/>
   <int value="1018346218"
       label="PocketLab; f000aa03-0452-4000-b000-000000000000"/>
@@ -18815,10 +18938,8 @@
   <int value="1648320092" label="fe7f"/>
   <int value="1651126525" label="fe25"/>
   <int value="1651610232" label="fe52"/>
-<!-- Hash values can be produced using tool: bluetooth_metrics_hash -->
-
   <int value="1655806770"
-      label="PocketLab; f000aa11-0452-4000-b000-000000000000"/>
+      label="PocketLab Voyager; f000aa11-0452-4000-b000-000000000000"/>
   <int value="1660904097" label="immediate_alert"/>
   <int value="1663141542" label="battery_service"/>
   <int value="1671670551" label="fe5a"/>
@@ -18911,12 +19032,14 @@
   <int value="2069612985" label="fee5"/>
   <int value="2070392722" label="fec2"/>
   <int value="2075745564" label="heart_rate"/>
+  <int value="2081202638"
+      label="PocketLab 1; f000aa60-0451-4000-b000-000000000000"/>
   <int value="2081534039" label="fe83"/>
   <int value="2086529225" label="tx_power"/>
   <int value="2093050338"
       label="PocketLab; f000aa08-0452-4000-b000-000000000000"/>
   <int value="2095670709"
-      label="PocketLab; f000aa31-0452-4000-b000-000000000000"/>
+      label="PocketLab Voyager; f000aa31-0452-4000-b000-000000000000"/>
   <int value="2097896377" label="fee8"/>
   <int value="2100033855" label="fef7"/>
   <int value="2103247472"
@@ -23934,6 +24057,7 @@
   <int value="-1912999136" label="enable-automatic-password-saving:enabled"/>
   <int value="-1911316813" label="BlockTabUnders:disabled"/>
   <int value="-1911153473" label="enable-easy-signin"/>
+  <int value="-1909983714" label="ExperimentalTabController:disabled"/>
   <int value="-1909356390"
       label="OverlayScrollbarFlashAfterAnyScrollUpdate:enabled"/>
   <int value="-1907342706" label="ReadItLaterInMenu:disabled"/>
@@ -24168,6 +24292,8 @@
   <int value="-1268836676" label="disable-out-of-process-pdf"/>
   <int value="-1267958145" label="disable-pdf-material-ui"/>
   <int value="-1262152606" label="disable-lock-screen-apps"/>
+  <int value="-1261263046"
+      label="RemoveUsageOfDeprecatedGaiaSigninEndpoint:disabled"/>
   <int value="-1254070521" label="enable-slimming-paint-invalidation"/>
   <int value="-1251411236" label="disable-new-md-input-view"/>
   <int value="-1248478422" label="enable-zip-archiver-packer"/>
@@ -24256,6 +24382,7 @@
   <int value="-1020450980" label="gesture-deletion"/>
   <int value="-1016202433" label="disable-add-to-shelf"/>
   <int value="-1015006759" label="ImportantSitesInCBD:disabled"/>
+  <int value="-1014649471" label="committed-interstitials"/>
   <int value="-998255750" label="ExperimentalKeyboardLockUI:enabled"/>
   <int value="-996673716" label="enable-web-app-frame"/>
   <int value="-991253797"
@@ -24401,6 +24528,7 @@
   <int value="-601384286" label="disable-contextual-search"/>
   <int value="-599932554" label="DoodlesOnLocalNtp:disabled"/>
   <int value="-598050737" label="disable-es3-apis"/>
+  <int value="-593536514" label="ExperimentalTabController:enabled"/>
   <int value="-589096918" label="ash-enable-fullscreen-app-list"/>
   <int value="-579192400" label="disable-input-view"/>
   <int value="-572112724" label="DialogTouchBar:disabled"/>
@@ -25307,6 +25435,8 @@
   <int value="2014331873" label="NTPDownloadSuggestions:disabled"/>
   <int value="2014629801" label="view-passwords:disabled"/>
   <int value="2020107447" label="AndroidPayIntegrationV1:enabled"/>
+  <int value="2032558514"
+      label="RemoveUsageOfDeprecatedGaiaSigninEndpoint:enabled"/>
   <int value="2037756154" label="enable-impl-side-painting"/>
   <int value="2043321329" label="OfflinePagesPrefetchingUI:disabled"/>
   <int value="2056572020" label="EnableUsernameCorrection:disabled"/>
@@ -35216,6 +35346,26 @@
   <int value="286" label="XHT"/>
   <int value="287" label="XHTM"/>
   <int value="288" label="XHTML"/>
+  <int value="289" label="VDX"/>
+  <int value="290" label="VSX"/>
+  <int value="291" label="VTX"/>
+  <int value="292" label="VSDX"/>
+  <int value="293" label="VSSX"/>
+  <int value="294" label="VSTX"/>
+  <int value="295" label="VSDM"/>
+  <int value="296" label="VSSM"/>
+  <int value="297" label="VSTM"/>
+  <int value="298" label="BTAPP"/>
+  <int value="299" label="BTBTSKIN"/>
+  <int value="300" label="BTINSTALL"/>
+  <int value="301" label="BTKEY"/>
+  <int value="302" label="BTSEARCH"/>
+  <int value="303" label="DHTML"/>
+  <int value="304" label="DHTM"/>
+  <int value="305" label="DHT"/>
+  <int value="306" label="SHTML"/>
+  <int value="307" label="SHTM"/>
+  <int value="308" label="SHT"/>
 </enum>
 
 <enum name="SBClientDownloadIsSignedBinary">
@@ -38473,6 +38623,19 @@
   <int value="4" label="Swap was unsuccessful (activation fails)"/>
 </enum>
 
+<enum name="SwapThrashingLevel">
+  <int value="0" label="No swap thrashing"/>
+  <int value="1" label="Suspiscion of swap thrashing"/>
+  <int value="2" label="Confirmed swap thrashing"/>
+</enum>
+
+<enum name="SwapThrashingLevelChanges">
+  <int value="0" label="None to Suspected"/>
+  <int value="1" label="Suspected to Confirmed"/>
+  <int value="2" label="Confirmed to Suspected"/>
+  <int value="3" label="Suspected to None"/>
+</enum>
+
 <enum name="SwReporterRunningTimeRegistryError">
   <int value="0" label="No error"/>
   <int value="1" label="Registry key invalid"/>
diff --git a/tools/metrics/histograms/histograms.xml b/tools/metrics/histograms/histograms.xml
index 3b213578..d8fc40ec 100644
--- a/tools/metrics/histograms/histograms.xml
+++ b/tools/metrics/histograms/histograms.xml
@@ -2287,6 +2287,17 @@
   </summary>
 </histogram>
 
+<histogram name="Apps.StateTransition.AnimationSmoothness" units="%">
+  <owner>vadimt@chromium.org</owner>
+  <summary>
+    Relative smoothness of animations of peeking launcher state transitions.
+    100% represents ideally smooth 60 frames per second. 50% represents only 30
+    frames per second is achieved during the animations. 0% should not happen.
+    This metric is recorded exactly once when the user switches states of the
+    launcher.
+  </summary>
+</histogram>
+
 <histogram name="Arc.AndroidBootTime" units="ms">
   <owner>elijahtaylor@google.com</owner>
   <owner>mitsuji@google.com</owner>
@@ -7976,6 +7987,13 @@
   <summary>Maximal amount of memory allocated by decoder.</summary>
 </histogram>
 
+<histogram name="BrowserActions.SelectedOption" enum="BrowserActionsMenuOption">
+  <owner>ltian@chromium.org</owner>
+  <summary>
+    The option that the user selected from a Browser Actions context menu.
+  </summary>
+</histogram>
+
 <histogram name="BrowserDialogs.ExternalProtocol.HandleState"
     enum="HandleStateType">
   <owner>ramyasharma@chromium.org</owner>
@@ -29526,6 +29544,9 @@
     histogram is emitted to each time a condition affecting Instant Tethering's
     state, e.g. the user enabling or disabling the feature, or Bluetooth
     becoming enabled or disabled.
+
+    Note: The &quot;Screen locked&quot; bucket is obsolete, and should not have
+    any reports.
   </summary>
 </histogram>
 
@@ -32659,6 +32680,21 @@
   </summary>
 </histogram>
 
+<histogram name="Media.EME.CdmLoadErrorCode" units="code">
+  <owner>media-dev@chromium.org</owner>
+  <summary>The error code of a library CDM load failure.</summary>
+</histogram>
+
+<histogram name="Media.EME.CdmLoadResult" enum="CdmLoadResult">
+  <owner>media-dev@chromium.org</owner>
+  <summary>The result from an attempt to load a library CDM.</summary>
+</histogram>
+
+<histogram name="Media.EME.CdmLoadTime" units="ms">
+  <owner>media-dev@chromium.org</owner>
+  <summary>The time spent to load a library CDM.</summary>
+</histogram>
+
 <histogram name="Media.EME.ClearKey" enum="CdmPromiseResult">
   <owner>sandersd@chromium.org</owner>
   <summary>
@@ -35684,6 +35720,25 @@
   </summary>
 </histogram>
 
+<histogram name="Memory.Experimental.SwapThrashingLevel"
+    enum="SwapThrashingLevel">
+  <owner>sebmarchand@chromium.org</owner>
+  <summary>
+    The swap thrashing level, which is recorded periodically. This shows the
+    cumulative number of seconds that systems spend in each of the swap
+    thrashing states. Only available on Windows.
+  </summary>
+</histogram>
+
+<histogram name="Memory.Experimental.SwapThrashingLevelChanges"
+    enum="SwapThrashingLevelChanges">
+  <owner>sebmarchand@chromium.org</owner>
+  <summary>
+    The number of swap-thrashing level state changes for each possible pairwise
+    state change. Only available on Windows.
+  </summary>
+</histogram>
+
 <histogram name="Memory.Experimental.Total2.PrivateMemoryFootprint" units="MB">
   <owner>erikchen@chromium.org</owner>
   <summary>
@@ -44233,6 +44288,13 @@
   </summary>
 </histogram>
 
+<histogram name="Net.QuicSession.RetryAfterWriteErrorCount" units="retries">
+  <owner>rch@chromium.org</owner>
+  <summary>
+    The number of consecutive times a packet was retried after a write error.
+  </summary>
+</histogram>
+
 <histogram name="Net.QuicSession.RstStreamErrorCodeClient"
     enum="QuicRstStreamErrorCodes">
   <owner>rch@chromium.org</owner>
@@ -77924,6 +77986,13 @@
   <summary>The total number of accounts in the cookie jar.</summary>
 </histogram>
 
+<histogram name="Signin.DiceEnabledForProfile" enum="Boolean">
+  <owner>droger@chromium.org</owner>
+  <summary>
+    Whether Dice is enabled for the current profile, recorded at startup.
+  </summary>
+</histogram>
+
 <histogram name="Signin.DiceResponseHeader" enum="SigninDiceResponseHeader">
   <owner>droger@chromium.org</owner>
   <summary>Records Dice responses (signin and signout).</summary>
diff --git a/tools/metrics/ukm/ukm.xml b/tools/metrics/ukm/ukm.xml
index 3ac0fab..25da3e5 100644
--- a/tools/metrics/ukm/ukm.xml
+++ b/tools/metrics/ukm/ukm.xml
@@ -279,6 +279,35 @@
   </metric>
 </event>
 
+<event name="Compositor.UserInteraction">
+  <owner>khushalsagar@chromium.org</owner>
+  <summary>
+    Metrics related to user interaction handled by the compositor. This includes
+    user gestures like scrolling, pinch-zoom and page-scale animations triggered
+    in response to a double-tap event. The length of the user interaction is
+    defined as the time the compositor is running an animation resulting from
+    user input.
+  </summary>
+  <metric name="CheckerboardedContentArea">
+    <summary>
+      The number of visible pixels per frame checkerboarded during this
+      interaction.
+    </summary>
+  </metric>
+  <metric name="CheckerboardedContentAreaRatio">
+    <summary>
+      The percentage of visible pixels per frame checkerboarded during this
+      interaction. This value should be between [0, 100].
+    </summary>
+  </metric>
+  <metric name="NumMissingTiles">
+    <summary>
+      The number of visible tiles per frame checkerboarded during this
+      interaction.
+    </summary>
+  </metric>
+</event>
+
 <event name="ContextualSearch">
   <owner>donnd@chromium.org</owner>
   <summary>
diff --git a/tools/perf/BUILD.gn b/tools/perf/BUILD.gn
index 55dacdd..ae4db175 100644
--- a/tools/perf/BUILD.gn
+++ b/tools/perf/BUILD.gn
@@ -28,9 +28,6 @@
     # For image_decoding.measurement
     "//chrome/test/data/image_decoding/",
 
-    # For indexeddb_perf
-    "//chrome/test/data/indexeddb/",
-
     # For Pylib used by VR tests
     "//build/android/pylib/",
   ]
diff --git a/tools/perf/benchmark.csv b/tools/perf/benchmark.csv
index 38d37d0..31390be 100644
--- a/tools/perf/benchmark.csv
+++ b/tools/perf/benchmark.csv
@@ -1,7 +1,7 @@
 AUTOGENERATED FILE DO NOT EDIT
 See //tools/perf/generate_perf_data.py to make changes
 Benchmark name,Individual owners,Component
-angle_perftests,jmadill@chromium.org,
+angle_perftests,"jmadill@chromium.org, chrome-gpu-perf-owners@chromium.org",Internals>GPU>ANGLE
 battor.steady_state,charliea@chromium.org,
 battor.trivial_pages,charliea@chromium.org,
 blink_perf.bindings,"jbroman@chromium.org, yukishiino@chromium.org, haraken@chromium.org",
@@ -24,7 +24,7 @@
 dummy_benchmark.histogram_benchmark_1,"eakuefner@chromium.org, simonhatch@chromium.org",
 dummy_benchmark.noisy_benchmark_1,nednguyen@google.com,
 dummy_benchmark.stable_benchmark_1,nednguyen@google.com,
-gpu_perftests,reveman@chromium.org,
+gpu_perftests,"reveman@chromium.org, chrome-gpu-perf-owners@chromium.org",Internals>GPU
 jetstream,hablich@chromium.org,
 kraken,hablich@chromium.org,
 load_library_perf_tests,,
@@ -42,6 +42,7 @@
 net_perftests,xunjieli@chromium.org,
 octane,hablich@chromium.org,
 oortonline_tbmv2,ulan@chromium.org,
+passthrough_command_buffer_perftests,"piman@chromium.org, chrome-gpu-perf-owners@chromium.org",Internals>GPU>ANGLE
 performance_browser_tests,miu@chromium.org,
 power.idle_platform,"charliea@chromium.org, rnephew@chromium.org",
 power.typical_10_mobile,perezju@chromium.org,
@@ -106,4 +107,5 @@
 v8.runtime_stats.top_25,cbruni@chromium.org,
 v8.runtimestats.browsing_desktop,mythria@chromium.org,
 v8.runtimestats.browsing_mobile,mythria@chromium.org,
+validating_command_buffer_perftests,"piman@chromium.org, chrome-gpu-perf-owners@chromium.org",Internals>GPU
 webrtc,"qiangchen@chromium.org, ehmaldonado@chromium.org, phoglund@chromium.org",
diff --git a/tools/perf/benchmarks/system_health_smoke_test.py b/tools/perf/benchmarks/system_health_smoke_test.py
index 00654647..7da35e3 100644
--- a/tools/perf/benchmarks/system_health_smoke_test.py
+++ b/tools/perf/benchmarks/system_health_smoke_test.py
@@ -66,15 +66,6 @@
 
   # crbug.com/725386
   'benchmarks.system_health_smoke_test.SystemHealthBenchmarkSmokeTest.system_health.memory_desktop.browse:social:twitter', # pylint: disable=line-too-long
-
-  # crbug.com/778095
-  'benchmarks.system_health_smoke_test.SystemHealthBenchmarkSmokeTest.system_health.memory_desktop.multitab:misc:typical24',  # pylint: disable=line-too-long
-
-  # https://crbug.com/778169
-  'benchmarks.system_health_smoke_test.SystemHealthBenchmarkSmokeTest.system_health.memory_desktop.browse:news:flipboard',  # pylint: disable=line-too-long
-
-  # https://crbug.com/778169
-  'benchmarks.system_health_smoke_test.SystemHealthBenchmarkSmokeTest.system_health.memory_desktop.load:games:alphabetty',  # pylint: disable=line-too-long
 })
 
 
diff --git a/tools/perf/chrome_telemetry_build/BUILD.gn b/tools/perf/chrome_telemetry_build/BUILD.gn
index 850be94..d73a58d3 100644
--- a/tools/perf/chrome_telemetry_build/BUILD.gn
+++ b/tools/perf/chrome_telemetry_build/BUILD.gn
@@ -3,6 +3,9 @@
 # found in the LICENSE file.
 
 import("//build/config/compiler/compiler.gni")
+if (is_android) {
+  import("//build/config/android/config.gni")  # For use_unpublished_apis
+}
 
 group("telemetry_chrome_test") {
   testonly = true
diff --git a/tools/perf/chromium.perf.fyi.extras.json b/tools/perf/chromium.perf.fyi.extras.json
index af852bd..f8d35a0f 100644
--- a/tools/perf/chromium.perf.fyi.extras.json
+++ b/tools/perf/chromium.perf.fyi.extras.json
@@ -85,6 +85,7 @@
     "isolated_scripts": [
       {
         "args": [
+          "--bot", "swarm823-c4",
           "--builder", "One Buildbot Step Test Builder",
           "-v",
           "--output-format=histograms",
@@ -101,6 +102,7 @@
           "can_use_on_swarming_builders": true,
           "dimension_sets": [
             {
+              "id": "swarm823-c4",
               "pool": "Chrome-perf-fyi"
             }
           ],
@@ -108,14 +110,6 @@
           "hard_timeout": 10800,
           "ignore_task_failure": false,
           "io_timeout": 3600
-        },
-        "trigger_script": {
-          "script": "//tools/perf/perf_device_trigger.py",
-          "args": [
-            "--bot-id", "swarm823-c4",
-            "--bot-id", "swarm846-c4",
-            "--bot-id", "swarm847-c4"
-          ]
         }
       }
     ]
diff --git a/tools/perf/core/perf_data_generator.py b/tools/perf/core/perf_data_generator.py
index e59db74d..8bfddbc8 100755
--- a/tools/perf/core/perf_data_generator.py
+++ b/tools/perf/core/perf_data_generator.py
@@ -61,6 +61,14 @@
 def add_tester(waterfall, name, perf_id, platform, target_bits=64,
                num_host_shards=1, num_device_shards=1, swarming=None,
                replace_system_webview=False):
+  """ Adds tester named |name| to |waterfall|.
+
+  Tests can be added via 'perf_tests', which expects a 2 element tuple of
+  (isolate_name, shard), or via 'perf_tests_with_args', which allows you
+  to specify command line arguments for the tests. 'perf_tests_with_args'
+  expects a tuple of 4 elements: (name, shard, test_args, isolate_name).
+  'test_args' is a list of strings pass via the test's command line.
+  """
   del perf_id # this will be needed
   waterfall['testers'][name] = {
     'platform': platform,
@@ -447,7 +455,15 @@
          ('load_library_perf_tests', 'build94-m1'),
          # crbug.com/735679
          # ('performance_browser_tests', 'build94-m1'),
-         ('media_perftests', 'build95-m1')]
+         ('media_perftests', 'build95-m1')
+        ],
+        'perf_tests_with_args': [
+         ('passthrough_command_buffer_perftests', 'build94-m1',
+          ['--use-cmd-decoder=passthrough', '--use-angle=gl-null'],
+          'command_buffer_perftests'),
+         ('validating_command_buffer_perftests', 'build94-m1',
+          ['--use-cmd-decoder=validating', '--use-stub'],
+          'command_buffer_perftests')]
       }
     ])
 
@@ -697,15 +713,30 @@
   return complete_dimension
 
 
+def generate_cplusplus_isolate_script_entry(
+    dimension, name, shard, test_args, isolate_name):
+  return generate_isolate_script_entry(
+      [get_swarming_dimension(dimension, shard)], test_args, isolate_name,
+         name, ignore_task_failure=False)
+
+
 def generate_cplusplus_isolate_script_test(dimension):
   return [
-    generate_isolate_script_entry(
-        [get_swarming_dimension(dimension, shard)], [], name,
-        name, ignore_task_failure=False)
+    generate_cplusplus_isolate_script_entry(
+        dimension, name, shard, [], name)
     for name, shard in dimension['perf_tests']
   ]
 
 
+def generate_cplusplus_isolate_script_test_with_args(dimension):
+  return [
+    generate_cplusplus_isolate_script_entry(
+        dimension, name, shard, test_args, isolate_name)
+    for name, shard, test_args, isolate_name
+        in dimension['perf_tests_with_args']
+  ]
+
+
 def ShouldBenchmarksBeScheduled(
     benchmark, name, os_name, browser_name):
   # StoryExpectations uses finder_options.browser_type, platform.GetOSName,
@@ -908,6 +939,9 @@
     if config['swarming_dimensions'][0].get('perf_tests', False):
       isolated_scripts += generate_cplusplus_isolate_script_test(
         config['swarming_dimensions'][0])
+    if config['swarming_dimensions'][0].get('perf_tests_with_args', False):
+      isolated_scripts += generate_cplusplus_isolate_script_test_with_args(
+        config['swarming_dimensions'][0])
 
     isolated_scripts, devices_to_test_skipped = remove_blacklisted_device_tests(
         isolated_scripts, BLACKLISTED_DEVICES)
@@ -1001,10 +1035,20 @@
 BenchmarkMetadata = collections.namedtuple(
     'BenchmarkMetadata', 'emails component not_scheduled')
 NON_TELEMETRY_BENCHMARKS = {
-    'angle_perftests': BenchmarkMetadata('jmadill@chromium.org', None, False),
+    'angle_perftests': BenchmarkMetadata(
+        'jmadill@chromium.org, chrome-gpu-perf-owners@chromium.org',
+        'Internals>GPU>ANGLE', False),
+    'validating_command_buffer_perftests': BenchmarkMetadata(
+        'piman@chromium.org, chrome-gpu-perf-owners@chromium.org',
+        'Internals>GPU', False),
+    'passthrough_command_buffer_perftests': BenchmarkMetadata(
+        'piman@chromium.org, chrome-gpu-perf-owners@chromium.org',
+        'Internals>GPU>ANGLE', False),
     'net_perftests': BenchmarkMetadata('xunjieli@chromium.org', None, False),
     'cc_perftests': BenchmarkMetadata('enne@chromium.org', None, False),
-    'gpu_perftests': BenchmarkMetadata('reveman@chromium.org', None, False),
+    'gpu_perftests': BenchmarkMetadata(
+        'reveman@chromium.org, chrome-gpu-perf-owners@chromium.org',
+        'Internals>GPU', False),
     'tracing_perftests': BenchmarkMetadata(
         'kkraynov@chromium.org, primiano@chromium.org', None, False),
     'load_library_perf_tests': BenchmarkMetadata(None, None, False),
diff --git a/tools/perf/core/perf_data_generator_unittest.py b/tools/perf/core/perf_data_generator_unittest.py
index 8aed158..f03f6f7 100644
--- a/tools/perf/core/perf_data_generator_unittest.py
+++ b/tools/perf/core/perf_data_generator_unittest.py
@@ -344,3 +344,44 @@
     for key in keys:
       lst = getattr(perf_data_generator, key)
       self.assertEqual(sorted(lst), lst, 'please sort %s' % key)
+
+  def testGenerateCplusplusIsolateScriptTest(self):
+    dimension={
+        'gpu': '10de:104a',
+        'os': 'Windows-2008ServerR2-SP1',
+        'pool': 'Chrome-perf',
+        'device_ids': [
+          'build92-m1', 'build93-m1',
+          'build94-m1', 'build95-m1', 'build96-m1'
+        ],
+        'perf_tests': [
+          ('angle_perftests', 'build94-m1'),
+        ],
+      }
+    test = perf_data_generator.generate_cplusplus_isolate_script_test(dimension)
+    test = test[0]
+    self.assertEqual(test['name'], 'angle_perftests')
+    self.assertEqual(test['isolate_name'], 'angle_perftests')
+
+  def testGenerateCplusplusIsolateScriptTestWithArgs(self):
+    dimension={
+      'gpu': '10de:104a',
+      'os': 'Windows-2008ServerR2-SP1',
+      'pool': 'Chrome-perf',
+      'device_ids': [
+        'build92-m1', 'build93-m1',
+        'build94-m1', 'build95-m1', 'build96-m1'
+      ],
+      'perf_tests_with_args': [
+        ('passthrough_command_buffer_perftests', 'build94-m1',
+          ['--use-cmd-decoder=passthrough', '--use-angle=gl-null'],
+          'command_buffer_perftests')
+      ]
+    }
+    test = perf_data_generator.generate_cplusplus_isolate_script_test_with_args(
+              dimension)
+    test = test[0]
+    self.assertEqual(test['name'], 'passthrough_command_buffer_perftests')
+    self.assertEqual(test['isolate_name'], 'command_buffer_perftests')
+    self.assertTrue('--use-cmd-decoder=passthrough' in test['args'])
+    self.assertTrue('--use-angle=gl-null' in test['args'])
diff --git a/tools/perf/metrics/memory.py b/tools/perf/metrics/memory.py
deleted file mode 100644
index 62bb370..0000000
--- a/tools/perf/metrics/memory.py
+++ /dev/null
@@ -1,248 +0,0 @@
-# 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.
-
-import logging
-import sys
-
-from telemetry.value import histogram
-from telemetry.value import histogram_util
-from telemetry.value import scalar
-
-from metrics import Metric
-
-
-_HISTOGRAMS = [
-    {
-        'name': 'V8.MemoryExternalFragmentationTotal', 'units': 'percent',
-        'display_name': 'V8_MemoryExternalFragmentationTotal',
-        'type': histogram_util.RENDERER_HISTOGRAM,
-        'description': 'Total external memory fragmentation after each GC in '
-                       'percent.',
-    },
-    {
-        'name': 'V8.MemoryHeapSampleTotalCommitted', 'units': 'kb',
-        'display_name': 'V8_MemoryHeapSampleTotalCommitted',
-        'type': histogram_util.RENDERER_HISTOGRAM,
-        'description': 'The total size of committed memory used by V8 after '
-                       'each GC in KB.'
-    },
-    {
-        'name': 'V8.MemoryHeapSampleTotalUsed', 'units': 'kb',
-        'display_name': 'V8_MemoryHeapSampleTotalUsed',
-        'type': histogram_util.RENDERER_HISTOGRAM,
-        'description': 'The total size of live memory used by V8 after each '
-                       'GC in KB.',
-    },
-    {
-        'name': 'V8.MemoryHeapSampleMaximumCommitted', 'units': 'kb',
-        'display_name': 'V8_MemoryHeapSampleMaximumCommitted',
-        'type': histogram_util.RENDERER_HISTOGRAM
-    },
-    {
-        'name': 'Memory.RendererUsed', 'units': 'kb',
-        'display_name': 'Memory_RendererUsed',
-        'type': histogram_util.RENDERER_HISTOGRAM
-    },
-    {
-        'name': 'Memory.BrowserUsed', 'units': 'kb',
-        'display_name': 'Memory_BrowserUsed',
-        'type': histogram_util.BROWSER_HISTOGRAM
-    },
-]
-
-
-class MemoryMetric(Metric):
-  """MemoryMetric gathers memory statistics from the browser object.
-
-  This includes both per-page histogram stats, most about javascript
-  memory usage, and overall memory stats from the system for the whole
-  test run."""
-
-  def __init__(self, browser):
-    super(MemoryMetric, self).__init__()
-    self._browser = browser
-    start_memory_stats = self._browser.memory_stats
-    self._start_commit_charge = None
-    if 'SystemCommitCharge' in start_memory_stats:
-      self._start_commit_charge = start_memory_stats['SystemCommitCharge']
-    self._memory_stats = None
-    self._histogram_start = dict()
-    self._histogram_delta = dict()
-    self._started = False
-
-  @classmethod
-  def CustomizeBrowserOptions(cls, options):
-    options.AppendExtraBrowserArgs([
-        '--enable-stats-collection-bindings',
-        # For a hard-coded set of Google pages (such as GMail), we produce
-        # custom memory histograms (V8.Something_gmail) instead of the generic
-        # histograms (V8.Something), if we detect that a renderer is only
-        # rendering this page and no other pages. For this test, we need to
-        # disable histogram customizing, so that we get the same generic
-        # histograms produced for all pages.
-        '--disable-histogram-customizer'
-    ])
-
-  def Start(self, page, tab):
-    """Start the per-page preparation for this metric.
-
-    Here, this consists of recording the start value of all the histograms.
-    """
-    if not self._browser.supports_memory_metrics:
-      logging.warning('Memory metrics not supported.')
-      return
-
-    self._started = True
-
-    for h in _HISTOGRAMS:
-      histogram_data = histogram_util.GetHistogram(
-          h['type'], h['name'], tab)
-      # Histogram data may not be available
-      if not histogram_data:
-        continue
-      self._histogram_start[h['name']] = histogram_data
-
-  def Stop(self, page, tab):
-    """Prepare the results for this page.
-
-    The results are the differences between the current histogram values
-    and the values when Start() was called.
-    """
-    if not self._browser.supports_memory_metrics:
-      return
-
-    assert self._started, 'Must call Start() first'
-    for h in _HISTOGRAMS:
-      # Histogram data may not be available
-      if h['name'] not in self._histogram_start:
-        continue
-      histogram_data = histogram_util.GetHistogram(
-          h['type'], h['name'], tab)
-      self._histogram_delta[h['name']] = histogram_util.SubtractHistogram(
-          histogram_data, self._histogram_start[h['name']])
-
-  # Optional argument trace_name is not in base class Metric.
-  # pylint: disable=arguments-differ
-  def AddResults(self, tab, results, trace_name=None):
-    """Add results for this page to the results object."""
-    if not self._browser.supports_memory_metrics:
-      return
-
-    assert self._histogram_delta, 'Must call Stop() first'
-    for h in _HISTOGRAMS:
-      # Histogram data may not be available
-      if h['name'] not in self._histogram_start:
-        continue
-      results.AddValue(histogram.HistogramValue(
-          results.current_page, h['display_name'], h['units'],
-          raw_value_json=self._histogram_delta[h['name']], important=False,
-          description=h.get('description')))
-    self._memory_stats = self._browser.memory_stats
-    if not self._memory_stats['Browser']:
-      return
-    AddResultsForProcesses(results, self._memory_stats,
-                           metric_trace_name=trace_name)
-
-    if self._start_commit_charge:
-      end_commit_charge = self._memory_stats['SystemCommitCharge']
-      commit_charge_difference = end_commit_charge - self._start_commit_charge
-      results.AddValue(scalar.ScalarValue(
-          results.current_page,
-          'commit_charge.' + (trace_name or 'commit_charge'),
-          'kb', commit_charge_difference, important=False,
-          description='System commit charge (committed memory pages).'))
-    results.AddValue(scalar.ScalarValue(
-        results.current_page, 'processes.' + (trace_name or 'processes'),
-        'count', self._memory_stats['ProcessCount'], important=False,
-        description='Number of processes used by Chrome.'))
-
-
-def AddResultsForProcesses(results, memory_stats, chart_trace_name='final',
-                           metric_trace_name=None,
-                           exclude_metrics=None):
-  """Adds memory stats for browser, renderer and gpu processes.
-
-  Args:
-    results: A telemetry.results.PageTestResults object.
-    memory_stats: System memory stats collected.
-    chart_trace_name: Trace to identify memory metrics. Default is 'final'.
-    metric_trace_name: Trace to identify the metric results per test page.
-    exclude_metrics: List of memory metrics to exclude from results,
-                     e.g. VM, WorkingSetSize, etc.
-  """
-  metric = 'resident_set_size'
-  if sys.platform == 'win32':
-    metric = 'working_set'
-
-  exclude_metrics = exclude_metrics or {}
-
-  def AddResultsForProcessTypes(process_types_memory, process_type_trace):
-    """Add all results for a given set of process types.
-
-    Args:
-      process_types_memory: A list of process types, e.g. Browser, 'Renderer'.
-      process_type_trace: The name of this set of process types in the output.
-    """
-    def AddResult(value_name_memory, value_name_trace, description):
-      """Add a result for a given statistic.
-
-      Args:
-        value_name_memory: Name of some statistic, e.g. VM, WorkingSetSize.
-        value_name_trace: Name of this statistic to be used in the output.
-      """
-      if value_name_memory in exclude_metrics:
-        return
-      if len(process_types_memory) > 1 and value_name_memory.endswith('Peak'):
-        return
-      values = []
-      for process_type_memory in process_types_memory:
-        stats = memory_stats[process_type_memory]
-        if value_name_memory in stats:
-          values.append(stats[value_name_memory])
-      if values:
-        if metric_trace_name:
-          current_trace = '%s_%s' % (metric_trace_name, process_type_trace)
-          chart_name = value_name_trace
-        else:
-          current_trace = '%s_%s' % (value_name_trace, process_type_trace)
-          chart_name = current_trace
-        results.AddValue(scalar.ScalarValue(
-            results.current_page, '%s.%s' % (chart_name, current_trace), 'kb',
-            sum(values) / 1024, important=False, description=description))
-
-    AddResult('VM', 'vm_%s_size' % chart_trace_name,
-              'Virtual Memory Size (address space allocated).')
-    AddResult('WorkingSetSize', 'vm_%s_%s_size' % (metric, chart_trace_name),
-              'Working Set Size (Windows) or Resident Set Size (other '
-              'platforms).')
-    AddResult('PrivateDirty', 'vm_private_dirty_%s' % chart_trace_name,
-              'Private Dirty is basically the amount of RAM inside the '
-              'process that can not be paged to disk (it is not backed by the '
-              'same data on disk), and is not shared with any other '
-              'processes. Another way to look at this is the RAM that will '
-              'become available to the system when that process goes away '
-              '(and probably quickly subsumed into caches and other uses of '
-              'it).')
-    AddResult('ProportionalSetSize',
-              'vm_proportional_set_size_%s' % chart_trace_name,
-              'The Proportional Set Size (PSS) number is a metric the kernel '
-              'computes that takes into account memory sharing -- basically '
-              'each page of RAM in a process is scaled by a ratio of the '
-              'number of other processes also using that page. This way you '
-              'can (in theory) add up the PSS across all processes to see '
-              'the total RAM they are using, and compare PSS between '
-              'processes to get a rough idea of their relative weight.')
-    AddResult('SharedDirty', 'vm_shared_dirty_%s' % chart_trace_name,
-              'Shared Dirty is the amount of RAM outside the process that can '
-              'not be paged to disk, and is shared with other processes.')
-    AddResult('VMPeak', 'vm_peak_size',
-              'The peak Virtual Memory Size (address space allocated) usage '
-              'achieved by the * process.')
-    AddResult('WorkingSetSizePeak', '%s_peak_size' % metric,
-              'Peak Working Set Size.')
-
-  AddResultsForProcessTypes(['Browser'], 'browser')
-  AddResultsForProcessTypes(['Renderer'], 'renderer')
-  AddResultsForProcessTypes(['Gpu'], 'gpu')
-  AddResultsForProcessTypes(['Browser', 'Renderer', 'Gpu'], 'total')
diff --git a/tools/perf/metrics/system_memory.py b/tools/perf/metrics/system_memory.py
index 4637705..d9fc7e1 100644
--- a/tools/perf/metrics/system_memory.py
+++ b/tools/perf/metrics/system_memory.py
@@ -2,13 +2,14 @@
 # Use of this source code is governed by a BSD-style license that can be
 # found in the LICENSE file.
 
+import sys
+
 from telemetry.value import scalar
 
-from metrics import memory
-from metrics import Metric
+import metrics
 
 
-class SystemMemoryMetric(Metric):
+class SystemMemoryMetric(metrics.Metric):
   """SystemMemoryMetric gathers system memory statistic.
 
   This metric collects system memory stats per test.  It reports the difference
@@ -49,7 +50,7 @@
     Args:
       trace_name: Trace name to identify the summary results for current page.
       exclude_metrics: List of memory metrics to exclude from results,
-                       e.g. VM, VMPeak, etc. See AddResultsForProcesses().
+                       e.g. VM, VMPeak, etc. See _AddResultsForProcesses().
     """
     assert self._memory_stats_end, 'Must call Stop() first'
     memory_stats = _SubtractMemoryStats(self._memory_stats_end,
@@ -57,7 +58,7 @@
     if not memory_stats['Browser']:
       return
     exclude_metrics = exclude_metrics or {}
-    memory.AddResultsForProcesses(
+    _AddResultsForProcesses(
         results, memory_stats,
         metric_trace_name=trace_name, chart_trace_name='delta',
         exclude_metrics=exclude_metrics)
@@ -124,3 +125,93 @@
         else:
           memory_stats[process_type][metric] = end_value - start_value
   return memory_stats
+
+
+def _AddResultsForProcesses(results, memory_stats, chart_trace_name='final',
+                           metric_trace_name=None,
+                           exclude_metrics=None):
+  """Adds memory stats for browser, renderer and gpu processes.
+
+  Args:
+    results: A telemetry.results.PageTestResults object.
+    memory_stats: System memory stats collected.
+    chart_trace_name: Trace to identify memory metrics. Default is 'final'.
+    metric_trace_name: Trace to identify the metric results per test page.
+    exclude_metrics: List of memory metrics to exclude from results,
+                     e.g. VM, WorkingSetSize, etc.
+  """
+  metric = 'resident_set_size'
+  if sys.platform == 'win32':
+    metric = 'working_set'
+
+  exclude_metrics = exclude_metrics or {}
+
+  def AddResultsForProcessTypes(process_types_memory, process_type_trace):
+    """Add all results for a given set of process types.
+
+    Args:
+      process_types_memory: A list of process types, e.g. Browser, 'Renderer'.
+      process_type_trace: The name of this set of process types in the output.
+    """
+    def AddResult(value_name_memory, value_name_trace, description):
+      """Add a result for a given statistic.
+
+      Args:
+        value_name_memory: Name of some statistic, e.g. VM, WorkingSetSize.
+        value_name_trace: Name of this statistic to be used in the output.
+      """
+      if value_name_memory in exclude_metrics:
+        return
+      if len(process_types_memory) > 1 and value_name_memory.endswith('Peak'):
+        return
+      values = []
+      for process_type_memory in process_types_memory:
+        stats = memory_stats[process_type_memory]
+        if value_name_memory in stats:
+          values.append(stats[value_name_memory])
+      if values:
+        if metric_trace_name:
+          current_trace = '%s_%s' % (metric_trace_name, process_type_trace)
+          chart_name = value_name_trace
+        else:
+          current_trace = '%s_%s' % (value_name_trace, process_type_trace)
+          chart_name = current_trace
+        results.AddValue(scalar.ScalarValue(
+            results.current_page, '%s.%s' % (chart_name, current_trace), 'kb',
+            sum(values) / 1024, important=False, description=description))
+
+    AddResult('VM', 'vm_%s_size' % chart_trace_name,
+              'Virtual Memory Size (address space allocated).')
+    AddResult('WorkingSetSize', 'vm_%s_%s_size' % (metric, chart_trace_name),
+              'Working Set Size (Windows) or Resident Set Size (other '
+              'platforms).')
+    AddResult('PrivateDirty', 'vm_private_dirty_%s' % chart_trace_name,
+              'Private Dirty is basically the amount of RAM inside the '
+              'process that can not be paged to disk (it is not backed by the '
+              'same data on disk), and is not shared with any other '
+              'processes. Another way to look at this is the RAM that will '
+              'become available to the system when that process goes away '
+              '(and probably quickly subsumed into caches and other uses of '
+              'it).')
+    AddResult('ProportionalSetSize',
+              'vm_proportional_set_size_%s' % chart_trace_name,
+              'The Proportional Set Size (PSS) number is a metric the kernel '
+              'computes that takes into account memory sharing -- basically '
+              'each page of RAM in a process is scaled by a ratio of the '
+              'number of other processes also using that page. This way you '
+              'can (in theory) add up the PSS across all processes to see '
+              'the total RAM they are using, and compare PSS between '
+              'processes to get a rough idea of their relative weight.')
+    AddResult('SharedDirty', 'vm_shared_dirty_%s' % chart_trace_name,
+              'Shared Dirty is the amount of RAM outside the process that can '
+              'not be paged to disk, and is shared with other processes.')
+    AddResult('VMPeak', 'vm_peak_size',
+              'The peak Virtual Memory Size (address space allocated) usage '
+              'achieved by the * process.')
+    AddResult('WorkingSetSizePeak', '%s_peak_size' % metric,
+              'Peak Working Set Size.')
+
+  AddResultsForProcessTypes(['Browser'], 'browser')
+  AddResultsForProcessTypes(['Renderer'], 'renderer')
+  AddResultsForProcessTypes(['Gpu'], 'gpu')
+  AddResultsForProcessTypes(['Browser', 'Renderer', 'Gpu'], 'total')
diff --git a/tools/perf/page_sets/indexeddb_perf/endure/app-worker.js b/tools/perf/page_sets/indexeddb_perf/endure/app-worker.js
deleted file mode 100644
index d98ee3e..0000000
--- a/tools/perf/page_sets/indexeddb_perf/endure/app-worker.js
+++ /dev/null
@@ -1,224 +0,0 @@
-// Copyright 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-// This file simulates a typical background process of an offline-capable
-// authoring application. When in an "online" state it receives chunks of
-// data updates from a simulated server and stores them in a temporary IDB
-// data store. On a different timer, the chunks are drained from the
-// temporary store and combined into larger records in a permanent store.
-// When in an "offline" state, nothing else happens.
-
-function unexpectedErrorCallback(e) {
-  self.postMessage({type: 'ERROR', error: {
-    name: e.target.error.name,
-    message: e.target.error.message
-  }});
-}
-
-function unexpectedAbortCallback(e) {
-  self.postMessage({type: 'ABORT', error: {
-    name: e.target.error.name,
-    message: e.target.error.message
-  }});
-}
-
-function log(message) {
-  self.postMessage({type: 'LOG', message: message});
-}
-
-function error(message) {
-  self.postMessage({type: 'ERROR', message: message});
-}
-
-var DBNAME = 'endurance-db';
-var DBVERSION = 1;
-
-var MAX_DOC_ID = 25;
-var MAX_CHUNK_ID = 10;
-var MAX_CHUNK_SIZE = 5 * 1024;
-var SYNC_TIMEOUT = 100;
-var COMBINE_TIMEOUT = 234; // relatively prime with SYNC_TIMEOUT
-
-function randomString(len)
-{
-  var s = '';
-  while (len--)
-    s += Math.floor((Math.random() * 36)).toString(36);
-  return s;
-}
-
-var getNextChunk = (
-  function () {
-    var nextDocID = 0;
-    var nextChunkID = 0;
-
-    return function () {
-      var doc_id = nextDocID;
-      var chunk_id = nextChunkID;
-
-      nextDocID += 1;
-      if (nextDocID >= MAX_DOC_ID) {
-        nextDocID = 0;
-        nextChunkID += 1;
-        if (nextChunkID >= MAX_CHUNK_ID)
-          nextChunkID = 0;
-      }
-
-      return {
-        docid: doc_id,
-        chunkid: chunk_id,
-        timestamp: new Date(),
-        data: randomString(MAX_CHUNK_SIZE)
-      };
-    };
-  }()
-);
-
-
-self.onmessage = function (event) {
-  switch (event.data.type) {
-    case 'offline':
-      goOffline();
-      break;
-    case 'online':
-      goOnline();
-      break;
-    default:
-      throw new Error("Unexpected message: " + event.data.type);
-  }
-};
-
-
-var offline = true;
-var syncTimeoutId = 0;
-var combineTimeoutId = 0;
-
-function goOffline() {
-  if (offline)
-    return;
-  log('offline');
-  offline = true;
-  clearTimeout(syncTimeoutId);
-  syncTimeoutId = 0;
-  clearTimeout(combineTimeoutId);
-  combineTimeoutId = 0;
-}
-
-function goOnline() {
-  if (!offline)
-    return;
-  offline = false;
-  log('online');
-  syncTimeoutId = setTimeout(sync, SYNC_TIMEOUT);
-  combineTimeoutId = setTimeout(combine, COMBINE_TIMEOUT);
-  // NOTE: Not using setInterval as we need to be sure they complete.
-}
-
-var sync_count = 0;
-function sync() {
-  if (offline)
-    return;
-
-  var sync_id = ++sync_count;
-  log('sync ' + sync_id +  ' started');
-
-  var chunk = getNextChunk();
-  log('sync ' + sync_id +
-      ' adding chunk: ' + chunk.chunkid +
-      ' to doc: ' + chunk.docid);
-
-  var request = indexedDB.open(DBNAME);
-  request.onerror = unexpectedErrorCallback;
-  request.onsuccess = function () {
-    var db = request.result;
-    if (db.version !== DBVERSION) {
-      error('DB version incorrect');
-      return;
-    }
-
-    var transaction = db.transaction('sync-chunks', 'readwrite');
-    var store = transaction.objectStore('sync-chunks');
-    request = store.put(chunk);
-    transaction.onabort = unexpectedAbortCallback;
-    transaction.oncomplete = function () {
-      log('sync ' + sync_id +  ' finished');
-      db.close();
-      syncTimeoutId = setTimeout(sync, SYNC_TIMEOUT);
-    };
-  };
-}
-
-var combine_count = 0;
-function combine() {
-  if (offline)
-    return;
-
-  var combine_id = ++combine_count;
-  log('combine ' + combine_id + ' started');
-
-  var combine_chunk_count = 0;
-
-  var request = indexedDB.open(DBNAME);
-  request.onerror = unexpectedErrorCallback;
-  request.onsuccess = function () {
-    var db = request.result;
-    if (db.version !== DBVERSION) {
-      error('DB version incorrect');
-      return;
-    }
-
-    var transaction = db.transaction(['sync-chunks', 'docs'], 'readwrite');
-    var syncStore = transaction.objectStore('sync-chunks');
-    var docStore = transaction.objectStore('docs');
-
-    var cursorRequest = syncStore.openCursor();
-    cursorRequest.onerror = unexpectedErrorCallback;
-    cursorRequest.onsuccess = function () {
-      var cursor = cursorRequest.result;
-      if (cursor) {
-        combine_chunk_count += 1;
-        log('combine ' + combine_id +
-            ' processing chunk # ' + combine_chunk_count);
-
-        var key = cursor.key;
-        var chunk = cursor.value;
-        var docRequest = docStore.get(chunk.docid);
-        docRequest.onerror = unexpectedErrorCallback;
-        docRequest.onsuccess = function () {
-          var doc = docRequest.result;
-          if (!doc) {
-            doc = {
-              docid: chunk.docid,
-              chunks: []
-            };
-            log('combine # ' + combine_id +
-                ' created doc: ' + doc.docid);
-          }
-
-          log('combine # ' + combine_id +
-              ' updating doc: ' + doc.docid +
-              ' chunk: ' + chunk.chunkid);
-
-          doc.chunks[chunk.chunkid] = chunk;
-          doc.timestamp = new Date();
-          request = docStore.put(doc);
-          request.onerror = unexpectedErrorCallback;
-          cursor.delete(key);
-          cursor.continue();
-        };
-      } else {
-        // let transaction complete
-        log('combine ' + combine_id +
-            ' done, processed ' + combine_chunk_count + ' chunks');
-      }
-    };
-    transaction.onabort = unexpectedAbortCallback;
-    transaction.oncomplete = function () {
-      log('combine ' + combine_id +
-          ' finished, processed ' + combine_chunk_count + ' chunks');
-      db.close();
-      combineTimeoutId = setTimeout(combine, COMBINE_TIMEOUT);
-    };
-  };
-}
diff --git a/tools/perf/page_sets/indexeddb_perf/endure/app.html b/tools/perf/page_sets/indexeddb_perf/endure/app.html
deleted file mode 100644
index 19a5b13d..0000000
--- a/tools/perf/page_sets/indexeddb_perf/endure/app.html
+++ /dev/null
@@ -1,21 +0,0 @@
-<!DOCTYPE html>
-<title>IndexedDB Offline</title>
-<p>This test models the typical design of an offline-aware authoring
-  application:
-<ul>
-<li>When "offline", a series of (fake) user events are logged into a
-  store
-<li>When "online", the events are played back to a (fake) server,
-  draining the store
-<li>When "online" a Worker synchronizes data from a (fake) remote
-  source into a store in chunks, then consolidates it into another
-  store
-</ul>
-
-<div id="status"></div>
-
-<button disabled="true" id="offline">Go Offline</button>
-<button disabled="true" id="online">Go Online</button>
-<div id="state"></div>
-
-<script src="app.js?cachebust"></script>
diff --git a/tools/perf/page_sets/indexeddb_perf/endure/app.js b/tools/perf/page_sets/indexeddb_perf/endure/app.js
deleted file mode 100644
index 6e0d5bc..0000000
--- a/tools/perf/page_sets/indexeddb_perf/endure/app.js
+++ /dev/null
@@ -1,274 +0,0 @@
-// Copyright 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-// This file simulates a typical foreground process of an offline-capable
-// authoring application. When in an "offline" state, simulated user actions
-// are recorded for later playback in an IDB data store. When in an "online"
-// state, the recorded actions are drained from the store (as if being sent
-// to the server).
-
-var $ = function(s) {
-  return document.querySelector(s);
-};
-
-function status(message) {
-  var elem = $('#status');
-  while (elem.firstChild)
-    elem.removeChild(elem.firstChild);
-  elem.appendChild(document.createTextNode(message));
-}
-
-function log(message) {
-  status(message);
-}
-
-function error(message) {
-  status(message);
-  console.error(message);
-}
-
-function unexpectedErrorCallback(e) {
-  error("Unexpected error callback: (" + e.target.error.name + ") " +
-        e.target.error.message);
-}
-
-function unexpectedAbortCallback(e) {
-  error("Unexpected abort callback: (" + e.target.error.name + ") " +
-        e.target.error.message);
-}
-
-function unexpectedBlockedCallback(e) {
-  error("Unexpected blocked callback!");
-}
-
-var DBNAME = 'endurance-db';
-var DBVERSION = 1;
-var MAX_DOC_ID = 25;
-
-var db;
-
-function initdb() {
-  var request = indexedDB.deleteDatabase(DBNAME);
-  request.onerror = unexpectedErrorCallback;
-  request.onblocked = unexpectedBlockedCallback;
-  request.onsuccess = function () {
-    request = indexedDB.open(DBNAME, DBVERSION);
-    request.onerror = unexpectedErrorCallback;
-    request.onblocked = unexpectedBlockedCallback;
-    request.onupgradeneeded = function () {
-      db = request.result;
-      request.transaction.onabort = unexpectedAbortCallback;
-
-      var syncStore = db.createObjectStore(
-        'sync-chunks', {keyPath: 'sequence', autoIncrement: true});
-      syncStore.createIndex('doc-index', 'docid');
-
-      var docStore = db.createObjectStore(
-        'docs', {keyPath: 'docid'});
-      docStore.createIndex(
-        'owner-index', 'owner', {multiEntry: true});
-
-      var userEventStore = db.createObjectStore(
-        'user-events', {keyPath: 'sequence', autoIncrement: true});
-      userEventStore.createIndex('doc-index', 'docid');
-    };
-    request.onsuccess = function () {
-      log('initialized');
-      $('#offline').disabled = true;
-      $('#online').disabled = false;
-    };
-  };
-}
-
-var offline = true;
-var worker = new Worker('app-worker.js?cachebust');
-worker.onmessage = function (event) {
-  var data = event.data;
-  switch (data.type) {
-    case 'ABORT':
-      unexpectedAbortCallback({target: {error: data.error}});
-      break;
-    case 'ERROR':
-      unexpectedErrorCallback({target: {error: data.error}});
-      break;
-    case 'BLOCKED':
-      unexpectedBlockedCallback({target: {error: data.error}});
-      break;
-    case 'LOG':
-      log('WORKER: ' + data.message);
-      break;
-    case 'ERROR':
-      error('WORKER: ' + data.message);
-      break;
-    }
-};
-worker.onerror = function (event) {
-  error("Error in: " + event.filename + "(" + event.lineno + "): " +
-        event.message);
-};
-
-$('#offline').addEventListener('click', goOffline);
-$('#online').addEventListener('click', goOnline);
-
-var EVENT_INTERVAL = 100;
-var eventIntervalId = 0;
-
-function goOffline() {
-  if (offline)
-    return;
-  offline = true;
-  $('#offline').disabled = offline;
-  $('#online').disabled = !offline;
-  $('#state').innerHTML = 'offline';
-  log('offline');
-
-  worker.postMessage({type: 'offline'});
-
-  eventIntervalId = setInterval(recordEvent, EVENT_INTERVAL);
-}
-
-function goOnline() {
-  if (!offline)
-    return;
-  offline = false;
-  $('#offline').disabled = offline;
-  $('#online').disabled = !offline;
-  $('#state').innerHTML = 'online';
-  log('online');
-
-  worker.postMessage({type: 'online'});
-
-  setTimeout(playbackEvents, 100);
-  clearInterval(eventIntervalId);
-  eventIntervalId = 0;
-};
-
-function recordEvent() {
-  if (!db) {
-    error("Database not initialized");
-    return;
-  }
-
-  var transaction = db.transaction(['user-events'], 'readwrite');
-  var store = transaction.objectStore('user-events');
-  var record = {
-    // 'sequence' key will be generated
-    docid: Math.floor(Math.random() * MAX_DOC_ID),
-    timestamp: new Date(),
-    data: randomString(256)
-  };
-
-  log('putting user event');
-  var request = store.put(record);
-  request.onerror = unexpectedErrorCallback;
-  transaction.onabort = unexpectedAbortCallback;
-  transaction.oncomplete = function () {
-    log('put user event');
-  };
-}
-
-function sendEvent(record, callback) {
-  setTimeout(
-    function () {
-      if (offline)
-        callback(false);
-      else {
-        var serialization = JSON.stringify(record);
-        callback(true);
-      }
-    },
-    Math.random() * 200); // Simulate network jitter
-}
-
-var PLAYBACK_NONE = 0;
-var PLAYBACK_SUCCESS = 1;
-var PLAYBACK_FAILURE = 2;
-
-function playbackEvent(callback) {
-  log('playbackEvent');
-  var result = false;
-  var transaction = db.transaction(['user-events'], 'readonly');
-  transaction.onabort = unexpectedAbortCallback;
-  var store = transaction.objectStore('user-events');
-  var cursorRequest = store.openCursor();
-  cursorRequest.onerror = unexpectedErrorCallback;
-  cursorRequest.onsuccess = function () {
-    var cursor = cursorRequest.result;
-    if (cursor) {
-      var record = cursor.value;
-      var key = cursor.key;
-      // NOTE: sendEvent is asynchronous so transaction should finish
-      sendEvent(
-        record,
-        function (success) {
-          if (success) {
-            // Use another transaction to delete event
-            var transaction = db.transaction(['user-events'], 'readwrite');
-            transaction.onabort = unexpectedAbortCallback;
-            var store = transaction.objectStore('user-events');
-            var deleteRequest = store.delete(key);
-            deleteRequest.onerror = unexpectedErrorCallback;
-            transaction.oncomplete = function () {
-              // successfully sent and deleted event
-              callback(PLAYBACK_SUCCESS);
-            };
-          } else {
-            // No progress made
-            callback(PLAYBACK_FAILURE);
-          }
-        });
-    } else {
-      callback(PLAYBACK_NONE);
-    }
-  };
-}
-
-var playback = false;
-
-function playbackEvents() {
-  log('playbackEvents');
-  if (!db) {
-    error("Database not initialized");
-    return;
-  }
-
-  if (playback)
-    return;
-
-  playback = true;
-  log("Playing back events");
-
-  function nextEvent() {
-    playbackEvent(
-      function (result) {
-        switch (result) {
-          case PLAYBACK_NONE:
-            playback = false;
-            log("Done playing back events");
-            return;
-          case PLAYBACK_SUCCESS:
-            setTimeout(nextEvent, 0);
-            return;
-          case PLAYBACK_FAILURE:
-            playback = false;
-            log("Failure during playback (dropped offline?)");
-            return;
-        }
-      });
-  }
-
-  nextEvent();
-}
-
-function randomString(len) {
-  var s = '';
-  while (len--)
-    s += Math.floor((Math.random() * 36)).toString(36);
-  return s;
-}
-
-window.onload = function () {
-  log("initializing...");
-  initdb();
-};
diff --git a/tools/perf/page_sets/indexeddb_perf/perf_shared.js b/tools/perf/page_sets/indexeddb_perf/perf_shared.js
deleted file mode 100644
index 7536e92..0000000
--- a/tools/perf/page_sets/indexeddb_perf/perf_shared.js
+++ /dev/null
@@ -1,435 +0,0 @@
-// Copyright 2012 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.
-
-var automation = {
-  results: {}
-};
-
-automation.setDone = function() {
-  this.setStatus("Test complete.");
-  document.cookie = '__done=1; path=/';
-};
-
-automation.addResult = function(name, result) {
-  result = "" + result;
-  this.results[name] = result;
-  var elt = document.getElementById('results');
-  var div = document.createElement('div');
-  div.textContent = name + ": " + result;
-  elt.appendChild(div);
-};
-
-automation.getResults = function() {
-  return this.results;
-};
-
-automation.setStatus = function(s) {
-  document.getElementById('status').textContent = s;
-};
-
-function assert(t) {
-  if (!t) {
-    var e = new Error("Assertion failed!");
-    console.log(e.stack);
-    throw e;
-  }
-}
-
-function onError(e) {
-  var s = "Caught error.";
-  if (e.target && e.target.error)
-    s += "\n" + e.target.error.name + "\n" + e.target.error.message;
-  console.log(s);
-  automation.setStatus(s);
-  e.stopPropagation();
-  throw new Error(e);
-}
-
-var baseVersion = 2;  // The version with our object stores.
-var curVersion;
-
-// Valid options fields:
-//  indexName: the name of an index to create on each object store
-//  indexKeyPath: the key path for that index
-//  indexIsUnique: the "unique" option for IDBIndexParameters
-//  indexIsMultiEntry: the "multiEntry" option for IDBIndexParameters
-//
-function createDatabase(
-    name, objectStoreNames, handler, errorHandler, optionSets) {
-  var openRequest = indexedDB.open(name, baseVersion);
-  openRequest.onblocked = errorHandler;
-  openRequest.onerror = errorHandler;
-  function createObjectStores(db) {
-    for (var store in objectStoreNames) {
-      var name = objectStoreNames[store];
-      assert(!db.objectStoreNames.contains(name));
-      var os = db.createObjectStore(name);
-      if (optionSets) {
-        for (o in optionSets) {
-          var options = optionSets[o];
-          assert(options.indexName);
-          assert('indexKeyPath' in options);
-          os.createIndex(options.indexName, options.indexKeyPath,
-              { unique: options.indexIsUnique,
-                multiEntry: options.indexIsMultiEntry });
-        }
-      }
-    }
-  }
-  openRequest.onupgradeneeded = function(ev) {
-    // This is the spec-compliant path, which doesn't yet run in Chrome, but
-    // works in Firefox.
-    assert(openRequest == ev.target);
-    var db = openRequest.result;
-    db.onerror = errorHandler;
-    createObjectStores(db);
-    // onsuccess will get called after this exits.
-  };
-  openRequest.onsuccess = function(ev) {
-    assert(openRequest == ev.target);
-    var db = openRequest.result;
-    curVersion = db.version;
-    db.onerror = function(ev) {
-      console.log("db error", arguments, openRequest.error.message);
-      errorHandler(ev);
-    };
-    if (curVersion != baseVersion) {
-      // This is the legacy path, which runs only in Chrome.
-      var setVersionRequest = db.setVersion(baseVersion);
-      setVersionRequest.onerror = errorHandler;
-      setVersionRequest.onsuccess = function(e) {
-        assert(setVersionRequest == e.target);
-        createObjectStores(db);
-        var versionTransaction = setVersionRequest.result;
-        versionTransaction.oncomplete = function() { handler(db); };
-        versionTransaction.onerror = onError;
-      };
-    } else {
-      handler(db);
-    }
-  };
-}
-
-// You must close all database connections before calling this.
-function alterObjectStores(
-    name, objectStoreNames, func, handler, errorHandler) {
-  var version = curVersion + 1;
-  var openRequest = indexedDB.open(name, version);
-  openRequest.onblocked = errorHandler;
-  openRequest.onupgradeneeded = function(ev) {
-    doAlteration(ev.target.transaction);
-    // onsuccess will get called after this exits.
-  };
-  openRequest.onsuccess = function(ev) {
-    assert(openRequest == ev.target);
-    var db = openRequest.result;
-    db.onerror = function(ev) {
-      console.log("error altering db", arguments,
-          openRequest.error.message);
-      errorHandler();
-    };
-    if (db.version != version) {
-      // This is the legacy path, which runs only in Chrome before M23.
-      var setVersionRequest = db.setVersion(version);
-      setVersionRequest.onerror = errorHandler;
-      setVersionRequest.onsuccess =
-          function(e) {
-            curVersion = db.version;
-            assert(setVersionRequest == e.target);
-            var versionTransaction = setVersionRequest.result;
-            versionTransaction.oncomplete = function() { handler(db); };
-            versionTransaction.onerror = onError;
-            doAlteration(versionTransaction);
-          };
-    } else {
-      handler(db);
-    }
-  };
-  function doAlteration(target) {
-    for (var store in objectStoreNames) {
-      func(target.objectStore(objectStoreNames[store]));
-    }
-  }
-}
-
-function getTransaction(db, objectStoreNames, mode, opt_handler) {
-  var transaction = db.transaction(objectStoreNames, mode);
-  transaction.onerror = onError;
-  transaction.onabort = onError;
-  if (opt_handler) {
-    transaction.oncomplete = opt_handler;
-  }
-  return transaction;
-}
-
-function deleteDatabase(name, opt_handler) {
-  var deleteRequest = indexedDB.deleteDatabase(name);
-  deleteRequest.onerror = onError;
-  deleteRequest.onblocked = onError;
-  if (opt_handler) {
-    deleteRequest.onsuccess = opt_handler;
-  }
-}
-
-function getCompletionFunc(db, testName, startTime, onTestComplete) {
-  function onDeleted() {
-    automation.setStatus("Deleted database.");
-    onTestComplete();
-  }
-  return function() {
-    var duration = window.performance.now() - startTime;
-    // Ignore the cleanup time for this test.
-    automation.addResult(testName, duration);
-    automation.setStatus("Deleting database.");
-    db.close();
-    deleteDatabase(testName, onDeleted);
-  };
-}
-
-function getDisplayName(args) {
-  function functionName(f) {
-    // Function.prototype.name is nonstandard, and not implemented in IE10-
-    return f.name || f.toString().match(/^function\s*([^(\s]*)/)[1];
-  }
-  // The last arg is the completion callback the test runner tacks on.
-  // TODO(ericu): Make test errors delete the database automatically.
-  return functionName(getDisplayName.caller) + (args.length > 1 ? "_" : "") +
-      Array.prototype.slice.call(args, 0, args.length - 1).join("_");
-}
-
-// Pad a string [or object convertible to a string] to a fixed width; use this
-// to have numeric strings sort properly.
-function padToWidth(s, width) {
-  s = String(s);
-  assert(s.length <= width);
-  if (s.length < width) {
-    s = stringOfLength(width - s.length, '0') + s;
-  }
-  return s;
-}
-
-function stringOfLength(n, c) {
-  if (c == null)
-    c = 'X';
-  assert(n > 0);
-  assert(n == Math.floor(n));
-  return new Array(n + 1).join(c);
-}
-
-function getSimpleKey(i) {
-  return "key " + padToWidth(i, 10);
-}
-
-function getSimpleValue(i) {
-  return "value " + padToWidth(i, 10);
-}
-
-function getIndexableValue(i) {
-  return { id: getSimpleValue(i) };
-}
-
-function getForwardIndexKey(i) {
-  return i;
-}
-
-function getBackwardIndexKey(i) {
-  return -i;
-}
-
-// This is useful for indexing by keypath; the two names should be ordered in
-// opposite directions for all i in uint32 range.
-function getObjectValue(i) {
-  return {
-    firstName: getForwardIndexKey(i),
-    lastName: getBackwardIndexKey(i)
-  };
-}
-
-function getNFieldName(k) {
-  return "field" + k;
-}
-
-function getNFieldObjectValue(i, n) {
-  assert(Math.floor(n) == n);
-  assert(n > 0);
-  var o = {};
-  for (; n > 0; --n) {
-    // The value varies per field, each object will tend to be unique,
-    // and thanks to the modulus, indexing on different fields will give you
-    // different ordering for large-enough data sets.
-    o[getNFieldName(n - 1)] = Math.pow(i + 0.5, n + 0.5) % 65536;
-  }
-  return o;
-}
-
-function putLinearValues(
-    transaction, objectStoreNames, numKeys, getKey, getValue) {
-  if (!getKey)
-    getKey = getSimpleKey;
-  if (!getValue)
-    getValue = getSimpleValue;
-  for (var i in objectStoreNames) {
-    var os = transaction.objectStore(objectStoreNames[i]);
-    for (var j = 0; j < numKeys; ++j) {
-      var request = os.put(getValue(j), getKey(j));
-      request.onerror = onError;
-    }
-  }
-}
-
-function verifyResultNonNull(result) {
-  assert(result != null);
-}
-
-function getRandomValues(
-    transaction, objectStoreNames, numReads, numKeys, indexName, getKey) {
-  if (!getKey)
-    getKey = getSimpleKey;
-  for (var i in objectStoreNames) {
-    var os = transaction.objectStore(objectStoreNames[i]);
-    var source = os;
-    if (indexName)
-      source = source.index(indexName);
-    for (var j = 0; j < numReads; ++j) {
-      var rand = Math.floor(random() * numKeys);
-      var request = source.get(getKey(rand));
-      request.onerror = onError;
-      request.onsuccess = verifyResultNonNull;
-    }
-  }
-}
-
-function putRandomValues(
-    transaction, objectStoreNames, numPuts, numKeys, getKey, getValue) {
-  if (!getKey)
-    getKey = getSimpleKey;
-  if (!getValue)
-    getValue = getSimpleValue;
-  for (var i in objectStoreNames) {
-    var os = transaction.objectStore(objectStoreNames[i]);
-    for (var j = 0; j < numPuts; ++j) {
-      var rand = Math.floor(random() * numKeys);
-      var request = os.put(getValue(rand), getKey(rand));
-      request.onerror = onError;
-    }
-  }
-}
-
-function getSpecificValues(transaction, objectStoreNames, indexName, keys) {
-  for (var i in objectStoreNames) {
-    var os = transaction.objectStore(objectStoreNames[i]);
-    var source = os;
-    if (indexName)
-      source = source.index(indexName);
-    for (var j = 0; j < keys.length; ++j) {
-      var request = source.get(keys[j]);
-      request.onerror = onError;
-      request.onsuccess = verifyResultNonNull;
-    }
-  }
-}
-
-// getKey should be deterministic, as we assume that a cursor that starts at
-// getKey(X) and runs through getKey(X + K) has exactly K values available.
-// This is annoying to guarantee generally when using an index, so we avoid both
-// ends of the key space just in case and use simple indices.
-// TODO(ericu): Figure out if this can be simplified and we can remove uses of
-// getObjectValue in favor of getNFieldObjectValue.
-function getValuesFromCursor(
-    transaction, inputObjectStoreName, numReads, numKeys, indexName, getKey,
-    readKeysOnly, outputObjectStoreName) {
-  assert(2 * numReads < numKeys);
-  if (!getKey)
-    getKey = getSimpleKey;
-  var rand = Math.floor(random() * (numKeys - 2 * numReads)) + numReads;
-  var values = [];
-  var queryObject = transaction.objectStore(inputObjectStoreName);
-  assert(queryObject);
-  if (indexName)
-    queryObject = queryObject.index(indexName);
-  var keyRange = IDBKeyRange.bound(
-      getKey(rand), getKey(rand + numReads), false, true);
-  var request;
-  if (readKeysOnly) {
-    request = queryObject.openKeyCursor(keyRange);
-  } else {
-    request = queryObject.openCursor(keyRange);
-  }
-  var oos;
-  if (outputObjectStoreName)
-    oos = transaction.objectStore(outputObjectStoreName);
-  var numReadsLeft = numReads;
-  request.onsuccess = function(event) {
-    var cursor = event.target.result;
-    if (cursor) {
-      assert(numReadsLeft);
-      --numReadsLeft;
-      if (oos)
-        // Put in random order for maximum difficulty.  We add in numKeys just
-        // in case we're writing back to the same store; this way we won't
-        // affect the number of keys available to the cursor, since we're always
-        // outside its range.
-        oos.put(cursor.value, numKeys + random());
-      values.push({key: cursor.key, value: cursor.value});
-      cursor.continue();
-    } else {
-      assert(!numReadsLeft);
-    }
-  };
-  request.onerror = onError;
-}
-
-function runTransactionBatch(db, count, batchFunc, objectStoreNames, mode,
-    onComplete) {
-  var numTransactionsRunning = 0;
-
-  runOneBatch(db);
-
-  function runOneBatch(db) {
-    if (count <= 0) {
-      return;
-    }
-    --count;
-    ++numTransactionsRunning;
-    var transaction = getTransaction(db, objectStoreNames, mode,
-        function() {
-          assert(!--numTransactionsRunning);
-          if (count <= 0) {
-            onComplete();
-          } else {
-            runOneBatch(db);
-          }
-        });
-
-    batchFunc(transaction);
-  }
-}
-
-// Use random() instead of Math.random() so runs are repeatable.
-var random = (function(seed) {
-
-  // Implementation of: http://www.burtleburtle.net/bob/rand/smallprng.html
-  function uint32(x) { return x >>> 0; }
-  function rot(x, k) { return (x << k) | (x >> (32 - k)); }
-
-  function SmallPRNG(seed) {
-    seed = uint32(seed);
-    this.a = 0xf1ea5eed;
-    this.b = this.c = this.d = seed;
-    for (var i = 0; i < 20; ++i)
-      this.ranval();
-  }
-
-  SmallPRNG.prototype.ranval = function() {
-    var e = uint32(this.a - rot(this.b, 27));
-    this.a = this.b ^ rot(this.c, 17);
-    this.b = uint32(this.c + this.d);
-    this.c = uint32(this.d + e);
-    this.d = uint32(e + this.a);
-    return this.d;
-  };
-
-  var prng = new SmallPRNG(seed);
-  return function() { return prng.ranval() / 0x100000000; };
-}(0));
diff --git a/tools/perf/page_sets/indexeddb_perf/perf_test.html b/tools/perf/page_sets/indexeddb_perf/perf_test.html
deleted file mode 100644
index c368ced..0000000
--- a/tools/perf/page_sets/indexeddb_perf/perf_test.html
+++ /dev/null
@@ -1,14 +0,0 @@
-<!DOCTYPE html>
-<html>
-  <head>
-    <title>IndexedDB perf test first try</title>
-    <meta charset="UTF-8">
-    <script type="text/javascript" src="perf_shared.js"></script>
-    <script type="text/javascript" src="perf_test.js"></script>
-  </head>
-  <body>
-    <div id="status">Starting...</div>
-    <div id="results"></div>
-  </body>
-</html>
-
diff --git a/tools/perf/page_sets/indexeddb_perf/perf_test.js b/tools/perf/page_sets/indexeddb_perf/perf_test.js
deleted file mode 100644
index 2569a5c..0000000
--- a/tools/perf/page_sets/indexeddb_perf/perf_test.js
+++ /dev/null
@@ -1,723 +0,0 @@
-// Copyright 2012 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.
-
-var overallTestStartTime = window.performance.now();
-var kUseIndex = true;
-var kDontUseIndex = false;
-var kReadKeysOnly = true;
-var kReadDataToo = false;
-var kWriteToo = true;
-var kDontWrite = false;
-var kWriteSameStore = true;
-var kWriteDifferentStore = false;
-var kPlaceholderArg = false;
-var kDontRead = false;
-var kAlternateWithReads = true;
-
-var tests = [
-// Create 30 databases, populate them with 20 object stores with 10 items
-// each, and then open them 60 times.  Each item is 100 bytes long.
-  [testCreateAndDeleteDatabases, 30, 60, 10, 20, 100],
-// Create a single small item in a single object store, then delete everything.
-  [testCreateAndDeleteDatabase,  1,    1,    1],
-// Create many small items in a single object store, then delete everything.
-  [testCreateAndDeleteDatabase,  1000,  1,    1],
-// Create a single small item in many object stores, then delete everything.
-  [testCreateAndDeleteDatabase,  1,    1000,  1],
-// Create many large items in a single object store, then delete everything.
-  [testCreateAndDeleteDatabase,  1000,    1,  10000],
-// Create a single small item in a single object store.
-  [testCreateKeysInStores, 1,     1,    1],
-// Create many small items in a single object store.
-  [testCreateKeysInStores, 1000,   1,    1],
-// Create a single small item in many object stores.
-  [testCreateKeysInStores, 1,     1000,  1],
-// Create many large items in a single object store.
-  [testCreateKeysInStores, 1000,   1,    10000],
-
-// Read one item per transaction.
-  [testRandomReadsAndWritesWithoutIndex, 1000, 1, 0, 1000],
-// Read a few random items in each of many transactions.
-  [testRandomReadsAndWritesWithoutIndex, 1000,  5,    0,  100],
-// Read many random items in each of a few transactions.
-  [testRandomReadsAndWritesWithoutIndex, 1000,  500,   0,  5],
-// Read many random items in each of a few transactions, in a large store.
-  [testRandomReadsAndWritesWithoutIndex, 10000,  500,   0,  5],
-// Read and write a few random items in each of many transactions.
-  [testRandomReadsAndWritesWithoutIndex, 1000,  5,    5,  50],
-
-// Read one item per transaction.
-  [testRandomReadsAndWritesWithIndex, 1000, 1, 0, 1000],
-// Read a few random items from an index, in each of many transactions.
-  [testRandomReadsAndWritesWithIndex, 1000,  5,    0,  100],
-// Read many random items from an index, in each of a few transactions.
-  [testRandomReadsAndWritesWithIndex, 1000,  500,   0,  5],
-// Read many random items from an index, in each of a few transactions, in a
-// large store.
-  [testRandomReadsAndWritesWithIndex, 10000,  500,   0,  5],
-// Read and write a few random items, reading from an index, in each of many
-// transactions.
-  [testRandomReadsAndWritesWithIndex, 1000,  5,    5,  50],
-
-// Read a long, contiguous sequence of an object store via a cursor.
-  [testCursorReadsAndRandomWrites, kReadDataToo, kDontUseIndex, kDontWrite,
-   kPlaceholderArg],
-// Read a sequence of an object store via a cursor, writing
-// transformed values into another.
-  [testCursorReadsAndRandomWrites, kReadDataToo, kDontUseIndex, kWriteToo,
-   kWriteDifferentStore],
-// Read a sequence of an object store via a cursor, writing
-// transformed values into another.
-  [testCursorReadsAndRandomWrites, kReadDataToo, kDontUseIndex, kWriteToo,
-   kWriteSameStore],
-// Read a sequence of an index into an object store via a cursor.
-  [testCursorReadsAndRandomWrites, kReadDataToo, kUseIndex, kDontWrite,
-   kPlaceholderArg],
-// Read a sequence of an index into an object store via a key cursor.
-  [testCursorReadsAndRandomWrites, kReadKeysOnly, kUseIndex, kDontWrite,
-   kPlaceholderArg],
-
-// Make a small bunch of batches of reads of the same keys from an object store.
-  [testReadCacheWithoutIndex, 10],
-// Make a bunch of batches of reads of the same keys from an object store.
-  [testReadCacheWithoutIndex, 50],
-// Make a small bunch of batches of reads of the same keys from an object store.
-  [testReadCacheWithIndex, 10],
-// Make a bunch of batches of reads of the same keys from an index.
-  [testReadCacheWithIndex, 50],
-
-// Create and delete an index on a store that already contains data [produces
-// a timing result for each of creation and deletion].
-  [testCreateAndDeleteIndex, 5000],
-// Walk through multiple cursors into the same object store, round-robin, until
-// you've reached the end of each of them.
-  [testWalkingMultipleCursors, 5],
-// Walk through many cursors into the same object store, round-robin, until
-// you've reached the end of each of them.
-  [testWalkingMultipleCursors, 50],
-// Open an object store cursor, then continue(key) to the last value.
-  [testCursorSeeksWithoutIndex, 2000, 10, 4],
-// Open an index key cursor, then continue(key) to the last value.
-  [testCursorSeeksWithIndex, 2000, 10, 4],
-];
-
-
-function testRandomReadsAndWritesWithIndex(
-    numKeys, numReadsPerTransaction, numWritesPerTransaction,
-    numTransactions, onTestComplete) {
-  testRandomReadsAndWrites(numKeys, numReadsPerTransaction,
-                           numWritesPerTransaction,
-                           numTransactions, true, onTestComplete);
-}
-
-function testRandomReadsAndWritesWithoutIndex(
-    numKeys, numReadsPerTransaction, numWritesPerTransaction,
-    numTransactions, onTestComplete) {
-  testRandomReadsAndWrites(numKeys, numReadsPerTransaction,
-                           numWritesPerTransaction,
-                           numTransactions, false, onTestComplete);
-}
-
-
-function testReadCacheWithIndex(numTransactions, onTestComplete) {
-  testReadCache(numTransactions, true, onTestComplete);
-}
-
-function testReadCacheWithoutIndex(numTransactions, onTestComplete) {
-  testReadCache(numTransactions, false, onTestComplete)
-}
-
-function testCursorSeeksWithIndex(numKeys, numSeeksPerTransaction,
-    numTransactions, onTestComplete) {
-  testCursorSeeks(numKeys, numSeeksPerTransaction, numTransactions,
-                  true, onTestComplete);
-}
-
-function testCursorSeeksWithoutIndex(numKeys, numSeeksPerTransaction,
-    numTransactions, onTestComplete) {
-  testCursorSeeks(numKeys, numSeeksPerTransaction, numTransactions,
-                  false, onTestComplete);
-}
-
-
-
-var currentTest = 0;
-var testFilter;
-var done = false;
-
-function test() {
-  done = false;
-  runNextTest();
-}
-
-
-function runNextTest() {
-  var running_test, f;
-  while (currentTest < tests.length) {
-    running_test = tests[currentTest];
-    f = running_test.shift();
-    if (!testFilter || f.name == testFilter)
-      break;
-    ++currentTest;
-  }
-
-  if (currentTest < tests.length) {
-    running_test.push(runNextTest);
-    f.apply(null, running_test);
-    ++currentTest;
-  } else {
-    onAllTestsComplete();
-  }
-}
-
-function onAllTestsComplete() {
-  var overallDuration = window.performance.now() - overallTestStartTime;
-  automation.addResult("OverallTestDuration", overallDuration);
-  automation.setDone();
-  done = true;
-}
-
-function testCreateAndDeleteDatabases(
-    numDatabases, numOpens, numKeys, numStores,
-    payloadLength, onTestComplete) {
-  var testName = getDisplayName(arguments);
-  assert(numOpens >= 1);
-  assert(numKeys >= 0);
-  assert(numStores >= 1);
-  var objectStoreNames = [];
-  for (var i=0; i < numStores; ++i) {
-    objectStoreNames.push("store " + i);
-  }
-  var value = stringOfLength(payloadLength);
-  function getValue() {
-    return value;
-  }
-
-  automation.setStatus("Creating databases.");
-  var startTime = window.performance.now();
-
-  var numCreated = 0;
-  for (var i = 0; i < numDatabases; i++) {
-    createDatabase(testName + i, objectStoreNames, onCreated, onError);
-  }
-
-  function onCreated(db) {
-    automation.setStatus("Constructing transactions.");
-    var transaction =
-        getTransaction(db, objectStoreNames, "readwrite",
-            function() { openLoop(db, numOpens); });
-    putLinearValues(transaction, objectStoreNames, numKeys, null, getValue);
-  }
-
-  function openLoop(db, timesLeft) {
-    db.close();
-    if (timesLeft == 0) {
-      deleteDatabase(db.name, onDeleted);
-      return;
-    }
-    createDatabase(db.name, objectStoreNames,
-        function(db) { openLoop(db, timesLeft - 1); }, onError)
-  }
-
-  var numDeleted = 0;
-  function onDeleted() {
-    var duration = window.performance.now() - startTime;
-    automation.addResult(testName, duration);
-    automation.setStatus("Deleted database.");
-    if (++numDeleted == numDatabases) {
-      onTestComplete();
-    }
-  }
-}
-
-function testCreateKeysInStores(
-    numKeys, numStores, payloadLength, onTestComplete) {
-  var testName = getDisplayName(arguments);
-  assert(numKeys >= 0);
-  assert(numStores >= 1);
-  var objectStoreNames = [];
-  for (var i=0; i < numStores; ++i) {
-    objectStoreNames.push("store " + i);
-  }
-  var value = stringOfLength(payloadLength);
-  function getValue() {
-    return value;
-  }
-
-  automation.setStatus("Creating database.");
-  createDatabase(testName, objectStoreNames, onCreated, onError);
-
-  function onCreated(db) {
-    automation.setStatus("Constructing transaction.");
-    var completionFunc =
-        getCompletionFunc(db, testName, window.performance.now(),
-            onTestComplete);
-    var transaction =
-        getTransaction(db, objectStoreNames, "readwrite", completionFunc);
-    putLinearValues(transaction, objectStoreNames, numKeys, null, getValue);
-  }
-}
-
-// This is the only test that includes database creation and deletion in its
-// results; the others just test specific operations.  To see only the
-// creation/deletion without the specific operations used to build up the data
-// in the object stores here, subtract off the results of
-// testCreateKeysInStores.
-function testCreateAndDeleteDatabase(
-    numKeys, numStores, payloadLength, onTestComplete) {
-  var testName = getDisplayName(arguments);
-  assert(numKeys >= 0);
-  assert(numStores >= 1);
-  var objectStoreNames = [];
-  for (var i=0; i < numStores; ++i) {
-    objectStoreNames.push("store " + i);
-  }
-  var value = stringOfLength(payloadLength);
-  function getValue() {
-    return value;
-  }
-
-  automation.setStatus("Creating database.");
-  var startTime = window.performance.now();
-
-  createDatabase(testName, objectStoreNames, onCreated, onError);
-
-  function onCreated(db) {
-    automation.setStatus("Constructing transaction.");
-    var transaction =
-        getTransaction(db, objectStoreNames, "readwrite",
-            function() { onValuesWritten(db); });
-    putLinearValues(transaction, objectStoreNames, numKeys, null, getValue);
-  }
-
-  function onValuesWritten(db) {
-    automation.setStatus("Deleting database.");
-    db.close();
-    deleteDatabase(testName, onDeleted);
-  }
-
-  function onDeleted() {
-    var duration = window.performance.now() - startTime;
-    automation.addResult(testName, duration);
-    automation.setStatus("Deleted database.");
-    onTestComplete();
-  }
-}
-
-function testCreateKeysInStores(
-    numKeys, numStores, payloadLength, onTestComplete) {
-  var testName = getDisplayName(arguments);
-  assert(numKeys >= 0);
-  assert(numStores >= 1);
-  var objectStoreNames = [];
-  for (var i=0; i < numStores; ++i) {
-    objectStoreNames.push("store " + i);
-  }
-  var value = stringOfLength(payloadLength);
-  function getValue() {
-    return value;
-  }
-
-  automation.setStatus("Creating database.");
-  createDatabase(testName, objectStoreNames, onCreated, onError);
-
-  function onCreated(db) {
-    automation.setStatus("Constructing transaction.");
-    var completionFunc =
-        getCompletionFunc(db, testName, window.performance.now(),
-            onTestComplete);
-    var transaction =
-        getTransaction(db, objectStoreNames, "readwrite", completionFunc);
-    putLinearValues(transaction, objectStoreNames, numKeys, null, getValue);
-  }
-}
-
-function testRandomReadsAndWrites(
-    numKeys, numReadsPerTransaction, numWritesPerTransaction, numTransactions,
-    useIndexForReads, onTestComplete) {
-  var indexName;
-  if (useIndexForReads)
-    indexName = "index";
-  var testName = getDisplayName(arguments);
-  var objectStoreNames = ["store"];
-  var getKey = getSimpleKey;
-  var getValue = useIndexForReads ? getIndexableValue : getSimpleValue;
-
-  automation.setStatus("Creating database.");
-  var options;
-  if (useIndexForReads) {
-    options = [{
-      indexName: indexName,
-      indexKeyPath: "id",
-      indexIsUnique: false,
-      indexIsMultiEntry: false,
-    }];
-  }
-  createDatabase(testName, objectStoreNames, onCreated, onError, options);
-
-  function onCreated(db) {
-    automation.setStatus("Setting up test database.");
-    var transaction = getTransaction(db, objectStoreNames, "readwrite",
-        function() { onSetupComplete(db); });
-    putLinearValues(transaction, objectStoreNames, numKeys, null,
-        function() { return "test value"; });
-  }
-
-  function onSetupComplete(db) {
-    automation.setStatus("Setup complete.");
-    var completionFunc =
-        getCompletionFunc(db, testName, window.performance.now(),
-            onTestComplete);
-    var mode = "readonly";
-    if (numWritesPerTransaction)
-      mode = "readwrite";
-    runTransactionBatch(db, numTransactions, batchFunc, objectStoreNames, mode,
-        completionFunc);
-  }
-
-  function batchFunc(transaction) {
-    getRandomValues(transaction, objectStoreNames, numReadsPerTransaction,
-        numKeys, indexName, getKey);
-    putRandomValues(transaction, objectStoreNames, numWritesPerTransaction,
-        numKeys, getKey, getValue);
-  }
-}
-
-function testReadCache(numTransactions, useIndexForReads, onTestComplete) {
-  var numKeys = 10000;
-  var numReadsPerTransaction = 50;
-  var numTransactionsLeft = numTransactions;
-  var indexName;
-  if (useIndexForReads)
-    indexName = "index";
-  var testName = getDisplayName(arguments);
-  var objectStoreNames = ["store"];
-  var getKey = getSimpleKey;
-  var getValue = useIndexForReads ? getIndexableValue : getSimpleValue;
-  var keys = [];
-
-  for (var i=0; i < numReadsPerTransaction; ++i) {
-    keys.push(getKey(Math.floor(random() * numKeys)));
-  }
-
-  automation.setStatus("Creating database.");
-  var options;
-  if (useIndexForReads) {
-    options = [{
-      indexName: indexName,
-      indexKeyPath: "id",
-      indexIsUnique: false,
-      indexIsMultiEntry: false,
-    }];
-  }
-  createDatabase(testName, objectStoreNames, onCreated, onError, options);
-
-  function onCreated(db) {
-    automation.setStatus("Setting up test database.");
-    var transaction = getTransaction(db, objectStoreNames, "readwrite",
-        function() { onSetupComplete(db); });
-    putLinearValues(transaction, objectStoreNames, numKeys, getKey,
-        getValue);
-  }
-
-  var completionFunc;
-  function onSetupComplete(db) {
-    automation.setStatus("Setup complete.");
-    completionFunc =
-        getCompletionFunc(db, testName, window.performance.now(),
-            onTestComplete);
-    runTransactionBatch(db, numTransactions, batchFunc, objectStoreNames,
-        "readonly", completionFunc);
-  }
-
-  function batchFunc(transaction) {
-    getSpecificValues(transaction, objectStoreNames, indexName, keys);
-  }
-}
-
-function testCreateAndDeleteIndex(numKeys, onTestComplete) {
-  var testName = getDisplayName(arguments);
-  var objectStoreNames = ["store"];
-
-  automation.setStatus("Creating database.");
-  createDatabase(testName, objectStoreNames, onCreated, onError);
-
-  var startTime;
-  function onCreated(db) {
-    automation.setStatus("Initializing data.");
-    var transaction = getTransaction(db, objectStoreNames, "readwrite",
-        function() { onPopulated(db); });
-    putLinearValues(transaction, objectStoreNames, numKeys, null, getValue);
-  }
-
-  function getValue(i) {
-    return { firstName: i + " first name", lastName: i + " last name" };
-  }
-
-  function onPopulated(db) {
-    db.close();
-    automation.setStatus("Building index.");
-    startTime = window.performance.now();
-    var f = function(objectStore) {
-      objectStore.createIndex("index", "firstName", {unique: true});
-    };
-    alterObjectStores(testName, objectStoreNames, f, onIndexCreated, onError);
-  }
-
-  var indexCreationCompleteTime;
-  function onIndexCreated(db) {
-    db.close();
-    indexCreationCompleteTime = window.performance.now();
-    automation.addResult("testCreateIndex",
-        indexCreationCompleteTime - startTime);
-    var f = function(objectStore) {
-      objectStore.deleteIndex("index");
-    };
-    automation.setStatus("Deleting index.");
-    alterObjectStores(testName, objectStoreNames, f, onIndexDeleted, onError);
-  }
-
-  function onIndexDeleted(db) {
-    var duration = window.performance.now() - indexCreationCompleteTime;
-    // Ignore the cleanup time for this test.
-    automation.addResult("testDeleteIndex", duration);
-    automation.setStatus("Deleting database.");
-    db.close();
-    deleteDatabase(testName, onDeleted);
-  }
-
-  function onDeleted() {
-    automation.setStatus("Deleted database.");
-    onTestComplete();
-  }
-}
-
-function testCursorReadsAndRandomWrites(
-    readKeysOnly, useIndexForReads, writeAlso, sameStoreForWrites,
-    onTestComplete) {
-  // There's no key cursor unless you're reading from an index.
-  assert(useIndexForReads || !readKeysOnly);
-  // If we're writing to another store, having an index would constrain our
-  // writes, as we create both object stores with the same configurations.
-  // We could do that if needed, but it's simpler not to.
-  assert(!useIndexForReads || !writeAlso);
-  var numKeys = 10000;
-  var numReadsPerTransaction = 1000;
-  var testName = getDisplayName(arguments);
-  var objectStoreNames = ["input store"];
-  var outputStoreName;
-  if (writeAlso) {
-    if (sameStoreForWrites) {
-      outputStoreName = objectStoreNames[0];
-    } else {
-      outputStoreName = "output store";
-      objectStoreNames.push(outputStoreName);
-    }
-  }
-  var getKeyForRead = getSimpleKey;
-  var indexName;
-  if (useIndexForReads) {
-    indexName = "index";
-    getKeyForRead = function(i) {
-      // This depends on the implementations of getValuesFromCursor and
-      // getObjectValue.  We reverse the order of the iteration here so that
-      // setting up bounds from k to k+n with n>0 works.  Without this reversal,
-      // the upper bound is below the lower bound.
-      return getBackwardIndexKey(numKeys - i);
-    };
-  }
-
-  automation.setStatus("Creating database.");
-  var options;
-  if (useIndexForReads) {
-    options = [{
-      indexName: indexName,
-      indexKeyPath: "lastName", // depends on getBackwardIndexKey()
-      indexIsUnique: true,
-      indexIsMultiEntry: false,
-    }];
-  }
-  createDatabase(testName, objectStoreNames, onCreated, onError, options);
-
-  function onCreated(db) {
-    automation.setStatus("Setting up test database.");
-    var transaction = getTransaction(db, objectStoreNames, "readwrite",
-        function() { onSetupComplete(db); });
-    putLinearValues(transaction, objectStoreNames, numKeys, getSimpleKey,
-        getObjectValue);
-  }
-  function onSetupComplete(db) {
-    automation.setStatus("Setup complete.");
-    var completionFunc =
-        getCompletionFunc(db, testName, window.performance.now(),
-            onTestComplete);
-    var mode = "readonly";
-    if (writeAlso)
-      mode = "readwrite";
-    var transaction =
-        getTransaction(db, objectStoreNames, mode, completionFunc);
-
-    getValuesFromCursor(
-        transaction, objectStoreNames[0], numReadsPerTransaction, numKeys,
-        indexName, getKeyForRead, readKeysOnly, outputStoreName);
-  }
-}
-
-function testWalkingMultipleCursors(numCursors, onTestComplete) {
-  var numKeys = 1000;
-  var numHitsPerKey = 10;
-  var testName = getDisplayName(arguments);
-  var objectStoreNames = ["input store"];
-  var indexName = "index name";
-  var getKey = getSimpleKey;
-  var getValue = getIndexableValue;
-
-  automation.setStatus("Creating database.");
-  var options = [{
-    indexName: indexName,
-    indexKeyPath: "id",
-    indexIsUnique: false,
-    indexIsMultiEntry: false,
-  }];
-  createDatabase(testName, objectStoreNames, onCreated, onError, options);
-
-  function onCreated(db) {
-    automation.setStatus("Setting up test database.");
-    var transaction = getTransaction(db, objectStoreNames, "readwrite",
-        function() { onSetupComplete(db); });
-    // This loop adds the same value numHitsPerKey times for each key.
-    for (var i = 0; i < numHitsPerKey; ++i) {
-      putLinearValues(transaction, objectStoreNames, numKeys, getKeyFunc(i),
-          getValue);
-    }
-  }
-  // While the value is the same each time through the putLinearValues loop, we
-  // want the key to keep increaasing for each copy.
-  function getKeyFunc(k) {
-    return function(i) {
-      return getKey(k * numKeys + i);
-    };
-  }
-  var completionFunc;
-  function onSetupComplete(db) {
-    automation.setStatus("Setup complete.");
-    completionFunc =
-        getCompletionFunc(db, testName, window.performance.now(),
-            onTestComplete);
-    var transaction =
-        getTransaction(db, objectStoreNames, "readonly", verifyComplete);
-
-    walkSeveralCursors(transaction, numKeys);
-  }
-  var responseCounts = [];
-  var cursorsRunning = numCursors;
-  function walkSeveralCursors(transaction, numKeys) {
-    var source = transaction.objectStore(objectStoreNames[0]).index(indexName);
-    var requests = [];
-    var continueCursorIndex = 0;
-    for (var i = 0; i < numCursors; ++i) {
-      var rand = Math.floor(random() * numKeys);
-      // Since we have numHitsPerKey copies of each value in the database,
-      // IDBKeyRange.only will return numHitsPerKey results, each referring to a
-      // different key with the matching value.
-      var request = source.openCursor(IDBKeyRange.only(getSimpleValue(rand)));
-      responseCounts.push(0);
-      request.onerror = onError;
-      request.onsuccess = function(event) {
-        assert(cursorsRunning);
-        var request = event.target;
-        if (!("requestIndex" in request)) {
-          assert(requests.length < numCursors);
-          request.requestIndex = requests.length;
-          requests.push(request);
-        }
-        var cursor = event.target.result;
-        if (cursor) {
-          assert(responseCounts[request.requestIndex] < numHitsPerKey);
-          ++responseCounts[request.requestIndex];
-        } else {
-          assert(responseCounts[request.requestIndex] == numHitsPerKey);
-          --cursorsRunning;
-        }
-        if (cursorsRunning) {
-          if (requests.length == numCursors) {
-            requests[continueCursorIndex++].result.continue();
-            continueCursorIndex %= numCursors;
-          }
-        }
-      };
-    }
-  }
-  function verifyComplete() {
-    assert(!cursorsRunning);
-    completionFunc();
-  }
-}
-
-function testCursorSeeks(
-    numKeys, numSeeksPerTransaction, numTransactions, useIndexForReads,
-    onTestComplete) {
-  var testName = getDisplayName(arguments);
-  var objectStoreNames = ["store"];
-  var getKey = useIndexForReads ? getForwardIndexKey : getSimpleKey;
-  var indexName;
-  if (useIndexForReads) {
-    indexName = "index";
-  }
-
-  automation.setStatus("Creating database.");
-  var options;
-  if (useIndexForReads) {
-    options = [{
-      indexName: indexName,
-      indexKeyPath: "firstName",
-      indexIsUnique: true,
-      indexIsMultiEntry: false,
-    }];
-  }
-  createDatabase(testName, objectStoreNames, onCreated, onError, options);
-
-  function onCreated(db) {
-    automation.setStatus("Setting up test database.");
-    var transaction = getTransaction(db, objectStoreNames, "readwrite",
-        function() { onSetupComplete(db); });
-    putLinearValues(transaction, objectStoreNames, numKeys, getSimpleKey,
-        getObjectValue);
-  }
-
-  function onSetupComplete(db) {
-    automation.setStatus("Setup complete.");
-    var completionFunc =
-          getCompletionFunc(db, testName, window.performance.now(),
-              onTestComplete);
-    var mode = "readonly";
-    runTransactionBatch(db, numTransactions, batchFunc, objectStoreNames, mode,
-        completionFunc);
-  }
-
-  function batchFunc(transaction) {
-    for (var i in objectStoreNames) {
-      var source = transaction.objectStore(objectStoreNames[i]);
-      if (useIndexForReads)
-        source = source.index(indexName);
-      for (var j = 0; j < numSeeksPerTransaction; ++j) {
-        randomSeek(source);
-      }
-    }
-  }
-
-  function randomSeek(source) {
-    var request = useIndexForReads ? source.openKeyCursor()
-          : source.openCursor();
-    var first = true;
-    request.onerror = onError;
-    request.onsuccess = function() {
-      var cursor = request.result;
-      if (cursor && first) {
-        first = false;
-        cursor.continue(getKey(numKeys - 1));
-      }
-    };
-  }
-}
diff --git a/tools/roll_swiftshader.py b/tools/roll_swiftshader.py
index 447d0ac..5b4dd0e 100755
--- a/tools/roll_swiftshader.py
+++ b/tools/roll_swiftshader.py
@@ -31,12 +31,6 @@
     "buildernames": ["android_optional_gpu_tests_rel"]
   }
 ]
-extra_fyi_trybots = [
-  {
-    "mastername": "master.tryserver.chromium.win",
-    "buildernames": ["win_clang_dbg"]
-  }
-]
 
 SCRIPT_DIR = os.path.dirname(os.path.realpath(__file__))
 SRC_DIR = os.path.abspath(os.path.join(SCRIPT_DIR, os.pardir))
@@ -316,16 +310,6 @@
       base_try_cmd = ['git', 'cl', 'try']
       self._RunCommand(base_try_cmd)
 
-      if extra_cq_trybots:
-        # Run additional tryjobs.
-        # TODO(kbr): this should not be necessary -- the
-        # CQ_INCLUDE_TRYBOTS directive above should handle it.
-        # http://crbug.com/585237
-        self._TriggerExtraTrybots(extra_cq_trybots)
-
-      if extra_fyi_trybots:
-        self._TriggerExtraTrybots(extra_fyi_trybots)
-
       # Mark the CL to be committed if requested
       if should_commit:
         self._RunCommand(['git', 'cl', 'set-commit'])
diff --git a/tools/roll_webgl_conformance.py b/tools/roll_webgl_conformance.py
index dad46670..985dad4 100755
--- a/tools/roll_webgl_conformance.py
+++ b/tools/roll_webgl_conformance.py
@@ -298,16 +298,6 @@
         # Kick off tryjobs.
         base_try_cmd = ['git', 'cl', 'try']
         self._RunCommand(base_try_cmd)
-        if extra_trybots:
-          # Run additional tryjobs.
-          # TODO(kbr): this should not be necessary -- the
-          # CQ_INCLUDE_TRYBOTS directive above should handle it.
-          # http://crbug.com/585237
-          for trybot in extra_trybots:
-            for builder in trybot['buildernames']:
-              self._RunCommand(base_try_cmd + [
-                  '-m', trybot['mastername'],
-                  '-b', builder])
 
       cl_info = self._GetCLInfo()
       print 'Issue: %d URL: %s' % (cl_info.issue, cl_info.url)
diff --git a/ui/app_list/app_list_features.cc b/ui/app_list/app_list_features.cc
index a11d5a6..d443c10 100644
--- a/ui/app_list/app_list_features.cc
+++ b/ui/app_list/app_list_features.cc
@@ -16,8 +16,6 @@
                                              base::FEATURE_DISABLED_BY_DEFAULT};
 const base::Feature kEnableBackgroundBlur{"EnableBackgroundBlur",
                                           base::FEATURE_DISABLED_BY_DEFAULT};
-const base::Feature kEnableFullscreenAppList{"EnableFullscreenAppList",
-                                             base::FEATURE_ENABLED_BY_DEFAULT};
 const base::Feature kEnablePlayStoreAppSearch{"EnablePlayStoreAppSearch",
                                               base::FEATURE_ENABLED_BY_DEFAULT};
 const base::Feature kEnableAppListFocus{"EnableAppListFocus",
@@ -42,8 +40,7 @@
 }
 
 bool IsFullscreenAppListEnabled() {
-  // Not using local static variable to allow tests to change this value.
-  return base::FeatureList::IsEnabled(kEnableFullscreenAppList);
+  return true;
 }
 
 bool IsTouchFriendlySearchResultsPageEnabled() {
diff --git a/ui/app_list/app_list_features.h b/ui/app_list/app_list_features.h
index 7e237c96..0b450c6 100644
--- a/ui/app_list/app_list_features.h
+++ b/ui/app_list/app_list_features.h
@@ -30,9 +30,6 @@
 // choppier app list animations. crbug.com/765292.
 APP_LIST_EXPORT extern const base::Feature kEnableBackgroundBlur;
 
-// Enables the fullscreen app list.
-APP_LIST_EXPORT extern const base::Feature kEnableFullscreenAppList;
-
 // Enables the Play Store app search.
 APP_LIST_EXPORT extern const base::Feature kEnablePlayStoreAppSearch;
 
diff --git a/ui/app_list/presenter/app_list_presenter_impl.cc b/ui/app_list/presenter/app_list_presenter_impl.cc
index 7bb5905..bcfef119 100644
--- a/ui/app_list/presenter/app_list_presenter_impl.cc
+++ b/ui/app_list/presenter/app_list_presenter_impl.cc
@@ -4,6 +4,7 @@
 
 #include "ui/app_list/presenter/app_list_presenter_impl.h"
 
+#include "base/metrics/histogram_macros.h"
 #include "base/metrics/user_metrics.h"
 #include "ui/app_list/app_list_constants.h"
 #include "ui/app_list/app_list_features.h"
@@ -14,6 +15,7 @@
 #include "ui/aura/client/focus_client.h"
 #include "ui/aura/window.h"
 #include "ui/compositor/layer.h"
+#include "ui/compositor/layer_animation_element.h"
 #include "ui/compositor/scoped_layer_animation_settings.h"
 #include "ui/display/screen.h"
 #include "ui/views/widget/widget.h"
@@ -28,12 +30,27 @@
   return widget->GetNativeView()->layer();
 }
 
+class StateAnimationMetricsReporter : public ui::AnimationMetricsReporter {
+ public:
+  StateAnimationMetricsReporter() = default;
+  ~StateAnimationMetricsReporter() override = default;
+
+  void Report(int value) override {
+    UMA_HISTOGRAM_PERCENTAGE("Apps.StateTransition.AnimationSmoothness", value);
+  }
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(StateAnimationMetricsReporter);
+};
+
 }  // namespace
 
 AppListPresenterImpl::AppListPresenterImpl(
     std::unique_ptr<AppListPresenterDelegateFactory> factory)
     : factory_(std::move(factory)),
-      is_fullscreen_app_list_enabled_(features::IsFullscreenAppListEnabled()) {
+      is_fullscreen_app_list_enabled_(features::IsFullscreenAppListEnabled()),
+      state_animation_metrics_reporter_(
+          std::make_unique<StateAnimationMetricsReporter>()) {
   DCHECK(factory_);
 }
 
@@ -221,6 +238,9 @@
     }
   }
 
+  animation.SetAnimationMetricsReporter(
+      state_animation_metrics_reporter_.get());
+
   animation.AddObserver(this);
   if (is_fullscreen_app_list_enabled_) {
     widget->GetNativeView()->SetBounds(target_bounds);
diff --git a/ui/app_list/presenter/app_list_presenter_impl.h b/ui/app_list/presenter/app_list_presenter_impl.h
index 8ceb731..4cb66df 100644
--- a/ui/app_list/presenter/app_list_presenter_impl.h
+++ b/ui/app_list/presenter/app_list_presenter_impl.h
@@ -21,6 +21,10 @@
 #include "ui/gfx/geometry/rect.h"
 #include "ui/views/widget/widget_observer.h"
 
+namespace ui {
+class AnimationMetricsReporter;
+}
+
 namespace app_list {
 class AppListView;
 class AppListViewDelegate;
@@ -148,6 +152,10 @@
   // The app list interface pointer; used for reporting visibility changes.
   mojom::AppListPtr app_list_;
 
+  // Metric reporter for state change animations.
+  const std::unique_ptr<ui::AnimationMetricsReporter>
+      state_animation_metrics_reporter_;
+
   DISALLOW_COPY_AND_ASSIGN(AppListPresenterImpl);
 };
 
diff --git a/ui/app_list/views/app_list_view.cc b/ui/app_list/views/app_list_view.cc
index 78824ca..20f3097 100644
--- a/ui/app_list/views/app_list_view.cc
+++ b/ui/app_list/views/app_list_view.cc
@@ -36,6 +36,7 @@
 #include "ui/base/l10n/l10n_util.h"
 #include "ui/base/ui_base_switches.h"
 #include "ui/compositor/layer.h"
+#include "ui/compositor/layer_animation_element.h"
 #include "ui/compositor/layer_animation_observer.h"
 #include "ui/compositor/layer_animation_sequence.h"
 #include "ui/compositor/scoped_layer_animation_settings.h"
@@ -186,6 +187,19 @@
   DISALLOW_COPY_AND_ASSIGN(AppListEventTargeter);
 };
 
+class StateAnimationMetricsReporter : public ui::AnimationMetricsReporter {
+ public:
+  StateAnimationMetricsReporter() = default;
+  ~StateAnimationMetricsReporter() override = default;
+
+  void Report(int value) override {
+    UMA_HISTOGRAM_PERCENTAGE("Apps.StateTransition.AnimationSmoothness", value);
+  }
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(StateAnimationMetricsReporter);
+};
+
 }  // namespace
 
 // An animation observer to hide the view at the end of the animation.
@@ -238,7 +252,9 @@
       display_observer_(this),
       animation_observer_(new HideViewAnimationObserver()),
       previous_arrow_key_traversal_enabled_(
-          views::FocusManager::arrow_key_traversal_enabled()) {
+          views::FocusManager::arrow_key_traversal_enabled()),
+      state_animation_metrics_reporter_(
+          std::make_unique<StateAnimationMetricsReporter>()) {
   CHECK(delegate);
   delegate_->GetSpeechUI()->AddObserver(this);
 
@@ -1273,8 +1289,11 @@
   animator->set_preemption_strategy(
       ui::LayerAnimator::IMMEDIATELY_ANIMATE_TO_NEW_TARGET);
   animator->StopAnimating();
-  animator->ScheduleAnimation(
-      new ui::LayerAnimationSequence(std::move(bounds_animation_element)));
+  ui::LayerAnimationSequence* animation_sequence =
+      new ui::LayerAnimationSequence(std::move(bounds_animation_element));
+  animation_sequence->SetAnimationMetricsReporter(
+      state_animation_metrics_reporter_.get());
+  animator->ScheduleAnimation(animation_sequence);
 }
 
 void AppListView::StartCloseAnimation(base::TimeDelta animation_duration) {
diff --git a/ui/app_list/views/app_list_view.h b/ui/app_list/views/app_list_view.h
index e8a56e1..ba117f96 100644
--- a/ui/app_list/views/app_list_view.h
+++ b/ui/app_list/views/app_list_view.h
@@ -31,6 +31,10 @@
 class Screen;
 }
 
+namespace ui {
+class AnimationMetricsReporter;
+}
+
 namespace app_list {
 class ApplicationDragAndDropHost;
 class AppListMainView;
@@ -405,6 +409,10 @@
   // Whether FocusManager can handle arrow key before this class is constructed.
   const bool previous_arrow_key_traversal_enabled_;
 
+  // Metric reporter for state change animations.
+  const std::unique_ptr<ui::AnimationMetricsReporter>
+      state_animation_metrics_reporter_;
+
   DISALLOW_COPY_AND_ASSIGN(AppListView);
 };
 
diff --git a/ui/app_list/views/app_list_view_unittest.cc b/ui/app_list/views/app_list_view_unittest.cc
index 6ab51cc..44e9132 100644
--- a/ui/app_list/views/app_list_view_unittest.cc
+++ b/ui/app_list/views/app_list_view_unittest.cc
@@ -193,8 +193,6 @@
   // testing::Test
   void SetUp() override {
     views::ViewsTestBase::SetUp();
-    scoped_feature_list_.InitAndEnableFeature(
-        features::kEnableFullscreenAppList);
   }
 
  protected:
diff --git a/ui/app_list/views/apps_grid_view_unittest.cc b/ui/app_list/views/apps_grid_view_unittest.cc
index e737607..013b8fd 100644
--- a/ui/app_list/views/apps_grid_view_unittest.cc
+++ b/ui/app_list/views/apps_grid_view_unittest.cc
@@ -119,7 +119,6 @@
       if (is_rtl_)
         base::i18n::SetICUDefaultLocale("he");
     }
-
     gfx::NativeView parent = GetContext();
     delegate_.reset(new AppListTestViewDelegate);
     app_list_view_ = new AppListView(delegate_.get());
@@ -149,10 +148,6 @@
   }
 
  protected:
-  void EnableFullscreenAppList() {
-    scoped_feature_list_.InitAndEnableFeature(
-        features::kEnableFullscreenAppList);
-  }
 
   AppListItemView* GetItemViewAt(int index) const {
     return static_cast<AppListItemView*>(test_api_->GetViewAtModelIndex(index));
@@ -250,6 +245,7 @@
   std::unique_ptr<AppsGridViewTestApi> test_api_;
   bool is_rtl_ = false;
   base::test::ScopedFeatureList scoped_feature_list_;
+  bool test_with_fullscreen_ = true;
 
  private:
   // Restores the locale to default when destructor is called.
@@ -299,7 +295,7 @@
   DISALLOW_COPY_AND_ASSIGN(TestAppsGridViewFolderDelegate);
 };
 
-TEST_P(AppsGridViewTest, CreatePage) {
+TEST_F(AppsGridViewTest, CreatePage) {
   // Fully populates a page.
   const int kPages = 1;
 
@@ -316,7 +312,7 @@
   EXPECT_EQ(kPages + 1, GetPaginationModel()->total_pages());
 }
 
-TEST_P(AppsGridViewTest, EnsureHighlightedVisible) {
+TEST_F(AppsGridViewTest, EnsureHighlightedVisible) {
   const int kPages = 3;
   model_->PopulateApps(GetTilesPerPage(0) + (kPages - 1) * GetTilesPerPage(1));
   EXPECT_EQ(kPages, GetPaginationModel()->total_pages());
@@ -338,7 +334,7 @@
   EXPECT_EQ(kPages - 1, GetPaginationModel()->selected_page());
 }
 
-TEST_P(AppsGridViewTest, RemoveSelectedLastApp) {
+TEST_F(AppsGridViewTest, RemoveSelectedLastApp) {
   const int kTotalItems = 2;
   const int kLastItemIndex = kTotalItems - 1;
 
@@ -356,7 +352,7 @@
   EXPECT_TRUE(apps_grid_view_->IsSelectedView(view));
 }
 
-TEST_P(AppsGridViewTest, MouseDragWithFolderDisabled) {
+TEST_F(AppsGridViewTest, MouseDragWithFolderDisabled) {
   model_->SetFoldersEnabled(false);
   const int kTotalItems = 4;
   model_->PopulateApps(kTotalItems);
@@ -405,7 +401,7 @@
   test_api_->LayoutToIdealBounds();
 }
 
-TEST_P(AppsGridViewTest, MouseDragItemIntoFolder) {
+TEST_F(AppsGridViewTest, MouseDragItemIntoFolder) {
   size_t kTotalItems = 3;
   model_->PopulateApps(kTotalItems);
   EXPECT_EQ(model_->top_level_item_list()->item_count(), kTotalItems);
@@ -546,7 +542,7 @@
   test_api_->LayoutToIdealBounds();
 }
 
-TEST_P(AppsGridViewTest, MouseDragItemReorder) {
+TEST_F(AppsGridViewTest, MouseDragItemReorder) {
   // Using a simulated 2x2 layout for the test. If fullscreen app list is
   // enabled, rows_per_page passed should be 3 as the first row is occupied by
   // suggested apps.
@@ -615,7 +611,7 @@
             model_->GetModelContent());
 }
 
-TEST_P(AppsGridViewTest, MouseDragFolderReorder) {
+TEST_F(AppsGridViewTest, MouseDragFolderReorder) {
   size_t kTotalItems = 2;
   model_->CreateAndPopulateFolderWithApps(kTotalItems);
   model_->PopulateAppWithId(kTotalItems);
@@ -639,7 +635,7 @@
   test_api_->LayoutToIdealBounds();
 }
 
-TEST_P(AppsGridViewTest, MouseDragWithCancelDeleteAddItem) {
+TEST_F(AppsGridViewTest, MouseDragWithCancelDeleteAddItem) {
   size_t kTotalItems = 4;
   model_->PopulateApps(kTotalItems);
   EXPECT_EQ(model_->top_level_item_list()->item_count(), kTotalItems);
@@ -672,7 +668,7 @@
   test_api_->LayoutToIdealBounds();
 }
 
-TEST_P(AppsGridViewTest, MouseDragFlipPage) {
+TEST_F(AppsGridViewTest, MouseDragFlipPage) {
   apps_grid_view_->set_page_flip_delay_in_ms_for_testing(10);
   GetPaginationModel()->SetTransitionDurations(10, 10);
 
@@ -715,7 +711,7 @@
   apps_grid_view_->EndDrag(true);
 }
 
-TEST_P(AppsGridViewTest, SimultaneousDragWithFolderDisabled) {
+TEST_F(AppsGridViewTest, SimultaneousDragWithFolderDisabled) {
   model_->SetFoldersEnabled(false);
   const int kTotalItems = 4;
   model_->PopulateApps(kTotalItems);
@@ -747,7 +743,7 @@
   test_api_->LayoutToIdealBounds();
 }
 
-TEST_P(AppsGridViewTest, UpdateFolderBackgroundOnCancelDrag) {
+TEST_F(AppsGridViewTest, UpdateFolderBackgroundOnCancelDrag) {
   const int kTotalItems = 4;
   TestAppsGridViewFolderDelegate folder_delegate;
   apps_grid_view_->set_folder_delegate(&folder_delegate);
@@ -1073,7 +1069,7 @@
   EXPECT_TRUE(CheckSelectionAtExpandArrow());
 }
 
-TEST_P(AppsGridViewTest, ItemLabelShortNameOverride) {
+TEST_F(AppsGridViewTest, ItemLabelShortNameOverride) {
   // If the app's full name and short name differ, the title label's tooltip
   // should always be the full name of the app.
   std::string expected_text("xyz");
@@ -1091,7 +1087,7 @@
   EXPECT_EQ(expected_text, base::UTF16ToUTF8(title_label->text()));
 }
 
-TEST_P(AppsGridViewTest, ItemLabelNoShortName) {
+TEST_F(AppsGridViewTest, ItemLabelNoShortName) {
   // If the app's full name and short name are the same, use the default tooltip
   // behavior of the label (only show a tooltip if the title is truncated).
   std::string title("a");
@@ -1130,7 +1126,7 @@
   ASSERT_EQ(0, GetPaginationModel()->transition().progress);
 }
 
-TEST_P(AppsGridViewTest,
+TEST_F(AppsGridViewTest,
        OnGestureEventScrollSequenceHandleByPaginationController) {
   model_->PopulateApps(GetTilesPerPage(0) + 1);
   EXPECT_EQ(2, GetPaginationModel()->total_pages());
diff --git a/ui/app_list/views/search_box_view.cc b/ui/app_list/views/search_box_view.cc
index 0d40e958..795312f 100644
--- a/ui/app_list/views/search_box_view.cc
+++ b/ui/app_list/views/search_box_view.cc
@@ -557,7 +557,9 @@
   UpdateSearchIcon();
   UpdateBackgroundColor(background_color_);
   search_box_->set_placeholder_text_draw_flags(
-      active ? gfx::Canvas::TEXT_ALIGN_LEFT : gfx::Canvas::TEXT_ALIGN_CENTER);
+      active ? (base::i18n::IsRTL() ? gfx::Canvas::TEXT_ALIGN_RIGHT
+                                    : gfx::Canvas::TEXT_ALIGN_LEFT)
+             : gfx::Canvas::TEXT_ALIGN_CENTER);
   search_box_->set_placeholder_text_color(active ? kZeroQuerySearchboxColor
                                                  : search_box_color_);
   search_box_->SetCursorEnabled(active);
diff --git a/ui/app_list/views/search_box_view_unittest.cc b/ui/app_list/views/search_box_view_unittest.cc
index 0d443d0..a6bb7a78 100644
--- a/ui/app_list/views/search_box_view_unittest.cc
+++ b/ui/app_list/views/search_box_view_unittest.cc
@@ -9,7 +9,6 @@
 
 #include "base/macros.h"
 #include "base/strings/utf_string_conversions.h"
-#include "base/test/scoped_feature_list.h"
 #include "ui/app_list/app_list_constants.h"
 #include "ui/app_list/app_list_features.h"
 #include "ui/app_list/test/app_list_test_view_delegate.h"
@@ -51,11 +50,9 @@
   DISALLOW_COPY_AND_ASSIGN(KeyPressCounterView);
 };
 
-// These tests run with both FullscreenAppList enabled and disabled.
 // TODO(crbug.com/743113) Unify the two test classes.
 class SearchBoxViewTest : public views::test::WidgetTest,
-                          public SearchBoxViewDelegate,
-                          public testing::WithParamInterface<bool> {
+                          public SearchBoxViewDelegate {
  public:
   SearchBoxViewTest() = default;
   ~SearchBoxViewTest() override = default;
@@ -64,15 +61,6 @@
   void SetUp() override {
     views::test::WidgetTest::SetUp();
 
-    if (testing::UnitTest::GetInstance()->current_test_info()->value_param()) {
-      // Current test is parameterized.
-      test_with_fullscreen_ = GetParam();
-      if (test_with_fullscreen_) {
-        scoped_feature_list_.InitAndEnableFeature(
-            features::kEnableFullscreenAppList);
-      }
-    }
-
     app_list_view_ = new AppListView(&view_delegate_);
     AppListView::InitParams params;
     params.parent = GetContext();
@@ -97,8 +85,6 @@
   SearchBoxView* view() { return view_.get(); }
   AppListView* app_list_view() { return app_list_view_; }
 
-  bool test_with_fullscreen() { return test_with_fullscreen_; }
-
   void SetLongAutoLaunchTimeout() {
     // Sets a long timeout that lasts longer than the test run.
     view_delegate_.set_auto_launch_timeout(base::TimeDelta::FromDays(1));
@@ -156,8 +142,6 @@
   KeyPressCounterView* counter_view_;
   base::string16 last_query_;
   int query_changed_count_ = 0;
-  bool test_with_fullscreen_ = false;
-  base::test::ScopedFeatureList scoped_feature_list_;
 
   DISALLOW_COPY_AND_ASSIGN(SearchBoxViewTest);
 };
@@ -171,9 +155,6 @@
   // Overridden from testing::Test:
   void SetUp() override {
     views::test::WidgetTest::SetUp();
-    scoped_feature_list_.InitAndEnableFeature(
-        app_list::features::kEnableFullscreenAppList);
-
     app_list_view_ = new AppListView(&view_delegate_);
     AppListView::InitParams params;
     params.parent = GetContext();
@@ -221,8 +202,6 @@
 
   void SetSearchResultSelection(bool select) override {}
 
-  base::test::ScopedFeatureList scoped_feature_list_;
-
   AppListTestViewDelegate view_delegate_;
   views::Widget* widget_;
   AppListView* app_list_view_ = nullptr;
@@ -231,11 +210,7 @@
   DISALLOW_COPY_AND_ASSIGN(SearchBoxViewFullscreenTest);
 };
 
-// Instantiate the Boolean which is used to toggle the Fullscreen app list in
-// the parameterized tests.
-INSTANTIATE_TEST_CASE_P(, SearchBoxViewTest, testing::Bool());
-
-TEST_P(SearchBoxViewTest, Basic) {
+TEST_F(SearchBoxViewTest, Basic) {
   // TODO(newcomer): this test needs to be reevaluated for the fullscreen app
   // list (http://crbug.com/759779).
   if (features::IsFullscreenAppListEnabled())
@@ -255,7 +230,7 @@
   EXPECT_TRUE(GetLastQueryAndReset().empty());
 }
 
-TEST_P(SearchBoxViewTest, CancelAutoLaunch) {
+TEST_F(SearchBoxViewTest, CancelAutoLaunch) {
   SetLongAutoLaunchTimeout();
   ASSERT_NE(base::TimeDelta(), GetAutoLaunchTimeout());
 
diff --git a/ui/app_list/views/search_result_list_view_unittest.cc b/ui/app_list/views/search_result_list_view_unittest.cc
index 9fe5f67..31044b8 100644
--- a/ui/app_list/views/search_result_list_view_unittest.cc
+++ b/ui/app_list/views/search_result_list_view_unittest.cc
@@ -13,7 +13,6 @@
 #include "base/memory/ptr_util.h"
 #include "base/strings/stringprintf.h"
 #include "base/strings/utf_string_conversions.h"
-#include "base/test/scoped_feature_list.h"
 #include "ui/app_list/app_list_features.h"
 #include "ui/app_list/app_list_model.h"
 #include "ui/app_list/test/app_list_test_view_delegate.h"
@@ -29,8 +28,7 @@
 int kDefaultSearchItems = 5;
 }  // namespace
 
-class SearchResultListViewTest : public views::ViewsTestBase,
-                                 public testing::WithParamInterface<bool> {
+class SearchResultListViewTest : public views::ViewsTestBase {
  public:
   SearchResultListViewTest() = default;
   ~SearchResultListViewTest() override = default;
@@ -38,11 +36,6 @@
   // Overridden from testing::Test:
   void SetUp() override {
     views::ViewsTestBase::SetUp();
-    if (!GetParam()) {
-      scoped_feature_list_.InitAndDisableFeature(
-          features::kEnableFullscreenAppList);
-    }
-
     view_.reset(new SearchResultListView(nullptr, &view_delegate_));
     view_->SetResults(view_delegate_.GetModel()->results());
   }
@@ -129,16 +122,11 @@
  private:
   AppListTestViewDelegate view_delegate_;
   std::unique_ptr<SearchResultListView> view_;
-  base::test::ScopedFeatureList scoped_feature_list_;
 
   DISALLOW_COPY_AND_ASSIGN(SearchResultListViewTest);
 };
 
-// Instantiate the Boolean which is used to toggle the Fullscreen app list in
-// the parameterized tests.
-INSTANTIATE_TEST_CASE_P(, SearchResultListViewTest, testing::Bool());
-
-TEST_P(SearchResultListViewTest, Basic) {
+TEST_F(SearchResultListViewTest, Basic) {
   SetUpSearchResults();
 
   const int results = GetResultCount();
@@ -176,7 +164,7 @@
   EXPECT_EQ(results - 1, GetSelectedIndex());
 }
 
-TEST_P(SearchResultListViewTest, AutoLaunch) {
+TEST_F(SearchResultListViewTest, AutoLaunch) {
   SetLongAutoLaunchTimeout();
   SetUpSearchResults();
 
@@ -191,7 +179,7 @@
   EXPECT_EQ(base::TimeDelta(), GetAutoLaunchTimeout());
 }
 
-TEST_P(SearchResultListViewTest, CancelAutoLaunch) {
+TEST_F(SearchResultListViewTest, CancelAutoLaunch) {
   SetLongAutoLaunchTimeout();
   SetUpSearchResults();
 
@@ -212,7 +200,7 @@
   EXPECT_TRUE(IsAutoLaunching());
 }
 
-TEST_P(SearchResultListViewTest, SpokenFeedback) {
+TEST_F(SearchResultListViewTest, SpokenFeedback) {
   SetUpSearchResults();
 
   // Result 0 has a detail text. Expect that the detail is appended to the
@@ -225,7 +213,7 @@
             GetResultViewAt(2)->ComputeAccessibleName());
 }
 
-TEST_P(SearchResultListViewTest, ModelObservers) {
+TEST_F(SearchResultListViewTest, ModelObservers) {
   SetUpSearchResults();
   ExpectConsistent();
 
@@ -252,7 +240,7 @@
 
 // Regression test for http://crbug.com/402859 to ensure ProgressBar is
 // initialized properly in SearchResultListView::SetResult().
-TEST_P(SearchResultListViewTest, ProgressBar) {
+TEST_F(SearchResultListViewTest, ProgressBar) {
   SetUpSearchResults();
 
   GetResults()->GetItemAt(0)->SetIsInstalling(true);
diff --git a/ui/app_list/views/search_result_page_view_unittest.cc b/ui/app_list/views/search_result_page_view_unittest.cc
index e6e1e3ab..f2e29f9 100644
--- a/ui/app_list/views/search_result_page_view_unittest.cc
+++ b/ui/app_list/views/search_result_page_view_unittest.cc
@@ -38,9 +38,9 @@
 namespace app_list {
 namespace test {
 
-class SearchResultPageViewTest : public views::ViewsTestBase,
-                                 public testing::WithParamInterface<
-                                     ::testing::tuple<bool, AnswerCardState>> {
+class SearchResultPageViewTest
+    : public views::ViewsTestBase,
+      public testing::WithParamInterface<AnswerCardState> {
  public:
   SearchResultPageViewTest() = default;
   ~SearchResultPageViewTest() override = default;
@@ -52,8 +52,7 @@
     // Reading test parameters.
     bool test_with_answer_card = true;
     if (testing::UnitTest::GetInstance()->current_test_info()->value_param()) {
-      test_with_fullscreen_ = testing::get<0>(GetParam());
-      const AnswerCardState answer_card_state = testing::get<1>(GetParam());
+      const AnswerCardState answer_card_state = GetParam();
       test_with_answer_card =
           answer_card_state != AnswerCardState::ANSWER_CARD_OFF;
       test_with_answer_card_result_ =
@@ -61,28 +60,11 @@
     }
 
     // Setting up the feature set.
-    if (test_with_fullscreen_) {
-      if (test_with_answer_card) {
-        scoped_feature_list_.InitWithFeatures(
-            {features::kEnableFullscreenAppList, features::kEnableAnswerCard},
-            {});
-      } else {
-        scoped_feature_list_.InitWithFeatures(
-            {features::kEnableFullscreenAppList},
-            {features::kEnableAnswerCard});
-      }
-    } else {
-      if (test_with_answer_card) {
-        scoped_feature_list_.InitWithFeatures(
-            {features::kEnableAnswerCard},
-            {features::kEnableFullscreenAppList});
-      } else {
-        scoped_feature_list_.InitWithFeatures(
-            {},
-            {features::kEnableFullscreenAppList, features::kEnableAnswerCard});
-      }
-    }
-    ASSERT_EQ(test_with_fullscreen_, features::IsFullscreenAppListEnabled());
+    if (test_with_answer_card)
+      scoped_feature_list_.InitAndEnableFeature(features::kEnableAnswerCard);
+    else
+      scoped_feature_list_.InitAndDisableFeature(features::kEnableAnswerCard);
+
     ASSERT_EQ(test_with_answer_card, features::IsAnswerCardEnabled());
 
     // Setting up views.
@@ -91,10 +73,6 @@
     AppListView::InitParams params;
     params.parent = GetContext();
     app_list_view_->Initialize(params);
-    // TODO(warx): remove MaybeSetAnchorPoint setup when bubble launcher is
-    // removed from code base.
-    app_list_view_->MaybeSetAnchorPoint(
-        params.parent->GetBoundsInRootWindow().CenterPoint());
     app_list_view_->GetWidget()->Show();
 
     ContentsView* contents_view =
@@ -172,7 +150,6 @@
     return view_->OnKeyPressed(event);
   }
 
-  bool test_with_fullscreen() const { return test_with_fullscreen_; }
   bool test_with_answer_card_result() const {
     return test_with_answer_card_result_;
   }
@@ -184,7 +161,6 @@
       nullptr;                                 // Owned by views hierarchy.
   SearchResultListView* list_view_ = nullptr;  // Owned by views hierarchy.
   std::unique_ptr<AppListTestViewDelegate> delegate_;
-  bool test_with_fullscreen_ = true;
   bool test_with_answer_card_result_ = true;
   base::test::ScopedFeatureList scoped_feature_list_;
 
@@ -196,58 +172,9 @@
 INSTANTIATE_TEST_CASE_P(
     ,
     SearchResultPageViewTest,
-    ::testing::Combine(
-        ::testing::Bool(),
-        ::testing::Values(AnswerCardState::ANSWER_CARD_OFF,
-                          AnswerCardState::ANSWER_CARD_ON_WITHOUT_RESULT,
-                          AnswerCardState::ANSWER_CARD_ON_WITH_RESULT)));
-
-// TODO(warx): This test applies to bubble launcher only. Remove this test once
-// bubble launcher is removed from code base.
-TEST_P(SearchResultPageViewTest, DirectionalMovement) {
-  if (test_with_fullscreen())
-    return;
-
-  SetUpFocusTestEnv();
-  EXPECT_EQ(0, GetSelectedIndex());
-  EXPECT_EQ(0, tile_list_view()->selected_index());
-
-  // Navigate to the second tile in the tile group.
-  EXPECT_TRUE(KeyPress(ui::VKEY_RIGHT));
-  EXPECT_EQ(0, GetSelectedIndex());
-  EXPECT_EQ(1, tile_list_view()->selected_index());
-  EXPECT_EQ(-1, list_view()->selected_index());
-
-  // Navigate to the list group.
-  EXPECT_TRUE(KeyPress(ui::VKEY_DOWN));
-  EXPECT_EQ(1, GetSelectedIndex());
-  EXPECT_EQ(-1, tile_list_view()->selected_index());
-  EXPECT_EQ(0, list_view()->selected_index());
-
-  // Navigate to the second result in the list view.
-  EXPECT_TRUE(KeyPress(ui::VKEY_DOWN));
-  EXPECT_EQ(1, GetSelectedIndex());
-  EXPECT_EQ(1, list_view()->selected_index());
-
-  // Attempt to navigate off bottom of list items.
-  EXPECT_FALSE(KeyPress(ui::VKEY_DOWN));
-  EXPECT_EQ(1, GetSelectedIndex());
-  EXPECT_EQ(1, list_view()->selected_index());
-
-  // Navigate back to the tile group (should select the first tile result).
-  EXPECT_TRUE(KeyPress(ui::VKEY_UP));
-  EXPECT_EQ(1, GetSelectedIndex());
-  EXPECT_EQ(0, list_view()->selected_index());
-  EXPECT_TRUE(KeyPress(ui::VKEY_UP));
-  EXPECT_EQ(0, GetSelectedIndex());
-  EXPECT_EQ(0, tile_list_view()->selected_index());
-  EXPECT_EQ(-1, list_view()->selected_index());
-
-  // Navigate off top of list.
-  EXPECT_FALSE(KeyPress(ui::VKEY_UP));
-  EXPECT_EQ(0, GetSelectedIndex());
-  EXPECT_EQ(0, tile_list_view()->selected_index());
-}
+    ::testing::Values(AnswerCardState::ANSWER_CARD_OFF,
+                      AnswerCardState::ANSWER_CARD_ON_WITHOUT_RESULT,
+                      AnswerCardState::ANSWER_CARD_ON_WITH_RESULT));
 
 TEST_P(SearchResultPageViewTest, TabMovement) {
   SetUpFocusTestEnv();
@@ -289,22 +216,12 @@
   EXPECT_EQ(-1, list_view()->selected_index());
 
   // Navigate off top of list.
-  if (test_with_fullscreen()) {
     EXPECT_TRUE(KeyPress(ui::VKEY_TAB, true));
     EXPECT_TRUE(KeyPress(ui::VKEY_TAB, true));
     EXPECT_FALSE(KeyPress(ui::VKEY_TAB, true));
     EXPECT_EQ(-1, GetSelectedIndex());
     EXPECT_EQ(-1, tile_list_view()->selected_index());
     EXPECT_EQ(-1, list_view()->selected_index());
-  } else {
-    EXPECT_TRUE(KeyPress(ui::VKEY_TAB, true));
-    EXPECT_EQ(1, tile_list_view()->selected_index());
-    EXPECT_TRUE(KeyPress(ui::VKEY_TAB, true));
-    EXPECT_EQ(0, tile_list_view()->selected_index());
-    EXPECT_FALSE(KeyPress(ui::VKEY_TAB, true));
-    EXPECT_EQ(0, GetSelectedIndex());
-    EXPECT_EQ(0, tile_list_view()->selected_index());
-  }
 }
 
 TEST_P(SearchResultPageViewTest, ResultsSorted) {
diff --git a/ui/app_list/views/search_result_tile_item_list_view_unittest.cc b/ui/app_list/views/search_result_tile_item_list_view_unittest.cc
index 0951214..7d3090c8 100644
--- a/ui/app_list/views/search_result_tile_item_list_view_unittest.cc
+++ b/ui/app_list/views/search_result_tile_item_list_view_unittest.cc
@@ -43,13 +43,10 @@
     // feature.
     if (IsPlayStoreAppSearchEnabled()) {
       scoped_feature_list_.InitWithFeatures(
-          {features::kEnableFullscreenAppList,
-           features::kEnablePlayStoreAppSearch},
-          {});
+          {features::kEnablePlayStoreAppSearch}, {});
     } else {
       scoped_feature_list_.InitWithFeatures(
-          {features::kEnableFullscreenAppList},
-          {features::kEnablePlayStoreAppSearch});
+          {}, {features::kEnablePlayStoreAppSearch});
     }
     ASSERT_EQ(IsPlayStoreAppSearchEnabled(),
               features::IsPlayStoreAppSearchEnabled());
diff --git a/ui/base/ime/input_method_chromeos.cc b/ui/base/ime/input_method_chromeos.cc
index 6519097..bfe3861 100644
--- a/ui/base/ime/input_method_chromeos.cc
+++ b/ui/base/ime/input_method_chromeos.cc
@@ -66,9 +66,22 @@
   DCHECK(event->IsKeyEvent());
   DCHECK(!(event->flags() & ui::EF_IS_SYNTHESIZED));
 
-  // The Caps Lock toggling has been removed from here, because now it is
-  // handled in accelerator controller.
-  // (see https://bugs.chromium.org/p/chromium/issues/detail?id=700705).
+  // For OS_CHROMEOS build of Chrome running on Linux, the IME keyboard cannot
+  // track the Caps Lock state by itself, so need to call SetCapsLockEnabled()
+  // method to reflect the Caps Lock state by the key event.
+  chromeos::input_method::InputMethodManager* manager =
+      chromeos::input_method::InputMethodManager::Get();
+  if (manager) {
+    chromeos::input_method::ImeKeyboard* keyboard = manager->GetImeKeyboard();
+    if (keyboard && event->type() == ET_KEY_PRESSED &&
+        event->key_code() != ui::VKEY_CAPITAL &&
+        keyboard->CapsLockIsEnabled() != event->IsCapsLockOn()) {
+      // Synchronize the keyboard state with event's state if they do not
+      // match. Do not synchronize for Caps Lock key because it is already
+      // handled in event rewriter.
+      keyboard->SetCapsLockEnabled(event->IsCapsLockOn());
+    }
+  }
 
   // If |context_| is not usable, then we can only dispatch the key event as is.
   // We only dispatch the key event to input method when the |context_| is an
diff --git a/ui/chromeos/events/event_rewriter_chromeos.cc b/ui/chromeos/events/event_rewriter_chromeos.cc
index 29bff27e..4ef27cc 100644
--- a/ui/chromeos/events/event_rewriter_chromeos.cc
+++ b/ui/chromeos/events/event_rewriter_chromeos.cc
@@ -796,9 +796,19 @@
       used_modifier_latches_ |= pressed_modifier_latches_;
       latched_modifier_latches_ = ui::EF_NONE;
     }
-    // The handling of Caps Lock toggling is now moved to accelerator
-    // controller.
-    // (see https://bugs.chromium.org/p/chromium/issues/detail?id=700705).
+  }
+
+  // Implement the Caps Lock modifier here, rather than in the
+  // AcceleratorController, so that the event is visible to apps (see
+  // crbug.com/775743).
+  if (key_event.type() == ui::ET_KEY_RELEASED &&
+      state->key_code == ui::VKEY_CAPITAL) {
+    ::chromeos::input_method::ImeKeyboard* ime_keyboard =
+        ime_keyboard_for_testing_
+            ? ime_keyboard_for_testing_
+            : ::chromeos::input_method::InputMethodManager::Get()
+                  ->GetImeKeyboard();
+    ime_keyboard->SetCapsLockEnabled(!ime_keyboard->CapsLockIsEnabled());
   }
   return exact_event;
 }
diff --git a/ui/gfx/geometry/mojo/geometry.mojom b/ui/gfx/geometry/mojo/geometry.mojom
index 9714386..fb257c1 100644
--- a/ui/gfx/geometry/mojo/geometry.mojom
+++ b/ui/gfx/geometry/mojo/geometry.mojom
@@ -4,11 +4,18 @@
 
 module gfx.mojom;
 
+// Don't make backwards-incompatible changes to this definition!
+// It's used in PageState serialization, so backwards incompatible changes
+// would cause stored PageState objects to be un-parseable.
 struct Point {
   int32 x;
   int32 y;
 };
 
+// Don't make backwards-incompatible changes to this definition!
+// It's used in PageState serialization, so backwards incompatible changes
+// would cause stored PageState objects to be un-parseable. Please contact the
+// page state serialization owners before making such a change.
 struct PointF {
   float x;
   float y;
diff --git a/ui/gfx/gpu_memory_buffer.cc b/ui/gfx/gpu_memory_buffer.cc
index 24e78217..5c05020 100644
--- a/ui/gfx/gpu_memory_buffer.cc
+++ b/ui/gfx/gpu_memory_buffer.cc
@@ -15,8 +15,7 @@
 
 GpuMemoryBufferHandle::~GpuMemoryBufferHandle() {}
 
-void GpuMemoryBuffer::SetColorSpaceForScanout(
-    const gfx::ColorSpace& color_space) {}
+void GpuMemoryBuffer::SetColorSpace(const gfx::ColorSpace& color_space) {}
 
 GpuMemoryBufferHandle CloneHandleForIPC(
     const GpuMemoryBufferHandle& source_handle) {
diff --git a/ui/gfx/gpu_memory_buffer.h b/ui/gfx/gpu_memory_buffer.h
index 0aded33b..87ebea26 100644
--- a/ui/gfx/gpu_memory_buffer.h
+++ b/ui/gfx/gpu_memory_buffer.h
@@ -88,8 +88,8 @@
   virtual int stride(size_t plane) const = 0;
 
   // Set the color space in which this buffer should be interpreted when used
-  // for scanout. Note that this will not impact texturing from the buffer.
-  virtual void SetColorSpaceForScanout(const gfx::ColorSpace& color_space);
+  // as an overlay. Note that this will not impact texturing from the buffer.
+  virtual void SetColorSpace(const gfx::ColorSpace& color_space);
 
   // Returns a unique identifier associated with buffer.
   virtual GpuMemoryBufferId GetId() const = 0;
diff --git a/ui/gl/BUILD.gn b/ui/gl/BUILD.gn
index d082bf9..131bd3e 100644
--- a/ui/gl/BUILD.gn
+++ b/ui/gl/BUILD.gn
@@ -442,6 +442,12 @@
   data_deps = [
     "//third_party/mesa:osmesa",
   ]
+
+  if (use_x11) {
+    sources += [ "gl_context_glx_unittest.cc" ]
+    deps += [ "//ui/gfx/x" ]
+    configs += [ "//build/config/linux:x11" ]
+  }
 }
 
 # We can't run this test on real Chrome OS hardware for Ozone, so new target.
diff --git a/ui/gl/gl_context.h b/ui/gl/gl_context.h
index aa1b2f0..79756a26 100644
--- a/ui/gl/gl_context.h
+++ b/ui/gl/gl_context.h
@@ -159,15 +159,6 @@
 
   GLShareGroup* share_group();
 
-  // Create a GL context that is compatible with the given surface.
-  // |share_group|, if non-NULL, is a group of contexts which the
-  // internally created OpenGL context shares textures and other resources.
-  // DEPRECATED(kylechar): Use gl::init::CreateGLContext from gl_factory.h.
-  static scoped_refptr<GLContext> CreateGLContext(
-      GLShareGroup* share_group,
-      GLSurface* compatible_surface,
-      GpuPreference gpu_preference);
-
   static bool LosesAllContextsOnContextLost();
 
   // Returns the last GLContext made current, virtual or real.
diff --git a/ui/gl/gl_context_glx.cc b/ui/gl/gl_context_glx.cc
index d66d3119..b185b2c 100644
--- a/ui/gl/gl_context_glx.cc
+++ b/ui/gl/gl_context_glx.cc
@@ -230,7 +230,6 @@
       reinterpret_cast<GLXDrawable>(surface->GetHandle()),
       static_cast<GLXContext>(context_))) {
     LOG(ERROR) << "Couldn't make context current with X drawable.";
-    Destroy();
     return false;
   }
 
@@ -242,7 +241,6 @@
 
   if (!surface->OnMakeCurrent(this)) {
     LOG(ERROR) << "Could not make current.";
-    Destroy();
     return false;
   }
 
diff --git a/ui/gl/gl_context_glx_unittest.cc b/ui/gl/gl_context_glx_unittest.cc
new file mode 100644
index 0000000..5b0a4276
--- /dev/null
+++ b/ui/gl/gl_context_glx_unittest.cc
@@ -0,0 +1,64 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ui/gl/gl_context_glx.h"
+
+#include "base/memory/scoped_refptr.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "ui/gfx/x/x11_error_tracker.h"
+#include "ui/gfx/x/x11_types.h"
+#include "ui/gl/gl_surface_glx_x11.h"
+#include "ui/gl/init/gl_factory.h"
+#include "ui/gl/test/gl_image_test_support.h"
+
+#include <X11/Xlib.h>
+
+namespace gl {
+
+TEST(GLContextGLXTest, DoNotDesrtroyOnFailedMakeCurrent) {
+  auto* xdisplay = gfx::GetXDisplay();
+  ASSERT_TRUE(xdisplay);
+
+  gfx::X11ErrorTracker error_tracker;
+
+  // Turn on sync behaviour, and create the window.
+  XSynchronize(xdisplay, True);
+  XSetWindowAttributes swa;
+  memset(&swa, 0, sizeof(swa));
+  swa.background_pixmap = 0;
+  swa.override_redirect = True;
+  auto xwindow = XCreateWindow(xdisplay, DefaultRootWindow(xdisplay), 0, 0, 10,
+                               10,              // x, y, width, height
+                               0,               // border width
+                               CopyFromParent,  // depth
+                               InputOutput,
+                               CopyFromParent,  // visual
+                               CWBackPixmap | CWOverrideRedirect, &swa);
+  XMapWindow(xdisplay, xwindow);
+
+  GLImageTestSupport::InitializeGL();
+  auto surface =
+      gl::InitializeGLSurface(base::MakeRefCounted<GLSurfaceGLXX11>(xwindow));
+  scoped_refptr<GLContext> context =
+      gl::init::CreateGLContext(nullptr, surface.get(), GLContextAttribs());
+  // Verify that MakeCurrent() is successful.
+  ASSERT_TRUE(context->GetHandle());
+  ASSERT_TRUE(context->MakeCurrent(surface.get()));
+  EXPECT_TRUE(context->GetHandle());
+
+  // Destroy the window, and turn off sync behaviour. We should get no x11
+  // errors so far.
+  context->ReleaseCurrent(surface.get());
+  XDestroyWindow(xdisplay, xwindow);
+  XSynchronize(xdisplay, False);
+  ASSERT_FALSE(error_tracker.FoundNewError());
+
+  // Now that the window is gone, MakeCurrent() should fail. But the context
+  // shouldn't be destroyed, and there should be some x11 errors captured.
+  EXPECT_FALSE(context->MakeCurrent(surface.get()));
+  ASSERT_TRUE(context->GetHandle());
+  EXPECT_TRUE(error_tracker.FoundNewError());
+}
+
+}  // namespace gl
diff --git a/ui/gl/gl_stub_api.cc b/ui/gl/gl_stub_api.cc
index e73f87a6..144bc30 100644
--- a/ui/gl/gl_stub_api.cc
+++ b/ui/gl/gl_stub_api.cc
@@ -133,12 +133,21 @@
     case GL_MAX_VARYING_VECTORS:
       *params = 8;
       break;
+    case GL_MAX_VARYING_FLOATS:
+      *params = 32;
+      break;
     case GL_MAX_VERTEX_UNIFORM_VECTORS:
       *params = 128;
       break;
+    case GL_MAX_VERTEX_UNIFORM_COMPONENTS:
+      *params = 512;
+      break;
     case GL_MAX_FRAGMENT_UNIFORM_VECTORS:
       *params = 16;
       break;
+    case GL_MAX_FRAGMENT_UNIFORM_COMPONENTS:
+      *params = 64;
+      break;
     case GL_MAX_VERTEX_OUTPUT_COMPONENTS:
       *params = 64;
       break;
diff --git a/ui/gl/test/run_all_unittests.cc b/ui/gl/test/run_all_unittests.cc
index 07d7020..a82cd7f0 100644
--- a/ui/gl/test/run_all_unittests.cc
+++ b/ui/gl/test/run_all_unittests.cc
@@ -28,7 +28,7 @@
 #if defined(USE_OZONE)
 class OzoneDrmTestService : public service_manager::Service {
  public:
-  OzoneDrmTestService() : factory_(this) {}
+  OzoneDrmTestService() = default;
   ~OzoneDrmTestService() override = default;
 
   service_manager::BinderRegistryWithArgs<
@@ -37,13 +37,6 @@
     return &registry_;
   }
 
-  service_manager::Connector* connector() {
-    if (!connector_) {
-      connector_ = factory_.CreateConnector();
-    }
-    return connector_.get();
-  }
-
   void OnBindInterface(const service_manager::BindSourceInfo& source_info,
                        const std::string& interface_name,
                        mojo::ScopedMessagePipeHandle interface_pipe) override {
@@ -56,7 +49,6 @@
       const service_manager::BindSourceInfo&>
       registry_;
 
-  service_manager::TestConnectorFactory factory_;
   std::unique_ptr<service_manager::Connector> connector_;
 
   DISALLOW_COPY_AND_ASSIGN(OzoneDrmTestService);
@@ -83,7 +75,14 @@
             base::test::ScopedTaskEnvironment::MainThreadType::UI);
 
 #if defined(USE_OZONE)
-    service_ = std::make_unique<OzoneDrmTestService>();
+    auto service_ptr = std::make_unique<OzoneDrmTestService>();
+    // |service| is valid as long as |connector_factory_| is valid.
+    OzoneDrmTestService* service = service_ptr.get();
+
+    connector_factory_ =
+        std::make_unique<service_manager::TestConnectorFactory>(
+            std::move(service_ptr));
+    connector_ = connector_factory_->CreateConnector();
 
     // Make Ozone run in single-process mode, where it doesn't expect a GPU
     // process and it spawns and starts its own DRM thread. Note that this mode
@@ -91,12 +90,12 @@
     // and GPU components.
     ui::OzonePlatform::InitParams params;
     params.single_process = true;
-    params.connector = service_->connector();
+    params.connector = connector_.get();
 
     // This initialization must be done after ScopedTaskEnvironment has
     // initialized the UI thread.
     ui::OzonePlatform::InitializeForUI(params);
-    ui::OzonePlatform::GetInstance()->AddInterfaces(service_->registry());
+    ui::OzonePlatform::GetInstance()->AddInterfaces(service->registry());
 #endif
   }
 
@@ -108,7 +107,8 @@
   std::unique_ptr<base::test::ScopedTaskEnvironment> scoped_task_environment_;
 
 #if defined(USE_OZONE)
-  std::unique_ptr<OzoneDrmTestService> service_;
+  std::unique_ptr<service_manager::TestConnectorFactory> connector_factory_;
+  std::unique_ptr<service_manager::Connector> connector_;
 #endif
 
   DISALLOW_COPY_AND_ASSIGN(GlTestSuite);
diff --git a/ui/keyboard/keyboard_controller.cc b/ui/keyboard/keyboard_controller.cc
index 42dad76..dc7f1c6 100644
--- a/ui/keyboard/keyboard_controller.cc
+++ b/ui/keyboard/keyboard_controller.cc
@@ -687,8 +687,7 @@
 
   DCHECK(error_message.str().empty())
       << "State: " << StateToStr(prev) << " -> " << StateToStr(next) << " "
-      << error_message.str()
-      << "  stack trace: " << base::debug::StackTrace(10).ToString();
+      << error_message.str();
 }
 
 void KeyboardController::ChangeState(KeyboardControllerState state) {
diff --git a/ui/keyboard/keyboard_util.cc b/ui/keyboard/keyboard_util.cc
index 7cacbce..356253966 100644
--- a/ui/keyboard/keyboard_util.cc
+++ b/ui/keyboard/keyboard_util.cc
@@ -7,6 +7,7 @@
 #include <string>
 
 #include "base/command_line.h"
+#include "base/feature_list.h"
 #include "base/lazy_instance.h"
 #include "base/logging.h"
 #include "base/metrics/histogram_macros.h"
@@ -189,7 +190,7 @@
 }
 
 bool IsFloatingVirtualKeyboardEnabled() {
-  return false;
+  return base::FeatureList::IsEnabled(features::kEnableFloatingVirtualKeyboard);
 }
 
 bool IsGestureTypingEnabled() {
diff --git a/ui/login/account_picker/user_pod_row.js b/ui/login/account_picker/user_pod_row.js
index 9dc625f..9ad05d0 100644
--- a/ui/login/account_picker/user_pod_row.js
+++ b/ui/login/account_picker/user_pod_row.js
@@ -2469,7 +2469,7 @@
 
     /** @override */
     get mainInput() {
-      if (this.user.needsSignin)
+      if (this.user.needsSignin && this.user.hasLocalCreds)
         return this.passwordElement;
       else
         return this.nameElement;
diff --git a/ui/views/controls/button/blue_button_unittest.cc b/ui/views/controls/button/blue_button_unittest.cc
index 657f5bfa..f516f44 100644
--- a/ui/views/controls/button/blue_button_unittest.cc
+++ b/ui/views/controls/button/blue_button_unittest.cc
@@ -51,17 +51,6 @@
 
   widget->GetContentsView()->AddChildView(blue_button);
   blue_button->SizeToPreferredSize();
-#if defined(OS_MACOSX)
-  // On Mac, themed STYLE_BUTTON buttons provide blue theming for dialog-default
-  // buttons. This makes it unlikely that they will appear together with a
-  // BlueButton on the same dialog. So the sizes don't really need to be
-  // consistent. However, for the purposes of this test (e.g. to ensure we don't
-  // accidentally make BlueButtons look like themed buttons on Mac), force the
-  // sizes to match (ignoring the minimum size) so that the bitmaps can be
-  // compared.
-  EXPECT_NE(button->size(), blue_button->size());  // Verify this is needed.
-  blue_button->SetSize(button->size());
-#endif
 
   SkBitmap blue_button_bitmap;
   blue_button_bitmap.allocN32Pixels(blue_button->size().width(),
diff --git a/ui/views/controls/button/label_button.cc b/ui/views/controls/button/label_button.cc
index 1303690..779744b 100644
--- a/ui/views/controls/button/label_button.cc
+++ b/ui/views/controls/button/label_button.cc
@@ -189,7 +189,7 @@
   label.SetLineHeight(label_->line_height());
   label.SetShadows(label_->shadows());
 
-  if (style_ == STYLE_BUTTON && PlatformStyle::kDefaultLabelButtonHasBoldFont) {
+  if (style_ == STYLE_BUTTON) {
     // Some text appears wider when rendered normally than when rendered bold.
     // Accommodate the widest, as buttons may show bold and shouldn't resize.
     const int current_width = label.GetPreferredSize().width();
@@ -468,13 +468,11 @@
   // never be given default status.
   DCHECK_EQ(cached_normal_font_list_.GetFontSize(),
             label()->font_list().GetFontSize());
-  const bool bold =
-      PlatformStyle::kDefaultLabelButtonHasBoldFont && is_default_;
   // TODO(tapted): This should use style::GetFont(), but this part can just be
   // deleted when default buttons no longer go bold. Colors will need updating
   // still.
-  label_->SetFontList(bold ? cached_default_button_font_list_
-                           : cached_normal_font_list_);
+  label_->SetFontList(is_default_ ? cached_default_button_font_list_
+                                  : cached_normal_font_list_);
   InvalidateLayout();
   ResetLabelEnabledColor();
 }
@@ -547,10 +545,7 @@
 }
 
 void LabelButton::ResetLabelEnabledColor() {
-  const SkColor color =
-      explicitly_set_colors_[state()]
-          ? button_state_colors_[state()]
-          : PlatformStyle::TextColorForButton(button_state_colors_, *this);
+  const SkColor color = button_state_colors_[state()];
   if (state() != STATE_DISABLED && label_->enabled_color() != color)
     label_->SetEnabledColor(color);
 }
diff --git a/ui/views/controls/button/label_button_unittest.cc b/ui/views/controls/button/label_button_unittest.cc
index 74b34b03..fa13a76 100644
--- a/ui/views/controls/button/label_button_unittest.cc
+++ b/ui/views/controls/button/label_button_unittest.cc
@@ -97,8 +97,6 @@
     styled_highlight_text_color_ = styled_normal_text_color_ =
         button_->GetNativeTheme()->GetSystemColor(
             ui::NativeTheme::kColorId_ButtonEnabledColor);
-#elif defined(OS_MACOSX)
-    styled_highlight_text_color_ = SK_ColorWHITE;
 #else
     styled_highlight_text_color_ = styled_normal_text_color_;
 #endif
@@ -398,26 +396,13 @@
   button->SizeToPreferredSize();
   button->Layout();
   EXPECT_EQ(styled_highlight_text_color_, button->label()->enabled_color());
-  if (PlatformStyle::kDefaultLabelButtonHasBoldFont) {
-    EXPECT_NE(non_default_size, button->label()->size());
-    EXPECT_EQ(button->label()->font_list().GetFontWeight(),
-              gfx::Font::Weight::BOLD);
-  } else {
-    EXPECT_EQ(non_default_size, button->label()->size());
-    EXPECT_EQ(button->label()->font_list().GetFontWeight(),
-              gfx::Font::Weight::NORMAL);
-  }
+  EXPECT_NE(non_default_size, button->label()->size());
+  EXPECT_EQ(button->label()->font_list().GetFontWeight(),
+            gfx::Font::Weight::BOLD);
 }
 
 // Ensure the label gets the correct style when pressed or becoming default.
 TEST_F(LabelButtonTest, HighlightedButtonStyle) {
-#if defined(OS_MACOSX)
-  // On Mac, ensure the normal and highlight colors are different, to ensure the
-  // tests are actually testing something. This might be the case on other
-  // platforms.
-  EXPECT_NE(styled_normal_text_color_, styled_highlight_text_color_);
-#endif
-
   // For STYLE_TEXTBUTTON, the NativeTheme might not provide SK_ColorBLACK, but
   // it should be the same for normal and pressed states.
   EXPECT_EQ(themed_normal_text_color_, button_->label()->enabled_color());
diff --git a/ui/views/style/platform_style.cc b/ui/views/style/platform_style.cc
index 648a5ac..1b0a90c 100644
--- a/ui/views/style/platform_style.cc
+++ b/ui/views/style/platform_style.cc
@@ -25,7 +25,7 @@
 namespace views {
 namespace {
 
-#if !defined(DESKTOP_LINUX) && !defined(OS_MACOSX)
+#if !defined(DESKTOP_LINUX)
 // Default text and shadow colors for STYLE_BUTTON.
 const SkColor kStyleButtonTextColor = SK_ColorBLACK;
 const SkColor kStyleButtonShadowColor = SK_ColorWHITE;
@@ -37,7 +37,6 @@
 
 const int PlatformStyle::kMinLabelButtonWidth = 70;
 const int PlatformStyle::kMinLabelButtonHeight = 33;
-const bool PlatformStyle::kDefaultLabelButtonHasBoldFont = true;
 const bool PlatformStyle::kDialogDefaultButtonCanBeCancel = true;
 const bool PlatformStyle::kSelectWordOnRightClick = false;
 const bool PlatformStyle::kSelectAllOnRightClickWhenUnfocused = false;
@@ -61,18 +60,11 @@
 }
 
 // static
-SkColor PlatformStyle::TextColorForButton(
-    const ButtonColorByState& color_by_state,
-    const LabelButton& button) {
-  return color_by_state[button.state()];
-}
-
-// static
 void PlatformStyle::OnTextfieldEditFailed() {}
 
 #endif  // OS_MACOSX
 
-#if !defined(DESKTOP_LINUX) && !defined(OS_MACOSX)
+#if !defined(DESKTOP_LINUX)
 // static
 void PlatformStyle::ApplyLabelButtonTextStyle(
     Label* label,
diff --git a/ui/views/style/platform_style.h b/ui/views/style/platform_style.h
index 255fd5b..1fde617 100644
--- a/ui/views/style/platform_style.h
+++ b/ui/views/style/platform_style.h
@@ -28,9 +28,6 @@
   static const int kMinLabelButtonWidth;
   static const int kMinLabelButtonHeight;
 
-  // Whether dialog-default buttons are given a bold font style.
-  static const bool kDefaultLabelButtonHasBoldFont;
-
   // Whether the default button for a dialog can be the Cancel button.
   static const bool kDialogDefaultButtonCanBeCancel;
 
@@ -68,10 +65,6 @@
   // Creates the default scrollbar for the given orientation.
   static std::unique_ptr<ScrollBar> CreateScrollBar(bool is_horizontal);
 
-  // Returns the current text color for the current button state.
-  static SkColor TextColorForButton(const ButtonColorByState& color_by_state,
-                                    const LabelButton& button);
-
   // Applies platform styles to |label| and fills |color_by_state| with the text
   // colors for normal, pressed, hovered, and disabled states, if the colors for
   // Button::STYLE_BUTTON buttons differ from those provided by ui::NativeTheme.
diff --git a/ui/views/style/platform_style_mac.mm b/ui/views/style/platform_style_mac.mm
index 979d07b1..ee6da44 100644
--- a/ui/views/style/platform_style_mac.mm
+++ b/ui/views/style/platform_style_mac.mm
@@ -16,7 +16,6 @@
 
 const int PlatformStyle::kMinLabelButtonWidth = 32;
 const int PlatformStyle::kMinLabelButtonHeight = 30;
-const bool PlatformStyle::kDefaultLabelButtonHasBoldFont = false;
 const bool PlatformStyle::kDialogDefaultButtonCanBeCancel = false;
 const bool PlatformStyle::kSelectWordOnRightClick = true;
 const bool PlatformStyle::kSelectAllOnRightClickWhenUnfocused = true;
@@ -46,27 +45,6 @@
 }
 
 // static
-SkColor PlatformStyle::TextColorForButton(
-    const ButtonColorByState& color_by_state,
-    const LabelButton& button) {
-  Button::ButtonState state = button.state();
-  if (button.style() == Button::STYLE_BUTTON && button.is_default()) {
-    // For convenience, we currently assume Mac wants the color corresponding to
-    // the pressed state for default buttons.
-    state = Button::STATE_PRESSED;
-  }
-  return color_by_state[state];
-}
-
-// static
-void PlatformStyle::ApplyLabelButtonTextStyle(
-    views::Label* label,
-    ButtonColorByState* color_by_state) {
-  ButtonColorByState& colors = *color_by_state;
-  colors[Button::STATE_PRESSED] = SK_ColorWHITE;
-}
-
-// static
 void PlatformStyle::OnTextfieldEditFailed() {
   NSBeep();
 }
diff --git a/ui/views/view.cc b/ui/views/view.cc
index 8a601800..0b91b86 100644
--- a/ui/views/view.cc
+++ b/ui/views/view.cc
@@ -2064,6 +2064,13 @@
   gfx::Canvas* canvas = recorder.canvas();
   const float scale = canvas->UndoDeviceScaleFactor();
   gfx::RectF outline_rect(ScaleToEnclosedRect(GetLocalBounds(), scale));
+  gfx::RectF content_outline_rect(
+      ScaleToEnclosedRect(GetContentsBounds(), scale));
+  if (content_outline_rect != outline_rect) {
+    content_outline_rect.Inset(0.5f, 0.5f);
+    const SkColor content_color = SkColorSetARGB(0x30, 0, 0, 0xff);
+    canvas->DrawRect(content_outline_rect, content_color);
+  }
   outline_rect.Inset(0.5f, 0.5f);
   const SkColor color = SkColorSetARGB(0x30, 0xff, 0, 0);
   canvas->DrawRect(outline_rect, color);
diff --git a/ui/views/widget/desktop_aura/desktop_window_tree_host_x11.cc b/ui/views/widget/desktop_aura/desktop_window_tree_host_x11.cc
index 0933ddb..eaede7b 100644
--- a/ui/views/widget/desktop_aura/desktop_window_tree_host_x11.cc
+++ b/ui/views/widget/desktop_aura/desktop_window_tree_host_x11.cc
@@ -974,7 +974,7 @@
 }
 
 bool DesktopWindowTreeHostX11::ShouldWindowContentsBeTransparent() const {
-  return false;
+  return use_argb_visual_;
 }
 
 void DesktopWindowTreeHostX11::FrameTypeChanged() {
diff --git a/ui/views/window/dialog_delegate_unittest.cc b/ui/views/window/dialog_delegate_unittest.cc
index 98ef4b80..e3eefef 100644
--- a/ui/views/window/dialog_delegate_unittest.cc
+++ b/ui/views/window/dialog_delegate_unittest.cc
@@ -309,6 +309,16 @@
   dialog2->set_title(base::ASCIIToUTF16("Title"));
   DialogDelegate::CreateDialogWidget(dialog2, GetContext(), nullptr);
 
+  // Remove the close button so it doesn't influence the bounds if it's taller
+  // than the title.
+  dialog()->set_show_close_button(false);
+  dialog2->set_show_close_button(false);
+  dialog()->GetWidget()->non_client_view()->ResetWindowControls();
+  dialog2->GetWidget()->non_client_view()->ResetWindowControls();
+
+  EXPECT_FALSE(dialog()->ShouldShowWindowTitle());
+  EXPECT_TRUE(dialog2->ShouldShowWindowTitle());
+
   // Titled dialogs have taller initial frame bounds than untitled dialogs.
   View* frame1 = dialog()->GetWidget()->non_client_view()->frame_view();
   View* frame2 = dialog2->GetWidget()->non_client_view()->frame_view();
@@ -317,6 +327,8 @@
 
   // Giving the default test dialog a title will yield the same bounds.
   dialog()->set_title(base::ASCIIToUTF16("Title"));
+  EXPECT_TRUE(dialog()->ShouldShowWindowTitle());
+
   dialog()->GetWidget()->UpdateWindowTitle();
   EXPECT_EQ(frame1->GetPreferredSize().height(),
             frame2->GetPreferredSize().height());
diff --git a/ui/webui/resources/cr_components/chromeos/bluetooth_dialog.html b/ui/webui/resources/cr_components/chromeos/bluetooth_dialog.html
index a89ba4d5..f23adbe 100644
--- a/ui/webui/resources/cr_components/chromeos/bluetooth_dialog.html
+++ b/ui/webui/resources/cr_components/chromeos/bluetooth_dialog.html
@@ -71,7 +71,7 @@
     <!-- TODO(stevenjb/dschuyler): Find a solution to support i18n{} here -->
     <dialog is="cr-dialog" id="dialog" on-cancel="onDialogCanceled_"
         close-text="[[i18n('close')]]" on-closed="onDialogCanceled_">
-      <div slot="title">[[title]]</div>
+      <div slot="title">[[dialogTitle]]</div>
       <div slot="body">
         <div class="contents layout vertical center center-justified">
           <template is="dom-if" if="[[!errorMessage_]]">
diff --git a/ui/webui/resources/cr_components/chromeos/bluetooth_dialog.js b/ui/webui/resources/cr_components/chromeos/bluetooth_dialog.js
index b061349..dfd2942 100644
--- a/ui/webui/resources/cr_components/chromeos/bluetooth_dialog.js
+++ b/ui/webui/resources/cr_components/chromeos/bluetooth_dialog.js
@@ -37,7 +37,7 @@
     },
 
     /** Dialog title */
-    title: String,
+    dialogTitle: String,
 
     /**
      * Current Pairing device.
diff --git a/ui/webui/resources/cr_components/chromeos/network/compiled_resources2.gyp b/ui/webui/resources/cr_components/chromeos/network/compiled_resources2.gyp
index bb4d984..16bf315a 100644
--- a/ui/webui/resources/cr_components/chromeos/network/compiled_resources2.gyp
+++ b/ui/webui/resources/cr_components/chromeos/network/compiled_resources2.gyp
@@ -98,5 +98,17 @@
       'target_name': 'network_proxy_exclusions',
       'includes': ['../../../../../../third_party/closure_compiler/compile_js2.gypi'],
     },
+    {
+      'target_name': 'network_siminfo',
+      'dependencies': [
+        '<(DEPTH)/third_party/polymer/v1_0/components-chromium/paper-input/compiled_resources2.gyp:paper-input-extracted',
+        '<(DEPTH)/ui/webui/resources/cr_elements/chromeos/network/compiled_resources2.gyp:cr_onc_types',
+        '<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:assert',
+        '<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:i18n_behavior',
+        '<(DEPTH)/ui/webui/resources/js/cr/ui/compiled_resources2.gyp:focus_without_ink',
+        '<(INTERFACES_GYP):networking_private_interface',
+      ],
+      'includes': ['../../../../../../third_party/closure_compiler/compile_js2.gypi'],
+    },
   ],
 }
diff --git a/ui/webui/resources/cr_components/chromeos/network/network_config.html b/ui/webui/resources/cr_components/chromeos/network/network_config.html
index ec6441d..94b151c 100644
--- a/ui/webui/resources/cr_components/chromeos/network/network_config.html
+++ b/ui/webui/resources/cr_components/chromeos/network/network_config.html
@@ -10,9 +10,10 @@
 <dom-module id="network-config">
   <template>
     <style include="network-shared">
-      paper-toggle-button {
-        -webkit-margin-end: calc(
-          var(--network-control-margin) - var(--cr-icon-ripple-padding));
+      .property-box {
+        /* Align the toggle controls with the show/hide password icon. */
+        width: calc(var(--network-control-width) +
+            var(--network-control-margin) + 4px);
       }
 
       #error {
@@ -21,18 +22,6 @@
       }
     </style>
 
-    <!-- Share (WiFi and WiMAX) -->
-    <template is="dom-if" if="[[shareIsVisible_(type)]]">
-      <div class="property-box hr">
-        <div id="shareLabel" class="start">[[i18n('networkConfigShare')]]</div>
-        <paper-toggle-button id="share" checked="{{shareNetwork_}}"
-            disabled="[[!shareIsEnabled_(guid, configProperties_.*,
-                security_, eapProperties_.*, shareAllowEnable)]]"
-            aria-label="[[i18n('networkConfigShare')]]">
-        </paper-toggle-button>
-      </div>
-    </template>
-
     <!-- SSID (WiFi) -->
     <template is="dom-if" if="[[isType_(NetworkType_.WI_FI, type)]]">
       <network-config-input id="ssid" label="[[i18n('OncWiFi-SSID')]]"
@@ -108,7 +97,7 @@
             cert-list>
         </network-config-select>
       </template>
-      <div class="property-box hr">
+      <div class="property-box">
         <div id="vpnSaveCredentialsLabel" class="start">
           [[i18n('networkConfigSaveCredentials')]]
         </div>
@@ -152,7 +141,7 @@
           value="{{eapProperties_.AnonymousIdentity}}"
           hidden="[[!showEap_.AnonymousIdentity]]">
       </network-config-input>
-      <div class="property-box hr">
+      <div class="property-box">
         <div id="eapSaveCredentialsLabel" class="start">
           [[i18n('networkConfigSaveCredentials')]]
         </div>
@@ -162,6 +151,18 @@
       </div>
     </template>
 
+    <!-- Share (WiFi and WiMAX) -->
+    <template is="dom-if" if="[[shareIsVisible_(type)]]">
+      <div class="property-box">
+        <div id="shareLabel" class="start">[[i18n('networkConfigShare')]]</div>
+        <paper-toggle-button id="share" checked="{{shareNetwork_}}"
+            disabled="[[!shareIsEnabled_(guid, configProperties_.*,
+                      security_, eapProperties_.*, shareAllowEnable)]]"
+            aria-label="[[i18n('networkConfigShare')]]">
+        </paper-toggle-button>
+      </div>
+    </template>
+
     <template is="dom-if" if="[[error_]]">
       <div class="property-box">
         <div id="error" class="start">
diff --git a/ui/webui/resources/cr_components/chromeos/network/network_config.js b/ui/webui/resources/cr_components/chromeos/network/network_config.js
index 197baf2..1007973 100644
--- a/ui/webui/resources/cr_components/chromeos/network/network_config.js
+++ b/ui/webui/resources/cr_components/chromeos/network/network_config.js
@@ -8,11 +8,9 @@
  * and existing networks.
  */
 
-(function() {
-'use strict';
-
 /**
  * Combinaiton of CrOnc.VPNType + AuthenticationType for IPsec.
+ * Note: closure does not always recognize this if inside function() {}.
  * @enum {string}
  */
 var VPNConfigType = {
@@ -21,6 +19,9 @@
   OPEN_VPN: 'OpenVPN',
 };
 
+(function() {
+'use strict';
+
 /** @const */ var DEFAULT_HASH = 'default';
 /** @const */ var DO_NOT_CHECK_HASH = 'do-not-check';
 
diff --git a/ui/webui/resources/cr_components/chromeos/network/network_config_input.html b/ui/webui/resources/cr_components/chromeos/network/network_config_input.html
index 7527795..fbf773e0 100644
--- a/ui/webui/resources/cr_components/chromeos/network/network_config_input.html
+++ b/ui/webui/resources/cr_components/chromeos/network/network_config_input.html
@@ -10,6 +10,9 @@
   <template>
     <style include="network-shared">
       paper-input-container {
+        --paper-input-container-color: var(--secondary-text-color);
+        --paper-input-container-focus-color: var(--secondary-text-color);
+        --paper-input-container-input-color: var(--primary-text-color);
         -webkit-margin-end: var(--network-control-margin);
       }
 
@@ -19,9 +22,9 @@
       }
     </style>
 
-    <div class="property-box hr">
-      <div id="label" class="start">[[label]]</div>
-      <paper-input-container no-label-float>
+    <div class="property-box two-line">
+      <paper-input-container always-float-label>
+        <label id="label">[[label]]</label>
         <input is="iron-input" value="{{value::change}}"
             disabled="[[disabled]]" aria-label$="[[label]]"
             type="[[getInputType_(password, showPassword)]]">
diff --git a/ui/webui/resources/cr_components/chromeos/network/network_config_select.html b/ui/webui/resources/cr_components/chromeos/network/network_config_select.html
index 4c0008f..56e789d 100644
--- a/ui/webui/resources/cr_components/chromeos/network/network_config_select.html
+++ b/ui/webui/resources/cr_components/chromeos/network/network_config_select.html
@@ -5,23 +5,33 @@
 <dom-module id="network-config-select">
   <template>
     <style include="network-shared md-select">
+      #label {
+        color: var(--secondary-text-color);
+      }
+
       .md-select {
-        -webkit-margin-end: calc(
-            var(--network-control-margin) - var(--cr-icon-ripple-padding) * 2);
+        color: var(--primary-text-color);
+      }
+
+      .md-select-wrapper {
+        -webkit-margin-start: calc(var(--md-select-side-padding) * -1);
       }
     </style>
 
-    <div class="property-box hr">
-      <div id="label" class="start">[[label]]</div>
-      <select class="md-select" disabled="[[disabled]]"
-          value="{{value::change}}" aria-label$="[[label]]">
-        <template is="dom-repeat" items="[[items]]">
-          <option value="[[getItemValue_(item)]]"
-              disabled="[[!getItemEnabled_(item)]]">
-            [[getItemLabel_(item, oncPrefix)]]
-          </option>
-        </template>
-      </select>
+    <div class="property-box two-line single-column">
+      <div id="label">[[label]]</div>
+      <div class="md-select-wrapper">
+        <select class="md-select" disabled="[[disabled]]"
+            value="{{value::change}}" aria-label$="[[label]]">
+          <template is="dom-repeat" items="[[items]]">
+            <option value="[[getItemValue_(item)]]"
+                disabled="[[!getItemEnabled_(item)]]">
+              [[getItemLabel_(item, oncPrefix)]]
+            </option>
+          </template>
+        </select>
+        <span class="md-select-underline"></span>
+      </div>
     </div>
 
   </template>
diff --git a/ui/webui/resources/cr_components/chromeos/network/network_shared_css.html b/ui/webui/resources/cr_components/chromeos/network/network_shared_css.html
index 14c5305..5bf2051 100644
--- a/ui/webui/resources/cr_components/chromeos/network/network_shared_css.html
+++ b/ui/webui/resources/cr_components/chromeos/network/network_shared_css.html
@@ -7,7 +7,7 @@
   <template>
     <style include="cr-shared-style md-select">
       :root {
-        --network-control-width: 250px;
+        --network-control-width: 350px;
         /* Margin for the show/hide password icon */
         --network-control-margin: 40px;
       }
@@ -62,10 +62,10 @@
 
       paper-input-container {
         --paper-input-container-input: {
-          color: var(--paper-grey-600);
           font-size: inherit;
           font-weight: 400;
         };
+        --paper-input-container-input-color: var(--secondary-text-color);
         margin-bottom: 0;
         margin-top: -9px;
         width: var(--network-control-width);
diff --git a/ui/webui/resources/cr_components/chromeos/network/network_siminfo.html b/ui/webui/resources/cr_components/chromeos/network/network_siminfo.html
new file mode 100644
index 0000000..e9e6ecb4
--- /dev/null
+++ b/ui/webui/resources/cr_components/chromeos/network/network_siminfo.html
@@ -0,0 +1,191 @@
+<link rel="import" href="chrome://resources/html/polymer.html">
+
+<link rel="import" href="chrome://resources/cr_elements/chromeos/network/cr_onc_types.html">
+<link rel="import" href="chrome://resources/cr_elements/cr_dialog/cr_dialog.html">
+<link rel="import" href="chrome://resources/cr_elements/icons.html">
+<link rel="import" href="chrome://resources/html/assert.html">
+<link rel="import" href="chrome://resources/html/cr/ui/focus_without_ink.html">
+<link rel="import" href="chrome://resources/html/i18n_behavior.html">
+<link rel="import" href="chrome://resources/polymer/v1_0/iron-a11y-keys/iron-a11y-keys.html">
+<link rel="import" href="chrome://resources/polymer/v1_0/iron-flex-layout/iron-flex-layout-classes.html">
+<link rel="import" href="chrome://resources/polymer/v1_0/iron-icon/iron-icon.html">
+<link rel="import" href="chrome://resources/polymer/v1_0/paper-button/paper-button.html">
+<link rel="import" href="chrome://resources/polymer/v1_0/paper-input/paper-input.html">
+<link rel="import" href="chrome://resources/polymer/v1_0/paper-toggle-button/paper-toggle-button.html">
+<link rel="import" href="network_shared_css.html">
+
+<dom-module id="network-siminfo">
+  <template>
+    <style include="network-shared iron-flex">
+      iron-icon {
+       -webkit-margin-end: 10px;
+      }
+
+      .dialog-error {
+        color: red;
+        font-size: 125%;
+        font-weight: 500;
+        margin-top: 10px;
+      }
+
+      .error {
+        color: red;
+        font-weight: 500;
+      }
+
+      .pin {
+        min-width: 100px;
+      }
+
+      .puk {
+        min-width: 200px;
+      }
+
+      paper-toggle-button {
+        -webkit-margin-start: var(--cr-button-edge-spacing);
+      }
+    </style>
+
+    <!-- SIM missing UI -->
+    <div class="property-box two-line"
+        hidden$="[[networkProperties.Cellular.SIMPresent]]">
+      <div class="start layout horizontal center">
+        <iron-icon icon="cr:sim-card-alert"></iron-icon>
+        <div class="error">[[i18n('networkSimCardMissing')]]</div>
+      </div>
+    </div>
+
+    <!-- SIM locked -->
+    <div class="property-box two-line"
+        hidden$="[[!showSimLocked_(networkProperties)]]">
+      <div class="start layout horizontal center">
+        <iron-icon icon="cr:sim-lock"></iron-icon>
+        <div class="error">[[i18n('networkSimCardLocked')]]</div>
+      </div>
+      <div class="separator"></div>
+      <paper-button id="unlockPinButton" on-tap="onUnlockPinTap_">
+        [[i18n('networkSimUnlock')]]
+      </paper-button>
+    </div>
+
+    <!-- SIM unlocked -->
+    <div class="property-box two-line"
+        hidden$="[[!showSimUnlocked_(networkProperties)]]">
+      <div id="simLockToggleLabel" class="start">
+        [[i18n('networkSimLockEnable')]]
+      </div>
+      <paper-button id="changePinButton" on-tap="onChangePinTap_"
+          hidden$="[[!networkProperties.Cellular.SIMLockStatus.LockEnabled]]">
+        [[i18n('networkSimChangePin')]]
+      </paper-button>
+      <paper-toggle-button id="simLockButton"
+          on-change="onSimLockEnabledChange_" checked="{{lockEnabled_}}"
+          aria-labelledby="simLockToggleLabel">
+      </paper-toggle-button>
+    </div>
+
+    <!-- Enter PIN dialog -->
+    <dialog is="cr-dialog" id="enterPinDialog" close-text="[[i18n('close')]]"
+        on-cancel="onEnterPinDialogCancel_"
+        on-close="onEnterPinDialogClose_">
+      <div slot="title">[[i18n('networkSimEnterPinTitle')]]</div>
+      <div slot="body">
+        <paper-input id="enterPin" class="pin" no-label-float autofocus
+            label="[[i18n('networkSimEnterPin')]]">
+          <iron-a11y-keys keys="enter" on-keys-pressed="sendEnterPin_">
+          </iron-a11y-keys>
+        </paper-input>
+        <div class="dialog-error">
+          [[getErrorMsg_(error_, networkProperties)]]
+        </div>
+      </div>
+      <div slot="button-container">
+        <paper-button on-tap="sendEnterPin_">
+          [[i18n('networkSimEnter')]]
+        </paper-button>
+      </div>
+    </dialog>
+
+    <!-- Change PIN dialog -->
+    <dialog is="cr-dialog" id="changePinDialog" close-text="[[i18n('close')]]"
+        on-close="onChangePinDialogClose_">
+      <div slot="title">[[i18n('networkSimChangePinTitle')]]</div>
+      <div slot="body">
+        <paper-input id="changePinOld" class="pin" no-label-float autofocus
+            label="[[i18n('networkSimEnterOldPin')]]">
+        </paper-input>
+        <paper-input id="changePinNew1" class="pin" no-label-float
+            label="[[i18n('networkSimEnterNewPin')]]">
+        </paper-input>
+        <paper-input id="changePinNew2" class="pin" no-label-float
+            label="[[i18n('networkSimReEnterNewPin')]]">
+          <iron-a11y-keys keys="enter" on-keys-pressed="sendChangePin_">
+          </iron-a11y-keys>
+        </paper-input>
+        <div class="dialog-error">
+          [[getErrorMsg_(error_, networkProperties)]]
+        </div>
+      </div>
+      <div slot="button-container">
+        <paper-button on-tap="sendChangePin_">
+          [[i18n('networkSimChange')]]
+        </paper-button>
+      </div>
+    </dialog>
+
+    <!-- Unlock PIN dialog -->
+    <dialog is="cr-dialog" id="unlockPinDialog" close-text="[[i18n('close')]]"
+        on-close="onUnlockPinDialogClose_">
+      <div slot="title">[[i18n('networkSimLockedTitle')]]</div>
+      <div slot="body">
+        <paper-input id="unlockPin" class="pin" no-label-float autofocus
+            label="[[i18n('networkSimEnterPin')]]">
+          <iron-a11y-keys keys="enter" on-keys-pressed="sendUnlockPin_">
+          </iron-a11y-keys>
+        </paper-input>
+        <div class="dialog-error">
+          [[getErrorMsg_(error_, networkProperties)]]
+        </div>
+      </div>
+      <div slot="button-container">
+        <paper-button on-tap="sendUnlockPin_">
+          [[i18n('networkSimUnlock')]]
+        </paper-button>
+      </div>
+    </dialog>
+
+    <!-- Unlock PUK dialog -->
+    <dialog is="cr-dialog" id="unlockPukDialog" close-text="[[i18n('close')]]"
+        on-close="onUnlockPinDialogClose_">
+      <div slot="title">[[i18n('networkSimLockedTitle')]]</div>
+      <div slot="body">
+        <div>
+          Enter the 8-digit PIN Unblocking Key provided by your carrier
+        </div>
+        <paper-input id="unlockPuk" class="puk" no-label-float autofocus
+            label="[[i18n('networkSimEnterPuk')]]">
+        </paper-input>
+        <paper-input id="unlockPin1" class="pin" no-label-float
+            label="[[i18n('networkSimEnterNewPin')]]">
+        </paper-input>
+        <paper-input id="unlockPin2" class="pin" no-label-float
+            label="[[i18n('networkSimReEnterNewPin')]]">
+          <iron-a11y-keys keys="enter" on-keys-pressed="sendUnlockPuk_">
+          </iron-a11y-keys>
+        </paper-input>
+        <div class="dialog-error">
+          [[i18n('networkSimLockedWarning')]]
+        </div>
+        <div class="dialog-error">
+          [[getErrorMsg_(error_, networkProperties)]]
+        </div>
+      </div>
+      <div slot="button-container">
+        <paper-button on-tap="sendUnlockPuk_">
+          [[i18n('networkSimUnlock')]]
+        </paper-button>
+      </div>
+    </dialog>
+  </template>
+  <script src="network_siminfo.js"></script>
+</dom-module>
diff --git a/ui/webui/resources/cr_components/chromeos/network/network_siminfo.js b/ui/webui/resources/cr_components/chromeos/network/network_siminfo.js
new file mode 100644
index 0000000..62e270d
--- /dev/null
+++ b/ui/webui/resources/cr_components/chromeos/network/network_siminfo.js
@@ -0,0 +1,404 @@
+// 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.
+
+/**
+ * @fileoverview Polymer element for displaying and modifying cellular sim info.
+ */
+(function() {
+
+/** @enum {string} */
+var ErrorType = {
+  NONE: 'none',
+  INCORRECT_PIN: 'incorrect-pin',
+  INCORRECT_PUK: 'incorrect-puk',
+  MISMATCHED_PIN: 'mismatched-pin',
+  INVALID_PIN: 'invalid-pin',
+  INVALID_PUK: 'invalid-puk'
+};
+
+var PIN_MIN_LENGTH = 4;
+var PUK_MIN_LENGTH = 8;
+
+Polymer({
+  is: 'network-siminfo',
+
+  behaviors: [I18nBehavior],
+
+  properties: {
+    /**
+     * The network properties associated with the element.
+     * @type {!CrOnc.NetworkProperties|undefined}
+     */
+    networkProperties: {
+      type: Object,
+      observer: 'networkPropertiesChanged_',
+    },
+
+    /**
+     * Interface for networkingPrivate calls, passed from internet_page.
+     * @type {NetworkingPrivate}
+     */
+    networkingPrivate: Object,
+
+    /**
+     * Reflects networkProperties.Cellular.SIMLockStatus.LockEnabled for the
+     * toggle button.
+     * @private
+     */
+    lockEnabled_: {
+      type: Boolean,
+      value: false,
+    },
+
+    /**
+     * Set to true when a PUK is required to unlock the SIM.
+     * @private
+     */
+    pukRequired_: {
+      type: Boolean,
+      value: false,
+      observer: 'pukRequiredChanged_',
+    },
+
+    /**
+     * Set to an ErrorType value after an incorrect PIN or PUK entry.
+     * @private {ErrorType}
+     */
+    error_: {
+      type: Object,
+      value: ErrorType.NONE,
+    },
+  },
+
+  sendSimLockEnabled_: false,
+
+  /** @override */
+  detached: function() {
+    if (this.$.enterPinDialog.open)
+      this.$.enterPinDialog.close();
+    if (this.$.changePinDialog.open)
+      this.$.changePinDialog.close();
+    if (this.$.unlockPinDialog.open)
+      this.$.unlockPinDialog.close();
+    if (this.$.unlockPukDialog.open)
+      this.$.unlockPukDialog.close();
+  },
+
+  /** @private */
+  networkPropertiesChanged_: function() {
+    if (!this.networkProperties || !this.networkProperties.Cellular)
+      return;
+    var simLockStatus = this.networkProperties.Cellular.SIMLockStatus;
+    this.pukRequired_ =
+        !!simLockStatus && simLockStatus.LockType == CrOnc.LockType.PUK;
+    this.lockEnabled_ = !!simLockStatus && simLockStatus.LockEnabled;
+  },
+
+  /** @private */
+  pukRequiredChanged_: function() {
+    if (this.$.unlockPukDialog.open) {
+      if (this.pukRequired_)
+        this.$.unlockPuk.focus();
+      else
+        this.$.unlockPukDialog.close();
+      return;
+    }
+
+    if (!this.pukRequired_)
+      return;
+
+    // If the PUK was activated while attempting to enter or change a pin,
+    // close the dialog and open the unlock PUK dialog.
+    var showUnlockPuk = false;
+    if (this.$.enterPinDialog.open) {
+      this.$.enterPinDialog.close();
+      showUnlockPuk = true;
+    }
+    if (this.$.changePinDialog.open) {
+      this.$.changePinDialog.close();
+      showUnlockPuk = true;
+    }
+    if (this.$.unlockPinDialog.open) {
+      this.$.unlockPinDialog.close();
+      showUnlockPuk = true;
+    }
+    if (!showUnlockPuk)
+      return;
+
+    this.showUnlockPukDialog_();
+  },
+
+  /**
+   * Opens the pin dialog when the sim lock enabled state changes.
+   * @param {!Event} event
+   * @private
+   */
+  onSimLockEnabledChange_: function(event) {
+    if (!this.networkProperties || !this.networkProperties.Cellular)
+      return;
+    this.sendSimLockEnabled_ = event.target.checked;
+    this.error_ = ErrorType.NONE;
+    this.$.enterPin.value = '';
+    this.$.enterPinDialog.showModal();
+  },
+
+  /**
+   * Sends the PIN value from the Enter PIN dialog.
+   * @param {!Event} event
+   * @private
+   */
+  sendEnterPin_: function(event) {
+    event.stopPropagation();
+    var guid = (this.networkProperties && this.networkProperties.GUID) || '';
+    var pin = this.$.enterPin.value;
+    if (!this.validatePin_(pin)) {
+      this.onEnterPinDialogCancel_();
+      return;
+    }
+    var simState = /** @type {!CrOnc.CellularSimState} */ ({
+      currentPin: pin,
+      requirePin: this.sendSimLockEnabled_,
+    });
+    this.networkingPrivate.setCellularSimState(guid, simState, () => {
+      if (chrome.runtime.lastError) {
+        this.error_ = ErrorType.INCORRECT_PIN;
+        this.$.enterPin.inputElement.select();
+      } else {
+        this.error_ = ErrorType.NONE;
+        this.$.enterPinDialog.close();
+      }
+    });
+  },
+
+  /**
+   * Opens the Change PIN dialog.
+   * @param {!Event} event
+   * @private
+   */
+  onChangePinTap_: function(event) {
+    event.stopPropagation();
+    if (!this.networkProperties || !this.networkProperties.Cellular)
+      return;
+    this.error_ = ErrorType.NONE;
+    this.$.changePinOld.value = '';
+    this.$.changePinNew1.value = '';
+    this.$.changePinNew2.value = '';
+    this.$.changePinDialog.showModal();
+  },
+
+  /**
+   * Sends the old and new PIN values from the Change PIN dialog.
+   * @param {!Event} event
+   * @private
+   */
+  sendChangePin_: function(event) {
+    event.stopPropagation();
+    var guid = (this.networkProperties && this.networkProperties.GUID) || '';
+    var newPin = this.$.changePinNew1.value;
+    if (!this.validatePin_(newPin, this.$.changePinNew2.value))
+      return;
+
+    var simState = /** @type {!CrOnc.CellularSimState} */ ({
+      requirePin: true,
+      currentPin: this.$.changePinOld.value,
+      newPin: newPin
+    });
+    this.networkingPrivate.setCellularSimState(guid, simState, () => {
+      if (chrome.runtime.lastError) {
+        this.error_ = ErrorType.INCORRECT_PIN;
+        this.$.changePinOld.inputElement.select();
+      } else {
+        this.error_ = ErrorType.NONE;
+        this.$.changePinDialog.close();
+      }
+    });
+  },
+
+  /**
+   * Opens the Unlock PIN / PUK dialog.
+   * @param {!Event} event
+   * @private
+   */
+  onUnlockPinTap_: function(event) {
+    event.stopPropagation();
+    if (this.pukRequired_) {
+      this.showUnlockPukDialog_();
+    } else {
+      this.showUnlockPinDialog_();
+    }
+  },
+
+  /**
+   * Sends the PIN value from the Unlock PIN dialog.
+   * @param {!Event} event
+   * @private
+   */
+  sendUnlockPin_: function(event) {
+    event.stopPropagation();
+    var guid = (this.networkProperties && this.networkProperties.GUID) || '';
+    var pin = this.$.unlockPin.value;
+    if (!this.validatePin_(pin))
+      return;
+
+    this.networkingPrivate.unlockCellularSim(guid, pin, '', () => {
+      if (chrome.runtime.lastError) {
+        this.error_ = ErrorType.INCORRECT_PIN;
+        this.$.unlockPin.inputElement.select();
+      } else {
+        this.error_ = ErrorType.NONE;
+        this.$.unlockPinDialog.close();
+      }
+    });
+  },
+
+  /** @private */
+  showUnlockPinDialog_: function() {
+    this.error_ = ErrorType.NONE;
+    this.$.unlockPin.value = '';
+    this.$.unlockPinDialog.showModal();
+  },
+
+  /** @private */
+  showUnlockPukDialog_: function() {
+    this.error_ = ErrorType.NONE;
+    this.$.unlockPuk.value = '';
+    this.$.unlockPin1.value = '';
+    this.$.unlockPin2.value = '';
+    this.$.unlockPukDialog.showModal();
+  },
+
+  /**
+   * Sends the PUK value and new PIN value from the Unblock PUK dialog.
+   * @param {!Event} event
+   * @private
+   */
+  sendUnlockPuk_: function(event) {
+    event.stopPropagation();
+    var guid = (this.networkProperties && this.networkProperties.GUID) || '';
+    var puk = this.$.unlockPuk.value;
+    if (!this.validatePuk_(puk))
+      return;
+    var pin = this.$.unlockPin1.value;
+    if (!this.validatePin_(pin, this.$.unlockPin2.value))
+      return;
+
+    this.networkingPrivate.unlockCellularSim(guid, pin, puk, () => {
+      if (chrome.runtime.lastError) {
+        this.error_ = ErrorType.INCORRECT_PUK;
+        this.$.unlockPuk.inputElement.select();
+      } else {
+        this.error_ = ErrorType.NONE;
+        this.$.unlockPukDialog.close();
+      }
+    });
+  },
+
+  /**
+   * @return {boolean}
+   * @private
+   */
+  showSimLocked_: function() {
+    if (!this.networkProperties || !this.networkProperties.Cellular ||
+        !this.networkProperties.Cellular.SIMPresent) {
+      return false;
+    }
+    return CrOnc.isSimLocked(this.networkProperties);
+  },
+
+  /**
+   * @return {boolean}
+   * @private
+   */
+  showSimUnlocked_: function() {
+    if (!this.networkProperties || !this.networkProperties.Cellular ||
+        !this.networkProperties.Cellular.SIMPresent) {
+      return false;
+    }
+    return !CrOnc.isSimLocked(this.networkProperties);
+  },
+
+  /** @private */
+  getErrorMsg_: function() {
+    if (this.error_ == ErrorType.NONE)
+      return '';
+    // TODO(stevenjb): Translate
+    var msg;
+    if (this.error_ == ErrorType.INCORRECT_PIN)
+      msg = 'Incorrect PIN.';
+    else if (this.error_ == ErrorType.INCORRECT_PUK)
+      msg = 'Incorrect PUK.';
+    else if (this.error_ == ErrorType.MISMATCHED_PIN)
+      msg = 'PIN values do not match.';
+    else if (this.error_ == ErrorType.INVALID_PIN)
+      msg = 'Invalid PIN.';
+    else if (this.error_ == ErrorType.INVALID_PUK)
+      msg = 'Invalid PUK.';
+    else
+      return 'UNKNOWN ERROR';
+    var retriesLeft =
+        this.get('Cellular.SIMLockStatus.RetriesLeft', this.networkProperties);
+    if (retriesLeft) {
+      msg += ' Retries left: ' + retriesLeft.toString();
+    }
+    return msg;
+  },
+
+  /**
+   * Checks whether |pin1| is of the proper length and if opt_pin2 is not
+   * undefined, whether pin1 and opt_pin2 match. On any failure, sets
+   * |this.error_| and returns false.
+   * @param {string} pin1
+   * @param {string=} opt_pin2
+   * @return {boolean} True if the pins match and are of minimum length.
+   * @private
+   */
+  validatePin_: function(pin1, opt_pin2) {
+    if (pin1.length < PIN_MIN_LENGTH) {
+      this.error_ = ErrorType.INVALID_PIN;
+      return false;
+    }
+    if (opt_pin2 != undefined && pin1 != opt_pin2) {
+      this.error_ = ErrorType.MISMATCHED_PIN;
+      return false;
+    }
+    return true;
+  },
+
+  /**
+   * Checks whether |puk| is of the proper length. If not, sets |this.error_|
+   * and returns false.
+   * @param {string} puk
+   * @return {boolean} True if the puk is of minimum length.
+   * @private
+   */
+  validatePuk_: function(puk) {
+    if (puk.length < PUK_MIN_LENGTH) {
+      this.error_ = ErrorType.INVALID_PUK;
+      return false;
+    }
+    return true;
+  },
+
+  /** @private */
+  onEnterPinDialogCancel_: function() {
+    this.lockEnabled_ =
+        this.networkProperties.Cellular.SIMLockStatus.LockEnabled;
+  },
+
+  /** @private */
+  onEnterPinDialogClose_: function() {
+    cr.ui.focusWithoutInk(assert(this.$$('#simLockButton')));
+  },
+
+  /** @private */
+  onChangePinDialogClose_: function() {
+    cr.ui.focusWithoutInk(assert(this.$$('#changePinButton')));
+  },
+
+  /** @private */
+  onUnlockPinDialogClose_: function() {
+    cr.ui.focusWithoutInk(assert(this.$$('#unlockPinButton')));
+  },
+});
+})();
diff --git a/ui/webui/resources/cr_components/cr_components_resources.grdp b/ui/webui/resources/cr_components/cr_components_resources.grdp
index 1db61d1..a4e035b9 100644
--- a/ui/webui/resources/cr_components/cr_components_resources.grdp
+++ b/ui/webui/resources/cr_components/cr_components_resources.grdp
@@ -148,6 +148,12 @@
     <structure name="IDR_WEBUI_CHROMEOS_NETWORK_PROXY_INPUT_JS"
                file="cr_components/chromeos/network/network_proxy_input.js"
                type="chrome_html" />
+    <structure name="IDR_WEBUI_CHROMEOS_NETWORK_SIMINFO_HTML"
+               file="cr_components/chromeos/network/network_siminfo.html"
+               type="chrome_html" />
+    <structure name="IDR_WEBUI_CHROMEOS_NETWORK_SIMINFO_JS"
+               file="cr_components/chromeos/network/network_siminfo.js"
+               type="chrome_html" />
     <structure name="IDR_WEBUI_CHROMEOS_NETWORK_SHARED_CSS_HTML"
                file="cr_components/chromeos/network/network_shared_css.html"
                type="chrome_html" />
diff --git a/ui/webui/resources/cr_elements/chromeos/cr_picture/compiled_resources2.gyp b/ui/webui/resources/cr_elements/chromeos/cr_picture/compiled_resources2.gyp
index e609ba6..7181c69 100644
--- a/ui/webui/resources/cr_elements/chromeos/cr_picture/compiled_resources2.gyp
+++ b/ui/webui/resources/cr_elements/chromeos/cr_picture/compiled_resources2.gyp
@@ -21,6 +21,7 @@
     {
       'dependencies': [
         'cr_camera',
+        'cr_png_behavior',
         'cr_picture_types',
       ],
       'target_name': 'cr_picture_pane',
diff --git a/ui/webui/resources/cr_elements/chromeos/cr_picture/cr_camera.html b/ui/webui/resources/cr_elements/chromeos/cr_picture/cr_camera.html
index 82fda19..6b8a0016 100644
--- a/ui/webui/resources/cr_elements/chromeos/cr_picture/cr_camera.html
+++ b/ui/webui/resources/cr_elements/chromeos/cr_picture/cr_camera.html
@@ -10,6 +10,11 @@
     <!-- Note: Do not include cr-shared-style, we use different
          paper-icon-button-light styling -->
     <style>
+      :host {
+        --cr-camera-hidden-frame-size: 406px;
+        --cr-camera-preview-frame-size: 280px;
+      }
+
       #perspectiveBox {
         height: var(--cr-camera-image-size, 228px);
         margin: auto;
@@ -28,29 +33,41 @@
       }
 
       #userImageStreamCrop::after {
-        -webkit-mask-image: radial-gradient(transparent 140px, black 140px);
-        background-color: rgb(214, 214, 214);
+        border: 100px solid rgba(214, 214, 214, 0.34);
+        border-radius: 100%;
         content: '';
         display: block;
-        height: 100%;
-        opacity: 0.34;
-        transform: translateZ(0);
-        width: 100%;
+        height: var(--cr-camera-hidden-frame-size);
+        margin: 50% 50%;
+        transform: translateZ(0) translateX(-50%) translateY(-50%);
+        transition: width 100ms, height 100ms;
+        transition-timing-function: ease-in;
+        width: var(--cr-camera-hidden-frame-size);
       }
 
-      @-webkit-keyframes pulse {
-        0% { opacity: 0; }
-        50% { opacity: 1; }
-        100% { opacity: 0; }
+      #userImageStreamCrop.preview::after {
+        height: var(--cr-camera-preview-frame-size);
+        transition-timing-function: ease-out;
+        width: var(--cr-camera-preview-frame-size);
       }
 
-      #userImageStreamCrop.capture::after {
-        -webkit-mask-image: none;
-        animation: pulse linear 100ms normal forwards;
+      :host([!videomode]) #userImageStreamCrop.capture::after {
+        background-color: white;
+        transition: background-color 50ms ease-in 100ms;
+      }
+
+      @-webkit-keyframes flash {
+        0% { background-color: rgba(255, 255, 255, 0); }
+        33% { background-color: rgba(255, 255, 255, 0.67); }
+        100% { background-color: rgba(255, 255, 255, 0); }
       }
 
       :host([videomode]) #userImageStreamCrop.capture::after {
-        animation: pulse linear 50ms 20;
+        animation-delay: 100ms;
+        animation-duration: 100ms;
+        animation-iteration-count: 10;
+        animation-name: flash;
+        animation-timing-function: ease-out;
       }
 
       paper-spinner {
diff --git a/ui/webui/resources/cr_elements/chromeos/cr_picture/cr_camera.js b/ui/webui/resources/cr_elements/chromeos/cr_picture/cr_camera.js
index d70e005..99b73c34 100644
--- a/ui/webui/resources/cr_elements/chromeos/cr_picture/cr_camera.js
+++ b/ui/webui/resources/cr_elements/chromeos/cr_picture/cr_camera.js
@@ -61,6 +61,7 @@
   /** @override */
   attached: function() {
     this.$.cameraVideo.addEventListener('canplay', function() {
+      this.$.userImageStreamCrop.classList.add('preview');
       this.cameraOnline_ = true;
     }.bind(this));
     this.startCamera();
@@ -97,17 +98,19 @@
 
     /** Start capturing frames at an interval. */
     var capturedFrames = [];
+    this.$.userImageStreamCrop.classList.remove('preview');
     this.$.userImageStreamCrop.classList.add('capture');
     var interval = setInterval(() => {
-      capturedFrames.push(this.captureFrame_(this.$.cameraVideo, frames.pop()));
-
       /** Stop capturing frames when all allocated frames have been consumed. */
-      if (!frames.length) {
-        this.$.userImageStreamCrop.classList.remove('capture');
+      if (frames.length) {
+        capturedFrames.push(
+            this.captureFrame_(this.$.cameraVideo, frames.pop()));
+      } else {
         clearInterval(interval);
         this.fire(
             'photo-taken',
             {photoDataUrl: this.convertFramesToPng_(capturedFrames)});
+        this.$.userImageStreamCrop.classList.remove('capture');
       }
     }, CAPTURE_INTERVAL_MS);
   },
@@ -142,6 +145,7 @@
 
   /** Stops the camera stream capture if it's currently active. */
   stopCamera: function() {
+    this.$.userImageStreamCrop.classList.remove('preview');
     this.cameraOnline_ = false;
     this.$.cameraVideo.src = '';
     if (this.cameraStream_)
diff --git a/ui/webui/resources/cr_elements/chromeos/cr_picture/cr_picture_pane.html b/ui/webui/resources/cr_elements/chromeos/cr_picture/cr_picture_pane.html
index 10b50fa..a6c95a4 100644
--- a/ui/webui/resources/cr_elements/chromeos/cr_picture/cr_picture_pane.html
+++ b/ui/webui/resources/cr_elements/chromeos/cr_picture/cr_picture_pane.html
@@ -4,6 +4,7 @@
 <link rel="import" href="chrome://resources/polymer/v1_0/paper-icon-button/paper-icon-button-light.html">
 <link rel="import" href="cr_camera.html">
 <link rel="import" href="cr_picture_types.html">
+<link rel="import" href="cr_png_behavior.html">
 
 <dom-module id="cr-picture-pane">
   <template>
@@ -21,6 +22,7 @@
       }
 
       img {
+        background-size: 100% 100%;
         border-top-left-radius: 2px;
         border-top-right-radius: 2px;
         display: block;
@@ -61,19 +63,16 @@
         border-radius: 50%;
       }
     </style>
-    <template is="dom-if"
-        if="[[showImagePreview_(cameraActive_, imageSrc)]]">
-      <div id="preview">
-        <img alt="[[previewAltText]]" src="[[getImgSrc_(imageUrl)]]"
-            data-show-discard$="[[showDiscard_(imageType)]]">
-        <div id="discard" hidden="[[!showDiscard_(imageType)]]">
-          <button is="paper-icon-button-light" id="discardImage"
-              class="icon-delete-white" title="[[discardImageLabel]]"
-              on-tap="onTapDiscardImage_">
-          </button>
-        </div>
+    <div id="preview" hidden="[[!showImagePreview_(cameraActive_, imageSrc)]]">
+      <img id="image" alt="[[previewAltText]]" src="[[getImgSrc_(imageUrl)]]"
+          data-show-discard$="[[showDiscard_(imageType)]]">
+      <div id="discard" hidden="[[!showDiscard_(imageType)]]">
+        <button is="paper-icon-button-light" id="discardImage"
+            class="icon-delete-white" title="[[discardImageLabel]]"
+            on-tap="onTapDiscardImage_">
+        </button>
       </div>
-    </template>
+    </div>
     <template is="dom-if" if="[[cameraActive_]]">
       <cr-camera id="camera"
           take-photo-label="[[takePhotoLabel]]"
diff --git a/ui/webui/resources/cr_elements/chromeos/cr_picture/cr_picture_pane.js b/ui/webui/resources/cr_elements/chromeos/cr_picture/cr_picture_pane.js
index abb2ed2..d8a830c 100644
--- a/ui/webui/resources/cr_elements/chromeos/cr_picture/cr_picture_pane.js
+++ b/ui/webui/resources/cr_elements/chromeos/cr_picture/cr_picture_pane.js
@@ -11,7 +11,10 @@
 Polymer({
   is: 'cr-picture-pane',
 
+  behaviors: [CrPngBehavior],
+
   properties: {
+
     /** Whether the camera is present / available */
     cameraPresent: Boolean,
 
@@ -93,14 +96,19 @@
      * Data URLs for PNG images can be large. Create an object URL to avoid
      * URL length limits.
      */
+    var image = /** @type {!HTMLImageElement} */ (this.$$('#image'));
     if (this.imageSrc.startsWith('data:image/png')) {
       var byteString = atob(this.imageSrc.split(',')[1]);
       var bytes = new Uint8Array(byteString.length);
       for (var i = 0; i < byteString.length; i++)
         bytes[i] = byteString.charCodeAt(i);
       var blob = new Blob([bytes], {'type': 'image/png'});
+      // Use first frame as placeholder while rest of image loads.
+      image.style.backgroundImage = 'url(' +
+          CrPngBehavior.convertImageSequenceToPng([this.imageSrc]) + ')';
       this.imageUrl = URL.createObjectURL(blob);
     } else {
+      image.style.backgroundImage = 'none';
       this.imageUrl = this.imageSrc;
     }
   },
diff --git a/ui/webui/resources/cr_elements/icons.html b/ui/webui/resources/cr_elements/icons.html
index 5a16957..ccff3013f 100644
--- a/ui/webui/resources/cr_elements/icons.html
+++ b/ui/webui/resources/cr_elements/icons.html
@@ -26,6 +26,7 @@
       These icons are copied from Polymer's iron-icons and kept in sorted order.
       See http://goo.gl/Y1OdAq for instructions on adding additional icons.
       -->
+      <g id="account-child-invert" viewBox="0 0 48 48"><path d="M24 4c3.31 0 6 2.69 6 6s-2.69 6-6 6-6-2.69-6-6 2.69-6 6-6z"></path><path fill="none" d="M0 0h48v48H0V0z"></path><circle fill="none" cx="24" cy="26" r="4"></circle><path d="M24 18c-6.16 0-13 3.12-13 7.23v11.54c0 2.32 2.19 4.33 5.2 5.63 2.32 1 5.12 1.59 7.8 1.59.66 0 1.33-.06 2-.14v-5.2c-.67.08-1.34.14-2 .14-2.63 0-5.39-.57-7.68-1.55.67-2.12 4.34-3.65 7.68-3.65.86 0 1.75.11 2.6.29 2.79.62 5.2 2.15 5.2 4.04v4.47c3.01-1.31 5.2-3.31 5.2-5.63V25.23C37 21.12 30.16 18 24 18zm0 12c-2.21 0-4-1.79-4-4s1.79-4 4-4 4 1.79 4 4-1.79 4-4 4z"></path></g>
       <g id="add"><path d="M19 13h-6v6h-2v-6H5v-2h6V5h2v6h6v2z"/></g>
       <g id="arrow-drop-up"><path d="M7 14l5-5 5 5z"></g>
       <g id="arrow-drop-down"><path d="M7 10l5 5 5-5z"></path></g>
@@ -33,7 +34,6 @@
       <g id="camera-alt"><circle cx="12" cy="12" r="3.2"></circle><path d="M9 2L7.17 4H4c-1.1 0-2 .9-2 2v12c0 1.1.9 2 2 2h16c1.1 0 2-.9 2-2V6c0-1.1-.9-2-2-2h-3.17L15 2H9zm3 15c-2.76 0-5-2.24-5-5s2.24-5 5-5 5 2.24 5 5-2.24 5-5 5z"></path></g>
       <g id="check"><path d="M9 16.17L4.83 12l-1.42 1.41L9 19 21 7l-1.41-1.41z"></path></g>
 </if>
-      <g id="account-child-invert" viewBox="0 0 48 48"><path d="M24 4c3.31 0 6 2.69 6 6s-2.69 6-6 6-6-2.69-6-6 2.69-6 6-6z"></path><path fill="none" d="M0 0h48v48H0V0z"></path><circle fill="none" cx="24" cy="26" r="4"></circle><path d="M24 18c-6.16 0-13 3.12-13 7.23v11.54c0 2.32 2.19 4.33 5.2 5.63 2.32 1 5.12 1.59 7.8 1.59.66 0 1.33-.06 2-.14v-5.2c-.67.08-1.34.14-2 .14-2.63 0-5.39-.57-7.68-1.55.67-2.12 4.34-3.65 7.68-3.65.86 0 1.75.11 2.6.29 2.79.62 5.2 2.15 5.2 4.04v4.47c3.01-1.31 5.2-3.31 5.2-5.63V25.23C37 21.12 30.16 18 24 18zm0 12c-2.21 0-4-1.79-4-4s1.79-4 4-4 4 1.79 4 4-1.79 4-4 4z"></path></g>
       <g id="chevron-right"><path d="M10 6L8.59 7.41 13.17 12l-4.58 4.59L10 18l6-6z"></path></g>
       <g id="clear"><path d="M19 6.41L17.59 5 12 10.59 6.41 5 5 6.41 10.59 12 5 17.59 6.41 19 12 13.41 17.59 19 19 17.59 13.41 12z"></path></g>
       <g id="close"><path d="M19 6.41L17.59 5 12 10.59 6.41 5 5 6.41 10.59 12 5 17.59 6.41 19 12 13.41 17.59 19 19 17.59 13.41 12z"></path></g>
@@ -51,7 +51,11 @@
       <g id="person"><path d="M12 12c2.21 0 4-1.79 4-4s-1.79-4-4-4-4 1.79-4 4 1.79 4 4 4zm0 2c-2.67 0-8 1.34-8 4v2h16v-2c0-2.66-5.33-4-8-4z"></path></g>
       <g id="print"><path d="M19 8H5c-1.66 0-3 1.34-3 3v6h4v4h12v-4h4v-6c0-1.66-1.34-3-3-3zm-3 11H8v-5h8v5zm3-7c-.55 0-1-.45-1-1s.45-1 1-1 1 .45 1 1-.45 1-1 1zm-1-9H6v4h12V3z"></path></g>
       <g id="search"><path d="M15.5 14h-.79l-.28-.27C15.41 12.59 16 11.11 16 9.5 16 5.91 13.09 3 9.5 3S3 5.91 3 9.5 5.91 16 9.5 16c1.61 0 3.09-.59 4.23-1.57l.27.28v.79l5 4.99L20.49 19l-4.99-5zm-6 0C7.01 14 5 11.99 5 9.5S7.01 5 9.5 5 14 7.01 14 9.5 11.99 14 9.5 14z"></path></g>
+<if expr="chromeos">
+      <g id="sim-card-alert"><path d="M18 2h-8L4.02 8 4 20c0 1.1.9 2 2 2h12c1.1 0 2-.9 2-2V4c0-1.1-.9-2-2-2zm-5 15h-2v-2h2v2zm0-4h-2V8h2v5z"></path></g>
+      <g id="sim-lock"><path d="M18 8h-1V6c0-2.76-2.24-5-5-5S7 3.24 7 6v2H6c-1.1 0-2 .9-2 2v10c0 1.1.9 2 2 2h12c1.1 0 2-.9 2-2V10c0-1.1-.9-2-2-2zm-6 9c-1.1 0-2-.9-2-2s.9-2 2-2 2 .9 2 2-.9 2-2 2zm3.1-9H8.9V6c0-1.71 1.39-3.1 3.1-3.1 1.71 0 3.1 1.39 3.1 3.1v2z"></path></g>
       <g id="sms-connect"><path d="M20,2C21.1,2 22,2.9 22,4L22,16C22,17.1 21.1,18 20,18L6,18L2,22L2.01,4C2.01,2.9 2.9,2 4,2L20,2ZM8,8L4,12L8,16L8,13L14,13L14,11L8,11L8,8ZM19.666,7.872L16.038,4.372L16.038,6.997L10,6.997L10,9L16.038,9L16.038,11.372L19.666,7.872Z"></path></g>
+</if>
       <!-- The <g> IDs are exposed as global variables in Vulcanized mode, which
         conflicts with the "settings" namespace of MD Settings. Using an "_icon"
         suffix prevents the naming conflict. -->
diff --git a/ui/wm/core/window_util.cc b/ui/wm/core/window_util.cc
index 18e4746..4deb1c2b 100644
--- a/ui/wm/core/window_util.cc
+++ b/ui/wm/core/window_util.cc
@@ -117,6 +117,23 @@
   }
 }
 
+bool WindowStateIs(aura::Window* window, ui::WindowShowState state) {
+  return window->GetProperty(aura::client::kShowStateKey) == state;
+}
+
+void SetWindowState(aura::Window* window, ui::WindowShowState state) {
+  window->SetProperty(aura::client::kShowStateKey, state);
+}
+
+void Unminimize(aura::Window* window) {
+  DCHECK_EQ(window->GetProperty(aura::client::kShowStateKey),
+            ui::SHOW_STATE_MINIMIZED);
+  window->SetProperty(
+      aura::client::kShowStateKey,
+      window->GetProperty(aura::client::kPreMinimizedShowStateKey));
+  window->ClearProperty(aura::client::kPreMinimizedShowStateKey);
+}
+
 aura::Window* GetActivatableWindow(aura::Window* window) {
   ActivationClient* client = GetActivationClient(window->GetRootWindow());
   return client ? client->GetActivatableWindow(window) : NULL;
diff --git a/ui/wm/core/window_util.h b/ui/wm/core/window_util.h
index 27c5400..1e6b4267 100644
--- a/ui/wm/core/window_util.h
+++ b/ui/wm/core/window_util.h
@@ -11,6 +11,7 @@
 
 #include "base/callback_forward.h"
 #include "base/compiler_specific.h"
+#include "ui/base/ui_base_types.h"
 #include "ui/wm/core/wm_core_export.h"
 
 namespace aura {
@@ -31,6 +32,17 @@
 WM_CORE_EXPORT bool CanActivateWindow(aura::Window* window);
 WM_CORE_EXPORT void SetWindowFullscreen(aura::Window* window, bool fullscreen);
 
+// Returns true if |window|'s show state is |state|.
+WM_CORE_EXPORT bool WindowStateIs(aura::Window* window,
+                                  ui::WindowShowState state);
+
+// Sets the window state to |state|.
+WM_CORE_EXPORT void SetWindowState(aura::Window* window,
+                                   ui::WindowShowState state);
+
+// Changes a window's state to its pre-minimized state.
+WM_CORE_EXPORT void Unminimize(aura::Window* window);
+
 // Retrieves the activatable window for |window|. The ActivationClient makes
 // this determination.
 WM_CORE_EXPORT aura::Window* GetActivatableWindow(aura::Window* window);
diff --git a/url/gurl.cc b/url/gurl.cc
index 2132cf2..ce0cb49 100644
--- a/url/gurl.cc
+++ b/url/gurl.cc
@@ -9,6 +9,7 @@
 #include <algorithm>
 #include <ostream>
 
+#include "base/lazy_instance.h"
 #include "base/logging.h"
 #include "base/strings/string_piece.h"
 #include "base/strings/string_util.h"
@@ -16,53 +17,11 @@
 #include "url/url_canon_stdstring.h"
 #include "url/url_util.h"
 
-#ifdef WIN32
-#include <windows.h>
-#else
-#include <pthread.h>
-#endif
-
 namespace {
 
-static std::string* empty_string = NULL;
-static GURL* empty_gurl = NULL;
-
-#ifdef WIN32
-
-// Returns a static reference to an empty string for returning a reference
-// when there is no underlying string.
-const std::string& EmptyStringForGURL() {
-  // Avoid static object construction/destruction on startup/shutdown.
-  if (!empty_string) {
-    // Create the string. Be careful that we don't break in the case that this
-    // is being called from multiple threads. Statics are not threadsafe.
-    std::string* new_empty_string = new std::string;
-    if (InterlockedCompareExchangePointer(
-        reinterpret_cast<PVOID*>(&empty_string), new_empty_string, NULL)) {
-      // The old value was non-NULL, so no replacement was done. Another
-      // thread did the initialization out from under us.
-      delete new_empty_string;
-    }
-  }
-  return *empty_string;
-}
-
-#else
-
-static pthread_once_t empty_string_once = PTHREAD_ONCE_INIT;
-static pthread_once_t empty_gurl_once = PTHREAD_ONCE_INIT;
-
-void EmptyStringForGURLOnce(void) {
-  empty_string = new std::string;
-}
-
-const std::string& EmptyStringForGURL() {
-  // Avoid static object construction/destruction on startup/shutdown.
-  pthread_once(&empty_string_once, EmptyStringForGURLOnce);
-  return *empty_string;
-}
-
-#endif  // WIN32
+static base::LazyInstance<std::string>::Leaky empty_string =
+    LAZY_INSTANCE_INITIALIZER;
+static base::LazyInstance<GURL>::Leaky empty_gurl = LAZY_INSTANCE_INITIALIZER;
 
 }  // namespace
 
@@ -208,7 +167,7 @@
     return spec_;
 
   DCHECK(false) << "Trying to get the spec of an invalid URL!";
-  return EmptyStringForGURL();
+  return empty_string.Get();
 }
 
 bool GURL::operator<(const GURL& other) const {
@@ -477,38 +436,10 @@
   return is_valid_ && url::HostIsIPAddress(host_piece());
 }
 
-#ifdef WIN32
-
 const GURL& GURL::EmptyGURL() {
-  // Avoid static object construction/destruction on startup/shutdown.
-  if (!empty_gurl) {
-    // Create the string. Be careful that we don't break in the case that this
-    // is being called from multiple threads.
-    GURL* new_empty_gurl = new GURL;
-    if (InterlockedCompareExchangePointer(
-        reinterpret_cast<PVOID*>(&empty_gurl), new_empty_gurl, NULL)) {
-      // The old value was non-NULL, so no replacement was done. Another
-      // thread did the initialization out from under us.
-      delete new_empty_gurl;
-    }
-  }
-  return *empty_gurl;
+  return empty_gurl.Get();
 }
 
-#else
-
-void EmptyGURLOnce(void) {
-  empty_gurl = new GURL;
-}
-
-const GURL& GURL::EmptyGURL() {
-  // Avoid static object construction/destruction on startup/shutdown.
-  pthread_once(&empty_gurl_once, EmptyGURLOnce);
-  return *empty_gurl;
-}
-
-#endif  // WIN32
-
 bool GURL::DomainIs(base::StringPiece canonical_domain) const {
   if (!is_valid_)
     return false;
diff --git a/url/mojo/url.mojom b/url/mojo/url.mojom
index 56ca8ee..3022837 100644
--- a/url/mojo/url.mojom
+++ b/url/mojo/url.mojom
@@ -4,6 +4,10 @@
 
 module url.mojom;
 
+// Don't make backwards-incompatible changes to this definition!
+// It's used in PageState serialization, so backwards incompatible changes
+// would cause stored PageState objects to be un-parseable. Please contact the
+// page state serialization owners before making such a change.
 struct Url {
   string url;
 };
\ No newline at end of file