diff --git a/.eslintrc.js b/.eslintrc.js
index 79c117d..270ced0 100644
--- a/.eslintrc.js
+++ b/.eslintrc.js
@@ -11,7 +11,16 @@
   'rules': {
     // Enabled checks.
     'no-extra-semi': 'error',
+    'no-restricted-properties': ['error', {
+      'object': 'document',
+      'property': 'getElementById',
+      'message': 'Use $(\'id\') or getSVGElement(\'id\') ' +
+          'from chrome://resources/js/util.js instead of ' +
+          'document.getElementById(\'id\')',
+      },
+    ],
     'semi': ['error', 'always'],
+
     // TODO(dpapad): Add more checks according to our styleguide.
   },
 };
diff --git a/DEPS b/DEPS
index 061d226..3aa0222 100644
--- a/DEPS
+++ b/DEPS
@@ -40,11 +40,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': '1919dc4c052418b14651e39be3a94e160b23c7a7',
+  'skia_revision': '2fdc3d56a250e15445ee073ec49981d2c4f94953',
   # 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': '40e1b24ffde7bd50e0c9cd00c8cc63065c3669fa',
+  'v8_revision': '7d459498f126a580e55979a9b1c4a80119644d3f',
   # 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.
@@ -202,7 +202,7 @@
     Var('chromium_git') + '/external/selenium/py.git' + '@' + '5fd78261a75fe08d27ca4835fb6c5ce4b42275bd',
 
   'src/third_party/libvpx/source/libvpx':
-    Var('chromium_git') + '/webm/libvpx.git' + '@' +  'b3bf91bdc60220c004a22d21c867cc392e684b81',
+    Var('chromium_git') + '/webm/libvpx.git' + '@' +  'b9649d240768cdcfc233960056aafb9ed1a3db14',
 
   'src/third_party/ffmpeg':
     Var('chromium_git') + '/chromium/third_party/ffmpeg.git' + '@' + 'cb7f9fc2adbe20d57520176bb239683b08d3bcc8',
@@ -232,7 +232,7 @@
     Var('chromium_git') + '/native_client/src/third_party/scons-2.0.1.git' + '@' + '1c1550e17fc26355d08627fbdec13d8291227067',
 
   'src/third_party/webrtc':
-    Var('chromium_git') + '/external/webrtc/trunk/webrtc.git' + '@' + '01915025bc1873e556d09b5083b5d7ccc31da068', # commit position 18252
+    Var('chromium_git') + '/external/webrtc/trunk/webrtc.git' + '@' + '7d76f48e5b8484b3c14f5e97db5f62dcf12e50b5', # commit position 18351
 
   'src/third_party/openmax_dl':
     Var('chromium_git') + '/external/webrtc/deps/third_party/openmax.git' + '@' +  Var('openmax_dl_revision'),
diff --git a/PRESUBMIT.py b/PRESUBMIT.py
index 7f09ce51..0a9282f 100644
--- a/PRESUBMIT.py
+++ b/PRESUBMIT.py
@@ -204,6 +204,8 @@
         r"^chrome[\\\/]browser[\\\/]lifetime[\\\/]application_lifetime\.cc$",
         r"^chrome[\\\/]browser[\\\/]chromeos[\\\/]"
             "customization_document_browsertest\.cc$",
+        r"^chrome[\\\/]test[\\\/]media_router[\\\/]" +
+            r"media_router_integration_browsertest\.cc$",
         r"^chrome[\\\/]test[\\\/]ppapi[\\\/]ppapi_filechooser_browsertest\.cc$",
         r"^components[\\\/]crash[\\\/]app[\\\/]breakpad_mac\.mm$",
         r"^content[\\\/]shell[\\\/]browser[\\\/]layout_test[\\\/]" +
diff --git a/PRESUBMIT_test_mocks.py b/PRESUBMIT_test_mocks.py
index c269deec..e2e43e3 100644
--- a/PRESUBMIT_test_mocks.py
+++ b/PRESUBMIT_test_mocks.py
@@ -27,6 +27,7 @@
     self.files = []
     self.is_committing = False
     self.change = MockChange([])
+    self.presubmit_local_path = os.path.dirname(__file__)
 
   def AffectedFiles(self, file_filter=None, include_deletes=False):
     return self.files
@@ -38,7 +39,7 @@
     return self.files
 
   def PresubmitLocalPath(self):
-    return os.path.dirname(__file__)
+    return self.presubmit_local_path
 
   def ReadFile(self, filename, mode='rU'):
     if hasattr(filename, 'AbsoluteLocalPath'):
diff --git a/WATCHLISTS b/WATCHLISTS
index f036247..0a791b11 100644
--- a/WATCHLISTS
+++ b/WATCHLISTS
@@ -1158,6 +1158,9 @@
                   '|ios/chrome/app/strings/ios(_.+)*_strings.grd'\
                   '|ui/strings/ui_strings.grd',
     },
+    'use_counter_features': {
+      'filepath': 'third_party/WebKit/public/platform/UseCounterFeature.def',
+    },
     'valgrind': {
       'filepath': 'valgrind',
     },
@@ -2272,6 +2275,7 @@
     'ui_display_win': ['robliao+watch@chromium.org'],
     'ui_resources': ['oshima+watch@chromium.org'],
     'ui_strings': ['srahim+watch@chromium.org'],
+    'use_counter_features': ['lunalu@chromium.org'],
     'valgrind': ['bruening+watch@chromium.org',
                  'glider+watch@chromium.org'],
     'version_assembly': ['caitkp+watch@chromium.org',
diff --git a/android_webview/tools/system_webview_shell/apk/res/layout/activity_webview_browser.xml b/android_webview/tools/system_webview_shell/apk/res/layout/activity_webview_browser.xml
index d20ef74e..01f8b29 100644
--- a/android_webview/tools/system_webview_shell/apk/res/layout/activity_webview_browser.xml
+++ b/android_webview/tools/system_webview_shell/apk/res/layout/activity_webview_browser.xml
@@ -25,14 +25,14 @@
             android:selectAllOnFocus="true"
             android:imeOptions="actionGo" />
         <ImageButton
-            android:layout_width="wrap_content" 
-            android:layout_height="match_parent" 
+            android:layout_width="wrap_content"
+            android:layout_height="match_parent"
             android:src="@drawable/breadcrumb_arrow_black"
             android:contentDescription="@string/load_url"
             android:onClick="loadUrlFromUrlBar" />
         <ImageButton
-            android:layout_width="wrap_content" 
-            android:layout_height="match_parent" 
+            android:layout_width="wrap_content"
+            android:layout_height="match_parent"
             android:src="@drawable/item_more_black"
             android:contentDescription="@string/menu_about"
             android:onClick="showPopup" />
diff --git a/ash/accelerators/accelerator_controller_unittest.cc b/ash/accelerators/accelerator_controller_unittest.cc
index 178130e40..d5120d95 100644
--- a/ash/accelerators/accelerator_controller_unittest.cc
+++ b/ash/accelerators/accelerator_controller_unittest.cc
@@ -26,7 +26,6 @@
 #include "ash/wm/window_state.h"
 #include "ash/wm/window_util.h"
 #include "ash/wm/wm_event.h"
-#include "ash/wm_window.h"
 #include "base/command_line.h"
 #include "base/test/user_action_tester.h"
 #include "services/ui/public/interfaces/window_manager_constants.mojom.h"
diff --git a/ash/accelerators/exit_warning_handler.cc b/ash/accelerators/exit_warning_handler.cc
index 6cc38d5..27989c0 100644
--- a/ash/accelerators/exit_warning_handler.cc
+++ b/ash/accelerators/exit_warning_handler.cc
@@ -10,7 +10,6 @@
 #include "ash/shell_delegate.h"
 #include "ash/shell_port.h"
 #include "ash/strings/grit/ash_strings.h"
-#include "ash/wm_window.h"
 #include "base/strings/utf_string_conversions.h"
 #include "base/time/time.h"
 #include "base/timer/timer.h"
diff --git a/ash/app_list/app_list_delegate_impl.cc b/ash/app_list/app_list_delegate_impl.cc
index c8fbf0f..ef2f8c9 100644
--- a/ash/app_list/app_list_delegate_impl.cc
+++ b/ash/app_list/app_list_delegate_impl.cc
@@ -10,7 +10,6 @@
 #include "ash/shelf/shelf_widget.h"
 #include "ash/shell.h"
 #include "ash/shell_port.h"
-#include "ash/wm_window.h"
 #include "ui/app_list/presenter/app_list.h"
 
 namespace ash {
diff --git a/ash/app_list/app_list_presenter_delegate.cc b/ash/app_list/app_list_presenter_delegate.cc
index e32d7c94..0bbb1c1 100644
--- a/ash/app_list/app_list_presenter_delegate.cc
+++ b/ash/app_list/app_list_presenter_delegate.cc
@@ -16,7 +16,6 @@
 #include "ash/shell.h"
 #include "ash/shell_port.h"
 #include "ash/wm/maximize_mode/maximize_mode_controller.h"
-#include "ash/wm_window.h"
 #include "base/command_line.h"
 #include "ui/app_list/app_list_constants.h"
 #include "ui/app_list/app_list_features.h"
@@ -28,6 +27,7 @@
 #include "ui/events/event.h"
 #include "ui/keyboard/keyboard_controller.h"
 #include "ui/views/widget/widget.h"
+#include "ui/wm/core/coordinate_conversion.h"
 
 namespace ash {
 namespace {
@@ -36,11 +36,11 @@
 // This calculation excludes the virtual keyboard area. If the height of the
 // display area is less than |minimum_height|, its bottom will be extended to
 // that height (so that the app list never starts above the top of the screen).
-gfx::Point GetCenterOfDisplayForWindow(WmWindow* window, int minimum_height) {
+gfx::Point GetCenterOfDisplayForWindow(aura::Window* window,
+                                       int minimum_height) {
   DCHECK(window);
-  gfx::Rect bounds =
-      ScreenUtil::GetDisplayBoundsWithShelf(window->aura_window());
-  bounds = window->GetRootWindow()->ConvertRectToScreen(bounds);
+  gfx::Rect bounds = ScreenUtil::GetDisplayBoundsWithShelf(window);
+  ::wm::ConvertRectToScreen(window->GetRootWindow(), &bounds);
 
   // If the virtual keyboard is active, subtract it from the display bounds, so
   // that the app list is centered in the non-keyboard area of the display.
@@ -102,7 +102,7 @@
 
   if (!app_list::features::IsFullscreenAppListEnabled()) {
     view->MaybeSetAnchorPoint(GetCenterOfDisplayForWindow(
-        WmWindow::Get(root_window), GetMinimumBoundsHeightForAppList(view)));
+        root_window, GetMinimumBoundsHeightForAppList(view)));
   }
   keyboard::KeyboardController* keyboard_controller =
       keyboard::KeyboardController::GetInstance();
@@ -146,9 +146,9 @@
     return;
 
   view_->UpdateBounds();
-  view_->MaybeSetAnchorPoint(GetCenterOfDisplayForWindow(
-      WmWindow::Get(view_->GetWidget()->GetNativeWindow()),
-      GetMinimumBoundsHeightForAppList(view_)));
+  view_->MaybeSetAnchorPoint(
+      GetCenterOfDisplayForWindow(view_->GetWidget()->GetNativeWindow(),
+                                  GetMinimumBoundsHeightForAppList(view_)));
 }
 
 gfx::Vector2d AppListPresenterDelegate::GetVisibilityAnimationOffset(
diff --git a/ash/app_list/app_list_presenter_delegate_unittest.cc b/ash/app_list/app_list_presenter_delegate_unittest.cc
index ecc32aa..ab85c94 100644
--- a/ash/app_list/app_list_presenter_delegate_unittest.cc
+++ b/ash/app_list/app_list_presenter_delegate_unittest.cc
@@ -10,7 +10,6 @@
 #include "ash/test/ash_test_base.h"
 #include "ash/test/test_app_list_view_presenter_impl.h"
 #include "ash/wm/window_util.h"
-#include "ash/wm_window.h"
 #include "base/command_line.h"
 #include "base/macros.h"
 #include "base/test/scoped_feature_list.h"
diff --git a/ash/ash_touch_exploration_manager_chromeos.cc b/ash/ash_touch_exploration_manager_chromeos.cc
index 3b56eef..bbe28d8a 100644
--- a/ash/ash_touch_exploration_manager_chromeos.cc
+++ b/ash/ash_touch_exploration_manager_chromeos.cc
@@ -11,7 +11,6 @@
 #include "ash/shell.h"
 #include "ash/system/tray/system_tray_notifier.h"
 #include "ash/wm/window_util.h"
-#include "ash/wm_window.h"
 #include "base/command_line.h"
 #include "base/memory/ptr_util.h"
 #include "chromeos/audio/chromeos_sounds.h"
@@ -104,8 +103,10 @@
 void AshTouchExplorationManager::OnDisplayMetricsChanged(
     const display::Display& display,
     uint32_t changed_metrics) {
-  if (root_window_controller_->GetWindow()->GetDisplayNearestWindow().id() ==
-      display.id())
+  const display::Display this_display =
+      display::Screen::GetScreen()->GetDisplayNearestWindow(
+          root_window_controller_->GetRootWindow());
+  if (this_display.id() == display.id())
     UpdateTouchExplorationState();
 }
 
@@ -190,9 +191,10 @@
               touch_accessibility_enabler_.get());
     }
     if (pass_through_surface) {
-      const gfx::Rect work_area = root_window_controller_->GetWindow()
-                                      ->GetDisplayNearestWindow()
-                                      .work_area();
+      const display::Display display =
+          display::Screen::GetScreen()->GetDisplayNearestWindow(
+              root_window_controller_->GetRootWindow());
+      const gfx::Rect work_area = display.work_area();
       touch_exploration_controller_->SetExcludeBounds(work_area);
       SilenceSpokenFeedback();
       Shell::Get()->accessibility_delegate()->ClearFocusHighlight();
diff --git a/ash/content/display/screen_orientation_controller_chromeos_unittest.cc b/ash/content/display/screen_orientation_controller_chromeos_unittest.cc
index 7aa3ab70..60fca91 100644
--- a/ash/content/display/screen_orientation_controller_chromeos_unittest.cc
+++ b/ash/content/display/screen_orientation_controller_chromeos_unittest.cc
@@ -22,7 +22,6 @@
 #include "ash/test/test_system_tray_delegate.h"
 #include "ash/wm/maximize_mode/maximize_mode_controller.h"
 #include "ash/wm/window_state.h"
-#include "ash/wm_window.h"
 #include "base/command_line.h"
 #include "chromeos/accelerometer/accelerometer_reader.h"
 #include "chromeos/accelerometer/accelerometer_types.h"
@@ -30,6 +29,7 @@
 #include "content/public/browser/web_contents.h"
 #include "content/public/test/test_browser_context.h"
 #include "third_party/WebKit/public/platform/modules/screen_orientation/WebScreenOrientationLockType.h"
+#include "ui/aura/client/aura_constants.h"
 #include "ui/aura/window.h"
 #include "ui/display/display.h"
 #include "ui/display/display_switches.h"
@@ -132,7 +132,8 @@
  protected:
   aura::Window* CreateAppWindowInShellWithId(int id) {
     aura::Window* window = CreateTestWindowInShellWithId(id);
-    WmWindow::Get(window)->SetAppType(static_cast<int>(AppType::CHROME_APP));
+    window->SetProperty(aura::client::kAppType,
+                        static_cast<int>(AppType::CHROME_APP));
     return window;
   }
 
diff --git a/ash/display/screen_position_controller.cc b/ash/display/screen_position_controller.cc
index 6b5da7c..ac3d906c 100644
--- a/ash/display/screen_position_controller.cc
+++ b/ash/display/screen_position_controller.cc
@@ -6,11 +6,9 @@
 
 #include "ash/public/cpp/shell_window_ids.h"
 #include "ash/shell.h"
-#include "ash/shell_port.h"
 #include "ash/wm/window_positioning_utils.h"
 #include "ash/wm/window_properties.h"
 #include "ash/wm/window_state.h"
-#include "ash/wm_window.h"
 #include "ui/aura/window.h"
 #include "ui/aura/window_tree_host.h"
 #include "ui/compositor/dip_util.h"
@@ -103,9 +101,8 @@
     gfx::Point* point) {
   aura::Window* root = root_window->GetRootWindow();
   aura::Window* target_root = nullptr;
-  ConvertHostPointToRelativeToRootWindow(
-      root, WmWindow::ToAuraWindows(ShellPort::Get()->GetAllRootWindows()),
-      point, &target_root);
+  ConvertHostPointToRelativeToRootWindow(root, Shell::GetAllRootWindows(),
+                                         point, &target_root);
   ConvertPointToScreen(target_root, point);
 }
 
diff --git a/ash/drag_drop/drag_drop_controller.cc b/ash/drag_drop/drag_drop_controller.cc
index 5ed0e09a..524fab5 100644
--- a/ash/drag_drop/drag_drop_controller.cc
+++ b/ash/drag_drop/drag_drop_controller.cc
@@ -10,7 +10,6 @@
 #include "ash/drag_drop/drag_image_view.h"
 #include "ash/shell.h"
 #include "ash/shell_port.h"
-#include "ash/wm_window.h"
 #include "base/bind.h"
 #include "base/memory/ptr_util.h"
 #include "base/message_loop/message_loop.h"
diff --git a/ash/drag_drop/drag_drop_tracker_unittest.cc b/ash/drag_drop/drag_drop_tracker_unittest.cc
index b8c37965..3cb8ec3 100644
--- a/ash/drag_drop/drag_drop_tracker_unittest.cc
+++ b/ash/drag_drop/drag_drop_tracker_unittest.cc
@@ -10,7 +10,6 @@
 #include "ash/scoped_root_window_for_new_windows.h"
 #include "ash/shell.h"
 #include "ash/test/ash_test_base.h"
-#include "ash/wm_window.h"
 #include "ui/aura/test/test_windows.h"
 #include "ui/aura/window.h"
 #include "ui/aura/window_event_dispatcher.h"
diff --git a/ash/first_run/first_run_helper_impl.cc b/ash/first_run/first_run_helper_impl.cc
index b4c5f9e..c9c4d17 100644
--- a/ash/first_run/first_run_helper_impl.cc
+++ b/ash/first_run/first_run_helper_impl.cc
@@ -10,7 +10,6 @@
 #include "ash/shelf/shelf_widget.h"
 #include "ash/shell.h"
 #include "ash/system/tray/system_tray.h"
-#include "ash/wm_window.h"
 #include "base/logging.h"
 #include "ui/app_list/views/app_list_view.h"
 #include "ui/aura/window.h"
diff --git a/ash/frame/custom_frame_view_ash.cc b/ash/frame/custom_frame_view_ash.cc
index 46c581c..7fd4fed 100644
--- a/ash/frame/custom_frame_view_ash.cc
+++ b/ash/frame/custom_frame_view_ash.cc
@@ -13,10 +13,11 @@
 #include "ash/shared/immersive_fullscreen_controller.h"
 #include "ash/shared/immersive_fullscreen_controller_delegate.h"
 #include "ash/shell_port.h"
+#include "ash/wm/resize_handle_window_targeter.h"
 #include "ash/wm/window_state.h"
 #include "ash/wm/window_state_delegate.h"
 #include "ash/wm/window_state_observer.h"
-#include "ash/wm_window.h"
+#include "ash/wm/window_util.h"
 #include "base/memory/ptr_util.h"
 #include "ui/aura/client/aura_constants.h"
 #include "ui/aura/window.h"
@@ -261,17 +262,17 @@
       immersive_delegate_(immersive_delegate ? immersive_delegate
                                              : header_view_),
       avatar_observer_(base::MakeUnique<AvatarObserver>(frame_, header_view_)) {
-  WmWindow* frame_window = WmWindow::Get(frame->GetNativeWindow());
-  frame_window->InstallResizeHandleWindowTargeter(nullptr);
+  aura::Window* frame_window = frame->GetNativeWindow();
+  wm::InstallResizeHandleWindowTargeterForWindow(frame_window, nullptr);
   // |header_view_| is set as the non client view's overlay view so that it can
   // overlay the web contents in immersive fullscreen.
   frame->non_client_view()->SetOverlayView(overlay_view_);
-  frame_window->aura_window()->SetProperty(
-      aura::client::kTopViewColor, header_view_->GetInactiveFrameColor());
+  frame_window->SetProperty(aura::client::kTopViewColor,
+                            header_view_->GetInactiveFrameColor());
 
   // A delegate for a more complex way of fullscreening the window may already
   // be set. This is the case for packaged apps.
-  wm::WindowState* window_state = frame_window->GetWindowState();
+  wm::WindowState* window_state = wm::GetWindowState(frame_window);
   if (!window_state->HasDelegate()) {
     window_state->SetDelegate(std::unique_ptr<wm::WindowStateDelegate>(
         new CustomFrameViewAshWindowStateDelegate(window_state, this,
@@ -290,9 +291,9 @@
 void CustomFrameViewAsh::SetFrameColors(SkColor active_frame_color,
                                         SkColor inactive_frame_color) {
   header_view_->SetFrameColors(active_frame_color, inactive_frame_color);
-  WmWindow* frame_window = WmWindow::Get(frame_->GetNativeWindow());
-  frame_window->aura_window()->SetProperty(
-      aura::client::kTopViewColor, header_view_->GetInactiveFrameColor());
+  aura::Window* frame_window = frame_->GetNativeWindow();
+  frame_window->SetProperty(aura::client::kTopViewColor,
+                            header_view_->GetInactiveFrameColor());
 }
 
 void CustomFrameViewAsh::SetHeaderHeight(base::Optional<int> height) {
@@ -361,9 +362,9 @@
 
 void CustomFrameViewAsh::Layout() {
   views::NonClientFrameView::Layout();
-  WmWindow* frame_window = WmWindow::Get(frame_->GetNativeWindow());
-  frame_window->aura_window()->SetProperty(aura::client::kTopViewInset,
-                                           NonClientTopBorderHeight());
+  aura::Window* frame_window = frame_->GetNativeWindow();
+  frame_window->SetProperty(aura::client::kTopViewInset,
+                            NonClientTopBorderHeight());
 }
 
 const char* CustomFrameViewAsh::GetClassName() const {
diff --git a/ash/frame/header_painter_util.cc b/ash/frame/header_painter_util.cc
index d7d79f8..f7f4550e 100644
--- a/ash/frame/header_painter_util.cc
+++ b/ash/frame/header_painter_util.cc
@@ -6,7 +6,7 @@
 
 #include <algorithm>
 
-#include "ash/wm_window.h"
+#include "ui/aura/window.h"
 #include "ui/compositor/layer.h"
 #include "ui/compositor/layer_animator.h"
 #include "ui/gfx/font_list.h"
@@ -82,13 +82,13 @@
   // rate.
   // TODO(sky): Expose a better way to determine this rather than assuming the
   // parent is a toplevel container.
-  WmWindow* window = WmWindow::Get(widget->GetNativeWindow());
-  // TODO(sky): GetParent()->GetLayer() is for mash until animations ported.
-  if (!window || !window->GetParent() || !window->GetParent()->GetLayer())
+  aura::Window* window = widget->GetNativeWindow();
+  // TODO(sky): parent()->layer() is for mash until animations ported.
+  if (!window || !window->parent() || !window->parent()->layer())
     return true;
 
   ui::LayerAnimator* parent_layer_animator =
-      window->GetParent()->GetLayer()->GetAnimator();
+      window->parent()->layer()->GetAnimator();
   return !parent_layer_animator->IsAnimatingProperty(
              ui::LayerAnimationElement::OPACITY) &&
          !parent_layer_animator->IsAnimatingProperty(
diff --git a/ash/frame/header_view.cc b/ash/frame/header_view.cc
index 85d0537..8b8358b 100644
--- a/ash/frame/header_view.cc
+++ b/ash/frame/header_view.cc
@@ -7,7 +7,6 @@
 #include "ash/frame/caption_buttons/frame_caption_button_container_view.h"
 #include "ash/frame/default_header_painter.h"
 #include "ash/shell.h"
-#include "ash/wm_window.h"
 #include "ui/views/controls/image_view.h"
 #include "ui/views/widget/widget.h"
 
diff --git a/ash/high_contrast/high_contrast_controller.cc b/ash/high_contrast/high_contrast_controller.cc
index ebe2176..d8a65d1 100644
--- a/ash/high_contrast/high_contrast_controller.cc
+++ b/ash/high_contrast/high_contrast_controller.cc
@@ -5,7 +5,6 @@
 #include "ash/high_contrast/high_contrast_controller.h"
 
 #include "ash/shell.h"
-#include "ash/wm_window.h"
 #include "ui/aura/window_event_dispatcher.h"
 #include "ui/compositor/layer.h"
 
diff --git a/ash/metrics/pointer_metrics_recorder.cc b/ash/metrics/pointer_metrics_recorder.cc
index 65d6f54..f216be6 100644
--- a/ash/metrics/pointer_metrics_recorder.cc
+++ b/ash/metrics/pointer_metrics_recorder.cc
@@ -8,8 +8,9 @@
 #include "ash/shell.h"
 #include "ash/shell_port.h"
 #include "ash/wm/maximize_mode/maximize_mode_controller.h"
-#include "ash/wm_window.h"
 #include "base/metrics/histogram_macros.h"
+#include "ui/aura/client/aura_constants.h"
+#include "ui/aura/window.h"
 #include "ui/events/event_constants.h"
 #include "ui/views/widget/widget.h"
 
@@ -39,9 +40,9 @@
   if (!target)
     return static_cast<int>(AppType::OTHERS);
 
-  WmWindow* window = WmWindow::Get(target->GetNativeWindow());
+  aura::Window* window = target->GetNativeWindow();
   DCHECK(window);
-  return window->GetAppType();
+  return window->GetProperty(aura::client::kAppType);
 }
 
 void RecordUMA(ui::EventPointerType type, views::Widget* target) {
diff --git a/ash/metrics/pointer_metrics_recorder_unittest.cc b/ash/metrics/pointer_metrics_recorder_unittest.cc
index 4a8212ef..3112ba5 100644
--- a/ash/metrics/pointer_metrics_recorder_unittest.cc
+++ b/ash/metrics/pointer_metrics_recorder_unittest.cc
@@ -9,8 +9,9 @@
 #include "ash/shell.h"
 #include "ash/test/ash_test_base.h"
 #include "ash/wm/maximize_mode/maximize_mode_controller.h"
-#include "ash/wm_window.h"
 #include "base/test/histogram_tester.h"
+#include "ui/aura/client/aura_constants.h"
+#include "ui/aura/window.h"
 #include "ui/events/event.h"
 #include "ui/views/pointer_watcher.h"
 #include "ui/views/widget/widget.h"
@@ -158,25 +159,29 @@
       ui::PointerDetails(ui::EventPointerType::POINTER_TYPE_MOUSE, 0),
       base::TimeTicks());
 
-  WmWindow* window = WmWindow::Get(target->GetNativeWindow());
+  aura::Window* window = target->GetNativeWindow();
   CHECK(window);
 
-  window->SetAppType(static_cast<int>(AppType::OTHERS));
+  window->SetProperty(aura::client::kAppType,
+                      static_cast<int>(AppType::OTHERS));
   pointer_metrics_recorder_->OnPointerEventObserved(pointer_event, gfx::Point(),
                                                     target.get());
   histogram_tester_->ExpectBucketCount(kDestinationHistogramName, 0, 1);
 
-  window->SetAppType(static_cast<int>(AppType::BROWSER));
+  window->SetProperty(aura::client::kAppType,
+                      static_cast<int>(AppType::BROWSER));
   pointer_metrics_recorder_->OnPointerEventObserved(pointer_event, gfx::Point(),
                                                     target.get());
   histogram_tester_->ExpectBucketCount(kDestinationHistogramName, 1, 1);
 
-  window->SetAppType(static_cast<int>(AppType::CHROME_APP));
+  window->SetProperty(aura::client::kAppType,
+                      static_cast<int>(AppType::CHROME_APP));
   pointer_metrics_recorder_->OnPointerEventObserved(pointer_event, gfx::Point(),
                                                     target.get());
   histogram_tester_->ExpectBucketCount(kDestinationHistogramName, 2, 1);
 
-  window->SetAppType(static_cast<int>(AppType::ARC_APP));
+  window->SetProperty(aura::client::kAppType,
+                      static_cast<int>(AppType::ARC_APP));
   pointer_metrics_recorder_->OnPointerEventObserved(pointer_event, gfx::Point(),
                                                     target.get());
   histogram_tester_->ExpectBucketCount(kDestinationHistogramName, 3, 1);
diff --git a/ash/metrics/user_metrics_recorder.cc b/ash/metrics/user_metrics_recorder.cc
index a25e505..065ad0f 100644
--- a/ash/metrics/user_metrics_recorder.cc
+++ b/ash/metrics/user_metrics_recorder.cc
@@ -14,7 +14,6 @@
 #include "ash/shelf/shelf_view.h"
 #include "ash/shell.h"
 #include "ash/wm/window_state.h"
-#include "ash/wm_window.h"
 #include "base/memory/ptr_util.h"
 #include "base/metrics/histogram_macros.h"
 #include "base/metrics/user_metrics.h"
diff --git a/ash/metrics/user_metrics_recorder_unittest.cc b/ash/metrics/user_metrics_recorder_unittest.cc
index f7323bb..d688800 100644
--- a/ash/metrics/user_metrics_recorder_unittest.cc
+++ b/ash/metrics/user_metrics_recorder_unittest.cc
@@ -15,7 +15,6 @@
 #include "ash/test/ash_test_base.h"
 #include "ash/test/test_session_controller_client.h"
 #include "ash/test/user_metrics_recorder_test_api.h"
-#include "ash/wm_window.h"
 #include "base/test/histogram_tester.h"
 
 using session_manager::SessionState;
diff --git a/ash/mus/disconnected_app_handler.cc b/ash/mus/disconnected_app_handler.cc
index 12d3c973..334cf182 100644
--- a/ash/mus/disconnected_app_handler.cc
+++ b/ash/mus/disconnected_app_handler.cc
@@ -5,7 +5,6 @@
 #include "ash/mus/disconnected_app_handler.h"
 
 #include "ash/public/cpp/shell_window_ids.h"
-#include "ash/wm_window.h"
 #include "ui/aura/window.h"
 #include "ui/base/class_property.h"
 
diff --git a/ash/mus/frame/detached_title_area_renderer.cc b/ash/mus/frame/detached_title_area_renderer.cc
index 7d153b55..f0b500f 100644
--- a/ash/mus/frame/detached_title_area_renderer.cc
+++ b/ash/mus/frame/detached_title_area_renderer.cc
@@ -8,7 +8,6 @@
 #include "ash/mus/property_util.h"
 #include "ash/mus/window_manager.h"
 #include "ash/wm/window_state.h"
-#include "ash/wm_window.h"
 #include "ui/aura/client/aura_constants.h"
 #include "ui/aura/client/transient_window_client.h"
 #include "ui/aura/mus/property_converter.h"
@@ -53,7 +52,7 @@
   // Default animations conflict with the reveal animation, so turn off the
   // default animation.
   window->SetProperty(aura::client::kAnimationsDisabledKey, true);
-  WmWindow::Get(window)->GetWindowState()->set_ignored_by_shelf(true);
+  wm::GetWindowState(window)->set_ignored_by_shelf(true);
 }
 
 void CreateHeaderView(views::Widget* frame,
diff --git a/ash/mus/top_level_window_factory.cc b/ash/mus/top_level_window_factory.cc
index 8149f63ac..639eb60 100644
--- a/ash/mus/top_level_window_factory.cc
+++ b/ash/mus/top_level_window_factory.cc
@@ -15,7 +15,6 @@
 #include "ash/shell.h"
 #include "ash/wm/container_finder.h"
 #include "ash/wm/window_state.h"
-#include "ash/wm_window.h"
 #include "mojo/public/cpp/bindings/type_converter.h"
 #include "services/ui/public/cpp/property_type_converters.h"
 #include "services/ui/public/interfaces/window_manager.mojom.h"
@@ -26,6 +25,7 @@
 #include "ui/aura/mus/window_tree_client.h"
 #include "ui/aura/window.h"
 #include "ui/display/display.h"
+#include "ui/display/screen.h"
 
 namespace ash {
 namespace mus {
@@ -95,7 +95,8 @@
       gfx::Rect bounds(root_size);
       if (!container_window) {
         const display::Display display =
-            root_window_controller->GetWindow()->GetDisplayNearestWindow();
+            display::Screen::GetScreen()->GetDisplayNearestWindow(
+                root_window_controller->GetRootWindow());
         bounds.Offset(display.bounds().OffsetFromOrigin());
       }
       return bounds;
@@ -178,13 +179,13 @@
   if (container_window) {
     container_window->AddChild(window);
   } else {
-    WmWindow* root = root_window_controller->GetWindow();
-    gfx::Point origin =
-        root->ConvertPointToTarget(root->GetRootWindow(), gfx::Point());
-    origin += root_window_controller->GetWindow()
-                  ->GetDisplayNearestWindow()
-                  .bounds()
-                  .OffsetFromOrigin();
+    aura::Window* root = root_window_controller->GetRootWindow();
+    gfx::Point origin;
+    aura::Window::ConvertPointToTarget(root, root->GetRootWindow(), &origin);
+    const display::Display display =
+        display::Screen::GetScreen()->GetDisplayNearestWindow(
+            root_window_controller->GetRootWindow());
+    origin += display.bounds().OffsetFromOrigin();
     gfx::Rect bounds_in_screen(origin, bounds.size());
     ash::wm::GetDefaultParent(window, bounds_in_screen)->AddChild(window);
   }
@@ -206,7 +207,7 @@
   auto ignored_by_shelf_iter = properties->find(
       ui::mojom::WindowManager::kWindowIgnoredByShelf_InitProperty);
   if (ignored_by_shelf_iter != properties->end()) {
-    wm::WindowState* window_state = WmWindow::Get(window)->GetWindowState();
+    wm::WindowState* window_state = wm::GetWindowState(window);
     window_state->set_ignored_by_shelf(
         mojo::ConvertTo<bool>(ignored_by_shelf_iter->second));
     // No need to persist this value.
diff --git a/ash/mus/window_manager.cc b/ash/mus/window_manager.cc
index 32a5fcfd..c9fad8d6 100644
--- a/ash/mus/window_manager.cc
+++ b/ash/mus/window_manager.cc
@@ -33,7 +33,6 @@
 #include "ash/wm/ash_focus_rules.h"
 #include "ash/wm/container_finder.h"
 #include "ash/wm/window_state.h"
-#include "ash/wm_window.h"
 #include "base/memory/ptr_util.h"
 #include "base/threading/sequenced_worker_pool.h"
 #include "services/service_manager/public/cpp/connector.h"
@@ -353,7 +352,7 @@
                                   const gfx::Rect& bounds) {
   // TODO(sky): this indirectly sets bounds, which is against what
   // OnWmSetBounds() recommends doing. Remove that restriction, or fix this.
-  WmWindow::Get(window)->SetBounds(bounds);
+  window->SetBounds(bounds);
 }
 
 bool WindowManager::OnWmSetProperty(
diff --git a/ash/screen_util.cc b/ash/screen_util.cc
index d054568..b6cbf603 100644
--- a/ash/screen_util.cc
+++ b/ash/screen_util.cc
@@ -8,7 +8,6 @@
 #include "ash/shelf/shelf.h"
 #include "ash/shell.h"
 #include "ash/shell_port.h"
-#include "ash/wm_window.h"
 #include "base/logging.h"
 #include "ui/aura/client/screen_position_client.h"
 #include "ui/aura/window_event_dispatcher.h"
diff --git a/ash/shared/immersive_fullscreen_controller.cc b/ash/shared/immersive_fullscreen_controller.cc
index a5f1199..0a6aec6 100644
--- a/ash/shared/immersive_fullscreen_controller.cc
+++ b/ash/shared/immersive_fullscreen_controller.cc
@@ -253,7 +253,6 @@
 
 void ImmersiveFullscreenController::OnWidgetDestroying(views::Widget* widget) {
   EnableWindowObservers(false);
-  widget_window_ = nullptr;
 
   // Set |enabled_| to false such that any calls to MaybeStartReveal() and
   // MaybeEndReveal() have no effect.
diff --git a/ash/shared/immersive_fullscreen_controller.h b/ash/shared/immersive_fullscreen_controller.h
index bbbca35..c81d99ac 100644
--- a/ash/shared/immersive_fullscreen_controller.h
+++ b/ash/shared/immersive_fullscreen_controller.h
@@ -39,7 +39,6 @@
 class ImmersiveFullscreenControllerDelegate;
 class ImmersiveFullscreenControllerTestApi;
 class ImmersiveGestureHandler;
-class WmWindow;
 
 class ASH_EXPORT ImmersiveFullscreenController
     : public gfx::AnimationDelegate,
@@ -227,8 +226,6 @@
   ImmersiveFullscreenControllerDelegate* delegate_;
   views::View* top_container_;
   views::Widget* widget_;
-  // The WmWindow for |widget_|.
-  WmWindow* widget_window_ = nullptr;
 
   // True if the observers have been enabled.
   bool observers_enabled_;
diff --git a/ash/shell/window_watcher.cc b/ash/shell/window_watcher.cc
index a824a40..2fb4b4c 100644
--- a/ash/shell/window_watcher.cc
+++ b/ash/shell/window_watcher.cc
@@ -15,7 +15,6 @@
 #include "ash/shell/window_watcher_shelf_item_delegate.h"
 #include "ash/shell_port.h"
 #include "ash/wm/window_util.h"
-#include "ash/wm_window.h"
 #include "base/strings/string_number_conversions.h"
 #include "ui/aura/window.h"
 #include "ui/aura/window_event_dispatcher.h"
diff --git a/ash/shell_delegate.h b/ash/shell_delegate.h
index 8aba5529..f5c62c3b 100644
--- a/ash/shell_delegate.h
+++ b/ash/shell_delegate.h
@@ -138,6 +138,9 @@
 
   // Toggles the status of touchpad between enabled and disabled.
   virtual void ToggleTouchpad() {}
+
+  // Suspends all WebContents-associated media sessions to stop managed players.
+  virtual void SuspendMediaSessions() {}
 };
 
 }  // namespace ash
diff --git a/ash/shell_unittest.cc b/ash/shell_unittest.cc
index 7506c18..62bf1237 100644
--- a/ash/shell_unittest.cc
+++ b/ash/shell_unittest.cc
@@ -22,7 +22,6 @@
 #include "ash/test/test_session_controller_client.h"
 #include "ash/wallpaper/wallpaper_widget_controller.h"
 #include "ash/wm/window_util.h"
-#include "ash/wm_window.h"
 #include "base/macros.h"
 #include "base/strings/utf_string_conversions.h"
 #include "base/threading/thread_task_runner_handle.h"
diff --git a/ash/sticky_keys/sticky_keys_overlay_unittest.cc b/ash/sticky_keys/sticky_keys_overlay_unittest.cc
index dcf60cb..02a00bdc 100644
--- a/ash/sticky_keys/sticky_keys_overlay_unittest.cc
+++ b/ash/sticky_keys/sticky_keys_overlay_unittest.cc
@@ -9,7 +9,6 @@
 #include "ash/shell_port.h"
 #include "ash/sticky_keys/sticky_keys_controller.h"
 #include "ash/test/ash_test_base.h"
-#include "ash/wm_window.h"
 #include "ui/display/display_layout.h"
 #include "ui/display/manager/display_manager.h"
 #include "ui/display/test/display_manager_test_api.h"
diff --git a/ash/system/power/tablet_power_button_controller.cc b/ash/system/power/tablet_power_button_controller.cc
index b4ed4f18..4beeb3e 100644
--- a/ash/system/power/tablet_power_button_controller.cc
+++ b/ash/system/power/tablet_power_button_controller.cc
@@ -221,6 +221,9 @@
   backlights_forced_off_ = forced_off;
   UpdateTouchscreenStatus();
 
+  if (backlights_forced_off_)
+    Shell::Get()->shell_delegate()->SuspendMediaSessions();
+
   // Send an a11y alert.
   Shell::Get()->accessibility_delegate()->TriggerAccessibilityAlert(
       forced_off ? A11Y_ALERT_SCREEN_OFF : A11Y_ALERT_SCREEN_ON);
diff --git a/ash/system/power/tablet_power_button_controller_unittest.cc b/ash/system/power/tablet_power_button_controller_unittest.cc
index a0bfcda..3a5139d8 100644
--- a/ash/system/power/tablet_power_button_controller_unittest.cc
+++ b/ash/system/power/tablet_power_button_controller_unittest.cc
@@ -558,5 +558,15 @@
   EXPECT_TRUE(tablet_controller_);
 }
 
+// Tests that when backlights get forced off due to tablet power button, media
+// sessions should be suspended.
+TEST_F(TabletPowerButtonControllerTest, SuspendMediaSessions) {
+  ASSERT_FALSE(shell_delegate_->media_sessions_suspended());
+  PressPowerButton();
+  ReleasePowerButton();
+  ASSERT_TRUE(GetBacklightsForcedOff());
+  EXPECT_TRUE(shell_delegate_->media_sessions_suspended());
+}
+
 }  // namespace test
 }  // namespace ash
diff --git a/ash/system/session/logout_confirmation_dialog.cc b/ash/system/session/logout_confirmation_dialog.cc
index 20a8ced..f322008 100644
--- a/ash/system/session/logout_confirmation_dialog.cc
+++ b/ash/system/session/logout_confirmation_dialog.cc
@@ -10,7 +10,6 @@
 #include "ash/strings/grit/ash_strings.h"
 #include "ash/system/session/logout_confirmation_controller.h"
 #include "ash/system/tray/tray_constants.h"
-#include "ash/wm_window.h"
 #include "base/location.h"
 #include "base/time/tick_clock.h"
 #include "ui/base/l10n/l10n_util.h"
diff --git a/ash/system/status_area_widget_delegate.cc b/ash/system/status_area_widget_delegate.cc
index b84b34d5..44eb28d5 100644
--- a/ash/system/status_area_widget_delegate.cc
+++ b/ash/system/status_area_widget_delegate.cc
@@ -13,7 +13,6 @@
 #include "ash/system/status_area_widget.h"
 #include "ash/system/tray/system_tray.h"
 #include "ash/system/tray/tray_constants.h"
-#include "ash/wm_window.h"
 #include "ui/compositor/layer.h"
 #include "ui/compositor/scoped_layer_animation_settings.h"
 #include "ui/gfx/animation/tween.h"
diff --git a/ash/system/tray/system_tray_controller.cc b/ash/system/tray/system_tray_controller.cc
index 41854e81..a3232bdb 100644
--- a/ash/system/tray/system_tray_controller.cc
+++ b/ash/system/tray/system_tray_controller.cc
@@ -10,7 +10,6 @@
 #include "ash/system/tray/system_tray.h"
 #include "ash/system/tray/system_tray_notifier.h"
 #include "ash/system/update/tray_update.h"
-#include "ash/wm_window.h"
 
 namespace ash {
 
@@ -217,8 +216,8 @@
 
 void SystemTrayController::ShowUpdateOverCellularAvailableIcon() {
   // Show the icon on all displays.
-  for (WmWindow* root : ShellPort::Get()->GetAllRootWindows()) {
-    ash::SystemTray* tray = root->GetRootWindowController()->GetSystemTray();
+  for (auto* root_window_controller : Shell::GetAllRootWindowControllers()) {
+    ash::SystemTray* tray = root_window_controller->GetSystemTray();
     // External monitors might not have a tray yet.
     if (!tray)
       continue;
diff --git a/ash/system/tray/system_tray_unittest.cc b/ash/system/tray/system_tray_unittest.cc
index 59b25c7..c8dc570c 100644
--- a/ash/system/tray/system_tray_unittest.cc
+++ b/ash/system/tray/system_tray_unittest.cc
@@ -22,7 +22,6 @@
 #include "ash/test/status_area_widget_test_helper.h"
 #include "ash/test/test_system_tray_item.h"
 #include "ash/wm/window_util.h"
-#include "ash/wm_window.h"
 #include "base/memory/ptr_util.h"
 #include "base/run_loop.h"
 #include "base/test/histogram_tester.h"
diff --git a/ash/system/user/user_view.cc b/ash/system/user/user_view.cc
index f45abed..9ace6f6f 100644
--- a/ash/system/user/user_view.cc
+++ b/ash/system/user/user_view.cc
@@ -27,7 +27,6 @@
 #include "ash/system/user/login_status.h"
 #include "ash/system/user/rounded_image_view.h"
 #include "ash/system/user/user_card_view.h"
-#include "ash/wm_window.h"
 #include "base/memory/ptr_util.h"
 #include "components/signin/core/account_id/account_id.h"
 #include "components/user_manager/user_info.h"
diff --git a/ash/system/web_notification/ash_popup_alignment_delegate.cc b/ash/system/web_notification/ash_popup_alignment_delegate.cc
index 08097b6..9ee5353c2d 100644
--- a/ash/system/web_notification/ash_popup_alignment_delegate.cc
+++ b/ash/system/web_notification/ash_popup_alignment_delegate.cc
@@ -10,7 +10,6 @@
 #include "ash/shelf/shelf.h"
 #include "ash/shelf/shelf_constants.h"
 #include "ash/shell.h"
-#include "ash/wm_window.h"
 #include "base/i18n/rtl.h"
 #include "ui/display/display.h"
 #include "ui/display/screen.h"
diff --git a/ash/system/web_notification/ash_popup_alignment_delegate_unittest.cc b/ash/system/web_notification/ash_popup_alignment_delegate_unittest.cc
index a0ffec2..f3218d6 100644
--- a/ash/system/web_notification/ash_popup_alignment_delegate_unittest.cc
+++ b/ash/system/web_notification/ash_popup_alignment_delegate_unittest.cc
@@ -14,7 +14,6 @@
 #include "ash/shelf/shelf.h"
 #include "ash/shell.h"
 #include "ash/test/ash_test_base.h"
-#include "ash/wm_window.h"
 #include "base/command_line.h"
 #include "base/memory/ptr_util.h"
 #include "ui/display/manager/display_manager.h"
diff --git a/ash/test/ash_test_base.cc b/ash/test/ash_test_base.cc
index d179027..1de82986 100644
--- a/ash/test/ash_test_base.cc
+++ b/ash/test/ash_test_base.cc
@@ -27,7 +27,6 @@
 #include "ash/test/test_shell_delegate.h"
 #include "ash/test/test_system_tray_delegate.h"
 #include "ash/wm/window_positioner.h"
-#include "ash/wm_window.h"
 #include "services/ui/public/cpp/property_type_converters.h"
 #include "services/ui/public/interfaces/window_manager.mojom.h"
 #include "services/ui/public/interfaces/window_manager_constants.mojom.h"
@@ -90,7 +89,7 @@
   DISALLOW_COPY_AND_ASSIGN(AshEventGeneratorDelegate);
 };
 
-ui::mojom::WindowType MusWindowTypeFromWmWindowType(
+ui::mojom::WindowType MusWindowTypeFromWindowType(
     aura::client::WindowType window_type) {
   switch (window_type) {
     case aura::client::WINDOW_TYPE_UNKNOWN:
@@ -299,7 +298,7 @@
               ui::mojom::kResizeBehaviorCanMinimize));
 
   const ui::mojom::WindowType mus_window_type =
-      MusWindowTypeFromWmWindowType(type);
+      MusWindowTypeFromWindowType(type);
   mus::WindowManager* window_manager =
       ash_test_helper_->window_manager_app()->window_manager();
   aura::Window* window = mus::CreateAndParentTopLevelWindow(
diff --git a/ash/test/ash_test_helper.cc b/ash/test/ash_test_helper.cc
index 913251e..e83f945b 100644
--- a/ash/test/ash_test_helper.cc
+++ b/ash/test/ash_test_helper.cc
@@ -25,7 +25,6 @@
 #include "ash/test/test_screenshot_delegate.h"
 #include "ash/test/test_shell_delegate.h"
 #include "ash/test/test_system_tray_delegate.h"
-#include "ash/wm_window.h"
 #include "base/memory/ptr_util.h"
 #include "base/run_loop.h"
 #include "base/strings/string_split.h"
@@ -49,9 +48,11 @@
 #include "ui/base/test/material_design_controller_test_api.h"
 #include "ui/compositor/scoped_animation_duration_scale_mode.h"
 #include "ui/compositor/test/context_factories_for_test.h"
+#include "ui/display/display.h"
 #include "ui/display/display_switches.h"
 #include "ui/display/manager/display_manager.h"
 #include "ui/display/manager/managed_display_info.h"
+#include "ui/display/screen.h"
 #include "ui/display/test/display_manager_test_api.h"
 #include "ui/message_center/message_center.h"
 #include "ui/wm/core/capture_controller.h"
@@ -64,10 +65,14 @@
 namespace test {
 namespace {
 
+const display::Display GetDisplayNearestWindow(aura::Window* window) {
+  return display::Screen::GetScreen()->GetDisplayNearestWindow(window);
+}
+
 bool CompareByDisplayId(RootWindowController* root1,
                         RootWindowController* root2) {
-  return root1->GetWindow()->GetDisplayNearestWindow().id() <
-         root2->GetWindow()->GetDisplayNearestWindow().id();
+  return GetDisplayNearestWindow(root1->GetRootWindow()).id() <
+         GetDisplayNearestWindow(root2->GetRootWindow()).id();
 }
 
 }  // namespace
@@ -314,7 +319,7 @@
   std::vector<RootWindowController*> roots = GetRootsOrderedByDisplayId();
   CHECK_LE(2U, roots.size());
   return roots.size() < 2 ? display::Display()
-                          : roots[1]->GetWindow()->GetDisplayNearestWindow();
+                          : GetDisplayNearestWindow(roots[1]->GetRootWindow());
 }
 
 void AshTestHelper::CreateMashWindowManager() {
@@ -396,7 +401,7 @@
   bounds.set_x(*next_x);
   *next_x += bounds.size().width();
   display::Display updated_display =
-      root_window_controller->GetWindow()->GetDisplayNearestWindow();
+      GetDisplayNearestWindow(root_window_controller->GetRootWindow());
   gfx::Insets work_area_insets = updated_display.GetWorkAreaInsets();
   updated_display.set_bounds(bounds);
   updated_display.UpdateWorkAreaFromInsets(work_area_insets);
diff --git a/ash/test/test_shell_delegate.cc b/ash/test/test_shell_delegate.cc
index 39dd23ef..846c6e5 100644
--- a/ash/test/test_shell_delegate.cc
+++ b/ash/test/test_shell_delegate.cc
@@ -20,7 +20,6 @@
 #include "ash/test/test_wallpaper_delegate.h"
 #include "ash/wm/window_state.h"
 #include "ash/wm/window_util.h"
-#include "ash/wm_window.h"
 #include "base/logging.h"
 #include "base/memory/ptr_util.h"
 #include "ui/aura/window.h"
@@ -52,14 +51,9 @@
   DISALLOW_COPY_AND_ASSIGN(ShelfInitializer);
 };
 
-TestShellDelegate::TestShellDelegate()
-    : num_exit_requests_(0),
-      multi_profiles_enabled_(false),
-      force_maximize_on_first_run_(false),
-      touchscreen_enabled_in_local_pref_(true),
-      active_user_pref_service_(nullptr) {}
+TestShellDelegate::TestShellDelegate() = default;
 
-TestShellDelegate::~TestShellDelegate() {}
+TestShellDelegate::~TestShellDelegate() = default;
 
 ::service_manager::Connector* TestShellDelegate::GetShellConnector() const {
   return nullptr;
@@ -159,5 +153,9 @@
 
 void TestShellDelegate::UpdateTouchscreenStatusFromPrefs() {}
 
+void TestShellDelegate::SuspendMediaSessions() {
+  media_sessions_suspended_ = true;
+}
+
 }  // namespace test
 }  // namespace ash
diff --git a/ash/test/test_shell_delegate.h b/ash/test/test_shell_delegate.h
index fcf01c7a..a5a0467 100644
--- a/ash/test/test_shell_delegate.h
+++ b/ash/test/test_shell_delegate.h
@@ -63,6 +63,7 @@
   void SetTouchscreenEnabledInPrefs(bool enabled,
                                     bool use_local_state) override;
   void UpdateTouchscreenStatusFromPrefs() override;
+  void SuspendMediaSessions() override;
 
   int num_exit_requests() const { return num_exit_requests_; }
 
@@ -70,13 +71,16 @@
     force_maximize_on_first_run_ = maximize;
   }
 
+  bool media_sessions_suspended() const { return media_sessions_suspended_; }
+
  private:
-  int num_exit_requests_;
-  bool multi_profiles_enabled_;
-  bool force_maximize_on_first_run_;
-  bool touchscreen_enabled_in_local_pref_;
+  int num_exit_requests_ = 0;
+  bool multi_profiles_enabled_ = false;
+  bool force_maximize_on_first_run_ = false;
+  bool touchscreen_enabled_in_local_pref_ = true;
+  bool media_sessions_suspended_ = false;
   std::unique_ptr<ShelfInitializer> shelf_initializer_;
-  PrefService* active_user_pref_service_;  // Not owned.
+  PrefService* active_user_pref_service_ = nullptr;  // Not owned.
 
   DISALLOW_COPY_AND_ASSIGN(TestShellDelegate);
 };
diff --git a/ash/virtual_keyboard_controller.cc b/ash/virtual_keyboard_controller.cc
index 2d1443c..b49c60a 100644
--- a/ash/virtual_keyboard_controller.cc
+++ b/ash/virtual_keyboard_controller.cc
@@ -12,7 +12,6 @@
 #include "ash/system/tray/system_tray_notifier.h"
 #include "ash/wm/maximize_mode/maximize_mode_controller.h"
 #include "ash/wm/window_util.h"
-#include "ash/wm_window.h"
 #include "base/command_line.h"
 #include "base/strings/string_util.h"
 #include "ui/display/display.h"
@@ -138,7 +137,8 @@
     // Move the virtual keyboard to the focused display if that display has
     // touch capability or keyboard is locked
     const display::Display focused_display =
-        WmWindow::Get(wm::GetFocusedWindow())->GetDisplayNearestWindow();
+        display::Screen::GetScreen()->GetDisplayNearestWindow(
+            wm::GetFocusedWindow());
     if (current_display.id() != focused_display.id() &&
         focused_display.id() != display::kInvalidDisplayId &&
         focused_display.touch_support() ==
diff --git a/ash/wallpaper/wallpaper_controller.cc b/ash/wallpaper/wallpaper_controller.cc
index 002449d8..159890a 100644
--- a/ash/wallpaper/wallpaper_controller.cc
+++ b/ash/wallpaper/wallpaper_controller.cc
@@ -327,7 +327,7 @@
         root_window_controller->wallpaper_widget_controller();
     if (wallpaper_widget_controller) {
       moved |= wallpaper_widget_controller->Reparent(
-          root_window_controller->GetWindow(), container);
+          root_window_controller->GetRootWindow(), container);
     }
     // During wallpaper show animations the controller lives in
     // AnimatingWallpaperWidgetController owned by RootWindowController.
@@ -341,7 +341,7 @@
             : nullptr;
     if (animating_controller) {
       moved |= animating_controller->Reparent(
-          root_window_controller->GetWindow(), container);
+          root_window_controller->GetRootWindow(), container);
     }
   }
   return moved;
diff --git a/ash/wallpaper/wallpaper_controller_unittest.cc b/ash/wallpaper/wallpaper_controller_unittest.cc
index 29591f6..ce51e84 100644
--- a/ash/wallpaper/wallpaper_controller_unittest.cc
+++ b/ash/wallpaper/wallpaper_controller_unittest.cc
@@ -18,7 +18,6 @@
 #include "ash/test/test_wallpaper_delegate.h"
 #include "ash/wallpaper/wallpaper_view.h"
 #include "ash/wallpaper/wallpaper_widget_controller.h"
-#include "ash/wm_window.h"
 #include "base/command_line.h"
 #include "base/message_loop/message_loop.h"
 #include "base/run_loop.h"
diff --git a/ash/wallpaper/wallpaper_widget_controller.cc b/ash/wallpaper/wallpaper_widget_controller.cc
index 736ac132..ecedde7 100644
--- a/ash/wallpaper/wallpaper_widget_controller.cc
+++ b/ash/wallpaper/wallpaper_widget_controller.cc
@@ -8,7 +8,7 @@
 #include "ash/root_window_controller.h"
 #include "ash/shell.h"
 #include "ash/wallpaper/wallpaper_delegate.h"
-#include "ash/wm_window.h"
+#include "ui/aura/window.h"
 #include "ui/compositor/layer_animation_observer.h"
 #include "ui/compositor/scoped_layer_animation_settings.h"
 #include "ui/views/widget/widget.h"
@@ -62,11 +62,10 @@
 }  // namespace
 
 WallpaperWidgetController::WallpaperWidgetController(views::Widget* widget)
-    : widget_(widget),
-      widget_parent_(WmWindow::Get(widget->GetNativeWindow())->GetParent()) {
+    : widget_(widget), widget_parent_(widget->GetNativeWindow()->parent()) {
   DCHECK(widget_);
   widget_->AddObserver(this);
-  widget_parent_->aura_window()->AddObserver(this);
+  widget_parent_->AddObserver(this);
 }
 
 WallpaperWidgetController::~WallpaperWidgetController() {
@@ -86,13 +85,14 @@
     widget_->SetBounds(bounds);
 }
 
-bool WallpaperWidgetController::Reparent(WmWindow* root_window, int container) {
+bool WallpaperWidgetController::Reparent(aura::Window* root_window,
+                                         int container) {
   if (widget_) {
-    widget_parent_->aura_window()->RemoveObserver(this);
-    WmWindow* window = WmWindow::Get(widget_->GetNativeWindow());
-    root_window->GetChildByShellWindowId(container)->AddChild(window);
-    widget_parent_ = WmWindow::Get(widget_->GetNativeWindow())->GetParent();
-    widget_parent_->aura_window()->AddObserver(this);
+    widget_parent_->RemoveObserver(this);
+    aura::Window* window = widget_->GetNativeWindow();
+    root_window->GetChildById(container)->AddChild(window);
+    widget_parent_ = widget_->GetNativeWindow()->parent();
+    widget_parent_->AddObserver(this);
     return true;
   }
   // Nothing to reparent.
@@ -100,7 +100,7 @@
 }
 
 void WallpaperWidgetController::RemoveObservers() {
-  widget_parent_->aura_window()->RemoveObserver(this);
+  widget_parent_->RemoveObserver(this);
   widget_->RemoveObserver(this);
   widget_ = nullptr;
 }
diff --git a/ash/wallpaper/wallpaper_widget_controller.h b/ash/wallpaper/wallpaper_widget_controller.h
index a1a61a30..1c379ee9 100644
--- a/ash/wallpaper/wallpaper_widget_controller.h
+++ b/ash/wallpaper/wallpaper_widget_controller.h
@@ -15,7 +15,6 @@
 namespace ash {
 
 class RootWindowController;
-class WmWindow;
 
 // This class implements a widget-based wallpaper.
 // WallpaperWidgetController is owned by RootWindowController.
@@ -36,7 +35,7 @@
   // Move the wallpaper for |root_window| to the specified |container|.
   // The lock screen moves the wallpaper container to hides the user's windows.
   // Returns true if there was something to reparent.
-  bool Reparent(WmWindow* root_window, int container);
+  bool Reparent(aura::Window* root_window, int container);
 
   // Starts wallpaper fade in animation. |root_window_controller| is
   // the root window where the animation will happen. (This is
@@ -56,7 +55,7 @@
   views::Widget* widget_;
 
   // Parent of |widget_|.
-  WmWindow* widget_parent_;
+  aura::Window* widget_parent_;
 
   DISALLOW_COPY_AND_ASSIGN(WallpaperWidgetController);
 };
diff --git a/ash/wm/immersive_context_ash.cc b/ash/wm/immersive_context_ash.cc
index 7b28828..0a844a8d 100644
--- a/ash/wm/immersive_context_ash.cc
+++ b/ash/wm/immersive_context_ash.cc
@@ -24,9 +24,8 @@
 
 void ImmersiveContextAsh::InstallResizeHandleWindowTargeter(
     ImmersiveFullscreenController* controller) {
-  aura::Window* window = controller->widget()->GetNativeWindow();
-  window->SetEventTargeter(
-      base::MakeUnique<ResizeHandleWindowTargeter>(window, controller));
+  wm::InstallResizeHandleWindowTargeterForWindow(
+      controller->widget()->GetNativeWindow(), controller);
 }
 
 void ImmersiveContextAsh::OnEnteringOrExitingImmersive(
diff --git a/ash/wm/lock_action_handler_layout_manager.cc b/ash/wm/lock_action_handler_layout_manager.cc
index ebc488fc3..e8ced5aa 100644
--- a/ash/wm/lock_action_handler_layout_manager.cc
+++ b/ash/wm/lock_action_handler_layout_manager.cc
@@ -15,7 +15,6 @@
 #include "ash/wm/window_state.h"
 #include "ash/wm/window_util.h"
 #include "ash/wm/wm_event.h"
-#include "ash/wm_window.h"
 
 namespace ash {
 
diff --git a/ash/wm/maximize_mode/maximize_mode_event_handler.cc b/ash/wm/maximize_mode/maximize_mode_event_handler.cc
index 0a38ac8..392d0d20 100644
--- a/ash/wm/maximize_mode/maximize_mode_event_handler.cc
+++ b/ash/wm/maximize_mode/maximize_mode_event_handler.cc
@@ -9,7 +9,7 @@
 #include "ash/wm/window_state.h"
 #include "ash/wm/window_util.h"
 #include "ash/wm/wm_event.h"
-#include "ash/wm_window.h"
+#include "ui/aura/window.h"
 #include "ui/events/event.h"
 
 namespace ash {
@@ -38,18 +38,18 @@
   }
 
   // Find the active window (from the primary screen) to un-fullscreen.
-  WmWindow* window = WmWindow::Get(GetActiveWindow());
+  aura::Window* window = GetActiveWindow();
   if (!window)
     return false;
 
-  WindowState* window_state = window->GetWindowState();
+  WindowState* window_state = GetWindowState(window);
   if (!window_state->IsFullscreen() || window_state->in_immersive_fullscreen())
     return false;
 
   // Test that the touch happened in the top or bottom lines.
   int y = event.y();
   if (y >= kLeaveFullScreenAreaHeightInPixel &&
-      y < (window->GetBounds().height() - kLeaveFullScreenAreaHeightInPixel)) {
+      y < (window->bounds().height() - kLeaveFullScreenAreaHeightInPixel)) {
     return false;
   }
 
@@ -58,7 +58,7 @@
     return false;
 
   WMEvent toggle_fullscreen(WM_EVENT_TOGGLE_FULLSCREEN);
-  window->GetWindowState()->OnWMEvent(&toggle_fullscreen);
+  GetWindowState(window)->OnWMEvent(&toggle_fullscreen);
   return true;
 }
 
diff --git a/ash/wm/maximize_mode/maximize_mode_window_manager_unittest.cc b/ash/wm/maximize_mode/maximize_mode_window_manager_unittest.cc
index 53816512..d17b318 100644
--- a/ash/wm/maximize_mode/maximize_mode_window_manager_unittest.cc
+++ b/ash/wm/maximize_mode/maximize_mode_window_manager_unittest.cc
@@ -24,7 +24,6 @@
 #include "ash/wm/window_state_observer.h"
 #include "ash/wm/window_util.h"
 #include "ash/wm/wm_event.h"
-#include "ash/wm_window.h"
 #include "base/command_line.h"
 #include "base/strings/stringprintf.h"
 #include "base/strings/utf_string_conversions.h"
diff --git a/ash/wm/panels/panel_frame_view.cc b/ash/wm/panels/panel_frame_view.cc
index a851e2a..022b933 100644
--- a/ash/wm/panels/panel_frame_view.cc
+++ b/ash/wm/panels/panel_frame_view.cc
@@ -9,6 +9,7 @@
 #include "ash/frame/frame_border_hit_test.h"
 #include "ash/shell.h"
 #include "ash/wm/resize_handle_window_targeter.h"
+#include "ash/wm/window_util.h"
 #include "ui/aura/client/aura_constants.h"
 #include "ui/aura/window.h"
 #include "ui/base/hit_test.h"
@@ -24,8 +25,7 @@
 
 PanelFrameView::PanelFrameView(views::Widget* frame, FrameType frame_type)
     : frame_(frame), caption_button_container_(nullptr), window_icon_(nullptr) {
-  GetWidgetWindow()->SetEventTargeter(
-      base::MakeUnique<ResizeHandleWindowTargeter>(GetWidgetWindow(), nullptr));
+  wm::InstallResizeHandleWindowTargeterForWindow(GetWidgetWindow(), nullptr);
   DCHECK(!frame_->widget_delegate()->CanMaximize());
   if (frame_type != FRAME_NONE)
     InitHeaderPainter();
diff --git a/ash/wm/window_util.cc b/ash/wm/window_util.cc
index 87091ace..42606b12 100644
--- a/ash/wm/window_util.cc
+++ b/ash/wm/window_util.cc
@@ -12,6 +12,7 @@
 #include "ash/shelf/shelf.h"
 #include "ash/shell.h"
 #include "ash/shell_port.h"
+#include "ash/wm/resize_handle_window_targeter.h"
 #include "ash/wm/widget_finder.h"
 #include "ash/wm/window_properties.h"
 #include "ash/wm/window_state.h"
@@ -197,5 +198,12 @@
   window->RemovePreTargetHandler(handler);
 }
 
+void InstallResizeHandleWindowTargeterForWindow(
+    aura::Window* window,
+    ImmersiveFullscreenController* immersive_fullscreen_controller) {
+  window->SetEventTargeter(base::MakeUnique<ResizeHandleWindowTargeter>(
+      window, immersive_fullscreen_controller));
+}
+
 }  // namespace wm
 }  // namespace ash
diff --git a/ash/wm/window_util.h b/ash/wm/window_util.h
index d3fcf3d5..e4e2e6e 100644
--- a/ash/wm/window_util.h
+++ b/ash/wm/window_util.h
@@ -25,6 +25,9 @@
 }
 
 namespace ash {
+
+class ImmersiveFullscreenController;
+
 namespace wm {
 
 // Utility functions for window activation.
@@ -99,6 +102,12 @@
     ui::EventHandler* handler,
     aura::Window* window);
 
+// Installs a resize handler on the window that makes it easier to resize
+// the window. See ResizeHandleWindowTargeter for the specifics.
+ASH_EXPORT void InstallResizeHandleWindowTargeterForWindow(
+    aura::Window* window,
+    ImmersiveFullscreenController* immersive_fullscreen_controller);
+
 }  // namespace wm
 }  // namespace ash
 
diff --git a/ash/wm_window.cc b/ash/wm_window.cc
index 07feeec..aea1e78 100644
--- a/ash/wm_window.cc
+++ b/ash/wm_window.cc
@@ -487,12 +487,6 @@
   return Get(window_->GetChildById(id));
 }
 
-void WmWindow::InstallResizeHandleWindowTargeter(
-    ImmersiveFullscreenController* immersive_fullscreen_controller) {
-  window_->SetEventTargeter(base::MakeUnique<ResizeHandleWindowTargeter>(
-      window_, immersive_fullscreen_controller));
-}
-
 void WmWindow::SetBoundsInScreenBehaviorForChildren(
     BoundsInScreenBehavior behavior) {
   window_->SetProperty(
diff --git a/ash/wm_window.h b/ash/wm_window.h
index 78cd28f..decd178 100644
--- a/ash/wm_window.h
+++ b/ash/wm_window.h
@@ -36,7 +36,6 @@
 
 namespace ash {
 
-class ImmersiveFullscreenController;
 class RootWindowController;
 class WmTransientWindowObserver;
 enum class WmWindowProperty;
@@ -260,11 +259,6 @@
 
   std::vector<WmWindow*> GetChildren();
 
-  // Installs a resize handler on the window that makes it easier to resize
-  // the window. See ResizeHandleWindowTargeter for the specifics.
-  void InstallResizeHandleWindowTargeter(
-      ImmersiveFullscreenController* immersive_fullscreen_controller);
-
   // See description in SetBoundsInScreen().
   void SetBoundsInScreenBehaviorForChildren(BoundsInScreenBehavior behavior);
 
diff --git a/base/containers/flat_set.h b/base/containers/flat_set.h
index 7a2316a0..d51dd26 100644
--- a/base/containers/flat_set.h
+++ b/base/containers/flat_set.h
@@ -48,7 +48,7 @@
 //   flat_set(const flat_set&);
 //   flat_set(flat_set&&);
 //   flat_set(std::vector<Key>, FlatContainerDupes);  // Re-use storage.
-//   flat_set(std::initializer_list<value_type> ilist,
+//   flat_set(std::initializer_list<value_type> ilist, FlatContainerDupes,
 //            const Compare& comp = Compare());
 //
 // Assignment functions:
diff --git a/base/message_loop/message_loop.cc b/base/message_loop/message_loop.cc
index 401a0ac..eda5ee1c 100644
--- a/base/message_loop/message_loop.cc
+++ b/base/message_loop/message_loop.cc
@@ -382,15 +382,22 @@
   if (run_loop_client_->IsNested())
     return false;
 
-  if (deferred_non_nestable_work_queue_.empty())
-    return false;
+  while (!deferred_non_nestable_work_queue_.empty()) {
+    PendingTask pending_task =
+        std::move(deferred_non_nestable_work_queue_.front());
+    deferred_non_nestable_work_queue_.pop();
 
-  PendingTask pending_task =
-      std::move(deferred_non_nestable_work_queue_.front());
-  deferred_non_nestable_work_queue_.pop();
+    if (!pending_task.task.IsCancelled()) {
+      RunTask(&pending_task);
+      return true;
+    }
 
-  RunTask(&pending_task);
-  return true;
+#if defined(OS_WIN)
+    DecrementHighResTaskCountIfNeeded(pending_task);
+#endif
+  }
+
+  return false;
 }
 
 void MessageLoop::RunTask(PendingTask* pending_task) {
@@ -398,10 +405,7 @@
   current_pending_task_ = pending_task;
 
 #if defined(OS_WIN)
-  if (pending_task->is_high_res) {
-    pending_high_res_tasks_--;
-    CHECK_GE(pending_high_res_tasks_, 0);
-  }
+  DecrementHighResTaskCountIfNeeded(*pending_task);
 #endif
 
   // Execute the task and assume the worst: It is probably not reentrant.
@@ -439,6 +443,20 @@
   delayed_work_queue_.push(std::move(pending_task));
 }
 
+bool MessageLoop::SweepDelayedWorkQueueAndReturnTrueIfStillHasWork() {
+  while (!delayed_work_queue_.empty()) {
+    const PendingTask& pending_task = delayed_work_queue_.top();
+    if (!pending_task.task.IsCancelled())
+      return true;
+
+#if defined(OS_WIN)
+    DecrementHighResTaskCountIfNeeded(pending_task);
+#endif
+    delayed_work_queue_.pop();
+  }
+  return false;
+}
+
 bool MessageLoop::DeletePendingTasks() {
   bool did_work = !work_queue_.empty();
   while (!work_queue_.empty()) {
@@ -502,7 +520,12 @@
     do {
       PendingTask pending_task = std::move(work_queue_.front());
       work_queue_.pop();
-      if (!pending_task.delayed_run_time.is_null()) {
+
+      if (pending_task.task.IsCancelled()) {
+#if defined(OS_WIN)
+        DecrementHighResTaskCountIfNeeded(pending_task);
+#endif
+      } else if (!pending_task.delayed_run_time.is_null()) {
         int sequence_num = pending_task.sequence_num;
         TimeTicks delayed_run_time = pending_task.delayed_run_time;
         AddToDelayedWorkQueue(std::move(pending_task));
@@ -521,7 +544,8 @@
 }
 
 bool MessageLoop::DoDelayedWork(TimeTicks* next_delayed_work_time) {
-  if (!nestable_tasks_allowed_ || delayed_work_queue_.empty()) {
+  if (!nestable_tasks_allowed_ ||
+      !SweepDelayedWorkQueueAndReturnTrueIfStillHasWork()) {
     recent_time_ = *next_delayed_work_time = TimeTicks();
     return false;
   }
@@ -546,7 +570,7 @@
       std::move(const_cast<PendingTask&>(delayed_work_queue_.top()));
   delayed_work_queue_.pop();
 
-  if (!delayed_work_queue_.empty())
+  if (SweepDelayedWorkQueueAndReturnTrueIfStillHasWork())
     *next_delayed_work_time = delayed_work_queue_.top().delayed_run_time;
 
   return DeferOrRunPendingTask(std::move(pending_task));
@@ -574,6 +598,16 @@
   return false;
 }
 
+#if defined(OS_WIN)
+void MessageLoop::DecrementHighResTaskCountIfNeeded(
+    const PendingTask& pending_task) {
+  if (!pending_task.is_high_res)
+    return;
+  --pending_high_res_tasks_;
+  DCHECK_GE(pending_high_res_tasks_, 0);
+}
+#endif
+
 #if !defined(OS_NACL)
 //------------------------------------------------------------------------------
 // MessageLoopForUI
diff --git a/base/message_loop/message_loop.h b/base/message_loop/message_loop.h
index 50fd7e4..1e53aad 100644
--- a/base/message_loop/message_loop.h
+++ b/base/message_loop/message_loop.h
@@ -367,6 +367,10 @@
   // Adds the pending task to delayed_work_queue_.
   void AddToDelayedWorkQueue(PendingTask pending_task);
 
+  // Sweeps any cancelled tasks from the front of the delayed work queue and
+  // returns true if there is remaining work.
+  bool SweepDelayedWorkQueueAndReturnTrueIfStillHasWork();
+
   // Delete tasks that haven't run yet without running them.  Used in the
   // destructor to make sure all the task's destructors get called.  Returns
   // true if some work was done.
@@ -392,6 +396,10 @@
   TaskQueue work_queue_;
 
 #if defined(OS_WIN)
+  // Helper to decrement the high resolution task count if |pending_task| is a
+  // high resolution task.
+  void DecrementHighResTaskCountIfNeeded(const PendingTask& pending_Task);
+
   // How many high resolution tasks are in the pending task queue. This value
   // increases by N every time we call ReloadWorkQueue() and decreases by 1
   // every time we call RunTask() if the task needs a high resolution timer.
diff --git a/base/process/process_info.h b/base/process/process_info.h
index 1d76f42..fe03b90 100644
--- a/base/process/process_info.h
+++ b/base/process/process_info.h
@@ -21,7 +21,6 @@
 };
 
 #if defined(OS_WIN)
-
 enum IntegrityLevel {
   INTEGRITY_UNKNOWN,
   LOW_INTEGRITY,
@@ -29,15 +28,11 @@
   HIGH_INTEGRITY,
 };
 
-// Returns the integrity level of the process. Returns INTEGRITY_UNKNOWN if the
-// system does not support integrity levels (pre-Vista) or in the case of an
-// underlying system failure.
+// Returns the integrity level of the process. Returns INTEGRITY_UNKNOWN in the
+// case of an underlying system failure.
 BASE_EXPORT IntegrityLevel GetCurrentProcessIntegrityLevel();
-
 #endif  // defined(OS_WIN)
 
-
-
 }  // namespace base
 
 #endif  // BASE_PROCESS_PROCESS_INFO_H_
diff --git a/base/process/process_info_win.cc b/base/process/process_info_win.cc
index 9c2843b..8c4b36cb 100644
--- a/base/process/process_info_win.cc
+++ b/base/process/process_info_win.cc
@@ -6,11 +6,10 @@
 
 #include <windows.h>
 
-#include <memory>
-
+#include "base/logging.h"
+#include "base/memory/ptr_util.h"
 #include "base/time/time.h"
 #include "base/win/scoped_handle.h"
-#include "base/win/windows_version.h"
 
 namespace base {
 
@@ -28,9 +27,6 @@
 }
 
 IntegrityLevel GetCurrentProcessIntegrityLevel() {
-  if (win::GetVersion() < base::win::VERSION_VISTA)
-    return INTEGRITY_UNKNOWN;
-
   HANDLE process_token;
   if (!::OpenProcessToken(::GetCurrentProcess(),
                           TOKEN_QUERY | TOKEN_QUERY_SOURCE, &process_token)) {
@@ -45,15 +41,9 @@
     return INTEGRITY_UNKNOWN;
   }
 
-  std::unique_ptr<char[]> token_label_bytes(new char[token_info_length]);
-  if (!token_label_bytes.get())
-    return INTEGRITY_UNKNOWN;
-
+  auto token_label_bytes = MakeUnique<char[]>(token_info_length);
   TOKEN_MANDATORY_LABEL* token_label =
       reinterpret_cast<TOKEN_MANDATORY_LABEL*>(token_label_bytes.get());
-  if (!token_label)
-    return INTEGRITY_UNKNOWN;
-
   if (!::GetTokenInformation(process_token, TokenIntegrityLevel, token_label,
                              token_info_length, &token_info_length)) {
     return INTEGRITY_UNKNOWN;
diff --git a/base/sequence_checker.h b/base/sequence_checker.h
index 3653fbc..db0de45 100644
--- a/base/sequence_checker.h
+++ b/base/sequence_checker.h
@@ -55,7 +55,7 @@
 #define DETACH_FROM_SEQUENCE(name) (name).DetachFromSequence()
 #else  // DCHECK_IS_ON()
 #define SEQUENCE_CHECKER(name)
-#define DCHECK_CALLED_ON_VALID_SEQUENCE(name)
+#define DCHECK_CALLED_ON_VALID_SEQUENCE(name) EAT_STREAM_PARAMETERS
 #define DETACH_FROM_SEQUENCE(name)
 #endif  // DCHECK_IS_ON()
 
diff --git a/base/sequence_checker_unittest.cc b/base/sequence_checker_unittest.cc
index 215a107..db3e450 100644
--- a/base/sequence_checker_unittest.cc
+++ b/base/sequence_checker_unittest.cc
@@ -271,16 +271,17 @@
 
   void ExpectDeathOnOtherSequence() {
 #if DCHECK_IS_ON()
-    EXPECT_DCHECK_DEATH(
-        { DCHECK_CALLED_ON_VALID_SEQUENCE(my_sequence_checker_); });
+    EXPECT_DCHECK_DEATH({
+      DCHECK_CALLED_ON_VALID_SEQUENCE(my_sequence_checker_) << "Error message.";
+    });
 #else
     // Happily no-ops on non-dcheck builds.
-    DCHECK_CALLED_ON_VALID_SEQUENCE(my_sequence_checker_);
+    DCHECK_CALLED_ON_VALID_SEQUENCE(my_sequence_checker_) << "Error message.";
 #endif
   }
 
   void ExpectNoDeathOnOtherSequenceAfterDetach() {
-    DCHECK_CALLED_ON_VALID_SEQUENCE(my_sequence_checker_);
+    DCHECK_CALLED_ON_VALID_SEQUENCE(my_sequence_checker_) << "Error message.";
   }
 
  protected:
diff --git a/build/android/binary_size/apk_downloader.py b/build/android/binary_size/apk_downloader.py
index dcea458c..e6d7082 100755
--- a/build/android/binary_size/apk_downloader.py
+++ b/build/android/binary_size/apk_downloader.py
@@ -15,7 +15,7 @@
 import find_depot_tools  # pylint: disable=import-error,unused-import
 import download_from_google_storage
 
-CURRENT_MILESTONE = '59'
+CURRENT_MILESTONE = '60'
 DEFAULT_BUCKET = 'gs://chromium-android-tools/apks'
 DEFAULT_DOWNLOAD_PATH = os.path.join(os.path.dirname(__file__), 'apks')
 DEFAULT_BUILDER = 'Android_Builder'
diff --git a/build/android/binary_size/apks/Android_Builder/60/ChromeModernPublic.apk.sha1 b/build/android/binary_size/apks/Android_Builder/60/ChromeModernPublic.apk.sha1
new file mode 100644
index 0000000..add0d9e
--- /dev/null
+++ b/build/android/binary_size/apks/Android_Builder/60/ChromeModernPublic.apk.sha1
@@ -0,0 +1 @@
+5ae5ce5404bd9b880cdda2f438b300a88d2b9dfe
\ No newline at end of file
diff --git a/build/android/binary_size/apks/Android_Builder/60/ChromePublic.apk.sha1 b/build/android/binary_size/apks/Android_Builder/60/ChromePublic.apk.sha1
new file mode 100644
index 0000000..79a9823
--- /dev/null
+++ b/build/android/binary_size/apks/Android_Builder/60/ChromePublic.apk.sha1
@@ -0,0 +1 @@
+4c3d75e982caab8e07aa3749e5a827c47cf7b8f8
\ No newline at end of file
diff --git a/build/android/binary_size/apks/Android_Builder/60/MonochromePublic.apk.sha1 b/build/android/binary_size/apks/Android_Builder/60/MonochromePublic.apk.sha1
new file mode 100644
index 0000000..b9ed7b4
--- /dev/null
+++ b/build/android/binary_size/apks/Android_Builder/60/MonochromePublic.apk.sha1
@@ -0,0 +1 @@
+71f1826377f3fec2b43249a5b0215432882f7f3e
\ No newline at end of file
diff --git a/build/android/binary_size/apks/Android_arm64_Builder/60/ChromeModernPublic.apk.sha1 b/build/android/binary_size/apks/Android_arm64_Builder/60/ChromeModernPublic.apk.sha1
new file mode 100644
index 0000000..af25e05
--- /dev/null
+++ b/build/android/binary_size/apks/Android_arm64_Builder/60/ChromeModernPublic.apk.sha1
@@ -0,0 +1 @@
+9bee475db96c3b63ec74d59f140c7ed6db58f2e5
\ No newline at end of file
diff --git a/build/android/binary_size/apks/Android_arm64_Builder/60/ChromePublic.apk.sha1 b/build/android/binary_size/apks/Android_arm64_Builder/60/ChromePublic.apk.sha1
new file mode 100644
index 0000000..1a8800df
--- /dev/null
+++ b/build/android/binary_size/apks/Android_arm64_Builder/60/ChromePublic.apk.sha1
@@ -0,0 +1 @@
+360384a694b944560b83b2f721dc77648a1e00d4
\ No newline at end of file
diff --git a/cc/BUILD.gn b/cc/BUILD.gn
index cb966fd..11e0b15 100644
--- a/cc/BUILD.gn
+++ b/cc/BUILD.gn
@@ -628,7 +628,6 @@
     "test/stub_layer_tree_host_client.h",
     "test/stub_layer_tree_host_single_thread_client.cc",
     "test/stub_layer_tree_host_single_thread_client.h",
-    "test/stub_surface_factory_client.h",
     "test/surface_aggregator_test_helpers.cc",
     "test/surface_aggregator_test_helpers.h",
     "test/surface_hittest_test_helpers.cc",
diff --git a/cc/blink/web_display_item_list_impl.cc b/cc/blink/web_display_item_list_impl.cc
index c1c47de..af418aef 100644
--- a/cc/blink/web_display_item_list_impl.cc
+++ b/cc/blink/web_display_item_list_impl.cc
@@ -148,8 +148,8 @@
   AppendEndTransformItem();
 }
 
-void WebDisplayItemListImpl::SetIsSuitableForGpuRasterization(bool isSuitable) {
-  display_item_list_->SetIsSuitableForGpuRasterization(isSuitable);
+void WebDisplayItemListImpl::SetNumSlowPaths(int num_slow_paths) {
+  display_item_list_->SetNumSlowPaths(num_slow_paths);
 }
 
 WebDisplayItemListImpl::~WebDisplayItemListImpl() {
diff --git a/cc/blink/web_display_item_list_impl.h b/cc/blink/web_display_item_list_impl.h
index e3fa9b8..3ec5f26 100644
--- a/cc/blink/web_display_item_list_impl.h
+++ b/cc/blink/web_display_item_list_impl.h
@@ -66,7 +66,7 @@
                         ScrollContainerId) override;
   void AppendEndScrollItem() override;
 
-  void SetIsSuitableForGpuRasterization(bool isSuitable) override;
+  void SetNumSlowPaths(int num_slow_paths) override;
 
  private:
   scoped_refptr<cc::DisplayItemList> display_item_list_;
diff --git a/cc/layers/picture_layer.cc b/cc/layers/picture_layer.cc
index d2ce7ccd..f94dba2 100644
--- a/cc/layers/picture_layer.cc
+++ b/cc/layers/picture_layer.cc
@@ -15,6 +15,8 @@
 #include "cc/trees/transform_node.h"
 #include "ui/gfx/geometry/rect_conversions.h"
 
+static constexpr int kMaxNumberOfSlowPathsBeforeVeto = 5;
+
 namespace cc {
 
 PictureLayer::PictureLayerInputs::PictureLayerInputs() = default;
@@ -188,7 +190,8 @@
   // create a display list (e.g., if the size is empty). We return true in these
   // cases because the gpu suitability bit sticks false.
   return !picture_layer_inputs_.display_list ||
-         picture_layer_inputs_.display_list->IsSuitableForGpuRasterization();
+         picture_layer_inputs_.display_list->NumSlowPaths() <=
+             kMaxNumberOfSlowPathsBeforeVeto;
 }
 
 void PictureLayer::ClearClient() {
diff --git a/cc/layers/picture_layer_impl_perftest.cc b/cc/layers/picture_layer_impl_perftest.cc
index 7db16d60b..a8f51685 100644
--- a/cc/layers/picture_layer_impl_perftest.cc
+++ b/cc/layers/picture_layer_impl_perftest.cc
@@ -134,7 +134,8 @@
     do {
       int count = num_tiles;
       std::unique_ptr<TilingSetEvictionQueue> queue(new TilingSetEvictionQueue(
-          pending_layer_->picture_layer_tiling_set()));
+          pending_layer_->picture_layer_tiling_set(),
+          pending_layer_->contributes_to_drawn_render_surface()));
       while (count--) {
         ASSERT_TRUE(!queue->IsEmpty()) << "count: " << count;
         ASSERT_TRUE(queue->Top().tile()) << "count: " << count;
@@ -162,7 +163,8 @@
     timer_.Reset();
     do {
       std::unique_ptr<TilingSetEvictionQueue> queue(new TilingSetEvictionQueue(
-          pending_layer_->picture_layer_tiling_set()));
+          pending_layer_->picture_layer_tiling_set(),
+          pending_layer_->contributes_to_drawn_render_surface()));
       timer_.NextLap();
     } while (!timer_.HasTimeLimitExpired());
 
diff --git a/cc/layers/picture_layer_impl_unittest.cc b/cc/layers/picture_layer_impl_unittest.cc
index 877b460..0e32438 100644
--- a/cc/layers/picture_layer_impl_unittest.cc
+++ b/cc/layers/picture_layer_impl_unittest.cc
@@ -2961,8 +2961,9 @@
   EXPECT_GT(number_of_unmarked_tiles, 1u);
 
   // Tiles don't have resources yet.
-  std::unique_ptr<TilingSetEvictionQueue> queue(
-      new TilingSetEvictionQueue(pending_layer()->picture_layer_tiling_set()));
+  std::unique_ptr<TilingSetEvictionQueue> queue(new TilingSetEvictionQueue(
+      pending_layer()->picture_layer_tiling_set(),
+      pending_layer()->contributes_to_drawn_render_surface()));
   EXPECT_TRUE(queue->IsEmpty());
 
   host_impl()->tile_manager()->InitializeTilesWithResourcesForTesting(
@@ -2975,8 +2976,9 @@
   PrioritizedTile last_tile;
   size_t distance_decreasing = 0;
   size_t distance_increasing = 0;
-  queue.reset(
-      new TilingSetEvictionQueue(pending_layer()->picture_layer_tiling_set()));
+  queue.reset(new TilingSetEvictionQueue(
+      pending_layer()->picture_layer_tiling_set(),
+      pending_layer()->contributes_to_drawn_render_surface()));
   while (!queue->IsEmpty()) {
     PrioritizedTile prioritized_tile = queue->Top();
     Tile* tile = prioritized_tile.tile();
@@ -3660,8 +3662,9 @@
     size_t occluded_tile_count = 0u;
     PrioritizedTile last_tile;
 
-    std::unique_ptr<TilingSetEvictionQueue> queue(
-        new TilingSetEvictionQueue(layer->picture_layer_tiling_set()));
+    std::unique_ptr<TilingSetEvictionQueue> queue(new TilingSetEvictionQueue(
+        layer->picture_layer_tiling_set(),
+        layer->contributes_to_drawn_render_surface()));
     while (!queue->IsEmpty()) {
       PrioritizedTile prioritized_tile = queue->Top();
       Tile* tile = prioritized_tile.tile();
diff --git a/cc/paint/display_item_list.cc b/cc/paint/display_item_list.cc
index b947403a..4447a58 100644
--- a/cc/paint/display_item_list.cc
+++ b/cc/paint/display_item_list.cc
@@ -243,14 +243,6 @@
     std::vector<gfx::Rect>().swap(visual_rects_);
 }
 
-bool DisplayItemList::IsSuitableForGpuRasterization() const {
-  // TODO(wkorman): This is more permissive than Picture's implementation, since
-  // none of the items might individually trigger a veto even though they
-  // collectively have enough "bad" operations that a corresponding Picture
-  // would get vetoed. See crbug.com/513016.
-  return all_items_are_suitable_for_gpu_rasterization_;
-}
-
 size_t DisplayItemList::OpCount() const {
   return op_count_;
 }
diff --git a/cc/paint/display_item_list.h b/cc/paint/display_item_list.h
index 893dc9f..5aa1490 100644
--- a/cc/paint/display_item_list.h
+++ b/cc/paint/display_item_list.h
@@ -125,10 +125,8 @@
   // applicable, create an internally cached SkPicture.
   void Finalize();
 
-  void SetIsSuitableForGpuRasterization(bool is_suitable) {
-    all_items_are_suitable_for_gpu_rasterization_ = is_suitable;
-  }
-  bool IsSuitableForGpuRasterization() const;
+  void SetNumSlowPaths(int num_slow_paths) { num_slow_paths_ = num_slow_paths; }
+  int NumSlowPaths() const { return num_slow_paths_; }
 
   size_t OpCount() const;
   size_t ApproximateMemoryUsage() const;
@@ -200,7 +198,7 @@
   std::vector<size_t> begin_item_indices_;
 
   size_t op_count_ = 0u;
-  bool all_items_are_suitable_for_gpu_rasterization_ = true;
+  int num_slow_paths_ = 0;
   // For testing purposes only. Whether to keep visual rects across calls to
   // Finalize().
   bool retain_visual_rects_ = false;
diff --git a/cc/paint/paint_op_buffer.cc b/cc/paint/paint_op_buffer.cc
index c0da765..3d1ce30 100644
--- a/cc/paint/paint_op_buffer.cc
+++ b/cc/paint/paint_op_buffer.cc
@@ -454,6 +454,10 @@
   return antialias && !path.isConvex() ? 1 : 0;
 }
 
+int DrawDisplayItemListOp::CountSlowPaths() const {
+  return list->NumSlowPaths();
+}
+
 int DrawLineOp::CountSlowPaths() const {
   if (const SkPathEffect* effect = flags.getPathEffect()) {
     SkPathEffect::DashInfo info;
@@ -616,43 +620,47 @@
   if (!*iter)
     return nullptr;
 
+  const size_t active_range = range_indices[*range_index];
+  DCHECK_GE(iter->op_idx(), range_starts[active_range]);
+
   // This grabs the PaintOp from the current iterator position, and advances it
   // to the next position immediately. We'll see we reached the end of the
   // buffer on the next call to this method.
   const PaintOp* op = **iter;
-
-  size_t active_range = range_indices[*range_index];
-  DCHECK_GE(iter->op_idx(), range_starts[active_range]);
+  ++*iter;
 
   if (active_range + 1 == range_starts.size()) {
-    // In the last possible range, so go right to the end of the buffer.
-    ++*iter;
-  } else {
-    size_t range_end = range_starts[active_range + 1];
-    DCHECK_LE(iter->op_idx(), range_end);
-
-    ++*iter;
-    if (iter->op_idx() == range_end) {
-      if (*range_index + 1 == range_indices.size()) {
-        // Leaving the last range that we want to iterate.
-        *iter = iter->end();
-      } else {
-        // Move to the next range.
-        ++(*range_index);
-        size_t next_range_start = range_starts[range_indices[*range_index]];
-        while (iter->op_idx() < next_range_start)
-          ++(*iter);
-      }
-    }
+    // In the last possible range, so let the iter go right to the end of the
+    // buffer.
+    return op;
   }
 
+  const size_t range_end = range_starts[active_range + 1];
+  DCHECK_LE(iter->op_idx(), range_end);
+  if (iter->op_idx() < range_end) {
+    // Still inside the range, so let the iter be.
+    return op;
+  }
+
+  if (*range_index + 1 == range_indices.size()) {
+    // We're now past the last range that we want to iterate.
+    *iter = iter->end();
+    return op;
+  }
+
+  // Move to the next range.
+  ++(*range_index);
+  size_t next_range_start = range_starts[range_indices[*range_index]];
+  while (iter->op_idx() < next_range_start)
+    ++(*iter);
   return op;
 }
 
 void PaintOpBuffer::playback(SkCanvas* canvas,
                              SkPicture::AbortCallback* callback) const {
+  static auto* zero = new std::vector<size_t>({0});
   // Treats the entire PaintOpBuffer as a single range.
-  PlaybackRanges({0}, {0}, canvas, callback);
+  PlaybackRanges(*zero, *zero, canvas, callback);
 }
 
 void PaintOpBuffer::PlaybackRanges(const std::vector<size_t>& range_starts,
diff --git a/cc/paint/paint_op_buffer.h b/cc/paint/paint_op_buffer.h
index 1fbcc6b..e8d31142 100644
--- a/cc/paint/paint_op_buffer.h
+++ b/cc/paint/paint_op_buffer.h
@@ -375,7 +375,7 @@
                      const SkMatrix& original_ctm);
   size_t AdditionalBytesUsed() const;
   bool HasDiscardableImages() const;
-  // TODO(enne): DisplayItemList should know number of slow paths.
+  int CountSlowPaths() const;
 
   scoped_refptr<DisplayItemList> list;
 };
diff --git a/cc/paint/paint_op_buffer_unittest.cc b/cc/paint/paint_op_buffer_unittest.cc
index 5751c2f..b85bc5d 100644
--- a/cc/paint/paint_op_buffer_unittest.cc
+++ b/cc/paint/paint_op_buffer_unittest.cc
@@ -497,7 +497,24 @@
   auto buffer2 = sk_make_sp<PaintOpBuffer>();
   EXPECT_EQ(buffer2->numSlowPaths(), 0);
   buffer2->push<DrawRecordOp>(buffer);
-  EXPECT_EQ(buffer->numSlowPaths(), buffer2->numSlowPaths());
+  EXPECT_EQ(buffer2->numSlowPaths(), 2);
+  buffer2->push<DrawRecordOp>(buffer);
+  EXPECT_EQ(buffer2->numSlowPaths(), 4);
+
+  // Drawing an empty display item list doesn't change anything.
+  auto empty_list = base::MakeRefCounted<DisplayItemList>();
+  buffer2->push<DrawDisplayItemListOp>(empty_list);
+  EXPECT_EQ(buffer2->numSlowPaths(), 4);
+
+  // Drawing a display item list adds the items from that list.
+  auto slow_path_list = base::MakeRefCounted<DisplayItemList>();
+  slow_path_list->CreateAndAppendDrawingItem<DrawingDisplayItem>(
+      gfx::Rect(1, 2, 3, 4), sk_make_sp<PaintOpBuffer>(),
+      SkRect::MakeXYWH(1, 2, 3, 4));
+  // Setting this properly is tested in PaintControllerTest.cpp.
+  slow_path_list->SetNumSlowPaths(50);
+  buffer2->push<DrawDisplayItemListOp>(slow_path_list);
+  EXPECT_EQ(buffer2->numSlowPaths(), 54);
 }
 
 TEST(PaintOpBufferTest, ContiguousRanges) {
diff --git a/cc/scheduler/begin_frame_source.cc b/cc/scheduler/begin_frame_source.cc
index 4b7fe01..5b4cd40 100644
--- a/cc/scheduler/begin_frame_source.cc
+++ b/cc/scheduler/begin_frame_source.cc
@@ -283,19 +283,10 @@
     client_->OnNeedsBeginFrames(true);
 
   // Send a MISSED begin frame if necessary.
-  if (last_begin_frame_args_.IsValid()) {
-    const BeginFrameArgs& last_args = obs->LastUsedBeginFrameArgs();
-    if (!last_args.IsValid() ||
-        (last_begin_frame_args_.frame_time > last_args.frame_time)) {
-      DCHECK(
-          (last_begin_frame_args_.source_id != last_args.source_id) ||
-          (last_begin_frame_args_.sequence_number > last_args.sequence_number))
-          << "current " << last_begin_frame_args_.AsValue()->ToString()
-          << ", last " << last_args.AsValue()->ToString();
-      BeginFrameArgs missed_args = last_begin_frame_args_;
-      missed_args.type = BeginFrameArgs::MISSED;
-      obs->OnBeginFrame(missed_args);
-    }
+  BeginFrameArgs missed_args = GetMissedBeginFrameArgs(obs);
+  if (missed_args.IsValid()) {
+    DCHECK_EQ(BeginFrameArgs::MISSED, missed_args.type);
+    obs->OnBeginFrame(missed_args);
   }
 }
 
@@ -304,10 +295,8 @@
   DCHECK(observers_.find(obs) != observers_.end());
 
   observers_.erase(obs);
-  if (observers_.empty()) {
-    last_begin_frame_args_ = BeginFrameArgs();
+  if (observers_.empty())
     client_->OnNeedsBeginFrames(false);
-  }
 }
 
 bool ExternalBeginFrameSource::IsThrottled() const {
@@ -341,4 +330,24 @@
   }
 }
 
+BeginFrameArgs ExternalBeginFrameSource::GetMissedBeginFrameArgs(
+    BeginFrameObserver* obs) {
+  if (!last_begin_frame_args_.IsValid())
+    return BeginFrameArgs();
+
+  const BeginFrameArgs& last_args = obs->LastUsedBeginFrameArgs();
+  if (last_args.IsValid() &&
+      last_begin_frame_args_.frame_time == last_args.frame_time) {
+    return BeginFrameArgs();
+  }
+
+  DCHECK((last_begin_frame_args_.source_id != last_args.source_id) ||
+         (last_begin_frame_args_.sequence_number > last_args.sequence_number))
+      << "current " << last_begin_frame_args_.AsValue()->ToString() << ", last "
+      << last_args.AsValue()->ToString();
+  BeginFrameArgs missed_args = last_begin_frame_args_;
+  missed_args.type = BeginFrameArgs::MISSED;
+  return missed_args;
+}
+
 }  // namespace cc
diff --git a/cc/scheduler/begin_frame_source.h b/cc/scheduler/begin_frame_source.h
index e21878dd..ea7276a2 100644
--- a/cc/scheduler/begin_frame_source.h
+++ b/cc/scheduler/begin_frame_source.h
@@ -257,6 +257,10 @@
   void OnBeginFrame(const BeginFrameArgs& args);
 
  protected:
+  // Called on AddObserver and gets missed BeginFrameArgs for the given
+  // observer.
+  virtual BeginFrameArgs GetMissedBeginFrameArgs(BeginFrameObserver* obs);
+
   BeginFrameArgs last_begin_frame_args_;
   std::unordered_set<BeginFrameObserver*> observers_;
   ExternalBeginFrameSourceClient* client_;
diff --git a/cc/test/stub_surface_factory_client.h b/cc/test/stub_surface_factory_client.h
deleted file mode 100644
index 4b1df0f..0000000
--- a/cc/test/stub_surface_factory_client.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 CC_TEST_STUB_SURFACE_FACTORY_CLIENT_H_
-#define CC_TEST_STUB_SURFACE_FACTORY_CLIENT_H_
-
-#include "cc/surfaces/surface_factory_client.h"
-
-namespace cc {
-
-class StubSurfaceFactoryClient : public SurfaceFactoryClient {
- public:
-  StubSurfaceFactoryClient() = default;
-  ~StubSurfaceFactoryClient() override = default;
-
-  void ReferencedSurfacesChanged(
-      const LocalSurfaceId& local_surface_id,
-      const std::vector<SurfaceId>* active_referenced_surfaces) override {}
-};
-
-}  // namespace cc
-
-#endif  //  CC_TEST_STUB_SURFACE_FACTORY_CLIENT_H_
diff --git a/cc/tiles/eviction_tile_priority_queue.cc b/cc/tiles/eviction_tile_priority_queue.cc
index df75f45..44066bbf 100644
--- a/cc/tiles/eviction_tile_priority_queue.cc
+++ b/cc/tiles/eviction_tile_priority_queue.cc
@@ -15,11 +15,11 @@
   explicit EvictionOrderComparator(TreePriority tree_priority)
       : tree_priority_(tree_priority) {}
 
+  // Note that in this function, we have to return true if and only if
+  // b is strictly lower priority than a.
   bool operator()(
       const std::unique_ptr<TilingSetEvictionQueue>& a_queue,
       const std::unique_ptr<TilingSetEvictionQueue>& b_queue) const {
-    // Note that in this function, we have to return true if and only if
-    // b is strictly lower priority than a.
     const PrioritizedTile& a_tile = a_queue->Top();
     const PrioritizedTile& b_tile = b_queue->Top();
 
@@ -27,6 +27,13 @@
     const TilePriority& b_priority = b_tile.priority();
     bool prioritize_low_res = tree_priority_ == SMOOTHNESS_TAKES_PRIORITY;
 
+    // If the priority bin is the same but one of the tiles is from a
+    // non-drawing layer, then the drawing layer has a higher priority.
+    if (b_priority.priority_bin == a_priority.priority_bin &&
+        b_queue->is_drawing_layer() != a_queue->is_drawing_layer()) {
+      return a_queue->is_drawing_layer();
+    }
+
     // If the priority bin differs, b is lower priority if it has the higher
     // priority bin.
     if (a_priority.priority_bin != b_priority.priority_bin)
@@ -73,7 +80,8 @@
   for (auto* layer : layers) {
     std::unique_ptr<TilingSetEvictionQueue> tiling_set_queue =
         base::MakeUnique<TilingSetEvictionQueue>(
-            layer->picture_layer_tiling_set());
+            layer->picture_layer_tiling_set(),
+            layer->contributes_to_drawn_render_surface());
     // Queues will only contain non empty tiling sets.
     if (!tiling_set_queue->IsEmpty())
       queues->push_back(std::move(tiling_set_queue));
diff --git a/cc/tiles/software_image_decode_cache.cc b/cc/tiles/software_image_decode_cache.cc
index c3b6eb7d..68b85db 100644
--- a/cc/tiles/software_image_decode_cache.cc
+++ b/cc/tiles/software_image_decode_cache.cc
@@ -587,7 +587,12 @@
                  "color conversion");
     image = image->makeColorSpace(target_color_space,
                                   SkTransferFunctionBehavior::kIgnore);
-    DCHECK(image);
+    // Because image is a lazy-decode image, the call to makeColorSpace will
+    // fail if image decode fails.
+    if (!image) {
+      decoded_pixels->Unlock();
+      return nullptr;
+    }
   }
   {
     TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("cc.debug"),
diff --git a/cc/tiles/tiling_set_eviction_queue.cc b/cc/tiles/tiling_set_eviction_queue.cc
index da09e31..5ba7913c 100644
--- a/cc/tiles/tiling_set_eviction_queue.cc
+++ b/cc/tiles/tiling_set_eviction_queue.cc
@@ -11,8 +11,11 @@
 namespace cc {
 
 TilingSetEvictionQueue::TilingSetEvictionQueue(
-    PictureLayerTilingSet* tiling_set)
-    : tree_(tiling_set->tree()), phase_(EVENTUALLY_RECT) {
+    PictureLayerTilingSet* tiling_set,
+    bool is_drawing_layer)
+    : tree_(tiling_set->tree()),
+      phase_(EVENTUALLY_RECT),
+      is_drawing_layer_(is_drawing_layer) {
   // Early out if the layer has no tilings.
   if (!tiling_set->num_tilings())
     return;
diff --git a/cc/tiles/tiling_set_eviction_queue.h b/cc/tiles/tiling_set_eviction_queue.h
index e6055e5..ebd0101 100644
--- a/cc/tiles/tiling_set_eviction_queue.h
+++ b/cc/tiles/tiling_set_eviction_queue.h
@@ -67,12 +67,14 @@
 // with low priority on one tree, but high combined priority.
 class CC_EXPORT TilingSetEvictionQueue {
  public:
-  explicit TilingSetEvictionQueue(PictureLayerTilingSet* tiling_set);
+  explicit TilingSetEvictionQueue(PictureLayerTilingSet* tiling_set,
+                                  bool is_drawing_layer);
   ~TilingSetEvictionQueue();
 
   const PrioritizedTile& Top() const;
   void Pop();
   bool IsEmpty() const;
+  bool is_drawing_layer() const { return is_drawing_layer_; }
 
  private:
   enum Phase {
@@ -198,6 +200,7 @@
   SkewportTilingIterator skewport_iterator_;
   PendingVisibleTilingIterator pending_visible_iterator_;
   VisibleTilingIterator visible_iterator_;
+  bool is_drawing_layer_;
 };
 
 }  // namespace cc
diff --git a/chrome/BUILD.gn b/chrome/BUILD.gn
index b26084b3..ecda2b9 100644
--- a/chrome/BUILD.gn
+++ b/chrome/BUILD.gn
@@ -1630,6 +1630,12 @@
     ]
   }
 
+  java_cpp_enum("payments_journey_logger_enum_javagen") {
+    sources = [
+      "../components/payments/core/journey_logger.h",
+    ]
+  }
+
   java_cpp_enum("quick_action_category_enum_javagen") {
     sources = [
       "browser/android/contextualsearch/resolved_search_term.h",
diff --git a/chrome/android/BUILD.gn b/chrome/android/BUILD.gn
index 83f6dc1..c8e1732 100644
--- a/chrome/android/BUILD.gn
+++ b/chrome/android/BUILD.gn
@@ -253,6 +253,7 @@
     "//chrome:offline_pages_enum_javagen",
     "//chrome:page_info_connection_type_javagen",
     "//chrome:page_info_action_javagen",
+    "//chrome:payments_journey_logger_enum_javagen",
     "//chrome:quick_action_category_enum_javagen",
     "//chrome:sad_tab_event_enum_javagen",
     "//chrome:signin_metrics_enum_javagen",
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/compositor/bottombar/contextualsearch/ContextualSearchPanelMetrics.java b/chrome/android/java/src/org/chromium/chrome/browser/compositor/bottombar/contextualsearch/ContextualSearchPanelMetrics.java
index db79b6f..b2b975d 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/compositor/bottombar/contextualsearch/ContextualSearchPanelMetrics.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/compositor/bottombar/contextualsearch/ContextualSearchPanelMetrics.java
@@ -8,21 +8,15 @@
 import org.chromium.chrome.browser.compositor.bottombar.OverlayPanel.StateChangeReason;
 import org.chromium.chrome.browser.contextualsearch.ContextualSearchHeuristics;
 import org.chromium.chrome.browser.contextualsearch.ContextualSearchRankerLogger;
-import org.chromium.chrome.browser.contextualsearch.ContextualSearchRankerLoggerImpl;
 import org.chromium.chrome.browser.contextualsearch.ContextualSearchUma;
 import org.chromium.chrome.browser.contextualsearch.QuickActionCategory;
 
-import java.net.URL;
-
 /**
  * This class is responsible for all the logging related to Contextual Search.
  */
 public class ContextualSearchPanelMetrics {
     private static final int MILLISECONDS_TO_NANOSECONDS = 1000000;
 
-    // The Ranker logger to use to write Tap Suppression Ranker logs to UMA.
-    private final ContextualSearchRankerLogger mTapSuppressionRankerLogger;
-
     // Flags for logging.
     private boolean mDidSearchInvolvePromo;
     private boolean mWasSearchContentViewSeen;
@@ -58,14 +52,7 @@
     private ContextualSearchHeuristics mResultsSeenExperiments;
     // The current set of heuristics to be logged through ranker with results seen when the panel
     // closes.
-    private ContextualSearchHeuristics mRankerLogExperiments;
-
-    /**
-     * Constructs an object to track metrics for the Contextual Search Overlay Panel.
-     */
-    ContextualSearchPanelMetrics() {
-        mTapSuppressionRankerLogger = new ContextualSearchRankerLoggerImpl();
-    }
+    private ContextualSearchRankerLogger mRankerLogger;
 
     /**
      * Log information when the panel's state has changed.
@@ -97,8 +84,6 @@
                     (System.nanoTime() - mPanelTriggerTimeFromTapNs) / MILLISECONDS_TO_NANOSECONDS;
             ContextualSearchUma.logDurationBetweenTriggerAndScroll(
                     durationMs, mWasSearchContentViewSeen);
-            mTapSuppressionRankerLogger.log(
-                    ContextualSearchRankerLogger.Feature.DURATION_BEFORE_SCROLL_MS, durationMs);
         }
 
         if (isEndingSearch) {
@@ -123,14 +108,19 @@
                         mQuickActionCategory);
                 ContextualSearchUma.logQuickActionClicked(mWasQuickActionClicked,
                         mQuickActionCategory);
-                mTapSuppressionRankerLogger.logOutcome(
-                        ContextualSearchRankerLogger.Feature.OUTCOME_WAS_QUICK_ACTION_CLICKED,
-                        mWasQuickActionClicked);
+                if (mRankerLogger != null) {
+                    mRankerLogger.logOutcome(
+                            ContextualSearchRankerLogger.Feature.OUTCOME_WAS_QUICK_ACTION_CLICKED,
+                            mWasQuickActionClicked);
+                }
             }
 
             if (mResultsSeenExperiments != null) {
                 mResultsSeenExperiments.logResultsSeen(
                         mWasSearchContentViewSeen, mWasActivatedByTap);
+                if (mRankerLogger != null) {
+                    mResultsSeenExperiments.logRankerTapSuppressionOutcome(mRankerLogger);
+                }
                 mResultsSeenExperiments = null;
             }
 
@@ -138,21 +128,22 @@
                 boolean wasAnySuppressionHeuristicSatisfied = mWasAnyHeuristicSatisfiedOnPanelShow;
                 ContextualSearchUma.logAnyTapSuppressionHeuristicSatisfied(
                         mWasSearchContentViewSeen, wasAnySuppressionHeuristicSatisfied);
-                // Log all the experiments to the Ranker logger.
-                if (mRankerLogExperiments != null) {
-                    mTapSuppressionRankerLogger.logOutcome(
+                // Update The Ranker logger.
+                if (mRankerLogger != null) {
+                    // Tell Ranker about the primary outcome.
+                    mRankerLogger.logOutcome(
                             ContextualSearchRankerLogger.Feature.OUTCOME_WAS_PANEL_OPENED,
                             mWasSearchContentViewSeen);
-                    mRankerLogExperiments.logRankerTapSuppression(mTapSuppressionRankerLogger);
-                    mRankerLogExperiments = null;
+                    // TODO(donnd): UMA-Log the Ranker inference signal once we're running a model.
                 }
-                // Reset writing to Ranker so whatever interactions occurred are recorded as a
-                // complete record.
-                mTapSuppressionRankerLogger.writeLogAndReset();
-
                 ContextualSearchUma.logSelectionLengthResultsSeen(
                         mWasSearchContentViewSeen, mSelectionLength);
             }
+
+            // Reset writing to Ranker so whatever interactions occurred are recorded as a
+            // complete record.
+            if (mRankerLogger != null) mRankerLogger.writeLogAndReset();
+            mRankerLogger = null;
         }
 
         if (isExitingPanelOpenedBeyondPeeked) {
@@ -329,15 +320,12 @@
     }
 
     /**
-     * Sets the experiments to log through Ranker with results seen.
-     * @param rankerLogExperiments The experiments to log through Ranker when the panel results
-     *        are known.
-     * @param basePageUrl The URL of the base page to log along with Ranker data.
+     * Sets up logging through Ranker for outcomes.
+     * @param rankerLogger The {@link ContextualSearchRankerLogger} currently being used to measure
+     *                     or suppress the UI by Ranker.
      */
-    public void setRankerLogExperiments(
-            ContextualSearchHeuristics rankerLogExperiments, URL basePageUrl) {
-        mRankerLogExperiments = rankerLogExperiments;
-        mTapSuppressionRankerLogger.setupLoggingForPage(basePageUrl);
+    public void setRankerLogger(ContextualSearchRankerLogger rankerLogger) {
+        mRankerLogger = rankerLogger;
     }
 
     /**
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/BarOverlapTapSuppression.java b/chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/BarOverlapTapSuppression.java
index 8bd295f..a07d88da 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/BarOverlapTapSuppression.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/BarOverlapTapSuppression.java
@@ -66,7 +66,8 @@
 
     @Override
     protected void logRankerTapSuppression(ContextualSearchRankerLogger logger) {
-        logger.log(ContextualSearchRankerLogger.Feature.WAS_SCREEN_BOTTOM, mIsConditionSatisfied);
+        logger.logFeature(
+                ContextualSearchRankerLogger.Feature.WAS_SCREEN_BOTTOM, mIsConditionSatisfied);
     }
 
     /**
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchFieldTrial.java b/chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchFieldTrial.java
index db5262a3..8f2fd64 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchFieldTrial.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchFieldTrial.java
@@ -32,7 +32,7 @@
     private static final int PEEK_PROMO_DEFAULT_MAX_SHOW_COUNT = 10;
 
     private static final String DISABLE_SEARCH_TERM_RESOLUTION = "disable_search_term_resolution";
-    private static final String ENABLE_BLACKLIST = "enable_blacklist";
+    private static final String WAIT_AFTER_TAP_DELAY_MS = "wait_after_tap_delay_ms";
 
     // Translation.  All these members are private, except for usage by testing.
     // Master switch, needed to disable all translate code for Contextual Search in case of an
@@ -86,6 +86,7 @@
     private static Boolean sIsPageContentNotificationDisabled;
     private static Boolean sContextualSearchUrlActionsEnabled;
     private static Boolean sIsRankerLoggingEnabled;
+    private static Integer sWaitAfterTapDelayMs;
 
     /**
      * Don't instantiate.
@@ -182,13 +183,6 @@
     }
 
     /**
-     * @return Whether the blacklist is enabled.
-     */
-    static boolean isBlacklistEnabled() {
-        return getBooleanParam(ENABLE_BLACKLIST);
-    }
-
-    /**
      * @return The maximum number of times the Peek Promo should be displayed.
      */
     static int getPeekPromoMaxShowCount() {
@@ -316,9 +310,23 @@
         return sIsRankerLoggingEnabled;
     }
 
-    // ---------------
-    // Features.
-    // ---------------
+    /**
+     * Gets an amount to delay after a Tap gesture is recognized, in case some user gesture
+     * immediately follows that would prevent the UI from showing.
+     * The classic example is a scroll, which might be a signal that the previous tap was
+     * accidental.
+     * @return The delay in MS after the Tap before showing any UI.
+     */
+    static int getWaitAfterTapDelayMs() {
+        if (sWaitAfterTapDelayMs == null) {
+            sWaitAfterTapDelayMs = getIntParamValueOrDefault(WAIT_AFTER_TAP_DELAY_MS, 0);
+        }
+        return sWaitAfterTapDelayMs.intValue();
+    }
+
+    // ---------------------------
+    // Feature-controlled Switches
+    // ---------------------------
 
     /**
      * @return Whether or not single actions based on Contextual Cards is enabled.
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchHeuristic.java b/chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchHeuristic.java
index c663351..1d5bdcb 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchHeuristic.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchHeuristic.java
@@ -59,4 +59,12 @@
     protected void logRankerTapSuppression(ContextualSearchRankerLogger logger) {
         // Default is to not log.
     }
+
+    /**
+     * Logs a Ranker outcome using the heuristic for the purpose of Ranker Tap Suppression.
+     * @param logger A logger to log to.
+     */
+    protected void logRankerTapSuppressionOutcome(ContextualSearchRankerLogger logger) {
+        // Default is to not log.
+    }
 }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchHeuristics.java b/chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchHeuristics.java
index 82a0502..9bc63f3 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchHeuristics.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchHeuristics.java
@@ -63,7 +63,7 @@
     }
 
     /**
-     * Logs all the heuristics to the given logger.
+     * Logs all the heuristics that want to provide a Ranker "feature" to the given logger.
      * @param logger The logger to log to.
      */
     public void logRankerTapSuppression(ContextualSearchRankerLogger logger) {
@@ -71,4 +71,14 @@
             heuristic.logRankerTapSuppression(logger);
         }
     }
+
+    /**
+     * Logs all the heuristics that want to provide outcomes to Ranker to the given logger.
+     * @param logger The logger to log to.
+     */
+    public void logRankerTapSuppressionOutcome(ContextualSearchRankerLogger logger) {
+        for (ContextualSearchHeuristic heuristic : mHeuristics) {
+            heuristic.logRankerTapSuppressionOutcome(logger);
+        }
+    }
 }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchManager.java b/chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchManager.java
index fc22a8e0..3f43032a 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchManager.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchManager.java
@@ -94,6 +94,8 @@
     // timer).
     private static final int TAP_NEAR_PREVIOUS_DETECTION_DELAY_MS = 100;
 
+    private static final int NANOSECONDS_IN_A_MILLISECOND = 1000000;
+
     private final ObserverList<ContextualSearchObserver> mObservers =
             new ObserverList<ContextualSearchObserver>();
 
@@ -102,6 +104,9 @@
     private final ViewTreeObserver.OnGlobalFocusChangeListener mOnFocusChangeListener;
     private final TabModelObserver mTabModelObserver;
 
+    // The Ranker logger to use to write Tap Suppression Ranker logs to UMA.
+    private final ContextualSearchRankerLogger mTapSuppressionRankerLogger;
+
     private ContextualSearchSelectionController mSelectionController;
     private ContextualSearchNetworkCommunicator mNetworkCommunicator;
     private ContextualSearchPolicy mPolicy;
@@ -224,15 +229,12 @@
         };
 
         mSelectionController = new ContextualSearchSelectionController(activity, this);
-
         mNetworkCommunicator = this;
-
         mPolicy = new ContextualSearchPolicy(mSelectionController, mNetworkCommunicator);
-
         mTranslateController = new ContextualSearchTranslateController(activity, mPolicy, this);
-
         mInternalStateController = new ContextualSearchInternalStateController(
                 mPolicy, getContextualSearchInternalStateHandler());
+        mTapSuppressionRankerLogger = new ContextualSearchRankerLoggerImpl();
     }
 
     /**
@@ -783,6 +785,7 @@
 
         // Notify the UI of the caption.
         mSearchPanel.setCaption(caption);
+        System.out.println("ctxs checking mQuickAnswersHeuristic " + mQuickAnswersHeuristic);
         if (mQuickAnswersHeuristic != null) {
             mQuickAnswersHeuristic.setConditionSatisfied(true);
             mQuickAnswersHeuristic.setDoesAnswer(doesAnswer);
@@ -1291,10 +1294,40 @@
     }
 
     @Override
-    public void handleNonSuppressedTap() {
+    public void handleNonSuppressedTap(long tapTimeNanoseconds) {
         if (mIsAccessibilityModeEnabled) return;
 
-        mInternalStateController.notifyFinishedWorkOn(InternalState.DECIDING_SUPPRESSION);
+        // If there's a wait-after-tap experiment then we may want to delay a bit longer for
+        // the user to take an action like scrolling that will reset our internal state.
+        long delayBeforeFinishingWorkMs = 0;
+        if (ContextualSearchFieldTrial.getWaitAfterTapDelayMs() > 0 && tapTimeNanoseconds > 0) {
+            delayBeforeFinishingWorkMs = ContextualSearchFieldTrial.getWaitAfterTapDelayMs()
+                    - (System.nanoTime() - tapTimeNanoseconds) / NANOSECONDS_IN_A_MILLISECOND;
+        }
+
+        // Finish work on the current state, either immediately or with a delay.
+        if (delayBeforeFinishingWorkMs <= 0) {
+            finishSuppressionDecision();
+        } else {
+            new Handler().postDelayed(new Runnable() {
+                @Override
+                public void run() {
+                    finishSuppressionDecision();
+                }
+            }, delayBeforeFinishingWorkMs);
+        }
+    }
+
+    /**
+     * Finishes work on the suppression decision if that work is still in progress.
+     * If no longer working on the suppression decision then resets the Ranker-logger.
+     */
+    private void finishSuppressionDecision() {
+        if (mInternalStateController.isStillWorkingOn(InternalState.DECIDING_SUPPRESSION)) {
+            mInternalStateController.notifyFinishedWorkOn(InternalState.DECIDING_SUPPRESSION);
+        } else {
+            mTapSuppressionRankerLogger.reset();
+        }
     }
 
     @Override
@@ -1308,7 +1341,7 @@
         mHeuristics.add(mQuickAnswersHeuristic);
 
         mSearchPanel.getPanelMetrics().setResultsSeenExperiments(mHeuristics);
-        mSearchPanel.getPanelMetrics().setRankerLogExperiments(mHeuristics, getBasePageUrl());
+        mSearchPanel.getPanelMetrics().setRankerLogger(mTapSuppressionRankerLogger);
     }
 
     @Override
@@ -1442,7 +1475,13 @@
             @Override
             public void decideSuppression() {
                 mInternalStateController.notifyStartingWorkOn(InternalState.DECIDING_SUPPRESSION);
-                mSelectionController.handleShouldSuppressTap();
+                // Ranker will handle the suppression, but our legacy implementation uses
+                // TapSuppressionHeuristics (run from the ContextualSearchSelectionConroller).
+                // Usage includes tap-far-from-previous suppression.
+                mTapSuppressionRankerLogger.setupLoggingForPage(getBasePageUrl());
+
+                // TODO(donnd): Move handleShouldSuppressTap out of the Selection Controller.
+                mSelectionController.handleShouldSuppressTap(mTapSuppressionRankerLogger);
             }
 
             /** Starts showing the Tap UI by selecting a word around the current caret. */
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchRankerLogger.java b/chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchRankerLogger.java
index 7668152b..0f1796f 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchRankerLogger.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchRankerLogger.java
@@ -18,7 +18,6 @@
         OUTCOME_WAS_QUICK_ANSWER_SEEN,
         // Features:
         DURATION_AFTER_SCROLL_MS,
-        DURATION_BEFORE_SCROLL_MS,
         SCREEN_TOP_DPS,
         WAS_SCREEN_BOTTOM,
         // User usage features:
@@ -30,7 +29,7 @@
 
     /**
      * Sets up logging for the page with the given URL.
-     * This method must be called before calling {@link #log} or {@link #logOutcome}.
+     * This method must be called before calling {@link #logFeature} or {@link #logOutcome}.
      * @param basePageUrl The URL of the base page to log with Ranker.
      */
     void setupLoggingForPage(URL basePageUrl);
@@ -40,7 +39,7 @@
      * @param feature The feature to log.
      * @param value The value to log, which is associated with the given key.
      */
-    void log(Feature feature, Object value);
+    void logFeature(Feature feature, Object value);
 
     /**
      * Logs an outcome value at training time that indicates an ML label as a key/value pair.
@@ -50,10 +49,30 @@
     void logOutcome(Feature feature, Object value);
 
     /**
+     * Infers whether the UI should be suppressed or not, based on the features already logged.
+     * @return {@code true} if the UI should not be shown.
+     */
+    boolean inferUiSuppression();
+
+    /**
+     * Reports whether the UI <b><i>would have been</i></b> suppressed if the ML model was active.
+     * TODO(donnd): remove once the Ranker model has been evaluated and launched -- this is only
+     * needed for evaluation.
+     * @return Whether the UI <b><i>would have been</i></b> suppressed.
+     */
+    boolean wasUiSuppressionInfered();
+
+    /**
+     * Resets the logger so that future log calls accumulate into a new record.
+     * Any accumulated logging for the current record is discarded.
+     */
+    void reset();
+
+    /**
      * Writes all the accumulated log entries and resets the logger so that future log calls
      * accumulate into a new record.
      * After calling this method another call to {@link #setupLoggingForPage} is required before
-     * additional {@link #log} or {@link #logOutcome} calls.
+     * additional {@link #logFeature} or {@link #logOutcome} calls.
      */
     void writeLogAndReset();
 }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchRankerLoggerImpl.java b/chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchRankerLoggerImpl.java
index 21ddc027..3948f0e6 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchRankerLoggerImpl.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchRankerLoggerImpl.java
@@ -4,9 +4,12 @@
 
 package org.chromium.chrome.browser.contextualsearch;
 
-import org.chromium.base.Log;
+import org.chromium.chrome.browser.contextualsearch.ContextualSearchRankerLogger.Feature;
 
 import java.net.URL;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
 
 /**
  * Implements the UMA logging for Ranker that's used for Contextual Search Tap Suppression.
@@ -14,17 +17,41 @@
 public class ContextualSearchRankerLoggerImpl implements ContextualSearchRankerLogger {
     private static final String TAG = "ContextualSearch";
 
+    // Names for our features.
+    private static final Map<Feature, String> FEATURE_NAMES;
+    static {
+        Map<Feature, String> names = new HashMap<Feature, String>();
+        names.put(Feature.OUTCOME_WAS_PANEL_OPENED, "OutcomeWasPanelOpened");
+        names.put(Feature.OUTCOME_WAS_QUICK_ACTION_CLICKED, "OutcomeWasQuickActionClicked");
+        names.put(Feature.OUTCOME_WAS_QUICK_ANSWER_SEEN, "OutcomeWasQuickAnswerSeen");
+        names.put(Feature.DURATION_AFTER_SCROLL_MS, "DurationAfterScrollMs");
+        names.put(Feature.SCREEN_TOP_DPS, "ScreenTopDps");
+        names.put(Feature.WAS_SCREEN_BOTTOM, "WasScreenBottom");
+        names.put(Feature.PREVIOUS_WEEK_IMPRESSIONS_COUNT, "PreviousWeekImpressionsCount");
+        names.put(Feature.PREVIOUS_WEEK_CTR_PERCENT, "PreviousWeekCtrPercent");
+        names.put(Feature.PREVIOUS_28DAY_IMPRESSIONS_COUNT, "Previous28DayImpressionsCount");
+        names.put(Feature.PREVIOUS_28DAY_CTR_PERCENT, "Previous28DayCtrPercent");
+        FEATURE_NAMES = Collections.unmodifiableMap(names);
+    }
+
     // Pointer to the native instance of this class.
     private long mNativePointer;
 
-    // Whether logging for the current URL is currently setup.
-    private boolean mIsLoggingSetup;
+    // Whether logging for the current URL has been setup.
+    private boolean mIsLoggingReadyForUrl;
 
-    // Whether the service is ready to actually record log data.
-    private boolean mCanServiceActuallyRecord;
+    // URL of the base page that the log data is associated with.
+    private URL mBasePageUrl;
 
-    // Whether any data has been written to the log since calling setupLoggingForPage().
-    private boolean mDidLog;
+    // Whether inference has already occurred for this interaction (and calling #logFeature is no
+    // longer allowed).
+    private boolean mHasInferenceOccurred;
+
+    // Whether the UI was suppressed.
+    private boolean mWasUiSuppressionInfered;
+
+    // Map that accumulates all of the Features to log for a specific user-interaction.
+    private Map<Feature, Object> mFeaturesToLog;
 
     /**
      * Constructs a Ranker Logger and associated native implementation to write Contextual Search
@@ -44,74 +71,107 @@
             writeLogAndReset();
             nativeDestroy(mNativePointer);
             mNativePointer = 0;
-            mCanServiceActuallyRecord = false;
-            mDidLog = false;
         }
-        mIsLoggingSetup = false;
+        mIsLoggingReadyForUrl = false;
     }
 
     @Override
     public void setupLoggingForPage(URL basePageUrl) {
-        mIsLoggingSetup = true;
-        if (isEnabled()) {
-            // The URL may be null for custom Chrome URIs like chrome://flags.
-            if (basePageUrl != null) {
-                nativeSetupLoggingAndRanker(mNativePointer, basePageUrl.toString());
-                mCanServiceActuallyRecord = true;
-            }
-        }
+        mIsLoggingReadyForUrl = true;
+        mBasePageUrl = basePageUrl;
+        mHasInferenceOccurred = false;
     }
 
     @Override
-    public void log(Feature feature, Object value) {
-        assert mIsLoggingSetup;
+    public void logFeature(Feature feature, Object value) {
+        assert mIsLoggingReadyForUrl : "mIsLoggingReadyForUrl false.";
+        assert !mHasInferenceOccurred;
         if (!isEnabled()) return;
 
-        // TODO(donnd): Add some enforcement that log() calls are done before inference time.
         logInternal(feature, value);
     }
 
     @Override
     public void logOutcome(Feature feature, Object value) {
-        assert mIsLoggingSetup;
         if (!isEnabled()) return;
 
+        // Since the panel can be closed at any time, we might try to log that outcome immediately.
+        if (!mIsLoggingReadyForUrl) return;
+
         logInternal(feature, value);
     }
 
     @Override
-    public void writeLogAndReset() {
-        if (isEnabled()) {
-            if (mDidLog) nativeWriteLogAndReset(mNativePointer);
-            mCanServiceActuallyRecord = false;
-            mDidLog = false;
-        }
-        mIsLoggingSetup = false;
+    public boolean inferUiSuppression() {
+        mHasInferenceOccurred = true;
+        // TODO(donnd): actually run the Ranker model and register its recommendation here!
+        mWasUiSuppressionInfered = false;
+        // TODO(donnd): actually return the recommendation so it can be acted upon!
+        return false;
     }
 
-    /** Whether actually writing data is enabled.  If not, we may do nothing or print. */
+    @Override
+    public boolean wasUiSuppressionInfered() {
+        return mWasUiSuppressionInfered;
+    }
+
+    @Override
+    public void reset() {
+        mIsLoggingReadyForUrl = false;
+        mHasInferenceOccurred = false;
+        mFeaturesToLog = null;
+        mBasePageUrl = null;
+        mWasUiSuppressionInfered = false;
+    }
+
+    @Override
+    public void writeLogAndReset() {
+        // The URL may be null for custom Chrome URIs like chrome://flags.
+        if (isEnabled() && mBasePageUrl != null && mFeaturesToLog != null) {
+            assert mIsLoggingReadyForUrl;
+            nativeSetupLoggingAndRanker(mNativePointer, mBasePageUrl.toString());
+            for (Map.Entry<Feature, Object> entry : mFeaturesToLog.entrySet()) {
+                logObject(entry.getKey(), entry.getValue());
+            }
+            nativeWriteLogAndReset(mNativePointer);
+        }
+        reset();
+    }
+
+    /**
+     * Logs the given feature/value to the internal map that accumulates an entire record (which can
+     * be logged by calling writeLogAndReset).
+     * @param feature The feature to log.
+     * @param value The value to log.
+     */
+    private void logInternal(Feature feature, Object value) {
+        if (mFeaturesToLog == null) mFeaturesToLog = new HashMap<Feature, Object>();
+        mFeaturesToLog.put(feature, value);
+    }
+
+    /** Whether actually writing data is enabled.  If not, we may do nothing, or just print. */
     private boolean isEnabled() {
         return ContextualSearchFieldTrial.isRankerLoggingEnabled();
     }
 
     /**
-     * Logs the given feature/value after checking that logging has been set up.
+     * Logs the given {@link ContextualSearchRankerLogger.Feature} with the given value
+     * {@link Object}.
      * @param feature The feature to log.
-     * @param value The value to log.
+     * @param value An {@link Object} value to log (must be convertible to a {@code long}).
      */
-    private void logInternal(Feature feature, Object value) {
+    private void logObject(Feature feature, Object value) {
         if (value instanceof Boolean) {
-            logToNative(feature.toString(), ((boolean) value ? 1 : 0));
+            logToNative(feature, ((boolean) value ? 1 : 0));
         } else if (value instanceof Integer) {
-            logToNative(feature.toString(), Long.valueOf((int) value));
+            logToNative(feature, Long.valueOf((int) value));
         } else if (value instanceof Long) {
-            logToNative(feature.toString(), (long) value);
+            logToNative(feature, (long) value);
         } else if (value instanceof Character) {
-            logToNative(feature.toString(), Character.getNumericValue((char) value));
+            logToNative(feature, Character.getNumericValue((char) value));
         } else {
-            Log.w(TAG,
-                    "Could not log feature to Ranker: " + feature.toString() + " of class "
-                            + value.getClass());
+            assert false : "Could not log feature to Ranker: " + feature.toString() + " of class "
+                           + value.getClass();
         }
     }
 
@@ -120,11 +180,15 @@
      * @param feature The feature to log.
      * @param value The value to log.
      */
-    private void logToNative(String feature, long value) {
-        if (mCanServiceActuallyRecord) {
-            nativeLogLong(mNativePointer, feature, value);
-            mDidLog = true;
-        }
+    private void logToNative(Feature feature, long value) {
+        nativeLogLong(mNativePointer, getFeatureName(feature), value);
+    }
+
+    /**
+     * @return The name of the given feature.
+     */
+    private String getFeatureName(Feature feature) {
+        return FEATURE_NAMES.get(feature);
     }
 
     // ============================================================================================
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchSelectionController.java b/chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchSelectionController.java
index c2472f5..9f296ce 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchSelectionController.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchSelectionController.java
@@ -351,8 +351,10 @@
      * or #handleNonSuppressedTap() after a possible delay.
      * This should be called when the context is fully built (by gathering surrounding text
      * if needed, etc) but before showing any UX.
+     * @param rankerLogger The {@link ContextualSearchRankerLogger} currently being used to measure
+     *        or suppress the UI by Ranker.
      */
-    void handleShouldSuppressTap() {
+    void handleShouldSuppressTap(ContextualSearchRankerLogger rankerLogger) {
         int x = (int) mX;
         int y = (int) mY;
 
@@ -362,25 +364,29 @@
                 - prefs.getContextualSearchTapQuickAnswerCount();
         TapSuppressionHeuristics tapHeuristics =
                 new TapSuppressionHeuristics(this, mLastTapState, x, y, adjustedTapsSinceOpen);
+
         // TODO(donnd): Move to be called when the panel closes to work with states that change.
         tapHeuristics.logConditionState();
+
+        tapHeuristics.logRankerTapSuppression(rankerLogger);
         // Tell the manager what it needs in order to log metrics on whether the tap would have
         // been suppressed if each of the heuristics were satisfied.
         mHandler.handleMetricsForWouldSuppressTap(tapHeuristics);
 
-        boolean shouldSuppressTap = tapHeuristics.shouldSuppressTap();
+        boolean shouldSuppressTapBasedOnHeuristics = tapHeuristics.shouldSuppressTap();
         if (mTapTimeNanoseconds != 0) {
             // Remember the tap state for subsequent tap evaluation.
-            mLastTapState =
-                    new ContextualSearchTapState(x, y, mTapTimeNanoseconds, shouldSuppressTap);
+            mLastTapState = new ContextualSearchTapState(
+                    x, y, mTapTimeNanoseconds, shouldSuppressTapBasedOnHeuristics);
         } else {
             mLastTapState = null;
         }
 
-        if (shouldSuppressTap) {
+        boolean shouldSuppressTapBasedOnRanker = rankerLogger.inferUiSuppression();
+        if (shouldSuppressTapBasedOnHeuristics || shouldSuppressTapBasedOnRanker) {
             mHandler.handleSuppressedTap();
         } else {
-            mHandler.handleNonSuppressedTap();
+            mHandler.handleNonSuppressedTap(mTapTimeNanoseconds);
         }
     }
 
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchSelectionHandler.java b/chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchSelectionHandler.java
index 5c26b3d..9194ed4 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchSelectionHandler.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchSelectionHandler.java
@@ -59,8 +59,9 @@
 
     /**
      * Handle a Tap gesture that has not been suppressed by showing the Tap Search UI.
+     * @param tapTimeNanoseconds When the last tap gesture happened, or {@code 0} if not known.
      */
-    public void handleNonSuppressedTap();
+    public void handleNonSuppressedTap(long tapTimeNanoseconds);
 
     /**
      * Handle updating metrics to reflect that a Tap gesture <i>would</i> be suppressed
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/CtrSuppression.java b/chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/CtrSuppression.java
index e1db697..4b552459 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/CtrSuppression.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/CtrSuppression.java
@@ -88,18 +88,18 @@
         if (nativeHasPreviousWeekData(mNativePointer)) {
             int previousWeekImpressions = nativeGetPreviousWeekImpressions(mNativePointer);
             int previousWeekCtr = (int) (100 * nativeGetPreviousWeekCtr(mNativePointer));
-            logger.log(ContextualSearchRankerLogger.Feature.PREVIOUS_WEEK_IMPRESSIONS_COUNT,
+            logger.logFeature(ContextualSearchRankerLogger.Feature.PREVIOUS_WEEK_IMPRESSIONS_COUNT,
                     previousWeekImpressions);
-            logger.log(ContextualSearchRankerLogger.Feature.PREVIOUS_WEEK_CTR_PERCENT,
+            logger.logFeature(ContextualSearchRankerLogger.Feature.PREVIOUS_WEEK_CTR_PERCENT,
                     previousWeekCtr);
         }
 
         if (nativeHasPrevious28DayData(mNativePointer)) {
             int previous28DayImpressions = nativeGetPrevious28DayImpressions(mNativePointer);
             int previous28DayCtr = (int) (100 * nativeGetPrevious28DayCtr(mNativePointer));
-            logger.log(ContextualSearchRankerLogger.Feature.PREVIOUS_28DAY_IMPRESSIONS_COUNT,
+            logger.logFeature(ContextualSearchRankerLogger.Feature.PREVIOUS_28DAY_IMPRESSIONS_COUNT,
                     previous28DayImpressions);
-            logger.log(ContextualSearchRankerLogger.Feature.PREVIOUS_28DAY_CTR_PERCENT,
+            logger.logFeature(ContextualSearchRankerLogger.Feature.PREVIOUS_28DAY_CTR_PERCENT,
                     previous28DayCtr);
         }
     }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/NearTopTapSuppression.java b/chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/NearTopTapSuppression.java
index 1f3f9f1..93a7d42a 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/NearTopTapSuppression.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/NearTopTapSuppression.java
@@ -48,7 +48,7 @@
 
     @Override
     protected void logRankerTapSuppression(ContextualSearchRankerLogger logger) {
-        logger.log(ContextualSearchRankerLogger.Feature.SCREEN_TOP_DPS, mYDp);
+        logger.logFeature(ContextualSearchRankerLogger.Feature.SCREEN_TOP_DPS, mYDp);
     }
 
     // TODO(twellington): Define a default value to use when determining if the condition is
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/QuickAnswersHeuristic.java b/chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/QuickAnswersHeuristic.java
index 4d5ce34..cdaba384 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/QuickAnswersHeuristic.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/QuickAnswersHeuristic.java
@@ -57,7 +57,8 @@
     }
 
     @Override
-    protected void logRankerTapSuppression(ContextualSearchRankerLogger logger) {
-        logger.log(ContextualSearchRankerLogger.Feature.OUTCOME_WAS_QUICK_ANSWER_SEEN, mDidAnswer);
+    protected void logRankerTapSuppressionOutcome(ContextualSearchRankerLogger logger) {
+        logger.logOutcome(
+                ContextualSearchRankerLogger.Feature.OUTCOME_WAS_QUICK_ANSWER_SEEN, mDidAnswer);
     }
 }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/RecentScrollTapSuppression.java b/chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/RecentScrollTapSuppression.java
index 2c41455..d7a6ed7 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/RecentScrollTapSuppression.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/RecentScrollTapSuppression.java
@@ -46,7 +46,7 @@
 
     @Override
     protected void logRankerTapSuppression(ContextualSearchRankerLogger logger) {
-        logger.log(ContextualSearchRankerLogger.Feature.DURATION_AFTER_SCROLL_MS,
+        logger.logFeature(ContextualSearchRankerLogger.Feature.DURATION_AFTER_SCROLL_MS,
                 mDurationSinceRecentScrollMs);
     }
 }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/instantapps/InstantAppsHandler.java b/chrome/android/java/src/org/chromium/chrome/browser/instantapps/InstantAppsHandler.java
index c37871d..f9c7582 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/instantapps/InstantAppsHandler.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/instantapps/InstantAppsHandler.java
@@ -25,7 +25,6 @@
 import org.chromium.chrome.browser.preferences.ChromePreferenceManager;
 import org.chromium.chrome.browser.tab.Tab;
 import org.chromium.chrome.browser.util.IntentUtils;
-import org.chromium.content_public.browser.WebContents;
 
 import java.util.concurrent.TimeUnit;
 
@@ -281,20 +280,6 @@
      * App banner.
      * @return Whether an Instant App intent was started.
      */
-    @Deprecated
-    public boolean handleNavigation(
-            Context context, String url, Uri referrer, WebContents webContents) {
-        if (InstantAppsSettings.isInstantAppDefault(webContents, url)) {
-            return launchInstantAppForNavigation(context, url, referrer);
-        }
-        return startCheckForInstantApps(context, url, referrer, webContents);
-    }
-
-    /**
-     * Evaluate a navigation for whether it should launch an Instant App or show the Instant
-     * App banner.
-     * @return Whether an Instant App intent was started.
-     */
     public boolean handleNavigation(Context context, String url, Uri referrer, Tab tab) {
         if (InstantAppsSettings.isInstantAppDefault(tab.getWebContents(), url)) {
             return launchInstantAppForNavigation(context, url, referrer);
@@ -305,15 +290,6 @@
     /**
      * Checks if an Instant App banner should be shown for the page we are loading.
      */
-    @Deprecated
-    protected boolean startCheckForInstantApps(
-            Context context, String url, Uri referrer, WebContents webContents) {
-        return false;
-    }
-
-    /**
-     * Checks if an Instant App banner should be shown for the page we are loading.
-     */
     protected boolean startCheckForInstantApps(Context context, String url, Uri referrer, Tab tab) {
         return false;
     }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/notifications/CustomNotificationBuilder.java b/chrome/android/java/src/org/chromium/chrome/browser/notifications/CustomNotificationBuilder.java
index fb8c9b3..ff3d347 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/notifications/CustomNotificationBuilder.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/notifications/CustomNotificationBuilder.java
@@ -79,9 +79,9 @@
 
     private final Context mContext;
 
-    public CustomNotificationBuilder(Context context) {
-        // TODO(crbug.com/726340): Pass in the ChannelDefinition
-        super(context.getResources(), ChannelDefinitions.CHANNEL_ID_SITES);
+    public CustomNotificationBuilder(
+            Context context, @ChannelDefinitions.ChannelId String channelId) {
+        super(context.getResources(), channelId);
         mContext = context;
     }
 
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/notifications/NotificationBuilderForO.java b/chrome/android/java/src/org/chromium/chrome/browser/notifications/NotificationBuilderForO.java
index f4423670..7800aee 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/notifications/NotificationBuilderForO.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/notifications/NotificationBuilderForO.java
@@ -27,6 +27,11 @@
             ChannelsInitializer channelsInitializer) {
         super(context);
         assert BuildInfo.isAtLeastO();
+        if (channelId == null) {
+            // The channelId may be null if the notification will be posted by another app that
+            // does not target O or sets its own channels. E.g. Web apk notifications.
+            return;
+        }
         channelsInitializer.ensureInitialized(channelId);
         // TODO(crbug.com/707804) Stop using reflection once compileSdkVersion is high enough.
         try {
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/notifications/NotificationPlatformBridge.java b/chrome/android/java/src/org/chromium/chrome/browser/notifications/NotificationPlatformBridge.java
index fe523ef0..2495103 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/notifications/NotificationPlatformBridge.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/notifications/NotificationPlatformBridge.java
@@ -513,9 +513,9 @@
                 incognito, tag, webApkPackage, -1 /* actionIndex */);
 
         boolean hasImage = image != null;
-
+        boolean forWebApk = !webApkPackage.isEmpty();
         NotificationBuilderBase notificationBuilder =
-                createNotificationBuilder(context, hasImage)
+                createNotificationBuilder(context, forWebApk, hasImage)
                         .setTitle(title)
                         .setBody(body)
                         .setImage(image)
@@ -558,7 +558,10 @@
         notificationBuilder.setVibrate(makeVibrationPattern(vibrationPattern));
 
         String platformTag = makePlatformTag(notificationId, origin, tag);
-        if (webApkPackage.isEmpty()) {
+        if (forWebApk) {
+            WebApkNotificationClient.notifyNotification(
+                    webApkPackage, notificationBuilder, platformTag, PLATFORM_ID);
+        } else {
             // Set up a pending intent for going to the settings screen for |origin|.
             Intent settingsIntent = PreferencesLauncher.createIntentForSettingsPage(
                     context, SingleWebsitePreferences.class.getName());
@@ -587,17 +590,19 @@
             mNotificationManager.notify(platformTag, PLATFORM_ID, notificationBuilder.build());
             NotificationUmaTracker.getInstance().onNotificationShown(
                     NotificationUmaTracker.SITES, ChannelDefinitions.CHANNEL_ID_SITES);
-        } else {
-            WebApkNotificationClient.notifyNotification(
-                    webApkPackage, notificationBuilder, platformTag, PLATFORM_ID);
         }
     }
 
-    private NotificationBuilderBase createNotificationBuilder(Context context, boolean hasImage) {
+    private NotificationBuilderBase createNotificationBuilder(
+            Context context, boolean forWebApk, boolean hasImage) {
+        // Don't set a channelId for web apk notifications because the channel won't be
+        // initialized for the web apk and it will crash on notify - see crbug.com/727178.
+        // (It's okay to not set a channel on them because web apks don't target O yet.)
+        String channelId = forWebApk ? null : ChannelDefinitions.CHANNEL_ID_SITES;
         if (useCustomLayouts(hasImage)) {
-            return new CustomNotificationBuilder(context);
+            return new CustomNotificationBuilder(context, channelId);
         }
-        return new StandardNotificationBuilder(context, ChannelDefinitions.CHANNEL_ID_SITES);
+        return new StandardNotificationBuilder(context, channelId);
     }
 
     /**
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/notifications/NotificationUmaTracker.java b/chrome/android/java/src/org/chromium/chrome/browser/notifications/NotificationUmaTracker.java
index e07f398..d1144a64 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/notifications/NotificationUmaTracker.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/notifications/NotificationUmaTracker.java
@@ -93,7 +93,7 @@
             recordHistogram("Mobile.SystemNotification.Blocked", type);
             return;
         }
-        if (BuildInfo.isAtLeastO() && isChannelBlocked(channelId)) {
+        if (BuildInfo.isAtLeastO() && channelId != null && isChannelBlocked(channelId)) {
             recordHistogram("Mobile.SystemNotification.ChannelBlocked", type);
             return;
         }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/ntp/NewTabPageView.java b/chrome/android/java/src/org/chromium/chrome/browser/ntp/NewTabPageView.java
index febb5cf..7281c047 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/ntp/NewTabPageView.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/ntp/NewTabPageView.java
@@ -38,6 +38,7 @@
 import org.chromium.chrome.browser.ntp.cards.NewTabPageAdapter;
 import org.chromium.chrome.browser.ntp.cards.NewTabPageRecyclerView;
 import org.chromium.chrome.browser.offlinepages.OfflinePageBridge;
+import org.chromium.chrome.browser.omnibox.OmniboxPlaceholderFieldTrial;
 import org.chromium.chrome.browser.profiles.Profile;
 import org.chromium.chrome.browser.suggestions.DestructionObserver;
 import org.chromium.chrome.browser.suggestions.SuggestionsUiDelegate;
@@ -337,7 +338,7 @@
             searchBoxTextView.setCompoundDrawables(null, null, null, null);
         }
 
-        String hintText = getResources().getString(R.string.search_or_type_url);
+        String hintText = OmniboxPlaceholderFieldTrial.getOmniboxPlaceholder();
         if (!DeviceFormFactor.isTablet()) {
             searchBoxTextView.setHint(hintText);
         } else {
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/omnibox/OmniboxPlaceholderFieldTrial.java b/chrome/android/java/src/org/chromium/chrome/browser/omnibox/OmniboxPlaceholderFieldTrial.java
new file mode 100644
index 0000000..99a70d5
--- /dev/null
+++ b/chrome/android/java/src/org/chromium/chrome/browser/omnibox/OmniboxPlaceholderFieldTrial.java
@@ -0,0 +1,86 @@
+// 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;
+
+import android.content.res.Resources;
+
+import org.chromium.base.ContextUtils;
+import org.chromium.base.FieldTrialList;
+import org.chromium.chrome.R;
+import org.chromium.chrome.browser.preferences.ChromePreferenceManager;
+
+/**
+ * Provides Field Trial support for Omnibox Placeholder Experiment.
+ */
+public class OmniboxPlaceholderFieldTrial {
+    private static final String FIELD_TRIAL_NAME = "OmniboxPlaceholderExperiment";
+    private static final String GROUP_SEARCH_OR_TYPE_URL = "SearchOrTypeUrl";
+    private static final String GROUP_SEARCH_OR_TYPE_WEBSITE_NAME = "SearchOrTypeWebsiteName";
+    private static final String GROUP_SEARCH_THE_WEB = "SearchTheWeb";
+    private static final String GROUP_ENTER_A_SEARCH_OR_WEBSITE = "EnterASearchOrWebsite";
+    private static final String GROUP_SEARCH_NEWS = "SearchNews";
+    private static final String GROUP_SEARCH_RECIPES = "SearchRecipes";
+    private static final String GROUP_SEARCH_WEATHER = "SearchWeather";
+    private static final String GROUP_BLANK = "Blank";
+
+    private static String sCachedHint;
+
+    /** Prevent initialization of this class. */
+    private OmniboxPlaceholderFieldTrial() {}
+
+    /**
+     * Caches omnibox placeholder experiment group to shared preferences.
+     */
+    public static void cacheOmniboxPlaceholderGroup() {
+        String groupName = FieldTrialList.findFullName(FIELD_TRIAL_NAME);
+        ChromePreferenceManager.getInstance().setOmniboxPlaceholderGroup(groupName);
+    }
+
+    /**
+     * Initialize ominibox placeholder text to static variable sCachedHint
+     */
+    private static void initOmniboxPlaceholder() {
+        // setUrlBarHint is only called once when hint is not cached to static variable sCachedHint.
+        // This is to keep consistency on showing same hint to user in one session.
+        String groupName = ChromePreferenceManager.getInstance().getOmniboxPlaceholderGroup();
+        Resources resources = ContextUtils.getApplicationContext().getResources();
+        switch (groupName) {
+            case GROUP_SEARCH_OR_TYPE_URL:
+                sCachedHint = resources.getString(R.string.search_or_type_url);
+                break;
+            case GROUP_SEARCH_OR_TYPE_WEBSITE_NAME:
+                sCachedHint = resources.getString(R.string.search_or_type_website_name);
+                break;
+            case GROUP_SEARCH_THE_WEB:
+                sCachedHint = resources.getString(R.string.search_the_web);
+                break;
+            case GROUP_ENTER_A_SEARCH_OR_WEBSITE:
+                sCachedHint = resources.getString(R.string.enter_a_search_or_website);
+                break;
+            case GROUP_SEARCH_NEWS:
+                sCachedHint = resources.getString(R.string.search_news);
+                break;
+            case GROUP_SEARCH_RECIPES:
+                sCachedHint = resources.getString(R.string.search_recipes);
+                break;
+            case GROUP_SEARCH_WEATHER:
+                sCachedHint = resources.getString(R.string.search_weather);
+                break;
+            case GROUP_BLANK:
+                sCachedHint = "";
+                break;
+            default:
+                sCachedHint = resources.getString(R.string.search_or_type_url);
+        }
+    }
+
+    /**
+     * @return String of hint text to show in omnibox url bar.
+     */
+    public static String getOmniboxPlaceholder() {
+        if (sCachedHint == null) initOmniboxPlaceholder();
+        return sCachedHint;
+    }
+}
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/omnibox/UrlBar.java b/chrome/android/java/src/org/chromium/chrome/browser/omnibox/UrlBar.java
index c16d5d8..7d8be3d3 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/omnibox/UrlBar.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/omnibox/UrlBar.java
@@ -204,6 +204,8 @@
         setFocusable(false);
         setFocusableInTouchMode(false);
 
+        setHint(OmniboxPlaceholderFieldTrial.getOmniboxPlaceholder());
+
         mGestureDetector = new GestureDetector(
                 getContext(), new GestureDetector.SimpleOnGestureListener() {
                     @Override
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/payments/JourneyLogger.java b/chrome/android/java/src/org/chromium/chrome/browser/payments/JourneyLogger.java
index abe5272..35718d7 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/payments/JourneyLogger.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/payments/JourneyLogger.java
@@ -4,7 +4,6 @@
 
 package org.chromium.chrome.browser.payments;
 
-import org.chromium.base.VisibleForTesting;
 import org.chromium.base.annotations.JNINamespace;
 
 /**
@@ -12,80 +11,6 @@
  */
 @JNINamespace("payments")
 public class JourneyLogger {
-    // Note: The constants should always be in sync with those in the
-    // components/payments/core/journey_logger.h file.
-    // The index of the different sections of a Payment Request. Used to record journey stats.
-    public static final int SECTION_CONTACT_INFO = 0;
-    public static final int SECTION_CREDIT_CARDS = 1;
-    public static final int SECTION_SHIPPING_ADDRESS = 2;
-    public static final int SECTION_MAX = 3;
-
-    // For the CanMakePayment histograms.
-    public static final int CAN_MAKE_PAYMENT_USED = 0;
-    public static final int CAN_MAKE_PAYMENT_NOT_USED = 1;
-    public static final int CAN_MAKE_PAYMENT_USE_MAX = 2;
-
-    // Used to log different parameters' effect on whether the transaction was completed.
-    public static final int COMPLETION_STATUS_COMPLETED = 0;
-    public static final int COMPLETION_STATUS_USER_ABORTED = 1;
-    public static final int COMPLETION_STATUS_OTHER_ABORTED = 2;
-    public static final int COMPLETION_STATUS_MAX = 3;
-
-    // Used to mesure the impact of the CanMakePayment return value on whether the Payment Request
-    // is shown to the user.
-    public static final int CMP_SHOW_COULD_NOT_MAKE_PAYMENT_AND_DID_NOT_SHOW = 0;
-    public static final int CMP_SHOW_DID_SHOW = 1 << 0;
-    public static final int CMP_SHOW_COULD_MAKE_PAYMENT = 1 << 1;
-    public static final int CMP_SHOW_MAX = 4;
-
-    // The events that can occur during a Payment Request.
-    public static final int EVENT_INITIATED = 0;
-    public static final int EVENT_SHOWN = 1 << 0;
-    public static final int EVENT_PAY_CLICKED = 1 << 1;
-    public static final int EVENT_RECEIVED_INSTRUMENT_DETAILS = 1 << 2;
-    public static final int EVENT_SKIPPED_SHOW = 1 << 3;
-    public static final int EVENT_MAX = 16;
-
-    // The minimum expected value of CustomCountHistograms is always set to 1. It is still possible
-    // to log the value 0 to that type of histogram.
-    private static final int MIN_EXPECTED_SAMPLE = 1;
-    private static final int MAX_EXPECTED_SAMPLE = 49;
-    private static final int NUMBER_BUCKETS = 50;
-
-    // PaymentRequestAbortReason defined in tools/metrics/histograms/histograms.xml.
-    @VisibleForTesting
-    public static final int ABORT_REASON_ABORTED_BY_USER = 0;
-    @VisibleForTesting
-    public static final int ABORT_REASON_ABORTED_BY_MERCHANT = 1;
-    @VisibleForTesting
-    public static final int ABORT_REASON_INVALID_DATA_FROM_RENDERER = 2;
-    @VisibleForTesting
-    public static final int ABORT_REASON_MOJO_CONNECTION_ERROR = 3;
-    @VisibleForTesting
-    public static final int ABORT_REASON_MOJO_RENDERER_CLOSING = 4;
-    @VisibleForTesting
-    public static final int ABORT_REASON_INSTRUMENT_DETAILS_ERROR = 5;
-    @VisibleForTesting
-    public static final int ABORT_REASON_NO_MATCHING_PAYMENT_METHOD = 6; // Deprecated.
-    @VisibleForTesting
-    public static final int ABORT_REASON_NO_SUPPORTED_PAYMENT_METHOD = 7; // Deprecated.
-    @VisibleForTesting
-    public static final int ABORT_REASON_OTHER = 8;
-    @VisibleForTesting
-    public static final int ABORT_REASON_MAX = 9;
-
-    // PaymentRequestNoShowReason defined in tools/metrics/histograms/histograms.xml
-    @VisibleForTesting
-    public static final int NO_SHOW_NO_MATCHING_PAYMENT_METHOD = 0;
-    @VisibleForTesting
-    public static final int NO_SHOW_NO_SUPPORTED_PAYMENT_METHOD = 1;
-    @VisibleForTesting
-    public static final int NO_SHOW_CONCURRENT_REQUESTS = 2;
-    @VisibleForTesting
-    public static final int NO_SHOW_REASON_OTHER = 3;
-    @VisibleForTesting
-    public static final int NO_SHOW_REASON_MAX = 4;
-
     /**
      * Pointer to the native implementation.
      */
@@ -115,7 +40,7 @@
      * @param number The number of suggestions.
      */
     public void setNumberOfSuggestionsShown(int section, int number) {
-        assert section < SECTION_MAX;
+        assert section < Section.MAX;
         nativeSetNumberOfSuggestionsShown(mJourneyLoggerAndroid, section, number);
     }
 
@@ -125,7 +50,7 @@
      * @param section The section for which to log.
      */
     public void incrementSelectionChanges(int section) {
-        assert section < SECTION_MAX;
+        assert section < Section.MAX;
         nativeIncrementSelectionChanges(mJourneyLoggerAndroid, section);
     }
 
@@ -135,7 +60,7 @@
      * @param section The section for which to log.
      */
     public void incrementSelectionEdits(int section) {
-        assert section < SECTION_MAX;
+        assert section < Section.MAX;
         nativeIncrementSelectionEdits(mJourneyLoggerAndroid, section);
     }
 
@@ -145,7 +70,7 @@
      * @param section The section for which to log.
      */
     public void incrementSelectionAdds(int section) {
-        assert section < SECTION_MAX;
+        assert section < Section.MAX;
         nativeIncrementSelectionAdds(mJourneyLoggerAndroid, section);
     }
 
@@ -170,7 +95,7 @@
      * Records that an event occurred.
      */
     public void setEventOccurred(int event) {
-        assert event < EVENT_MAX;
+        assert event < Event.ENUM_MAX;
         nativeSetEventOccurred(mJourneyLoggerAndroid, event);
     }
 
@@ -195,7 +120,7 @@
      * @param reason An int indicating why the payment request was aborted.
      */
     public void setAborted(int reason) {
-        assert reason < ABORT_REASON_MAX;
+        assert reason < AbortReason.MAX;
         assert mWasShowCalled;
 
         // The abort reasons on Android cascade into each other, so only the first one should be
@@ -212,7 +137,7 @@
      * @param reason An int indicating why the payment request was not shown.
      */
     public void setNotShown(int reason) {
-        assert reason < NO_SHOW_REASON_MAX;
+        assert reason < NotShownReason.MAX;
         assert !mWasShowCalled;
         assert !mHasRecorded;
 
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/payments/PaymentRequestImpl.java b/chrome/android/java/src/org/chromium/chrome/browser/payments/PaymentRequestImpl.java
index 0fc8f46..fbfd05f 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/payments/PaymentRequestImpl.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/payments/PaymentRequestImpl.java
@@ -406,13 +406,13 @@
     public void init(PaymentRequestClient client, PaymentMethodData[] methodData,
             PaymentDetails details, PaymentOptions options) {
         if (mClient != null) {
-            mJourneyLogger.setAborted(JourneyLogger.ABORT_REASON_INVALID_DATA_FROM_RENDERER);
+            mJourneyLogger.setAborted(AbortReason.INVALID_DATA_FROM_RENDERER);
             disconnectFromClientWithDebugMessage("Renderer should never call init() twice");
             return;
         }
 
         if (client == null) {
-            mJourneyLogger.setAborted(JourneyLogger.ABORT_REASON_INVALID_DATA_FROM_RENDERER);
+            mJourneyLogger.setAborted(AbortReason.INVALID_DATA_FROM_RENDERER);
             disconnectFromClientWithDebugMessage("Invalid mojo client");
             return;
         }
@@ -421,7 +421,7 @@
         mMethodData = new HashMap<>();
 
         if (!OriginSecurityChecker.isOriginSecure(mWebContents.getLastCommittedUrl())) {
-            mJourneyLogger.setAborted(JourneyLogger.ABORT_REASON_INVALID_DATA_FROM_RENDERER);
+            mJourneyLogger.setAborted(AbortReason.INVALID_DATA_FROM_RENDERER);
             disconnectFromClientWithDebugMessage("Not in a secure context");
             return;
         }
@@ -456,7 +456,7 @@
 
         mMethodData = getValidatedMethodData(methodData, mCardEditor);
         if (mMethodData == null) {
-            mJourneyLogger.setAborted(JourneyLogger.ABORT_REASON_INVALID_DATA_FROM_RENDERER);
+            mJourneyLogger.setAborted(AbortReason.INVALID_DATA_FROM_RENDERER);
             disconnectFromClientWithDebugMessage("Invalid payment methods or data");
             return;
         }
@@ -464,7 +464,7 @@
         if (!parseAndValidateDetailsOrDisconnectFromClient(details)) return;
 
         if (mRawTotal == null) {
-            mJourneyLogger.setAborted(JourneyLogger.ABORT_REASON_INVALID_DATA_FROM_RENDERER);
+            mJourneyLogger.setAborted(AbortReason.INVALID_DATA_FROM_RENDERER);
             disconnectFromClientWithDebugMessage("Missing total");
             return;
         }
@@ -567,8 +567,7 @@
         }
 
         // Log the number of suggested shipping addresses.
-        mJourneyLogger.setNumberOfSuggestionsShown(
-                JourneyLogger.SECTION_SHIPPING_ADDRESS, addresses.size());
+        mJourneyLogger.setNumberOfSuggestionsShown(Section.SHIPPING_ADDRESS, addresses.size());
 
         // Automatically select the first address if one is complete and if the merchant does
         // not require a shipping address to calculate shipping costs.
@@ -597,7 +596,7 @@
             // Can be triggered only by a compromised renderer. In normal operation, calling show()
             // twice on the same instance of PaymentRequest in JavaScript is rejected at the
             // renderer level.
-            mJourneyLogger.setAborted(JourneyLogger.ABORT_REASON_INVALID_DATA_FROM_RENDERER);
+            mJourneyLogger.setAborted(AbortReason.INVALID_DATA_FROM_RENDERER);
             disconnectFromClientWithDebugMessage("Renderer should never invoke show() twice");
             return;
         }
@@ -606,7 +605,7 @@
             // The renderer can create multiple instances of PaymentRequest and call show() on each
             // one. Only the first one will be shown. This also prevents multiple tabs and windows
             // from showing PaymentRequest UI at the same time.
-            mJourneyLogger.setNotShown(JourneyLogger.NO_SHOW_CONCURRENT_REQUESTS);
+            mJourneyLogger.setNotShown(NotShownReason.CONCURRENT_REQUESTS);
             disconnectFromClientWithDebugMessage("A PaymentRequest UI is already showing");
             if (sObserverForTest != null) sObserverForTest.onPaymentRequestServiceShowFailed();
             return;
@@ -617,7 +616,7 @@
 
         ChromeActivity chromeActivity = ChromeActivity.fromWebContents(mWebContents);
         if (chromeActivity == null) {
-            mJourneyLogger.setNotShown(JourneyLogger.NO_SHOW_REASON_OTHER);
+            mJourneyLogger.setNotShown(NotShownReason.OTHER);
             disconnectFromClientWithDebugMessage("Unable to find Chrome activity");
             if (sObserverForTest != null) sObserverForTest.onPaymentRequestServiceShowFailed();
             return;
@@ -645,7 +644,7 @@
 
             mDidRecordShowEvent = true;
             mShouldRecordAbortReason = true;
-            mJourneyLogger.setEventOccurred(JourneyLogger.EVENT_SKIPPED_SHOW);
+            mJourneyLogger.setEventOccurred(Event.SKIPPED_SHOW);
             mJourneyLogger.setShowCalled();
 
             onPayClicked(null /* selectedShippingAddress */, null /* selectedShippingOption */,
@@ -745,7 +744,7 @@
         if (mClient == null) return;
 
         if (mUI == null) {
-            mJourneyLogger.setAborted(JourneyLogger.ABORT_REASON_INVALID_DATA_FROM_RENDERER);
+            mJourneyLogger.setAborted(AbortReason.INVALID_DATA_FROM_RENDERER);
             disconnectFromClientWithDebugMessage(
                     "PaymentRequestUpdateEvent.updateWith() called without PaymentRequest.show()");
             return;
@@ -778,7 +777,7 @@
      */
     private boolean parseAndValidateDetailsOrDisconnectFromClient(PaymentDetails details) {
         if (!PaymentValidator.validatePaymentDetails(details)) {
-            mJourneyLogger.setAborted(JourneyLogger.ABORT_REASON_INVALID_DATA_FROM_RENDERER);
+            mJourneyLogger.setAborted(AbortReason.INVALID_DATA_FROM_RENDERER);
             disconnectFromClientWithDebugMessage("Invalid payment details");
             return false;
         }
@@ -993,7 +992,7 @@
         if (!mDidRecordShowEvent) {
             mDidRecordShowEvent = true;
             mShouldRecordAbortReason = true;
-            mJourneyLogger.setEventOccurred(JourneyLogger.EVENT_SHOWN);
+            mJourneyLogger.setEventOccurred(Event.SHOWN);
             mJourneyLogger.setShowCalled();
         }
     }
@@ -1035,7 +1034,7 @@
         if (optionType == PaymentRequestUI.TYPE_SHIPPING_ADDRESSES) {
             assert option instanceof AutofillAddress;
             // Log the change of shipping address.
-            mJourneyLogger.incrementSelectionChanges(JourneyLogger.SECTION_SHIPPING_ADDRESS);
+            mJourneyLogger.incrementSelectionChanges(Section.SHIPPING_ADDRESS);
             AutofillAddress address = (AutofillAddress) option;
             if (address.isComplete()) {
                 mShippingAddressesSection.setSelectedItem(option);
@@ -1054,7 +1053,7 @@
         } else if (optionType == PaymentRequestUI.TYPE_CONTACT_DETAILS) {
             assert option instanceof AutofillContact;
             // Log the change of contact info.
-            mJourneyLogger.incrementSelectionChanges(JourneyLogger.SECTION_CONTACT_INFO);
+            mJourneyLogger.incrementSelectionChanges(Section.CONTACT_INFO);
             AutofillContact contact = (AutofillContact) option;
 
             if (contact.isComplete()) {
@@ -1067,7 +1066,7 @@
             assert option instanceof PaymentInstrument;
             if (option instanceof AutofillPaymentInstrument) {
                 // Log the change of credit card.
-                mJourneyLogger.incrementSelectionChanges(JourneyLogger.SECTION_CREDIT_CARDS);
+                mJourneyLogger.incrementSelectionChanges(Section.CREDIT_CARDS);
                 AutofillPaymentInstrument card = (AutofillPaymentInstrument) option;
 
                 if (!card.isComplete()) {
@@ -1118,17 +1117,17 @@
             editAddress(null);
             mPaymentInformationCallback = callback;
             // Log the add of shipping address.
-            mJourneyLogger.incrementSelectionAdds(JourneyLogger.SECTION_SHIPPING_ADDRESS);
+            mJourneyLogger.incrementSelectionAdds(Section.SHIPPING_ADDRESS);
             return PaymentRequestUI.SELECTION_RESULT_ASYNCHRONOUS_VALIDATION;
         } else if (optionType == PaymentRequestUI.TYPE_CONTACT_DETAILS) {
             editContact(null);
             // Log the add of contact info.
-            mJourneyLogger.incrementSelectionAdds(JourneyLogger.SECTION_CONTACT_INFO);
+            mJourneyLogger.incrementSelectionAdds(Section.CONTACT_INFO);
             return PaymentRequestUI.SELECTION_RESULT_EDITOR_LAUNCH;
         } else if (optionType == PaymentRequestUI.TYPE_PAYMENT_METHODS) {
             editCard(null);
             // Log the add of credit card.
-            mJourneyLogger.incrementSelectionAdds(JourneyLogger.SECTION_CREDIT_CARDS);
+            mJourneyLogger.incrementSelectionAdds(Section.CREDIT_CARDS);
             return PaymentRequestUI.SELECTION_RESULT_EDITOR_LAUNCH;
         }
 
@@ -1138,7 +1137,7 @@
     private void editAddress(final AutofillAddress toEdit) {
         if (toEdit != null) {
             // Log the edit of a shipping address.
-            mJourneyLogger.incrementSelectionEdits(JourneyLogger.SECTION_SHIPPING_ADDRESS);
+            mJourneyLogger.incrementSelectionEdits(Section.SHIPPING_ADDRESS);
         }
         mAddressEditor.edit(toEdit, new Callback<AutofillAddress>() {
             @Override
@@ -1186,7 +1185,7 @@
     private void editContact(final AutofillContact toEdit) {
         if (toEdit != null) {
             // Log the edit of a contact info.
-            mJourneyLogger.incrementSelectionEdits(JourneyLogger.SECTION_CONTACT_INFO);
+            mJourneyLogger.incrementSelectionEdits(Section.CONTACT_INFO);
         }
         mContactEditor.edit(toEdit, new Callback<AutofillContact>() {
             @Override
@@ -1219,7 +1218,7 @@
     private void editCard(final AutofillPaymentInstrument toEdit) {
         if (toEdit != null) {
             // Log the edit of a credit card.
-            mJourneyLogger.incrementSelectionEdits(JourneyLogger.SECTION_CREDIT_CARDS);
+            mJourneyLogger.incrementSelectionEdits(Section.CREDIT_CARDS);
         }
         mCardEditor.edit(toEdit, new Callback<AutofillPaymentInstrument>() {
             @Override
@@ -1292,13 +1291,13 @@
                 mCertificateChain, Collections.unmodifiableMap(methodData), mRawTotal,
                 mRawLineItems, Collections.unmodifiableMap(modifiers), this);
 
-        mJourneyLogger.setEventOccurred(JourneyLogger.EVENT_PAY_CLICKED);
+        mJourneyLogger.setEventOccurred(Event.PAY_CLICKED);
         return !(instrument instanceof AutofillPaymentInstrument);
     }
 
     @Override
     public void onDismiss() {
-        mJourneyLogger.setAborted(JourneyLogger.ABORT_REASON_ABORTED_BY_USER);
+        mJourneyLogger.setAborted(AbortReason.ABORTED_BY_USER);
         disconnectFromClientWithDebugMessage("Dialog dismissed");
     }
 
@@ -1325,7 +1324,7 @@
         } else {
             closeClient();
             closeUI(true);
-            mJourneyLogger.setAborted(JourneyLogger.ABORT_REASON_ABORTED_BY_MERCHANT);
+            mJourneyLogger.setAborted(AbortReason.ABORTED_BY_MERCHANT);
         }
     }
 
@@ -1357,7 +1356,7 @@
     public void onCardAndAddressSettingsClicked() {
         Context context = ChromeActivity.fromWebContents(mWebContents);
         if (context == null) {
-            mJourneyLogger.setAborted(JourneyLogger.ABORT_REASON_OTHER);
+            mJourneyLogger.setAborted(AbortReason.OTHER);
             disconnectFromClientWithDebugMessage("Unable to find Chrome activity");
             return;
         }
@@ -1365,7 +1364,7 @@
         Intent intent = PreferencesLauncher.createIntentForSettingsPage(
                 context, AutofillAndPaymentsPreferences.class.getName());
         context.startActivity(intent);
-        mJourneyLogger.setAborted(JourneyLogger.ABORT_REASON_ABORTED_BY_USER);
+        mJourneyLogger.setAborted(AbortReason.ABORTED_BY_USER);
         disconnectFromClientWithDebugMessage("Card and address settings clicked");
     }
 
@@ -1456,7 +1455,7 @@
         if (mClient == null) return;
         closeClient();
         closeUI(true);
-        mJourneyLogger.setAborted(JourneyLogger.ABORT_REASON_MOJO_RENDERER_CLOSING);
+        mJourneyLogger.setAborted(AbortReason.MOJO_RENDERER_CLOSING);
     }
 
     /**
@@ -1467,7 +1466,7 @@
         if (mClient == null) return;
         closeClient();
         closeUI(true);
-        mJourneyLogger.setAborted(JourneyLogger.ABORT_REASON_MOJO_CONNECTION_ERROR);
+        mJourneyLogger.setAborted(AbortReason.MOJO_CONNECTION_ERROR);
     }
 
     /**
@@ -1539,7 +1538,7 @@
 
         // Log the number of suggested credit cards.
         mJourneyLogger.setNumberOfSuggestionsShown(
-                JourneyLogger.SECTION_CREDIT_CARDS, mPendingAutofillInstruments.size());
+                Section.CREDIT_CARDS, mPendingAutofillInstruments.size());
 
         // Possibly pre-select the first instrument on the list.
         int selection = SectionInformation.NO_SELECTION;
@@ -1596,8 +1595,8 @@
             // add credit cards, but the merchant does not support them either. The payment request
             // must be rejected.
             mJourneyLogger.setNotShown(mArePaymentMethodsSupported
-                            ? JourneyLogger.NO_SHOW_NO_MATCHING_PAYMENT_METHOD
-                            : JourneyLogger.NO_SHOW_NO_SUPPORTED_PAYMENT_METHOD);
+                            ? NotShownReason.NO_MATCHING_PAYMENT_METHOD
+                            : NotShownReason.NO_SUPPORTED_PAYMENT_METHOD);
             disconnectFromClientWithDebugMessage("Requested payment methods have no instruments",
                     mIsIncognito ? PaymentErrorReason.USER_CANCEL
                                  : PaymentErrorReason.NOT_SUPPORTED);
@@ -1629,21 +1628,21 @@
                         selectedPaymentMethod.getIdentifier());
             }
             PaymentRequestMetrics.recordSelectedPaymentMethodHistogram(
-                    PaymentRequestMetrics.SELECTED_METHOD_CREDIT_CARD);
+                    SelectedPaymentMethod.CREDIT_CARD);
         } else if (methodName.equals(ANDROID_PAY_METHOD_NAME)
                 || methodName.equals(PAY_WITH_GOOGLE_METHOD_NAME)) {
             PaymentRequestMetrics.recordSelectedPaymentMethodHistogram(
-                    PaymentRequestMetrics.SELECTED_METHOD_ANDROID_PAY);
+                    SelectedPaymentMethod.ANDROID_PAY);
         } else {
             PaymentRequestMetrics.recordSelectedPaymentMethodHistogram(
-                    PaymentRequestMetrics.SELECTED_METHOD_OTHER_PAYMENT_APP);
+                    SelectedPaymentMethod.OTHER_PAYMENT_APP);
         }
 
         // Showing the payment request UI if we were previously skipping it so the loading
         // spinner shows up until the merchant notifies that payment was completed.
         if (mShouldSkipShowingPaymentRequestUi) mUI.showProcessingMessageAfterUiSkip();
 
-        mJourneyLogger.setEventOccurred(JourneyLogger.EVENT_RECEIVED_INSTRUMENT_DETAILS);
+        mJourneyLogger.setEventOccurred(Event.RECEIVED_INSTRUMENT_DETAILS);
 
         mPaymentResponseHelper.onInstrumentDetailsReceived(methodName, stringifiedDetails);
     }
@@ -1696,7 +1695,7 @@
 
         // Can happen if the tab is closed during the normalization process.
         if (chromeActivity == null) {
-            mJourneyLogger.setAborted(JourneyLogger.ABORT_REASON_OTHER);
+            mJourneyLogger.setAborted(AbortReason.OTHER);
             disconnectFromClientWithDebugMessage("Unable to find Chrome activity");
             if (sObserverForTest != null) sObserverForTest.onPaymentRequestServiceShowFailed();
             return;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/payments/PaymentRequestMetrics.java b/chrome/android/java/src/org/chromium/chrome/browser/payments/PaymentRequestMetrics.java
index 7888cf2..be85cca5 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/payments/PaymentRequestMetrics.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/payments/PaymentRequestMetrics.java
@@ -4,38 +4,12 @@
 
 package org.chromium.chrome.browser.payments;
 
-import org.chromium.base.VisibleForTesting;
 import org.chromium.base.metrics.RecordHistogram;
 
 /**
  * A class used to record metrics for the Payment Request feature.
  */
 public final class PaymentRequestMetrics {
-
-    // PaymentRequestRequestedInformation defined in tools/metrics/histograms/histograms.xml.
-    @VisibleForTesting
-    public static final int REQUESTED_INFORMATION_NONE = 0;
-    @VisibleForTesting
-    public static final int REQUESTED_INFORMATION_EMAIL = 1 << 0;
-    @VisibleForTesting
-    public static final int REQUESTED_INFORMATION_PHONE = 1 << 1;
-    @VisibleForTesting
-    public static final int REQUESTED_INFORMATION_SHIPPING = 1 << 2;
-    @VisibleForTesting
-    public static final int REQUESTED_INFORMATION_NAME = 1 << 3;
-    @VisibleForTesting
-    public static final int REQUESTED_INFORMATION_MAX = 16;
-
-    // PaymentRequestPaymentMethods defined in tools/metrics/histograms/histograms.xml.
-    @VisibleForTesting
-    public static final int SELECTED_METHOD_CREDIT_CARD = 0;
-    @VisibleForTesting
-    public static final int SELECTED_METHOD_ANDROID_PAY = 1;
-    @VisibleForTesting
-    public static final int SELECTED_METHOD_OTHER_PAYMENT_APP = 2;
-    @VisibleForTesting
-    public static final int SELECTED_METHOD_MAX = 3;
-
     // There should be no instance of PaymentRequestMetrics created.
     private PaymentRequestMetrics() {}
 
@@ -50,13 +24,12 @@
      */
     public static void recordRequestedInformationHistogram(boolean requestEmail,
             boolean requestPhone, boolean requestShipping, boolean requestName) {
-        int requestInformation =
-                (requestEmail ? REQUESTED_INFORMATION_EMAIL : 0)
-                | (requestPhone ? REQUESTED_INFORMATION_PHONE : 0)
-                | (requestShipping ? REQUESTED_INFORMATION_SHIPPING : 0)
-                | (requestName ? REQUESTED_INFORMATION_NAME : 0);
+        int requestInformation = (requestEmail ? RequestedInformation.EMAIL : 0)
+                | (requestPhone ? RequestedInformation.PHONE : 0)
+                | (requestShipping ? RequestedInformation.SHIPPING : 0)
+                | (requestName ? RequestedInformation.NAME : 0);
         RecordHistogram.recordEnumeratedHistogram("PaymentRequest.RequestedInformation",
-                requestInformation, REQUESTED_INFORMATION_MAX);
+                requestInformation, RequestedInformation.MAX);
     }
 
     /*
@@ -66,8 +39,8 @@
      * @param paymentMethod The payment method that was used to complete the current transaction.
      */
     public static void recordSelectedPaymentMethodHistogram(int paymentMethod) {
-        assert paymentMethod < SELECTED_METHOD_MAX;
-        RecordHistogram.recordEnumeratedHistogram("PaymentRequest.SelectedPaymentMethod",
-                paymentMethod, SELECTED_METHOD_MAX);
+        assert paymentMethod < SelectedPaymentMethod.MAX;
+        RecordHistogram.recordEnumeratedHistogram(
+                "PaymentRequest.SelectedPaymentMethod", paymentMethod, SelectedPaymentMethod.MAX);
     }
 }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/preferences/ChromePreferenceManager.java b/chrome/android/java/src/org/chromium/chrome/browser/preferences/ChromePreferenceManager.java
index eb5eaa25..c65ad816 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/preferences/ChromePreferenceManager.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/preferences/ChromePreferenceManager.java
@@ -58,6 +58,8 @@
     private static final String SUCCESS_UPLOAD_SUFFIX = "_crash_success_upload";
     private static final String FAILURE_UPLOAD_SUFFIX = "_crash_failure_upload";
 
+    private static final String OMNIBOX_PLACEHOLDER_GROUP = "omnibox-placeholder-group";
+
     private static ChromePreferenceManager sPrefs;
 
     private final SharedPreferences mSharedPreferences;
@@ -419,6 +421,22 @@
     }
 
     /**
+     * Set group of omnibox placeholder experiment
+     * @param group group name of omnibox placeholder experiment
+     */
+    public void setOmniboxPlaceholderGroup(String group) {
+        writeString(OMNIBOX_PLACEHOLDER_GROUP, group);
+    }
+
+    /**
+     * Get group of omnibox placeholder experiment
+     * @return String of omnibox placeholder experiment group name, empty string if not set
+     */
+    public String getOmniboxPlaceholderGroup() {
+        return mSharedPreferences.getString(OMNIBOX_PLACEHOLDER_GROUP, "");
+    }
+
+    /**
      * Writes the given int value to the named shared preference.
      * @param key The name of the preference to modify.
      * @param value The new value for the preference.
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/util/FeatureUtilities.java b/chrome/android/java/src/org/chromium/chrome/browser/util/FeatureUtilities.java
index d4e40032..c21d9c7 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/util/FeatureUtilities.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/util/FeatureUtilities.java
@@ -27,6 +27,7 @@
 import org.chromium.chrome.browser.ChromeFeatureList;
 import org.chromium.chrome.browser.ChromeSwitches;
 import org.chromium.chrome.browser.firstrun.FirstRunGlueImpl;
+import org.chromium.chrome.browser.omnibox.OmniboxPlaceholderFieldTrial;
 import org.chromium.chrome.browser.preferences.ChromePreferenceManager;
 import org.chromium.chrome.browser.tabmodel.DocumentModeAssassin;
 import org.chromium.chrome.browser.webapps.ChromeWebApkHost;
@@ -189,6 +190,7 @@
         ChromeWebApkHost.cacheEnabledStateForNextLaunch();
         cacheChromeHomeEnabled();
         FirstRunGlueImpl.cacheFirstRunPrefs();
+        OmniboxPlaceholderFieldTrial.cacheOmniboxPlaceholderGroup();
     }
 
     /**
@@ -268,6 +270,7 @@
      * @return Whether or not the expand button for Chrome Home is enabled.
      */
     public static boolean isChromeHomeExpandButtonEnabled() {
+        if (!ChromeFeatureList.isInitialized()) return false;
         return ChromeFeatureList.isEnabled(ChromeFeatureList.CHROME_HOME_EXPAND_BUTTON);
     }
 
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebApkDisclosureNotificationManager.java b/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebApkDisclosureNotificationManager.java
index ea3f5566..b010f1db 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebApkDisclosureNotificationManager.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebApkDisclosureNotificationManager.java
@@ -36,8 +36,10 @@
         Context context = ContextUtils.getApplicationContext();
         String title = webappInfo.shortName();
 
+        // It's okay to not set a valid channelId for web apk notifications because web apks don't
+        // target O yet.
         StandardNotificationBuilder builder =
-                new StandardNotificationBuilder(context, ChannelDefinitions.CHANNEL_ID_BROWSER);
+                new StandardNotificationBuilder(context, null /* channelId */);
         builder.setTitle(title)
                 .setPriority(Notification.PRIORITY_MIN)
                 .setLargeIcon(BitmapFactory.decodeResource(
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/widget/ToolbarProgressBar.java b/chrome/android/java/src/org/chromium/chrome/browser/widget/ToolbarProgressBar.java
index e1e9319..77b0e8b 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/widget/ToolbarProgressBar.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/widget/ToolbarProgressBar.java
@@ -238,8 +238,6 @@
             mAnimationLogic = new ProgressAnimationFastStart();
         } else if (TextUtils.equals(animation, "linear")) {
             mAnimationLogic = new ProgressAnimationLinear();
-        } else {
-            assert TextUtils.isEmpty(animation) || TextUtils.equals(animation, "disabled");
         }
     }
 
diff --git a/chrome/android/java/strings/android_chrome_strings.grd b/chrome/android/java/strings/android_chrome_strings.grd
index d3c6a62..79c932c 100644
--- a/chrome/android/java/strings/android_chrome_strings.grd
+++ b/chrome/android/java/strings/android_chrome_strings.grd
@@ -2512,6 +2512,26 @@
         Offline
       </message>
 
+      <!-- Omnibox Placeholder Experiment -->
+      <message name="IDS_SEARCH_OR_TYPE_WEBSITE_NAME" desc="Prompt to enter text into the text field that will either perform web searches or navigate to a URL. [CHAR-LIMIT=38]">
+        Search or type website name
+      </message>
+      <message name="IDS_SEARCH_THE_WEB" desc="Prompt to enter text into the text field that will either perform web searches or navigate to a URL. [CHAR-LIMIT=38]">
+        Search the web
+      </message>
+      <message name="IDS_ENTER_A_SEARCH_OR_WEBSITE" desc="Prompt to enter text into the text field that will either perform web searches or navigate to a URL. [CHAR-LIMIT=38]">
+        Enter a search or website
+      </message>
+      <message name="IDS_SEARCH_NEWS" desc="Prompt to enter text into the text field that will either perform web searches or navigate to a URL, with a suggestion of searching news. [CHAR-LIMIT=38]">
+        Search… news
+      </message>
+      <message name="IDS_SEARCH_RECIPES" desc="Prompt to enter text into the text field that will either perform web searches or navigate to a URL, with a suggestion of searching recipes. [CHAR-LIMIT=38]">
+        Search… recipes
+      </message>
+      <message name="IDS_SEARCH_WEATHER" desc="Prompt to enter text into the text field that will either perform web searches or navigate to a URL, with a suggestion of searching weather. [CHAR-LIMIT=38]">
+        Search… weather
+      </message>
+
       <!-- Voice search -->
       <message name="IDS_VOICE_SEARCH_ERROR" desc="Toast when the voice search activity couldn't be started. [CHAR-LIMIT=40]">
         No enabled voice search available
diff --git a/chrome/android/java_sources.gni b/chrome/android/java_sources.gni
index 063d23ff..6d89300a 100644
--- a/chrome/android/java_sources.gni
+++ b/chrome/android/java_sources.gni
@@ -727,6 +727,7 @@
   "java/src/org/chromium/chrome/browser/omnibox/SuggestionAnswer.java",
   "java/src/org/chromium/chrome/browser/omnibox/SuggestionView.java",
   "java/src/org/chromium/chrome/browser/omnibox/UrlBar.java",
+  "java/src/org/chromium/chrome/browser/omnibox/OmniboxPlaceholderFieldTrial.java",
   "java/src/org/chromium/chrome/browser/omnibox/UrlFocusChangeListener.java",
   "java/src/org/chromium/chrome/browser/omnibox/VoiceSuggestionProvider.java",
   "java/src/org/chromium/chrome/browser/omnibox/geo/GeolocationHeader.java",
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/SelectFileDialogTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/SelectFileDialogTest.java
index 8942422..a86161cc 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/SelectFileDialogTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/SelectFileDialogTest.java
@@ -210,6 +210,7 @@
 
     @Test
     @MediumTest
+    @DisabledTest
     public void testPhotoPickerLaunchAndMimeTypes() throws Throwable {
         assertEquals("", SelectFileDialog.ensureMimeType(""));
         assertEquals("image/jpeg", SelectFileDialog.ensureMimeType(".jpg"));
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/instantapps/InstantAppsHandlerTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/instantapps/InstantAppsHandlerTest.java
index 1e0d714..a9921183 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/instantapps/InstantAppsHandlerTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/instantapps/InstantAppsHandlerTest.java
@@ -29,9 +29,9 @@
 import org.chromium.chrome.browser.ChromeSwitches;
 import org.chromium.chrome.browser.IntentHandler;
 import org.chromium.chrome.browser.ShortcutHelper;
+import org.chromium.chrome.browser.tab.Tab;
 import org.chromium.chrome.test.ChromeActivityTestRule;
 import org.chromium.chrome.test.ChromeJUnit4ClassRunner;
-import org.chromium.content_public.browser.WebContents;
 
 /**
  * Unit tests for {@link InstantAppsHandler}.
@@ -172,12 +172,9 @@
         ThreadUtils.runOnUiThreadBlocking(new Runnable() {
             @Override
             public void run() {
-                Assert.assertFalse(
-                        mHandler.handleNavigation(mContext, INSTANT_APP_URL, REFERRER_URI,
-                                mActivityTestRule.getActivity()
-                                        .getTabModelSelector()
-                                        .getCurrentTab()
-                                        .getWebContents()));
+                Assert.assertFalse(mHandler.handleNavigation(mContext, INSTANT_APP_URL,
+                        REFERRER_URI,
+                        mActivityTestRule.getActivity().getTabModelSelector().getCurrentTab()));
             }
         });
         Assert.assertFalse(mHandler.mLaunchInstantApp);
@@ -223,10 +220,7 @@
             @Override
             public void run() {
                 Assert.assertTrue(mHandler.handleNavigation(mContext, INSTANT_APP_URL, REFERRER_URI,
-                        mActivityTestRule.getActivity()
-                                .getTabModelSelector()
-                                .getCurrentTab()
-                                .getWebContents()));
+                        mActivityTestRule.getActivity().getTabModelSelector().getCurrentTab()));
             }
         });
         Assert.assertFalse(mHandler.mStartedAsyncCall);
@@ -252,8 +246,8 @@
         }
 
         @Override
-        protected boolean startCheckForInstantApps(Context context, String url, Uri referrer,
-                WebContents webContents) {
+        protected boolean startCheckForInstantApps(
+                Context context, String url, Uri referrer, Tab tab) {
             mStartedAsyncCall = true;
             return false;
         }
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/notifications/CustomNotificationBuilderTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/notifications/CustomNotificationBuilderTest.java
index e4683ae..aed64582 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/notifications/CustomNotificationBuilderTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/notifications/CustomNotificationBuilderTest.java
@@ -35,6 +35,7 @@
 import org.chromium.base.test.util.Feature;
 import org.chromium.base.test.util.MinAndroidSdkLevel;
 import org.chromium.chrome.R;
+import org.chromium.chrome.browser.notifications.channels.ChannelDefinitions;
 import org.chromium.content.browser.test.NativeLibraryTestRule;
 
 import java.util.ArrayList;
@@ -74,24 +75,25 @@
                 new int[] {Color.WHITE}, 1 /* width */, 1 /* height */, Bitmap.Config.ARGB_8888);
         actionIcon = actionIcon.copy(Bitmap.Config.ARGB_8888, true /* isMutable */);
 
-        Notification notification = new CustomNotificationBuilder(context)
-                                            .setSmallIcon(R.drawable.ic_chrome)
-                                            .setLargeIcon(largeIcon)
-                                            .setTitle("title")
-                                            .setBody("body")
-                                            .setOrigin("origin")
-                                            .setTicker("ticker")
-                                            .setDefaults(Notification.DEFAULT_ALL)
-                                            .setVibrate(new long[] {100L})
-                                            .setContentIntent(contentIntent)
-                                            .setDeleteIntent(deleteIntent)
-                                            .addButtonAction(actionIcon, "button",
-                                                    createIntent(context, "ActionButtonOne"))
-                                            .addButtonAction(actionIcon, "button",
-                                                    createIntent(context, "ActionButtonTwo"))
-                                            .addSettingsAction(0 /* iconId */, "settings",
-                                                    createIntent(context, "SettingsButton"))
-                                            .build();
+        Notification notification =
+                new CustomNotificationBuilder(context, ChannelDefinitions.CHANNEL_ID_SITES)
+                        .setSmallIcon(R.drawable.ic_chrome)
+                        .setLargeIcon(largeIcon)
+                        .setTitle("title")
+                        .setBody("body")
+                        .setOrigin("origin")
+                        .setTicker("ticker")
+                        .setDefaults(Notification.DEFAULT_ALL)
+                        .setVibrate(new long[] {100L})
+                        .setContentIntent(contentIntent)
+                        .setDeleteIntent(deleteIntent)
+                        .addButtonAction(
+                                actionIcon, "button", createIntent(context, "ActionButtonOne"))
+                        .addButtonAction(
+                                actionIcon, "button", createIntent(context, "ActionButtonTwo"))
+                        .addSettingsAction(
+                                0 /* iconId */, "settings", createIntent(context, "SettingsButton"))
+                        .build();
 
         assertSmallNotificationIconAsExpected(context, notification, smallIcon);
         assertLargeNotificationIconAsExpected(context, notification, largeIcon);
@@ -144,7 +146,8 @@
     @Feature({"Browser", "Notifications"})
     public void testZeroActionButtons() {
         Context context = InstrumentationRegistry.getInstrumentation().getTargetContext();
-        Notification notification = new CustomNotificationBuilder(context).build();
+        Notification notification =
+                new CustomNotificationBuilder(context, ChannelDefinitions.CHANNEL_ID_SITES).build();
         View bigView = notification.bigContentView.apply(context, new LinearLayout(context));
         ArrayList<View> buttons = new ArrayList<>();
         bigView.findViewsWithText(buttons, "button", View.FIND_VIEWS_WITH_TEXT);
@@ -160,11 +163,12 @@
     @Feature({"Browser", "Notifications"})
     public void testMaxActionButtons() {
         Context context = InstrumentationRegistry.getInstrumentation().getTargetContext();
-        NotificationBuilderBase builder = new CustomNotificationBuilder(context)
-                                                  .addButtonAction(null /* iconBitmap */, "button",
-                                                          createIntent(context, "ActionButtonOne"))
-                                                  .addButtonAction(null /* iconBitmap */, "button",
-                                                          createIntent(context, "ActionButtonTwo"));
+        NotificationBuilderBase builder =
+                new CustomNotificationBuilder(context, ChannelDefinitions.CHANNEL_ID_SITES)
+                        .addButtonAction(null /* iconBitmap */, "button",
+                                createIntent(context, "ActionButtonOne"))
+                        .addButtonAction(null /* iconBitmap */, "button",
+                                createIntent(context, "ActionButtonTwo"));
         try {
             builder.addButtonAction(
                     null /* iconBitmap */, "button", createIntent(context, "ActionButtonThree"));
@@ -199,12 +203,13 @@
                 new int[] {Color.RED}, 1 /* width */, 1 /* height */, Bitmap.Config.ARGB_8888);
         actionIcon = actionIcon.copy(Bitmap.Config.ARGB_8888, true /* isMutable */);
 
-        Notification notification = new CustomNotificationBuilder(context)
-                                            .setLargeIcon(largeIcon)
-                                            .setSmallIcon(smallIcon)
-                                            .addButtonAction(actionIcon, "button",
-                                                    createIntent(context, "ActionButton"))
-                                            .build();
+        Notification notification =
+                new CustomNotificationBuilder(context, ChannelDefinitions.CHANNEL_ID_SITES)
+                        .setLargeIcon(largeIcon)
+                        .setSmallIcon(smallIcon)
+                        .addButtonAction(
+                                actionIcon, "button", createIntent(context, "ActionButton"))
+                        .build();
 
         // The large icon should be unchanged.
         assertLargeNotificationIconAsExpected(context, notification, largeIcon);
@@ -229,7 +234,7 @@
         Context context = InstrumentationRegistry.getInstrumentation().getTargetContext();
         int maxLength = CustomNotificationBuilder.MAX_CHARSEQUENCE_LENGTH;
         Notification notification =
-                new CustomNotificationBuilder(context)
+                new CustomNotificationBuilder(context, ChannelDefinitions.CHANNEL_ID_SITES)
                         .setTitle(createString('a', maxLength + 1))
                         .setBody(createString('b', maxLength + 1))
                         .setOrigin(createString('c', maxLength + 1))
@@ -285,7 +290,8 @@
     public void testGeneratesLargeIconFromOriginWhenNoLargeIconProvided() {
         Context context = InstrumentationRegistry.getInstrumentation().getTargetContext();
         NotificationBuilderBase notificationBuilder =
-                new CustomNotificationBuilder(context).setOrigin("https://www.google.com");
+                new CustomNotificationBuilder(context, ChannelDefinitions.CHANNEL_ID_SITES)
+                        .setOrigin("https://www.google.com");
 
         Notification notification = notificationBuilder.build();
 
@@ -300,9 +306,10 @@
     @Feature({"Browser", "Notifications"})
     public void testGeneratesLargeIconFromOriginWhenLargeIconProvidedIsNull() {
         Context context = InstrumentationRegistry.getInstrumentation().getTargetContext();
-        NotificationBuilderBase notificationBuilder = new CustomNotificationBuilder(context)
-                                                              .setOrigin("https://www.chromium.org")
-                                                              .setLargeIcon(null);
+        NotificationBuilderBase notificationBuilder =
+                new CustomNotificationBuilder(context, ChannelDefinitions.CHANNEL_ID_SITES)
+                        .setOrigin("https://www.chromium.org")
+                        .setLargeIcon(null);
 
         Notification notification = notificationBuilder.build();
 
@@ -325,8 +332,9 @@
     @Feature({"Browser", "Notifications"})
     public void testAddTextActionSetsRemoteInput() {
         Context context = InstrumentationRegistry.getInstrumentation().getTargetContext();
-        NotificationBuilderBase notificationBuilder = new CustomNotificationBuilder(
-                context).addTextAction(null, "Action Title", null, "Placeholder");
+        NotificationBuilderBase notificationBuilder =
+                new CustomNotificationBuilder(context, ChannelDefinitions.CHANNEL_ID_SITES)
+                        .addTextAction(null, "Action Title", null, "Placeholder");
 
         Notification notification = notificationBuilder.build();
 
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestCanMakePaymentMetricsTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestCanMakePaymentMetricsTest.java
index 8e03288d..f2812ee 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestCanMakePaymentMetricsTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestCanMakePaymentMetricsTest.java
@@ -81,20 +81,20 @@
         Assert.assertEquals(1,
                 RecordHistogram.getHistogramValueCountForTesting(
                         "PaymentRequest.CanMakePayment.Usage",
-                        JourneyLogger.CAN_MAKE_PAYMENT_USED));
+                        CanMakePaymentUsage.CAN_MAKE_PAYMENT_USED));
 
         // The CanMakePayment effect on show should be recorded as being false and shown.
         Assert.assertEquals(1,
                 RecordHistogram.getHistogramValueCountForTesting(
                         "PaymentRequest.CanMakePayment.Used.EffectOnShow",
-                        JourneyLogger.CMP_SHOW_DID_SHOW));
+                        CanMakePaymentEffectOnShow.DID_SHOW));
 
         // There should be a record for an abort when CanMakePayment is false but the PR is shown to
         // the user.
         Assert.assertEquals(1,
                 RecordHistogram.getHistogramValueCountForTesting(
                         "PaymentRequest.CanMakePayment.Used.FalseWithShowEffectOnCompletion",
-                        JourneyLogger.COMPLETION_STATUS_USER_ABORTED));
+                        CompletionStatus.USER_ABORTED));
     }
 
     /**
@@ -133,20 +133,20 @@
         Assert.assertEquals(1,
                 RecordHistogram.getHistogramValueCountForTesting(
                         "PaymentRequest.CanMakePayment.Usage",
-                        JourneyLogger.CAN_MAKE_PAYMENT_USED));
+                        CanMakePaymentUsage.CAN_MAKE_PAYMENT_USED));
 
         // The CanMakePayment effect on show should be recorded as being false and shown.
         Assert.assertEquals(1,
                 RecordHistogram.getHistogramValueCountForTesting(
                         "PaymentRequest.CanMakePayment.Used.EffectOnShow",
-                        JourneyLogger.CMP_SHOW_DID_SHOW));
+                        CanMakePaymentEffectOnShow.DID_SHOW));
 
         // There should be a record for a completion when CanMakePayment is false but the PR is
         // shown to the user.
         Assert.assertEquals(1,
                 RecordHistogram.getHistogramValueCountForTesting(
                         "PaymentRequest.CanMakePayment.Used.FalseWithShowEffectOnCompletion",
-                        JourneyLogger.COMPLETION_STATUS_COMPLETED));
+                        CompletionStatus.COMPLETED));
     }
 
     /**
@@ -174,21 +174,21 @@
         Assert.assertEquals(1,
                 RecordHistogram.getHistogramValueCountForTesting(
                         "PaymentRequest.CanMakePayment.Usage",
-                        JourneyLogger.CAN_MAKE_PAYMENT_USED));
+                        CanMakePaymentUsage.CAN_MAKE_PAYMENT_USED));
 
         // The CanMakePayment effect on show should be recorded as being false and shown.
         Assert.assertEquals(1,
                 RecordHistogram.getHistogramValueCountForTesting(
                         "PaymentRequest.CanMakePayment.Used.EffectOnShow",
-                        JourneyLogger.CMP_SHOW_DID_SHOW
-                                | JourneyLogger.CMP_SHOW_COULD_MAKE_PAYMENT));
+                        CanMakePaymentEffectOnShow.DID_SHOW
+                                | CanMakePaymentEffectOnShow.COULD_MAKE_PAYMENT));
 
         // There should be a record for an abort when CanMakePayment is false but the PR is shown to
         // the user.
         Assert.assertEquals(1,
                 RecordHistogram.getHistogramValueCountForTesting(
                         "PaymentRequest.CanMakePayment.Used.TrueWithShowEffectOnCompletion",
-                        JourneyLogger.COMPLETION_STATUS_OTHER_ABORTED));
+                        CompletionStatus.OTHER_ABORTED));
     }
 
     /**
@@ -214,21 +214,21 @@
         Assert.assertEquals(1,
                 RecordHistogram.getHistogramValueCountForTesting(
                         "PaymentRequest.CanMakePayment.Usage",
-                        JourneyLogger.CAN_MAKE_PAYMENT_USED));
+                        CanMakePaymentUsage.CAN_MAKE_PAYMENT_USED));
 
         // The CanMakePayment effect on show should be recorded as being false and shown.
         Assert.assertEquals(1,
                 RecordHistogram.getHistogramValueCountForTesting(
                         "PaymentRequest.CanMakePayment.Used.EffectOnShow",
-                        JourneyLogger.CMP_SHOW_DID_SHOW
-                                | JourneyLogger.CMP_SHOW_COULD_MAKE_PAYMENT));
+                        CanMakePaymentEffectOnShow.DID_SHOW
+                                | CanMakePaymentEffectOnShow.COULD_MAKE_PAYMENT));
 
         // There should be a record for an abort when CanMakePayment is false but the PR is shown to
         // the user.
         Assert.assertEquals(1,
                 RecordHistogram.getHistogramValueCountForTesting(
                         "PaymentRequest.CanMakePayment.Used.TrueWithShowEffectOnCompletion",
-                        JourneyLogger.COMPLETION_STATUS_COMPLETED));
+                        CompletionStatus.COMPLETED));
     }
 
     /**
@@ -259,14 +259,14 @@
         Assert.assertEquals(1,
                 RecordHistogram.getHistogramValueCountForTesting(
                         "PaymentRequest.CanMakePayment.Usage",
-                        JourneyLogger.CAN_MAKE_PAYMENT_NOT_USED));
+                        CanMakePaymentUsage.CAN_MAKE_PAYMENT_NOT_USED));
 
         // There should be a record for an abort when CanMakePayment is not called but the PR is
         // shown to the user.
         Assert.assertEquals(1,
                 RecordHistogram.getHistogramValueCountForTesting(
                         "PaymentRequest.CanMakePayment.NotUsed.WithShowEffectOnCompletion",
-                        JourneyLogger.COMPLETION_STATUS_USER_ABORTED));
+                        CompletionStatus.USER_ABORTED));
     }
 
     /**
@@ -291,13 +291,13 @@
         Assert.assertEquals(1,
                 RecordHistogram.getHistogramValueCountForTesting(
                         "PaymentRequest.CanMakePayment.Usage",
-                        JourneyLogger.CAN_MAKE_PAYMENT_NOT_USED));
+                        CanMakePaymentUsage.CAN_MAKE_PAYMENT_NOT_USED));
 
         // There should be a record for a completion when CanMakePayment is not called but the PR is
         // shown to the user.
         Assert.assertEquals(1,
                 RecordHistogram.getHistogramValueCountForTesting(
                         "PaymentRequest.CanMakePayment.NotUsed.WithShowEffectOnCompletion",
-                        JourneyLogger.COMPLETION_STATUS_COMPLETED));
+                        CompletionStatus.COMPLETED));
     }
 }
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestContactDetailsAndFreeShippingTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestContactDetailsAndFreeShippingTest.java
index 0e95190a..30376cf 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestContactDetailsAndFreeShippingTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestContactDetailsAndFreeShippingTest.java
@@ -90,18 +90,14 @@
         mPaymentRequestTestRule.triggerUIAndWait(mPaymentRequestTestRule.getReadyToPay());
 
         // Make sure that only the appropriate enum value was logged.
-        for (int i = 0; i < PaymentRequestMetrics.REQUESTED_INFORMATION_MAX; ++i) {
-            Assert.assertEquals(
-                    (i
-                                            == (PaymentRequestMetrics.REQUESTED_INFORMATION_EMAIL
-                                                       | PaymentRequestMetrics
-                                                                 .REQUESTED_INFORMATION_PHONE
-                                                       | PaymentRequestMetrics
-                                                                 .REQUESTED_INFORMATION_SHIPPING
-                                                       | PaymentRequestMetrics
-                                                                 .REQUESTED_INFORMATION_NAME)
-                                    ? 1
-                                    : 0),
+        for (int i = 0; i < RequestedInformation.MAX; ++i) {
+            Assert.assertEquals((i
+                                                        == (RequestedInformation.EMAIL
+                                                                   | RequestedInformation.PHONE
+                                                                   | RequestedInformation.SHIPPING
+                                                                   | RequestedInformation.NAME)
+                                                ? 1
+                                                : 0),
                     RecordHistogram.getHistogramValueCountForTesting(
                             "PaymentRequest.RequestedInformation", i));
         }
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestContactDetailsTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestContactDetailsTest.java
index b786557..30ad561 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestContactDetailsTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestContactDetailsTest.java
@@ -330,16 +330,13 @@
         mPaymentRequestTestRule.triggerUIAndWait(mPaymentRequestTestRule.getReadyToPay());
 
         // Make sure that only the appropriate enum value was logged.
-        for (int i = 0; i < PaymentRequestMetrics.REQUESTED_INFORMATION_MAX; ++i) {
-            Assert.assertEquals(
-                    (i
-                                            == (PaymentRequestMetrics.REQUESTED_INFORMATION_EMAIL
-                                                       | PaymentRequestMetrics
-                                                                 .REQUESTED_INFORMATION_PHONE
-                                                       | PaymentRequestMetrics
-                                                                 .REQUESTED_INFORMATION_NAME)
-                                    ? 1
-                                    : 0),
+        for (int i = 0; i < RequestedInformation.MAX; ++i) {
+            Assert.assertEquals((i
+                                                        == (RequestedInformation.EMAIL
+                                                                   | RequestedInformation.PHONE
+                                                                   | RequestedInformation.NAME)
+                                                ? 1
+                                                : 0),
                     RecordHistogram.getHistogramValueCountForTesting(
                             "PaymentRequest.RequestedInformation", i));
         }
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestEmailAndFreeShippingTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestEmailAndFreeShippingTest.java
index 24e21c71..0b11772 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestEmailAndFreeShippingTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestEmailAndFreeShippingTest.java
@@ -85,14 +85,9 @@
         mPaymentRequestTestRule.triggerUIAndWait(mPaymentRequestTestRule.getReadyToPay());
 
         // Make sure that only the appropriate enum value was logged.
-        for (int i = 0; i < PaymentRequestMetrics.REQUESTED_INFORMATION_MAX; ++i) {
+        for (int i = 0; i < RequestedInformation.MAX; ++i) {
             Assert.assertEquals(
-                    (i
-                                            == (PaymentRequestMetrics.REQUESTED_INFORMATION_EMAIL
-                                                       | PaymentRequestMetrics
-                                                                 .REQUESTED_INFORMATION_SHIPPING)
-                                    ? 1
-                                    : 0),
+                    (i == (RequestedInformation.EMAIL | RequestedInformation.SHIPPING) ? 1 : 0),
                     RecordHistogram.getHistogramValueCountForTesting(
                             "PaymentRequest.RequestedInformation", i));
         }
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestEmailAndPhoneTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestEmailAndPhoneTest.java
index b8dc730..593f2ca00 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestEmailAndPhoneTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestEmailAndPhoneTest.java
@@ -156,11 +156,10 @@
         // Start the Payment Request.
         mPaymentRequestTestRule.triggerUIAndWait(mPaymentRequestTestRule.getReadyToPay());
 
-        int appropriateEnumValue = PaymentRequestMetrics.REQUESTED_INFORMATION_EMAIL
-                | PaymentRequestMetrics.REQUESTED_INFORMATION_PHONE;
+        int appropriateEnumValue = RequestedInformation.EMAIL | RequestedInformation.PHONE;
 
         // Make sure that only the appropriate enum value was logged.
-        for (int i = 0; i < PaymentRequestMetrics.REQUESTED_INFORMATION_MAX; ++i) {
+        for (int i = 0; i < RequestedInformation.MAX; ++i) {
             Assert.assertEquals((i == (appropriateEnumValue) ? 1 : 0),
                     RecordHistogram.getHistogramValueCountForTesting(
                             "PaymentRequest.RequestedInformation", i));
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestEmailTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestEmailTest.java
index a911019c..de6b8cf 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestEmailTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestEmailTest.java
@@ -155,8 +155,8 @@
         mPaymentRequestTestRule.triggerUIAndWait(mPaymentRequestTestRule.getReadyToPay());
 
         // Make sure that only the appropriate enum value was logged.
-        for (int i = 0; i < PaymentRequestMetrics.REQUESTED_INFORMATION_MAX; ++i) {
-            Assert.assertEquals((i == PaymentRequestMetrics.REQUESTED_INFORMATION_EMAIL ? 1 : 0),
+        for (int i = 0; i < RequestedInformation.MAX; ++i) {
+            Assert.assertEquals((i == RequestedInformation.EMAIL ? 1 : 0),
                     RecordHistogram.getHistogramValueCountForTesting(
                             "PaymentRequest.RequestedInformation", i));
         }
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestFreeShippingTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestFreeShippingTest.java
index 4b66b6d..84db9ac 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestFreeShippingTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestFreeShippingTest.java
@@ -291,8 +291,8 @@
         mPaymentRequestTestRule.triggerUIAndWait(mPaymentRequestTestRule.getReadyToPay());
 
         // Make sure that only the appropriate enum value was logged.
-        for (int i = 0; i < PaymentRequestMetrics.REQUESTED_INFORMATION_MAX; ++i) {
-            Assert.assertEquals((i == PaymentRequestMetrics.REQUESTED_INFORMATION_SHIPPING ? 1 : 0),
+        for (int i = 0; i < RequestedInformation.MAX; ++i) {
+            Assert.assertEquals((i == RequestedInformation.SHIPPING ? 1 : 0),
                     RecordHistogram.getHistogramValueCountForTesting(
                             "PaymentRequest.RequestedInformation", i));
         }
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestMetricsTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestMetricsTest.java
index c452ed2..b818d7b0 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestMetricsTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestMetricsTest.java
@@ -129,8 +129,7 @@
         mPaymentRequestTestRule.getDismissed().waitForCallback(callCount);
         mPaymentRequestTestRule.expectResultContains(new String[] {"Request cancelled"});
 
-        mPaymentRequestTestRule.assertOnlySpecificAbortMetricLogged(
-                JourneyLogger.ABORT_REASON_ABORTED_BY_USER);
+        mPaymentRequestTestRule.assertOnlySpecificAbortMetricLogged(AbortReason.ABORTED_BY_USER);
     }
 
     /**
@@ -151,8 +150,7 @@
                 R.id.close_button, mPaymentRequestTestRule.getDismissed());
         mPaymentRequestTestRule.expectResultContains(new String[] {"Request cancelled"});
 
-        mPaymentRequestTestRule.assertOnlySpecificAbortMetricLogged(
-                JourneyLogger.ABORT_REASON_ABORTED_BY_USER);
+        mPaymentRequestTestRule.assertOnlySpecificAbortMetricLogged(AbortReason.ABORTED_BY_USER);
     }
 
     /**
@@ -179,8 +177,7 @@
         mPaymentRequestTestRule.getDismissed().waitForCallback(callCount);
         mPaymentRequestTestRule.expectResultContains(new String[] {"Request cancelled"});
 
-        mPaymentRequestTestRule.assertOnlySpecificAbortMetricLogged(
-                JourneyLogger.ABORT_REASON_ABORTED_BY_USER);
+        mPaymentRequestTestRule.assertOnlySpecificAbortMetricLogged(AbortReason.ABORTED_BY_USER);
     }
 
     /**
@@ -201,7 +198,7 @@
                 mPaymentRequestTestRule.getActivity());
 
         mPaymentRequestTestRule.assertOnlySpecificAbortMetricLogged(
-                JourneyLogger.ABORT_REASON_MOJO_RENDERER_CLOSING);
+                AbortReason.MOJO_RENDERER_CLOSING);
     }
 
     /**
@@ -220,7 +217,7 @@
         mPaymentRequestTestRule.expectResultContains(new String[] {"Abort"});
 
         mPaymentRequestTestRule.assertOnlySpecificAbortMetricLogged(
-                JourneyLogger.ABORT_REASON_ABORTED_BY_MERCHANT);
+                AbortReason.ABORTED_BY_MERCHANT);
     }
 
     /**
@@ -249,7 +246,7 @@
         Assert.assertEquals(1,
                 RecordHistogram.getHistogramValueCountForTesting(
                         "PaymentRequest.CheckoutFunnel.NoShow",
-                        JourneyLogger.NO_SHOW_NO_MATCHING_PAYMENT_METHOD));
+                        NotShownReason.NO_MATCHING_PAYMENT_METHOD));
     }
 
     /**
@@ -274,7 +271,7 @@
         Assert.assertEquals(1,
                 RecordHistogram.getHistogramValueCountForTesting(
                         "PaymentRequest.CheckoutFunnel.NoShow",
-                        JourneyLogger.NO_SHOW_NO_SUPPORTED_PAYMENT_METHOD));
+                        NotShownReason.NO_SUPPORTED_PAYMENT_METHOD));
     }
 
     /**
@@ -295,8 +292,7 @@
         mPaymentRequestTestRule.clickCardUnmaskButtonAndWait(
                 DialogInterface.BUTTON_POSITIVE, mPaymentRequestTestRule.getDismissed());
 
-        assertOnlySpecificSelectedPaymentMethodMetricLogged(
-                PaymentRequestMetrics.SELECTED_METHOD_CREDIT_CARD);
+        assertOnlySpecificSelectedPaymentMethodMetricLogged(SelectedPaymentMethod.CREDIT_CARD);
     }
 
     /**
@@ -316,8 +312,7 @@
         mPaymentRequestTestRule.clickAndWait(
                 R.id.button_primary, mPaymentRequestTestRule.getDismissed());
 
-        assertOnlySpecificSelectedPaymentMethodMetricLogged(
-                PaymentRequestMetrics.SELECTED_METHOD_ANDROID_PAY);
+        assertOnlySpecificSelectedPaymentMethodMetricLogged(SelectedPaymentMethod.ANDROID_PAY);
     }
 
     /**
@@ -416,7 +411,7 @@
      *                      have a record.
      */
     private void assertOnlySpecificSelectedPaymentMethodMetricLogged(int paymentMethod) {
-        for (int i = 0; i < PaymentRequestMetrics.SELECTED_METHOD_MAX; ++i) {
+        for (int i = 0; i < SelectedPaymentMethod.MAX; ++i) {
             Assert.assertEquals((i == paymentMethod ? 1 : 0),
                     RecordHistogram.getHistogramValueCountForTesting(
                             "PaymentRequest.SelectedPaymentMethod", i));
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestMetricsUnitTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestMetricsUnitTest.java
index c0742f4..a67c439 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestMetricsUnitTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestMetricsUnitTest.java
@@ -45,211 +45,177 @@
         // No information requested.
         Assert.assertEquals(0,
                 RecordHistogram.getHistogramValueCountForTesting(
-                        "PaymentRequest.RequestedInformation",
-                        PaymentRequestMetrics.REQUESTED_INFORMATION_NONE));
+                        "PaymentRequest.RequestedInformation", RequestedInformation.NONE));
         PaymentRequestMetrics.recordRequestedInformationHistogram(false, false, false, false);
         Assert.assertEquals(1,
                 RecordHistogram.getHistogramValueCountForTesting(
-                        "PaymentRequest.RequestedInformation",
-                        PaymentRequestMetrics.REQUESTED_INFORMATION_NONE));
+                        "PaymentRequest.RequestedInformation", RequestedInformation.NONE));
 
         // Only email requested.
         Assert.assertEquals(0,
                 RecordHistogram.getHistogramValueCountForTesting(
-                        "PaymentRequest.RequestedInformation",
-                        PaymentRequestMetrics.REQUESTED_INFORMATION_EMAIL));
+                        "PaymentRequest.RequestedInformation", RequestedInformation.EMAIL));
         PaymentRequestMetrics.recordRequestedInformationHistogram(true, false, false, false);
         Assert.assertEquals(1,
                 RecordHistogram.getHistogramValueCountForTesting(
-                        "PaymentRequest.RequestedInformation",
-                        PaymentRequestMetrics.REQUESTED_INFORMATION_EMAIL));
+                        "PaymentRequest.RequestedInformation", RequestedInformation.EMAIL));
 
         // Only phone requested.
         Assert.assertEquals(0,
                 RecordHistogram.getHistogramValueCountForTesting(
-                        "PaymentRequest.RequestedInformation",
-                        PaymentRequestMetrics.REQUESTED_INFORMATION_PHONE));
+                        "PaymentRequest.RequestedInformation", RequestedInformation.PHONE));
         PaymentRequestMetrics.recordRequestedInformationHistogram(false, true, false, false);
         Assert.assertEquals(1,
                 RecordHistogram.getHistogramValueCountForTesting(
-                        "PaymentRequest.RequestedInformation",
-                        PaymentRequestMetrics.REQUESTED_INFORMATION_PHONE));
+                        "PaymentRequest.RequestedInformation", RequestedInformation.PHONE));
 
         // Only shipping address requested.
         Assert.assertEquals(0,
                 RecordHistogram.getHistogramValueCountForTesting(
-                        "PaymentRequest.RequestedInformation",
-                        PaymentRequestMetrics.REQUESTED_INFORMATION_SHIPPING));
+                        "PaymentRequest.RequestedInformation", RequestedInformation.SHIPPING));
         PaymentRequestMetrics.recordRequestedInformationHistogram(false, false, true, false);
         Assert.assertEquals(1,
                 RecordHistogram.getHistogramValueCountForTesting(
-                        "PaymentRequest.RequestedInformation",
-                        PaymentRequestMetrics.REQUESTED_INFORMATION_SHIPPING));
+                        "PaymentRequest.RequestedInformation", RequestedInformation.SHIPPING));
 
         // Email and phone requested.
         Assert.assertEquals(0,
                 RecordHistogram.getHistogramValueCountForTesting(
                         "PaymentRequest.RequestedInformation",
-                        PaymentRequestMetrics.REQUESTED_INFORMATION_EMAIL
-                                | PaymentRequestMetrics.REQUESTED_INFORMATION_PHONE));
+                        RequestedInformation.EMAIL | RequestedInformation.PHONE));
         PaymentRequestMetrics.recordRequestedInformationHistogram(true, true, false, false);
         Assert.assertEquals(1,
                 RecordHistogram.getHistogramValueCountForTesting(
                         "PaymentRequest.RequestedInformation",
-                        PaymentRequestMetrics.REQUESTED_INFORMATION_EMAIL
-                                | PaymentRequestMetrics.REQUESTED_INFORMATION_PHONE));
+                        RequestedInformation.EMAIL | RequestedInformation.PHONE));
 
         // Email and shipping address requested.
         Assert.assertEquals(0,
                 RecordHistogram.getHistogramValueCountForTesting(
                         "PaymentRequest.RequestedInformation",
-                        PaymentRequestMetrics.REQUESTED_INFORMATION_EMAIL
-                                | PaymentRequestMetrics.REQUESTED_INFORMATION_SHIPPING));
+                        RequestedInformation.EMAIL | RequestedInformation.SHIPPING));
         PaymentRequestMetrics.recordRequestedInformationHistogram(true, false, true, false);
         Assert.assertEquals(1,
                 RecordHistogram.getHistogramValueCountForTesting(
                         "PaymentRequest.RequestedInformation",
-                        PaymentRequestMetrics.REQUESTED_INFORMATION_EMAIL
-                                | PaymentRequestMetrics.REQUESTED_INFORMATION_SHIPPING));
+                        RequestedInformation.EMAIL | RequestedInformation.SHIPPING));
 
         // Phone and shipping address requested.
         Assert.assertEquals(0,
                 RecordHistogram.getHistogramValueCountForTesting(
                         "PaymentRequest.RequestedInformation",
-                        PaymentRequestMetrics.REQUESTED_INFORMATION_PHONE
-                                | PaymentRequestMetrics.REQUESTED_INFORMATION_SHIPPING));
+                        RequestedInformation.PHONE | RequestedInformation.SHIPPING));
         PaymentRequestMetrics.recordRequestedInformationHistogram(false, true, true, false);
         Assert.assertEquals(1,
                 RecordHistogram.getHistogramValueCountForTesting(
                         "PaymentRequest.RequestedInformation",
-                        PaymentRequestMetrics.REQUESTED_INFORMATION_PHONE
-                                | PaymentRequestMetrics.REQUESTED_INFORMATION_SHIPPING));
+                        RequestedInformation.PHONE | RequestedInformation.SHIPPING));
 
         // Email, phone and shipping address requested.
         Assert.assertEquals(0,
                 RecordHistogram.getHistogramValueCountForTesting(
                         "PaymentRequest.RequestedInformation",
-                        PaymentRequestMetrics.REQUESTED_INFORMATION_EMAIL
-                                | PaymentRequestMetrics.REQUESTED_INFORMATION_PHONE
-                                | PaymentRequestMetrics.REQUESTED_INFORMATION_SHIPPING));
+                        RequestedInformation.EMAIL | RequestedInformation.PHONE
+                                | RequestedInformation.SHIPPING));
         PaymentRequestMetrics.recordRequestedInformationHistogram(true, true, true, false);
         Assert.assertEquals(1,
                 RecordHistogram.getHistogramValueCountForTesting(
                         "PaymentRequest.RequestedInformation",
-                        PaymentRequestMetrics.REQUESTED_INFORMATION_EMAIL
-                                | PaymentRequestMetrics.REQUESTED_INFORMATION_PHONE
-                                | PaymentRequestMetrics.REQUESTED_INFORMATION_SHIPPING));
+                        RequestedInformation.EMAIL | RequestedInformation.PHONE
+                                | RequestedInformation.SHIPPING));
 
         // Name requested.
         Assert.assertEquals(0,
                 RecordHistogram.getHistogramValueCountForTesting(
-                        "PaymentRequest.RequestedInformation",
-                        PaymentRequestMetrics.REQUESTED_INFORMATION_NAME));
+                        "PaymentRequest.RequestedInformation", RequestedInformation.NAME));
         PaymentRequestMetrics.recordRequestedInformationHistogram(false, false, false, true);
         Assert.assertEquals(1,
                 RecordHistogram.getHistogramValueCountForTesting(
-                        "PaymentRequest.RequestedInformation",
-                        PaymentRequestMetrics.REQUESTED_INFORMATION_NAME));
+                        "PaymentRequest.RequestedInformation", RequestedInformation.NAME));
 
         // Email and name requested.
         Assert.assertEquals(0,
                 RecordHistogram.getHistogramValueCountForTesting(
                         "PaymentRequest.RequestedInformation",
-                        PaymentRequestMetrics.REQUESTED_INFORMATION_EMAIL
-                                | PaymentRequestMetrics.REQUESTED_INFORMATION_NAME));
+                        RequestedInformation.EMAIL | RequestedInformation.NAME));
         PaymentRequestMetrics.recordRequestedInformationHistogram(true, false, false, true);
         Assert.assertEquals(1,
                 RecordHistogram.getHistogramValueCountForTesting(
                         "PaymentRequest.RequestedInformation",
-                        PaymentRequestMetrics.REQUESTED_INFORMATION_EMAIL
-                                | PaymentRequestMetrics.REQUESTED_INFORMATION_NAME));
+                        RequestedInformation.EMAIL | RequestedInformation.NAME));
 
         // Phone and name requested.
         Assert.assertEquals(0,
                 RecordHistogram.getHistogramValueCountForTesting(
                         "PaymentRequest.RequestedInformation",
-                        PaymentRequestMetrics.REQUESTED_INFORMATION_PHONE
-                                | PaymentRequestMetrics.REQUESTED_INFORMATION_NAME));
+                        RequestedInformation.PHONE | RequestedInformation.NAME));
         PaymentRequestMetrics.recordRequestedInformationHistogram(false, true, false, true);
         Assert.assertEquals(1,
                 RecordHistogram.getHistogramValueCountForTesting(
                         "PaymentRequest.RequestedInformation",
-                        PaymentRequestMetrics.REQUESTED_INFORMATION_PHONE
-                                | PaymentRequestMetrics.REQUESTED_INFORMATION_NAME));
+                        RequestedInformation.PHONE | RequestedInformation.NAME));
 
         // Email, phone and name requested.
         Assert.assertEquals(0,
                 RecordHistogram.getHistogramValueCountForTesting(
                         "PaymentRequest.RequestedInformation",
-                        PaymentRequestMetrics.REQUESTED_INFORMATION_EMAIL
-                                | PaymentRequestMetrics.REQUESTED_INFORMATION_PHONE
-                                | PaymentRequestMetrics.REQUESTED_INFORMATION_NAME));
+                        RequestedInformation.EMAIL | RequestedInformation.PHONE
+                                | RequestedInformation.NAME));
         PaymentRequestMetrics.recordRequestedInformationHistogram(true, true, false, true);
         Assert.assertEquals(1,
                 RecordHistogram.getHistogramValueCountForTesting(
                         "PaymentRequest.RequestedInformation",
-                        PaymentRequestMetrics.REQUESTED_INFORMATION_EMAIL
-                                | PaymentRequestMetrics.REQUESTED_INFORMATION_PHONE
-                                | PaymentRequestMetrics.REQUESTED_INFORMATION_NAME));
+                        RequestedInformation.EMAIL | RequestedInformation.PHONE
+                                | RequestedInformation.NAME));
 
         // Shipping address and name requested.
         Assert.assertEquals(0,
                 RecordHistogram.getHistogramValueCountForTesting(
                         "PaymentRequest.RequestedInformation",
-                        PaymentRequestMetrics.REQUESTED_INFORMATION_SHIPPING
-                                | PaymentRequestMetrics.REQUESTED_INFORMATION_NAME));
+                        RequestedInformation.SHIPPING | RequestedInformation.NAME));
         PaymentRequestMetrics.recordRequestedInformationHistogram(false, false, true, true);
         Assert.assertEquals(1,
                 RecordHistogram.getHistogramValueCountForTesting(
                         "PaymentRequest.RequestedInformation",
-                        PaymentRequestMetrics.REQUESTED_INFORMATION_SHIPPING
-                                | PaymentRequestMetrics.REQUESTED_INFORMATION_NAME));
+                        RequestedInformation.SHIPPING | RequestedInformation.NAME));
 
         // Email, shipping address and name requested.
         Assert.assertEquals(0,
                 RecordHistogram.getHistogramValueCountForTesting(
                         "PaymentRequest.RequestedInformation",
-                        PaymentRequestMetrics.REQUESTED_INFORMATION_EMAIL
-                                | PaymentRequestMetrics.REQUESTED_INFORMATION_SHIPPING
-                                | PaymentRequestMetrics.REQUESTED_INFORMATION_NAME));
+                        RequestedInformation.EMAIL | RequestedInformation.SHIPPING
+                                | RequestedInformation.NAME));
         PaymentRequestMetrics.recordRequestedInformationHistogram(true, false, true, true);
         Assert.assertEquals(1,
                 RecordHistogram.getHistogramValueCountForTesting(
                         "PaymentRequest.RequestedInformation",
-                        PaymentRequestMetrics.REQUESTED_INFORMATION_EMAIL
-                                | PaymentRequestMetrics.REQUESTED_INFORMATION_SHIPPING
-                                | PaymentRequestMetrics.REQUESTED_INFORMATION_NAME));
+                        RequestedInformation.EMAIL | RequestedInformation.SHIPPING
+                                | RequestedInformation.NAME));
 
         // Phone shipping address and name requested.
         Assert.assertEquals(0,
                 RecordHistogram.getHistogramValueCountForTesting(
                         "PaymentRequest.RequestedInformation",
-                        PaymentRequestMetrics.REQUESTED_INFORMATION_PHONE
-                                | PaymentRequestMetrics.REQUESTED_INFORMATION_SHIPPING
-                                | PaymentRequestMetrics.REQUESTED_INFORMATION_NAME));
+                        RequestedInformation.PHONE | RequestedInformation.SHIPPING
+                                | RequestedInformation.NAME));
         PaymentRequestMetrics.recordRequestedInformationHistogram(false, true, true, true);
         Assert.assertEquals(1,
                 RecordHistogram.getHistogramValueCountForTesting(
                         "PaymentRequest.RequestedInformation",
-                        PaymentRequestMetrics.REQUESTED_INFORMATION_PHONE
-                                | PaymentRequestMetrics.REQUESTED_INFORMATION_SHIPPING
-                                | PaymentRequestMetrics.REQUESTED_INFORMATION_NAME));
+                        RequestedInformation.PHONE | RequestedInformation.SHIPPING
+                                | RequestedInformation.NAME));
 
         // Email, phone, shipping address and name requested.
         Assert.assertEquals(0,
                 RecordHistogram.getHistogramValueCountForTesting(
                         "PaymentRequest.RequestedInformation",
-                        PaymentRequestMetrics.REQUESTED_INFORMATION_EMAIL
-                                | PaymentRequestMetrics.REQUESTED_INFORMATION_PHONE
-                                | PaymentRequestMetrics.REQUESTED_INFORMATION_SHIPPING
-                                | PaymentRequestMetrics.REQUESTED_INFORMATION_NAME));
+                        RequestedInformation.EMAIL | RequestedInformation.PHONE
+                                | RequestedInformation.SHIPPING | RequestedInformation.NAME));
         PaymentRequestMetrics.recordRequestedInformationHistogram(true, true, true, true);
         Assert.assertEquals(1,
                 RecordHistogram.getHistogramValueCountForTesting(
                         "PaymentRequest.RequestedInformation",
-                        PaymentRequestMetrics.REQUESTED_INFORMATION_EMAIL
-                                | PaymentRequestMetrics.REQUESTED_INFORMATION_PHONE
-                                | PaymentRequestMetrics.REQUESTED_INFORMATION_SHIPPING
-                                | PaymentRequestMetrics.REQUESTED_INFORMATION_NAME));
+                        RequestedInformation.EMAIL | RequestedInformation.PHONE
+                                | RequestedInformation.SHIPPING | RequestedInformation.NAME));
     }
 }
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestNameAndFreeShippingTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestNameAndFreeShippingTest.java
index 068ed39..77a43b27 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestNameAndFreeShippingTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestNameAndFreeShippingTest.java
@@ -85,14 +85,9 @@
         mPaymentRequestTestRule.triggerUIAndWait(mPaymentRequestTestRule.getReadyToPay());
 
         // Make sure that only the appropriate enum value was logged.
-        for (int i = 0; i < PaymentRequestMetrics.REQUESTED_INFORMATION_MAX; ++i) {
+        for (int i = 0; i < RequestedInformation.MAX; ++i) {
             Assert.assertEquals(
-                    (i
-                                            == (PaymentRequestMetrics.REQUESTED_INFORMATION_SHIPPING
-                                                       | PaymentRequestMetrics
-                                                                 .REQUESTED_INFORMATION_NAME)
-                                    ? 1
-                                    : 0),
+                    (i == (RequestedInformation.SHIPPING | RequestedInformation.NAME) ? 1 : 0),
                     RecordHistogram.getHistogramValueCountForTesting(
                             "PaymentRequest.RequestedInformation", i));
         }
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestNameTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestNameTest.java
index e9a58e5..69e84cf 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestNameTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestNameTest.java
@@ -162,8 +162,8 @@
         mPaymentRequestTestRule.triggerUIAndWait(mPaymentRequestTestRule.getReadyToPay());
 
         // Make sure that only the appropriate enum value was logged.
-        for (int i = 0; i < PaymentRequestMetrics.REQUESTED_INFORMATION_MAX; ++i) {
-            Assert.assertEquals((i == PaymentRequestMetrics.REQUESTED_INFORMATION_NAME ? 1 : 0),
+        for (int i = 0; i < RequestedInformation.MAX; ++i) {
+            Assert.assertEquals((i == RequestedInformation.NAME ? 1 : 0),
                     RecordHistogram.getHistogramValueCountForTesting(
                             "PaymentRequest.RequestedInformation", i));
         }
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestNoShippingTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestNoShippingTest.java
index 4324a007..8d81b24 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestNoShippingTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestNoShippingTest.java
@@ -496,8 +496,8 @@
         mPaymentRequestTestRule.triggerUIAndWait(mPaymentRequestTestRule.getReadyToPay());
 
         // Make sure that only the appropriate enum value was logged.
-        for (int i = 0; i < PaymentRequestMetrics.REQUESTED_INFORMATION_MAX; ++i) {
-            Assert.assertEquals((i == PaymentRequestMetrics.REQUESTED_INFORMATION_NONE ? 1 : 0),
+        for (int i = 0; i < RequestedInformation.MAX; ++i) {
+            Assert.assertEquals((i == RequestedInformation.NONE ? 1 : 0),
                     RecordHistogram.getHistogramValueCountForTesting(
                             "PaymentRequest.RequestedInformation", i));
         }
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestPhoneAndFreeShippingTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestPhoneAndFreeShippingTest.java
index fc11573..ef90aec3 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestPhoneAndFreeShippingTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestPhoneAndFreeShippingTest.java
@@ -85,14 +85,9 @@
         mPaymentRequestTestRule.triggerUIAndWait(mPaymentRequestTestRule.getReadyToPay());
 
         // Make sure that only the appropriate enum value was logged.
-        for (int i = 0; i < PaymentRequestMetrics.REQUESTED_INFORMATION_MAX; ++i) {
+        for (int i = 0; i < RequestedInformation.MAX; ++i) {
             Assert.assertEquals(
-                    (i
-                                            == (PaymentRequestMetrics.REQUESTED_INFORMATION_PHONE
-                                                       | PaymentRequestMetrics
-                                                                 .REQUESTED_INFORMATION_SHIPPING)
-                                    ? 1
-                                    : 0),
+                    (i == (RequestedInformation.PHONE | RequestedInformation.SHIPPING) ? 1 : 0),
                     RecordHistogram.getHistogramValueCountForTesting(
                             "PaymentRequest.RequestedInformation", i));
         }
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestPhoneTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestPhoneTest.java
index 70d10df7..de63d915 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestPhoneTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestPhoneTest.java
@@ -155,8 +155,8 @@
         mPaymentRequestTestRule.triggerUIAndWait(mPaymentRequestTestRule.getReadyToPay());
 
         // Make sure that only the appropriate enum value was logged.
-        for (int i = 0; i < PaymentRequestMetrics.REQUESTED_INFORMATION_MAX; ++i) {
-            Assert.assertEquals((i == PaymentRequestMetrics.REQUESTED_INFORMATION_PHONE ? 1 : 0),
+        for (int i = 0; i < RequestedInformation.MAX; ++i) {
+            Assert.assertEquals((i == RequestedInformation.PHONE ? 1 : 0),
                     RecordHistogram.getHistogramValueCountForTesting(
                             "PaymentRequest.RequestedInformation", i));
         }
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestShowTwiceTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestShowTwiceTest.java
index 82002bca..5796c98 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestShowTwiceTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestShowTwiceTest.java
@@ -67,7 +67,7 @@
         Assert.assertEquals(1,
                 RecordHistogram.getHistogramValueCountForTesting(
                         "PaymentRequest.CheckoutFunnel.NoShow",
-                        JourneyLogger.NO_SHOW_CONCURRENT_REQUESTS));
+                        NotShownReason.CONCURRENT_REQUESTS));
 
         mPaymentRequestTestRule.clickAndWait(
                 R.id.close_button, mPaymentRequestTestRule.getDismissed());
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestTestCommon.java b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestTestCommon.java
index 8d05371..e25e1e4 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestTestCommon.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestTestCommon.java
@@ -731,7 +731,7 @@
     }
 
     protected void assertOnlySpecificAbortMetricLogged(int abortReason) {
-        for (int i = 0; i < JourneyLogger.ABORT_REASON_MAX; ++i) {
+        for (int i = 0; i < AbortReason.MAX; ++i) {
             Assert.assertEquals(
                     String.format(Locale.getDefault(), "Found %d instead of %d", i, abortReason),
                     (i == abortReason ? 1 : 0),
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/vr_shell/WebVrTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/vr_shell/WebVrTest.java
index 2d8da549..d436ba18 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/vr_shell/WebVrTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/vr_shell/WebVrTest.java
@@ -22,10 +22,10 @@
 import org.junit.runner.RunWith;
 
 import org.chromium.base.test.util.CommandLineFlags;
+import org.chromium.base.test.util.DisableIf;
 import org.chromium.base.test.util.DisabledTest;
 import org.chromium.base.test.util.MinAndroidSdkLevel;
 import org.chromium.base.test.util.Restriction;
-import org.chromium.base.test.util.RetryOnFailure;
 import org.chromium.chrome.R;
 import org.chromium.chrome.browser.ChromeSwitches;
 import org.chromium.chrome.test.ChromeActivityTestRule;
@@ -141,7 +141,9 @@
     @Test
     @MediumTest
     @Restriction(RESTRICTION_TYPE_VIEWER_NON_DAYDREAM)
-    @RetryOnFailure(message = "Flaky on L crbug.com/713781")
+    @DisableIf.Build(message = "Flaky on L crbug.com/713781",
+            sdk_is_greater_than = Build.VERSION_CODES.KITKAT,
+            sdk_is_less_than = Build.VERSION_CODES.M)
     public void testScreenTapsRegisteredOnCardboard() throws InterruptedException {
         mVrTestRule.loadUrlAndAwaitInitialization(
                 VrTestRule.getHtmlTestFile("test_screen_taps_registered"), PAGE_LOAD_TIMEOUT_S);
@@ -290,7 +292,6 @@
      */
     @Test
     @MediumTest
-    @RetryOnFailure(message = "Flaky on L crbug.com/713781")
     public void testPresentationLocksFocus() throws InterruptedException {
         mVrTestRule.loadUrlAndAwaitInitialization(
                 VrTestRule.getHtmlTestFile("test_presentation_locks_focus"), PAGE_LOAD_TIMEOUT_S);
diff --git a/chrome/app/generated_resources.grd b/chrome/app/generated_resources.grd
index 1f6d25d..e661482 100644
--- a/chrome/app/generated_resources.grd
+++ b/chrome/app/generated_resources.grd
@@ -4211,9 +4211,6 @@
         <message name="IDS_EXTENSIONS_INFO_LINK" desc="The text for the link that opens the App Info dialog for the extension, displaying permissions and other useful information about the app.">
           Details
         </message>
-        <message name="IDS_EXTENSIONS_SHOW_BUTTON" desc="The text for the Show link.">
-          Show button
-        </message>
         <message name="IDS_EXTENSIONS_LOG_LEVEL_INFO" desc="Alt-text indicating a low severity level for the error icon in the chrome://extensions page.">
           Log
         </message>
diff --git a/chrome/browser/BUILD.gn b/chrome/browser/BUILD.gn
index d4ed886..1f71e2b 100644
--- a/chrome/browser/BUILD.gn
+++ b/chrome/browser/BUILD.gn
@@ -1432,6 +1432,8 @@
     "win/jumplist_factory.h",
     "win/jumplist_file_util.cc",
     "win/jumplist_file_util.h",
+    "win/jumplist_update_util.cc",
+    "win/jumplist_update_util.h",
     "win/jumplist_updater.cc",
     "win/jumplist_updater.h",
     "win/settings_app_monitor.cc",
diff --git a/chrome/browser/android/instantapps/instant_apps_infobar_delegate.cc b/chrome/browser/android/instantapps/instant_apps_infobar_delegate.cc
index 22997f26..a0bad77 100644
--- a/chrome/browser/android/instantapps/instant_apps_infobar_delegate.cc
+++ b/chrome/browser/android/instantapps/instant_apps_infobar_delegate.cc
@@ -12,23 +12,28 @@
 #include "chrome/browser/infobars/infobar_service.h"
 #include "chrome/browser/ui/android/infobars/instant_apps_infobar.h"
 #include "components/infobars/core/infobar_delegate.h"
+#include "content/public/browser/navigation_handle.h"
 #include "content/public/browser/web_contents.h"
 #include "jni/InstantAppsInfoBarDelegate_jni.h"
 
 InstantAppsInfoBarDelegate::~InstantAppsInfoBarDelegate() {}
 
 // static
-void InstantAppsInfoBarDelegate::Create(InfoBarService* infobar_service,
+void InstantAppsInfoBarDelegate::Create(content::WebContents* web_contents,
                                         const jobject jdata,
                                         const std::string& url) {
+  InfoBarService* infobar_service =
+      InfoBarService::FromWebContents(web_contents);
   infobar_service->AddInfoBar(base::MakeUnique<InstantAppsInfoBar>(
       std::unique_ptr<InstantAppsInfoBarDelegate>(
-          new InstantAppsInfoBarDelegate(jdata, url))));
+          new InstantAppsInfoBarDelegate(web_contents, jdata, url))));
 }
 
-InstantAppsInfoBarDelegate::InstantAppsInfoBarDelegate(const jobject jdata,
-                                                       const std::string& url)
-    : url_(url) {
+InstantAppsInfoBarDelegate::InstantAppsInfoBarDelegate(
+    content::WebContents* web_contents,
+    const jobject jdata,
+    const std::string& url)
+    : content::WebContentsObserver(web_contents), url_(url) {
   JNIEnv* env = base::android::AttachCurrentThread();
   java_delegate_.Reset(Java_InstantAppsInfoBarDelegate_create(env));
   data_.Reset(env, jdata);
@@ -68,6 +73,13 @@
       "Android.InstantApps.BannerDismissed"));
 }
 
+void InstantAppsInfoBarDelegate::DidFinishNavigation(
+    content::NavigationHandle* navigation_handle) {
+  if (navigation_handle->IsErrorPage()) {
+    infobar()->RemoveSelf();
+  }
+}
+
 void Launch(JNIEnv* env,
             const base::android::JavaParamRef<jclass>& clazz,
             const base::android::JavaParamRef<jobject>& jweb_contents,
@@ -75,10 +87,8 @@
             const base::android::JavaParamRef<jstring>& jurl) {
   auto* web_contents = content::WebContents::FromJavaWebContents(jweb_contents);
   std::string url(base::android::ConvertJavaStringToUTF8(env, jurl));
-  InstantAppsInfoBarDelegate::Create(
-      InfoBarService::FromWebContents(web_contents),
-      jdata,
-      url);
+
+  InstantAppsInfoBarDelegate::Create(web_contents, jdata, url);
   InstantAppsSettings::RecordInfoBarShowEvent(web_contents, url);
   base::RecordAction(base::UserMetricsAction(
       "Android.InstantApps.BannerShown"));
diff --git a/chrome/browser/android/instantapps/instant_apps_infobar_delegate.h b/chrome/browser/android/instantapps/instant_apps_infobar_delegate.h
index 7b259e6..d0b877a 100644
--- a/chrome/browser/android/instantapps/instant_apps_infobar_delegate.h
+++ b/chrome/browser/android/instantapps/instant_apps_infobar_delegate.h
@@ -11,21 +11,26 @@
 #include "base/strings/string16.h"
 #include "components/infobars/core/confirm_infobar_delegate.h"
 #include "components/infobars/core/infobar_delegate.h"
+#include "content/public/browser/web_contents_observer.h"
 
-class InfoBarService;
-
-class InstantAppsInfoBarDelegate : public ConfirmInfoBarDelegate {
+class InstantAppsInfoBarDelegate : public ConfirmInfoBarDelegate,
+                                   public content::WebContentsObserver {
  public:
   ~InstantAppsInfoBarDelegate() override;
 
-  static void Create(InfoBarService* infobar_service,
+  static void Create(content::WebContents* web_contents,
                      const jobject jdata,
                      const std::string& url);
 
   base::android::ScopedJavaGlobalRef<jobject> data() { return data_; }
 
+  // WebContentsObserver:
+  void DidFinishNavigation(
+      content::NavigationHandle* navigation_handle) override;
+
  private:
-  explicit InstantAppsInfoBarDelegate(const jobject jdata,
+  explicit InstantAppsInfoBarDelegate(content::WebContents* web_contents,
+                                      const jobject jdata,
                                       const std::string& url);
 
   // ConfirmInfoBarDelegate:
diff --git a/chrome/browser/android/vr_shell/non_presenting_gvr_delegate.cc b/chrome/browser/android/vr_shell/non_presenting_gvr_delegate.cc
index d3ac006..1f2518c 100644
--- a/chrome/browser/android/vr_shell/non_presenting_gvr_delegate.cc
+++ b/chrome/browser/android/vr_shell/non_presenting_gvr_delegate.cc
@@ -111,7 +111,7 @@
   }
 }
 
-void NonPresentingGvrDelegate::GetVSync(const GetVSyncCallback& callback) {
+void NonPresentingGvrDelegate::GetVSync(GetVSyncCallback callback) {
   if (!pending_vsync_) {
     if (!callback_.is_null()) {
       mojo::ReportBadMessage(
@@ -119,11 +119,11 @@
       binding_.Close();
       return;
     }
-    callback_ = callback;
+    callback_ = std::move(callback);
     return;
   }
   pending_vsync_ = false;
-  SendVSync(pending_time_, callback);
+  SendVSync(pending_time_, std::move(callback));
 }
 
 void NonPresentingGvrDelegate::UpdateVSyncInterval(int64_t timebase_nanos,
@@ -135,15 +135,16 @@
 }
 
 void NonPresentingGvrDelegate::SendVSync(base::TimeDelta time,
-                                         const GetVSyncCallback& callback) {
+                                         GetVSyncCallback callback) {
   if (!gvr_api_) {
-    callback.Run(device::mojom::VRPosePtr(nullptr), time, -1,
-                 device::mojom::VRVSyncProvider::Status::SUCCESS);
+    std::move(callback).Run(device::mojom::VRPosePtr(nullptr), time, -1,
+                            device::mojom::VRVSyncProvider::Status::SUCCESS);
     return;
   }
 
-  callback.Run(GvrDelegate::GetVRPosePtrWithNeckModel(gvr_api_.get(), nullptr),
-               time, -1, device::mojom::VRVSyncProvider::Status::SUCCESS);
+  std::move(callback).Run(
+      GvrDelegate::GetVRPosePtrWithNeckModel(gvr_api_.get(), nullptr), time, -1,
+      device::mojom::VRVSyncProvider::Status::SUCCESS);
 }
 
 void NonPresentingGvrDelegate::CreateVRDisplayInfo(
diff --git a/chrome/browser/android/vr_shell/non_presenting_gvr_delegate.h b/chrome/browser/android/vr_shell/non_presenting_gvr_delegate.h
index 846dcbb..24365a8 100644
--- a/chrome/browser/android/vr_shell/non_presenting_gvr_delegate.h
+++ b/chrome/browser/android/vr_shell/non_presenting_gvr_delegate.h
@@ -53,10 +53,10 @@
   void StopVSyncLoop();
   void StartVSyncLoop();
   void OnVSync();
-  void SendVSync(base::TimeDelta time, const GetVSyncCallback& callback);
+  void SendVSync(base::TimeDelta time, GetVSyncCallback callback);
 
   // VRVSyncProvider implementation
-  void GetVSync(const GetVSyncCallback& callback) override;
+  void GetVSync(GetVSyncCallback callback) override;
 
   std::unique_ptr<gvr::GvrApi> gvr_api_;
   scoped_refptr<base::SingleThreadTaskRunner> task_runner_;
diff --git a/chrome/browser/android/vr_shell/ui_elements/ui_element.h b/chrome/browser/android/vr_shell/ui_elements/ui_element.h
index 1cdeac7..0a5b354 100644
--- a/chrome/browser/android/vr_shell/ui_elements/ui_element.h
+++ b/chrome/browser/android/vr_shell/ui_elements/ui_element.h
@@ -215,6 +215,9 @@
     center_color_ = center_color;
   }
 
+  SkColor grid_color() const { return grid_color_; }
+  void set_grid_color(const SkColor& grid_color) { grid_color_ = grid_color; }
+
   int gridline_count() const { return gridline_count_; }
   void set_gridline_count(int gridline_count) {
     gridline_count_ = gridline_count;
@@ -307,6 +310,7 @@
 
   SkColor edge_color_ = SK_ColorWHITE;
   SkColor center_color_ = SK_ColorWHITE;
+  SkColor grid_color_ = SK_ColorWHITE;
 
   int gridline_count_ = 1;
 
diff --git a/chrome/browser/android/vr_shell/ui_elements/ui_element_debug_id.h b/chrome/browser/android/vr_shell/ui_elements/ui_element_debug_id.h
index 46131f9..d32d8280 100644
--- a/chrome/browser/android/vr_shell/ui_elements/ui_element_debug_id.h
+++ b/chrome/browser/android/vr_shell/ui_elements/ui_element_debug_id.h
@@ -17,7 +17,6 @@
   kBackplane,
   kCeiling,
   kFloor,
-  kFloorGrid,
   kUrlBar,
   kLoadingIndicator,
   kAudioCaptureIndicator,
diff --git a/chrome/browser/android/vr_shell/ui_scene_manager.cc b/chrome/browser/android/vr_shell/ui_scene_manager.cc
index f1173584..4a6f4511 100644
--- a/chrome/browser/android/vr_shell/ui_scene_manager.cc
+++ b/chrome/browser/android/vr_shell/ui_scene_manager.cc
@@ -229,8 +229,9 @@
   element->set_size({kSceneSize, kSceneSize, 1.0});
   element->set_translation({0.0, -kSceneHeight / 2, 0.0});
   element->set_rotation({1.0, 0.0, 0.0, -M_PI / 2.0});
-  element->set_fill(vr_shell::Fill::OPAQUE_GRADIENT);
+  element->set_fill(vr_shell::Fill::GRID_GRADIENT);
   element->set_draw_phase(0);
+  element->set_gridline_count(kFloorGridlineCount);
   floor_ = element.get();
   content_elements_.push_back(element.get());
   scene_->AddUiElement(std::move(element));
@@ -239,7 +240,6 @@
   element = base::MakeUnique<UiElement>();
   element->set_debug_id(kCeiling);
   element->set_id(AllocateId());
-  element->set_fill(vr_shell::Fill::OPAQUE_GRADIENT);
   element->set_size({kSceneSize, kSceneSize, 1.0});
   element->set_translation({0.0, kSceneHeight / 2, 0.0});
   element->set_rotation({1.0, 0.0, 0.0, M_PI / 2});
@@ -249,20 +249,6 @@
   content_elements_.push_back(element.get());
   scene_->AddUiElement(std::move(element));
 
-  // Floor grid.
-  element = base::MakeUnique<UiElement>();
-  element->set_debug_id(kFloorGrid);
-  element->set_id(AllocateId());
-  element->set_size({kSceneSize, kSceneSize, 1.0});
-  element->set_translation({0.0, -kSceneHeight / 2 + kTextureOffset, 0.0});
-  element->set_rotation({1.0, 0.0, 0.0, -M_PI / 2});
-  element->set_fill(vr_shell::Fill::GRID_GRADIENT);
-  element->set_gridline_count(kFloorGridlineCount);
-  element->set_draw_phase(0);
-  floor_grid_ = element.get();
-  content_elements_.push_back(element.get());
-  scene_->AddUiElement(std::move(element));
-
   UpdateBackgroundColor();
 }
 
@@ -364,9 +350,7 @@
   ceiling_->set_edge_color(color_scheme().horizon);
   floor_->set_center_color(color_scheme().floor);
   floor_->set_edge_color(color_scheme().horizon);
-  floor_grid_->set_center_color(color_scheme().floor_grid);
-  SkColor floor_grid_edge_color = SkColorSetA(color_scheme().floor_grid, 0);
-  floor_grid_->set_edge_color(floor_grid_edge_color);
+  floor_->set_grid_color(color_scheme().floor_grid);
 }
 
 void UiSceneManager::SetAudioCapturingIndicator(bool enabled) {
diff --git a/chrome/browser/android/vr_shell/ui_scene_manager.h b/chrome/browser/android/vr_shell/ui_scene_manager.h
index 4f63b8d..ba4ddd8 100644
--- a/chrome/browser/android/vr_shell/ui_scene_manager.h
+++ b/chrome/browser/android/vr_shell/ui_scene_manager.h
@@ -86,7 +86,6 @@
   UiElement* screen_dimmer_ = nullptr;
   UiElement* ceiling_ = nullptr;
   UiElement* floor_ = nullptr;
-  UiElement* floor_grid_ = nullptr;
   UrlBar* url_bar_ = nullptr;
   LoadingIndicator* loading_indicator_ = nullptr;
 
diff --git a/chrome/browser/android/vr_shell/ui_scene_manager_unittest.cc b/chrome/browser/android/vr_shell/ui_scene_manager_unittest.cc
index 89f15ae8..0e1345f 100644
--- a/chrome/browser/android/vr_shell/ui_scene_manager_unittest.cc
+++ b/chrome/browser/android/vr_shell/ui_scene_manager_unittest.cc
@@ -197,14 +197,12 @@
 
 TEST_F(UiSceneManagerTest, UiUpdatesForFullscreenChanges) {
   std::set<UiElementDebugId> visible_in_browsing = {
-      UiElementDebugId::kContentQuad,     UiElementDebugId::kBackplane,
-      UiElementDebugId::kCeiling,         UiElementDebugId::kFloor,
-      UiElementDebugId::kFloorGrid,       UiElementDebugId::kUrlBar,
-      UiElementDebugId::kLoadingIndicator};
+      UiElementDebugId::kContentQuad, UiElementDebugId::kBackplane,
+      UiElementDebugId::kCeiling,     UiElementDebugId::kFloor,
+      UiElementDebugId::kUrlBar,      UiElementDebugId::kLoadingIndicator};
   std::set<UiElementDebugId> visible_in_fullscreen = {
       UiElementDebugId::kContentQuad, UiElementDebugId::kBackplane,
-      UiElementDebugId::kCeiling, UiElementDebugId::kFloor,
-      UiElementDebugId::kFloorGrid};
+      UiElementDebugId::kCeiling, UiElementDebugId::kFloor};
 
   MakeManager(kNotInCct, kNotInWebVr);
 
diff --git a/chrome/browser/android/vr_shell/vr_shell_gl.cc b/chrome/browser/android/vr_shell/vr_shell_gl.cc
index a68f6f8d..deb62e5 100644
--- a/chrome/browser/android/vr_shell/vr_shell_gl.cc
+++ b/chrome/browser/android/vr_shell/vr_shell_gl.cc
@@ -1261,7 +1261,8 @@
     case Fill::GRID_GRADIENT: {
       vr_shell_renderer_->GetGradientGridRenderer()->Draw(
           transform, element.edge_color(), element.center_color(),
-          element.gridline_count(), element.computed_opacity());
+          element.grid_color(), element.gridline_count(),
+          element.computed_opacity());
       break;
     }
     case Fill::CONTENT: {
@@ -1525,7 +1526,7 @@
   binding_.Bind(std::move(request));
 }
 
-void VrShellGl::GetVSync(const GetVSyncCallback& callback) {
+void VrShellGl::GetVSync(GetVSyncCallback callback) {
   // In surfaceless (reprojecting) rendering, stay locked
   // to vsync intervals. Otherwise, for legacy Cardboard mode,
   // run requested animation frames now if it missed a vsync.
@@ -1536,11 +1537,11 @@
       binding_.Close();
       return;
     }
-    callback_ = callback;
+    callback_ = std::move(callback);
     return;
   }
   pending_vsync_ = false;
-  SendVSync(pending_time_, callback);
+  SendVSync(pending_time_, std::move(callback));
 }
 
 void VrShellGl::UpdateVSyncInterval(int64_t timebase_nanos,
@@ -1573,8 +1574,7 @@
   return expected_frame_micros * 1000;
 }
 
-void VrShellGl::SendVSync(base::TimeDelta time,
-                          const GetVSyncCallback& callback) {
+void VrShellGl::SendVSync(base::TimeDelta time, GetVSyncCallback callback) {
   uint8_t frame_index = frame_index_++;
 
   TRACE_EVENT1("input", "VrShellGl::SendVSync", "frame", frame_index);
@@ -1588,8 +1588,8 @@
 
   webvr_head_pose_[frame_index % kPoseRingBufferSize] = head_mat;
 
-  callback.Run(std::move(pose), time, frame_index,
-               device::mojom::VRVSyncProvider::Status::SUCCESS);
+  std::move(callback).Run(std::move(pose), time, frame_index,
+                          device::mojom::VRVSyncProvider::Status::SUCCESS);
 }
 
 void VrShellGl::CreateVRDisplayInfo(
diff --git a/chrome/browser/android/vr_shell/vr_shell_gl.h b/chrome/browser/android/vr_shell/vr_shell_gl.h
index ecaf524..f88836e 100644
--- a/chrome/browser/android/vr_shell/vr_shell_gl.h
+++ b/chrome/browser/android/vr_shell/vr_shell_gl.h
@@ -182,11 +182,11 @@
   void OnVSync();
 
   // VRVSyncProvider
-  void GetVSync(const GetVSyncCallback& callback) override;
+  void GetVSync(GetVSyncCallback callback) override;
 
   void ForceExitVr();
 
-  void SendVSync(base::TimeDelta time, const GetVSyncCallback& callback);
+  void SendVSync(base::TimeDelta time, GetVSyncCallback callback);
 
   // samplerExternalOES texture data for main content image.
   int content_texture_id_ = 0;
diff --git a/chrome/browser/android/vr_shell/vr_shell_renderer.cc b/chrome/browser/android/vr_shell/vr_shell_renderer.cc
index d5d3c86..df3705c8 100644
--- a/chrome/browser/android/vr_shell/vr_shell_renderer.cc
+++ b/chrome/browser/android/vr_shell/vr_shell_renderer.cc
@@ -225,10 +225,9 @@
           }
           /* clang-format on */);
     case vr_shell::ShaderID::GRADIENT_QUAD_FRAGMENT_SHADER:
-    case vr_shell::ShaderID::GRADIENT_GRID_FRAGMENT_SHADER:
-      return OEIE_SHADER(
+      return SHADER(
           /* clang-format off */
-          precision highp float;
+          precision lowp float;
           varying vec2 v_GridPosition;
           uniform vec4 u_CenterColor;
           uniform vec4 u_EdgeColor;
@@ -243,6 +242,41 @@
                                 color.w * u_Opacity);
           }
           /* clang-format on */);
+    case vr_shell::ShaderID::GRADIENT_GRID_FRAGMENT_SHADER:
+      return SHADER(
+          /* clang-format off */
+          precision lowp float;
+          varying vec2 v_GridPosition;
+          uniform vec4 u_CenterColor;
+          uniform vec4 u_EdgeColor;
+          uniform vec4 u_GridColor;
+          uniform mediump float u_Opacity;
+          uniform int u_LinesCount;
+
+          void main() {
+            float edgeColorWeight = clamp(length(v_GridPosition), 0.0, 1.0);
+            float centerColorWeight = 1.0 - edgeColorWeight;
+            vec4 bg_color = u_CenterColor * centerColorWeight +
+                u_EdgeColor * edgeColorWeight;
+            bg_color = vec4(bg_color.xyz * bg_color.w, bg_color.w);
+            float linesCountF = float(u_LinesCount) / 2.0;
+            float pos_x = abs(v_GridPosition.x) * linesCountF;
+            float pos_y = abs(v_GridPosition.y) * linesCountF;
+            float diff_x = abs(pos_x - floor(pos_x + 0.5));
+            float diff_y = abs(pos_y - floor(pos_y + 0.5));
+            float diff = min(diff_x, diff_y);
+            if (diff < 0.01) {
+              float opacity = 1.0 - diff / 0.01;
+              opacity = opacity * opacity * centerColorWeight * u_GridColor.w;
+              vec3 grid_color = u_GridColor.xyz * opacity;
+              gl_FragColor = vec4(
+                  grid_color.xyz + bg_color.xyz * (1.0 - opacity),
+                  opacity + bg_color.w * (1.0 - opacity));
+            } else {
+              gl_FragColor = bg_color;
+            }
+          }
+          /* clang-format on */);
     case vr_shell::ShaderID::CONTROLLER_FRAGMENT_SHADER:
       return SHADER(
           /* clang-format off */
@@ -719,89 +753,44 @@
 GradientQuadRenderer::~GradientQuadRenderer() = default;
 
 GradientGridRenderer::GradientGridRenderer()
-    : BaseRenderer(GRADIENT_QUAD_VERTEX_SHADER, GRADIENT_QUAD_FRAGMENT_SHADER) {
+    : BaseQuadRenderer(GRADIENT_QUAD_VERTEX_SHADER,
+                       GRADIENT_GRID_FRAGMENT_SHADER) {
   model_view_proj_matrix_handle_ =
       glGetUniformLocation(program_handle_, "u_ModelViewProjMatrix");
   scene_radius_handle_ = glGetUniformLocation(program_handle_, "u_SceneRadius");
   center_color_handle_ = glGetUniformLocation(program_handle_, "u_CenterColor");
   edge_color_handle_ = glGetUniformLocation(program_handle_, "u_EdgeColor");
+  grid_color_handle_ = glGetUniformLocation(program_handle_, "u_GridColor");
   opacity_handle_ = glGetUniformLocation(program_handle_, "u_Opacity");
+  lines_count_handle_ = glGetUniformLocation(program_handle_, "u_LinesCount");
 }
 
 void GradientGridRenderer::Draw(const vr::Mat4f& view_proj_matrix,
                                 SkColor edge_color,
                                 SkColor center_color,
+                                SkColor grid_color,
                                 int gridline_count,
                                 float opacity) {
-  // In case the tile number changed we have to regenerate the grid lines.
-  if (grid_lines_.size() != static_cast<size_t>(2 * (gridline_count + 1))) {
-    MakeGridLines(gridline_count);
-  }
-
-  glUseProgram(program_handle_);
-
-  // Pass in model view project matrix.
-  glUniformMatrix4fv(model_view_proj_matrix_handle_, 1, false,
-                     MatrixToGLArray(view_proj_matrix).data());
+  PrepareToDraw(model_view_proj_matrix_handle_, view_proj_matrix);
 
   // Tell shader the grid size so that it can calculate the fading.
   glUniform1f(scene_radius_handle_, kHalfSize);
+  glUniform1i(lines_count_handle_, gridline_count);
 
   // Set the edge color to the fog color so that it seems to fade out.
   SetColorUniform(edge_color_handle_, edge_color);
   SetColorUniform(center_color_handle_, center_color);
+  SetColorUniform(grid_color_handle_, grid_color);
   glUniform1f(opacity_handle_, opacity);
 
-  // Draw the grid.
-  glBindBuffer(GL_ARRAY_BUFFER, vertex_buffer_);
-
-  glVertexAttribPointer(position_handle_, kPositionDataSize, GL_FLOAT, false, 0,
-                        VOID_OFFSET(0));
-  glEnableVertexAttribArray(position_handle_);
-  glEnable(GL_BLEND);
-  glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
-  int verticesNumber = 4 * (gridline_count + 1);
-  glDrawArrays(GL_LINES, 0, verticesNumber);
+  glDrawArrays(GL_TRIANGLES, 0, kVerticesNumber);
 
   glDisableVertexAttribArray(position_handle_);
+  glDisableVertexAttribArray(tex_coord_handle_);
 }
 
 GradientGridRenderer::~GradientGridRenderer() = default;
 
-void GradientGridRenderer::MakeGridLines(int gridline_count) {
-  int linesNumber = 2 * (gridline_count + 1);
-  grid_lines_.resize(linesNumber);
-
-  for (int i = 0; i < linesNumber - 1; i += 2) {
-    float position = -kHalfSize + (i / 2) * kHalfSize * 2.0f / gridline_count;
-
-    // Line parallel to the z axis.
-    Line3d& zLine = grid_lines_[i];
-    // Line parallel to the x axis.
-    Line3d& xLine = grid_lines_[i + 1];
-
-    zLine.start.x = position;
-    zLine.start.y = kHalfSize;
-    zLine.start.z = 0.0f;
-    zLine.end.x = position;
-    zLine.end.y = -kHalfSize;
-    zLine.end.z = 0.0f;
-    xLine.start.x = -kHalfSize;
-    xLine.start.y = -position;
-    xLine.start.z = 0.0f;
-    xLine.end.x = kHalfSize;
-    xLine.end.y = -position;
-    xLine.end.z = 0.0f;
-  }
-
-  size_t vertex_buffer_size = sizeof(Line3d) * linesNumber;
-
-  glGenBuffersARB(1, &vertex_buffer_);
-  glBindBuffer(GL_ARRAY_BUFFER, vertex_buffer_);
-  glBufferData(GL_ARRAY_BUFFER, vertex_buffer_size, grid_lines_.data(),
-               GL_STATIC_DRAW);
-}
-
 VrShellRenderer::VrShellRenderer()
     : external_textured_quad_renderer_(
           base::MakeUnique<ExternalTexturedQuadRenderer>()),
diff --git a/chrome/browser/android/vr_shell/vr_shell_renderer.h b/chrome/browser/android/vr_shell/vr_shell_renderer.h
index 6d8337a..85791ab1 100644
--- a/chrome/browser/android/vr_shell/vr_shell_renderer.h
+++ b/chrome/browser/android/vr_shell/vr_shell_renderer.h
@@ -248,7 +248,7 @@
   DISALLOW_COPY_AND_ASSIGN(GradientQuadRenderer);
 };
 
-class GradientGridRenderer : public BaseRenderer {
+class GradientGridRenderer : public BaseQuadRenderer {
  public:
   GradientGridRenderer();
   ~GradientGridRenderer() override;
@@ -256,19 +256,18 @@
   void Draw(const vr::Mat4f& view_proj_matrix,
             SkColor edge_color,
             SkColor center_color,
+            SkColor grid_color,
             int gridline_count,
             float opacity);
 
  private:
-  void MakeGridLines(int gridline_count);
-
-  GLuint vertex_buffer_ = 0;
   GLuint model_view_proj_matrix_handle_;
   GLuint scene_radius_handle_;
   GLuint center_color_handle_;
   GLuint edge_color_handle_;
+  GLuint grid_color_handle_;
   GLuint opacity_handle_;
-  std::vector<Line3d> grid_lines_;
+  GLuint lines_count_handle_;
 
   DISALLOW_COPY_AND_ASSIGN(GradientGridRenderer);
 };
diff --git a/chrome/browser/apps/app_shim/app_shim_host_mac.cc b/chrome/browser/apps/app_shim/app_shim_host_mac.cc
index 4669f43..996db77 100644
--- a/chrome/browser/apps/app_shim/app_shim_host_mac.cc
+++ b/chrome/browser/apps/app_shim/app_shim_host_mac.cc
@@ -19,14 +19,14 @@
 AppShimHost::AppShimHost() : initial_launch_finished_(false) {}
 
 AppShimHost::~AppShimHost() {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
   apps::AppShimHandler* handler = apps::AppShimHandler::GetForAppMode(app_id_);
   if (handler)
     handler->OnShimClose(this);
 }
 
 void AppShimHost::ServeChannel(mojo::edk::ScopedPlatformHandle handle) {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
   DCHECK(!channel_.get());
   channel_ = IPC::ChannelProxy::Create(
       IPC::ChannelMojo::CreateServerFactory(
@@ -49,7 +49,7 @@
 }
 
 bool AppShimHost::OnMessageReceived(const IPC::Message& message) {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
   bool handled = true;
   IPC_BEGIN_MESSAGE_MAP(AppShimHost, message)
     IPC_MESSAGE_HANDLER(AppShimHostMsg_LaunchApp, OnLaunchApp)
@@ -75,7 +75,7 @@
                               const std::string& app_id,
                               apps::AppShimLaunchType launch_type,
                               const std::vector<base::FilePath>& files) {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
   DCHECK(profile_path_.empty());
   // Only one app launch message per channel.
   if (!profile_path_.empty())
@@ -93,21 +93,21 @@
 
 void AppShimHost::OnFocus(apps::AppShimFocusType focus_type,
                           const std::vector<base::FilePath>& files) {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
   apps::AppShimHandler* handler = apps::AppShimHandler::GetForAppMode(app_id_);
   if (handler)
     handler->OnShimFocus(this, focus_type, files);
 }
 
 void AppShimHost::OnSetHidden(bool hidden) {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
   apps::AppShimHandler* handler = apps::AppShimHandler::GetForAppMode(app_id_);
   if (handler)
     handler->OnShimSetHidden(this, hidden);
 }
 
 void AppShimHost::OnQuit() {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
   apps::AppShimHandler* handler = apps::AppShimHandler::GetForAppMode(app_id_);
   if (handler)
     handler->OnShimQuit(this);
@@ -137,6 +137,6 @@
 }
 
 void AppShimHost::Close() {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
   delete this;
 }
diff --git a/chrome/browser/apps/app_shim/app_shim_host_mac.h b/chrome/browser/apps/app_shim/app_shim_host_mac.h
index 7507aaf..168a07bf 100644
--- a/chrome/browser/apps/app_shim/app_shim_host_mac.h
+++ b/chrome/browser/apps/app_shim/app_shim_host_mac.h
@@ -10,7 +10,7 @@
 #include <vector>
 
 #include "base/files/file_path.h"
-#include "base/threading/non_thread_safe.h"
+#include "base/threading/thread_checker.h"
 #include "chrome/browser/apps/app_shim/app_shim_handler_mac.h"
 #include "ipc/ipc_listener.h"
 #include "ipc/ipc_sender.h"
@@ -28,8 +28,7 @@
 // connected to the app shim is closed.
 class AppShimHost : public IPC::Listener,
                     public IPC::Sender,
-                    public apps::AppShimHandler::Host,
-                    public base::NonThreadSafe {
+                    public apps::AppShimHandler::Host {
  public:
   AppShimHost();
   ~AppShimHost() override;
@@ -83,6 +82,8 @@
   std::string app_id_;
   base::FilePath profile_path_;
   bool initial_launch_finished_;
+
+  THREAD_CHECKER(thread_checker_);
 };
 
 #endif  // CHROME_BROWSER_APPS_APP_SHIM_APP_SHIM_HOST_MAC_H_
diff --git a/chrome/browser/chrome_browser_main_win.cc b/chrome/browser/chrome_browser_main_win.cc
index ea0e3a4..d781db9 100644
--- a/chrome/browser/chrome_browser_main_win.cc
+++ b/chrome/browser/chrome_browser_main_win.cc
@@ -353,15 +353,6 @@
 void ChromeBrowserMainPartsWin::PostProfileInit() {
   ChromeBrowserMainParts::PostProfileInit();
 
-  // TODO(kulshin): remove this cleanup code in 2017. http://crbug.com/603718
-  // Attempt to delete the font cache and ignore any errors.
-  base::FilePath path(
-      profile()->GetPath().AppendASCII("ChromeDWriteFontCache"));
-  content::BrowserThread::PostAfterStartupTask(
-      FROM_HERE, content::BrowserThread::GetTaskRunnerForThread(
-                     content::BrowserThread::FILE),
-      base::Bind(base::IgnoreResult(&base::DeleteFile), path, false));
-
   // Create the module database and hook up the in-process module watcher. This
   // needs to be done before any child processes are initialized as the
   // ModuleDatabase is an endpoint for IPC from child processes.
diff --git a/chrome/browser/chromeos/BUILD.gn b/chrome/browser/chromeos/BUILD.gn
index f22e7aa..10c3cc3 100644
--- a/chrome/browser/chromeos/BUILD.gn
+++ b/chrome/browser/chromeos/BUILD.gn
@@ -977,8 +977,6 @@
     "login/ui/user_adding_screen_input_methods_controller.h",
     "login/ui/web_contents_forced_title.cc",
     "login/ui/web_contents_forced_title.h",
-    "login/ui/web_contents_set_background_color.cc",
-    "login/ui/web_contents_set_background_color.h",
     "login/ui/webui_login_display.cc",
     "login/ui/webui_login_display.h",
     "login/ui/webui_login_view.cc",
diff --git a/chrome/browser/chromeos/accessibility/accessibility_manager.cc b/chrome/browser/chromeos/accessibility/accessibility_manager.cc
index c16dfec..9806ffb0 100644
--- a/chrome/browser/chromeos/accessibility/accessibility_manager.cc
+++ b/chrome/browser/chromeos/accessibility/accessibility_manager.cc
@@ -20,7 +20,6 @@
 #include "ash/shell.h"
 #include "ash/shell_port.h"
 #include "ash/sticky_keys/sticky_keys_controller.h"
-#include "ash/wm_window.h"
 #include "base/callback.h"
 #include "base/callback_helpers.h"
 #include "base/command_line.h"
diff --git a/chrome/browser/chromeos/accessibility/chromevox_panel.cc b/chrome/browser/chromeos/accessibility/chromevox_panel.cc
index 827273d..76a9333 100644
--- a/chrome/browser/chromeos/accessibility/chromevox_panel.cc
+++ b/chrome/browser/chromeos/accessibility/chromevox_panel.cc
@@ -10,7 +10,6 @@
 #include "ash/shelf/shelf.h"
 #include "ash/shelf/shelf_layout_manager.h"
 #include "ash/shell.h"
-#include "ash/wm_window.h"
 #include "base/macros.h"
 #include "chrome/browser/chromeos/accessibility/accessibility_manager.h"
 #include "chrome/browser/chromeos/profiles/profile_helper.h"
diff --git a/chrome/browser/chromeos/login/login_browsertest.cc b/chrome/browser/chromeos/login/login_browsertest.cc
index f238666d..e567a7b 100644
--- a/chrome/browser/chromeos/login/login_browsertest.cc
+++ b/chrome/browser/chromeos/login/login_browsertest.cc
@@ -7,7 +7,6 @@
 #include "ash/shelf/shelf.h"
 #include "ash/shell.h"
 #include "ash/system/tray/system_tray.h"
-#include "ash/wm_window.h"
 #include "base/command_line.h"
 #include "base/location.h"
 #include "base/single_thread_task_runner.h"
diff --git a/chrome/browser/chromeos/login/ui/webui_login_view.cc b/chrome/browser/chromeos/login/ui/webui_login_view.cc
index 89d498d..78e038c8 100644
--- a/chrome/browser/chromeos/login/ui/webui_login_view.cc
+++ b/chrome/browser/chromeos/login/ui/webui_login_view.cc
@@ -25,7 +25,6 @@
 #include "chrome/browser/chromeos/login/ui/preloaded_web_view_factory.h"
 #include "chrome/browser/chromeos/login/ui/proxy_settings_dialog.h"
 #include "chrome/browser/chromeos/login/ui/web_contents_forced_title.h"
-#include "chrome/browser/chromeos/login/ui/web_contents_set_background_color.h"
 #include "chrome/browser/chromeos/login/ui/webui_login_display.h"
 #include "chrome/browser/chromeos/profiles/profile_helper.h"
 #include "chrome/browser/extensions/chrome_extension_web_contents_observer.h"
@@ -57,6 +56,7 @@
 #include "ui/gfx/geometry/rect.h"
 #include "ui/gfx/geometry/size.h"
 #include "ui/keyboard/keyboard_controller.h"
+#include "ui/views/controls/webview/web_contents_set_background_color.h"
 #include "ui/views/controls/webview/webview.h"
 #include "ui/views/widget/widget.h"
 
@@ -220,7 +220,7 @@
   if (!title.empty())
     WebContentsForcedTitle::CreateForWebContentsWithTitle(web_contents, title);
 
-  WebContentsSetBackgroundColor::CreateForWebContentsWithColor(
+  views::WebContentsSetBackgroundColor::CreateForWebContentsWithColor(
       web_contents, SK_ColorTRANSPARENT);
 
   // Ensure that the login UI has a tab ID, which will allow the GAIA auth
diff --git a/chrome/browser/chromeos/login/users/wallpaper/wallpaper_window_state_manager.cc b/chrome/browser/chromeos/login/users/wallpaper/wallpaper_window_state_manager.cc
index a3e27949..5e55f6d 100644
--- a/chrome/browser/chromeos/login/users/wallpaper/wallpaper_window_state_manager.cc
+++ b/chrome/browser/chromeos/login/users/wallpaper/wallpaper_window_state_manager.cc
@@ -8,7 +8,6 @@
 #include "ash/wm/mru_window_tracker.h"
 #include "ash/wm/window_state.h"
 #include "ash/wm/window_util.h"
-#include "ash/wm_window.h"
 #include "chrome/browser/ui/ash/ash_util.h"
 #include "ui/aura/window.h"
 
diff --git a/chrome/browser/chromeos/net/network_portal_detector_impl.cc b/chrome/browser/chromeos/net/network_portal_detector_impl.cc
index 2cec9cd3..d16ab571 100644
--- a/chrome/browser/chromeos/net/network_portal_detector_impl.cc
+++ b/chrome/browser/chromeos/net/network_portal_detector_impl.cc
@@ -245,7 +245,7 @@
 
 NetworkPortalDetectorImpl::~NetworkPortalDetectorImpl() {
   NET_LOG(EVENT) << "NetworkPortalDetectorImpl::~NetworkPortalDetectorImpl()";
-  DCHECK(CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
 
   attempt_task_.Cancel();
   attempt_timeout_.Cancel();
@@ -260,13 +260,13 @@
 }
 
 void NetworkPortalDetectorImpl::AddObserver(Observer* observer) {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   if (observer && !observers_.HasObserver(observer))
     observers_.AddObserver(observer);
 }
 
 void NetworkPortalDetectorImpl::AddAndFireObserver(Observer* observer) {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   if (!observer)
     return;
   AddObserver(observer);
@@ -278,7 +278,7 @@
 }
 
 void NetworkPortalDetectorImpl::RemoveObserver(Observer* observer) {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   if (observer)
     observers_.RemoveObserver(observer);
 }
@@ -286,7 +286,7 @@
 bool NetworkPortalDetectorImpl::IsEnabled() { return enabled_; }
 
 void NetworkPortalDetectorImpl::Enable(bool start_detection) {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   if (enabled_)
     return;
 
@@ -304,7 +304,7 @@
 
 NetworkPortalDetectorImpl::CaptivePortalState
 NetworkPortalDetectorImpl::GetCaptivePortalState(const std::string& guid) {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   CaptivePortalStateMap::const_iterator it = portal_state_map_.find(guid);
   if (it == portal_state_map_.end())
     return CaptivePortalState();
@@ -334,7 +334,7 @@
 
 void NetworkPortalDetectorImpl::DefaultNetworkChanged(
     const NetworkState* default_network) {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
 
   if (!default_network) {
     NET_LOG(EVENT) << "Default network changed: None";
@@ -459,7 +459,7 @@
 }
 
 void NetworkPortalDetectorImpl::OnAttemptTimeout() {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   DCHECK(is_checking_for_portal());
 
   NET_LOG(ERROR) << "Portal detection timeout: "
@@ -474,7 +474,7 @@
 
 void NetworkPortalDetectorImpl::OnAttemptCompleted(
     const CaptivePortalDetector::Results& results) {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   DCHECK(is_checking_for_portal());
 
   captive_portal::CaptivePortalResult result = results.result;
diff --git a/chrome/browser/chromeos/net/network_portal_detector_impl.h b/chrome/browser/chromeos/net/network_portal_detector_impl.h
index a4aa5b1..042f6bd 100644
--- a/chrome/browser/chromeos/net/network_portal_detector_impl.h
+++ b/chrome/browser/chromeos/net/network_portal_detector_impl.h
@@ -15,7 +15,7 @@
 #include "base/memory/ref_counted.h"
 #include "base/memory/weak_ptr.h"
 #include "base/observer_list.h"
-#include "base/threading/non_thread_safe.h"
+#include "base/sequence_checker.h"
 #include "base/time/time.h"
 #include "chromeos/network/network_state_handler_observer.h"
 #include "chromeos/network/portal_detector/network_portal_detector.h"
@@ -42,7 +42,6 @@
 // NetworkStateHandler and delegates portal detection for the default
 // network to CaptivePortalService.
 class NetworkPortalDetectorImpl : public NetworkPortalDetector,
-                                  public base::NonThreadSafe,
                                   public chromeos::NetworkStateHandlerObserver,
                                   public content::NotificationObserver,
                                   public PortalDetectorStrategy::Delegate {
@@ -259,6 +258,11 @@
   // Number of detection attempts in a row with NO RESPONSE result.
   int no_response_result_count_ = 0;
 
+  // Must be declared before |notification_controller_| as
+  // ~NetworkPortalNotificationController() calls
+  // NetworkPortalDetectorImpl::RemoveObserver() which uses this.
+  SEQUENCE_CHECKER(sequence_checker_);
+
   // UI notification controller about captive portal state.
   std::unique_ptr<NetworkPortalNotificationController> notification_controller_;
 
diff --git a/chrome/browser/chromeos/ui/accessibility_cursor_ring_layer.cc b/chrome/browser/chromeos/ui/accessibility_cursor_ring_layer.cc
index 7089873..515c5952 100644
--- a/chrome/browser/chromeos/ui/accessibility_cursor_ring_layer.cc
+++ b/chrome/browser/chromeos/ui/accessibility_cursor_ring_layer.cc
@@ -5,7 +5,6 @@
 #include "chrome/browser/chromeos/ui/accessibility_cursor_ring_layer.h"
 
 #include "ash/shell_port.h"
-#include "ash/wm_window.h"
 #include "third_party/skia/include/core/SkPaint.h"
 #include "third_party/skia/include/core/SkPath.h"
 #include "ui/aura/window.h"
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 28e78c1..2cf800a 100644
--- a/chrome/browser/data_use_measurement/chrome_data_use_ascriber.cc
+++ b/chrome/browser/data_use_measurement/chrome_data_use_ascriber.cc
@@ -58,10 +58,6 @@
     const net::URLRequest& request) {
   DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
 
-  // TODO(ryansturm): Handle PlzNavigate (http://crbug/664233).
-  if (content::IsBrowserSideNavigationEnabled())
-    return nullptr;
-
   // If a DataUseRecorder has already been set as user data, then return that.
   auto* user_data = static_cast<DataUseRecorderEntryAsUserData*>(
       request.GetUserData(DataUseRecorderEntryAsUserData::kUserDataKey));
@@ -73,10 +69,6 @@
     net::URLRequest* request) {
   DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
 
-  // TODO(ryansturm): Handle PlzNavigate (http://crbug/664233).
-  if (content::IsBrowserSideNavigationEnabled())
-    return data_use_recorders_.end();
-
   // If a DataUseRecorder has already been set as user data, then return that.
   auto* user_data = static_cast<DataUseRecorderEntryAsUserData*>(
       request->GetUserData(DataUseRecorderEntryAsUserData::kUserDataKey));
@@ -96,13 +88,38 @@
     return entry;
   }
 
+  if (!request->url().SchemeIsHTTPOrHTTPS())
+    return data_use_recorders_.end();
+
+  const content::ResourceRequestInfo* request_info =
+      content::ResourceRequestInfo::ForRequest(request);
+  if (!request_info ||
+      request_info->GetGlobalRequestID() == content::GlobalRequestID()) {
+    // Create a new DataUseRecorder for all non-content initiated requests.
+    DataUseRecorderEntry entry =
+        CreateNewDataUseRecorder(request, DataUse::TrafficType::UNKNOWN);
+    DataUse& data_use = entry->data_use();
+    data_use.set_url(request->url());
+    return entry;
+  }
+
+  if (request_info->GetResourceType() == content::RESOURCE_TYPE_MAIN_FRAME) {
+    DataUseRecorderEntry new_entry =
+        CreateNewDataUseRecorder(request, DataUse::TrafficType::USER_TRAFFIC);
+    new_entry->set_main_frame_request_id(request_info->GetGlobalRequestID());
+    pending_navigation_data_use_map_.insert(
+        std::make_pair(request_info->GetGlobalRequestID(), new_entry));
+    return new_entry;
+  }
+
   int render_process_id = -1;
   int render_frame_id = -1;
   bool has_valid_frame = content::ResourceRequestInfo::GetRenderFrameForRequest(
       request, &render_process_id, &render_frame_id);
   if (has_valid_frame &&
       render_frame_id != SpecialRoutingIDs::MSG_ROUTING_NONE) {
-    DCHECK(render_process_id >= 0 || render_frame_id >= 0);
+    DCHECK(content::IsBrowserSideNavigationEnabled() ||
+           render_process_id >= 0 || render_frame_id >= 0);
 
     // Browser tests may not set up DataUseWebContentsObservers in which case
     // this class never sees navigation and frame events so DataUseRecorders
@@ -111,37 +128,17 @@
     // URLRequests racing the frame create events.
     // TODO(kundaji): Add UMA.
     RenderFrameHostID frame_key(render_process_id, render_frame_id);
-    auto main_frame_key_iter = subframe_to_mainframe_map_.find(frame_key);
+    const auto main_frame_key_iter = subframe_to_mainframe_map_.find(frame_key);
     if (main_frame_key_iter == subframe_to_mainframe_map_.end()) {
       return data_use_recorders_.end();
     }
-    auto frame_iter =
+    const auto frame_iter =
         main_render_frame_data_use_map_.find(main_frame_key_iter->second);
     if (frame_iter == main_render_frame_data_use_map_.end()) {
       return data_use_recorders_.end();
     }
 
-    const content::ResourceRequestInfo* request_info =
-        content::ResourceRequestInfo::ForRequest(request);
-    content::ResourceType resource_type =
-        request_info ? request_info->GetResourceType()
-                     : content::RESOURCE_TYPE_LAST_TYPE;
-
-    if (resource_type == content::RESOURCE_TYPE_MAIN_FRAME) {
-      content::GlobalRequestID navigation_key =
-          request_info->GetGlobalRequestID();
-
-      DataUseRecorderEntry new_entry =
-          CreateNewDataUseRecorder(request, DataUse::TrafficType::USER_TRAFFIC);
-      new_entry->set_main_frame_request_id(navigation_key);
-      pending_navigation_data_use_map_.insert(
-          std::make_pair(navigation_key, new_entry));
-
-      return new_entry;
-    }
-
-    DCHECK(frame_iter != main_render_frame_data_use_map_.end());
-    auto entry = frame_iter->second;
+    const auto entry = frame_iter->second;
     request->SetUserData(
         DataUseRecorderEntryAsUserData::kUserDataKey,
         base::MakeUnique<DataUseRecorderEntryAsUserData>(entry));
@@ -190,7 +187,7 @@
   // TODO(rajendrant): GetDataUseRecorder is sufficient and
   // GetOrCreateDataUseRecorderEntry is not needed. The entry gets created in
   // DataUseAscriber::OnBeforeUrlRequest().
-  DataUseRecorderEntry entry = GetOrCreateDataUseRecorderEntry(request);
+  const DataUseRecorderEntry entry = GetOrCreateDataUseRecorderEntry(request);
 
   if (entry == data_use_recorders_.end())
     return;
@@ -198,26 +195,30 @@
   for (auto& observer : observers_)
     observer.OnPageResourceLoad(*request, &entry->data_use());
 
-  RenderFrameHostID frame_key = entry->main_frame_id();
-  auto frame_iter = main_render_frame_data_use_map_.find(frame_key);
-  bool is_in_render_frame_map =
-      frame_iter != main_render_frame_data_use_map_.end() &&
-      frame_iter->second->HasPendingURLRequest(request);
-
+  bool will_datause_complete = false;
   const content::ResourceRequestInfo* request_info =
       content::ResourceRequestInfo::ForRequest(request);
-  bool is_in_pending_navigation_map =
-      request_info &&
-      request_info->GetResourceType() == content::RESOURCE_TYPE_MAIN_FRAME &&
-      pending_navigation_data_use_map_.find(entry->main_frame_request_id()) !=
-          pending_navigation_data_use_map_.end();
+
+  if (request_info &&
+      request_info->GetResourceType() == content::RESOURCE_TYPE_MAIN_FRAME) {
+    will_datause_complete =
+        pending_navigation_data_use_map_.find(entry->main_frame_request_id()) ==
+        pending_navigation_data_use_map_.end();
+  } else {
+    // Non-mainframe, Services, and other requests.
+    const auto frame_iter =
+        main_render_frame_data_use_map_.find(entry->main_frame_id());
+    will_datause_complete =
+        frame_iter == main_render_frame_data_use_map_.end() ||
+        !frame_iter->second->HasPendingURLRequest(request);
+  }
 
   DataUseAscriber::OnUrlRequestDestroyed(request);
   request->RemoveUserData(DataUseRecorderEntryAsUserData::kUserDataKey);
 
-  if (entry->IsDataUseComplete() && !is_in_render_frame_map &&
-      !is_in_pending_navigation_map) {
+  if (entry->IsDataUseComplete() && will_datause_complete) {
     NotifyDataUseCompleted(entry);
+    main_render_frame_data_use_map_.erase(entry->main_frame_id());
     data_use_recorders_.erase(entry);
   }
 }
@@ -228,9 +229,6 @@
                                                int main_render_frame_id) {
   DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
 
-  if (content::IsBrowserSideNavigationEnabled())
-    return;
-
   if (main_render_process_id != -1 && main_render_frame_id != -1) {
     // Create an entry in |subframe_to_mainframe_map_| for this frame mapped to
     // it's parent frame.
@@ -259,19 +257,19 @@
                                                int main_render_frame_id) {
   DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
 
-  if (content::IsBrowserSideNavigationEnabled())
-    return;
-
   RenderFrameHostID key(render_process_id, render_frame_id);
 
   if (main_render_process_id == -1 && main_render_frame_id == -1) {
     auto frame_iter = main_render_frame_data_use_map_.find(key);
-    DataUseRecorderEntry entry = frame_iter->second;
-    if (entry->IsDataUseComplete()) {
-      NotifyDataUseCompleted(entry);
-      data_use_recorders_.erase(entry);
+
+    if (main_render_frame_data_use_map_.end() != frame_iter) {
+      DataUseRecorderEntry entry = frame_iter->second;
+      if (entry->IsDataUseComplete()) {
+        NotifyDataUseCompleted(entry);
+        data_use_recorders_.erase(entry);
+      }
+      main_render_frame_data_use_map_.erase(frame_iter);
     }
-    main_render_frame_data_use_map_.erase(frame_iter);
   }
   subframe_to_mainframe_map_.erase(key);
   visible_main_render_frames_.erase(key);
@@ -328,7 +326,7 @@
     // No pending navigation entry to worry about. However, the old frame entry
     // must be removed from frame map, and possibly marked complete and deleted.
     if (frame_it != main_render_frame_data_use_map_.end()) {
-      DataUseRecorderEntry old_frame_entry = frame_it->second;
+      const DataUseRecorderEntry old_frame_entry = frame_it->second;
       DataUse::TrafficType old_traffic_type =
           old_frame_entry->data_use().traffic_type();
       old_frame_entry->set_page_transition(page_transition);
@@ -336,6 +334,7 @@
       NotifyPageLoadCommit(old_frame_entry);
       if (old_frame_entry->IsDataUseComplete()) {
         NotifyDataUseCompleted(old_frame_entry);
+        main_render_frame_data_use_map_.erase(old_frame_entry->main_frame_id());
         data_use_recorders_.erase(old_frame_entry);
       }
 
@@ -348,7 +347,7 @@
     return;
   }
 
-  DataUseRecorderEntry entry = navigation_iter->second;
+  const DataUseRecorderEntry entry = navigation_iter->second;
   pending_navigation_data_use_map_.erase(navigation_iter);
   entry->set_main_frame_id(mainframe);
 
@@ -359,6 +358,7 @@
     NotifyPageLoadCommit(entry);
     if (entry->IsDataUseComplete()) {
       NotifyDataUseCompleted(entry);
+      main_render_frame_data_use_map_.erase(entry->main_frame_id());
       data_use_recorders_.erase(entry);
     }
     return;
@@ -382,9 +382,6 @@
 
     data_use_recorders_.erase(entry);
   } else {
-    // Navigation is not same page, so remove old entry from
-    // |main_render_frame_data_use_map_|, possibly marking it complete.
-    main_render_frame_data_use_map_.erase(frame_it);
     if (old_frame_entry->IsDataUseComplete()) {
       NotifyDataUseCompleted(old_frame_entry);
       data_use_recorders_.erase(old_frame_entry);
@@ -405,6 +402,7 @@
       data_use.set_url(gurl);
     }
 
+    main_render_frame_data_use_map_.erase(frame_it);
     main_render_frame_data_use_map_.insert(std::make_pair(mainframe, entry));
   }
 }
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 00be665..a2bf680 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
@@ -92,32 +92,28 @@
 };
 
 TEST_F(ChromeDataUseAscriberTest, NoRecorderWithoutFrame) {
-  if (content::IsBrowserSideNavigationEnabled())
-    return;
-
   std::unique_ptr<net::URLRequest> request = CreateNewRequest(
       "http://test.com", true, kRequestId, kRenderProcessId, kRenderFrameId);
 
-  // Main frame request should not cause a recorder to be created, since the
-  // frame does not exist.
+  // Main frame request causes a recorder to be created.
   ascriber()->OnBeforeUrlRequest(request.get());
-  EXPECT_EQ(0u, recorders().size());
+  EXPECT_EQ(1u, recorders().size());
 
   // Frame is created.
   ascriber()->RenderFrameCreated(kRenderProcessId, kRenderFrameId, -1, -1);
-  EXPECT_EQ(1u, recorders().size());
+  EXPECT_EQ(2u, recorders().size());
 
-  // Request should cause a recorder to be created.
+  // Same mainframe request should not cause another recorder to be created.
   ascriber()->OnBeforeUrlRequest(request.get());
   EXPECT_EQ(2u, recorders().size());
 
   ascriber()->RenderFrameDeleted(kRenderProcessId, kRenderFrameId, -1, -1);
+  ascriber()->OnUrlRequestDestroyed(request.get());
+
+  EXPECT_EQ(1u, recorders().size());
 }
 
 TEST_F(ChromeDataUseAscriberTest, RenderFrameShownAndHidden) {
-  if (content::IsBrowserSideNavigationEnabled())
-    return;
-
   std::unique_ptr<net::URLRequest> request = CreateNewRequest(
       "http://test.com", true, kRequestId, kRenderProcessId, kRenderFrameId);
 
@@ -141,9 +137,6 @@
 }
 
 TEST_F(ChromeDataUseAscriberTest, RenderFrameHiddenAndShown) {
-  if (content::IsBrowserSideNavigationEnabled())
-    return;
-
   std::unique_ptr<net::URLRequest> request = CreateNewRequest(
       "http://test.com", true, kRequestId, kRenderProcessId, kRenderFrameId);
 
@@ -167,9 +160,6 @@
 }
 
 TEST_F(ChromeDataUseAscriberTest, RenderFrameHostChanged) {
-  if (content::IsBrowserSideNavigationEnabled())
-    return;
-
   std::unique_ptr<net::URLRequest> request = CreateNewRequest(
       "http://test.com", true, kRequestId, kRenderProcessId, kRenderFrameId);
 
@@ -197,9 +187,6 @@
 }
 
 TEST_F(ChromeDataUseAscriberTest, MainFrameNavigation) {
-  if (content::IsBrowserSideNavigationEnabled())
-    return;
-
   std::unique_ptr<net::URLRequest> request = CreateNewRequest(
       "http://test.com", true, kRequestId, kRenderProcessId, kRenderFrameId);
 
@@ -241,9 +228,6 @@
 }
 
 TEST_F(ChromeDataUseAscriberTest, FailedMainFrameNavigation) {
-  if (content::IsBrowserSideNavigationEnabled())
-    return;
-
   std::unique_ptr<net::URLRequest> request = CreateNewRequest(
       "http://test.com", true, kRequestId, kRenderProcessId, kRenderFrameId);
 
@@ -267,9 +251,6 @@
 
 TEST_F(ChromeDataUseAscriberTest, PageLoadObserverNotified) {
   // TODO(rajendrant): Handle PlzNavigate (http://crbug/664233).
-  if (content::IsBrowserSideNavigationEnabled())
-    return;
-
   MockPageLoadObserver mock_observer;
   ascriber()->AddObserver(&mock_observer);
 
diff --git a/chrome/browser/download/download_service_factory.cc b/chrome/browser/download/download_service_factory.cc
index aae4341..7689662 100644
--- a/chrome/browser/download/download_service_factory.cc
+++ b/chrome/browser/download/download_service_factory.cc
@@ -5,6 +5,7 @@
 #include "chrome/browser/download/download_service_factory.h"
 
 #include "base/files/file_path.h"
+#include "base/memory/ptr_util.h"
 #include "base/memory/singleton.h"
 #include "base/sequenced_task_runner.h"
 #include "base/task_scheduler/post_task.h"
@@ -12,6 +13,7 @@
 #include "chrome/browser/profiles/incognito_helpers.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/common/chrome_constants.h"
+#include "components/download/public/clients.h"
 #include "components/download/public/download_service.h"
 #include "components/keyed_service/content/browser_context_dependency_manager.h"
 #include "content/public/browser/browser_context.h"
@@ -49,8 +51,9 @@
         profile->GetPath().Append(chrome::kDownloadServiceStorageDirname);
   }
 
-  download::DownloadService* service =
-      download::DownloadService::Create(storage_dir, background_task_runner);
+  download::DownloadService* service = download::DownloadService::Create(
+      base::MakeUnique<download::DownloadClientMap>(), storage_dir,
+      background_task_runner);
 
   // TODO(dtrainor): Register all clients here.
   return service;
diff --git a/chrome/browser/extensions/api/developer_private/developer_private_api.cc b/chrome/browser/extensions/api/developer_private/developer_private_api.cc
index 81ec02f..94d1f9042c 100644
--- a/chrome/browser/extensions/api/developer_private/developer_private_api.cc
+++ b/chrome/browser/extensions/api/developer_private/developer_private_api.cc
@@ -22,7 +22,6 @@
 #include "chrome/browser/extensions/api/developer_private/entry_picker.h"
 #include "chrome/browser/extensions/api/developer_private/extension_info_generator.h"
 #include "chrome/browser/extensions/api/developer_private/show_permissions_dialog_helper.h"
-#include "chrome/browser/extensions/api/extension_action/extension_action_api.h"
 #include "chrome/browser/extensions/devtools_util.h"
 #include "chrome/browser/extensions/extension_commands_global_registry.h"
 #include "chrome/browser/extensions/extension_service.h"
@@ -243,7 +242,6 @@
       error_console_observer_(this),
       process_manager_observer_(this),
       app_window_registry_observer_(this),
-      extension_action_api_observer_(this),
       warning_service_observer_(this),
       extension_prefs_observer_(this),
       extension_management_observer_(this),
@@ -255,7 +253,6 @@
   error_console_observer_.Add(ErrorConsole::Get(profile));
   process_manager_observer_.Add(ProcessManager::Get(profile));
   app_window_registry_observer_.Add(AppWindowRegistry::Get(profile));
-  extension_action_api_observer_.Add(ExtensionActionAPI::Get(profile));
   warning_service_observer_.Add(WarningService::Get(profile));
   extension_prefs_observer_.Add(ExtensionPrefs::Get(profile));
   extension_management_observer_.Add(
@@ -371,12 +368,6 @@
                             extension_id);
 }
 
-void DeveloperPrivateEventRouter::OnExtensionActionVisibilityChanged(
-    const std::string& extension_id,
-    bool is_now_visible) {
-  BroadcastItemStateChanged(developer::EVENT_TYPE_PREFS_CHANGED, extension_id);
-}
-
 void DeveloperPrivateEventRouter::OnExtensionDisableReasonsChanged(
     const std::string& extension_id, int disable_reasons) {
   BroadcastItemStateChanged(developer::EVENT_TYPE_PREFS_CHANGED, extension_id);
@@ -721,11 +712,6 @@
     }
     modifier.SetAllowedOnAllUrls(*update.run_on_all_urls);
   }
-  if (update.show_action_button) {
-    ExtensionActionAPI::Get(browser_context())->SetBrowserActionVisibility(
-        extension->id(),
-        *update.show_action_button);
-  }
 
   return RespondNow(NoArguments());
 }
diff --git a/chrome/browser/extensions/api/developer_private/developer_private_api.h b/chrome/browser/extensions/api/developer_private/developer_private_api.h
index 7b0d29f8..56dc506 100644
--- a/chrome/browser/extensions/api/developer_private/developer_private_api.h
+++ b/chrome/browser/extensions/api/developer_private/developer_private_api.h
@@ -13,7 +13,6 @@
 #include "base/scoped_observer.h"
 #include "chrome/browser/extensions/api/commands/command_service.h"
 #include "chrome/browser/extensions/api/developer_private/entry_picker.h"
-#include "chrome/browser/extensions/api/extension_action/extension_action_api.h"
 #include "chrome/browser/extensions/api/file_system/file_system_api.h"
 #include "chrome/browser/extensions/chrome_extension_function.h"
 #include "chrome/browser/extensions/error_console/error_console.h"
@@ -55,7 +54,6 @@
                                     public ProcessManagerObserver,
                                     public AppWindowRegistry::Observer,
                                     public CommandService::Observer,
-                                    public ExtensionActionAPI::Observer,
                                     public ExtensionPrefsObserver,
                                     public ExtensionManagement::Observer,
                                     public WarningService::Observer {
@@ -103,10 +101,6 @@
   void OnExtensionCommandRemoved(const std::string& extension_id,
                                  const Command& removed_command) override;
 
-  // ExtensionActionAPI::Observer:
-  void OnExtensionActionVisibilityChanged(const std::string& extension_id,
-                                          bool is_now_visible) override;
-
   // ExtensionPrefsObserver:
   void OnExtensionDisableReasonsChanged(const std::string& extension_id,
                                         int disable_reasons) override;
@@ -137,8 +131,6 @@
       process_manager_observer_;
   ScopedObserver<AppWindowRegistry, AppWindowRegistry::Observer>
       app_window_registry_observer_;
-  ScopedObserver<ExtensionActionAPI, ExtensionActionAPI::Observer>
-      extension_action_api_observer_;
   ScopedObserver<WarningService, WarningService::Observer>
       warning_service_observer_;
   ScopedObserver<ExtensionPrefs, ExtensionPrefsObserver>
diff --git a/chrome/browser/extensions/api/developer_private/extension_info_generator.cc b/chrome/browser/extensions/api/developer_private/extension_info_generator.cc
index a9f4ffc..e0dcc70 100644
--- a/chrome/browser/extensions/api/developer_private/extension_info_generator.cc
+++ b/chrome/browser/extensions/api/developer_private/extension_info_generator.cc
@@ -311,12 +311,6 @@
   std::unique_ptr<developer::ExtensionInfo> info(
       new developer::ExtensionInfo());
 
-  // Don't consider the button hidden with the redesign, because "hidden"
-  // buttons are now just hidden in the wrench menu.
-  info->action_button_hidden =
-      !extension_action_api_->GetBrowserActionVisibility(extension.id()) &&
-      !FeatureSwitch::extension_action_redesign()->IsEnabled();
-
   // Blacklist text.
   int blacklist_text = -1;
   switch (extension_prefs_->GetExtensionBlacklistState(extension.id())) {
diff --git a/chrome/browser/io_thread.cc b/chrome/browser/io_thread.cc
index f863d07..a730d14 100644
--- a/chrome/browser/io_thread.cc
+++ b/chrome/browser/io_thread.cc
@@ -618,10 +618,11 @@
         command_line.GetSwitchValueASCII(switches::kHostRules));
     TRACE_EVENT_END0("startup", "IOThread::InitAsync:SetRulesFromString");
   }
-  params_.host_mapping_rules = *globals_->host_mapping_rules.get();
+
+  session_params_.host_mapping_rules = *globals_->host_mapping_rules.get();
   globals_->enable_brotli =
       base::FeatureList::IsEnabled(features::kBrotliEncoding);
-  params_.enable_token_binding =
+  session_params_.enable_token_binding =
       base::FeatureList::IsEnabled(features::kTokenBinding);
 
   // Check for OS support of TCP FastOpen, and turn it on for all connections if
@@ -635,7 +636,7 @@
 
   ConfigureParamsFromFieldTrialsAndCommandLine(
       command_line, is_quic_allowed_by_policy_,
-      http_09_on_non_default_ports_enabled_, &params_);
+      http_09_on_non_default_ports_enabled_, &session_params_);
 
 #if defined(OS_MACOSX)
   // Start observing Keychain events. This needs to be done on the UI thread,
@@ -777,11 +778,11 @@
 }
 
 const net::HttpNetworkSession::Params& IOThread::NetworkSessionParams() const {
-  return params_;
+  return session_params_;
 }
 
 void IOThread::DisableQuic() {
-  params_.enable_quic = false;
+  session_params_.enable_quic = false;
 
   if (globals_->system_request_context_storage)
     globals_->system_request_context_storage->http_network_session()
@@ -877,6 +878,7 @@
   context->set_cert_verifier(globals_->cert_verifier.get());
   context->set_cert_transparency_verifier(
       globals_->cert_transparency_verifier.get());
+
   context_storage->set_ct_policy_enforcer(
       base::MakeUnique<net::CTPolicyEnforcer>());
 
@@ -887,12 +889,13 @@
       std::move(system_proxy_config_service_), command_line,
       WpadQuickCheckEnabled(), PacHttpsUrlStrippingEnabled()));
 
-  net::HttpNetworkSession::Params system_params(params_);
+  net::HttpNetworkSession::Context session_context;
   net::URLRequestContextBuilder::SetHttpNetworkSessionComponents(
-      context, &system_params);
+      context, &session_context);
 
   context_storage->set_http_network_session(
-      base::MakeUnique<net::HttpNetworkSession>(system_params));
+      base::MakeUnique<net::HttpNetworkSession>(session_params_,
+                                                session_context));
   context_storage->set_http_transaction_factory(
       base::MakeUnique<net::HttpNetworkLayer>(
           context_storage->http_network_session()));
diff --git a/chrome/browser/io_thread.h b/chrome/browser/io_thread.h
index 2a0b606..4f2db70 100644
--- a/chrome/browser/io_thread.h
+++ b/chrome/browser/io_thread.h
@@ -291,7 +291,7 @@
 
   Globals* globals_;
 
-  net::HttpNetworkSession::Params params_;
+  net::HttpNetworkSession::Params session_params_;
 
   // Observer that logs network changes to the ChromeNetLog.
   std::unique_ptr<net::LoggingNetworkChangeObserver> network_change_observer_;
diff --git a/chrome/browser/metrics/thread_watcher.cc b/chrome/browser/metrics/thread_watcher.cc
index b64c70d..d0d4b7d 100644
--- a/chrome/browser/metrics/thread_watcher.cc
+++ b/chrome/browser/metrics/thread_watcher.cc
@@ -35,20 +35,6 @@
 
 using content::BrowserThread;
 
-namespace {
-
-base::StackSamplingProfiler::SamplingParams GetJankTimeBombSamplingParams() {
-  base::StackSamplingProfiler::SamplingParams params;
-  params.initial_delay = base::TimeDelta::FromMilliseconds(0);
-  params.bursts = 1;
-  // 5 seconds at 10Hz.
-  params.samples_per_burst = 50;
-  params.sampling_interval = base::TimeDelta::FromMilliseconds(100);
-  return params;
-}
-
-}  // namespace
-
 // ThreadWatcher methods and members.
 ThreadWatcher::ThreadWatcher(const WatchingParams& params)
     : thread_id_(params.thread_id),
@@ -929,47 +915,6 @@
     g_startup_timebomb_->Disarm();
 }
 
-// JankTimeBomb methods and members.
-//
-JankTimeBomb::JankTimeBomb(base::TimeDelta duration,
-                           metrics::CallStackProfileParams::Thread thread)
-    : thread_(thread), weak_ptr_factory_(this) {
-  if (IsEnabled()) {
-    WatchDogThread::PostDelayedTask(
-        FROM_HERE,
-        base::Bind(&JankTimeBomb::Alarm,
-                   weak_ptr_factory_.GetWeakPtr(),
-                   base::PlatformThread::CurrentId()),
-        duration);
-  }
-}
-
-JankTimeBomb::~JankTimeBomb() {
-}
-
-bool JankTimeBomb::IsEnabled() const {
-  version_info::Channel channel = chrome::GetChannel();
-  return channel == version_info::Channel::UNKNOWN ||
-      channel == version_info::Channel::CANARY ||
-      channel == version_info::Channel::DEV;
-}
-
-void JankTimeBomb::Alarm(base::PlatformThreadId thread_id) {
-  DCHECK(WatchDogThread::CurrentlyOnWatchDogThread());
-  sampling_profiler_.reset(new base::StackSamplingProfiler(
-      thread_id,
-      GetJankTimeBombSamplingParams(),
-      metrics::CallStackProfileMetricsProvider::GetProfilerCallback(
-          metrics::CallStackProfileParams(
-              metrics::CallStackProfileParams::BROWSER_PROCESS,
-              thread_,
-              metrics::CallStackProfileParams::JANKY_TASK,
-              metrics::CallStackProfileParams::PRESERVE_ORDER))));
-  // Use synchronous profiler. It will automatically stop collection when
-  // destroyed.
-  sampling_profiler_->Start();
-}
-
 // ShutdownWatcherHelper methods and members.
 //
 // ShutdownWatcherHelper is a wrapper class for detecting hangs during
diff --git a/chrome/browser/metrics/thread_watcher.h b/chrome/browser/metrics/thread_watcher.h
index 4c0d414a..4a50cff 100644
--- a/chrome/browser/metrics/thread_watcher.h
+++ b/chrome/browser/metrics/thread_watcher.h
@@ -55,7 +55,6 @@
 #include "base/memory/weak_ptr.h"
 #include "base/message_loop/message_loop.h"
 #include "base/metrics/histogram.h"
-#include "base/profiler/stack_sampling_profiler.h"
 #include "base/single_thread_task_runner.h"
 #include "base/synchronization/lock.h"
 #include "base/threading/platform_thread.h"
@@ -588,8 +587,6 @@
   void CleanUp() override;
 
  private:
-  friend class JankTimeBombTest;
-
   // This method returns true if Init() is called.
   bool Started() const;
 
@@ -642,39 +639,6 @@
   DISALLOW_COPY_AND_ASSIGN(StartupTimeBomb);
 };
 
-// This is a wrapper class for metrics logging of the stack of a janky method.
-class JankTimeBomb {
- public:
-  // This is instantiated when the jank needs to be detected in a method. Posts
-  // an Alarm callback task on WatchDogThread with |duration| as the delay. This
-  // can be called on any thread, but the thread's identity should be provided
-  // in |thread|.
-  JankTimeBomb(base::TimeDelta duration,
-               metrics::CallStackProfileParams::Thread thread);
-  virtual ~JankTimeBomb();
-
-  // Returns true if JankTimeBomb is enabled.
-  bool IsEnabled() const;
-
- protected:
-  // Logs the call stack of given thread_id's janky method. This runs on
-  // WatchDogThread. This is overridden in tests to prevent the metrics logging.
-  virtual void Alarm(base::PlatformThreadId thread_id);
-
- private:
-  // The thread that instantiated this object.
-  const metrics::CallStackProfileParams::Thread thread_;
-
-  // A profiler that periodically samples stack traces. Used to sample jank
-  // behavior.
-  std::unique_ptr<base::StackSamplingProfiler> sampling_profiler_;
-
-  // We use this factory during creation and starting timer.
-  base::WeakPtrFactory<JankTimeBomb> weak_ptr_factory_;
-
-  DISALLOW_COPY_AND_ASSIGN(JankTimeBomb);
-};
-
 // This is a wrapper class for detecting hangs during shutdown.
 class ShutdownWatcherHelper {
  public:
diff --git a/chrome/browser/metrics/thread_watcher_unittest.cc b/chrome/browser/metrics/thread_watcher_unittest.cc
index d4dd444..20349ba 100644
--- a/chrome/browser/metrics/thread_watcher_unittest.cc
+++ b/chrome/browser/metrics/thread_watcher_unittest.cc
@@ -747,87 +747,3 @@
              true /* stopped */,
              "Stopped");
 }
-
-class TestingJankTimeBomb : public JankTimeBomb {
- public:
-  explicit TestingJankTimeBomb(base::TimeDelta duration)
-      : JankTimeBomb(duration, metrics::CallStackProfileParams::UI_THREAD),
-        thread_id_(base::PlatformThread::CurrentId()),
-        alarm_invoked_(false) {
-  }
-
-  ~TestingJankTimeBomb() override {}
-
-  void Alarm(base::PlatformThreadId thread_id) override {
-    EXPECT_EQ(thread_id_, thread_id);
-    alarm_invoked_ = true;
-  }
-
-  bool alarm_invoked() const { return alarm_invoked_; }
-
- private:
-  const base::PlatformThreadId thread_id_;
-  bool alarm_invoked_;
-
-  DISALLOW_COPY_AND_ASSIGN(TestingJankTimeBomb);
-};
-
-class JankTimeBombTest : public ::testing::Test {
- public:
-  JankTimeBombTest() {
-    watchdog_thread_.reset(new WatchDogThread());
-    watchdog_thread_->Start();
-    EXPECT_TRUE(watchdog_thread_->IsRunning());
-    SPIN_FOR_TIMEDELTA_OR_UNTIL_TRUE(TimeDelta::FromMinutes(1),
-                                     watchdog_thread_->Started());
-    WaitForWatchDogThreadPostTask();
-  }
-
-  ~JankTimeBombTest() override {
-    watchdog_thread_.reset();
-  }
-
-  static void WaitForWatchDogThreadPostTask() {
-    base::WaitableEvent watchdog_thread_event(
-        base::WaitableEvent::ResetPolicy::AUTOMATIC,
-        base::WaitableEvent::InitialState::NOT_SIGNALED);
-    PostAndWaitForWatchdogThread(&watchdog_thread_event);
-  }
-
- private:
-  static void OnJankTimeBombTask(base::WaitableEvent* event) {
-    event->Signal();
-  }
-
-  static void PostAndWaitForWatchdogThread(base::WaitableEvent* event) {
-    WatchDogThread::PostDelayedTask(
-        FROM_HERE,
-        base::Bind(&JankTimeBombTest::OnJankTimeBombTask, event),
-        base::TimeDelta::FromSeconds(0));
-
-    event->Wait();
-  }
-
-  std::unique_ptr<WatchDogThread> watchdog_thread_;
-
-  DISALLOW_COPY_AND_ASSIGN(JankTimeBombTest);
-};
-
-// JankTimeBomb minimal constructor/destructor test..
-TEST_F(JankTimeBombTest, StartShutdownTest) {
-  // Disarm's itself when it goes out of scope.
-  TestingJankTimeBomb timebomb1(TimeDelta::FromMinutes(5));
-  TestingJankTimeBomb timebomb2(TimeDelta::FromMinutes(5));
-  WaitForWatchDogThreadPostTask();
-  EXPECT_FALSE(timebomb1.alarm_invoked());
-  EXPECT_FALSE(timebomb2.alarm_invoked());
-}
-
-TEST_F(JankTimeBombTest, ArmTest) {
-  // Test firing of Alarm by passing empty delay.
-  TestingJankTimeBomb timebomb((base::TimeDelta()));
-  if (!timebomb.IsEnabled())
-    return;
-  WaitForWatchDogThreadPostTask();
-  EXPECT_TRUE(timebomb.alarm_invoked());
-}
diff --git a/chrome/browser/notifications/native_notification_display_service.cc b/chrome/browser/notifications/native_notification_display_service.cc
index 2ffcd75..e791a8e1 100644
--- a/chrome/browser/notifications/native_notification_display_service.cc
+++ b/chrome/browser/notifications/native_notification_display_service.cc
@@ -171,11 +171,6 @@
   notification_handlers_[notification_type] = std::move(handler);
 }
 
-void NativeNotificationDisplayService::RemoveNotificationHandler(
-    NotificationCommon::Type notification_type) {
-  notification_handlers_.erase(notification_type);
-}
-
 NotificationHandler* NativeNotificationDisplayService::GetNotificationHandler(
     NotificationCommon::Type notification_type) {
   DCHECK(notification_handlers_.find(notification_type) !=
diff --git a/chrome/browser/notifications/native_notification_display_service.h b/chrome/browser/notifications/native_notification_display_service.h
index b02bac9..0ba2220 100644
--- a/chrome/browser/notifications/native_notification_display_service.h
+++ b/chrome/browser/notifications/native_notification_display_service.h
@@ -56,10 +56,6 @@
   // for |notification_type|.
   void AddNotificationHandler(NotificationCommon::Type notification_type,
                               std::unique_ptr<NotificationHandler> handler);
-
-  // Removes an implementation added via |AddNotificationHandler|.
-  void RemoveNotificationHandler(NotificationCommon::Type notification_type);
-
  private:
   NotificationHandler* GetNotificationHandler(
       NotificationCommon::Type notification_type);
diff --git a/chrome/browser/page_load_metrics/metrics_web_contents_observer.cc b/chrome/browser/page_load_metrics/metrics_web_contents_observer.cc
index fe9f2818..c3d51772 100644
--- a/chrome/browser/page_load_metrics/metrics_web_contents_observer.cc
+++ b/chrome/browser/page_load_metrics/metrics_web_contents_observer.cc
@@ -103,10 +103,20 @@
   return metrics;
 }
 
-MetricsWebContentsObserver::~MetricsWebContentsObserver() {
+MetricsWebContentsObserver::~MetricsWebContentsObserver() {}
+
+void MetricsWebContentsObserver::WebContentsDestroyed() {
   // TODO(csharrison): Use a more user-initiated signal for CLOSE.
   NotifyPageEndAllLoads(END_CLOSE, UserInitiatedInfo::NotUserInitiated());
 
+  // We tear down PageLoadTrackers in WebContentsDestroyed, rather than in the
+  // destructor, since |web_contents()| returns nullptr in the destructor, and
+  // PageLoadMetricsObservers can cause code to execute that wants to be able to
+  // access the current WebContents.
+  committed_load_ = nullptr;
+  provisional_loads_.clear();
+  aborted_provisional_loads_.clear();
+
   for (auto& observer : testing_observers_)
     observer.OnGoingAway();
 }
diff --git a/chrome/browser/page_load_metrics/metrics_web_contents_observer.h b/chrome/browser/page_load_metrics/metrics_web_contents_observer.h
index ac5c21b..27bc8c8 100644
--- a/chrome/browser/page_load_metrics/metrics_web_contents_observer.h
+++ b/chrome/browser/page_load_metrics/metrics_web_contents_observer.h
@@ -97,6 +97,7 @@
   void MediaStartedPlaying(
       const content::WebContentsObserver::MediaPlayerInfo& video_type,
       const content::WebContentsObserver::MediaPlayerId& id) override;
+  void WebContentsDestroyed() override;
 
   // These methods are forwarded from the MetricsNavigationThrottle.
   void WillStartNavigationRequest(content::NavigationHandle* navigation_handle);
diff --git a/chrome/browser/page_load_metrics/metrics_web_contents_observer_unittest.cc b/chrome/browser/page_load_metrics/metrics_web_contents_observer_unittest.cc
index 3a1b844d8..4c38023 100644
--- a/chrome/browser/page_load_metrics/metrics_web_contents_observer_unittest.cc
+++ b/chrome/browser/page_load_metrics/metrics_web_contents_observer_unittest.cc
@@ -9,14 +9,17 @@
 
 #include "base/macros.h"
 #include "base/memory/ptr_util.h"
+#include "base/memory/weak_ptr.h"
 #include "base/process/kill.h"
 #include "base/test/histogram_tester.h"
 #include "base/time/time.h"
+#include "base/timer/mock_timer.h"
 #include "chrome/browser/page_load_metrics/metrics_navigation_throttle.h"
 #include "chrome/browser/page_load_metrics/page_load_metrics_embedder_interface.h"
 #include "chrome/browser/page_load_metrics/page_load_metrics_observer.h"
 #include "chrome/browser/page_load_metrics/page_load_tracker.h"
 #include "chrome/common/page_load_metrics/page_load_metrics_messages.h"
+#include "chrome/common/page_load_metrics/test/weak_mock_timer.h"
 #include "chrome/common/url_constants.h"
 #include "chrome/test/base/chrome_render_view_host_test_harness.h"
 #include "content/public/browser/navigation_handle.h"
@@ -117,7 +120,8 @@
 };
 
 class TestPageLoadMetricsEmbedderInterface
-    : public PageLoadMetricsEmbedderInterface {
+    : public PageLoadMetricsEmbedderInterface,
+      public test::WeakMockTimerProvider {
  public:
   TestPageLoadMetricsEmbedderInterface() : is_ntp_(false) {}
 
@@ -130,6 +134,11 @@
     tracker->AddObserver(base::MakeUnique<FilteringPageLoadMetricsObserver>(
         &completed_filtered_urls_));
   }
+  std::unique_ptr<base::Timer> CreateTimer() override {
+    auto timer = base::MakeUnique<test::WeakMockTimer>();
+    SetMockTimer(timer->AsWeakPtr());
+    return std::move(timer);
+  }
   const std::vector<mojom::PageLoadTimingPtr>& updated_timings() const {
     return updated_timings_;
   }
@@ -160,6 +169,14 @@
   bool is_ntp_;
 };
 
+void PopulatePageLoadTiming(mojom::PageLoadTiming* timing) {
+  page_load_metrics::InitPageLoadTimingForTest(timing);
+  timing->navigation_start = base::Time::FromDoubleT(1);
+  timing->response_start = base::TimeDelta::FromMilliseconds(10);
+  timing->parse_timing->parse_start = base::TimeDelta::FromMilliseconds(20);
+  timing->document_timing->first_layout = base::TimeDelta::FromMilliseconds(30);
+}
+
 }  //  namespace
 
 class MetricsWebContentsObserverTest : public ChromeRenderViewHostTestHarness {
@@ -176,12 +193,30 @@
         ->NavigateAndCommit(GURL(url::kAboutBlankURL));
   }
 
+  // Returns the mock timer used for buffering updates in the
+  // PageLoadMetricsUpdateDispatcher.
+  base::MockTimer* GetMostRecentTimer() {
+    return embedder_interface_->GetMockTimer();
+  }
+
   void SimulateTimingUpdate(const mojom::PageLoadTiming& timing) {
     SimulateTimingUpdate(timing, web_contents()->GetMainFrame());
   }
 
   void SimulateTimingUpdate(const mojom::PageLoadTiming& timing,
                             content::RenderFrameHost* render_frame_host) {
+    SimulateTimingUpdateWithoutFiringDispatchTimer(timing, render_frame_host);
+    // If sending the timing update caused the PageLoadMetricsUpdateDispatcher
+    // to schedule a buffering timer, then fire it now so metrics are dispatched
+    // to observers.
+    base::MockTimer* mock_timer = GetMostRecentTimer();
+    if (mock_timer && mock_timer->IsRunning())
+      mock_timer->Fire();
+  }
+
+  void SimulateTimingUpdateWithoutFiringDispatchTimer(
+      const mojom::PageLoadTiming& timing,
+      content::RenderFrameHost* render_frame_host) {
     observer()->OnTimingUpdated(render_frame_host, timing,
                                 mojom::PageLoadMetadata());
   }
@@ -736,13 +771,7 @@
 
   // Dispatch a timing update for the child frame that includes a first paint.
   mojom::PageLoadTiming subframe_timing;
-  page_load_metrics::InitPageLoadTimingForTest(&subframe_timing);
-  subframe_timing.navigation_start = base::Time::FromDoubleT(2);
-  subframe_timing.response_start = base::TimeDelta::FromMilliseconds(10);
-  subframe_timing.parse_timing->parse_start =
-      base::TimeDelta::FromMilliseconds(20);
-  subframe_timing.document_timing->first_layout =
-      base::TimeDelta::FromMilliseconds(30);
+  PopulatePageLoadTiming(&subframe_timing);
   subframe_timing.paint_timing->first_paint =
       base::TimeDelta::FromMilliseconds(40);
   content::RenderFrameHostTester* subframe_tester =
@@ -798,4 +827,125 @@
   CheckNoErrorEvents();
 }
 
+// We buffer cross-frame paint updates to account for paint timings from
+// different frames arriving out of order.
+TEST_F(MetricsWebContentsObserverTest, OutOfOrderCrossFrameTiming2) {
+  // Dispatch a timing update for the main frame that includes a first
+  // paint. This should be buffered, with the dispatch timer running.
+  mojom::PageLoadTiming timing;
+  PopulatePageLoadTiming(&timing);
+  timing.paint_timing->first_paint = base::TimeDelta::FromMilliseconds(1000);
+  content::WebContentsTester* web_contents_tester =
+      content::WebContentsTester::For(web_contents());
+  web_contents_tester->NavigateAndCommit(GURL(kDefaultTestUrl));
+  SimulateTimingUpdateWithoutFiringDispatchTimer(timing, main_rfh());
+
+  EXPECT_TRUE(GetMostRecentTimer()->IsRunning());
+  ASSERT_EQ(0, CountUpdatedTimingReported());
+
+  content::RenderFrameHostTester* rfh_tester =
+      content::RenderFrameHostTester::For(main_rfh());
+
+  // Dispatch a timing update for a child frame that includes a first paint.
+  mojom::PageLoadTiming subframe_timing;
+  PopulatePageLoadTiming(&subframe_timing);
+  subframe_timing.paint_timing->first_paint =
+      base::TimeDelta::FromMilliseconds(500);
+  content::RenderFrameHost* subframe = rfh_tester->AppendChild("subframe");
+  content::RenderFrameHostTester* subframe_tester =
+      content::RenderFrameHostTester::For(subframe);
+  subframe_tester->SimulateNavigationStart(GURL(kDefaultTestUrl2));
+  subframe_tester->SimulateNavigationCommit(GURL(kDefaultTestUrl2));
+  SimulateTimingUpdateWithoutFiringDispatchTimer(subframe_timing, subframe);
+  subframe_tester->SimulateNavigationStop();
+
+  histogram_tester_.ExpectTotalCount(
+      page_load_metrics::internal::kHistogramOutOfOrderTiming, 1);
+
+  EXPECT_TRUE(GetMostRecentTimer()->IsRunning());
+  ASSERT_EQ(0, CountUpdatedTimingReported());
+
+  // At this point, the timing update is buffered, waiting for the timer to
+  // fire.
+  GetMostRecentTimer()->Fire();
+
+  // Firing the timer should produce a timing update. The update should be a
+  // merged view of the main frame timing, with a first paint timestamp from the
+  // subframe.
+  ASSERT_EQ(1, CountUpdatedTimingReported());
+  EXPECT_FALSE(timing.Equals(*updated_timings().back()));
+  EXPECT_TRUE(
+      updated_timings().back()->parse_timing->Equals(*timing.parse_timing));
+  EXPECT_TRUE(updated_timings().back()->document_timing->Equals(
+      *timing.document_timing));
+  EXPECT_FALSE(
+      updated_timings().back()->paint_timing->Equals(*timing.paint_timing));
+  EXPECT_TRUE(updated_timings().back()->paint_timing->first_paint);
+
+  // The first paint value should be the min of all received first paints, which
+  // in this case is the first paint from the subframe. Since it is offset by
+  // the subframe's navigation start, the received value should be >= the first
+  // paint value specified in the subframe.
+  EXPECT_GE(updated_timings().back()->paint_timing->first_paint,
+            subframe_timing.paint_timing->first_paint);
+  EXPECT_LT(updated_timings().back()->paint_timing->first_paint,
+            timing.paint_timing->first_paint);
+
+  base::TimeDelta initial_first_paint =
+      updated_timings().back()->paint_timing->first_paint.value();
+
+  // Dispatch a timing update for an additional child frame, with an earlier
+  // first paint time. This should cause an immediate update, without a timer
+  // delay.
+  subframe_timing.paint_timing->first_paint =
+      base::TimeDelta::FromMilliseconds(50);
+  content::RenderFrameHost* subframe2 = rfh_tester->AppendChild("subframe");
+  content::RenderFrameHostTester* subframe2_tester =
+      content::RenderFrameHostTester::For(subframe2);
+  subframe2_tester->SimulateNavigationStart(GURL(kDefaultTestUrl2));
+  subframe2_tester->SimulateNavigationCommit(GURL(kDefaultTestUrl2));
+  SimulateTimingUpdateWithoutFiringDispatchTimer(subframe_timing, subframe2);
+  subframe2_tester->SimulateNavigationStop();
+
+  base::TimeDelta updated_first_paint =
+      updated_timings().back()->paint_timing->first_paint.value();
+
+  EXPECT_FALSE(GetMostRecentTimer()->IsRunning());
+  ASSERT_EQ(2, CountUpdatedTimingReported());
+  EXPECT_LT(updated_first_paint, initial_first_paint);
+
+  histogram_tester_.ExpectTotalCount(
+      page_load_metrics::internal::kHistogramOutOfOrderTimingBuffered, 1);
+  histogram_tester_.ExpectBucketCount(
+      page_load_metrics::internal::kHistogramOutOfOrderTimingBuffered,
+      (initial_first_paint - updated_first_paint).InMilliseconds(), 1);
+
+  CheckNoErrorEvents();
+}
+
+TEST_F(MetricsWebContentsObserverTest, DispatchDelayedMetricsOnPageClose) {
+  mojom::PageLoadTiming timing;
+  PopulatePageLoadTiming(&timing);
+  timing.paint_timing->first_paint = base::TimeDelta::FromMilliseconds(1000);
+  content::WebContentsTester* web_contents_tester =
+      content::WebContentsTester::For(web_contents());
+  web_contents_tester->NavigateAndCommit(GURL(kDefaultTestUrl));
+  SimulateTimingUpdateWithoutFiringDispatchTimer(timing, main_rfh());
+
+  EXPECT_TRUE(GetMostRecentTimer()->IsRunning());
+  ASSERT_EQ(0, CountUpdatedTimingReported());
+  ASSERT_EQ(0, CountCompleteTimingReported());
+
+  // Navigate to a new page. This should force dispatch of the buffered timing
+  // update.
+  NavigateToUntrackedUrl();
+
+  ASSERT_EQ(1, CountUpdatedTimingReported());
+  ASSERT_EQ(1, CountCompleteTimingReported());
+  EXPECT_TRUE(timing.Equals(*updated_timings().back()));
+  EXPECT_TRUE(timing.Equals(*complete_timings().back()));
+
+  CheckNoErrorEvents();
+}
+
 }  // namespace page_load_metrics
diff --git a/chrome/browser/page_load_metrics/observers/page_load_metrics_observer_test_harness.cc b/chrome/browser/page_load_metrics/observers/page_load_metrics_observer_test_harness.cc
index bc777a0..37a51c54 100644
--- a/chrome/browser/page_load_metrics/observers/page_load_metrics_observer_test_harness.cc
+++ b/chrome/browser/page_load_metrics/observers/page_load_metrics_observer_test_harness.cc
@@ -38,6 +38,12 @@
     test_->RegisterObservers(tracker);
   }
 
+  std::unique_ptr<base::Timer> CreateTimer() override {
+    auto timer = base::MakeUnique<test::WeakMockTimer>();
+    test_->SetMockTimer(timer->AsWeakPtr());
+    return std::move(timer);
+  }
+
  private:
   PageLoadMetricsObserverTestHarness* test_;
 
@@ -51,76 +57,6 @@
 
 PageLoadMetricsObserverTestHarness::~PageLoadMetricsObserverTestHarness() {}
 
-// static
-void PageLoadMetricsObserverTestHarness::PopulateRequiredTimingFields(
-    mojom::PageLoadTiming* inout_timing) {
-  if (inout_timing->paint_timing->first_meaningful_paint &&
-      !inout_timing->paint_timing->first_contentful_paint) {
-    inout_timing->paint_timing->first_contentful_paint =
-        inout_timing->paint_timing->first_meaningful_paint;
-  }
-  if ((inout_timing->paint_timing->first_text_paint ||
-       inout_timing->paint_timing->first_image_paint ||
-       inout_timing->paint_timing->first_contentful_paint) &&
-      !inout_timing->paint_timing->first_paint) {
-    inout_timing->paint_timing->first_paint =
-        OptionalMin(OptionalMin(inout_timing->paint_timing->first_text_paint,
-                                inout_timing->paint_timing->first_image_paint),
-                    inout_timing->paint_timing->first_contentful_paint);
-  }
-  if (inout_timing->paint_timing->first_paint &&
-      !inout_timing->document_timing->first_layout) {
-    inout_timing->document_timing->first_layout =
-        inout_timing->paint_timing->first_paint;
-  }
-  if (inout_timing->document_timing->load_event_start &&
-      !inout_timing->document_timing->dom_content_loaded_event_start) {
-    inout_timing->document_timing->dom_content_loaded_event_start =
-        inout_timing->document_timing->load_event_start;
-  }
-  if (inout_timing->document_timing->first_layout &&
-      !inout_timing->parse_timing->parse_start) {
-    inout_timing->parse_timing->parse_start =
-        inout_timing->document_timing->first_layout;
-  }
-  if (inout_timing->document_timing->dom_content_loaded_event_start &&
-      !inout_timing->parse_timing->parse_stop) {
-    inout_timing->parse_timing->parse_stop =
-        inout_timing->document_timing->dom_content_loaded_event_start;
-  }
-  if (inout_timing->parse_timing->parse_stop &&
-      !inout_timing->parse_timing->parse_start) {
-    inout_timing->parse_timing->parse_start =
-        inout_timing->parse_timing->parse_stop;
-  }
-  if (inout_timing->parse_timing->parse_start &&
-      !inout_timing->response_start) {
-    inout_timing->response_start = inout_timing->parse_timing->parse_start;
-  }
-  if (inout_timing->parse_timing->parse_start) {
-    if (!inout_timing->parse_timing->parse_blocked_on_script_load_duration)
-      inout_timing->parse_timing->parse_blocked_on_script_load_duration =
-          base::TimeDelta();
-    if (!inout_timing->parse_timing
-             ->parse_blocked_on_script_execution_duration) {
-      inout_timing->parse_timing->parse_blocked_on_script_execution_duration =
-          base::TimeDelta();
-    }
-    if (!inout_timing->parse_timing
-             ->parse_blocked_on_script_load_from_document_write_duration) {
-      inout_timing->parse_timing
-          ->parse_blocked_on_script_load_from_document_write_duration =
-          base::TimeDelta();
-    }
-    if (!inout_timing->parse_timing
-             ->parse_blocked_on_script_execution_from_document_write_duration) {
-      inout_timing->parse_timing
-          ->parse_blocked_on_script_execution_from_document_write_duration =
-          base::TimeDelta();
-    }
-  }
-}
-
 void PageLoadMetricsObserverTestHarness::SetUp() {
   ChromeRenderViewHostTestHarness::SetUp();
   SetContents(CreateTestWebContents());
@@ -146,6 +82,12 @@
     const mojom::PageLoadTiming& timing,
     const mojom::PageLoadMetadata& metadata) {
   observer_->OnTimingUpdated(web_contents()->GetMainFrame(), timing, metadata);
+  // If sending the timing update caused the PageLoadMetricsUpdateDispatcher to
+  // schedule a buffering timer, then fire it now so metrics are dispatched to
+  // observers.
+  base::MockTimer* mock_timer = GetMockTimer();
+  if (mock_timer && mock_timer->IsRunning())
+    mock_timer->Fire();
 }
 
 void PageLoadMetricsObserverTestHarness::SimulateStartedResource(
diff --git a/chrome/browser/page_load_metrics/observers/page_load_metrics_observer_test_harness.h b/chrome/browser/page_load_metrics/observers/page_load_metrics_observer_test_harness.h
index 5d4cd7da..79c2ce5 100644
--- a/chrome/browser/page_load_metrics/observers/page_load_metrics_observer_test_harness.h
+++ b/chrome/browser/page_load_metrics/observers/page_load_metrics_observer_test_harness.h
@@ -9,6 +9,8 @@
 #include "base/test/histogram_tester.h"
 #include "chrome/browser/page_load_metrics/metrics_web_contents_observer.h"
 #include "chrome/browser/page_load_metrics/page_load_tracker.h"
+#include "chrome/common/page_load_metrics/test/page_load_metrics_test_util.h"
+#include "chrome/common/page_load_metrics/test/weak_mock_timer.h"
 #include "chrome/common/url_constants.h"
 #include "chrome/test/base/chrome_render_view_host_test_harness.h"
 #include "content/public/test/web_contents_tester.h"
@@ -21,15 +23,12 @@
 // an observer, override RegisterObservers and call tracker->AddObserver. This
 // will attach the observer to all main frame navigations.
 class PageLoadMetricsObserverTestHarness
-    : public ChromeRenderViewHostTestHarness {
+    : public ChromeRenderViewHostTestHarness,
+      public test::WeakMockTimerProvider {
  public:
   PageLoadMetricsObserverTestHarness();
   ~PageLoadMetricsObserverTestHarness() override;
 
-  // Helper that fills in any timing fields that MWCO requires but that are
-  // currently missing.
-  static void PopulateRequiredTimingFields(mojom::PageLoadTiming* inout_timing);
-
   void SetUp() override;
 
   virtual void RegisterObservers(PageLoadTracker* tracker) {}
diff --git a/chrome/browser/page_load_metrics/page_load_metrics_embedder_interface.h b/chrome/browser/page_load_metrics/page_load_metrics_embedder_interface.h
index 983a0145..000fa2e 100644
--- a/chrome/browser/page_load_metrics/page_load_metrics_embedder_interface.h
+++ b/chrome/browser/page_load_metrics/page_load_metrics_embedder_interface.h
@@ -5,8 +5,14 @@
 #ifndef CHROME_BROWSER_PAGE_LOAD_METRICS_PAGE_LOAD_METRICS_EMBEDDER_INTERFACE_H_
 #define CHROME_BROWSER_PAGE_LOAD_METRICS_PAGE_LOAD_METRICS_EMBEDDER_INTERFACE_H_
 
+#include <memory>
+
 class GURL;
 
+namespace base {
+class Timer;
+}  // namespace base
+
 namespace page_load_metrics {
 
 class PageLoadTracker;
@@ -18,6 +24,7 @@
   virtual ~PageLoadMetricsEmbedderInterface() {}
   virtual bool IsNewTabPageUrl(const GURL& url) = 0;
   virtual void RegisterObservers(PageLoadTracker* metrics) = 0;
+  virtual std::unique_ptr<base::Timer> CreateTimer() = 0;
 };
 
 }  // namespace page_load_metrics
diff --git a/chrome/browser/page_load_metrics/page_load_metrics_initialize.cc b/chrome/browser/page_load_metrics/page_load_metrics_initialize.cc
index ac44410..c0c3791c 100644
--- a/chrome/browser/page_load_metrics/page_load_metrics_initialize.cc
+++ b/chrome/browser/page_load_metrics/page_load_metrics_initialize.cc
@@ -6,6 +6,7 @@
 
 #include "base/macros.h"
 #include "base/memory/ptr_util.h"
+#include "base/timer/timer.h"
 #include "chrome/browser/page_load_metrics/metrics_web_contents_observer.h"
 #if defined(OS_ANDROID)
 #include "chrome/browser/page_load_metrics/observers/android_page_load_metrics_observer.h"
@@ -55,6 +56,7 @@
   // page_load_metrics::PageLoadMetricsEmbedderInterface:
   bool IsNewTabPageUrl(const GURL& url) override;
   void RegisterObservers(page_load_metrics::PageLoadTracker* tracker) override;
+  std::unique_ptr<base::Timer> CreateTimer() override;
 
  private:
   bool IsPrerendering() const;
@@ -142,6 +144,10 @@
          nullptr;
 }
 
+std::unique_ptr<base::Timer> PageLoadMetricsEmbedder::CreateTimer() {
+  return base::MakeUnique<base::OneShotTimer>();
+}
+
 bool PageLoadMetricsEmbedder::IsNewTabPageUrl(const GURL& url) {
   Profile* profile =
       Profile::FromBrowserContext(web_contents_->GetBrowserContext());
diff --git a/chrome/browser/page_load_metrics/page_load_metrics_update_dispatcher.cc b/chrome/browser/page_load_metrics/page_load_metrics_update_dispatcher.cc
index f5e4ec5..0f47b82 100644
--- a/chrome/browser/page_load_metrics/page_load_metrics_update_dispatcher.cc
+++ b/chrome/browser/page_load_metrics/page_load_metrics_update_dispatcher.cc
@@ -25,6 +25,10 @@
 const char kPageLoadTimingStatus[] = "PageLoad.Internal.PageLoadTimingStatus";
 const char kPageLoadTimingDispatchStatus[] =
     "PageLoad.Internal.PageLoadTimingStatus.AtTimingCallbackDispatch";
+const char kHistogramOutOfOrderTiming[] =
+    "PageLoad.Internal.OutOfOrderInterFrameTiming";
+const char kHistogramOutOfOrderTimingBuffered[] =
+    "PageLoad.Internal.OutOfOrderInterFrameTiming.AfterBuffering";
 
 }  // namespace internal
 
@@ -200,10 +204,57 @@
   return internal::VALID;
 }
 
+// If the updated value has an earlier time than the current value, log so we
+// can keep track of how often this happens.
+void LogIfOutOfOrderTiming(const base::Optional<base::TimeDelta>& current,
+                           const base::Optional<base::TimeDelta>& update) {
+  if (!current || !update)
+    return;
+
+  if (update < current) {
+    PAGE_LOAD_HISTOGRAM(internal::kHistogramOutOfOrderTimingBuffered,
+                        current.value() - update.value());
+  }
+}
+
+// PaintTimingMerger merges paint timing values received from different frames
+// together.
+class PaintTimingMerger {
+ public:
+  explicit PaintTimingMerger(mojom::PaintTiming* target) : target_(target) {}
+
+  // Merge paint timing values from |new_paint_timing| into the target
+  // PaintTiming.
+  void Merge(base::TimeDelta navigation_start_offset,
+             const mojom::PaintTiming& new_paint_timing,
+             bool is_main_frame);
+
+  // Whether we merged a new value, for a paint timing field we didn't
+  // previously have a value for in the target PaintTiming.
+  bool did_merge_new_timing_value() const {
+    return did_merge_new_timing_value_;
+  }
+
+ private:
+  void MaybeUpdateTimeDelta(
+      base::Optional<base::TimeDelta>* inout_existing_value,
+      base::TimeDelta navigation_start_offset,
+      const base::Optional<base::TimeDelta>& optional_candidate_new_value);
+
+  // The target PaintTiming we are merging values into.
+  mojom::PaintTiming* const target_;
+
+  // Whether we merged a new value, for a paint timing field we didn't
+  // previously have a value for in |target_|.
+  bool did_merge_new_timing_value_ = false;
+
+  DISALLOW_COPY_AND_ASSIGN(PaintTimingMerger);
+};
+
 // Updates *|inout_existing_value| with |optional_candidate_new_value|, if
 // either *|inout_existing_value| isn't set, or |optional_candidate_new_value| <
 // |inout_existing_value|.
-void MaybeUpdateTimeDelta(
+void PaintTimingMerger::MaybeUpdateTimeDelta(
     base::Optional<base::TimeDelta>* inout_existing_value,
     base::TimeDelta navigation_start_offset,
     const base::Optional<base::TimeDelta>& optional_candidate_new_value) {
@@ -228,13 +279,33 @@
     // occasionally, as inter-frame updates can arrive out of order. Record a
     // histogram to track how frequently it happens, along with the magnitude
     // of the delta.
-    PAGE_LOAD_HISTOGRAM("PageLoad.Internal.OutOfOrderInterFrameTiming",
+    PAGE_LOAD_HISTOGRAM(internal::kHistogramOutOfOrderTiming,
                         inout_existing_value->value() - candidate_new_value);
+  } else {
+    did_merge_new_timing_value_ = true;
   }
 
   *inout_existing_value = candidate_new_value;
 }
 
+void PaintTimingMerger::Merge(base::TimeDelta navigation_start_offset,
+                              const mojom::PaintTiming& new_paint_timing,
+                              bool is_main_frame) {
+  MaybeUpdateTimeDelta(&target_->first_paint, navigation_start_offset,
+                       new_paint_timing.first_paint);
+  MaybeUpdateTimeDelta(&target_->first_text_paint, navigation_start_offset,
+                       new_paint_timing.first_text_paint);
+  MaybeUpdateTimeDelta(&target_->first_image_paint, navigation_start_offset,
+                       new_paint_timing.first_image_paint);
+  MaybeUpdateTimeDelta(&target_->first_contentful_paint,
+                       navigation_start_offset,
+                       new_paint_timing.first_contentful_paint);
+  if (is_main_frame) {
+    // First meaningful paint is only tracked in the main frame.
+    target_->first_meaningful_paint = new_paint_timing.first_meaningful_paint;
+  }
+}
+
 }  // namespace
 
 PageLoadMetricsUpdateDispatcher::PageLoadMetricsUpdateDispatcher(
@@ -243,13 +314,24 @@
     PageLoadMetricsEmbedderInterface* embedder_interface)
     : client_(client),
       embedder_interface_(embedder_interface),
+      timer_(embedder_interface->CreateTimer()),
       navigation_start_(navigation_handle->NavigationStart()),
       current_merged_page_timing_(CreatePageLoadTiming()),
       pending_merged_page_timing_(CreatePageLoadTiming()),
       main_frame_metadata_(mojom::PageLoadMetadata::New()),
       subframe_metadata_(mojom::PageLoadMetadata::New()) {}
 
-PageLoadMetricsUpdateDispatcher::~PageLoadMetricsUpdateDispatcher() {}
+PageLoadMetricsUpdateDispatcher::~PageLoadMetricsUpdateDispatcher() {
+  ShutDown();
+}
+
+void PageLoadMetricsUpdateDispatcher::ShutDown() {
+  if (timer_ && timer_->IsRunning()) {
+    timer_->Stop();
+    DispatchTimingUpdates();
+  }
+  timer_ = nullptr;
+}
 
 void PageLoadMetricsUpdateDispatcher::UpdateMetrics(
     content::RenderFrameHost* render_frame_host,
@@ -303,32 +385,11 @@
   client_->OnSubFrameTimingChanged(new_timing);
 
   base::TimeDelta navigation_start_offset = it->second;
-  MergePaintTiming(navigation_start_offset, *(new_timing.paint_timing),
-                   false /* is_main_frame */);
+  PaintTimingMerger merger(pending_merged_page_timing_->paint_timing.get());
+  merger.Merge(navigation_start_offset, *new_timing.paint_timing,
+               false /* is_main_frame */);
 
-  DispatchTimingUpdates();
-}
-
-void PageLoadMetricsUpdateDispatcher::MergePaintTiming(
-    base::TimeDelta navigation_start_offset,
-    const mojom::PaintTiming& new_paint_timing,
-    bool is_main_frame) {
-  MaybeUpdateTimeDelta(&pending_merged_page_timing_->paint_timing->first_paint,
-                       navigation_start_offset, new_paint_timing.first_paint);
-  MaybeUpdateTimeDelta(
-      &pending_merged_page_timing_->paint_timing->first_text_paint,
-      navigation_start_offset, new_paint_timing.first_text_paint);
-  MaybeUpdateTimeDelta(
-      &pending_merged_page_timing_->paint_timing->first_image_paint,
-      navigation_start_offset, new_paint_timing.first_image_paint);
-  MaybeUpdateTimeDelta(
-      &pending_merged_page_timing_->paint_timing->first_contentful_paint,
-      navigation_start_offset, new_paint_timing.first_contentful_paint);
-  if (is_main_frame) {
-    // first meaningful paint is only tracked in the main frame.
-    pending_merged_page_timing_->paint_timing->first_meaningful_paint =
-        new_paint_timing.first_meaningful_paint;
-  }
+  MaybeDispatchTimingUpdates(merger.did_merge_new_timing_value());
 }
 
 void PageLoadMetricsUpdateDispatcher::UpdateSubFrameMetadata(
@@ -374,10 +435,12 @@
   // observed |paint_timing|, which is tracked across all frames in the page.
   pending_merged_page_timing_ = new_timing.Clone();
   pending_merged_page_timing_->paint_timing = std::move(last_paint_timing);
-  MergePaintTiming(base::TimeDelta(), *new_timing.paint_timing,
-                   true /* is_main_frame */);
 
-  DispatchTimingUpdates();
+  PaintTimingMerger merger(pending_merged_page_timing_->paint_timing.get());
+  merger.Merge(base::TimeDelta(), *new_timing.paint_timing,
+               true /* is_main_frame */);
+
+  MaybeDispatchTimingUpdates(merger.did_merge_new_timing_value());
 }
 
 void PageLoadMetricsUpdateDispatcher::UpdateMainFrameMetadata(
@@ -398,7 +461,24 @@
   client_->OnMainFrameMetadataChanged();
 }
 
+void PageLoadMetricsUpdateDispatcher::MaybeDispatchTimingUpdates(
+    bool did_merge_new_timing_value) {
+  // If we merged a new timing value, then we should buffer updates for
+  // |kBufferTimerDelayMillis|, to allow for any other out of order timings to
+  // arrive before we dispatch the minimum observed timings to observers.
+  if (did_merge_new_timing_value) {
+    timer_->Start(
+        FROM_HERE, base::TimeDelta::FromMilliseconds(kBufferTimerDelayMillis),
+        base::Bind(&PageLoadMetricsUpdateDispatcher::DispatchTimingUpdates,
+                   base::Unretained(this)));
+  } else if (!timer_->IsRunning()) {
+    DispatchTimingUpdates();
+  }
+}
+
 void PageLoadMetricsUpdateDispatcher::DispatchTimingUpdates() {
+  DCHECK(!timer_->IsRunning());
+
   if (pending_merged_page_timing_->paint_timing->first_paint) {
     if (!pending_merged_page_timing_->parse_timing->parse_start ||
         !pending_merged_page_timing_->document_timing->first_layout) {
@@ -418,6 +498,19 @@
 
   if (current_merged_page_timing_->Equals(*pending_merged_page_timing_))
     return;
+
+  LogIfOutOfOrderTiming(current_merged_page_timing_->paint_timing->first_paint,
+                        pending_merged_page_timing_->paint_timing->first_paint);
+  LogIfOutOfOrderTiming(
+      current_merged_page_timing_->paint_timing->first_text_paint,
+      pending_merged_page_timing_->paint_timing->first_text_paint);
+  LogIfOutOfOrderTiming(
+      current_merged_page_timing_->paint_timing->first_image_paint,
+      pending_merged_page_timing_->paint_timing->first_image_paint);
+  LogIfOutOfOrderTiming(
+      current_merged_page_timing_->paint_timing->first_contentful_paint,
+      pending_merged_page_timing_->paint_timing->first_contentful_paint);
+
   current_merged_page_timing_ = pending_merged_page_timing_->Clone();
 
   internal::PageLoadTimingStatus status =
diff --git a/chrome/browser/page_load_metrics/page_load_metrics_update_dispatcher.h b/chrome/browser/page_load_metrics/page_load_metrics_update_dispatcher.h
index 47f6e4f..7af5111c4 100644
--- a/chrome/browser/page_load_metrics/page_load_metrics_update_dispatcher.h
+++ b/chrome/browser/page_load_metrics/page_load_metrics_update_dispatcher.h
@@ -6,9 +6,11 @@
 #define CHROME_BROWSER_PAGE_LOAD_METRICS_PAGE_LOAD_METRICS_UPDATE_DISPATCHER_H_
 
 #include <map>
+#include <memory>
 
 #include "base/macros.h"
 #include "base/time/time.h"
+#include "base/timer/timer.h"
 #include "chrome/common/page_load_metrics/page_load_metrics.mojom.h"
 
 namespace content {
@@ -65,6 +67,8 @@
 };
 
 extern const char kPageLoadTimingStatus[];
+extern const char kHistogramOutOfOrderTiming[];
+extern const char kHistogramOutOfOrderTimingBuffered[];
 
 }  // namespace internal
 
@@ -101,6 +105,8 @@
   void DidFinishSubFrameNavigation(
       content::NavigationHandle* navigation_handle);
 
+  void ShutDown();
+
   const mojom::PageLoadTiming& timing() const {
     return *(current_merged_page_timing_.get());
   }
@@ -122,12 +128,7 @@
   void UpdateMainFrameMetadata(const mojom::PageLoadMetadata& new_metadata);
   void UpdateSubFrameMetadata(const mojom::PageLoadMetadata& subframe_metadata);
 
-  // Merge values from |new_paint_timing| into |pending_merged_page_timing_|,
-  // offsetting any new timings by the |navigation_start_offset|.
-  void MergePaintTiming(base::TimeDelta navigation_start_offset,
-                        const mojom::PaintTiming& new_paint_timing,
-                        bool is_main_frame);
-
+  void MaybeDispatchTimingUpdates(bool did_merge_new_timing_value);
   void DispatchTimingUpdates();
 
   // The client is guaranteed to outlive this object.
@@ -136,6 +137,8 @@
   // Interface to chrome features. Must outlive the class.
   PageLoadMetricsEmbedderInterface* const embedder_interface_;
 
+  std::unique_ptr<base::Timer> timer_;
+
   // Time the navigation for this page load was initiated.
   const base::TimeTicks navigation_start_;
 
diff --git a/chrome/browser/page_load_metrics/page_load_metrics_util.cc b/chrome/browser/page_load_metrics/page_load_metrics_util.cc
index 22ec5505..ab1acc1 100644
--- a/chrome/browser/page_load_metrics/page_load_metrics_util.cc
+++ b/chrome/browser/page_load_metrics/page_load_metrics_util.cc
@@ -7,8 +7,6 @@
 #include <algorithm>
 
 #include "chrome/common/page_load_metrics/page_load_timing.h"
-#include "net/base/registry_controlled_domains/registry_controlled_domain.h"
-#include "url/gurl.h"
 
 namespace page_load_metrics {
 
@@ -45,45 +43,6 @@
 
 }  // namespace
 
-base::Optional<std::string> GetGoogleHostnamePrefix(const GURL& url) {
-  const size_t registry_length =
-      net::registry_controlled_domains::GetRegistryLength(
-          url,
-
-          // Do not include unknown registries (registries that don't have any
-          // matches in effective TLD names).
-          net::registry_controlled_domains::EXCLUDE_UNKNOWN_REGISTRIES,
-
-          // Do not include private registries, such as appspot.com. We don't
-          // want to match URLs like www.google.appspot.com.
-          net::registry_controlled_domains::EXCLUDE_PRIVATE_REGISTRIES);
-
-  const base::StringPiece hostname = url.host_piece();
-  if (registry_length == 0 || registry_length == std::string::npos ||
-      registry_length >= hostname.length()) {
-    return base::Optional<std::string>();
-  }
-
-  // Removes the tld and the preceding dot.
-  const base::StringPiece hostname_minus_registry =
-      hostname.substr(0, hostname.length() - (registry_length + 1));
-
-  if (hostname_minus_registry == "google")
-    return std::string("");
-
-  if (!base::EndsWith(hostname_minus_registry, ".google",
-                      base::CompareCase::INSENSITIVE_ASCII)) {
-    return base::Optional<std::string>();
-  }
-
-  return std::string(hostname_minus_registry.substr(
-      0, hostname_minus_registry.length() - strlen(".google")));
-}
-
-bool IsGoogleHostname(const GURL& url) {
-  return GetGoogleHostnamePrefix(url).has_value();
-}
-
 bool WasStartedInForegroundOptionalEventInForeground(
     const base::Optional<base::TimeDelta>& event,
     const PageLoadExtraInfo& info) {
@@ -132,18 +91,6 @@
   return time_on_page;
 }
 
-base::Optional<base::TimeDelta> OptionalMin(
-    const base::Optional<base::TimeDelta>& a,
-    const base::Optional<base::TimeDelta>& b) {
-  if (a && !b)
-    return a;
-  if (b && !a)
-    return b;
-  if (!a && !b)
-    return a;  // doesn't matter which
-  return base::Optional<base::TimeDelta>(std::min(a.value(), b.value()));
-}
-
 bool DidObserveLoadingBehaviorInAnyFrame(
     const page_load_metrics::PageLoadExtraInfo& info,
     blink::WebLoadingBehaviorFlag behavior) {
diff --git a/chrome/browser/page_load_metrics/page_load_metrics_util.h b/chrome/browser/page_load_metrics/page_load_metrics_util.h
index 1e6af571..a81c0432 100644
--- a/chrome/browser/page_load_metrics/page_load_metrics_util.h
+++ b/chrome/browser/page_load_metrics/page_load_metrics_util.h
@@ -9,6 +9,7 @@
 #include "base/optional.h"
 #include "base/time/time.h"
 #include "chrome/browser/page_load_metrics/page_load_metrics_observer.h"
+#include "chrome/common/page_load_metrics/page_load_metrics_util.h"
 #include "third_party/WebKit/public/platform/WebLoadingBehaviorFlag.h"
 
 // Up to 10 minutes, with 100 buckets.
@@ -118,34 +119,12 @@
     const PageLoadExtraInfo& info,
     base::TimeTicks app_background_time);
 
-// Returns the minimum value of the optional TimeDeltas, if both values are
-// set. Otherwise, if one value is set, returns that value. Otherwise, returns
-// an unset value.
-base::Optional<base::TimeDelta> OptionalMin(
-    const base::Optional<base::TimeDelta>& a,
-    const base::Optional<base::TimeDelta>& b);
-
 // Whether the given loading behavior was observed in any frame (either the main
 // frame or a subframe).
 bool DidObserveLoadingBehaviorInAnyFrame(
     const page_load_metrics::PageLoadExtraInfo& info,
     blink::WebLoadingBehaviorFlag behavior);
 
-// Whether the given url has a google hostname.
-bool IsGoogleHostname(const GURL& url);
-
-// If the given hostname is a google hostname, returns the portion of the
-// hostname before the google hostname. Otherwise, returns an unset optional
-// value.
-//
-// For example:
-//   https://example.com/foo => returns an unset optional value
-//   https://google.com/foo => returns ''
-//   https://www.google.com/foo => returns 'www'
-//   https://news.google.com/foo => returns 'news'
-//   https://a.b.c.google.com/foo => returns 'a.b.c'
-base::Optional<std::string> GetGoogleHostnamePrefix(const GURL& url);
-
 }  // namespace page_load_metrics
 
 #endif  // CHROME_BROWSER_PAGE_LOAD_METRICS_PAGE_LOAD_METRICS_UTIL_H_
diff --git a/chrome/browser/page_load_metrics/page_load_tracker.cc b/chrome/browser/page_load_metrics/page_load_tracker.cc
index 742c841..9f83e20f 100644
--- a/chrome/browser/page_load_metrics/page_load_tracker.cc
+++ b/chrome/browser/page_load_metrics/page_load_tracker.cc
@@ -201,6 +201,8 @@
   if (did_stop_tracking_)
     return;
 
+  metrics_update_dispatcher_.ShutDown();
+
   if (page_end_time_.is_null()) {
     // page_end_time_ can be unset in some cases, such as when a navigation is
     // aborted by a navigation that started before it. In these cases, set the
diff --git a/chrome/browser/platform_util_win.cc b/chrome/browser/platform_util_win.cc
index 84282394..67a0827b3b 100644
--- a/chrome/browser/platform_util_win.cc
+++ b/chrome/browser/platform_util_win.cc
@@ -11,13 +11,14 @@
 #include <stddef.h>
 
 #include "base/bind.h"
-#include "base/bind_helpers.h"
 #include "base/files/file_path.h"
 #include "base/files/file_util.h"
 #include "base/logging.h"
 #include "base/macros.h"
 #include "base/strings/string_util.h"
 #include "base/strings/utf_string_conversions.h"
+#include "base/task_scheduler/post_task.h"
+#include "base/threading/thread_restrictions.h"
 #include "base/win/registry.h"
 #include "base/win/scoped_co_mem.h"
 #include "base/win/scoped_comptr.h"
@@ -35,8 +36,8 @@
 
 namespace {
 
-void ShowItemInFolderOnFileThread(const base::FilePath& full_path) {
-  DCHECK_CURRENTLY_ON(BrowserThread::FILE);
+void ShowItemInFolderOnWorkerThread(const base::FilePath& full_path) {
+  base::ThreadRestrictions::AssertIOAllowed();
   base::FilePath dir = full_path.DirName().AsEndingWithSeparator();
   // ParseDisplayName will fail if the directory is "C:", it must be "C:\\".
   if (dir.empty())
@@ -126,7 +127,8 @@
   return true;
 }
 
-void OpenExternalOnFileThread(const GURL& url) {
+void OpenExternalOnWorkerThread(const GURL& url) {
+  base::ThreadRestrictions::AssertIOAllowed();
   // Quote the input scheme to be sure that the command does not have
   // parameters unexpected by the external program. This url should already
   // have been escaped.
@@ -162,8 +164,9 @@
 }  // namespace
 
 void ShowItemInFolder(Profile* profile, const base::FilePath& full_path) {
-  BrowserThread::PostTask(BrowserThread::FILE, FROM_HERE,
-      base::Bind(&ShowItemInFolderOnFileThread, full_path));
+  PostTaskWithTraits(FROM_HERE,
+                     {base::MayBlock(), base::TaskPriority::USER_BLOCKING},
+                     base::Bind(&ShowItemInFolderOnWorkerThread, full_path));
 }
 
 namespace internal {
@@ -185,8 +188,9 @@
 void OpenExternal(Profile* profile, const GURL& url) {
   DCHECK_CURRENTLY_ON(BrowserThread::UI);
 
-  BrowserThread::PostTask(BrowserThread::FILE, FROM_HERE,
-                          base::Bind(&OpenExternalOnFileThread, url));
+  PostTaskWithTraits(FROM_HERE,
+                     {base::MayBlock(), base::TaskPriority::USER_BLOCKING},
+                     base::Bind(&OpenExternalOnWorkerThread, url));
 }
 
 }  // namespace platform_util
diff --git a/chrome/browser/predictors/resource_prefetch_predictor_browsertest.cc b/chrome/browser/predictors/resource_prefetch_predictor_browsertest.cc
index 306f3987..03bd3d3 100644
--- a/chrome/browser/predictors/resource_prefetch_predictor_browsertest.cc
+++ b/chrome/browser/predictors/resource_prefetch_predictor_browsertest.cc
@@ -783,7 +783,7 @@
       GetURL(kImagePath), content::RESOURCE_TYPE_IMAGE, net::LOWEST);
   // Delay HTTP response to ensure enough time to receive notice of
   // firstContentfulPaint.
-  image->delay = base::TimeDelta::FromMilliseconds(1500);
+  image->delay = base::TimeDelta::FromMilliseconds(2500);
   image->request.before_first_contentful_paint = false;
 
   TestLearningAndPrefetching(GetURL(kHtmlFcpOrderPath), true);
diff --git a/chrome/browser/prerender/prerender_browsertest.cc b/chrome/browser/prerender/prerender_browsertest.cc
index 9736d35f1..0c6d628 100644
--- a/chrome/browser/prerender/prerender_browsertest.cc
+++ b/chrome/browser/prerender/prerender_browsertest.cc
@@ -40,7 +40,6 @@
 #include "chrome/browser/extensions/extension_apitest.h"
 #include "chrome/browser/external_protocol/external_protocol_handler.h"
 #include "chrome/browser/net/prediction_options.h"
-#include "chrome/browser/page_load_metrics/observers/page_load_metrics_observer_test_harness.h"
 #include "chrome/browser/page_load_metrics/observers/prerender_page_load_metrics_observer.h"
 #include "chrome/browser/password_manager/password_store_factory.h"
 #include "chrome/browser/predictors/autocomplete_action_predictor.h"
@@ -71,6 +70,7 @@
 #include "chrome/common/chrome_features.h"
 #include "chrome/common/chrome_paths.h"
 #include "chrome/common/chrome_switches.h"
+#include "chrome/common/page_load_metrics/test/page_load_metrics_test_util.h"
 #include "chrome/test/base/ui_test_utils.h"
 #include "components/content_settings/core/browser/host_content_settings_map.h"
 #include "components/favicon/content/content_favicon_driver.h"
@@ -3439,8 +3439,7 @@
   timing.navigation_start = base::Time::FromDoubleT(1);  // Non-null time.
   timing.paint_timing->first_contentful_paint =
       base::TimeDelta::FromMilliseconds(2654);
-  page_load_metrics::PageLoadMetricsObserverTestHarness::
-      PopulateRequiredTimingFields(&timing);
+  PopulateRequiredTimingFields(&timing);
   observer.OnFirstContentfulPaintInPage(timing,
                                         GenericPageLoadExtraInfo(dest_url()));
 
@@ -3482,8 +3481,7 @@
   timing.navigation_start = base::Time::FromDoubleT(1);  // Non-null time.
   timing.paint_timing->first_contentful_paint =
       base::TimeDelta::FromMilliseconds(2361);
-  page_load_metrics::PageLoadMetricsObserverTestHarness::
-      PopulateRequiredTimingFields(&timing);
+  PopulateRequiredTimingFields(&timing);
   observer.OnFirstContentfulPaintInPage(timing,
                                         GenericPageLoadExtraInfo(dest_url()));
 
@@ -3525,8 +3523,7 @@
   timing.navigation_start = base::Time::FromDoubleT(1);  // Non-null time.
   timing.paint_timing->first_contentful_paint =
       base::TimeDelta::FromMilliseconds(2361);
-  page_load_metrics::PageLoadMetricsObserverTestHarness::
-      PopulateRequiredTimingFields(&timing);
+  PopulateRequiredTimingFields(&timing);
   observer.OnFirstContentfulPaintInPage(timing,
                                         GenericPageLoadExtraInfo(dest_url()));
 
@@ -3570,8 +3567,7 @@
   timing.navigation_start = base::Time::FromDoubleT(1);  // Non-null time.
   timing.paint_timing->first_contentful_paint =
       base::TimeDelta::FromMilliseconds(2362);
-  page_load_metrics::PageLoadMetricsObserverTestHarness::
-      PopulateRequiredTimingFields(&timing);
+  PopulateRequiredTimingFields(&timing);
   observer.OnFirstContentfulPaintInPage(timing,
                                         GenericPageLoadExtraInfo(dest_url()));
 
@@ -3622,8 +3618,7 @@
   // The FCP time should end up on the edge of the bucket.
   timing.paint_timing->first_contentful_paint =
       base::TimeDelta::FromMilliseconds(2654);
-  page_load_metrics::PageLoadMetricsObserverTestHarness::
-      PopulateRequiredTimingFields(&timing);
+  PopulateRequiredTimingFields(&timing);
   observer.OnFirstContentfulPaintInPage(timing,
                                         GenericPageLoadExtraInfo(dest_url()));
 
@@ -3655,8 +3650,7 @@
   timing.navigation_start = base::Time::FromDoubleT(1);  // Non-null time.
   timing.paint_timing->first_contentful_paint =
       base::TimeDelta::FromMilliseconds(2654);
-  page_load_metrics::PageLoadMetricsObserverTestHarness::
-      PopulateRequiredTimingFields(&timing);
+  PopulateRequiredTimingFields(&timing);
   observer.OnFirstContentfulPaintInPage(timing,
                                         GenericPageLoadExtraInfo(dest_url()));
 
@@ -3702,8 +3696,7 @@
   timing.navigation_start = base::Time::FromDoubleT(1);  // Non-null time.
   timing.paint_timing->first_contentful_paint =
       base::TimeDelta::FromMilliseconds(2362);
-  page_load_metrics::PageLoadMetricsObserverTestHarness::
-      PopulateRequiredTimingFields(&timing);
+  PopulateRequiredTimingFields(&timing);
   observer.OnFirstContentfulPaintInPage(timing,
                                         GenericPageLoadExtraInfo(dest_url()));
 
diff --git a/chrome/browser/profiles/off_the_record_profile_io_data.cc b/chrome/browser/profiles/off_the_record_profile_io_data.cc
index c41e80c..3510d12 100644
--- a/chrome/browser/profiles/off_the_record_profile_io_data.cc
+++ b/chrome/browser/profiles/off_the_record_profile_io_data.cc
@@ -289,11 +289,13 @@
   context->SetCookieStore(std::move(cookie_store));
 
   // Build a new HttpNetworkSession that uses the new ChannelIDService.
-  net::HttpNetworkSession::Params network_params =
-      main_request_context_storage()->http_network_session()->params();
-  network_params.channel_id_service = channel_id_service.get();
+  net::HttpNetworkSession::Context session_context =
+      main_request_context_storage()->http_network_session()->context();
+  session_context.channel_id_service = channel_id_service.get();
   std::unique_ptr<net::HttpNetworkSession> http_network_session(
-      new net::HttpNetworkSession(network_params));
+      new net::HttpNetworkSession(
+          main_request_context_storage()->http_network_session()->params(),
+          session_context));
 
   // Use a separate in-memory cache for the app.
   std::unique_ptr<net::HttpCache> app_http_cache = CreateMainHttpFactory(
diff --git a/chrome/browser/profiles/profile.cc b/chrome/browser/profiles/profile.cc
index a610a51..c56f39e 100644
--- a/chrome/browser/profiles/profile.cc
+++ b/chrome/browser/profiles/profile.cc
@@ -40,20 +40,63 @@
 #include "extensions/browser/pref_names.h"
 #endif
 
+#if DCHECK_IS_ON()
+
+#include <set>
+#include "base/lazy_instance.h"
+#include "base/logging.h"
+#include "base/synchronization/lock.h"
+
+namespace {
+
+base::LazyInstance<base::Lock>::Leaky g_instances_lock =
+    LAZY_INSTANCE_INITIALIZER;
+base::LazyInstance<std::set<content::BrowserContext*>>::Leaky g_instances =
+    LAZY_INSTANCE_INITIALIZER;
+
+}  // namespace
+
+#endif  // DCHECK_IS_ON()
+
 Profile::Profile()
     : restored_last_session_(false),
       sent_destroyed_notification_(false),
       accessibility_pause_level_(0),
       is_guest_profile_(false),
       is_system_profile_(false) {
+#if DCHECK_IS_ON()
+  base::AutoLock lock(g_instances_lock.Get());
+  g_instances.Get().insert(this);
+#endif  // DCHECK_IS_ON()
 }
 
 Profile::~Profile() {
+#if DCHECK_IS_ON()
+  base::AutoLock lock(g_instances_lock.Get());
+  g_instances.Get().erase(this);
+#endif  // DCHECK_IS_ON()
 }
 
 // static
 Profile* Profile::FromBrowserContext(content::BrowserContext* browser_context) {
-  // This is safe; this is the only implementation of the browser context.
+  if (!browser_context)
+    return nullptr;
+
+  // For code running in a chrome/ environment, it is safe to cast to Profile*
+  // because Profile is the only implementation of BrowserContext used. In
+  // testing, however, there are several BrowserContext subclasses that are not
+  // Profile subclasses, and we can catch them. http://crbug.com/725276
+#if DCHECK_IS_ON()
+  base::AutoLock lock(g_instances_lock.Get());
+  if (!g_instances.Get().count(browser_context)) {
+    DCHECK(false)
+        << "Non-Profile BrowserContext passed to Profile::FromBrowserContext! "
+           "If you have a test linked in chrome/ you need a chrome/ based test "
+           "class such as TestingProfile in chrome/test/base/testing_profile.h "
+           "or you need to subclass your test class from Profile, not from "
+           "BrowserContext.";
+  }
+#endif  // DCHECK_IS_ON()
   return static_cast<Profile*>(browser_context);
 }
 
@@ -63,12 +106,12 @@
 }
 
 TestingProfile* Profile::AsTestingProfile() {
-  return NULL;
+  return nullptr;
 }
 
 #if !defined(OS_ANDROID)
 ChromeZoomLevelPrefs* Profile::GetZoomLevelPrefs() {
-  return NULL;
+  return nullptr;
 }
 #endif  // !defined(OS_ANDROID)
 
diff --git a/chrome/browser/profiles/profile_browsertest.cc b/chrome/browser/profiles/profile_browsertest.cc
index de478a9..1dddc38 100644
--- a/chrome/browser/profiles/profile_browsertest.cc
+++ b/chrome/browser/profiles/profile_browsertest.cc
@@ -566,12 +566,12 @@
   // the one directly on the URLRequestContext.
   EXPECT_EQ(extension_context->http_transaction_factory()
                 ->GetSession()
-                ->params()
+                ->context()
                 .channel_id_service,
             extension_context->channel_id_service());
   EXPECT_EQ(main_context->http_transaction_factory()
                 ->GetSession()
-                ->params()
+                ->context()
                 .channel_id_service,
             main_context->channel_id_service());
 }
diff --git a/chrome/browser/profiles/profile_impl_io_data.cc b/chrome/browser/profiles/profile_impl_io_data.cc
index 7a039d6..a6eebb3fa 100644
--- a/chrome/browser/profiles/profile_impl_io_data.cc
+++ b/chrome/browser/profiles/profile_impl_io_data.cc
@@ -651,15 +651,17 @@
   cookie_store->SetChannelIDServiceID(channel_id_service->GetUniqueID());
 
   // Build a new HttpNetworkSession that uses the new ChannelIDService.
-  // TODO(mmenke):  It weird to combine state from
+  // TODO(mmenke):  It's weird to combine state from
   // main_request_context_storage() objects and the argumet to this method,
   // |main_context|.  Remove |main_context| as an argument, and just use
   // main_context() instead.
-  net::HttpNetworkSession::Params network_params =
-      main_request_context_storage()->http_network_session()->params();
-  network_params.channel_id_service = channel_id_service.get();
+  net::HttpNetworkSession::Context session_context =
+      main_request_context_storage()->http_network_session()->context();
+  session_context.channel_id_service = channel_id_service.get();
   std::unique_ptr<net::HttpNetworkSession> http_network_session(
-      new net::HttpNetworkSession(network_params));
+      new net::HttpNetworkSession(
+          main_request_context_storage()->http_network_session()->params(),
+          session_context));
   std::unique_ptr<net::HttpCache> app_http_cache =
       CreateMainHttpFactory(http_network_session.get(), std::move(app_backend));
 
diff --git a/chrome/browser/profiles/profile_io_data.cc b/chrome/browser/profiles/profile_io_data.cc
index 88755d5..fd34c47d 100644
--- a/chrome/browser/profiles/profile_io_data.cc
+++ b/chrome/browser/profiles/profile_io_data.cc
@@ -1309,19 +1309,21 @@
 
   IOThread* const io_thread = profile_params.io_thread;
 
-  net::HttpNetworkSession::Params params(io_thread->NetworkSessionParams());
-  net::URLRequestContextBuilder::SetHttpNetworkSessionComponents(context,
-                                                                 &params);
+  net::HttpNetworkSession::Context session_context;
+  net::URLRequestContextBuilder::SetHttpNetworkSessionComponents(
+      context, &session_context);
   if (!IsOffTheRecord() && io_thread->globals()->network_quality_estimator) {
-    params.socket_performance_watcher_factory =
+    session_context.socket_performance_watcher_factory =
         io_thread->globals()
             ->network_quality_estimator->GetSocketPerformanceWatcherFactory();
   }
-  if (data_reduction_proxy_io_data_.get())
-    params.proxy_delegate = data_reduction_proxy_io_data_->proxy_delegate();
+  if (data_reduction_proxy_io_data_.get()) {
+    session_context.proxy_delegate =
+        data_reduction_proxy_io_data_->proxy_delegate();
+  }
 
-  return std::unique_ptr<net::HttpNetworkSession>(
-      new net::HttpNetworkSession(params));
+  return std::unique_ptr<net::HttpNetworkSession>(new net::HttpNetworkSession(
+      io_thread->NetworkSessionParams(), session_context));
 }
 
 std::unique_ptr<net::HttpCache> ProfileIOData::CreateMainHttpFactory(
diff --git a/chrome/browser/resources/extensions/extension_list.js b/chrome/browser/resources/extensions/extension_list.js
index df40e77..235c758 100644
--- a/chrome/browser/resources/extensions/extension_list.js
+++ b/chrome/browser/resources/extensions/extension_list.js
@@ -481,14 +481,6 @@
         e.preventDefault();
       });
 
-      // The 'Show Browser Action' button.
-      wrapper.setupColumn('showButton', '.show-button', 'click', function(e) {
-        chrome.developerPrivate.updateExtensionConfiguration({
-          extensionId: extension.id,
-          showActionButton: true
-        });
-      });
-
       // The 'allow in incognito' checkbox.
       wrapper.setupColumn('incognito', '.incognito-control input', 'change',
                           function(e) {
@@ -631,10 +623,6 @@
       this.setText_(wrapper, '.blacklist-text', extension.blacklistText || '');
       this.setText_(wrapper, '.extension-description', extension.description);
 
-      // The 'Show Browser Action' button.
-      this.updateVisibility_(wrapper, '.show-button',
-                             isActive && extension.actionButtonHidden);
-
       // The 'allow in incognito' checkbox.
       this.updateVisibility_(wrapper, '.incognito-control',
                              isActive && this.incognitoAvailable_,
diff --git a/chrome/browser/resources/extensions/extensions.html b/chrome/browser/resources/extensions/extensions.html
index 0f4be9a..72a4c4c 100644
--- a/chrome/browser/resources/extensions/extensions.html
+++ b/chrome/browser/resources/extensions/extensions.html
@@ -207,8 +207,6 @@
           </div>
         </div>
         <div class="optional-controls">
-          <button class="show-button"
-              hidden>$i18n{extensionSettingsShowButton}</button>
           <div class="checkbox">
             <label class="incognito-control">
               <input type="checkbox">
diff --git a/chrome/browser/supervised_user/supervised_user_url_filter.cc b/chrome/browser/supervised_user/supervised_user_url_filter.cc
index 43767fc..adde909b 100644
--- a/chrome/browser/supervised_user/supervised_user_url_filter.cc
+++ b/chrome/browser/supervised_user/supervised_user_url_filter.cc
@@ -243,12 +243,11 @@
   DCHECK(amp_cache_path_regex_.ok());
   DCHECK(google_amp_viewer_path_regex_.ok());
   DCHECK(google_web_cache_query_regex_.ok());
-  // Detach from the current thread so we can be constructed on a different
-  // thread than the one where we're used.
-  DetachFromThread();
 }
 
-SupervisedUserURLFilter::~SupervisedUserURLFilter() {}
+SupervisedUserURLFilter::~SupervisedUserURLFilter() {
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+}
 
 // static
 SupervisedUserURLFilter::FilteringBehavior
@@ -337,7 +336,7 @@
     const GURL& url,
     bool manual_only,
     supervised_user_error_page::FilteringBehaviorReason* reason) const {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
 
   GURL effective_url = GetEmbeddedURL(url);
   if (!effective_url.is_valid())
@@ -463,7 +462,7 @@
 
 void SupervisedUserURLFilter::SetDefaultFilteringBehavior(
     FilteringBehavior behavior) {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   default_behavior_ = behavior;
 }
 
@@ -474,7 +473,7 @@
 
 void SupervisedUserURLFilter::LoadWhitelists(
     const std::vector<scoped_refptr<SupervisedUserSiteList>>& site_lists) {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
 
   base::PostTaskAndReplyWithResult(
       blocking_task_runner_.get(), FROM_HERE,
@@ -494,7 +493,7 @@
 
 void SupervisedUserURLFilter::SetFromPatternsForTesting(
     const std::vector<std::string>& patterns) {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
 
   base::PostTaskAndReplyWithResult(
       blocking_task_runner_.get(), FROM_HERE,
@@ -505,7 +504,7 @@
 
 void SupervisedUserURLFilter::SetFromSiteListsForTesting(
     const std::vector<scoped_refptr<SupervisedUserSiteList>>& site_lists) {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
 
   base::PostTaskAndReplyWithResult(
       blocking_task_runner_.get(), FROM_HERE,
@@ -516,12 +515,12 @@
 
 void SupervisedUserURLFilter::SetManualHosts(
     std::map<std::string, bool> host_map) {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   host_map_ = std::move(host_map);
 }
 
 void SupervisedUserURLFilter::SetManualURLs(std::map<GURL, bool> url_map) {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   url_map_ = std::move(url_map);
 }
 
@@ -661,7 +660,7 @@
 }
 
 void SupervisedUserURLFilter::SetContents(std::unique_ptr<Contents> contents) {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   contents_ = std::move(contents);
   for (Observer& observer : observers_)
     observer.OnSiteListUpdated();
diff --git a/chrome/browser/supervised_user/supervised_user_url_filter.h b/chrome/browser/supervised_user/supervised_user_url_filter.h
index 3e3d87d..9bb5171 100644
--- a/chrome/browser/supervised_user/supervised_user_url_filter.h
+++ b/chrome/browser/supervised_user/supervised_user_url_filter.h
@@ -13,7 +13,7 @@
 #include "base/callback_forward.h"
 #include "base/macros.h"
 #include "base/observer_list.h"
-#include "base/threading/non_thread_safe.h"
+#include "base/sequence_checker.h"
 #include "base/values.h"
 #include "chrome/browser/safe_search_api/safe_search_url_checker.h"
 #include "chrome/browser/supervised_user/supervised_user_site_list.h"
@@ -41,7 +41,7 @@
 //   * User-specified manual overrides (allow or block) for either sites
 //     (hostnames) or exact URLs, which take precedence over the previous
 //     sources.
-class SupervisedUserURLFilter : public base::NonThreadSafe {
+class SupervisedUserURLFilter {
  public:
   enum FilteringBehavior {
     ALLOW,
@@ -219,6 +219,8 @@
 
   scoped_refptr<base::TaskRunner> blocking_task_runner_;
 
+  SEQUENCE_CHECKER(sequence_checker_);
+
   base::WeakPtrFactory<SupervisedUserURLFilter> weak_ptr_factory_;
 
   DISALLOW_COPY_AND_ASSIGN(SupervisedUserURLFilter);
diff --git a/chrome/browser/ui/app_list/search_answer_web_contents_delegate.cc b/chrome/browser/ui/app_list/search_answer_web_contents_delegate.cc
index d9ba2e56..a0f9487b 100644
--- a/chrome/browser/ui/app_list/search_answer_web_contents_delegate.cc
+++ b/chrome/browser/ui/app_list/search_answer_web_contents_delegate.cc
@@ -21,6 +21,7 @@
 #include "ui/app_list/app_list_features.h"
 #include "ui/app_list/app_list_model.h"
 #include "ui/app_list/search_box_model.h"
+#include "ui/views/controls/webview/web_contents_set_background_color.h"
 #include "ui/views/controls/webview/webview.h"
 #include "ui/views/widget/widget.h"
 
@@ -105,6 +106,11 @@
     web_view_->SetFocusBehavior(views::View::FocusBehavior::NEVER);
 
   model->AddObserver(this);
+
+  // Make the webview transparent since it's going to be shown on top of a
+  // highlightable button.
+  views::WebContentsSetBackgroundColor::CreateForWebContentsWithColor(
+      web_contents_.get(), SK_ColorTRANSPARENT);
 }
 
 SearchAnswerWebContentsDelegate::~SearchAnswerWebContentsDelegate() {
@@ -168,8 +174,7 @@
       IsCardSizeOk(pref_size) || features::IsAnswerCardDarkRunEnabled();
   model_->SetSearchAnswerAvailable(is_card_size_ok_ && received_answer_ &&
                                    !web_contents_->IsLoading());
-  if (!features::IsAnswerCardDarkRunEnabled())
-    web_view_->SetPreferredSize(pref_size);
+  web_view_->SetPreferredSize(pref_size);
   if (!answer_loaded_time_.is_null()) {
     UMA_HISTOGRAM_TIMES("SearchAnswer.ResizeAfterLoadTime",
                         base::TimeTicks::Now() - answer_loaded_time_);
diff --git a/chrome/browser/ui/ash/app_list/app_list_interactive_uitest.cc b/chrome/browser/ui/ash/app_list/app_list_interactive_uitest.cc
index f139a47..76973be 100644
--- a/chrome/browser/ui/ash/app_list/app_list_interactive_uitest.cc
+++ b/chrome/browser/ui/ash/app_list/app_list_interactive_uitest.cc
@@ -10,7 +10,6 @@
 #include "ash/shelf/shelf_widget.h"
 #include "ash/shell.h"
 #include "ash/wm/window_util.h"
-#include "ash/wm_window.h"
 #include "base/run_loop.h"
 #include "chrome/test/base/in_process_browser_test.h"
 #include "ui/app_list/presenter/app_list.h"
diff --git a/chrome/browser/ui/ash/chrome_shell_delegate.cc b/chrome/browser/ui/ash/chrome_shell_delegate.cc
index 9709904..9aa1fd61 100644
--- a/chrome/browser/ui/ash/chrome_shell_delegate.cc
+++ b/chrome/browser/ui/ash/chrome_shell_delegate.cc
@@ -19,7 +19,6 @@
 #include "ash/wm/mru_window_tracker.h"
 #include "ash/wm/window_state.h"
 #include "ash/wm/window_util.h"
-#include "ash/wm_window.h"
 #include "base/command_line.h"
 #include "base/macros.h"
 #include "base/memory/ptr_util.h"
@@ -60,6 +59,7 @@
 #include "chrome/browser/ui/browser_tabstrip.h"
 #include "chrome/browser/ui/browser_window.h"
 #include "chrome/browser/ui/scoped_tabbed_browser_displayer.h"
+#include "chrome/browser/ui/tab_contents/tab_contents_iterator.h"
 #include "chrome/common/pref_names.h"
 #include "chrome/grit/chromium_strings.h"
 #include "chrome/grit/generated_resources.h"
@@ -68,6 +68,7 @@
 #include "components/prefs/pref_service.h"
 #include "components/user_manager/user.h"
 #include "components/user_manager/user_manager.h"
+#include "content/public/browser/media_session.h"
 #include "content/public/browser/notification_service.h"
 #include "content/public/common/service_manager_connection.h"
 #include "ui/aura/window.h"
@@ -588,6 +589,13 @@
   chromeos::system::InputDeviceSettings::Get()->ToggleTouchpad();
 }
 
+void ChromeShellDelegate::SuspendMediaSessions() {
+  for (TabContentsIterator it; !it.done(); it.Next()) {
+    content::MediaSession::Get(*it)->Suspend(
+        content::MediaSession::SuspendType::SYSTEM);
+  }
+}
+
 keyboard::KeyboardUI* ChromeShellDelegate::CreateKeyboardUI() {
   return new ChromeKeyboardUI(ProfileManager::GetActiveUserProfile());
 }
diff --git a/chrome/browser/ui/ash/chrome_shell_delegate.h b/chrome/browser/ui/ash/chrome_shell_delegate.h
index 3b953ff..1002ad8 100644
--- a/chrome/browser/ui/ash/chrome_shell_delegate.h
+++ b/chrome/browser/ui/ash/chrome_shell_delegate.h
@@ -60,6 +60,7 @@
                                     bool use_local_state) override;
   void UpdateTouchscreenStatusFromPrefs() override;
   void ToggleTouchpad() override;
+  void SuspendMediaSessions() override;
 
   // content::NotificationObserver override:
   void Observe(int type,
diff --git a/chrome/browser/ui/ash/launcher/arc_app_window_launcher_controller.cc b/chrome/browser/ui/ash/launcher/arc_app_window_launcher_controller.cc
index 229fff1..88779bd 100644
--- a/chrome/browser/ui/ash/launcher/arc_app_window_launcher_controller.cc
+++ b/chrome/browser/ui/ash/launcher/arc_app_window_launcher_controller.cc
@@ -13,7 +13,6 @@
 #include "ash/wm/maximize_mode/maximize_mode_controller.h"
 #include "ash/wm/window_state.h"
 #include "ash/wm/window_util.h"
-#include "ash/wm_window.h"
 #include "base/bind.h"
 #include "base/memory/ptr_util.h"
 #include "chrome/browser/chromeos/arc/arc_util.h"
diff --git a/chrome/browser/ui/ash/launcher/browser_shortcut_launcher_item_controller.cc b/chrome/browser/ui/ash/launcher/browser_shortcut_launcher_item_controller.cc
index 18f8895..359bf41 100644
--- a/chrome/browser/ui/ash/launcher/browser_shortcut_launcher_item_controller.cc
+++ b/chrome/browser/ui/ash/launcher/browser_shortcut_launcher_item_controller.cc
@@ -11,7 +11,6 @@
 #include "ash/public/cpp/window_properties.h"
 #include "ash/resources/grit/ash_resources.h"
 #include "ash/shelf/shelf_model.h"
-#include "ash/wm_window.h"
 #include "base/memory/ptr_util.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/ui/ash/launcher/chrome_launcher_controller.h"
diff --git a/chrome/browser/ui/ash/launcher/chrome_launcher_controller_browsertest.cc b/chrome/browser/ui/ash/launcher/chrome_launcher_controller_browsertest.cc
index 2ca87d9..4d5aa7c4 100644
--- a/chrome/browser/ui/ash/launcher/chrome_launcher_controller_browsertest.cc
+++ b/chrome/browser/ui/ash/launcher/chrome_launcher_controller_browsertest.cc
@@ -20,7 +20,6 @@
 #include "ash/test/shelf_view_test_api.h"
 #include "ash/wm/window_state.h"
 #include "ash/wm/window_util.h"
-#include "ash/wm_window.h"
 #include "base/macros.h"
 #include "base/run_loop.h"
 #include "base/strings/stringprintf.h"
diff --git a/chrome/browser/ui/ash/launcher/extension_app_window_launcher_controller.cc b/chrome/browser/ui/ash/launcher/extension_app_window_launcher_controller.cc
index fbf6bd2..b8da64f 100644
--- a/chrome/browser/ui/ash/launcher/extension_app_window_launcher_controller.cc
+++ b/chrome/browser/ui/ash/launcher/extension_app_window_launcher_controller.cc
@@ -8,7 +8,6 @@
 #include "ash/public/cpp/window_properties.h"
 #include "ash/shelf/shelf_model.h"
 #include "ash/wm/window_util.h"
-#include "ash/wm_window.h"
 #include "base/stl_util.h"
 #include "base/strings/stringprintf.h"
 #include "chrome/browser/profiles/profile.h"
diff --git a/chrome/browser/ui/ash/launcher/launcher_context_menu_unittest.cc b/chrome/browser/ui/ash/launcher/launcher_context_menu_unittest.cc
index 9b2b0a4..4eb1833 100644
--- a/chrome/browser/ui/ash/launcher/launcher_context_menu_unittest.cc
+++ b/chrome/browser/ui/ash/launcher/launcher_context_menu_unittest.cc
@@ -13,7 +13,6 @@
 #include "ash/test/ash_test_helper.h"
 #include "ash/test/shell_test_api.h"
 #include "ash/test/test_shell_delegate.h"
-#include "ash/wm_window.h"
 #include "base/macros.h"
 #include "base/memory/ptr_util.h"
 #include "chrome/app/chrome_command_ids.h"
diff --git a/chrome/browser/ui/ash/launcher/multi_profile_browser_status_monitor.cc b/chrome/browser/ui/ash/launcher/multi_profile_browser_status_monitor.cc
index 465c5a38..55fd1151 100644
--- a/chrome/browser/ui/ash/launcher/multi_profile_browser_status_monitor.cc
+++ b/chrome/browser/ui/ash/launcher/multi_profile_browser_status_monitor.cc
@@ -6,7 +6,6 @@
 
 #include "ash/public/cpp/shelf_item.h"
 #include "ash/public/cpp/window_properties.h"
-#include "ash/wm_window.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/profiles/profile_manager.h"
 #include "chrome/browser/ui/ash/launcher/chrome_launcher_controller.h"
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 ab990c9..d400c3f 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
@@ -13,7 +13,6 @@
 #include "ash/shell.h"
 #include "ash/wm/maximize_mode/maximize_mode_controller.h"
 #include "ash/wm/window_state.h"
-#include "ash/wm_window.h"
 #include "base/auto_reset.h"
 #include "base/macros.h"
 #include "base/message_loop/message_loop.h"
diff --git a/chrome/browser/ui/ash/multi_user/multi_user_window_manager_chromeos_unittest.cc b/chrome/browser/ui/ash/multi_user/multi_user_window_manager_chromeos_unittest.cc
index 67062a9..73cbbbd 100644
--- a/chrome/browser/ui/ash/multi_user/multi_user_window_manager_chromeos_unittest.cc
+++ b/chrome/browser/ui/ash/multi_user/multi_user_window_manager_chromeos_unittest.cc
@@ -22,7 +22,6 @@
 #include "ash/wm/window_state.h"
 #include "ash/wm/window_util.h"
 #include "ash/wm/wm_event.h"
-#include "ash/wm_window.h"
 #include "base/compiler_specific.h"
 #include "base/logging.h"
 #include "base/macros.h"
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 7be43c57..c4935d7a 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
@@ -15,7 +15,6 @@
 #include "ash/wm/window_positioner.h"
 #include "ash/wm/window_state.h"
 #include "ash/wm/window_util.h"
-#include "ash/wm_window.h"
 #include "base/macros.h"
 #include "chrome/browser/chromeos/login/users/wallpaper/wallpaper_manager.h"
 #include "chrome/browser/ui/ash/launcher/chrome_launcher_controller.h"
diff --git a/chrome/browser/ui/cocoa/omnibox/omnibox_popup_cell.h b/chrome/browser/ui/cocoa/omnibox/omnibox_popup_cell.h
index 21ba308..63e4c554 100644
--- a/chrome/browser/ui/cocoa/omnibox/omnibox_popup_cell.h
+++ b/chrome/browser/ui/cocoa/omnibox/omnibox_popup_cell.h
@@ -68,7 +68,7 @@
 
 + (CGFloat)getContentAreaWidth:(NSRect)cellFrame;
 
-+ (CGFloat)getContentTextHeight;
++ (CGFloat)getContentTextHeightForDoubleLine:(BOOL)isDoubleLine;
 
 @end
 
diff --git a/chrome/browser/ui/cocoa/omnibox/omnibox_popup_cell.mm b/chrome/browser/ui/cocoa/omnibox/omnibox_popup_cell.mm
index a41858a..2350df54 100644
--- a/chrome/browser/ui/cocoa/omnibox/omnibox_popup_cell.mm
+++ b/chrome/browser/ui/cocoa/omnibox/omnibox_popup_cell.mm
@@ -9,6 +9,7 @@
 #include <algorithm>
 #include <cmath>
 
+#include "base/feature_list.h"
 #include "base/i18n/rtl.h"
 #include "base/mac/foundation_util.h"
 #include "base/mac/objc_property_releaser.h"
@@ -40,10 +41,12 @@
 
 constexpr CGFloat kMaterialImageXOffset = 6.0;
 
+constexpr CGFloat kDefaultVerticalMargin = 3.0;
+
+constexpr CGFloat kDefaultTextHeight = 19;
+
 // Returns the margin that should appear at the top and bottom of the result.
 CGFloat GetVerticalMargin() {
-  constexpr CGFloat kDefaultVerticalMargin = 3.0;
-
   return base::GetFieldTrialParamByFeatureAsInt(
       omnibox::kUIExperimentVerticalMargin,
       OmniboxFieldTrial::kUIVerticalMarginParam, kDefaultVerticalMargin);
@@ -421,11 +424,21 @@
           match.contents, ContentTextColor(isDarkTheme), match.contents_class,
           isDarkTheme) retain];
       if (!match.description.empty()) {
+        // Swap the contents and description of non-search suggestions in
+        // vertical layouts.
+        BOOL swapMatchText = base::FeatureList::IsEnabled(
+                                 omnibox::kUIExperimentVerticalLayout) &&
+                             !AutocompleteMatch::IsSearchType(match.type);
+
         description_ = [CreateClassifiedAttributedString(
-            match.description, DimTextColor(isDarkTheme),
+            match.description,
+            swapMatchText ? ContentTextColor(isDarkTheme)
+                          : DimTextColor(isDarkTheme),
             match.description_class, isDarkTheme) retain];
+
+        if (swapMatchText)
+          std::swap(contents_, description_);
       }
-      maxLines_ = 1;
     }
     propertyReleaser_OmniboxPopupCellData_.Init(self,
                                                 [OmniboxPopupCellData class]);
@@ -463,6 +476,9 @@
 }
 
 - (void)drawMatchWithFrame:(NSRect)cellFrame inView:(NSView*)controlView {
+  bool isVerticalLayout =
+      base::FeatureList::IsEnabled(omnibox::kUIExperimentVerticalLayout);
+
   OmniboxPopupCellData* cellData =
       base::mac::ObjCCastStrict<OmniboxPopupCellData>([self objectValue]);
   OmniboxPopupMatrix* tableView =
@@ -476,12 +492,12 @@
   int contentsMaxWidth, descriptionMaxWidth;
   OmniboxPopupModel::ComputeMatchMaxWidths(
       ceilf(contentsWidth), ceilf(separatorWidth), ceilf(descriptionWidth),
-      ceilf(remainingWidth),
-      [cellData isAnswer],
-      !AutocompleteMatch::IsSearchType([cellData matchType]),
-      &contentsMaxWidth,
+      ceilf(remainingWidth), [cellData isAnswer] || isVerticalLayout,
+      !AutocompleteMatch::IsSearchType([cellData matchType]), &contentsMaxWidth,
       &descriptionMaxWidth);
 
+  CGFloat halfLineHeight = (kDefaultTextHeight + kDefaultVerticalMargin) / 2;
+
   NSWindow* parentWindow = [[controlView window] parentWindow];
   BOOL isDarkTheme = [parentWindow hasDarkTheme];
   NSRect imageRect = cellFrame;
@@ -491,6 +507,8 @@
   imageRect.origin.x += kMaterialImageXOffset + [tableView contentLeftPadding];
   imageRect.origin.y +=
       GetVerticalMargin() + kMaterialExtraVerticalImagePadding;
+  if (isVerticalLayout)
+    imageRect.origin.y += halfLineHeight;
   [theImage drawInRect:FlipIfRTL(imageRect, cellFrame)
               fromRect:NSZeroRect
              operation:NSCompositeSourceOver
@@ -498,9 +516,13 @@
         respectFlipped:YES
                  hints:nil];
 
-  NSPoint origin =
-      NSMakePoint(kMaterialTextStartOffset + [tableView contentLeftPadding],
-                  GetVerticalMargin());
+  CGFloat left = kMaterialTextStartOffset + [tableView contentLeftPadding];
+  NSPoint origin = NSMakePoint(left, GetVerticalMargin());
+
+  // For matches lacking description in vertical layout, center vertically.
+  if (isVerticalLayout && descriptionMaxWidth == 0)
+    origin.y += halfLineHeight;
+
   if ([cellData matchType] == AutocompleteMatchType::SEARCH_SUGGEST_TAIL) {
     // Tail suggestions are rendered with a prefix (usually ellipsis), which
     // appear vertically stacked.
@@ -518,8 +540,8 @@
   if (descriptionMaxWidth > 0) {
     if ([cellData isAnswer]) {
       origin = NSMakePoint(
-          kMaterialTextStartOffset + [tableView contentLeftPadding],
-          [OmniboxPopupCell getContentTextHeight] - GetVerticalMargin());
+          left, [OmniboxPopupCell getContentTextHeightForDoubleLine:NO] -
+                    GetVerticalMargin());
       CGFloat imageSize = [tableView answerLineHeight];
       NSRect imageRect =
           NSMakeRect(NSMinX(cellFrame) + origin.x, NSMinY(cellFrame) + origin.y,
@@ -538,17 +560,22 @@
         origin.y += 1;
       }
     } else {
-      origin.x += [self drawMatchPart:[tableView separator]
-                            withFrame:cellFrame
-                               origin:origin
-                         withMaxWidth:separatorWidth
-                         forDarkTheme:isDarkTheme];
+      if (isVerticalLayout) {
+        origin.x = left;
+        origin.y += halfLineHeight * 2;
+      } else {
+        origin.x += [self drawMatchPart:[tableView separator]
+                              withFrame:cellFrame
+                                 origin:origin
+                           withMaxWidth:separatorWidth
+                           forDarkTheme:isDarkTheme];
+      }
     }
-    origin.x += [self drawMatchPart:[cellData description]
-                          withFrame:cellFrame
-                             origin:origin
-                       withMaxWidth:descriptionMaxWidth
-                       forDarkTheme:isDarkTheme];
+    [self drawMatchPart:[cellData description]
+              withFrame:cellFrame
+                 origin:origin
+           withMaxWidth:descriptionMaxWidth
+           forDarkTheme:isDarkTheme];
   }
 }
 
@@ -695,9 +722,11 @@
   return NSWidth(cellFrame) - kMaterialTextStartOffset;
 }
 
-+ (CGFloat)getContentTextHeight {
-  constexpr CGFloat kDefaultTextHeight = 19;
-  return kDefaultTextHeight + 2 * GetVerticalMargin();
++ (CGFloat)getContentTextHeightForDoubleLine:(BOOL)isDoubleLine {
+  CGFloat height = kDefaultTextHeight + 2 * GetVerticalMargin();
+  if (isDoubleLine)
+    height += kDefaultTextHeight + kDefaultVerticalMargin;
+  return height;
 }
 
 @end
diff --git a/chrome/browser/ui/cocoa/omnibox/omnibox_popup_matrix.mm b/chrome/browser/ui/cocoa/omnibox/omnibox_popup_matrix.mm
index ca66db2..86a132b 100644
--- a/chrome/browser/ui/cocoa/omnibox/omnibox_popup_matrix.mm
+++ b/chrome/browser/ui/cocoa/omnibox/omnibox_popup_matrix.mm
@@ -4,12 +4,14 @@
 
 #import "chrome/browser/ui/cocoa/omnibox/omnibox_popup_matrix.h"
 
+#include "base/feature_list.h"
 #include "base/logging.h"
 #include "base/mac/foundation_util.h"
 #import "chrome/browser/ui/cocoa/omnibox/omnibox_popup_cell.h"
 #include "chrome/browser/ui/cocoa/omnibox/omnibox_popup_view_mac.h"
 #include "chrome/browser/ui/cocoa/omnibox/omnibox_view_mac.h"
 #include "components/omnibox/browser/autocomplete_result.h"
+#include "components/omnibox/browser/omnibox_field_trial.h"
 
 namespace {
 
@@ -106,8 +108,13 @@
 }
 
 - (CGFloat)tableView:(NSTableView*)tableView heightOfRow:(NSInteger)row {
-  CGFloat height = [OmniboxPopupCell getContentTextHeight];
-  if ([[array_ objectAtIndex:row] isAnswer]) {
+  BOOL isAnswer = [[array_ objectAtIndex:row] isAnswer];
+  BOOL isDoubleLine = !isAnswer && base::FeatureList::IsEnabled(
+                                       omnibox::kUIExperimentVerticalLayout);
+  CGFloat height =
+      [OmniboxPopupCell getContentTextHeightForDoubleLine:isDoubleLine];
+
+  if (isAnswer) {
     OmniboxPopupMatrix* matrix =
         base::mac::ObjCCastStrict<OmniboxPopupMatrix>(tableView);
     NSRect rowRect = [tableView rectOfColumn:0];
diff --git a/chrome/browser/ui/javascript_dialogs/javascript_dialog_browsertest.cc b/chrome/browser/ui/javascript_dialogs/javascript_dialog_browsertest.cc
index 73a3549..a84ba449 100644
--- a/chrome/browser/ui/javascript_dialogs/javascript_dialog_browsertest.cc
+++ b/chrome/browser/ui/javascript_dialogs/javascript_dialog_browsertest.cc
@@ -5,11 +5,9 @@
 #include "base/logging.h"
 #include "base/strings/utf_string_conversions.h"
 #include "base/test/scoped_command_line.h"
-#include "base/test/scoped_feature_list.h"
 #include "chrome/browser/ui/browser.h"
 #include "chrome/browser/ui/javascript_dialogs/javascript_dialog_tab_helper.h"
 #include "chrome/browser/ui/tabs/tab_strip_model.h"
-#include "chrome/common/chrome_features.h"
 #include "chrome/common/chrome_switches.h"
 #include "chrome/test/base/in_process_browser_test.h"
 #include "content/public/browser/render_frame_host.h"
@@ -20,9 +18,6 @@
 using JavaScriptDialogTest = InProcessBrowserTest;
 
 IN_PROC_BROWSER_TEST_F(JavaScriptDialogTest, ReloadDoesntHang) {
-  base::test::ScopedFeatureList feature_list;
-  feature_list.InitAndEnableFeature(features::kAutoDismissingDialogs);
-
   content::WebContents* tab =
       browser()->tab_strip_model()->GetActiveWebContents();
   JavaScriptDialogTabHelper* js_helper =
@@ -44,9 +39,6 @@
 
 IN_PROC_BROWSER_TEST_F(JavaScriptDialogTest,
                        ClosingPageSharingRendererDoesntHang) {
-  base::test::ScopedFeatureList feature_list;
-  feature_list.InitAndEnableFeature(features::kAutoDismissingDialogs);
-
   // Turn off popup blocking.
   base::test::ScopedCommandLine scoped_command_line;
   scoped_command_line.GetProcessCommandLine()->AppendSwitch(
@@ -85,9 +77,6 @@
 
 IN_PROC_BROWSER_TEST_F(JavaScriptDialogTest,
                        ClosingPageWithSubframeAlertingDoesntCrash) {
-  base::test::ScopedFeatureList feature_list;
-  feature_list.InitAndEnableFeature(features::kAutoDismissingDialogs);
-
   content::WebContents* tab =
       browser()->tab_strip_model()->GetActiveWebContents();
   JavaScriptDialogTabHelper* js_helper =
diff --git a/chrome/browser/ui/javascript_dialogs/javascript_dialog_tab_helper.cc b/chrome/browser/ui/javascript_dialogs/javascript_dialog_tab_helper.cc
index 3c129dd..299623b 100644
--- a/chrome/browser/ui/javascript_dialogs/javascript_dialog_tab_helper.cc
+++ b/chrome/browser/ui/javascript_dialogs/javascript_dialog_tab_helper.cc
@@ -14,7 +14,6 @@
 #include "chrome/browser/ui/browser_list.h"
 #include "chrome/browser/ui/tab_modal_confirm_dialog.h"
 #include "chrome/browser/ui/tabs/tab_strip_model.h"
-#include "chrome/common/chrome_features.h"
 #include "components/app_modal/javascript_dialog_manager.h"
 #include "content/public/browser/navigation_handle.h"
 #include "content/public/browser/render_frame_host.h"
@@ -24,10 +23,6 @@
 
 namespace {
 
-bool IsEnabled() {
-  return base::FeatureList::IsEnabled(features::kAutoDismissingDialogs);
-}
-
 app_modal::JavaScriptDialogManager* AppModalDialogManager() {
   return app_modal::JavaScriptDialogManager::GetInstance();
 }
@@ -133,70 +128,64 @@
       break;
   }
 
-  if (IsEnabled()) {
-    if (!IsWebContentsForemost(parent_web_contents) &&
-        dialog_type == content::JAVASCRIPT_DIALOG_TYPE_PROMPT) {
-      // Don't allow "prompt" dialogs to steal the user's focus. TODO(avi):
-      // Eventually, for subsequent phases of http://bit.ly/project-oldspice,
-      // turn off focus stealing for other dialog types.
-      *did_suppress_message = true;
-      alerting_web_contents->GetMainFrame()->AddMessageToConsole(
-          content::CONSOLE_MESSAGE_LEVEL_WARNING,
-          "A window.prompt() dialog generated by this page was suppressed "
-          "because this page is not the active tab of the front window. "
-          "Please make sure your dialogs are triggered by user interactions "
-          "to avoid this situation. "
-          "https://www.chromestatus.com/feature/5637107137642496");
-      return;
-    }
+  if (!IsWebContentsForemost(parent_web_contents) &&
+      dialog_type == content::JAVASCRIPT_DIALOG_TYPE_PROMPT) {
+    // Don't allow "prompt" dialogs to steal the user's focus. TODO(avi):
+    // Eventually, for subsequent phases of http://bit.ly/project-oldspice,
+    // turn off focus stealing for other dialog types.
+    *did_suppress_message = true;
+    alerting_web_contents->GetMainFrame()->AddMessageToConsole(
+        content::CONSOLE_MESSAGE_LEVEL_WARNING,
+        "A window.prompt() dialog generated by this page was suppressed "
+        "because this page is not the active tab of the front window. "
+        "Please make sure your dialogs are triggered by user interactions "
+        "to avoid this situation. "
+        "https://www.chromestatus.com/feature/5637107137642496");
+    return;
+  }
 
-    if (dialog_) {
-      // There's already a dialog up; clear it out.
-      CloseDialog(false, base::string16(),
-                  DismissalCause::SUBSEQUENT_DIALOG_SHOWN);
-    }
+  if (dialog_) {
+    // There's already a dialog up; clear it out.
+    CloseDialog(false, base::string16(),
+                DismissalCause::SUBSEQUENT_DIALOG_SHOWN);
+  }
 
-    // Enforce sane sizes. ElideRectangleString breaks horizontally, which isn't
-    // strictly needed, but it restricts the vertical size, which is crucial.
-    // This gives about 2000 characters, which is about the same as the
-    // AppModalDialogManager provides, but allows no more than 24 lines.
-    const int kMessageTextMaxRows = 24;
-    const int kMessageTextMaxCols = 80;
-    const size_t kDefaultPromptMaxSize = 2000;
-    base::string16 truncated_message_text;
-    gfx::ElideRectangleString(message_text, kMessageTextMaxRows,
-                              kMessageTextMaxCols, false,
-                              &truncated_message_text);
-    base::string16 truncated_default_prompt_text;
-    gfx::ElideString(default_prompt_text, kDefaultPromptMaxSize,
-                     &truncated_default_prompt_text);
+  // Enforce sane sizes. ElideRectangleString breaks horizontally, which isn't
+  // strictly needed, but it restricts the vertical size, which is crucial.
+  // This gives about 2000 characters, which is about the same as the
+  // AppModalDialogManager provides, but allows no more than 24 lines.
+  const int kMessageTextMaxRows = 24;
+  const int kMessageTextMaxCols = 80;
+  const size_t kDefaultPromptMaxSize = 2000;
+  base::string16 truncated_message_text;
+  gfx::ElideRectangleString(message_text, kMessageTextMaxRows,
+                            kMessageTextMaxCols, false,
+                            &truncated_message_text);
+  base::string16 truncated_default_prompt_text;
+  gfx::ElideString(default_prompt_text, kDefaultPromptMaxSize,
+                   &truncated_default_prompt_text);
 
-    base::string16 title =
-        AppModalDialogManager()->GetTitle(alerting_web_contents, origin_url);
-    dialog_callback_ = callback;
-    dialog_type_ = dialog_type;
-    dialog_ = JavaScriptDialog::Create(
-        parent_web_contents, alerting_web_contents, title, dialog_type,
-        truncated_message_text, truncated_default_prompt_text,
-        base::Bind(&JavaScriptDialogTabHelper::OnDialogClosed,
-                   base::Unretained(this), callback));
+  base::string16 title =
+      AppModalDialogManager()->GetTitle(alerting_web_contents, origin_url);
+  dialog_callback_ = callback;
+  dialog_type_ = dialog_type;
+  dialog_ = JavaScriptDialog::Create(
+      parent_web_contents, alerting_web_contents, title, dialog_type,
+      truncated_message_text, truncated_default_prompt_text,
+      base::Bind(&JavaScriptDialogTabHelper::OnDialogClosed,
+                 base::Unretained(this), callback));
 
-    BrowserList::AddObserver(this);
+  BrowserList::AddObserver(this);
 
-    // Message suppression is something that we don't give the user a checkbox
-    // for any more. It was useful back in the day when dialogs were app-modal
-    // and clicking the checkbox was the only way to escape a loop that the page
-    // was doing, but now the user can just close the page.
-    *did_suppress_message = false;
+  // Message suppression is something that we don't give the user a checkbox
+  // for any more. It was useful back in the day when dialogs were app-modal
+  // and clicking the checkbox was the only way to escape a loop that the page
+  // was doing, but now the user can just close the page.
+  *did_suppress_message = false;
 
-    if (!dialog_shown_.is_null()) {
-      dialog_shown_.Run();
-      dialog_shown_.Reset();
-    }
-  } else {
-    AppModalDialogManager()->RunJavaScriptDialog(
-        alerting_web_contents, origin_url, dialog_type, message_text,
-        default_prompt_text, callback, did_suppress_message);
+  if (!dialog_shown_.is_null()) {
+    dialog_shown_.Run();
+    dialog_shown_.Reset();
   }
 
   if (did_suppress_message) {
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 5c7f6c1..360f4fab 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
@@ -12,7 +12,7 @@
 #include "ash/frame/frame_border_hit_test.h"
 #include "ash/frame/header_painter_util.h"
 #include "ash/shell.h"
-#include "ash/wm_window.h"
+#include "ash/wm/window_util.h"
 #include "base/feature_list.h"
 #include "build/build_config.h"
 #include "chrome/browser/profiles/profiles_state.h"
@@ -75,8 +75,8 @@
     : BrowserNonClientFrameView(frame, browser_view),
       caption_button_container_(nullptr),
       window_icon_(nullptr) {
-  ash::WmWindow::Get(frame->GetNativeWindow())
-      ->InstallResizeHandleWindowTargeter(nullptr);
+  ash::wm::InstallResizeHandleWindowTargeterForWindow(frame->GetNativeWindow(),
+                                                      nullptr);
   ash::Shell::Get()->AddShellObserver(this);
 }
 
diff --git a/chrome/browser/ui/views/payments/payment_request_can_make_payment_metrics_browsertest.cc b/chrome/browser/ui/views/payments/payment_request_can_make_payment_metrics_browsertest.cc
index b9c76b8..eb211487 100644
--- a/chrome/browser/ui/views/payments/payment_request_can_make_payment_metrics_browsertest.cc
+++ b/chrome/browser/ui/views/payments/payment_request_can_make_payment_metrics_browsertest.cc
@@ -63,8 +63,8 @@
                                      JourneyLogger::CAN_MAKE_PAYMENT_USED, 1);
   histogram_tester.ExpectBucketCount(
       "PaymentRequest.CanMakePayment.Used.EffectOnShow",
-      JourneyLogger::CMP_SHOW_DID_SHOW |
-          JourneyLogger::CMP_SHOW_COULD_MAKE_PAYMENT,
+      JourneyLogger::CMP_EFFECT_ON_SHOW_DID_SHOW |
+          JourneyLogger::CMP_EFFECT_ON_SHOW_COULD_MAKE_PAYMENT,
       1);
   histogram_tester.ExpectBucketCount(
       "PaymentRequest.CanMakePayment.Used.TrueWithShowEffectOnCompletion",
@@ -100,8 +100,8 @@
                                      JourneyLogger::CAN_MAKE_PAYMENT_USED, 1);
   histogram_tester.ExpectBucketCount(
       "PaymentRequest.CanMakePayment.Used.EffectOnShow",
-      JourneyLogger::CMP_SHOW_DID_SHOW |
-          JourneyLogger::CMP_SHOW_COULD_MAKE_PAYMENT,
+      JourneyLogger::CMP_EFFECT_ON_SHOW_DID_SHOW |
+          JourneyLogger::CMP_EFFECT_ON_SHOW_COULD_MAKE_PAYMENT,
       1);
   histogram_tester.ExpectBucketCount(
       "PaymentRequest.CanMakePayment.Used.TrueWithShowEffectOnCompletion",
@@ -131,8 +131,8 @@
                                      JourneyLogger::CAN_MAKE_PAYMENT_USED, 1);
   histogram_tester.ExpectBucketCount(
       "PaymentRequest.CanMakePayment.Used.EffectOnShow",
-      JourneyLogger::CMP_SHOW_DID_SHOW |
-          JourneyLogger::CMP_SHOW_COULD_MAKE_PAYMENT,
+      JourneyLogger::CMP_EFFECT_ON_SHOW_DID_SHOW |
+          JourneyLogger::CMP_EFFECT_ON_SHOW_COULD_MAKE_PAYMENT,
       1);
   histogram_tester.ExpectBucketCount(
       "PaymentRequest.CanMakePayment.Used.TrueWithShowEffectOnCompletion",
@@ -176,7 +176,7 @@
                                      JourneyLogger::CAN_MAKE_PAYMENT_USED, 1);
   histogram_tester.ExpectBucketCount(
       "PaymentRequest.CanMakePayment.Used.EffectOnShow",
-      JourneyLogger::CMP_SHOW_DID_SHOW, 1);
+      JourneyLogger::CMP_EFFECT_ON_SHOW_DID_SHOW, 1);
   histogram_tester.ExpectBucketCount(
       "PaymentRequest.CanMakePayment.Used.FalseWithShowEffectOnCompletion",
       JourneyLogger::COMPLETION_STATUS_COMPLETED, 1);
@@ -208,7 +208,7 @@
                                      JourneyLogger::CAN_MAKE_PAYMENT_USED, 1);
   histogram_tester.ExpectBucketCount(
       "PaymentRequest.CanMakePayment.Used.EffectOnShow",
-      JourneyLogger::CMP_SHOW_DID_SHOW, 1);
+      JourneyLogger::CMP_EFFECT_ON_SHOW_DID_SHOW, 1);
   histogram_tester.ExpectBucketCount(
       "PaymentRequest.CanMakePayment.Used.FalseWithShowEffectOnCompletion",
       JourneyLogger::COMPLETION_STATUS_OTHER_ABORTED, 1);
@@ -234,7 +234,7 @@
                                      JourneyLogger::CAN_MAKE_PAYMENT_USED, 1);
   histogram_tester.ExpectBucketCount(
       "PaymentRequest.CanMakePayment.Used.EffectOnShow",
-      JourneyLogger::CMP_SHOW_DID_SHOW, 1);
+      JourneyLogger::CMP_EFFECT_ON_SHOW_DID_SHOW, 1);
   histogram_tester.ExpectBucketCount(
       "PaymentRequest.CanMakePayment.Used.FalseWithShowEffectOnCompletion",
       JourneyLogger::COMPLETION_STATUS_USER_ABORTED, 1);
@@ -261,7 +261,7 @@
                                      JourneyLogger::CAN_MAKE_PAYMENT_USED, 1);
   histogram_tester.ExpectBucketCount(
       "PaymentRequest.CanMakePayment.Used.EffectOnShow",
-      JourneyLogger::CMP_SHOW_COULD_MAKE_PAYMENT, 1);
+      JourneyLogger::CMP_EFFECT_ON_SHOW_COULD_MAKE_PAYMENT, 1);
 }
 
 IN_PROC_BROWSER_TEST_F(PaymentRequestCanMakePaymentMetricsTest,
@@ -282,7 +282,8 @@
                                      JourneyLogger::CAN_MAKE_PAYMENT_USED, 1);
   histogram_tester.ExpectBucketCount(
       "PaymentRequest.CanMakePayment.Used.EffectOnShow",
-      JourneyLogger::CMP_SHOW_COULD_NOT_MAKE_PAYMENT_AND_DID_NOT_SHOW, 1);
+      JourneyLogger::CMP_EFFECT_ON_SHOW_COULD_NOT_MAKE_PAYMENT_AND_DID_NOT_SHOW,
+      1);
 }
 
 IN_PROC_BROWSER_TEST_F(PaymentRequestCanMakePaymentMetricsTest,
diff --git a/chrome/browser/ui/views/payments/shipping_address_editor_view_controller_browsertest.cc b/chrome/browser/ui/views/payments/shipping_address_editor_view_controller_browsertest.cc
index 2c0b9167..f919819 100644
--- a/chrome/browser/ui/views/payments/shipping_address_editor_view_controller_browsertest.cc
+++ b/chrome/browser/ui/views/payments/shipping_address_editor_view_controller_browsertest.cc
@@ -11,6 +11,8 @@
 #include "chrome/browser/ui/views/payments/payment_request_dialog_view_ids.h"
 #include "chrome/browser/ui/views/payments/validating_textfield.h"
 #include "components/autofill/core/browser/autofill_country.h"
+#include "components/autofill/core/browser/autofill_profile.h"
+#include "components/autofill/core/browser/autofill_test_utils.h"
 #include "components/autofill/core/browser/country_combobox_model.h"
 #include "components/autofill/core/browser/personal_data_manager.h"
 #include "components/autofill/core/browser/region_combobox_model.h"
@@ -21,6 +23,7 @@
 #include "third_party/libaddressinput/src/cpp/include/libaddressinput/null_storage.h"
 #include "third_party/libaddressinput/src/cpp/include/libaddressinput/source.h"
 #include "ui/views/controls/combobox/combobox.h"
+#include "ui/views/controls/label.h"
 
 namespace payments {
 
@@ -601,7 +604,7 @@
 
 // Tests that the editor accepts an international phone from another country.
 IN_PROC_BROWSER_TEST_F(PaymentRequestShippingAddressEditorTest,
-                       InternationalPhoneNumberFromOtherCountry) {
+                       AddInternationalPhoneNumberFromOtherCountry) {
   InvokePaymentRequestUI();
   OpenShippingAddressEditorScreen();
 
@@ -617,7 +620,7 @@
 
 // Tests that the editor doesn't accept a local phone from another country.
 IN_PROC_BROWSER_TEST_F(PaymentRequestShippingAddressEditorTest,
-                       LocalPhoneNumberFromOtherCountry) {
+                       AddLocalPhoneNumberFromOtherCountry) {
   InvokePaymentRequestUI();
   OpenShippingAddressEditorScreen();
 
@@ -630,4 +633,50 @@
   EXPECT_TRUE(IsEditorTextfieldInvalid(autofill::PHONE_HOME_WHOLE_NUMBER));
 }
 
+// Tests that there is no error label for an international phone from another
+// country.
+IN_PROC_BROWSER_TEST_F(
+    PaymentRequestShippingAddressEditorTest,
+    NoErrorLabelForInternationalPhoneNumberFromOtherCountry) {
+  // Create a profile in the US and add a valid AU phone number in international
+  // format.
+  autofill::AutofillProfile california = autofill::test::GetFullProfile();
+  california.SetRawInfo(autofill::PHONE_HOME_WHOLE_NUMBER,
+                        base::UTF8ToUTF16("+61 2 9374 4000"));
+  AddAutofillProfile(california);
+
+  InvokePaymentRequestUI();
+  OpenShippingAddressSectionScreen();
+
+  // There should be no error label.
+  views::View* sheet = dialog_view()->GetViewByID(
+      static_cast<int>(DialogViewID::SHIPPING_ADDRESS_SHEET_LIST_VIEW));
+  ASSERT_EQ(1, sheet->child_count());
+  EXPECT_EQ(nullptr, sheet->child_at(0)->GetViewByID(
+                         static_cast<int>(DialogViewID::PROFILE_LABEL_ERROR)));
+}
+
+// Tests that there is an error label for an local phone from another country.
+IN_PROC_BROWSER_TEST_F(PaymentRequestShippingAddressEditorTest,
+                       ErrorLabelForLocalPhoneNumberFromOtherCountry) {
+  // Create a profile in the US and add a valid AU phone number in local format.
+  autofill::AutofillProfile california = autofill::test::GetFullProfile();
+  california.set_use_count(50U);
+  california.SetRawInfo(autofill::PHONE_HOME_WHOLE_NUMBER,
+                        base::UTF8ToUTF16("02 9374 4000"));
+  AddAutofillProfile(california);
+
+  InvokePaymentRequestUI();
+  OpenShippingAddressSectionScreen();
+
+  // There should be an error label for the phone number.
+  views::View* sheet = dialog_view()->GetViewByID(
+      static_cast<int>(DialogViewID::SHIPPING_ADDRESS_SHEET_LIST_VIEW));
+  ASSERT_EQ(1, sheet->child_count());
+  views::View* error_label = sheet->child_at(0)->GetViewByID(
+      static_cast<int>(DialogViewID::PROFILE_LABEL_ERROR));
+  EXPECT_EQ(base::ASCIIToUTF16("Phone number required"),
+            static_cast<views::Label*>(error_label)->text());
+}
+
 }  // namespace payments
diff --git a/chrome/browser/ui/webui/extensions/extension_settings_handler.cc b/chrome/browser/ui/webui/extensions/extension_settings_handler.cc
index 7ecfc696..e26eb13f 100644
--- a/chrome/browser/ui/webui/extensions/extension_settings_handler.cc
+++ b/chrome/browser/ui/webui/extensions/extension_settings_handler.cc
@@ -171,8 +171,6 @@
                         google_util::AppendGoogleLocaleParam(
                             GURL(chrome::kRemoveNonCWSExtensionURL),
                             g_browser_process->GetApplicationLocale()).spec()));
-  source->AddString("extensionSettingsShowButton",
-      l10n_util::GetStringUTF16(IDS_EXTENSIONS_SHOW_BUTTON));
   source->AddString("extensionSettingsLoadUnpackedButton",
       l10n_util::GetStringUTF16(IDS_EXTENSIONS_LOAD_UNPACKED_BUTTON));
   source->AddString("extensionSettingsPackButton",
diff --git a/chrome/browser/ui/webui/sync_internals_message_handler.cc b/chrome/browser/ui/webui/sync_internals_message_handler.cc
index 5979034..e67fbc1 100644
--- a/chrome/browser/ui/webui/sync_internals_message_handler.cc
+++ b/chrome/browser/ui/webui/sync_internals_message_handler.cc
@@ -59,16 +59,11 @@
 SyncInternalsMessageHandler::SyncInternalsMessageHandler()
     : SyncInternalsMessageHandler(
           base::BindRepeating(
-              &SyncInternalsMessageHandler::BindForSyncServiceProvider,
-              base::Unretained(this)),
-          base::BindRepeating(
               &syncer::sync_ui_util::ConstructAboutInformation)) {}
 
 SyncInternalsMessageHandler::SyncInternalsMessageHandler(
-    SyncServiceProvider sync_service_provider,
     AboutSyncDataDelegate about_sync_data_delegate)
-    : sync_service_provider_(std::move(sync_service_provider)),
-      about_sync_data_delegate_(std::move(about_sync_data_delegate)),
+    : about_sync_data_delegate_(std::move(about_sync_data_delegate)),
       weak_ptr_factory_(this) {}
 
 SyncInternalsMessageHandler::~SyncInternalsMessageHandler() {
@@ -132,7 +127,7 @@
   // is_registered_ flag protects us from double-registering.  This could
   // happen on a page refresh, where the JavaScript gets re-run but the
   // message handler remains unchanged.
-  SyncService* service = sync_service_provider_.Run();
+  SyncService* service = GetSyncService();
   if (service && !is_registered_) {
     service->AddObserver(this);
     service->AddProtocolEventObserver(this);
@@ -147,7 +142,7 @@
   DCHECK(args->empty());
   AllowJavascript();
 
-  SyncService* service = sync_service_provider_.Run();
+  SyncService* service = GetSyncService();
   if (!service)
     return;
 
@@ -192,7 +187,7 @@
   bool success = ExtractIntegerValue(args, &request_id);
   DCHECK(success);
 
-  SyncService* service = sync_service_provider_.Run();
+  SyncService* service = GetSyncService();
   if (service) {
     // This opens up the possibility of non-javascript code calling us
     // asynchronously, and potentially at times we're not allowed to call into
@@ -284,12 +279,12 @@
 }
 
 void SyncInternalsMessageHandler::SendAboutInfo() {
-  std::unique_ptr<DictionaryValue> value = about_sync_data_delegate_.Run(
-      sync_service_provider_.Run(), chrome::GetChannel());
+  std::unique_ptr<DictionaryValue> value =
+      about_sync_data_delegate_.Run(GetSyncService(), chrome::GetChannel());
   DispatchEvent(syncer::sync_ui_util::kOnAboutInfoUpdated, *value);
 }
 
-SyncService* SyncInternalsMessageHandler::BindForSyncServiceProvider() {
+SyncService* SyncInternalsMessageHandler::GetSyncService() {
   return ProfileSyncServiceFactory::GetForProfile(
       Profile::FromWebUI(web_ui())->GetOriginalProfile());
 }
@@ -301,7 +296,7 @@
 }
 
 void SyncInternalsMessageHandler::UnregisterModelNotifications() {
-  SyncService* service = sync_service_provider_.Run();
+  SyncService* service = GetSyncService();
   if (!service)
     return;
 
diff --git a/chrome/browser/ui/webui/sync_internals_message_handler.h b/chrome/browser/ui/webui/sync_internals_message_handler.h
index 2ef1840..fa703cfa 100644
--- a/chrome/browser/ui/webui/sync_internals_message_handler.h
+++ b/chrome/browser/ui/webui/sync_internals_message_handler.h
@@ -96,16 +96,14 @@
                          std::unique_ptr<base::DictionaryValue> value);
 
  protected:
-  using SyncServiceProvider = base::RepeatingCallback<syncer::SyncService*()>;
-
   using AboutSyncDataDelegate =
       base::RepeatingCallback<std::unique_ptr<base::DictionaryValue>(
           syncer::SyncService* service,
           version_info::Channel channel)>;
 
   // Constructor used for unit testing to override dependencies.
-  SyncInternalsMessageHandler(SyncServiceProvider sync_service_provider,
-                              AboutSyncDataDelegate about_sync_data_delegate);
+  explicit SyncInternalsMessageHandler(
+      AboutSyncDataDelegate about_sync_data_delegate);
 
  private:
   // Fetches updated aboutInfo and sends it to the page in the form of an
@@ -113,9 +111,8 @@
   void SendAboutInfo();
 
   // Gets the ProfileSyncService of the underlying original profile. May return
-  // nullptr (e.g., if sync is disabled on the command line). Shouldn't be
-  // called directly, but instead through |sync_service_provider_|.
-  syncer::SyncService* BindForSyncServiceProvider();
+  // nullptr (e.g., if sync is disabled on the command line).
+  syncer::SyncService* GetSyncService();
 
   // Sends a dispatch event to the UI. Javascript must be enabled.
   void DispatchEvent(const std::string& name, const base::Value& details_value);
@@ -133,9 +130,6 @@
   // ProfileSyncService.
   bool is_registered_for_counters_ = false;
 
-  // An abstraction of who provides the SyncService.
-  SyncServiceProvider sync_service_provider_;
-
   // An abstraction of who creates the about sync info value map.
   AboutSyncDataDelegate about_sync_data_delegate_;
 
diff --git a/chrome/browser/ui/webui/sync_internals_message_handler_unittest.cc b/chrome/browser/ui/webui/sync_internals_message_handler_unittest.cc
index b161119..41299ef 100644
--- a/chrome/browser/ui/webui/sync_internals_message_handler_unittest.cc
+++ b/chrome/browser/ui/webui/sync_internals_message_handler_unittest.cc
@@ -9,6 +9,8 @@
 
 #include "base/command_line.h"
 #include "base/memory/ref_counted.h"
+#include "chrome/browser/sync/profile_sync_service_factory.h"
+#include "chrome/browser/sync/user_event_service_factory.h"
 #include "chrome/test/base/testing_profile.h"
 #include "components/browser_sync/browser_sync_switches.h"
 #include "components/sync/driver/about_sync_util.h"
@@ -34,10 +36,8 @@
  public:
   TestableSyncInternalsMessageHandler(
       content::WebUI* web_ui,
-      SyncServiceProvider sync_service_provider,
       AboutSyncDataDelegate about_sync_data_delegate)
-      : SyncInternalsMessageHandler(std::move(sync_service_provider),
-                                    std::move(about_sync_data_delegate)) {
+      : SyncInternalsMessageHandler(std::move(about_sync_data_delegate)) {
     set_web_ui(web_ui);
   }
 };
@@ -92,6 +92,11 @@
       get_all_nodes_callback_;
 };
 
+static std::unique_ptr<KeyedService> BuildTestSyncService(
+    content::BrowserContext* context) {
+  return base::MakeUnique<TestSyncService>();
+}
+
 class SyncInternalsMessageHandlerTest : public ::testing::Test {
  protected:
   SyncInternalsMessageHandlerTest() {
@@ -99,11 +104,11 @@
     web_contents_.reset(content::WebContents::Create(
         content::WebContents::CreateParams(&profile_, site_instance_.get())));
     web_ui_.set_web_contents(web_contents_.get());
-    test_sync_service_ = base::MakeUnique<TestSyncService>();
+    test_sync_service_ = static_cast<TestSyncService*>(
+        ProfileSyncServiceFactory::GetInstance()->SetTestingFactoryAndUse(
+            &profile_, &BuildTestSyncService));
     handler_.reset(new TestableSyncInternalsMessageHandler(
         &web_ui_,
-        base::BindRepeating(&SyncInternalsMessageHandlerTest::sync_service,
-                            base::Unretained(this)),
         base::BindRepeating(
             &SyncInternalsMessageHandlerTest::ConstructAboutInformation,
             base::Unretained(this))));
@@ -149,7 +154,9 @@
     EXPECT_TRUE(web_ui_.call_data().empty());
   }
 
-  TestSyncService* test_sync_service() { return test_sync_service_.get(); }
+  TestingProfile* profile() { return &profile_; }
+
+  TestSyncService* test_sync_service() { return test_sync_service_; }
 
   TestableSyncInternalsMessageHandler* handler() { return handler_.get(); }
 
@@ -171,19 +178,15 @@
     return last_delegate_sync_service_;
   }
 
-  void ResetSyncService() { test_sync_service_.reset(); }
-
   void ResetHandler() { handler_.reset(); }
 
  private:
-  SyncService* sync_service() { return test_sync_service_.get(); }
-
   content::TestBrowserThreadBundle thread_bundle_;
   TestingProfile profile_;
-  content::TestWebUI web_ui_;
   scoped_refptr<content::SiteInstance> site_instance_;
   std::unique_ptr<content::WebContents> web_contents_;
-  std::unique_ptr<TestSyncService> test_sync_service_;
+  content::TestWebUI web_ui_;
+  TestSyncService* test_sync_service_;
   std::unique_ptr<TestableSyncInternalsMessageHandler> handler_;
   int about_sync_data_delegate_call_count_ = 0;
   SyncService* last_delegate_sync_service_ = nullptr;
@@ -238,7 +241,8 @@
 
 TEST_F(SyncInternalsMessageHandlerTest, AddRemoveObserversSyncDisabled) {
   // Simulate completely disabling sync by flag or other mechanism.
-  ResetSyncService();
+  ProfileSyncServiceFactory::GetInstance()->SetTestingFactory(profile(),
+                                                              nullptr);
 
   ListValue empty_list;
   handler()->HandleRegisterForEvents(&empty_list);
@@ -301,7 +305,8 @@
 
 TEST_F(SyncInternalsMessageHandlerTest, SendAboutInfoSyncDisabled) {
   // Simulate completely disabling sync by flag or other mechanism.
-  ResetSyncService();
+  ProfileSyncServiceFactory::GetInstance()->SetTestingFactory(profile(),
+                                                              nullptr);
 
   handler()->AllowJavascriptForTesting();
   handler()->OnStateChanged(nullptr);
diff --git a/chrome/browser/ui/window_sizer/window_sizer_ash.cc b/chrome/browser/ui/window_sizer/window_sizer_ash.cc
index 8ba020d..9ee0042 100644
--- a/chrome/browser/ui/window_sizer/window_sizer_ash.cc
+++ b/chrome/browser/ui/window_sizer/window_sizer_ash.cc
@@ -7,7 +7,6 @@
 #include "ash/shell.h"
 #include "ash/wm/window_positioner.h"
 #include "ash/wm/window_state.h"
-#include "ash/wm_window.h"
 #include "chrome/browser/ui/ash/ash_util.h"
 #include "chrome/browser/ui/browser.h"
 #include "chrome/browser/ui/browser_window.h"
diff --git a/chrome/browser/ui/window_sizer/window_sizer_ash_uitest.cc b/chrome/browser/ui/window_sizer/window_sizer_ash_uitest.cc
index 8fd7d652..7539e22 100644
--- a/chrome/browser/ui/window_sizer/window_sizer_ash_uitest.cc
+++ b/chrome/browser/ui/window_sizer/window_sizer_ash_uitest.cc
@@ -5,7 +5,6 @@
 #include "ash/shelf/shelf.h"
 #include "ash/shelf/shelf_view.h"
 #include "ash/shell.h"
-#include "ash/wm_window.h"
 #include "base/command_line.h"
 #include "base/location.h"
 #include "base/macros.h"
diff --git a/chrome/browser/ui/window_sizer/window_sizer_ash_unittest.cc b/chrome/browser/ui/window_sizer/window_sizer_ash_unittest.cc
index 637f9cc..69b02c3 100644
--- a/chrome/browser/ui/window_sizer/window_sizer_ash_unittest.cc
+++ b/chrome/browser/ui/window_sizer/window_sizer_ash_unittest.cc
@@ -8,7 +8,6 @@
 #include "ash/wm/window_positioner.h"
 #include "ash/wm/window_resizer.h"
 #include "ash/wm/window_state.h"
-#include "ash/wm_window.h"
 #include "base/memory/ptr_util.h"
 #include "build/build_config.h"
 #include "chrome/browser/ui/ash/ash_util.h"
diff --git a/chrome/browser/win/jumplist.cc b/chrome/browser/win/jumplist.cc
index f8da8be..281ea90 100644
--- a/chrome/browser/win/jumplist.cc
+++ b/chrome/browser/win/jumplist.cc
@@ -30,6 +30,7 @@
 #include "chrome/browser/sessions/tab_restore_service_factory.h"
 #include "chrome/browser/shell_integration_win.h"
 #include "chrome/browser/win/jumplist_file_util.h"
+#include "chrome/browser/win/jumplist_update_util.h"
 #include "chrome/common/chrome_constants.h"
 #include "chrome/common/chrome_icon_resources_win.h"
 #include "chrome/common/chrome_switches.h"
@@ -98,7 +99,7 @@
 
 // Creates a ShellLinkItem preloaded with common switches.
 scoped_refptr<ShellLinkItem> CreateShellLink() {
-  scoped_refptr<ShellLinkItem> link(new ShellLinkItem);
+  auto link = base::MakeRefCounted<ShellLinkItem>();
   AppendCommonSwitches(link.get());
   return link;
 }
@@ -292,6 +293,14 @@
   {
     JumpListData* data = &jumplist_data_->data;
     base::AutoLock auto_lock(data->list_lock_);
+
+    // There is no need to update the JumpList if the top most visited sites in
+    // display have not changed.
+    if (MostVisitedItemsUnchanged(data->most_visited_pages_, urls,
+                                  kMostVisitedItems)) {
+      return;
+    }
+
     data->most_visited_pages_.clear();
 
     for (size_t i = 0; i < urls.size() && i < kMostVisitedItems; i++) {
diff --git a/chrome/browser/win/jumplist_file_util.h b/chrome/browser/win/jumplist_file_util.h
index db92b0f..776c6eaf 100644
--- a/chrome/browser/win/jumplist_file_util.h
+++ b/chrome/browser/win/jumplist_file_util.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2017 The Chromium Authors. All rights reserved.
+// 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.
 
diff --git a/chrome/browser/win/jumplist_update_util.cc b/chrome/browser/win/jumplist_update_util.cc
new file mode 100644
index 0000000..c8a8a25
--- /dev/null
+++ b/chrome/browser/win/jumplist_update_util.cc
@@ -0,0 +1,26 @@
+// Copyright (c) 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/win/jumplist_update_util.h"
+
+#include <algorithm>
+#include <iterator>
+
+bool MostVisitedItemsUnchanged(const ShellLinkItemList& items,
+                               const history::MostVisitedURLList& urls,
+                               size_t max_item_count) {
+  // If the number of urls going to be displayed doesn't equal to the current
+  // one, the most visited items are considered to have changes.
+  // Otherwise, check if the current urls stored in |items| equal to the first
+  // |max_item_count| urls in |urls| to determine if the most visited items
+  // are changed or not.
+
+  if (std::min(urls.size(), max_item_count) != items.size())
+    return false;
+
+  return std::equal(std::begin(items), std::end(items), std::begin(urls),
+                    [](const auto& item_ptr, const auto& most_visited_url) {
+                      return item_ptr->url() == most_visited_url.url.spec();
+                    });
+}
diff --git a/chrome/browser/win/jumplist_update_util.h b/chrome/browser/win/jumplist_update_util.h
new file mode 100644
index 0000000..c5459bc
--- /dev/null
+++ b/chrome/browser/win/jumplist_update_util.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 CHROME_BROWSER_WIN_JUMPLIST_UPDATE_UTIL_H_
+#define CHROME_BROWSER_WIN_JUMPLIST_UPDATE_UTIL_H_
+
+#include "chrome/browser/win/jumplist_updater.h"
+#include "components/history/core/browser/history_types.h"
+
+// Checks if the urls stored in |items| are unchanged compared to the first
+// |max_item_count| urls in |urls|.
+bool MostVisitedItemsUnchanged(const ShellLinkItemList& items,
+                               const history::MostVisitedURLList& urls,
+                               size_t max_item_count);
+
+#endif  // CHROME_BROWSER_WIN_JUMPLIST_UPDATE_UTIL_H_
diff --git a/chrome/browser/win/jumplist_update_util_unittest.cc b/chrome/browser/win/jumplist_update_util_unittest.cc
new file mode 100644
index 0000000..16f9471b
--- /dev/null
+++ b/chrome/browser/win/jumplist_update_util_unittest.cc
@@ -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 "chrome/browser/win/jumplist_update_util.h"
+
+#include <algorithm>
+
+#include "base/strings/utf_string_conversions.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace {
+
+// Helper function to create a ShellLinkItem whose url is specified by |url|.
+scoped_refptr<ShellLinkItem> CreateShellLinkWithURL(const std::string& url) {
+  auto item = base::MakeRefCounted<ShellLinkItem>();
+  item->set_url(url);
+  return item;
+}
+
+}  // namespace
+
+TEST(JumpListUpdateUtilTest, MostVisitedItemsUnchanged) {
+  // Test data.
+  static constexpr struct {
+    const char* url;
+    const wchar_t* title;
+  } kTestData[] = {{"https://www.google.com/", L"Google"},
+                   {"https://www.youtube.com/", L"Youtube"},
+                   {"https://www.gmail.com/", L"Gmail"}};
+
+  ShellLinkItemList jumplist_items;
+  history::MostVisitedURLList history_items;
+
+  for (const auto& test_data : kTestData) {
+    jumplist_items.push_back(CreateShellLinkWithURL(test_data.url));
+    history_items.emplace_back(GURL(test_data.url), test_data.title);
+  }
+
+  // Both jumplist_items and history_items have 3 urls: Google, Youtube, Gmail.
+  // Also, their urls have the same order.
+  EXPECT_TRUE(MostVisitedItemsUnchanged(jumplist_items, history_items, 3));
+  EXPECT_FALSE(MostVisitedItemsUnchanged(jumplist_items, history_items, 2));
+  EXPECT_FALSE(MostVisitedItemsUnchanged(jumplist_items, history_items, 1));
+
+  // Reverse history_items, so the 3 urls in history_items are in reverse order:
+  // Gmail, Youtube, Google.
+  // The 3 urls in jumplist_items remain the same: Google, Youtube, Gmail.
+  std::reverse(history_items.begin(), history_items.end());
+  EXPECT_FALSE(MostVisitedItemsUnchanged(jumplist_items, history_items, 3));
+
+  // Reverse history_items back.
+  std::reverse(history_items.begin(), history_items.end());
+  EXPECT_TRUE(MostVisitedItemsUnchanged(jumplist_items, history_items, 3));
+
+  // Pop out the last url ("Gmail") from jumplist_items.
+  // Now jumplist_items has 2 urls: Google, Youtube,
+  // and history_items has 3 urls: Google, Youtube, Gmail.
+  jumplist_items.pop_back();
+  EXPECT_FALSE(MostVisitedItemsUnchanged(jumplist_items, history_items, 3));
+  EXPECT_TRUE(MostVisitedItemsUnchanged(jumplist_items, history_items, 2));
+  EXPECT_FALSE(MostVisitedItemsUnchanged(jumplist_items, history_items, 1));
+
+  // Pop out the last two urls ("Youtube", "Gmail") from history_items.
+  // Now jumplist_items has 2 urls: Google, Youtube,
+  // and history_items has 1 url: Google.
+  history_items.pop_back();
+  history_items.pop_back();
+  EXPECT_FALSE(MostVisitedItemsUnchanged(jumplist_items, history_items, 3));
+  EXPECT_FALSE(MostVisitedItemsUnchanged(jumplist_items, history_items, 2));
+  EXPECT_FALSE(MostVisitedItemsUnchanged(jumplist_items, history_items, 1));
+}
diff --git a/chrome/common/BUILD.gn b/chrome/common/BUILD.gn
index 47d8aff..eafd8cd 100644
--- a/chrome/common/BUILD.gn
+++ b/chrome/common/BUILD.gn
@@ -113,6 +113,8 @@
     "page_load_metrics/page_load_metrics_messages.h",
     "page_load_metrics/page_load_metrics_param_traits.cc",
     "page_load_metrics/page_load_metrics_param_traits.h",
+    "page_load_metrics/page_load_metrics_util.cc",
+    "page_load_metrics/page_load_metrics_util.h",
     "page_load_metrics/page_load_timing.cc",
     "page_load_metrics/page_load_timing.h",
     "page_load_metrics/page_track_decider.cc",
@@ -654,6 +656,8 @@
   visibility = [ "//chrome/test:*" ]
 
   sources = [
+    "page_load_metrics/test/page_load_metrics_test_util.cc",
+    "page_load_metrics/test/page_load_metrics_test_util.h",
     "search/mock_searchbox.cc",
     "search/mock_searchbox.h",
   ]
diff --git a/chrome/common/chrome_features.cc b/chrome/common/chrome_features.cc
index 7e8134d0..61a830d 100644
--- a/chrome/common/chrome_features.cc
+++ b/chrome/common/chrome_features.cc
@@ -40,12 +40,6 @@
 const base::Feature kAssetDownloadSuggestionsFeature{
     "NTPAssetDownloadSuggestions", base::FEATURE_ENABLED_BY_DEFAULT};
 
-#if !defined(OS_ANDROID) && !defined(OS_IOS)
-// Enables auto-dismissing JavaScript dialogs.
-const base::Feature kAutoDismissingDialogs{"AutoDismissingDialogs",
-                                           base::FEATURE_ENABLED_BY_DEFAULT};
-#endif
-
 #if defined(OS_WIN) || defined(OS_MACOSX)
 // Enables automatic tab discarding, when the system is in low memory state.
 const base::Feature kAutomaticTabDiscarding{"AutomaticTabDiscarding",
diff --git a/chrome/common/chrome_features.h b/chrome/common/chrome_features.h
index 1ac4866..ede452d8 100644
--- a/chrome/common/chrome_features.h
+++ b/chrome/common/chrome_features.h
@@ -34,10 +34,6 @@
 
 extern const base::Feature kAssetDownloadSuggestionsFeature;
 
-#if !defined(OS_ANDROID) && !defined(OS_IOS)
-extern const base::Feature kAutoDismissingDialogs;
-#endif
-
 #if defined(OS_WIN) || defined(OS_MACOSX)
 extern const base::Feature kAutomaticTabDiscarding;
 #endif  // defined(OS_WIN) || defined(OS_MACOSX)
diff --git a/chrome/common/extensions/api/developer_private.idl b/chrome/common/extensions/api/developer_private.idl
index 2859a68..9201cea8 100644
--- a/chrome/common/extensions/api/developer_private.idl
+++ b/chrome/common/extensions/api/developer_private.idl
@@ -186,7 +186,6 @@
   };
 
   dictionary ExtensionInfo {
-    boolean actionButtonHidden;
     DOMString? blacklistText;
     Command[] commands;
     ControlledInfo? controlledInfo;
@@ -279,7 +278,6 @@
     boolean? incognitoAccess;
     boolean? errorCollection;
     boolean? runOnAllUrls;
-    boolean? showActionButton;
   };
 
   dictionary ProfileConfigurationUpdate {
diff --git a/chrome/common/page_load_metrics/page_load_metrics_util.cc b/chrome/common/page_load_metrics/page_load_metrics_util.cc
new file mode 100644
index 0000000..43e65e9
--- /dev/null
+++ b/chrome/common/page_load_metrics/page_load_metrics_util.cc
@@ -0,0 +1,65 @@
+// 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/common/page_load_metrics/page_load_metrics_util.h"
+
+#include <algorithm>
+
+#include "base/strings/string_util.h"
+#include "net/base/registry_controlled_domains/registry_controlled_domain.h"
+
+namespace page_load_metrics {
+
+base::Optional<std::string> GetGoogleHostnamePrefix(const GURL& url) {
+  const size_t registry_length =
+      net::registry_controlled_domains::GetRegistryLength(
+          url,
+
+          // Do not include unknown registries (registries that don't have any
+          // matches in effective TLD names).
+          net::registry_controlled_domains::EXCLUDE_UNKNOWN_REGISTRIES,
+
+          // Do not include private registries, such as appspot.com. We don't
+          // want to match URLs like www.google.appspot.com.
+          net::registry_controlled_domains::EXCLUDE_PRIVATE_REGISTRIES);
+
+  const base::StringPiece hostname = url.host_piece();
+  if (registry_length == 0 || registry_length == std::string::npos ||
+      registry_length >= hostname.length()) {
+    return base::Optional<std::string>();
+  }
+
+  // Removes the tld and the preceding dot.
+  const base::StringPiece hostname_minus_registry =
+      hostname.substr(0, hostname.length() - (registry_length + 1));
+
+  if (hostname_minus_registry == "google")
+    return std::string("");
+
+  if (!base::EndsWith(hostname_minus_registry, ".google",
+                      base::CompareCase::INSENSITIVE_ASCII)) {
+    return base::Optional<std::string>();
+  }
+
+  return std::string(hostname_minus_registry.substr(
+      0, hostname_minus_registry.length() - strlen(".google")));
+}
+
+bool IsGoogleHostname(const GURL& url) {
+  return GetGoogleHostnamePrefix(url).has_value();
+}
+
+base::Optional<base::TimeDelta> OptionalMin(
+    const base::Optional<base::TimeDelta>& a,
+    const base::Optional<base::TimeDelta>& b) {
+  if (a && !b)
+    return a;
+  if (b && !a)
+    return b;
+  if (!a && !b)
+    return a;  // doesn't matter which
+  return base::Optional<base::TimeDelta>(std::min(a.value(), b.value()));
+}
+
+}  // namespace page_load_metrics
diff --git a/chrome/common/page_load_metrics/page_load_metrics_util.h b/chrome/common/page_load_metrics/page_load_metrics_util.h
new file mode 100644
index 0000000..03e4b830
--- /dev/null
+++ b/chrome/common/page_load_metrics/page_load_metrics_util.h
@@ -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.
+
+#ifndef CHROME_COMMON_PAGE_LOAD_METRICS_PAGE_LOAD_METRICS_UTIL_H_
+#define CHROME_COMMON_PAGE_LOAD_METRICS_PAGE_LOAD_METRICS_UTIL_H_
+
+#include <string>
+
+#include "base/optional.h"
+#include "base/time/time.h"
+#include "url/gurl.h"
+
+namespace page_load_metrics {
+
+// Returns the minimum value of the optional TimeDeltas, if both values are
+// set. Otherwise, if one value is set, returns that value. Otherwise, returns
+// an unset value.
+base::Optional<base::TimeDelta> OptionalMin(
+    const base::Optional<base::TimeDelta>& a,
+    const base::Optional<base::TimeDelta>& b);
+
+// Whether the given url has a google hostname.
+bool IsGoogleHostname(const GURL& url);
+
+// If the given hostname is a google hostname, returns the portion of the
+// hostname before the google hostname. Otherwise, returns an unset optional
+// value.
+//
+// For example:
+//   https://example.com/foo => returns an unset optional value
+//   https://google.com/foo => returns ''
+//   https://www.google.com/foo => returns 'www'
+//   https://news.google.com/foo => returns 'news'
+//   https://a.b.c.google.com/foo => returns 'a.b.c'
+base::Optional<std::string> GetGoogleHostnamePrefix(const GURL& url);
+
+}  // namespace page_load_metrics
+
+#endif  // CHROME_COMMON_PAGE_LOAD_METRICS_PAGE_LOAD_METRICS_UTIL_H_
diff --git a/chrome/common/page_load_metrics/test/page_load_metrics_test_util.cc b/chrome/common/page_load_metrics/test/page_load_metrics_test_util.cc
new file mode 100644
index 0000000..4b587e8
--- /dev/null
+++ b/chrome/common/page_load_metrics/test/page_load_metrics_test_util.cc
@@ -0,0 +1,79 @@
+// 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/common/page_load_metrics/test/page_load_metrics_test_util.h"
+
+#include "chrome/common/page_load_metrics/page_load_metrics.mojom.h"
+#include "chrome/common/page_load_metrics/page_load_metrics_util.h"
+
+using page_load_metrics::OptionalMin;
+
+void PopulateRequiredTimingFields(
+    page_load_metrics::mojom::PageLoadTiming* inout_timing) {
+  if (inout_timing->paint_timing->first_meaningful_paint &&
+      !inout_timing->paint_timing->first_contentful_paint) {
+    inout_timing->paint_timing->first_contentful_paint =
+        inout_timing->paint_timing->first_meaningful_paint;
+  }
+  if ((inout_timing->paint_timing->first_text_paint ||
+       inout_timing->paint_timing->first_image_paint ||
+       inout_timing->paint_timing->first_contentful_paint) &&
+      !inout_timing->paint_timing->first_paint) {
+    inout_timing->paint_timing->first_paint =
+        OptionalMin(OptionalMin(inout_timing->paint_timing->first_text_paint,
+                                inout_timing->paint_timing->first_image_paint),
+                    inout_timing->paint_timing->first_contentful_paint);
+  }
+  if (inout_timing->paint_timing->first_paint &&
+      !inout_timing->document_timing->first_layout) {
+    inout_timing->document_timing->first_layout =
+        inout_timing->paint_timing->first_paint;
+  }
+  if (inout_timing->document_timing->load_event_start &&
+      !inout_timing->document_timing->dom_content_loaded_event_start) {
+    inout_timing->document_timing->dom_content_loaded_event_start =
+        inout_timing->document_timing->load_event_start;
+  }
+  if (inout_timing->document_timing->first_layout &&
+      !inout_timing->parse_timing->parse_start) {
+    inout_timing->parse_timing->parse_start =
+        inout_timing->document_timing->first_layout;
+  }
+  if (inout_timing->document_timing->dom_content_loaded_event_start &&
+      !inout_timing->parse_timing->parse_stop) {
+    inout_timing->parse_timing->parse_stop =
+        inout_timing->document_timing->dom_content_loaded_event_start;
+  }
+  if (inout_timing->parse_timing->parse_stop &&
+      !inout_timing->parse_timing->parse_start) {
+    inout_timing->parse_timing->parse_start =
+        inout_timing->parse_timing->parse_stop;
+  }
+  if (inout_timing->parse_timing->parse_start &&
+      !inout_timing->response_start) {
+    inout_timing->response_start = inout_timing->parse_timing->parse_start;
+  }
+  if (inout_timing->parse_timing->parse_start) {
+    if (!inout_timing->parse_timing->parse_blocked_on_script_load_duration)
+      inout_timing->parse_timing->parse_blocked_on_script_load_duration =
+          base::TimeDelta();
+    if (!inout_timing->parse_timing
+             ->parse_blocked_on_script_execution_duration) {
+      inout_timing->parse_timing->parse_blocked_on_script_execution_duration =
+          base::TimeDelta();
+    }
+    if (!inout_timing->parse_timing
+             ->parse_blocked_on_script_load_from_document_write_duration) {
+      inout_timing->parse_timing
+          ->parse_blocked_on_script_load_from_document_write_duration =
+          base::TimeDelta();
+    }
+    if (!inout_timing->parse_timing
+             ->parse_blocked_on_script_execution_from_document_write_duration) {
+      inout_timing->parse_timing
+          ->parse_blocked_on_script_execution_from_document_write_duration =
+          base::TimeDelta();
+    }
+  }
+}
diff --git a/chrome/common/page_load_metrics/test/page_load_metrics_test_util.h b/chrome/common/page_load_metrics/test/page_load_metrics_test_util.h
new file mode 100644
index 0000000..cd0d9c1a
--- /dev/null
+++ b/chrome/common/page_load_metrics/test/page_load_metrics_test_util.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 CHROME_COMMON_PAGE_LOAD_METRICS_TEST_PAGE_LOAD_METRICS_TEST_UTIL_H_
+#define CHROME_COMMON_PAGE_LOAD_METRICS_TEST_PAGE_LOAD_METRICS_TEST_UTIL_H_
+
+namespace page_load_metrics {
+namespace mojom {
+class PageLoadTiming;
+}  // namespace mojom
+}  // namespace page_load_metrics
+
+// Helper that fills in any timing fields that page load metrics requires but
+// that are currently missing.
+void PopulateRequiredTimingFields(
+    page_load_metrics::mojom::PageLoadTiming* inout_timing);
+
+#endif  // CHROME_COMMON_PAGE_LOAD_METRICS_TEST_PAGE_LOAD_METRICS_TEST_UTIL_H_
diff --git a/chrome/common/page_load_metrics/test/weak_mock_timer.cc b/chrome/common/page_load_metrics/test/weak_mock_timer.cc
new file mode 100644
index 0000000..0fe222af
--- /dev/null
+++ b/chrome/common/page_load_metrics/test/weak_mock_timer.cc
@@ -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.
+
+#include "chrome/common/page_load_metrics/test/weak_mock_timer.h"
+
+namespace page_load_metrics {
+namespace test {
+
+WeakMockTimer::WeakMockTimer()
+    : MockTimer(false /* retain_user_task */, false /* is_repeating */) {}
+
+WeakMockTimerProvider::WeakMockTimerProvider() {}
+WeakMockTimerProvider::~WeakMockTimerProvider() {}
+
+base::MockTimer* WeakMockTimerProvider::GetMockTimer() const {
+  return timer_.get();
+}
+
+void WeakMockTimerProvider::SetMockTimer(base::WeakPtr<WeakMockTimer> timer) {
+  timer_ = timer;
+}
+
+}  // namespace test
+}  // namespace page_load_metrics
diff --git a/chrome/common/page_load_metrics/test/weak_mock_timer.h b/chrome/common/page_load_metrics/test/weak_mock_timer.h
new file mode 100644
index 0000000..185b586
--- /dev/null
+++ b/chrome/common/page_load_metrics/test/weak_mock_timer.h
@@ -0,0 +1,44 @@
+// 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_COMMON_PAGE_LOAD_METRICS_TEST_WEAK_MOCK_TIMER_H_
+#define CHROME_COMMON_PAGE_LOAD_METRICS_TEST_WEAK_MOCK_TIMER_H_
+
+#include "base/macros.h"
+#include "base/memory/weak_ptr.h"
+#include "base/timer/mock_timer.h"
+
+namespace page_load_metrics {
+namespace test {
+
+// WeakMockTimer is a MockTimer that allows clients to keep WeakPtr<>s to it.
+class WeakMockTimer : public base::MockTimer,
+                      public base::SupportsWeakPtr<WeakMockTimer> {
+ public:
+  WeakMockTimer();
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(WeakMockTimer);
+};
+
+// WeakMockTimerProvider is a testing helper class that test classes can inherit
+// from to provide basic MockTimer tracking capabilities.
+class WeakMockTimerProvider {
+ public:
+  WeakMockTimerProvider();
+  virtual ~WeakMockTimerProvider();
+
+  base::MockTimer* GetMockTimer() const;
+  void SetMockTimer(base::WeakPtr<WeakMockTimer> timer);
+
+ private:
+  base::WeakPtr<WeakMockTimer> timer_;
+
+  DISALLOW_COPY_AND_ASSIGN(WeakMockTimerProvider);
+};
+
+}  // namespace test
+}  // namespace page_load_metrics
+
+#endif  // CHROME_COMMON_PAGE_LOAD_METRICS_TEST_WEAK_MOCK_TIMER_H_
diff --git a/chrome/installer/util/advanced_firewall_manager_win_unittest.cc b/chrome/installer/util/advanced_firewall_manager_win_unittest.cc
index 81ffaf1..84ee581 100644
--- a/chrome/installer/util/advanced_firewall_manager_win_unittest.cc
+++ b/chrome/installer/util/advanced_firewall_manager_win_unittest.cc
@@ -22,7 +22,7 @@
   // Sets up the test fixture.
   void SetUp() override {
     if (base::GetCurrentProcessIntegrityLevel() != base::HIGH_INTEGRITY) {
-      LOG(WARNING) << "XP or not elevated. Skipping the test.";
+      LOG(WARNING) << "Not elevated. Skipping the test.";
       return;
     }
     skip_test_ = false;
diff --git a/chrome/renderer/page_load_metrics/metrics_render_frame_observer.cc b/chrome/renderer/page_load_metrics/metrics_render_frame_observer.cc
index 9996789b..64352d06 100644
--- a/chrome/renderer/page_load_metrics/metrics_render_frame_observer.cc
+++ b/chrome/renderer/page_load_metrics/metrics_render_frame_observer.cc
@@ -207,8 +207,8 @@
   return timing;
 }
 
-std::unique_ptr<base::Timer> MetricsRenderFrameObserver::CreateTimer() const {
-  return base::WrapUnique(new base::OneShotTimer);
+std::unique_ptr<base::Timer> MetricsRenderFrameObserver::CreateTimer() {
+  return base::MakeUnique<base::OneShotTimer>();
 }
 
 std::unique_ptr<PageTimingSender>
diff --git a/chrome/renderer/page_load_metrics/metrics_render_frame_observer.h b/chrome/renderer/page_load_metrics/metrics_render_frame_observer.h
index 78b8b3f..db52f07 100644
--- a/chrome/renderer/page_load_metrics/metrics_render_frame_observer.h
+++ b/chrome/renderer/page_load_metrics/metrics_render_frame_observer.h
@@ -47,7 +47,7 @@
   void SendMetrics();
   virtual bool ShouldSendMetrics() const;
   virtual mojom::PageLoadTimingPtr GetTiming() const;
-  virtual std::unique_ptr<base::Timer> CreateTimer() const;
+  virtual std::unique_ptr<base::Timer> CreateTimer();
   virtual std::unique_ptr<PageTimingSender> CreatePageTimingSender();
   virtual bool HasNoRenderFrame() const;
 
diff --git a/chrome/renderer/page_load_metrics/metrics_render_frame_observer_unittest.cc b/chrome/renderer/page_load_metrics/metrics_render_frame_observer_unittest.cc
index 90f0859..8dbb975 100644
--- a/chrome/renderer/page_load_metrics/metrics_render_frame_observer_unittest.cc
+++ b/chrome/renderer/page_load_metrics/metrics_render_frame_observer_unittest.cc
@@ -11,6 +11,7 @@
 #include "base/time/time.h"
 #include "base/timer/mock_timer.h"
 #include "chrome/common/page_load_metrics/page_load_timing.h"
+#include "chrome/common/page_load_metrics/test/weak_mock_timer.h"
 #include "chrome/renderer/page_load_metrics/fake_page_timing_sender.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
@@ -19,14 +20,15 @@
 // Implementation of the MetricsRenderFrameObserver class we're testing,
 // with the GetTiming() and ShouldSendMetrics() methods stubbed out to make
 // the rest of the class more testable.
-class TestMetricsRenderFrameObserver : public MetricsRenderFrameObserver {
+class TestMetricsRenderFrameObserver : public MetricsRenderFrameObserver,
+                                       public test::WeakMockTimerProvider {
  public:
   TestMetricsRenderFrameObserver() : MetricsRenderFrameObserver(nullptr) {}
 
-  std::unique_ptr<base::Timer> CreateTimer() const override {
-    if (!mock_timer_)
-      ADD_FAILURE() << "CreateTimer() called, but no MockTimer available.";
-    return std::move(mock_timer_);
+  std::unique_ptr<base::Timer> CreateTimer() override {
+    auto timer = base::MakeUnique<test::WeakMockTimer>();
+    SetMockTimer(timer->AsWeakPtr());
+    return std::move(timer);
   }
 
   std::unique_ptr<PageTimingSender> CreatePageTimingSender() override {
@@ -34,11 +36,6 @@
         new FakePageTimingSender(&validator_));
   }
 
-  void set_mock_timer(std::unique_ptr<base::Timer> timer) {
-    ASSERT_EQ(nullptr, mock_timer_);
-    mock_timer_ = std::move(timer);
-  }
-
   void ExpectPageLoadTiming(const mojom::PageLoadTiming& timing) {
     SetFakePageLoadTiming(timing);
     validator_.ExpectPageLoadTiming(timing);
@@ -65,18 +62,14 @@
  private:
   FakePageTimingSender::PageTimingValidator validator_;
   mutable mojom::PageLoadTimingPtr fake_timing_;
-  mutable std::unique_ptr<base::Timer> mock_timer_;
 };
 
 typedef testing::Test MetricsRenderFrameObserverTest;
 
 TEST_F(MetricsRenderFrameObserverTest, NoMetrics) {
   TestMetricsRenderFrameObserver observer;
-  base::MockTimer* mock_timer = new base::MockTimer(false, false);
-  observer.set_mock_timer(base::WrapUnique(mock_timer));
-
   observer.DidChangePerformanceTiming();
-  ASSERT_FALSE(mock_timer->IsRunning());
+  ASSERT_EQ(nullptr, observer.GetMockTimer());
 }
 
 TEST_F(MetricsRenderFrameObserverTest, SingleMetric) {
@@ -84,21 +77,19 @@
   base::TimeDelta first_layout = base::TimeDelta::FromMillisecondsD(10);
 
   TestMetricsRenderFrameObserver observer;
-  base::MockTimer* mock_timer = new base::MockTimer(false, false);
-  observer.set_mock_timer(base::WrapUnique(mock_timer));
 
   mojom::PageLoadTiming timing;
   page_load_metrics::InitPageLoadTimingForTest(&timing);
   timing.navigation_start = nav_start;
   observer.ExpectPageLoadTiming(timing);
   observer.DidCommitProvisionalLoad(true, false);
-  mock_timer->Fire();
+  observer.GetMockTimer()->Fire();
 
   timing.document_timing->first_layout = first_layout;
   observer.ExpectPageLoadTiming(timing);
 
   observer.DidChangePerformanceTiming();
-  mock_timer->Fire();
+  observer.GetMockTimer()->Fire();
 }
 
 TEST_F(MetricsRenderFrameObserverTest, MultipleMetrics) {
@@ -108,22 +99,20 @@
   base::TimeDelta load_event = base::TimeDelta::FromMillisecondsD(2);
 
   TestMetricsRenderFrameObserver observer;
-  base::MockTimer* mock_timer = new base::MockTimer(false, false);
-  observer.set_mock_timer(base::WrapUnique(mock_timer));
 
   mojom::PageLoadTiming timing;
   page_load_metrics::InitPageLoadTimingForTest(&timing);
   timing.navigation_start = nav_start;
   observer.ExpectPageLoadTiming(timing);
   observer.DidCommitProvisionalLoad(true, false);
-  mock_timer->Fire();
+  observer.GetMockTimer()->Fire();
 
   timing.document_timing->first_layout = first_layout;
   timing.document_timing->dom_content_loaded_event_start = dom_event;
   observer.ExpectPageLoadTiming(timing);
 
   observer.DidChangePerformanceTiming();
-  mock_timer->Fire();
+  observer.GetMockTimer()->Fire();
 
   // At this point, we should have triggered the generation of two metrics.
   // Verify and reset the observer's expectations before moving on to the next
@@ -134,7 +123,7 @@
   observer.ExpectPageLoadTiming(timing);
 
   observer.DidChangePerformanceTiming();
-  mock_timer->Fire();
+  observer.GetMockTimer()->Fire();
 
   // Verify and reset the observer's expectations before moving on to the next
   // part of the test.
@@ -146,7 +135,7 @@
   // this invocation to generate any additional metrics.
   observer.SetFakePageLoadTiming(timing);
   observer.DidChangePerformanceTiming();
-  ASSERT_FALSE(mock_timer->IsRunning());
+  ASSERT_FALSE(observer.GetMockTimer()->IsRunning());
 }
 
 TEST_F(MetricsRenderFrameObserverTest, MultipleNavigations) {
@@ -156,22 +145,20 @@
   base::TimeDelta load_event = base::TimeDelta::FromMillisecondsD(2);
 
   TestMetricsRenderFrameObserver observer;
-  base::MockTimer* mock_timer = new base::MockTimer(false, false);
-  observer.set_mock_timer(base::WrapUnique(mock_timer));
 
   mojom::PageLoadTiming timing;
   page_load_metrics::InitPageLoadTimingForTest(&timing);
   timing.navigation_start = nav_start;
   observer.ExpectPageLoadTiming(timing);
   observer.DidCommitProvisionalLoad(true, false);
-  mock_timer->Fire();
+  observer.GetMockTimer()->Fire();
 
   timing.document_timing->first_layout = first_layout;
   timing.document_timing->dom_content_loaded_event_start = dom_event;
   timing.document_timing->load_event_start = load_event;
   observer.ExpectPageLoadTiming(timing);
   observer.DidChangePerformanceTiming();
-  mock_timer->Fire();
+  observer.GetMockTimer()->Fire();
 
   // At this point, we should have triggered the generation of two metrics.
   // Verify and reset the observer's expectations before moving on to the next
@@ -186,12 +173,11 @@
   page_load_metrics::InitPageLoadTimingForTest(&timing_2);
   timing_2.navigation_start = nav_start_2;
 
-  base::MockTimer* mock_timer2 = new base::MockTimer(false, false);
-  observer.set_mock_timer(base::WrapUnique(mock_timer2));
+  observer.SetMockTimer(nullptr);
 
   observer.ExpectPageLoadTiming(timing_2);
   observer.DidCommitProvisionalLoad(true, false);
-  mock_timer2->Fire();
+  observer.GetMockTimer()->Fire();
 
   timing_2.document_timing->first_layout = first_layout_2;
   timing_2.document_timing->dom_content_loaded_event_start = dom_event_2;
@@ -199,7 +185,7 @@
   observer.ExpectPageLoadTiming(timing_2);
 
   observer.DidChangePerformanceTiming();
-  mock_timer2->Fire();
+  observer.GetMockTimer()->Fire();
 }
 
 }  // namespace page_load_metrics
diff --git a/chrome/service/cloud_print/print_system_win.cc b/chrome/service/cloud_print/print_system_win.cc
index d299ac9..2cc2aaba 100644
--- a/chrome/service/cloud_print/print_system_win.cc
+++ b/chrome/service/cloud_print/print_system_win.cc
@@ -720,17 +720,18 @@
   DCHECK(print_ticket_data_mime_type == kContentTypeXML);
 
   printing::ScopedXPSInitializer xps_initializer;
-  if (!xps_initializer.initialized()) {
-    // TODO(sanjeevr): Handle legacy proxy case (with no prntvpt.dll)
-    return false;
-  }
-  bool ret = false;
-  HPTPROVIDER provider = NULL;
+  CHECK(xps_initializer.initialized());
+
+  HPTPROVIDER provider = nullptr;
   printing::XPSModule::OpenProvider(base::UTF8ToWide(printer_name), 1,
                                     &provider);
-  if (provider) {
+  if (!provider)
+    return false;
+
+  bool ret;
+  {
     base::win::ScopedComPtr<IStream> print_ticket_stream;
-    CreateStreamOnHGlobal(NULL, TRUE, print_ticket_stream.GetAddressOf());
+    CreateStreamOnHGlobal(nullptr, TRUE, print_ticket_stream.GetAddressOf());
     ULONG bytes_written = 0;
     print_ticket_stream->Write(print_ticket_data.c_str(),
                                print_ticket_data.length(),
@@ -741,14 +742,10 @@
     print_ticket_stream->Seek(pos, STREAM_SEEK_SET, &new_pos);
     base::win::ScopedBstr error;
     base::win::ScopedComPtr<IStream> result_ticket_stream;
-    CreateStreamOnHGlobal(NULL, TRUE, result_ticket_stream.GetAddressOf());
+    CreateStreamOnHGlobal(nullptr, TRUE, result_ticket_stream.GetAddressOf());
     ret = SUCCEEDED(printing::XPSModule::MergeAndValidatePrintTicket(
-        provider,
-        print_ticket_stream.Get(),
-        NULL,
-        kPTJobScope,
-        result_ticket_stream.Get(),
-        error.Receive()));
+        provider, print_ticket_stream.Get(), nullptr, kPTJobScope,
+        result_ticket_stream.Get(), error.Receive()));
     printing::XPSModule::CloseProvider(provider);
   }
   return ret;
diff --git a/chrome/test/BUILD.gn b/chrome/test/BUILD.gn
index b621d062..013b968 100644
--- a/chrome/test/BUILD.gn
+++ b/chrome/test/BUILD.gn
@@ -1522,8 +1522,6 @@
       "../browser/ntp_snippets/content_suggestions_service_factory_browsertest.cc",
       "../browser/page_load_metrics/observers/ads_page_load_metrics_observer_browsertest.cc",
       "../browser/page_load_metrics/observers/https_engagement_metrics/https_engagement_page_load_metrics_observer_browsertest.cc",
-      "../browser/page_load_metrics/observers/page_load_metrics_observer_test_harness.cc",
-      "../browser/page_load_metrics/observers/page_load_metrics_observer_test_harness.h",
       "../browser/page_load_metrics/page_load_metrics_browsertest.cc",
       "../browser/password_manager/credential_manager_browsertest.cc",
       "../browser/password_manager/password_manager_browsertest.cc",
@@ -3305,6 +3303,7 @@
     "../browser/win/chrome_elf_init_unittest.cc",
     "../browser/win/enumerate_modules_model_unittest.cc",
     "../browser/win/jumplist_file_util_unittest.cc",
+    "../browser/win/jumplist_update_util_unittest.cc",
     "../browser/win/taskbar_icon_finder_unittest.cc",
     "../common/chrome_constants_win_unittest.cc",
     "../common/chrome_content_client_unittest.cc",
@@ -3323,6 +3322,8 @@
     "../common/media_router/media_source_helper_unittest.cc",
     "../common/media_router/media_source_unittest.cc",
     "../common/origin_trials/chrome_origin_trial_policy_unittest.cc",
+    "../common/page_load_metrics/test/weak_mock_timer.cc",
+    "../common/page_load_metrics/test/weak_mock_timer.h",
     "../common/partial_circular_buffer_unittest.cc",
     "../common/pref_names_util_unittest.cc",
     "../common/search/instant_types_unittest.cc",
diff --git a/chrome/test/base/chrome_test_launcher.cc b/chrome/test/base/chrome_test_launcher.cc
index 8ba431f..4257986 100644
--- a/chrome/test/base/chrome_test_launcher.cc
+++ b/chrome/test/base/chrome_test_launcher.cc
@@ -116,17 +116,15 @@
                                       install_static::GetRegistryPath().c_str(),
                                       KEY_SET_VALUE);
 
-  if (result != ERROR_SUCCESS && result != ERROR_FILE_NOT_FOUND) {
-    LOG(ERROR) << "Failed to open distribution key for cleanup: " << result;
+  if (result != ERROR_SUCCESS) {
+    LOG_IF(ERROR, result != ERROR_FILE_NOT_FOUND)
+        << "Failed to open distribution key for cleanup: " << result;
     return;
   }
 
   result = distrubution_key.DeleteKey(L"PreferenceMACs");
-
-  if (result != ERROR_SUCCESS && result != ERROR_FILE_NOT_FOUND) {
-    LOG(ERROR) << "Failed to cleanup PreferenceMACs: " << result;
-    return;
-  }
+  LOG_IF(ERROR, result != ERROR_SUCCESS && result != ERROR_FILE_NOT_FOUND)
+      << "Failed to cleanup PreferenceMACs: " << result;
 #endif
 }
 
diff --git a/chrome/test/data/extensions/api_test/developer/generated_output/behllobkkfkfnphdnhnkndlbkcpglgmj.json b/chrome/test/data/extensions/api_test/developer/generated_output/behllobkkfkfnphdnhnkndlbkcpglgmj.json
index db9884b..2853199 100644
--- a/chrome/test/data/extensions/api_test/developer/generated_output/behllobkkfkfnphdnhnkndlbkcpglgmj.json
+++ b/chrome/test/data/extensions/api_test/developer/generated_output/behllobkkfkfnphdnhnkndlbkcpglgmj.json
@@ -1,5 +1,4 @@
 {
-   "actionButtonHidden": false,
    "dependentExtensions": [  ],
    "description": "__MSG_chrome_extension_description__",
    "disableReasons": {
diff --git a/chrome/test/data/extensions/api_test/developer/generated_output/bjafgdebaacbbbecmhlhpofkepfkgcpa.json b/chrome/test/data/extensions/api_test/developer/generated_output/bjafgdebaacbbbecmhlhpofkepfkgcpa.json
index 4a59bef..e9331c5 100644
--- a/chrome/test/data/extensions/api_test/developer/generated_output/bjafgdebaacbbbecmhlhpofkepfkgcpa.json
+++ b/chrome/test/data/extensions/api_test/developer/generated_output/bjafgdebaacbbbecmhlhpofkepfkgcpa.json
@@ -1,5 +1,4 @@
 {
-   "actionButtonHidden": false,
    "dependentExtensions": [  ],
    "description": "",
    "disableReasons": {
diff --git a/chrome/test/data/extensions/api_test/developer/generated_output/hpiknbiabeeppbpihjehijgoemciehgk.json b/chrome/test/data/extensions/api_test/developer/generated_output/hpiknbiabeeppbpihjehijgoemciehgk.json
index cd016d5..8661a5e 100644
--- a/chrome/test/data/extensions/api_test/developer/generated_output/hpiknbiabeeppbpihjehijgoemciehgk.json
+++ b/chrome/test/data/extensions/api_test/developer/generated_output/hpiknbiabeeppbpihjehijgoemciehgk.json
@@ -1,5 +1,4 @@
 {
-   "actionButtonHidden": false,
    "dependentExtensions": [  ],
    "description": "",
    "disableReasons": {
diff --git a/chrome/test/data/webui/settings/site_list_tests.js b/chrome/test/data/webui/settings/site_list_tests.js
index d7496db..d0367da 100644
--- a/chrome/test/data/webui/settings/site_list_tests.js
+++ b/chrome/test/data/webui/settings/site_list_tests.js
@@ -10,7 +10,7 @@
  * all types, even though some might be blank.
  * @type {SiteSettingsPref}
  */
-var prefs = {
+var prefsGeolocation = {
   exceptions: {
     auto_downloads: [],
     background_sync: [],
@@ -485,17 +485,17 @@
   test('initial ALLOW state is correct', function() {
     setUpCategory(
         settings.ContentSettingsTypes.GEOLOCATION,
-        settings.PermissionValues.ALLOW, prefs);
+        settings.PermissionValues.ALLOW, prefsGeolocation);
     return browserProxy.whenCalled('getExceptionList')
         .then(function(contentType) {
           assertEquals(settings.ContentSettingsTypes.GEOLOCATION, contentType);
 
           assertEquals(2, testElement.sites.length);
           assertEquals(
-              prefs.exceptions.geolocation[0].origin,
+              prefsGeolocation.exceptions.geolocation[0].origin,
               testElement.sites[0].origin);
           assertEquals(
-              prefs.exceptions.geolocation[1].origin,
+              prefsGeolocation.exceptions.geolocation[1].origin,
               testElement.sites[1].origin);
           assertEquals(
               settings.PermissionValues.ALLOW, testElement.categorySubtype);
@@ -510,7 +510,7 @@
   test('action menu closes when list changes', function() {
     setUpCategory(
         settings.ContentSettingsTypes.GEOLOCATION,
-        settings.PermissionValues.ALLOW, prefs);
+        settings.PermissionValues.ALLOW, prefsGeolocation);
     var actionMenu = testElement.$$('dialog[is=cr-action-menu]');
     return browserProxy.whenCalled('getExceptionList')
         .then(function(contentType) {
@@ -538,16 +538,16 @@
     return browserProxy.whenCalled('getExceptionList')
         .then(function(contentType) {
           assertEquals(settings.ContentSettingsTypes.GEOLOCATION, contentType);
-
           assertEquals(3, testElement.sites.length);
-          for (var i = 0; i < 3; i++) {
+          for (var i = 0; i < testElement.sites.length; ++i) {
             assertEquals(
-                prefsMixedProvider.exceptions.geolocation[0].origin,
-                testElement.sites[0].origin);
+                prefsMixedProvider.exceptions.geolocation[i].origin,
+                testElement.sites[i].origin);
             assertEquals(
-                kControlledByLookup[prefsMixedProvider.exceptions.geolocation[0]
-                                        .source],
-                testElement.sites[0].controlledBy);
+                kControlledByLookup[prefsMixedProvider.exceptions.geolocation[i]
+                                        .source] ||
+                    '',
+                testElement.sites[i].controlledBy);
           }
         });
   });
@@ -555,7 +555,7 @@
   test('initial BLOCK state is correct', function() {
     var contentType = settings.ContentSettingsTypes.GEOLOCATION;
     var categorySubtype = settings.PermissionValues.BLOCK;
-    setUpCategory(contentType, categorySubtype, prefs);
+    setUpCategory(contentType, categorySubtype, prefsGeolocation);
     return browserProxy.whenCalled('getExceptionList')
         .then(function(actualContentType) {
           assertEquals(contentType, actualContentType);
@@ -563,10 +563,10 @@
 
           assertEquals(2, testElement.sites.length);
           assertEquals(
-              prefs.exceptions.geolocation[2].origin,
+              prefsGeolocation.exceptions.geolocation[2].origin,
               testElement.sites[0].origin);
           assertEquals(
-              prefs.exceptions.geolocation[3].origin,
+              prefsGeolocation.exceptions.geolocation[3].origin,
               testElement.sites[1].origin);
           Polymer.dom.flush();  // Populates action menu.
           openActionMenu(0);
@@ -771,7 +771,8 @@
 
   test('list items shown and clickable when data is present', function() {
     var contentType = settings.ContentSettingsTypes.GEOLOCATION;
-    setUpCategory(contentType, settings.PermissionValues.ALLOW, prefs);
+    setUpCategory(
+        contentType, settings.PermissionValues.ALLOW, prefsGeolocation);
     return browserProxy.whenCalled('getExceptionList')
         .then(function(actualContentType) {
           assertEquals(contentType, actualContentType);
@@ -782,10 +783,10 @@
           // Validate that the sites gets populated from pre-canned prefs.
           assertEquals(2, testElement.sites.length);
           assertEquals(
-              prefs.exceptions.geolocation[0].origin,
+              prefsGeolocation.exceptions.geolocation[0].origin,
               testElement.sites[0].origin);
           assertEquals(
-              prefs.exceptions.geolocation[1].origin,
+              prefsGeolocation.exceptions.geolocation[1].origin,
               testElement.sites[1].origin);
           assertFalse(!!testElement.selectedOrigin);
 
@@ -795,7 +796,7 @@
           assertTrue(!!clickable);
           MockInteractions.tap(clickable);
           assertEquals(
-              prefs.exceptions.geolocation[0].origin,
+              prefsGeolocation.exceptions.geolocation[0].origin,
               settings.getQueryParameters().get('site'));
         });
   });
@@ -818,7 +819,8 @@
   test('Block list closed when Allow list is not empty', function() {
     // Prefs: Items in both Block and Allow list.
     var contentType = settings.ContentSettingsTypes.GEOLOCATION;
-    setUpCategory(contentType, settings.PermissionValues.BLOCK, prefs);
+    setUpCategory(
+        contentType, settings.PermissionValues.BLOCK, prefsGeolocation);
     return browserProxy.whenCalled('getExceptionList')
         .then(function(actualContentType) {
           assertEquals(contentType, actualContentType);
@@ -845,7 +847,8 @@
   test('Allow list is always open (Block list non-empty)', function() {
     // Prefs: Items in both Block and Allow list.
     var contentType = settings.ContentSettingsTypes.GEOLOCATION;
-    setUpCategory(contentType, settings.PermissionValues.ALLOW, prefs);
+    setUpCategory(
+        contentType, settings.PermissionValues.ALLOW, prefsGeolocation);
     return browserProxy.whenCalled('getExceptionList')
         .then(function(actualContentType) {
           assertEquals(contentType, actualContentType);
@@ -914,7 +917,7 @@
     // Test for error: "Cannot read property 'origin' of undefined".
     setUpCategory(
         settings.ContentSettingsTypes.GEOLOCATION,
-        settings.PermissionValues.ALLOW, prefs);
+        settings.PermissionValues.ALLOW, prefsGeolocation);
     return browserProxy.whenCalled('getExceptionList')
         .then(function(contentType) {
           Polymer.dom.flush();
diff --git a/chrome/test/media_router/media_router_integration_browsertest.cc b/chrome/test/media_router/media_router_integration_browsertest.cc
index ff88be48d..8358165 100644
--- a/chrome/test/media_router/media_router_integration_browsertest.cc
+++ b/chrome/test/media_router/media_router_integration_browsertest.cc
@@ -13,6 +13,7 @@
 #include "base/json/json_writer.h"
 #include "base/path_service.h"
 #include "base/strings/stringprintf.h"
+#include "base/threading/thread_restrictions.h"
 #include "base/threading/thread_task_runner_handle.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/ui/browser_finder.h"
@@ -283,8 +284,12 @@
   JSONFileValueDeserializer deserializer(full_path);
   int error_code = 0;
   std::string error_message;
-  std::unique_ptr<base::Value> value =
-      deserializer.Deserialize(&error_code, &error_message);
+  std::unique_ptr<base::Value> value;
+  {
+    // crbug.com/724573
+    base::ThreadRestrictions::ScopedAllowIO allow_io;
+    value = deserializer.Deserialize(&error_code, &error_message);
+  }
   CHECK(value.get()) << "Deserialize failed: " << error_message;
   std::string test_data_str;
   ASSERT_TRUE(base::JSONWriter::Write(*value, &test_data_str));
@@ -318,7 +323,11 @@
   CHECK(PathService::Get(base::DIR_MODULE, &base_dir));
   base::FilePath full_path =
       base_dir.Append(kResourcePath).Append(relative_path);
-  CHECK(PathExists(full_path));
+  {
+    // crbug.com/724573
+    base::ThreadRestrictions::ScopedAllowIO allow_io;
+    CHECK(PathExists(full_path));
+  }
   return full_path;
 }
 
diff --git a/chrome/test/vr/OWNERS b/chrome/test/vr/OWNERS
new file mode 100644
index 0000000..d7c5c49
--- /dev/null
+++ b/chrome/test/vr/OWNERS
@@ -0,0 +1,4 @@
+cjgrant@chromium.org
+mthiesse@chromium.org
+
+# COMPONENT: UI>Browser>VR
diff --git a/chromecast/browser/url_request_context_factory.cc b/chromecast/browser/url_request_context_factory.cc
index 659d294..75852d84 100644
--- a/chromecast/browser/url_request_context_factory.cc
+++ b/chromecast/browser/url_request_context_factory.cc
@@ -320,31 +320,35 @@
 
 void URLRequestContextFactory::PopulateNetworkSessionParams(
     bool ignore_certificate_errors,
-    net::HttpNetworkSession::Params* params) {
+    net::HttpNetworkSession::Params* session_params,
+    net::HttpNetworkSession::Context* session_context) {
   DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
-  params->host_resolver = host_resolver_.get();
-  params->cert_verifier = cert_verifier_.get();
-  params->channel_id_service = channel_id_service_.get();
-  params->ssl_config_service = ssl_config_service_.get();
-  params->transport_security_state = transport_security_state_.get();
-  params->cert_transparency_verifier = cert_transparency_verifier_.get();
-  params->ct_policy_enforcer = ct_policy_enforcer_.get();
-  params->http_auth_handler_factory = http_auth_handler_factory_.get();
-  params->http_server_properties = http_server_properties_.get();
-  params->ignore_certificate_errors = ignore_certificate_errors;
-  params->proxy_service = proxy_service_.get();
+  session_context->host_resolver = host_resolver_.get();
+  session_context->cert_verifier = cert_verifier_.get();
+  session_context->channel_id_service = channel_id_service_.get();
+  session_context->ssl_config_service = ssl_config_service_.get();
+  session_context->transport_security_state = transport_security_state_.get();
+  session_context->cert_transparency_verifier =
+      cert_transparency_verifier_.get();
+  session_context->ct_policy_enforcer = ct_policy_enforcer_.get();
+  session_context->http_auth_handler_factory = http_auth_handler_factory_.get();
+  session_context->http_server_properties = http_server_properties_.get();
+  session_context->proxy_service = proxy_service_.get();
 
+  session_params->ignore_certificate_errors = ignore_certificate_errors;
   LOG(INFO) << "Set HttpNetworkSessionParams.enable_quic = " << enable_quic_;
-  params->enable_quic = enable_quic_;
+  session_params->enable_quic = enable_quic_;
 }
 
 net::URLRequestContext* URLRequestContextFactory::CreateSystemRequestContext() {
   DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
   InitializeSystemContextDependencies();
-  net::HttpNetworkSession::Params system_params;
-  PopulateNetworkSessionParams(IgnoreCertificateErrors(), &system_params);
+  net::HttpNetworkSession::Params session_params;
+  net::HttpNetworkSession::Context session_context;
+  PopulateNetworkSessionParams(IgnoreCertificateErrors(), &session_params,
+                               &session_context);
   system_transaction_factory_.reset(new net::HttpNetworkLayer(
-      new net::HttpNetworkSession(system_params)));
+      new net::HttpNetworkSession(session_params, session_context)));
   system_job_factory_.reset(new net::URLRequestJobFactoryImpl());
   system_cookie_store_ =
       content::CreateCookieStore(content::CookieStoreConfig());
@@ -398,12 +402,13 @@
   DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
   InitializeSystemContextDependencies();
 
-  net::HttpNetworkSession::Params network_session_params;
-  PopulateNetworkSessionParams(IgnoreCertificateErrors(),
-                               &network_session_params);
+  net::HttpNetworkSession::Params session_params;
+  net::HttpNetworkSession::Context session_context;
+  PopulateNetworkSessionParams(IgnoreCertificateErrors(), &session_params,
+                               &session_context);
   InitializeMainContextDependencies(
       new net::HttpNetworkLayer(
-          new net::HttpNetworkSession(network_session_params)),
+          new net::HttpNetworkSession(session_params, session_context)),
       protocol_handlers, std::move(request_interceptors));
 
   content::CookieStoreConfig cookie_config(
diff --git a/chromecast/browser/url_request_context_factory.h b/chromecast/browser/url_request_context_factory.h
index 18f5d87..ba8deda 100644
--- a/chromecast/browser/url_request_context_factory.h
+++ b/chromecast/browser/url_request_context_factory.h
@@ -82,8 +82,10 @@
       content::URLRequestInterceptorScopedVector request_interceptors);
   void InitializeMediaContextDependencies(net::HttpTransactionFactory* factory);
 
-  void PopulateNetworkSessionParams(bool ignore_certificate_errors,
-                                    net::HttpNetworkSession::Params* params);
+  void PopulateNetworkSessionParams(
+      bool ignore_certificate_errors,
+      net::HttpNetworkSession::Params* session_params,
+      net::HttpNetworkSession::Context* session_context);
   void DisableQuicOnBrowserIOThread();
 
   // These are called by the RequestContextGetters to create each
diff --git a/chromecast/media/base/decrypt_context_impl.cc b/chromecast/media/base/decrypt_context_impl.cc
index 07cd81e..b45fb67 100644
--- a/chromecast/media/base/decrypt_context_impl.cc
+++ b/chromecast/media/base/decrypt_context_impl.cc
@@ -37,7 +37,7 @@
   bool called = false;
   bool success = false;
   DecryptAsync(buffer, output, data_offset,
-               base::Bind(&BufferDecryptCB, &called, &success));
+               base::BindOnce(&BufferDecryptCB, &called, &success));
   CHECK(called) << "Sync Decrypt isn't supported";
 
   return success;
@@ -46,8 +46,8 @@
 void DecryptContextImpl::DecryptAsync(CastDecoderBuffer* buffer,
                                       uint8_t* output,
                                       size_t data_offset,
-                                      const DecryptCB& decrypt_cb) {
-  decrypt_cb.Run(false);
+                                      DecryptCB decrypt_cb) {
+  std::move(decrypt_cb).Run(false);
 }
 
 bool DecryptContextImpl::CanDecryptToBuffer() const {
diff --git a/chromecast/media/base/decrypt_context_impl.h b/chromecast/media/base/decrypt_context_impl.h
index 9b0cce2d..5b74261 100644
--- a/chromecast/media/base/decrypt_context_impl.h
+++ b/chromecast/media/base/decrypt_context_impl.h
@@ -23,7 +23,7 @@
 // decryption context.
 class DecryptContextImpl : public DecryptContext {
  public:
-  using DecryptCB = base::Callback<void(bool)>;
+  using DecryptCB = base::OnceCallback<void(bool)>;
 
   explicit DecryptContextImpl(CastKeySystem key_system);
   ~DecryptContextImpl() override;
@@ -39,7 +39,7 @@
   virtual void DecryptAsync(CastDecoderBuffer* buffer,
                             uint8_t* output,
                             size_t data_offset,
-                            const DecryptCB& decrypt_cb);
+                            DecryptCB decrypt_cb);
 
   // Returns whether the data can be decrypted into user memory.
   // If the key system doesn't support secure output or the app explicitly
diff --git a/chromecast/media/base/decrypt_context_impl_clearkey.cc b/chromecast/media/base/decrypt_context_impl_clearkey.cc
index d65f56f..a68c30d 100644
--- a/chromecast/media/base/decrypt_context_impl_clearkey.cc
+++ b/chromecast/media/base/decrypt_context_impl_clearkey.cc
@@ -30,8 +30,8 @@
 void DecryptContextImplClearKey::DecryptAsync(CastDecoderBuffer* buffer,
                                               uint8_t* output,
                                               size_t data_offset,
-                                              const DecryptCB& decrypt_cb) {
-  decrypt_cb.Run(DoDecrypt(buffer, output, data_offset));
+                                              DecryptCB decrypt_cb) {
+  std::move(decrypt_cb).Run(DoDecrypt(buffer, output, data_offset));
 }
 
 bool DecryptContextImplClearKey::DoDecrypt(CastDecoderBuffer* buffer,
diff --git a/chromecast/media/base/decrypt_context_impl_clearkey.h b/chromecast/media/base/decrypt_context_impl_clearkey.h
index d21a188..84ff669 100644
--- a/chromecast/media/base/decrypt_context_impl_clearkey.h
+++ b/chromecast/media/base/decrypt_context_impl_clearkey.h
@@ -29,7 +29,7 @@
   void DecryptAsync(CastDecoderBuffer* buffer,
                     uint8_t* output,
                     size_t data_offset,
-                    const DecryptCB& decrypt_cb) override;
+                    DecryptCB decrypt_cb) override;
 
   bool CanDecryptToBuffer() const override;
 
diff --git a/chromecast/media/base/media_resource_tracker.cc b/chromecast/media/base/media_resource_tracker.cc
index 0052f58..e233922 100644
--- a/chromecast/media/base/media_resource_tracker.cc
+++ b/chromecast/media/base/media_resource_tracker.cc
@@ -42,19 +42,19 @@
 void MediaResourceTracker::InitializeMediaLib() {
   DCHECK(ui_task_runner_->BelongsToCurrentThread());
   media_task_runner_->PostTask(
-      FROM_HERE, base::Bind(&MediaResourceTracker::CallInitializeOnMediaThread,
-                            base::Unretained(this)));
+      FROM_HERE,
+      base::BindOnce(&MediaResourceTracker::CallInitializeOnMediaThread,
+                     base::Unretained(this)));
 }
 
-void MediaResourceTracker::FinalizeMediaLib(
-    const base::Closure& completion_cb) {
+void MediaResourceTracker::FinalizeMediaLib(base::OnceClosure completion_cb) {
   DCHECK(ui_task_runner_->BelongsToCurrentThread());
   DCHECK(!completion_cb.is_null());
 
   media_task_runner_->PostTask(
       FROM_HERE,
-      base::Bind(&MediaResourceTracker::MaybeCallFinalizeOnMediaThread,
-                 base::Unretained(this), completion_cb));
+      base::BindOnce(&MediaResourceTracker::MaybeCallFinalizeOnMediaThread,
+                     base::Unretained(this), std::move(completion_cb)));
 }
 
 void MediaResourceTracker::FinalizeAndDestroy() {
@@ -62,7 +62,7 @@
 
   media_task_runner_->PostTask(
       FROM_HERE,
-      base::Bind(
+      base::BindOnce(
           &MediaResourceTracker::MaybeCallFinalizeOnMediaThreadAndDeleteSelf,
           base::Unretained(this)));
 }
@@ -70,7 +70,7 @@
 void MediaResourceTracker::IncrementUsageCount() {
   DCHECK(media_task_runner_->BelongsToCurrentThread());
   DCHECK(media_lib_initialized_);
-  DCHECK(finalize_completion_cb_.is_null());
+  DCHECK(!finalize_completion_cb_);
   media_use_count_++;
 }
 
@@ -79,8 +79,8 @@
   media_use_count_--;
 
   if (media_use_count_ == 0 &&
-      (delete_on_finalize_ || !finalize_completion_cb_.is_null())) {
-      CallFinalizeOnMediaThread();
+      (delete_on_finalize_ || finalize_completion_cb_)) {
+    CallFinalizeOnMediaThread();
   }
 }
 
@@ -94,14 +94,15 @@
 }
 
 void MediaResourceTracker::MaybeCallFinalizeOnMediaThread(
-    const base::Closure& completion_cb) {
+    base::OnceClosure completion_cb) {
   DCHECK(media_task_runner_->BelongsToCurrentThread());
-  DCHECK(finalize_completion_cb_.is_null());
+  DCHECK(!finalize_completion_cb_);
 
-  finalize_completion_cb_ = BindToTaskRunner(ui_task_runner_, completion_cb);
+  finalize_completion_cb_ =
+      BindToTaskRunner(ui_task_runner_, std::move(completion_cb));
   if (!media_lib_initialized_) {
-    if (!finalize_completion_cb_.is_null())
-      base::ResetAndReturn(&finalize_completion_cb_).Run();
+    if (finalize_completion_cb_)
+      std::move(finalize_completion_cb_).Run();
     return;
   }
 
@@ -137,8 +138,8 @@
   DoFinalizeMediaLib();
   media_lib_initialized_ = false;
 
-  if (!finalize_completion_cb_.is_null())
-    base::ResetAndReturn(&finalize_completion_cb_).Run();
+  if (finalize_completion_cb_)
+    std::move(finalize_completion_cb_).Run();
 
   if (delete_on_finalize_)
     ui_task_runner_->DeleteSoon(FROM_HERE, this);
diff --git a/chromecast/media/base/media_resource_tracker.h b/chromecast/media/base/media_resource_tracker.h
index db659228..639502c4 100644
--- a/chromecast/media/base/media_resource_tracker.h
+++ b/chromecast/media/base/media_resource_tracker.h
@@ -62,7 +62,7 @@
   // (3) Calls completion_cb
   // Must be called on UI thread.  Only one Finalize request may be in flight
   // at a time. |completion_cb| must not be null.
-  void FinalizeMediaLib(const base::Closure& completion_cb);
+  void FinalizeMediaLib(base::OnceClosure completion_cb);
 
   // Shutdown process:
   // (1) Waits for usage count to drop to zero
@@ -84,7 +84,7 @@
 
   // Tasks posted to media thread
   void CallInitializeOnMediaThread();
-  void MaybeCallFinalizeOnMediaThread(const base::Closure& completion_cb);
+  void MaybeCallFinalizeOnMediaThread(base::OnceClosure completion_cb);
   void MaybeCallFinalizeOnMediaThreadAndDeleteSelf();
   void CallFinalizeOnMediaThread();
 
@@ -95,7 +95,7 @@
   // Accessed on media thread + ctor
   size_t media_use_count_;
   bool media_lib_initialized_;
-  base::Closure finalize_completion_cb_;
+  base::OnceClosure finalize_completion_cb_;
   bool delete_on_finalize_;
 
   scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner_;
diff --git a/chromecast/media/base/media_resource_tracker_unittest.cc b/chromecast/media/base/media_resource_tracker_unittest.cc
index bf10f66..eb6949a 100644
--- a/chromecast/media/base/media_resource_tracker_unittest.cc
+++ b/chromecast/media/base/media_resource_tracker_unittest.cc
@@ -119,8 +119,8 @@
   EXPECT_CALL(*test_mocks_, Destroyed()).Times(0);
   EXPECT_CALL(*test_mocks_, FinalizeCallback()).Times(1);
   resource_tracker_->FinalizeMediaLib(
-      base::Bind(&MediaResourceTrackerTestMocks::FinalizeCallback,
-                 base::Unretained(test_mocks_.get())));
+      base::BindOnce(&MediaResourceTrackerTestMocks::FinalizeCallback,
+                     base::Unretained(test_mocks_.get())));
   base::RunLoop().RunUntilIdle();
 
   EXPECT_CALL(*test_mocks_, Destroyed()).Times(1);
@@ -138,8 +138,8 @@
   EXPECT_CALL(*test_mocks_, Finalize()).Times(0);
   EXPECT_CALL(*test_mocks_, Destroyed()).Times(0);
   resource_tracker_->FinalizeMediaLib(
-      base::Bind(&MediaResourceTrackerTestMocks::FinalizeCallback,
-                 base::Unretained(test_mocks_.get())));
+      base::BindOnce(&MediaResourceTrackerTestMocks::FinalizeCallback,
+                     base::Unretained(test_mocks_.get())));
   base::RunLoop().RunUntilIdle();
 
   EXPECT_CALL(*test_mocks_, Finalize()).Times(1);
diff --git a/chromecast/media/base/video_mode_switcher.h b/chromecast/media/base/video_mode_switcher.h
index 11df341..de08fbc 100644
--- a/chromecast/media/base/video_mode_switcher.h
+++ b/chromecast/media/base/video_mode_switcher.h
@@ -24,14 +24,14 @@
 
   // Input parameter is true if mode switch succeeded (or wasn't needed) and
   // playback should proceed. False indicates failed mode switch.
-  using CompletionCB = base::Callback<void(bool)>;
+  using CompletionCB = base::OnceCallback<void(bool)>;
 
   // The |video_configs| describe input streams (potentially multiple streams in
   // case of dual layer content). The |mode_switch_completion_cb| will be
   // invoked to notify the caller about mode switch result.
   virtual void SwitchMode(
       const std::vector<::media::VideoDecoderConfig>& video_configs,
-      const CompletionCB& mode_switch_completion_cb) = 0;
+      CompletionCB mode_switch_completion_cb) = 0;
 };
 
 }  // namespace media
diff --git a/chromecast/media/base/video_plane_controller.cc b/chromecast/media/base/video_plane_controller.cc
index 2c0864e..26d231b 100644
--- a/chromecast/media/base/video_plane_controller.cc
+++ b/chromecast/media/base/video_plane_controller.cc
@@ -73,7 +73,7 @@
 
         task_runner_->PostDelayedTask(
             FROM_HERE,
-            base::Bind(
+            base::BindOnce(
                 &RateLimitedSetVideoPlaneGeometry::ApplyPendingSetGeometry,
                 this),
             base::TimeDelta::FromMilliseconds(2 * min_calling_interval_ms_));
@@ -240,9 +240,9 @@
   }
 
   media_task_runner_->PostTask(
-      FROM_HERE,
-      base::Bind(&RateLimitedSetVideoPlaneGeometry::SetGeometry,
-                 video_plane_wrapper_, scaled_rect, video_plane_transform_));
+      FROM_HERE, base::BindOnce(&RateLimitedSetVideoPlaneGeometry::SetGeometry,
+                                video_plane_wrapper_, scaled_rect,
+                                video_plane_transform_));
 }
 
 bool VideoPlaneController::HaveDataForSetGeometry() const {
diff --git a/chromecast/media/cma/pipeline/decrypt_util.cc b/chromecast/media/cma/pipeline/decrypt_util.cc
index e45d07a..f05af67a 100644
--- a/chromecast/media/cma/pipeline/decrypt_util.cc
+++ b/chromecast/media/cma/pipeline/decrypt_util.cc
@@ -103,7 +103,7 @@
                           const BufferDecryptedCB& buffer_decrypted_cb) {
   decrypt_ctxt->DecryptAsync(
       buffer.get(), buffer->writable_data(), 0,
-      base::Bind(&OnBufferDecrypted, buffer, buffer_decrypted_cb));
+      base::BindOnce(&OnBufferDecrypted, buffer, buffer_decrypted_cb));
 }
 
 }  // namespace media
diff --git a/chromecast/media/service/cast_renderer.cc b/chromecast/media/service/cast_renderer.cc
index c074788c..372c18b 100644
--- a/chromecast/media/service/cast_renderer.cc
+++ b/chromecast/media/service/cast_renderer.cc
@@ -202,8 +202,8 @@
         base::Bind(&CastRenderer::OnVideoInitializationFinished,
                    weak_factory_.GetWeakPtr(), init_cb);
     video_mode_switcher_->SwitchMode(
-        video_configs,
-        base::Bind(&VideoModeSwitchCompletionCb, mode_switch_completion_cb));
+        video_configs, base::BindOnce(&VideoModeSwitchCompletionCb,
+                                      mode_switch_completion_cb));
   } else if (video_stream) {
     // No mode switch needed.
     OnVideoInitializationFinished(init_cb, ::media::PIPELINE_OK);
diff --git a/chromeos/components/tether/BUILD.gn b/chromeos/components/tether/BUILD.gn
index 7adcb374..6f22f8cd 100644
--- a/chromeos/components/tether/BUILD.gn
+++ b/chromeos/components/tether/BUILD.gn
@@ -65,6 +65,8 @@
     "tether_host_response_recorder.h",
     "tether_network_disconnection_handler.cc",
     "tether_network_disconnection_handler.h",
+    "timer_factory.cc",
+    "timer_factory.h",
     "wifi_hotspot_connector.cc",
     "wifi_hotspot_connector.h",
   ]
diff --git a/chromeos/components/tether/ble_connection_manager.cc b/chromeos/components/tether/ble_connection_manager.cc
index 78401ed0..18cb02a 100644
--- a/chromeos/components/tether/ble_connection_manager.cc
+++ b/chromeos/components/tether/ble_connection_manager.cc
@@ -5,6 +5,7 @@
 #include "chromeos/components/tether/ble_connection_manager.h"
 
 #include "chromeos/components/tether/ble_constants.h"
+#include "chromeos/components/tether/timer_factory.h"
 #include "components/cryptauth/ble/bluetooth_low_energy_weave_client_connection.h"
 #include "components/cryptauth/cryptauth_service.h"
 #include "components/proximity_auth/logging/logging.h"
@@ -165,10 +166,6 @@
   manager_->SendMessageReceivedEvent(remote_device_, payload);
 }
 
-std::unique_ptr<base::Timer> BleConnectionManager::TimerFactory::CreateTimer() {
-  return base::MakeUnique<base::OneShotTimer>();
-}
-
 BleConnectionManager::BleConnectionManager(
     cryptauth::CryptAuthService* cryptauth_service,
     scoped_refptr<device::BluetoothAdapter> adapter,
@@ -183,7 +180,7 @@
                                           local_device_data_provider,
                                           remote_beacon_seed_fetcher),
           base::MakeUnique<BleAdvertisementDeviceQueue>(),
-          base::WrapUnique<TimerFactory>(new TimerFactory()),
+          base::MakeUnique<TimerFactory>(),
           bluetooth_throttler) {}
 
 BleConnectionManager::BleConnectionManager(
@@ -372,7 +369,7 @@
     return existing_data;
   }
 
-  std::unique_ptr<base::Timer> timer = timer_factory_->CreateTimer();
+  std::unique_ptr<base::Timer> timer = timer_factory_->CreateOneShotTimer();
   device_to_metadata_map_.insert(
       std::pair<cryptauth::RemoteDevice, std::shared_ptr<ConnectionMetadata>>(
           remote_device,
diff --git a/chromeos/components/tether/ble_connection_manager.h b/chromeos/components/tether/ble_connection_manager.h
index c6d73c4..e69cdce 100644
--- a/chromeos/components/tether/ble_connection_manager.h
+++ b/chromeos/components/tether/ble_connection_manager.h
@@ -29,6 +29,8 @@
 
 namespace tether {
 
+class TimerFactory;
+
 // Manages connections to remote devices. When a device is registered,
 // BleConnectionManager intiates a connection to that device. If the connection
 // succeeds and authenticates successfully, messages can be sent/received
@@ -109,11 +111,6 @@
       cryptauth::RemoteDevice remote_device) override;
 
  protected:
-  class TimerFactory {
-   public:
-    virtual std::unique_ptr<base::Timer> CreateTimer();
-  };
-
   BleConnectionManager(
       cryptauth::CryptAuthService* cryptauth_service,
       scoped_refptr<device::BluetoothAdapter> adapter,
diff --git a/chromeos/components/tether/ble_connection_manager_unittest.cc b/chromeos/components/tether/ble_connection_manager_unittest.cc
index b18e5ef5..86cb008 100644
--- a/chromeos/components/tether/ble_connection_manager_unittest.cc
+++ b/chromeos/components/tether/ble_connection_manager_unittest.cc
@@ -8,6 +8,7 @@
 #include "base/timer/mock_timer.h"
 #include "chromeos/components/tether/ble_constants.h"
 #include "chromeos/components/tether/proto/tether.pb.h"
+#include "chromeos/components/tether/timer_factory.h"
 #include "components/cryptauth/ble/bluetooth_low_energy_weave_client_connection.h"
 #include "components/cryptauth/bluetooth_throttler.h"
 #include "components/cryptauth/connection.h"
@@ -60,6 +61,14 @@
   std::string payload;
 };
 
+class MockTimerFactory : public TimerFactory {
+ public:
+  std::unique_ptr<base::Timer> CreateOneShotTimer() override {
+    return base::MakeUnique<base::MockTimer>(false /* retains_user_task */,
+                                             false /* is_repeating */);
+  }
+};
+
 class TestObserver : public BleConnectionManager::Observer {
  public:
   TestObserver() {}
@@ -229,14 +238,6 @@
     std::string expected_device_address_;
   };
 
-  class MockTimerFactory : public BleConnectionManager::TimerFactory {
-   public:
-    std::unique_ptr<base::Timer> CreateTimer() override {
-      return base::MakeUnique<base::MockTimer>(false /* retains_user_task */,
-                                               false /* is_repeating */);
-    }
-  };
-
   BleConnectionManagerTest() : test_devices_(CreateTestDevices(4)) {
     // These tests assume a maximum of two concurrent advertisers. Some of the
     // multi-device tests would need to be re-written if this constant changes.
diff --git a/chromeos/components/tether/fake_ble_connection_manager.cc b/chromeos/components/tether/fake_ble_connection_manager.cc
index 2d182997..ea60007 100644
--- a/chromeos/components/tether/fake_ble_connection_manager.cc
+++ b/chromeos/components/tether/fake_ble_connection_manager.cc
@@ -4,6 +4,8 @@
 
 #include "chromeos/components/tether/fake_ble_connection_manager.h"
 
+#include "chromeos/components/tether/timer_factory.h"
+
 namespace chromeos {
 
 namespace tether {
diff --git a/chromeos/components/tether/host_scan_cache.cc b/chromeos/components/tether/host_scan_cache.cc
index 38a7aae..c059aeb 100644
--- a/chromeos/components/tether/host_scan_cache.cc
+++ b/chromeos/components/tether/host_scan_cache.cc
@@ -11,6 +11,7 @@
 #include "chromeos/components/tether/active_host.h"
 #include "chromeos/components/tether/device_id_tether_network_guid_map.h"
 #include "chromeos/components/tether/tether_host_response_recorder.h"
+#include "chromeos/components/tether/timer_factory.h"
 #include "chromeos/network/network_state_handler.h"
 #include "components/proximity_auth/logging/logging.h"
 
@@ -18,27 +19,12 @@
 
 namespace tether {
 
-namespace {
-
-class TimerFactoryImpl : public HostScanCache::TimerFactory {
- public:
-  TimerFactoryImpl() {}
-  ~TimerFactoryImpl() {}
-
-  // HostScanCache::TimerFactory:
-  std::unique_ptr<base::Timer> CreateOneShotTimer() override {
-    return base::MakeUnique<base::OneShotTimer>();
-  }
-};
-
-}  // namespace
-
 HostScanCache::HostScanCache(
     NetworkStateHandler* network_state_handler,
     ActiveHost* active_host,
     TetherHostResponseRecorder* tether_host_response_recorder,
     DeviceIdTetherNetworkGuidMap* device_id_tether_network_guid_map)
-    : timer_factory_(base::MakeUnique<TimerFactoryImpl>()),
+    : timer_factory_(base::MakeUnique<TimerFactory>()),
       network_state_handler_(network_state_handler),
       active_host_(active_host),
       tether_host_response_recorder_(tether_host_response_recorder),
diff --git a/chromeos/components/tether/host_scan_cache.h b/chromeos/components/tether/host_scan_cache.h
index d3ab465f..3d705e48 100644
--- a/chromeos/components/tether/host_scan_cache.h
+++ b/chromeos/components/tether/host_scan_cache.h
@@ -22,6 +22,7 @@
 class ActiveHost;
 class DeviceIdTetherNetworkGuidMap;
 class TetherHostResponseRecorder;
+class TimerFactory;
 
 // Caches scan results and inserts them into the network stack.
 class HostScanCache : public TetherHostResponseRecorder::Observer {
@@ -76,11 +77,6 @@
   // TetherHostResponseRecorder::Observer:
   void OnPreviouslyConnectedHostIdsChanged() override;
 
-  class TimerFactory {
-   public:
-    virtual std::unique_ptr<base::Timer> CreateOneShotTimer() = 0;
-  };
-
  private:
   friend class HostScanCacheTest;
 
diff --git a/chromeos/components/tether/host_scan_cache_unittest.cc b/chromeos/components/tether/host_scan_cache_unittest.cc
index b082e59..d0e3640 100644
--- a/chromeos/components/tether/host_scan_cache_unittest.cc
+++ b/chromeos/components/tether/host_scan_cache_unittest.cc
@@ -16,6 +16,7 @@
 #include "chromeos/components/tether/fake_active_host.h"
 #include "chromeos/components/tether/fake_host_scan_cache.h"
 #include "chromeos/components/tether/mock_tether_host_response_recorder.h"
+#include "chromeos/components/tether/timer_factory.h"
 #include "chromeos/dbus/dbus_thread_manager.h"
 #include "chromeos/network/network_state.h"
 #include "chromeos/network/network_state_handler.h"
@@ -70,6 +71,43 @@
   base::Closure destructor_callback_;
 };
 
+class TestTimerFactory : public TimerFactory {
+ public:
+  TestTimerFactory() {}
+  ~TestTimerFactory() override {}
+
+  std::unordered_map<std::string, ExtendedMockTimer*>&
+  tether_network_guid_to_timer_map() {
+    return tether_network_guid_to_timer_map_;
+  }
+
+  void set_tether_network_guid_for_next_timer(
+      const std::string& tether_network_guid_for_next_timer) {
+    tether_network_guid_for_next_timer_ = tether_network_guid_for_next_timer;
+  }
+
+  // TimerFactory:
+  std::unique_ptr<base::Timer> CreateOneShotTimer() override {
+    EXPECT_FALSE(tether_network_guid_for_next_timer_.empty());
+    ExtendedMockTimer* mock_timer = new ExtendedMockTimer(base::Bind(
+        &TestTimerFactory::OnActiveTimerDestructor, base::Unretained(this),
+        tether_network_guid_for_next_timer_));
+    tether_network_guid_to_timer_map_[tether_network_guid_for_next_timer_] =
+        mock_timer;
+    return base::WrapUnique(mock_timer);
+  }
+
+ private:
+  void OnActiveTimerDestructor(const std::string& tether_network_guid) {
+    tether_network_guid_to_timer_map_.erase(
+        tether_network_guid_to_timer_map_.find(tether_network_guid));
+  }
+
+  std::string tether_network_guid_for_next_timer_;
+  std::unordered_map<std::string, ExtendedMockTimer*>
+      tether_network_guid_to_timer_map_;
+};
+
 }  // namespace
 
 // TODO(khorimoto): The test uses a FakeHostScanCache to keep an in-memory
@@ -78,43 +116,6 @@
 // if possible.
 class HostScanCacheTest : public NetworkStateTest {
  protected:
-  class TestTimerFactory : public HostScanCache::TimerFactory {
-   public:
-    TestTimerFactory() {}
-    ~TestTimerFactory() {}
-
-    std::unordered_map<std::string, ExtendedMockTimer*>&
-    tether_network_guid_to_timer_map() {
-      return tether_network_guid_to_timer_map_;
-    }
-
-    void set_tether_network_guid_for_next_timer(
-        const std::string& tether_network_guid_for_next_timer) {
-      tether_network_guid_for_next_timer_ = tether_network_guid_for_next_timer;
-    }
-
-    // HostScanCache::TimerFactory:
-    std::unique_ptr<base::Timer> CreateOneShotTimer() override {
-      EXPECT_FALSE(tether_network_guid_for_next_timer_.empty());
-      ExtendedMockTimer* mock_timer = new ExtendedMockTimer(base::Bind(
-          &TestTimerFactory::OnActiveTimerDestructor, base::Unretained(this),
-          tether_network_guid_for_next_timer_));
-      tether_network_guid_to_timer_map_[tether_network_guid_for_next_timer_] =
-          mock_timer;
-      return base::WrapUnique(mock_timer);
-    }
-
-   private:
-    void OnActiveTimerDestructor(const std::string& tether_network_guid) {
-      tether_network_guid_to_timer_map_.erase(
-          tether_network_guid_to_timer_map_.find(tether_network_guid));
-    }
-
-    std::string tether_network_guid_for_next_timer_;
-    std::unordered_map<std::string, ExtendedMockTimer*>
-        tether_network_guid_to_timer_map_;
-  };
-
   HostScanCacheTest() {}
 
   void SetUp() override {
diff --git a/chromeos/components/tether/timer_factory.cc b/chromeos/components/tether/timer_factory.cc
new file mode 100644
index 0000000..c26f9b9
--- /dev/null
+++ b/chromeos/components/tether/timer_factory.cc
@@ -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.
+
+#include "chromeos/components/tether/timer_factory.h"
+
+namespace chromeos {
+
+namespace tether {
+
+TimerFactory::~TimerFactory() {}
+
+std::unique_ptr<base::Timer> TimerFactory::CreateOneShotTimer() {
+  return base::MakeUnique<base::OneShotTimer>();
+}
+
+}  // namespace tether
+
+}  // namespace chromeos
diff --git a/chromeos/components/tether/timer_factory.h b/chromeos/components/tether/timer_factory.h
new file mode 100644
index 0000000..74d5f68
--- /dev/null
+++ b/chromeos/components/tether/timer_factory.h
@@ -0,0 +1,32 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROMEOS_COMPONENTS_TETHER_TIMER_FACTORY_H_
+#define CHROMEOS_COMPONENTS_TETHER_TIMER_FACTORY_H_
+
+#include <memory>
+
+#include "base/macros.h"
+#include "base/memory/ptr_util.h"
+#include "base/timer/timer.h"
+
+namespace chromeos {
+
+namespace tether {
+
+// Serves as a simple Timer creator, injected into classes that use Timers.
+// Is intended to be overriden during testing in order to stub or mock the
+// Timers used by the object under test.
+class TimerFactory {
+ public:
+  virtual ~TimerFactory();
+
+  virtual std::unique_ptr<base::Timer> CreateOneShotTimer();
+};
+
+}  // namespace tether
+
+}  // namespace chromeos
+
+#endif  // CHROMEOS_COMPONENTS_TETHER_TIMER_FACTORY_H_
diff --git a/cloud_print/virtual_driver/win/port_monitor/port_monitor_dll.cc b/cloud_print/virtual_driver/win/port_monitor/port_monitor_dll.cc
index 18d1248..f6d2228 100644
--- a/cloud_print/virtual_driver/win/port_monitor/port_monitor_dll.cc
+++ b/cloud_print/virtual_driver/win/port_monitor/port_monitor_dll.cc
@@ -20,7 +20,6 @@
 #include "base/strings/string16.h"
 #include "base/win/registry.h"
 #include "base/win/scoped_handle.h"
-#include "base/win/windows_version.h"
 #include "chrome/common/chrome_switches.h"
 #include "cloud_print/common/win/cloud_print_utils.h"
 #include "cloud_print/virtual_driver/win/port_monitor/spooler_win.h"
@@ -40,26 +39,18 @@
 // Returns true if Xps support is installed.
 bool XpsIsInstalled() {
   base::FilePath xps_path;
-  if (!SUCCEEDED(GetPrinterDriverDir(&xps_path))) {
+  if (!SUCCEEDED(GetPrinterDriverDir(&xps_path)))
     return false;
-  }
+
   xps_path = xps_path.Append(L"mxdwdrv.dll");
-  if (!base::PathExists(xps_path)) {
-    return false;
-  }
-  return true;
+  return base::PathExists(xps_path);
 }
 
 // Returns true if registration/unregistration can be attempted.
 bool CanRegister() {
-  if (!XpsIsInstalled()) {
+  if (!XpsIsInstalled())
     return false;
-  }
-  if (base::win::GetVersion() >= base::win::VERSION_VISTA) {
-    if (base::GetCurrentProcessIntegrityLevel() != base::HIGH_INTEGRITY)
-      return false;
-  }
-  return true;
+  return base::GetCurrentProcessIntegrityLevel() == base::HIGH_INTEGRITY;
 }
 
 }  // namespace
diff --git a/components/browser_sync/profile_sync_service.h b/components/browser_sync/profile_sync_service.h
index a713ca3c..6c6a408 100644
--- a/components/browser_sync/profile_sync_service.h
+++ b/components/browser_sync/profile_sync_service.h
@@ -25,7 +25,6 @@
 #include "base/time/time.h"
 #include "base/timer/timer.h"
 #include "build/build_config.h"
-#include "components/keyed_service/core/keyed_service.h"
 #include "components/signin/core/browser/gaia_cookie_manager_service.h"
 #include "components/signin/core/browser/signin_manager_base.h"
 #include "components/sync/base/experiments.h"
@@ -170,7 +169,6 @@
                            public syncer::SyncPrefObserver,
                            public syncer::DataTypeManagerObserver,
                            public syncer::UnrecoverableErrorHandler,
-                           public KeyedService,
                            public OAuth2TokenService::Consumer,
                            public OAuth2TokenService::Observer,
                            public SigninManagerBase::Observer,
diff --git a/components/crash/android/javatests/src/org/chromium/components/crash/browser/CrashDumpManagerTest.java b/components/crash/android/javatests/src/org/chromium/components/crash/browser/CrashDumpManagerTest.java
index 8a23e99..53b91f6 100644
--- a/components/crash/android/javatests/src/org/chromium/components/crash/browser/CrashDumpManagerTest.java
+++ b/components/crash/android/javatests/src/org/chromium/components/crash/browser/CrashDumpManagerTest.java
@@ -8,9 +8,10 @@
 import android.test.InstrumentationTestCase;
 
 import org.chromium.base.ContextUtils;
-import org.chromium.base.FileUtils;
 import org.chromium.base.ThreadUtils;
+import org.chromium.base.test.util.DisabledTest;
 import org.chromium.base.test.util.Feature;
+import org.chromium.base.test.util.TestFileUtil;
 
 import java.io.File;
 import java.io.IOException;
@@ -24,24 +25,26 @@
     @Override
     protected void setUp() throws Exception {
         super.setUp();
-
         ContextUtils.initApplicationContextForTests(
                 getInstrumentation().getTargetContext().getApplicationContext());
-        mTempDir = new File(ContextUtils.getApplicationContext().getCacheDir(), "crash-dump-test");
-        if (mTempDir.exists()) {
-            FileUtils.recursivelyDeleteFile(mTempDir);
-        }
-        assert mTempDir.mkdirs();
+        mTempDir = ContextUtils.getApplicationContext().getCacheDir();
+        assert mTempDir.exists();
     }
 
     @Override
     protected void tearDown() throws Exception {
-        FileUtils.recursivelyDeleteFile(mTempDir);
         super.tearDown();
+        File[] files = mTempDir.listFiles();
+        if (files == null) return;
+
+        for (File file : files) {
+            TestFileUtil.deleteFile(file);
+        }
     }
 
     @SmallTest
     @Feature({"Android-AppBase"})
+    @DisabledTest // Flaky, crbug.com/725379.
     public void testUploadMinidump_NoCallback() throws IOException {
         File minidump = new File(mTempDir, "mini.dmp");
         assertTrue(minidump.createNewFile());
@@ -51,6 +54,7 @@
 
     @SmallTest
     @Feature({"Android-AppBase"})
+    @DisabledTest // Flaky, crbug.com/725379.
     public void testUploadMinidump_NullMinidumpPath() {
         registerUploadCallback(new CrashDumpManager.UploadMinidumpCallback() {
             @Override
@@ -62,8 +66,9 @@
         CrashDumpManager.tryToUploadMinidump(null);
     }
 
-    @SmallTest
-    @Feature({"Android-AppBase"})
+    // @SmallTest
+    // @Feature({"Android-AppBase"})
+    @DisabledTest // Flaky, crbug.com/726976.
     public void testUploadMinidump_FileDoesntExist() {
         registerUploadCallback(new CrashDumpManager.UploadMinidumpCallback() {
             @Override
diff --git a/components/cronet/android/BUILD.gn b/components/cronet/android/BUILD.gn
index c751bd3..811f6306 100644
--- a/components/cronet/android/BUILD.gn
+++ b/components/cronet/android/BUILD.gn
@@ -673,6 +673,7 @@
     "test/javatests/src/org/chromium/net/Criteria.java",
     "test/javatests/src/org/chromium/net/CronetEngineBuilderTest.java",
     "test/javatests/src/org/chromium/net/CronetTestBase.java",
+    "test/javatests/src/org/chromium/net/CronetTestBaseTest.java",
     "test/javatests/src/org/chromium/net/CronetUploadTest.java",
     "test/javatests/src/org/chromium/net/CronetUrlRequestContextTest.java",
     "test/javatests/src/org/chromium/net/CronetUrlRequestTest.java",
diff --git a/components/cronet/android/java/src/org/chromium/net/impl/JavaUrlRequest.java b/components/cronet/android/java/src/org/chromium/net/impl/JavaUrlRequest.java
index f47541d7..afaa35e 100644
--- a/components/cronet/android/java/src/org/chromium/net/impl/JavaUrlRequest.java
+++ b/components/cronet/android/java/src/org/chromium/net/impl/JavaUrlRequest.java
@@ -8,7 +8,6 @@
 import android.annotation.TargetApi;
 import android.net.TrafficStats;
 import android.os.Build;
-
 import android.util.Log;
 
 import org.chromium.net.CronetException;
@@ -17,7 +16,6 @@
 import org.chromium.net.UploadDataSink;
 import org.chromium.net.UrlResponseInfo;
 
-import java.io.Closeable;
 import java.io.IOException;
 import java.io.OutputStream;
 import java.net.HttpURLConnection;
@@ -98,17 +96,10 @@
 
     /* These change with redirects. */
     private String mCurrentUrl;
-    private ReadableByteChannel mResponseChannel;
+    private ReadableByteChannel mResponseChannel; // Only accessed on mExecutor.
     private UrlResponseInfoImpl mUrlResponseInfo;
     private String mPendingRedirectUrl;
-    /**
-     * The happens-before edges created by the executor submission and AtomicReference setting are
-     * sufficient to guarantee the correct behavior of this field; however, this is an
-     * AtomicReference so that we can cleanly dispose of a new connection if we're cancelled during
-     * a redirect, which requires get-and-set semantics.
-     * */
-    private final AtomicReference<HttpURLConnection> mCurrentUrlConnection =
-            new AtomicReference<>();
+    private HttpURLConnection mCurrentUrlConnection; // Only accessed on mExecutor.
 
     /**
      *             /- AWAITING_FOLLOW_REDIRECT <-  REDIRECT_RECEIVED <-\     /- READING <--\
@@ -585,29 +576,30 @@
         mExecutor.execute(errorSetting(new CheckedRunnable() {
             @Override
             public void run() throws Exception {
-                HttpURLConnection connection = mCurrentUrlConnection.get();
-                if (connection == null) {
+                if (mCurrentUrlConnection == null) {
                     return; // We've been cancelled
                 }
                 final List<Map.Entry<String, String>> headerList = new ArrayList<>();
                 String selectedTransport = "http/1.1";
                 String headerKey;
-                for (int i = 0; (headerKey = connection.getHeaderFieldKey(i)) != null; i++) {
+                for (int i = 0; (headerKey = mCurrentUrlConnection.getHeaderFieldKey(i)) != null;
+                        i++) {
                     if (X_ANDROID_SELECTED_TRANSPORT.equalsIgnoreCase(headerKey)) {
-                        selectedTransport = connection.getHeaderField(i);
+                        selectedTransport = mCurrentUrlConnection.getHeaderField(i);
                     }
                     if (!headerKey.startsWith(X_ANDROID)) {
-                        headerList.add(new SimpleEntry<>(headerKey, connection.getHeaderField(i)));
+                        headerList.add(new SimpleEntry<>(
+                                headerKey, mCurrentUrlConnection.getHeaderField(i)));
                     }
                 }
 
-                int responseCode = connection.getResponseCode();
+                int responseCode = mCurrentUrlConnection.getResponseCode();
                 // Important to copy the list here, because although we never concurrently modify
                 // the list ourselves, user code might iterate over it while we're redirecting, and
                 // that would throw ConcurrentModificationException.
                 mUrlResponseInfo = new UrlResponseInfoImpl(new ArrayList<>(mUrlChain), responseCode,
-                        connection.getResponseMessage(), Collections.unmodifiableList(headerList),
-                        false, selectedTransport, "");
+                        mCurrentUrlConnection.getResponseMessage(),
+                        Collections.unmodifiableList(headerList), false, selectedTransport, "");
                 // TODO(clm) actual redirect handling? post -> get and whatnot?
                 if (responseCode >= 300 && responseCode < 400) {
                     fireRedirectReceived(mUrlResponseInfo.getAllHeaders());
@@ -615,10 +607,12 @@
                 }
                 fireCloseUploadDataProvider();
                 if (responseCode >= 400) {
-                    mResponseChannel = InputStreamChannel.wrap(connection.getErrorStream());
+                    mResponseChannel =
+                            InputStreamChannel.wrap(mCurrentUrlConnection.getErrorStream());
                     mCallbackAsync.onResponseStarted(mUrlResponseInfo);
                 } else {
-                    mResponseChannel = InputStreamChannel.wrap(connection.getInputStream());
+                    mResponseChannel =
+                            InputStreamChannel.wrap(mCurrentUrlConnection.getInputStream());
                     mCallbackAsync.onResponseStarted(mUrlResponseInfo);
                 }
             }
@@ -671,29 +665,29 @@
                 }
 
                 final URL url = new URL(mCurrentUrl);
-                HttpURLConnection newConnection = (HttpURLConnection) url.openConnection();
-                HttpURLConnection oldConnection = mCurrentUrlConnection.getAndSet(newConnection);
-                if (oldConnection != null) {
-                    oldConnection.disconnect();
+                if (mCurrentUrlConnection != null) {
+                    mCurrentUrlConnection.disconnect();
+                    mCurrentUrlConnection = null;
                 }
-                newConnection.setInstanceFollowRedirects(false);
+                mCurrentUrlConnection = (HttpURLConnection) url.openConnection();
+                mCurrentUrlConnection.setInstanceFollowRedirects(false);
                 if (!mRequestHeaders.containsKey(USER_AGENT)) {
                     mRequestHeaders.put(USER_AGENT, mUserAgent);
                 }
                 for (Map.Entry<String, String> entry : mRequestHeaders.entrySet()) {
-                    newConnection.setRequestProperty(entry.getKey(), entry.getValue());
+                    mCurrentUrlConnection.setRequestProperty(entry.getKey(), entry.getValue());
                 }
                 if (mInitialMethod == null) {
                     mInitialMethod = "GET";
                 }
-                newConnection.setRequestMethod(mInitialMethod);
+                mCurrentUrlConnection.setRequestMethod(mInitialMethod);
                 if (mUploadDataProvider != null) {
                     OutputStreamDataSink dataSink = new OutputStreamDataSink(
-                            mUploadExecutor, mExecutor, newConnection, mUploadDataProvider);
+                            mUploadExecutor, mExecutor, mCurrentUrlConnection, mUploadDataProvider);
                     dataSink.start(mUrlChain.size() == 1);
                 } else {
                     mAdditionalStatusDetails = Status.CONNECTING;
-                    newConnection.connect();
+                    mCurrentUrlConnection.connect();
                     fireGetHeaders();
                 }
             }
@@ -772,15 +766,15 @@
     }
 
     private void fireDisconnect() {
-        final HttpURLConnection connection = mCurrentUrlConnection.getAndSet(null);
-        if (connection != null) {
-            mExecutor.execute(new Runnable() {
-                @Override
-                public void run() {
-                    connection.disconnect();
+        mExecutor.execute(new Runnable() {
+            @Override
+            public void run() {
+                if (mCurrentUrlConnection != null) {
+                    mCurrentUrlConnection.disconnect();
+                    mCurrentUrlConnection = null;
                 }
-            });
-        }
+            }
+        });
     }
 
     @Override
@@ -965,18 +959,16 @@
     }
 
     private void closeResponseChannel() {
-        final Closeable closeable = mResponseChannel;
-        if (closeable == null) {
-            return;
-        }
-        mResponseChannel = null;
         mExecutor.execute(new Runnable() {
             @Override
             public void run() {
-                try {
-                    closeable.close();
-                } catch (IOException e) {
-                    e.printStackTrace();
+                if (mResponseChannel != null) {
+                    try {
+                        mResponseChannel.close();
+                    } catch (IOException e) {
+                        e.printStackTrace();
+                    }
+                    mResponseChannel = null;
                 }
             }
         });
diff --git a/components/cronet/android/test/javatests/src/org/chromium/net/BrotliTest.java b/components/cronet/android/test/javatests/src/org/chromium/net/BrotliTest.java
index a26fccc..e1504474 100644
--- a/components/cronet/android/test/javatests/src/org/chromium/net/BrotliTest.java
+++ b/components/cronet/android/test/javatests/src/org/chromium/net/BrotliTest.java
@@ -7,10 +7,12 @@
 import android.support.test.filters.SmallTest;
 
 import org.chromium.base.test.util.Feature;
+import org.chromium.net.CronetTestBase.RequiresMinApi;
 
 /**
  * Simple test for Brotli support.
  */
+@RequiresMinApi(5) // Brotli support added in API version 5: crrev.com/465216
 public class BrotliTest extends CronetTestBase {
     private CronetEngine mCronetEngine;
 
diff --git a/components/cronet/android/test/javatests/src/org/chromium/net/CronetTestBase.java b/components/cronet/android/test/javatests/src/org/chromium/net/CronetTestBase.java
index 581dfb6f..8e004ed3 100644
--- a/components/cronet/android/test/javatests/src/org/chromium/net/CronetTestBase.java
+++ b/components/cronet/android/test/javatests/src/org/chromium/net/CronetTestBase.java
@@ -5,9 +5,11 @@
 package org.chromium.net;
 
 import android.content.Context;
+import android.os.StrictMode;
 import android.test.AndroidTestCase;
 
 import org.chromium.base.ContextUtils;
+import org.chromium.base.Log;
 import org.chromium.base.PathUtils;
 import org.chromium.base.annotations.SuppressFBWarnings;
 import org.chromium.net.impl.CronetEngineBase;
@@ -16,6 +18,7 @@
 import org.chromium.net.impl.UserAgent;
 
 import java.io.File;
+import java.lang.annotation.Annotation;
 import java.lang.annotation.ElementType;
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
@@ -43,6 +46,8 @@
         }
     }
 
+    private static final String TAG = CronetTestBase.class.getSimpleName();
+
     /**
      * Name of the file that contains the test server certificate in PEM format.
      */
@@ -62,6 +67,7 @@
     // {@code true} when test is being run against system HttpURLConnection implementation.
     private boolean mTestingSystemHttpURLConnection;
     private boolean mTestingJavaImpl = false;
+    private StrictMode.VmPolicy mOldVmPolicy;
 
     @Override
     protected void setUp() throws Exception {
@@ -70,6 +76,29 @@
         ContextUtils.initApplicationContext(getContext().getApplicationContext());
         PathUtils.setPrivateDataDirectorySuffix(PRIVATE_DATA_DIRECTORY_SUFFIX);
         prepareTestStorage(getContext());
+        mOldVmPolicy = StrictMode.getVmPolicy();
+        StrictMode.setVmPolicy(new StrictMode.VmPolicy.Builder()
+                                       .detectLeakedClosableObjects()
+                                       .penaltyLog()
+                                       .penaltyDeath()
+                                       .build());
+    }
+
+    @SuppressFBWarnings("DM_GC") // Used to trigger strictmode detecting leaked closeables
+    @Override
+    protected void tearDown() throws Exception {
+        try {
+            // Run GC and finalizers a few times to pick up leaked closeables
+            for (int i = 0; i < 10; i++) {
+                System.gc();
+                System.runFinalization();
+            }
+            System.gc();
+            System.runFinalization();
+            super.tearDown();
+        } finally {
+            StrictMode.setVmPolicy(mOldVmPolicy);
+        }
     }
 
     /**
@@ -94,14 +123,42 @@
         return mTestingJavaImpl;
     }
 
+    private int getMaximumAvailableApiLevel() {
+        // Prior to M59 the ApiVersion.getMaximumAvailableApiLevel API didn't exist
+        if (ApiVersion.getCronetVersion().compareTo("59") < 0) {
+            return 3;
+        }
+        return ApiVersion.getMaximumAvailableApiLevel();
+    }
+
     @Override
     protected void runTest() throws Throwable {
         mTestingSystemHttpURLConnection = false;
         mTestingJavaImpl = false;
         String packageName = getClass().getPackage().getName();
-        if (packageName.equals("org.chromium.net.urlconnection")) {
+
+        // Find the API version required by the test.
+        int requiredApiVersion = getMaximumAvailableApiLevel();
+        for (Annotation a : getClass().getAnnotations()) {
+            if (a instanceof RequiresMinApi) {
+                requiredApiVersion = ((RequiresMinApi) a).value();
+            }
+        }
+        AnnotatedElement method = getClass().getMethod(getName(), (Class[]) null);
+        for (Annotation a : method.getAnnotations()) {
+            if (a instanceof RequiresMinApi) {
+                // Method scoped requirements take precedence over class scoped
+                // requirements.
+                requiredApiVersion = ((RequiresMinApi) a).value();
+            }
+        }
+
+        if (requiredApiVersion > getMaximumAvailableApiLevel()) {
+            Log.i(TAG,
+                    getName() + " skipped because it requires API " + requiredApiVersion
+                            + " but only API " + getMaximumAvailableApiLevel() + " is present.");
+        } else if (packageName.equals("org.chromium.net.urlconnection")) {
             try {
-                AnnotatedElement method = getClass().getMethod(getName(), (Class[]) null);
                 if (method.isAnnotationPresent(CompareDefaultWithCronet.class)) {
                     // Run with the default HttpURLConnection implementation first.
                     mTestingSystemHttpURLConnection = true;
@@ -123,7 +180,6 @@
             }
         } else if (packageName.equals("org.chromium.net")) {
             try {
-                AnnotatedElement method = getClass().getMethod(getName(), (Class[]) null);
                 super.runTest();
                 if (!method.isAnnotationPresent(OnlyRunNativeCronet.class)) {
                     if (mCronetTestFramework != null) {
@@ -193,21 +249,49 @@
         mStreamHandlerFactory = cronetEngine.createURLStreamHandlerFactory();
     }
 
+    /**
+     * Annotation for test methods in org.chromium.net.urlconnection pacakage that runs them
+     * against both Cronet's HttpURLConnection implementation, and against the system's
+     * HttpURLConnection implementation.
+     */
     @Target(ElementType.METHOD)
     @Retention(RetentionPolicy.RUNTIME)
     public @interface CompareDefaultWithCronet {
     }
 
+    /**
+     * Annotation for test methods in org.chromium.net.urlconnection pacakage that runs them
+     * only against Cronet's HttpURLConnection implementation, and not against the system's
+     * HttpURLConnection implementation.
+     */
     @Target(ElementType.METHOD)
     @Retention(RetentionPolicy.RUNTIME)
     public @interface OnlyRunCronetHttpURLConnection {
     }
 
+    /**
+     * Annotation for test methods in org.chromium.net package that disables rerunning the test
+     * against the Java-only implementation. When this annotation is present the test is only run
+     * against the native implementation.
+     */
     @Target(ElementType.METHOD)
     @Retention(RetentionPolicy.RUNTIME)
     public @interface OnlyRunNativeCronet {}
 
     /**
+     * Annotation allowing classes or individual tests to be skipped based on the version of the
+     * Cronet API present. Takes the minimum API version upon which the test should be run.
+     * For example if a test should only be run with API version 2 or greater:
+     *   @RequiresMinApi(2)
+     *   public void testFoo() {}
+     */
+    @Target({ElementType.TYPE, ElementType.METHOD})
+    @Retention(RetentionPolicy.RUNTIME)
+    public @interface RequiresMinApi {
+        int value();
+    }
+
+    /**
      * Prepares the path for the test storage (http cache, QUIC server info).
      */
     public static void prepareTestStorage(Context context) {
diff --git a/components/cronet/android/test/javatests/src/org/chromium/net/CronetTestBaseTest.java b/components/cronet/android/test/javatests/src/org/chromium/net/CronetTestBaseTest.java
new file mode 100644
index 0000000..9dad2cc
--- /dev/null
+++ b/components/cronet/android/test/javatests/src/org/chromium/net/CronetTestBaseTest.java
@@ -0,0 +1,82 @@
+// 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.net;
+
+import android.support.test.filters.SmallTest;
+
+import org.chromium.base.test.util.Feature;
+import org.chromium.net.impl.CronetUrlRequestContext;
+import org.chromium.net.impl.JavaCronetEngine;
+
+/**
+ * Tests features of CronetTestBase.
+ */
+public class CronetTestBaseTest extends CronetTestBase {
+    private CronetTestFramework mTestFramework;
+    /**
+     * For any test whose name contains "MustRun", it's enforced that the test must run and set
+     * {@code mTestWasRun} to {@code true}.
+     */
+    private boolean mTestWasRun;
+    /**
+     * For {@link #testRunBothImplsMustRun}, use {@link #mTestNativeImplRun} to verify that the
+     * test is run against the native implementation.
+     */
+    private boolean mTestNativeImplRun;
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+        mTestFramework = startCronetTestFramework();
+    }
+
+    @Override
+    protected void tearDown() throws Exception {
+        if (getName().contains("MustRun") && !mTestWasRun) {
+            fail(getName() + " should have run but didn't.");
+        }
+        super.tearDown();
+    }
+
+    @SmallTest
+    @RequiresMinApi(999999999)
+    @Feature({"Cronet"})
+    public void testRequiresMinApiDisable() {
+        fail("RequiresMinApi failed to disable.");
+    }
+
+    @SmallTest
+    @RequiresMinApi(-999999999)
+    @Feature({"Cronet"})
+    public void testRequiresMinApiMustRun() {
+        mTestWasRun = true;
+    }
+
+    @SmallTest
+    @Feature({"Cronet"})
+    public void testRunBothImplsMustRun() {
+        if (testingJavaImpl()) {
+            assertFalse(mTestWasRun);
+            assertTrue(mTestNativeImplRun);
+            mTestWasRun = true;
+            assertEquals(mTestFramework.mCronetEngine.getClass(), JavaCronetEngine.class);
+        } else {
+            assertFalse(mTestWasRun);
+            assertFalse(mTestNativeImplRun);
+            mTestNativeImplRun = true;
+            assertEquals(mTestFramework.mCronetEngine.getClass(), CronetUrlRequestContext.class);
+        }
+    }
+
+    @SmallTest
+    @Feature({"Cronet"})
+    @OnlyRunNativeCronet
+    public void testRunOnlyNativeMustRun() {
+        assertFalse(testingJavaImpl());
+        assertFalse(mTestWasRun);
+        mTestWasRun = true;
+        assertEquals(mTestFramework.mCronetEngine.getClass(), CronetUrlRequestContext.class);
+    }
+}
\ No newline at end of file
diff --git a/components/cronet/android/test/javatests/src/org/chromium/net/CronetUrlRequestContextTest.java b/components/cronet/android/test/javatests/src/org/chromium/net/CronetUrlRequestContextTest.java
index 2fbdd80..186cff6b 100644
--- a/components/cronet/android/test/javatests/src/org/chromium/net/CronetUrlRequestContextTest.java
+++ b/components/cronet/android/test/javatests/src/org/chromium/net/CronetUrlRequestContextTest.java
@@ -1304,6 +1304,7 @@
 
     @SmallTest
     @Feature({"Cronet"})
+    @RequiresMinApi(6) // setThreadPriority added in API 6: crrev.com/472449
     public void testCronetEngineThreadPriority() throws Exception {
         ExperimentalCronetEngine.Builder builder =
                 new ExperimentalCronetEngine.Builder(getContext());
diff --git a/components/cronet/android/test/javatests/src/org/chromium/net/CronetUrlRequestTest.java b/components/cronet/android/test/javatests/src/org/chromium/net/CronetUrlRequestTest.java
index dd2230df..4c973ead 100644
--- a/components/cronet/android/test/javatests/src/org/chromium/net/CronetUrlRequestTest.java
+++ b/components/cronet/android/test/javatests/src/org/chromium/net/CronetUrlRequestTest.java
@@ -2118,4 +2118,39 @@
                     ((NetworkException) callback.mError).getCronetInternalErrorCode());
         }
     }
+
+    @SmallTest
+    @Feature({"Cronet"})
+    /**
+     * Open many connections and cancel them right away. This test verifies all internal
+     * sockets and other Closeables are properly closed. See crbug.com/726193.
+     */
+    public void testGzipCancel() throws Exception {
+        String url = NativeTestServer.getFileURL("/gzipped.html");
+        for (int i = 0; i < 100; i++) {
+            TestUrlRequestCallback callback = new TestUrlRequestCallback();
+            callback.setAutoAdvance(false);
+            UrlRequest urlRequest =
+                    mTestFramework.mCronetEngine
+                            .newUrlRequestBuilder(url, callback, callback.getExecutor())
+                            .build();
+            urlRequest.start();
+            urlRequest.cancel();
+            // If the test blocks until each UrlRequest finishes before starting the next UrlRequest
+            // then it never catches the leak. If it starts all UrlRequests and then blocks until
+            // all UrlRequests finish, it only catches the leak ~10% of the time. In its current
+            // form it appears to catch the leak ~70% of the time.
+            // Catching the leak may require a lot of busy threads so that the cancel() happens
+            // before the UrlRequest has made much progress (and set mCurrentUrlConnection and
+            // mResponseChannel).  This may be why blocking until each UrlRequest finishes doesn't
+            // catch the leak.
+            // The other quirk of this is that from teardown(), JavaCronetEngine.shutdown() is
+            // called which calls ExecutorService.shutdown() which doesn't wait for the thread to
+            // finish running tasks, and then teardown() calls GC looking for leaks. One possible
+            // modification would be to expose the ExecutorService and then have tests call
+            // awaitTermination() but this would complicate things, and adding a 1s sleep() to
+            // allow the ExecutorService to terminate did not increase the chances of catching the
+            // leak.
+        }
+    }
 }
diff --git a/components/cronet/android/test/javatests/src/org/chromium/net/UploadDataProvidersTest.java b/components/cronet/android/test/javatests/src/org/chromium/net/UploadDataProvidersTest.java
index 4e186529..5f98532 100644
--- a/components/cronet/android/test/javatests/src/org/chromium/net/UploadDataProvidersTest.java
+++ b/components/cronet/android/test/javatests/src/org/chromium/net/UploadDataProvidersTest.java
@@ -6,10 +6,8 @@
 
 import android.os.ConditionVariable;
 import android.os.ParcelFileDescriptor;
-import android.os.StrictMode;
 import android.support.test.filters.SmallTest;
 
-import org.chromium.base.annotations.SuppressFBWarnings;
 import org.chromium.base.test.util.Feature;
 
 import java.io.File;
@@ -24,18 +22,11 @@
             + "lacinia lorem eros vel sapien.";
     private CronetTestFramework mTestFramework;
     private File mFile;
-    private StrictMode.VmPolicy mOldVmPolicy;
     private MockUrlRequestJobFactory mMockUrlRequestJobFactory;
 
     @Override
     protected void setUp() throws Exception {
         super.setUp();
-        mOldVmPolicy = StrictMode.getVmPolicy();
-        StrictMode.setVmPolicy(new StrictMode.VmPolicy.Builder()
-                                       .detectLeakedClosableObjects()
-                                       .penaltyLog()
-                                       .penaltyDeath()
-                                       .build());
         mTestFramework = startCronetTestFramework();
         assertTrue(NativeTestServer.startNativeTestServer(getContext()));
         // Add url interceptors after native application context is initialized.
@@ -49,25 +40,13 @@
         }
     }
 
-    @SuppressFBWarnings("DM_GC") // Used to trigger strictmode detecting leaked closeables
     @Override
     protected void tearDown() throws Exception {
-        try {
-            mMockUrlRequestJobFactory.shutdown();
-            NativeTestServer.shutdownNativeTestServer();
-            mTestFramework.mCronetEngine.shutdown();
-            assertTrue(mFile.delete());
-            // Run GC and finalizers a few times to pick up leaked closeables
-            for (int i = 0; i < 10; i++) {
-                System.gc();
-                System.runFinalization();
-            }
-            System.gc();
-            System.runFinalization();
-            super.tearDown();
-        } finally {
-            StrictMode.setVmPolicy(mOldVmPolicy);
-        }
+        mMockUrlRequestJobFactory.shutdown();
+        NativeTestServer.shutdownNativeTestServer();
+        mTestFramework.mCronetEngine.shutdown();
+        assertTrue(mFile.delete());
+        super.tearDown();
     }
 
     @SmallTest
diff --git a/components/data_reduction_proxy/core/browser/data_reduction_proxy_compression_stats.cc b/components/data_reduction_proxy/core/browser/data_reduction_proxy_compression_stats.cc
index 3cfa1ff..72ba804 100644
--- a/components/data_reduction_proxy/core/browser/data_reduction_proxy_compression_stats.cc
+++ b/components/data_reduction_proxy/core/browser/data_reduction_proxy_compression_stats.cc
@@ -1172,6 +1172,7 @@
     int64_t data_used,
     int64_t original_size,
     const base::Time time) {
+  DCHECK(thread_checker_.CalledOnValidThread());
   if (current_data_usage_load_status_ != LOADED)
     return;
 
diff --git a/components/data_reduction_proxy/core/browser/data_reduction_proxy_data_use_observer.cc b/components/data_reduction_proxy/core/browser/data_reduction_proxy_data_use_observer.cc
index 391674fa..b7683d29 100644
--- a/components/data_reduction_proxy/core/browser/data_reduction_proxy_data_use_observer.cc
+++ b/components/data_reduction_proxy/core/browser/data_reduction_proxy_data_use_observer.cc
@@ -85,8 +85,9 @@
   DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
 
   if (data_use->traffic_type() !=
-      data_use_measurement::DataUse::TrafficType::USER_TRAFFIC)
+      data_use_measurement::DataUse::TrafficType::USER_TRAFFIC) {
     return;
+  }
 
   if (!request.url().SchemeIs(url::kHttpsScheme) &&
       !request.url().SchemeIs(url::kHttpScheme)) {
diff --git a/components/data_reduction_proxy/core/browser/data_reduction_proxy_network_delegate.cc b/components/data_reduction_proxy/core/browser/data_reduction_proxy_network_delegate.cc
index df46721..9666e3b8 100644
--- a/components/data_reduction_proxy/core/browser/data_reduction_proxy_network_delegate.cc
+++ b/components/data_reduction_proxy/core/browser/data_reduction_proxy_network_delegate.cc
@@ -13,6 +13,7 @@
 #include "base/metrics/histogram_macros.h"
 #include "base/strings/string_number_conversions.h"
 #include "base/strings/string_split.h"
+#include "base/strings/stringprintf.h"
 #include "base/time/time.h"
 #include "components/data_reduction_proxy/core/browser/data_reduction_proxy_bypass_stats.h"
 #include "components/data_reduction_proxy/core/browser/data_reduction_proxy_config.h"
@@ -55,13 +56,13 @@
 }
 
 void RecordNewContentLengthHistograms(
+    const char* prefix,
     bool is_https,
     bool is_video,
     DataReductionProxyRequestType request_type,
-    int64_t received_content_length) {
-  std::string prefix = "Net.HttpContentLength";
-  std::string connection_type = is_https ? ".Https" : ".Http";
-  std::string suffix = ".Other";
+    int64_t content_length) {
+  const char* connection_type = is_https ? ".Https" : ".Http";
+  const char* suffix = ".Other";
   // TODO(crbug.com/726411): Differentiate between a bypass and a disabled
   // proxy config.
   switch (request_type) {
@@ -82,11 +83,13 @@
       break;
   }
   // Record a histogram for all traffic, including video.
-  RecordNewContentLengthHistogram(prefix + connection_type + suffix,
-                                  received_content_length);
+  RecordNewContentLengthHistogram(
+      base::StringPrintf("%s%s%s", prefix, connection_type, suffix),
+      content_length);
   if (is_video) {
     RecordNewContentLengthHistogram(
-        prefix + connection_type + suffix + ".Video", received_content_length);
+        base::StringPrintf("%s%s%s.Video", prefix, connection_type, suffix),
+        content_length);
   }
 }
 
@@ -133,8 +136,11 @@
   UMA_HISTOGRAM_COUNTS_1M("Net.HttpContentLength", received_content_length);
 
   // Record the new histograms broken down by HTTP/HTTPS and video/non-video
-  RecordNewContentLengthHistograms(is_https, is_video, request_type,
-                                   received_content_length);
+  RecordNewContentLengthHistograms("Net.HttpContentLength", is_https, is_video,
+                                   request_type, received_content_length);
+  RecordNewContentLengthHistograms("Net.HttpOriginalContentLength", is_https,
+                                   is_video, request_type,
+                                   original_content_length);
 
   UMA_HISTOGRAM_COUNTS_1M("Net.HttpOriginalContentLength",
                           original_content_length);
diff --git a/components/data_reduction_proxy/core/browser/data_reduction_proxy_network_delegate_unittest.cc b/components/data_reduction_proxy/core/browser/data_reduction_proxy_network_delegate_unittest.cc
index 2549758..fe69c11 100644
--- a/components/data_reduction_proxy/core/browser/data_reduction_proxy_network_delegate_unittest.cc
+++ b/components/data_reduction_proxy/core/browser/data_reduction_proxy_network_delegate_unittest.cc
@@ -77,64 +77,99 @@
 const char kTestURL[] = "http://www.google.com/";
 const char kSecureTestURL[] = "https://www.google.com/";
 
-const std::string kReceivedValidOCLHistogramName =
+const char kReceivedValidOCLHistogramName[] =
     "Net.HttpContentLengthWithValidOCL";
-const std::string kOriginalValidOCLHistogramName =
+const char kOriginalValidOCLHistogramName[] =
     "Net.HttpOriginalContentLengthWithValidOCL";
-const std::string kDifferenceValidOCLHistogramName =
+const char kDifferenceValidOCLHistogramName[] =
     "Net.HttpContentLengthDifferenceWithValidOCL";
 
+// HTTP original content length
+const char kOriginalInsecureDirectHistogramName[] =
+    "Net.HttpOriginalContentLength.Http.Direct";
+const char kOriginalInsecureViaDRPHistogramName[] =
+    "Net.HttpOriginalContentLength.Http.ViaDRP";
+const char kOriginalInsecureBypassedHistogramName[] =
+    "Net.HttpOriginalContentLength.Http.BypassedDRP";
+const char kOriginalInsecureOtherHistogramName[] =
+    "Net.HttpOriginalContentLength.Http.Other";
+// HTTP video original content length
+const char kOriginalVideoInsecureDirectHistogramName[] =
+    "Net.HttpOriginalContentLength.Http.Direct.Video";
+const char kOriginalVideoInsecureViaDRPHistogramName[] =
+    "Net.HttpOriginalContentLength.Http.ViaDRP.Video";
+const char kOriginalVideoInsecureBypassedHistogramName[] =
+    "Net.HttpOriginalContentLength.Http.BypassedDRP.Video";
+const char kOriginalVideoInsecureOtherHistogramName[] =
+    "Net.HttpOriginalContentLength.Http.Other.Video";
+// HTTPS original content length
+const char kOriginalSecureDirectHistogramName[] =
+    "Net.HttpOriginalContentLength.Https.Direct";
+const char kOriginalSecureViaDRPHistogramName[] =
+    "Net.HttpOriginalContentLength.Https.ViaDRP";
+const char kOriginalSecureBypassedHistogramName[] =
+    "Net.HttpOriginalContentLength.Https.BypassedDRP";
+const char kOriginalSecureOtherHistogramName[] =
+    "Net.HttpOriginalContentLength.Https.Other";
+// HTTPS video original content length
+const char kOriginalVideoSecureDirectHistogramName[] =
+    "Net.HttpOriginalContentLength.Https.Direct.Video";
+const char kOriginalVideoSecureViaDRPHistogramName[] =
+    "Net.HttpOriginalContentLength.Https.ViaDRP.Video";
+const char kOriginalVideoSecureBypassedHistogramName[] =
+    "Net.HttpOriginalContentLength.Https.BypassedDRP.Video";
+const char kOriginalVideoSecureOtherHistogramName[] =
+    "Net.HttpOriginalContentLength.Https.Other.Video";
+
 // Lo-Fi histograms.
-const std::string kReceivedValidOCLLoFiOnHistogramName =
+const char kReceivedValidOCLLoFiOnHistogramName[] =
     "Net.HttpContentLengthWithValidOCL.LoFiOn";
-const std::string kOriginalValidOCLLoFiOnHistogramName =
+const char kOriginalValidOCLLoFiOnHistogramName[] =
     "Net.HttpOriginalContentLengthWithValidOCL.LoFiOn";
-const std::string kDifferenceValidOCLLoFiOnHistogramName =
+const char kDifferenceValidOCLLoFiOnHistogramName[] =
     "Net.HttpContentLengthDifferenceWithValidOCL.LoFiOn";
 
-const std::string kReceivedHistogramName = "Net.HttpContentLength";
-const std::string kReceivedInsecureDirectHistogramName =
+const char kReceivedHistogramName[] = "Net.HttpContentLength";
+const char kReceivedInsecureDirectHistogramName[] =
     "Net.HttpContentLength.Http.Direct";
-const std::string kReceivedInsecureViaDRPHistogramName =
+const char kReceivedInsecureViaDRPHistogramName[] =
     "Net.HttpContentLength.Http.ViaDRP";
-const std::string kReceivedInsecureBypassedHistogramName =
+const char kReceivedInsecureBypassedHistogramName[] =
     "Net.HttpContentLength.Http.BypassedDRP";
-const std::string kReceivedInsecureOtherHistogramName =
+const char kReceivedInsecureOtherHistogramName[] =
     "Net.HttpContentLength.Http.Other";
-const std::string kReceivedSecureDirectHistogramName =
+const char kReceivedSecureDirectHistogramName[] =
     "Net.HttpContentLength.Https.Direct";
-const std::string kReceivedSecureViaDRPHistogramName =
+const char kReceivedSecureViaDRPHistogramName[] =
     "Net.HttpContentLength.Https.ViaDRP";
-const std::string kReceivedSecureBypassedHistogramName =
+const char kReceivedSecureBypassedHistogramName[] =
     "Net.HttpContentLength.Https.BypassedDRP";
-const std::string kReceivedSecureOtherHistogramName =
+const char kReceivedSecureOtherHistogramName[] =
     "Net.HttpContentLength.Https.Other";
-const std::string kReceivedSecureOtheristogramName =
-    "Net.HttpContentLength.Https.Other";
-const std::string kReceivedVideoInsecureDirectHistogramName =
+const char kReceivedVideoInsecureDirectHistogramName[] =
     "Net.HttpContentLength.Http.Direct.Video";
-const std::string kReceivedVideoInsecureViaDRPHistogramName =
+const char kReceivedVideoInsecureViaDRPHistogramName[] =
     "Net.HttpContentLength.Http.ViaDRP.Video";
-const std::string kReceivedVideoInsecureBypassedHistogramName =
+const char kReceivedVideoInsecureBypassedHistogramName[] =
     "Net.HttpContentLength.Http.BypassedDRP.Video";
-const std::string kReceivedVideoInsecureOtherHistogramName =
+const char kReceivedVideoInsecureOtherHistogramName[] =
     "Net.HttpContentLength.Http.Other.Video";
-const std::string kReceivedVideoSecureDirectHistogramName =
+const char kReceivedVideoSecureDirectHistogramName[] =
     "Net.HttpContentLength.Https.Direct.Video";
-const std::string kReceivedVideoSecureViaDRPHistogramName =
+const char kReceivedVideoSecureViaDRPHistogramName[] =
     "Net.HttpContentLength.Https.ViaDRP.Video";
-const std::string kReceivedVideoSecureBypassedHistogramName =
+const char kReceivedVideoSecureBypassedHistogramName[] =
     "Net.HttpContentLength.Https.BypassedDRP.Video";
-const std::string kReceivedVideoSecureOtherHistogramName =
+const char kReceivedVideoSecureOtherHistogramName[] =
     "Net.HttpContentLength.Https.Other.Video";
-const std::string kOriginalHistogramName = "Net.HttpOriginalContentLength";
-const std::string kDifferenceHistogramName = "Net.HttpContentLengthDifference";
-const std::string kFreshnessLifetimeHistogramName =
+const char kOriginalHistogramName[] = "Net.HttpOriginalContentLength";
+const char kDifferenceHistogramName[] = "Net.HttpContentLengthDifference";
+const char kFreshnessLifetimeHistogramName[] =
     "Net.HttpContentFreshnessLifetime";
-const std::string kCacheableHistogramName = "Net.HttpContentLengthCacheable";
-const std::string kCacheable4HoursHistogramName =
+const char kCacheableHistogramName[] = "Net.HttpContentLengthCacheable";
+const char kCacheable4HoursHistogramName[] =
     "Net.HttpContentLengthCacheable4Hours";
-const std::string kCacheable24HoursHistogramName =
+const char kCacheable24HoursHistogramName[] =
     "Net.HttpContentLengthCacheable24Hours";
 const int64_t kResponseContentLength = 100;
 const int64_t kOriginalContentLength = 200;
@@ -292,9 +327,7 @@
 class DataReductionProxyNetworkDelegateTest : public testing::Test {
  public:
   DataReductionProxyNetworkDelegateTest()
-      : context_(true),
-        context_storage_(&context_),
-        lofi_decider_(nullptr),
+      : lofi_decider_(nullptr),
         lofi_ui_service_(nullptr),
         ssl_socket_data_provider_(net::ASYNC, net::OK) {
     ssl_socket_data_provider_.next_proto = net::kProtoHTTP11;
@@ -317,13 +350,18 @@
                                                  net::ProxyServer::SCHEME_HTTP);
         break;
     }
+    context_.reset(new net::TestURLRequestContext(true));
+    context_storage_.reset(new net::URLRequestContextStorage(context_.get()));
     proxy_service_ =
         net::ProxyService::CreateFixedFromPacResult(proxy_server.ToPacString());
-    context_.set_proxy_service(proxy_service_.get());
+    context_->set_proxy_service(proxy_service_.get());
+
+    mock_socket_factory_.reset(new net::MockClientSocketFactory());
+
     DataReductionProxyTestContext::Builder builder;
     builder = builder.WithClient(kClient)
-                  .WithMockClientSocketFactory(&mock_socket_factory_)
-                  .WithURLRequestContext(&context_);
+                  .WithMockClientSocketFactory(mock_socket_factory_.get())
+                  .WithURLRequestContext(context_.get());
 
     if (proxy_config != BYPASS_PROXY) {
       builder = builder.WithProxiesForHttp({DataReductionProxyServer(
@@ -332,8 +370,8 @@
 
     test_context_ = builder.Build();
 
-    context_.set_client_socket_factory(&mock_socket_factory_);
-    test_context_->AttachToURLRequestContext(&context_storage_);
+    context_->set_client_socket_factory(mock_socket_factory_.get());
+    test_context_->AttachToURLRequestContext(context_storage_.get());
 
     std::unique_ptr<TestLoFiDecider> lofi_decider(new TestLoFiDecider());
     lofi_decider_ = lofi_decider.get();
@@ -343,9 +381,9 @@
     lofi_ui_service_ = lofi_ui_service.get();
     test_context_->io_data()->set_lofi_ui_service(std::move(lofi_ui_service));
 
-    context_.set_enable_brotli(enable_brotli_globally);
-    context_.set_network_quality_estimator(&test_network_quality_estimator_);
-    context_.Init();
+    context_->set_enable_brotli(enable_brotli_globally);
+    context_->set_network_quality_estimator(&test_network_quality_estimator_);
+    context_->Init();
 
     test_context_->EnableDataReductionProxyWithSecureProxyCheckSuccess();
   }
@@ -399,7 +437,7 @@
         io_data()->test_request_options()->GetHeaderValueForTesting() +
         std::string("\r\n\r\n");
 
-    mock_socket_factory_.AddSSLSocketDataProvider(&ssl_socket_data_provider_);
+    mock_socket_factory_->AddSSLSocketDataProvider(&ssl_socket_data_provider_);
 
     for (net::EffectiveConnectionType effective_connection_type :
          effective_connection_types) {
@@ -420,7 +458,7 @@
     socket_ = base::MakeUnique<net::StaticSocketDataProvider>(
         reads_list->data(), reads_list->size(), writes_list->data(),
         writes_list->size());
-    mock_socket_factory_.AddSocketDataProvider(socket_.get());
+    mock_socket_factory_->AddSocketDataProvider(socket_.get());
   }
 
   static void VerifyHeaders(bool expected_data_reduction_proxy_used,
@@ -469,10 +507,10 @@
                              net::MockRead(response_body.c_str()),
                              net::MockRead(net::SYNCHRONOUS, net::OK)};
     net::StaticSocketDataProvider socket(reads, arraysize(reads), nullptr, 0);
-    mock_socket_factory_.AddSocketDataProvider(&socket);
+    mock_socket_factory_->AddSocketDataProvider(&socket);
 
     net::TestDelegate delegate;
-    std::unique_ptr<net::URLRequest> request = context_.CreateRequest(
+    std::unique_ptr<net::URLRequest> request = context_->CreateRequest(
         url, net::IDLE, &delegate, TRAFFIC_ANNOTATION_FOR_TESTS);
     if (request_headers)
       request->SetExtraRequestHeaders(*request_headers);
@@ -525,7 +563,7 @@
           std::string(base::checked_cast<size_t>(response_body_size), ' ');
     }
 
-    mock_socket_factory_.AddSSLSocketDataProvider(&ssl_socket_data_provider_);
+    mock_socket_factory_->AddSSLSocketDataProvider(&ssl_socket_data_provider_);
 
     net::MockRead reads[] = {net::MockRead(response_headers.c_str()),
                              net::MockRead(response_body.c_str()),
@@ -583,10 +621,10 @@
     net::MockWrite writes[] = {net::MockWrite(mock_write.c_str())};
     net::StaticSocketDataProvider socket(reads, arraysize(reads), writes,
                                          arraysize(writes));
-    mock_socket_factory_.AddSocketDataProvider(&socket);
+    mock_socket_factory_->AddSocketDataProvider(&socket);
 
     net::TestDelegate delegate;
-    std::unique_ptr<net::URLRequest> request = context_.CreateRequest(
+    std::unique_ptr<net::URLRequest> request = context_->CreateRequest(
         url, net::IDLE, &delegate, TRAFFIC_ANNOTATION_FOR_TESTS);
     if (request_headers)
       request->SetExtraRequestHeaders(*request_headers);
@@ -650,7 +688,7 @@
     std::string response_body =
         std::string(base::checked_cast<size_t>(response_body_size), ' ');
 
-    mock_socket_factory_.AddSSLSocketDataProvider(&ssl_socket_data_provider_);
+    mock_socket_factory_->AddSSLSocketDataProvider(&ssl_socket_data_provider_);
 
     net::MockRead redirect_reads[] = {
         net::MockRead("HTTP/1.1 302 Redirect\r\n"),
@@ -693,10 +731,10 @@
           arraysize(redirect_writes));
     }
 
-    mock_socket_factory_.AddSocketDataProvider(socket.get());
+    mock_socket_factory_->AddSocketDataProvider(socket.get());
 
     net::TestDelegate delegate;
-    std::unique_ptr<net::URLRequest> request = context_.CreateRequest(
+    std::unique_ptr<net::URLRequest> request = context_->CreateRequest(
         url, net::IDLE, &delegate, TRAFFIC_ANNOTATION_FOR_TESTS);
     if (!page_id_value.empty()) {
       request->SetLoadFlags(request->load_flags() |
@@ -719,7 +757,7 @@
         effective_connection_type);
 
     net::TestDelegate delegate;
-    std::unique_ptr<net::URLRequest> request = context_.CreateRequest(
+    std::unique_ptr<net::URLRequest> request = context_->CreateRequest(
         GURL(kTestURL), net::IDLE, &delegate, TRAFFIC_ANNOTATION_FOR_TESTS);
 
     request->Start();
@@ -773,13 +811,13 @@
   }
 
   net::MockClientSocketFactory* mock_socket_factory() {
-    return &mock_socket_factory_;
+    return mock_socket_factory_.get();
   }
 
-  net::TestURLRequestContext* context() { return &context_; }
+  net::TestURLRequestContext* context() { return context_.get(); }
 
   net::NetworkDelegate* network_delegate() const {
-    return context_.network_delegate();
+    return context_->network_delegate();
   }
 
   TestDataReductionProxyParams* params() const {
@@ -806,10 +844,10 @@
 
  private:
   base::MessageLoopForIO message_loop_;
-  net::MockClientSocketFactory mock_socket_factory_;
+  std::unique_ptr<net::MockClientSocketFactory> mock_socket_factory_;
   std::unique_ptr<net::ProxyService> proxy_service_;
-  net::TestURLRequestContext context_;
-  net::URLRequestContextStorage context_storage_;
+  std::unique_ptr<net::TestURLRequestContext> context_;
+  std::unique_ptr<net::URLRequestContextStorage> context_storage_;
 
   TestLoFiDecider* lofi_decider_;
   TestLoFiUIService* lofi_ui_service_;
@@ -1229,6 +1267,8 @@
                                       kResponseContentLength, 1);
   histogram_tester.ExpectUniqueSample(kOriginalValidOCLHistogramName,
                                       kOriginalContentLength, 1);
+  histogram_tester.ExpectUniqueSample(kOriginalInsecureViaDRPHistogramName,
+                                      kOriginalContentLength, 1);
   histogram_tester.ExpectUniqueSample(
       kDifferenceValidOCLHistogramName,
       kOriginalContentLength - kResponseContentLength, 1);
@@ -1376,46 +1416,192 @@
   histogram_tester.ExpectTotalCount(kReceivedVideoSecureOtherHistogramName, 0);
 }
 
-TEST_F(DataReductionProxyNetworkDelegateTest, NetSSLHistograms) {
-  Init(BYPASS_PROXY, false);
+struct ExpectedHistogram {
+  const std::string name;
+  int64_t value;
+};
 
-  base::HistogramTester histogram_tester;
+bool operator<(const ExpectedHistogram& hist1, const ExpectedHistogram& hist2) {
+  return hist1.name < hist2.name;
+}
 
-  // Check https
-  std::string secure_response_headers =
-      "HTTP/1.1 200 OK\r\n"
-      "Date: Wed, 28 Nov 2007 09:40:09 GMT\r\n"
-      "Expires: Mon, 24 Nov 2014 12:45:26 GMT\r\n"
-      "Via: 1.1 Chrome-Compression-Proxy\r\n"
-      "x-original-content-length: " +
-      base::Int64ToString(kOriginalContentLength) + "\r\n\r\n";
+TEST_F(DataReductionProxyNetworkDelegateTest, DetailedNetHistograms) {
+  // List of all the histograms we're concerned with.
+  // Each test case can define interesting histograms from this list.
+  // Any histogram not called out in an invidual test will have an expected
+  // count of 0 samples.
+  const std::set<std::string> all_new_net_histograms{
+      // HTTP received content length
+      kReceivedInsecureDirectHistogramName,
+      kReceivedInsecureViaDRPHistogramName,
+      kReceivedInsecureBypassedHistogramName,
+      kReceivedInsecureOtherHistogramName,
+      // HTTP video received content length
+      kReceivedVideoInsecureDirectHistogramName,
+      kReceivedVideoInsecureViaDRPHistogramName,
+      kReceivedVideoInsecureBypassedHistogramName,
+      kReceivedVideoInsecureOtherHistogramName,
+      // HTTPS received content length
+      kReceivedSecureDirectHistogramName, kReceivedSecureViaDRPHistogramName,
+      kReceivedSecureBypassedHistogramName, kReceivedSecureOtherHistogramName,
+      // HTTPS video received content length
+      kReceivedVideoSecureDirectHistogramName,
+      kReceivedVideoSecureViaDRPHistogramName,
+      kReceivedVideoSecureBypassedHistogramName,
+      kReceivedVideoSecureOtherHistogramName,
+      // HTTP Original content length
+      kOriginalInsecureDirectHistogramName,
+      kOriginalInsecureViaDRPHistogramName,
+      kOriginalInsecureBypassedHistogramName,
+      kOriginalInsecureOtherHistogramName,
+      // HTTP video Original content length
+      kOriginalVideoInsecureDirectHistogramName,
+      kOriginalVideoInsecureViaDRPHistogramName,
+      kOriginalVideoInsecureBypassedHistogramName,
+      kOriginalVideoInsecureOtherHistogramName,
+      // HTTPS Original content length
+      kOriginalSecureDirectHistogramName, kOriginalSecureViaDRPHistogramName,
+      kOriginalSecureBypassedHistogramName, kOriginalSecureOtherHistogramName,
+      // HTTPS video Original content length
+      kOriginalVideoSecureDirectHistogramName,
+      kOriginalVideoSecureViaDRPHistogramName,
+      kOriginalVideoSecureBypassedHistogramName,
+      kOriginalVideoSecureOtherHistogramName,
+  };
 
-  mock_socket_factory()->AddSSLSocketDataProvider(ssl_socket_data_provider());
-  FetchURLRequest(GURL(kSecureTestURL), nullptr, secure_response_headers,
-                  kResponseContentLength, 0);
+  const struct {
+    const std::string name;
+    bool is_video;
+    bool is_https;
+    ProxyTestConfig proxy_config;
+    int64_t original_content_length;
+    int64_t content_length;
+    // Any histogram listed in all_new_net_histograms but not here should have
+    // no samples.
+    const std::set<ExpectedHistogram> expected_histograms;
+  } tests[] = {
+      {"HTTP nonvideo request via DRP",
+       false,
+       false,
+       USE_INSECURE_PROXY,
+       kOriginalContentLength,
+       kResponseContentLength,
+       {
+           {kReceivedInsecureViaDRPHistogramName, kResponseContentLength},
+           {kOriginalInsecureViaDRPHistogramName, kOriginalContentLength},
+       }},
+      {"HTTP video request via DRP",
+       true,
+       false,
+       USE_INSECURE_PROXY,
+       kOriginalContentLength,
+       kResponseContentLength,
+       {
+           {kReceivedInsecureViaDRPHistogramName, kResponseContentLength},
+           {kOriginalInsecureViaDRPHistogramName, kOriginalContentLength},
+           {kReceivedVideoInsecureViaDRPHistogramName, kResponseContentLength},
+           {kOriginalVideoInsecureViaDRPHistogramName, kOriginalContentLength},
+       }},
+      {"DRP not configured for http",
+       false,
+       false,
+       BYPASS_PROXY,
+       kOriginalContentLength,
+       kResponseContentLength,
+       {
+           {kReceivedInsecureOtherHistogramName, kResponseContentLength},
+           {kOriginalInsecureOtherHistogramName, kResponseContentLength},
+       }},
+      {"DRP not configured for http video",
+       true,
+       false,
+       BYPASS_PROXY,
+       kOriginalContentLength,
+       kResponseContentLength,
+       {
+           {kReceivedInsecureOtherHistogramName, kResponseContentLength},
+           {kOriginalInsecureOtherHistogramName, kResponseContentLength},
+           {kReceivedVideoInsecureOtherHistogramName, kResponseContentLength},
+           {kOriginalVideoInsecureOtherHistogramName, kResponseContentLength},
+       }},
+      {"nonvideo over https",
+       false,
+       true,
+       BYPASS_PROXY,
+       kOriginalContentLength,
+       kResponseContentLength,
+       {
+           {kReceivedSecureDirectHistogramName, kResponseContentLength},
+           {kOriginalSecureDirectHistogramName, kResponseContentLength},
+       }},
+      {"video over https",
+       true,
+       true,
+       BYPASS_PROXY,
+       kOriginalContentLength,
+       kResponseContentLength,
+       {
+           {kReceivedSecureDirectHistogramName, kResponseContentLength},
+           {kOriginalSecureDirectHistogramName, kResponseContentLength},
+           {kReceivedVideoSecureDirectHistogramName, kResponseContentLength},
+           {kOriginalVideoSecureDirectHistogramName, kResponseContentLength},
+       }},
+  };
 
-  histogram_tester.ExpectTotalCount(kReceivedInsecureDirectHistogramName, 0);
-  histogram_tester.ExpectTotalCount(kReceivedInsecureViaDRPHistogramName, 0);
-  histogram_tester.ExpectTotalCount(kReceivedInsecureBypassedHistogramName, 0);
-  histogram_tester.ExpectTotalCount(kReceivedInsecureOtherHistogramName, 0);
-  histogram_tester.ExpectTotalCount(kReceivedSecureViaDRPHistogramName, 0);
-  histogram_tester.ExpectTotalCount(kReceivedSecureBypassedHistogramName, 0);
-  histogram_tester.ExpectTotalCount(kReceivedSecureOtherHistogramName, 0);
-  histogram_tester.ExpectUniqueSample(kReceivedSecureDirectHistogramName,
-                                      kResponseContentLength, 1);
-  histogram_tester.ExpectTotalCount(kReceivedVideoInsecureViaDRPHistogramName,
-                                    0);
-  histogram_tester.ExpectTotalCount(kReceivedVideoInsecureDirectHistogramName,
-                                    0);
-  histogram_tester.ExpectTotalCount(kReceivedVideoInsecureBypassedHistogramName,
-                                    0);
-  histogram_tester.ExpectTotalCount(kReceivedVideoInsecureOtherHistogramName,
-                                    0);
-  histogram_tester.ExpectTotalCount(kReceivedVideoSecureViaDRPHistogramName, 0);
-  histogram_tester.ExpectTotalCount(kReceivedVideoSecureDirectHistogramName, 0);
-  histogram_tester.ExpectTotalCount(kReceivedVideoSecureBypassedHistogramName,
-                                    0);
-  histogram_tester.ExpectTotalCount(kReceivedVideoSecureOtherHistogramName, 0);
+  for (const auto& test : tests) {
+    LOG(INFO) << "NetHistograms: " << test.name;
+    Init(test.proxy_config, false);
+    base::HistogramTester histogram_tester;
+
+    GURL test_url = GURL(kTestURL);
+
+    if (test.is_https) {
+      test_url = GURL(kSecureTestURL);
+      mock_socket_factory()->AddSSLSocketDataProvider(
+          ssl_socket_data_provider());
+    }
+
+    std::string via_header = "";
+    std::string ocl_header = "";
+
+    if (test.proxy_config == USE_INSECURE_PROXY) {
+      via_header = "Via: 1.1 Chrome-Compression-Proxy\r\n";
+      ocl_header = "x-original-content-length: " +
+                   base::Int64ToString(kOriginalContentLength) + "\r\n";
+    }
+    if (test.is_video) {
+      // Check video
+      std::string video_response_headers =
+          "HTTP/1.1 200 OK\r\n"
+          "Date: Wed, 28 Nov 2007 09:40:09 GMT\r\n"
+          "Expires: Mon, 24 Nov 2014 12:45:26 GMT\r\n"
+          "Content-Type: video/mp4\r\n" +
+          via_header + ocl_header + "\r\n";
+
+      FetchURLRequest(test_url, nullptr, video_response_headers,
+                      kResponseContentLength, 0);
+    } else {
+      // Check https
+      std::string response_headers =
+          "HTTP/1.1 200 OK\r\n"
+          "Date: Wed, 28 Nov 2007 09:40:09 GMT\r\n"
+          "Expires: Mon, 24 Nov 2014 12:45:26 GMT\r\n" +
+          via_header + ocl_header + "\r\n\r\n";
+
+      FetchURLRequest(test_url, nullptr, response_headers,
+                      kResponseContentLength, 0);
+    }
+
+    for (const auto& histogram : all_new_net_histograms) {
+      auto expected_it = test.expected_histograms.find({histogram, 0});
+      if (expected_it == test.expected_histograms.end()) {
+        histogram_tester.ExpectTotalCount(histogram, 0);
+      } else {
+        histogram_tester.ExpectUniqueSample(expected_it->name,
+                                            expected_it->value, 1);
+      }
+    }
+  }
 }
 
 TEST_F(DataReductionProxyNetworkDelegateTest, OnCompletedInternalLoFi) {
diff --git a/components/download/internal/BUILD.gn b/components/download/internal/BUILD.gn
index dc74506..ae5c2ae 100644
--- a/components/download/internal/BUILD.gn
+++ b/components/download/internal/BUILD.gn
@@ -16,8 +16,13 @@
   ]
 
   sources = [
+    "client_set.cc",
+    "client_set.h",
     "config.cc",
     "config.h",
+    "controller.h",
+    "controller_impl.cc",
+    "controller_impl.h",
     "download_driver.h",
     "download_service_impl.cc",
     "download_service_impl.h",
@@ -27,6 +32,8 @@
     "driver_entry.h",
     "entry.cc",
     "entry.h",
+    "entry_utils.cc",
+    "entry_utils.h",
     "model.h",
     "model_impl.cc",
     "model_impl.h",
@@ -36,6 +43,10 @@
     "scheduler/battery_listener.h",
     "scheduler/network_listener.cc",
     "scheduler/network_listener.h",
+    "startup_status.cc",
+    "startup_status.h",
+    "stats.cc",
+    "stats.h",
     "store.h",
   ]
 
@@ -54,7 +65,10 @@
   visibility = [ "//components/download:unit_tests" ]
 
   sources = [
+    "client_set_unittest.cc",
+    "controller_impl_unittest.cc",
     "download_store_unittest.cc",
+    "entry_utils_unittest.cc",
     "model_impl_unittest.cc",
     "proto_conversions_unittest.cc",
     "scheduler/battery_listener_unittest.cc",
diff --git a/components/download/internal/client_set.cc b/components/download/internal/client_set.cc
new file mode 100644
index 0000000..f74834b
--- /dev/null
+++ b/components/download/internal/client_set.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 "components/download/internal/client_set.h"
+
+namespace download {
+
+ClientSet::ClientSet(std::unique_ptr<DownloadClientMap> clients)
+    : clients_(std::move(clients)) {
+  DCHECK(clients_->find(DownloadClient::INVALID) == clients_->end());
+}
+
+ClientSet::~ClientSet() = default;
+
+std::set<DownloadClient> ClientSet::GetRegisteredClients() const {
+  std::set<DownloadClient> clients;
+  for (const auto& it : *clients_) {
+    clients.insert(it.first);
+  }
+
+  return clients;
+}
+
+Client* ClientSet::GetClient(DownloadClient id) const {
+  const auto& it = clients_->find(id);
+  return it == clients_->end() ? nullptr : it->second.get();
+}
+
+}  // namespace download
diff --git a/components/download/internal/client_set.h b/components/download/internal/client_set.h
new file mode 100644
index 0000000..2daa5206
--- /dev/null
+++ b/components/download/internal/client_set.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 COMPONENTS_DOWNLOAD_INTERNAL_CLIENT_SET_H_
+#define COMPONENTS_DOWNLOAD_INTERNAL_CLIENT_SET_H_
+
+#include <map>
+#include <memory>
+#include <set>
+
+#include "base/macros.h"
+#include "components/download/public/clients.h"
+
+namespace download {
+
+// Helper class to hold a list of Clients and associates them with their
+// respective DownloadClient identifier.
+class ClientSet {
+ public:
+  explicit ClientSet(std::unique_ptr<DownloadClientMap> clients);
+  virtual ~ClientSet();
+
+  std::set<DownloadClient> GetRegisteredClients() const;
+  Client* GetClient(DownloadClient id) const;
+
+ private:
+  std::unique_ptr<DownloadClientMap> clients_;
+
+  DISALLOW_COPY_AND_ASSIGN(ClientSet);
+};
+
+}  // namespace download
+
+#endif  // COMPONENTS_DOWNLOAD_INTERNAL_CLIENT_SET_H_
diff --git a/components/download/internal/client_set_unittest.cc b/components/download/internal/client_set_unittest.cc
new file mode 100644
index 0000000..04d454c
--- /dev/null
+++ b/components/download/internal/client_set_unittest.cc
@@ -0,0 +1,43 @@
+// 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/download/internal/client_set.h"
+
+#include <algorithm>
+
+#include "base/memory/ptr_util.h"
+#include "components/download/internal/test/empty_client.h"
+#include "components/download/public/clients.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace download {
+
+TEST(DownloadServiceClientSetTest, TestGetClient) {
+  auto client = base::MakeUnique<test::EmptyClient>();
+  Client* raw_client = client.get();
+
+  auto client_map = base::MakeUnique<DownloadClientMap>();
+  client_map->insert(std::make_pair(DownloadClient::TEST, std::move(client)));
+  ClientSet clients(std::move(client_map));
+
+  EXPECT_EQ(raw_client, clients.GetClient(DownloadClient::TEST));
+  EXPECT_EQ(nullptr, clients.GetClient(DownloadClient::INVALID));
+}
+
+TEST(DownloadServiceClientSetTest, TestGetRegisteredClients) {
+  auto client = base::MakeUnique<test::EmptyClient>();
+
+  auto client_map = base::MakeUnique<DownloadClientMap>();
+  client_map->insert(std::make_pair(DownloadClient::TEST, std::move(client)));
+  ClientSet clients(std::move(client_map));
+
+  std::set<DownloadClient> expected_set = {DownloadClient::TEST};
+  std::set<DownloadClient> actual_set = clients.GetRegisteredClients();
+
+  EXPECT_EQ(expected_set.size(), actual_set.size());
+  EXPECT_TRUE(
+      std::equal(expected_set.begin(), expected_set.end(), actual_set.begin()));
+}
+
+}  // namespace download
diff --git a/components/download/internal/config.cc b/components/download/internal/config.cc
index 564da91..264add3 100644
--- a/components/download/internal/config.cc
+++ b/components/download/internal/config.cc
@@ -16,29 +16,29 @@
 namespace {
 
 // Default value for max concurrent downloads configuration.
-const int kDefaultMaxConcurrentDownloads = 4;
+const uint32_t kDefaultMaxConcurrentDownloads = 4;
 
 // Default value for maximum running downloads of the download service.
-const int kDefaultMaxRunningDownloads = 1;
+const uint32_t kDefaultMaxRunningDownloads = 1;
 
 // Default value for maximum scheduled downloads.
-const int kDefaultMaxScheduledDownloads = 15;
+const uint32_t kDefaultMaxScheduledDownloads = 15;
 
 // Default value for maximum retry count.
-const int kDefaultMaxRetryCount = 5;
+const uint32_t kDefaultMaxRetryCount = 5;
 
 // Default value for file keep alive time in minutes, keep the file alive for
 // 12 hours by default.
-const int kDefaultFileKeepAliveTimeMinutes = 12 * 60;
+const uint32_t kDefaultFileKeepAliveTimeMinutes = 12 * 60;
 
 // Helper routine to get Finch experiment parameter. If no Finch seed was found,
 // use the |default_value|. The |name| should match an experiment
 // parameter in Finch server configuration.
-int GetFinchConfigInt(const std::string& name, int default_value) {
+uint32_t GetFinchConfigUInt(const std::string& name, uint32_t default_value) {
   std::string finch_value =
       base::GetFieldTrialParamValueByFeature(kDownloadServiceFeature, name);
-  int result;
-  return base::StringToInt(finch_value, &result) ? result : default_value;
+  uint32_t result;
+  return base::StringToUint(finch_value, &result) ? result : default_value;
 }
 
 }  // namespace
@@ -46,16 +46,17 @@
 // static
 std::unique_ptr<Configuration> Configuration::CreateFromFinch() {
   std::unique_ptr<Configuration> config(new Configuration());
-  config->max_concurrent_downloads = GetFinchConfigInt(
+  config->max_concurrent_downloads = GetFinchConfigUInt(
       kMaxConcurrentDownloadsConfig, kDefaultMaxConcurrentDownloads);
-  config->max_running_downloads = GetFinchConfigInt(
+  config->max_running_downloads = GetFinchConfigUInt(
       kMaxRunningDownloadsConfig, kDefaultMaxRunningDownloads);
-  config->max_scheduled_downloads = GetFinchConfigInt(
+  config->max_scheduled_downloads = GetFinchConfigUInt(
       kMaxScheduledDownloadsConfig, kDefaultMaxScheduledDownloads);
   config->max_retry_count =
-      GetFinchConfigInt(kMaxRetryCountConfig, kDefaultMaxRetryCount);
-  config->file_keep_alive_time = base::TimeDelta::FromMinutes(GetFinchConfigInt(
-      kFileKeepAliveTimeMinutesConfig, kDefaultFileKeepAliveTimeMinutes));
+      GetFinchConfigUInt(kMaxRetryCountConfig, kDefaultMaxRetryCount);
+  config->file_keep_alive_time =
+      base::TimeDelta::FromMinutes(base::saturated_cast<int>(GetFinchConfigUInt(
+          kFileKeepAliveTimeMinutesConfig, kDefaultFileKeepAliveTimeMinutes)));
   return config;
 }
 
@@ -64,7 +65,7 @@
       max_running_downloads(kDefaultMaxRunningDownloads),
       max_scheduled_downloads(kDefaultMaxScheduledDownloads),
       max_retry_count(kDefaultMaxRetryCount),
-      file_keep_alive_time(
-          base::TimeDelta::FromMinutes(kDefaultFileKeepAliveTimeMinutes)) {}
+      file_keep_alive_time(base::TimeDelta::FromMinutes(
+          base::saturated_cast<int>(kDefaultFileKeepAliveTimeMinutes))) {}
 
 }  // namespace download
diff --git a/components/download/internal/config.h b/components/download/internal/config.h
index c5b3b0d..6dc23f1 100644
--- a/components/download/internal/config.h
+++ b/components/download/internal/config.h
@@ -39,18 +39,18 @@
 
   // The maximum number of downloads the DownloadService can have currently in
   // Active or Paused states.
-  int max_concurrent_downloads;
+  uint32_t max_concurrent_downloads;
 
   // The maximum number of downloads the DownloadService can have currently in
   // only Active state.
-  int max_running_downloads;
+  uint32_t max_running_downloads;
 
   // The maximum number of downloads that are scheduled but not yet in Active
   // state, for each client using the download service.
-  int max_scheduled_downloads;
+  uint32_t max_scheduled_downloads;
 
   // The maximum number of retries before the download is aborted.
-  int max_retry_count;
+  uint32_t max_retry_count;
 
   // The time that the download service will keep the files around before
   // deleting them if the client hasn't handle the files.
diff --git a/components/download/internal/controller.h b/components/download/internal/controller.h
new file mode 100644
index 0000000..3e8888a
--- /dev/null
+++ b/components/download/internal/controller.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 COMPONENTS_DOWNLOAD_INTERNAL_CONTROLLER_H_
+#define COMPONENTS_DOWNLOAD_INTERNAL_CONTROLLER_H_
+
+#include <string>
+
+#include "base/macros.h"
+#include "components/download/public/clients.h"
+
+namespace download {
+
+struct DownloadParams;
+struct SchedulingParams;
+struct StartupStatus;
+
+// The core Controller responsible for gluing various DownloadService components
+// together to manage the active downloads.
+class Controller {
+ public:
+  Controller() = default;
+  virtual ~Controller() = default;
+
+  // Initializes the controller.  Initialization may be asynchronous.
+  virtual void Initialize() = 0;
+
+  // Returns the status of Controller.
+  virtual const StartupStatus& GetStartupStatus() = 0;
+
+  // Starts a download with |params|.  See DownloadParams::StartCallback and
+  // DownloadParams::StartResponse for information on how a caller can determine
+  // whether or not the download was successfully accepted and queued.
+  virtual void StartDownload(const DownloadParams& params) = 0;
+
+  // Pauses a download request associated with |guid| if one exists.
+  virtual void PauseDownload(const std::string& guid) = 0;
+
+  // Resumes a download request associated with |guid| if one exists.  The
+  // download request may or may not start downloading at this time, but it will
+  // no longer be blocked by any prior PauseDownload() actions.
+  virtual void ResumeDownload(const std::string& guid) = 0;
+
+  // Cancels a download request associated with |guid| if one exists.
+  virtual void CancelDownload(const std::string& guid) = 0;
+
+  // Changes the SchedulingParams of a download request associated with |guid|
+  // to |params|.
+  virtual void ChangeDownloadCriteria(const std::string& guid,
+                                      const SchedulingParams& params) = 0;
+
+  // Exposes the owner of the download request for |guid| if one exists.
+  // Otherwise returns DownloadClient::INVALID for an unowned entry.
+  virtual DownloadClient GetOwnerOfDownload(const std::string& guid) = 0;
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(Controller);
+};
+
+}  // namespace download
+
+#endif  // COMPONENTS_DOWNLOAD_INTERNAL_CONTROLLER_H_
diff --git a/components/download/internal/controller_impl.cc b/components/download/internal/controller_impl.cc
new file mode 100644
index 0000000..ae434285
--- /dev/null
+++ b/components/download/internal/controller_impl.cc
@@ -0,0 +1,267 @@
+// 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/download/internal/controller_impl.h"
+
+#include <string>
+#include <vector>
+
+#include "base/bind.h"
+#include "base/threading/thread_task_runner_handle.h"
+#include "components/download/internal/client_set.h"
+#include "components/download/internal/config.h"
+#include "components/download/internal/entry.h"
+#include "components/download/internal/entry_utils.h"
+#include "components/download/internal/model.h"
+#include "components/download/internal/stats.h"
+
+namespace download {
+
+ControllerImpl::ControllerImpl(std::unique_ptr<ClientSet> clients,
+                               std::unique_ptr<Configuration> config,
+                               std::unique_ptr<DownloadDriver> driver,
+                               std::unique_ptr<Model> model)
+    : clients_(std::move(clients)),
+      config_(std::move(config)),
+      driver_(std::move(driver)),
+      model_(std::move(model)) {}
+
+ControllerImpl::~ControllerImpl() = default;
+
+void ControllerImpl::Initialize() {
+  DCHECK(!startup_status_.Complete());
+
+  driver_->Initialize(this);
+  model_->Initialize(this);
+}
+
+const StartupStatus& ControllerImpl::GetStartupStatus() {
+  return startup_status_;
+}
+
+void ControllerImpl::StartDownload(const DownloadParams& params) {
+  DCHECK(startup_status_.Ok());
+
+  if (start_callbacks_.find(params.guid) != start_callbacks_.end() ||
+      model_->Get(params.guid) != nullptr) {
+    HandleStartDownloadResponse(params.client, params.guid,
+                                DownloadParams::StartResult::UNEXPECTED_GUID,
+                                params.callback);
+    return;
+  }
+
+  auto* client = clients_->GetClient(params.client);
+  if (!client) {
+    HandleStartDownloadResponse(params.client, params.guid,
+                                DownloadParams::StartResult::UNEXPECTED_CLIENT,
+                                params.callback);
+    return;
+  }
+
+  uint32_t client_count =
+      util::GetNumberOfEntriesForClient(params.client, model_->PeekEntries());
+  if (client_count >= config_->max_scheduled_downloads) {
+    HandleStartDownloadResponse(params.client, params.guid,
+                                DownloadParams::StartResult::BACKOFF,
+                                params.callback);
+    return;
+  }
+
+  start_callbacks_[params.guid] = params.callback;
+  model_->Add(Entry(params));
+}
+
+void ControllerImpl::PauseDownload(const std::string& guid) {
+  DCHECK(startup_status_.Ok());
+
+  auto* entry = model_->Get(guid);
+  DCHECK(entry);
+
+  if (entry->state == Entry::State::PAUSED ||
+      entry->state == Entry::State::COMPLETE ||
+      entry->state == Entry::State::WATCHDOG) {
+    return;
+  }
+
+  // TODO(dtrainor): Pause the download.
+}
+
+void ControllerImpl::ResumeDownload(const std::string& guid) {
+  DCHECK(startup_status_.Ok());
+
+  auto* entry = model_->Get(guid);
+  DCHECK(entry);
+
+  if (entry->state != Entry::State::PAUSED)
+    return;
+
+  // TODO(dtrainor): Resume the download.
+}
+
+void ControllerImpl::CancelDownload(const std::string& guid) {
+  DCHECK(startup_status_.Ok());
+
+  auto* entry = model_->Get(guid);
+  DCHECK(entry);
+
+  if (entry->state == Entry::State::NEW) {
+    // Check if we're currently trying to add the download.
+    DCHECK(start_callbacks_.find(entry->guid) != start_callbacks_.end());
+    HandleStartDownloadResponse(entry->client, entry->guid,
+                                DownloadParams::StartResult::CLIENT_CANCELLED);
+  }
+
+  // TODO(dtrainor): Cancel the download.
+}
+
+void ControllerImpl::ChangeDownloadCriteria(const std::string& guid,
+                                            const SchedulingParams& params) {
+  DCHECK(startup_status_.Ok());
+
+  auto* entry = model_->Get(guid);
+  DCHECK(entry);
+
+  // TODO(dtrainor): Change the criteria of the download.
+}
+
+DownloadClient ControllerImpl::GetOwnerOfDownload(const std::string& guid) {
+  auto* entry = model_->Get(guid);
+  return entry ? entry->client : DownloadClient::INVALID;
+}
+
+void ControllerImpl::OnDriverReady(bool success) {
+  DCHECK(!startup_status_.driver_ok.has_value());
+  startup_status_.driver_ok = success;
+  AttemptToFinalizeSetup();
+}
+
+void ControllerImpl::OnDownloadCreated(const DriverEntry& download) {}
+
+void ControllerImpl::OnDownloadFailed(const DriverEntry& download, int reason) {
+}
+
+void ControllerImpl::OnDownloadSucceeded(const DriverEntry& download,
+                                         const base::FilePath& path) {}
+
+void ControllerImpl::OnDownloadUpdated(const DriverEntry& download) {}
+
+void ControllerImpl::OnModelReady(bool success) {
+  DCHECK(!startup_status_.model_ok.has_value());
+  startup_status_.model_ok = success;
+  AttemptToFinalizeSetup();
+}
+
+void ControllerImpl::OnItemAdded(bool success,
+                                 DownloadClient client,
+                                 const std::string& guid) {
+  // If the StartCallback doesn't exist, we already notified the Client about
+  // this item.  That means something went wrong, so stop here.
+  if (start_callbacks_.find(guid) == start_callbacks_.end())
+    return;
+
+  if (!success) {
+    HandleStartDownloadResponse(client, guid,
+                                DownloadParams::StartResult::INTERNAL_ERROR);
+    return;
+  }
+
+  HandleStartDownloadResponse(client, guid,
+                              DownloadParams::StartResult::ACCEPTED);
+
+  auto* entry = model_->Get(guid);
+  DCHECK(entry);
+  DCHECK_EQ(Entry::State::NEW, entry->state);
+
+  // TODO(dtrainor): Make sure we're running all of the downloads we care about.
+}
+
+void ControllerImpl::OnItemUpdated(bool success,
+                                   DownloadClient client,
+                                   const std::string& guid) {
+  // TODO(dtrainor): Fail and clean up the download if necessary.
+}
+
+void ControllerImpl::OnItemRemoved(bool success,
+                                   DownloadClient client,
+                                   const std::string& guid) {
+  // TODO(dtrainor): Fail and clean up the download if necessary.
+}
+
+void ControllerImpl::AttemptToFinalizeSetup() {
+  if (!startup_status_.Complete())
+    return;
+
+  stats::LogControllerStartupStatus(startup_status_);
+  if (!startup_status_.Ok()) {
+    // TODO(dtrainor): Recover here.  Try to clean up any disk state and, if
+    // possible, any DownloadDriver data and continue with initialization?
+    return;
+  }
+
+  CancelOrphanedRequests();
+  ResolveInitialRequestStates();
+  PullCurrentRequestStatus();
+
+  // TODO(dtrainor): Post this so that the initialization step is finalized
+  // before Clients can take action.
+  NotifyClientsOfStartup();
+}
+
+void ControllerImpl::CancelOrphanedRequests() {
+  auto entries = model_->PeekEntries();
+
+  std::vector<std::string> guids_to_remove;
+  for (auto* entry : entries) {
+    if (!clients_->GetClient(entry->client))
+      guids_to_remove.push_back(entry->guid);
+  }
+
+  for (auto guid : guids_to_remove) {
+    // TODO(dtrainor): Remove the download.
+  }
+}
+
+void ControllerImpl::ResolveInitialRequestStates() {
+  // TODO(dtrainor): Implement.
+}
+
+void ControllerImpl::PullCurrentRequestStatus() {
+  // TODO(dtrainor): Implement.
+}
+
+void ControllerImpl::NotifyClientsOfStartup() {
+  auto categorized = util::MapEntriesToClients(clients_->GetRegisteredClients(),
+                                               model_->PeekEntries());
+
+  for (auto client_id : clients_->GetRegisteredClients()) {
+    clients_->GetClient(client_id)->OnServiceInitialized(
+        categorized[client_id]);
+  }
+}
+
+void ControllerImpl::HandleStartDownloadResponse(
+    DownloadClient client,
+    const std::string& guid,
+    DownloadParams::StartResult result) {
+  auto callback = start_callbacks_[guid];
+  start_callbacks_.erase(guid);
+  HandleStartDownloadResponse(client, guid, result, callback);
+}
+
+void ControllerImpl::HandleStartDownloadResponse(
+    DownloadClient client,
+    const std::string& guid,
+    DownloadParams::StartResult result,
+    const DownloadParams::StartCallback& callback) {
+  stats::LogStartDownloadResult(client, result);
+
+  if (result != DownloadParams::StartResult::ACCEPTED) {
+    // TODO(dtrainor): Clean up any download state.
+  }
+
+  base::ThreadTaskRunnerHandle::Get()->PostTask(
+      FROM_HERE, base::Bind(callback, guid, result));
+}
+
+}  // namespace download
diff --git a/components/download/internal/controller_impl.h b/components/download/internal/controller_impl.h
new file mode 100644
index 0000000..1581737
--- /dev/null
+++ b/components/download/internal/controller_impl.h
@@ -0,0 +1,119 @@
+// 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_DOWNLOAD_INTERNAL_CONTROLLER_IMPL_H_
+#define COMPONENTS_DOWNLOAD_INTERNAL_CONTROLLER_IMPL_H_
+
+#include <map>
+#include <memory>
+
+#include "base/macros.h"
+#include "base/optional.h"
+#include "components/download/internal/controller.h"
+#include "components/download/internal/download_driver.h"
+#include "components/download/internal/model.h"
+#include "components/download/internal/startup_status.h"
+#include "components/download/public/download_params.h"
+
+namespace download {
+
+class ClientSet;
+class DownloadDriver;
+class Model;
+
+struct Configuration;
+struct SchedulingParams;
+
+// The internal Controller implementation.  This class does all of the heavy
+// lifting for the DownloadService.
+class ControllerImpl : public Controller,
+                       public DownloadDriver::Client,
+                       public Model::Client {
+ public:
+  // |clients| is externally owned and must be guaranteed to outlive this class.
+  ControllerImpl(std::unique_ptr<ClientSet> clients,
+                 std::unique_ptr<Configuration> config,
+                 std::unique_ptr<DownloadDriver> driver,
+                 std::unique_ptr<Model> model);
+  ~ControllerImpl() override;
+
+  // Controller implementation.
+  void Initialize() override;
+  const StartupStatus& GetStartupStatus() override;
+  void StartDownload(const DownloadParams& params) override;
+  void PauseDownload(const std::string& guid) override;
+  void ResumeDownload(const std::string& guid) override;
+  void CancelDownload(const std::string& guid) override;
+  void ChangeDownloadCriteria(const std::string& guid,
+                              const SchedulingParams& params) override;
+  DownloadClient GetOwnerOfDownload(const std::string& guid) override;
+
+ private:
+  // DownloadDriver::Client implementation.
+  void OnDriverReady(bool success) override;
+  void OnDownloadCreated(const DriverEntry& download) override;
+  void OnDownloadFailed(const DriverEntry& download, int reason) override;
+  void OnDownloadSucceeded(const DriverEntry& download,
+                           const base::FilePath& path) override;
+  void OnDownloadUpdated(const DriverEntry& download) override;
+
+  // Model::Client implementation.
+  void OnModelReady(bool success) override;
+  void OnItemAdded(bool success,
+                   DownloadClient client,
+                   const std::string& guid) override;
+  void OnItemUpdated(bool success,
+                     DownloadClient client,
+                     const std::string& guid) override;
+  void OnItemRemoved(bool success,
+                     DownloadClient client,
+                     const std::string& guid) override;
+
+  // Checks if initialization is complete and successful.  If so, completes the
+  // internal state initialization.
+  void AttemptToFinalizeSetup();
+
+  // Cancels and cleans upany requests that are no longer associated with a
+  // Client in |clients_|.
+  void CancelOrphanedRequests();
+
+  // Fixes any discrepencies in state between |model_| and |driver_|.  Meant to
+  // resolve state issues during startup.
+  void ResolveInitialRequestStates();
+
+  // Notifies all Client in |clients_| that this controller is initialized and
+  // lets them know which download requests we are aware of for their
+  // DownloadClient.
+  void NotifyClientsOfStartup();
+
+  // Pulls the current state of requests from |model_| and |driver_| and sets
+  // the other internal states appropriately.
+  void PullCurrentRequestStatus();
+
+  void HandleStartDownloadResponse(DownloadClient client,
+                                   const std::string& guid,
+                                   DownloadParams::StartResult result);
+  void HandleStartDownloadResponse(
+      DownloadClient client,
+      const std::string& guid,
+      DownloadParams::StartResult result,
+      const DownloadParams::StartCallback& callback);
+
+  std::unique_ptr<ClientSet> clients_;
+  std::unique_ptr<Configuration> config_;
+
+  // Owned Dependencies.
+  std::unique_ptr<DownloadDriver> driver_;
+  std::unique_ptr<Model> model_;
+
+  // Internal state.
+  StartupStatus startup_status_;
+  std::map<std::string, DownloadParams::StartCallback> start_callbacks_;
+
+  DISALLOW_COPY_AND_ASSIGN(ControllerImpl);
+};
+
+}  // namespace download
+
+#endif  // COMPONENTS_DOWNLOAD_INTERNAL_CONTROLLER_IMPL_H_
diff --git a/components/download/internal/controller_impl_unittest.cc b/components/download/internal/controller_impl_unittest.cc
new file mode 100644
index 0000000..47bf0a27
--- /dev/null
+++ b/components/download/internal/controller_impl_unittest.cc
@@ -0,0 +1,356 @@
+// 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/download/internal/controller_impl.h"
+
+#include <algorithm>
+#include <memory>
+
+#include "base/bind.h"
+#include "base/guid.h"
+#include "base/macros.h"
+#include "base/memory/ptr_util.h"
+#include "base/test/test_simple_task_runner.h"
+#include "base/threading/thread_task_runner_handle.h"
+#include "components/download/internal/client_set.h"
+#include "components/download/internal/config.h"
+#include "components/download/internal/entry.h"
+#include "components/download/internal/model_impl.h"
+#include "components/download/internal/test/entry_utils.h"
+#include "components/download/internal/test/mock_client.h"
+#include "components/download/internal/test/test_download_driver.h"
+#include "components/download/internal/test/test_store.h"
+#include "testing/gmock/include/gmock/gmock.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+using testing::_;
+
+namespace download {
+
+namespace {
+
+class DownloadServiceControllerImplTest : public testing::Test {
+ public:
+  DownloadServiceControllerImplTest()
+      : task_runner_(new base::TestSimpleTaskRunner),
+        handle_(task_runner_),
+        client_(nullptr),
+        driver_(nullptr),
+        store_(nullptr) {
+    start_callback_ =
+        base::Bind(&DownloadServiceControllerImplTest::StartCallback,
+                   base::Unretained(this));
+  }
+  ~DownloadServiceControllerImplTest() override = default;
+
+  void SetUp() override {
+    auto client = base::MakeUnique<test::MockClient>();
+    auto driver = base::MakeUnique<test::TestDownloadDriver>();
+    auto store = base::MakeUnique<test::TestStore>();
+    auto config = base::MakeUnique<Configuration>();
+
+    client_ = client.get();
+    driver_ = driver.get();
+    store_ = store.get();
+    config_ = config.get();
+
+    auto clients = base::MakeUnique<DownloadClientMap>();
+    clients->insert(std::make_pair(DownloadClient::TEST, std::move(client)));
+    auto client_set = base::MakeUnique<ClientSet>(std::move(clients));
+    auto model = base::MakeUnique<ModelImpl>(std::move(store));
+
+    controller_ = base::MakeUnique<ControllerImpl>(
+        std::move(client_set), std::move(config), std::move(driver),
+        std::move(model));
+  }
+
+ protected:
+  DownloadParams MakeDownloadParams() {
+    DownloadParams params;
+    params.client = DownloadClient::TEST;
+    params.guid = base::GenerateGUID();
+    params.callback = start_callback_;
+    return params;
+  }
+
+  MOCK_METHOD2(StartCallback,
+               void(const std::string&, DownloadParams::StartResult));
+
+  scoped_refptr<base::TestSimpleTaskRunner> task_runner_;
+  base::ThreadTaskRunnerHandle handle_;
+
+  std::unique_ptr<ControllerImpl> controller_;
+  Configuration* config_;
+  test::MockClient* client_;
+  test::TestDownloadDriver* driver_;
+  test::TestStore* store_;
+
+  DownloadParams::StartCallback start_callback_;
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(DownloadServiceControllerImplTest);
+};
+
+}  // namespace
+
+TEST_F(DownloadServiceControllerImplTest, SuccessfulInitModelFirst) {
+  EXPECT_CALL(*client_, OnServiceInitialized(_)).Times(0);
+
+  controller_->Initialize();
+  EXPECT_TRUE(store_->init_called());
+  EXPECT_FALSE(controller_->GetStartupStatus().Complete());
+
+  store_->TriggerInit(true, base::MakeUnique<std::vector<Entry>>());
+  EXPECT_FALSE(controller_->GetStartupStatus().Complete());
+  EXPECT_FALSE(controller_->GetStartupStatus().driver_ok.has_value());
+  EXPECT_TRUE(controller_->GetStartupStatus().model_ok.value());
+
+  EXPECT_CALL(*client_, OnServiceInitialized(_)).Times(1);
+
+  driver_->MakeReady();
+  EXPECT_TRUE(controller_->GetStartupStatus().Complete());
+  EXPECT_TRUE(controller_->GetStartupStatus().driver_ok.value());
+  EXPECT_TRUE(controller_->GetStartupStatus().Ok());
+
+  task_runner_->RunUntilIdle();
+}
+
+TEST_F(DownloadServiceControllerImplTest, SuccessfulInitDriverFirst) {
+  EXPECT_CALL(*client_, OnServiceInitialized(_)).Times(0);
+
+  controller_->Initialize();
+  EXPECT_TRUE(store_->init_called());
+  EXPECT_FALSE(controller_->GetStartupStatus().Complete());
+
+  driver_->MakeReady();
+  EXPECT_FALSE(controller_->GetStartupStatus().Complete());
+  EXPECT_FALSE(controller_->GetStartupStatus().model_ok.has_value());
+  EXPECT_TRUE(controller_->GetStartupStatus().driver_ok.value());
+
+  EXPECT_CALL(*client_, OnServiceInitialized(_)).Times(1);
+
+  store_->TriggerInit(true, base::MakeUnique<std::vector<Entry>>());
+  EXPECT_TRUE(controller_->GetStartupStatus().Complete());
+  EXPECT_TRUE(controller_->GetStartupStatus().model_ok.value());
+  EXPECT_TRUE(controller_->GetStartupStatus().Ok());
+
+  task_runner_->RunUntilIdle();
+}
+
+TEST_F(DownloadServiceControllerImplTest, SuccessfulInitWithExistingDownload) {
+  Entry entry1 = test::BuildEntry(DownloadClient::TEST, base::GenerateGUID());
+  Entry entry2 = test::BuildEntry(DownloadClient::TEST, base::GenerateGUID());
+  Entry entry3 =
+      test::BuildEntry(DownloadClient::INVALID, base::GenerateGUID());
+
+  std::vector<Entry> entries = {entry1, entry2, entry3};
+  std::vector<std::string> expected_guids = {entry1.guid, entry2.guid};
+
+  EXPECT_CALL(
+      *client_,
+      OnServiceInitialized(testing::UnorderedElementsAreArray(expected_guids)));
+
+  controller_->Initialize();
+  driver_->MakeReady();
+  store_->TriggerInit(true, base::MakeUnique<std::vector<Entry>>(entries));
+
+  task_runner_->RunUntilIdle();
+}
+
+TEST_F(DownloadServiceControllerImplTest, FailedInitWithBadModel) {
+  EXPECT_CALL(*client_, OnServiceInitialized(_)).Times(0);
+
+  controller_->Initialize();
+  store_->TriggerInit(false, base::MakeUnique<std::vector<Entry>>());
+  driver_->MakeReady();
+
+  task_runner_->RunUntilIdle();
+}
+
+TEST_F(DownloadServiceControllerImplTest, GetOwnerOfDownload) {
+  Entry entry = test::BuildEntry(DownloadClient::TEST, base::GenerateGUID());
+  std::vector<Entry> entries = {entry};
+
+  EXPECT_CALL(*client_, OnServiceInitialized(_)).Times(1);
+
+  controller_->Initialize();
+  driver_->MakeReady();
+  store_->TriggerInit(true, base::MakeUnique<std::vector<Entry>>(entries));
+
+  task_runner_->RunUntilIdle();
+
+  EXPECT_EQ(DownloadClient::TEST, controller_->GetOwnerOfDownload(entry.guid));
+  EXPECT_EQ(DownloadClient::INVALID,
+            controller_->GetOwnerOfDownload(base::GenerateGUID()));
+}
+
+TEST_F(DownloadServiceControllerImplTest, AddDownloadAccepted) {
+  EXPECT_CALL(*client_, OnServiceInitialized(_)).Times(1);
+
+  // Set up the Controller.
+  controller_->Initialize();
+  store_->TriggerInit(true, base::MakeUnique<std::vector<Entry>>());
+  driver_->MakeReady();
+  task_runner_->RunUntilIdle();
+
+  // Trigger the download.
+  DownloadParams params = MakeDownloadParams();
+  EXPECT_CALL(*this,
+              StartCallback(params.guid, DownloadParams::StartResult::ACCEPTED))
+      .Times(1);
+  controller_->StartDownload(params);
+
+  // TODO(dtrainor): Compare the full DownloadParams with the full Entry.
+  store_->TriggerUpdate(true);
+
+  task_runner_->RunUntilIdle();
+}
+
+TEST_F(DownloadServiceControllerImplTest, AddDownloadFailsWithBackoff) {
+  EXPECT_CALL(*client_, OnServiceInitialized(_)).Times(1);
+
+  Entry entry = test::BuildEntry(DownloadClient::TEST, base::GenerateGUID());
+  std::vector<Entry> entries = {entry};
+
+  // Set up the Controller.
+  controller_->Initialize();
+  store_->TriggerInit(true, base::MakeUnique<std::vector<Entry>>(entries));
+  driver_->MakeReady();
+  task_runner_->RunUntilIdle();
+
+  // Set the failure expectations.
+  config_->max_scheduled_downloads = 1U;
+
+  // Trigger the download.
+  DownloadParams params = MakeDownloadParams();
+  EXPECT_CALL(*this,
+              StartCallback(params.guid, DownloadParams::StartResult::BACKOFF))
+      .Times(1);
+  controller_->StartDownload(params);
+
+  EXPECT_TRUE(store_->updated_entries().empty());
+
+  task_runner_->RunUntilIdle();
+}
+
+TEST_F(DownloadServiceControllerImplTest,
+       AddDownloadFailsWithDuplicateGuidInModel) {
+  EXPECT_CALL(*client_, OnServiceInitialized(_)).Times(1);
+
+  Entry entry = test::BuildEntry(DownloadClient::TEST, base::GenerateGUID());
+  std::vector<Entry> entries = {entry};
+
+  // Set up the Controller.
+  controller_->Initialize();
+  store_->TriggerInit(true, base::MakeUnique<std::vector<Entry>>(entries));
+  driver_->MakeReady();
+  task_runner_->RunUntilIdle();
+
+  // Trigger the download.
+  DownloadParams params = MakeDownloadParams();
+  params.guid = entry.guid;
+  EXPECT_CALL(
+      *this,
+      StartCallback(params.guid, DownloadParams::StartResult::UNEXPECTED_GUID))
+      .Times(1);
+  controller_->StartDownload(params);
+
+  EXPECT_TRUE(store_->updated_entries().empty());
+
+  task_runner_->RunUntilIdle();
+}
+
+TEST_F(DownloadServiceControllerImplTest, AddDownloadFailsWithDuplicateCall) {
+  testing::InSequence sequence;
+
+  EXPECT_CALL(*client_, OnServiceInitialized(_)).Times(1);
+
+  // Set up the Controller.
+  controller_->Initialize();
+  store_->TriggerInit(true, base::MakeUnique<std::vector<Entry>>());
+  driver_->MakeReady();
+  task_runner_->RunUntilIdle();
+
+  // Trigger the download twice.
+  DownloadParams params = MakeDownloadParams();
+  EXPECT_CALL(
+      *this,
+      StartCallback(params.guid, DownloadParams::StartResult::UNEXPECTED_GUID))
+      .Times(1);
+  EXPECT_CALL(*this,
+              StartCallback(params.guid, DownloadParams::StartResult::ACCEPTED))
+      .Times(1);
+  controller_->StartDownload(params);
+  controller_->StartDownload(params);
+  store_->TriggerUpdate(true);
+
+  task_runner_->RunUntilIdle();
+}
+
+TEST_F(DownloadServiceControllerImplTest, AddDownloadFailsWithBadClient) {
+  EXPECT_CALL(*client_, OnServiceInitialized(_)).Times(1);
+
+  // Set up the Controller.
+  controller_->Initialize();
+  store_->TriggerInit(true, base::MakeUnique<std::vector<Entry>>());
+  driver_->MakeReady();
+  task_runner_->RunUntilIdle();
+
+  // Trigger the download.
+  DownloadParams params = MakeDownloadParams();
+  params.client = DownloadClient::INVALID;
+  EXPECT_CALL(*this,
+              StartCallback(params.guid,
+                            DownloadParams::StartResult::UNEXPECTED_CLIENT))
+      .Times(1);
+  controller_->StartDownload(params);
+
+  task_runner_->RunUntilIdle();
+}
+
+TEST_F(DownloadServiceControllerImplTest, AddDownloadFailsWithClientCancel) {
+  EXPECT_CALL(*client_, OnServiceInitialized(_)).Times(1);
+
+  // Set up the Controller.
+  controller_->Initialize();
+  store_->TriggerInit(true, base::MakeUnique<std::vector<Entry>>());
+  driver_->MakeReady();
+  task_runner_->RunUntilIdle();
+
+  // Trigger the download.
+  DownloadParams params = MakeDownloadParams();
+  EXPECT_CALL(
+      *this,
+      StartCallback(params.guid, DownloadParams::StartResult::CLIENT_CANCELLED))
+      .Times(1);
+  controller_->StartDownload(params);
+
+  controller_->CancelDownload(params.guid);
+  store_->TriggerUpdate(true);
+
+  task_runner_->RunUntilIdle();
+}
+
+TEST_F(DownloadServiceControllerImplTest, AddDownloadFailsWithInternalError) {
+  EXPECT_CALL(*client_, OnServiceInitialized(_)).Times(1);
+
+  // Set up the Controller.
+  controller_->Initialize();
+  store_->TriggerInit(true, base::MakeUnique<std::vector<Entry>>());
+  driver_->MakeReady();
+  task_runner_->RunUntilIdle();
+
+  // Trigger the download.
+  DownloadParams params = MakeDownloadParams();
+  EXPECT_CALL(*this, StartCallback(params.guid,
+                                   DownloadParams::StartResult::INTERNAL_ERROR))
+      .Times(1);
+  controller_->StartDownload(params);
+
+  store_->TriggerUpdate(false);
+
+  task_runner_->RunUntilIdle();
+}
+
+}  // namespace download
diff --git a/components/download/internal/download_driver.h b/components/download/internal/download_driver.h
index 88247d1..3c83807 100644
--- a/components/download/internal/download_driver.h
+++ b/components/download/internal/download_driver.h
@@ -46,6 +46,8 @@
     virtual void OnDownloadUpdated(const DriverEntry& download) = 0;
   };
 
+  virtual ~DownloadDriver() = default;
+
   // Initialize the driver to receive download updates.
   virtual void Initialize(Client* client) = 0;
 
diff --git a/components/download/internal/download_service_impl.cc b/components/download/internal/download_service_impl.cc
index 44610a9a..e0bbda4 100644
--- a/components/download/internal/download_service_impl.cc
+++ b/components/download/internal/download_service_impl.cc
@@ -4,27 +4,96 @@
 
 #include "components/download/internal/download_service_impl.h"
 
+#include <memory>
+
+#include "base/files/file_path.h"
+#include "base/memory/ptr_util.h"
+#include "components/download/internal/client_set.h"
+#include "components/download/internal/config.h"
+#include "components/download/internal/controller_impl.h"
+#include "components/download/internal/download_driver.h"
+#include "components/download/internal/download_store.h"
+#include "components/download/internal/model_impl.h"
+#include "components/download/internal/proto/entry.pb.h"
+#include "components/download/internal/stats.h"
+#include "components/leveldb_proto/proto_database_impl.h"
+
 namespace download {
+namespace {
+const char kEntryDBStorageDir[] = "EntryDB";
+}  // namespace
 
 // static
 DownloadService* DownloadService::Create(
+    std::unique_ptr<DownloadClientMap> clients,
     const base::FilePath& storage_dir,
     const scoped_refptr<base::SequencedTaskRunner>& background_task_runner) {
-  return new DownloadServiceImpl(Configuration::CreateFromFinch());
+  auto entry_db_storage_dir = storage_dir.AppendASCII(kEntryDBStorageDir);
+  auto entry_db =
+      base::MakeUnique<leveldb_proto::ProtoDatabaseImpl<protodb::Entry>>(
+          background_task_runner);
+
+  auto store = base::MakeUnique<DownloadStore>(entry_db_storage_dir,
+                                               std::move(entry_db));
+  auto client_set = base::MakeUnique<ClientSet>(std::move(clients));
+  auto config = Configuration::CreateFromFinch();
+  auto driver = base::WrapUnique<DownloadDriver>(nullptr);
+  auto model = base::MakeUnique<ModelImpl>(std::move(store));
+
+  std::unique_ptr<Controller> controller =
+      base::MakeUnique<ControllerImpl>(std::move(client_set), std::move(config),
+                                       std::move(driver), std::move(model));
+
+  return new DownloadServiceImpl(std::move(controller));
 }
 
-DownloadServiceImpl::DownloadServiceImpl(std::unique_ptr<Configuration> config)
-    : config_(std::move(config)) {}
+DownloadServiceImpl::DownloadServiceImpl(std::unique_ptr<Controller> controller)
+    : controller_(std::move(controller)) {
+  controller_->Initialize();
+}
 
 DownloadServiceImpl::~DownloadServiceImpl() = default;
 
-void DownloadServiceImpl::StartDownload(const DownloadParams& download_params) {
+DownloadService::ServiceStatus DownloadServiceImpl::GetStatus() {
+  if (!controller_->GetStartupStatus().Complete())
+    return DownloadService::ServiceStatus::STARTING_UP;
+
+  if (!controller_->GetStartupStatus().Ok())
+    return DownloadService::ServiceStatus::UNAVAILABLE;
+
+  return DownloadService::ServiceStatus::READY;
 }
-void DownloadServiceImpl::PauseDownload(const std::string& guid) {}
-void DownloadServiceImpl::ResumeDownload(const std::string& guid) {}
-void DownloadServiceImpl::CancelDownload(const std::string& guid) {}
+
+void DownloadServiceImpl::StartDownload(const DownloadParams& download_params) {
+  stats::LogServiceApiAction(download_params.client,
+                             stats::ServiceApiAction::START_DOWNLOAD);
+  controller_->StartDownload(download_params);
+}
+
+void DownloadServiceImpl::PauseDownload(const std::string& guid) {
+  stats::LogServiceApiAction(controller_->GetOwnerOfDownload(guid),
+                             stats::ServiceApiAction::PAUSE_DOWNLOAD);
+  controller_->PauseDownload(guid);
+}
+
+void DownloadServiceImpl::ResumeDownload(const std::string& guid) {
+  stats::LogServiceApiAction(controller_->GetOwnerOfDownload(guid),
+                             stats::ServiceApiAction::RESUME_DOWNLOAD);
+  controller_->ResumeDownload(guid);
+}
+
+void DownloadServiceImpl::CancelDownload(const std::string& guid) {
+  stats::LogServiceApiAction(controller_->GetOwnerOfDownload(guid),
+                             stats::ServiceApiAction::CANCEL_DOWNLOAD);
+  controller_->CancelDownload(guid);
+}
+
 void DownloadServiceImpl::ChangeDownloadCriteria(
     const std::string& guid,
-    const SchedulingParams& params) {}
+    const SchedulingParams& params) {
+  stats::LogServiceApiAction(controller_->GetOwnerOfDownload(guid),
+                             stats::ServiceApiAction::CHANGE_CRITERIA);
+  controller_->ChangeDownloadCriteria(guid, params);
+}
 
 }  // namespace download
diff --git a/components/download/internal/download_service_impl.h b/components/download/internal/download_service_impl.h
index 319aea1..e9f8e89 100644
--- a/components/download/internal/download_service_impl.h
+++ b/components/download/internal/download_service_impl.h
@@ -9,21 +9,23 @@
 #include <string>
 
 #include "base/macros.h"
-#include "components/download/internal/config.h"
 #include "components/download/public/download_service.h"
 
 namespace download {
 
+class Controller;
+
 struct DownloadParams;
 struct SchedulingParams;
 
 // The internal implementation of the DownloadService.
 class DownloadServiceImpl : public DownloadService {
  public:
-  DownloadServiceImpl(std::unique_ptr<Configuration> config);
+  DownloadServiceImpl(std::unique_ptr<Controller> controller);
   ~DownloadServiceImpl() override;
 
   // DownloadService implementation.
+  ServiceStatus GetStatus() override;
   void StartDownload(const DownloadParams& download_params) override;
   void PauseDownload(const std::string& guid) override;
   void ResumeDownload(const std::string& guid) override;
@@ -32,7 +34,7 @@
                               const SchedulingParams& params) override;
 
  private:
-  std::unique_ptr<Configuration> config_;
+  std::unique_ptr<Controller> controller_;
 
   DISALLOW_COPY_AND_ASSIGN(DownloadServiceImpl);
 };
diff --git a/components/download/internal/download_service_impl_unittest.cc b/components/download/internal/download_service_impl_unittest.cc
new file mode 100644
index 0000000..80f5c6f
--- /dev/null
+++ b/components/download/internal/download_service_impl_unittest.cc
@@ -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.
+
+#include "components/download/internal/download_service_impl.h"
+
+#include "base/macros.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace download {
+namespace {
+
+class DownloadServiceImplTest : public testing::Test {
+ public:
+  DownloadServiceImplTest() {}
+  ~DownloadServiceImplTest() override = default;
+
+  void SetUp() override {}
+
+ protected:
+ private:
+  DISALLOW_COPY_AND_ASSIGN(DownloadServiceImplTest);
+};
+
+}  // namespace
+
+TEST_F(DownloadServiceImplTest, Dummy) {}
+
+}  // namespace download
diff --git a/components/download/internal/download_store.h b/components/download/internal/download_store.h
index e662e80c..0ef08e2 100644
--- a/components/download/internal/download_store.h
+++ b/components/download/internal/download_store.h
@@ -16,8 +16,7 @@
 
 namespace protodb {
 class Entry;
-
-}  // namespace
+}  // namespace protodb
 
 namespace download {
 
diff --git a/components/download/internal/entry.cc b/components/download/internal/entry.cc
index 56d819c3..f68d5bf2 100644
--- a/components/download/internal/entry.cc
+++ b/components/download/internal/entry.cc
@@ -8,6 +8,13 @@
 
 Entry::Entry() = default;
 Entry::Entry(const Entry& other) = default;
+
+Entry::Entry(const DownloadParams& params)
+    : client(params.client),
+      guid(params.guid),
+      scheduling_params(params.scheduling_params),
+      request_params(params.request_params) {}
+
 Entry::~Entry() = default;
 
 }  // namespace download
diff --git a/components/download/internal/entry.h b/components/download/internal/entry.h
index 9ba0c42..7e971c07 100644
--- a/components/download/internal/entry.h
+++ b/components/download/internal/entry.h
@@ -43,6 +43,7 @@
 
   Entry();
   Entry(const Entry& other);
+  explicit Entry(const DownloadParams& params);
   ~Entry();
 
   // The feature that is requesting this download.
diff --git a/components/download/internal/entry_utils.cc b/components/download/internal/entry_utils.cc
new file mode 100644
index 0000000..c5b38aa
--- /dev/null
+++ b/components/download/internal/entry_utils.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 "components/download/internal/entry_utils.h"
+
+#include "components/download/internal/entry.h"
+
+namespace download {
+namespace util {
+
+uint32_t GetNumberOfEntriesForClient(DownloadClient client,
+                                     const std::vector<Entry*>& entries) {
+  uint32_t count = 0;
+  for (auto* entry : entries)
+    if (entry->client == client)
+      count++;
+
+  return count;
+}
+
+std::map<DownloadClient, std::vector<std::string>> MapEntriesToClients(
+    const std::set<DownloadClient>& clients,
+    const std::vector<Entry*>& entries) {
+  std::map<DownloadClient, std::vector<std::string>> categorized;
+
+  for (auto* entry : entries) {
+    DownloadClient client = entry->client;
+    if (clients.find(client) == clients.end())
+      client = DownloadClient::INVALID;
+
+    categorized[client].push_back(entry->guid);
+  }
+
+  return categorized;
+}
+
+}  // namespace util
+}  // namespace download
diff --git a/components/download/internal/entry_utils.h b/components/download/internal/entry_utils.h
new file mode 100644
index 0000000..1d7ac884
--- /dev/null
+++ b/components/download/internal/entry_utils.h
@@ -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.
+
+#ifndef COMPONENTS_DOWNLOAD_INTERNAL_ENTRY_UTILS_H_
+#define COMPONENTS_DOWNLOAD_INTERNAL_ENTRY_UTILS_H_
+
+#include <map>
+#include <set>
+#include <string>
+#include <vector>
+
+#include "components/download/public/clients.h"
+
+namespace download {
+
+struct Entry;
+
+namespace util {
+
+// Helper method to return the number of Entry objects in |entries| are
+// associated with |client|.
+uint32_t GetNumberOfEntriesForClient(DownloadClient client,
+                                     const std::vector<Entry*>& entries);
+
+// Effectively runs a map reduce to turn a list of Entry objects into a map of
+// [Client Id] -> List of entries.  Any Entry in |entries| that does not have a
+// matching DownloadClient in |clients| will be put in the
+// DownloadClient::INVALID bucket.
+std::map<DownloadClient, std::vector<std::string>> MapEntriesToClients(
+    const std::set<DownloadClient>& clients,
+    const std::vector<Entry*>& entries);
+
+}  // namespace util
+}  // namespace download
+
+#endif  // COMPONENTS_DOWNLOAD_INTERNAL_ENTRY_UTILS_H_
diff --git a/components/download/internal/entry_utils_unittest.cc b/components/download/internal/entry_utils_unittest.cc
new file mode 100644
index 0000000..e914ed9
--- /dev/null
+++ b/components/download/internal/entry_utils_unittest.cc
@@ -0,0 +1,65 @@
+// 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/download/internal/entry_utils.h"
+
+#include <algorithm>
+
+#include "base/guid.h"
+#include "base/memory/ptr_util.h"
+#include "components/download/internal/test/entry_utils.h"
+#include "components/download/public/clients.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace download {
+
+TEST(DownloadServiceEntryUtilsTest, TestGetNumberOfEntriesForClient_NoEntries) {
+  Entry entry1 = test::BuildEntry(DownloadClient::TEST, base::GenerateGUID());
+  Entry entry2 = test::BuildEntry(DownloadClient::TEST, base::GenerateGUID());
+  Entry entry3 = test::BuildEntry(DownloadClient::TEST, base::GenerateGUID());
+
+  std::vector<Entry*> entries = {&entry1, &entry2, &entry3};
+
+  EXPECT_EQ(
+      0U, util::GetNumberOfEntriesForClient(DownloadClient::INVALID, entries));
+  EXPECT_EQ(3U,
+            util::GetNumberOfEntriesForClient(DownloadClient::TEST, entries));
+}
+
+TEST(DownloadServiceEntryUtilsTest, MapEntriesToClients) {
+  Entry entry1 = test::BuildEntry(DownloadClient::TEST, base::GenerateGUID());
+  Entry entry2 = test::BuildEntry(DownloadClient::TEST, base::GenerateGUID());
+  Entry entry3 = test::BuildEntry(DownloadClient::TEST, base::GenerateGUID());
+
+  std::vector<Entry*> entries = {&entry1, &entry2, &entry3};
+  std::vector<std::string> expected_list = {entry1.guid, entry2.guid,
+                                            entry3.guid};
+
+  // If DownloadClient::TEST isn't a valid Client, all of the associated entries
+  // should move to the DownloadClient::INVALID bucket.
+  auto mapped1 = util::MapEntriesToClients(std::set<DownloadClient>(), entries);
+  EXPECT_EQ(1U, mapped1.size());
+  EXPECT_NE(mapped1.end(), mapped1.find(DownloadClient::INVALID));
+  EXPECT_EQ(mapped1.end(), mapped1.find(DownloadClient::TEST));
+
+  auto list1 = mapped1.find(DownloadClient::INVALID)->second;
+  EXPECT_EQ(3U, list1.size());
+  EXPECT_TRUE(
+      std::equal(expected_list.begin(), expected_list.end(), list1.begin()));
+
+  // If DownloadClient::TEST is a valid Client, it should have the associated
+  // entries.
+  std::set<DownloadClient> clients = {DownloadClient::TEST};
+  auto mapped2 = util::MapEntriesToClients(clients, entries);
+  EXPECT_EQ(1U, mapped2.size());
+  EXPECT_NE(mapped2.end(), mapped2.find(DownloadClient::TEST));
+  EXPECT_EQ(mapped2.end(), mapped2.find(DownloadClient::INVALID));
+
+  auto list2 = mapped2.find(DownloadClient::TEST)->second;
+  EXPECT_EQ(3U, list2.size());
+  EXPECT_TRUE(
+      std::equal(expected_list.begin(), expected_list.end(), list2.begin()));
+}
+
+}  // namespace download
diff --git a/components/download/internal/model.h b/components/download/internal/model.h
index d7f6d10..d45a2559 100644
--- a/components/download/internal/model.h
+++ b/components/download/internal/model.h
@@ -30,7 +30,7 @@
     // |success| is |false|, initialization of the Model and/or the underlying
     // Store failed.  Initialization of the Model is complete after this
     // callback.  If |success| is true it can be accessed now.
-    virtual void OnInitialized(bool success) = 0;
+    virtual void OnModelReady(bool success) = 0;
 
     // Called when an Entry addition is complete.  |success| determines whether
     // or not the entry has been successfully persisted to the Store.
@@ -57,7 +57,7 @@
 
   // Initializes the Model.  Client::OnInitialized() will be called in response.
   // The Model can be used after that call.
-  virtual void Initialize() = 0;
+  virtual void Initialize(Client* client) = 0;
 
   // Adds |entry| to this Model and attempts to write |entry| to the Store.
   // Client::OnItemAdded() will be called in response asynchronously.
diff --git a/components/download/internal/model_impl.cc b/components/download/internal/model_impl.cc
index 3ab384b..266c086 100644
--- a/components/download/internal/model_impl.cc
+++ b/components/download/internal/model_impl.cc
@@ -7,21 +7,25 @@
 #include "base/bind.h"
 #include "base/memory/ptr_util.h"
 #include "components/download/internal/entry.h"
+#include "components/download/internal/stats.h"
 
 namespace download {
 
-ModelImpl::ModelImpl(Client* client, std::unique_ptr<Store> store)
-    : client_(client), store_(std::move(store)), weak_ptr_factory_(this) {
-  DCHECK(client_);
+ModelImpl::ModelImpl(std::unique_ptr<Store> store)
+    : client_(nullptr), store_(std::move(store)), weak_ptr_factory_(this) {
   DCHECK(store_);
 }
 
 ModelImpl::~ModelImpl() = default;
 
-void ModelImpl::Initialize() {
+void ModelImpl::Initialize(Client* client) {
+  DCHECK(!client_);
+  client_ = client;
+  DCHECK(client_);
+
   DCHECK(!store_->IsInitialized());
-  store_->Initialize(base::BindOnce(&ModelImpl::OnInitializedFinished,
-                                    weak_ptr_factory_.GetWeakPtr()));
+  store_->Initialize(base::Bind(&ModelImpl::OnInitializedFinished,
+                                weak_ptr_factory_.GetWeakPtr()));
 }
 
 void ModelImpl::Add(const Entry& entry) {
@@ -74,20 +78,24 @@
 void ModelImpl::OnInitializedFinished(
     bool success,
     std::unique_ptr<std::vector<Entry>> entries) {
+  stats::LogModelOperationResult(stats::ModelAction::INITIALIZE, success);
+
   if (!success) {
-    client_->OnInitialized(false);
+    client_->OnModelReady(false);
     return;
   }
 
   for (const auto& entry : *entries)
     entries_.emplace(entry.guid, base::MakeUnique<Entry>(entry));
 
-  client_->OnInitialized(true);
+  client_->OnModelReady(true);
 }
 
 void ModelImpl::OnAddFinished(DownloadClient client,
                               const std::string& guid,
                               bool success) {
+  stats::LogModelOperationResult(stats::ModelAction::ADD, success);
+
   // Don't notify the Client if the entry was already removed.
   if (entries_.find(guid) == entries_.end())
     return;
@@ -102,6 +110,8 @@
 void ModelImpl::OnUpdateFinished(DownloadClient client,
                                  const std::string& guid,
                                  bool success) {
+  stats::LogModelOperationResult(stats::ModelAction::UPDATE, success);
+
   // Don't notify the Client if the entry was already removed.
   if (entries_.find(guid) == entries_.end())
     return;
@@ -112,6 +122,8 @@
 void ModelImpl::OnRemoveFinished(DownloadClient client,
                                  const std::string& guid,
                                  bool success) {
+  stats::LogModelOperationResult(stats::ModelAction::REMOVE, success);
+
   DCHECK(entries_.find(guid) == entries_.end());
   client_->OnItemRemoved(success, client, guid);
 }
diff --git a/components/download/internal/model_impl.h b/components/download/internal/model_impl.h
index 3f4d198..bb5fecb 100644
--- a/components/download/internal/model_impl.h
+++ b/components/download/internal/model_impl.h
@@ -23,11 +23,11 @@
 // The internal implementation of Model.
 class ModelImpl : public Model {
  public:
-  ModelImpl(Client* client, std::unique_ptr<Store> store);
+  ModelImpl(std::unique_ptr<Store> store);
   ~ModelImpl() override;
 
   // Model implementation.
-  void Initialize() override;
+  void Initialize(Client* client) override;
   void Add(const Entry& entry) override;
   void Update(const Entry& entry) override;
   void Remove(const std::string& guid) override;
@@ -51,7 +51,7 @@
 
   // The external Model::Client reference that will receive all interesting
   // Model notifications.
-  Client* const client_;
+  Client* client_;
 
   // The backing Store that is responsible for saving and loading the
   // persisted entries.
diff --git a/components/download/internal/model_impl_unittest.cc b/components/download/internal/model_impl_unittest.cc
index c0b3f215..8359cb5 100644
--- a/components/download/internal/model_impl_unittest.cc
+++ b/components/download/internal/model_impl_unittest.cc
@@ -35,7 +35,7 @@
   void SetUp() override {
     auto store = base::MakeUnique<test::TestStore>();
     store_ = store.get();
-    model_ = base::MakeUnique<ModelImpl>(&client_, std::move(store));
+    model_ = base::MakeUnique<ModelImpl>(std::move(store));
   }
 
  protected:
@@ -51,9 +51,9 @@
 
 TEST_F(DownloadServiceModelImplTest, SuccessfulLifecycle) {
   InSequence sequence;
-  EXPECT_CALL(client_, OnInitialized(true)).Times(1);
+  EXPECT_CALL(client_, OnModelReady(true)).Times(1);
 
-  model_->Initialize();
+  model_->Initialize(&client_);
   EXPECT_TRUE(store_->init_called());
   store_->TriggerInit(true, base::MakeUnique<std::vector<Entry>>());
 }
@@ -64,9 +64,9 @@
   std::vector<Entry> entries = {entry1, entry2};
 
   InSequence sequence;
-  EXPECT_CALL(client_, OnInitialized(true)).Times(1);
+  EXPECT_CALL(client_, OnModelReady(true)).Times(1);
 
-  model_->Initialize();
+  model_->Initialize(&client_);
   EXPECT_TRUE(store_->init_called());
   store_->TriggerInit(true, base::MakeUnique<std::vector<Entry>>(entries));
 
@@ -75,9 +75,9 @@
 }
 
 TEST_F(DownloadServiceModelImplTest, BadInit) {
-  EXPECT_CALL(client_, OnInitialized(false)).Times(1);
+  EXPECT_CALL(client_, OnModelReady(false)).Times(1);
 
-  model_->Initialize();
+  model_->Initialize(&client_);
   EXPECT_TRUE(store_->init_called());
   store_->TriggerInit(false, base::MakeUnique<std::vector<Entry>>());
 }
@@ -87,11 +87,11 @@
   Entry entry2 = test::BuildEntry(DownloadClient::TEST, base::GenerateGUID());
 
   InSequence sequence;
-  EXPECT_CALL(client_, OnInitialized(true)).Times(1);
+  EXPECT_CALL(client_, OnModelReady(true)).Times(1);
   EXPECT_CALL(client_, OnItemAdded(true, entry1.client, entry1.guid)).Times(1);
   EXPECT_CALL(client_, OnItemAdded(false, entry2.client, entry2.guid)).Times(1);
 
-  model_->Initialize();
+  model_->Initialize(&client_);
   store_->TriggerInit(true, base::MakeUnique<std::vector<Entry>>());
 
   model_->Add(entry1);
@@ -119,13 +119,13 @@
   std::vector<Entry> entries = {entry1};
 
   InSequence sequence;
-  EXPECT_CALL(client_, OnInitialized(true)).Times(1);
+  EXPECT_CALL(client_, OnModelReady(true)).Times(1);
   EXPECT_CALL(client_, OnItemUpdated(true, entry1.client, entry1.guid))
       .Times(1);
   EXPECT_CALL(client_, OnItemUpdated(false, entry1.client, entry1.guid))
       .Times(1);
 
-  model_->Initialize();
+  model_->Initialize(&client_);
   store_->TriggerInit(true, base::MakeUnique<std::vector<Entry>>(entries));
 
   model_->Update(entry2);
@@ -147,13 +147,13 @@
   std::vector<Entry> entries = {entry1, entry2};
 
   InSequence sequence;
-  EXPECT_CALL(client_, OnInitialized(true)).Times(1);
+  EXPECT_CALL(client_, OnModelReady(true)).Times(1);
   EXPECT_CALL(client_, OnItemRemoved(true, entry1.client, entry1.guid))
       .Times(1);
   EXPECT_CALL(client_, OnItemRemoved(false, entry2.client, entry2.guid))
       .Times(1);
 
-  model_->Initialize();
+  model_->Initialize(&client_);
   store_->TriggerInit(true, base::MakeUnique<std::vector<Entry>>(entries));
 
   model_->Remove(entry1.guid);
@@ -173,9 +173,9 @@
   std::vector<Entry> entries = {entry};
 
   InSequence sequence;
-  EXPECT_CALL(client_, OnInitialized(true)).Times(1);
+  EXPECT_CALL(client_, OnModelReady(true)).Times(1);
 
-  model_->Initialize();
+  model_->Initialize(&client_);
   store_->TriggerInit(true, base::MakeUnique<std::vector<Entry>>(entries));
 
   EXPECT_TRUE(test::CompareEntry(&entry, model_->Get(entry.guid)));
@@ -188,9 +188,9 @@
   std::vector<Entry> entries = {entry1, entry2};
 
   InSequence sequence;
-  EXPECT_CALL(client_, OnInitialized(true)).Times(1);
+  EXPECT_CALL(client_, OnModelReady(true)).Times(1);
 
-  model_->Initialize();
+  model_->Initialize(&client_);
   store_->TriggerInit(true, base::MakeUnique<std::vector<Entry>>(entries));
 
   std::vector<Entry*> expected_peek = {&entry1, &entry2};
@@ -202,11 +202,11 @@
   Entry entry = test::BuildEntry(DownloadClient::TEST, base::GenerateGUID());
 
   InSequence sequence;
-  EXPECT_CALL(client_, OnInitialized(true)).Times(1);
+  EXPECT_CALL(client_, OnModelReady(true)).Times(1);
   EXPECT_CALL(client_, OnItemAdded(_, _, _)).Times(0);
   EXPECT_CALL(client_, OnItemRemoved(true, entry.client, entry.guid)).Times(1);
 
-  model_->Initialize();
+  model_->Initialize(&client_);
   store_->TriggerInit(true, base::MakeUnique<std::vector<Entry>>());
 
   model_->Add(entry);
@@ -228,12 +228,12 @@
   std::vector<Entry> entries = {entry1};
 
   InSequence sequence;
-  EXPECT_CALL(client_, OnInitialized(true)).Times(1);
+  EXPECT_CALL(client_, OnModelReady(true)).Times(1);
   EXPECT_CALL(client_, OnItemUpdated(_, _, _)).Times(0);
   EXPECT_CALL(client_, OnItemRemoved(true, entry1.client, entry1.guid))
       .Times(1);
 
-  model_->Initialize();
+  model_->Initialize(&client_);
   store_->TriggerInit(true, base::MakeUnique<std::vector<Entry>>(entries));
   EXPECT_TRUE(test::CompareEntry(&entry1, model_->Get(entry1.guid)));
 
diff --git a/components/download/internal/startup_status.cc b/components/download/internal/startup_status.cc
new file mode 100644
index 0000000..5531dd6
--- /dev/null
+++ b/components/download/internal/startup_status.cc
@@ -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.
+
+#include "components/download/internal/startup_status.h"
+
+namespace download {
+
+StartupStatus::StartupStatus() = default;
+StartupStatus::~StartupStatus() = default;
+
+bool StartupStatus::Complete() const {
+  return driver_ok.has_value() && model_ok.has_value();
+}
+
+bool StartupStatus::Ok() const {
+  DCHECK(Complete());
+  return driver_ok.value() && model_ok.value();
+}
+
+}  // namespace download
diff --git a/components/download/internal/startup_status.h b/components/download/internal/startup_status.h
new file mode 100644
index 0000000..3e21edf
--- /dev/null
+++ b/components/download/internal/startup_status.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 COMPONENTS_DOWNLOAD_STARTUP_STATUS_H_
+#define COMPONENTS_DOWNLOAD_STARTUP_STATUS_H_
+
+#include "base/macros.h"
+#include "base/optional.h"
+
+namespace download {
+
+// Helper struct to track the initialization status of various Controller
+// internal components.
+struct StartupStatus {
+  StartupStatus();
+  ~StartupStatus();
+
+  base::Optional<bool> driver_ok;
+  base::Optional<bool> model_ok;
+
+  // Whether or not all components have finished initialization.  Note that this
+  // does not mean that all components were initialized successfully.
+  bool Complete() const;
+
+  // Whether or not all components have initialized successfully.  Should only
+  // be called if Complete() is true.
+  bool Ok() const;
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(StartupStatus);
+};
+
+}  // namespace download
+
+#endif  // COMPONENTS_DOWNLOAD_STARTUP_STATUS_H_
diff --git a/components/download/internal/stats.cc b/components/download/internal/stats.cc
new file mode 100644
index 0000000..ac019b7
--- /dev/null
+++ b/components/download/internal/stats.cc
@@ -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.
+
+#include "components/download/internal/stats.h"
+
+#include "components/download/internal/startup_status.h"
+
+namespace download {
+namespace stats {
+
+void LogControllerStartupStatus(const StartupStatus& status) {
+  DCHECK(status.Complete());
+
+  // TODO(dtrainor): Log each failure reason.
+  // TODO(dtrainor): Finally, log SUCCESS or FAILURE based on status.Ok().
+}
+
+void LogServiceApiAction(DownloadClient client, ServiceApiAction action) {
+  // TODO(dtrainor): Log |action| for |client|.
+}
+
+void LogStartDownloadResult(DownloadClient client,
+                            DownloadParams::StartResult result) {
+  // TODO(dtrainor): Log |result| for |client|.
+}
+
+void LogModelOperationResult(ModelAction action, bool success) {
+  // TODO(dtrainor): Log |action|.
+}
+
+}  // namespace stats
+}  // namespace download
diff --git a/components/download/internal/stats.h b/components/download/internal/stats.h
new file mode 100644
index 0000000..5142760
--- /dev/null
+++ b/components/download/internal/stats.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.
+
+#ifndef COMPONENTS_DOWNLOAD_INTERNAL_STATS_H_
+#define COMPONENTS_DOWNLOAD_INTERNAL_STATS_H_
+
+#include "components/download/public/clients.h"
+#include "components/download/public/download_params.h"
+
+namespace download {
+
+struct StartupStatus;
+
+namespace stats {
+
+// Please follow the following rules for all enums:
+// 1. Keep them in sync with the corresponding entry in enums.xml.
+// 2. Treat them as append only.
+// 3. Do not remove any enums.  Only mark them as deprecated.
+
+// Enum used by UMA metrics to track which actions a Client is taking on the
+// service.
+enum class ServiceApiAction {
+  // Represents a call to DownloadService::StartDownload.
+  START_DOWNLOAD = 0,
+
+  // Represents a call to DownloadService::PauseDownload.
+  PAUSE_DOWNLOAD = 1,
+
+  // Represents a call to DownloadService::ResumeDownload.
+  RESUME_DOWNLOAD = 2,
+
+  // Represents a call to DownloadService::CancelDownload.
+  CANCEL_DOWNLOAD = 3,
+
+  // Represents a call to DownloadService::ChangeCriteria.
+  CHANGE_CRITERIA = 4,
+
+  // The last entry for the enum.
+  COUNT = 5,
+};
+
+// Enum used by UMA metrics to tie to specific actions taken on a Model.  This
+// can be used to track failure events.
+enum class ModelAction {
+  // Represents an attempt to initialize the Model.
+  INITIALIZE = 0,
+
+  // Represents an attempt to add an Entry to the Model.
+  ADD = 1,
+
+  // Represents an attempt to update an Entry in the Model.
+  UPDATE = 2,
+
+  // Represents an attempt to remove an Entry from the Model.
+  REMOVE = 3,
+
+  // The last entry for the enum.
+  COUNT = 4,
+};
+
+// Logs the results of starting up the Controller.  Will log each failure reason
+// if |status| contains more than one initialization failure.
+void LogControllerStartupStatus(const StartupStatus& status);
+
+// Logs an action taken on the service API.
+void LogServiceApiAction(DownloadClient client, ServiceApiAction action);
+
+// Logs the result of a StartDownload() attempt on the service.
+void LogStartDownloadResult(DownloadClient client,
+                            DownloadParams::StartResult result);
+
+// Logs statistics about the result of a Model operation.  Used to track failure
+// cases.
+void LogModelOperationResult(ModelAction action, bool success);
+
+}  // namespace stats
+}  // namespace download
+
+#endif  // COMPONENTS_DOWNLOAD_INTERNAL_STATS_H_
diff --git a/components/download/internal/test/BUILD.gn b/components/download/internal/test/BUILD.gn
index 3ee693e..46f1d42 100644
--- a/components/download/internal/test/BUILD.gn
+++ b/components/download/internal/test/BUILD.gn
@@ -8,8 +8,12 @@
   testonly = true
 
   sources = [
+    "empty_client.cc",
+    "empty_client.h",
     "entry_utils.cc",
     "entry_utils.h",
+    "mock_client.cc",
+    "mock_client.h",
     "mock_model_client.cc",
     "mock_model_client.h",
     "noop_store.cc",
diff --git a/components/download/internal/test/empty_client.cc b/components/download/internal/test/empty_client.cc
new file mode 100644
index 0000000..e90db302
--- /dev/null
+++ b/components/download/internal/test/empty_client.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 "components/download/internal/test/empty_client.h"
+
+namespace download {
+namespace test {
+
+void EmptyClient::OnServiceInitialized(
+    const std::vector<std::string>& outstanding_download_guids) {}
+
+Client::ShouldDownload EmptyClient::OnDownloadStarted(
+    const std::string& guid,
+    const std::vector<GURL>& url_chain,
+    const scoped_refptr<const net::HttpResponseHeaders>& headers) {
+  return Client::ShouldDownload::CONTINUE;
+}
+
+void EmptyClient::OnDownloadUpdated(const std::string& guid,
+                                    uint64_t bytes_downloaded) {}
+
+void EmptyClient::OnDownloadFailed(const std::string& guid) {}
+
+void EmptyClient::OnDownloadTimedOut(const std::string& guid) {}
+
+void EmptyClient::OnDownloadAborted(const std::string& guid) {}
+
+void EmptyClient::OnDownloadSucceeded(const std::string& guid,
+                                      const base::FilePath& path,
+                                      uint64_t size) {}
+
+}  // namespace test
+}  // namespace download
diff --git a/components/download/internal/test/empty_client.h b/components/download/internal/test/empty_client.h
new file mode 100644
index 0000000..a855b20
--- /dev/null
+++ b/components/download/internal/test/empty_client.h
@@ -0,0 +1,42 @@
+// 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_DOWNLOAD_INTERNAL_TEST_EMPTY_CLIENT_H_
+#define COMPONENTS_DOWNLOAD_INTERNAL_TEST_EMPTY_CLIENT_H_
+
+#include "base/macros.h"
+#include "components/download/public/client.h"
+
+namespace download {
+namespace test {
+
+class EmptyClient : public Client {
+ public:
+  EmptyClient() = default;
+  ~EmptyClient() override = default;
+
+  // Client implementation.
+  void OnServiceInitialized(
+      const std::vector<std::string>& outstanding_download_guids) override;
+  ShouldDownload OnDownloadStarted(
+      const std::string& guid,
+      const std::vector<GURL>& url_chain,
+      const scoped_refptr<const net::HttpResponseHeaders>& headers) override;
+  void OnDownloadUpdated(const std::string& guid,
+                         uint64_t bytes_downloaded) override;
+  void OnDownloadFailed(const std::string& guid) override;
+  void OnDownloadTimedOut(const std::string& guid) override;
+  void OnDownloadAborted(const std::string& guid) override;
+  void OnDownloadSucceeded(const std::string& guid,
+                           const base::FilePath& path,
+                           uint64_t size) override;
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(EmptyClient);
+};
+
+}  // namespace test
+}  // namespace download
+
+#endif  // COMPONENTS_DOWNLOAD_INTERNAL_TEST_EMPTY_CLIENT_H_
diff --git a/components/download/internal/test/mock_client.cc b/components/download/internal/test/mock_client.cc
new file mode 100644
index 0000000..e520323
--- /dev/null
+++ b/components/download/internal/test/mock_client.cc
@@ -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 "components/download/internal/test/mock_client.h"
+
+namespace download {
+namespace test {
+
+MockClient::MockClient() = default;
+MockClient::~MockClient() = default;
+
+}  // namespace test
+}  // namespace download
diff --git a/components/download/internal/test/mock_client.h b/components/download/internal/test/mock_client.h
new file mode 100644
index 0000000..442e29e
--- /dev/null
+++ b/components/download/internal/test/mock_client.h
@@ -0,0 +1,41 @@
+// 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_DOWNLOAD_INTERNAL_TEST_MOCK_CLIENT_H_
+#define COMPONENTS_DOWNLOAD_INTERNAL_TEST_MOCK_CLIENT_H_
+
+#include "base/macros.h"
+#include "components/download/public/client.h"
+#include "testing/gmock/include/gmock/gmock.h"
+
+namespace download {
+namespace test {
+
+class MockClient : public Client {
+ public:
+  MockClient();
+  ~MockClient() override;
+
+  // Client implementation.
+  MOCK_METHOD1(OnServiceInitialized, void(const std::vector<std::string>&));
+  MOCK_METHOD3(
+      OnDownloadStarted,
+      ShouldDownload(const std::string&,
+                     const std::vector<GURL>&,
+                     const scoped_refptr<const net::HttpResponseHeaders>&));
+  MOCK_METHOD2(OnDownloadUpdated, void(const std::string&, uint64_t));
+  MOCK_METHOD1(OnDownloadFailed, void(const std::string&));
+  MOCK_METHOD1(OnDownloadTimedOut, void(const std::string&));
+  MOCK_METHOD1(OnDownloadAborted, void(const std::string&));
+  MOCK_METHOD3(OnDownloadSucceeded,
+               void(const std::string&, const base::FilePath&, uint64_t));
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(MockClient);
+};
+
+}  // namespace test
+}  // namespace download
+
+#endif  // COMPONENTS_DOWNLOAD_INTERNAL_TEST_MOCK_CLIENT_H_
diff --git a/components/download/internal/test/mock_model_client.h b/components/download/internal/test/mock_model_client.h
index cd9a7f8..c1ca11b 100644
--- a/components/download/internal/test/mock_model_client.h
+++ b/components/download/internal/test/mock_model_client.h
@@ -19,7 +19,7 @@
   ~MockModelClient() override;
 
   // Model::Client implementation.
-  MOCK_METHOD1(OnInitialized, void(bool));
+  MOCK_METHOD1(OnModelReady, void(bool));
   MOCK_METHOD3(OnItemAdded, void(bool, DownloadClient, const std::string&));
   MOCK_METHOD3(OnItemUpdated, void(bool, DownloadClient, const std::string&));
   MOCK_METHOD3(OnItemRemoved, void(bool, DownloadClient, const std::string&));
diff --git a/components/download/internal/test/test_download_driver.cc b/components/download/internal/test/test_download_driver.cc
index 78de8d77..3f67629 100644
--- a/components/download/internal/test/test_download_driver.cc
+++ b/components/download/internal/test/test_download_driver.cc
@@ -9,6 +9,7 @@
 #include "net/http/http_response_headers.h"
 
 namespace download {
+namespace test {
 
 TestDownloadDriver::TestDownloadDriver() : is_ready_(false), client_(nullptr) {}
 
@@ -81,4 +82,5 @@
   return it->second;
 }
 
-}  // namespace downloads
+}  // namespace test
+}  // namespace download
diff --git a/components/download/internal/test/test_download_driver.h b/components/download/internal/test/test_download_driver.h
index 0ee9f3d..010777a 100644
--- a/components/download/internal/test/test_download_driver.h
+++ b/components/download/internal/test/test_download_driver.h
@@ -12,12 +12,13 @@
 #include "components/download/internal/download_driver.h"
 
 namespace download {
+namespace test {
 
 // Download driver that simulates content layer download logic.
 class TestDownloadDriver : public DownloadDriver {
  public:
   TestDownloadDriver();
-  ~TestDownloadDriver();
+  ~TestDownloadDriver() override;
 
   // Marks download driver as ready, used to test logic that depends on
   // data initialization.
@@ -48,6 +49,7 @@
   DISALLOW_COPY_AND_ASSIGN(TestDownloadDriver);
 };
 
+}  // namespace test
 }  // namespace download
 
 #endif  // COMPONENTS_DOWNLOAD_CONTENT_TEST_TEST_DOWNLOAD_DRIVER_H_
diff --git a/components/download/public/clients.h b/components/download/public/clients.h
index a464d212..36665b6 100644
--- a/components/download/public/clients.h
+++ b/components/download/public/clients.h
@@ -5,6 +5,11 @@
 #ifndef COMPONENTS_DOWNLOAD_PUBLIC_CLIENTS_H_
 #define COMPONENTS_DOWNLOAD_PUBLIC_CLIENTS_H_
 
+#include <map>
+#include <memory>
+
+#include "components/download/public/client.h"
+
 namespace download {
 
 // A list of all clients that are able to make download requests through the
@@ -28,6 +33,8 @@
   BOUNDARY = 3,
 };
 
+using DownloadClientMap = std::map<DownloadClient, std::unique_ptr<Client>>;
+
 }  // namespace download
 
 #endif  // COMPONENTS_DOWNLOAD_PUBLIC_CLIENTS_H_
diff --git a/components/download/public/download_params.h b/components/download/public/download_params.h
index dcf25b4..e9885e9 100644
--- a/components/download/public/download_params.h
+++ b/components/download/public/download_params.h
@@ -102,12 +102,25 @@
     // The DownloadService has too many downloads.  Backoff and retry.
     BACKOFF,
 
-    // Failed to create the download.  Invalid input parameters.
-    BAD_PARAMETERS,
+    // The DownloadService has no knowledge of the DownloadClient associated
+    // with this request.
+    UNEXPECTED_CLIENT,
+
+    // Failed to create the download.  The guid is already in use.
+    UNEXPECTED_GUID,
+
+    // The download was cancelled by the Client while it was being persisted.
+    CLIENT_CANCELLED,
+
+    // The DownloadService was unable to accept and persist this download due to
+    // an internal error like the underlying DB store failing to write to disk.
+    INTERNAL_ERROR,
 
     // TODO(dtrainor): Add more error codes.
   };
 
+  using StartCallback = base::Callback<void(const std::string&, StartResult)>;
+
   DownloadParams();
   DownloadParams(const DownloadParams& other);
   ~DownloadParams();
@@ -120,7 +133,7 @@
 
   // A callback that will be notified if this download has been accepted and
   // persisted by the DownloadService.
-  base::Callback<void(const DownloadParams&, StartResult)> callback;
+  StartCallback callback;
 
   // The parameters that determine under what device conditions this download
   // will occur.
diff --git a/components/download/public/download_service.h b/components/download/public/download_service.h
index f0733de..82a6076 100644
--- a/components/download/public/download_service.h
+++ b/components/download/public/download_service.h
@@ -5,6 +5,7 @@
 #ifndef COMPONENTS_DOWNLOAD_PUBLIC_DOWNLOAD_SERVICE_H_
 #define COMPONENTS_DOWNLOAD_PUBLIC_DOWNLOAD_SERVICE_H_
 
+#include <memory>
 #include <string>
 
 #include "base/files/file_path.h"
@@ -12,10 +13,12 @@
 #include "base/memory/ptr_util.h"
 #include "base/memory/ref_counted.h"
 #include "base/sequenced_task_runner.h"
+#include "components/download/public/clients.h"
 #include "components/keyed_service/core/keyed_service.h"
 
 namespace download {
 
+class Client;
 struct DownloadParams;
 struct SchedulingParams;
 
@@ -29,6 +32,25 @@
 // a process restart.
 class DownloadService : public KeyedService {
  public:
+  // The current status of the Service.
+  enum class ServiceStatus {
+    // The service is in the process of initializing and should not be used yet.
+    // All registered Clients will be notified via
+    // Client::OnServiceInitialized() once the service is ready.
+    STARTING_UP = 0,
+
+    // The service is ready and available for use.
+    READY = 1,
+
+    // The service is unavailable.  This is typically due to an unrecoverable
+    // error on some internal component like the persistence layer.
+    UNAVAILABLE = 2,
+  };
+
+  // |clients| is a map of DownloadClient -> std::unique_ptr<Client>.  This
+  // represents all of the clients that are allowed to have requests made on
+  // their behalf.  This cannot be changed after startup.  Any existing requests
+  // no longer associated with a client will be cancelled.
   // |storage_dir| is a path to where all the local storage will be.  This will
   // hold the internal database as well as any temporary files on disk.  If this
   // is an empty path, the service will not persist any information to disk and
@@ -36,9 +58,14 @@
   // restarts, no files written on completion, etc.).
   // |background_task_runner| will be used for all disk reads and writes.
   static DownloadService* Create(
+      std::unique_ptr<DownloadClientMap> clients,
       const base::FilePath& storage_dir,
       const scoped_refptr<base::SequencedTaskRunner>& background_task_runner);
 
+  // Whether or not the DownloadService is currently available, initialized
+  // successfully, and ready to be used.
+  virtual ServiceStatus GetStatus() = 0;
+
   // Sends the download to the service.  A callback to
   // |DownloadParams::callback| will be triggered once the download has been
   // persisted and saved in the service
diff --git a/components/exo/pointer_unittest.cc b/components/exo/pointer_unittest.cc
index 6df66bcc..1831ec5c 100644
--- a/components/exo/pointer_unittest.cc
+++ b/components/exo/pointer_unittest.cc
@@ -446,5 +446,34 @@
   pointer.reset();
 }
 
+TEST_F(PointerTest, OnPointerInStylusOnlyWindow) {
+  std::unique_ptr<Surface> surface(new Surface);
+  std::unique_ptr<ShellSurface> shell_surface(new ShellSurface(surface.get()));
+  gfx::Size buffer_size(10, 10);
+  std::unique_ptr<Buffer> buffer(
+      new Buffer(exo_test_helper()->CreateGpuMemoryBuffer(buffer_size)));
+  surface->Attach(buffer.get());
+  surface->SetStylusOnly();
+  surface->Commit();
+
+  MockPointerDelegate delegate;
+  std::unique_ptr<Pointer> pointer(new Pointer(&delegate));
+  ui::test::EventGenerator generator(ash::Shell::GetPrimaryRootWindow());
+
+  EXPECT_CALL(delegate, CanAcceptPointerEventsForSurface(surface.get()))
+      .WillRepeatedly(testing::Return(true));
+
+  EXPECT_CALL(delegate, OnPointerFrame()).Times(0);
+  EXPECT_CALL(delegate, OnPointerEnter(surface.get(), testing::_, 0)).Times(0);
+  EXPECT_CALL(delegate, OnPointerButton(testing::_, testing::_, testing::_))
+      .Times(0);
+
+  generator.MoveMouseTo(surface->window()->GetBoundsInScreen().origin());
+  generator.ClickLeftButton();
+
+  EXPECT_CALL(delegate, OnPointerDestroying(pointer.get()));
+  pointer.reset();
+}
+
 }  // namespace
 }  // namespace exo
diff --git a/components/exo/shell_surface.cc b/components/exo/shell_surface.cc
index 1ece422..534e506a 100644
--- a/components/exo/shell_surface.cc
+++ b/components/exo/shell_surface.cc
@@ -150,7 +150,10 @@
           return shadow_underlay;
       }
     }
-    return aura::WindowTargeter::FindTargetForEvent(root, event);
+    ui::EventTarget* target =
+        aura::WindowTargeter::FindTargetForEvent(root, event);
+    // Do not accept events in ShellSurface window.
+    return target != root ? target : nullptr;
   }
 
  private:
diff --git a/components/exo/shell_surface_unittest.cc b/components/exo/shell_surface_unittest.cc
index 338210a..cc402b6 100644
--- a/components/exo/shell_surface_unittest.cc
+++ b/components/exo/shell_surface_unittest.cc
@@ -15,7 +15,6 @@
 #include "ash/wm/window_state.h"
 #include "ash/wm/wm_event.h"
 #include "ash/wm/workspace/workspace_window_resizer.h"
-#include "ash/wm_window.h"
 #include "base/message_loop/message_loop.h"
 #include "base/strings/utf_string_conversions.h"
 #include "components/exo/buffer.h"
@@ -872,17 +871,16 @@
             shell_surface->GetWidget()->GetWindowBoundsInScreen().width());
 
   ash::wm::WMEvent event(ash::wm::WM_EVENT_TOGGLE_FULLSCREEN);
-  ash::WmWindow* window =
-      ash::WmWindow::Get(shell_surface->GetWidget()->GetNativeWindow());
+  aura::Window* window = shell_surface->GetWidget()->GetNativeWindow();
 
   // Enter fullscreen mode.
-  window->GetWindowState()->OnWMEvent(&event);
+  ash::wm::GetWindowState(window)->OnWMEvent(&event);
 
   EXPECT_EQ(CurrentContext()->bounds().ToString(),
             shell_surface->GetWidget()->GetWindowBoundsInScreen().ToString());
 
   // Leave fullscreen mode.
-  window->GetWindowState()->OnWMEvent(&event);
+  ash::wm::GetWindowState(window)->OnWMEvent(&event);
 
   // Check that shell surface is maximized.
   EXPECT_EQ(CurrentContext()->bounds().width(),
@@ -919,26 +917,25 @@
   EXPECT_FALSE(test_helper.GetBackdropWindow());
 
   ash::wm::WMEvent fullscreen_event(ash::wm::WM_EVENT_TOGGLE_FULLSCREEN);
-  ash::WmWindow* window =
-      ash::WmWindow::Get(shell_surface->GetWidget()->GetNativeWindow());
+  aura::Window* window = shell_surface->GetWidget()->GetNativeWindow();
 
   // Enter immersive fullscreen mode. Shadow underlay is fullscreen.
-  window->GetWindowState()->OnWMEvent(&fullscreen_event);
+  ash::wm::GetWindowState(window)->OnWMEvent(&fullscreen_event);
 
   EXPECT_TRUE(test_helper.GetBackdropWindow());
 
   // Leave fullscreen mode. Shadow underlay is restored.
-  window->GetWindowState()->OnWMEvent(&fullscreen_event);
+  ash::wm::GetWindowState(window)->OnWMEvent(&fullscreen_event);
   EXPECT_FALSE(test_helper.GetBackdropWindow());
 
   ash::wm::WMEvent maximize_event(ash::wm::WM_EVENT_TOGGLE_MAXIMIZE);
 
   // Enter maximized mode.
-  window->GetWindowState()->OnWMEvent(&maximize_event);
+  ash::wm::GetWindowState(window)->OnWMEvent(&maximize_event);
   EXPECT_TRUE(test_helper.GetBackdropWindow());
 
   // Leave maximized mode.
-  window->GetWindowState()->OnWMEvent(&maximize_event);
+  ash::wm::GetWindowState(window)->OnWMEvent(&maximize_event);
   EXPECT_FALSE(test_helper.GetBackdropWindow());
 }
 
@@ -973,9 +970,8 @@
             shell_surface->surface_for_testing()->window()->bounds().size());
 
   ash::wm::WMEvent minimize_event(ash::wm::WM_EVENT_MINIMIZE);
-  ash::WmWindow* window =
-      ash::WmWindow::Get(shell_surface->GetWidget()->GetNativeWindow());
-  window->GetWindowState()->OnWMEvent(&minimize_event);
+  aura::Window* window = shell_surface->GetWidget()->GetNativeWindow();
+  ash::wm::GetWindowState(window)->OnWMEvent(&minimize_event);
 }
 
 }  // namespace
diff --git a/components/exo/surface.cc b/components/exo/surface.cc
index 301b8d96..771e0aa 100644
--- a/components/exo/surface.cc
+++ b/components/exo/surface.cc
@@ -145,6 +145,24 @@
   ~CustomWindowTargeter() override {}
 
   // Overridden from aura::WindowTargeter:
+  bool SubtreeCanAcceptEvent(aura::Window* window,
+                             const ui::LocatedEvent& event) const override {
+    Surface* surface = Surface::AsSurface(window);
+    if (!surface)
+      return false;
+
+    if (surface->IsStylusOnly()) {
+      ui::EventPointerType type = ui::EventPointerType::POINTER_TYPE_UNKNOWN;
+      if (event.IsTouchEvent()) {
+        auto* touch_event = static_cast<const ui::TouchEvent*>(&event);
+        type = touch_event->pointer_details().pointer_type;
+      }
+      if (type != ui::EventPointerType::POINTER_TYPE_PEN)
+        return false;
+    }
+    return aura::WindowTargeter::SubtreeCanAcceptEvent(window, event);
+  }
+
   bool EventLocationInsideBounds(aura::Window* window,
                                  const ui::LocatedEvent& event) const override {
     Surface* surface = Surface::AsSurface(window);
diff --git a/components/exo/touch_unittest.cc b/components/exo/touch_unittest.cc
index 665b2701..743461d1 100644
--- a/components/exo/touch_unittest.cc
+++ b/components/exo/touch_unittest.cc
@@ -9,7 +9,6 @@
 #include "ash/shell_port.h"
 #include "ash/wm/window_positioner.h"
 #include "ash/wm/window_positioning_utils.h"
-#include "ash/wm_window.h"
 #include "components/exo/buffer.h"
 #include "components/exo/shell_surface.h"
 #include "components/exo/surface.h"
@@ -399,5 +398,30 @@
   touch.reset();
 }
 
+TEST_F(TouchTest, OnTouchInStylusOnlyWindow) {
+  auto window = exo_test_helper()->CreateWindow(10, 10, true);
+  window.surface()->SetStylusOnly();
+
+  MockTouchDelegate delegate;
+  std::unique_ptr<Touch> touch(new Touch(&delegate));
+  ui::test::EventGenerator generator(ash::Shell::GetPrimaryRootWindow());
+
+  EXPECT_CALL(delegate, CanAcceptTouchEventsForSurface(window.surface()))
+      .WillRepeatedly(testing::Return(true));
+
+  EXPECT_CALL(delegate,
+              OnTouchDown(window.surface(), testing::_, testing::_, testing::_))
+      .Times(0);
+  EXPECT_CALL(delegate, OnTouchMotion(testing::_, testing::_, testing::_))
+      .Times(0);
+  EXPECT_CALL(delegate, OnTouchUp(testing::_, testing::_)).Times(0);
+  EXPECT_CALL(delegate, OnTouchFrame()).Times(0);
+  generator.set_current_location(window.origin());
+  generator.PressMoveAndReleaseTouchBy(5, 5);
+
+  EXPECT_CALL(delegate, OnTouchDestroying(touch.get()));
+  touch.reset();
+}
+
 }  // namespace
 }  // namespace exo
diff --git a/components/gcm_driver/gcm_client_impl.cc b/components/gcm_driver/gcm_client_impl.cc
index a0b30d5f9c..8754ba2 100644
--- a/components/gcm_driver/gcm_client_impl.cc
+++ b/components/gcm_driver/gcm_client_impl.cc
@@ -325,7 +325,11 @@
       url_request_context_getter_->GetURLRequestContext()->
           GetNetworkSessionParams();
   DCHECK(network_session_params);
-  network_session_.reset(new net::HttpNetworkSession(*network_session_params));
+  const net::HttpNetworkSession::Context* network_session_context =
+      url_request_context_getter_->GetURLRequestContext()
+          ->GetNetworkSessionContext();
+  network_session_.reset(new net::HttpNetworkSession(*network_session_params,
+                                                     *network_session_context));
 
   chrome_build_info_ = chrome_build_info;
 
diff --git a/components/offline_pages/core/archive_manager.cc b/components/offline_pages/core/archive_manager.cc
index cd817767..a397648f 100644
--- a/components/offline_pages/core/archive_manager.cc
+++ b/components/offline_pages/core/archive_manager.cc
@@ -2,6 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
+#include "components/offline_pages/core/archive_manager.h"
+
 #include "base/bind.h"
 #include "base/callback.h"
 #include "base/files/file_enumerator.h"
@@ -11,8 +13,8 @@
 #include "base/memory/ref_counted.h"
 #include "base/sequenced_task_runner.h"
 #include "base/sys_info.h"
+#include "base/task_runner_util.h"
 #include "base/threading/thread_task_runner_handle.h"
-#include "components/offline_pages/core/archive_manager.h"
 
 namespace offline_pages {
 
@@ -21,8 +23,13 @@
 using StorageStatsCallback =
     base::Callback<void(const ArchiveManager::StorageStats& storage_stats)>;
 
-void EnsureArchivesDirCreatedImpl(const base::FilePath& archives_dir) {
-  CHECK(base::CreateDirectory(archives_dir));
+ArchiveManager::ArchivesDirCreationResult EnsureArchivesDirCreatedImpl(
+    const base::FilePath& archives_dir) {
+  if (base::PathExists(archives_dir))
+    return ArchiveManager::ArchivesDirCreationResult::ALREADY_EXISTS;
+  if (base::CreateDirectory(archives_dir))
+    return ArchiveManager::ArchivesDirCreationResult::SUCCESS;
+  return ArchiveManager::ArchivesDirCreationResult::FAILURE;
 }
 
 void ExistsArchiveImpl(const base::FilePath& file_path,
@@ -79,10 +86,11 @@
 
 ArchiveManager::~ArchiveManager() {}
 
-void ArchiveManager::EnsureArchivesDirCreated(const base::Closure& callback) {
-  task_runner_->PostTaskAndReply(
-      FROM_HERE, base::Bind(EnsureArchivesDirCreatedImpl, archives_dir_),
-      callback);
+void ArchiveManager::EnsureArchivesDirCreated(
+    const base::Callback<void(ArchivesDirCreationResult)>& callback) {
+  base::PostTaskAndReplyWithResult(
+      task_runner_.get(), FROM_HERE,
+      base::Bind(EnsureArchivesDirCreatedImpl, archives_dir_), callback);
 }
 
 void ArchiveManager::ExistsArchive(const base::FilePath& archive_path,
diff --git a/components/offline_pages/core/archive_manager.h b/components/offline_pages/core/archive_manager.h
index dc92e7d..f4c823e2 100644
--- a/components/offline_pages/core/archive_manager.h
+++ b/components/offline_pages/core/archive_manager.h
@@ -28,12 +28,19 @@
     int64_t total_archives_size;
   };
 
+  enum class ArchivesDirCreationResult {
+    SUCCESS,
+    ALREADY_EXISTS,
+    FAILURE,
+  };
+
   ArchiveManager(const base::FilePath& archives_dir,
                  const scoped_refptr<base::SequencedTaskRunner>& task_runner);
   virtual ~ArchiveManager();
 
   // Creates archives directory if one does not exist yet;
-  virtual void EnsureArchivesDirCreated(const base::Closure& callback);
+  virtual void EnsureArchivesDirCreated(
+      const base::Callback<void(ArchivesDirCreationResult)>& callback);
 
   // Checks whether an archive with specified |archive_path| exists.
   virtual void ExistsArchive(const base::FilePath& archive_path,
diff --git a/components/offline_pages/core/archive_manager_unittest.cc b/components/offline_pages/core/archive_manager_unittest.cc
index 57f868a8..d3c949ea 100644
--- a/components/offline_pages/core/archive_manager_unittest.cc
+++ b/components/offline_pages/core/archive_manager_unittest.cc
@@ -43,10 +43,15 @@
   void GetAllArchivesCallback(const std::set<base::FilePath>& archive_paths);
   void GetStorageStatsCallback(
       const ArchiveManager::StorageStats& storage_sizes);
+  void ArchivesDirCreationCallback(
+      ArchiveManager::ArchivesDirCreationResult result);
 
   ArchiveManager* manager() { return manager_.get(); }
   const base::FilePath& temp_path() const { return temp_dir_.GetPath(); }
   CallbackStatus callback_status() const { return callback_status_; }
+  ArchiveManager::ArchivesDirCreationResult creation_result() const {
+    return creation_result_;
+  }
   const std::set<base::FilePath>& last_archive_paths() const {
     return last_archvie_paths_;
   }
@@ -61,6 +66,7 @@
 
   std::unique_ptr<ArchiveManager> manager_;
   CallbackStatus callback_status_;
+  ArchiveManager::ArchivesDirCreationResult creation_result_;
   std::set<base::FilePath> last_archvie_paths_;
   ArchiveManager::StorageStats last_storage_sizes_;
 };
@@ -105,6 +111,11 @@
   last_storage_sizes_ = storage_sizes;
 }
 
+void ArchiveManagerTest::ArchivesDirCreationCallback(
+    ArchiveManager::ArchivesDirCreationResult result) {
+  creation_result_ = result;
+}
+
 TEST_F(ArchiveManagerTest, EnsureArchivesDirCreated) {
   base::FilePath archive_dir =
       temp_path().Append(FILE_PATH_LITERAL("test_path"));
@@ -113,17 +124,21 @@
 
   // Ensure archives dir exists, when it doesn't.
   manager()->EnsureArchivesDirCreated(
-      base::Bind(&ArchiveManagerTest::Callback, base::Unretained(this), true));
+      base::Bind(&ArchiveManagerTest::ArchivesDirCreationCallback,
+                 base::Unretained(this)));
   PumpLoop();
-  EXPECT_EQ(CallbackStatus::CALLED_TRUE, callback_status());
+  EXPECT_EQ(ArchiveManager::ArchivesDirCreationResult::SUCCESS,
+            creation_result());
   EXPECT_TRUE(base::PathExists(archive_dir));
 
   // Try again when the file already exists.
   ResetResults();
   manager()->EnsureArchivesDirCreated(
-      base::Bind(&ArchiveManagerTest::Callback, base::Unretained(this), true));
+      base::Bind(&ArchiveManagerTest::ArchivesDirCreationCallback,
+                 base::Unretained(this)));
   PumpLoop();
-  EXPECT_EQ(CallbackStatus::CALLED_TRUE, callback_status());
+  EXPECT_EQ(ArchiveManager::ArchivesDirCreationResult::ALREADY_EXISTS,
+            creation_result());
   EXPECT_TRUE(base::PathExists(archive_dir));
 }
 
diff --git a/components/offline_pages/core/offline_page_model_impl.cc b/components/offline_pages/core/offline_page_model_impl.cc
index 0030051..e9ba89b 100644
--- a/components/offline_pages/core/offline_page_model_impl.cc
+++ b/components/offline_pages/core/offline_page_model_impl.cc
@@ -8,6 +8,7 @@
 #include <limits>
 
 #include "base/bind.h"
+#include "base/bind_helpers.h"
 #include "base/files/file_util.h"
 #include "base/location.h"
 #include "base/logging.h"
@@ -325,9 +326,10 @@
       archive_manager_(new ArchiveManager(archives_dir, task_runner)),
       testing_clock_(nullptr),
       weak_ptr_factory_(this) {
-  archive_manager_->EnsureArchivesDirCreated(
-      base::Bind(&OfflinePageModelImpl::OnEnsureArchivesDirCreatedDone,
-                 weak_ptr_factory_.GetWeakPtr(), base::TimeTicks::Now()));
+  const int kResetAttemptsLeft = 1;
+  store_->Initialize(base::Bind(&OfflinePageModelImpl::OnStoreInitialized,
+                                weak_ptr_factory_.GetWeakPtr(),
+                                base::TimeTicks::Now(), kResetAttemptsLeft));
 }
 
 OfflinePageModelImpl::~OfflinePageModelImpl() {}
@@ -361,6 +363,38 @@
     return;
   }
 
+  archive_manager_->EnsureArchivesDirCreated(base::Bind(
+      &OfflinePageModelImpl::ContinueSavingPageWithArchivesDir,
+      weak_ptr_factory_.GetWeakPtr(), save_page_params,
+      base::Passed(std::move(archiver)), callback, base::TimeTicks::Now()));
+}
+
+void OfflinePageModelImpl::ContinueSavingPageWithArchivesDir(
+    const SavePageParams& save_page_params,
+    std::unique_ptr<OfflinePageArchiver> archiver,
+    const SavePageCallback& callback,
+    const base::TimeTicks& start_time,
+    ArchiveManager::ArchivesDirCreationResult result) {
+  // Since the archive folder might be missing when saving a page (especially
+  // temporary pages if they live in cache directory which is vulnerable to
+  // 'clear cache' actions). After the attempt to create the archive directory,
+  // as long as the result of creation is not ALREADY_EXISTS, we need to start
+  // a consistency check for saved pages.
+  // This is going to be primarily applicable when we start to use cache
+  // directory for temporary pages.
+  if (result != ArchiveManager::ArchivesDirCreationResult::ALREADY_EXISTS)
+    CheckMetadataConsistency();
+
+  if (result == ArchiveManager::ArchivesDirCreationResult::SUCCESS) {
+    UMA_HISTOGRAM_TIMES("OfflinePages.Model.ArchiveDirCreationTime",
+                        base::TimeTicks::Now() - start_time);
+  }
+  if (result == ArchiveManager::ArchivesDirCreationResult::FAILURE) {
+    InformSavePageDone(callback, SavePageResult::ARCHIVE_DIR_MISSING,
+                       save_page_params.client_id, kInvalidOfflineId);
+    return;
+  }
+
   // If we already have an offline id, use it.  If not, generate one.
   int64_t offline_id = save_page_params.proposed_offline_id;
   if (offline_id == kInvalidOfflineId)
@@ -773,17 +807,6 @@
   // should not have any impact to the UI.
 }
 
-void OfflinePageModelImpl::OnEnsureArchivesDirCreatedDone(
-    const base::TimeTicks& start_time) {
-  UMA_HISTOGRAM_TIMES("OfflinePages.Model.ArchiveDirCreationTime",
-                      base::TimeTicks::Now() - start_time);
-
-  const int kResetAttemptsLeft = 1;
-  store_->Initialize(base::Bind(&OfflinePageModelImpl::OnStoreInitialized,
-                                weak_ptr_factory_.GetWeakPtr(), start_time,
-                                kResetAttemptsLeft));
-}
-
 void OfflinePageModelImpl::OnStoreInitialized(const base::TimeTicks& start_time,
                                               int reset_attempts_left,
                                               bool success) {
diff --git a/components/offline_pages/core/offline_page_model_impl.h b/components/offline_pages/core/offline_page_model_impl.h
index 64e2e3c..86559824 100644
--- a/components/offline_pages/core/offline_page_model_impl.h
+++ b/components/offline_pages/core/offline_page_model_impl.h
@@ -120,8 +120,13 @@
 
   typedef std::vector<std::unique_ptr<OfflinePageArchiver>> PendingArchivers;
 
-  // Callback for ensuring archive directory is created.
-  void OnEnsureArchivesDirCreatedDone(const base::TimeTicks& start_time);
+  // Callback for ensuring archive directory is created when saving page.
+  void ContinueSavingPageWithArchivesDir(
+      const SavePageParams& save_page_params,
+      std::unique_ptr<OfflinePageArchiver> archiver,
+      const SavePageCallback& callback,
+      const base::TimeTicks& start_time,
+      ArchiveManager::ArchivesDirCreationResult result);
 
   void GetPagesMatchingQueryWhenLoadDone(
       std::unique_ptr<OfflinePageModelQuery> query,
diff --git a/components/offline_pages/core/offline_page_model_impl_unittest.cc b/components/offline_pages/core/offline_page_model_impl_unittest.cc
index 5e70978..572bc15 100644
--- a/components/offline_pages/core/offline_page_model_impl_unittest.cc
+++ b/components/offline_pages/core/offline_page_model_impl_unittest.cc
@@ -600,7 +600,7 @@
   archiver_ptr->set_delayed(true);
   SavePageWithArchiverAsync(
       kTestUrl, kTestClientId1, GURL(), std::move(archiver));
-  EXPECT_TRUE(archiver_ptr->create_archive_called());
+  EXPECT_FALSE(archiver_ptr->create_archive_called());
   // |remove_popup_overlay| should not be turned on on foreground mode.
   EXPECT_FALSE(archiver_ptr->create_archive_params().remove_popup_overlay);
 
@@ -672,11 +672,12 @@
   save_page_params.is_background = true;
   save_page_params.use_page_problem_detectors = false;
   SavePageWithParamsAsync(save_page_params, std::move(archiver));
-  EXPECT_TRUE(archiver_ptr->create_archive_called());
-  // |remove_popup_overlay| should be turned on on background mode.
-  EXPECT_TRUE(archiver_ptr->create_archive_params().remove_popup_overlay);
+  EXPECT_FALSE(archiver_ptr->create_archive_called());
+  EXPECT_FALSE(archiver_ptr->create_archive_params().remove_popup_overlay);
 
   PumpLoop();
+  // In the destructor of archiver, the create_archive_called() will be checked
+  // to be true. Otherwise this test case will fail.
 }
 
 TEST_F(OfflinePageModelImplTest, MarkPageAccessed) {
diff --git a/components/offline_pages/core/offline_page_types.h b/components/offline_pages/core/offline_page_types.h
index e266bba41..0f16f08 100644
--- a/components/offline_pages/core/offline_page_types.h
+++ b/components/offline_pages/core/offline_page_types.h
@@ -38,6 +38,9 @@
   ERROR_PAGE,
   // Returned when we detect trying to save a chrome interstitial page.
   INTERSTITIAL_PAGE,
+  // Returned when we don't have an archive directory available, and the
+  // attempt to create the directory also failed.
+  ARCHIVE_DIR_MISSING,
   // NOTE: always keep this entry at the end. Add new result types only
   // immediately above this line. Make sure to update the corresponding
   // histogram enum accordingly.
diff --git a/components/payments/core/journey_logger.cc b/components/payments/core/journey_logger.cc
index af815ccd..2e76c224 100644
--- a/components/payments/core/journey_logger.cc
+++ b/components/payments/core/journey_logger.cc
@@ -242,12 +242,12 @@
 
   int effect_on_show = 0;
   if (was_show_called_)
-    effect_on_show |= CMP_SHOW_DID_SHOW;
+    effect_on_show |= CMP_EFFECT_ON_SHOW_DID_SHOW;
   if (could_make_payment_)
-    effect_on_show |= CMP_SHOW_COULD_MAKE_PAYMENT;
+    effect_on_show |= CMP_EFFECT_ON_SHOW_COULD_MAKE_PAYMENT;
 
   UMA_HISTOGRAM_ENUMERATION("PaymentRequest.CanMakePayment.Used.EffectOnShow",
-                            effect_on_show, CMP_SHOW_MAX);
+                            effect_on_show, CMP_EFFECT_ON_SHOW_MAX);
 }
 
 void JourneyLogger::RecordCanMakePaymentEffectOnCompletion(
diff --git a/components/payments/core/journey_logger.h b/components/payments/core/journey_logger.h
index 711e585..7521127 100644
--- a/components/payments/core/journey_logger.h
+++ b/components/payments/core/journey_logger.h
@@ -30,11 +30,12 @@
 // of the Payment Request.
 class JourneyLogger {
  public:
-  // Note: These constants should always be in sync with their counterpart in
-  // components/payments/content/android/java/src/org/chromium/components/
-  // payments/JourneyLogger.java.
+  // Note: Java counterparts will be generated for these enums.
+
   // The different sections of a Payment Request. Used to record journey
   // stats.
+  // GENERATED_JAVA_ENUM_PACKAGE: org.chromium.chrome.browser.payments
+  // GENERATED_JAVA_CLASS_NAME_OVERRIDE: Section
   enum Section {
     SECTION_CONTACT_INFO = 0,
     SECTION_CREDIT_CARDS = 1,
@@ -43,14 +44,51 @@
   };
 
   // For the CanMakePayment histograms.
+  // GENERATED_JAVA_ENUM_PACKAGE: org.chromium.chrome.browser.payments
+  // GENERATED_JAVA_CLASS_NAME_OVERRIDE: CanMakePaymentUsage
   enum CanMakePaymentUsage {
     CAN_MAKE_PAYMENT_USED = 0,
     CAN_MAKE_PAYMENT_NOT_USED = 1,
     CAN_MAKE_PAYMENT_USE_MAX,
   };
 
+  // The information requested by the merchant.
+  // GENERATED_JAVA_ENUM_PACKAGE: org.chromium.chrome.browser.payments
+  // GENERATED_JAVA_CLASS_NAME_OVERRIDE: RequestedInformation
+  enum RequestedInformation {
+    REQUESTED_INFORMATION_NONE = 0,
+    REQUESTED_INFORMATION_EMAIL = 1 << 0,
+    REQUESTED_INFORMATION_PHONE = 1 << 1,
+    REQUESTED_INFORMATION_SHIPPING = 1 << 2,
+    REQUESTED_INFORMATION_NAME = 1 << 3,
+    REQUESTED_INFORMATION_MAX = 16,
+  };
+
+  // The payment method that was used by the user to complete the transaction.
+  // GENERATED_JAVA_ENUM_PACKAGE: org.chromium.chrome.browser.payments
+  // GENERATED_JAVA_CLASS_NAME_OVERRIDE: SelectedPaymentMethod
+  enum SelectedPaymentMethod {
+    SELECTED_PAYMENT_METHOD_CREDIT_CARD = 0,
+    SELECTED_PAYMENT_METHOD_ANDROID_PAY = 1,
+    SELECTED_PAYMENT_METHOD_OTHER_PAYMENT_APP = 2,
+    SELECTED_PAYMENT_METHOD_MAX = 3,
+  };
+
+  // Used to mesure the impact of the CanMakePayment return value on whether the
+  // Payment Request is shown to the user.
+  // GENERATED_JAVA_ENUM_PACKAGE: org.chromium.chrome.browser.payments
+  // GENERATED_JAVA_CLASS_NAME_OVERRIDE: CanMakePaymentEffectOnShow
+  enum CmpEffectOnShow {
+    CMP_EFFECT_ON_SHOW_COULD_NOT_MAKE_PAYMENT_AND_DID_NOT_SHOW = 0,
+    CMP_EFFECT_ON_SHOW_DID_SHOW = 1 << 0,
+    CMP_EFFECT_ON_SHOW_COULD_MAKE_PAYMENT = 1 << 1,
+    CMP_EFFECT_ON_SHOW_MAX = 4,
+  };
+
   // Used to log different parameters' effect on whether the transaction was
   // completed.
+  // GENERATED_JAVA_ENUM_PACKAGE: org.chromium.chrome.browser.payments
+  // GENERATED_JAVA_CLASS_NAME_OVERRIDE: CompletionStatus
   enum CompletionStatus {
     COMPLETION_STATUS_COMPLETED = 0,
     COMPLETION_STATUS_USER_ABORTED = 1,
@@ -60,6 +98,8 @@
 
   // Used to record the different events that happened during the Payment
   // Request.
+  // GENERATED_JAVA_ENUM_PACKAGE: org.chromium.chrome.browser.payments
+  // GENERATED_JAVA_CLASS_NAME_OVERRIDE: Event
   enum Event {
     EVENT_INITIATED = 0,
     EVENT_SHOWN = 1 << 0,
@@ -69,6 +109,9 @@
     EVENT_ENUM_MAX = 16,
   };
 
+  // The reason why the Payment Request was aborted.
+  // GENERATED_JAVA_ENUM_PACKAGE: org.chromium.chrome.browser.payments
+  // GENERATED_JAVA_CLASS_NAME_OVERRIDE: AbortReason
   enum AbortReason {
     ABORT_REASON_ABORTED_BY_USER = 0,
     ABORT_REASON_ABORTED_BY_MERCHANT = 1,
@@ -83,22 +126,18 @@
   };
 
 #ifdef OS_ANDROID
+  // The reason why the Payment Request was not shown to the user.
+  // GENERATED_JAVA_ENUM_PACKAGE: org.chromium.chrome.browser.payments
+  // GENERATED_JAVA_CLASS_NAME_OVERRIDE: NotShownReason
   enum NotShownReason {
-    NOT_SHOWN_NO_MATCHING_PAYMENT_METHOD = 0,
-    NOT_SHOWN_NO_SUPPORTED_PAYMENT_METHOD = 1,
-    NOT_SHOWN_CONCURRENT_REQUESTS = 2,
+    NOT_SHOWN_REASON_NO_MATCHING_PAYMENT_METHOD = 0,
+    NOT_SHOWN_REASON_NO_SUPPORTED_PAYMENT_METHOD = 1,
+    NOT_SHOWN_REASON_CONCURRENT_REQUESTS = 2,
     NOT_SHOWN_REASON_OTHER = 3,
     NOT_SHOWN_REASON_MAX = 4,
   };
 #endif
 
-  // Used to mesure the impact of the CanMakePayment return value on whether the
-  // Payment Request is shown to the user.
-  static const int CMP_SHOW_COULD_NOT_MAKE_PAYMENT_AND_DID_NOT_SHOW = 0;
-  static const int CMP_SHOW_DID_SHOW = 1 << 0;
-  static const int CMP_SHOW_COULD_MAKE_PAYMENT = 1 << 1;
-  static const int CMP_SHOW_MAX = 4;
-
   JourneyLogger(bool is_incognito,
                 const GURL& url,
                 ukm::UkmRecorder* ukm_recorder);
diff --git a/components/payments/core/journey_logger_unittest.cc b/components/payments/core/journey_logger_unittest.cc
index 5bc8222..941fccb 100644
--- a/components/payments/core/journey_logger_unittest.cc
+++ b/components/payments/core/journey_logger_unittest.cc
@@ -149,7 +149,8 @@
   // shown.
   histogram_tester.ExpectBucketCount(
       "PaymentRequest.CanMakePayment.Used.EffectOnShow",
-      JourneyLogger::CMP_SHOW_COULD_NOT_MAKE_PAYMENT_AND_DID_NOT_SHOW, 1);
+      JourneyLogger::CMP_EFFECT_ON_SHOW_COULD_NOT_MAKE_PAYMENT_AND_DID_NOT_SHOW,
+      1);
 
   // There should be no completion stats since PR was not shown to the user.
   EXPECT_THAT(
@@ -182,7 +183,7 @@
   // shown.
   histogram_tester.ExpectBucketCount(
       "PaymentRequest.CanMakePayment.Used.EffectOnShow",
-      JourneyLogger::CMP_SHOW_COULD_MAKE_PAYMENT, 1);
+      JourneyLogger::CMP_EFFECT_ON_SHOW_COULD_MAKE_PAYMENT, 1);
 
   // There should be no completion stats since PR was not shown to the user.
   EXPECT_THAT(
@@ -216,7 +217,7 @@
   // shown.
   histogram_tester.ExpectBucketCount(
       "PaymentRequest.CanMakePayment.Used.EffectOnShow",
-      JourneyLogger::CMP_SHOW_DID_SHOW, 1);
+      JourneyLogger::CMP_EFFECT_ON_SHOW_DID_SHOW, 1);
   // There should be a record for an abort when CanMakePayment is false but the
   // PR is shown to the user.
   histogram_tester.ExpectBucketCount(
@@ -249,7 +250,7 @@
   // shown.
   histogram_tester.ExpectBucketCount(
       "PaymentRequest.CanMakePayment.Used.EffectOnShow",
-      JourneyLogger::CMP_SHOW_DID_SHOW, 1);
+      JourneyLogger::CMP_EFFECT_ON_SHOW_DID_SHOW, 1);
   // There should be a record for an abort when CanMakePayment is false but the
   // PR is shown to the user.
   histogram_tester.ExpectBucketCount(
@@ -282,7 +283,7 @@
   // shown.
   histogram_tester.ExpectBucketCount(
       "PaymentRequest.CanMakePayment.Used.EffectOnShow",
-      JourneyLogger::CMP_SHOW_DID_SHOW, 1);
+      JourneyLogger::CMP_EFFECT_ON_SHOW_DID_SHOW, 1);
 
   // There should be a record for an completion when CanMakePayment is false but
   // the PR is shown to the user.
@@ -316,8 +317,8 @@
   // shown.
   histogram_tester.ExpectBucketCount(
       "PaymentRequest.CanMakePayment.Used.EffectOnShow",
-      JourneyLogger::CMP_SHOW_DID_SHOW |
-          JourneyLogger::CMP_SHOW_COULD_MAKE_PAYMENT,
+      JourneyLogger::CMP_EFFECT_ON_SHOW_DID_SHOW |
+          JourneyLogger::CMP_EFFECT_ON_SHOW_COULD_MAKE_PAYMENT,
       1);
   // There should be a record for an abort when CanMakePayment is true and the
   // PR is shown to the user.
@@ -351,8 +352,8 @@
   // shown.
   histogram_tester.ExpectBucketCount(
       "PaymentRequest.CanMakePayment.Used.EffectOnShow",
-      JourneyLogger::CMP_SHOW_DID_SHOW |
-          JourneyLogger::CMP_SHOW_COULD_MAKE_PAYMENT,
+      JourneyLogger::CMP_EFFECT_ON_SHOW_DID_SHOW |
+          JourneyLogger::CMP_EFFECT_ON_SHOW_COULD_MAKE_PAYMENT,
       1);
   // There should be a record for an abort when CanMakePayment is true and the
   // PR is shown to the user.
@@ -386,8 +387,8 @@
   // shown.
   histogram_tester.ExpectBucketCount(
       "PaymentRequest.CanMakePayment.Used.EffectOnShow",
-      JourneyLogger::CMP_SHOW_DID_SHOW |
-          JourneyLogger::CMP_SHOW_COULD_MAKE_PAYMENT,
+      JourneyLogger::CMP_EFFECT_ON_SHOW_DID_SHOW |
+          JourneyLogger::CMP_EFFECT_ON_SHOW_COULD_MAKE_PAYMENT,
       1);
   // There should be a record for a completion when CanMakePayment is true and
   // the PR is shown to the user.
diff --git a/components/payments/core/payment_request_data_util.cc b/components/payments/core/payment_request_data_util.cc
index 9973b91b..7f68941 100644
--- a/components/payments/core/payment_request_data_util.cc
+++ b/components/payments/core/payment_request_data_util.cc
@@ -13,6 +13,7 @@
 #include "components/autofill/core/browser/credit_card.h"
 #include "components/autofill/core/browser/field_types.h"
 #include "components/autofill/core/browser/personal_data_manager.h"
+#include "components/autofill/core/browser/validation.h"
 #include "components/payments/core/basic_card_response.h"
 #include "components/payments/core/payment_address.h"
 #include "components/payments/core/payment_method_data.h"
@@ -165,15 +166,11 @@
       autofill::AutofillType(autofill::PHONE_HOME_WHOLE_NUMBER), locale));
   std::string tentative_intl_phone = "+" + phone;
 
-  autofill::i18n::PhoneObject phone_obj(
-      base::UTF8ToUTF16(phone), GetCountryCodeWithFallback(&profile, locale));
-  autofill::i18n::PhoneObject tentative_intl_phone_obj(
-      base::UTF8ToUTF16(tentative_intl_phone),
-      GetCountryCodeWithFallback(&profile, locale));
-
   // Always favor the tentative international phone number if it's determined as
   // being a valid number.
-  if (!tentative_intl_phone_obj.region().empty()) {
+  if (autofill::IsValidPhoneNumber(
+          base::UTF8ToUTF16(tentative_intl_phone),
+          GetCountryCodeWithFallback(&profile, locale))) {
     return base::UTF8ToUTF16(FormatPhoneForDisplay(
         tentative_intl_phone, GetCountryCodeWithFallback(&profile, locale)));
   }
diff --git a/components/payments/core/payments_profile_comparator.cc b/components/payments/core/payments_profile_comparator.cc
index e295762..3190bac 100644
--- a/components/payments/core/payments_profile_comparator.cc
+++ b/components/payments/core/payments_profile_comparator.cc
@@ -207,7 +207,9 @@
 
   base::string16 phone = profile.GetInfo(
       autofill::AutofillType(autofill::PHONE_HOME_WHOLE_NUMBER), app_locale());
-  if (!autofill::IsValidPhoneNumber(phone, country))
+  base::string16 intl_phone = base::UTF8ToUTF16("+" + base::UTF16ToUTF8(phone));
+  if (!(autofill::IsValidPhoneNumber(phone, country) ||
+        autofill::IsValidPhoneNumber(intl_phone, country)))
     missing |= kPhone;
 
   base::string16 email = profile.GetInfo(
diff --git a/components/prefs/json_pref_store.cc b/components/prefs/json_pref_store.cc
index 240f1da..c44dfa9 100644
--- a/components/prefs/json_pref_store.cc
+++ b/components/prefs/json_pref_store.cc
@@ -162,7 +162,7 @@
 
 bool JsonPrefStore::GetValue(const std::string& key,
                              const base::Value** result) const {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
 
   base::Value* tmp = nullptr;
   if (!prefs_->Get(key, &tmp))
@@ -178,32 +178,32 @@
 }
 
 void JsonPrefStore::AddObserver(PrefStore::Observer* observer) {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
 
   observers_.AddObserver(observer);
 }
 
 void JsonPrefStore::RemoveObserver(PrefStore::Observer* observer) {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
 
   observers_.RemoveObserver(observer);
 }
 
 bool JsonPrefStore::HasObservers() const {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
 
   return observers_.might_have_observers();
 }
 
 bool JsonPrefStore::IsInitializationComplete() const {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
 
   return initialized_;
 }
 
 bool JsonPrefStore::GetMutableValue(const std::string& key,
                                     base::Value** result) {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
 
   return prefs_->Get(key, result);
 }
@@ -211,7 +211,7 @@
 void JsonPrefStore::SetValue(const std::string& key,
                              std::unique_ptr<base::Value> value,
                              uint32_t flags) {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
 
   DCHECK(value);
   base::Value* old_value = nullptr;
@@ -225,7 +225,7 @@
 void JsonPrefStore::SetValueSilently(const std::string& key,
                                      std::unique_ptr<base::Value> value,
                                      uint32_t flags) {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
 
   DCHECK(value);
   base::Value* old_value = nullptr;
@@ -237,7 +237,7 @@
 }
 
 void JsonPrefStore::RemoveValue(const std::string& key, uint32_t flags) {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
 
   if (prefs_->RemovePath(key, nullptr))
     ReportValueChanged(key, flags);
@@ -245,26 +245,26 @@
 
 void JsonPrefStore::RemoveValueSilently(const std::string& key,
                                         uint32_t flags) {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
 
   prefs_->RemovePath(key, nullptr);
   ScheduleWrite(flags);
 }
 
 bool JsonPrefStore::ReadOnly() const {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
 
   return read_only_;
 }
 
 PersistentPrefStore::PrefReadError JsonPrefStore::GetReadError() const {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
 
   return read_error_;
 }
 
 PersistentPrefStore::PrefReadError JsonPrefStore::ReadPrefs() {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
 
   OnFileRead(ReadPrefsFromDisk(path_));
   return filtering_in_progress_ ? PREF_READ_ERROR_ASYNCHRONOUS_TASK_INCOMPLETE
@@ -272,7 +272,7 @@
 }
 
 void JsonPrefStore::ReadPrefsAsync(ReadErrorDelegate* error_delegate) {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
 
   initialized_ = false;
   error_delegate_.reset(error_delegate);
@@ -285,7 +285,7 @@
 }
 
 void JsonPrefStore::CommitPendingWrite() {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
 
   // Schedule a write for any lossy writes that are outstanding to ensure that
   // they get flushed when this function is called.
@@ -301,7 +301,7 @@
 }
 
 void JsonPrefStore::ReportValueChanged(const std::string& key, uint32_t flags) {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
 
   if (pref_filter_)
     pref_filter_->FilterUpdate(key);
@@ -314,7 +314,7 @@
 
 void JsonPrefStore::RunOrScheduleNextSuccessfulWriteCallback(
     bool write_success) {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
 
   has_pending_write_reply_ = false;
   if (!on_next_successful_write_reply_.is_null()) {
@@ -345,7 +345,7 @@
 
 void JsonPrefStore::RegisterOnNextSuccessfulWriteReply(
     const base::Closure& on_next_successful_write_reply) {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   DCHECK(on_next_successful_write_reply_.is_null());
 
   on_next_successful_write_reply_ = on_next_successful_write_reply;
@@ -367,7 +367,7 @@
 
 void JsonPrefStore::RegisterOnNextWriteSynchronousCallbacks(
     OnWriteCallbackPair callbacks) {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
 
   has_pending_write_reply_ = true;
 
@@ -385,7 +385,7 @@
 }
 
 void JsonPrefStore::OnFileRead(std::unique_ptr<ReadResult> read_result) {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
 
   DCHECK(read_result);
 
@@ -441,11 +441,12 @@
 }
 
 JsonPrefStore::~JsonPrefStore() {
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   CommitPendingWrite();
 }
 
 bool JsonPrefStore::SerializeData(std::string* output) {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
 
   pending_lossy_write_ = false;
 
@@ -472,7 +473,7 @@
     bool initialization_successful,
     std::unique_ptr<base::DictionaryValue> prefs,
     bool schedule_write) {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
 
   filtering_in_progress_ = false;
 
diff --git a/components/prefs/json_pref_store.h b/components/prefs/json_pref_store.h
index b298d30..90fde73 100644
--- a/components/prefs/json_pref_store.h
+++ b/components/prefs/json_pref_store.h
@@ -19,8 +19,8 @@
 #include "base/macros.h"
 #include "base/memory/weak_ptr.h"
 #include "base/observer_list.h"
+#include "base/sequence_checker.h"
 #include "base/task_scheduler/post_task.h"
-#include "base/threading/non_thread_safe.h"
 #include "components/prefs/base_prefs_export.h"
 #include "components/prefs/persistent_pref_store.h"
 #include "components/prefs/pref_filter.h"
@@ -48,8 +48,7 @@
 class COMPONENTS_PREFS_EXPORT JsonPrefStore
     : public PersistentPrefStore,
       public base::ImportantFileWriter::DataSerializer,
-      public base::SupportsWeakPtr<JsonPrefStore>,
-      public base::NonThreadSafe {
+      public base::SupportsWeakPtr<JsonPrefStore> {
  public:
   struct ReadResult;
 
@@ -253,6 +252,8 @@
 
   WriteCountHistogram write_count_histogram_;
 
+  SEQUENCE_CHECKER(sequence_checker_);
+
   DISALLOW_COPY_AND_ASSIGN(JsonPrefStore);
 };
 
diff --git a/components/prefs/pref_service.cc b/components/prefs/pref_service.cc
index dccebf4..6abc09bc 100644
--- a/components/prefs/pref_service.cc
+++ b/components/prefs/pref_service.cc
@@ -80,7 +80,7 @@
 }
 
 PrefService::~PrefService() {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
 
   // Reset pointers so accesses after destruction reliably crash.
   pref_value_store_.reset();
@@ -104,17 +104,17 @@
 }
 
 void PrefService::CommitPendingWrite() {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   user_pref_store_->CommitPendingWrite();
 }
 
 void PrefService::SchedulePendingLossyWrites() {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   user_pref_store_->SchedulePendingLossyWrites();
 }
 
 bool PrefService::GetBoolean(const std::string& path) const {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
 
   bool result = false;
 
@@ -129,7 +129,7 @@
 }
 
 int PrefService::GetInteger(const std::string& path) const {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
 
   int result = 0;
 
@@ -144,7 +144,7 @@
 }
 
 double PrefService::GetDouble(const std::string& path) const {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
 
   double result = 0.0;
 
@@ -159,7 +159,7 @@
 }
 
 std::string PrefService::GetString(const std::string& path) const {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
 
   std::string result;
 
@@ -174,7 +174,7 @@
 }
 
 base::FilePath PrefService::GetFilePath(const std::string& path) const {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
 
   base::FilePath result;
 
@@ -196,14 +196,14 @@
 void PrefService::IteratePreferenceValues(
     base::RepeatingCallback<void(const std::string& key,
                                  const base::Value& value)> callback) const {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   for (const auto& it : *pref_registry_)
     callback.Run(it.first, *GetPreferenceValue(it.first));
 }
 
 std::unique_ptr<base::DictionaryValue> PrefService::GetPreferenceValues(
     IncludeDefaults include_defaults) const {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   std::unique_ptr<base::DictionaryValue> out(new base::DictionaryValue);
   for (const auto& it : *pref_registry_) {
     if (include_defaults == INCLUDE_DEFAULTS) {
@@ -220,7 +220,7 @@
 
 const PrefService::Preference* PrefService::FindPreference(
     const std::string& pref_name) const {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   PreferenceMap::iterator it = prefs_map_.find(pref_name);
   if (it != prefs_map_.end())
     return &(it->second);
@@ -271,7 +271,7 @@
 
 const base::DictionaryValue* PrefService::GetDictionary(
     const std::string& path) const {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
 
   const base::Value* value = GetPreferenceValue(path);
   if (!value) {
@@ -287,7 +287,7 @@
 
 const base::Value* PrefService::GetUserPrefValue(
     const std::string& path) const {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
 
   const Preference* pref = FindPreference(path);
   if (!pref) {
@@ -311,13 +311,13 @@
 
 void PrefService::SetDefaultPrefValue(const std::string& path,
                                       base::Value* value) {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   pref_registry_->SetDefaultPrefValue(path, value);
 }
 
 const base::Value* PrefService::GetDefaultPrefValue(
     const std::string& path) const {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   // Lookup the preference in the default store.
   const base::Value* value = NULL;
   if (!pref_registry_->defaults()->GetValue(path, &value)) {
@@ -328,7 +328,7 @@
 }
 
 const base::ListValue* PrefService::GetList(const std::string& path) const {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
 
   const base::Value* value = GetPreferenceValue(path);
   if (!value) {
@@ -360,7 +360,7 @@
 }
 
 void PrefService::ClearPref(const std::string& path) {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
 
   const Preference* pref = FindPreference(path);
   if (!pref) {
@@ -405,7 +405,7 @@
 }
 
 int64_t PrefService::GetInt64(const std::string& path) const {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
 
   const base::Value* value = GetPreferenceValue(path);
   if (!value) {
@@ -427,7 +427,7 @@
 }
 
 uint64_t PrefService::GetUint64(const std::string& path) const {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
 
   const base::Value* value = GetPreferenceValue(path);
   if (!value) {
@@ -447,7 +447,7 @@
                                              base::Value::Type type) {
   CHECK(type == base::Value::Type::DICTIONARY ||
         type == base::Value::Type::LIST);
-  DCHECK(CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
 
   const Preference* pref = FindPreference(path);
   if (!pref) {
@@ -478,21 +478,21 @@
 }
 
 void PrefService::ReportUserPrefChanged(const std::string& key) {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   user_pref_store_->ReportValueChanged(key, GetWriteFlags(FindPreference(key)));
 }
 
 void PrefService::ReportUserPrefChanged(
     const std::string& key,
     std::set<std::vector<std::string>> path_components) {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   user_pref_store_->ReportSubValuesChanged(key, std::move(path_components),
                                            GetWriteFlags(FindPreference(key)));
 }
 
 void PrefService::SetUserPrefValue(const std::string& path,
                                    std::unique_ptr<base::Value> new_value) {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
 
   const Preference* pref = FindPreference(path);
   if (!pref) {
@@ -596,7 +596,7 @@
 
 const base::Value* PrefService::GetPreferenceValue(
     const std::string& path) const {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
 
   // TODO(battre): This is a check for crbug.com/435208. After analyzing some
   // crash dumps it looks like the PrefService is accessed even though it has
diff --git a/components/prefs/pref_service.h b/components/prefs/pref_service.h
index a360afa4..8b33717 100644
--- a/components/prefs/pref_service.h
+++ b/components/prefs/pref_service.h
@@ -23,7 +23,7 @@
 #include "base/macros.h"
 #include "base/memory/ref_counted.h"
 #include "base/observer_list.h"
-#include "base/threading/non_thread_safe.h"
+#include "base/sequence_checker.h"
 #include "base/values.h"
 #include "components/prefs/base_prefs_export.h"
 #include "components/prefs/persistent_pref_store.h"
@@ -55,7 +55,7 @@
 // Settings and storage accessed through this class represent
 // user-selected preferences and information and MUST not be
 // extracted, overwritten or modified except through the defined APIs.
-class COMPONENTS_PREFS_EXPORT PrefService : public base::NonThreadSafe {
+class COMPONENTS_PREFS_EXPORT PrefService {
  public:
   enum PrefInitializationStatus {
     INITIALIZATION_STATUS_WAITING,
@@ -397,6 +397,8 @@
   // of registered preferences are.
   mutable PreferenceMap prefs_map_;
 
+  SEQUENCE_CHECKER(sequence_checker_);
+
   DISALLOW_COPY_AND_ASSIGN(PrefService);
 };
 
diff --git a/components/prefs/scoped_user_pref_update.cc b/components/prefs/scoped_user_pref_update.cc
index dfba334..bec88eef 100644
--- a/components/prefs/scoped_user_pref_update.cc
+++ b/components/prefs/scoped_user_pref_update.cc
@@ -13,15 +13,16 @@
 ScopedUserPrefUpdateBase::ScopedUserPrefUpdateBase(PrefService* service,
                                                    const std::string& path)
     : service_(service), path_(path), value_(NULL) {
-  DCHECK(service_->CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(service_->sequence_checker_);
 }
 
 ScopedUserPrefUpdateBase::~ScopedUserPrefUpdateBase() {
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   Notify();
 }
 
 base::Value* ScopedUserPrefUpdateBase::GetValueOfType(base::Value::Type type) {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   if (!value_)
     value_ = service_->GetMutableUserPref(path_, type);
   return value_;
diff --git a/components/prefs/scoped_user_pref_update.h b/components/prefs/scoped_user_pref_update.h
index 29859d65..f8f45fc6 100644
--- a/components/prefs/scoped_user_pref_update.h
+++ b/components/prefs/scoped_user_pref_update.h
@@ -11,7 +11,7 @@
 #include <string>
 
 #include "base/macros.h"
-#include "base/threading/non_thread_safe.h"
+#include "base/sequence_checker.h"
 #include "base/values.h"
 #include "components/prefs/base_prefs_export.h"
 #include "components/prefs/pref_service.h"
@@ -31,8 +31,7 @@
 // We need this base class mostly for making it a friend of PrefService
 // and getting access to PrefService::GetMutableUserPref and
 // PrefService::ReportUserPrefChanged.
-class COMPONENTS_PREFS_EXPORT ScopedUserPrefUpdateBase
-    : public base::NonThreadSafe {
+class COMPONENTS_PREFS_EXPORT ScopedUserPrefUpdateBase {
  protected:
   ScopedUserPrefUpdateBase(PrefService* service, const std::string& path);
 
@@ -54,6 +53,8 @@
   // Cache of value from user pref store (set between Get() and Notify() calls).
   base::Value* value_;
 
+  SEQUENCE_CHECKER(sequence_checker_);
+
   DISALLOW_COPY_AND_ASSIGN(ScopedUserPrefUpdateBase);
 };
 
diff --git a/components/printing/test/print_web_view_helper_browsertest.cc b/components/printing/test/print_web_view_helper_browsertest.cc
index 0cd8115..3c708f7 100644
--- a/components/printing/test/print_web_view_helper_browsertest.cc
+++ b/components/printing/test/print_web_view_helper_browsertest.cc
@@ -413,7 +413,9 @@
   // Find the frame and set it as the focused one.  This should mean that that
   // the printout should only contain the contents of that frame.
   auto* web_view = view_->GetWebView();
-  WebFrame* sub1_frame = web_view->FindFrameByName(WebString::FromUTF8("sub1"));
+  WebFrame* sub1_frame =
+      web_view->MainFrame()->ToWebLocalFrame()->FindFrameByName(
+          WebString::FromUTF8("sub1"));
   ASSERT_TRUE(sub1_frame);
   web_view->SetFocusedFrame(sub1_frame);
   ASSERT_NE(web_view->FocusedFrame(), web_view->MainFrame());
diff --git a/components/safe_browsing/browser/safe_browsing_url_request_context_getter.cc b/components/safe_browsing/browser/safe_browsing_url_request_context_getter.cc
index 513698f..7c5ce4a 100644
--- a/components/safe_browsing/browser/safe_browsing_url_request_context_getter.cc
+++ b/components/safe_browsing/browser/safe_browsing_url_request_context_getter.cc
@@ -78,13 +78,18 @@
     if (safe_browsing_request_context_->http_transaction_factory() &&
         safe_browsing_request_context_->http_transaction_factory()
             ->GetSession()) {
-      net::HttpNetworkSession::Params safe_browsing_params =
+      net::HttpNetworkSession::Params safe_browsing_session_params =
           safe_browsing_request_context_->http_transaction_factory()
               ->GetSession()
               ->params();
-      safe_browsing_params.channel_id_service = channel_id_service_.get();
-      http_network_session_.reset(
-          new net::HttpNetworkSession(safe_browsing_params));
+      net::HttpNetworkSession::Context safe_browsing_session_context =
+          safe_browsing_request_context_->http_transaction_factory()
+              ->GetSession()
+              ->context();
+      safe_browsing_session_context.channel_id_service =
+          channel_id_service_.get();
+      http_network_session_.reset(new net::HttpNetworkSession(
+          safe_browsing_session_params, safe_browsing_session_context));
       http_transaction_factory_.reset(
           new net::HttpNetworkLayer(http_network_session_.get()));
       safe_browsing_request_context_->set_http_transaction_factory(
diff --git a/components/safe_browsing_db/v4_get_hash_protocol_manager.cc b/components/safe_browsing_db/v4_get_hash_protocol_manager.cc
index 77488c2c..9cfd8ff 100644
--- a/components/safe_browsing_db/v4_get_hash_protocol_manager.cc
+++ b/components/safe_browsing_db/v4_get_hash_protocol_manager.cc
@@ -255,10 +255,12 @@
   threat_types_.assign(threat_types.begin(), threat_types.end());
 }
 
-V4GetHashProtocolManager::~V4GetHashProtocolManager() {}
+V4GetHashProtocolManager::~V4GetHashProtocolManager() {
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+}
 
 void V4GetHashProtocolManager::ClearCache() {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   full_hash_cache_.clear();
 }
 
@@ -267,7 +269,7 @@
         full_hash_to_store_and_hash_prefixes,
     FullHashCallback callback) {
   DCHECK_CURRENTLY_ON(BrowserThread::IO);
-  DCHECK(CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   DCHECK(!full_hash_to_store_and_hash_prefixes.empty());
 
   std::vector<HashPrefix> prefixes_to_request;
@@ -506,7 +508,7 @@
 }
 
 void V4GetHashProtocolManager::HandleGetHashError(const Time& now) {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   TimeDelta next = V4ProtocolManagerUtil::GetNextBackOffInterval(
       &gethash_error_count_, &gethash_back_off_mult_);
   next_gethash_time_ = now + next;
@@ -738,7 +740,7 @@
 // SafeBrowsing request responses are handled here.
 void V4GetHashProtocolManager::OnURLFetchComplete(
     const net::URLFetcher* source) {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   DCHECK_CURRENTLY_ON(BrowserThread::IO);
 
   PendingHashRequests::iterator it = pending_hash_requests_.find(source);
diff --git a/components/safe_browsing_db/v4_get_hash_protocol_manager.h b/components/safe_browsing_db/v4_get_hash_protocol_manager.h
index 7d9c2c2..6e43e88 100644
--- a/components/safe_browsing_db/v4_get_hash_protocol_manager.h
+++ b/components/safe_browsing_db/v4_get_hash_protocol_manager.h
@@ -20,7 +20,7 @@
 
 #include "base/gtest_prod_util.h"
 #include "base/macros.h"
-#include "base/threading/non_thread_safe.h"
+#include "base/sequence_checker.h"
 #include "base/time/default_clock.h"
 #include "base/time/time.h"
 #include "base/timer/timer.h"
@@ -139,8 +139,7 @@
 
 class V4GetHashProtocolManagerFactory;
 
-class V4GetHashProtocolManager : public net::URLFetcherDelegate,
-                                 public base::NonThreadSafe {
+class V4GetHashProtocolManager : public net::URLFetcherDelegate {
  public:
   // Invoked when GetFullHashesWithApis completes.
   // Parameters:
@@ -341,6 +340,8 @@
   std::vector<ThreatEntryType> threat_entry_types_;
   std::vector<ThreatType> threat_types_;
 
+  SEQUENCE_CHECKER(sequence_checker_);
+
   DISALLOW_COPY_AND_ASSIGN(V4GetHashProtocolManager);
 };
 
diff --git a/components/safe_browsing_db/v4_update_protocol_manager.cc b/components/safe_browsing_db/v4_update_protocol_manager.cc
index 3d485bdd..ddd08f5 100644
--- a/components/safe_browsing_db/v4_update_protocol_manager.cc
+++ b/components/safe_browsing_db/v4_update_protocol_manager.cc
@@ -153,7 +153,9 @@
   // when it is ready to process updates.
 }
 
-V4UpdateProtocolManager::~V4UpdateProtocolManager() {}
+V4UpdateProtocolManager::~V4UpdateProtocolManager() {
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+}
 
 bool V4UpdateProtocolManager::IsUpdateScheduled() const {
   return update_timer_.IsRunning();
@@ -166,7 +168,7 @@
 }
 
 void V4UpdateProtocolManager::ScheduleNextUpdateWithBackoff(bool back_off) {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
 
   if (config_.disable_auto_update) {
     DCHECK(!IsUpdateScheduled());
@@ -181,7 +183,7 @@
 // According to section 5 of the SafeBrowsing protocol specification, we must
 // back off after a certain number of errors.
 base::TimeDelta V4UpdateProtocolManager::GetNextUpdateInterval(bool back_off) {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   DCHECK(next_update_interval_ > base::TimeDelta());
 
   base::TimeDelta next = next_update_interval_;
@@ -208,7 +210,7 @@
 
 void V4UpdateProtocolManager::ScheduleNextUpdateAfterInterval(
     base::TimeDelta interval) {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   DCHECK(interval >= base::TimeDelta());
 
   // Unschedule any current timer.
@@ -299,7 +301,7 @@
 }
 
 void V4UpdateProtocolManager::IssueUpdateRequest() {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
 
   // If an update request is already pending, record and return silently.
   if (request_.get()) {
@@ -370,7 +372,7 @@
 // SafeBrowsing request responses are handled here.
 void V4UpdateProtocolManager::OnURLFetchComplete(
     const net::URLFetcher* source) {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
 
   timeout_timer_.Stop();
 
diff --git a/components/safe_browsing_db/v4_update_protocol_manager.h b/components/safe_browsing_db/v4_update_protocol_manager.h
index 5c60a0c3..706c7d4 100644
--- a/components/safe_browsing_db/v4_update_protocol_manager.h
+++ b/components/safe_browsing_db/v4_update_protocol_manager.h
@@ -18,7 +18,7 @@
 
 #include "base/gtest_prod_util.h"
 #include "base/macros.h"
-#include "base/threading/non_thread_safe.h"
+#include "base/sequence_checker.h"
 #include "base/time/time.h"
 #include "base/timer/timer.h"
 #include "components/safe_browsing/common/safe_browsing_prefs.h"
@@ -47,8 +47,7 @@
 
 typedef base::Callback<ExtendedReportingLevel()> ExtendedReportingLevelCallback;
 
-class V4UpdateProtocolManager : public net::URLFetcherDelegate,
-                                public base::NonThreadSafe {
+class V4UpdateProtocolManager : public net::URLFetcherDelegate {
  public:
   ~V4UpdateProtocolManager() override;
 
@@ -192,6 +191,8 @@
 
   ExtendedReportingLevelCallback extended_reporting_level_callback_;
 
+  SEQUENCE_CHECKER(sequence_checker_);
+
   DISALLOW_COPY_AND_ASSIGN(V4UpdateProtocolManager);
 };
 
diff --git a/components/signin/ios/browser/BUILD.gn b/components/signin/ios/browser/BUILD.gn
index b914497..af96184 100644
--- a/components/signin/ios/browser/BUILD.gn
+++ b/components/signin/ios/browser/BUILD.gn
@@ -62,7 +62,8 @@
     "//components/signin/core/common",
     "//components/sync_preferences:test_support",
     "//ios/web",
-    "//ios/web:test_support",
+    "//ios/web/public/test",
+    "//ios/web/public/test/fakes",
     "//third_party/ocmock",
   ]
 }
diff --git a/components/sync/base/sync_prefs.cc b/components/sync/base/sync_prefs.cc
index 26b2a36a..b5728c4a 100644
--- a/components/sync/base/sync_prefs.cc
+++ b/components/sync/base/sync_prefs.cc
@@ -31,7 +31,7 @@
 SyncPrefs::SyncPrefs() : pref_service_(nullptr) {}
 
 SyncPrefs::~SyncPrefs() {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
 }
 
 // static
@@ -93,17 +93,17 @@
 }
 
 void SyncPrefs::AddSyncPrefObserver(SyncPrefObserver* sync_pref_observer) {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   sync_pref_observers_.AddObserver(sync_pref_observer);
 }
 
 void SyncPrefs::RemoveSyncPrefObserver(SyncPrefObserver* sync_pref_observer) {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   sync_pref_observers_.RemoveObserver(sync_pref_observer);
 }
 
 void SyncPrefs::ClearPreferences() {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   pref_service_->ClearPref(prefs::kSyncLastSyncedTime);
   pref_service_->ClearPref(prefs::kSyncLastPollTime);
   pref_service_->ClearPref(prefs::kSyncFirstSetupComplete);
@@ -123,74 +123,74 @@
 }
 
 bool SyncPrefs::IsFirstSetupComplete() const {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   return pref_service_->GetBoolean(prefs::kSyncFirstSetupComplete);
 }
 
 void SyncPrefs::SetFirstSetupComplete() {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   pref_service_->SetBoolean(prefs::kSyncFirstSetupComplete, true);
 }
 
 bool SyncPrefs::SyncHasAuthError() const {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   return pref_service_->GetBoolean(prefs::kSyncHasAuthError);
 }
 
 void SyncPrefs::SetSyncAuthError(bool error) {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   pref_service_->SetBoolean(prefs::kSyncHasAuthError, error);
 }
 
 bool SyncPrefs::IsSyncRequested() const {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   // IsSyncRequested is the inverse of the old SuppressStart pref.
   // Since renaming a pref value is hard, here we still use the old one.
   return !pref_service_->GetBoolean(prefs::kSyncSuppressStart);
 }
 
 void SyncPrefs::SetSyncRequested(bool is_requested) {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   // See IsSyncRequested for why we use this pref and !is_requested.
   pref_service_->SetBoolean(prefs::kSyncSuppressStart, !is_requested);
 }
 
 base::Time SyncPrefs::GetLastSyncedTime() const {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   return base::Time::FromInternalValue(
       pref_service_->GetInt64(prefs::kSyncLastSyncedTime));
 }
 
 void SyncPrefs::SetLastSyncedTime(base::Time time) {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   pref_service_->SetInt64(prefs::kSyncLastSyncedTime, time.ToInternalValue());
 }
 
 base::Time SyncPrefs::GetLastPollTime() const {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   return base::Time::FromInternalValue(
       pref_service_->GetInt64(prefs::kSyncLastSyncedTime));
 }
 
 void SyncPrefs::SetLastPollTime(base::Time time) {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   pref_service_->SetInt64(prefs::kSyncLastPollTime, time.ToInternalValue());
 }
 
 bool SyncPrefs::HasKeepEverythingSynced() const {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   return pref_service_->GetBoolean(prefs::kSyncKeepEverythingSynced);
 }
 
 void SyncPrefs::SetKeepEverythingSynced(bool keep_everything_synced) {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   pref_service_->SetBoolean(prefs::kSyncKeepEverythingSynced,
                             keep_everything_synced);
 }
 
 ModelTypeSet SyncPrefs::GetPreferredDataTypes(
     ModelTypeSet registered_types) const {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
 
   if (pref_service_->GetBoolean(prefs::kSyncKeepEverythingSynced)) {
     return registered_types;
@@ -208,7 +208,7 @@
 
 void SyncPrefs::SetPreferredDataTypes(ModelTypeSet registered_types,
                                       ModelTypeSet preferred_types) {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   preferred_types = ResolvePrefGroups(registered_types, preferred_types);
   DCHECK(registered_types.HasAll(preferred_types));
   for (ModelTypeSet::Iterator i = registered_types.First(); i.Good(); i.Inc()) {
@@ -217,37 +217,37 @@
 }
 
 bool SyncPrefs::IsManaged() const {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   return pref_service_->GetBoolean(prefs::kSyncManaged);
 }
 
 std::string SyncPrefs::GetEncryptionBootstrapToken() const {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   return pref_service_->GetString(prefs::kSyncEncryptionBootstrapToken);
 }
 
 void SyncPrefs::SetEncryptionBootstrapToken(const std::string& token) {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   pref_service_->SetString(prefs::kSyncEncryptionBootstrapToken, token);
 }
 
 std::string SyncPrefs::GetKeystoreEncryptionBootstrapToken() const {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   return pref_service_->GetString(prefs::kSyncKeystoreEncryptionBootstrapToken);
 }
 
 void SyncPrefs::SetKeystoreEncryptionBootstrapToken(const std::string& token) {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   pref_service_->SetString(prefs::kSyncKeystoreEncryptionBootstrapToken, token);
 }
 
 std::string SyncPrefs::GetSyncSessionsGUID() const {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   return pref_service_->GetString(prefs::kSyncSessionsGUID);
 }
 
 void SyncPrefs::SetSyncSessionsGUID(const std::string& guid) {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   pref_service_->SetString(prefs::kSyncSessionsGUID, guid);
 }
 
@@ -340,24 +340,24 @@
 
 #if defined(OS_CHROMEOS)
 std::string SyncPrefs::GetSpareBootstrapToken() const {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   return pref_service_->GetString(prefs::kSyncSpareBootstrapToken);
 }
 
 void SyncPrefs::SetSpareBootstrapToken(const std::string& token) {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   pref_service_->SetString(prefs::kSyncSpareBootstrapToken, token);
 }
 #endif
 
 void SyncPrefs::OnSyncManagedPrefChanged() {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   for (auto& observer : sync_pref_observers_)
     observer.OnSyncManagedPrefChange(*pref_sync_managed_);
 }
 
 void SyncPrefs::SetManagedForTest(bool is_managed) {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   pref_service_->SetBoolean(prefs::kSyncManaged, is_managed);
 }
 
@@ -406,7 +406,7 @@
 }
 
 bool SyncPrefs::GetDataTypePreferred(ModelType type) const {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   const char* pref_name = GetPrefNameForDataType(type);
   if (!pref_name) {
     NOTREACHED();
@@ -429,7 +429,7 @@
 }
 
 void SyncPrefs::SetDataTypePreferred(ModelType type, bool is_preferred) {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   const char* pref_name = GetPrefNameForDataType(type);
   if (!pref_name) {
     NOTREACHED();
diff --git a/components/sync/base/sync_prefs.h b/components/sync/base/sync_prefs.h
index 4f60110c..ec363594 100644
--- a/components/sync/base/sync_prefs.h
+++ b/components/sync/base/sync_prefs.h
@@ -15,7 +15,7 @@
 #include "base/macros.h"
 #include "base/memory/weak_ptr.h"
 #include "base/observer_list.h"
-#include "base/threading/non_thread_safe.h"
+#include "base/sequence_checker.h"
 #include "base/time/time.h"
 #include "build/build_config.h"
 #include "components/prefs/pref_member.h"
@@ -53,8 +53,7 @@
 //   sync_setup_wizard.cc
 //   sync_setup_wizard_unittest.cc
 //   two_client_preferences_sync_test.cc
-class SyncPrefs : NON_EXPORTED_BASE(public base::NonThreadSafe),
-                  public base::SupportsWeakPtr<SyncPrefs> {
+class SyncPrefs : public base::SupportsWeakPtr<SyncPrefs> {
  public:
   // |pref_service| may not be null.
   // Does not take ownership of |pref_service|.
@@ -220,6 +219,8 @@
   using PrefGroupsMap = std::map<ModelType, ModelTypeSet>;
   PrefGroupsMap pref_groups_;
 
+  SEQUENCE_CHECKER(sequence_checker_);
+
   DISALLOW_COPY_AND_ASSIGN(SyncPrefs);
 };
 
diff --git a/components/sync/base/weak_handle.h b/components/sync/base/weak_handle.h
index 5db9810..dd5915f2 100644
--- a/components/sync/base/weak_handle.h
+++ b/components/sync/base/weak_handle.h
@@ -47,7 +47,7 @@
 //   const WeakHandle<Foo> foo_;
 // };
 //
-// class Foo : public SupportsWeakPtr<Foo>, public NonThreadSafe {
+// class Foo : public SupportsWeakPtr<Foo> {
 //  public:
 //   Foo() {
 //     SpawnFooIOWorkerOnIOThread(base::MakeWeakHandle(AsWeakPtr()));
@@ -58,6 +58,9 @@
 //   void OnIOStart() { DCHECK(CalledOnValidThread(); ... }
 //   void OnIOEvent(IOEvent e) { DCHECK(CalledOnValidThread(); ... }
 //   void OnIOError(IOError err) { DCHECK(CalledOnValidThread(); ... }
+//
+//  private:
+//   SEQUENCE_CHECKER(sequence_checker_);
 // };
 
 namespace tracked_objects {
diff --git a/components/sync/device_info/local_device_info_provider_impl.cc b/components/sync/device_info/local_device_info_provider_impl.cc
index 9da066f..4b50c63 100644
--- a/components/sync/device_info/local_device_info_provider_impl.cc
+++ b/components/sync/device_info/local_device_info_provider_impl.cc
@@ -42,30 +42,32 @@
       version_(version),
       is_tablet_(is_tablet),
       weak_factory_(this) {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
 }
 
-LocalDeviceInfoProviderImpl::~LocalDeviceInfoProviderImpl() {}
+LocalDeviceInfoProviderImpl::~LocalDeviceInfoProviderImpl() {
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+}
 
 const DeviceInfo* LocalDeviceInfoProviderImpl::GetLocalDeviceInfo() const {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   return local_device_info_.get();
 }
 
 std::string LocalDeviceInfoProviderImpl::GetSyncUserAgent() const {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   return MakeUserAgentForSync(channel_, is_tablet_);
 }
 
 std::string LocalDeviceInfoProviderImpl::GetLocalSyncCacheGUID() const {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   return cache_guid_;
 }
 
 std::unique_ptr<LocalDeviceInfoProvider::Subscription>
 LocalDeviceInfoProviderImpl::RegisterOnInitializedCallback(
     const base::Closure& callback) {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   DCHECK(!local_device_info_.get());
   return callback_list_.Add(callback);
 }
@@ -74,7 +76,7 @@
     const std::string& cache_guid,
     const std::string& signin_scoped_device_id,
     const scoped_refptr<base::TaskRunner>& blocking_task_runner) {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   DCHECK(!cache_guid.empty());
   cache_guid_ = cache_guid;
 
@@ -89,7 +91,7 @@
     const std::string& guid,
     const std::string& signin_scoped_device_id,
     const std::string& session_name) {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   if (guid != cache_guid_) {
     // Clear() happened before this callback; abort.
     return;
@@ -104,7 +106,7 @@
 }
 
 void LocalDeviceInfoProviderImpl::Clear() {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   cache_guid_ = "";
   local_device_info_.reset();
 }
diff --git a/components/sync/device_info/local_device_info_provider_impl.h b/components/sync/device_info/local_device_info_provider_impl.h
index a786975c..f15743f 100644
--- a/components/sync/device_info/local_device_info_provider_impl.h
+++ b/components/sync/device_info/local_device_info_provider_impl.h
@@ -10,15 +10,14 @@
 
 #include "base/macros.h"
 #include "base/memory/weak_ptr.h"
-#include "base/threading/non_thread_safe.h"
+#include "base/sequence_checker.h"
 #include "components/sync/device_info/device_info.h"
 #include "components/sync/device_info/local_device_info_provider.h"
 #include "components/version_info/version_info.h"
 
 namespace syncer {
 
-class LocalDeviceInfoProviderImpl : public LocalDeviceInfoProvider,
-                                    public base::NonThreadSafe {
+class LocalDeviceInfoProviderImpl : public LocalDeviceInfoProvider {
  public:
   LocalDeviceInfoProviderImpl(version_info::Channel channel,
                               const std::string& version,
@@ -55,6 +54,9 @@
   std::string cache_guid_;
   std::unique_ptr<DeviceInfo> local_device_info_;
   base::CallbackList<void(void)> callback_list_;
+
+  SEQUENCE_CHECKER(sequence_checker_);
+
   base::WeakPtrFactory<LocalDeviceInfoProviderImpl> weak_factory_;
 
   DISALLOW_COPY_AND_ASSIGN(LocalDeviceInfoProviderImpl);
diff --git a/components/sync/driver/DEPS b/components/sync/driver/DEPS
index 29e27de..72a2c53 100644
--- a/components/sync/driver/DEPS
+++ b/components/sync/driver/DEPS
@@ -1,6 +1,7 @@
 include_rules = [
   "+components/data_use_measurement/core",
   "+components/invalidation",
+  "+components/keyed_service/core",
   "+components/os_crypt",
   "+components/policy",
   "+components/pref_registry",
diff --git a/components/sync/driver/fake_sync_service.cc b/components/sync/driver/fake_sync_service.cc
index e0d00fd..691d27ba 100644
--- a/components/sync/driver/fake_sync_service.cc
+++ b/components/sync/driver/fake_sync_service.cc
@@ -146,14 +146,6 @@
 
 void FakeSyncService::ReenableDatatype(ModelType type) {}
 
-bool FakeSyncService::IsPassphraseRequired() const {
-  return false;
-}
-
-ModelTypeSet FakeSyncService::GetEncryptedDataTypes() const {
-  return ModelTypeSet();
-}
-
 FakeSyncService::SyncTokenStatus FakeSyncService::GetSyncTokenStatus() const {
   return FakeSyncService::SyncTokenStatus();
 }
@@ -218,4 +210,14 @@
   return nullptr;
 }
 
+bool FakeSyncService::IsPassphraseRequired() const {
+  return false;
+}
+
+ModelTypeSet FakeSyncService::GetEncryptedDataTypes() const {
+  return ModelTypeSet();
+}
+
+void FakeSyncService::Shutdown() {}
+
 }  // namespace syncer
diff --git a/components/sync/driver/fake_sync_service.h b/components/sync/driver/fake_sync_service.h
index 086953e..095fbc1 100644
--- a/components/sync/driver/fake_sync_service.h
+++ b/components/sync/driver/fake_sync_service.h
@@ -24,7 +24,7 @@
   ~FakeSyncService() override;
 
  private:
-  // SyncService:
+  // SyncService implementation.
   bool IsFirstSetupComplete() const override;
   bool IsSyncAllowed() const override;
   bool IsSyncActive() const override;
@@ -85,10 +85,13 @@
                        callback) override;
   SigninManagerBase* signin() const override;
 
-  // DataTypeEncryptionHandler:
+  // DataTypeEncryptionHandler implementation.
   bool IsPassphraseRequired() const override;
   ModelTypeSet GetEncryptedDataTypes() const override;
 
+  // KeyedService implementation.
+  void Shutdown() override;
+
   GoogleServiceAuthError error_;
   GURL sync_service_url_;
   std::string unrecoverable_error_message_;
diff --git a/components/sync/driver/sync_service.h b/components/sync/driver/sync_service.h
index 1b323b2f..ca749543 100644
--- a/components/sync/driver/sync_service.h
+++ b/components/sync/driver/sync_service.h
@@ -13,6 +13,7 @@
 #include "base/macros.h"
 #include "base/memory/weak_ptr.h"
 #include "base/time/time.h"
+#include "components/keyed_service/core/keyed_service.h"
 #include "components/sync/base/model_type.h"
 #include "components/sync/driver/data_type_encryption_handler.h"
 #include "components/sync/driver/sync_service_observer.h"
@@ -72,7 +73,7 @@
   base::Closure on_destroy_;
 };
 
-class SyncService : public DataTypeEncryptionHandler {
+class SyncService : public DataTypeEncryptionHandler, public KeyedService {
  public:
   // Used to specify the kind of passphrase with which sync data is encrypted.
   enum PassphraseType {
diff --git a/components/sync/engine/attachments/attachment_store_frontend.cc b/components/sync/engine/attachments/attachment_store_frontend.cc
index ffc50eb..d67c2c14 100644
--- a/components/sync/engine/attachments/attachment_store_frontend.cc
+++ b/components/sync/engine/attachments/attachment_store_frontend.cc
@@ -31,6 +31,7 @@
 }
 
 AttachmentStoreFrontend::~AttachmentStoreFrontend() {
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   DCHECK(backend_);
   // To delete backend post task that doesn't do anything, but binds backend
   // through base::Passed. This way backend will be deleted regardless whether
@@ -41,7 +42,7 @@
 
 void AttachmentStoreFrontend::Init(
     const AttachmentStore::InitCallback& callback) {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   backend_task_runner_->PostTask(
       FROM_HERE, base::Bind(&AttachmentStoreBackend::Init,
                             base::Unretained(backend_.get()), callback));
@@ -51,7 +52,7 @@
     AttachmentStore::Component component,
     const AttachmentIdList& ids,
     const AttachmentStore::ReadCallback& callback) {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   backend_task_runner_->PostTask(
       FROM_HERE,
       base::Bind(&AttachmentStoreBackend::Read,
@@ -62,7 +63,7 @@
     AttachmentStore::Component component,
     const AttachmentList& attachments,
     const AttachmentStore::WriteCallback& callback) {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   backend_task_runner_->PostTask(
       FROM_HERE, base::Bind(&AttachmentStoreBackend::Write,
                             base::Unretained(backend_.get()), component,
@@ -71,7 +72,7 @@
 
 void AttachmentStoreFrontend::SetReference(AttachmentStore::Component component,
                                            const AttachmentIdList& ids) {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   backend_task_runner_->PostTask(
       FROM_HERE, base::Bind(&AttachmentStoreBackend::SetReference,
                             base::Unretained(backend_.get()), component, ids));
@@ -81,7 +82,7 @@
     AttachmentStore::Component component,
     const AttachmentIdList& ids,
     const AttachmentStore::DropCallback& callback) {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   backend_task_runner_->PostTask(
       FROM_HERE,
       base::Bind(&AttachmentStoreBackend::DropReference,
@@ -92,7 +93,7 @@
     AttachmentStore::Component component,
     const AttachmentIdList& ids,
     const AttachmentStore::ReadMetadataCallback& callback) {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   backend_task_runner_->PostTask(
       FROM_HERE,
       base::Bind(&AttachmentStoreBackend::ReadMetadataById,
@@ -102,7 +103,7 @@
 void AttachmentStoreFrontend::ReadMetadata(
     AttachmentStore::Component component,
     const AttachmentStore::ReadMetadataCallback& callback) {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   backend_task_runner_->PostTask(
       FROM_HERE,
       base::Bind(&AttachmentStoreBackend::ReadMetadata,
diff --git a/components/sync/engine/attachments/attachment_store_frontend.h b/components/sync/engine/attachments/attachment_store_frontend.h
index fc1b14eb..c146896 100644
--- a/components/sync/engine/attachments/attachment_store_frontend.h
+++ b/components/sync/engine/attachments/attachment_store_frontend.h
@@ -9,7 +9,7 @@
 
 #include "base/macros.h"
 #include "base/memory/ref_counted.h"
-#include "base/threading/non_thread_safe.h"
+#include "base/sequence_checker.h"
 #include "components/sync/model/attachments/attachment_store.h"
 
 namespace base {
@@ -30,8 +30,7 @@
 // Method signatures of AttachmentStoreFrontend match exactly methods of
 // AttachmentStoreBackend.
 class AttachmentStoreFrontend
-    : public base::RefCounted<AttachmentStoreFrontend>,
-      public base::NonThreadSafe {
+    : public base::RefCounted<AttachmentStoreFrontend> {
  public:
   AttachmentStoreFrontend(
       std::unique_ptr<AttachmentStoreBackend> backend,
@@ -66,6 +65,8 @@
   std::unique_ptr<AttachmentStoreBackend> backend_;
   scoped_refptr<base::SequencedTaskRunner> backend_task_runner_;
 
+  SEQUENCE_CHECKER(sequence_checker_);
+
   DISALLOW_COPY_AND_ASSIGN(AttachmentStoreFrontend);
 };
 
diff --git a/components/sync/engine/attachments/fake_attachment_downloader.cc b/components/sync/engine/attachments/fake_attachment_downloader.cc
index 66f85fb..767a586 100644
--- a/components/sync/engine/attachments/fake_attachment_downloader.cc
+++ b/components/sync/engine/attachments/fake_attachment_downloader.cc
@@ -18,13 +18,13 @@
 FakeAttachmentDownloader::FakeAttachmentDownloader() {}
 
 FakeAttachmentDownloader::~FakeAttachmentDownloader() {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
 }
 
 void FakeAttachmentDownloader::DownloadAttachment(
     const AttachmentId& attachment_id,
     const DownloadCallback& callback) {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   // This is happy fake downloader, it always successfully downloads empty
   // attachment.
   scoped_refptr<base::RefCountedMemory> data(new base::RefCountedBytes());
diff --git a/components/sync/engine/attachments/fake_attachment_downloader.h b/components/sync/engine/attachments/fake_attachment_downloader.h
index 6c57281..13eb7e2 100644
--- a/components/sync/engine/attachments/fake_attachment_downloader.h
+++ b/components/sync/engine/attachments/fake_attachment_downloader.h
@@ -6,15 +6,14 @@
 #define COMPONENTS_SYNC_ENGINE_ATTACHMENTS_FAKE_ATTACHMENT_DOWNLOADER_H_
 
 #include "base/macros.h"
-#include "base/threading/non_thread_safe.h"
+#include "base/sequence_checker.h"
 #include "components/sync/engine/attachments/attachment_downloader.h"
 
 namespace syncer {
 
 // FakeAttachmentDownloader is for tests. For every request it posts a success
 // callback with empty attachment.
-class FakeAttachmentDownloader : public AttachmentDownloader,
-                                 public base::NonThreadSafe {
+class FakeAttachmentDownloader : public AttachmentDownloader {
  public:
   FakeAttachmentDownloader();
   ~FakeAttachmentDownloader() override;
@@ -24,6 +23,8 @@
                           const DownloadCallback& callback) override;
 
  private:
+  SEQUENCE_CHECKER(sequence_checker_);
+
   DISALLOW_COPY_AND_ASSIGN(FakeAttachmentDownloader);
 };
 
diff --git a/components/sync/engine/attachments/fake_attachment_uploader.cc b/components/sync/engine/attachments/fake_attachment_uploader.cc
index 3560e733..f5f7ad59 100644
--- a/components/sync/engine/attachments/fake_attachment_uploader.cc
+++ b/components/sync/engine/attachments/fake_attachment_uploader.cc
@@ -14,16 +14,16 @@
 namespace syncer {
 
 FakeAttachmentUploader::FakeAttachmentUploader() {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
 }
 
 FakeAttachmentUploader::~FakeAttachmentUploader() {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
 }
 
 void FakeAttachmentUploader::UploadAttachment(const Attachment& attachment,
                                               const UploadCallback& callback) {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   DCHECK(!attachment.GetId().GetProto().unique_id().empty());
 
   UploadResult result = UPLOAD_SUCCESS;
diff --git a/components/sync/engine/attachments/fake_attachment_uploader.h b/components/sync/engine/attachments/fake_attachment_uploader.h
index b6e4ecd..6e8d114 100644
--- a/components/sync/engine/attachments/fake_attachment_uploader.h
+++ b/components/sync/engine/attachments/fake_attachment_uploader.h
@@ -6,14 +6,13 @@
 #define COMPONENTS_SYNC_ENGINE_ATTACHMENTS_FAKE_ATTACHMENT_UPLOADER_H_
 
 #include "base/macros.h"
-#include "base/threading/non_thread_safe.h"
+#include "base/sequence_checker.h"
 #include "components/sync/engine/attachments/attachment_uploader.h"
 
 namespace syncer {
 
 // A fake implementation of AttachmentUploader.
-class FakeAttachmentUploader : public AttachmentUploader,
-                               public base::NonThreadSafe {
+class FakeAttachmentUploader : public AttachmentUploader {
  public:
   FakeAttachmentUploader();
   ~FakeAttachmentUploader() override;
@@ -23,6 +22,8 @@
                         const UploadCallback& callback) override;
 
  private:
+  SEQUENCE_CHECKER(sequence_checker_);
+
   DISALLOW_COPY_AND_ASSIGN(FakeAttachmentUploader);
 };
 
diff --git a/components/sync/engine/attachments/in_memory_attachment_store.cc b/components/sync/engine/attachments/in_memory_attachment_store.cc
index 7a82b55..0af71baf 100644
--- a/components/sync/engine/attachments/in_memory_attachment_store.cc
+++ b/components/sync/engine/attachments/in_memory_attachment_store.cc
@@ -28,14 +28,16 @@
     const scoped_refptr<base::SequencedTaskRunner>& callback_task_runner)
     : AttachmentStoreBackend(callback_task_runner) {
   // Object is created on one thread but used on another.
-  DetachFromThread();
+  DETACH_FROM_SEQUENCE(sequence_checker_);
 }
 
-InMemoryAttachmentStore::~InMemoryAttachmentStore() {}
+InMemoryAttachmentStore::~InMemoryAttachmentStore() {
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+}
 
 void InMemoryAttachmentStore::Init(
     const AttachmentStore::InitCallback& callback) {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   PostCallback(base::Bind(callback, AttachmentStore::SUCCESS));
 }
 
@@ -43,7 +45,7 @@
     AttachmentStore::Component component,
     const AttachmentIdList& ids,
     const AttachmentStore::ReadCallback& callback) {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   AttachmentStore::Result result_code = AttachmentStore::SUCCESS;
   std::unique_ptr<AttachmentMap> result_map(new AttachmentMap);
   std::unique_ptr<AttachmentIdList> unavailable_attachments(
@@ -70,7 +72,7 @@
     AttachmentStore::Component component,
     const AttachmentList& attachments,
     const AttachmentStore::WriteCallback& callback) {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   for (const auto& attachment : attachments) {
     attachments_.insert(std::make_pair(attachment.GetId(),
                                        AttachmentEntry(attachment, component)));
@@ -80,7 +82,7 @@
 
 void InMemoryAttachmentStore::SetReference(AttachmentStore::Component component,
                                            const AttachmentIdList& ids) {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   for (const auto& id : ids) {
     AttachmentEntryMap::iterator attachments_iter = attachments_.find(id);
     if (attachments_iter != attachments_.end()) {
@@ -93,7 +95,7 @@
     AttachmentStore::Component component,
     const AttachmentIdList& ids,
     const AttachmentStore::DropCallback& callback) {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   AttachmentStore::Result result = AttachmentStore::SUCCESS;
   for (const auto& id : ids) {
     AttachmentEntryMap::iterator attachments_iter = attachments_.find(id);
@@ -112,7 +114,7 @@
     AttachmentStore::Component component,
     const AttachmentIdList& ids,
     const AttachmentStore::ReadMetadataCallback& callback) {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   AttachmentStore::Result result_code = AttachmentStore::SUCCESS;
   std::unique_ptr<AttachmentMetadataList> metadata_list(
       new AttachmentMetadataList());
@@ -136,7 +138,7 @@
 void InMemoryAttachmentStore::ReadMetadata(
     AttachmentStore::Component component,
     const AttachmentStore::ReadMetadataCallback& callback) {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   AttachmentStore::Result result_code = AttachmentStore::SUCCESS;
   std::unique_ptr<AttachmentMetadataList> metadata_list(
       new AttachmentMetadataList());
diff --git a/components/sync/engine/attachments/in_memory_attachment_store.h b/components/sync/engine/attachments/in_memory_attachment_store.h
index 831d647..e5f1e67 100644
--- a/components/sync/engine/attachments/in_memory_attachment_store.h
+++ b/components/sync/engine/attachments/in_memory_attachment_store.h
@@ -10,7 +10,7 @@
 
 #include "base/macros.h"
 #include "base/memory/ref_counted.h"
-#include "base/threading/non_thread_safe.h"
+#include "base/sequence_checker.h"
 #include "components/sync/engine/attachments/attachment_store_backend.h"
 #include "components/sync/model/attachments/attachment.h"
 #include "components/sync/model/attachments/attachment_id.h"
@@ -25,8 +25,7 @@
 // An in-memory implementation of AttachmentStore used for testing.
 // InMemoryAttachmentStore is not threadsafe, it lives on backend thread and
 // posts callbacks with results on |callback_task_runner|.
-class InMemoryAttachmentStore : public AttachmentStoreBackend,
-                                public base::NonThreadSafe {
+class InMemoryAttachmentStore : public AttachmentStoreBackend {
  public:
   InMemoryAttachmentStore(
       const scoped_refptr<base::SequencedTaskRunner>& callback_task_runner);
@@ -67,6 +66,8 @@
   using AttachmentEntryMap = std::map<AttachmentId, AttachmentEntry>;
   AttachmentEntryMap attachments_;
 
+  SEQUENCE_CHECKER(sequence_checker_);
+
   DISALLOW_COPY_AND_ASSIGN(InMemoryAttachmentStore);
 };
 
diff --git a/components/sync/engine/attachments/on_disk_attachment_store.cc b/components/sync/engine/attachments/on_disk_attachment_store.cc
index 5ad339d4..e4f083b 100644
--- a/components/sync/engine/attachments/on_disk_attachment_store.cc
+++ b/components/sync/engine/attachments/on_disk_attachment_store.cc
@@ -154,11 +154,13 @@
     const base::FilePath& path)
     : AttachmentStoreBackend(callback_task_runner), path_(path) {}
 
-OnDiskAttachmentStore::~OnDiskAttachmentStore() {}
+OnDiskAttachmentStore::~OnDiskAttachmentStore() {
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+}
 
 void OnDiskAttachmentStore::Init(
     const AttachmentStore::InitCallback& callback) {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   AttachmentStore::Result result_code = OpenOrCreate(path_);
   UMA_HISTOGRAM_ENUMERATION("Sync.Attachments.StoreInitResult", result_code,
                             AttachmentStore::RESULT_SIZE);
@@ -169,7 +171,7 @@
     AttachmentStore::Component component,
     const AttachmentIdList& ids,
     const AttachmentStore::ReadCallback& callback) {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   std::unique_ptr<AttachmentMap> result_map(new AttachmentMap());
   std::unique_ptr<AttachmentIdList> unavailable_attachments(
       new AttachmentIdList());
@@ -203,7 +205,7 @@
     AttachmentStore::Component component,
     const AttachmentList& attachments,
     const AttachmentStore::WriteCallback& callback) {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   AttachmentStore::Result result_code =
       AttachmentStore::STORE_INITIALIZATION_FAILED;
 
@@ -221,7 +223,7 @@
 
 void OnDiskAttachmentStore::SetReference(AttachmentStore::Component component,
                                          const AttachmentIdList& ids) {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   if (!db_)
     return;
   attachment_store_pb::RecordMetadata::Component proto_component =
@@ -239,7 +241,7 @@
     AttachmentStore::Component component,
     const AttachmentIdList& ids,
     const AttachmentStore::DropCallback& callback) {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   AttachmentStore::Result result_code =
       AttachmentStore::STORE_INITIALIZATION_FAILED;
   if (db_) {
@@ -279,7 +281,7 @@
     AttachmentStore::Component component,
     const AttachmentIdList& ids,
     const AttachmentStore::ReadMetadataCallback& callback) {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   AttachmentStore::Result result_code =
       AttachmentStore::STORE_INITIALIZATION_FAILED;
   std::unique_ptr<AttachmentMetadataList> metadata_list(
@@ -306,7 +308,7 @@
 void OnDiskAttachmentStore::ReadMetadata(
     AttachmentStore::Component component,
     const AttachmentStore::ReadMetadataCallback& callback) {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   AttachmentStore::Result result_code =
       AttachmentStore::STORE_INITIALIZATION_FAILED;
   std::unique_ptr<AttachmentMetadataList> metadata_list(
diff --git a/components/sync/engine/attachments/on_disk_attachment_store.h b/components/sync/engine/attachments/on_disk_attachment_store.h
index 9e2512f3..af63ecf 100644
--- a/components/sync/engine/attachments/on_disk_attachment_store.h
+++ b/components/sync/engine/attachments/on_disk_attachment_store.h
@@ -11,7 +11,7 @@
 #include "base/files/file_path.h"
 #include "base/macros.h"
 #include "base/memory/ref_counted.h"
-#include "base/threading/non_thread_safe.h"
+#include "base/sequence_checker.h"
 #include "components/sync/engine/attachments/attachment_store_backend.h"
 #include "components/sync/model/attachments/attachment.h"
 #include "components/sync/model/attachments/attachment_id.h"
@@ -33,8 +33,7 @@
 
 // On-disk implementation of AttachmentStore. Stores attachments in leveldb
 // database in |path| directory.
-class OnDiskAttachmentStore : public AttachmentStoreBackend,
-                              public base::NonThreadSafe {
+class OnDiskAttachmentStore : public AttachmentStoreBackend {
  public:
   // Constructs attachment store.
   OnDiskAttachmentStore(
@@ -99,6 +98,8 @@
   const base::FilePath path_;
   std::unique_ptr<leveldb::DB> db_;
 
+  SEQUENCE_CHECKER(sequence_checker_);
+
   DISALLOW_COPY_AND_ASSIGN(OnDiskAttachmentStore);
 };
 
diff --git a/components/sync/engine_impl/attachments/attachment_downloader_impl.cc b/components/sync/engine_impl/attachments/attachment_downloader_impl.cc
index 2651c581..8f98019 100644
--- a/components/sync/engine_impl/attachments/attachment_downloader_impl.cc
+++ b/components/sync/engine_impl/attachments/attachment_downloader_impl.cc
@@ -76,12 +76,14 @@
   DCHECK(!raw_store_birthday_.empty());
 }
 
-AttachmentDownloaderImpl::~AttachmentDownloaderImpl() {}
+AttachmentDownloaderImpl::~AttachmentDownloaderImpl() {
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+}
 
 void AttachmentDownloaderImpl::DownloadAttachment(
     const AttachmentId& attachment_id,
     const DownloadCallback& callback) {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
 
   AttachmentUrl url = AttachmentUploaderImpl::GetURLForAttachmentId(
                           sync_service_url_, attachment_id)
@@ -107,7 +109,7 @@
     const OAuth2TokenService::Request* request,
     const std::string& access_token,
     const base::Time& expiration_time) {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   DCHECK(request == access_token_request_.get());
   access_token_request_.reset();
   StateList::const_iterator iter;
@@ -127,7 +129,7 @@
 void AttachmentDownloaderImpl::OnGetTokenFailure(
     const OAuth2TokenService::Request* request,
     const GoogleServiceAuthError& error) {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   DCHECK(request == access_token_request_.get());
   access_token_request_.reset();
   StateList::const_iterator iter;
@@ -149,7 +151,7 @@
 
 void AttachmentDownloaderImpl::OnURLFetchComplete(
     const net::URLFetcher* source) {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
 
   // Find DownloadState by url.
   AttachmentUrl url = source->GetOriginalURL().spec();
diff --git a/components/sync/engine_impl/attachments/attachment_downloader_impl.h b/components/sync/engine_impl/attachments/attachment_downloader_impl.h
index 2a4cef8a..56b2f6f 100644
--- a/components/sync/engine_impl/attachments/attachment_downloader_impl.h
+++ b/components/sync/engine_impl/attachments/attachment_downloader_impl.h
@@ -14,7 +14,7 @@
 
 #include "base/gtest_prod_util.h"
 #include "base/macros.h"
-#include "base/threading/non_thread_safe.h"
+#include "base/sequence_checker.h"
 #include "components/sync/base/model_type.h"
 #include "components/sync/engine/attachments/attachment_downloader.h"
 #include "google_apis/gaia/oauth2_token_service_request.h"
@@ -31,8 +31,7 @@
 // An implementation of AttachmentDownloader.
 class AttachmentDownloaderImpl : public AttachmentDownloader,
                                  public OAuth2TokenService::Consumer,
-                                 public net::URLFetcherDelegate,
-                                 public base::NonThreadSafe {
+                                 public net::URLFetcherDelegate {
  public:
   // |sync_service_url| is the URL of the sync service.
   //
@@ -122,6 +121,8 @@
 
   ModelType model_type_;
 
+  SEQUENCE_CHECKER(sequence_checker_);
+
   DISALLOW_COPY_AND_ASSIGN(AttachmentDownloaderImpl);
 };
 
diff --git a/components/sync/engine_impl/attachments/attachment_downloader_impl_unittest.cc b/components/sync/engine_impl/attachments/attachment_downloader_impl_unittest.cc
index 5c801306..5a3c42a6 100644
--- a/components/sync/engine_impl/attachments/attachment_downloader_impl_unittest.cc
+++ b/components/sync/engine_impl/attachments/attachment_downloader_impl_unittest.cc
@@ -13,6 +13,7 @@
 #include "base/memory/weak_ptr.h"
 #include "base/message_loop/message_loop.h"
 #include "base/run_loop.h"
+#include "base/sequence_checker.h"
 #include "base/single_thread_task_runner.h"
 #include "base/test/histogram_tester.h"
 #include "base/threading/thread_task_runner_handle.h"
@@ -105,8 +106,7 @@
 }
 
 class TokenServiceProvider
-    : public OAuth2TokenServiceRequest::TokenServiceProvider,
-      base::NonThreadSafe {
+    : public OAuth2TokenServiceRequest::TokenServiceProvider {
  public:
   explicit TokenServiceProvider(OAuth2TokenService* token_service);
 
@@ -120,6 +120,8 @@
 
   scoped_refptr<base::SingleThreadTaskRunner> task_runner_;
   OAuth2TokenService* token_service_;
+
+  SEQUENCE_CHECKER(sequence_checker_);
 };
 
 TokenServiceProvider::TokenServiceProvider(OAuth2TokenService* token_service)
@@ -128,7 +130,9 @@
   DCHECK(token_service_);
 }
 
-TokenServiceProvider::~TokenServiceProvider() {}
+TokenServiceProvider::~TokenServiceProvider() {
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+}
 
 scoped_refptr<base::SingleThreadTaskRunner>
 TokenServiceProvider::GetTokenServiceTaskRunner() {
diff --git a/components/sync/engine_impl/attachments/attachment_uploader_impl.cc b/components/sync/engine_impl/attachments/attachment_uploader_impl.cc
index 7ff3d63..ce3be82 100644
--- a/components/sync/engine_impl/attachments/attachment_uploader_impl.cc
+++ b/components/sync/engine_impl/attachments/attachment_uploader_impl.cc
@@ -41,9 +41,9 @@
 namespace syncer {
 
 // Encapsulates all the state associated with a single upload.
-class AttachmentUploaderImpl::UploadState : public net::URLFetcherDelegate,
-                                            public OAuth2TokenService::Consumer,
-                                            public base::NonThreadSafe {
+class AttachmentUploaderImpl::UploadState
+    : public net::URLFetcherDelegate,
+      public OAuth2TokenService::Consumer {
  public:
   // Construct an UploadState.
   //
@@ -117,6 +117,8 @@
   std::unique_ptr<OAuth2TokenServiceRequest> access_token_request_;
   ModelType model_type_;
 
+  SEQUENCE_CHECKER(sequence_checker_);
+
   DISALLOW_COPY_AND_ASSIGN(UploadState);
 };
 
@@ -156,25 +158,25 @@
 AttachmentUploaderImpl::UploadState::~UploadState() {}
 
 bool AttachmentUploaderImpl::UploadState::IsStopped() const {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   return is_stopped_;
 }
 
 void AttachmentUploaderImpl::UploadState::AddUserCallback(
     const UploadCallback& user_callback) {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   DCHECK(!is_stopped_);
   user_callbacks_.push_back(user_callback);
 }
 
 const Attachment& AttachmentUploaderImpl::UploadState::GetAttachment() {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   return attachment_;
 }
 
 void AttachmentUploaderImpl::UploadState::OnURLFetchComplete(
     const net::URLFetcher* source) {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   if (is_stopped_) {
     return;
   }
@@ -207,7 +209,7 @@
     const OAuth2TokenService::Request* request,
     const std::string& access_token,
     const base::Time& expiration_time) {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   if (is_stopped_) {
     return;
   }
@@ -266,7 +268,7 @@
 void AttachmentUploaderImpl::UploadState::OnGetTokenFailure(
     const OAuth2TokenService::Request* request,
     const GoogleServiceAuthError& error) {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   if (is_stopped_) {
     return;
   }
@@ -319,7 +321,7 @@
       raw_store_birthday_(store_birthday),
       model_type_(model_type),
       weak_ptr_factory_(this) {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   DCHECK(!account_id.empty());
   DCHECK(!scopes.empty());
   DCHECK(token_service_provider_.get());
@@ -327,12 +329,12 @@
 }
 
 AttachmentUploaderImpl::~AttachmentUploaderImpl() {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
 }
 
 void AttachmentUploaderImpl::UploadAttachment(const Attachment& attachment,
                                               const UploadCallback& callback) {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   const AttachmentId attachment_id = attachment.GetId();
   const std::string unique_id = attachment_id.GetProto().unique_id();
   DCHECK(!unique_id.empty());
diff --git a/components/sync/engine_impl/attachments/attachment_uploader_impl.h b/components/sync/engine_impl/attachments/attachment_uploader_impl.h
index 90a27800..3d59d12 100644
--- a/components/sync/engine_impl/attachments/attachment_uploader_impl.h
+++ b/components/sync/engine_impl/attachments/attachment_uploader_impl.h
@@ -12,7 +12,7 @@
 #include <unordered_map>
 
 #include "base/macros.h"
-#include "base/threading/non_thread_safe.h"
+#include "base/sequence_checker.h"
 #include "components/sync/base/model_type.h"
 #include "components/sync/engine/attachments/attachment_uploader.h"
 #include "google_apis/gaia/oauth2_token_service_request.h"
@@ -27,8 +27,7 @@
 namespace syncer {
 
 // An implementation of AttachmentUploader.
-class AttachmentUploaderImpl : public AttachmentUploader,
-                               public base::NonThreadSafe {
+class AttachmentUploaderImpl : public AttachmentUploader {
  public:
   // |sync_service_url| is the URL of the sync service.
   //
@@ -96,6 +95,8 @@
   StateMap state_map_;
   ModelType model_type_;
 
+  SEQUENCE_CHECKER(sequence_checker_);
+
   // Must be last data member.
   base::WeakPtrFactory<AttachmentUploaderImpl> weak_ptr_factory_;
 
diff --git a/components/sync/engine_impl/attachments/attachment_uploader_impl_unittest.cc b/components/sync/engine_impl/attachments/attachment_uploader_impl_unittest.cc
index cc226e8..fd9e7f1 100644
--- a/components/sync/engine_impl/attachments/attachment_uploader_impl_unittest.cc
+++ b/components/sync/engine_impl/attachments/attachment_uploader_impl_unittest.cc
@@ -15,6 +15,7 @@
 #include "base/memory/ref_counted_memory.h"
 #include "base/message_loop/message_loop.h"
 #include "base/run_loop.h"
+#include "base/sequence_checker.h"
 #include "base/single_thread_task_runner.h"
 #include "base/strings/string_number_conversions.h"
 #include "base/strings/stringprintf.h"
@@ -144,8 +145,7 @@
 }
 
 class TokenServiceProvider
-    : public OAuth2TokenServiceRequest::TokenServiceProvider,
-      base::NonThreadSafe {
+    : public OAuth2TokenServiceRequest::TokenServiceProvider {
  public:
   explicit TokenServiceProvider(OAuth2TokenService* token_service);
 
@@ -159,6 +159,8 @@
 
   scoped_refptr<base::SingleThreadTaskRunner> task_runner_;
   OAuth2TokenService* token_service_;
+
+  SEQUENCE_CHECKER(sequence_checker_);
 };
 
 TokenServiceProvider::TokenServiceProvider(OAuth2TokenService* token_service)
@@ -167,7 +169,9 @@
   DCHECK(token_service_);
 }
 
-TokenServiceProvider::~TokenServiceProvider() {}
+TokenServiceProvider::~TokenServiceProvider() {
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+}
 
 scoped_refptr<base::SingleThreadTaskRunner>
 TokenServiceProvider::GetTokenServiceTaskRunner() {
@@ -183,13 +187,13 @@
 //
 // This fixture provides an embedded HTTP server and a mock OAuth2 token service
 // for interacting with AttachmentUploaderImpl
-class AttachmentUploaderImplTest : public testing::Test,
-                                   public base::NonThreadSafe {
+class AttachmentUploaderImplTest : public testing::Test {
  public:
   void OnRequestReceived(const HttpRequest& request);
 
  protected:
   AttachmentUploaderImplTest();
+  ~AttachmentUploaderImplTest() override;
   void SetUp() override;
   void TearDown() override;
 
@@ -228,6 +232,8 @@
   std::vector<AttachmentId> attachment_ids_;
   std::unique_ptr<MockOAuth2TokenService> token_service_;
 
+  SEQUENCE_CHECKER(sequence_checker_);
+
   // Must be last data member.
   base::WeakPtrFactory<AttachmentUploaderImplTest> weak_ptr_factory_;
 };
@@ -235,7 +241,7 @@
 // Handles HTTP requests received by the EmbeddedTestServer.
 //
 // Responds with HTTP_OK by default.  See |SetStatusCode|.
-class RequestHandler : public base::NonThreadSafe {
+class RequestHandler {
  public:
   // Construct a RequestHandler that will PostTask to |test| using
   // |test_task_runner|.
@@ -260,18 +266,24 @@
 
   scoped_refptr<base::SingleThreadTaskRunner> test_task_runner_;
   base::WeakPtr<AttachmentUploaderImplTest> test_;
+
+  SEQUENCE_CHECKER(sequence_checker_);
 };
 
 AttachmentUploaderImplTest::AttachmentUploaderImplTest()
     : weak_ptr_factory_(this) {}
 
+AttachmentUploaderImplTest::~AttachmentUploaderImplTest() {
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+}
+
 void AttachmentUploaderImplTest::OnRequestReceived(const HttpRequest& request) {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   http_requests_received_.push_back(request);
 }
 
 void AttachmentUploaderImplTest::SetUp() {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   request_handler_ = base::MakeUnique<RequestHandler>(
       message_loop_.task_runner(), weak_ptr_factory_.GetWeakPtr());
   url_request_context_getter_ =
@@ -359,7 +371,7 @@
 void AttachmentUploaderImplTest::UploadDone(
     const AttachmentUploader::UploadResult& result,
     const AttachmentId& attachment_id) {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   upload_results_.push_back(result);
   attachment_ids_.push_back(attachment_id);
   DCHECK(!signal_upload_done_.is_null());
@@ -372,16 +384,14 @@
     : status_code_(net::HTTP_OK),
       test_task_runner_(test_task_runner),
       test_(test) {
-  DetachFromThread();
+  DETACH_FROM_SEQUENCE(sequence_checker_);
 }
 
-RequestHandler::~RequestHandler() {
-  DetachFromThread();
-}
+RequestHandler::~RequestHandler() = default;
 
 std::unique_ptr<HttpResponse> RequestHandler::HandleRequest(
     const HttpRequest& request) {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   test_task_runner_->PostTask(
       FROM_HERE, base::Bind(&AttachmentUploaderImplTest::OnRequestReceived,
                             test_, request));
diff --git a/components/sync/engine_impl/js_mutation_event_observer.cc b/components/sync/engine_impl/js_mutation_event_observer.cc
index 2554b1aa..7b174482 100644
--- a/components/sync/engine_impl/js_mutation_event_observer.cc
+++ b/components/sync/engine_impl/js_mutation_event_observer.cc
@@ -18,7 +18,7 @@
 JsMutationEventObserver::JsMutationEventObserver() : weak_ptr_factory_(this) {}
 
 JsMutationEventObserver::~JsMutationEventObserver() {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
 }
 
 base::WeakPtr<JsMutationEventObserver> JsMutationEventObserver::AsWeakPtr() {
@@ -82,7 +82,7 @@
 void JsMutationEventObserver::OnTransactionWrite(
     const syncable::ImmutableWriteTransactionInfo& write_transaction_info,
     ModelTypeSet models_with_changes) {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   if (!event_handler_.IsInitialized()) {
     return;
   }
diff --git a/components/sync/engine_impl/js_mutation_event_observer.h b/components/sync/engine_impl/js_mutation_event_observer.h
index ed3d81e..09c314e 100644
--- a/components/sync/engine_impl/js_mutation_event_observer.h
+++ b/components/sync/engine_impl/js_mutation_event_observer.h
@@ -12,7 +12,7 @@
 #include "base/compiler_specific.h"
 #include "base/macros.h"
 #include "base/memory/weak_ptr.h"
-#include "base/threading/non_thread_safe.h"
+#include "base/sequence_checker.h"
 #include "components/sync/base/weak_handle.h"
 #include "components/sync/engine/sync_manager.h"
 #include "components/sync/syncable/transaction_observer.h"
@@ -29,8 +29,7 @@
 // Observes all change- and transaction-related events and routes a
 // summarized version to a JsEventHandler.
 class JsMutationEventObserver : public SyncManager::ChangeObserver,
-                                public syncable::TransactionObserver,
-                                public base::NonThreadSafe {
+                                public syncable::TransactionObserver {
  public:
   JsMutationEventObserver();
 
@@ -60,6 +59,8 @@
                      const std::string& name,
                      const JsEventDetails& details);
 
+  SEQUENCE_CHECKER(sequence_checker_);
+
   base::WeakPtrFactory<JsMutationEventObserver> weak_ptr_factory_;
 
   DISALLOW_COPY_AND_ASSIGN(JsMutationEventObserver);
diff --git a/components/sync/engine_impl/sync_scheduler_impl.cc b/components/sync/engine_impl/sync_scheduler_impl.cc
index c2055eb..58d3e57 100644
--- a/components/sync/engine_impl/sync_scheduler_impl.cc
+++ b/components/sync/engine_impl/sync_scheduler_impl.cc
@@ -148,13 +148,13 @@
       weak_ptr_factory_(this) {}
 
 SyncSchedulerImpl::~SyncSchedulerImpl() {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
 
   Stop();
 }
 
 void SyncSchedulerImpl::OnCredentialsUpdated() {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
 
   if (HttpResponse::SYNC_AUTH_ERROR ==
       cycle_context_->connection_manager()->server_status()) {
@@ -163,7 +163,7 @@
 }
 
 void SyncSchedulerImpl::OnConnectionStatusChange() {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
 
   if (HttpResponse::CONNECTION_UNAVAILABLE ==
       cycle_context_->connection_manager()->server_status()) {
@@ -189,7 +189,7 @@
 }
 
 void SyncSchedulerImpl::Start(Mode mode, base::Time last_poll_time) {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
 
   std::string thread_name = base::PlatformThread::GetName();
   if (thread_name.empty())
@@ -242,7 +242,7 @@
 }
 
 void SyncSchedulerImpl::SendInitialSnapshot() {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
 
   SyncCycleEvent event(SyncCycleEvent::STATUS_CHANGED);
   event.snapshot = SyncCycle(cycle_context_, this).TakeSnapshot();
@@ -252,7 +252,7 @@
 
 void SyncSchedulerImpl::ScheduleConfiguration(
     const ConfigurationParams& params) {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   DCHECK(IsConfigRelatedUpdateSourceValue(params.source));
   DCHECK_EQ(CONFIGURATION_MODE, mode_);
   DCHECK(!params.ready_task.is_null());
@@ -274,7 +274,7 @@
 }
 
 void SyncSchedulerImpl::ScheduleClearServerData(const ClearParams& params) {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   DCHECK_EQ(CLEAR_SERVER_DATA_MODE, mode_);
   DCHECK(!pending_configure_params_);
   DCHECK(!params.report_success_task.is_null());
@@ -285,7 +285,7 @@
 }
 
 bool SyncSchedulerImpl::CanRunJobNow(JobPriority priority) {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
 
   if (IsCurrentlyThrottled()) {
     SDVLOG(1) << "Unable to run a job because we're throttled.";
@@ -307,7 +307,7 @@
 }
 
 bool SyncSchedulerImpl::CanRunNudgeJobNow(JobPriority priority) {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
 
   if (!CanRunJobNow(priority)) {
     SDVLOG(1) << "Unable to run a nudge job right now";
@@ -332,7 +332,7 @@
 void SyncSchedulerImpl::ScheduleLocalNudge(
     ModelTypeSet types,
     const tracked_objects::Location& nudge_location) {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   DCHECK(!types.Empty());
 
   SDVLOG_LOC(nudge_location, 2) << "Scheduling sync because of local change to "
@@ -345,7 +345,7 @@
 void SyncSchedulerImpl::ScheduleLocalRefreshRequest(
     ModelTypeSet types,
     const tracked_objects::Location& nudge_location) {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   DCHECK(!types.Empty());
 
   SDVLOG_LOC(nudge_location, 2)
@@ -359,7 +359,7 @@
     ModelType model_type,
     std::unique_ptr<InvalidationInterface> invalidation,
     const tracked_objects::Location& nudge_location) {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
 
   SDVLOG_LOC(nudge_location, 2)
       << "Scheduling sync because we received invalidation for "
@@ -370,7 +370,7 @@
 }
 
 void SyncSchedulerImpl::ScheduleInitialSyncNudge(ModelType model_type) {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
 
   SDVLOG(2) << "Scheduling non-blocking initial sync for "
             << ModelTypeToString(model_type);
@@ -383,7 +383,7 @@
 void SyncSchedulerImpl::ScheduleNudgeImpl(
     const TimeDelta& delay,
     const tracked_objects::Location& nudge_location) {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   CHECK(!syncer_->IsSyncing());
 
   if (!started_) {
@@ -423,13 +423,13 @@
 }
 
 void SyncSchedulerImpl::SetDefaultNudgeDelay(TimeDelta delay_ms) {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
 
   nudge_tracker_.SetDefaultNudgeDelay(delay_ms);
 }
 
 void SyncSchedulerImpl::DoNudgeSyncCycleJob(JobPriority priority) {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   DCHECK(CanRunNudgeJobNow(priority));
 
   DVLOG(2) << "Will run normal mode sync cycle with types "
@@ -457,7 +457,7 @@
 }
 
 void SyncSchedulerImpl::DoConfigurationSyncCycleJob(JobPriority priority) {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   DCHECK_EQ(mode_, CONFIGURATION_MODE);
   DCHECK(pending_configure_params_ != nullptr);
 
@@ -490,7 +490,7 @@
 }
 
 void SyncSchedulerImpl::DoClearServerDataSyncCycleJob(JobPriority priority) {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   DCHECK_EQ(mode_, CLEAR_SERVER_DATA_MODE);
 
   if (!CanRunJobNow(priority)) {
@@ -556,7 +556,7 @@
 }
 
 void SyncSchedulerImpl::UpdateNudgeTimeRecords(ModelTypeSet types) {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
 
   TimeTicks now = TimeTicks::Now();
   // Update timing information for how often datatypes are triggering nudges.
@@ -581,7 +581,7 @@
 }
 
 void SyncSchedulerImpl::AdjustPolling(PollAdjustType type) {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
 
   if (!started_)
     return;
@@ -663,7 +663,7 @@
 }
 
 void SyncSchedulerImpl::Stop() {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   SDVLOG(2) << "Stop called";
 
   // Kill any in-flight method calls.
@@ -695,7 +695,7 @@
 }
 
 void SyncSchedulerImpl::TrySyncCycleJobImpl() {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
 
   JobPriority priority = next_sync_cycle_job_priority_;
   next_sync_cycle_job_priority_ = NORMAL_PRIORITY;
@@ -730,7 +730,7 @@
 }
 
 void SyncSchedulerImpl::PollTimerCallback() {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   CHECK(!syncer_->IsSyncing());
 
   TrySyncCycleJob();
@@ -741,7 +741,7 @@
 }
 
 void SyncSchedulerImpl::Unthrottle() {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   DCHECK_EQ(WaitInterval::THROTTLED, wait_interval_->mode);
 
   // We're no longer throttled, so clear the wait interval.
@@ -758,7 +758,7 @@
 }
 
 void SyncSchedulerImpl::OnTypesUnblocked() {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
 
   nudge_tracker_.UpdateTypeThrottlingAndBackoffState();
   NotifyBlockedTypesChanged(nudge_tracker_.GetBlockedTypes());
@@ -815,14 +815,14 @@
 }
 
 bool SyncSchedulerImpl::IsBackingOff() const {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
 
   return wait_interval_.get() &&
          wait_interval_->mode == WaitInterval::EXPONENTIAL_BACKOFF;
 }
 
 void SyncSchedulerImpl::OnThrottled(const TimeDelta& throttle_duration) {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
 
   wait_interval_ = base::MakeUnique<WaitInterval>(WaitInterval::THROTTLED,
                                                   throttle_duration);
@@ -835,7 +835,7 @@
 
 void SyncSchedulerImpl::OnTypesThrottled(ModelTypeSet types,
                                          const TimeDelta& throttle_duration) {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
 
   TimeTicks now = TimeTicks::Now();
 
@@ -847,7 +847,7 @@
 }
 
 void SyncSchedulerImpl::OnTypesBackedOff(ModelTypeSet types) {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
 
   TimeTicks now = TimeTicks::Now();
 
@@ -868,7 +868,7 @@
 }
 
 bool SyncSchedulerImpl::IsCurrentlyThrottled() {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
 
   return wait_interval_.get() &&
          wait_interval_->mode == WaitInterval::THROTTLED;
@@ -876,7 +876,7 @@
 
 void SyncSchedulerImpl::OnReceivedShortPollIntervalUpdate(
     const TimeDelta& new_interval) {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
 
   if (new_interval == syncer_short_poll_interval_seconds_)
     return;
@@ -888,7 +888,7 @@
 
 void SyncSchedulerImpl::OnReceivedLongPollIntervalUpdate(
     const TimeDelta& new_interval) {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
 
   if (new_interval == syncer_long_poll_interval_seconds_)
     return;
@@ -900,13 +900,13 @@
 
 void SyncSchedulerImpl::OnReceivedCustomNudgeDelays(
     const std::map<ModelType, TimeDelta>& nudge_delays) {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
 
   nudge_tracker_.OnReceivedCustomNudgeDelays(nudge_delays);
 }
 
 void SyncSchedulerImpl::OnReceivedClientInvalidationHintBufferSize(int size) {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
 
   if (size > 0)
     nudge_tracker_.SetHintBufferSize(size);
@@ -916,7 +916,7 @@
 
 void SyncSchedulerImpl::OnSyncProtocolError(
     const SyncProtocolError& sync_protocol_error) {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
 
   if (ShouldRequestEarlyExit(sync_protocol_error)) {
     SDVLOG(2) << "Sync Scheduler requesting early exit.";
@@ -930,7 +930,7 @@
 }
 
 void SyncSchedulerImpl::OnReceivedGuRetryDelay(const TimeDelta& delay) {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
 
   nudge_tracker_.SetNextRetryTime(TimeTicks::Now() + delay);
   retry_timer_.Start(FROM_HERE, delay, this,
@@ -938,14 +938,14 @@
 }
 
 void SyncSchedulerImpl::OnReceivedMigrationRequest(ModelTypeSet types) {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
 
   for (auto& observer : *cycle_context_->listeners())
     observer.OnMigrationRequested(types);
 }
 
 void SyncSchedulerImpl::SetNotificationsEnabled(bool notifications_enabled) {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
 
   cycle_context_->set_notifications_enabled(notifications_enabled);
   if (notifications_enabled)
diff --git a/components/sync/engine_impl/sync_scheduler_impl.h b/components/sync/engine_impl/sync_scheduler_impl.h
index 92572f8f..d83b038 100644
--- a/components/sync/engine_impl/sync_scheduler_impl.h
+++ b/components/sync/engine_impl/sync_scheduler_impl.h
@@ -15,7 +15,7 @@
 #include "base/gtest_prod_util.h"
 #include "base/macros.h"
 #include "base/memory/weak_ptr.h"
-#include "base/threading/non_thread_safe.h"
+#include "base/sequence_checker.h"
 #include "base/time/time.h"
 #include "base/timer/timer.h"
 #include "components/sync/engine/polling_constants.h"
@@ -32,7 +32,7 @@
 class BackoffDelayProvider;
 struct ModelNeutralState;
 
-class SyncSchedulerImpl : public SyncScheduler, public base::NonThreadSafe {
+class SyncSchedulerImpl : public SyncScheduler {
  public:
   // |name| is a display string to identify the syncer thread.  Takes
   // |ownership of |syncer| and |delay_provider|.
@@ -294,6 +294,8 @@
   // Dictates if the scheduler should wait for authentication to happen or not.
   bool ignore_auth_credentials_;
 
+  SEQUENCE_CHECKER(sequence_checker_);
+
   base::WeakPtrFactory<SyncSchedulerImpl> weak_ptr_factory_;
 
   DISALLOW_COPY_AND_ASSIGN(SyncSchedulerImpl);
diff --git a/components/sync/model/attachments/attachment_service_proxy_unittest.cc b/components/sync/model/attachments/attachment_service_proxy_unittest.cc
index 52faba4..13bee5a 100644
--- a/components/sync/model/attachments/attachment_service_proxy_unittest.cc
+++ b/components/sync/model/attachments/attachment_service_proxy_unittest.cc
@@ -12,10 +12,10 @@
 #include "base/memory/ref_counted_memory.h"
 #include "base/message_loop/message_loop.h"
 #include "base/run_loop.h"
+#include "base/sequence_checker.h"
 #include "base/single_thread_task_runner.h"
 #include "base/synchronization/lock.h"
 #include "base/synchronization/waitable_event.h"
-#include "base/threading/non_thread_safe.h"
 #include "base/threading/thread.h"
 #include "base/threading/thread_task_runner_handle.h"
 #include "components/sync/base/model_type.h"
@@ -26,21 +26,22 @@
 
 // A stub implementation of AttachmentService that counts the number of times
 // its methods are invoked.
-class StubAttachmentService : public AttachmentService,
-                              public base::NonThreadSafe {
+class StubAttachmentService : public AttachmentService {
  public:
   StubAttachmentService() : call_count_(0), weak_ptr_factory_(this) {
     // DetachFromThread because we will be constructed in one thread and
     // used/destroyed in another.
-    DetachFromThread();
+    DETACH_FROM_SEQUENCE(sequence_checker_);
   }
 
-  ~StubAttachmentService() override {}
+  ~StubAttachmentService() override {
+    DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+  }
 
   void GetOrDownloadAttachments(
       const AttachmentIdList& attachment_ids,
       const GetOrDownloadCallback& callback) override {
-    CalledOnValidThread();
+    DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
     Increment();
     std::unique_ptr<AttachmentMap> attachments(new AttachmentMap());
     base::ThreadTaskRunnerHandle::Get()->PostTask(
@@ -50,7 +51,7 @@
   }
 
   void UploadAttachments(const AttachmentIdList& attachments_ids) override {
-    CalledOnValidThread();
+    DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
     Increment();
   }
 
@@ -76,15 +77,16 @@
     base::AutoLock lock(mutex_);
     ++call_count_;
   }
+
+  SEQUENCE_CHECKER(sequence_checker_);
 };
 
-class AttachmentServiceProxyTest : public testing::Test,
-                                   public base::NonThreadSafe {
+class AttachmentServiceProxyTest : public testing::Test {
  protected:
   AttachmentServiceProxyTest() {}
 
   void SetUp() override {
-    CalledOnValidThread();
+    DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
     stub_thread_ =
         base::MakeUnique<base::Thread>("attachment service stub thread");
     stub_thread_->Start();
@@ -111,7 +113,7 @@
   // a GetOrDownloadCallback
   void IncrementGetOrDownload(const AttachmentService::GetOrDownloadResult&,
                               std::unique_ptr<AttachmentMap>) {
-    CalledOnValidThread();
+    DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
     ++count_callback_get_or_download_;
   }
 
@@ -133,6 +135,8 @@
 
   // number of times callback_get_or_download_ was invoked
   int count_callback_get_or_download_;
+
+  SEQUENCE_CHECKER(sequence_checker_);
 };
 
 // Verify that each of AttachmentServiceProxy's methods are invoked on the stub.
diff --git a/components/sync/model_impl/attachments/attachment_service_impl.cc b/components/sync/model_impl/attachments/attachment_service_impl.cc
index 695e8e4..538c2b1 100644
--- a/components/sync/model_impl/attachments/attachment_service_impl.cc
+++ b/components/sync/model_impl/attachments/attachment_service_impl.cc
@@ -23,8 +23,7 @@
 // GetOrDownloadState tracks completion of these calls and posts callback for
 // consumer once all attachments are either retrieved or reported unavailable.
 class AttachmentServiceImpl::GetOrDownloadState
-    : public base::RefCounted<GetOrDownloadState>,
-      public base::NonThreadSafe {
+    : public base::RefCounted<GetOrDownloadState> {
  public:
   // GetOrDownloadState gets parameter from values passed to
   // AttachmentService::GetOrDownloadAttachments.
@@ -57,6 +56,8 @@
   AttachmentIdSet unavailable_attachments_;
   std::unique_ptr<AttachmentMap> retrieved_attachments_;
 
+  SEQUENCE_CHECKER(sequence_checker_);
+
   DISALLOW_COPY_AND_ASSIGN(GetOrDownloadState);
 };
 
@@ -71,12 +72,12 @@
 }
 
 AttachmentServiceImpl::GetOrDownloadState::~GetOrDownloadState() {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
 }
 
 void AttachmentServiceImpl::GetOrDownloadState::AddAttachment(
     const Attachment& attachment) {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   DCHECK(retrieved_attachments_->find(attachment.GetId()) ==
          retrieved_attachments_->end());
   retrieved_attachments_->insert(
@@ -89,7 +90,7 @@
 
 void AttachmentServiceImpl::GetOrDownloadState::AddUnavailableAttachmentId(
     const AttachmentId& attachment_id) {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   DCHECK(unavailable_attachments_.find(attachment_id) ==
          unavailable_attachments_.end());
   unavailable_attachments_.insert(attachment_id);
@@ -123,7 +124,7 @@
       attachment_downloader_(std::move(attachment_downloader)),
       delegate_(delegate),
       weak_ptr_factory_(this) {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   DCHECK(attachment_store_.get());
 
   // TODO(maniscalco): Observe network connectivity change events.  When the
@@ -139,14 +140,14 @@
 }
 
 AttachmentServiceImpl::~AttachmentServiceImpl() {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   net::NetworkChangeNotifier::RemoveNetworkChangeObserver(this);
 }
 
 void AttachmentServiceImpl::GetOrDownloadAttachments(
     const AttachmentIdList& attachment_ids,
     const GetOrDownloadCallback& callback) {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   scoped_refptr<GetOrDownloadState> state(
       new GetOrDownloadState(attachment_ids, callback));
   // SetModelTypeReference() makes attachments visible for model type.
@@ -205,7 +206,7 @@
 void AttachmentServiceImpl::UploadDone(
     const AttachmentUploader::UploadResult& result,
     const AttachmentId& attachment_id) {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   AttachmentIdList ids;
   ids.push_back(attachment_id);
   switch (result) {
@@ -251,7 +252,7 @@
 }
 
 void AttachmentServiceImpl::BeginUpload(const AttachmentId& attachment_id) {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   AttachmentIdList attachment_ids;
   attachment_ids.push_back(attachment_id);
   attachment_store_->Read(attachment_ids,
@@ -261,7 +262,7 @@
 
 void AttachmentServiceImpl::UploadAttachments(
     const AttachmentIdList& attachment_ids) {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   if (!attachment_uploader_.get()) {
     return;
   }
@@ -284,7 +285,7 @@
     const AttachmentStore::Result& result,
     std::unique_ptr<AttachmentMap> attachments,
     std::unique_ptr<AttachmentIdList> unavailable_attachment_ids) {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   if (!unavailable_attachment_ids->empty()) {
     // TODO(maniscalco): We failed to read some attachments. What should we do
     // now?
diff --git a/components/sync/model_impl/attachments/attachment_service_impl.h b/components/sync/model_impl/attachments/attachment_service_impl.h
index 1db20e9..251a310 100644
--- a/components/sync/model_impl/attachments/attachment_service_impl.h
+++ b/components/sync/model_impl/attachments/attachment_service_impl.h
@@ -11,7 +11,7 @@
 #include "base/macros.h"
 #include "base/memory/ref_counted.h"
 #include "base/memory/weak_ptr.h"
-#include "base/threading/non_thread_safe.h"
+#include "base/sequence_checker.h"
 #include "components/sync/engine/attachments/attachment_downloader.h"
 #include "components/sync/engine/attachments/attachment_uploader.h"
 #include "components/sync/model/attachments/attachment_service.h"
@@ -25,8 +25,7 @@
 // Implementation of AttachmentService.
 class AttachmentServiceImpl
     : public AttachmentService,
-      public net::NetworkChangeNotifier::NetworkChangeObserver,
-      public base::NonThreadSafe {
+      public net::NetworkChangeNotifier::NetworkChangeObserver {
  public:
   // |attachment_store| is required. UploadAttachments reads attachment data
   // from it. Downloaded attachments will be written into it.
@@ -110,6 +109,8 @@
 
   std::unique_ptr<TaskQueue<AttachmentId>> upload_task_queue_;
 
+  SEQUENCE_CHECKER(sequence_checker_);
+
   // Must be last data member.
   base::WeakPtrFactory<AttachmentServiceImpl> weak_ptr_factory_;
 
diff --git a/components/sync/model_impl/attachments/task_queue.h b/components/sync/model_impl/attachments/task_queue.h
index afd602b..cfdfe24 100644
--- a/components/sync/model_impl/attachments/task_queue.h
+++ b/components/sync/model_impl/attachments/task_queue.h
@@ -17,7 +17,7 @@
 #include "base/macros.h"
 #include "base/memory/ptr_util.h"
 #include "base/memory/weak_ptr.h"
-#include "base/threading/non_thread_safe.h"
+#include "base/sequence_checker.h"
 #include "base/threading/thread_task_runner_handle.h"
 #include "base/time/time.h"
 #include "base/timer/timer.h"
@@ -69,7 +69,7 @@
 // }
 //
 template <typename T>
-class TaskQueue : base::NonThreadSafe {
+class TaskQueue {
  public:
   // A callback provided by users of the TaskQueue to handle tasks.
   //
@@ -94,6 +94,8 @@
             const base::TimeDelta& initial_backoff_delay,
             const base::TimeDelta& max_backoff_delay);
 
+  ~TaskQueue();
+
   // Add |task| to the end of the queue.
   //
   // If |task| is already present (as determined by operator==) it is not added.
@@ -157,6 +159,8 @@
   std::unique_ptr<base::Timer> backoff_timer_;
   base::TimeDelta delay_;
 
+  SEQUENCE_CHECKER(sequence_checker_);
+
   // Must be last data member.
   base::WeakPtrFactory<TaskQueue> weak_ptr_factory_;
 
@@ -191,8 +195,13 @@
 }
 
 template <typename T>
+TaskQueue<T>::~TaskQueue() {
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+}
+
+template <typename T>
 void TaskQueue<T>::AddToQueue(const T& task) {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   // Ignore duplicates.
   if (tasks_.find(task) == tasks_.end()) {
     queue_.push_back(task);
@@ -203,7 +212,7 @@
 
 template <typename T>
 void TaskQueue<T>::MarkAsSucceeded(const T& task) {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   FinishTask(task);
   // The task succeeded.  Stop any pending timer, reset (clear) the backoff, and
   // reschedule a dispatch.
@@ -214,7 +223,7 @@
 
 template <typename T>
 void TaskQueue<T>::MarkAsFailed(const T& task) {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   FinishTask(task);
   backoff_entry_->InformOfRequest(false);
   ScheduleDispatch();
@@ -222,7 +231,7 @@
 
 template <typename T>
 void TaskQueue<T>::Cancel(const T& task) {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   FinishTask(task);
   ScheduleDispatch();
 }
@@ -236,14 +245,14 @@
 
 template <typename T>
 void TaskQueue<T>::SetTimerForTest(std::unique_ptr<base::Timer> timer) {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   DCHECK(timer.get());
   backoff_timer_ = std::move(timer);
 }
 
 template <typename T>
 void TaskQueue<T>::FinishTask(const T& task) {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   DCHECK_GE(num_in_progress_, 1);
   --num_in_progress_;
   const size_t num_erased = tasks_.erase(task);
@@ -252,7 +261,7 @@
 
 template <typename T>
 void TaskQueue<T>::ScheduleDispatch() {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   if (backoff_timer_->IsRunning() || !ShouldDispatch()) {
     return;
   }
@@ -263,7 +272,7 @@
 
 template <typename T>
 void TaskQueue<T>::Dispatch() {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   if (!ShouldDispatch()) {
     return;
   }
diff --git a/components/sync/model_impl/model_type_store_impl.cc b/components/sync/model_impl/model_type_store_impl.cc
index 9fd0f825..11debfa 100644
--- a/components/sync/model_impl/model_type_store_impl.cc
+++ b/components/sync/model_impl/model_type_store_impl.cc
@@ -119,7 +119,7 @@
 }
 
 ModelTypeStoreImpl::~ModelTypeStoreImpl() {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   backend_task_runner_->PostTask(
       FROM_HERE, base::Bind(&NoOpForBackendDtor, base::Passed(&backend_)));
 }
@@ -196,7 +196,7 @@
 
 void ModelTypeStoreImpl::ReadData(const IdList& id_list,
                                   const ReadDataCallback& callback) {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   DCHECK(!callback.is_null());
   std::unique_ptr<RecordList> record_list(new RecordList());
   std::unique_ptr<IdList> missing_id_list(new IdList());
@@ -216,12 +216,12 @@
                                       std::unique_ptr<RecordList> record_list,
                                       std::unique_ptr<IdList> missing_id_list,
                                       Result result) {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   callback.Run(result, std::move(record_list), std::move(missing_id_list));
 }
 
 void ModelTypeStoreImpl::ReadAllData(const ReadAllDataCallback& callback) {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   DCHECK(!callback.is_null());
   std::unique_ptr<RecordList> record_list(new RecordList());
   auto task = base::Bind(&ModelTypeStoreBackend::ReadAllRecordsWithPrefix,
@@ -238,12 +238,12 @@
     const ReadAllDataCallback& callback,
     std::unique_ptr<RecordList> record_list,
     Result result) {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   callback.Run(result, std::move(record_list));
 }
 
 void ModelTypeStoreImpl::ReadAllMetadata(const ReadMetadataCallback& callback) {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   DCHECK(!callback.is_null());
 
   // ReadAllMetadata performs two steps sequentially: read all metadata records
@@ -265,7 +265,7 @@
     const ReadMetadataCallback& callback,
     std::unique_ptr<RecordList> metadata_records,
     Result result) {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   if (result != Result::SUCCESS) {
     callback.Run(ModelError(FROM_HERE, "Reading metadata failed."),
                  base::MakeUnique<MetadataBatch>());
@@ -295,7 +295,7 @@
     std::unique_ptr<RecordList> global_metadata_records,
     std::unique_ptr<IdList> missing_id_list,
     Result result) {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
 
   if (result != Result::SUCCESS) {
     callback.Run(ModelError(FROM_HERE, "Reading metadata failed."),
@@ -349,14 +349,14 @@
 
 std::unique_ptr<ModelTypeStore::WriteBatch>
 ModelTypeStoreImpl::CreateWriteBatch() {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   return base::MakeUnique<WriteBatchImpl>(this);
 }
 
 void ModelTypeStoreImpl::CommitWriteBatch(
     std::unique_ptr<WriteBatch> write_batch,
     const CallbackWithResult& callback) {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   DCHECK(!callback.is_null());
   WriteBatchImpl* write_batch_impl =
       static_cast<WriteBatchImpl*>(write_batch.get());
@@ -372,44 +372,44 @@
 void ModelTypeStoreImpl::WriteModificationsDone(
     const CallbackWithResult& callback,
     Result result) {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   callback.Run(result);
 }
 
 void ModelTypeStoreImpl::WriteData(WriteBatch* write_batch,
                                    const std::string& id,
                                    const std::string& value) {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   GetLeveldbWriteBatch(write_batch)->Put(FormatDataKey(id), value);
 }
 
 void ModelTypeStoreImpl::WriteMetadata(WriteBatch* write_batch,
                                        const std::string& id,
                                        const std::string& value) {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   GetLeveldbWriteBatch(write_batch)->Put(FormatMetadataKey(id), value);
 }
 
 void ModelTypeStoreImpl::WriteGlobalMetadata(WriteBatch* write_batch,
                                              const std::string& value) {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   GetLeveldbWriteBatch(write_batch)->Put(global_metadata_key_, value);
 }
 
 void ModelTypeStoreImpl::DeleteData(WriteBatch* write_batch,
                                     const std::string& id) {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   GetLeveldbWriteBatch(write_batch)->Delete(FormatDataKey(id));
 }
 
 void ModelTypeStoreImpl::DeleteMetadata(WriteBatch* write_batch,
                                         const std::string& id) {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   GetLeveldbWriteBatch(write_batch)->Delete(FormatMetadataKey(id));
 }
 
 void ModelTypeStoreImpl::DeleteGlobalMetadata(WriteBatch* write_batch) {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   GetLeveldbWriteBatch(write_batch)->Delete(global_metadata_key_);
 }
 
diff --git a/components/sync/model_impl/model_type_store_impl.h b/components/sync/model_impl/model_type_store_impl.h
index 3870329..3889bec 100644
--- a/components/sync/model_impl/model_type_store_impl.h
+++ b/components/sync/model_impl/model_type_store_impl.h
@@ -10,8 +10,8 @@
 
 #include "base/memory/ref_counted.h"
 #include "base/memory/weak_ptr.h"
+#include "base/sequence_checker.h"
 #include "base/sequenced_task_runner.h"
-#include "base/threading/non_thread_safe.h"
 #include "components/sync/base/model_type.h"
 #include "components/sync/model/model_type_store.h"
 
@@ -26,7 +26,7 @@
 // ModelTypeStoreImpl handles details of store initialization, threading and
 // leveldb key formatting. Actual leveldb IO calls are performed by
 // ModelTypeStoreBackend.
-class ModelTypeStoreImpl : public ModelTypeStore, public base::NonThreadSafe {
+class ModelTypeStoreImpl : public ModelTypeStore {
  public:
   ~ModelTypeStoreImpl() override;
 
@@ -122,6 +122,8 @@
   // Key for this type's global metadata record.
   const std::string global_metadata_key_;
 
+  SEQUENCE_CHECKER(sequence_checker_);
+
   base::WeakPtrFactory<ModelTypeStoreImpl> weak_ptr_factory_;
 };
 
diff --git a/components/sync/model_impl/shared_model_type_processor.cc b/components/sync/model_impl/shared_model_type_processor.cc
index f7ecbde..e24917d 100644
--- a/components/sync/model_impl/shared_model_type_processor.cc
+++ b/components/sync/model_impl/shared_model_type_processor.cc
@@ -33,12 +33,14 @@
   DCHECK(bridge);
 }
 
-SharedModelTypeProcessor::~SharedModelTypeProcessor() = default;
+SharedModelTypeProcessor::~SharedModelTypeProcessor() {
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+}
 
 void SharedModelTypeProcessor::OnSyncStarting(
     const ModelErrorHandler& error_handler,
     const StartCallback& start_callback) {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   DCHECK(!IsConnected());
   DCHECK(error_handler);
   DCHECK(start_callback);
@@ -51,7 +53,7 @@
 
 void SharedModelTypeProcessor::ModelReadyToSync(
     std::unique_ptr<MetadataBatch> batch) {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   DCHECK(waiting_for_metadata_);
   DCHECK(entities_.empty());
 
@@ -117,18 +119,18 @@
 }
 
 bool SharedModelTypeProcessor::IsAllowingChanges() const {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   // Changes can be handled correctly even before pending data is loaded.
   return !waiting_for_metadata_;
 }
 
 bool SharedModelTypeProcessor::IsConnected() const {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   return !!worker_;
 }
 
 void SharedModelTypeProcessor::DisableSync() {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   std::unique_ptr<MetadataChangeList> change_list =
       bridge_->CreateMetadataChangeList();
   for (auto it = entities_.begin(); it != entities_.end(); ++it) {
@@ -144,7 +146,7 @@
 }
 
 void SharedModelTypeProcessor::ReportError(const ModelError& error) {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
 
   // Ignore all errors after the first.
   if (model_error_)
@@ -175,7 +177,7 @@
 
 void SharedModelTypeProcessor::ConnectSync(
     std::unique_ptr<CommitQueue> worker) {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   DVLOG(1) << "Successfully connected " << ModelTypeToString(type_);
 
   worker_ = std::move(worker);
@@ -184,7 +186,7 @@
 }
 
 void SharedModelTypeProcessor::DisconnectSync() {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   DCHECK(IsConnected());
 
   DVLOG(1) << "Disconnecting sync for " << ModelTypeToString(type_);
@@ -199,7 +201,7 @@
 void SharedModelTypeProcessor::Put(const std::string& storage_key,
                                    std::unique_ptr<EntityData> data,
                                    MetadataChangeList* metadata_change_list) {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   DCHECK(IsAllowingChanges());
   DCHECK(data);
   DCHECK(!data->is_deleted());
@@ -234,7 +236,7 @@
 void SharedModelTypeProcessor::Delete(
     const std::string& storage_key,
     MetadataChangeList* metadata_change_list) {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   DCHECK(IsAllowingChanges());
 
   if (!model_type_state_.initial_sync_done()) {
@@ -308,7 +310,7 @@
 void SharedModelTypeProcessor::OnCommitCompleted(
     const sync_pb::ModelTypeState& type_state,
     const CommitResponseDataList& response_list) {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   std::unique_ptr<MetadataChangeList> change_list =
       bridge_->CreateMetadataChangeList();
 
@@ -345,7 +347,7 @@
 void SharedModelTypeProcessor::OnUpdateReceived(
     const sync_pb::ModelTypeState& model_type_state,
     const UpdateResponseDataList& updates) {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   if (!model_type_state_.initial_sync_done()) {
     OnInitialUpdateReceived(model_type_state, updates);
     return;
@@ -604,7 +606,7 @@
 
 void SharedModelTypeProcessor::OnInitialPendingDataLoaded(
     std::unique_ptr<DataBatch> data_batch) {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   DCHECK(waiting_for_pending_data_);
 
   // The model already experienced an error; abort;
@@ -619,7 +621,7 @@
 
 void SharedModelTypeProcessor::OnDataLoadedForReEncryption(
     std::unique_ptr<DataBatch> data_batch) {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   DCHECK(!waiting_for_pending_data_);
 
   ConsumeDataBatch(std::move(data_batch));
diff --git a/components/sync/model_impl/shared_model_type_processor.h b/components/sync/model_impl/shared_model_type_processor.h
index 62c136f..d8b54483 100644
--- a/components/sync/model_impl/shared_model_type_processor.h
+++ b/components/sync/model_impl/shared_model_type_processor.h
@@ -12,7 +12,7 @@
 
 #include "base/memory/weak_ptr.h"
 #include "base/optional.h"
-#include "base/threading/non_thread_safe.h"
+#include "base/sequence_checker.h"
 #include "components/sync/base/model_type.h"
 #include "components/sync/engine/cycle/status_counters.h"
 #include "components/sync/engine/model_type_processor.h"
@@ -36,8 +36,7 @@
 // model type threads. See //docs/sync/uss/shared_model_type_processor.md for a
 // more thorough description.
 class SharedModelTypeProcessor : public ModelTypeProcessor,
-                                 public ModelTypeChangeProcessor,
-                                 base::NonThreadSafe {
+                                 public ModelTypeChangeProcessor {
  public:
   SharedModelTypeProcessor(ModelType type,
                            ModelTypeSyncBridge* bridge,
@@ -211,6 +210,8 @@
   // client tag hash. The other direction can use |entities_|.
   std::map<std::string, std::string> storage_key_to_tag_hash_;
 
+  SEQUENCE_CHECKER(sequence_checker_);
+
   // WeakPtrFactory for this processor which will be sent to sync thread.
   base::WeakPtrFactory<SharedModelTypeProcessor> weak_ptr_factory_;
 
diff --git a/components/sync/syncable/directory_backing_store.cc b/components/sync/syncable/directory_backing_store.cc
index 3714cd90..677ffc5 100644
--- a/components/sync/syncable/directory_backing_store.cc
+++ b/components/sync/syncable/directory_backing_store.cc
@@ -283,6 +283,7 @@
 }
 
 DirectoryBackingStore::~DirectoryBackingStore() {
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
 }
 
 bool DirectoryBackingStore::DeleteEntries(EntryTable from,
@@ -316,7 +317,7 @@
 
 bool DirectoryBackingStore::SaveChanges(
     const Directory::SaveChangesSnapshot& snapshot) {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   DCHECK(db_->is_open());
 
   // Back out early if there is nothing to write.
@@ -1804,7 +1805,7 @@
 
 void DirectoryBackingStore::SetCatastrophicErrorHandler(
     const base::Closure& catastrophic_error_handler) {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   DCHECK(!catastrophic_error_handler.is_null());
   catastrophic_error_handler_ = catastrophic_error_handler;
   sql::Connection::ErrorCallback error_callback =
diff --git a/components/sync/syncable/directory_backing_store.h b/components/sync/syncable/directory_backing_store.h
index b50f2df..149a32f 100644
--- a/components/sync/syncable/directory_backing_store.h
+++ b/components/sync/syncable/directory_backing_store.h
@@ -12,7 +12,7 @@
 
 #include "base/gtest_prod_util.h"
 #include "base/macros.h"
-#include "base/threading/non_thread_safe.h"
+#include "base/sequence_checker.h"
 #include "components/sync/base/model_type.h"
 #include "components/sync/syncable/dir_open_result.h"
 #include "components/sync/syncable/directory.h"
@@ -51,7 +51,7 @@
 // This class is abstract so that we can extend it in interesting ways for use
 // in tests.  The concrete class used in non-test scenarios is
 // OnDiskDirectoryBackingStore.
-class DirectoryBackingStore : public base::NonThreadSafe {
+class DirectoryBackingStore {
  public:
   explicit DirectoryBackingStore(const std::string& dir_name);
   virtual ~DirectoryBackingStore();
@@ -195,6 +195,8 @@
   // Destroys the existing Connection and creates a new one.
   void ResetAndCreateConnection();
 
+  SEQUENCE_CHECKER(sequence_checker_);
+
  private:
   friend class DirectoryBackingStoreTest;
   friend class TestDirectoryBackingStore;
diff --git a/components/sync/syncable/on_disk_directory_backing_store.cc b/components/sync/syncable/on_disk_directory_backing_store.cc
index ba2e5d89a..63575be 100644
--- a/components/sync/syncable/on_disk_directory_backing_store.cc
+++ b/components/sync/syncable/on_disk_directory_backing_store.cc
@@ -35,7 +35,7 @@
     JournalIndex* delete_journals,
     MetahandleSet* metahandles_to_purge,
     Directory::KernelLoadInfo* kernel_load_info) {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
 
   if (!IsOpen()) {
     if (!Open(backing_file_path_))
@@ -62,7 +62,7 @@
     JournalIndex* delete_journals,
     MetahandleSet* metahandles_to_purge,
     Directory::KernelLoadInfo* kernel_load_info) {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   DirOpenResult result = TryLoad(handles_map, delete_journals,
                                  metahandles_to_purge, kernel_load_info);
   if (result == OPENED) {
@@ -108,7 +108,7 @@
 }
 
 const base::FilePath& OnDiskDirectoryBackingStore::backing_file_path() const {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   return backing_file_path_;
 }
 
diff --git a/components/translate/ios/browser/BUILD.gn b/components/translate/ios/browser/BUILD.gn
index 3ef1f8d..878ec3949 100644
--- a/components/translate/ios/browser/BUILD.gn
+++ b/components/translate/ios/browser/BUILD.gn
@@ -58,7 +58,8 @@
     "//components/prefs:test_support",
     "//components/resources",
     "//components/translate/core/browser",
-    "//ios/web:test_support",
+    "//ios/web/public/test",
+    "//ios/web/public/test/fakes",
     "//testing/gtest",
     "//third_party/ocmock",
     "//ui/base",
diff --git a/components/ukm/observers/sync_disable_observer_unittest.cc b/components/ukm/observers/sync_disable_observer_unittest.cc
index 4e4080e..05f9f2f7 100644
--- a/components/ukm/observers/sync_disable_observer_unittest.cc
+++ b/components/ukm/observers/sync_disable_observer_unittest.cc
@@ -28,7 +28,7 @@
     }
   }
 
-  void Shutdown() {
+  void Shutdown() override {
     for (auto& observer : observers_) {
       observer.OnSyncShutdown(this);
     }
diff --git a/content/browser/compositor/gpu_vsync_begin_frame_source.cc b/content/browser/compositor/gpu_vsync_begin_frame_source.cc
index 7e43be47..e4f039a7 100644
--- a/content/browser/compositor/gpu_vsync_begin_frame_source.cc
+++ b/content/browser/compositor/gpu_vsync_begin_frame_source.cc
@@ -22,7 +22,7 @@
   if (!needs_begin_frames_)
     return;
 
-  base::TimeTicks now = base::TimeTicks::Now();
+  base::TimeTicks now = Now();
   base::TimeTicks deadline = now.SnappedToNextTick(timestamp, interval);
 
   TRACE_EVENT1("cc", "GpuVSyncBeginFrameSource::OnVSync", "latency",
@@ -39,4 +39,43 @@
   vsync_control_->SetNeedsVSync(needs_begin_frames);
 }
 
+base::TimeTicks GpuVSyncBeginFrameSource::Now() const {
+  return base::TimeTicks::Now();
+}
+
+cc::BeginFrameArgs GpuVSyncBeginFrameSource::GetMissedBeginFrameArgs(
+    cc::BeginFrameObserver* obs) {
+  if (!last_begin_frame_args_.IsValid())
+    return cc::BeginFrameArgs();
+
+  base::TimeTicks now = Now();
+  base::TimeTicks estimated_next_timestamp = now.SnappedToNextTick(
+      last_begin_frame_args_.frame_time, last_begin_frame_args_.interval);
+  base::TimeTicks missed_timestamp =
+      estimated_next_timestamp - last_begin_frame_args_.interval;
+
+  if (missed_timestamp > last_begin_frame_args_.frame_time) {
+    // The projected missed timestamp is newer than the last known timestamp.
+    // In this case create BeginFrameArgs with a new sequence number.
+    next_sequence_number_++;
+    last_begin_frame_args_ = cc::BeginFrameArgs::Create(
+        BEGINFRAME_FROM_HERE, source_id(), next_sequence_number_,
+        missed_timestamp, estimated_next_timestamp,
+        last_begin_frame_args_.interval, cc::BeginFrameArgs::MISSED);
+    return last_begin_frame_args_;
+  }
+
+  // The last known args object is up-to-date. Skip sending notification
+  // if the observer has already seen it.
+  const cc::BeginFrameArgs& last_observer_args = obs->LastUsedBeginFrameArgs();
+  if (last_observer_args.IsValid() &&
+      last_begin_frame_args_.frame_time <= last_observer_args.frame_time) {
+    return cc::BeginFrameArgs();
+  }
+
+  cc::BeginFrameArgs missed_args = last_begin_frame_args_;
+  missed_args.type = cc::BeginFrameArgs::MISSED;
+  return missed_args;
+}
+
 }  // namespace content
diff --git a/content/browser/compositor/gpu_vsync_begin_frame_source.h b/content/browser/compositor/gpu_vsync_begin_frame_source.h
index a3ddd6b..9df2f07 100644
--- a/content/browser/compositor/gpu_vsync_begin_frame_source.h
+++ b/content/browser/compositor/gpu_vsync_begin_frame_source.h
@@ -8,19 +8,21 @@
 #include "base/memory/weak_ptr.h"
 #include "base/time/time.h"
 #include "cc/scheduler/begin_frame_source.h"
+#include "content/common/content_export.h"
 
 namespace content {
 
 // This class is used to control VSync production on GPU side.
-class GpuVSyncControl {
+class CONTENT_EXPORT GpuVSyncControl {
  public:
   virtual void SetNeedsVSync(bool needs_vsync) = 0;
 };
 
 // This is a type of ExternalBeginFrameSource where VSync signals are
 // generated externally on GPU side.
-class GpuVSyncBeginFrameSource : public cc::ExternalBeginFrameSource,
-                                 cc::ExternalBeginFrameSourceClient {
+class CONTENT_EXPORT GpuVSyncBeginFrameSource
+    : public cc::ExternalBeginFrameSource,
+      public cc::ExternalBeginFrameSourceClient {
  public:
   explicit GpuVSyncBeginFrameSource(GpuVSyncControl* vsync_control);
   ~GpuVSyncBeginFrameSource() override;
@@ -30,7 +32,14 @@
 
   void OnVSync(base::TimeTicks timestamp, base::TimeDelta interval);
 
+ protected:
+  // Virtual for testing.
+  virtual base::TimeTicks Now() const;
+
  private:
+  cc::BeginFrameArgs GetMissedBeginFrameArgs(
+      cc::BeginFrameObserver* obs) override;
+
   GpuVSyncControl* const vsync_control_;
   bool needs_begin_frames_;
   uint64_t next_sequence_number_;
diff --git a/content/browser/compositor/gpu_vsync_begin_frame_source_unittest.cc b/content/browser/compositor/gpu_vsync_begin_frame_source_unittest.cc
new file mode 100644
index 0000000..b3b234f8
--- /dev/null
+++ b/content/browser/compositor/gpu_vsync_begin_frame_source_unittest.cc
@@ -0,0 +1,185 @@
+// 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/compositor/gpu_vsync_begin_frame_source.h"
+
+#include "base/macros.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace content {
+namespace {
+
+class TestBeginFrameObserver : public cc::BeginFrameObserverBase {
+ public:
+  TestBeginFrameObserver() = default;
+
+  int begin_frame_count() { return begin_frame_count_; }
+
+ private:
+  bool OnBeginFrameDerivedImpl(const cc::BeginFrameArgs& args) override {
+    begin_frame_count_++;
+    return true;
+  }
+
+  void OnBeginFrameSourcePausedChanged(bool paused) override {};
+
+  int begin_frame_count_ = 0;
+
+  DISALLOW_COPY_AND_ASSIGN(TestBeginFrameObserver);
+};
+
+class TestGpuVSyncBeginFrameSource : public GpuVSyncBeginFrameSource {
+ public:
+  explicit TestGpuVSyncBeginFrameSource(GpuVSyncControl* vsync_control)
+      : GpuVSyncBeginFrameSource(vsync_control) {}
+
+  void SetNow(base::TimeTicks now) { now_ = now; }
+
+ private:
+  base::TimeTicks Now() const override { return now_; }
+
+  base::TimeTicks now_;
+
+  DISALLOW_COPY_AND_ASSIGN(TestGpuVSyncBeginFrameSource);
+};
+
+class GpuVSyncBeginFrameSourceTest : public testing::Test,
+                                     public GpuVSyncControl {
+ public:
+  GpuVSyncBeginFrameSourceTest() = default;
+  ~GpuVSyncBeginFrameSourceTest() override = default;
+
+ protected:
+  void SetNeedsVSync(bool needs_vsync) override { needs_vsync_ = needs_vsync; }
+
+  bool needs_vsync_ = false;
+
+  DISALLOW_COPY_AND_ASSIGN(GpuVSyncBeginFrameSourceTest);
+};
+
+// Test that an observer can be added to BFS and that it receives OnBeginFrame
+// notification.
+TEST_F(GpuVSyncBeginFrameSourceTest, BasicTest) {
+  TestBeginFrameObserver observer;
+  TestGpuVSyncBeginFrameSource begin_frame_source(this);
+
+  base::TimeTicks now = base::TimeTicks() + base::TimeDelta::FromHours(2);
+  begin_frame_source.SetNow(now);
+
+  EXPECT_FALSE(needs_vsync_);
+
+  begin_frame_source.AddObserver(&observer);
+
+  EXPECT_TRUE(needs_vsync_);
+  EXPECT_FALSE(observer.LastUsedBeginFrameArgs().IsValid());
+
+  base::TimeTicks frame_time = now - base::TimeDelta::FromSeconds(1);
+  base::TimeDelta interval = base::TimeDelta::FromSeconds(2);
+
+  begin_frame_source.OnVSync(frame_time, interval);
+
+  EXPECT_EQ(1, observer.begin_frame_count());
+
+  cc::BeginFrameArgs args = observer.LastUsedBeginFrameArgs();
+  EXPECT_TRUE(args.IsValid());
+  EXPECT_EQ(frame_time, args.frame_time);
+  EXPECT_EQ(interval, args.interval);
+  EXPECT_EQ(frame_time + interval, args.deadline);
+  EXPECT_EQ(cc::BeginFrameArgs::kStartingFrameNumber + 1, args.sequence_number);
+  EXPECT_EQ(cc::BeginFrameArgs::NORMAL, args.type);
+  EXPECT_EQ(begin_frame_source.source_id(), args.source_id);
+
+  // Make sure that the deadline time is correctly advanced forward to be after
+  // 'now' when frame time is way behind.
+  now += base::TimeDelta::FromSeconds(10);
+  begin_frame_source.SetNow(now);
+  // Frame time is 5 seconds behind but the deadline should be 1 second after
+  // 'now' considering the 2 second interval.
+  frame_time = now - base::TimeDelta::FromSeconds(5);
+
+  begin_frame_source.OnVSync(frame_time, interval);
+
+  EXPECT_EQ(2, observer.begin_frame_count());
+
+  args = observer.LastUsedBeginFrameArgs();
+  EXPECT_TRUE(args.IsValid());
+  EXPECT_EQ(frame_time, args.frame_time);
+  EXPECT_EQ(interval, args.interval);
+  EXPECT_EQ(now + base::TimeDelta::FromSeconds(1), args.deadline);
+  EXPECT_EQ(cc::BeginFrameArgs::kStartingFrameNumber + 2, args.sequence_number);
+  EXPECT_EQ(cc::BeginFrameArgs::NORMAL, args.type);
+  EXPECT_EQ(begin_frame_source.source_id(), args.source_id);
+
+  begin_frame_source.RemoveObserver(&observer);
+
+  EXPECT_EQ(2, observer.begin_frame_count());
+  EXPECT_FALSE(needs_vsync_);
+}
+
+// Test that MISSED OnBeginFrame is produced as expected.
+TEST_F(GpuVSyncBeginFrameSourceTest, MissedBeginFrameArgs) {
+  TestBeginFrameObserver observer1;
+  TestBeginFrameObserver observer2;
+  TestGpuVSyncBeginFrameSource begin_frame_source(this);
+
+  base::TimeTicks now = base::TimeTicks() + base::TimeDelta::FromHours(2);
+  begin_frame_source.SetNow(now);
+
+  begin_frame_source.AddObserver(&observer1);
+
+  // The observer shouldn't be getting any BeginFrame at this point.
+  EXPECT_EQ(0, observer1.begin_frame_count());
+
+  base::TimeDelta interval = base::TimeDelta::FromSeconds(2);
+
+  // Trigger first OnBeginFrame 5 seconds behind now.
+  begin_frame_source.OnVSync(now - base::TimeDelta::FromSeconds(5), interval);
+
+  // The observer should get a NORMAL BeginFrame notification which is covered
+  // by BasicTest above.
+  EXPECT_EQ(1, observer1.begin_frame_count());
+  EXPECT_EQ(cc::BeginFrameArgs::NORMAL,
+            observer1.LastUsedBeginFrameArgs().type);
+
+  // Remove the first observer and add it back. It should get a more
+  // recent missed notification calculated from the projection of the previous
+  // notification.
+  begin_frame_source.RemoveObserver(&observer1);
+  begin_frame_source.AddObserver(&observer1);
+
+  EXPECT_EQ(2, observer1.begin_frame_count());
+
+  // The projected MISSED frame_time should be 1 second behind 'now'.
+  base::TimeTicks timestamp1 = now - base::TimeDelta::FromSeconds(1);
+  cc::BeginFrameArgs args1 = observer1.LastUsedBeginFrameArgs();
+  EXPECT_TRUE(args1.IsValid());
+  EXPECT_EQ(timestamp1, args1.frame_time);
+  EXPECT_EQ(timestamp1 + interval, args1.deadline);
+  EXPECT_EQ(cc::BeginFrameArgs::kStartingFrameNumber + 2,
+            args1.sequence_number);
+  EXPECT_EQ(cc::BeginFrameArgs::MISSED, args1.type);
+
+  // Add second observer which should receive the same notification.
+  begin_frame_source.AddObserver(&observer2);
+
+  EXPECT_EQ(1, observer2.begin_frame_count());
+
+  cc::BeginFrameArgs args2 = observer2.LastUsedBeginFrameArgs();
+  EXPECT_TRUE(args2.IsValid());
+  EXPECT_EQ(timestamp1, args2.frame_time);
+  EXPECT_EQ(timestamp1 + interval, args2.deadline);
+  EXPECT_EQ(cc::BeginFrameArgs::kStartingFrameNumber + 2,
+            args2.sequence_number);
+  EXPECT_EQ(cc::BeginFrameArgs::MISSED, args2.type);
+
+  // Adding and removing the second observer shouldn't produce any
+  // new notifications.
+  begin_frame_source.RemoveObserver(&observer2);
+  begin_frame_source.AddObserver(&observer2);
+
+  EXPECT_EQ(1, observer2.begin_frame_count());
+}
+
+}  // namespace
+}  // namespace content
diff --git a/content/browser/download/download_stats.cc b/content/browser/download/download_stats.cc
index ea49d2d..d008996c 100644
--- a/content/browser/download/download_stats.cc
+++ b/content/browser/download/download_stats.cc
@@ -343,6 +343,8 @@
 // will be kept in overflow bucket.
 const int64_t kMaxFileSizeKb = 4 * 1024 * 1024; /* 4GB. */
 
+const int64_t kHighBandwidthBytesPerSecond = 30 * 1024 * 1024;
+
 // Maps extensions to their matching UMA histogram int value.
 int GetDangerousFileType(const base::FilePath& file_path) {
   for (size_t i = 0; i < arraysize(kDangerousFileTypes); ++i) {
@@ -886,6 +888,14 @@
   UMA_HISTOGRAM_LONG_TIMES("Download.Parallelizable.DownloadTime", time_span);
   UMA_HISTOGRAM_CUSTOM_COUNTS("Download.Parallelizable.FileSize", file_size_kb,
                               1, kMaxFileSizeKb, 50);
+  if (average_bandwidth > kHighBandwidthBytesPerSecond) {
+    UMA_HISTOGRAM_LONG_TIMES(
+        "Download.Parallelizable.DownloadTime.HighDownloadBandwidth",
+        time_span);
+    UMA_HISTOGRAM_CUSTOM_COUNTS(
+        "Download.Parallelizable.FileSize.HighDownloadBandwidth", file_size_kb,
+        1, kMaxFileSizeKb, 50);
+  }
 }
 
 void RecordParallelDownloadCreationEvent(ParallelDownloadCreationEvent event) {
diff --git a/content/browser/gpu/gpu_process_host.cc b/content/browser/gpu/gpu_process_host.cc
index 172a84b..4bcf3466 100644
--- a/content/browser/gpu/gpu_process_host.cc
+++ b/content/browser/gpu/gpu_process_host.cc
@@ -512,7 +512,7 @@
 }
 
 GpuProcessHost::~GpuProcessHost() {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
 
   SendOutstandingReplies();
 
@@ -659,7 +659,7 @@
 }
 
 bool GpuProcessHost::Send(IPC::Message* msg) {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   if (process_->GetHost()->IsChannelOpening()) {
     queued_messages_.push(msg);
     return true;
@@ -676,7 +676,7 @@
 }
 
 bool GpuProcessHost::OnMessageReceived(const IPC::Message& message) {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
 #if defined(USE_OZONE)
   BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
                           base::Bind(&RouteMessageToOzoneOnUI, message));
@@ -700,7 +700,7 @@
     bool allow_view_command_buffers,
     bool allow_real_time_streams,
     const EstablishChannelCallback& callback) {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   TRACE_EVENT0("gpu", "GpuProcessHost::EstablishGpuChannel");
 
   // If GPU features are already blacklisted, no need to establish the channel.
@@ -737,7 +737,7 @@
     const CreateGpuMemoryBufferCallback& callback) {
   TRACE_EVENT0("gpu", "GpuProcessHost::CreateGpuMemoryBuffer");
 
-  DCHECK(CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   create_gpu_memory_buffer_requests_.push(callback);
   gpu_service_ptr_->CreateGpuMemoryBuffer(
       id, size, format, usage, client_id, surface_handle,
diff --git a/content/browser/gpu/gpu_process_host.h b/content/browser/gpu/gpu_process_host.h
index 7572b2c9..8cef249 100644
--- a/content/browser/gpu/gpu_process_host.h
+++ b/content/browser/gpu/gpu_process_host.h
@@ -17,7 +17,7 @@
 #include "base/containers/hash_tables.h"
 #include "base/macros.h"
 #include "base/memory/weak_ptr.h"
-#include "base/threading/non_thread_safe.h"
+#include "base/sequence_checker.h"
 #include "base/time/time.h"
 #include "build/build_config.h"
 #include "content/common/content_export.h"
@@ -57,8 +57,7 @@
 
 class GpuProcessHost : public BrowserChildProcessHostDelegate,
                        public IPC::Sender,
-                       public ui::mojom::GpuHost,
-                       public base::NonThreadSafe {
+                       public ui::mojom::GpuHost {
  public:
   enum GpuProcessKind {
     GPU_PROCESS_KIND_UNSANDBOXED,
@@ -292,6 +291,8 @@
   mojo::Binding<ui::mojom::GpuHost> gpu_host_binding_;
   gpu::GpuProcessHostActivityFlags activity_flags_;
 
+  SEQUENCE_CHECKER(sequence_checker_);
+
   base::WeakPtrFactory<GpuProcessHost> weak_ptr_factory_;
 
   DISALLOW_COPY_AND_ASSIGN(GpuProcessHost);
diff --git a/content/browser/indexed_db/database_impl.cc b/content/browser/indexed_db/database_impl.cc
index 191b0db..61887172 100644
--- a/content/browser/indexed_db/database_impl.cc
+++ b/content/browser/indexed_db/database_impl.cc
@@ -548,6 +548,10 @@
   if (!connection_->IsConnected())
     return;
 
+  // Can't call BadMessage as we're no longer on the IO thread. So ignore.
+  if (connection_->GetTransaction(transaction_id))
+    return;
+
   connection_->database()->CreateTransaction(transaction_id, connection_.get(),
                                              object_store_ids, mode);
 }
diff --git a/content/browser/indexed_db/indexed_db_connection.cc b/content/browser/indexed_db/indexed_db_connection.cc
index f78c1aa..a541a70f 100644
--- a/content/browser/indexed_db/indexed_db_connection.cc
+++ b/content/browser/indexed_db/indexed_db_connection.cc
@@ -107,7 +107,7 @@
     const std::set<int64_t>& scope,
     blink::WebIDBTransactionMode mode,
     IndexedDBBackingStore::Transaction* backing_store_transaction) {
-  DCHECK_EQ(GetTransaction(id), nullptr) << "Duplicate transaction id." << id;
+  CHECK_EQ(GetTransaction(id), nullptr) << "Duplicate transaction id." << id;
   std::unique_ptr<IndexedDBTransaction> transaction =
       IndexedDBClassFactory::Get()->CreateIndexedDBTransaction(
           id, this, scope, mode, backing_store_transaction);
diff --git a/content/browser/media/session/media_session_browsertest.cc b/content/browser/media/session/media_session_browsertest.cc
index c33254ea..0339ba0 100644
--- a/content/browser/media/session/media_session_browsertest.cc
+++ b/content/browser/media/session/media_session_browsertest.cc
@@ -111,8 +111,8 @@
 
 }  // anonymous namespace
 
-#if !defined(OS_ANDROID)
-// The feature can't be disabled on Android.
+#if !defined(OS_ANDROID) && !defined(OS_CHROMEOS)
+// The feature can't be disabled on Android and Chrome OS.
 IN_PROC_BROWSER_TEST_F(MediaSessionBrowserTest, MediaSessionNoOpWhenDisabled) {
   NavigateToURL(shell(), GetTestUrl("media/session", "media-session.html"));
 
@@ -129,7 +129,7 @@
   EXPECT_FALSE(IsPlaying(shell(), "long-audio"));
   EXPECT_TRUE(IsPlaying(shell(), "long-video"));
 }
-#endif  // !defined(OS_ANDROID)
+#endif  // !defined(OS_ANDROID) && !defined(OS_CHROMEOS)
 
 IN_PROC_BROWSER_TEST_F(MediaSessionBrowserTest, SimplePlayPause) {
   EnableInternalMediaSesion();
diff --git a/content/browser/media/session/media_session_controllers_manager.cc b/content/browser/media/session/media_session_controllers_manager.cc
index baad1185..c0eecf52 100644
--- a/content/browser/media/session/media_session_controllers_manager.cc
+++ b/content/browser/media/session/media_session_controllers_manager.cc
@@ -13,7 +13,9 @@
 namespace {
 
 bool IsMediaSessionEnabled() {
-#if defined(OS_ANDROID)
+// Media session is enabled on Android and Chrome OS to allow control of media
+// players as needed.
+#if defined(OS_ANDROID) || defined(OS_CHROMEOS)
   return true;
 #else
   base::CommandLine* command_line = base::CommandLine::ForCurrentProcess();
diff --git a/content/browser/resources/media/client_renderer.js b/content/browser/resources/media/client_renderer.js
index 63c7dcf..adfa319a 100644
--- a/content/browser/resources/media/client_renderer.js
+++ b/content/browser/resources/media/client_renderer.js
@@ -29,7 +29,10 @@
     this.bufferCanvas.width = media.BAR_WIDTH;
     this.bufferCanvas.height = media.BAR_HEIGHT;
 
+    this.clipboardDialog = document.getElementById('clipboard-dialog');
+
     this.clipboardTextarea = document.getElementById('clipboard-textarea');
+    this.clipboardTextarea.onblur = this.hideClipboard_.bind(this);
     var clipboardButtons = document.getElementsByClassName('copy-button');
     for (var i = 0; i < clipboardButtons.length; i++) {
       clipboardButtons[i].onclick = this.copyToClipboard_.bind(this);
@@ -214,9 +217,8 @@
       var copyButtonElement =
           document.getElementById('video-capture-capabilities-copy-button');
       copyButtonElement.onclick = function() {
-        window.prompt('Copy to clipboard: Ctrl+C, Enter',
-                      JSON.stringify(videoCaptureCapabilities))
-      }
+        this.showClipboard(JSON.stringify(videoCaptureCapabilities, null, 2));
+      }.bind(this);
 
       var videoTableBodyElement  =
           document.getElementById('video-capture-capabilities-tbody');
@@ -296,7 +298,7 @@
       }
 
       var fragment = document.createDocumentFragment();
-      for (id in components) {
+      for (var id in components) {
         var li = document.createElement('li');
         var button_cb = this.selectAudioComponent_.bind(
                 this, componentType, id, components[id]);
@@ -339,7 +341,7 @@
 
       var hasPlayers = false;
       var fragment = document.createDocumentFragment();
-      for (id in players) {
+      for (var id in players) {
         hasPlayers = true;
         var player = players[id];
         var usableName = player.properties.name ||
@@ -419,7 +421,7 @@
 
     saveLog_: function() {
       var strippedPlayers = []
-      for (id in this.players) {
+      for (var id in this.players) {
         var p = this.players[id];
         strippedPlayers.push({properties: p.properties, events: p.allEvents});
       }
@@ -496,6 +498,17 @@
       ctx.fillRect(middle, 0, right - middle, height);
     },
 
+    showClipboard: function(string) {
+      this.clipboardTextarea.value = string;
+      this.clipboardDialog.showModal();
+      this.clipboardTextarea.focus();
+      this.clipboardTextarea.select();
+    },
+
+    hideClipboard_: function() {
+      this.clipboardDialog.close();
+    },
+
     copyToClipboard_: function() {
       if (!this.selectedPlayer && !this.selectedAudioCompontentData) {
         return;
@@ -512,17 +525,7 @@
         stringBuffer.push('\n');
       }
 
-      this.clipboardTextarea.value = stringBuffer.join('');
-      this.clipboardTextarea.classList.remove('hiddenClipboard');
-      this.clipboardTextarea.focus();
-      this.clipboardTextarea.select();
-
-      // Hide the clipboard element when it loses focus.
-      this.clipboardTextarea.onblur = function(event) {
-        setTimeout(function(element) {
-          event.target.classList.add('hiddenClipboard');
-        }, 0);
-      };
+      this.showClipboard(stringBuffer.join(''));
     },
 
     onTextChange_: function(event) {
diff --git a/content/browser/resources/media/manager.js b/content/browser/resources/media/manager.js
index 983cca5..f07ecb3e 100644
--- a/content/browser/resources/media/manager.js
+++ b/content/browser/resources/media/manager.js
@@ -17,6 +17,18 @@
     this.audioComponents_ = [];
     this.clientRenderer_ = clientRenderer;
 
+    var copyAllPlayerButton = document.getElementById('copy-all-player-button');
+    copyAllPlayerButton.onclick = function() {
+      this.clientRenderer_.showClipboard(
+        JSON.stringify(this.players_, null, 2));
+    }.bind(this);
+
+    var copyAllAudioButton = document.getElementById('copy-all-audio-button');
+    copyAllAudioButton.onclick = function() {
+      this.clientRenderer_.showClipboard(
+        JSON.stringify(this.audioComponents_, null, 2));
+    }.bind(this);
+
     this.hidePlayersButton = document.getElementById('hide-players-button');
     // In tests we may not have this button.
     if (this.hidePlayersButton)
diff --git a/content/browser/resources/media/media_internals.css b/content/browser/resources/media/media_internals.css
index 7b2c43f..33f969d 100644
--- a/content/browser/resources/media/media_internals.css
+++ b/content/browser/resources/media/media_internals.css
@@ -123,17 +123,14 @@
   list-style-type: none;
 }
 
-#clipboard-textarea {
-  position: absolute;
-  width: 50%;
-  height: 50%;
-
-  left: 25%;
-  top: 25%;
+#clipboard-dialog {
+  top: 0;
+  bottom: 0;
 }
 
-.hiddenClipboard {
-  display: none;
+::backdrop {
+  background-color: #000;
+  opacity: 0.5;
 }
 
 .timestamp {
diff --git a/content/browser/resources/media/media_internals.html b/content/browser/resources/media/media_internals.html
index 5ceeec2c..fc16569 100644
--- a/content/browser/resources/media/media_internals.html
+++ b/content/browser/resources/media/media_internals.html
@@ -29,6 +29,7 @@
       <tabpanel id="players">
         <button id="save-log-button" title="Save all player logs into a file." style="display:none">Save log</button>
         <button id="hide-players-button" title="Hide all players in the current view." stype="display:inline-block">Hide players</button>
+        <button id="copy-all-player-button">Copy all to clipboard</button>
         <div id="list-wrapper">
           <div id="player-list-wrapper">
             <h2>Recent Players</h2>
@@ -68,6 +69,7 @@
         <ul id="graphs"></ul>
       </tabpanel>
       <tabpanel id="audio">
+        <button id="copy-all-audio-button">Copy all to clipboard</button>
         <div id="audio-component-list-wrapper">
           <h2>Input Controllers</h2>
           <ul id="audio-input-controller-list" class="show-none-if-empty"></ul>
@@ -119,7 +121,9 @@
       </tabpanel>
     </tabpanels>
   </tabbox>
-  <textarea id="clipboard-textarea" class="hiddenClipboard"></textarea>
+  <dialog id="clipboard-dialog">
+    <textarea id="clipboard-textarea" rows="30" cols="80"></textarea>
+  </dialog>
   <script src="media_internals.js"></script>
 </body>
 </html>
diff --git a/content/renderer/pepper/pepper_plugin_instance_impl.cc b/content/renderer/pepper/pepper_plugin_instance_impl.cc
index bddc0aa500..cb06ebf 100644
--- a/content/renderer/pepper/pepper_plugin_instance_impl.cc
+++ b/content/renderer/pepper/pepper_plugin_instance_impl.cc
@@ -3265,7 +3265,7 @@
     // In imitation of the NPAPI implementation, only |target_frame == frame| is
     // allowed for security reasons.
     WebFrame* target_frame =
-        frame->View()->FindFrameByName(WebString::FromUTF8(target), frame);
+        frame->FindFrameByName(WebString::FromUTF8(target));
     if (target_frame != frame)
       return PP_ERROR_NOACCESS;
 
diff --git a/content/renderer/render_view_browsertest.cc b/content/renderer/render_view_browsertest.cc
index 54fb6f8..a7f6ff2 100644
--- a/content/renderer/render_view_browsertest.cc
+++ b/content/renderer/render_view_browsertest.cc
@@ -1718,7 +1718,7 @@
 
   TestRenderFrame* subframe =
       static_cast<TestRenderFrame*>(RenderFrameImpl::FromWebFrame(
-          view()->webview()->FindFrameByName("frame")));
+          frame()->GetWebFrame()->FindFrameByName("frame")));
   subframe->Navigate(common_params, StartNavigationParams(), request_params);
   FrameLoadWaiter(subframe).Wait();
 
diff --git a/content/shell/browser/layout_test/blink_test_controller.cc b/content/shell/browser/layout_test/blink_test_controller.cc
index dbb37e3..adea703 100644
--- a/content/shell/browser/layout_test/blink_test_controller.cc
+++ b/content/shell/browser/layout_test/blink_test_controller.cc
@@ -278,7 +278,7 @@
 }
 
 BlinkTestController::~BlinkTestController() {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   CHECK(instance_ == this);
   CHECK(test_phase_ == BETWEEN_TESTS);
   GpuDataManager::GetInstance()->RemoveObserver(this);
@@ -291,7 +291,7 @@
     const base::FilePath& current_working_directory,
     bool enable_pixel_dumping,
     const std::string& expected_pixel_hash) {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   test_phase_ = DURING_TEST;
   current_working_directory_ = current_working_directory;
   enable_pixel_dumping_ = enable_pixel_dumping;
@@ -366,7 +366,7 @@
 }
 
 bool BlinkTestController::ResetAfterLayoutTest() {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   printer_->PrintTextFooter();
   printer_->PrintImageFooter();
   printer_->CloseStderr();
@@ -393,7 +393,7 @@
 }
 
 void BlinkTestController::RendererUnresponsive() {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   LOG(WARNING) << "renderer unresponsive";
 }
 
@@ -443,7 +443,7 @@
 }
 
 bool BlinkTestController::OnMessageReceived(const IPC::Message& message) {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   bool handled = true;
   IPC_BEGIN_MESSAGE_MAP(BlinkTestController, message)
     IPC_MESSAGE_HANDLER(ShellViewHostMsg_PrintMessage, OnPrintMessage)
@@ -501,7 +501,7 @@
 
 void BlinkTestController::PluginCrashed(const base::FilePath& plugin_path,
                                         base::ProcessId plugin_pid) {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   printer_->AddErrorMessage(
       base::StringPrintf("#CRASHED - plugin (pid %d)", plugin_pid));
   base::ThreadTaskRunnerHandle::Get()->PostTask(
@@ -512,12 +512,12 @@
 
 void BlinkTestController::RenderFrameCreated(
     RenderFrameHost* render_frame_host) {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   HandleNewRenderFrameHost(render_frame_host);
 }
 
 void BlinkTestController::DevToolsProcessCrashed() {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   printer_->AddErrorMessage("#CRASHED - devtools");
   devtools_bindings_.reset();
   if (devtools_window_)
@@ -526,7 +526,7 @@
 }
 
 void BlinkTestController::WebContentsDestroyed() {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   printer_->AddErrorMessage("FAIL: main window was destroyed");
   DiscardMainWindow();
 }
@@ -542,7 +542,7 @@
     RenderProcessHost* render_process_host,
     base::TerminationStatus status,
     int exit_code) {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   switch (status) {
     case base::TerminationStatus::TERMINATION_STATUS_NORMAL_TERMINATION:
     case base::TerminationStatus::TERMINATION_STATUS_STILL_RUNNING:
@@ -571,7 +571,7 @@
 void BlinkTestController::Observe(int type,
                                   const NotificationSource& source,
                                   const NotificationDetails& details) {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   switch (type) {
     case NOTIFICATION_RENDERER_PROCESS_CREATED: {
       if (!main_window_)
@@ -594,7 +594,7 @@
 
 void BlinkTestController::OnGpuProcessCrashed(
     base::TerminationStatus exit_code) {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   printer_->AddErrorMessage("#CRASHED - gpu");
   DiscardMainWindow();
 }
diff --git a/content/shell/browser/layout_test/blink_test_controller.h b/content/shell/browser/layout_test/blink_test_controller.h
index bb39168..a96d888 100644
--- a/content/shell/browser/layout_test/blink_test_controller.h
+++ b/content/shell/browser/layout_test/blink_test_controller.h
@@ -15,8 +15,8 @@
 #include "base/files/file_path.h"
 #include "base/macros.h"
 #include "base/scoped_observer.h"
+#include "base/sequence_checker.h"
 #include "base/synchronization/lock.h"
-#include "base/threading/non_thread_safe.h"
 #include "base/values.h"
 #include "build/build_config.h"
 #include "content/public/browser/bluetooth_chooser.h"
@@ -113,8 +113,7 @@
   DISALLOW_COPY_AND_ASSIGN(BlinkTestResultPrinter);
 };
 
-class BlinkTestController : public base::NonThreadSafe,
-                            public WebContentsObserver,
+class BlinkTestController : public WebContentsObserver,
                             public RenderProcessHostObserver,
                             public NotificationObserver,
                             public GpuDataManagerObserver {
@@ -299,6 +298,8 @@
   ScopedAllowWaitForAndroidLayoutTests reduced_restrictions_;
 #endif
 
+  SEQUENCE_CHECKER(sequence_checker_);
+
   DISALLOW_COPY_AND_ASSIGN(BlinkTestController);
 };
 
diff --git a/content/shell/browser/shell_url_request_context_getter.cc b/content/shell/browser/shell_url_request_context_getter.cc
index 34e4521..3962571 100644
--- a/content/shell/browser/shell_url_request_context_getter.cc
+++ b/content/shell/browser/shell_url_request_context_getter.cc
@@ -191,27 +191,28 @@
             cache_path, 0,
             BrowserThread::GetTaskRunnerForThread(BrowserThread::CACHE)));
 
-    net::HttpNetworkSession::Params network_session_params;
-    network_session_params.cert_verifier =
+    net::HttpNetworkSession::Context network_session_context;
+    network_session_context.cert_verifier =
         url_request_context_->cert_verifier();
-    network_session_params.transport_security_state =
+    network_session_context.transport_security_state =
         url_request_context_->transport_security_state();
-    network_session_params.cert_transparency_verifier =
+    network_session_context.cert_transparency_verifier =
         url_request_context_->cert_transparency_verifier();
-    network_session_params.ct_policy_enforcer =
+    network_session_context.ct_policy_enforcer =
         url_request_context_->ct_policy_enforcer();
-    network_session_params.channel_id_service =
+    network_session_context.channel_id_service =
         url_request_context_->channel_id_service();
-    network_session_params.proxy_service =
+    network_session_context.proxy_service =
         url_request_context_->proxy_service();
-    network_session_params.ssl_config_service =
+    network_session_context.ssl_config_service =
         url_request_context_->ssl_config_service();
-    network_session_params.http_auth_handler_factory =
+    network_session_context.http_auth_handler_factory =
         url_request_context_->http_auth_handler_factory();
-    network_session_params.http_server_properties =
+    network_session_context.http_server_properties =
         url_request_context_->http_server_properties();
-    network_session_params.net_log =
-        url_request_context_->net_log();
+    network_session_context.net_log = url_request_context_->net_log();
+
+    net::HttpNetworkSession::Params network_session_params;
     network_session_params.ignore_certificate_errors =
         ignore_certificate_errors_;
     if (command_line.HasSwitch(switches::kTestingFixedHttpPort)) {
@@ -236,11 +237,12 @@
 
     // Give |storage_| ownership at the end in case it's |mapped_host_resolver|.
     storage_->set_host_resolver(std::move(host_resolver));
-    network_session_params.host_resolver =
+    network_session_context.host_resolver =
         url_request_context_->host_resolver();
 
     storage_->set_http_network_session(
-        base::MakeUnique<net::HttpNetworkSession>(network_session_params));
+        base::MakeUnique<net::HttpNetworkSession>(network_session_params,
+                                                  network_session_context));
     storage_->set_http_transaction_factory(base::MakeUnique<net::HttpCache>(
         storage_->http_network_session(), std::move(main_backend),
         true /* is_main_cache */));
diff --git a/content/shell/test_runner/test_runner_for_specific_view.cc b/content/shell/test_runner/test_runner_for_specific_view.cc
index cbd139b..e90cbab 100644
--- a/content/shell/test_runner/test_runner_for_specific_view.cc
+++ b/content/shell/test_runner/test_runner_for_specific_view.cc
@@ -679,8 +679,14 @@
 
 void TestRunnerForSpecificView::SetViewSourceForFrame(const std::string& name,
                                                       bool enabled) {
+  if (!web_view()->MainFrame()->IsWebLocalFrame()) {
+    CHECK(false) << "This function cannot be called if the main frame is not a "
+                    "local frame.";
+  }
+
   WebFrame* target_frame =
-      web_view()->FindFrameByName(WebString::FromUTF8(name));
+      web_view()->MainFrame()->ToWebLocalFrame()->FindFrameByName(
+          WebString::FromUTF8(name));
   if (target_frame)
     target_frame->EnableViewSourceMode(enabled);
 }
diff --git a/content/test/BUILD.gn b/content/test/BUILD.gn
index ff1edbd..b43eab8 100644
--- a/content/test/BUILD.gn
+++ b/content/test/BUILD.gn
@@ -1092,6 +1092,7 @@
     "../browser/cache_storage/cache_storage_scheduler_unittest.cc",
     "../browser/child_process_security_policy_unittest.cc",
     "../browser/cocoa/system_hotkey_map_unittest.mm",
+    "../browser/compositor/gpu_vsync_begin_frame_source_unittest.cc",
     "../browser/compositor/reflector_impl_unittest.cc",
     "../browser/compositor/software_browser_compositor_output_surface_unittest.cc",
     "../browser/compositor/software_output_device_mac_unittest.mm",
@@ -1800,6 +1801,7 @@
   }
   if (!use_aura && !is_mac) {
     sources -= [
+      "../browser/compositor/gpu_vsync_begin_frame_source_unittest.cc",
       "../browser/compositor/reflector_impl_unittest.cc",
       "../browser/compositor/software_browser_compositor_output_surface_unittest.cc",
       "../browser/renderer_host/compositor_resize_lock_unittest.cc",
diff --git a/device/vr/BUILD.gn b/device/vr/BUILD.gn
index 677d999a..9db88fa 100644
--- a/device/vr/BUILD.gn
+++ b/device/vr/BUILD.gn
@@ -131,9 +131,6 @@
     "//mojo/common:common_custom_types",
   ]
 
-  # TODO(crbug.com/714018): Convert the implementation to use OnceCallback.
-  use_once_callback = false
-
   # TODO(crbug.com/699569): Convert to use the new JS bindings.
   use_new_js_bindings = false
 }
diff --git a/device/vr/test/fake_vr_display_impl_client.h b/device/vr/test/fake_vr_display_impl_client.h
index 67b0dd1..e67447e 100644
--- a/device/vr/test/fake_vr_display_impl_client.h
+++ b/device/vr/test/fake_vr_display_impl_client.h
@@ -24,7 +24,7 @@
   void OnBlur() override {}
   void OnFocus() override {}
   void OnActivate(mojom::VRDisplayEventReason reason,
-                  const OnActivateCallback& callback) override {}
+                  OnActivateCallback callback) override {}
   void OnDeactivate(mojom::VRDisplayEventReason reason) override {}
 
  private:
diff --git a/device/vr/vr_display_impl.cc b/device/vr/vr_display_impl.cc
index 880e5d9..884269d8 100644
--- a/device/vr/vr_display_impl.cc
+++ b/device/vr/vr_display_impl.cc
@@ -59,26 +59,26 @@
 
 void VRDisplayImpl::RequestPresent(bool secure_origin,
                                    mojom::VRSubmitFrameClientPtr submit_client,
-                                   const RequestPresentCallback& callback) {
+                                   RequestPresentCallback callback) {
   if (!device_->IsAccessAllowed(this)) {
-    callback.Run(false);
+    std::move(callback).Run(false);
     return;
   }
 
-  device_->RequestPresent(
-      std::move(submit_client),
-      base::Bind(&VRDisplayImpl::RequestPresentResult,
-                 weak_ptr_factory_.GetWeakPtr(), callback, secure_origin));
+  device_->RequestPresent(std::move(submit_client),
+                          base::Bind(&VRDisplayImpl::RequestPresentResult,
+                                     weak_ptr_factory_.GetWeakPtr(),
+                                     base::Passed(&callback), secure_origin));
 }
 
-void VRDisplayImpl::RequestPresentResult(const RequestPresentCallback& callback,
+void VRDisplayImpl::RequestPresentResult(RequestPresentCallback callback,
                                          bool secure_origin,
                                          bool success) {
   if (success) {
     device_->SetPresentingDisplay(this);
     device_->SetSecureOrigin(secure_origin);
   }
-  callback.Run(success);
+  std::move(callback).Run(success);
 }
 
 void VRDisplayImpl::ExitPresent() {
diff --git a/device/vr/vr_display_impl.h b/device/vr/vr_display_impl.h
index 7aaa68a3..e8c93170 100644
--- a/device/vr/vr_display_impl.h
+++ b/device/vr/vr_display_impl.h
@@ -45,7 +45,7 @@
 
   void RequestPresent(bool secure_origin,
                       mojom::VRSubmitFrameClientPtr submit_client,
-                      const RequestPresentCallback& callback) override;
+                      RequestPresentCallback callback) override;
   void ExitPresent() override;
   void SubmitFrame(int16_t frame_index,
                    const gpu::MailboxHolder& mailbox) override;
@@ -57,7 +57,7 @@
                          int16_t source_height) override;
   void GetVRVSyncProvider(mojom::VRVSyncProviderRequest request) override;
 
-  void RequestPresentResult(const RequestPresentCallback& callback,
+  void RequestPresentResult(RequestPresentCallback callback,
                             bool secure_origin,
                             bool success);
 
diff --git a/device/vr/vr_service_impl.cc b/device/vr/vr_service_impl.cc
index 5b7256a..7ceb154d 100644
--- a/device/vr/vr_service_impl.cc
+++ b/device/vr/vr_service_impl.cc
@@ -32,7 +32,7 @@
 }
 
 void VRServiceImpl::SetClient(mojom::VRServiceClientPtr service_client,
-                              const SetClientCallback& callback) {
+                              SetClientCallback callback) {
   DCHECK(!client_.get());
   client_ = std::move(service_client);
   VRDeviceManager* device_manager = VRDeviceManager::GetInstance();
@@ -41,7 +41,7 @@
   // displays. Thereafter it will stay up to date by virtue of listening for new
   // connected events.
   device_manager->AddService(this);
-  callback.Run(device_manager->GetNumberOfConnectedDevices());
+  std::move(callback).Run(device_manager->GetNumberOfConnectedDevices());
 }
 
 void VRServiceImpl::ConnectDevice(VRDevice* device) {
diff --git a/device/vr/vr_service_impl.h b/device/vr/vr_service_impl.h
index bb4cdfc..6b0c4b65 100644
--- a/device/vr/vr_service_impl.h
+++ b/device/vr/vr_service_impl.h
@@ -38,7 +38,7 @@
   // mojom::VRService implementation
   // Adds this service to the VRDeviceManager.
   void SetClient(mojom::VRServiceClientPtr service_client,
-                 const SetClientCallback& callback) override;
+                 SetClientCallback callback) override;
 
   bool listening_for_activate() { return listening_for_activate_; }
 
diff --git a/extensions/renderer/api_binding.cc b/extensions/renderer/api_binding.cc
index 87f8fc2..a45cd3a 100644
--- a/extensions/renderer/api_binding.cc
+++ b/extensions/renderer/api_binding.cc
@@ -105,6 +105,7 @@
             bool supports_filters,
             bool supports_rules,
             int max_listeners,
+            bool notify_on_change,
             std::vector<std::string> actions,
             std::vector<std::string> conditions,
             APIBinding* binding)
@@ -113,6 +114,7 @@
         supports_filters(supports_filters),
         supports_rules(supports_rules),
         max_listeners(max_listeners),
+        notify_on_change(notify_on_change),
         actions(std::move(actions)),
         conditions(std::move(conditions)),
         binding(binding) {}
@@ -132,6 +134,9 @@
   // The maximum number of listeners this event supports.
   int max_listeners;
 
+  // Whether to notify the browser of listener changes.
+  bool notify_on_change;
+
   // The associated actions and conditions for declarative events.
   std::vector<std::string> actions;
   std::vector<std::string> conditions;
@@ -266,6 +271,7 @@
       std::vector<std::string> rule_conditions;
       const base::DictionaryValue* options = nullptr;
       bool supports_rules = false;
+      bool notify_on_change = true;
       int max_listeners = binding::kNoListenerMax;
       if (event_dict->GetDictionary("options", &options)) {
         bool temp_supports_filters = false;
@@ -295,12 +301,15 @@
         }
 
         options->GetInteger("maxListeners", &max_listeners);
+        bool unmanaged = false;
+        if (options->GetBoolean("unmanaged", &unmanaged))
+          notify_on_change = !unmanaged;
       }
 
       events_.push_back(base::MakeUnique<EventData>(
           std::move(name), std::move(full_name), supports_filters,
-          supports_rules, max_listeners, std::move(rule_actions),
-          std::move(rule_conditions), this));
+          supports_rules, max_listeners, notify_on_change,
+          std::move(rule_actions), std::move(rule_conditions), this));
     }
   }
 }
@@ -482,7 +491,7 @@
   } else {
     retval = event_data->binding->event_handler_->CreateEventInstance(
         event_data->full_name, event_data->supports_filters,
-        event_data->max_listeners, context);
+        event_data->max_listeners, event_data->notify_on_change, context);
   }
   info.GetReturnValue().Set(retval);
 }
diff --git a/extensions/renderer/api_binding_js_util.cc b/extensions/renderer/api_binding_js_util.cc
index c5fd2ba..1f84df2 100644
--- a/extensions/renderer/api_binding_js_util.cc
+++ b/extensions/renderer/api_binding_js_util.cc
@@ -128,8 +128,10 @@
   if (event_name.empty()) {
     event = event_handler_->CreateAnonymousEventInstance(context);
   } else {
-    event = event_handler_->CreateEventInstance(
-        event_name, supports_filters, binding::kNoListenerMax, context);
+    bool notify_on_change = true;
+    event = event_handler_->CreateEventInstance(event_name, supports_filters,
+                                                binding::kNoListenerMax,
+                                                notify_on_change, context);
   }
 
   arguments->Return(event);
diff --git a/extensions/renderer/api_event_handler.cc b/extensions/renderer/api_event_handler.cc
index fc8c3a1a..7c37c60 100644
--- a/extensions/renderer/api_event_handler.cc
+++ b/extensions/renderer/api_event_handler.cc
@@ -116,6 +116,7 @@
     const std::string& event_name,
     bool supports_filters,
     int max_listeners,
+    bool notify_on_change,
     v8::Local<v8::Context> context) {
   // We need a context scope since gin::CreateHandle only takes the isolate
   // and infers the context from that.
@@ -127,7 +128,8 @@
   DCHECK(data->emitters.find(event_name) == data->emitters.end());
 
   APIEventListeners::ListenersUpdated updated =
-      base::Bind(listeners_changed_, event_name);
+      notify_on_change ? base::Bind(listeners_changed_, event_name)
+                       : base::Bind(&DoNothingOnListenersChanged);
   std::unique_ptr<APIEventListeners> listeners;
   if (supports_filters) {
     listeners = base::MakeUnique<FilteredEventListeners>(
diff --git a/extensions/renderer/api_event_handler.h b/extensions/renderer/api_event_handler.h
index 13451d4b..35278bb 100644
--- a/extensions/renderer/api_event_handler.h
+++ b/extensions/renderer/api_event_handler.h
@@ -42,10 +42,12 @@
                   const EventListenersChangedMethod& listeners_changed);
   ~APIEventHandler();
 
-  // Returns a new v8::Object for an event with the given |event_name|.
+  // Returns a new v8::Object for an event with the given |event_name|. If
+  // |notify_on_change| is true, notifies whenever listeners state is changed.
   v8::Local<v8::Object> CreateEventInstance(const std::string& event_name,
                                             bool supports_filters,
                                             int max_listeners,
+                                            bool notify_on_change,
                                             v8::Local<v8::Context> context);
 
   // Creates a new event without any name. This is used by custom bindings when
diff --git a/extensions/renderer/api_event_handler_unittest.cc b/extensions/renderer/api_event_handler_unittest.cc
index 6333e96c..fc66f83 100644
--- a/extensions/renderer/api_event_handler_unittest.cc
+++ b/extensions/renderer/api_event_handler_unittest.cc
@@ -76,7 +76,7 @@
   v8::Local<v8::Context> context = MainContext();
 
   v8::Local<v8::Object> event = handler()->CreateEventInstance(
-      kEventName, false, binding::kNoListenerMax, context);
+      kEventName, false, binding::kNoListenerMax, true, context);
   ASSERT_FALSE(event.IsEmpty());
 
   EXPECT_EQ(0u, handler()->GetNumEventListenersForTesting(kEventName, context));
@@ -175,9 +175,9 @@
   v8::Local<v8::Context> context = MainContext();
 
   v8::Local<v8::Object> alpha_event = handler()->CreateEventInstance(
-      kAlphaName, false, binding::kNoListenerMax, context);
+      kAlphaName, false, binding::kNoListenerMax, true, context);
   v8::Local<v8::Object> beta_event = handler()->CreateEventInstance(
-      kBetaName, false, binding::kNoListenerMax, context);
+      kBetaName, false, binding::kNoListenerMax, true, context);
   ASSERT_FALSE(alpha_event.IsEmpty());
   ASSERT_FALSE(beta_event.IsEmpty());
 
@@ -273,7 +273,7 @@
 
   const char kEventName[] = "alpha";
   v8::Local<v8::Object> event = handler()->CreateEventInstance(
-      kEventName, false, binding::kNoListenerMax, context);
+      kEventName, false, binding::kNoListenerMax, true, context);
   ASSERT_FALSE(event.IsEmpty());
 
   const char kListenerFunction[] =
@@ -321,10 +321,10 @@
 
   // Create two instances of the same event in different contexts.
   v8::Local<v8::Object> event_a = handler()->CreateEventInstance(
-      kEventName, false, binding::kNoListenerMax, context_a);
+      kEventName, false, binding::kNoListenerMax, true, context_a);
   ASSERT_FALSE(event_a.IsEmpty());
   v8::Local<v8::Object> event_b = handler()->CreateEventInstance(
-      kEventName, false, binding::kNoListenerMax, context_b);
+      kEventName, false, binding::kNoListenerMax, true, context_b);
   ASSERT_FALSE(event_b.IsEmpty());
 
   // Add two separate listeners to the event, one in each context.
@@ -395,7 +395,7 @@
 
   const char kEventName[] = "alpha";
   v8::Local<v8::Object> event = handler()->CreateEventInstance(
-      kEventName, false, binding::kNoListenerMax, context);
+      kEventName, false, binding::kNoListenerMax, true, context);
   ASSERT_FALSE(event.IsEmpty());
 
   const char kAddListenerOnNull[] =
@@ -447,7 +447,7 @@
   v8::Local<v8::Context> context = MainContext();
 
   v8::Local<v8::Object> event = handler()->CreateEventInstance(
-      "alpha", false, binding::kNoListenerMax, context);
+      "alpha", false, binding::kNoListenerMax, true, context);
   ASSERT_FALSE(event.IsEmpty());
 
   const char kListenerFunction[] =
@@ -488,7 +488,7 @@
 
   const char kEventName[] = "alpha";
   v8::Local<v8::Object> event = handler()->CreateEventInstance(
-      kEventName, false, binding::kNoListenerMax, context);
+      kEventName, false, binding::kNoListenerMax, true, context);
   ASSERT_FALSE(event.IsEmpty());
   {
     // Cache the event object on the global in order to allow for easy removal.
@@ -563,7 +563,7 @@
 
   const char kEventName[] = "alpha";
   v8::Local<v8::Object> event = handler()->CreateEventInstance(
-      kEventName, false, binding::kNoListenerMax, context);
+      kEventName, false, binding::kNoListenerMax, true, context);
   ASSERT_FALSE(event.IsEmpty());
 
   bool did_throw = false;
@@ -637,13 +637,13 @@
   const char kEventName1[] = "onFoo";
   const char kEventName2[] = "onBar";
   v8::Local<v8::Object> event1_a = handler()->CreateEventInstance(
-      kEventName1, false, binding::kNoListenerMax, context_a);
+      kEventName1, false, binding::kNoListenerMax, true, context_a);
   ASSERT_FALSE(event1_a.IsEmpty());
   v8::Local<v8::Object> event2_a = handler()->CreateEventInstance(
-      kEventName2, false, binding::kNoListenerMax, context_a);
+      kEventName2, false, binding::kNoListenerMax, true, context_a);
   ASSERT_FALSE(event2_a.IsEmpty());
   v8::Local<v8::Object> event1_b = handler()->CreateEventInstance(
-      kEventName1, false, binding::kNoListenerMax, context_b);
+      kEventName1, false, binding::kNoListenerMax, true, context_b);
   ASSERT_FALSE(event1_b.IsEmpty());
 
   const char kAddListenerFunction[] =
@@ -765,7 +765,7 @@
 
   const char kEventName[] = "alpha";
   v8::Local<v8::Object> event = handler()->CreateEventInstance(
-      kEventName, false, binding::kNoListenerMax, context);
+      kEventName, false, binding::kNoListenerMax, true, context);
   ASSERT_FALSE(event.IsEmpty());
 
   const char kArgumentMassager[] =
@@ -814,7 +814,7 @@
 
   const char kEventName[] = "alpha";
   v8::Local<v8::Object> event = handler()->CreateEventInstance(
-      kEventName, false, binding::kNoListenerMax, context);
+      kEventName, false, binding::kNoListenerMax, true, context);
   ASSERT_FALSE(event.IsEmpty());
 
   const char kArgumentMassager[] =
@@ -878,7 +878,7 @@
 
   const char kEventName[] = "alpha";
   v8::Local<v8::Object> event = handler()->CreateEventInstance(
-      kEventName, false, binding::kNoListenerMax, context);
+      kEventName, false, binding::kNoListenerMax, true, context);
   ASSERT_FALSE(event.IsEmpty());
 
   // A massager that never dispatches.
@@ -978,4 +978,54 @@
   DisposeContext(context);
 }
 
+TEST_F(APIEventHandlerTest, TestUnmanagedEvents) {
+  v8::HandleScope handle_scope(isolate());
+  v8::Local<v8::Context> context = MainContext();
+
+  auto fail_on_notified =
+      [](const std::string& event_name, binding::EventListenersChanged changed,
+         const base::DictionaryValue* filter, bool was_manual,
+         v8::Local<v8::Context> context) { ADD_FAILURE(); };
+
+  APIEventHandler handler(base::Bind(&RunFunctionOnGlobalAndIgnoreResult),
+                          base::Bind(fail_on_notified));
+
+  const char kEventName[] = "alpha";
+  v8::Local<v8::Object> event = handler.CreateEventInstance(
+      kEventName, false, binding::kNoListenerMax, false, context);
+
+  const char kListener[] =
+      "(function() {\n"
+      "  this.eventArgs = Array.from(arguments);\n"
+      "});";
+  v8::Local<v8::Function> listener = FunctionFromString(context, kListener);
+
+  {
+    const char kAddListener[] =
+        "(function(event, listener) { event.addListener(listener); })";
+    v8::Local<v8::Value> args[] = {event, listener};
+    RunFunction(FunctionFromString(context, kAddListener), context,
+                arraysize(args), args);
+  }
+
+  EXPECT_EQ(1u, handler.GetNumEventListenersForTesting(kEventName, context));
+
+  handler.FireEventInContext(kEventName, context,
+                             *ListValueFromString("[1, 'foo']"),
+                             EventFilteringInfo());
+
+  EXPECT_EQ("[1,\"foo\"]", GetStringPropertyFromObject(context->Global(),
+                                                       context, "eventArgs"));
+
+  {
+    const char kRemoveListener[] =
+        "(function(event, listener) { event.removeListener(listener); })";
+    v8::Local<v8::Value> args[] = {event, listener};
+    RunFunction(FunctionFromString(context, kRemoveListener), context,
+                arraysize(args), args);
+  }
+
+  EXPECT_EQ(0u, handler.GetNumEventListenersForTesting(kEventName, context));
+}
+
 }  // namespace extensions
diff --git a/extensions/renderer/chrome_setting.cc b/extensions/renderer/chrome_setting.cc
index 4753dbe3..2509bfb 100644
--- a/extensions/renderer/chrome_setting.cc
+++ b/extensions/renderer/chrome_setting.cc
@@ -116,7 +116,7 @@
     event = event_handler_->CreateEventInstance(
         base::StringPrintf("types.ChromeSetting.%s.onChange",
                            pref_name_.c_str()),
-        supports_filters, binding::kNoListenerMax, context);
+        supports_filters, binding::kNoListenerMax, true, context);
     v8::Maybe<bool> set_result = wrapper->SetPrivate(context, key, event);
     if (!set_result.IsJust() || !set_result.FromJust()) {
       NOTREACHED();
diff --git a/extensions/renderer/native_extension_bindings_system_unittest.cc b/extensions/renderer/native_extension_bindings_system_unittest.cc
index b76fb63..03782536 100644
--- a/extensions/renderer/native_extension_bindings_system_unittest.cc
+++ b/extensions/renderer/native_extension_bindings_system_unittest.cc
@@ -1019,4 +1019,34 @@
   }
 }
 
+TEST_F(NativeExtensionBindingsSystemUnittest, UnmanagedEvents) {
+  InitEventChangeHandler();
+
+  scoped_refptr<Extension> extension =
+      CreateExtension("foo", ItemType::EXTENSION, std::vector<std::string>());
+  RegisterExtension(extension->id());
+
+  v8::HandleScope handle_scope(isolate());
+  v8::Local<v8::Context> context = MainContext();
+  ScriptContext* script_context = CreateScriptContext(
+      context, extension.get(), Feature::BLESSED_EXTENSION_CONTEXT);
+  script_context->set_url(extension->url());
+
+  bindings_system()->UpdateBindingsForContext(script_context);
+
+  const char kAddListeners[] =
+      "(function() {\n"
+      "  chrome.runtime.onMessage.addListener(function() {});\n"
+      "  chrome.runtime.onConnect.addListener(function() {});\n"
+      "});";
+
+  v8::Local<v8::Function> add_listeners =
+      FunctionFromString(context, kAddListeners);
+  RunFunctionOnGlobal(add_listeners, context, 0, nullptr);
+
+  // We should have no notifications for event listeners added (since the
+  // mock is a strict mock, this will fail if anything was called).
+  ::testing::Mock::VerifyAndClearExpectations(event_change_handler());
+}
+
 }  // namespace extensions
diff --git a/google_apis/gcm/tools/mcs_probe.cc b/google_apis/gcm/tools/mcs_probe.cc
index 798c5029..28d69363 100644
--- a/google_apis/gcm/tools/mcs_probe.cc
+++ b/google_apis/gcm/tools/mcs_probe.cc
@@ -409,22 +409,26 @@
 
 void MCSProbe::BuildNetworkSession() {
   net::HttpNetworkSession::Params session_params;
-  session_params.host_resolver = host_resolver_.get();
-  session_params.cert_verifier = cert_verifier_.get();
-  session_params.channel_id_service = system_channel_id_service_.get();
-  session_params.transport_security_state = transport_security_state_.get();
-  session_params.cert_transparency_verifier = cert_transparency_verifier_.get();
-  session_params.ct_policy_enforcer = ct_policy_enforcer_.get();
-  session_params.ssl_config_service = new net::SSLConfigServiceDefaults();
-  session_params.http_auth_handler_factory = http_auth_handler_factory_.get();
-  session_params.http_server_properties = http_server_properties_.get();
   session_params.ignore_certificate_errors = true;
   session_params.testing_fixed_http_port = 0;
   session_params.testing_fixed_https_port = 0;
-  session_params.net_log = &net_log_;
-  session_params.proxy_service = proxy_service_.get();
 
-  network_session_.reset(new net::HttpNetworkSession(session_params));
+  net::HttpNetworkSession::Context session_context;
+  session_context.host_resolver = host_resolver_.get();
+  session_context.cert_verifier = cert_verifier_.get();
+  session_context.channel_id_service = system_channel_id_service_.get();
+  session_context.transport_security_state = transport_security_state_.get();
+  session_context.cert_transparency_verifier =
+      cert_transparency_verifier_.get();
+  session_context.ct_policy_enforcer = ct_policy_enforcer_.get();
+  session_context.ssl_config_service = new net::SSLConfigServiceDefaults();
+  session_context.http_auth_handler_factory = http_auth_handler_factory_.get();
+  session_context.http_server_properties = http_server_properties_.get();
+  session_context.net_log = &net_log_;
+  session_context.proxy_service = proxy_service_.get();
+
+  network_session_.reset(
+      new net::HttpNetworkSession(session_params, session_context));
 }
 
 void MCSProbe::ErrorCallback() {
diff --git a/ios/chrome/app/application_delegate/BUILD.gn b/ios/chrome/app/application_delegate/BUILD.gn
index e823432..4d492a21 100644
--- a/ios/chrome/app/application_delegate/BUILD.gn
+++ b/ios/chrome/app/application_delegate/BUILD.gn
@@ -60,7 +60,7 @@
     "//ios/public/provider/chrome/browser/user_feedback:test_support",
     "//ios/testing:ocmock_support",
     "//ios/web",
-    "//ios/web:test_support",
+    "//ios/web/public/test",
     "//net:test_support",
     "//testing/gtest",
     "//third_party/ocmock",
diff --git a/ios/chrome/browser/BUILD.gn b/ios/chrome/browser/BUILD.gn
index f178f43a..46d68bc 100644
--- a/ios/chrome/browser/BUILD.gn
+++ b/ios/chrome/browser/BUILD.gn
@@ -229,7 +229,7 @@
     "//components/proxy_config",
     "//components/ssl_config",
     "//components/variations",
-    "//ios/web:test_support",
+    "//ios/web/public/test",
     "//net",
     "//net:test_support",
     "//testing/gtest",
diff --git a/ios/chrome/browser/autofill/BUILD.gn b/ios/chrome/browser/autofill/BUILD.gn
index 148f1ab..f1396db 100644
--- a/ios/chrome/browser/autofill/BUILD.gn
+++ b/ios/chrome/browser/autofill/BUILD.gn
@@ -106,7 +106,7 @@
     "//ios/chrome/browser/web:test_support",
     "//ios/chrome/test/base",
     "//ios/web",
-    "//ios/web:test_support",
+    "//ios/web/public/test",
     "//testing/gtest",
     "//third_party/ocmock",
     "//ui/base:test_support",
@@ -131,6 +131,6 @@
     "//ios/testing/earl_grey:earl_grey_support",
     "//ios/third_party/earl_grey",
     "//ios/web:earl_grey_test_support",
-    "//ios/web:test_support",
+    "//ios/web/public/test/http_server",
   ]
 }
diff --git a/ios/chrome/browser/autofill/form_input_egtest.mm b/ios/chrome/browser/autofill/form_input_egtest.mm
index ebebfa9c..4b426a02 100644
--- a/ios/chrome/browser/autofill/form_input_egtest.mm
+++ b/ios/chrome/browser/autofill/form_input_egtest.mm
@@ -17,8 +17,8 @@
 #import "ios/testing/wait_util.h"
 #import "ios/web/public/test/earl_grey/web_view_actions.h"
 #import "ios/web/public/test/earl_grey/web_view_matchers.h"
-#import "ios/web/public/test/http_server.h"
-#include "ios/web/public/test/http_server_util.h"
+#import "ios/web/public/test/http_server/http_server.h"
+#include "ios/web/public/test/http_server/http_server_util.h"
 
 #if !defined(__has_feature) || !__has_feature(objc_arc)
 #error "This file requires ARC support."
diff --git a/ios/chrome/browser/browser_state/chrome_browser_state_impl_io_data.mm b/ios/chrome/browser/browser_state/chrome_browser_state_impl_io_data.mm
index 0d0dfbf..feea79b 100644
--- a/ios/chrome/browser/browser_state/chrome_browser_state_impl_io_data.mm
+++ b/ios/chrome/browser/browser_state/chrome_browser_state_impl_io_data.mm
@@ -305,11 +305,12 @@
       new net::ChannelIDService(new net::DefaultChannelIDStore(nullptr)));
 
   // Build a new HttpNetworkSession that uses the new ChannelIDService.
-  net::HttpNetworkSession::Params network_params =
-      http_network_session_->params();
-  network_params.channel_id_service = channel_id_service.get();
+  net::HttpNetworkSession::Context session_context =
+      http_network_session_->context();
+  session_context.channel_id_service = channel_id_service.get();
   std::unique_ptr<net::HttpNetworkSession> http_network_session(
-      new net::HttpNetworkSession(network_params));
+      new net::HttpNetworkSession(http_network_session_->params(),
+                                  session_context));
 
   // Use a separate HTTP disk cache for isolated apps.
   std::unique_ptr<net::HttpCache::BackendFactory> app_backend =
diff --git a/ios/chrome/browser/browser_state/chrome_browser_state_io_data.cc b/ios/chrome/browser/browser_state/chrome_browser_state_io_data.cc
index 16fb60e0..bfa51b91 100644
--- a/ios/chrome/browser/browser_state/chrome_browser_state_io_data.cc
+++ b/ios/chrome/browser/browser_state/chrome_browser_state_io_data.cc
@@ -484,17 +484,17 @@
 
   IOSChromeIOThread* const io_thread = profile_params.io_thread;
 
-  net::HttpNetworkSession::Params params(io_thread->NetworkSessionParams());
-  net::URLRequestContextBuilder::SetHttpNetworkSessionComponents(context,
-                                                                 &params);
+  net::HttpNetworkSession::Context session_context;
+  net::URLRequestContextBuilder::SetHttpNetworkSessionComponents(
+      context, &session_context);
   if (!IsOffTheRecord() && io_thread->globals()->network_quality_estimator) {
-    params.socket_performance_watcher_factory =
+    session_context.socket_performance_watcher_factory =
         io_thread->globals()
             ->network_quality_estimator->GetSocketPerformanceWatcherFactory();
   }
 
-  return std::unique_ptr<net::HttpNetworkSession>(
-      new net::HttpNetworkSession(params));
+  return std::unique_ptr<net::HttpNetworkSession>(new net::HttpNetworkSession(
+      io_thread->NetworkSessionParams(), session_context));
 }
 
 std::unique_ptr<net::HttpCache> ChromeBrowserStateIOData::CreateMainHttpFactory(
diff --git a/ios/chrome/browser/browsing_data/BUILD.gn b/ios/chrome/browser/browsing_data/BUILD.gn
index 7626afc..d6bf5805 100644
--- a/ios/chrome/browser/browsing_data/BUILD.gn
+++ b/ios/chrome/browser/browsing_data/BUILD.gn
@@ -68,7 +68,8 @@
     "//components/prefs:test_support",
     "//ios/chrome/browser/browser_state:test_support",
     "//ios/web",
-    "//ios/web:test_support",
+    "//ios/web/public/test",
+    "//ios/web/public/test/fakes",
     "//net",
     "//testing/gtest",
     "//third_party/ocmock",
diff --git a/ios/chrome/browser/context_menu/BUILD.gn b/ios/chrome/browser/context_menu/BUILD.gn
index da003576..4de5c20 100644
--- a/ios/chrome/browser/context_menu/BUILD.gn
+++ b/ios/chrome/browser/context_menu/BUILD.gn
@@ -17,7 +17,7 @@
     "//ios/testing:ios_test_support",
     "//ios/third_party/earl_grey",
     "//ios/web:earl_grey_test_support",
-    "//ios/web:test_support",
+    "//ios/web/public/test/http_server",
     "//url",
   ]
   libs = [
diff --git a/ios/chrome/browser/context_menu/context_menu_egtest.mm b/ios/chrome/browser/context_menu/context_menu_egtest.mm
index 5de3cd5..a81e4e5 100644
--- a/ios/chrome/browser/context_menu/context_menu_egtest.mm
+++ b/ios/chrome/browser/context_menu/context_menu_egtest.mm
@@ -21,8 +21,8 @@
 #import "ios/chrome/test/earl_grey/chrome_test_case.h"
 #import "ios/testing/wait_util.h"
 #import "ios/web/public/test/earl_grey/web_view_matchers.h"
-#import "ios/web/public/test/http_server.h"
-#import "ios/web/public/test/http_server_util.h"
+#import "ios/web/public/test/http_server/http_server.h"
+#import "ios/web/public/test/http_server/http_server_util.h"
 #include "url/gurl.h"
 
 #if !defined(__has_feature) || !__has_feature(objc_arc)
diff --git a/ios/chrome/browser/crash_report/BUILD.gn b/ios/chrome/browser/crash_report/BUILD.gn
index e49f8f6d9..1b6257f 100644
--- a/ios/chrome/browser/crash_report/BUILD.gn
+++ b/ios/chrome/browser/crash_report/BUILD.gn
@@ -73,7 +73,7 @@
     "//ios/chrome/browser/sessions:serialisation",
     "//ios/chrome/test/base",
     "//ios/chrome/test/ocmock",
-    "//ios/web:test_support",
+    "//ios/web/public/test",
     "//testing/gmock",
     "//testing/gtest",
     "//third_party/ocmock",
diff --git a/ios/chrome/browser/device_sharing/BUILD.gn b/ios/chrome/browser/device_sharing/BUILD.gn
index a15e20b1..cc9b463 100644
--- a/ios/chrome/browser/device_sharing/BUILD.gn
+++ b/ios/chrome/browser/device_sharing/BUILD.gn
@@ -31,7 +31,7 @@
     "//components/handoff",
     "//components/sync_preferences:test_support",
     "//ios/chrome/browser/browser_state:test_support",
-    "//ios/web:test_support",
+    "//ios/web/public/test",
     "//testing/gtest",
     "//third_party/ocmock",
     "//url",
@@ -51,7 +51,7 @@
     "//ios/chrome/test/app:test_support",
     "//ios/chrome/test/earl_grey:test_support",
     "//ios/third_party/earl_grey",
-    "//ios/web:test_support",
+    "//ios/web/public/test/http_server",
     "//net",
     "//url",
   ]
diff --git a/ios/chrome/browser/device_sharing/handoff_manager_egtest.mm b/ios/chrome/browser/device_sharing/handoff_manager_egtest.mm
index f4355cf..5d04f89 100644
--- a/ios/chrome/browser/device_sharing/handoff_manager_egtest.mm
+++ b/ios/chrome/browser/device_sharing/handoff_manager_egtest.mm
@@ -12,8 +12,8 @@
 #import "ios/chrome/test/app/tab_test_util.h"
 #import "ios/chrome/test/earl_grey/chrome_earl_grey.h"
 #import "ios/chrome/test/earl_grey/chrome_test_case.h"
-#include "ios/web/public/test/http_server.h"
-#include "ios/web/public/test/http_server_util.h"
+#include "ios/web/public/test/http_server/http_server.h"
+#include "ios/web/public/test/http_server/http_server_util.h"
 #import "net/base/mac/url_conversions.h"
 #include "url/gurl.h"
 
diff --git a/ios/chrome/browser/find_in_page/BUILD.gn b/ios/chrome/browser/find_in_page/BUILD.gn
index 38653e9..ff13a51 100644
--- a/ios/chrome/browser/find_in_page/BUILD.gn
+++ b/ios/chrome/browser/find_in_page/BUILD.gn
@@ -46,7 +46,8 @@
     "//base/test:test_support",
     "//ios/chrome/browser/web:test_support",
     "//ios/web",
-    "//ios/web:test_support",
+    "//ios/web/public/test",
+    "//ios/web/public/test/fakes",
     "//testing/gtest",
   ]
 }
@@ -63,7 +64,6 @@
     "//base/test:test_support",
     "//ios/chrome/browser/web:test_support",
     "//ios/web",
-    "//ios/web:test_support",
     "//testing/gtest",
   ]
 }
diff --git a/ios/chrome/browser/find_in_page/js_findinpage_manager.h b/ios/chrome/browser/find_in_page/js_findinpage_manager.h
index ce5d2b8..2049442 100644
--- a/ios/chrome/browser/find_in_page/js_findinpage_manager.h
+++ b/ios/chrome/browser/find_in_page/js_findinpage_manager.h
@@ -44,8 +44,6 @@
 // Searches for more matches. Calls |completionHandler| with a success BOOL and
 // scroll position if pumping was successful. If the pumping was unsuccessfull
 // another pumping call maybe required. |completionHandler| cannot be nil.
-// TODO(shreyasv): Consider folding the logic for re-pumping into this class
-// instead of having clients having to do it.
 - (void)pumpWithCompletionHandler:(void (^)(BOOL, CGPoint))completionHandler;
 
 // Moves to the next matched location and executes the completion handler with
diff --git a/ios/chrome/browser/find_in_page/js_findinpage_manager.mm b/ios/chrome/browser/find_in_page/js_findinpage_manager.mm
index 51bedc9..d08d1ca 100644
--- a/ios/chrome/browser/find_in_page/js_findinpage_manager.mm
+++ b/ios/chrome/browser/find_in_page/js_findinpage_manager.mm
@@ -101,6 +101,9 @@
   __weak JsFindinpageManager* weakSelf = self;
   [self executeJavaScript:JSONQuery
         completionHandler:^(id result, NSError* error) {
+          // Conservative early return in case of error.
+          if (error)
+            return;
           [weakSelf processFindInPagePumpResult:result
                               completionHandler:completionHandler];
         }];
@@ -111,8 +114,9 @@
   __weak JsFindinpageManager* weakSelf = self;
   [self executeJavaScript:kFindInPagePump
         completionHandler:^(id result, NSError* error) {
-          // TODO(shreyasv): What to do here if this returns an NSError in the
-          // WKWebView version.
+          // Conservative early return in case of error.
+          if (error)
+            return;
           [weakSelf processFindInPagePumpResult:result
                               completionHandler:completionHandler];
         }];
@@ -138,7 +142,9 @@
           JsFindinpageManager* strongSelf = weakSelf;
           if (!strongSelf)
             return;
-          DCHECK(!error);
+          // Conservative early return in case of error.
+          if (error)
+            return;
           FindInPageEntry entry = kFindInPageEntryZero;
           if (![result isEqual:kFindInPagePending]) {
             NSString* stringResult =
@@ -203,8 +209,6 @@
   if ([result isEqual:kFindInPagePending]) {
     completionHandler(NO, point);
   }
-  // TODO(shreyasv): Inline this call from the logic from the above function
-  // and remove the above function.
   BOOL processFIPResult =
       [self processFindInPageResult:result scrollPosition:&point];
   completionHandler(processFIPResult, point);
diff --git a/ios/chrome/browser/itunes_links/BUILD.gn b/ios/chrome/browser/itunes_links/BUILD.gn
index 7552a6b..ecedc575 100644
--- a/ios/chrome/browser/itunes_links/BUILD.gn
+++ b/ios/chrome/browser/itunes_links/BUILD.gn
@@ -26,7 +26,7 @@
     ":itunes_links",
     "//base",
     "//ios/chrome/browser/store_kit",
-    "//ios/web:test_support",
+    "//ios/web/public/test/fakes",
     "//testing/gtest",
     "//third_party/ocmock",
     "//url",
diff --git a/ios/chrome/browser/metrics/BUILD.gn b/ios/chrome/browser/metrics/BUILD.gn
index f9703b0..3ac24ce 100644
--- a/ios/chrome/browser/metrics/BUILD.gn
+++ b/ios/chrome/browser/metrics/BUILD.gn
@@ -78,6 +78,7 @@
     "//components/prefs:test_support",
     "//components/version_info",
     "//ios/chrome/test:test_support",
+    "//ios/web/public/test",
     "//testing/gtest",
   ]
 }
@@ -145,7 +146,7 @@
     "//ios/chrome/browser/ui",
     "//ios/testing:ocmock_support",
     "//ios/web",
-    "//ios/web:test_support",
+    "//ios/web/public/test",
     "//testing/gtest",
     "//third_party/ocmock",
   ]
@@ -171,7 +172,8 @@
     "//ios/chrome/test/earl_grey:test_support",
     "//ios/testing:ios_test_support",
     "//ios/web:earl_grey_test_support",
-    "//ios/web:test_support",
+    "//ios/web/public/test",
+    "//ios/web/public/test/http_server",
     "//ui/base",
     "//url",
   ]
@@ -192,7 +194,7 @@
     ":test_support",
     "//ios/chrome/test/app:test_support",
     "//ios/chrome/test/earl_grey:test_support",
-    "//ios/web:test_support",
+    "//ios/web/public/test/http_server",
   ]
   libs = [ "XCTest.framework" ]
 }
diff --git a/ios/chrome/browser/metrics/external_url_tab_usage_recorder_egtest.mm b/ios/chrome/browser/metrics/external_url_tab_usage_recorder_egtest.mm
index 0313a6a..e6090d8 100644
--- a/ios/chrome/browser/metrics/external_url_tab_usage_recorder_egtest.mm
+++ b/ios/chrome/browser/metrics/external_url_tab_usage_recorder_egtest.mm
@@ -10,7 +10,7 @@
 #import "ios/chrome/test/app/tab_test_util.h"
 #import "ios/chrome/test/earl_grey/chrome_earl_grey.h"
 #import "ios/chrome/test/earl_grey/chrome_test_case.h"
-#include "ios/web/public/test/http_server_util.h"
+#include "ios/web/public/test/http_server/http_server_util.h"
 
 #if !defined(__has_feature) || !__has_feature(objc_arc)
 #error "This file requires ARC support."
diff --git a/ios/chrome/browser/metrics/tab_usage_recorder_egtest.mm b/ios/chrome/browser/metrics/tab_usage_recorder_egtest.mm
index 8a762f9c..a37d0cd 100644
--- a/ios/chrome/browser/metrics/tab_usage_recorder_egtest.mm
+++ b/ios/chrome/browser/metrics/tab_usage_recorder_egtest.mm
@@ -29,10 +29,10 @@
 #import "ios/chrome/test/earl_grey/chrome_test_case.h"
 #import "ios/testing/wait_util.h"
 #import "ios/web/public/test/earl_grey/web_view_matchers.h"
-#import "ios/web/public/test/http_server.h"
-#import "ios/web/public/test/http_server_util.h"
-#include "ios/web/public/test/response_providers/delayed_response_provider.h"
-#include "ios/web/public/test/response_providers/html_response_provider.h"
+#include "ios/web/public/test/http_server/delayed_response_provider.h"
+#include "ios/web/public/test/http_server/html_response_provider.h"
+#import "ios/web/public/test/http_server/http_server.h"
+#include "ios/web/public/test/http_server/http_server_util.h"
 #include "ui/base/l10n/l10n_util_mac.h"
 #include "url/gurl.h"
 
diff --git a/ios/chrome/browser/native_app_launcher/BUILD.gn b/ios/chrome/browser/native_app_launcher/BUILD.gn
index e81b5cd..c502fc3 100644
--- a/ios/chrome/browser/native_app_launcher/BUILD.gn
+++ b/ios/chrome/browser/native_app_launcher/BUILD.gn
@@ -42,7 +42,6 @@
     "//ios/public/provider/chrome/browser:test_support",
     "//ios/public/provider/chrome/browser/native_app_launcher",
     "//ios/web",
-    "//ios/web:test_support",
     "//net:test_support",
     "//testing/gmock",
     "//testing/gtest",
@@ -103,7 +102,7 @@
     "//ios/public/provider/chrome/browser/native_app_launcher:test_support",
     "//ios/public/provider/chrome/browser/signin:test_support",
     "//ios/web",
-    "//ios/web:test_support",
+    "//ios/web/public/test/fakes",
     "//net:test_support",
     "//testing/gmock",
     "//testing/gtest",
diff --git a/ios/chrome/browser/net/BUILD.gn b/ios/chrome/browser/net/BUILD.gn
index 94b7fe0..8e24ebb 100644
--- a/ios/chrome/browser/net/BUILD.gn
+++ b/ios/chrome/browser/net/BUILD.gn
@@ -68,7 +68,7 @@
     ":net",
     "//base",
     "//base/test:test_support",
-    "//ios/web:test_support",
+    "//ios/web/public/test",
     "//net",
     "//net:test_support",
     "//testing/gtest",
@@ -86,7 +86,8 @@
     "//ios/chrome/test/app:test_support",
     "//ios/chrome/test/earl_grey:test_support",
     "//ios/third_party/earl_grey",
-    "//ios/web:test_support",
+    "//ios/web/public/test",
+    "//ios/web/public/test/http_server",
     "//url",
   ]
   libs = [ "XCTest.framework" ]
diff --git a/ios/chrome/browser/net/cookies_egtest.mm b/ios/chrome/browser/net/cookies_egtest.mm
index aed6f27..1398de74 100644
--- a/ios/chrome/browser/net/cookies_egtest.mm
+++ b/ios/chrome/browser/net/cookies_egtest.mm
@@ -15,10 +15,10 @@
 #import "ios/chrome/test/app/tab_test_util.h"
 #import "ios/chrome/test/earl_grey/chrome_earl_grey.h"
 #import "ios/chrome/test/earl_grey/chrome_test_case.h"
-#include "ios/web/public/test/http_server.h"
-#include "ios/web/public/test/http_server_util.h"
-#include "ios/web/public/test/response_providers/html_response_provider.h"
-#include "ios/web/public/test/response_providers/response_provider.h"
+#include "ios/web/public/test/http_server/html_response_provider.h"
+#import "ios/web/public/test/http_server/http_server.h"
+#include "ios/web/public/test/http_server/http_server_util.h"
+#include "ios/web/public/test/http_server/response_provider.h"
 #include "url/gurl.h"
 
 #if !defined(__has_feature) || !__has_feature(objc_arc)
diff --git a/ios/chrome/browser/omaha/BUILD.gn b/ios/chrome/browser/omaha/BUILD.gn
index aa08abd..fccb632 100644
--- a/ios/chrome/browser/omaha/BUILD.gn
+++ b/ios/chrome/browser/omaha/BUILD.gn
@@ -48,7 +48,7 @@
     "//ios/public/provider/chrome/browser",
     "//ios/public/provider/chrome/browser/omaha",
     "//ios/web",
-    "//ios/web:test_support",
+    "//ios/web/public/test",
     "//net:test_support",
     "//testing/gtest",
   ]
diff --git a/ios/chrome/browser/passwords/BUILD.gn b/ios/chrome/browser/passwords/BUILD.gn
index 94c811f0..d8deb32 100644
--- a/ios/chrome/browser/passwords/BUILD.gn
+++ b/ios/chrome/browser/passwords/BUILD.gn
@@ -118,7 +118,8 @@
     "//ios/chrome/browser/ui/commands",
     "//ios/testing:ocmock_support",
     "//ios/web",
-    "//ios/web:test_support",
+    "//ios/web/public/test",
+    "//ios/web/public/test/fakes",
     "//testing/gtest",
     "//third_party/ocmock",
     "//url",
diff --git a/ios/chrome/browser/reading_list/BUILD.gn b/ios/chrome/browser/reading_list/BUILD.gn
index ede1a4c..fe219ec 100644
--- a/ios/chrome/browser/reading_list/BUILD.gn
+++ b/ios/chrome/browser/reading_list/BUILD.gn
@@ -97,7 +97,8 @@
     "//ios/testing:ios_test_support",
     "//ios/web",
     "//ios/web:reload_type",
-    "//ios/web:test_support",
+    "//ios/web/public/test",
+    "//ios/web/public/test/fakes",
     "//net",
     "//testing/gtest",
     "//url",
diff --git a/ios/chrome/browser/sessions/BUILD.gn b/ios/chrome/browser/sessions/BUILD.gn
index c778963f..5a6195c 100644
--- a/ios/chrome/browser/sessions/BUILD.gn
+++ b/ios/chrome/browser/sessions/BUILD.gn
@@ -83,7 +83,6 @@
     "//ios/chrome/browser",
     "//ios/chrome/browser/browser_state:test_support",
     "//ios/web",
-    "//ios/web:test_support",
     "//testing/gtest",
     "//third_party/ocmock",
   ]
diff --git a/ios/chrome/browser/signin/BUILD.gn b/ios/chrome/browser/signin/BUILD.gn
index 87452e6..5a29b4f 100644
--- a/ios/chrome/browser/signin/BUILD.gn
+++ b/ios/chrome/browser/signin/BUILD.gn
@@ -128,7 +128,8 @@
     "//ios/public/provider/chrome/browser",
     "//ios/public/provider/chrome/browser/signin",
     "//ios/public/provider/chrome/browser/signin:test_support",
-    "//ios/web:test_support",
+    "//ios/web/public/test",
+    "//ios/web/public/test/fakes",
     "//net:test_support",
     "//testing/gmock",
     "//testing/gtest",
diff --git a/ios/chrome/browser/snapshots/BUILD.gn b/ios/chrome/browser/snapshots/BUILD.gn
index 062cc82d..95b3d33 100644
--- a/ios/chrome/browser/snapshots/BUILD.gn
+++ b/ios/chrome/browser/snapshots/BUILD.gn
@@ -42,12 +42,13 @@
     "//base",
     "//ios/chrome/browser/ui",
     "//ios/web",
-    "//ios/web:test_support",
+    "//ios/web/public/test",
     "//testing/gtest",
   ]
 }
 
 source_set("snapshots_internal") {
+  configs += [ "//build/config/compiler:enable_arc" ]
   sources = [
     "snapshot_overlay_provider.h",
     "web_controller_snapshot_helper.h",
diff --git a/ios/chrome/browser/snapshots/snapshot_cache.h b/ios/chrome/browser/snapshots/snapshot_cache.h
index afb74dd9..3b6908f 100644
--- a/ios/chrome/browser/snapshots/snapshot_cache.h
+++ b/ios/chrome/browser/snapshots/snapshot_cache.h
@@ -25,7 +25,7 @@
 + (SnapshotCache*)sharedInstance;
 
 // The scale that should be used for snapshots.
-+ (CGFloat)snapshotScaleForDevice;
+- (CGFloat)snapshotScaleForDevice;
 
 // Retrieve a cached snapshot for the |sessionID| and return it via the callback
 // if it exists. The callback is guaranteed to be called synchronously if the
diff --git a/ios/chrome/browser/snapshots/snapshot_cache.mm b/ios/chrome/browser/snapshots/snapshot_cache.mm
index 34be527..e0f5c65a 100644
--- a/ios/chrome/browser/snapshots/snapshot_cache.mm
+++ b/ios/chrome/browser/snapshots/snapshot_cache.mm
@@ -6,6 +6,7 @@
 
 #import <UIKit/UIKit.h>
 
+#include "base/base_paths.h"
 #include "base/critical_closure.h"
 #include "base/files/file_enumerator.h"
 #include "base/files/file_path.h"
@@ -14,6 +15,7 @@
 #include "base/logging.h"
 #include "base/mac/bind_objc_block.h"
 #include "base/mac/scoped_nsobject.h"
+#include "base/path_service.h"
 #include "base/strings/sys_string_conversions.h"
 #include "base/task_runner_util.h"
 #include "base/threading/thread_restrictions.h"
@@ -25,10 +27,6 @@
 #include "ios/web/public/web_thread.h"
 
 @interface SnapshotCache ()
-// Returns the directory where the thumbnails are saved.
-+ (base::FilePath)cacheDirectory;
-// Returns the directory where the thumbnails were stored in M28 and earlier.
-- (base::FilePath)oldCacheDirectory;
 // Remove all UIImages from |lruCache_|.
 - (void)handleEnterBackground;
 // Remove all but adjacent UIImages from |lruCache_|.
@@ -45,7 +43,20 @@
 @end
 
 namespace {
-static NSArray* const kSnapshotCacheDirectory = @[ @"Chromium", @"Snapshots" ];
+enum ImageType {
+  IMAGE_TYPE_COLOR,
+  IMAGE_TYPE_GREYSCALE,
+};
+
+enum ImageScale {
+  IMAGE_SCALE_1X,
+  IMAGE_SCALE_2X,
+  IMAGE_SCALE_3X,
+};
+
+const ImageType kImageTypes[] = {
+    IMAGE_TYPE_COLOR, IMAGE_TYPE_GREYSCALE,
+};
 
 const NSUInteger kGreyInitialCapacity = 8;
 const CGFloat kJPEGImageQuality = 1.0;  // Highest quality. No compression.
@@ -55,73 +66,137 @@
 // starting to evict elements.
 const NSUInteger kLRUCacheMaxCapacity = 6;
 
-// The paths of the images saved to disk, given a cache directory.
-base::FilePath FilePathForSessionID(NSString* sessionID,
-                                    const base::FilePath& directory) {
-  base::FilePath path = directory.Append(base::SysNSStringToUTF8(sessionID))
-                            .ReplaceExtension(".jpg");
-  if ([SnapshotCache snapshotScaleForDevice] == 2.0) {
-    path = path.InsertBeforeExtension("@2x");
-  } else if ([SnapshotCache snapshotScaleForDevice] == 3.0) {
-    path = path.InsertBeforeExtension("@3x");
-  }
-  return path;
+// Returns the path of the directory containing the snapshots.
+bool GetSnapshotsCacheDirectory(base::FilePath* snapshots_cache_directory) {
+  base::FilePath cache_directory;
+  if (!base::PathService::Get(base::DIR_CACHE, &cache_directory))
+    return false;
+
+  *snapshots_cache_directory =
+      cache_directory.Append(FILE_PATH_LITERAL("Chromium"))
+          .Append(FILE_PATH_LITERAL("Snapshots"));
+  return true;
 }
 
-base::FilePath GreyFilePathForSessionID(NSString* sessionID,
-                                        const base::FilePath& directory) {
-  base::FilePath path = directory.Append(base::SysNSStringToUTF8(sessionID) +
-                                         "Grey").ReplaceExtension(".jpg");
-  if ([SnapshotCache snapshotScaleForDevice] == 2.0) {
-    path = path.InsertBeforeExtension("@2x");
-  } else if ([SnapshotCache snapshotScaleForDevice] == 3.0) {
-    path = path.InsertBeforeExtension("@3x");
+// Returns the path of the image for |session_id|, in |cache_directory|,
+// of type |image_type| and scale |image_scale|.
+base::FilePath ImagePath(NSString* session_id,
+                         ImageType image_type,
+                         ImageScale image_scale,
+                         const base::FilePath& cache_directory) {
+  NSString* filename = session_id;
+  switch (image_type) {
+    case IMAGE_TYPE_COLOR:
+      // no-op
+      break;
+    case IMAGE_TYPE_GREYSCALE:
+      filename = [filename stringByAppendingString:@"Grey"];
+      break;
   }
-  return path;
+  switch (image_scale) {
+    case IMAGE_SCALE_1X:
+      // no-op
+      break;
+    case IMAGE_SCALE_2X:
+      filename = [filename stringByAppendingString:@"@2x"];
+      break;
+    case IMAGE_SCALE_3X:
+      filename = [filename stringByAppendingString:@"@3x"];
+      break;
+  }
+  filename = [filename stringByAppendingPathExtension:@"jpg"];
+  return cache_directory.Append(base::SysNSStringToUTF8(filename));
 }
 
-UIImage* ReadImageFromDisk(const base::FilePath& filePath) {
+ImageScale ImageScaleForDevice() {
+  // On handset, the color snapshot is used for the stack view, so the scale of
+  // the snapshot images should match the scale of the device.
+  // On tablet, the color snapshot is only used to generate the grey snapshot,
+  // which does not have to be high quality, so use scale of 1.0 on all tablets.
+  if (IsIPadIdiom())
+    return IMAGE_SCALE_1X;
+
+  // Cap snapshot resolution to 2x to reduce the amount of memory used.
+  return [UIScreen mainScreen].scale == 1.0 ? IMAGE_SCALE_1X : IMAGE_SCALE_2X;
+}
+
+CGFloat ScaleFromImageScale(ImageScale image_scale) {
+  switch (image_scale) {
+    case IMAGE_SCALE_1X:
+      return 1.0;
+    case IMAGE_SCALE_2X:
+      return 2.0;
+    case IMAGE_SCALE_3X:
+      return 3.0;
+  }
+}
+
+UIImage* ReadImageForSessionFromDisk(NSString* session_id,
+                                     ImageType image_type,
+                                     ImageScale image_scale,
+                                     const base::FilePath& cache_directory) {
   base::ThreadRestrictions::AssertIOAllowed();
-  // TODO(justincohen): Consider changing this back to -imageWithContentsOfFile
-  // instead of -imageWithData, if the crashing rdar://15747161 is ever fixed.
-  // Tracked in crbug.com/295891.
-  NSString* path = base::SysUTF8ToNSString(filePath.value());
+  // TODO(crbug.com/295891): consider changing back to -imageWithContentsOfFile
+  // instead of -imageWithData if both rdar://15747161 and the bug incorrectly
+  // reporting the image as damaged https://stackoverflow.com/q/5081297/5353
+  // are fixed.
+  base::FilePath file_path =
+      ImagePath(session_id, image_type, image_scale, cache_directory);
+  NSString* path = base::SysUTF8ToNSString(file_path.AsUTF8Unsafe());
   return [UIImage imageWithData:[NSData dataWithContentsOfFile:path]
-                          scale:[SnapshotCache snapshotScaleForDevice]];
+                          scale:(image_type == IMAGE_TYPE_GREYSCALE
+                                     ? 1.0
+                                     : ScaleFromImageScale(image_scale))];
 }
 
-void WriteImageToDisk(UIImage* image, const base::FilePath& filePath) {
+void WriteImageToDisk(UIImage* image, const base::FilePath& file_path) {
   base::ThreadRestrictions::AssertIOAllowed();
   if (!image)
     return;
-  NSString* path = base::SysUTF8ToNSString(filePath.value());
+
+  base::FilePath directory = file_path.DirName();
+  if (!base::DirectoryExists(directory)) {
+    bool success = base::CreateDirectory(directory);
+    if (!success) {
+      DLOG(ERROR) << "Error creating thumbnail directory "
+                  << directory.AsUTF8Unsafe();
+      return;
+    }
+  }
+
+  NSString* path = base::SysUTF8ToNSString(file_path.AsUTF8Unsafe());
   [UIImageJPEGRepresentation(image, kJPEGImageQuality) writeToFile:path
                                                         atomically:YES];
+
   // Encrypt the snapshot file (mostly for Incognito, but can't hurt to
   // always do it).
-  NSDictionary* attributeDict =
+  NSDictionary* attribute_dict =
       [NSDictionary dictionaryWithObject:NSFileProtectionComplete
                                   forKey:NSFileProtectionKey];
   NSError* error = nil;
-  BOOL success = [[NSFileManager defaultManager] setAttributes:attributeDict
+  BOOL success = [[NSFileManager defaultManager] setAttributes:attribute_dict
                                                   ofItemAtPath:path
                                                          error:&error];
   if (!success) {
-    DLOG(ERROR) << "Error encrypting thumbnail file"
+    DLOG(ERROR) << "Error encrypting thumbnail file "
                 << base::SysNSStringToUTF8([error description]);
   }
 }
 
-void ConvertAndSaveGreyImage(const base::FilePath& color_image_path,
-                             const base::FilePath& grey_image_path,
-                             UIImage* color_image) {
+void ConvertAndSaveGreyImage(NSString* session_id,
+                             ImageScale image_scale,
+                             UIImage* color_image,
+                             const base::FilePath& cache_directory) {
   base::ThreadRestrictions::AssertIOAllowed();
-  if (!color_image)
-    color_image = ReadImageFromDisk(color_image_path);
-  if (!color_image)
-    return;
+  if (!color_image) {
+    color_image = ReadImageForSessionFromDisk(session_id, IMAGE_TYPE_COLOR,
+                                              image_scale, cache_directory);
+    if (!color_image)
+      return;
+  }
   UIImage* grey_image = GreyImage(color_image);
-  WriteImageToDisk(grey_image, grey_image_path);
+  WriteImageToDisk(grey_image, ImagePath(session_id, IMAGE_TYPE_GREYSCALE,
+                                         image_scale, cache_directory));
 }
 
 }  // anonymous namespace
@@ -145,6 +220,13 @@
   // be requested to be saved to disk when the application is backgrounded.
   NSString* backgroundingImageSessionId_;
   UIImage* backgroundingColorImage_;
+
+  // Scale for snapshot images. May be smaller than the screen scale in order
+  // to save memory on some devices.
+  ImageScale snapshotsScale_;
+
+  // Directory where the thumbnails are saved.
+  base::FilePath cacheDirectory_;
 }
 
 @synthesize pinnedIDs = pinnedIDs_;
@@ -154,10 +236,24 @@
   return instance;
 }
 
-- (id)init {
+- (instancetype)init {
+  base::FilePath cacheDirectory;
+  if (!GetSnapshotsCacheDirectory(&cacheDirectory))
+    return nil;
+
+  return [self initWithCacheDirectory:cacheDirectory
+                       snapshotsScale:ImageScaleForDevice()];
+}
+
+- (instancetype)initWithCacheDirectory:(const base::FilePath&)cacheDirectory
+                        snapshotsScale:(ImageScale)snapshotsScale {
   if ((self = [super init])) {
     DCHECK_CURRENTLY_ON(web::WebThread::UI);
+
     lruCache_ = [[LRUCache alloc] initWithCacheSize:kLRUCacheMaxCapacity];
+    cacheDirectory_ = cacheDirectory;
+    snapshotsScale_ = snapshotsScale;
+
     [[NSNotificationCenter defaultCenter]
         addObserver:self
            selector:@selector(handleLowMemory)
@@ -192,16 +288,8 @@
               object:nil];
 }
 
-+ (CGFloat)snapshotScaleForDevice {
-  // On handset, the color snapshot is used for the stack view, so the scale of
-  // the snapshot images should match the scale of the device.
-  // On tablet, the color snapshot is only used to generate the grey snapshot,
-  // which does not have to be high quality, so use scale of 1.0 on all tablets.
-  if (IsIPadIdiom()) {
-    return 1.0;
-  }
-  // Cap snapshot resolution to 2x to reduce the amount of memory they use.
-  return MIN([UIScreen mainScreen].scale, 2.0);
+- (CGFloat)snapshotScaleForDevice {
+  return ScaleFromImageScale(snapshotsScale_);
 }
 
 - (void)retrieveImageForSessionID:(NSString*)sessionID
@@ -216,13 +304,17 @@
     return;
   }
 
+  // Copy ivars used by the block so that it does not reference |self|.
+  const base::FilePath cacheDirectory = cacheDirectory_;
+  const ImageScale snapshotsScale = snapshotsScale_;
+
   base::PostTaskAndReplyWithResult(
       web::WebThread::GetTaskRunnerForThread(web::WebThread::FILE_USER_BLOCKING)
           .get(),
       FROM_HERE, base::BindBlockArc(^base::scoped_nsobject<UIImage>() {
         // Retrieve the image on a high priority thread.
-        return base::scoped_nsobject<UIImage>(
-            ReadImageFromDisk([SnapshotCache imagePathForSessionID:sessionID]));
+        return base::scoped_nsobject<UIImage>(ReadImageForSessionFromDisk(
+            sessionID, IMAGE_TYPE_COLOR, snapshotsScale, cacheDirectory));
       }),
       base::BindBlockArc(^(base::scoped_nsobject<UIImage> image) {
         if (image)
@@ -239,11 +331,15 @@
 
   [lruCache_ setObject:image forKey:sessionID];
 
+  // Copy ivars used by the block so that it does not reference |self|.
+  const base::FilePath cacheDirectory = cacheDirectory_;
+  const ImageScale snapshotsScale = snapshotsScale_;
+
   // Save the image to disk.
   web::WebThread::PostBlockingPoolSequencedTask(
       kSequenceToken, FROM_HERE, base::BindBlockArc(^{
-        WriteImageToDisk(image,
-                         [SnapshotCache imagePathForSessionID:sessionID]);
+        WriteImageToDisk(image, ImagePath(sessionID, IMAGE_TYPE_COLOR,
+                                          snapshotsScale, cacheDirectory));
       }));
 }
 
@@ -251,95 +347,65 @@
   DCHECK_CURRENTLY_ON(web::WebThread::UI);
   [lruCache_ removeObjectForKey:sessionID];
 
+  // Copy ivars used by the block so that it does not reference |self|.
+  const base::FilePath cacheDirectory = cacheDirectory_;
+  const ImageScale snapshotsScale = snapshotsScale_;
+
   web::WebThread::PostBlockingPoolSequencedTask(
       kSequenceToken, FROM_HERE, base::BindBlockArc(^{
-        base::FilePath imagePath =
-            [SnapshotCache imagePathForSessionID:sessionID];
-        base::DeleteFile(imagePath, false);
-        base::DeleteFile([SnapshotCache greyImagePathForSessionID:sessionID],
-                         false);
+        for (size_t index = 0; index < arraysize(kImageTypes); ++index) {
+          base::DeleteFile(ImagePath(sessionID, kImageTypes[index],
+                                     snapshotsScale, cacheDirectory),
+                           false /* recursive */);
+        }
       }));
 }
 
-- (base::FilePath)oldCacheDirectory {
-  DCHECK_CURRENTLY_ON(web::WebThread::UI);
-  NSArray* paths = NSSearchPathForDirectoriesInDomains(NSCachesDirectory,
-                                                       NSUserDomainMask, YES);
-  NSString* path = [paths objectAtIndex:0];
-  NSArray* path_components =
-      [NSArray arrayWithObjects:path, kSnapshotCacheDirectory[1], nil];
-  return base::FilePath(
-      base::SysNSStringToUTF8([NSString pathWithComponents:path_components]));
+- (base::FilePath)imagePathForSessionID:(NSString*)sessionID {
+  return ImagePath(sessionID, IMAGE_TYPE_COLOR, snapshotsScale_,
+                   cacheDirectory_);
 }
 
-+ (base::FilePath)cacheDirectory {
-  NSArray* paths = NSSearchPathForDirectoriesInDomains(NSCachesDirectory,
-                                                       NSUserDomainMask, YES);
-  NSString* path = [paths objectAtIndex:0];
-  NSArray* path_components =
-      [NSArray arrayWithObjects:path, kSnapshotCacheDirectory[0],
-                                kSnapshotCacheDirectory[1], nil];
-  return base::FilePath(
-      base::SysNSStringToUTF8([NSString pathWithComponents:path_components]));
-}
-
-+ (base::FilePath)imagePathForSessionID:(NSString*)sessionID {
-  base::ThreadRestrictions::AssertIOAllowed();
-
-  base::FilePath path([SnapshotCache cacheDirectory]);
-
-  BOOL exists = base::PathExists(path);
-  DCHECK(base::DirectoryExists(path) || !exists);
-  if (!exists) {
-    bool result = base::CreateDirectory(path);
-    DCHECK(result);
-  }
-  return FilePathForSessionID(sessionID, path);
-}
-
-+ (base::FilePath)greyImagePathForSessionID:(NSString*)sessionID {
-  base::ThreadRestrictions::AssertIOAllowed();
-
-  base::FilePath path([self cacheDirectory]);
-
-  BOOL exists = base::PathExists(path);
-  DCHECK(base::DirectoryExists(path) || !exists);
-  if (!exists) {
-    bool result = base::CreateDirectory(path);
-    DCHECK(result);
-  }
-  return GreyFilePathForSessionID(sessionID, path);
+- (base::FilePath)greyImagePathForSessionID:(NSString*)sessionID {
+  return ImagePath(sessionID, IMAGE_TYPE_GREYSCALE, snapshotsScale_,
+                   cacheDirectory_);
 }
 
 - (void)purgeCacheOlderThan:(const base::Time&)date
                     keeping:(NSSet*)liveSessionIds {
   DCHECK_CURRENTLY_ON(web::WebThread::UI);
+
   // Copying the date, as the block must copy the value, not the reference.
   const base::Time dateCopy = date;
+
+  // Copy ivars used by the block so that it does not reference |self|.
+  const base::FilePath cacheDirectory = cacheDirectory_;
+  const ImageScale snapshotsScale = snapshotsScale_;
+
   web::WebThread::PostBlockingPoolSequencedTask(
       kSequenceToken, FROM_HERE, base::BindBlockArc(^{
+        if (!base::DirectoryExists(cacheDirectory))
+          return;
+
         std::set<base::FilePath> filesToKeep;
         for (NSString* sessionID : liveSessionIds) {
-          base::FilePath curImagePath =
-              [SnapshotCache imagePathForSessionID:sessionID];
-          filesToKeep.insert(curImagePath);
-          filesToKeep.insert(
-              [SnapshotCache greyImagePathForSessionID:sessionID]);
+          for (size_t index = 0; index < arraysize(kImageTypes); ++index) {
+            filesToKeep.insert(ImagePath(sessionID, kImageTypes[index],
+                                         snapshotsScale, cacheDirectory));
+          }
         }
-        base::FileEnumerator enumerator([SnapshotCache cacheDirectory], false,
+        base::FileEnumerator enumerator(cacheDirectory, false,
                                         base::FileEnumerator::FILES);
-        base::FilePath cur_file;
-        while (!(cur_file = enumerator.Next()).value().empty()) {
-          if (cur_file.Extension() != ".jpg")
+        base::FilePath current_file = enumerator.Next();
+        for (; !current_file.empty(); current_file = enumerator.Next()) {
+          if (current_file.Extension() != ".jpg")
             continue;
-          if (filesToKeep.find(cur_file) != filesToKeep.end()) {
+          if (filesToKeep.find(current_file) != filesToKeep.end())
             continue;
-          }
           base::FileEnumerator::FileInfo fileInfo = enumerator.GetInfo();
-          if (fileInfo.GetLastModifiedTime() > dateCopy) {
+          if (fileInfo.GetLastModifiedTime() > dateCopy)
             continue;
-          }
-          base::DeleteFile(cur_file, false);
+          base::DeleteFile(current_file, false);
         }
       }));
 }
@@ -394,6 +460,10 @@
   // already in the cache, use it.
   UIImage* image = [lruCache_ objectForKey:sessionID];
 
+  // Copy ivars used by the block so that it does not reference |self|.
+  const base::FilePath cacheDirectory = cacheDirectory_;
+  const ImageScale snapshotsScale = snapshotsScale_;
+
   base::PostTaskAndReplyWithResult(
       web::WebThread::GetTaskRunnerForThread(web::WebThread::FILE_USER_BLOCKING)
           .get(),
@@ -401,8 +471,8 @@
         base::scoped_nsobject<UIImage> result(image);
         // If the image is not in the cache, load it from disk.
         if (!result) {
-          result.reset(ReadImageFromDisk(
-              [SnapshotCache imagePathForSessionID:sessionID]));
+          result.reset(ReadImageForSessionFromDisk(
+              sessionID, IMAGE_TYPE_COLOR, snapshotsScale, cacheDirectory));
         }
         if (result)
           result.reset(GreyImage(result));
@@ -458,36 +528,29 @@
     }
   }
 
+  // Copy ivars used by the block so that it does not reference |self|.
+  const base::FilePath cacheDirectory = cacheDirectory_;
+  const ImageScale snapshotsScale = snapshotsScale_;
+
   base::PostTaskAndReplyWithResult(
       web::WebThread::GetTaskRunnerForThread(web::WebThread::FILE_USER_BLOCKING)
           .get(),
       FROM_HERE, base::BindBlockArc(^base::scoped_nsobject<UIImage>() {
         // Retrieve the image on a high priority thread.
-        // Loading the file into NSData is more reliable.
-        // -imageWithContentsOfFile would ocassionally claim the image was not a
-        // valid jpg.
-        // "ImageIO: <ERROR> JPEGNot a JPEG file: starts with 0xff 0xd9"
-        // See
-        // http://stackoverflow.com/questions/5081297/ios-uiimagejpegrepresentation-error-not-a-jpeg-file-starts-with-0xff-0xd9
-        NSData* imageData = [NSData
-            dataWithContentsOfFile:base::SysUTF8ToNSString(
-                [SnapshotCache greyImagePathForSessionID:sessionID].value())];
-        if (!imageData)
-          return base::scoped_nsobject<UIImage>();
-        DCHECK(callback);
-        return base::scoped_nsobject<UIImage>(
-            [UIImage imageWithData:imageData]);
+        return base::scoped_nsobject<UIImage>(ReadImageForSessionFromDisk(
+            sessionID, IMAGE_TYPE_GREYSCALE, snapshotsScale, cacheDirectory));
       }),
       base::BindBlockArc(^(base::scoped_nsobject<UIImage> image) {
-        if (!image) {
-          [self retrieveImageForSessionID:sessionID
-                                 callback:^(UIImage* local_image) {
-                                   if (callback && local_image)
-                                     callback(GreyImage(local_image));
-                                 }];
-        } else if (callback) {
-          callback(image);
+        if (image) {
+          if (callback)
+            callback(image);
+          return;
         }
+        [self retrieveImageForSessionID:sessionID
+                               callback:^(UIImage* local_image) {
+                                 if (callback && local_image)
+                                   callback(GreyImage(local_image));
+                               }];
       }));
 }
 
@@ -496,11 +559,6 @@
   if (!sessionID)
     return;
 
-  base::FilePath greyImagePath =
-      GreyFilePathForSessionID(sessionID, [SnapshotCache cacheDirectory]);
-  base::FilePath colorImagePath =
-      FilePathForSessionID(sessionID, [SnapshotCache cacheDirectory]);
-
   // The color image may still be in memory.  Verify the sessionID matches.
   if (backgroundingColorImage_) {
     if (![backgroundingImageSessionId_ isEqualToString:sessionID]) {
@@ -509,13 +567,16 @@
     }
   }
 
-  // Copy the UIImage* so that the block does not reference |self|.
+  // Copy ivars used by the block so that it does not reference |self|.
   UIImage* backgroundingColorImage = backgroundingColorImage_;
-  web::WebThread::PostBlockingPoolTask(FROM_HERE, base::BindBlockArc(^{
-                                         ConvertAndSaveGreyImage(
-                                             colorImagePath, greyImagePath,
-                                             backgroundingColorImage);
-                                       }));
+  const base::FilePath cacheDirectory = cacheDirectory_;
+  const ImageScale snapshotsScale = snapshotsScale_;
+
+  web::WebThread::PostBlockingPoolTask(
+      FROM_HERE, base::BindBlockArc(^{
+        ConvertAndSaveGreyImage(sessionID, snapshotsScale,
+                                backgroundingColorImage, cacheDirectory);
+      }));
 }
 
 @end
diff --git a/ios/chrome/browser/snapshots/snapshot_cache_internal.h b/ios/chrome/browser/snapshots/snapshot_cache_internal.h
index 2283f66..672e543 100644
--- a/ios/chrome/browser/snapshots/snapshot_cache_internal.h
+++ b/ios/chrome/browser/snapshots/snapshot_cache_internal.h
@@ -15,9 +15,9 @@
 
 @interface SnapshotCache (Internal)
 // Returns filepath to the color snapshot of |sessionID|.
-+ (base::FilePath)imagePathForSessionID:(NSString*)sessionID;
+- (base::FilePath)imagePathForSessionID:(NSString*)sessionID;
 // Returns filepath to the greyscale snapshot of |sessionID|.
-+ (base::FilePath)greyImagePathForSessionID:(NSString*)sessionID;
+- (base::FilePath)greyImagePathForSessionID:(NSString*)sessionID;
 @end
 
 #endif  // IOS_CHROME_BROWSER_SNAPSHOTS_SNAPSHOT_CACHE_INTERNAL_H_
diff --git a/ios/chrome/browser/snapshots/snapshot_cache_unittest.mm b/ios/chrome/browser/snapshots/snapshot_cache_unittest.mm
index 4c1c2be..b0754899 100644
--- a/ios/chrome/browser/snapshots/snapshot_cache_unittest.mm
+++ b/ios/chrome/browser/snapshots/snapshot_cache_unittest.mm
@@ -41,7 +41,7 @@
     testSessions_.reset(
         [[NSMutableArray alloc] initWithCapacity:kSessionCount]);
 
-    CGFloat scale = [SnapshotCache snapshotScaleForDevice];
+    CGFloat scale = [snapshotCache_ snapshotScaleForDevice];
     UIGraphicsBeginImageContextWithOptions(
         CGSizeMake(kSnapshotPixelSize, kSnapshotPixelSize), NO, scale);
     CGContextRef context = UIGraphicsGetCurrentContext();
@@ -105,7 +105,7 @@
     __block BOOL foundImage = NO;
     __block NSUInteger numCallbacks = 0;
     for (sessionID in testSessions_.get()) {
-      base::FilePath path([SnapshotCache imagePathForSessionID:sessionID]);
+      base::FilePath path([cache imagePathForSessionID:sessionID]);
 
       // Checks that the snapshot is not on disk.
       EXPECT_FALSE(base::PathExists(path));
@@ -147,7 +147,7 @@
       for (NSUInteger i = 0; i < count; ++i) {
         // Check that images are on the disk.
         NSString* sessionID = [testSessions_ objectAtIndex:i];
-        base::FilePath path([SnapshotCache imagePathForSessionID:sessionID]);
+        base::FilePath path([cache imagePathForSessionID:sessionID]);
         EXPECT_TRUE(base::PathExists(path));
       }
     }
@@ -258,7 +258,7 @@
     // Check that images are on the disk.
     NSString* sessionID = [testSessions_ objectAtIndex:i];
 
-    base::FilePath path([SnapshotCache imagePathForSessionID:sessionID]);
+    base::FilePath path([cache imagePathForSessionID:sessionID]);
     EXPECT_TRUE(base::PathExists(path));
 
     // Check image colors by comparing the first pixel against the reference
@@ -322,7 +322,7 @@
     // Check that images are on the disk.
     NSString* sessionID = [testSessions_ objectAtIndex:i];
 
-    base::FilePath path([SnapshotCache imagePathForSessionID:sessionID]);
+    base::FilePath path([cache imagePathForSessionID:sessionID]);
     EXPECT_TRUE(base::PathExists(path));
   }
 
@@ -335,7 +335,7 @@
     // Check that images are on the disk.
     NSString* sessionID = [testSessions_ objectAtIndex:i];
 
-    base::FilePath path([SnapshotCache imagePathForSessionID:sessionID]);
+    base::FilePath path([cache imagePathForSessionID:sessionID]);
     if (i == 0)
       EXPECT_TRUE(base::PathExists(path));
     else
@@ -480,7 +480,6 @@
 
 // Test the function used to save a grey copy of a color snapshot fully on a
 // background thread when the application is backgrounded.
-// Disabled due to the greyImage crash.  b/8048597
 TEST_F(SnapshotCacheTest, GreyImageAllInBackground) {
   LoadAllColorImagesIntoCache(true);
 
@@ -496,7 +495,7 @@
   FlushRunLoops();
 
   for (NSString* sessionID in testSessions_.get()) {
-    base::FilePath path([SnapshotCache greyImagePathForSessionID:sessionID]);
+    base::FilePath path([cache greyImagePathForSessionID:sessionID]);
     EXPECT_TRUE(base::PathExists(path));
     base::DeleteFile(path, false);
   }
@@ -505,8 +504,10 @@
 // Verifies that image size and scale are preserved when writing and reading
 // from disk.
 TEST_F(SnapshotCacheTest, SizeAndScalePreservation) {
+  SnapshotCache* cache = GetSnapshotCache();
+
   // Create an image with the expected snapshot scale.
-  CGFloat scale = [SnapshotCache snapshotScaleForDevice];
+  CGFloat scale = [cache snapshotScaleForDevice];
   UIGraphicsBeginImageContextWithOptions(
       CGSizeMake(kSnapshotPixelSize, kSnapshotPixelSize), NO, scale);
   CGContextRef context = UIGraphicsGetCurrentContext();
@@ -515,7 +516,6 @@
 
   // Add the image to the cache then call handle low memory to ensure the image
   // is read from disk instead of the in-memory cache.
-  SnapshotCache* cache = GetSnapshotCache();
   NSString* const kSession = @"foo";
   [cache setImage:image withSessionID:kSession];
   FlushRunLoops();  // ensure the file is written to disk.
@@ -538,7 +538,8 @@
 
 // Verifies that retina-scale images are deleted properly.
 TEST_F(SnapshotCacheTest, DeleteRetinaImages) {
-  if ([SnapshotCache snapshotScaleForDevice] != 2.0) {
+  SnapshotCache* cache = GetSnapshotCache();
+  if ([cache snapshotScaleForDevice] != 2.0) {
     return;
   }
 
@@ -551,14 +552,13 @@
 
   // Add the image to the cache then call handle low memory to ensure the image
   // is read from disk instead of the in-memory cache.
-  SnapshotCache* cache = GetSnapshotCache();
   NSString* const kSession = @"foo";
   [cache setImage:image withSessionID:kSession];
   FlushRunLoops();  // ensure the file is written to disk.
   TriggerMemoryWarning();
 
   // Verify the file was writted with @2x in the file name.
-  base::FilePath retinaFile = [SnapshotCache imagePathForSessionID:kSession];
+  base::FilePath retinaFile = [cache imagePathForSessionID:kSession];
   EXPECT_TRUE(base::PathExists(retinaFile));
 
   // Delete the image.
diff --git a/ios/chrome/browser/snapshots/snapshot_manager.mm b/ios/chrome/browser/snapshots/snapshot_manager.mm
index 84f684de..3e8f535 100644
--- a/ios/chrome/browser/snapshots/snapshot_manager.mm
+++ b/ios/chrome/browser/snapshots/snapshot_manager.mm
@@ -39,7 +39,8 @@
       << ": size.width=" << size.width;
   DCHECK(std::isnormal(size.height) && (size.height > 0))
       << ": size.height=" << size.height;
-  const CGFloat kScale = [SnapshotCache snapshotScaleForDevice];
+  const CGFloat kScale =
+      [[SnapshotCache sharedInstance] snapshotScaleForDevice];
   UIGraphicsBeginImageContextWithOptions(size, YES, kScale);
   CGContext* context = UIGraphicsGetCurrentContext();
   if (!context) {
diff --git a/ios/chrome/browser/snapshots/web_controller_snapshot_helper.mm b/ios/chrome/browser/snapshots/web_controller_snapshot_helper.mm
index 3a8d301..4e904f14 100644
--- a/ios/chrome/browser/snapshots/web_controller_snapshot_helper.mm
+++ b/ios/chrome/browser/snapshots/web_controller_snapshot_helper.mm
@@ -4,14 +4,16 @@
 
 #import "ios/chrome/browser/snapshots/web_controller_snapshot_helper.h"
 
-#import "base/ios/weak_nsobject.h"
-#import "base/mac/scoped_nsobject.h"
 #import "ios/chrome/browser/snapshots/snapshot_manager.h"
 #import "ios/chrome/browser/tabs/tab.h"
 #import "ios/chrome/browser/tabs/tab_headers_delegate.h"
 #import "ios/chrome/browser/ui/uikit_ui_util.h"
 #import "ios/web/web_state/ui/crw_web_controller.h"
 
+#if !defined(__has_feature) || !__has_feature(objc_arc)
+#error "This file requires ARC support."
+#endif
+
 @interface WebControllerSnapshotHelper ()
 
 // Takes a snapshot image for the WebController's current page. Returns an
@@ -50,7 +52,7 @@
 @end
 
 @implementation CoalescingSnapshotContext {
-  base::scoped_nsobject<UIImage> _cachedSnapshot;
+  UIImage* _cachedSnapshot;
 }
 
 // Returns whether a snapshot should be cached in a page loaded context.
@@ -77,18 +79,18 @@
   if ([self shouldCacheSnapshotWithOverlays:overlays
                            visibleFrameOnly:visibleFrameOnly]) {
     DCHECK(!_cachedSnapshot);
-    _cachedSnapshot.reset([snapshot retain]);
+    _cachedSnapshot = snapshot;
   }
 }
 
 @end
 
 @implementation WebControllerSnapshotHelper {
-  base::scoped_nsobject<CoalescingSnapshotContext> _coalescingSnapshotContext;
-  base::scoped_nsobject<SnapshotManager> _snapshotManager;
-  base::WeakNSObject<CRWWebController> _webController;
+  CoalescingSnapshotContext* _coalescingSnapshotContext;
+  SnapshotManager* _snapshotManager;
+  __weak CRWWebController* _webController;
   // Owns this WebControllerSnapshotHelper.
-  base::WeakNSObject<Tab> _tab;
+  __weak Tab* _tab;
 }
 
 - (instancetype)init {
@@ -104,9 +106,9 @@
     DCHECK(tab);
     DCHECK(tab.tabId);
     DCHECK([tab webController]);
-    _snapshotManager.reset([snapshotManager retain]);
-    _webController.reset([tab webController]);
-    _tab.reset(tab);
+    _snapshotManager = snapshotManager;
+    _webController = [tab webController];
+    _tab = tab;
   }
   return self;
 }
@@ -114,10 +116,10 @@
 - (void)setSnapshotCoalescingEnabled:(BOOL)snapshotCoalescingEnabled {
   if (snapshotCoalescingEnabled) {
     DCHECK(!_coalescingSnapshotContext);
-    _coalescingSnapshotContext.reset([[CoalescingSnapshotContext alloc] init]);
+    _coalescingSnapshotContext = [[CoalescingSnapshotContext alloc] init];
   } else {
     DCHECK(_coalescingSnapshotContext);
-    _coalescingSnapshotContext.reset();
+    _coalescingSnapshotContext = nil;
   }
 }
 
@@ -242,8 +244,7 @@
     UIImage* result = UIGraphicsGetImageFromCurrentImageContext();
     UIGraphicsEndImageContext();
 
-    defaultImage =
-        [[result stretchableImageWithLeftCapWidth:1 topCapHeight:1] retain];
+    defaultImage = [result stretchableImageWithLeftCapWidth:1 topCapHeight:1];
   }
   return defaultImage;
 }
diff --git a/ios/chrome/browser/ssl/BUILD.gn b/ios/chrome/browser/ssl/BUILD.gn
index 29e125e..cd12309 100644
--- a/ios/chrome/browser/ssl/BUILD.gn
+++ b/ios/chrome/browser/ssl/BUILD.gn
@@ -41,7 +41,7 @@
     ":ssl",
     "//ios/chrome/browser/browser_state:test_support",
     "//ios/web",
-    "//ios/web:test_support",
+    "//ios/web/public/test",
     "//net",
     "//net:test_support",
   ]
diff --git a/ios/chrome/browser/store_kit/BUILD.gn b/ios/chrome/browser/store_kit/BUILD.gn
index 02e9d06..234adb4 100644
--- a/ios/chrome/browser/store_kit/BUILD.gn
+++ b/ios/chrome/browser/store_kit/BUILD.gn
@@ -25,7 +25,7 @@
     ":store_kit",
     "//base",
     "//ios/web",
-    "//ios/web:test_support",
+    "//ios/web/public/test",
     "//testing/gtest",
     "//third_party/ocmock:ocmock",
   ]
diff --git a/ios/chrome/browser/sync/BUILD.gn b/ios/chrome/browser/sync/BUILD.gn
index cd24a765..16d626da 100644
--- a/ios/chrome/browser/sync/BUILD.gn
+++ b/ios/chrome/browser/sync/BUILD.gn
@@ -114,7 +114,7 @@
     "//components/browser_sync",
     "//components/sync",
     "//ios/chrome/browser/browser_state:test_support",
-    "//ios/web:test_support",
+    "//ios/web/public/test",
     "//testing/gtest",
   ]
 }
diff --git a/ios/chrome/browser/tabs/BUILD.gn b/ios/chrome/browser/tabs/BUILD.gn
index c73b2c3..2259699 100644
--- a/ios/chrome/browser/tabs/BUILD.gn
+++ b/ios/chrome/browser/tabs/BUILD.gn
@@ -170,7 +170,7 @@
     "//ios/public/provider/chrome/browser/native_app_launcher:test_support",
     "//ios/testing:ocmock_support",
     "//ios/web",
-    "//ios/web:test_support",
+    "//ios/web/public/test",
     "//net",
     "//testing/gtest",
     "//third_party/ocmock",
diff --git a/ios/chrome/browser/test/BUILD.gn b/ios/chrome/browser/test/BUILD.gn
index 72ce1899..992af1f 100644
--- a/ios/chrome/browser/test/BUILD.gn
+++ b/ios/chrome/browser/test/BUILD.gn
@@ -26,7 +26,7 @@
     "//ios/chrome/test:test_support",
     "//ios/chrome/test/base:perf_test_support",
     "//ios/public/provider/chrome/browser",
-    "//ios/web:test_support",
+    "//ios/web/public/test",
 
     # Perf tests can run with any provider, but the resulting numbers will only
     # be meaningful if ChromeBrowserProviderImpl is used.
diff --git a/ios/chrome/browser/translate/BUILD.gn b/ios/chrome/browser/translate/BUILD.gn
index 244fef7..8f70c26 100644
--- a/ios/chrome/browser/translate/BUILD.gn
+++ b/ios/chrome/browser/translate/BUILD.gn
@@ -68,7 +68,7 @@
     "//ios/chrome/common",
     "//ios/public/provider/chrome/browser:test_support",
     "//ios/web",
-    "//ios/web:test_support",
+    "//ios/web/public/test",
     "//testing/gtest",
     "//url",
   ]
@@ -97,7 +97,8 @@
     "//ios/chrome/test/earl_grey:test_support",
     "//ios/testing:ios_test_support",
     "//ios/third_party/earl_grey",
-    "//ios/web:test_support",
+    "//ios/web/public/test",
+    "//ios/web/public/test/http_server",
     "//net",
     "//ui/base",
   ]
diff --git a/ios/chrome/browser/translate/translate_egtest.mm b/ios/chrome/browser/translate/translate_egtest.mm
index 6a17641..946d04b 100644
--- a/ios/chrome/browser/translate/translate_egtest.mm
+++ b/ios/chrome/browser/translate/translate_egtest.mm
@@ -27,9 +27,9 @@
 #import "ios/chrome/test/earl_grey/chrome_matchers.h"
 #import "ios/chrome/test/earl_grey/chrome_test_case.h"
 #import "ios/testing/wait_util.h"
-#import "ios/web/public/test/http_server.h"
-#include "ios/web/public/test/http_server_util.h"
-#include "ios/web/public/test/response_providers/data_response_provider.h"
+#include "ios/web/public/test/http_server/data_response_provider.h"
+#import "ios/web/public/test/http_server/http_server.h"
+#include "ios/web/public/test/http_server/http_server_util.h"
 #include "net/base/url_util.h"
 #include "ui/base/l10n/l10n_util.h"
 
diff --git a/ios/chrome/browser/u2f/BUILD.gn b/ios/chrome/browser/u2f/BUILD.gn
index b79d7ad..bfb6bab 100644
--- a/ios/chrome/browser/u2f/BUILD.gn
+++ b/ios/chrome/browser/u2f/BUILD.gn
@@ -31,7 +31,7 @@
     "//base",
     "//ios/chrome/browser",
     "//ios/web",
-    "//ios/web:test_support",
+    "//ios/web/public/test/fakes",
     "//testing/gmock",
     "//testing/gtest",
     "//url",
diff --git a/ios/chrome/browser/ui/BUILD.gn b/ios/chrome/browser/ui/BUILD.gn
index 419fce24..3acfec22e 100644
--- a/ios/chrome/browser/ui/BUILD.gn
+++ b/ios/chrome/browser/ui/BUILD.gn
@@ -111,7 +111,8 @@
     "//ios/chrome/test:test_support",
     "//ios/testing:ocmock_support",
     "//ios/web",
-    "//ios/web:test_support",
+    "//ios/web/public/test",
+    "//ios/web/public/test/fakes",
     "//net",
     "//net:test_support",
     "//testing/gmock",
@@ -510,7 +511,8 @@
     "//ios/chrome/test/app:test_support",
     "//ios/chrome/test/earl_grey:test_support",
     "//ios/web:earl_grey_test_support",
-    "//ios/web:test_support",
+    "//ios/web/public/test",
+    "//ios/web/public/test/http_server",
     "//ui/base",
   ]
   libs = [ "XCTest.framework" ]
@@ -539,7 +541,8 @@
     "//ios/testing:ios_test_support",
     "//ios/third_party/earl_grey",
     "//ios/web:earl_grey_test_support",
-    "//ios/web:test_support",
+    "//ios/web/public/test",
+    "//ios/web/public/test/http_server",
     "//ui/base",
     "//url",
   ]
@@ -571,7 +574,7 @@
     "//ios/chrome/browser/web_state_list",
     "//ios/chrome/browser/web_state_list:test_support",
     "//ios/chrome/test/base:perf_test_support",
-    "//ios/web:test_support",
+    "//ios/web/public/test/fakes",
     "//testing/gtest",
     "//third_party/ocmock",
     "//ui/base:test_support",
diff --git a/ios/chrome/browser/ui/activity_services/BUILD.gn b/ios/chrome/browser/ui/activity_services/BUILD.gn
index e2e750cd..6c78775b 100644
--- a/ios/chrome/browser/ui/activity_services/BUILD.gn
+++ b/ios/chrome/browser/ui/activity_services/BUILD.gn
@@ -85,7 +85,7 @@
     "//ios/chrome/app/strings",
     "//ios/chrome/browser/browser_state:test_support",
     "//ios/chrome/browser/tabs",
-    "//ios/web:test_support",
+    "//ios/web/public/test",
     "//testing/gtest",
     "//third_party/ocmock",
     "//ui/base",
@@ -109,7 +109,8 @@
     "//ios/chrome/test/earl_grey:test_support",
     "//ios/third_party/material_components_ios",
     "//ios/web:earl_grey_test_support",
-    "//ios/web:test_support",
+    "//ios/web/public/test",
+    "//ios/web/public/test/http_server",
     "//ui/base",
   ]
   libs = [ "XCTest.framework" ]
diff --git a/ios/chrome/browser/ui/activity_services/activity_service_controller_egtest.mm b/ios/chrome/browser/ui/activity_services/activity_service_controller_egtest.mm
index 9e5992d..39be4f7 100644
--- a/ios/chrome/browser/ui/activity_services/activity_service_controller_egtest.mm
+++ b/ios/chrome/browser/ui/activity_services/activity_service_controller_egtest.mm
@@ -9,17 +9,17 @@
 #import "ios/chrome/browser/ui/browser_view_controller_dependency_factory.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/earl_grey/chrome_earl_grey.h"
 #import "ios/chrome/test/earl_grey/chrome_earl_grey_ui.h"
 #import "ios/chrome/test/earl_grey/chrome_matchers.h"
 #import "ios/chrome/test/earl_grey/chrome_test_case.h"
 #import "ios/third_party/material_components_ios/src/components/Snackbar/src/MaterialSnackbar.h"
-#import "ios/chrome/test/app/chrome_test_util.h"
 #import "ios/web/public/test/earl_grey/web_view_matchers.h"
-#import "ios/web/public/test/http_server.h"
-#import "ios/web/public/test/http_server_util.h"
-#include "ios/web/public/test/response_providers/error_page_response_provider.h"
-#include "ios/web/public/test/response_providers/response_provider.h"
+#include "ios/web/public/test/http_server/error_page_response_provider.h"
+#import "ios/web/public/test/http_server/http_server.h"
+#include "ios/web/public/test/http_server/http_server_util.h"
+#include "ios/web/public/test/http_server/response_provider.h"
 #include "ui/base/l10n/l10n_util_mac.h"
 
 #if !defined(__has_feature) || !__has_feature(objc_arc)
diff --git a/ios/chrome/browser/ui/alert_coordinator/BUILD.gn b/ios/chrome/browser/ui/alert_coordinator/BUILD.gn
index 091d8653..ada5adb 100644
--- a/ios/chrome/browser/ui/alert_coordinator/BUILD.gn
+++ b/ios/chrome/browser/ui/alert_coordinator/BUILD.gn
@@ -40,7 +40,7 @@
     "//components/strings",
     "//ios/chrome/browser/ui",
     "//ios/chrome/test:test_support",
-    "//ios/web:test_support",
+    "//ios/web/public/test/fakes",
     "//testing/gtest",
     "//third_party/ocmock",
     "//ui/base",
diff --git a/ios/chrome/browser/ui/authentication/BUILD.gn b/ios/chrome/browser/ui/authentication/BUILD.gn
index be66384..ef51df33 100644
--- a/ios/chrome/browser/ui/authentication/BUILD.gn
+++ b/ios/chrome/browser/ui/authentication/BUILD.gn
@@ -182,7 +182,7 @@
     "//ios/chrome/test:test_support",
     "//ios/public/provider/chrome/browser/signin:test_support",
     "//ios/third_party/material_components_ios",
-    "//ios/web:test_support",
+    "//ios/web/public/test",
     "//testing/gtest",
     "//third_party/ocmock",
     "//ui/base",
diff --git a/ios/chrome/browser/ui/bookmarks/BUILD.gn b/ios/chrome/browser/ui/bookmarks/BUILD.gn
index 8254035..24e3b9fe 100644
--- a/ios/chrome/browser/ui/bookmarks/BUILD.gn
+++ b/ios/chrome/browser/ui/bookmarks/BUILD.gn
@@ -144,7 +144,7 @@
     "//ios/chrome/browser",
     "//ios/chrome/browser/bookmarks",
     "//ios/chrome/browser/browser_state:test_support",
-    "//ios/web:test_support",
+    "//ios/web/public/test",
     "//testing/gtest",
   ]
 }
@@ -174,7 +174,7 @@
     "//ios/public/provider/chrome/browser/signin:test_support",
     "//ios/testing:ios_test_support",
     "//ios/third_party/earl_grey",
-    "//ios/web:test_support",
+    "//ios/web/public/test/http_server",
     "//ui/base",
     "//url",
   ]
diff --git a/ios/chrome/browser/ui/bookmarks/bookmarks_egtest.mm b/ios/chrome/browser/ui/bookmarks/bookmarks_egtest.mm
index 3605e785..653bce0 100644
--- a/ios/chrome/browser/ui/bookmarks/bookmarks_egtest.mm
+++ b/ios/chrome/browser/ui/bookmarks/bookmarks_egtest.mm
@@ -36,8 +36,8 @@
 #import "ios/public/provider/chrome/browser/signin/fake_chrome_identity.h"
 #import "ios/public/provider/chrome/browser/signin/fake_chrome_identity_service.h"
 #import "ios/testing/wait_util.h"
-#import "ios/web/public/test/http_server.h"
-#include "ios/web/public/test/http_server_util.h"
+#import "ios/web/public/test/http_server/http_server.h"
+#include "ios/web/public/test/http_server/http_server_util.h"
 #include "ui/base/l10n/l10n_util.h"
 #include "ui/base/models/tree_node_iterator.h"
 #include "url/gurl.h"
diff --git a/ios/chrome/browser/ui/browser_view_controller_egtest.mm b/ios/chrome/browser/ui/browser_view_controller_egtest.mm
index e39d500..b6445ba 100644
--- a/ios/chrome/browser/ui/browser_view_controller_egtest.mm
+++ b/ios/chrome/browser/ui/browser_view_controller_egtest.mm
@@ -16,9 +16,9 @@
 #import "ios/chrome/test/earl_grey/chrome_earl_grey.h"
 #import "ios/chrome/test/earl_grey/chrome_matchers.h"
 #import "ios/chrome/test/earl_grey/chrome_test_case.h"
-#import "ios/web/public/test/http_server.h"
-#include "ios/web/public/test/http_server_util.h"
-#include "ios/web/public/test/response_providers/html_response_provider.h"
+#include "ios/web/public/test/http_server/html_response_provider.h"
+#import "ios/web/public/test/http_server/http_server.h"
+#include "ios/web/public/test/http_server/http_server_util.h"
 #include "ui/base/l10n/l10n_util.h"
 
 #if !defined(__has_feature) || !__has_feature(objc_arc)
diff --git a/ios/chrome/browser/ui/contextual_search/BUILD.gn b/ios/chrome/browser/ui/contextual_search/BUILD.gn
index 1ad528c..7b4a8e9 100644
--- a/ios/chrome/browser/ui/contextual_search/BUILD.gn
+++ b/ios/chrome/browser/ui/contextual_search/BUILD.gn
@@ -138,7 +138,7 @@
     "//ios/chrome/browser/sync:test_support",
     "//ios/chrome/browser/web:test_support",
     "//ios/web",
-    "//ios/web:test_support",
+    "//ios/web/public/test",
     "//net",
     "//testing/gtest",
     "//third_party/ocmock",
diff --git a/ios/chrome/browser/ui/dialogs/BUILD.gn b/ios/chrome/browser/ui/dialogs/BUILD.gn
index d28a3a5..0cb7340 100644
--- a/ios/chrome/browser/ui/dialogs/BUILD.gn
+++ b/ios/chrome/browser/ui/dialogs/BUILD.gn
@@ -26,7 +26,7 @@
   deps = [
     ":dialogs",
     "//ios/web",
-    "//ios/web:test_support",
+    "//ios/web/public/test/fakes",
     "//testing/gtest",
   ]
 
@@ -72,7 +72,7 @@
     "//ios/chrome/app/strings",
     "//ios/chrome/browser/ui/alert_coordinator",
     "//ios/web",
-    "//ios/web:test_support",
+    "//ios/web/public/test/fakes",
     "//testing/gtest",
     "//ui/base",
     "//url",
@@ -98,7 +98,8 @@
     "//ios/testing/earl_grey:earl_grey_support",
     "//ios/third_party/earl_grey",
     "//ios/web",
-    "//ios/web:test_support",
+    "//ios/web/public/test",
+    "//ios/web/public/test/http_server",
     "//ui/base",
     "//url",
   ]
diff --git a/ios/chrome/browser/ui/dialogs/javascript_dialog_egtest.mm b/ios/chrome/browser/ui/dialogs/javascript_dialog_egtest.mm
index 45c395d3..a14b69e 100644
--- a/ios/chrome/browser/ui/dialogs/javascript_dialog_egtest.mm
+++ b/ios/chrome/browser/ui/dialogs/javascript_dialog_egtest.mm
@@ -21,8 +21,8 @@
 #import "ios/chrome/test/earl_grey/chrome_test_case.h"
 #import "ios/testing/earl_grey/matchers.h"
 #import "ios/testing/wait_util.h"
-#import "ios/web/public/test/http_server.h"
-#import "ios/web/public/test/http_server_util.h"
+#import "ios/web/public/test/http_server/http_server.h"
+#include "ios/web/public/test/http_server/http_server_util.h"
 #include "ios/web/public/test/url_test_util.h"
 #include "ios/web/public/web_state/web_state.h"
 #include "ui/base/l10n/l10n_util.h"
diff --git a/ios/chrome/browser/ui/downloads/BUILD.gn b/ios/chrome/browser/ui/downloads/BUILD.gn
index c8bafe4..b0bd380 100644
--- a/ios/chrome/browser/ui/downloads/BUILD.gn
+++ b/ios/chrome/browser/ui/downloads/BUILD.gn
@@ -78,7 +78,7 @@
     "//ios/chrome/browser",
     "//ios/chrome/browser/store_kit",
     "//ios/chrome/browser/web:test_support",
-    "//ios/web:test_support",
+    "//ios/web/public/test",
     "//net:test_support",
     "//testing/gtest",
     "//third_party/ocmock:ocmock",
diff --git a/ios/chrome/browser/ui/external_url_error_page_egtest.mm b/ios/chrome/browser/ui/external_url_error_page_egtest.mm
index efb9806c..176620d 100644
--- a/ios/chrome/browser/ui/external_url_error_page_egtest.mm
+++ b/ios/chrome/browser/ui/external_url_error_page_egtest.mm
@@ -11,10 +11,10 @@
 #import "ios/chrome/test/earl_grey/chrome_matchers.h"
 #import "ios/chrome/test/earl_grey/chrome_test_case.h"
 #import "ios/web/public/test/earl_grey/web_view_matchers.h"
-#import "ios/web/public/test/http_server.h"
-#include "ios/web/public/test/http_server_util.h"
-#include "ios/web/public/test/response_providers/data_response_provider.h"
-#include "ios/web/public/test/response_providers/error_page_response_provider.h"
+#include "ios/web/public/test/http_server/data_response_provider.h"
+#include "ios/web/public/test/http_server/error_page_response_provider.h"
+#import "ios/web/public/test/http_server/http_server.h"
+#include "ios/web/public/test/http_server/http_server_util.h"
 #include "ui/base/l10n/l10n_util.h"
 #include "ui/base/l10n/l10n_util_mac.h"
 
diff --git a/ios/chrome/browser/ui/find_bar/BUILD.gn b/ios/chrome/browser/ui/find_bar/BUILD.gn
index fa5f496..dd2e3eb 100644
--- a/ios/chrome/browser/ui/find_bar/BUILD.gn
+++ b/ios/chrome/browser/ui/find_bar/BUILD.gn
@@ -99,7 +99,7 @@
     "//ios/chrome/test/app:test_support",
     "//ios/chrome/test/earl_grey:test_support",
     "//ios/testing:ios_test_support",
-    "//ios/web:test_support",
+    "//ios/web/public/test/http_server",
     "//ui/base",
   ]
   libs = [ "XCTest.framework" ]
diff --git a/ios/chrome/browser/ui/find_bar/find_in_page_egtest.mm b/ios/chrome/browser/ui/find_bar/find_in_page_egtest.mm
index 0864dcc..99f47694 100644
--- a/ios/chrome/browser/ui/find_bar/find_in_page_egtest.mm
+++ b/ios/chrome/browser/ui/find_bar/find_in_page_egtest.mm
@@ -18,8 +18,8 @@
 #import "ios/chrome/test/earl_grey/chrome_matchers.h"
 #import "ios/chrome/test/earl_grey/chrome_test_case.h"
 #import "ios/testing/wait_util.h"
-#import "ios/web/public/test/http_server.h"
-#import "ios/web/public/test/http_server_util.h"
+#import "ios/web/public/test/http_server/http_server.h"
+#include "ios/web/public/test/http_server/http_server_util.h"
 #include "ui/base/l10n/l10n_util_mac.h"
 
 #if !defined(__has_feature) || !__has_feature(objc_arc)
diff --git a/ios/chrome/browser/ui/first_run/BUILD.gn b/ios/chrome/browser/ui/first_run/BUILD.gn
index 7ed8dec..cb132a4 100644
--- a/ios/chrome/browser/ui/first_run/BUILD.gn
+++ b/ios/chrome/browser/ui/first_run/BUILD.gn
@@ -92,7 +92,7 @@
     "//ios/chrome/browser/ui",
     "//ios/chrome/browser/ui/fancy_ui",
     "//ios/chrome/test:test_support",
-    "//ios/web:test_support",
+    "//ios/web/public/test",
     "//testing/gtest",
     "//third_party/ocmock",
   ]
diff --git a/ios/chrome/browser/ui/fullscreen_controller.h b/ios/chrome/browser/ui/fullscreen_controller.h
index 33c65bce..bc6f858 100644
--- a/ios/chrome/browser/ui/fullscreen_controller.h
+++ b/ios/chrome/browser/ui/fullscreen_controller.h
@@ -119,8 +119,6 @@
 // Enables/Disables the FullScreenController in tests. The unit tests do not set
 // the delegate which is crucial for methods to work on the controller.
 // This a temporary solution.
-// TODO(shreyasv): Find a better solution/remove this when FullScreenController
-// moves to Tab.
 + (void)setEnabledForTests:(BOOL)enabled;
 @end
 
diff --git a/ios/chrome/browser/ui/fullscreen_egtest.mm b/ios/chrome/browser/ui/fullscreen_egtest.mm
index 62adad1..b61d981 100644
--- a/ios/chrome/browser/ui/fullscreen_egtest.mm
+++ b/ios/chrome/browser/ui/fullscreen_egtest.mm
@@ -22,9 +22,9 @@
 #import "ios/chrome/test/earl_grey/chrome_test_case.h"
 #import "ios/testing/wait_util.h"
 #import "ios/web/public/test/earl_grey/web_view_matchers.h"
-#import "ios/web/public/test/http_server.h"
-#import "ios/web/public/test/http_server_util.h"
-#import "ios/web/public/test/response_providers/error_page_response_provider.h"
+#import "ios/web/public/test/http_server/error_page_response_provider.h"
+#import "ios/web/public/test/http_server/http_server.h"
+#include "ios/web/public/test/http_server/http_server_util.h"
 #import "ios/web/public/test/web_view_interaction_test_util.h"
 #include "url/gurl.h"
 
diff --git a/ios/chrome/browser/ui/history/BUILD.gn b/ios/chrome/browser/ui/history/BUILD.gn
index 373847d6..db6baae0 100644
--- a/ios/chrome/browser/ui/history/BUILD.gn
+++ b/ios/chrome/browser/ui/history/BUILD.gn
@@ -125,7 +125,7 @@
     "//ios/chrome/common",
     "//ios/chrome/test:test_support",
     "//ios/web",
-    "//ios/web:test_support",
+    "//ios/web/public/test",
     "//skia",
     "//testing/gmock",
     "//testing/gtest",
@@ -174,7 +174,7 @@
     "//ios/chrome/common",
     "//ios/chrome/test:test_support",
     "//ios/web",
-    "//ios/web:test_support",
+    "//ios/web/public/test",
     "//skia",
     "//testing/gmock",
     "//testing/gtest",
@@ -227,7 +227,8 @@
     "//ios/public/provider/chrome/browser/signin:test_support",
     "//ios/testing:ios_test_support",
     "//ios/third_party/earl_grey",
-    "//ios/web:test_support",
+    "//ios/web/public/test",
+    "//ios/web/public/test/http_server",
     "//net",
     "//ui/base",
   ]
diff --git a/ios/chrome/browser/ui/history/history_ui_egtest.mm b/ios/chrome/browser/ui/history/history_ui_egtest.mm
index 014dfa30..beae9e1 100644
--- a/ios/chrome/browser/ui/history/history_ui_egtest.mm
+++ b/ios/chrome/browser/ui/history/history_ui_egtest.mm
@@ -32,8 +32,8 @@
 #import "ios/public/provider/chrome/browser/signin/fake_chrome_identity.h"
 #import "ios/public/provider/chrome/browser/signin/fake_chrome_identity_service.h"
 #import "ios/testing/wait_util.h"
-#import "ios/web/public/test/http_server.h"
-#import "ios/web/public/test/http_server_util.h"
+#import "ios/web/public/test/http_server/http_server.h"
+#import "ios/web/public/test/http_server/http_server_util.h"
 #import "net/base/mac/url_conversions.h"
 #include "ui/base/l10n/l10n_util.h"
 
diff --git a/ios/chrome/browser/ui/history/tab_history_popup_controller_egtest.mm b/ios/chrome/browser/ui/history/tab_history_popup_controller_egtest.mm
index 5ed4e78..f01f764 100644
--- a/ios/chrome/browser/ui/history/tab_history_popup_controller_egtest.mm
+++ b/ios/chrome/browser/ui/history/tab_history_popup_controller_egtest.mm
@@ -9,8 +9,8 @@
 #import "ios/chrome/test/earl_grey/chrome_earl_grey.h"
 #import "ios/chrome/test/earl_grey/chrome_matchers.h"
 #import "ios/chrome/test/earl_grey/chrome_test_case.h"
-#import "ios/web/public/test/http_server.h"
-#import "ios/web/public/test/http_server_util.h"
+#import "ios/web/public/test/http_server/http_server.h"
+#import "ios/web/public/test/http_server/http_server_util.h"
 #include "ios/web/public/test/url_test_util.h"
 
 #if !defined(__has_feature) || !__has_feature(objc_arc)
diff --git a/ios/chrome/browser/ui/infobars/BUILD.gn b/ios/chrome/browser/ui/infobars/BUILD.gn
index 405fd269..46558788 100644
--- a/ios/chrome/browser/ui/infobars/BUILD.gn
+++ b/ios/chrome/browser/ui/infobars/BUILD.gn
@@ -57,7 +57,7 @@
     "//ios/chrome/test/app:test_support",
     "//ios/chrome/test/earl_grey:test_support",
     "//ios/third_party/earl_grey",
-    "//ios/web:test_support",
+    "//ios/web/public/test/http_server",
     "//url",
   ]
   libs = [ "XCTest.framework" ]
diff --git a/ios/chrome/browser/ui/infobars/infobar_egtest.mm b/ios/chrome/browser/ui/infobars/infobar_egtest.mm
index 2306d72..1982579 100644
--- a/ios/chrome/browser/ui/infobars/infobar_egtest.mm
+++ b/ios/chrome/browser/ui/infobars/infobar_egtest.mm
@@ -19,8 +19,8 @@
 #import "ios/chrome/test/earl_grey/chrome_earl_grey.h"
 #import "ios/chrome/test/earl_grey/chrome_matchers.h"
 #import "ios/chrome/test/earl_grey/chrome_test_case.h"
-#import "ios/web/public/test/http_server.h"
-#include "ios/web/public/test/http_server_util.h"
+#import "ios/web/public/test/http_server/http_server.h"
+#include "ios/web/public/test/http_server/http_server_util.h"
 #include "url/gurl.h"
 #include "url/url_constants.h"
 
diff --git a/ios/chrome/browser/ui/keyboard_commands_egtest.mm b/ios/chrome/browser/ui/keyboard_commands_egtest.mm
index 971ce430..2b72f680 100644
--- a/ios/chrome/browser/ui/keyboard_commands_egtest.mm
+++ b/ios/chrome/browser/ui/keyboard_commands_egtest.mm
@@ -21,8 +21,8 @@
 #import "ios/chrome/test/earl_grey/chrome_earl_grey_ui.h"
 #import "ios/chrome/test/earl_grey/chrome_matchers.h"
 #import "ios/chrome/test/earl_grey/chrome_test_case.h"
-#import "ios/web/public/test/http_server.h"
-#include "ios/web/public/test/http_server_util.h"
+#import "ios/web/public/test/http_server/http_server.h"
+#include "ios/web/public/test/http_server/http_server_util.h"
 
 #if !defined(__has_feature) || !__has_feature(objc_arc)
 #error "This file requires ARC support."
diff --git a/ios/chrome/browser/ui/main/BUILD.gn b/ios/chrome/browser/ui/main/BUILD.gn
index 4f3bbc84..9b8fac54 100644
--- a/ios/chrome/browser/ui/main/BUILD.gn
+++ b/ios/chrome/browser/ui/main/BUILD.gn
@@ -49,7 +49,7 @@
     "//ios/chrome/browser/browser_state:test_support",
     "//ios/chrome/browser/tabs",
     "//ios/chrome/browser/ui:ui_internal",
-    "//ios/web:test_support",
+    "//ios/web/public/test",
     "//testing/gtest",
   ]
 }
diff --git a/ios/chrome/browser/ui/ntp/BUILD.gn b/ios/chrome/browser/ui/ntp/BUILD.gn
index 5cd58c03..60285e5 100644
--- a/ios/chrome/browser/ui/ntp/BUILD.gn
+++ b/ios/chrome/browser/ui/ntp/BUILD.gn
@@ -268,7 +268,7 @@
     "//ios/chrome/browser/web_state_list:web_state_list",
     "//ios/chrome/test:test_support",
     "//ios/public/provider/chrome/browser/images",
-    "//ios/web:test_support",
+    "//ios/web/public/test",
     "//testing/gtest",
     "//third_party/ocmock",
     "//ui/base",
diff --git a/ios/chrome/browser/ui/ntp/recent_tabs/BUILD.gn b/ios/chrome/browser/ui/ntp/recent_tabs/BUILD.gn
index 782cb8d..4cf4957 100644
--- a/ios/chrome/browser/ui/ntp/recent_tabs/BUILD.gn
+++ b/ios/chrome/browser/ui/ntp/recent_tabs/BUILD.gn
@@ -71,7 +71,7 @@
     "//ios/chrome/browser/sync:test_support",
     "//ios/chrome/browser/ui/ntp:ntp_internal",
     "//ios/chrome/test:test_support",
-    "//ios/web:test_support",
+    "//ios/web/public/test",
     "//testing/gtest",
     "//third_party/ocmock",
   ]
@@ -91,7 +91,7 @@
     "//ios/chrome/test/app:test_support",
     "//ios/chrome/test/earl_grey:test_support",
     "//ios/third_party/earl_grey",
-    "//ios/web:test_support",
+    "//ios/web/public/test/http_server",
   ]
   libs = [ "XCTest.framework" ]
 }
diff --git a/ios/chrome/browser/ui/ntp/recent_tabs/recent_tabs_panel_controller_egtest.mm b/ios/chrome/browser/ui/ntp/recent_tabs/recent_tabs_panel_controller_egtest.mm
index f350245..a062b21 100644
--- a/ios/chrome/browser/ui/ntp/recent_tabs/recent_tabs_panel_controller_egtest.mm
+++ b/ios/chrome/browser/ui/ntp/recent_tabs/recent_tabs_panel_controller_egtest.mm
@@ -17,8 +17,8 @@
 #import "ios/chrome/test/earl_grey/chrome_earl_grey_ui.h"
 #import "ios/chrome/test/earl_grey/chrome_matchers.h"
 #import "ios/chrome/test/earl_grey/chrome_test_case.h"
-#import "ios/web/public/test/http_server.h"
-#include "ios/web/public/test/http_server_util.h"
+#import "ios/web/public/test/http_server/http_server.h"
+#include "ios/web/public/test/http_server/http_server_util.h"
 
 #if !defined(__has_feature) || !__has_feature(objc_arc)
 #error "This file requires ARC support."
diff --git a/ios/chrome/browser/ui/payments/BUILD.gn b/ios/chrome/browser/ui/payments/BUILD.gn
index f37688f..f11fb097 100644
--- a/ios/chrome/browser/ui/payments/BUILD.gn
+++ b/ios/chrome/browser/ui/payments/BUILD.gn
@@ -175,7 +175,7 @@
     "//ios/testing:ocmock_support",
     "//ios/third_party/material_components_ios",
     "//ios/web",
-    "//ios/web:test_support",
+    "//ios/web/public/test",
     "//testing/gmock",
     "//testing/gtest",
     "//third_party/ocmock",
diff --git a/ios/chrome/browser/ui/print/BUILD.gn b/ios/chrome/browser/ui/print/BUILD.gn
index 3215362..fabf5878 100644
--- a/ios/chrome/browser/ui/print/BUILD.gn
+++ b/ios/chrome/browser/ui/print/BUILD.gn
@@ -33,7 +33,7 @@
     "//ios/chrome/test/app:test_support",
     "//ios/chrome/test/earl_grey:test_support",
     "//ios/third_party/earl_grey",
-    "//ios/web:test_support",
+    "//ios/web/public/test/http_server",
     "//ui/base",
     "//url",
   ]
diff --git a/ios/chrome/browser/ui/print/print_controller_egtest.mm b/ios/chrome/browser/ui/print/print_controller_egtest.mm
index c5f7987d..066babc 100644
--- a/ios/chrome/browser/ui/print/print_controller_egtest.mm
+++ b/ios/chrome/browser/ui/print/print_controller_egtest.mm
@@ -12,8 +12,8 @@
 #import "ios/chrome/test/earl_grey/chrome_earl_grey_ui.h"
 #import "ios/chrome/test/earl_grey/chrome_matchers.h"
 #import "ios/chrome/test/earl_grey/chrome_test_case.h"
-#import "ios/web/public/test/http_server.h"
-#import "ios/web/public/test/http_server_util.h"
+#import "ios/web/public/test/http_server/http_server.h"
+#include "ios/web/public/test/http_server/http_server_util.h"
 #include "ui/base/l10n/l10n_util_mac.h"
 #include "url/gurl.h"
 
diff --git a/ios/chrome/browser/ui/promos/BUILD.gn b/ios/chrome/browser/ui/promos/BUILD.gn
index 2a8131f..ef35caf 100644
--- a/ios/chrome/browser/ui/promos/BUILD.gn
+++ b/ios/chrome/browser/ui/promos/BUILD.gn
@@ -44,7 +44,7 @@
     "//ios/chrome/browser/signin:test_support",
     "//ios/chrome/test:test_support",
     "//ios/public/provider/chrome/browser/signin:test_support",
-    "//ios/web:test_support",
+    "//ios/web/public/test",
     "//testing/gtest",
     "//third_party/ocmock",
   ]
diff --git a/ios/chrome/browser/ui/qr_scanner/BUILD.gn b/ios/chrome/browser/ui/qr_scanner/BUILD.gn
index 1eb05b7..9618c87d 100644
--- a/ios/chrome/browser/ui/qr_scanner/BUILD.gn
+++ b/ios/chrome/browser/ui/qr_scanner/BUILD.gn
@@ -75,7 +75,7 @@
     "//ios/shared/chrome/browser/ui/omnibox",
     "//ios/testing/earl_grey:earl_grey_support",
     "//ios/third_party/earl_grey",
-    "//ios/web:test_support",
+    "//ios/web/public/test/http_server",
     "//third_party/ocmock",
     "//ui/base",
   ]
diff --git a/ios/chrome/browser/ui/qr_scanner/qr_scanner_view_controller_egtest.mm b/ios/chrome/browser/ui/qr_scanner/qr_scanner_view_controller_egtest.mm
index e656803c..468065a 100644
--- a/ios/chrome/browser/ui/qr_scanner/qr_scanner_view_controller_egtest.mm
+++ b/ios/chrome/browser/ui/qr_scanner/qr_scanner_view_controller_egtest.mm
@@ -28,8 +28,8 @@
 #import "ios/chrome/test/earl_grey/chrome_matchers.h"
 #import "ios/chrome/test/earl_grey/chrome_test_case.h"
 #include "ios/shared/chrome/browser/ui/omnibox/location_bar_delegate.h"
-#include "ios/web/public/test/http_server.h"
-#include "ios/web/public/test/http_server_util.h"
+#import "ios/web/public/test/http_server/http_server.h"
+#include "ios/web/public/test/http_server/http_server_util.h"
 #import "third_party/ocmock/OCMock/OCMock.h"
 #import "ui/base/l10n/l10n_util.h"
 #import "ui/base/l10n/l10n_util_mac.h"
diff --git a/ios/chrome/browser/ui/reading_list/BUILD.gn b/ios/chrome/browser/ui/reading_list/BUILD.gn
index 762560e..4ef334a 100644
--- a/ios/chrome/browser/ui/reading_list/BUILD.gn
+++ b/ios/chrome/browser/ui/reading_list/BUILD.gn
@@ -98,7 +98,7 @@
     "//ios/chrome/browser/ui",
     "//ios/chrome/browser/ui/static_content",
     "//ios/web",
-    "//ios/web:test_support",
+    "//ios/web/public/test",
     "//testing/gtest",
     "//third_party/ocmock",
     "//ui/base",
@@ -129,7 +129,8 @@
     "//ios/third_party/material_components_ios",
     "//ios/web",
     "//ios/web:reload_type",
-    "//ios/web:test_support",
+    "//ios/web/public/test",
+    "//ios/web/public/test/http_server",
     "//net",
   ]
   libs = [
diff --git a/ios/chrome/browser/ui/reading_list/reading_list_egtest.mm b/ios/chrome/browser/ui/reading_list/reading_list_egtest.mm
index e37e6cd..d1e78e8a 100644
--- a/ios/chrome/browser/ui/reading_list/reading_list_egtest.mm
+++ b/ios/chrome/browser/ui/reading_list/reading_list_egtest.mm
@@ -31,10 +31,10 @@
 #import "ios/third_party/material_components_ios/src/components/Snackbar/src/MaterialSnackbar.h"
 #import "ios/web/public/navigation_manager.h"
 #import "ios/web/public/reload_type.h"
-#import "ios/web/public/test/http_server.h"
-#import "ios/web/public/test/http_server_util.h"
-#import "ios/web/public/test/response_providers/delayed_response_provider.h"
-#import "ios/web/public/test/response_providers/html_response_provider.h"
+#import "ios/web/public/test/http_server/delayed_response_provider.h"
+#import "ios/web/public/test/http_server/html_response_provider.h"
+#import "ios/web/public/test/http_server/http_server.h"
+#include "ios/web/public/test/http_server/http_server_util.h"
 #include "net/base/network_change_notifier.h"
 
 #if !defined(__has_feature) || !__has_feature(objc_arc)
diff --git a/ios/chrome/browser/ui/settings/BUILD.gn b/ios/chrome/browser/ui/settings/BUILD.gn
index 1b95fc0..6ae3b8d 100644
--- a/ios/chrome/browser/ui/settings/BUILD.gn
+++ b/ios/chrome/browser/ui/settings/BUILD.gn
@@ -235,7 +235,7 @@
     "//ios/chrome/browser/sync:test_support",
     "//ios/chrome/browser/ui/collection_view:test_support",
     "//ios/public/provider/chrome/browser/signin:test_support",
-    "//ios/web:test_support",
+    "//ios/web/public/test",
     "//testing/gtest",
   ]
 }
@@ -329,7 +329,7 @@
     "//ios/public/provider/chrome/browser/voice",
     "//ios/third_party/material_components_ios",
     "//ios/web",
-    "//ios/web:test_support",
+    "//ios/web/public/test",
     "//net",
     "//net:test_support",
     "//testing/gmock",
@@ -386,7 +386,8 @@
     "//ios/testing/earl_grey:earl_grey_support",
     "//ios/third_party/earl_grey",
     "//ios/web",
-    "//ios/web:test_support",
+    "//ios/web/public/test",
+    "//ios/web/public/test/http_server",
     "//net",
     "//ui/base",
     "//url",
diff --git a/ios/chrome/browser/ui/settings/autofill_settings_egtest.mm b/ios/chrome/browser/ui/settings/autofill_settings_egtest.mm
index ce16d3f..07e92304 100644
--- a/ios/chrome/browser/ui/settings/autofill_settings_egtest.mm
+++ b/ios/chrome/browser/ui/settings/autofill_settings_egtest.mm
@@ -13,8 +13,8 @@
 #import "ios/chrome/test/earl_grey/chrome_earl_grey_ui.h"
 #import "ios/chrome/test/earl_grey/chrome_matchers.h"
 #import "ios/chrome/test/earl_grey/chrome_test_case.h"
-#import "ios/web/public/test/http_server.h"
-#include "ios/web/public/test/http_server_util.h"
+#import "ios/web/public/test/http_server/http_server.h"
+#include "ios/web/public/test/http_server/http_server_util.h"
 #include "ui/base/l10n/l10n_util.h"
 
 #if !defined(__has_feature) || !__has_feature(objc_arc)
diff --git a/ios/chrome/browser/ui/settings/block_popups_egtest.mm b/ios/chrome/browser/ui/settings/block_popups_egtest.mm
index 968d670..58fbbaa 100644
--- a/ios/chrome/browser/ui/settings/block_popups_egtest.mm
+++ b/ios/chrome/browser/ui/settings/block_popups_egtest.mm
@@ -25,8 +25,8 @@
 #import "ios/chrome/test/earl_grey/chrome_earl_grey_ui.h"
 #import "ios/chrome/test/earl_grey/chrome_matchers.h"
 #import "ios/chrome/test/earl_grey/chrome_test_case.h"
-#import "ios/web/public/test/http_server.h"
-#include "ios/web/public/test/http_server_util.h"
+#import "ios/web/public/test/http_server/http_server.h"
+#include "ios/web/public/test/http_server/http_server_util.h"
 #import "ios/web/public/test/web_view_interaction_test_util.h"
 #include "ui/base/l10n/l10n_util_mac.h"
 #include "url/gurl.h"
diff --git a/ios/chrome/browser/ui/settings/settings_egtest.mm b/ios/chrome/browser/ui/settings/settings_egtest.mm
index 35a579c5..0382d89 100644
--- a/ios/chrome/browser/ui/settings/settings_egtest.mm
+++ b/ios/chrome/browser/ui/settings/settings_egtest.mm
@@ -40,8 +40,8 @@
 #import "ios/chrome/test/earl_grey/chrome_earl_grey_ui.h"
 #import "ios/chrome/test/earl_grey/chrome_matchers.h"
 #import "ios/chrome/test/earl_grey/chrome_test_case.h"
-#import "ios/web/public/test/http_server.h"
-#include "ios/web/public/test/http_server_util.h"
+#import "ios/web/public/test/http_server/http_server.h"
+#include "ios/web/public/test/http_server/http_server_util.h"
 #import "ios/web/public/test/web_view_interaction_test_util.h"
 #import "ios/web/public/web_state/web_state.h"
 #include "ios/web/public/web_thread.h"
diff --git a/ios/chrome/browser/ui/settings/utils/BUILD.gn b/ios/chrome/browser/ui/settings/utils/BUILD.gn
index 06dcac4..2e4473c 100644
--- a/ios/chrome/browser/ui/settings/utils/BUILD.gn
+++ b/ios/chrome/browser/ui/settings/utils/BUILD.gn
@@ -49,7 +49,7 @@
     "//components/sync_preferences:test_support",
     "//ios/chrome/browser/browser_state:test_support",
     "//ios/chrome/browser/content_settings",
-    "//ios/web:test_support",
+    "//ios/web/public/test",
     "//testing/gtest",
   ]
 }
diff --git a/ios/chrome/browser/ui/side_swipe/BUILD.gn b/ios/chrome/browser/ui/side_swipe/BUILD.gn
index 4130c43..7365ad5 100644
--- a/ios/chrome/browser/ui/side_swipe/BUILD.gn
+++ b/ios/chrome/browser/ui/side_swipe/BUILD.gn
@@ -65,7 +65,7 @@
     "//base",
     "//ios/chrome/browser/browser_state:test_support",
     "//ios/chrome/browser/ui/toolbar",
-    "//ios/web:test_support",
+    "//ios/web/public/test",
     "//testing/gtest",
     "//third_party/ocmock",
   ]
diff --git a/ios/chrome/browser/ui/static_content/BUILD.gn b/ios/chrome/browser/ui/static_content/BUILD.gn
index 307a2708..b0be5865 100644
--- a/ios/chrome/browser/ui/static_content/BUILD.gn
+++ b/ios/chrome/browser/ui/static_content/BUILD.gn
@@ -34,7 +34,8 @@
     "//ios/chrome/browser/ui",
     "//ios/testing:ocmock_support",
     "//ios/web",
-    "//ios/web:test_support",
+    "//ios/web/public/test",
+    "//ios/web/public/test/fakes",
     "//net",
     "//testing/gtest",
     "//third_party/ocmock",
diff --git a/ios/chrome/browser/ui/sync/BUILD.gn b/ios/chrome/browser/ui/sync/BUILD.gn
index 53aaf3e..c889262b 100644
--- a/ios/chrome/browser/ui/sync/BUILD.gn
+++ b/ios/chrome/browser/ui/sync/BUILD.gn
@@ -52,7 +52,7 @@
     "//ios/public/provider/chrome/browser/signin:test_support",
     "//ios/testing:ios_test_support",
     "//ios/third_party/earl_grey",
-    "//ios/web:test_support",
+    "//ios/web/public/test/http_server",
     "//net",
     "//ui/base",
     "//url",
diff --git a/ios/chrome/browser/ui/sync/sync_fake_server_egtest.mm b/ios/chrome/browser/ui/sync/sync_fake_server_egtest.mm
index 71cd0e37..f45b4cd 100644
--- a/ios/chrome/browser/ui/sync/sync_fake_server_egtest.mm
+++ b/ios/chrome/browser/ui/sync/sync_fake_server_egtest.mm
@@ -32,8 +32,8 @@
 #import "ios/public/provider/chrome/browser/signin/fake_chrome_identity.h"
 #import "ios/public/provider/chrome/browser/signin/fake_chrome_identity_service.h"
 #import "ios/testing/wait_util.h"
-#import "ios/web/public/test/http_server.h"
-#import "ios/web/public/test/http_server_util.h"
+#import "ios/web/public/test/http_server/http_server.h"
+#include "ios/web/public/test/http_server/http_server_util.h"
 #import "net/base/mac/url_conversions.h"
 #include "ui/base/l10n/l10n_util.h"
 #include "url/gurl.h"
diff --git a/ios/chrome/browser/ui/tabs/BUILD.gn b/ios/chrome/browser/ui/tabs/BUILD.gn
index a67a403..29100e6d 100644
--- a/ios/chrome/browser/ui/tabs/BUILD.gn
+++ b/ios/chrome/browser/ui/tabs/BUILD.gn
@@ -86,7 +86,7 @@
     "//ios/chrome/browser/sessions:test_support",
     "//ios/chrome/browser/tabs",
     "//ios/chrome/browser/ui",
-    "//ios/web:test_support",
+    "//ios/web/public/test",
     "//testing/gtest",
     "//third_party/ocmock",
   ]
diff --git a/ios/chrome/browser/ui/toolbar/BUILD.gn b/ios/chrome/browser/ui/toolbar/BUILD.gn
index 32b6c41f..4e40796f 100644
--- a/ios/chrome/browser/ui/toolbar/BUILD.gn
+++ b/ios/chrome/browser/ui/toolbar/BUILD.gn
@@ -178,7 +178,8 @@
     "//ios/chrome/test:test_support",
     "//ios/shared/chrome/browser/ui/toolbar:test_support",
     "//ios/testing:ocmock_support",
-    "//ios/web:test_support",
+    "//ios/web/public/test",
+    "//ios/web/public/test/fakes",
     "//testing/gtest",
     "//third_party/ocmock",
   ]
@@ -205,7 +206,7 @@
     "//ios/chrome/test/earl_grey:test_support",
     "//ios/testing/earl_grey:earl_grey_support",
     "//ios/third_party/earl_grey",
-    "//ios/web:test_support",
+    "//ios/web/public/test/http_server",
     "//ui/base",
   ]
   libs = [ "XCTest.framework" ]
diff --git a/ios/chrome/browser/ui/toolbar/toolbar_egtest.mm b/ios/chrome/browser/ui/toolbar/toolbar_egtest.mm
index 20370738..0c4d4f1 100644
--- a/ios/chrome/browser/ui/toolbar/toolbar_egtest.mm
+++ b/ios/chrome/browser/ui/toolbar/toolbar_egtest.mm
@@ -22,8 +22,8 @@
 #import "ios/chrome/test/earl_grey/chrome_earl_grey_ui.h"
 #import "ios/chrome/test/earl_grey/chrome_matchers.h"
 #import "ios/chrome/test/earl_grey/chrome_test_case.h"
-#import "ios/web/public/test/http_server.h"
-#include "ios/web/public/test/http_server_util.h"
+#import "ios/web/public/test/http_server/http_server.h"
+#include "ios/web/public/test/http_server/http_server_util.h"
 #include "ui/base/l10n/l10n_util_mac.h"
 
 #if !defined(__has_feature) || !__has_feature(objc_arc)
diff --git a/ios/chrome/browser/ui/tools_menu/BUILD.gn b/ios/chrome/browser/ui/tools_menu/BUILD.gn
index c522ae6..c96edc32 100644
--- a/ios/chrome/browser/ui/tools_menu/BUILD.gn
+++ b/ios/chrome/browser/ui/tools_menu/BUILD.gn
@@ -79,7 +79,8 @@
     "//ios/chrome/browser/ui/toolbar",
     "//ios/chrome/test/earl_grey:test_support",
     "//ios/third_party/earl_grey",
-    "//ios/web:test_support",
+    "//ios/web/public/test",
+    "//ios/web/public/test/http_server",
     "//ui/base",
   ]
   libs = [ "XCTest.framework" ]
diff --git a/ios/chrome/browser/ui/tools_menu/tools_popup_menu_egtest.mm b/ios/chrome/browser/ui/tools_menu/tools_popup_menu_egtest.mm
index 79784cc..3520c56e 100644
--- a/ios/chrome/browser/ui/tools_menu/tools_popup_menu_egtest.mm
+++ b/ios/chrome/browser/ui/tools_menu/tools_popup_menu_egtest.mm
@@ -17,9 +17,9 @@
 #import "ios/chrome/test/earl_grey/chrome_earl_grey_ui.h"
 #import "ios/chrome/test/earl_grey/chrome_matchers.h"
 #import "ios/chrome/test/earl_grey/chrome_test_case.h"
-#import "ios/web/public/test/http_server.h"
-#include "ios/web/public/test/http_server_util.h"
-#include "ios/web/public/test/response_providers/data_response_provider.h"
+#include "ios/web/public/test/http_server/data_response_provider.h"
+#import "ios/web/public/test/http_server/http_server.h"
+#include "ios/web/public/test/http_server/http_server_util.h"
 #include "ui/base/l10n/l10n_util.h"
 
 #if !defined(__has_feature) || !__has_feature(objc_arc)
diff --git a/ios/chrome/browser/ui/voice/BUILD.gn b/ios/chrome/browser/ui/voice/BUILD.gn
index 1039524..aa2b017 100644
--- a/ios/chrome/browser/ui/voice/BUILD.gn
+++ b/ios/chrome/browser/ui/voice/BUILD.gn
@@ -33,7 +33,7 @@
     "//base",
     "//base/test:test_support",
     "//ios/web",
-    "//ios/web:test_support",
+    "//ios/web/public/test",
     "//testing/gtest",
     "//url",
   ]
diff --git a/ios/chrome/browser/voice/BUILD.gn b/ios/chrome/browser/voice/BUILD.gn
index d7c3926..c2a0f1d 100644
--- a/ios/chrome/browser/voice/BUILD.gn
+++ b/ios/chrome/browser/voice/BUILD.gn
@@ -74,7 +74,7 @@
     ":tts",
     "//base",
     "//ios/web",
-    "//ios/web:test_support",
+    "//ios/web/public/test",
     "//testing/gtest",
     "//third_party/google_toolbox_for_mac",
   ]
diff --git a/ios/chrome/browser/web/BUILD.gn b/ios/chrome/browser/web/BUILD.gn
index b1564dd..eadf4a5 100644
--- a/ios/chrome/browser/web/BUILD.gn
+++ b/ios/chrome/browser/web/BUILD.gn
@@ -74,8 +74,9 @@
     "//ios/chrome/browser/ui:ui",
     "//ios/chrome/browser/ui/sad_tab",
     "//ios/chrome/test:test_support",
-    "//ios/web:test_support",
     "//ios/web:web_arc",
+    "//ios/web/public/test",
+    "//ios/web/public/test/fakes",
     "//testing/gtest",
     "//ui/base:base",
     "//url:url",
@@ -259,7 +260,7 @@
     "//ios/chrome/browser/ui:ui_internal",
     "//ios/chrome/browser/web",
     "//ios/web",
-    "//ios/web:test_support",
+    "//ios/web/public/test",
   ]
 }
 
@@ -286,7 +287,8 @@
     "//ios/chrome/browser/infobars",
     "//ios/chrome/browser/ui",
     "//ios/web",
-    "//ios/web:test_support",
+    "//ios/web/public/test",
+    "//ios/web/public/test/fakes",
     "//net",
     "//testing/gtest",
     "//third_party/ocmock",
@@ -332,7 +334,8 @@
     "//ios/third_party/earl_grey",
     "//ios/third_party/material_components_ios",
     "//ios/web:earl_grey_test_support",
-    "//ios/web:test_support",
+    "//ios/web/public/test",
+    "//ios/web/public/test/http_server",
     "//net",
     "//ui/base",
     "//url",
@@ -353,7 +356,8 @@
     "//base",
     "//ios/chrome/test/base:perf_test_support",
     "//ios/web",
-    "//ios/web:test_support",
+    "//ios/web/public/test",
+    "//ios/web/public/test/fakes",
   ]
   libs = [ "WebKit.framework" ]
 }
diff --git a/ios/chrome/browser/web/browsing_egtest.mm b/ios/chrome/browser/web/browsing_egtest.mm
index 534ee43..47a8fca 100644
--- a/ios/chrome/browser/web/browsing_egtest.mm
+++ b/ios/chrome/browser/web/browsing_egtest.mm
@@ -28,9 +28,9 @@
 #import "ios/testing/wait_util.h"
 #import "ios/web/public/test/earl_grey/web_view_actions.h"
 #import "ios/web/public/test/earl_grey/web_view_matchers.h"
-#import "ios/web/public/test/http_server.h"
-#include "ios/web/public/test/http_server_util.h"
-#include "ios/web/public/test/response_providers/data_response_provider.h"
+#include "ios/web/public/test/http_server/data_response_provider.h"
+#import "ios/web/public/test/http_server/http_server.h"
+#include "ios/web/public/test/http_server/http_server_util.h"
 #include "net/http/http_response_headers.h"
 #include "ui/base/l10n/l10n_util.h"
 #include "url/gurl.h"
diff --git a/ios/chrome/browser/web/browsing_prevent_default_egtest.mm b/ios/chrome/browser/web/browsing_prevent_default_egtest.mm
index 1fe2b76..61ae6d3 100644
--- a/ios/chrome/browser/web/browsing_prevent_default_egtest.mm
+++ b/ios/chrome/browser/web/browsing_prevent_default_egtest.mm
@@ -16,8 +16,8 @@
 #import "ios/chrome/test/earl_grey/chrome_earl_grey.h"
 #import "ios/chrome/test/earl_grey/chrome_matchers.h"
 #import "ios/chrome/test/earl_grey/chrome_test_case.h"
-#import "ios/web/public/test/http_server.h"
-#include "ios/web/public/test/http_server_util.h"
+#import "ios/web/public/test/http_server/http_server.h"
+#include "ios/web/public/test/http_server/http_server_util.h"
 #include "url/url_constants.h"
 
 #if !defined(__has_feature) || !__has_feature(objc_arc)
diff --git a/ios/chrome/browser/web/cache_egtest.mm b/ios/chrome/browser/web/cache_egtest.mm
index 90c3926b..e168797 100644
--- a/ios/chrome/browser/web/cache_egtest.mm
+++ b/ios/chrome/browser/web/cache_egtest.mm
@@ -20,9 +20,9 @@
 #import "ios/chrome/test/earl_grey/chrome_matchers.h"
 #import "ios/chrome/test/earl_grey/chrome_test_case.h"
 #import "ios/testing/wait_util.h"
-#import "ios/web/public/test/http_server.h"
-#include "ios/web/public/test/http_server_util.h"
-#include "ios/web/public/test/response_providers/html_response_provider.h"
+#include "ios/web/public/test/http_server/html_response_provider.h"
+#import "ios/web/public/test/http_server/http_server.h"
+#include "ios/web/public/test/http_server/http_server_util.h"
 #include "url/gurl.h"
 
 #if !defined(__has_feature) || !__has_feature(objc_arc)
diff --git a/ios/chrome/browser/web/child_window_open_by_dom_egtest.mm b/ios/chrome/browser/web/child_window_open_by_dom_egtest.mm
index b895991..c6e330b 100644
--- a/ios/chrome/browser/web/child_window_open_by_dom_egtest.mm
+++ b/ios/chrome/browser/web/child_window_open_by_dom_egtest.mm
@@ -13,8 +13,8 @@
 #import "ios/chrome/test/earl_grey/chrome_earl_grey.h"
 #import "ios/chrome/test/earl_grey/chrome_matchers.h"
 #import "ios/chrome/test/earl_grey/chrome_test_case.h"
-#import "ios/web/public/test/http_server.h"
-#include "ios/web/public/test/http_server_util.h"
+#import "ios/web/public/test/http_server/http_server.h"
+#include "ios/web/public/test/http_server/http_server_util.h"
 
 #if !defined(__has_feature) || !__has_feature(objc_arc)
 #error "This file requires ARC support."
diff --git a/ios/chrome/browser/web/chrome_web_client.h b/ios/chrome/browser/web/chrome_web_client.h
index 440a75dd..3c31f9f 100644
--- a/ios/chrome/browser/web/chrome_web_client.h
+++ b/ios/chrome/browser/web/chrome_web_client.h
@@ -5,6 +5,8 @@
 #ifndef IOS_CHROME_BROWSER_WEB_CHROME_WEB_CLIENT_H_
 #define IOS_CHROME_BROWSER_WEB_CHROME_WEB_CLIENT_H_
 
+#include <memory>
+
 #include "base/macros.h"
 #include "ios/web/public/web_client.h"
 
@@ -15,7 +17,7 @@
   ~ChromeWebClient() override;
 
   // WebClient implementation.
-  web::WebMainParts* CreateWebMainParts() override;
+  std::unique_ptr<web::WebMainParts> CreateWebMainParts() override;
   void PreWebViewCreation() const override;
   void AddAdditionalSchemes(std::vector<url::SchemeWithType>*
                                 additional_standard_schemes) const override;
diff --git a/ios/chrome/browser/web/chrome_web_client.mm b/ios/chrome/browser/web/chrome_web_client.mm
index 0c9883b..3e468dbf 100644
--- a/ios/chrome/browser/web/chrome_web_client.mm
+++ b/ios/chrome/browser/web/chrome_web_client.mm
@@ -8,6 +8,7 @@
 #include "base/files/file_util.h"
 #include "base/ios/ios_util.h"
 #include "base/mac/bundle_locations.h"
+#include "base/memory/ptr_util.h"
 #include "base/strings/sys_string_conversions.h"
 #include "components/dom_distiller/core/url_constants.h"
 #include "components/prefs/pref_service.h"
@@ -63,8 +64,9 @@
 
 ChromeWebClient::~ChromeWebClient() {}
 
-web::WebMainParts* ChromeWebClient::CreateWebMainParts() {
-  return new IOSChromeMainParts(*base::CommandLine::ForCurrentProcess());
+std::unique_ptr<web::WebMainParts> ChromeWebClient::CreateWebMainParts() {
+  return base::MakeUnique<IOSChromeMainParts>(
+      *base::CommandLine::ForCurrentProcess());
 }
 
 void ChromeWebClient::PreWebViewCreation() const {
diff --git a/ios/chrome/browser/web/forms_egtest.mm b/ios/chrome/browser/web/forms_egtest.mm
index 6ba882ee..4c712c5 100644
--- a/ios/chrome/browser/web/forms_egtest.mm
+++ b/ios/chrome/browser/web/forms_egtest.mm
@@ -17,9 +17,9 @@
 #import "ios/chrome/test/earl_grey/chrome_matchers.h"
 #import "ios/chrome/test/earl_grey/chrome_test_case.h"
 #import "ios/testing/wait_util.h"
-#import "ios/web/public/test/http_server.h"
-#import "ios/web/public/test/http_server_util.h"
-#include "ios/web/public/test/response_providers/data_response_provider.h"
+#include "ios/web/public/test/http_server/data_response_provider.h"
+#import "ios/web/public/test/http_server/http_server.h"
+#include "ios/web/public/test/http_server/http_server_util.h"
 #include "ios/web/public/test/url_test_util.h"
 
 #if !defined(__has_feature) || !__has_feature(objc_arc)
diff --git a/ios/chrome/browser/web/http_auth_egtest.mm b/ios/chrome/browser/web/http_auth_egtest.mm
index 1224c7e..21eb1224 100644
--- a/ios/chrome/browser/web/http_auth_egtest.mm
+++ b/ios/chrome/browser/web/http_auth_egtest.mm
@@ -13,9 +13,9 @@
 #import "ios/chrome/test/earl_grey/chrome_matchers.h"
 #import "ios/chrome/test/earl_grey/chrome_test_case.h"
 #import "ios/testing/wait_util.h"
-#import "ios/web/public/test/http_server.h"
-#include "ios/web/public/test/http_server_util.h"
-#import "ios/web/public/test/response_providers/http_auth_response_provider.h"
+#import "ios/web/public/test/http_server/http_auth_response_provider.h"
+#import "ios/web/public/test/http_server/http_server.h"
+#include "ios/web/public/test/http_server/http_server_util.h"
 #include "ui/base/l10n/l10n_util_mac.h"
 #include "url/gurl.h"
 
diff --git a/ios/chrome/browser/web/js_print_egtest.mm b/ios/chrome/browser/web/js_print_egtest.mm
index afa8dbc..70e0d4190 100644
--- a/ios/chrome/browser/web/js_print_egtest.mm
+++ b/ios/chrome/browser/web/js_print_egtest.mm
@@ -9,8 +9,8 @@
 #import "ios/chrome/test/earl_grey/chrome_earl_grey.h"
 #import "ios/chrome/test/earl_grey/chrome_matchers.h"
 #import "ios/chrome/test/earl_grey/chrome_test_case.h"
-#import "ios/web/public/test/http_server.h"
-#import "ios/web/public/test/http_server_util.h"
+#import "ios/web/public/test/http_server/http_server.h"
+#include "ios/web/public/test/http_server/http_server_util.h"
 
 #if !defined(__has_feature) || !__has_feature(objc_arc)
 #error "This file requires ARC support."
diff --git a/ios/chrome/browser/web/navigation_egtest.mm b/ios/chrome/browser/web/navigation_egtest.mm
index 6298fb2..068b76c 100644
--- a/ios/chrome/browser/web/navigation_egtest.mm
+++ b/ios/chrome/browser/web/navigation_egtest.mm
@@ -10,9 +10,9 @@
 #import "ios/chrome/test/earl_grey/chrome_earl_grey.h"
 #import "ios/chrome/test/earl_grey/chrome_matchers.h"
 #import "ios/chrome/test/earl_grey/chrome_test_case.h"
-#import "ios/web/public/test/http_server.h"
-#include "ios/web/public/test/http_server_util.h"
-#include "ios/web/public/test/response_providers/data_response_provider.h"
+#include "ios/web/public/test/http_server/data_response_provider.h"
+#import "ios/web/public/test/http_server/http_server.h"
+#include "ios/web/public/test/http_server/http_server_util.h"
 #include "ui/base/l10n/l10n_util.h"
 
 #if !defined(__has_feature) || !__has_feature(objc_arc)
diff --git a/ios/chrome/browser/web/progress_indicator_egtest.mm b/ios/chrome/browser/web/progress_indicator_egtest.mm
index a47512a..cecc6d0 100644
--- a/ios/chrome/browser/web/progress_indicator_egtest.mm
+++ b/ios/chrome/browser/web/progress_indicator_egtest.mm
@@ -16,9 +16,9 @@
 #import "ios/chrome/test/earl_grey/chrome_matchers.h"
 #import "ios/chrome/test/earl_grey/chrome_test_case.h"
 #import "ios/third_party/material_components_ios/src/components/ProgressView/src/MaterialProgressView.h"
-#import "ios/web/public/test/http_server.h"
-#import "ios/web/public/test/http_server_util.h"
-#include "ios/web/public/test/response_providers/html_response_provider.h"
+#include "ios/web/public/test/http_server/html_response_provider.h"
+#import "ios/web/public/test/http_server/http_server.h"
+#import "ios/web/public/test/http_server/http_server_util.h"
 #include "url/gurl.h"
 
 #if !defined(__has_feature) || !__has_feature(objc_arc)
diff --git a/ios/chrome/browser/web/push_and_replace_state_navigation_egtest.mm b/ios/chrome/browser/web/push_and_replace_state_navigation_egtest.mm
index ec2743d1..a022996 100644
--- a/ios/chrome/browser/web/push_and_replace_state_navigation_egtest.mm
+++ b/ios/chrome/browser/web/push_and_replace_state_navigation_egtest.mm
@@ -11,8 +11,8 @@
 #import "ios/chrome/test/earl_grey/chrome_earl_grey_ui.h"
 #import "ios/chrome/test/earl_grey/chrome_matchers.h"
 #import "ios/chrome/test/earl_grey/chrome_test_case.h"
-#import "ios/web/public/test/http_server.h"
-#include "ios/web/public/test/http_server_util.h"
+#import "ios/web/public/test/http_server/http_server.h"
+#include "ios/web/public/test/http_server/http_server_util.h"
 
 #if !defined(__has_feature) || !__has_feature(objc_arc)
 #error "This file requires ARC support."
diff --git a/ios/chrome/browser/web/stop_loading_egtest.mm b/ios/chrome/browser/web/stop_loading_egtest.mm
index 2e2db46..2648d03 100644
--- a/ios/chrome/browser/web/stop_loading_egtest.mm
+++ b/ios/chrome/browser/web/stop_loading_egtest.mm
@@ -12,9 +12,9 @@
 #import "ios/chrome/test/earl_grey/chrome_earl_grey_ui.h"
 #import "ios/chrome/test/earl_grey/chrome_matchers.h"
 #import "ios/chrome/test/earl_grey/chrome_test_case.h"
-#import "ios/web/public/test/http_server.h"
-#include "ios/web/public/test/http_server_util.h"
-#include "ios/web/public/test/response_providers/html_response_provider.h"
+#include "ios/web/public/test/http_server/html_response_provider.h"
+#import "ios/web/public/test/http_server/http_server.h"
+#include "ios/web/public/test/http_server/http_server_util.h"
 #include "url/gurl.h"
 
 #if !defined(__has_feature) || !__has_feature(objc_arc)
diff --git a/ios/chrome/browser/web/visible_url_egtest.mm b/ios/chrome/browser/web/visible_url_egtest.mm
index 7d16941a..e97e233 100644
--- a/ios/chrome/browser/web/visible_url_egtest.mm
+++ b/ios/chrome/browser/web/visible_url_egtest.mm
@@ -18,9 +18,9 @@
 #import "ios/chrome/test/earl_grey/chrome_earl_grey_ui.h"
 #import "ios/chrome/test/earl_grey/chrome_matchers.h"
 #import "ios/chrome/test/earl_grey/chrome_test_case.h"
-#import "ios/web/public/test/http_server.h"
-#include "ios/web/public/test/http_server_util.h"
-#include "ios/web/public/test/response_providers/html_response_provider.h"
+#include "ios/web/public/test/http_server/html_response_provider.h"
+#import "ios/web/public/test/http_server/http_server.h"
+#include "ios/web/public/test/http_server/http_server_util.h"
 #include "ios/web/public/test/url_test_util.h"
 #include "url/gurl.h"
 
diff --git a/ios/chrome/browser/web/window_open_by_dom_egtest.mm b/ios/chrome/browser/web/window_open_by_dom_egtest.mm
index 3c8f2f649..077be28 100644
--- a/ios/chrome/browser/web/window_open_by_dom_egtest.mm
+++ b/ios/chrome/browser/web/window_open_by_dom_egtest.mm
@@ -18,8 +18,8 @@
 #import "ios/chrome/test/earl_grey/chrome_earl_grey.h"
 #import "ios/chrome/test/earl_grey/chrome_matchers.h"
 #import "ios/chrome/test/earl_grey/chrome_test_case.h"
-#import "ios/web/public/test/http_server.h"
-#include "ios/web/public/test/http_server_util.h"
+#import "ios/web/public/test/http_server/http_server.h"
+#include "ios/web/public/test/http_server/http_server_util.h"
 #include "ui/base/l10n/l10n_util.h"
 
 #if !defined(__has_feature) || !__has_feature(objc_arc)
diff --git a/ios/chrome/browser/web_state_list/BUILD.gn b/ios/chrome/browser/web_state_list/BUILD.gn
index 7ddb1ae..3b8eb0e 100644
--- a/ios/chrome/browser/web_state_list/BUILD.gn
+++ b/ios/chrome/browser/web_state_list/BUILD.gn
@@ -60,7 +60,7 @@
     "//base",
     "//ios/chrome/browser/sessions:serialisation",
     "//ios/web",
-    "//ios/web:test_support",
+    "//ios/web/public/test/fakes",
     "//net",
     "//testing/gtest",
     "//ui/base",
diff --git a/ios/chrome/test/BUILD.gn b/ios/chrome/test/BUILD.gn
index 4c64b5a..a41fb98 100644
--- a/ios/chrome/test/BUILD.gn
+++ b/ios/chrome/test/BUILD.gn
@@ -48,7 +48,7 @@
     "//ios/public/provider/chrome/browser",
     "//ios/public/provider/chrome/browser:test_support",
     "//ios/web",
-    "//ios/web:test_support",
+    "//ios/web/public/test",
     "//net",
     "//testing/gmock",
     "//testing/gtest",
diff --git a/ios/chrome/test/app/BUILD.gn b/ios/chrome/test/app/BUILD.gn
index b1c07a69..523bfb7d 100644
--- a/ios/chrome/test/app/BUILD.gn
+++ b/ios/chrome/test/app/BUILD.gn
@@ -75,7 +75,7 @@
     "//ios/public/provider/chrome/browser/signin:test_support",
     "//ios/testing:ios_test_support",
     "//ios/web",
-    "//ios/web:test_support",
+    "//ios/web/public/test",
     "//net",
     "//net:test_support",
     "//url",
diff --git a/ios/chrome/test/base/BUILD.gn b/ios/chrome/test/base/BUILD.gn
index 5b902b2c..02f8dfe 100644
--- a/ios/chrome/test/base/BUILD.gn
+++ b/ios/chrome/test/base/BUILD.gn
@@ -38,6 +38,6 @@
     "//base",
     "//ios/chrome/browser/web:web_internal",
     "//ios/chrome/test:test_support",
-    "//ios/web:test_support",
+    "//ios/web/public/test",
   ]
 }
diff --git a/ios/chrome/test/earl_grey/BUILD.gn b/ios/chrome/test/earl_grey/BUILD.gn
index 7da5f69..2606082 100644
--- a/ios/chrome/test/earl_grey/BUILD.gn
+++ b/ios/chrome/test/earl_grey/BUILD.gn
@@ -184,7 +184,8 @@
     "//ios/third_party/material_components_ios",
     "//ios/web",
     "//ios/web:earl_grey_test_support",
-    "//ios/web:test_support",
+    "//ios/web/public/test",
+    "//ios/web/public/test/http_server",
     "//ui/base",
     "//ui/base:test_support",
     "//url",
@@ -193,6 +194,7 @@
   public_deps = [
     "//build/config/ios:xctest",
     "//ios/third_party/earl_grey",
+    "//ios/web/public/test/fakes",
   ]
 
   libs = [
diff --git a/ios/chrome/test/earl_grey/chrome_test_case.mm b/ios/chrome/test/earl_grey/chrome_test_case.mm
index 9e5a45bf..07383641 100644
--- a/ios/chrome/test/earl_grey/chrome_test_case.mm
+++ b/ios/chrome/test/earl_grey/chrome_test_case.mm
@@ -15,7 +15,7 @@
 #include "ios/chrome/test/app/signin_test_util.h"
 #import "ios/chrome/test/app/sync_test_util.h"
 #import "ios/chrome/test/app/tab_test_util.h"
-#import "ios/web/public/test/http_server.h"
+#import "ios/web/public/test/http_server/http_server.h"
 
 #if !defined(__has_feature) || !__has_feature(objc_arc)
 #error "This file requires ARC support."
diff --git a/ios/clean/chrome/browser/ui/context_menu/BUILD.gn b/ios/clean/chrome/browser/ui/context_menu/BUILD.gn
index 7d1bfea..b75b5d3f1 100644
--- a/ios/clean/chrome/browser/ui/context_menu/BUILD.gn
+++ b/ios/clean/chrome/browser/ui/context_menu/BUILD.gn
@@ -60,7 +60,7 @@
     "//base/test:test_support",
     "//ios/chrome/test/base",
     "//ios/web",
-    "//ios/web:test_support",
+    "//ios/web/public/test",
     "//testing/gtest",
   ]
 }
diff --git a/ios/clean/chrome/browser/ui/tab/BUILD.gn b/ios/clean/chrome/browser/ui/tab/BUILD.gn
index 1b7c709..35184302 100644
--- a/ios/clean/chrome/browser/ui/tab/BUILD.gn
+++ b/ios/clean/chrome/browser/ui/tab/BUILD.gn
@@ -61,7 +61,7 @@
     "//ios/shared/chrome/browser/ui/browser_list",
     "//ios/shared/chrome/browser/ui/coordinators",
     "//ios/shared/chrome/browser/ui/toolbar:test_support",
-    "//ios/web:test_support",
+    "//ios/web/public/test",
     "//testing/gtest",
   ]
 }
diff --git a/ios/clean/chrome/browser/ui/tab_collection/BUILD.gn b/ios/clean/chrome/browser/ui/tab_collection/BUILD.gn
index d599e37..2301668 100644
--- a/ios/clean/chrome/browser/ui/tab_collection/BUILD.gn
+++ b/ios/clean/chrome/browser/ui/tab_collection/BUILD.gn
@@ -47,7 +47,7 @@
     "//ios/chrome/browser/web_state_list",
     "//ios/chrome/browser/web_state_list:test_support",
     "//ios/chrome/test/base",
-    "//ios/web:test_support",
+    "//ios/web/public/test/fakes",
     "//testing/gtest",
     "//third_party/ocmock",
     "//url:url",
diff --git a/ios/clean/chrome/browser/ui/tab_collection/tab_collection_mediator.mm b/ios/clean/chrome/browser/ui/tab_collection/tab_collection_mediator.mm
index 58839e6..41ac68e 100644
--- a/ios/clean/chrome/browser/ui/tab_collection/tab_collection_mediator.mm
+++ b/ios/clean/chrome/browser/ui/tab_collection/tab_collection_mediator.mm
@@ -49,6 +49,7 @@
 #pragma mark - Properties
 
 - (void)setWebStateList:(WebStateList*)webStateList {
+  // TODO(crbug.com/727427):Add support for DCHECK(webStateList).
   _scopedWebStateListObserver->RemoveAll();
   _webStateList = webStateList;
   [self populateConsumerItems];
diff --git a/ios/clean/chrome/browser/ui/tab_grid/BUILD.gn b/ios/clean/chrome/browser/ui/tab_grid/BUILD.gn
index b7eddbb..25b5240b 100644
--- a/ios/clean/chrome/browser/ui/tab_grid/BUILD.gn
+++ b/ios/clean/chrome/browser/ui/tab_grid/BUILD.gn
@@ -86,7 +86,7 @@
     "//ios/chrome/browser/web_state_list",
     "//ios/chrome/browser/web_state_list:test_support",
     "//ios/chrome/test/base",
-    "//ios/web:test_support",
+    "//ios/web/public/test/fakes",
     "//testing/gtest",
     "//third_party/ocmock",
   ]
diff --git a/ios/clean/chrome/browser/ui/toolbar/BUILD.gn b/ios/clean/chrome/browser/ui/toolbar/BUILD.gn
index 2648d06..3095a53 100644
--- a/ios/clean/chrome/browser/ui/toolbar/BUILD.gn
+++ b/ios/clean/chrome/browser/ui/toolbar/BUILD.gn
@@ -15,6 +15,7 @@
   deps = [
     ":toolbar_ui",
     "//base",
+    "//ios/chrome/browser/web_state_list",
     "//ios/clean/chrome/browser/ui/commands",
     "//ios/clean/chrome/browser/ui/omnibox",
     "//ios/clean/chrome/browser/ui/tools",
@@ -36,6 +37,7 @@
   deps = [
     ":toolbar_components_ui",
     "//base",
+    "//ios/chrome/browser/ui",
     "//ios/clean/chrome/browser/ui/actions",
     "//ios/clean/chrome/browser/ui/animators",
     "//ios/clean/chrome/browser/ui/commands",
@@ -76,9 +78,11 @@
     ":toolbar_ui",
     "//base",
     "//base/test:test_support",
+    "//ios/chrome/browser/web_state_list",
+    "//ios/chrome/browser/web_state_list:test_support",
     "//ios/shared/chrome/browser/ui/toolbar:test_support",
     "//ios/web",
-    "//ios/web:test_support",
+    "//ios/web/public/test/fakes",
     "//testing/gtest",
     "//third_party/ocmock",
   ]
diff --git a/ios/clean/chrome/browser/ui/toolbar/toolbar_button.mm b/ios/clean/chrome/browser/ui/toolbar/toolbar_button.mm
index a96deea2..4061a75 100644
--- a/ios/clean/chrome/browser/ui/toolbar/toolbar_button.mm
+++ b/ios/clean/chrome/browser/ui/toolbar/toolbar_button.mm
@@ -4,6 +4,8 @@
 
 #import "ios/clean/chrome/browser/ui/toolbar/toolbar_button.h"
 
+#import "ios/chrome/browser/ui/uikit_ui_util.h"
+
 #if !defined(__has_feature) || !__has_feature(objc_arc)
 #error "This file requires ARC support."
 #endif
@@ -20,10 +22,25 @@
   [button setImage:normalImage forState:UIControlStateNormal];
   [button setImage:highlightedImage forState:UIControlStateHighlighted];
   [button setImage:disabledImage forState:UIControlStateDisabled];
+  button.titleLabel.textAlignment = NSTextAlignmentCenter;
   button.translatesAutoresizingMaskIntoConstraints = NO;
   return button;
 }
 
+- (void)layoutSubviews {
+  [super layoutSubviews];
+  // If the UIButton title has text it will center it on top of the image,
+  // this is currently used for the TabStripButton which displays the
+  // total number of tabs.
+  if (self.titleLabel.text) {
+    CGSize size = self.bounds.size;
+    CGPoint center = CGPointMake(size.width / 2, size.height / 2);
+    self.imageView.center = center;
+    self.imageView.frame = AlignRectToPixel(self.imageView.frame);
+    self.titleLabel.frame = self.bounds;
+  }
+}
+
 #pragma mark - Public Methods
 
 - (void)updateHiddenInCurrentSizeClass {
diff --git a/ios/clean/chrome/browser/ui/toolbar/toolbar_constants.h b/ios/clean/chrome/browser/ui/toolbar/toolbar_constants.h
index 8547440..fc4c159e 100644
--- a/ios/clean/chrome/browser/ui/toolbar/toolbar_constants.h
+++ b/ios/clean/chrome/browser/ui/toolbar/toolbar_constants.h
@@ -6,9 +6,14 @@
 #define IOS_CLEAN_CHROME_BROWSER_UI_TOOLBAR_TOOLBAR_CONSTANTS_H_
 
 #import <CoreGraphics/CoreGraphics.h>
+#import <Foundation/Foundation.h>
+
+// All kxxxColor constants are RGB values stored in a Hex integer. These will be
+// converted into UIColors using the UIColorFromRGB() function, from
+// uikit_ui_util.h
 
 // Toolbar styling.
-extern const CGFloat kToolbarBackgroundBrightness;
+extern const CGFloat kToolbarBackgroundColor;
 
 // Stackview constraints.
 extern const CGFloat kVerticalMargin;
@@ -17,7 +22,7 @@
 
 // Location bar styling.
 extern const CGFloat kLocationBarBorderWidth;
-extern const CGFloat kLocationBarBorderColorBrightness;
+extern const CGFloat kLocationBarBorderColor;
 extern const CGFloat kLocationBarShadowRadius;
 extern const CGFloat kLocationBarShadowOpacity;
 
@@ -26,5 +31,14 @@
 
 // Toolbar Buttons.
 extern const CGFloat kToolbarButtonWidth;
+extern const CGFloat kToolbarButtonTitleNormalColor;
+extern const CGFloat kToolbarButtonTitleHighlightedColor;
+
+// Maximum number of tabs displayed by the button containing the tab count.
+extern const NSInteger kShowTabStripButtonMaxTabCount;
+
+// Font sizes for the button containing the tab count.
+extern const NSInteger kFontSizeFewerThanTenTabs;
+extern const NSInteger kFontSizeTenTabsOrMore;
 
 #endif  // IOS_CLEAN_CHROME_BROWSER_UI_TOOLBAR_TOOLBAR_CONSTANTS_H_
diff --git a/ios/clean/chrome/browser/ui/toolbar/toolbar_constants.mm b/ios/clean/chrome/browser/ui/toolbar/toolbar_constants.mm
index 662f5a0f..964dd9a 100644
--- a/ios/clean/chrome/browser/ui/toolbar/toolbar_constants.mm
+++ b/ios/clean/chrome/browser/ui/toolbar/toolbar_constants.mm
@@ -4,17 +4,24 @@
 
 #import "ios/clean/chrome/browser/ui/toolbar/toolbar_constants.h"
 
-const CGFloat kToolbarBackgroundBrightness = 242.0 / 255.0;
+const CGFloat kToolbarBackgroundColor = 0xF2F2F2;
 
 const CGFloat kVerticalMargin = 7.0f;
 const CGFloat kHorizontalMargin = 1.0f;
 const CGFloat kStackViewSpacing = 2.0f;
 
 const CGFloat kLocationBarBorderWidth = 1.0f;
-const CGFloat kLocationBarBorderColorBrightness = 208.0 / 255.0;
+const CGFloat kLocationBarBorderColor = 0xD0D0D0;
 const CGFloat kLocationBarShadowRadius = 0.0f;
 const CGFloat kLocationBarShadowOpacity = 0.2f;
 
 const CGFloat kProgressBarHeight = 2.0f;
 
 const CGFloat kToolbarButtonWidth = 42.0f;
+const CGFloat kToolbarButtonTitleNormalColor = 0x555555;
+const CGFloat kToolbarButtonTitleHighlightedColor = 0x4285F4;
+
+const NSInteger kShowTabStripButtonMaxTabCount = 99;
+
+const NSInteger kFontSizeFewerThanTenTabs = 11;
+const NSInteger kFontSizeTenTabsOrMore = 9;
diff --git a/ios/clean/chrome/browser/ui/toolbar/toolbar_consumer.h b/ios/clean/chrome/browser/ui/toolbar/toolbar_consumer.h
index 99e8e3d..1207ca3 100644
--- a/ios/clean/chrome/browser/ui/toolbar/toolbar_consumer.h
+++ b/ios/clean/chrome/browser/ui/toolbar/toolbar_consumer.h
@@ -19,6 +19,8 @@
 - (void)setLoadingProgress:(double)progress;
 // Sets whether the toolbar should display for a visible tab strip or not.
 - (void)setTabStripVisible:(BOOL)visible;
+// Updates the toolbar with the current number of total tabs.
+- (void)setTabCount:(int)tabCount;
 @end
 
 #endif  // IOS_CLEAN_CHROME_BROWSER_UI_TOOLBAR_TOOLBAR_CONSUMER_H_
diff --git a/ios/clean/chrome/browser/ui/toolbar/toolbar_coordinator.mm b/ios/clean/chrome/browser/ui/toolbar/toolbar_coordinator.mm
index f2a5212..52845a7 100644
--- a/ios/clean/chrome/browser/ui/toolbar/toolbar_coordinator.mm
+++ b/ios/clean/chrome/browser/ui/toolbar/toolbar_coordinator.mm
@@ -63,6 +63,7 @@
 
   self.viewController.dispatcher = static_cast<id>(self.browser->dispatcher());
   self.mediator.consumer = self.viewController;
+  self.mediator.webStateList = &self.browser->web_state_list();
 
   [self.browser->broadcaster()
       addObserver:self.mediator
diff --git a/ios/clean/chrome/browser/ui/toolbar/toolbar_mediator.h b/ios/clean/chrome/browser/ui/toolbar/toolbar_mediator.h
index e6059ed..c7c38c25 100644
--- a/ios/clean/chrome/browser/ui/toolbar/toolbar_mediator.h
+++ b/ios/clean/chrome/browser/ui/toolbar/toolbar_mediator.h
@@ -14,6 +14,7 @@
 namespace web {
 class WebState;
 }
+class WebStateList;
 
 // A mediator object that provides the relevant properties of a web state
 // to a consumer.
@@ -23,10 +24,17 @@
 // the lifetime of this object and may be null.
 @property(nonatomic, assign) web::WebState* webState;
 
+// The WebStateList that this mediator listens for any changes on the total
+// number of Webstates.
+@property(nonatomic, assign) WebStateList* webStateList;
+
 // The consumer for this object. This can change during the lifetime of this
 // object and may be nil.
 @property(nonatomic, strong) id<ToolbarConsumer> consumer;
 
+// Stops observing all objects.
+- (void)disconnect;
+
 @end
 
 #endif  // IOS_CLEAN_CHROME_BROWSER_UI_TOOLBAR_TOOLBAR_MEDIATOR_H_
diff --git a/ios/clean/chrome/browser/ui/toolbar/toolbar_mediator.mm b/ios/clean/chrome/browser/ui/toolbar/toolbar_mediator.mm
index e082076..dfc0512 100644
--- a/ios/clean/chrome/browser/ui/toolbar/toolbar_mediator.mm
+++ b/ios/clean/chrome/browser/ui/toolbar/toolbar_mediator.mm
@@ -5,7 +5,10 @@
 #import "ios/clean/chrome/browser/ui/toolbar/toolbar_mediator.h"
 
 #include "base/memory/ptr_util.h"
+#include "base/scoped_observer.h"
 #include "base/strings/sys_string_conversions.h"
+#import "ios/chrome/browser/web_state_list/web_state_list.h"
+#import "ios/chrome/browser/web_state_list/web_state_list_observer_bridge.h"
 #import "ios/clean/chrome/browser/ui/toolbar/toolbar_consumer.h"
 #import "ios/web/public/navigation_manager.h"
 #include "ios/web/public/web_state/web_state.h"
@@ -15,19 +18,29 @@
 #error "This file requires ARC support."
 #endif
 
-@interface ToolbarMediator ()<CRWWebStateObserver>
+@interface ToolbarMediator ()<CRWWebStateObserver, WebStateListObserving>
 @end
 
 @implementation ToolbarMediator {
   std::unique_ptr<web::WebStateObserverBridge> _webStateObserver;
+  std::unique_ptr<WebStateListObserverBridge> _webStateListObserver;
+  std::unique_ptr<ScopedObserver<WebStateList, WebStateListObserverBridge>>
+      _scopedWebStateListObserver;
 }
 
 @synthesize consumer = _consumer;
 @synthesize webState = _webState;
+@synthesize webStateList = _webStateList;
 
 - (void)dealloc {
+  [self disconnect];
+}
+
+#pragma mark - Public
+
+- (void)disconnect {
+  self.webStateList = nullptr;
   _webStateObserver.reset();
-  _webState = nullptr;
 }
 
 #pragma mark - CRWWebStateObserver
@@ -58,6 +71,20 @@
   [self.consumer setTabStripVisible:visible];
 }
 
+#pragma mark - WebStateListObserver
+
+- (void)webStateList:(WebStateList*)webStateList
+    didInsertWebState:(web::WebState*)webState
+              atIndex:(int)index {
+  [self.consumer setTabCount:_webStateList->count()];
+}
+
+- (void)webStateList:(WebStateList*)webStateList
+    didDetachWebState:(web::WebState*)webState
+              atIndex:(int)index {
+  [self.consumer setTabCount:_webStateList->count()];
+}
+
 #pragma mark - Setters
 
 - (void)setWebState:(web::WebState*)webState {
@@ -74,6 +101,24 @@
   if (self.webState) {
     [self updateConsumer];
   }
+  if (self.webStateList) {
+    [self.consumer setTabCount:_webStateList->count()];
+  }
+}
+
+- (void)setWebStateList:(WebStateList*)webStateList {
+  // TODO(crbug.com/727427):Add support for DCHECK(webStateList).
+  _webStateList = webStateList;
+  _webStateListObserver = base::MakeUnique<WebStateListObserverBridge>(self);
+  _scopedWebStateListObserver = base::MakeUnique<
+      ScopedObserver<WebStateList, WebStateListObserverBridge>>(
+      _webStateListObserver.get());
+  if (_webStateList) {
+    _scopedWebStateListObserver->Add(_webStateList);
+    if (self.consumer) {
+      [self.consumer setTabCount:_webStateList->count()];
+    }
+  }
 }
 
 #pragma mark - Helper methods
diff --git a/ios/clean/chrome/browser/ui/toolbar/toolbar_mediator_unittest.mm b/ios/clean/chrome/browser/ui/toolbar/toolbar_mediator_unittest.mm
index 3adcfac4..ac97b1e 100644
--- a/ios/clean/chrome/browser/ui/toolbar/toolbar_mediator_unittest.mm
+++ b/ios/clean/chrome/browser/ui/toolbar/toolbar_mediator_unittest.mm
@@ -5,6 +5,9 @@
 #import "ios/clean/chrome/browser/ui/toolbar/toolbar_mediator.h"
 
 #include "base/memory/ptr_util.h"
+#include "ios/chrome/browser/web_state_list/fake_web_state_list_delegate.h"
+#include "ios/chrome/browser/web_state_list/web_state_list.h"
+#import "ios/chrome/browser/web_state_list/web_state_list_observer_bridge.h"
 #import "ios/clean/chrome/browser/ui/toolbar/toolbar_consumer.h"
 #import "ios/shared/chrome/browser/ui/toolbar/toolbar_test_util.h"
 #import "ios/web/public/test/fakes/test_navigation_manager.h"
@@ -18,7 +21,8 @@
 #error "This file requires ARC support."
 #endif
 
-@interface TestToolbarMediator : ToolbarMediator<CRWWebStateObserver>
+@interface TestToolbarMediator
+    : ToolbarMediator<CRWWebStateObserver, WebStateListObserving>
 @end
 
 @implementation TestToolbarMediator
@@ -26,6 +30,7 @@
 
 namespace {
 
+static const int kNumberOfWebStates = 3;
 static const char kTestUrl[] = "http://www.chromium.org";
 
 class ToolbarMediatorTest : public PlatformTest {
@@ -40,10 +45,30 @@
     consumer_ = OCMProtocolMock(@protocol(ToolbarConsumer));
   }
 
+  // Explicitly disconnect the mediator so there won't be any WebStateList
+  // observers when web_state_list_ gets dealloc.
+  ~ToolbarMediatorTest() override { [mediator_ disconnect]; }
+
  protected:
+  void SetUpWebStateList() {
+    web_state_list_ = base::MakeUnique<WebStateList>(&web_state_list_delegate_);
+    for (int i = 0; i < kNumberOfWebStates; i++) {
+      InsertWebState(i);
+    }
+  }
+
+  void InsertWebState(int index) {
+    auto web_state = base::MakeUnique<web::TestWebState>();
+    GURL url("http://test/" + std::to_string(index));
+    web_state->SetCurrentURL(url);
+    web_state_list_->InsertWebState(index, std::move(web_state));
+  }
+
   TestToolbarMediator* mediator_;
   ToolbarTestWebState test_web_state_;
   ToolbarTestNavigationManager* navigation_manager_;
+  std::unique_ptr<WebStateList> web_state_list_;
+  FakeWebStateListDelegate web_state_list_delegate_;
   id consumer_;
 };
 
@@ -65,6 +90,15 @@
   [[consumer_ reject] setIsLoading:YES];
 }
 
+// Test no WebstateList related setup is being done on the Toolbar if there's no
+// WebstateList.
+TEST_F(ToolbarMediatorTest, TestToolbarSetupWithNoWebstateList) {
+  mediator_.consumer = consumer_;
+  mediator_.webState = &test_web_state_;
+
+  [[[consumer_ reject] ignoringNonObjectArgs] setTabCount:0];
+}
+
 // Test the Toolbar Setup gets called when the mediator's WebState and Consumer
 // have been set.
 TEST_F(ToolbarMediatorTest, TestToolbarSetup) {
@@ -87,10 +121,30 @@
   [[consumer_ verify] setIsLoading:YES];
 }
 
+// Test the WebstateList related setup gets called when the mediator's WebState
+// and Consumer have been set.
+TEST_F(ToolbarMediatorTest, TestWebstateListRelatedSetup) {
+  SetUpWebStateList();
+  mediator_.webStateList = web_state_list_.get();
+  mediator_.consumer = consumer_;
+
+  [[consumer_ verify] setTabCount:3];
+}
+
+// Test the WebstateList related setup gets called when the mediator's WebState
+// and Consumer have been set in reverse order.
+TEST_F(ToolbarMediatorTest, TestWebstateListRelatedSetupReverse) {
+  mediator_.consumer = consumer_;
+  SetUpWebStateList();
+  mediator_.webStateList = web_state_list_.get();
+
+  [[consumer_ verify] setTabCount:3];
+}
+
 // Test the Toolbar is updated when the Webstate observer method DidStartLoading
 // is triggered by SetLoading.
 TEST_F(ToolbarMediatorTest, TestDidStartLoading) {
-  // Change the default loading state to false so we can verify the Webstate
+  // Change the default loading state to false to verify the Webstate
   // callback with true.
   test_web_state_.SetLoading(false);
   mediator_.webState = &test_web_state_;
@@ -147,4 +201,26 @@
   [[consumer_ verify] setTabStripVisible:NO];
 }
 
+// Test that increasing the number of Webstates will update the consumer with
+// the right value.
+TEST_F(ToolbarMediatorTest, TestIncreaseNumberOfWebstates) {
+  SetUpWebStateList();
+  mediator_.webStateList = web_state_list_.get();
+  mediator_.consumer = consumer_;
+
+  InsertWebState(0);
+  [[consumer_ verify] setTabCount:kNumberOfWebStates + 1];
+}
+
+// Test that decreasing the number of Webstates will update the consumer with
+// the right value.
+TEST_F(ToolbarMediatorTest, TestDecreaseNumberOfWebstates) {
+  SetUpWebStateList();
+  mediator_.webStateList = web_state_list_.get();
+  mediator_.consumer = consumer_;
+
+  web_state_list_->DetachWebStateAt(0);
+  [[consumer_ verify] setTabCount:kNumberOfWebStates - 1];
+}
+
 }  // namespace
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 39b3093..6643757 100644
--- a/ios/clean/chrome/browser/ui/toolbar/toolbar_view_controller.mm
+++ b/ios/clean/chrome/browser/ui/toolbar/toolbar_view_controller.mm
@@ -5,6 +5,7 @@
 #import "ios/clean/chrome/browser/ui/toolbar/toolbar_view_controller.h"
 
 #import "base/mac/foundation_util.h"
+#import "ios/chrome/browser/ui/uikit_ui_util.h"
 #import "ios/clean/chrome/browser/ui/actions/tab_strip_actions.h"
 #import "ios/clean/chrome/browser/ui/commands/navigation_commands.h"
 #import "ios/clean/chrome/browser/ui/commands/tab_grid_commands.h"
@@ -60,8 +61,7 @@
 #pragma mark - View lifecyle
 
 - (void)viewDidLoad {
-  self.view.backgroundColor =
-      [UIColor colorWithWhite:kToolbarBackgroundBrightness alpha:1.0];
+  self.view.backgroundColor = UIColorFromRGB(kToolbarBackgroundColor);
   [self addChildViewController:self.locationBarViewController
                      toSubview:self.locationBarContainer];
   [self setUpToolbarStackView];
@@ -162,6 +162,12 @@
   [self.tabSwitchStripButton addTarget:nil
                                 action:@selector(showTabStrip:)
                       forControlEvents:UIControlEventTouchUpInside];
+  [self.tabSwitchStripButton
+      setTitleColor:UIColorFromRGB(kToolbarButtonTitleNormalColor)
+           forState:UIControlStateNormal];
+  [self.tabSwitchStripButton
+      setTitleColor:UIColorFromRGB(kToolbarButtonTitleHighlightedColor)
+           forState:UIControlStateHighlighted];
 
   // Tab switcher Grid button.
   self.tabSwitchGridButton = [ToolbarButton tabSwitcherGridToolbarButton];
@@ -217,7 +223,7 @@
                       action:@selector(stop:)
             forControlEvents:UIControlEventTouchUpInside];
 
-  // // Set the buttons constraints priority to UILayoutPriorityDefaultHigh so
+  // Set the button constraint priority to UILayoutPriorityDefaultHigh so
   // these are not broken when being hidden by the StackView.
   [self activateConstraints:buttonConstraints
                withPriority:UILayoutPriorityDefaultHigh];
@@ -229,8 +235,7 @@
   locationBarContainer.backgroundColor = [UIColor whiteColor];
   locationBarContainer.layer.borderWidth = kLocationBarBorderWidth;
   locationBarContainer.layer.borderColor =
-      [UIColor colorWithWhite:kLocationBarBorderColorBrightness alpha:1.0]
-          .CGColor;
+      UIColorFromRGB(kLocationBarBorderColor).CGColor;
   locationBarContainer.layer.shadowRadius = kLocationBarShadowRadius;
   locationBarContainer.layer.shadowOpacity = kLocationBarShadowOpacity;
   locationBarContainer.layer.shadowOffset = CGSizeMake(0.0f, 0.5f);
@@ -329,6 +334,40 @@
   [self updateAllButtonsVisibility];
 }
 
+- (void)setTabCount:(int)tabCount {
+  // Return if tabSwitchStripButton wasn't initialized.
+  if (!self.tabSwitchStripButton)
+    return;
+
+  // Update the text shown in the |self.tabSwitchStripButton|. Note that the
+  // button's title may be empty or contain an easter egg, but the accessibility
+  // value will always be equal to |tabCount|.
+  NSString* tabStripButtonValue = [NSString stringWithFormat:@"%d", tabCount];
+  NSString* tabStripButtonTitle;
+  if (tabCount <= 0) {
+    tabStripButtonTitle = @"";
+  } else if (tabCount > kShowTabStripButtonMaxTabCount) {
+    // As an easter egg, show a smiley face instead of the count if the user has
+    // more than 99 tabs open.
+    tabStripButtonTitle = @":)";
+    [[self.tabSwitchStripButton titleLabel]
+        setFont:[UIFont boldSystemFontOfSize:kFontSizeFewerThanTenTabs]];
+  } else {
+    tabStripButtonTitle = tabStripButtonValue;
+    if (tabCount < 10) {
+      [[self.tabSwitchStripButton titleLabel]
+          setFont:[UIFont boldSystemFontOfSize:kFontSizeFewerThanTenTabs]];
+    } else {
+      [[self.tabSwitchStripButton titleLabel]
+          setFont:[UIFont boldSystemFontOfSize:kFontSizeTenTabsOrMore]];
+    }
+  }
+
+  [self.tabSwitchStripButton setTitle:tabStripButtonTitle
+                             forState:UIControlStateNormal];
+  [self.tabSwitchStripButton setAccessibilityValue:tabStripButtonValue];
+}
+
 #pragma mark - ZoomTransitionDelegate
 
 - (CGRect)rectForZoomWithKey:(NSObject*)key inView:(UIView*)view {
diff --git a/ios/clean/chrome/browser/ui/web_contents/BUILD.gn b/ios/clean/chrome/browser/ui/web_contents/BUILD.gn
index 3e27619..b10606f 100644
--- a/ios/clean/chrome/browser/ui/web_contents/BUILD.gn
+++ b/ios/clean/chrome/browser/ui/web_contents/BUILD.gn
@@ -53,7 +53,7 @@
     "//ios/chrome/browser/web_state_list",
     "//ios/chrome/browser/web_state_list:test_support",
     "//ios/chrome/test/base",
-    "//ios/web:test_support",
+    "//ios/web/public/test/fakes",
     "//testing/gtest",
   ]
 }
diff --git a/ios/components/io_thread/ios_io_thread.mm b/ios/components/io_thread/ios_io_thread.mm
index 59b6047..fd4c2d68 100644
--- a/ios/components/io_thread/ios_io_thread.mm
+++ b/ios/components/io_thread/ios_io_thread.mm
@@ -513,12 +513,12 @@
 
   context->set_http_server_properties(globals->http_server_properties.get());
 
-  net::HttpNetworkSession::Params system_params(params);
+  net::HttpNetworkSession::Context system_context;
   net::URLRequestContextBuilder::SetHttpNetworkSessionComponents(
-      context, &system_params);
+      context, &system_context);
 
   globals->system_http_network_session.reset(
-      new net::HttpNetworkSession(system_params));
+      new net::HttpNetworkSession(params, system_context));
   globals->system_http_transaction_factory.reset(
       new net::HttpNetworkLayer(globals->system_http_network_session.get()));
   context->set_http_transaction_factory(
diff --git a/ios/crnet/crnet_environment.mm b/ios/crnet/crnet_environment.mm
index 6d5e987..f071163 100644
--- a/ios/crnet/crnet_environment.mm
+++ b/ios/crnet/crnet_environment.mm
@@ -440,35 +440,40 @@
                                          0,  // Default cache size.
                                          network_cache_thread_->task_runner()));
 
-  net::HttpNetworkSession::Params params;
-  params.host_resolver = main_context_->host_resolver();
-  params.cert_verifier = main_context_->cert_verifier();
-  params.cert_transparency_verifier =
-      main_context_->cert_transparency_verifier();
-  params.ct_policy_enforcer = main_context_->ct_policy_enforcer();
-  params.channel_id_service = main_context_->channel_id_service();
-  params.transport_security_state = main_context_->transport_security_state();
-  params.proxy_service = main_context_->proxy_service();
-  params.ssl_config_service = main_context_->ssl_config_service();
-  params.http_auth_handler_factory = main_context_->http_auth_handler_factory();
-  params.http_server_properties = main_context_->http_server_properties();
-  params.net_log = main_context_->net_log();
-  params.enable_http2 = spdy_enabled();
-  params.enable_quic = quic_enabled();
+  net::HttpNetworkSession::Params session_params;
+  session_params.enable_http2 = spdy_enabled();
+  session_params.enable_quic = quic_enabled();
 
-  if (!params.channel_id_service) {
+  net::HttpNetworkSession::Context session_context;
+  session_context.host_resolver = main_context_->host_resolver();
+  session_context.cert_verifier = main_context_->cert_verifier();
+  session_context.cert_transparency_verifier =
+      main_context_->cert_transparency_verifier();
+  session_context.ct_policy_enforcer = main_context_->ct_policy_enforcer();
+  session_context.channel_id_service = main_context_->channel_id_service();
+  session_context.transport_security_state =
+      main_context_->transport_security_state();
+  session_context.proxy_service = main_context_->proxy_service();
+  session_context.ssl_config_service = main_context_->ssl_config_service();
+  session_context.http_auth_handler_factory =
+      main_context_->http_auth_handler_factory();
+  session_context.http_server_properties =
+      main_context_->http_server_properties();
+  session_context.net_log = main_context_->net_log();
+
+  if (!session_context.channel_id_service) {
     // The main context may not have a ChannelIDService, since it is lazily
     // constructed. If not, build an ephemeral ChannelIDService with no backing
     // disk store.
     // TODO(ellyjones): support persisting ChannelID.
-    params.channel_id_service =
+    session_context.channel_id_service =
         new net::ChannelIDService(new net::DefaultChannelIDStore(NULL));
   }
 
   // TODO(mmenke):  These really shouldn't be leaked.
   //                See https://crbug.com/523858.
   net::HttpNetworkSession* http_network_session =
-      new net::HttpNetworkSession(params);
+      new net::HttpNetworkSession(session_params, session_context);
   net::HttpCache* main_cache =
       new net::HttpCache(http_network_session, std::move(main_backend),
                          true /* set_up_quic_server_info */);
diff --git a/ios/shared/chrome/browser/ui/toolbar/BUILD.gn b/ios/shared/chrome/browser/ui/toolbar/BUILD.gn
index d787bd37d..a4877b96 100644
--- a/ios/shared/chrome/browser/ui/toolbar/BUILD.gn
+++ b/ios/shared/chrome/browser/ui/toolbar/BUILD.gn
@@ -9,7 +9,7 @@
     "toolbar_test_util.mm",
   ]
   deps = [
-    "//ios/web:test_support",
+    "//ios/web/public/test/fakes",
   ]
   configs += [ "//build/config/compiler:enable_arc" ]
 }
diff --git a/ios/web/BUILD.gn b/ios/web/BUILD.gn
index b5e1ad8..f68865d5 100644
--- a/ios/web/BUILD.gn
+++ b/ios/web/BUILD.gn
@@ -357,17 +357,32 @@
   ]
 }
 
+# TODO(crbug.com/727860): Remove this when nothing depends on it.
+source_set("test_support") {
+  testonly = true
+
+  public_deps = [
+    "//ios/web/public/test",
+    "//ios/web/public/test/fakes",
+    "//ios/web/public/test/http_server",
+  ]
+
+  sources = [
+    "public/test/http_server.h",
+  ]
+}
+
 source_set("earl_grey_test_support") {
   testonly = true
 
   deps = [
-    ":test_support",
     ":web",
     "//base",
     "//base/test:test_support",
     "//ios/testing:ios_test_support",
     "//ios/testing/earl_grey:earl_grey_support",
     "//ios/third_party/earl_grey",
+    "//ios/web/public/test",
     "//net",
   ]
 
@@ -381,122 +396,16 @@
   ]
 }
 
-source_set("test_support") {
-  testonly = true
-
-  deps = [
-    ":web",
-    "//base",
-    "//base/test:test_support",
-    "//ios/testing:ios_test_support",
-    "//ios/testing:ocmock_support",
-    "//ios/third_party/gcdwebserver",
-    "//ios/web/test:mojo_bindings",
-    "//net:test_support",
-    "//testing/gmock",
-    "//testing/gtest",
-    "//third_party/ocmock",
-    "//ui/base",
-  ]
-
-  sources = [
-    "public/test/fakes/crw_test_js_injection_receiver.h",
-    "public/test/fakes/crw_test_js_injection_receiver.mm",
-    "public/test/fakes/crw_test_web_state_observer.h",
-    "public/test/fakes/crw_test_web_state_observer.mm",
-    "public/test/fakes/test_browser_state.cc",
-    "public/test/fakes/test_browser_state.h",
-    "public/test/fakes/test_java_script_dialog_presenter.h",
-    "public/test/fakes/test_java_script_dialog_presenter.mm",
-    "public/test/fakes/test_native_content.h",
-    "public/test/fakes/test_native_content.mm",
-    "public/test/fakes/test_native_content_provider.h",
-    "public/test/fakes/test_native_content_provider.mm",
-    "public/test/fakes/test_navigation_manager.h",
-    "public/test/fakes/test_navigation_manager.mm",
-    "public/test/fakes/test_web_client.h",
-    "public/test/fakes/test_web_client.mm",
-    "public/test/fakes/test_web_state.h",
-    "public/test/fakes/test_web_state.mm",
-    "public/test/fakes/test_web_state_delegate.h",
-    "public/test/fakes/test_web_state_delegate.mm",
-    "public/test/fakes/test_web_state_observer.h",
-    "public/test/fakes/test_web_state_observer.mm",
-    "public/test/fakes/test_web_state_observer_util.h",
-    "public/test/fakes/test_web_state_observer_util.mm",
-    "public/test/fakes/test_web_view_content_view.h",
-    "public/test/fakes/test_web_view_content_view.mm",
-    "public/test/http_server.h",
-    "public/test/http_server.mm",
-    "public/test/http_server_util.h",
-    "public/test/http_server_util.mm",
-    "public/test/js_test_util.h",
-    "public/test/js_test_util.mm",
-    "public/test/native_controller_test_util.h",
-    "public/test/native_controller_test_util.mm",
-    "public/test/navigation_test_util.h",
-    "public/test/navigation_test_util.mm",
-    "public/test/response_providers/data_response_provider.h",
-    "public/test/response_providers/data_response_provider.mm",
-    "public/test/response_providers/delayed_response_provider.h",
-    "public/test/response_providers/delayed_response_provider.mm",
-    "public/test/response_providers/error_page_response_provider.h",
-    "public/test/response_providers/error_page_response_provider.mm",
-    "public/test/response_providers/file_based_response_provider.h",
-    "public/test/response_providers/file_based_response_provider.mm",
-    "public/test/response_providers/file_based_response_provider_impl.h",
-    "public/test/response_providers/file_based_response_provider_impl.mm",
-    "public/test/response_providers/html_response_provider.h",
-    "public/test/response_providers/html_response_provider.mm",
-    "public/test/response_providers/html_response_provider_impl.h",
-    "public/test/response_providers/html_response_provider_impl.mm",
-    "public/test/response_providers/http_auth_response_provider.h",
-    "public/test/response_providers/http_auth_response_provider.mm",
-    "public/test/response_providers/response_provider.h",
-    "public/test/response_providers/response_provider.mm",
-    "public/test/response_providers/string_response_provider.h",
-    "public/test/response_providers/string_response_provider.mm",
-    "public/test/scoped_testing_web_client.h",
-    "public/test/scoped_testing_web_client.mm",
-    "public/test/test_redirect_observer.h",
-    "public/test/test_redirect_observer.mm",
-    "public/test/test_web_thread.h",
-    "public/test/test_web_thread_bundle.h",
-    "public/test/url_test_util.h",
-    "public/test/web_js_test.h",
-    "public/test/web_test.h",
-    "public/test/web_test.mm",
-    "public/test/web_test_suite.h",
-    "public/test/web_test_with_web_state.h",
-    "public/test/web_test_with_web_state.mm",
-    "public/test/web_view_interaction_test_util.h",
-    "public/test/web_view_interaction_test_util.mm",
-    "test/crw_fake_web_controller_observer.h",
-    "test/crw_fake_web_controller_observer.mm",
-    "test/test_url_constants.cc",
-    "test/test_url_constants.h",
-    "test/test_web_thread.cc",
-    "test/test_web_thread_bundle.cc",
-    "test/url_test_util.mm",
-    "test/web_int_test.h",
-    "test/web_int_test.mm",
-    "test/web_test_suite.mm",
-    "test/web_test_with_web_controller.h",
-    "test/web_test_with_web_controller.mm",
-    "test/wk_web_view_crash_utils.h",
-    "test/wk_web_view_crash_utils.mm",
-  ]
-}
-
 source_set("run_all_unittests") {
   testonly = true
   sources = [
     "test/run_all_unittests.cc",
   ]
   deps = [
-    ":test_support",
     "//base",
     "//base/test:test_support",
+    "//ios/web/public/test",
+    "//ios/web/public/test/http_server",
     "//mojo/edk/system",
   ]
 }
@@ -520,7 +429,6 @@
     ":core",
     ":ios_web_unittests_bundle_data",
     ":run_all_unittests",
-    ":test_support",
     ":user_agent",
     ":web",
     "//base",
@@ -530,6 +438,8 @@
     "//ios/net",
     "//ios/testing:ios_test_support",
     "//ios/testing:ocmock_support",
+    "//ios/web/public/test",
+    "//ios/web/public/test/fakes",
     "//ios/web/test:mojo_bindings",
     "//net:test_support",
     "//services/service_manager/public/cpp",
@@ -554,7 +464,6 @@
     ":core",
     ":ios_web_unittests_bundle_data",
     ":run_all_unittests",
-    ":test_support",
     ":user_agent",
     ":web",
     "//base",
@@ -564,7 +473,11 @@
     "//ios/net",
     "//ios/testing:ios_test_support",
     "//ios/testing:ocmock_support",
+    "//ios/web/public/test",
+    "//ios/web/public/test/fakes",
     "//ios/web/test:mojo_bindings",
+    "//ios/web/test:test_constants",
+    "//ios/web/test:test_support",
     "//net:test_support",
     "//services/service_manager/public/cpp",
     "//testing/gmock",
@@ -646,14 +559,18 @@
 
 test("ios_web_inttests") {
   deps = [
-    ":test_support",
     ":web",
     "//base/test:test_support",
     "//ios/testing:http_server_bundle_data",
     "//ios/testing:ios_test_support",
+    "//ios/web/public/test",
+    "//ios/web/public/test/fakes",
+    "//ios/web/public/test/http_server",
     "//ios/web/test:mojo_bindings",
     "//ios/web/test:packed_resources",
     "//ios/web/test:resources",
+    "//ios/web/test:test_constants",
+    "//ios/web/test:test_support",
     "//mojo/edk/system",
     "//net:test_support",
     "//services/service_manager/public/cpp",
diff --git a/ios/web/app/web_main_loop.mm b/ios/web/app/web_main_loop.mm
index 55aa9ff..17bcc71 100644
--- a/ios/web/app/web_main_loop.mm
+++ b/ios/web/app/web_main_loop.mm
@@ -83,7 +83,7 @@
 }
 
 void WebMainLoop::Init() {
-  parts_.reset(web::GetWebClient()->CreateWebMainParts());
+  parts_ = web::GetWebClient()->CreateWebMainParts();
 }
 
 void WebMainLoop::EarlyInitialization() {
diff --git a/ios/web/browser_state_web_view_partition_inttest.mm b/ios/web/browser_state_web_view_partition_inttest.mm
index 906ceb2..e0b46d0 100644
--- a/ios/web/browser_state_web_view_partition_inttest.mm
+++ b/ios/web/browser_state_web_view_partition_inttest.mm
@@ -13,9 +13,9 @@
 #import "base/test/ios/wait_util.h"
 #include "base/test/test_timeouts.h"
 #include "ios/web/public/browser_state.h"
-#import "ios/web/public/test/http_server.h"
+#import "ios/web/public/test/http_server/http_server.h"
+#import "ios/web/public/test/http_server/string_response_provider.h"
 #import "ios/web/public/test/js_test_util.h"
-#import "ios/web/public/test/response_providers/string_response_provider.h"
 #import "ios/web/public/web_view_creation_util.h"
 #import "ios/web/test/web_int_test.h"
 #import "net/base/mac/url_conversions.h"
diff --git a/ios/web/navigation/history_state_operations_inttest.mm b/ios/web/navigation/history_state_operations_inttest.mm
index 88dbcba..99d5f84 100644
--- a/ios/web/navigation/history_state_operations_inttest.mm
+++ b/ios/web/navigation/history_state_operations_inttest.mm
@@ -10,8 +10,8 @@
 #import "ios/web/navigation/navigation_item_impl.h"
 #import "ios/web/public/navigation_item.h"
 #import "ios/web/public/navigation_manager.h"
-#import "ios/web/public/test/http_server.h"
-#include "ios/web/public/test/http_server_util.h"
+#import "ios/web/public/test/http_server/http_server.h"
+#include "ios/web/public/test/http_server/http_server_util.h"
 #import "ios/web/public/test/web_view_interaction_test_util.h"
 #import "ios/web/public/web_state/web_state.h"
 #import "ios/web/test/web_int_test.h"
diff --git a/ios/web/navigation/window_location_inttest.mm b/ios/web/navigation/window_location_inttest.mm
index d6821a5..4637b9d1 100644
--- a/ios/web/navigation/window_location_inttest.mm
+++ b/ios/web/navigation/window_location_inttest.mm
@@ -9,8 +9,8 @@
 #include "base/test/ios/wait_util.h"
 #import "ios/web/public/navigation_item.h"
 #import "ios/web/public/navigation_manager.h"
-#import "ios/web/public/test/http_server.h"
-#include "ios/web/public/test/http_server_util.h"
+#import "ios/web/public/test/http_server/http_server.h"
+#include "ios/web/public/test/http_server/http_server_util.h"
 #import "ios/web/public/test/web_view_interaction_test_util.h"
 #import "ios/web/public/web_state/web_state.h"
 #include "ios/web/public/web_state/web_state_observer.h"
diff --git a/ios/web/public/app/BUILD.gn b/ios/web/public/app/BUILD.gn
index 0d512ff..b2dfa0af 100644
--- a/ios/web/public/app/BUILD.gn
+++ b/ios/web/public/app/BUILD.gn
@@ -13,8 +13,18 @@
   deps = [
     "//base",
     "//ios/web/app",
-  ]
-  configs += [ "//build/config/compiler:enable_arc" ]
 
-  allow_circular_includes_from = [ "//ios/web/app" ]
+    # TODO(crbug.com/728161): remove this dependency as it is not needed but
+    # is there just to allow adding the target to allow_circular_includes_from
+    # in order to fix a circular include issue.
+    "//ios/web:web_arc",
+  ]
+  allow_circular_includes_from = [
+    "//ios/web/app",
+
+    # TODO(crbug.com/728161): remove this exception.
+    "//ios/web:web_arc",
+  ]
+
+  configs += [ "//build/config/compiler:enable_arc" ]
 }
diff --git a/ios/web/public/test/BUILD.gn b/ios/web/public/test/BUILD.gn
new file mode 100644
index 0000000..90975bd2
--- /dev/null
+++ b/ios/web/public/test/BUILD.gn
@@ -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.
+
+source_set("test") {
+  testonly = true
+
+  deps = [
+    "//base",
+    "//base/test:test_support",
+    "//ios/testing:ios_test_support",
+    "//ios/third_party/gcdwebserver",
+    "//ios/web:web",
+    "//ios/web:web_arc",
+    "//ios/web/public/test/fakes",
+    "//ios/web/public/test/http_server",
+    "//ios/web/test:test_support",
+    "//testing/gtest",
+    "//ui/base",
+    "//url",
+  ]
+
+  allow_circular_includes_from = [ "//ios/web/test:test_support" ]
+
+  sources = [
+    "js_test_util.h",
+    "js_test_util.mm",
+    "native_controller_test_util.h",
+    "native_controller_test_util.mm",
+    "navigation_test_util.h",
+    "navigation_test_util.mm",
+    "scoped_testing_web_client.h",
+    "scoped_testing_web_client.mm",
+    "test_redirect_observer.h",
+    "test_redirect_observer.mm",
+    "test_web_thread.h",
+    "test_web_thread_bundle.h",
+    "url_test_util.h",
+    "web_js_test.h",
+    "web_test.h",
+    "web_test.mm",
+    "web_test_suite.h",
+    "web_test_with_web_state.h",
+    "web_test_with_web_state.mm",
+    "web_view_interaction_test_util.h",
+    "web_view_interaction_test_util.mm",
+  ]
+}
diff --git a/ios/web/public/test/fakes/BUILD.gn b/ios/web/public/test/fakes/BUILD.gn
new file mode 100644
index 0000000..6746ba4
--- /dev/null
+++ b/ios/web/public/test/fakes/BUILD.gn
@@ -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.
+
+source_set("fakes") {
+  testonly = true
+
+  deps = [
+    "//base",
+    "//ios/web:web",
+    "//ios/web/test:test_constants",
+    "//mojo/common:common_custom_types",
+    "//net:test_support",
+    "//testing/gtest",
+    "//ui/base",
+  ]
+
+  sources = [
+    "crw_test_js_injection_receiver.h",
+    "crw_test_js_injection_receiver.mm",
+    "crw_test_web_state_observer.h",
+    "crw_test_web_state_observer.mm",
+    "test_browser_state.cc",
+    "test_browser_state.h",
+    "test_java_script_dialog_presenter.h",
+    "test_java_script_dialog_presenter.mm",
+    "test_native_content.h",
+    "test_native_content.mm",
+    "test_native_content_provider.h",
+    "test_native_content_provider.mm",
+    "test_navigation_manager.h",
+    "test_navigation_manager.mm",
+    "test_web_client.h",
+    "test_web_client.mm",
+    "test_web_state.h",
+    "test_web_state.mm",
+    "test_web_state_delegate.h",
+    "test_web_state_delegate.mm",
+    "test_web_state_observer.h",
+    "test_web_state_observer.mm",
+    "test_web_state_observer_util.h",
+    "test_web_state_observer_util.mm",
+    "test_web_view_content_view.h",
+    "test_web_view_content_view.mm",
+  ]
+}
diff --git a/ios/web/public/test/http_server.h b/ios/web/public/test/http_server.h
index af51875f..a31f2dd 100644
--- a/ios/web/public/test/http_server.h
+++ b/ios/web/public/test/http_server.h
@@ -1,134 +1,10 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
+// 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_TEST_HTTP_SERVER_H_
 #define IOS_WEB_PUBLIC_TEST_HTTP_SERVER_H_
 
-#include <memory>
-#include <vector>
-
-#import "base/mac/scoped_nsobject.h"
-#include "base/macros.h"
-#include "base/memory/ref_counted.h"
-#include "base/synchronization/lock.h"
-#import "ios/web/public/test/response_providers/response_provider.h"
-
-@class GCDWebServer;
-
-namespace web {
-namespace test {
-
-// A convience class for wrapping a ResponseProvider so that it can be used
-// inside data structures that operate on ref counted objects. This class is a
-// ref counted container for a ResponseProvider.
-// This object exists for legacy reasons since a large part of the code base
-// still uses ResponseProviders that are not ref counted.
-class RefCountedResponseProviderWrapper :
-   public base::RefCounted<RefCountedResponseProviderWrapper> {
- public:
-  // Main constructor.
-  explicit RefCountedResponseProviderWrapper(
-      std::unique_ptr<ResponseProvider> response_provider);
-  // Returns the ResponseProvider that backs this object.
-  ResponseProvider* GetResponseProvider() { return response_provider_.get(); }
- private:
-  friend class base::RefCounted<RefCountedResponseProviderWrapper>;
-  // The ResponseProvider that backs this object.
-  std::unique_ptr<ResponseProvider> response_provider_;
-  virtual ~RefCountedResponseProviderWrapper();
-};
-
-// The HttpServer is an in-process web server that is used to service requests.
-// It is a singleton and backed by a GCDWebServer.
-// HttpServer can be configured to serve requests by registering
-// web::ResponseProviders.
-// This class is not thread safe on the whole and only certain methods are
-// thread safe.
-class HttpServer {
- public:
-  typedef std::vector<std::unique_ptr<ResponseProvider>> ProviderList;
-
-  // Returns the shared HttpServer instance. Thread safe.
-  static HttpServer& GetSharedInstance();
-  // Returns the shared HttpServer instance and registers the response providers
-  // as well. Takes ownership of the response providers. Must be called from the
-  // main thread.
-  static HttpServer& GetSharedInstanceWithResponseProviders(
-      ProviderList response_providers);
-
-  // A convenience method for the longer form of
-  // |web::test::HttpServer::GetSharedInstance().MakeUrlForHttpServer|
-  static GURL MakeUrl(const std::string& url);
-
-  // Starts the server on the default port 8080. CHECKs if the server can not be
-  // started.
-  // Must be called from the main thread.
-  void StartOrDie();
-  // Starts the server on |port|. Returns true on success, false otherwise.
-  // Must be called from the main thread.
-  bool StartOnPort(NSUInteger port);
-  // Stops the server and prevents it from accepting new requests.
-  // Must be called from the main thread.
-  void Stop();
-  // Returns true if the server is running.
-  // Must be called from the main thread.
-  bool IsRunning() const;
-
-  // Returns the port that the server is running on. Thread Safe
-  NSUInteger GetPort() const;
-
-  // Adds a ResponseProvider. Takes ownership of the ResponseProvider.
-  // Note for using URLs inside of the |response_provider|:
-  // The HttpServer cannot run on default HTTP port 80, so URLs used in
-  // ResponseProviders must be converted at runtime after the HttpServer's port
-  // is determined. Please use |MakeUrl| to handle converting URLs.
-  // Must be called from the main thread.
-  void AddResponseProvider(std::unique_ptr<ResponseProvider> response_provider);
-  // Removes the |response_provider|. Must be called from the main thread.
-  void RemoveResponseProvider(ResponseProvider* response_provider);
-  // Removes all the response providers. Must be called from the main thread.
-  void RemoveAllResponseProviders();
-
- private:
-  // Initializes the server by registering for a GCDWebServer servlet. Must be
-  // called from the main thread.
-  void InitHttpServer();
-  HttpServer();
-  ~HttpServer();
-
-  // Sets the port that the server is running on. Thread Safe
-  void SetPort(NSUInteger port);
-
-  // Creates a GURL that the server can service based on the |url|
-  // passed in.
-  // It does not rewrite URLs if the |url| can already be serviced by the
-  // server.
-  // |url| must be a valid URL. Thread safe.
-  GURL MakeUrlForHttpServer(const std::string& url) const;
-
-  // Returns the response provider that can handle the |request|.
-  // Note: No more than one reponse provider can handle the request.
-  // Thread safe.
-  scoped_refptr<RefCountedResponseProviderWrapper>
-      GetResponseProviderForRequest(
-          const web::ResponseProvider::Request& request);
-
-  // Lock for serializing access to |provider_|.
-  mutable base::Lock provider_list_lock_;
-  // Lock for serializing access to |port_|.
-  mutable base::Lock port_lock_;
-  // The port that the server is running on. 0 if the server is not running.
-  NSUInteger port_;
-  // The GCDWebServer backing the HttpServer.
-  base::scoped_nsobject<GCDWebServer> gcd_web_server_;
-  // The list of providers to service a request.
-  std::vector<scoped_refptr<RefCountedResponseProviderWrapper>> providers_;
-  DISALLOW_COPY_AND_ASSIGN(HttpServer);
-};
-
-}  // namespace test
-}  // namspace web
+#import "ios/web/public/test/http_server.h"
 
 #endif  // IOS_WEB_PUBLIC_TEST_HTTP_SERVER_H_
-
diff --git a/ios/web/public/test/http_server/BUILD.gn b/ios/web/public/test/http_server/BUILD.gn
new file mode 100644
index 0000000..76175f2f
--- /dev/null
+++ b/ios/web/public/test/http_server/BUILD.gn
@@ -0,0 +1,42 @@
+# 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("http_server") {
+  testonly = true
+
+  deps = [
+    "//base",
+    "//base/test:test_support",
+    "//ios/third_party/gcdwebserver",
+    "//net",
+    "//url",
+  ]
+
+  sources = [
+    "data_response_provider.h",
+    "data_response_provider.mm",
+    "delayed_response_provider.h",
+    "delayed_response_provider.mm",
+    "error_page_response_provider.h",
+    "error_page_response_provider.mm",
+    "file_based_response_provider.h",
+    "file_based_response_provider.mm",
+    "file_based_response_provider_impl.h",
+    "file_based_response_provider_impl.mm",
+    "html_response_provider.h",
+    "html_response_provider.mm",
+    "html_response_provider_impl.h",
+    "html_response_provider_impl.mm",
+    "http_auth_response_provider.h",
+    "http_auth_response_provider.mm",
+    "http_server.h",
+    "http_server.mm",
+    "http_server_util.h",
+    "http_server_util.mm",
+    "response_provider.h",
+    "response_provider.mm",
+    "string_response_provider.h",
+    "string_response_provider.mm",
+  ]
+}
diff --git a/ios/web/public/test/response_providers/data_response_provider.h b/ios/web/public/test/http_server/data_response_provider.h
similarity index 80%
rename from ios/web/public/test/response_providers/data_response_provider.h
rename to ios/web/public/test/http_server/data_response_provider.h
index 9c32c70..d5c999b4 100644
--- a/ios/web/public/test/response_providers/data_response_provider.h
+++ b/ios/web/public/test/http_server/data_response_provider.h
@@ -2,14 +2,14 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef IOS_WEB_PUBLIC_TEST_RESPONSE_PROVIDERS_DATA_RESPONSE_PROVIDER_H_
-#define IOS_WEB_PUBLIC_TEST_RESPONSE_PROVIDERS_DATA_RESPONSE_PROVIDER_H_
+#ifndef IOS_WEB_PUBLIC_TEST_HTTP_SERVER_DATA_RESPONSE_PROVIDER_H_
+#define IOS_WEB_PUBLIC_TEST_HTTP_SERVER_DATA_RESPONSE_PROVIDER_H_
 
 #include <string>
 
 #include "base/compiler_specific.h"
 #include "base/memory/ref_counted.h"
-#import "ios/web/public/test/response_providers/response_provider.h"
+#import "ios/web/public/test/http_server/response_provider.h"
 #include "net/http/http_response_headers.h"
 
 namespace web {
@@ -36,4 +36,4 @@
 
 }  // namespace web
 
-#endif  // IOS_WEB_PUBLIC_TEST_RESPONSE_PROVIDERS_DATA_RESPONSE_PROVIDER_H_
+#endif  // IOS_WEB_PUBLIC_TEST_HTTP_SERVER_DATA_RESPONSE_PROVIDER_H_
diff --git a/ios/web/public/test/response_providers/data_response_provider.mm b/ios/web/public/test/http_server/data_response_provider.mm
similarity index 94%
rename from ios/web/public/test/response_providers/data_response_provider.mm
rename to ios/web/public/test/http_server/data_response_provider.mm
index b73dcc23..3b282e7a 100644
--- a/ios/web/public/test/response_providers/data_response_provider.mm
+++ b/ios/web/public/test/http_server/data_response_provider.mm
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#import "ios/web/public/test/response_providers/data_response_provider.h"
+#import "ios/web/public/test/http_server/data_response_provider.h"
 
 #include "base/strings/sys_string_conversions.h"
 #import "ios/third_party/gcdwebserver/src/GCDWebServer/Responses/GCDWebServerDataResponse.h"
diff --git a/ios/web/public/test/response_providers/delayed_response_provider.h b/ios/web/public/test/http_server/delayed_response_provider.h
similarity index 79%
rename from ios/web/public/test/response_providers/delayed_response_provider.h
rename to ios/web/public/test/http_server/delayed_response_provider.h
index c313510..d196911 100644
--- a/ios/web/public/test/response_providers/delayed_response_provider.h
+++ b/ios/web/public/test/http_server/delayed_response_provider.h
@@ -2,12 +2,12 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef IOS_WEB_PUBLIC_TEST_RESPONSE_PROVIDERS_DELAYED_RESPONSE_PROVIDER_H_
-#define IOS_WEB_PUBLIC_TEST_RESPONSE_PROVIDERS_DELAYED_RESPONSE_PROVIDER_H_
+#ifndef IOS_WEB_PUBLIC_TEST_HTTP_SERVER_DELAYED_RESPONSE_PROVIDER_H_
+#define IOS_WEB_PUBLIC_TEST_HTTP_SERVER_DELAYED_RESPONSE_PROVIDER_H_
 
 #include <memory>
 
-#import "ios/web/public/test/response_providers/response_provider.h"
+#import "ios/web/public/test/http_server/response_provider.h"
 
 namespace web {
 
@@ -40,4 +40,4 @@
 
 }  // namespace web
 
-#endif  // IOS_WEB_PUBLIC_TEST_RESPONSE_PROVIDERS_DELAYED_RESPONSE_PROVIDER_H_
+#endif  // IOS_WEB_PUBLIC_TEST_HTTP_SERVER_DELAYED_RESPONSE_PROVIDER_H_
diff --git a/ios/web/public/test/response_providers/delayed_response_provider.mm b/ios/web/public/test/http_server/delayed_response_provider.mm
similarity index 97%
rename from ios/web/public/test/response_providers/delayed_response_provider.mm
rename to ios/web/public/test/http_server/delayed_response_provider.mm
index 7d57911..fd20ac1 100644
--- a/ios/web/public/test/response_providers/delayed_response_provider.mm
+++ b/ios/web/public/test/http_server/delayed_response_provider.mm
@@ -2,13 +2,13 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#import "ios/web/public/test/response_providers/delayed_response_provider.h"
+#import "ios/web/public/test/http_server/delayed_response_provider.h"
 
 #import <Foundation/Foundation.h>
 
 #import "base/ios/weak_nsobject.h"
-#import "base/mac/scoped_nsobject.h"
 #import "base/mac/foundation_util.h"
+#import "base/mac/scoped_nsobject.h"
 #import "ios/third_party/gcdwebserver/src/GCDWebServer/Responses/GCDWebServerDataResponse.h"
 
 // A proxy class that will forward all messages to the |_response|.
diff --git a/ios/web/public/test/response_providers/error_page_response_provider.h b/ios/web/public/test/http_server/error_page_response_provider.h
similarity index 78%
rename from ios/web/public/test/response_providers/error_page_response_provider.h
rename to ios/web/public/test/http_server/error_page_response_provider.h
index 79f4730b..39d214d3 100644
--- a/ios/web/public/test/response_providers/error_page_response_provider.h
+++ b/ios/web/public/test/http_server/error_page_response_provider.h
@@ -2,13 +2,13 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef IOS_WEB_PUBLIC_TEST_RESPONSE_PROVIDERS_ERROR_PAGE_RESPONSE_PROVIDER_H_
-#define IOS_WEB_PUBLIC_TEST_RESPONSE_PROVIDERS_ERROR_PAGE_RESPONSE_PROVIDER_H_
+#ifndef IOS_WEB_PUBLIC_TEST_HTTP_SERVER_ERROR_PAGE_RESPONSE_PROVIDER_H_
+#define IOS_WEB_PUBLIC_TEST_HTTP_SERVER_ERROR_PAGE_RESPONSE_PROVIDER_H_
 
 #include <map>
 #include <string>
 
-#import "ios/web/public/test/response_providers/html_response_provider.h"
+#import "ios/web/public/test/http_server/html_response_provider.h"
 #include "url/gurl.h"
 
 // A HtmlResponseProvider that supports the following additional URLs:
@@ -34,4 +34,4 @@
       std::string* response_body) override;
 };
 
-#endif  // IOS_WEB_PUBLIC_TEST_RESPONSE_PROVIDERS_ERROR_PAGE_RESPONSE_PROVIDER_H_
+#endif  // IOS_WEB_PUBLIC_TEST_HTTP_SERVER_ERROR_PAGE_RESPONSE_PROVIDER_H_
diff --git a/ios/web/public/test/response_providers/error_page_response_provider.mm b/ios/web/public/test/http_server/error_page_response_provider.mm
similarity index 91%
rename from ios/web/public/test/response_providers/error_page_response_provider.mm
rename to ios/web/public/test/http_server/error_page_response_provider.mm
index f8fb072..c2ad683 100644
--- a/ios/web/public/test/response_providers/error_page_response_provider.mm
+++ b/ios/web/public/test/http_server/error_page_response_provider.mm
@@ -2,10 +2,10 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#import "ios/web/public/test/response_providers/error_page_response_provider.h"
+#import "ios/web/public/test/http_server/error_page_response_provider.h"
 
 #include "base/logging.h"
-#import "ios/web/public/test/http_server.h"
+#import "ios/web/public/test/http_server/http_server.h"
 #include "net/http/http_status_code.h"
 
 // static
diff --git a/ios/web/public/test/response_providers/file_based_response_provider.h b/ios/web/public/test/http_server/file_based_response_provider.h
similarity index 68%
rename from ios/web/public/test/response_providers/file_based_response_provider.h
rename to ios/web/public/test/http_server/file_based_response_provider.h
index e0b0eef..5ed6455b 100644
--- a/ios/web/public/test/response_providers/file_based_response_provider.h
+++ b/ios/web/public/test/http_server/file_based_response_provider.h
@@ -2,14 +2,14 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef IOS_WEB_PUBLIC_TEST_RESPONSE_PROVIDERS_FILE_BASED_RESPONSE_PROVIDER_H_
-#define IOS_WEB_PUBLIC_TEST_RESPONSE_PROVIDERS_FILE_BASED_RESPONSE_PROVIDER_H_
+#ifndef IOS_WEB_PUBLIC_TEST_HTTP_SERVER_FILE_BASED_RESPONSE_PROVIDER_H_
+#define IOS_WEB_PUBLIC_TEST_HTTP_SERVER_FILE_BASED_RESPONSE_PROVIDER_H_
 
 #include <memory>
 
 #include "base/compiler_specific.h"
-#import "ios/web/public/test/response_providers/file_based_response_provider_impl.h"
-#import "ios/web/public/test/response_providers/response_provider.h"
+#import "ios/web/public/test/http_server/file_based_response_provider_impl.h"
+#import "ios/web/public/test/http_server/response_provider.h"
 
 namespace base {
 class FilePath;
@@ -34,4 +34,4 @@
 };
 }
 
-#endif  // IOS_WEB_PUBLIC_TEST_RESPONSE_PROVIDERS_FILE_BASED_RESPONSE_PROVIDER_H_
+#endif  // IOS_WEB_PUBLIC_TEST_HTTP_SERVER_FILE_BASED_RESPONSE_PROVIDER_H_
diff --git a/ios/web/public/test/response_providers/file_based_response_provider.mm b/ios/web/public/test/http_server/file_based_response_provider.mm
similarity index 86%
rename from ios/web/public/test/response_providers/file_based_response_provider.mm
rename to ios/web/public/test/http_server/file_based_response_provider.mm
index 457a5f88..20ac8d8e 100644
--- a/ios/web/public/test/response_providers/file_based_response_provider.mm
+++ b/ios/web/public/test/http_server/file_based_response_provider.mm
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#import "ios/web/public/test/response_providers/file_based_response_provider.h"
+#import "ios/web/public/test/http_server/file_based_response_provider.h"
 
 #include "base/files/file_path.h"
 #include "base/strings/sys_string_conversions.h"
@@ -11,11 +11,9 @@
 namespace web {
 
 FileBasedResponseProvider::FileBasedResponseProvider(const base::FilePath& path)
-    : response_provider_impl_(new FileBasedResponseProviderImpl(path)) {
-}
+    : response_provider_impl_(new FileBasedResponseProviderImpl(path)) {}
 
-FileBasedResponseProvider::~FileBasedResponseProvider() {
-}
+FileBasedResponseProvider::~FileBasedResponseProvider() {}
 
 bool FileBasedResponseProvider::CanHandleRequest(const Request& request) {
   return response_provider_impl_->CanHandleRequest(request);
diff --git a/ios/web/public/test/response_providers/file_based_response_provider_impl.h b/ios/web/public/test/http_server/file_based_response_provider_impl.h
similarity index 75%
rename from ios/web/public/test/response_providers/file_based_response_provider_impl.h
rename to ios/web/public/test/http_server/file_based_response_provider_impl.h
index a04163c..b6e98a4e 100644
--- a/ios/web/public/test/response_providers/file_based_response_provider_impl.h
+++ b/ios/web/public/test/http_server/file_based_response_provider_impl.h
@@ -2,11 +2,11 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef IOS_WEB_PUBLIC_TEST_RESPONSE_PROVIDERS_FILE_BASED_RESPONSE_PROVIDER_IMPL_H_
-#define IOS_WEB_PUBLIC_TEST_RESPONSE_PROVIDERS_FILE_BASED_RESPONSE_PROVIDER_IMPL_H_
+#ifndef IOS_WEB_PUBLIC_TEST_HTTP_SERVER_FILE_BASED_RESPONSE_PROVIDER_IMPL_H_
+#define IOS_WEB_PUBLIC_TEST_HTTP_SERVER_FILE_BASED_RESPONSE_PROVIDER_IMPL_H_
 
 #include "base/files/file_path.h"
-#import "ios/web/public/test/response_providers/response_provider.h"
+#import "ios/web/public/test/http_server/response_provider.h"
 
 class GURL;
 
@@ -33,4 +33,4 @@
 };
 }
 
-#endif  // IOS_WEB_PUBLIC_TEST_RESPONSE_PROVIDERS_FILE_BASED_RESPONSE_PROVIDER_IMPL_H_
+#endif  // IOS_WEB_PUBLIC_TEST_HTTP_SERVER_FILE_BASED_RESPONSE_PROVIDER_IMPL_H_
diff --git a/ios/web/public/test/response_providers/file_based_response_provider_impl.mm b/ios/web/public/test/http_server/file_based_response_provider_impl.mm
similarity index 87%
rename from ios/web/public/test/response_providers/file_based_response_provider_impl.mm
rename to ios/web/public/test/http_server/file_based_response_provider_impl.mm
index f10ab13..42b39f7 100644
--- a/ios/web/public/test/response_providers/file_based_response_provider_impl.mm
+++ b/ios/web/public/test/http_server/file_based_response_provider_impl.mm
@@ -2,10 +2,10 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#import "ios/web/public/test/response_providers/file_based_response_provider_impl.h"
+#import "ios/web/public/test/http_server/file_based_response_provider_impl.h"
 
 #include "base/files/file_util.h"
-#import "ios/web/public/test/response_providers/response_provider.h"
+#import "ios/web/public/test/http_server/response_provider.h"
 #include "url/gurl.h"
 
 namespace web {
diff --git a/ios/web/public/test/response_providers/html_response_provider.h b/ios/web/public/test/http_server/html_response_provider.h
similarity index 79%
rename from ios/web/public/test/response_providers/html_response_provider.h
rename to ios/web/public/test/http_server/html_response_provider.h
index 86a021c..985d114 100644
--- a/ios/web/public/test/response_providers/html_response_provider.h
+++ b/ios/web/public/test/http_server/html_response_provider.h
@@ -2,16 +2,16 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef IOS_WEB_PUBLIC_TEST_RESPONSE_PROVIDERS_HTML_RESPONSE_PROVIDER_H_
-#define IOS_WEB_PUBLIC_TEST_RESPONSE_PROVIDERS_HTML_RESPONSE_PROVIDER_H_
+#ifndef IOS_WEB_PUBLIC_TEST_HTTP_SERVER_HTML_RESPONSE_PROVIDER_H_
+#define IOS_WEB_PUBLIC_TEST_HTTP_SERVER_HTML_RESPONSE_PROVIDER_H_
 
 #include <map>
 #include <string>
 
 #include "base/memory/ref_counted.h"
-#import "ios/web/public/test/response_providers/data_response_provider.h"
-#import "ios/web/public/test/response_providers/html_response_provider_impl.h"
-#import "ios/web/public/test/response_providers/response_provider.h"
+#import "ios/web/public/test/http_server/data_response_provider.h"
+#import "ios/web/public/test/http_server/html_response_provider_impl.h"
+#import "ios/web/public/test/http_server/response_provider.h"
 #include "url/gurl.h"
 
 namespace net {
@@ -50,4 +50,4 @@
   std::unique_ptr<HtmlResponseProviderImpl> response_provider_impl_;
 };
 
-#endif  // IOS_WEB_PUBLIC_TEST_RESPONSE_PROVIDERS_HTML_RESPONSE_PROVIDER_H_
+#endif  // IOS_WEB_PUBLIC_TEST_HTTP_SERVER_HTML_RESPONSE_PROVIDER_H_
diff --git a/ios/web/public/test/response_providers/html_response_provider.mm b/ios/web/public/test/http_server/html_response_provider.mm
similarity index 90%
rename from ios/web/public/test/response_providers/html_response_provider.mm
rename to ios/web/public/test/http_server/html_response_provider.mm
index cf09ede8..702f48fd 100644
--- a/ios/web/public/test/response_providers/html_response_provider.mm
+++ b/ios/web/public/test/http_server/html_response_provider.mm
@@ -2,9 +2,9 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#import "ios/web/public/test/response_providers/html_response_provider.h"
+#import "ios/web/public/test/http_server/html_response_provider.h"
 
-#import "ios/web/public/test/response_providers/response_provider.h"
+#import "ios/web/public/test/http_server/response_provider.h"
 #include "url/gurl.h"
 
 HtmlResponseProvider::HtmlResponseProvider()
diff --git a/ios/web/public/test/response_providers/html_response_provider_impl.h b/ios/web/public/test/http_server/html_response_provider_impl.h
similarity index 87%
rename from ios/web/public/test/response_providers/html_response_provider_impl.h
rename to ios/web/public/test/http_server/html_response_provider_impl.h
index 298a49d..896ad271 100644
--- a/ios/web/public/test/response_providers/html_response_provider_impl.h
+++ b/ios/web/public/test/http_server/html_response_provider_impl.h
@@ -2,15 +2,15 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef IOS_WEB_PUBLIC_TEST_RESPONSE_PROVIDERS_HTML_RESPONSE_PROVIDER_IMPL_H_
-#define IOS_WEB_PUBLIC_TEST_RESPONSE_PROVIDERS_HTML_RESPONSE_PROVIDER_IMPL_H_
+#ifndef IOS_WEB_PUBLIC_TEST_HTTP_SERVER_HTML_RESPONSE_PROVIDER_IMPL_H_
+#define IOS_WEB_PUBLIC_TEST_HTTP_SERVER_HTML_RESPONSE_PROVIDER_IMPL_H_
 
 #include <map>
 #include <string>
 
 #include "base/memory/ref_counted.h"
-#import "ios/web/public/test/response_providers/data_response_provider.h"
-#import "ios/web/public/test/response_providers/response_provider.h"
+#import "ios/web/public/test/http_server/data_response_provider.h"
+#import "ios/web/public/test/http_server/response_provider.h"
 #include "net/http/http_response_headers.h"
 #include "net/http/http_status_code.h"
 #include "url/gurl.h"
@@ -71,4 +71,4 @@
   const std::map<GURL, Response> responses_;
 };
 
-#endif  // IOS_WEB_PUBLIC_TEST_RESPONSE_PROVIDERS_HTML_RESPONSE_PROVIDER_IMPL_H_
+#endif  // IOS_WEB_PUBLIC_TEST_HTTP_SERVER_HTML_RESPONSE_PROVIDER_IMPL_H_
diff --git a/ios/web/public/test/response_providers/html_response_provider_impl.mm b/ios/web/public/test/http_server/html_response_provider_impl.mm
similarity index 95%
rename from ios/web/public/test/response_providers/html_response_provider_impl.mm
rename to ios/web/public/test/http_server/html_response_provider_impl.mm
index 543f190..2b26e20 100644
--- a/ios/web/public/test/response_providers/html_response_provider_impl.mm
+++ b/ios/web/public/test/http_server/html_response_provider_impl.mm
@@ -2,9 +2,9 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#import "ios/web/public/test/response_providers/html_response_provider_impl.h"
+#import "ios/web/public/test/http_server/html_response_provider_impl.h"
 
-#import "ios/web/public/test/response_providers/response_provider.h"
+#import "ios/web/public/test/http_server/response_provider.h"
 #include "net/http/http_response_headers.h"
 #include "net/http/http_status_code.h"
 #include "url/gurl.h"
diff --git a/ios/web/public/test/response_providers/http_auth_response_provider.h b/ios/web/public/test/http_server/http_auth_response_provider.h
similarity index 85%
rename from ios/web/public/test/response_providers/http_auth_response_provider.h
rename to ios/web/public/test/http_server/http_auth_response_provider.h
index 1787b38..aadc36d 100644
--- a/ios/web/public/test/response_providers/http_auth_response_provider.h
+++ b/ios/web/public/test/http_server/http_auth_response_provider.h
@@ -2,12 +2,12 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef IOS_WEB_PUBLIC_TEST_RESPONSE_PROVIDERS_HTTP_AUTH_RESPONSE_PROVIDER_H_
-#define IOS_WEB_PUBLIC_TEST_RESPONSE_PROVIDERS_HTTP_AUTH_RESPONSE_PROVIDER_H_
+#ifndef IOS_WEB_PUBLIC_TEST_HTTP_SERVER_HTTP_AUTH_RESPONSE_PROVIDER_H_
+#define IOS_WEB_PUBLIC_TEST_HTTP_SERVER_HTTP_AUTH_RESPONSE_PROVIDER_H_
 
 #include <string>
 
-#import "ios/web/public/test/response_providers/html_response_provider.h"
+#import "ios/web/public/test/http_server/html_response_provider.h"
 #include "url/gurl.h"
 
 namespace net {
@@ -58,4 +58,4 @@
 
 }  // namespace web
 
-#endif  // IOS_WEB_PUBLIC_TEST_RESPONSE_PROVIDERS_HTTP_AUTH_RESPONSE_PROVIDER_H_
+#endif  // IOS_WEB_PUBLIC_TEST_HTTP_SERVER_HTTP_AUTH_RESPONSE_PROVIDER_H_
diff --git a/ios/web/public/test/response_providers/http_auth_response_provider.mm b/ios/web/public/test/http_server/http_auth_response_provider.mm
similarity index 95%
rename from ios/web/public/test/response_providers/http_auth_response_provider.mm
rename to ios/web/public/test/http_server/http_auth_response_provider.mm
index 36ed46c..6205c07 100644
--- a/ios/web/public/test/response_providers/http_auth_response_provider.mm
+++ b/ios/web/public/test/http_server/http_auth_response_provider.mm
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#import "ios/web/public/test/response_providers/http_auth_response_provider.h"
+#import "ios/web/public/test/http_server/http_auth_response_provider.h"
 
 #include "base/base64.h"
 #include "base/strings/stringprintf.h"
diff --git a/ios/web/public/test/http_server/http_server.h b/ios/web/public/test/http_server/http_server.h
new file mode 100644
index 0000000..e1a584f
--- /dev/null
+++ b/ios/web/public/test/http_server/http_server.h
@@ -0,0 +1,133 @@
+// 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 IOS_WEB_PUBLIC_TEST_HTTP_SERVER_HTTP_SERVER_H_
+#define IOS_WEB_PUBLIC_TEST_HTTP_SERVER_HTTP_SERVER_H_
+
+#include <memory>
+#include <vector>
+
+#import "base/mac/scoped_nsobject.h"
+#include "base/macros.h"
+#include "base/memory/ref_counted.h"
+#include "base/synchronization/lock.h"
+#import "ios/web/public/test/http_server/response_provider.h"
+
+@class GCDWebServer;
+
+namespace web {
+namespace test {
+
+// A convience class for wrapping a ResponseProvider so that it can be used
+// inside data structures that operate on ref counted objects. This class is a
+// ref counted container for a ResponseProvider.
+// This object exists for legacy reasons since a large part of the code base
+// still uses ResponseProviders that are not ref counted.
+class RefCountedResponseProviderWrapper
+    : public base::RefCounted<RefCountedResponseProviderWrapper> {
+ public:
+  // Main constructor.
+  explicit RefCountedResponseProviderWrapper(
+      std::unique_ptr<ResponseProvider> response_provider);
+  // Returns the ResponseProvider that backs this object.
+  ResponseProvider* GetResponseProvider() { return response_provider_.get(); }
+
+ private:
+  friend class base::RefCounted<RefCountedResponseProviderWrapper>;
+  // The ResponseProvider that backs this object.
+  std::unique_ptr<ResponseProvider> response_provider_;
+  virtual ~RefCountedResponseProviderWrapper();
+};
+
+// The HttpServer is an in-process web server that is used to service requests.
+// It is a singleton and backed by a GCDWebServer.
+// HttpServer can be configured to serve requests by registering
+// web::ResponseProviders.
+// This class is not thread safe on the whole and only certain methods are
+// thread safe.
+class HttpServer {
+ public:
+  typedef std::vector<std::unique_ptr<ResponseProvider>> ProviderList;
+
+  // Returns the shared HttpServer instance. Thread safe.
+  static HttpServer& GetSharedInstance();
+  // Returns the shared HttpServer instance and registers the response providers
+  // as well. Takes ownership of the response providers. Must be called from the
+  // main thread.
+  static HttpServer& GetSharedInstanceWithResponseProviders(
+      ProviderList response_providers);
+
+  // A convenience method for the longer form of
+  // |web::test::HttpServer::GetSharedInstance().MakeUrlForHttpServer|
+  static GURL MakeUrl(const std::string& url);
+
+  // Starts the server on the default port 8080. CHECKs if the server can not be
+  // started.
+  // Must be called from the main thread.
+  void StartOrDie();
+  // Starts the server on |port|. Returns true on success, false otherwise.
+  // Must be called from the main thread.
+  bool StartOnPort(NSUInteger port);
+  // Stops the server and prevents it from accepting new requests.
+  // Must be called from the main thread.
+  void Stop();
+  // Returns true if the server is running.
+  // Must be called from the main thread.
+  bool IsRunning() const;
+
+  // Returns the port that the server is running on. Thread Safe
+  NSUInteger GetPort() const;
+
+  // Adds a ResponseProvider. Takes ownership of the ResponseProvider.
+  // Note for using URLs inside of the |response_provider|:
+  // The HttpServer cannot run on default HTTP port 80, so URLs used in
+  // ResponseProviders must be converted at runtime after the HttpServer's port
+  // is determined. Please use |MakeUrl| to handle converting URLs.
+  // Must be called from the main thread.
+  void AddResponseProvider(std::unique_ptr<ResponseProvider> response_provider);
+  // Removes the |response_provider|. Must be called from the main thread.
+  void RemoveResponseProvider(ResponseProvider* response_provider);
+  // Removes all the response providers. Must be called from the main thread.
+  void RemoveAllResponseProviders();
+
+ private:
+  // Initializes the server by registering for a GCDWebServer servlet. Must be
+  // called from the main thread.
+  void InitHttpServer();
+  HttpServer();
+  ~HttpServer();
+
+  // Sets the port that the server is running on. Thread Safe
+  void SetPort(NSUInteger port);
+
+  // Creates a GURL that the server can service based on the |url|
+  // passed in.
+  // It does not rewrite URLs if the |url| can already be serviced by the
+  // server.
+  // |url| must be a valid URL. Thread safe.
+  GURL MakeUrlForHttpServer(const std::string& url) const;
+
+  // Returns the response provider that can handle the |request|.
+  // Note: No more than one reponse provider can handle the request.
+  // Thread safe.
+  scoped_refptr<RefCountedResponseProviderWrapper>
+  GetResponseProviderForRequest(const web::ResponseProvider::Request& request);
+
+  // Lock for serializing access to |provider_|.
+  mutable base::Lock provider_list_lock_;
+  // Lock for serializing access to |port_|.
+  mutable base::Lock port_lock_;
+  // The port that the server is running on. 0 if the server is not running.
+  NSUInteger port_;
+  // The GCDWebServer backing the HttpServer.
+  base::scoped_nsobject<GCDWebServer> gcd_web_server_;
+  // The list of providers to service a request.
+  std::vector<scoped_refptr<RefCountedResponseProviderWrapper>> providers_;
+  DISALLOW_COPY_AND_ASSIGN(HttpServer);
+};
+
+}  // namespace test
+}  // namspace web
+
+#endif  // IOS_WEB_PUBLIC_TEST_HTTP_SERVER_HTTP_SERVER_H_
diff --git a/ios/web/public/test/http_server.mm b/ios/web/public/test/http_server/http_server.mm
similarity index 79%
rename from ios/web/public/test/http_server.mm
rename to ios/web/public/test/http_server/http_server.mm
index b5789f4..3b6972ff 100644
--- a/ios/web/public/test/http_server.mm
+++ b/ios/web/public/test/http_server/http_server.mm
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#import "ios/web/public/test/http_server.h"
+#import "ios/web/public/test/http_server/http_server.h"
 
 #import <Foundation/Foundation.h>
 
@@ -30,15 +30,14 @@
     GCDWebServerDataRequest* request) {
   GURL url(net::GURLWithNSURL(request.URL));
   std::string method(base::SysNSStringToUTF8(request.method));
-  base::scoped_nsobject<NSString> body(
-      [[NSString alloc] initWithData:request.data
-                            encoding:NSUTF8StringEncoding]);
+  base::scoped_nsobject<NSString> body([[NSString alloc]
+      initWithData:request.data
+          encoding:NSUTF8StringEncoding]);
   __block net::HttpRequestHeaders headers;
-  [[request headers] enumerateKeysAndObjectsUsingBlock:^(NSString* header_key,
-                                                         NSString* header_value,
-                                                         BOOL*) {
-      headers.SetHeader(base::SysNSStringToUTF8(header_key),
-                        base::SysNSStringToUTF8(header_value));
+  [[request headers] enumerateKeysAndObjectsUsingBlock:^(
+                         NSString* header_key, NSString* header_value, BOOL*) {
+    headers.SetHeader(base::SysNSStringToUTF8(header_key),
+                      base::SysNSStringToUTF8(header_value));
   }];
   return web::ResponseProvider::Request(url, method,
                                         base::SysNSStringToUTF8(body), headers);
@@ -60,7 +59,7 @@
   static web::test::HttpServer* shared_instance = nullptr;
   static dispatch_once_t once;
   dispatch_once(&once, ^{
-      shared_instance = new HttpServer();
+    shared_instance = new HttpServer();
   });
   return *shared_instance;
 }
@@ -81,27 +80,27 @@
   // Note: This block is called from an arbitrary GCD thread.
   id process_request =
       ^GCDWebServerResponse*(GCDWebServerDataRequest* request) {
-      // Relax the cross-thread access restriction to non-thread-safe RefCount.
-      // TODO(crbug.com/707010): Remove ScopedAllowCrossThreadRefCountAccess.
-      base::ScopedAllowCrossThreadRefCountAccess
-          allow_cross_thread_ref_count_access;
+    // Relax the cross-thread access restriction to non-thread-safe RefCount.
+    // TODO(crbug.com/707010): Remove ScopedAllowCrossThreadRefCountAccess.
+    base::ScopedAllowCrossThreadRefCountAccess
+        allow_cross_thread_ref_count_access;
 
-      ResponseProvider::Request provider_request =
-          ResponseProviderRequestFromGCDWebServerRequest(request);
-      scoped_refptr<RefCountedResponseProviderWrapper>
-          ref_counted_response_provider = GetResponseProviderForRequest(
-              provider_request);
+    ResponseProvider::Request provider_request =
+        ResponseProviderRequestFromGCDWebServerRequest(request);
+    scoped_refptr<RefCountedResponseProviderWrapper>
+        ref_counted_response_provider =
+            GetResponseProviderForRequest(provider_request);
 
-      if (!ref_counted_response_provider) {
-        return [GCDWebServerResponse response];
-      }
-      ResponseProvider* response_provider =
-          ref_counted_response_provider->GetResponseProvider();
-      if (!response_provider) {
-        return [GCDWebServerResponse response];
-      }
+    if (!ref_counted_response_provider) {
+      return [GCDWebServerResponse response];
+    }
+    ResponseProvider* response_provider =
+        ref_counted_response_provider->GetResponseProvider();
+    if (!response_provider) {
+      return [GCDWebServerResponse response];
+    }
 
-      return response_provider->GetGCDWebServerResponse(provider_request);
+    return response_provider->GetGCDWebServerResponse(provider_request);
   };
   [gcd_web_server_ removeAllHandlers];
   // Register a servlet for all HTTP GET, POST methods.
@@ -118,8 +117,7 @@
   InitHttpServer();
 }
 
-HttpServer::~HttpServer() {
-}
+HttpServer::~HttpServer() {}
 
 bool HttpServer::StartOnPort(NSUInteger port) {
   DCHECK([NSThread isMainThread]);
@@ -157,7 +155,7 @@
 }
 
 // static
-GURL HttpServer::MakeUrl(const std::string &url) {
+GURL HttpServer::MakeUrl(const std::string& url) {
   return HttpServer::GetSharedInstance().MakeUrlForHttpServer(url);
 }
 
@@ -173,8 +171,7 @@
   GURL::Replacements replacements;
   replacements.SetHostStr(kLocalhostHost);
 
-  const std::string port = std::string(
-      base::IntToString(static_cast<int>(GetPort())));
+  const std::string port = base::IntToString(static_cast<int>(GetPort()));
   replacements.SetPortStr(port);
 
   // It is necessary to prepend the host of the input URL so that URLs such
@@ -186,8 +183,8 @@
 }
 
 scoped_refptr<RefCountedResponseProviderWrapper>
-    HttpServer::GetResponseProviderForRequest(
-        const web::ResponseProvider::Request& request) {
+HttpServer::GetResponseProviderForRequest(
+    const web::ResponseProvider::Request& request) {
   base::AutoLock autolock(provider_list_lock_);
   // Relax the cross-thread access restriction to non-thread-safe RefCount.
   // The lock above protects non-thread-safe RefCount in HTTPServer.
@@ -198,8 +195,8 @@
     ResponseProvider* response_provider =
         ref_counted_response_provider.get()->GetResponseProvider();
     if (response_provider->CanHandleRequest(request)) {
-      DCHECK(!result) <<
-          "No more than one response provider can handle the same request.";
+      DCHECK(!result)
+          << "No more than one response provider can handle the same request.";
       result = ref_counted_response_provider;
     }
   }
@@ -256,5 +253,5 @@
   port_ = port;
 }
 
-} // namespace test
-} // namespace web
+}  // namespace test
+}  // namespace web
diff --git a/ios/web/public/test/http_server/http_server_util.h b/ios/web/public/test/http_server/http_server_util.h
new file mode 100644
index 0000000..49cdc230
--- /dev/null
+++ b/ios/web/public/test/http_server/http_server_util.h
@@ -0,0 +1,46 @@
+// 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 IOS_WEB_PUBLIC_TEST_HTTP_SERVER_HTTP_SERVER_UTIL_H_
+#define IOS_WEB_PUBLIC_TEST_HTTP_SERVER_HTTP_SERVER_UTIL_H_
+
+#include <map>
+
+#include "url/gurl.h"
+
+namespace web {
+
+class ResponseProvider;
+
+namespace test {
+
+// Sets up a web::test::HttpServer with a simple HtmlResponseProvider. The
+// HtmlResponseProvider will use the |responses| map to resolve URLs.
+void SetUpSimpleHttpServer(const std::map<GURL, std::string>& responses);
+
+// Sets up a web::test::HttpServer with a simple HtmlResponseProvider. The
+// HtmlResponseProvider will use the |responses| map to resolve URLs. The value
+// of |responses| is the cookie and response body pair where the first string is
+// the cookie and the second string is the response body. Set the cookie string
+// as empty string if cookie is not needed in the response headers.
+void SetUpSimpleHttpServerWithSetCookies(
+    const std::map<GURL, std::pair<std::string, std::string>>& responses);
+
+// Sets up a web::test::HttpServer with a FileBasedResponseProvider. The
+// server will try to resolve URLs as file paths relative to the application
+// bundle path. web::test::MakeUrl should be used to rewrite URLs before doing
+// a request.
+void SetUpFileBasedHttpServer();
+
+// Sets up a web::test::HttpServer with a single custom provider.
+// Takes ownership of the provider.
+void SetUpHttpServer(std::unique_ptr<web::ResponseProvider> provider);
+
+// Adds a single custom provider.
+// Takes ownership of the provider.
+void AddResponseProvider(std::unique_ptr<web::ResponseProvider> provider);
+}  // namespace test
+}  // namespace web
+
+#endif  // IOS_WEB_PUBLIC_TEST_HTTP_SERVER_HTTP_SERVER_UTIL_H_
diff --git a/ios/web/public/test/http_server_util.mm b/ios/web/public/test/http_server/http_server_util.mm
similarity index 83%
rename from ios/web/public/test/http_server_util.mm
rename to ios/web/public/test/http_server/http_server_util.mm
index 42276a6..f9601445 100644
--- a/ios/web/public/test/http_server_util.mm
+++ b/ios/web/public/test/http_server/http_server_util.mm
@@ -2,13 +2,13 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "ios/web/public/test/http_server_util.h"
+#include "ios/web/public/test/http_server/http_server_util.h"
 
 #include "base/memory/ptr_util.h"
 #include "base/path_service.h"
-#import "ios/web/public/test/http_server.h"
-#import "ios/web/public/test/response_providers/file_based_response_provider.h"
-#import "ios/web/public/test/response_providers/html_response_provider.h"
+#import "ios/web/public/test/http_server/file_based_response_provider.h"
+#import "ios/web/public/test/http_server/html_response_provider.h"
+#import "ios/web/public/test/http_server/http_server.h"
 
 namespace web {
 namespace test {
diff --git a/ios/web/public/test/response_providers/response_provider.h b/ios/web/public/test/http_server/response_provider.h
similarity index 91%
rename from ios/web/public/test/response_providers/response_provider.h
rename to ios/web/public/test/http_server/response_provider.h
index 37b7ad7..d27914b 100644
--- a/ios/web/public/test/response_providers/response_provider.h
+++ b/ios/web/public/test/http_server/response_provider.h
@@ -2,8 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef IOS_WEB_PUBLIC_TEST_RESPONSE_PROVIDERS_RESPONSE_PROVIDER_H_
-#define IOS_WEB_PUBLIC_TEST_RESPONSE_PROVIDERS_RESPONSE_PROVIDER_H_
+#ifndef IOS_WEB_PUBLIC_TEST_HTTP_SERVER_RESPONSE_PROVIDER_H_
+#define IOS_WEB_PUBLIC_TEST_HTTP_SERVER_RESPONSE_PROVIDER_H_
 
 #include <map>
 #include <string>
@@ -75,11 +75,12 @@
       const net::HttpStatusCode& http_status);
 
   ResponseProvider();
-  virtual ~ResponseProvider() {};
+  virtual ~ResponseProvider() {}
+
  private:
   DISALLOW_COPY_AND_ASSIGN(ResponseProvider);
 };
 
 }  // namspace web
 
-#endif  // IOS_WEB_PUBLIC_TEST_RESPONSE_PROVIDERS_RESPONSE_PROVIDER_H_
+#endif  // IOS_WEB_PUBLIC_TEST_HTTP_SERVER_RESPONSE_PROVIDER_H_
diff --git a/ios/web/public/test/response_providers/response_provider.mm b/ios/web/public/test/http_server/response_provider.mm
similarity index 97%
rename from ios/web/public/test/response_providers/response_provider.mm
rename to ios/web/public/test/http_server/response_provider.mm
index b47d62b..0c69529 100644
--- a/ios/web/public/test/response_providers/response_provider.mm
+++ b/ios/web/public/test/http_server/response_provider.mm
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#import "ios/web/public/test/response_providers/response_provider.h"
+#import "ios/web/public/test/http_server/response_provider.h"
 
 #include "base/strings/stringprintf.h"
 #include "net/http/http_response_headers.h"
diff --git a/ios/web/public/test/response_providers/string_response_provider.h b/ios/web/public/test/http_server/string_response_provider.h
similarity index 74%
rename from ios/web/public/test/response_providers/string_response_provider.h
rename to ios/web/public/test/http_server/string_response_provider.h
index 2b20d7d..2e53b68 100644
--- a/ios/web/public/test/response_providers/string_response_provider.h
+++ b/ios/web/public/test/http_server/string_response_provider.h
@@ -2,13 +2,13 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef IOS_WEB_PUBLIC_TEST_RESPONSE_PROVIDERS_STRING_RESPONSE_PROVIDER_H_
-#define IOS_WEB_PUBLIC_TEST_RESPONSE_PROVIDERS_STRING_RESPONSE_PROVIDER_H_
+#ifndef IOS_WEB_PUBLIC_TEST_HTTP_SERVER_STRING_RESPONSE_PROVIDER_H_
+#define IOS_WEB_PUBLIC_TEST_HTTP_SERVER_STRING_RESPONSE_PROVIDER_H_
 
 #include <string>
 
 #include "base/macros.h"
-#import "ios/web/public/test/response_providers/data_response_provider.h"
+#import "ios/web/public/test/http_server/data_response_provider.h"
 
 namespace web {
 
@@ -33,4 +33,4 @@
 
 }  // namespace web
 
-#endif  // IOS_WEB_PUBLIC_TEST_RESPONSE_PROVIDERS_STRING_RESPONSE_PROVIDER_H_
+#endif  // IOS_WEB_PUBLIC_TEST_HTTP_SERVER_STRING_RESPONSE_PROVIDER_H_
diff --git a/ios/web/public/test/response_providers/string_response_provider.mm b/ios/web/public/test/http_server/string_response_provider.mm
similarity index 89%
rename from ios/web/public/test/response_providers/string_response_provider.mm
rename to ios/web/public/test/http_server/string_response_provider.mm
index 41834a4..2e694e2 100644
--- a/ios/web/public/test/response_providers/string_response_provider.mm
+++ b/ios/web/public/test/http_server/string_response_provider.mm
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#import "ios/web/public/test/response_providers/string_response_provider.h"
+#import "ios/web/public/test/http_server/string_response_provider.h"
 
 namespace web {
 
diff --git a/ios/web/public/test/http_server_inttest.mm b/ios/web/public/test/http_server_inttest.mm
index 6e556e2d..39582e1 100644
--- a/ios/web/public/test/http_server_inttest.mm
+++ b/ios/web/public/test/http_server_inttest.mm
@@ -10,8 +10,8 @@
 #import "base/mac/scoped_nsobject.h"
 #include "base/strings/sys_string_conversions.h"
 #import "base/test/ios/wait_util.h"
-#import "ios/web/public/test/http_server.h"
-#import "ios/web/public/test/response_providers/string_response_provider.h"
+#import "ios/web/public/test/http_server/http_server.h"
+#import "ios/web/public/test/http_server/string_response_provider.h"
 #import "ios/web/test/web_int_test.h"
 #import "net/base/mac/url_conversions.h"
 #include "net/http/http_response_headers.h"
diff --git a/ios/web/public/test/http_server_util.h b/ios/web/public/test/http_server_util.h
index b6635698..909b48a 100644
--- a/ios/web/public/test/http_server_util.h
+++ b/ios/web/public/test/http_server_util.h
@@ -1,46 +1,10 @@
-// Copyright 2016 The Chromium Authors. All rights reserved.
+// 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_TEST_HTTP_SERVER_UTIL_H_
 #define IOS_WEB_PUBLIC_TEST_HTTP_SERVER_UTIL_H_
 
-#include <map>
-
-#include "url/gurl.h"
-
-namespace web {
-
-class ResponseProvider;
-
-namespace test {
-
-// Sets up a web::test::HttpServer with a simple HtmlResponseProvider. The
-// HtmlResponseProvider will use the |responses| map to resolve URLs.
-void SetUpSimpleHttpServer(const std::map<GURL, std::string>& responses);
-
-// Sets up a web::test::HttpServer with a simple HtmlResponseProvider. The
-// HtmlResponseProvider will use the |responses| map to resolve URLs. The value
-// of |responses| is the cookie and response body pair where the first string is
-// the cookie and the second string is the response body. Set the cookie string
-// as empty string if cookie is not needed in the response headers.
-void SetUpSimpleHttpServerWithSetCookies(
-    const std::map<GURL, std::pair<std::string, std::string>>& responses);
-
-// Sets up a web::test::HttpServer with a FileBasedResponseProvider. The
-// server will try to resolve URLs as file paths relative to the application
-// bundle path. web::test::MakeUrl should be used to rewrite URLs before doing
-// a request.
-void SetUpFileBasedHttpServer();
-
-// Sets up a web::test::HttpServer with a single custom provider.
-// Takes ownership of the provider.
-void SetUpHttpServer(std::unique_ptr<web::ResponseProvider> provider);
-
-// Adds a single custom provider.
-// Takes ownership of the provider.
-void AddResponseProvider(std::unique_ptr<web::ResponseProvider> provider);
-}  // namespace test
-}  // namespace web
+#include "ios/web/public/test/http_server/http_server_util.h"
 
 #endif  // IOS_WEB_PUBLIC_TEST_HTTP_SERVER_UTIL_H_
diff --git a/ios/web/public/web_client.h b/ios/web/public/web_client.h
index 0ade6ca..5423310 100644
--- a/ios/web/public/web_client.h
+++ b/ios/web/public/web_client.h
@@ -5,6 +5,7 @@
 #ifndef IOS_WEB_PUBLIC_WEB_CLIENT_H_
 #define IOS_WEB_PUBLIC_WEB_CLIENT_H_
 
+#include <memory>
 #include <string>
 #include <vector>
 
@@ -50,7 +51,7 @@
 
   // Allows the embedder to set a custom WebMainParts implementation for the
   // browser startup code.
-  virtual WebMainParts* CreateWebMainParts();
+  virtual std::unique_ptr<WebMainParts> CreateWebMainParts();
 
   // Gives the embedder a chance to perform tasks before a web view is created.
   virtual void PreWebViewCreation() const {}
diff --git a/ios/web/public/web_client.mm b/ios/web/public/web_client.mm
index c86a33ca..2fb74c6 100644
--- a/ios/web/public/web_client.mm
+++ b/ios/web/public/web_client.mm
@@ -6,6 +6,8 @@
 
 #import <Foundation/Foundation.h>
 
+#include "ios/web/public/app/web_main_parts.h"
+
 #if !defined(__has_feature) || !__has_feature(objc_arc)
 #error "This file requires ARC support."
 #endif
@@ -28,7 +30,7 @@
 WebClient::~WebClient() {
 }
 
-WebMainParts* WebClient::CreateWebMainParts() {
+std::unique_ptr<WebMainParts> WebClient::CreateWebMainParts() {
   return nullptr;
 }
 
diff --git a/ios/web/shell/shell_url_request_context_getter.mm b/ios/web/shell/shell_url_request_context_getter.mm
index 4805d54..ce2d5d3 100644
--- a/ios/web/shell/shell_url_request_context_getter.mm
+++ b/ios/web/shell/shell_url_request_context_getter.mm
@@ -120,27 +120,27 @@
         net::HttpAuthHandlerFactory::CreateDefault(host_resolver.get()));
     storage_->set_host_resolver(std::move(host_resolver));
 
-    net::HttpNetworkSession::Params network_session_params;
-    network_session_params.cert_verifier =
+    net::HttpNetworkSession::Context network_session_context;
+    network_session_context.cert_verifier =
         url_request_context_->cert_verifier();
-    network_session_params.transport_security_state =
+    network_session_context.transport_security_state =
         url_request_context_->transport_security_state();
-    network_session_params.cert_transparency_verifier =
+    network_session_context.cert_transparency_verifier =
         url_request_context_->cert_transparency_verifier();
-    network_session_params.ct_policy_enforcer =
+    network_session_context.ct_policy_enforcer =
         url_request_context_->ct_policy_enforcer();
-    network_session_params.channel_id_service =
+    network_session_context.channel_id_service =
         url_request_context_->channel_id_service();
-    network_session_params.net_log = url_request_context_->net_log();
-    network_session_params.proxy_service =
+    network_session_context.net_log = url_request_context_->net_log();
+    network_session_context.proxy_service =
         url_request_context_->proxy_service();
-    network_session_params.ssl_config_service =
+    network_session_context.ssl_config_service =
         url_request_context_->ssl_config_service();
-    network_session_params.http_auth_handler_factory =
+    network_session_context.http_auth_handler_factory =
         url_request_context_->http_auth_handler_factory();
-    network_session_params.http_server_properties =
+    network_session_context.http_server_properties =
         url_request_context_->http_server_properties();
-    network_session_params.host_resolver =
+    network_session_context.host_resolver =
         url_request_context_->host_resolver();
 
     base::FilePath cache_path = base_path_.Append(FILE_PATH_LITERAL("Cache"));
@@ -150,7 +150,8 @@
                                            cache_path, 0, cache_task_runner_));
 
     storage_->set_http_network_session(
-        base::MakeUnique<net::HttpNetworkSession>(network_session_params));
+        base::MakeUnique<net::HttpNetworkSession>(
+            net::HttpNetworkSession::Params(), network_session_context));
     storage_->set_http_transaction_factory(base::MakeUnique<net::HttpCache>(
         storage_->http_network_session(), std::move(main_backend),
         true /* set_up_quic_server_info */));
diff --git a/ios/web/shell/shell_web_client.h b/ios/web/shell/shell_web_client.h
index 0043909b..c4eb4e0 100644
--- a/ios/web/shell/shell_web_client.h
+++ b/ios/web/shell/shell_web_client.h
@@ -21,7 +21,7 @@
   ~ShellWebClient() override;
 
   // WebClient implementation.
-  WebMainParts* CreateWebMainParts() override;
+  std::unique_ptr<WebMainParts> CreateWebMainParts() override;
   std::string GetProduct() const override;
   std::string GetUserAgent(UserAgentType type) const override;
   void AllowCertificateError(
@@ -35,7 +35,7 @@
   ShellBrowserState* browser_state() const;
 
  private:
-  std::unique_ptr<ShellWebMainParts> web_main_parts_;
+  ShellWebMainParts* web_main_parts_;
 
   DISALLOW_COPY_AND_ASSIGN(ShellWebClient);
 };
diff --git a/ios/web/shell/shell_web_client.mm b/ios/web/shell/shell_web_client.mm
index 707d0cac..2f87d214 100644
--- a/ios/web/shell/shell_web_client.mm
+++ b/ios/web/shell/shell_web_client.mm
@@ -6,6 +6,7 @@
 
 #import <UIKit/UIKit.h>
 
+#include "base/memory/ptr_util.h"
 #include "ios/web/public/user_agent.h"
 #include "ios/web/shell/shell_web_main_parts.h"
 
@@ -15,15 +16,16 @@
 
 namespace web {
 
-ShellWebClient::ShellWebClient() {
-}
+ShellWebClient::ShellWebClient() : web_main_parts_(nullptr) {}
 
 ShellWebClient::~ShellWebClient() {
 }
 
-WebMainParts* ShellWebClient::CreateWebMainParts() {
-  web_main_parts_.reset(new ShellWebMainParts);
-  return web_main_parts_.get();
+std::unique_ptr<web::WebMainParts> ShellWebClient::CreateWebMainParts() {
+  auto web_main_parts = base::MakeUnique<ShellWebMainParts>();
+  web_main_parts_ = web_main_parts.get();
+  // TODO(crbug.com/703565): remove std::move() once Xcode 9.0+ is required.
+  return std::move(web_main_parts);
 }
 
 ShellBrowserState* ShellWebClient::browser_state() const {
diff --git a/ios/web/shell/test/BUILD.gn b/ios/web/shell/test/BUILD.gn
index 7d7eedcd..d310d7902 100644
--- a/ios/web/shell/test/BUILD.gn
+++ b/ios/web/shell/test/BUILD.gn
@@ -31,7 +31,9 @@
     "//ios/testing:ios_test_support",
     "//ios/testing/earl_grey:earl_grey_support",
     "//ios/web:earl_grey_test_support",
-    "//ios/web:test_support",
+    "//ios/web/public/test",
+    "//ios/web/public/test/fakes",
+    "//ios/web/public/test/http_server",
     "//ios/web/shell",
     "//net",
     "//url",
@@ -59,7 +61,8 @@
     "//ios/third_party/earl_grey",
     "//ios/web",
     "//ios/web:earl_grey_test_support",
-    "//ios/web:test_support",
+    "//ios/web/public/test",
+    "//ios/web/public/test/http_server",
     "//ios/web/shell",
     "//url",
   ]
diff --git a/ios/web/shell/test/context_menu_egtest.mm b/ios/web/shell/test/context_menu_egtest.mm
index 06c84ca..bc1e69e0 100644
--- a/ios/web/shell/test/context_menu_egtest.mm
+++ b/ios/web/shell/test/context_menu_egtest.mm
@@ -10,8 +10,8 @@
 #import "base/ios/block_types.h"
 #include "base/strings/sys_string_conversions.h"
 #import "ios/testing/earl_grey/matchers.h"
-#import "ios/web/public/test/http_server.h"
-#include "ios/web/public/test/http_server_util.h"
+#import "ios/web/public/test/http_server/http_server.h"
+#include "ios/web/public/test/http_server/http_server_util.h"
 #import "ios/web/public/test/web_view_interaction_test_util.h"
 #import "ios/web/shell/test/app/web_shell_test_util.h"
 #include "ios/web/shell/test/app/web_view_interaction_test_util.h"
diff --git a/ios/web/shell/test/earl_grey/web_shell_test_case.mm b/ios/web/shell/test/earl_grey/web_shell_test_case.mm
index 0c64573..6f2c7d3 100644
--- a/ios/web/shell/test/earl_grey/web_shell_test_case.mm
+++ b/ios/web/shell/test/earl_grey/web_shell_test_case.mm
@@ -6,7 +6,7 @@
 
 #import <EarlGrey/EarlGrey.h>
 
-#import "ios/web/public/test/http_server.h"
+#import "ios/web/public/test/http_server/http_server.h"
 #import "ios/web/shell/test/earl_grey/shell_matchers.h"
 
 #if !defined(__has_feature) || !__has_feature(objc_arc)
diff --git a/ios/web/shell/test/meta_tags_egtest.mm b/ios/web/shell/test/meta_tags_egtest.mm
index a1f92005..fbe44b7b 100644
--- a/ios/web/shell/test/meta_tags_egtest.mm
+++ b/ios/web/shell/test/meta_tags_egtest.mm
@@ -6,8 +6,8 @@
 
 #include "base/strings/stringprintf.h"
 #import "base/test/ios/wait_util.h"
-#import "ios/web/public/test/http_server.h"
-#include "ios/web/public/test/http_server_util.h"
+#import "ios/web/public/test/http_server/http_server.h"
+#include "ios/web/public/test/http_server/http_server_util.h"
 #import "ios/web/shell/test/earl_grey/shell_earl_grey.h"
 #import "ios/web/shell/test/earl_grey/shell_matchers.h"
 #import "ios/web/shell/test/earl_grey/web_shell_test_case.h"
diff --git a/ios/web/shell/test/navigation_egtest.mm b/ios/web/shell/test/navigation_egtest.mm
index 1698e41..8ed626d6 100644
--- a/ios/web/shell/test/navigation_egtest.mm
+++ b/ios/web/shell/test/navigation_egtest.mm
@@ -9,8 +9,8 @@
 #import <EarlGrey/EarlGrey.h>
 
 #include "base/strings/sys_string_conversions.h"
-#import "ios/web/public/test/http_server.h"
-#include "ios/web/public/test/http_server_util.h"
+#import "ios/web/public/test/http_server/http_server.h"
+#include "ios/web/public/test/http_server/http_server_util.h"
 #include "ios/web/shell/test/app/web_view_interaction_test_util.h"
 #import "ios/web/shell/test/earl_grey/shell_earl_grey.h"
 #import "ios/web/shell/test/earl_grey/shell_matchers.h"
diff --git a/ios/web/shell/test/page_state_egtest.mm b/ios/web/shell/test/page_state_egtest.mm
index 292d322b..1b0f8c78 100644
--- a/ios/web/shell/test/page_state_egtest.mm
+++ b/ios/web/shell/test/page_state_egtest.mm
@@ -9,8 +9,8 @@
 
 #include "base/ios/ios_util.h"
 #include "base/strings/string_number_conversions.h"
-#import "ios/web/public/test/http_server.h"
-#include "ios/web/public/test/http_server_util.h"
+#import "ios/web/public/test/http_server/http_server.h"
+#include "ios/web/public/test/http_server/http_server_util.h"
 #import "ios/web/shell/test/earl_grey/shell_earl_grey.h"
 #import "ios/web/shell/test/earl_grey/shell_matchers.h"
 #import "ios/web/shell/test/earl_grey/web_shell_test_case.h"
diff --git a/ios/web/shell/test/pdf_egtest.mm b/ios/web/shell/test/pdf_egtest.mm
index ae39644..ac6a946 100644
--- a/ios/web/shell/test/pdf_egtest.mm
+++ b/ios/web/shell/test/pdf_egtest.mm
@@ -7,8 +7,8 @@
 #import "base/test/ios/wait_util.h"
 #import "ios/testing/wait_util.h"
 #import "ios/web/public/test/earl_grey/web_view_matchers.h"
-#import "ios/web/public/test/http_server.h"
-#include "ios/web/public/test/http_server_util.h"
+#import "ios/web/public/test/http_server/http_server.h"
+#include "ios/web/public/test/http_server/http_server_util.h"
 #import "ios/web/shell/test/app/web_shell_test_util.h"
 #import "ios/web/shell/test/earl_grey/shell_earl_grey.h"
 #import "ios/web/shell/test/earl_grey/web_shell_test_case.h"
diff --git a/ios/web/shell/test/plugin_placeholder_egtest.mm b/ios/web/shell/test/plugin_placeholder_egtest.mm
index 5c8941c..843a9d4 100644
--- a/ios/web/shell/test/plugin_placeholder_egtest.mm
+++ b/ios/web/shell/test/plugin_placeholder_egtest.mm
@@ -9,8 +9,8 @@
 
 #include "base/strings/stringprintf.h"
 #import "base/test/ios/wait_util.h"
-#import "ios/web/public/test/http_server.h"
-#include "ios/web/public/test/http_server_util.h"
+#import "ios/web/public/test/http_server/http_server.h"
+#include "ios/web/public/test/http_server/http_server_util.h"
 #import "ios/web/shell/test/earl_grey/shell_earl_grey.h"
 #import "ios/web/shell/test/earl_grey/shell_matchers.h"
 #import "ios/web/shell/test/earl_grey/web_shell_test_case.h"
diff --git a/ios/web/shell/test/redirect_egtest.mm b/ios/web/shell/test/redirect_egtest.mm
index b9df80e..daa9261 100644
--- a/ios/web/shell/test/redirect_egtest.mm
+++ b/ios/web/shell/test/redirect_egtest.mm
@@ -4,10 +4,10 @@
 
 #import <EarlGrey/EarlGrey.h>
 
-#import "ios/web/public/test/http_server.h"
-#include "ios/web/public/test/http_server_util.h"
-#import "ios/web/public/test/response_providers/html_response_provider.h"
-#import "ios/web/public/test/response_providers/html_response_provider_impl.h"
+#import "ios/web/public/test/http_server/html_response_provider.h"
+#import "ios/web/public/test/http_server/html_response_provider_impl.h"
+#import "ios/web/public/test/http_server/http_server.h"
+#include "ios/web/public/test/http_server/http_server_util.h"
 #import "ios/web/shell/test/earl_grey/shell_earl_grey.h"
 #import "ios/web/shell/test/earl_grey/shell_matchers.h"
 #import "ios/web/shell/test/earl_grey/web_shell_test_case.h"
diff --git a/ios/web/test/BUILD.gn b/ios/web/test/BUILD.gn
index 855ecb2b..035d33b6 100644
--- a/ios/web/test/BUILD.gn
+++ b/ios/web/test/BUILD.gn
@@ -46,3 +46,42 @@
     "root_gen_dir=" + rebase_path(root_gen_dir, root_build_dir),
   ]
 }
+
+source_set("test_support") {
+  testonly = true
+
+  deps = [
+    ":test_constants",
+    "//base",
+    "//base/test:test_support",
+    "//ios/web:web",
+    "//ios/web/public/test/fakes",
+    "//ios/web/public/test/http_server",
+    "//testing/gtest",
+    "//third_party/ocmock",
+    "//ui/base",
+  ]
+
+  sources = [
+    "crw_fake_web_controller_observer.h",
+    "crw_fake_web_controller_observer.mm",
+    "test_web_thread.cc",
+    "test_web_thread_bundle.cc",
+    "url_test_util.mm",
+    "web_int_test.h",
+    "web_int_test.mm",
+    "web_test_suite.mm",
+    "web_test_with_web_controller.h",
+    "web_test_with_web_controller.mm",
+    "wk_web_view_crash_utils.h",
+    "wk_web_view_crash_utils.mm",
+  ]
+}
+
+source_set("test_constants") {
+  testonly = true
+  sources = [
+    "test_url_constants.cc",
+    "test_url_constants.h",
+  ]
+}
diff --git a/ios/web/test/web_int_test.mm b/ios/web/test/web_int_test.mm
index 067e312a..8d5160b8 100644
--- a/ios/web/test/web_int_test.mm
+++ b/ios/web/test/web_int_test.mm
@@ -7,7 +7,7 @@
 #import "base/ios/block_types.h"
 #include "base/memory/ptr_util.h"
 #import "base/test/ios/wait_util.h"
-#import "ios/web/public/test/http_server.h"
+#import "ios/web/public/test/http_server/http_server.h"
 #import "ios/web/public/test/js_test_util.h"
 #include "ios/web/public/web_state/web_state_observer.h"
 #import "ios/web/public/web_view_creation_util.h"
diff --git a/ios/web/web_state/http_auth_inttest.mm b/ios/web/web_state/http_auth_inttest.mm
index 41bbbd3..baa3b7c 100644
--- a/ios/web/web_state/http_auth_inttest.mm
+++ b/ios/web/web_state/http_auth_inttest.mm
@@ -6,9 +6,9 @@
 #include "base/strings/sys_string_conversions.h"
 #include "base/test/ios/wait_util.h"
 #import "ios/web/public/navigation_manager.h"
-#import "ios/web/public/test/http_server.h"
-#include "ios/web/public/test/http_server_util.h"
-#import "ios/web/public/test/response_providers/http_auth_response_provider.h"
+#import "ios/web/public/test/http_server/http_auth_response_provider.h"
+#import "ios/web/public/test/http_server/http_server.h"
+#include "ios/web/public/test/http_server/http_server_util.h"
 #import "ios/web/test/web_int_test.h"
 #import "testing/gtest_mac.h"
 #include "url/gurl.h"
diff --git a/ios/web/web_state/navigation_callbacks_inttest.mm b/ios/web/web_state/navigation_callbacks_inttest.mm
index ac78fd2..4b8ea7f 100644
--- a/ios/web/web_state/navigation_callbacks_inttest.mm
+++ b/ios/web/web_state/navigation_callbacks_inttest.mm
@@ -9,8 +9,8 @@
 #include "base/strings/stringprintf.h"
 #import "ios/web/public/navigation_item.h"
 #import "ios/web/public/navigation_manager.h"
-#import "ios/web/public/test/http_server.h"
-#include "ios/web/public/test/http_server_util.h"
+#import "ios/web/public/test/http_server/http_server.h"
+#include "ios/web/public/test/http_server/http_server_util.h"
 #import "ios/web/public/web_state/navigation_context.h"
 #include "ios/web/public/web_state/web_state_observer.h"
 #include "ios/web/test/test_url_constants.h"
diff --git a/ios/web_view/internal/web_view_url_request_context_getter.mm b/ios/web_view/internal/web_view_url_request_context_getter.mm
index ca10329..b35f433 100644
--- a/ios/web_view/internal/web_view_url_request_context_getter.mm
+++ b/ios/web_view/internal/web_view_url_request_context_getter.mm
@@ -119,27 +119,27 @@
         net::HttpAuthHandlerFactory::CreateDefault(host_resolver.get()));
     storage_->set_host_resolver(std::move(host_resolver));
 
-    net::HttpNetworkSession::Params network_session_params;
-    network_session_params.cert_verifier =
+    net::HttpNetworkSession::Context network_session_context;
+    network_session_context.cert_verifier =
         url_request_context_->cert_verifier();
-    network_session_params.transport_security_state =
+    network_session_context.transport_security_state =
         url_request_context_->transport_security_state();
-    network_session_params.cert_transparency_verifier =
+    network_session_context.cert_transparency_verifier =
         url_request_context_->cert_transparency_verifier();
-    network_session_params.channel_id_service =
+    network_session_context.channel_id_service =
         url_request_context_->channel_id_service();
-    network_session_params.net_log = url_request_context_->net_log();
-    network_session_params.proxy_service =
+    network_session_context.net_log = url_request_context_->net_log();
+    network_session_context.proxy_service =
         url_request_context_->proxy_service();
-    network_session_params.ssl_config_service =
+    network_session_context.ssl_config_service =
         url_request_context_->ssl_config_service();
-    network_session_params.http_auth_handler_factory =
+    network_session_context.http_auth_handler_factory =
         url_request_context_->http_auth_handler_factory();
-    network_session_params.http_server_properties =
+    network_session_context.http_server_properties =
         url_request_context_->http_server_properties();
-    network_session_params.host_resolver =
+    network_session_context.host_resolver =
         url_request_context_->host_resolver();
-    network_session_params.ct_policy_enforcer =
+    network_session_context.ct_policy_enforcer =
         url_request_context_->ct_policy_enforcer();
 
     base::FilePath cache_path = base_path_.Append(FILE_PATH_LITERAL("Cache"));
@@ -149,7 +149,8 @@
                                            cache_path, 0, cache_task_runner_));
 
     storage_->set_http_network_session(
-        base::MakeUnique<net::HttpNetworkSession>(network_session_params));
+        base::MakeUnique<net::HttpNetworkSession>(
+            net::HttpNetworkSession::Params(), network_session_context));
     storage_->set_http_transaction_factory(base::MakeUnique<net::HttpCache>(
         storage_->http_network_session(), std::move(main_backend),
         true /* set_up_quic_server_info */));
diff --git a/ios/web_view/internal/web_view_web_client.h b/ios/web_view/internal/web_view_web_client.h
index b2752b5..b63bd7b 100644
--- a/ios/web_view/internal/web_view_web_client.h
+++ b/ios/web_view/internal/web_view_web_client.h
@@ -11,7 +11,6 @@
 #import "ios/web/public/web_client.h"
 
 namespace ios_web_view {
-class WebViewWebMainParts;
 
 // WebView implementation of WebClient.
 class WebViewWebClient : public web::WebClient {
@@ -20,15 +19,12 @@
   ~WebViewWebClient() override;
 
   // WebClient implementation.
-  web::WebMainParts* CreateWebMainParts() override;
+  std::unique_ptr<web::WebMainParts> CreateWebMainParts() override;
   std::string GetProduct() const override;
   std::string GetUserAgent(web::UserAgentType type) const override;
   NSString* GetEarlyPageScript(web::BrowserState* browser_state) const override;
 
  private:
-  // The WebMainParts created by |CreateWebMainParts()|.
-  WebViewWebMainParts* web_main_parts_;
-
   DISALLOW_COPY_AND_ASSIGN(WebViewWebClient);
 };
 
diff --git a/ios/web_view/internal/web_view_web_client.mm b/ios/web_view/internal/web_view_web_client.mm
index 319b5e3..c011a36 100644
--- a/ios/web_view/internal/web_view_web_client.mm
+++ b/ios/web_view/internal/web_view_web_client.mm
@@ -4,6 +4,7 @@
 
 #import "ios/web_view/internal/web_view_web_client.h"
 
+#include "base/memory/ptr_util.h"
 #include "base/strings/sys_string_conversions.h"
 #include "ios/web/public/user_agent.h"
 #include "ios/web_view/internal/web_view_browser_state.h"
@@ -17,13 +18,12 @@
 
 namespace ios_web_view {
 
-WebViewWebClient::WebViewWebClient() : web_main_parts_(nullptr) {}
+WebViewWebClient::WebViewWebClient() = default;
 
 WebViewWebClient::~WebViewWebClient() = default;
 
-web::WebMainParts* WebViewWebClient::CreateWebMainParts() {
-  web_main_parts_ = new WebViewWebMainParts();
-  return web_main_parts_;
+std::unique_ptr<web::WebMainParts> WebViewWebClient::CreateWebMainParts() {
+  return base::MakeUnique<WebViewWebMainParts>();
 }
 
 std::string WebViewWebClient::GetProduct() const {
diff --git a/ipc/ipc_channel_proxy.cc b/ipc/ipc_channel_proxy.cc
index 616a99404..d35328e4 100644
--- a/ipc/ipc_channel_proxy.cc
+++ b/ipc/ipc_channel_proxy.cc
@@ -439,7 +439,7 @@
 }
 
 ChannelProxy::~ChannelProxy() {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
 
   Close();
 }
@@ -463,7 +463,7 @@
 
 void ChannelProxy::Init(std::unique_ptr<ChannelFactory> factory,
                         bool create_pipe_now) {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   DCHECK(!did_init_);
 
   if (create_pipe_now) {
@@ -503,7 +503,7 @@
 }
 
 void ChannelProxy::Close() {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
 
   // Clear the backpointer to the listener so that any pending calls to
   // Context::OnDispatchMessage or OnDispatchError will be ignored.  It is
@@ -539,13 +539,13 @@
 }
 
 void ChannelProxy::AddFilter(MessageFilter* filter) {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
 
   context_->AddFilter(filter);
 }
 
 void ChannelProxy::RemoveFilter(MessageFilter* filter) {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
 
   context_->ipc_task_runner()->PostTask(
       FROM_HERE, base::Bind(&Context::OnRemoveFilter, context_,
@@ -567,7 +567,7 @@
 }
 
 void ChannelProxy::ClearIPCTaskRunner() {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   context()->ClearIPCTaskRunner();
 }
 
diff --git a/ipc/ipc_channel_proxy.h b/ipc/ipc_channel_proxy.h
index 2825226e..85cf510a 100644
--- a/ipc/ipc_channel_proxy.h
+++ b/ipc/ipc_channel_proxy.h
@@ -14,8 +14,8 @@
 
 #include "base/callback.h"
 #include "base/memory/ref_counted.h"
+#include "base/sequence_checker.h"
 #include "base/synchronization/lock.h"
-#include "base/threading/non_thread_safe.h"
 #include "build/build_config.h"
 #include "ipc/ipc_channel.h"
 #include "ipc/ipc_channel_handle.h"
@@ -72,7 +72,7 @@
 // |channel_lifetime_lock_| is used to protect it. The locking overhead is only
 // paid if the underlying channel supports thread-safe |Send|.
 //
-class IPC_EXPORT ChannelProxy : public Sender, public base::NonThreadSafe {
+class IPC_EXPORT ChannelProxy : public Sender {
  public:
 #if defined(ENABLE_IPC_FUZZER)
   // Interface for a filter to be imposed on outgoing messages which can
@@ -404,6 +404,8 @@
 #if defined(ENABLE_IPC_FUZZER)
   OutgoingMessageFilter* outgoing_message_filter_;
 #endif
+
+  SEQUENCE_CHECKER(sequence_checker_);
 };
 
 }  // namespace IPC
diff --git a/jingle/glue/proxy_resolving_client_socket.cc b/jingle/glue/proxy_resolving_client_socket.cc
index 4417590..3e37a44 100644
--- a/jingle/glue/proxy_resolving_client_socket.cc
+++ b/jingle/glue/proxy_resolving_client_socket.cc
@@ -57,27 +57,31 @@
   DCHECK_GT(dest_host_port_pair_.port(), 0);
   DCHECK(proxy_url_.is_valid());
 
-  net::HttpNetworkSession::Params session_params;
-  session_params.client_socket_factory = socket_factory;
-  session_params.host_resolver = request_context->host_resolver();
-  session_params.cert_verifier = request_context->cert_verifier();
-  session_params.transport_security_state =
+  net::HttpNetworkSession::Context session_context;
+  session_context.client_socket_factory = socket_factory;
+  session_context.host_resolver = request_context->host_resolver();
+  session_context.cert_verifier = request_context->cert_verifier();
+  session_context.transport_security_state =
       request_context->transport_security_state();
-  session_params.cert_transparency_verifier =
+  session_context.cert_transparency_verifier =
       request_context->cert_transparency_verifier();
-  session_params.ct_policy_enforcer = request_context->ct_policy_enforcer();
+  session_context.ct_policy_enforcer = request_context->ct_policy_enforcer();
   // TODO(rkn): This is NULL because ChannelIDService is not thread safe.
-  session_params.channel_id_service = NULL;
-  session_params.proxy_service = request_context->proxy_service();
-  session_params.ssl_config_service = request_context->ssl_config_service();
-  session_params.http_auth_handler_factory =
+  // TODO(mmenke):  The above comment makes no sense, as not a single one of
+  // these classes is thread safe. Figure out if the comment's wrong, or if this
+  // entire class is badly broken.
+  session_context.channel_id_service = NULL;
+  session_context.proxy_service = request_context->proxy_service();
+  session_context.ssl_config_service = request_context->ssl_config_service();
+  session_context.http_auth_handler_factory =
       request_context->http_auth_handler_factory();
-  session_params.http_server_properties =
+  session_context.http_server_properties =
       request_context->http_server_properties();
-  session_params.net_log = request_context->net_log();
+  session_context.net_log = request_context->net_log();
 
   const net::HttpNetworkSession::Params* reference_params =
       request_context->GetNetworkSessionParams();
+  net::HttpNetworkSession::Params session_params;
   if (reference_params) {
     // TODO(mmenke):  Just copying specific parameters seems highly regression
     // prone.  Should have a better way to do this.
@@ -93,7 +97,8 @@
         reference_params->enable_http2_alternative_service;
   }
 
-  network_session_.reset(new net::HttpNetworkSession(session_params));
+  network_session_.reset(
+      new net::HttpNetworkSession(session_params, session_context));
 
   net::HttpAuthCache* other_auth_cache =
       request_context->http_transaction_factory()
diff --git a/media/cast/common/transport_encryption_handler.h b/media/cast/common/transport_encryption_handler.h
index 053d5d730..ab3667cd 100644
--- a/media/cast/common/transport_encryption_handler.h
+++ b/media/cast/common/transport_encryption_handler.h
@@ -14,7 +14,6 @@
 
 #include "base/macros.h"
 #include "base/strings/string_piece.h"
-#include "base/threading/non_thread_safe.h"
 #include "media/cast/common/frame_id.h"
 
 namespace crypto {
@@ -25,7 +24,7 @@
 namespace media {
 namespace cast {
 
-class TransportEncryptionHandler : public base::NonThreadSafe {
+class TransportEncryptionHandler {
  public:
   TransportEncryptionHandler();
   ~TransportEncryptionHandler();
diff --git a/media/cast/net/cast_transport.h b/media/cast/net/cast_transport.h
index 0ac9f5d..bfae9fc 100644
--- a/media/cast/net/cast_transport.h
+++ b/media/cast/net/cast_transport.h
@@ -24,7 +24,6 @@
 
 #include "base/callback.h"
 #include "base/single_thread_task_runner.h"
-#include "base/threading/non_thread_safe.h"
 #include "base/time/tick_clock.h"
 #include "base/values.h"
 #include "media/cast/logging/logging_defines.h"
@@ -71,7 +70,7 @@
 };
 
 // The application should only trigger this class from the transport thread.
-class CastTransport : public base::NonThreadSafe {
+class CastTransport {
  public:
   // Interface used for receiving status updates, raw events, and RTP packets
   // from CastTransport.
diff --git a/media/cast/sender/audio_sender.h b/media/cast/sender/audio_sender.h
index 315f5f8..4080526 100644
--- a/media/cast/sender/audio_sender.h
+++ b/media/cast/sender/audio_sender.h
@@ -11,7 +11,6 @@
 #include "base/macros.h"
 #include "base/memory/ref_counted.h"
 #include "base/memory/weak_ptr.h"
-#include "base/threading/non_thread_safe.h"
 #include "base/time/tick_clock.h"
 #include "base/time/time.h"
 #include "media/base/audio_bus.h"
@@ -30,7 +29,7 @@
 // RTCP packets.
 // Additionally it posts a bunch of delayed tasks to the main thread for various
 // timeouts.
-class AudioSender : public FrameSender, public base::NonThreadSafe {
+class AudioSender : public FrameSender {
  public:
   AudioSender(scoped_refptr<CastEnvironment> cast_environment,
               const FrameSenderConfig& audio_config,
diff --git a/media/cast/sender/video_sender.h b/media/cast/sender/video_sender.h
index e383faa2..910e155 100644
--- a/media/cast/sender/video_sender.h
+++ b/media/cast/sender/video_sender.h
@@ -11,7 +11,6 @@
 #include "base/macros.h"
 #include "base/memory/ref_counted.h"
 #include "base/memory/weak_ptr.h"
-#include "base/threading/non_thread_safe.h"
 #include "base/time/tick_clock.h"
 #include "base/time/time.h"
 #include "media/cast/cast_config.h"
@@ -38,7 +37,7 @@
 // RTCP packets.
 // Additionally it posts a bunch of delayed tasks to the main thread for various
 // timeouts.
-class VideoSender : public FrameSender, public base::NonThreadSafe {
+class VideoSender : public FrameSender {
  public:
   VideoSender(scoped_refptr<CastEnvironment> cast_environment,
               const FrameSenderConfig& video_config,
diff --git a/net/base/network_change_notifier.cc b/net/base/network_change_notifier.cc
index 85ca185..7ae0489 100644
--- a/net/base/network_change_notifier.cc
+++ b/net/base/network_change_notifier.cc
@@ -815,6 +815,16 @@
     if (interfaces[i].friendly_name == "Teredo Tunneling Pseudo-Interface")
       continue;
 #endif
+#if defined(OS_MACOSX)
+    // Ignore tunnel and airdrop interfaces.
+    if (base::StartsWith(interfaces[i].friendly_name, "utun",
+                         base::CompareCase::SENSITIVE) ||
+        base::StartsWith(interfaces[i].friendly_name, "awdl",
+                         base::CompareCase::SENSITIVE)) {
+      continue;
+    }
+#endif
+
     // Remove VMware network interfaces as they're internal and should not be
     // used to determine the network connection type.
     if (base::ToLowerASCII(interfaces[i].friendly_name).find("vmnet") !=
diff --git a/net/base/network_change_notifier_mac.cc b/net/base/network_change_notifier_mac.cc
index 0082153..dc6430f1a 100644
--- a/net/base/network_change_notifier_mac.cc
+++ b/net/base/network_change_notifier_mac.cc
@@ -21,24 +21,6 @@
   return reachable && !connection_required;
 }
 
-NetworkChangeNotifier::ConnectionType CalculateConnectionType(
-    SCNetworkConnectionFlags flags) {
-  bool reachable = CalculateReachability(flags);
-  if (reachable) {
-#if defined(OS_IOS)
-    return (flags & kSCNetworkReachabilityFlagsIsWWAN) ?
-        NetworkChangeNotifier::CONNECTION_3G :
-        NetworkChangeNotifier::CONNECTION_WIFI;
-#else
-    // TODO(droger): Get something more detailed than CONNECTION_UNKNOWN.
-    // http://crbug.com/112937
-    return NetworkChangeNotifier::CONNECTION_UNKNOWN;
-#endif  // defined(OS_IOS)
-  } else {
-    return NetworkChangeNotifier::CONNECTION_NONE;
-  }
-}
-
 // Thread on which we can run DnsConfigService, which requires a TYPE_IO
 // message loop.
 class NetworkChangeNotifierMac::DnsConfigServiceThread : public base::Thread {
@@ -117,6 +99,23 @@
   net_config_watcher_->SetInitialConnectionType();
 }
 
+// static
+NetworkChangeNotifier::ConnectionType
+NetworkChangeNotifierMac::CalculateConnectionType(
+    SCNetworkConnectionFlags flags) {
+  bool reachable = CalculateReachability(flags);
+  if (reachable) {
+#if defined(OS_IOS)
+    return (flags & kSCNetworkReachabilityFlagsIsWWAN) ? CONNECTION_3G
+                                                       : CONNECTION_WIFI;
+#else
+    return ConnectionTypeFromInterfaces();
+#endif  // defined(OS_IOS)
+  } else {
+    return CONNECTION_NONE;
+  }
+}
+
 void NetworkChangeNotifierMac::Forwarder::StartReachabilityNotifications() {
   net_config_watcher_->StartReachabilityNotifications();
 }
diff --git a/net/base/network_change_notifier_mac.h b/net/base/network_change_notifier_mac.h
index 9acb47c..34b1266 100644
--- a/net/base/network_change_notifier_mac.h
+++ b/net/base/network_change_notifier_mac.h
@@ -48,6 +48,9 @@
  private:
   class DnsConfigServiceThread;
 
+  // Called on the main thread on startup, afterwards on the notifier thread.
+  static ConnectionType CalculateConnectionType(SCNetworkConnectionFlags flags);
+
   // Methods directly called by the NetworkConfigWatcherMac::Delegate:
   void StartReachabilityNotifications();
   void SetDynamicStoreNotificationKeys(SCDynamicStoreRef store);
diff --git a/net/base/network_change_notifier_unittest.cc b/net/base/network_change_notifier_unittest.cc
index c06d358..ef15630 100644
--- a/net/base/network_change_notifier_unittest.cc
+++ b/net/base/network_change_notifier_unittest.cc
@@ -105,6 +105,40 @@
 #endif
 }
 
+TEST(NetworkChangeNotifierTest, IgnoreAirdropOnMac) {
+  NetworkInterfaceList list;
+  NetworkInterface interface_airdrop;
+  interface_airdrop.type = NetworkChangeNotifier::CONNECTION_ETHERNET;
+  interface_airdrop.name = "awdl0";
+  interface_airdrop.friendly_name = "awdl0";
+  list.push_back(interface_airdrop);
+
+#if defined(OS_MACOSX)
+  EXPECT_EQ(NetworkChangeNotifier::CONNECTION_NONE,
+            NetworkChangeNotifier::ConnectionTypeFromInterfaceList(list));
+#else
+  EXPECT_EQ(NetworkChangeNotifier::CONNECTION_ETHERNET,
+            NetworkChangeNotifier::ConnectionTypeFromInterfaceList(list));
+#endif
+}
+
+TEST(NetworkChangeNotifierTest, IgnoreTunnelsOnMac) {
+  NetworkInterfaceList list;
+  NetworkInterface interface_tunnel;
+  interface_tunnel.type = NetworkChangeNotifier::CONNECTION_ETHERNET;
+  interface_tunnel.name = "utun0";
+  interface_tunnel.friendly_name = "utun0";
+  list.push_back(interface_tunnel);
+
+#if defined(OS_MACOSX)
+  EXPECT_EQ(NetworkChangeNotifier::CONNECTION_NONE,
+            NetworkChangeNotifier::ConnectionTypeFromInterfaceList(list));
+#else
+  EXPECT_EQ(NetworkChangeNotifier::CONNECTION_ETHERNET,
+            NetworkChangeNotifier::ConnectionTypeFromInterfaceList(list));
+#endif
+}
+
 TEST(NetworkChangeNotifierTest, IgnoreVMInterfaces) {
   NetworkInterfaceList list;
   NetworkInterface interface_vmnet_linux;
diff --git a/net/base/network_config_watcher_mac.cc b/net/base/network_config_watcher_mac.cc
index 24eaee90..bc46c12 100644
--- a/net/base/network_config_watcher_mac.cc
+++ b/net/base/network_config_watcher_mac.cc
@@ -67,10 +67,7 @@
 }
 
 void NetworkConfigWatcherMacThread::Init() {
-  // Disallow IO to make sure NetworkConfigWatcherMacThread's helper thread does
-  // not perform blocking operations.
-  base::ThreadRestrictions::SetIOAllowed(false);
-
+  base::ThreadRestrictions::SetIOAllowed(true);
   delegate_->Init();
 
   // TODO(willchan): Look to see if there's a better signal for when it's ok to
diff --git a/net/cert_net/cert_net_fetcher_impl_unittest.cc b/net/cert_net/cert_net_fetcher_impl_unittest.cc
index 6669cfd..12e468e 100644
--- a/net/cert_net/cert_net_fetcher_impl_unittest.cc
+++ b/net/cert_net/cert_net_fetcher_impl_unittest.cc
@@ -57,17 +57,17 @@
     storage_.set_http_server_properties(
         std::unique_ptr<HttpServerProperties>(new HttpServerPropertiesImpl()));
 
-    HttpNetworkSession::Params params;
-    params.host_resolver = host_resolver();
-    params.cert_verifier = cert_verifier();
-    params.transport_security_state = transport_security_state();
-    params.cert_transparency_verifier = cert_transparency_verifier();
-    params.ct_policy_enforcer = ct_policy_enforcer();
-    params.proxy_service = proxy_service();
-    params.ssl_config_service = ssl_config_service();
-    params.http_server_properties = http_server_properties();
-    storage_.set_http_network_session(
-        base::MakeUnique<HttpNetworkSession>(params));
+    HttpNetworkSession::Context session_context;
+    session_context.host_resolver = host_resolver();
+    session_context.cert_verifier = cert_verifier();
+    session_context.transport_security_state = transport_security_state();
+    session_context.cert_transparency_verifier = cert_transparency_verifier();
+    session_context.ct_policy_enforcer = ct_policy_enforcer();
+    session_context.proxy_service = proxy_service();
+    session_context.ssl_config_service = ssl_config_service();
+    session_context.http_server_properties = http_server_properties();
+    storage_.set_http_network_session(base::MakeUnique<HttpNetworkSession>(
+        HttpNetworkSession::Params(), session_context));
     storage_.set_http_transaction_factory(base::MakeUnique<HttpCache>(
         storage_.http_network_session(), HttpCache::DefaultBackend::InMemory(0),
         false /* is_main_cache */));
diff --git a/net/http/bidirectional_stream_unittest.cc b/net/http/bidirectional_stream_unittest.cc
index 2f1bde1..6d62d57 100644
--- a/net/http/bidirectional_stream_unittest.cc
+++ b/net/http/bidirectional_stream_unittest.cc
@@ -445,9 +445,9 @@
   request_info->url = GURL("http://www.example.org/");
 
   TestDelegateBase delegate(nullptr, 0);
-  HttpNetworkSession::Params params =
-      SpdySessionDependencies::CreateSessionParams(&session_deps_);
-  std::unique_ptr<HttpNetworkSession> session(new HttpNetworkSession(params));
+  std::unique_ptr<HttpNetworkSession> session(new HttpNetworkSession(
+      SpdySessionDependencies::CreateSessionParams(&session_deps_),
+      SpdySessionDependencies::CreateSessionContext(&session_deps_)));
   delegate.SetRunUntilCompletion(true);
   delegate.Start(std::move(request_info), session.get());
 
@@ -566,9 +566,9 @@
   request_info->url = GURL("http://www.example.org/");
 
   std::unique_ptr<TestDelegateBase> delegate(new TestDelegateBase(nullptr, 0));
-  HttpNetworkSession::Params params =
-      SpdySessionDependencies::CreateSessionParams(&session_deps_);
-  std::unique_ptr<HttpNetworkSession> session(new HttpNetworkSession(params));
+  std::unique_ptr<HttpNetworkSession> session(new HttpNetworkSession(
+      SpdySessionDependencies::CreateSessionParams(&session_deps_),
+      SpdySessionDependencies::CreateSessionContext(&session_deps_)));
   delegate->Start(std::move(request_info), session.get());
   // Reset stream right before the OnFailed task is executed.
   delegate.reset();
diff --git a/net/http/http_network_layer_unittest.cc b/net/http/http_network_layer_unittest.cc
index af1fa3b0..2e443a6 100644
--- a/net/http/http_network_layer_unittest.cc
+++ b/net/http/http_network_layer_unittest.cc
@@ -44,17 +44,18 @@
     cert_verifier_.reset(new MockCertVerifier);
     transport_security_state_.reset(new TransportSecurityState);
     proxy_service_ = std::move(proxy_service);
-    HttpNetworkSession::Params session_params;
-    session_params.client_socket_factory = &mock_socket_factory_;
-    session_params.host_resolver = &host_resolver_;
-    session_params.cert_verifier = cert_verifier_.get();
-    session_params.transport_security_state = transport_security_state_.get();
-    session_params.cert_transparency_verifier = &ct_verifier_;
-    session_params.ct_policy_enforcer = &ct_policy_enforcer_;
-    session_params.proxy_service = proxy_service_.get();
-    session_params.ssl_config_service = ssl_config_service_.get();
-    session_params.http_server_properties = &http_server_properties_;
-    network_session_.reset(new HttpNetworkSession(session_params));
+    HttpNetworkSession::Context session_context;
+    session_context.client_socket_factory = &mock_socket_factory_;
+    session_context.host_resolver = &host_resolver_;
+    session_context.cert_verifier = cert_verifier_.get();
+    session_context.transport_security_state = transport_security_state_.get();
+    session_context.cert_transparency_verifier = &ct_verifier_;
+    session_context.ct_policy_enforcer = &ct_policy_enforcer_;
+    session_context.proxy_service = proxy_service_.get();
+    session_context.ssl_config_service = ssl_config_service_.get();
+    session_context.http_server_properties = &http_server_properties_;
+    network_session_.reset(
+        new HttpNetworkSession(HttpNetworkSession::Params(), session_context));
     factory_.reset(new HttpNetworkLayer(network_session_.get()));
   }
 
diff --git a/net/http/http_network_session.cc b/net/http/http_network_session.cc
index 6f5a1e5..7148208 100644
--- a/net/http/http_network_session.cc
+++ b/net/http/http_network_session.cc
@@ -49,19 +49,19 @@
 
 ClientSocketPoolManager* CreateSocketPoolManager(
     HttpNetworkSession::SocketPoolType pool_type,
-    const HttpNetworkSession::Params& params,
+    const HttpNetworkSession::Context& context,
     const std::string& ssl_session_cache_shard) {
   // TODO(yutak): Differentiate WebSocket pool manager and allow more
   // simultaneous connections for WebSockets.
   return new ClientSocketPoolManagerImpl(
-      params.net_log,
-      params.client_socket_factory ? params.client_socket_factory
-                                   : ClientSocketFactory::GetDefaultFactory(),
-      params.socket_performance_watcher_factory, params.host_resolver,
-      params.cert_verifier, params.channel_id_service,
-      params.transport_security_state, params.cert_transparency_verifier,
-      params.ct_policy_enforcer, ssl_session_cache_shard,
-      params.ssl_config_service, pool_type);
+      context.net_log,
+      context.client_socket_factory ? context.client_socket_factory
+                                    : ClientSocketFactory::GetDefaultFactory(),
+      context.socket_performance_watcher_factory, context.host_resolver,
+      context.cert_verifier, context.channel_id_service,
+      context.transport_security_state, context.cert_transparency_verifier,
+      context.ct_policy_enforcer, ssl_session_cache_shard,
+      context.ssl_config_service, pool_type);
 }
 
 }  // unnamed namespace
@@ -97,19 +97,7 @@
 }  // unnamed namespace
 
 HttpNetworkSession::Params::Params()
-    : client_socket_factory(nullptr),
-      host_resolver(nullptr),
-      cert_verifier(nullptr),
-      enable_server_push_cancellation(false),
-      channel_id_service(nullptr),
-      transport_security_state(nullptr),
-      cert_transparency_verifier(nullptr),
-      ct_policy_enforcer(nullptr),
-      proxy_service(nullptr),
-      ssl_config_service(nullptr),
-      http_auth_handler_factory(nullptr),
-      net_log(nullptr),
-      socket_performance_watcher_factory(nullptr),
+    : enable_server_push_cancellation(false),
       ignore_certificate_errors(false),
       testing_fixed_http_port(0),
       testing_fixed_https_port(0),
@@ -122,10 +110,6 @@
       enable_http2_alternative_service(false),
       enable_quic(false),
       quic_max_packet_length(kDefaultMaxPacketSize),
-      quic_clock(nullptr),
-      quic_random(nullptr),
-      quic_crypto_client_stream_factory(
-          QuicCryptoClientStreamFactory::GetDefaultFactory()),
       quic_max_server_configs_stored_in_properties(0u),
       mark_quic_broken_when_network_blackholes(false),
       retry_without_alt_svc_on_quic_errors(false),
@@ -142,7 +126,6 @@
       quic_race_cert_verification(false),
       quic_do_not_fragment(false),
       quic_estimate_initial_rtt(false),
-      proxy_delegate(nullptr),
       enable_token_binding(false),
       http_09_on_non_default_ports_enabled(false) {
   quic_supported_versions.push_back(QUIC_VERSION_37);
@@ -152,33 +135,57 @@
 
 HttpNetworkSession::Params::~Params() {}
 
+HttpNetworkSession::Context::Context()
+    : client_socket_factory(nullptr),
+      host_resolver(nullptr),
+      cert_verifier(nullptr),
+      channel_id_service(nullptr),
+      transport_security_state(nullptr),
+      cert_transparency_verifier(nullptr),
+      ct_policy_enforcer(nullptr),
+      proxy_service(nullptr),
+      ssl_config_service(nullptr),
+      http_auth_handler_factory(nullptr),
+      net_log(nullptr),
+      socket_performance_watcher_factory(nullptr),
+      quic_clock(nullptr),
+      quic_random(nullptr),
+      quic_crypto_client_stream_factory(
+          QuicCryptoClientStreamFactory::GetDefaultFactory()),
+      proxy_delegate(nullptr) {}
+
+HttpNetworkSession::Context::Context(const Context& other) = default;
+
+HttpNetworkSession::Context::~Context() {}
+
 // TODO(mbelshe): Move the socket factories into HttpStreamFactory.
-HttpNetworkSession::HttpNetworkSession(const Params& params)
-    : net_log_(params.net_log),
-      http_server_properties_(params.http_server_properties),
-      cert_verifier_(params.cert_verifier),
-      http_auth_handler_factory_(params.http_auth_handler_factory),
-      proxy_service_(params.proxy_service),
-      ssl_config_service_(params.ssl_config_service),
+HttpNetworkSession::HttpNetworkSession(const Params& params,
+                                       const Context& context)
+    : net_log_(context.net_log),
+      http_server_properties_(context.http_server_properties),
+      cert_verifier_(context.cert_verifier),
+      http_auth_handler_factory_(context.http_auth_handler_factory),
+      proxy_service_(context.proxy_service),
+      ssl_config_service_(context.ssl_config_service),
       push_delegate_(nullptr),
       quic_stream_factory_(
-          params.net_log,
-          params.host_resolver,
-          params.ssl_config_service,
-          params.client_socket_factory
-              ? params.client_socket_factory
+          context.net_log,
+          context.host_resolver,
+          context.ssl_config_service,
+          context.client_socket_factory
+              ? context.client_socket_factory
               : ClientSocketFactory::GetDefaultFactory(),
-          params.http_server_properties,
-          params.cert_verifier,
-          params.ct_policy_enforcer,
-          params.channel_id_service,
-          params.transport_security_state,
-          params.cert_transparency_verifier,
-          params.socket_performance_watcher_factory,
-          params.quic_crypto_client_stream_factory,
-          params.quic_random ? params.quic_random : QuicRandom::GetInstance(),
-          params.quic_clock ? params.quic_clock
-                            : QuicChromiumClock::GetInstance(),
+          context.http_server_properties,
+          context.cert_verifier,
+          context.ct_policy_enforcer,
+          context.channel_id_service,
+          context.transport_security_state,
+          context.cert_transparency_verifier,
+          context.socket_performance_watcher_factory,
+          context.quic_crypto_client_stream_factory,
+          context.quic_random ? context.quic_random : QuicRandom::GetInstance(),
+          context.quic_clock ? context.quic_clock
+                             : QuicChromiumClock::GetInstance(),
           params.quic_max_packet_length,
           params.quic_user_agent_id,
           params.quic_supported_versions,
@@ -197,19 +204,20 @@
           params.quic_estimate_initial_rtt,
           params.quic_connection_options,
           params.enable_token_binding),
-      spdy_session_pool_(params.host_resolver,
-                         params.ssl_config_service,
-                         params.http_server_properties,
-                         params.transport_security_state,
+      spdy_session_pool_(context.host_resolver,
+                         context.ssl_config_service,
+                         context.http_server_properties,
+                         context.transport_security_state,
                          params.enable_spdy_ping_based_connection_checking,
                          params.spdy_session_max_recv_window_size,
                          AddDefaultHttp2Settings(params.http2_settings),
                          params.time_func,
-                         params.proxy_delegate),
+                         context.proxy_delegate),
       http_stream_factory_(new HttpStreamFactoryImpl(this, false)),
       http_stream_factory_for_websocket_(new HttpStreamFactoryImpl(this, true)),
       network_stream_throttler_(new NetworkThrottleManagerImpl()),
-      params_(params) {
+      params_(params),
+      context_(context) {
   DCHECK(proxy_service_);
   DCHECK(ssl_config_service_.get());
   CHECK(http_server_properties_);
@@ -217,9 +225,9 @@
   const std::string ssl_session_cache_shard =
       "http_network_session/" + base::IntToString(g_next_shard_id.GetNext());
   normal_socket_pool_manager_.reset(CreateSocketPoolManager(
-      NORMAL_SOCKET_POOL, params, ssl_session_cache_shard));
+      NORMAL_SOCKET_POOL, context, ssl_session_cache_shard));
   websocket_socket_pool_manager_.reset(CreateSocketPoolManager(
-      WEBSOCKET_SOCKET_POOL, params, ssl_session_cache_shard));
+      WEBSOCKET_SOCKET_POOL, context, ssl_session_cache_shard));
 
   if (params_.enable_http2) {
     next_protos_.push_back(kProtoHTTP2);
@@ -401,7 +409,7 @@
   *proxy_config = *server_config;
   if (request.privacy_mode == PRIVACY_MODE_ENABLED) {
     server_config->channel_id_enabled = false;
-  } else if (params_.enable_token_binding && params_.channel_id_service) {
+  } else if (params_.enable_token_binding && context_.channel_id_service) {
     server_config->token_binding_params.push_back(TB_PARAM_ECDSAP256);
   }
 }
diff --git a/net/http/http_network_session.h b/net/http/http_network_session.h
index 89234cb..9e4a484 100644
--- a/net/http/http_network_session.h
+++ b/net/http/http_network_session.h
@@ -78,26 +78,15 @@
     : NON_EXPORTED_BASE(public base::NonThreadSafe),
       public base::MemoryCoordinatorClient {
  public:
+  // Self-contained structure with all the simple configuration options
+  // supported by the HttpNetworkSession.
   struct NET_EXPORT Params {
     Params();
     Params(const Params& other);
     ~Params();
 
-    ClientSocketFactory* client_socket_factory;
-    HostResolver* host_resolver;
-    CertVerifier* cert_verifier;
     bool enable_server_push_cancellation;
-    ChannelIDService* channel_id_service;
-    TransportSecurityState* transport_security_state;
-    CTVerifier* cert_transparency_verifier;
-    CTPolicyEnforcer* ct_policy_enforcer;
-    ProxyService* proxy_service;
-    SSLConfigService* ssl_config_service;
-    HttpAuthHandlerFactory* http_auth_handler_factory;
-    HttpServerProperties* http_server_properties;
-    NetLog* net_log;
     HostMappingRules host_mapping_rules;
-    SocketPerformanceWatcherFactory* socket_performance_watcher_factory;
     bool ignore_certificate_errors;
     uint16_t testing_fixed_http_port;
     uint16_t testing_fixed_https_port;
@@ -127,12 +116,6 @@
     std::string quic_user_agent_id;
     // Limit on the size of QUIC packets.
     size_t quic_max_packet_length;
-    // Source of time for QUIC connections.
-    QuicClock* quic_clock;
-    // Source of entropy for QUIC connections.
-    QuicRandom* quic_random;
-    // Optional factory to use for creating QuicCryptoClientStreams.
-    QuicCryptoClientStreamFactory* quic_crypto_client_stream_factory;
     // Maximum number of server configs that are to be stored in
     // HttpServerProperties, instead of the disk cache.
     size_t quic_max_server_configs_stored_in_properties;
@@ -179,7 +162,6 @@
     // If true, estimate the initial RTT for QUIC connections based on network.
     bool quic_estimate_initial_rtt;
 
-    ProxyDelegate* proxy_delegate;
     // Enable support for Token Binding.
     bool enable_token_binding;
 
@@ -188,13 +170,44 @@
     bool http_09_on_non_default_ports_enabled;
   };
 
+  // Structure with pointers to the dependencies of the HttpNetworkSession.
+  // These objects must all outlive the HttpNetworkSession.
+  struct NET_EXPORT Context {
+    Context();
+    Context(const Context& other);
+    ~Context();
+
+    ClientSocketFactory* client_socket_factory;
+    HostResolver* host_resolver;
+    CertVerifier* cert_verifier;
+    ChannelIDService* channel_id_service;
+    TransportSecurityState* transport_security_state;
+    CTVerifier* cert_transparency_verifier;
+    CTPolicyEnforcer* ct_policy_enforcer;
+    ProxyService* proxy_service;
+    SSLConfigService* ssl_config_service;
+    HttpAuthHandlerFactory* http_auth_handler_factory;
+    HttpServerProperties* http_server_properties;
+    NetLog* net_log;
+    SocketPerformanceWatcherFactory* socket_performance_watcher_factory;
+
+    // Source of time for QUIC connections.
+    QuicClock* quic_clock;
+    // Source of entropy for QUIC connections.
+    QuicRandom* quic_random;
+    // Optional factory to use for creating QuicCryptoClientStreams.
+    QuicCryptoClientStreamFactory* quic_crypto_client_stream_factory;
+
+    ProxyDelegate* proxy_delegate;
+  };
+
   enum SocketPoolType {
     NORMAL_SOCKET_POOL,
     WEBSOCKET_SOCKET_POOL,
     NUM_SOCKET_POOL_TYPES
   };
 
-  explicit HttpNetworkSession(const Params& params);
+  HttpNetworkSession(const Params& params, const Context& context);
   ~HttpNetworkSession() override;
 
   HttpAuthCache* http_auth_cache() { return &http_auth_cache_; }
@@ -258,6 +271,8 @@
 
   // Returns the original Params used to construct this session.
   const Params& params() const { return params_; }
+  // Returns the original Context used to construct this session.
+  const Context& context() const { return context_; }
 
   bool IsProtocolEnabled(NextProto protocol) const;
 
@@ -320,6 +335,7 @@
   NextProtoVector next_protos_;
 
   Params params_;
+  Context context_;
 
   std::unique_ptr<base::MemoryPressureListener> memory_pressure_listener_;
 };
diff --git a/net/http/http_network_transaction.cc b/net/http/http_network_transaction.cc
index e29b01d4..32aa872 100644
--- a/net/http/http_network_transaction.cc
+++ b/net/http/http_network_transaction.cc
@@ -610,7 +610,7 @@
   stream_->GetSSLInfo(&ssl_info);
   return ssl_info.token_binding_negotiated &&
          ssl_info.token_binding_key_param == TB_PARAM_ECDSAP256 &&
-         session_->params().channel_id_service;
+         session_->context().channel_id_service;
 }
 
 void HttpNetworkTransaction::RecordTokenBindingSupport() const {
@@ -628,7 +628,7 @@
   stream_->GetSSLInfo(&ssl_info);
   if (!session_->params().enable_token_binding) {
     supported = DISABLED;
-  } else if (!session_->params().channel_id_service) {
+  } else if (!session_->context().channel_id_service) {
     supported = CLIENT_NO_CHANNEL_ID_SERVICE;
   } else if (ssl_info.token_binding_negotiated) {
     supported = CLIENT_AND_SERVER;
@@ -969,7 +969,7 @@
     return OK;
 
   net_log_.BeginEvent(NetLogEventType::HTTP_TRANSACTION_GET_TOKEN_BINDING_KEY);
-  ChannelIDService* channel_id_service = session_->params().channel_id_service;
+  ChannelIDService* channel_id_service = session_->context().channel_id_service;
   return channel_id_service->GetOrCreateChannelID(
       request_->url.host(), &provided_token_binding_key_, io_callback_,
       &token_binding_request_);
@@ -993,7 +993,7 @@
     return OK;
 
   net_log_.BeginEvent(NetLogEventType::HTTP_TRANSACTION_GET_TOKEN_BINDING_KEY);
-  ChannelIDService* channel_id_service = session_->params().channel_id_service;
+  ChannelIDService* channel_id_service = session_->context().channel_id_service;
   return channel_id_service->GetOrCreateChannelID(
       request_->token_binding_referrer, &referred_token_binding_key_,
       io_callback_, &token_binding_request_);
diff --git a/net/http/http_network_transaction_ssl_unittest.cc b/net/http/http_network_transaction_ssl_unittest.cc
index b412bbe..2bd3edd 100644
--- a/net/http/http_network_transaction_ssl_unittest.cc
+++ b/net/http/http_network_transaction_ssl_unittest.cc
@@ -59,21 +59,21 @@
 
   void SetUp() override {
     ssl_config_service_ = new TokenBindingSSLConfigService;
-    session_params_.ssl_config_service = ssl_config_service_.get();
+    session_context_.ssl_config_service = ssl_config_service_.get();
 
     auth_handler_factory_.reset(new HttpAuthHandlerMock::Factory());
-    session_params_.http_auth_handler_factory = auth_handler_factory_.get();
+    session_context_.http_auth_handler_factory = auth_handler_factory_.get();
 
     proxy_service_ = ProxyService::CreateDirect();
-    session_params_.proxy_service = proxy_service_.get();
+    session_context_.proxy_service = proxy_service_.get();
 
-    session_params_.client_socket_factory = &mock_socket_factory_;
-    session_params_.host_resolver = &mock_resolver_;
-    session_params_.http_server_properties = &http_server_properties_;
-    session_params_.cert_verifier = &cert_verifier_;
-    session_params_.transport_security_state = &transport_security_state_;
-    session_params_.cert_transparency_verifier = &ct_verifier_;
-    session_params_.ct_policy_enforcer = &ct_policy_enforcer_;
+    session_context_.client_socket_factory = &mock_socket_factory_;
+    session_context_.host_resolver = &mock_resolver_;
+    session_context_.http_server_properties = &http_server_properties_;
+    session_context_.cert_verifier = &cert_verifier_;
+    session_context_.transport_security_state = &transport_security_state_;
+    session_context_.cert_transparency_verifier = &ct_verifier_;
+    session_context_.ct_policy_enforcer = &ct_policy_enforcer_;
   }
 
   HttpRequestInfo* GetRequestInfo(const std::string& url) {
@@ -95,14 +95,14 @@
   TransportSecurityState transport_security_state_;
   MultiLogCTVerifier ct_verifier_;
   CTPolicyEnforcer ct_policy_enforcer_;
-  HttpNetworkSession::Params session_params_;
+  HttpNetworkSession::Context session_context_;
   std::vector<std::unique_ptr<HttpRequestInfo>> request_info_vector_;
 };
 
 #if !defined(OS_IOS)
 TEST_F(HttpNetworkTransactionSSLTest, TokenBinding) {
   ChannelIDService channel_id_service(new DefaultChannelIDStore(NULL));
-  session_params_.channel_id_service = &channel_id_service;
+  session_context_.channel_id_service = &channel_id_service;
 
   SSLSocketDataProvider ssl_data(ASYNC, OK);
   ssl_data.token_binding_negotiated = true;
@@ -113,7 +113,7 @@
   StaticSocketDataProvider data(mock_reads, arraysize(mock_reads), NULL, 0);
   mock_socket_factory_.AddSocketDataProvider(&data);
 
-  HttpNetworkSession session(session_params_);
+  HttpNetworkSession session(HttpNetworkSession::Params(), session_context_);
   HttpNetworkTransaction trans1(DEFAULT_PRIORITY, &session);
 
   TestCompletionCallback callback;
@@ -151,7 +151,7 @@
 
 TEST_F(HttpNetworkTransactionSSLTest, NoTokenBindingOverHttp) {
   ChannelIDService channel_id_service(new DefaultChannelIDStore(NULL));
-  session_params_.channel_id_service = &channel_id_service;
+  session_context_.channel_id_service = &channel_id_service;
 
   SSLSocketDataProvider ssl_data(ASYNC, OK);
   ssl_data.token_binding_negotiated = true;
@@ -162,7 +162,7 @@
   StaticSocketDataProvider data(mock_reads, arraysize(mock_reads), NULL, 0);
   mock_socket_factory_.AddSocketDataProvider(&data);
 
-  HttpNetworkSession session(session_params_);
+  HttpNetworkSession session(HttpNetworkSession::Params(), session_context_);
   HttpNetworkTransaction trans(DEFAULT_PRIORITY, &session);
 
   TestCompletionCallback callback;
@@ -188,7 +188,7 @@
       new base::DeferredSequencedTaskRunner(channel_id_thread.task_runner());
   ChannelIDService channel_id_service(new DefaultChannelIDStore(nullptr));
   channel_id_service.set_task_runner_for_testing(channel_id_runner);
-  session_params_.channel_id_service = &channel_id_service;
+  session_context_.channel_id_service = &channel_id_service;
 
   SSLSocketDataProvider ssl_data(ASYNC, OK);
   ssl_data.token_binding_negotiated = true;
@@ -205,7 +205,7 @@
   request_info.method = "GET";
   request_info.token_binding_referrer = "encrypted.example.com";
 
-  HttpNetworkSession session(session_params_);
+  HttpNetworkSession session(HttpNetworkSession::Params(), session_context_);
   HttpNetworkTransaction trans(DEFAULT_PRIORITY, &session);
 
   TestCompletionCallback callback;
diff --git a/net/http/http_response_body_drainer_unittest.cc b/net/http/http_response_body_drainer_unittest.cc
index 44943e29..a02ed66 100644
--- a/net/http/http_response_body_drainer_unittest.cc
+++ b/net/http/http_response_body_drainer_unittest.cc
@@ -245,15 +245,15 @@
   ~HttpResponseBodyDrainerTest() override {}
 
   HttpNetworkSession* CreateNetworkSession() {
-    HttpNetworkSession::Params params;
-    params.proxy_service = proxy_service_.get();
-    params.ssl_config_service = ssl_config_service_.get();
-    params.http_server_properties = http_server_properties_.get();
-    params.cert_verifier = &cert_verifier_;
-    params.transport_security_state = &transport_security_state_;
-    params.cert_transparency_verifier = &ct_verifier_;
-    params.ct_policy_enforcer = &ct_policy_enforcer_;
-    return new HttpNetworkSession(params);
+    HttpNetworkSession::Context context;
+    context.proxy_service = proxy_service_.get();
+    context.ssl_config_service = ssl_config_service_.get();
+    context.http_server_properties = http_server_properties_.get();
+    context.cert_verifier = &cert_verifier_;
+    context.transport_security_state = &transport_security_state_;
+    context.cert_transparency_verifier = &ct_verifier_;
+    context.ct_policy_enforcer = &ct_policy_enforcer_;
+    return new HttpNetworkSession(HttpNetworkSession::Params(), context);
   }
 
   std::unique_ptr<ProxyService> proxy_service_;
diff --git a/net/http/http_stream_factory_impl_job.cc b/net/http/http_stream_factory_impl_job.cc
index e3ca09e..544e28d 100644
--- a/net/http/http_stream_factory_impl_job.cc
+++ b/net/http/http_stream_factory_impl_job.cc
@@ -785,7 +785,7 @@
 
   return session_->proxy_service()->ResolveProxy(
       origin_url_, request_info_.method, &proxy_info_, io_callback_,
-      &pac_request_, session_->params().proxy_delegate, net_log_);
+      &pac_request_, session_->context().proxy_delegate, net_log_);
 }
 
 int HttpStreamFactoryImpl::Job::DoResolveProxyComplete(int result) {
@@ -1213,7 +1213,7 @@
   if (using_ssl_ && connection_->socket()) {
     SSLClientSocket* ssl_socket =
         static_cast<SSLClientSocket*>(connection_->socket());
-    RecordChannelIDKeyMatch(ssl_socket, session_->params().channel_id_service,
+    RecordChannelIDKeyMatch(ssl_socket, session_->context().channel_id_service,
                             destination_.HostForURL());
   }
 
@@ -1305,7 +1305,7 @@
     return result;
 
   session_->proxy_service()->ReportSuccess(proxy_info_,
-                                           session_->params().proxy_delegate);
+                                           session_->context().proxy_delegate);
   next_state_ = STATE_NONE;
   return OK;
 }
@@ -1485,7 +1485,8 @@
 
   int rv = session_->proxy_service()->ReconsiderProxyAfterError(
       request_info_.url, request_info_.method, error, &proxy_info_,
-      io_callback_, &pac_request_, session_->params().proxy_delegate, net_log_);
+      io_callback_, &pac_request_, session_->context().proxy_delegate,
+      net_log_);
   if (rv == OK || rv == ERR_IO_PENDING) {
     // If the error was during connection setup, there is no socket to
     // disconnect.
diff --git a/net/http/http_stream_factory_impl_job_controller.cc b/net/http/http_stream_factory_impl_job_controller.cc
index 986f9a3..6cbd700 100644
--- a/net/http/http_stream_factory_impl_job_controller.cc
+++ b/net/http/http_stream_factory_impl_job_controller.cc
@@ -869,7 +869,7 @@
   }
 
   if (failed_alternative_proxy_server_.is_valid()) {
-    ProxyDelegate* proxy_delegate = session_->params().proxy_delegate;
+    ProxyDelegate* proxy_delegate = session_->context().proxy_delegate;
     if (proxy_delegate) {
       proxy_delegate->OnAlternativeProxyBroken(
           failed_alternative_proxy_server_);
@@ -1081,7 +1081,7 @@
     return false;
   }
 
-  ProxyDelegate* proxy_delegate = session_->params().proxy_delegate;
+  ProxyDelegate* proxy_delegate = session_->context().proxy_delegate;
   if (!proxy_delegate)
     return false;
 
diff --git a/net/http/http_stream_factory_impl_unittest.cc b/net/http/http_stream_factory_impl_unittest.cc
index f7dc841f..a994f8f5 100644
--- a/net/http/http_stream_factory_impl_unittest.cc
+++ b/net/http/http_stream_factory_impl_unittest.cc
@@ -713,28 +713,31 @@
     proxy_service =
         ProxyService::CreateFixedFromPacResult("QUIC bad:99; DIRECT");
 
-    HttpNetworkSession::Params params;
-    params.enable_quic = true;
+    HttpNetworkSession::Params session_params;
+    session_params.enable_quic = true;
+
+    HttpNetworkSession::Context session_context;
     scoped_refptr<SSLConfigServiceDefaults> ssl_config_service(
         new SSLConfigServiceDefaults);
     HttpServerPropertiesImpl http_server_properties;
     MockClientSocketFactory socket_factory;
-    params.client_socket_factory = &socket_factory;
+    session_context.client_socket_factory = &socket_factory;
     MockHostResolver host_resolver;
-    params.host_resolver = &host_resolver;
+    session_context.host_resolver = &host_resolver;
     MockCertVerifier cert_verifier;
-    params.cert_verifier = &cert_verifier;
+    session_context.cert_verifier = &cert_verifier;
     TransportSecurityState transport_security_state;
-    params.transport_security_state = &transport_security_state;
+    session_context.transport_security_state = &transport_security_state;
     MultiLogCTVerifier ct_verifier;
-    params.cert_transparency_verifier = &ct_verifier;
+    session_context.cert_transparency_verifier = &ct_verifier;
     CTPolicyEnforcer ct_policy_enforcer;
-    params.ct_policy_enforcer = &ct_policy_enforcer;
-    params.proxy_service = proxy_service.get();
-    params.ssl_config_service = ssl_config_service.get();
-    params.http_server_properties = &http_server_properties;
+    session_context.ct_policy_enforcer = &ct_policy_enforcer;
+    session_context.proxy_service = proxy_service.get();
+    session_context.ssl_config_service = ssl_config_service.get();
+    session_context.http_server_properties = &http_server_properties;
 
-    auto session = base::MakeUnique<HttpNetworkSession>(params);
+    auto session =
+        base::MakeUnique<HttpNetworkSession>(session_params, session_context);
     session->quic_stream_factory()->set_require_confirmation(false);
 
     StaticSocketDataProvider socket_data1;
@@ -838,7 +841,8 @@
 };
 
 void SetupForQuicAlternativeProxyTest(
-    HttpNetworkSession::Params* params,
+    HttpNetworkSession::Params* session_params,
+    HttpNetworkSession::Context* session_context,
     MockClientSocketFactory* socket_factory,
     ProxyService* proxy_service,
     TestProxyDelegate* test_proxy_delegate,
@@ -850,22 +854,23 @@
     MockHostResolver* host_resolver,
     TransportSecurityState* transport_security_state,
     bool set_alternative_proxy_server) {
-  params->enable_quic = true;
-  params->client_socket_factory = socket_factory;
-  params->host_resolver = host_resolver;
-  params->transport_security_state = transport_security_state;
-  params->proxy_service = proxy_service;
-  params->ssl_config_service = ssl_config_service;
-  params->http_server_properties = http_server_properties;
-  params->cert_verifier = cert_verifier;
-  params->ct_policy_enforcer = ct_policy_enforcer;
-  params->cert_transparency_verifier = ct_verifier;
+  session_params->enable_quic = true;
+
+  session_context->client_socket_factory = socket_factory;
+  session_context->host_resolver = host_resolver;
+  session_context->transport_security_state = transport_security_state;
+  session_context->proxy_service = proxy_service;
+  session_context->ssl_config_service = ssl_config_service;
+  session_context->http_server_properties = http_server_properties;
+  session_context->cert_verifier = cert_verifier;
+  session_context->ct_policy_enforcer = ct_policy_enforcer;
+  session_context->cert_transparency_verifier = ct_verifier;
 
   if (set_alternative_proxy_server) {
     test_proxy_delegate->set_alternative_proxy_server(
         ProxyServer::FromPacString("QUIC badproxy:99"));
   }
-  params->proxy_delegate = test_proxy_delegate;
+  session_context->proxy_delegate = test_proxy_delegate;
 }
 
 }  // namespace
@@ -881,7 +886,8 @@
   for (auto mock_error : quic_proxy_test_mock_errors) {
     for (auto set_alternative_proxy_server :
          set_alternative_proxy_server_values) {
-      HttpNetworkSession::Params params;
+      HttpNetworkSession::Params session_params;
+      HttpNetworkSession::Context session_context;
       MockClientSocketFactory socket_factory;
       std::unique_ptr<ProxyService> proxy_service =
           ProxyService::CreateFixedFromPacResult(
@@ -896,12 +902,14 @@
       MockHostResolver host_resolver;
       TransportSecurityState transport_security_state;
       SetupForQuicAlternativeProxyTest(
-          &params, &socket_factory, proxy_service.get(), &test_proxy_delegate,
-          &http_server_properties, &cert_verifier, &ct_policy_enforcer,
-          &ct_verifier, ssl_config_service.get(), &host_resolver,
-          &transport_security_state, set_alternative_proxy_server);
+          &session_params, &session_context, &socket_factory,
+          proxy_service.get(), &test_proxy_delegate, &http_server_properties,
+          &cert_verifier, &ct_policy_enforcer, &ct_verifier,
+          ssl_config_service.get(), &host_resolver, &transport_security_state,
+          set_alternative_proxy_server);
 
-      auto session = base::MakeUnique<HttpNetworkSession>(params);
+      auto session =
+          base::MakeUnique<HttpNetworkSession>(session_params, session_context);
 
       // Before starting the test, verify that there are no proxies marked as
       // bad.
@@ -999,7 +1007,8 @@
 // not marked as bad if only the alternative proxy server job fails.
 TEST_F(HttpStreamFactoryTest, WithQUICAlternativeProxyNotMarkedAsBad) {
   for (auto mock_error : quic_proxy_test_mock_errors) {
-    HttpNetworkSession::Params params;
+    HttpNetworkSession::Params session_params;
+    HttpNetworkSession::Context session_context;
     MockClientSocketFactory socket_factory;
     std::unique_ptr<ProxyService> proxy_service =
         ProxyService::CreateFixedFromPacResult("HTTPS badproxy:99; DIRECT");
@@ -1015,13 +1024,14 @@
     TransportSecurityState transport_security_state;
 
     SetupForQuicAlternativeProxyTest(
-        &params, &socket_factory, proxy_service.get(), &test_proxy_delegate,
-        &http_server_properties, &cert_verifier, &ct_policy_enforcer,
-        &ct_verifier, ssl_config_service.get(), &host_resolver,
-        &transport_security_state, true);
+        &session_params, &session_context, &socket_factory, proxy_service.get(),
+        &test_proxy_delegate, &http_server_properties, &cert_verifier,
+        &ct_policy_enforcer, &ct_verifier, ssl_config_service.get(),
+        &host_resolver, &transport_security_state, true);
 
     HostPortPair host_port_pair("badproxy", 99);
-    auto session = base::MakeUnique<HttpNetworkSession>(params);
+    auto session =
+        base::MakeUnique<HttpNetworkSession>(session_params, session_context);
 
     // Before starting the test, verify that there are no proxies marked as
     // bad.
@@ -1113,12 +1123,16 @@
         ProxyService::CreateFixed("http_proxy"));
 
     // Setup params to disable preconnect, but QUIC doesn't 0RTT.
-    HttpNetworkSession::Params params =
+    HttpNetworkSession::Params session_params =
         SpdySessionDependencies::CreateSessionParams(&session_deps);
-    params.enable_quic = true;
-    params.http_server_properties = &http_server_properties;
+    session_params.enable_quic = true;
 
-    auto session = base::MakeUnique<HttpNetworkSession>(params);
+    HttpNetworkSession::Context session_context =
+        SpdySessionDependencies::CreateSessionContext(&session_deps);
+    session_context.http_server_properties = &http_server_properties;
+
+    auto session =
+        base::MakeUnique<HttpNetworkSession>(session_params, session_context);
     HttpNetworkSessionPeer peer(session.get());
     HostPortPair proxy_host("http_proxy", 80);
     CapturePreconnectsHttpProxySocketPool* http_proxy_pool =
@@ -1162,13 +1176,17 @@
       }
 
       SpdySessionDependencies session_deps;
-      HttpNetworkSession::Params params =
+      HttpNetworkSession::Params session_params =
           SpdySessionDependencies::CreateSessionParams(&session_deps);
-      params.enable_quic = true;
-      params.proxy_service = proxy_service.get();
-      params.http_server_properties = &http_server_properties;
+      session_params.enable_quic = true;
 
-      auto session = base::MakeUnique<HttpNetworkSession>(params);
+      HttpNetworkSession::Context session_context =
+          SpdySessionDependencies::CreateSessionContext(&session_deps);
+      session_context.proxy_service = proxy_service.get();
+      session_context.http_server_properties = &http_server_properties;
+
+      auto session =
+          base::MakeUnique<HttpNetworkSession>(session_params, session_context);
 
       HttpNetworkSessionPeer peer(session.get());
       HostPortPair proxy_host("myproxy.org", 443);
@@ -1250,13 +1268,17 @@
   http_server_properties.SetSupportsSpdy(spdy_server, true);
 
   SpdySessionDependencies session_deps;
-  HttpNetworkSession::Params params =
+  HttpNetworkSession::Params session_params =
       SpdySessionDependencies::CreateSessionParams(&session_deps);
-  params.enable_quic = true;
-  params.proxy_service = proxy_service.get();
-  params.http_server_properties = &http_server_properties;
+  session_params.enable_quic = true;
 
-  auto session = base::MakeUnique<HttpNetworkSession>(params);
+  HttpNetworkSession::Context session_context =
+      SpdySessionDependencies::CreateSessionContext(&session_deps);
+  session_context.proxy_service = proxy_service.get();
+  session_context.http_server_properties = &http_server_properties;
+
+  auto session =
+      base::MakeUnique<HttpNetworkSession>(session_params, session_context);
 
   HttpNetworkSessionPeer peer(session.get());
   HostPortPair proxy_host("myproxy.org", 443);
@@ -2152,9 +2174,12 @@
 
   void Initialize() {
     params_.enable_quic = true;
-    params_.http_server_properties = &http_server_properties_;
-    params_.quic_random = &random_generator_;
-    params_.quic_clock = &clock_;
+    params_.quic_supported_versions = test::SupportedVersions(GetParam());
+
+    HttpNetworkSession::Context session_context;
+    session_context.http_server_properties = &http_server_properties_;
+    session_context.quic_random = &random_generator_;
+    session_context.quic_clock = &clock_;
 
     // Load a certificate that is valid for *.example.org
     scoped_refptr<X509Certificate> test_cert(
@@ -2165,17 +2190,17 @@
     crypto_client_stream_factory_.AddProofVerifyDetails(&verify_details_);
     crypto_client_stream_factory_.set_handshake_mode(
         MockCryptoClientStream::CONFIRM_HANDSHAKE);
-    params_.cert_verifier = &cert_verifier_;
-    params_.quic_crypto_client_stream_factory = &crypto_client_stream_factory_;
-    params_.quic_supported_versions = test::SupportedVersions(GetParam());
-    params_.transport_security_state = &transport_security_state_;
-    params_.cert_transparency_verifier = &ct_verifier_;
-    params_.ct_policy_enforcer = &ct_policy_enforcer_;
-    params_.host_resolver = &host_resolver_;
-    params_.proxy_service = proxy_service_.get();
-    params_.ssl_config_service = ssl_config_service_.get();
-    params_.client_socket_factory = &socket_factory_;
-    session_ = base::MakeUnique<HttpNetworkSession>(params_);
+    session_context.cert_verifier = &cert_verifier_;
+    session_context.quic_crypto_client_stream_factory =
+        &crypto_client_stream_factory_;
+    session_context.transport_security_state = &transport_security_state_;
+    session_context.cert_transparency_verifier = &ct_verifier_;
+    session_context.ct_policy_enforcer = &ct_policy_enforcer_;
+    session_context.host_resolver = &host_resolver_;
+    session_context.proxy_service = proxy_service_.get();
+    session_context.ssl_config_service = ssl_config_service_.get();
+    session_context.client_socket_factory = &socket_factory_;
+    session_.reset(new HttpNetworkSession(params_, session_context));
     session_->quic_stream_factory()->set_require_confirmation(false);
   }
 
diff --git a/net/nqe/network_quality_estimator_unittest.cc b/net/nqe/network_quality_estimator_unittest.cc
index fe4d359..4f7941ed 100644
--- a/net/nqe/network_quality_estimator_unittest.cc
+++ b/net/nqe/network_quality_estimator_unittest.cc
@@ -2157,12 +2157,12 @@
   TestURLRequestContext context(true);
   context.set_network_quality_estimator(&estimator);
 
-  std::unique_ptr<HttpNetworkSession::Params> params(
-      new HttpNetworkSession::Params);
+  std::unique_ptr<HttpNetworkSession::Context> session_context(
+      new HttpNetworkSession::Context);
   // |estimator| should be notified of TCP RTT observations.
-  params->socket_performance_watcher_factory =
+  session_context->socket_performance_watcher_factory =
       estimator.GetSocketPerformanceWatcherFactory();
-  context.set_http_network_session_params(std::move(params));
+  context.set_http_network_session_context(std::move(session_context));
   context.Init();
 
   EXPECT_EQ(0U, rtt_observer.observations().size());
diff --git a/net/proxy/proxy_script_fetcher_impl_unittest.cc b/net/proxy/proxy_script_fetcher_impl_unittest.cc
index a57e0de..d46909c 100644
--- a/net/proxy/proxy_script_fetcher_impl_unittest.cc
+++ b/net/proxy/proxy_script_fetcher_impl_unittest.cc
@@ -93,17 +93,17 @@
     storage_.set_http_server_properties(
         std::unique_ptr<HttpServerProperties>(new HttpServerPropertiesImpl()));
 
-    HttpNetworkSession::Params params;
-    params.host_resolver = host_resolver();
-    params.cert_verifier = cert_verifier();
-    params.transport_security_state = transport_security_state();
-    params.cert_transparency_verifier = cert_transparency_verifier();
-    params.ct_policy_enforcer = ct_policy_enforcer();
-    params.proxy_service = proxy_service();
-    params.ssl_config_service = ssl_config_service();
-    params.http_server_properties = http_server_properties();
-    storage_.set_http_network_session(
-        base::MakeUnique<HttpNetworkSession>(params));
+    HttpNetworkSession::Context session_context;
+    session_context.host_resolver = host_resolver();
+    session_context.cert_verifier = cert_verifier();
+    session_context.transport_security_state = transport_security_state();
+    session_context.cert_transparency_verifier = cert_transparency_verifier();
+    session_context.ct_policy_enforcer = ct_policy_enforcer();
+    session_context.proxy_service = proxy_service();
+    session_context.ssl_config_service = ssl_config_service();
+    session_context.http_server_properties = http_server_properties();
+    storage_.set_http_network_session(base::MakeUnique<HttpNetworkSession>(
+        HttpNetworkSession::Params(), session_context));
     storage_.set_http_transaction_factory(base::MakeUnique<HttpCache>(
         storage_.http_network_session(), HttpCache::DefaultBackend::InMemory(0),
         false));
diff --git a/net/quic/chromium/quic_end_to_end_unittest.cc b/net/quic/chromium/quic_end_to_end_unittest.cc
index 7fb9618..3cc1c9ed 100644
--- a/net/quic/chromium/quic_end_to_end_unittest.cc
+++ b/net/quic/chromium/quic_end_to_end_unittest.cc
@@ -56,8 +56,10 @@
 // Factory for creating HttpTransactions, used by TestTransactionConsumer.
 class TestTransactionFactory : public HttpTransactionFactory {
  public:
-  explicit TestTransactionFactory(const HttpNetworkSession::Params& params)
-      : session_(new HttpNetworkSession(params)) {}
+  explicit TestTransactionFactory(
+      const HttpNetworkSession::Params& session_params,
+      const HttpNetworkSession::Context& session_context)
+      : session_(new HttpNetworkSession(session_params, session_context)) {}
 
   ~TestTransactionFactory() override {}
 
@@ -108,23 +110,25 @@
     request_.url = GURL("https://test.example.com/");
     request_.load_flags = 0;
 
-    params_.enable_quic = true;
-    params_.quic_random = nullptr;
+    session_params_.enable_quic = true;
     if (GetParam().use_stateless_rejects) {
-      params_.quic_connection_options.push_back(kSREJ);
+      session_params_.quic_connection_options.push_back(kSREJ);
     }
-    params_.host_resolver = &host_resolver_;
-    params_.cert_verifier = &cert_verifier_;
-    params_.transport_security_state = &transport_security_state_;
-    params_.cert_transparency_verifier = cert_transparency_verifier_.get();
-    params_.ct_policy_enforcer = &ct_policy_enforcer_;
-    params_.proxy_service = proxy_service_.get();
-    params_.ssl_config_service = ssl_config_service_.get();
-    params_.http_auth_handler_factory = auth_handler_factory_.get();
-    params_.http_server_properties = &http_server_properties_;
+
+    session_context_.quic_random = nullptr;
+    session_context_.host_resolver = &host_resolver_;
+    session_context_.cert_verifier = &cert_verifier_;
+    session_context_.transport_security_state = &transport_security_state_;
+    session_context_.cert_transparency_verifier =
+        cert_transparency_verifier_.get();
+    session_context_.ct_policy_enforcer = &ct_policy_enforcer_;
+    session_context_.proxy_service = proxy_service_.get();
+    session_context_.ssl_config_service = ssl_config_service_.get();
+    session_context_.http_auth_handler_factory = auth_handler_factory_.get();
+    session_context_.http_server_properties = &http_server_properties_;
     channel_id_service_.reset(
         new ChannelIDService(new DefaultChannelIDStore(nullptr)));
-    params_.channel_id_service = channel_id_service_.get();
+    session_context_.channel_id_service = channel_id_service_.get();
 
     CertVerifyResult verify_result;
     verify_result.verified_cert = ImportCertFromFile(
@@ -158,10 +162,11 @@
 
     // To simplify the test, and avoid the race with the HTTP request, we force
     // QUIC for these requests.
-    params_.origins_to_force_quic_on.insert(
+    session_params_.origins_to_force_quic_on.insert(
         HostPortPair::FromString("test.example.com:443"));
 
-    transaction_factory_.reset(new TestTransactionFactory(params_));
+    transaction_factory_.reset(
+        new TestTransactionFactory(session_params_, session_context_));
   }
 
   void TearDown() override {}
@@ -239,7 +244,8 @@
   std::unique_ptr<ProxyService> proxy_service_;
   std::unique_ptr<HttpAuthHandlerFactory> auth_handler_factory_;
   HttpServerPropertiesImpl http_server_properties_;
-  HttpNetworkSession::Params params_;
+  HttpNetworkSession::Params session_params_;
+  HttpNetworkSession::Context session_context_;
   std::unique_ptr<TestTransactionFactory> transaction_factory_;
   HttpRequestInfo request_;
   std::string request_body_;
@@ -275,8 +281,9 @@
 
 TEST_P(QuicEndToEndTest, TokenBinding) {
   // Enable token binding and re-initialize the TestTransactionFactory.
-  params_.enable_token_binding = true;
-  transaction_factory_.reset(new TestTransactionFactory(params_));
+  session_params_.enable_token_binding = true;
+  transaction_factory_.reset(
+      new TestTransactionFactory(session_params_, session_context_));
 
   AddToCache(request_.url.PathForRequest(), 200, "OK", kResponseBody);
 
diff --git a/net/quic/chromium/quic_network_transaction_unittest.cc b/net/quic/chromium/quic_network_transaction_unittest.cc
index 570bfaad..1762682 100644
--- a/net/quic/chromium/quic_network_transaction_unittest.cc
+++ b/net/quic/chromium/quic_network_transaction_unittest.cc
@@ -500,26 +500,29 @@
   }
 
   void CreateSession() {
-    params_.enable_quic = true;
-    params_.quic_clock = &clock_;
-    params_.quic_random = &random_generator_;
-    params_.client_socket_factory = &socket_factory_;
-    params_.quic_crypto_client_stream_factory = &crypto_client_stream_factory_;
-    params_.host_resolver = &host_resolver_;
-    params_.cert_verifier = &cert_verifier_;
-    params_.transport_security_state = &transport_security_state_;
-    params_.cert_transparency_verifier = cert_transparency_verifier_.get();
-    params_.ct_policy_enforcer = &ct_policy_enforcer_;
-    params_.socket_performance_watcher_factory =
-        &test_socket_performance_watcher_factory_;
-    params_.proxy_service = proxy_service_.get();
-    params_.ssl_config_service = ssl_config_service_.get();
-    params_.http_auth_handler_factory = auth_handler_factory_.get();
-    params_.http_server_properties = &http_server_properties_;
-    params_.quic_supported_versions = SupportedVersions(version_);
-    params_.net_log = net_log_.bound().net_log();
+    session_params_.enable_quic = true;
+    session_params_.quic_supported_versions = SupportedVersions(version_);
 
-    session_.reset(new HttpNetworkSession(params_));
+    session_context_.quic_clock = &clock_;
+    session_context_.quic_random = &random_generator_;
+    session_context_.client_socket_factory = &socket_factory_;
+    session_context_.quic_crypto_client_stream_factory =
+        &crypto_client_stream_factory_;
+    session_context_.host_resolver = &host_resolver_;
+    session_context_.cert_verifier = &cert_verifier_;
+    session_context_.transport_security_state = &transport_security_state_;
+    session_context_.cert_transparency_verifier =
+        cert_transparency_verifier_.get();
+    session_context_.ct_policy_enforcer = &ct_policy_enforcer_;
+    session_context_.socket_performance_watcher_factory =
+        &test_socket_performance_watcher_factory_;
+    session_context_.proxy_service = proxy_service_.get();
+    session_context_.ssl_config_service = ssl_config_service_.get();
+    session_context_.http_auth_handler_factory = auth_handler_factory_.get();
+    session_context_.http_server_properties = &http_server_properties_;
+    session_context_.net_log = net_log_.bound().net_log();
+
+    session_.reset(new HttpNetworkSession(session_params_, session_context_));
     session_->quic_stream_factory()->set_require_confirmation(false);
   }
 
@@ -697,7 +700,7 @@
     test_proxy_delegate.set_alternative_proxy_server(
         ProxyServer::FromPacString("QUIC myproxy.org:443"));
 
-    params_.proxy_delegate = &test_proxy_delegate;
+    session_context_.proxy_delegate = &test_proxy_delegate;
     proxy_service_ =
         ProxyService::CreateFixedFromPacResult("HTTPS myproxy.org:443");
 
@@ -747,7 +750,8 @@
   std::unique_ptr<HttpAuthHandlerFactory> auth_handler_factory_;
   MockRandom random_generator_;
   HttpServerPropertiesImpl http_server_properties_;
-  HttpNetworkSession::Params params_;
+  HttpNetworkSession::Params session_params_;
+  HttpNetworkSession::Context session_context_;
   HttpRequestInfo request_;
   BoundTestNetLog net_log_;
   std::vector<std::unique_ptr<StaticSocketDataProvider>> hanging_data_;
@@ -781,7 +785,7 @@
                         ::testing::ValuesIn(AllSupportedVersions()));
 
 TEST_P(QuicNetworkTransactionTest, SocketWatcherEnabled) {
-  params_.origins_to_force_quic_on.insert(
+  session_params_.origins_to_force_quic_on.insert(
       HostPortPair::FromString("mail.example.org:443"));
 
   MockQuicData mock_quic_data;
@@ -812,7 +816,7 @@
 }
 
 TEST_P(QuicNetworkTransactionTest, SocketWatcherDisabled) {
-  params_.origins_to_force_quic_on.insert(
+  session_params_.origins_to_force_quic_on.insert(
       HostPortPair::FromString("mail.example.org:443"));
 
   MockQuicData mock_quic_data;
@@ -843,7 +847,7 @@
 }
 
 TEST_P(QuicNetworkTransactionTest, ForceQuic) {
-  params_.origins_to_force_quic_on.insert(
+  session_params_.origins_to_force_quic_on.insert(
       HostPortPair::FromString("mail.example.org:443"));
 
   MockQuicData mock_quic_data;
@@ -907,7 +911,7 @@
 }
 
 TEST_P(QuicNetworkTransactionTest, LargeResponseHeaders) {
-  params_.origins_to_force_quic_on.insert(
+  session_params_.origins_to_force_quic_on.insert(
       HostPortPair::FromString("mail.example.org:443"));
 
   MockQuicData mock_quic_data;
@@ -957,7 +961,7 @@
 }
 
 TEST_P(QuicNetworkTransactionTest, TooLargeResponseHeaders) {
-  params_.origins_to_force_quic_on.insert(
+  session_params_.origins_to_force_quic_on.insert(
       HostPortPair::FromString("mail.example.org:443"));
 
   MockQuicData mock_quic_data;
@@ -1013,7 +1017,7 @@
 }
 
 TEST_P(QuicNetworkTransactionTest, ForceQuicForAll) {
-  params_.origins_to_force_quic_on.insert(HostPortPair());
+  session_params_.origins_to_force_quic_on.insert(HostPortPair());
 
   AddQuicAlternateProtocolMapping(MockCryptoClientStream::CONFIRM_HANDSHAKE);
 
@@ -1042,7 +1046,7 @@
 }
 
 TEST_P(QuicNetworkTransactionTest, QuicProxy) {
-  params_.enable_quic = true;
+  session_params_.enable_quic = true;
   proxy_service_ =
       ProxyService::CreateFixedFromPacResult("QUIC mail.example.org:70");
 
@@ -1084,7 +1088,7 @@
   const std::string origin_host = "mail.example.com";
   const std::string proxy_host = "www.example.org";
 
-  params_.enable_quic = true;
+  session_params_.enable_quic = true;
   proxy_service_ =
       ProxyService::CreateFixedFromPacResult("QUIC " + proxy_host + ":70");
 
@@ -1249,7 +1253,7 @@
 }
 
 TEST_P(QuicNetworkTransactionTest, ForceQuicWithErrorConnecting) {
-  params_.origins_to_force_quic_on.insert(
+  session_params_.origins_to_force_quic_on.insert(
       HostPortPair::FromString("mail.example.org:443"));
 
   MockQuicData mock_quic_data1;
@@ -1283,7 +1287,7 @@
 
 TEST_P(QuicNetworkTransactionTest, DoNotForceQuicForHttps) {
   // Attempt to "force" quic on 443, which will not be honored.
-  params_.origins_to_force_quic_on.insert(
+  session_params_.origins_to_force_quic_on.insert(
       HostPortPair::FromString("www.google.com:443"));
 
   MockRead http_reads[] = {
@@ -1552,7 +1556,7 @@
 // Verify that if a QUIC connection times out, the QuicHttpStream will
 // return QUIC_PROTOCOL_ERROR.
 TEST_P(QuicNetworkTransactionTest, TimeoutAfterHandshakeConfirmed) {
-  params_.quic_idle_connection_timeout_seconds = 5;
+  session_params_.quic_idle_connection_timeout_seconds = 5;
 
   // The request will initially go out over QUIC.
   MockQuicData quic_data;
@@ -1642,7 +1646,7 @@
 // Verify that if a QUIC connection RTOs, the QuicHttpStream will
 // return QUIC_PROTOCOL_ERROR.
 TEST_P(QuicNetworkTransactionTest, TooManyRtosAfterHandshakeConfirmed) {
-  params_.quic_connection_options.push_back(k5RTO);
+  session_params_.quic_connection_options.push_back(k5RTO);
 
   // The request will initially go out over QUIC.
   MockQuicData quic_data;
@@ -1741,7 +1745,7 @@
 // QUIC will not be marked as broken.
 TEST_P(QuicNetworkTransactionTest,
        TooManyRtosAfterHandshakeConfirmedAndStreamReset) {
-  params_.quic_connection_options.push_back(k5RTO);
+  session_params_.quic_connection_options.push_back(k5RTO);
 
   // The request will initially go out over QUIC.
   MockQuicData quic_data;
@@ -1908,8 +1912,8 @@
 // connection times out, then QUIC will be marked as broken and the request
 // retried over TCP.
 TEST_P(QuicNetworkTransactionTest, TimeoutAfterHandshakeConfirmedThenBroken) {
-  params_.mark_quic_broken_when_network_blackholes = true;
-  params_.quic_idle_connection_timeout_seconds = 5;
+  session_params_.mark_quic_broken_when_network_blackholes = true;
+  session_params_.quic_idle_connection_timeout_seconds = 5;
 
   // The request will initially go out over QUIC.
   MockQuicData quic_data;
@@ -2025,8 +2029,8 @@
 // connection times out, then QUIC will be marked as broken and the request
 // retried over TCP.
 TEST_P(QuicNetworkTransactionTest, TimeoutAfterHandshakeConfirmedThenBroken2) {
-  params_.retry_without_alt_svc_on_quic_errors = true;
-  params_.quic_idle_connection_timeout_seconds = 5;
+  session_params_.retry_without_alt_svc_on_quic_errors = true;
+  session_params_.quic_idle_connection_timeout_seconds = 5;
 
   // The request will initially go out over QUIC.
   MockQuicData quic_data;
@@ -2145,8 +2149,8 @@
 // will not be retried over TCP.
 TEST_P(QuicNetworkTransactionTest,
        TimeoutAfterHandshakeConfirmedAndHeadersThenBrokenNotRetried) {
-  params_.mark_quic_broken_when_network_blackholes = true;
-  params_.quic_idle_connection_timeout_seconds = 5;
+  session_params_.mark_quic_broken_when_network_blackholes = true;
+  session_params_.quic_idle_connection_timeout_seconds = 5;
 
   // The request will initially go out over QUIC.
   MockQuicData quic_data;
@@ -2257,8 +2261,8 @@
 // over TCP.
 TEST_P(QuicNetworkTransactionTest,
        TooManyRtosAfterHandshakeConfirmedThenBroken) {
-  params_.mark_quic_broken_when_network_blackholes = true;
-  params_.quic_connection_options.push_back(k5RTO);
+  session_params_.mark_quic_broken_when_network_blackholes = true;
+  session_params_.quic_connection_options.push_back(k5RTO);
 
   // The request will initially go out over QUIC.
   MockQuicData quic_data;
@@ -2382,8 +2386,8 @@
 // QUIC will be marked as broken.
 TEST_P(QuicNetworkTransactionTest,
        TooManyRtosAfterHandshakeConfirmedAndStreamResetThenBroken) {
-  params_.mark_quic_broken_when_network_blackholes = true;
-  params_.quic_connection_options.push_back(k5RTO);
+  session_params_.mark_quic_broken_when_network_blackholes = true;
+  session_params_.quic_connection_options.push_back(k5RTO);
 
   // The request will initially go out over QUIC.
   MockQuicData quic_data;
@@ -2490,8 +2494,8 @@
 // retried over TCP and the QUIC will be marked as broken.
 TEST_P(QuicNetworkTransactionTest,
        ProtocolErrorAfterHandshakeConfirmedThenBroken) {
-  params_.retry_without_alt_svc_on_quic_errors = true;
-  params_.quic_idle_connection_timeout_seconds = 5;
+  session_params_.retry_without_alt_svc_on_quic_errors = true;
+  session_params_.quic_idle_connection_timeout_seconds = 5;
 
   // The request will initially go out over QUIC.
   MockQuicData quic_data;
@@ -2715,7 +2719,7 @@
 
   test_proxy_delegate.set_alternative_proxy_server(
       ProxyServer::FromPacString("QUIC mail.example.org:443"));
-  params_.proxy_delegate = &test_proxy_delegate;
+  session_context_.proxy_delegate = &test_proxy_delegate;
 
   request_.url = GURL("http://mail.example.org/");
 
@@ -3122,7 +3126,7 @@
 
   test_proxy_delegate.set_alternative_proxy_server(
       ProxyServer::FromPacString("QUIC mail.example.org:443"));
-  params_.proxy_delegate = &test_proxy_delegate;
+  session_context_.proxy_delegate = &test_proxy_delegate;
   CreateSession();
   EXPECT_TRUE(test_proxy_delegate.alternative_proxy_server().is_quic());
 
@@ -3834,7 +3838,7 @@
       ProxyServer::FromPacString("QUIC myproxy.org:443"));
   EXPECT_TRUE(test_proxy_delegate.alternative_proxy_server().is_quic());
 
-  params_.proxy_delegate = &test_proxy_delegate;
+  session_context_.proxy_delegate = &test_proxy_delegate;
   proxy_service_ =
       ProxyService::CreateFixedFromPacResult("HTTPS myproxy.org:443");
   request_.url = GURL("http://mail.example.org/");
@@ -3897,7 +3901,7 @@
 
   test_proxy_delegate.set_alternative_proxy_server(
       ProxyServer::FromPacString("QUIC mail.example.org:443"));
-  params_.proxy_delegate = &test_proxy_delegate;
+  session_context_.proxy_delegate = &test_proxy_delegate;
 
   request_.url = GURL("http://mail.example.org/");
 
@@ -3936,7 +3940,7 @@
 }
 
 TEST_P(QuicNetworkTransactionTest, QuicUpload) {
-  params_.origins_to_force_quic_on.insert(
+  session_params_.origins_to_force_quic_on.insert(
       HostPortPair::FromString("mail.example.org:443"));
 
   MockRead reads[] = {MockRead(SYNCHRONOUS, ERR_IO_PENDING, 0)};
@@ -3971,9 +3975,9 @@
   mock_ncn->SetConnectedNetworksList(
       {kDefaultNetworkForTests, kNewNetworkForTests});
 
-  params_.origins_to_force_quic_on.insert(
+  session_params_.origins_to_force_quic_on.insert(
       HostPortPair::FromString("mail.example.org:443"));
-  params_.quic_migrate_sessions_on_network_change = true;
+  session_params_.quic_migrate_sessions_on_network_change = true;
 
   MockQuicData socket_data;
   socket_data.AddRead(SYNCHRONOUS, ERR_IO_PENDING);
@@ -4016,7 +4020,7 @@
 
 // Adds coverage to catch regression such as https://crbug.com/622043
 TEST_P(QuicNetworkTransactionTest, QuicServerPush) {
-  params_.origins_to_force_quic_on.insert(
+  session_params_.origins_to_force_quic_on.insert(
       HostPortPair::FromString("mail.example.org:443"));
 
   MockQuicData mock_quic_data;
@@ -4074,8 +4078,8 @@
 }
 
 TEST_P(QuicNetworkTransactionTest, QuicForceHolBlocking) {
-  params_.quic_force_hol_blocking = true;
-  params_.origins_to_force_quic_on.insert(
+  session_params_.quic_force_hol_blocking = true;
+  session_params_.origins_to_force_quic_on.insert(
       HostPortPair::FromString("mail.example.org:443"));
 
   MockQuicData mock_quic_data;
@@ -4157,7 +4161,7 @@
 };
 
 TEST_P(QuicNetworkTransactionTest, RawHeaderSizeSuccessfullRequest) {
-  params_.origins_to_force_quic_on.insert(
+  session_params_.origins_to_force_quic_on.insert(
       HostPortPair::FromString("mail.example.org:443"));
 
   MockQuicData mock_quic_data;
@@ -4216,7 +4220,7 @@
 }
 
 TEST_P(QuicNetworkTransactionTest, RawHeaderSizeSuccessfullPushHeadersFirst) {
-  params_.origins_to_force_quic_on.insert(
+  session_params_.origins_to_force_quic_on.insert(
       HostPortPair::FromString("mail.example.org:443"));
 
   MockQuicData mock_quic_data;
@@ -4312,32 +4316,36 @@
     NetworkChangeNotifier::NotifyObserversOfIPAddressChangeForTests();
     base::RunLoop().RunUntilIdle();
 
-    HttpNetworkSession::Params params;
+    HttpNetworkSession::Params session_params;
+    session_params.enable_quic = true;
+    session_params.quic_supported_versions = SupportedVersions(version_);
+
+    HttpNetworkSession::Context session_context;
 
     clock_.AdvanceTime(QuicTime::Delta::FromMilliseconds(20));
-    params.quic_clock = &clock_;
+    session_context.quic_clock = &clock_;
 
     crypto_client_stream_factory_.set_handshake_mode(
         MockCryptoClientStream::CONFIRM_HANDSHAKE);
-    params.quic_crypto_client_stream_factory = &crypto_client_stream_factory_;
+    session_context.quic_crypto_client_stream_factory =
+        &crypto_client_stream_factory_;
 
-    params.enable_quic = true;
-    params.quic_random = &random_generator_;
-    params.client_socket_factory = &socket_factory_;
-    params.host_resolver = &host_resolver_;
-    params.cert_verifier = &cert_verifier_;
-    params.transport_security_state = &transport_security_state_;
-    params.cert_transparency_verifier = cert_transparency_verifier_.get();
-    params.ct_policy_enforcer = &ct_policy_enforcer_;
-    params.socket_performance_watcher_factory =
+    session_context.quic_random = &random_generator_;
+    session_context.client_socket_factory = &socket_factory_;
+    session_context.host_resolver = &host_resolver_;
+    session_context.cert_verifier = &cert_verifier_;
+    session_context.transport_security_state = &transport_security_state_;
+    session_context.cert_transparency_verifier =
+        cert_transparency_verifier_.get();
+    session_context.ct_policy_enforcer = &ct_policy_enforcer_;
+    session_context.socket_performance_watcher_factory =
         &test_socket_performance_watcher_factory_;
-    params.ssl_config_service = ssl_config_service_.get();
-    params.proxy_service = proxy_service_.get();
-    params.http_auth_handler_factory = auth_handler_factory_.get();
-    params.http_server_properties = &http_server_properties_;
-    params.quic_supported_versions = SupportedVersions(version_);
+    session_context.ssl_config_service = ssl_config_service_.get();
+    session_context.proxy_service = proxy_service_.get();
+    session_context.http_auth_handler_factory = auth_handler_factory_.get();
+    session_context.http_server_properties = &http_server_properties_;
 
-    session_.reset(new HttpNetworkSession(params));
+    session_.reset(new HttpNetworkSession(session_params, session_context));
     session_->quic_stream_factory()->set_require_confirmation(true);
   }
 
@@ -4732,7 +4740,7 @@
 // crbug.com/705109 - this confirms that matching request with a body
 // triggers a crash (pre-fix).
 TEST_P(QuicNetworkTransactionTest, QuicServerPushMatchesRequestWithBody) {
-  params_.origins_to_force_quic_on.insert(
+  session_params_.origins_to_force_quic_on.insert(
       HostPortPair::FromString("mail.example.org:443"));
 
   MockQuicData mock_quic_data;
diff --git a/net/socket/client_socket_pool_manager.cc b/net/socket/client_socket_pool_manager.cc
index fd02b02..1a002aee 100644
--- a/net/socket/client_socket_pool_manager.cc
+++ b/net/socket/client_socket_pool_manager.cc
@@ -156,16 +156,11 @@
         proxy_tcp_params = NULL;
       }
 
-      http_proxy_params =
-          new HttpProxySocketParams(proxy_tcp_params,
-                                    ssl_params,
-                                    user_agent,
-                                    origin_host_port,
-                                    session->http_auth_cache(),
-                                    session->http_auth_handler_factory(),
-                                    session->spdy_session_pool(),
-                                    force_tunnel || using_ssl,
-                                    session->params().proxy_delegate);
+      http_proxy_params = new HttpProxySocketParams(
+          proxy_tcp_params, ssl_params, user_agent, origin_host_port,
+          session->http_auth_cache(), session->http_auth_handler_factory(),
+          session->spdy_session_pool(), force_tunnel || using_ssl,
+          session->context().proxy_delegate);
     } else {
       DCHECK(proxy_info.is_socks());
       char socks_version;
diff --git a/net/socket/ssl_client_socket_pool_unittest.cc b/net/socket/ssl_client_socket_pool_unittest.cc
index 732a82e..7702979 100644
--- a/net/socket/ssl_client_socket_pool_unittest.cc
+++ b/net/socket/ssl_client_socket_pool_unittest.cc
@@ -167,18 +167,20 @@
   }
 
   HttpNetworkSession* CreateNetworkSession() {
-    HttpNetworkSession::Params params;
-    params.host_resolver = &host_resolver_;
-    params.cert_verifier = cert_verifier_.get();
-    params.transport_security_state = transport_security_state_.get();
-    params.cert_transparency_verifier = &ct_verifier_;
-    params.ct_policy_enforcer = &ct_policy_enforcer_;
-    params.proxy_service = proxy_service_.get();
-    params.client_socket_factory = &socket_factory_;
-    params.ssl_config_service = ssl_config_service_.get();
-    params.http_auth_handler_factory = http_auth_handler_factory_.get();
-    params.http_server_properties = http_server_properties_.get();
-    return new HttpNetworkSession(params);
+    HttpNetworkSession::Context session_context;
+    session_context.host_resolver = &host_resolver_;
+    session_context.cert_verifier = cert_verifier_.get();
+    session_context.transport_security_state = transport_security_state_.get();
+    session_context.cert_transparency_verifier = &ct_verifier_;
+    session_context.ct_policy_enforcer = &ct_policy_enforcer_;
+    session_context.proxy_service = proxy_service_.get();
+    session_context.client_socket_factory = &socket_factory_;
+    session_context.ssl_config_service = ssl_config_service_.get();
+    session_context.http_auth_handler_factory =
+        http_auth_handler_factory_.get();
+    session_context.http_server_properties = http_server_properties_.get();
+    return new HttpNetworkSession(HttpNetworkSession::Params(),
+                                  session_context);
   }
 
   void TestIPPoolingDisabled(SSLSocketDataProvider* ssl);
diff --git a/net/spdy/chromium/spdy_test_util_common.cc b/net/spdy/chromium/spdy_test_util_common.cc
index 787ad80..a30a582 100644
--- a/net/spdy/chromium/spdy_test_util_common.cc
+++ b/net/spdy/chromium/spdy_test_util_common.cc
@@ -376,9 +376,12 @@
 SpdySessionDependencies::SpdyCreateSessionWithSocketFactory(
     SpdySessionDependencies* session_deps,
     ClientSocketFactory* factory) {
-  HttpNetworkSession::Params params = CreateSessionParams(session_deps);
-  params.client_socket_factory = factory;
-  auto http_session = base::MakeUnique<HttpNetworkSession>(params);
+  HttpNetworkSession::Params session_params = CreateSessionParams(session_deps);
+  HttpNetworkSession::Context session_context =
+      CreateSessionContext(session_deps);
+  session_context.client_socket_factory = factory;
+  auto http_session =
+      base::MakeUnique<HttpNetworkSession>(session_params, session_context);
   SpdySessionPoolPeer pool_peer(http_session->spdy_session_pool());
   pool_peer.SetEnableSendingInitialData(false);
   return http_session;
@@ -388,19 +391,6 @@
 HttpNetworkSession::Params SpdySessionDependencies::CreateSessionParams(
     SpdySessionDependencies* session_deps) {
   HttpNetworkSession::Params params;
-  params.host_resolver = session_deps->host_resolver.get();
-  params.cert_verifier = session_deps->cert_verifier.get();
-  params.channel_id_service = session_deps->channel_id_service.get();
-  params.transport_security_state =
-      session_deps->transport_security_state.get();
-  params.cert_transparency_verifier =
-      session_deps->cert_transparency_verifier.get();
-  params.ct_policy_enforcer = session_deps->ct_policy_enforcer.get();
-  params.proxy_service = session_deps->proxy_service.get();
-  params.ssl_config_service = session_deps->ssl_config_service.get();
-  params.http_auth_handler_factory =
-      session_deps->http_auth_handler_factory.get();
-  params.http_server_properties = session_deps->http_server_properties.get();
   params.enable_spdy_ping_based_connection_checking = session_deps->enable_ping;
   params.enable_user_alternate_protocol_ports =
       session_deps->enable_user_alternate_protocol_ports;
@@ -411,15 +401,34 @@
       session_deps->session_max_recv_window_size;
   params.http2_settings = session_deps->http2_settings;
   params.time_func = session_deps->time_func;
-  params.proxy_delegate = session_deps->proxy_delegate.get();
   params.enable_http2_alternative_service =
       session_deps->enable_http2_alternative_service;
-  params.net_log = session_deps->net_log;
   params.http_09_on_non_default_ports_enabled =
       session_deps->http_09_on_non_default_ports_enabled;
   return params;
 }
 
+HttpNetworkSession::Context SpdySessionDependencies::CreateSessionContext(
+    SpdySessionDependencies* session_deps) {
+  HttpNetworkSession::Context context;
+  context.host_resolver = session_deps->host_resolver.get();
+  context.cert_verifier = session_deps->cert_verifier.get();
+  context.channel_id_service = session_deps->channel_id_service.get();
+  context.transport_security_state =
+      session_deps->transport_security_state.get();
+  context.cert_transparency_verifier =
+      session_deps->cert_transparency_verifier.get();
+  context.ct_policy_enforcer = session_deps->ct_policy_enforcer.get();
+  context.proxy_service = session_deps->proxy_service.get();
+  context.ssl_config_service = session_deps->ssl_config_service.get();
+  context.http_auth_handler_factory =
+      session_deps->http_auth_handler_factory.get();
+  context.http_server_properties = session_deps->http_server_properties.get();
+  context.proxy_delegate = session_deps->proxy_delegate.get();
+  context.net_log = session_deps->net_log;
+  return context;
+}
+
 class AllowAnyCertCTPolicyEnforcer : public CTPolicyEnforcer {
  public:
   AllowAnyCertCTPolicyEnforcer() {}
@@ -458,20 +467,22 @@
   storage_.set_http_server_properties(
       std::unique_ptr<HttpServerProperties>(new HttpServerPropertiesImpl()));
   storage_.set_job_factory(base::MakeUnique<URLRequestJobFactoryImpl>());
-  HttpNetworkSession::Params params;
-  params.client_socket_factory = &socket_factory_;
-  params.host_resolver = host_resolver();
-  params.cert_verifier = cert_verifier();
-  params.transport_security_state = transport_security_state();
-  params.proxy_service = proxy_service();
-  params.ct_policy_enforcer = ct_policy_enforcer();
-  params.cert_transparency_verifier = cert_transparency_verifier();
-  params.ssl_config_service = ssl_config_service();
-  params.http_auth_handler_factory = http_auth_handler_factory();
-  params.enable_spdy_ping_based_connection_checking = false;
-  params.http_server_properties = http_server_properties();
+  HttpNetworkSession::Params session_params;
+  session_params.enable_spdy_ping_based_connection_checking = false;
+
+  HttpNetworkSession::Context session_context;
+  session_context.client_socket_factory = &socket_factory_;
+  session_context.host_resolver = host_resolver();
+  session_context.cert_verifier = cert_verifier();
+  session_context.transport_security_state = transport_security_state();
+  session_context.proxy_service = proxy_service();
+  session_context.ct_policy_enforcer = ct_policy_enforcer();
+  session_context.cert_transparency_verifier = cert_transparency_verifier();
+  session_context.ssl_config_service = ssl_config_service();
+  session_context.http_auth_handler_factory = http_auth_handler_factory();
+  session_context.http_server_properties = http_server_properties();
   storage_.set_http_network_session(
-      base::MakeUnique<HttpNetworkSession>(params));
+      base::MakeUnique<HttpNetworkSession>(session_params, session_context));
   SpdySessionPoolPeer pool_peer(
       storage_.http_network_session()->spdy_session_pool());
   pool_peer.SetEnableSendingInitialData(false);
diff --git a/net/spdy/chromium/spdy_test_util_common.h b/net/spdy/chromium/spdy_test_util_common.h
index e27bce2..31aa8e7 100644
--- a/net/spdy/chromium/spdy_test_util_common.h
+++ b/net/spdy/chromium/spdy_test_util_common.h
@@ -192,6 +192,8 @@
       ClientSocketFactory* factory);
   static HttpNetworkSession::Params CreateSessionParams(
       SpdySessionDependencies* session_deps);
+  static HttpNetworkSession::Context CreateSessionContext(
+      SpdySessionDependencies* session_deps);
 
   // NOTE: host_resolver must be ordered before http_auth_handler_factory.
   std::unique_ptr<MockHostResolverBase> host_resolver;
diff --git a/net/url_request/url_request_context.cc b/net/url_request/url_request_context.cc
index ce0676e..4a2f9dba 100644
--- a/net/url_request/url_request_context.cc
+++ b/net/url_request/url_request_context.cc
@@ -101,6 +101,17 @@
   return &network_session->params();
 }
 
+const HttpNetworkSession::Context* URLRequestContext::GetNetworkSessionContext()
+    const {
+  HttpTransactionFactory* transaction_factory = http_transaction_factory();
+  if (!transaction_factory)
+    return nullptr;
+  HttpNetworkSession* network_session = transaction_factory->GetSession();
+  if (!network_session)
+    return nullptr;
+  return &network_session->context();
+}
+
 std::unique_ptr<URLRequest> URLRequestContext::CreateRequest(
     const GURL& url,
     RequestPriority priority,
diff --git a/net/url_request/url_request_context.h b/net/url_request/url_request_context.h
index 0d954a6..5874bbc 100644
--- a/net/url_request/url_request_context.h
+++ b/net/url_request/url_request_context.h
@@ -73,6 +73,10 @@
   // session.
   const HttpNetworkSession::Params* GetNetworkSessionParams() const;
 
+  // May return nullptr if this context doesn't have an associated network
+  // session.
+  const HttpNetworkSession::Context* GetNetworkSessionContext() const;
+
   // This function should not be used in Chromium, please use the version with
   // NetworkTrafficAnnotationTag in the future.
   std::unique_ptr<URLRequest> CreateRequest(
diff --git a/net/url_request/url_request_context_builder.cc b/net/url_request/url_request_context_builder.cc
index 5937f2a6..d0b7aa5 100644
--- a/net/url_request/url_request_context_builder.cc
+++ b/net/url_request/url_request_context_builder.cc
@@ -259,19 +259,23 @@
 URLRequestContextBuilder::~URLRequestContextBuilder() {}
 
 void URLRequestContextBuilder::SetHttpNetworkSessionComponents(
-    const URLRequestContext* context,
-    HttpNetworkSession::Params* params) {
-  params->host_resolver = context->host_resolver();
-  params->cert_verifier = context->cert_verifier();
-  params->transport_security_state = context->transport_security_state();
-  params->cert_transparency_verifier = context->cert_transparency_verifier();
-  params->ct_policy_enforcer = context->ct_policy_enforcer();
-  params->proxy_service = context->proxy_service();
-  params->ssl_config_service = context->ssl_config_service();
-  params->http_auth_handler_factory = context->http_auth_handler_factory();
-  params->http_server_properties = context->http_server_properties();
-  params->net_log = context->net_log();
-  params->channel_id_service = context->channel_id_service();
+    const URLRequestContext* request_context,
+    HttpNetworkSession::Context* session_context) {
+  session_context->host_resolver = request_context->host_resolver();
+  session_context->cert_verifier = request_context->cert_verifier();
+  session_context->transport_security_state =
+      request_context->transport_security_state();
+  session_context->cert_transparency_verifier =
+      request_context->cert_transparency_verifier();
+  session_context->ct_policy_enforcer = request_context->ct_policy_enforcer();
+  session_context->proxy_service = request_context->proxy_service();
+  session_context->ssl_config_service = request_context->ssl_config_service();
+  session_context->http_auth_handler_factory =
+      request_context->http_auth_handler_factory();
+  session_context->http_server_properties =
+      request_context->http_server_properties();
+  session_context->net_log = request_context->net_log();
+  session_context->channel_id_service = request_context->channel_id_service();
 }
 
 void URLRequestContextBuilder::EnableHttpCache(const HttpCacheParams& params) {
@@ -451,21 +455,22 @@
   }
   storage->set_proxy_service(std::move(proxy_service_));
 
+  HttpNetworkSession::Context network_session_context;
+  SetHttpNetworkSessionComponents(context.get(), &network_session_context);
   HttpNetworkSession::Params network_session_params;
-  SetHttpNetworkSessionComponents(context.get(), &network_session_params);
   http_network_session_params_.ConfigureSessionParams(&network_session_params);
 
   if (proxy_delegate_) {
-    network_session_params.proxy_delegate = proxy_delegate_.get();
+    network_session_context.proxy_delegate = proxy_delegate_.get();
     storage->set_proxy_delegate(std::move(proxy_delegate_));
   }
   if (socket_performance_watcher_factory_) {
-    network_session_params.socket_performance_watcher_factory =
+    network_session_context.socket_performance_watcher_factory =
         socket_performance_watcher_factory_;
   }
 
-  storage->set_http_network_session(
-      base::MakeUnique<HttpNetworkSession>(network_session_params));
+  storage->set_http_network_session(base::MakeUnique<HttpNetworkSession>(
+      network_session_params, network_session_context));
 
   std::unique_ptr<HttpTransactionFactory> http_transaction_factory;
   if (http_cache_enabled_) {
diff --git a/net/url_request/url_request_context_builder.h b/net/url_request/url_request_context_builder.h
index 45526b0a..a8b3d24 100644
--- a/net/url_request/url_request_context_builder.h
+++ b/net/url_request/url_request_context_builder.h
@@ -130,12 +130,12 @@
   }
 
   // Extracts the component pointers required to construct an HttpNetworkSession
-  // and copies them into the Params used to create the session. This function
-  // should be used to ensure that a context and its associated
-  // HttpNetworkSession are consistent.
+  // and copies them into the HttpNetworkSession::Context used to create the
+  // session. This function should be used to ensure that a context and its
+  // associated HttpNetworkSession are consistent.
   static void SetHttpNetworkSessionComponents(
-      const URLRequestContext* context,
-      HttpNetworkSession::Params* params);
+      const URLRequestContext* request_context,
+      HttpNetworkSession::Context* session_context);
 
   // These functions are mutually exclusive.  The ProxyConfigService, if
   // set, will be used to construct a ProxyService.
diff --git a/net/url_request/url_request_http_job.cc b/net/url_request/url_request_http_job.cc
index 203a6e2..58546175 100644
--- a/net/url_request/url_request_http_job.cc
+++ b/net/url_request/url_request_http_job.cc
@@ -124,19 +124,21 @@
     PERSISTENT_UNKNOWN = 12,
     EPHEMERALITY_MAX
   } ephemerality;
-  const net::HttpNetworkSession::Params* params =
-      context->GetNetworkSessionParams();
+  const net::HttpNetworkSession::Context* session_context =
+      context->GetNetworkSessionContext();
   net::CookieStore* cookie_store = context->cookie_store();
-  if (params == nullptr || params->channel_id_service == nullptr) {
+  if (session_context == nullptr ||
+      session_context->channel_id_service == nullptr) {
     ephemerality = NO_CHANNEL_ID_STORE;
   } else if (cookie_store == nullptr) {
     ephemerality = NO_COOKIE_STORE;
-  } else if (params->channel_id_service->GetChannelIDStore()->IsEphemeral()) {
+  } else if (session_context->channel_id_service->GetChannelIDStore()
+                 ->IsEphemeral()) {
     if (cookie_store->IsEphemeral()) {
       if (cookie_store->GetChannelIDServiceID() == -1) {
         ephemerality = EPHEMERAL_UNKNOWN;
       } else if (cookie_store->GetChannelIDServiceID() ==
-                 params->channel_id_service->GetUniqueID()) {
+                 session_context->channel_id_service->GetUniqueID()) {
         ephemerality = EPHEMERAL_MATCH;
       } else {
         NOTREACHED();
@@ -152,7 +154,7 @@
   } else if (cookie_store->GetChannelIDServiceID() == -1) {
     ephemerality = PERSISTENT_UNKNOWN;
   } else if (cookie_store->GetChannelIDServiceID() ==
-             params->channel_id_service->GetUniqueID()) {
+             session_context->channel_id_service->GetUniqueID()) {
     ephemerality = PERSISTENT_MATCH;
   } else {
     NOTREACHED();
diff --git a/net/url_request/url_request_quic_unittest.cc b/net/url_request/url_request_quic_unittest.cc
index f9ec11d1..e28e714 100644
--- a/net/url_request/url_request_quic_unittest.cc
+++ b/net/url_request/url_request_quic_unittest.cc
@@ -68,7 +68,6 @@
     // To simplify the test, and avoid the race with the HTTP request, we force
     // QUIC for these requests.
     params->origins_to_force_quic_on.insert(HostPortPair(kTestServerHost, 443));
-    params->cert_verifier = &cert_verifier_;
     params->enable_quic = true;
     params->enable_server_push_cancellation = true;
     context_->set_host_resolver(host_resolver_.get());
diff --git a/net/url_request/url_request_test_util.cc b/net/url_request/url_request_test_util.cc
index 4c602012..110105c 100644
--- a/net/url_request/url_request_test_util.cc
+++ b/net/url_request/url_request_test_util.cc
@@ -114,25 +114,28 @@
     // Make sure we haven't been passed an object we're not going to use.
     EXPECT_FALSE(client_socket_factory_);
   } else {
-    HttpNetworkSession::Params params;
-
+    HttpNetworkSession::Params session_params;
     if (http_network_session_params_)
-      params = *http_network_session_params_;
-    params.client_socket_factory = client_socket_factory();
-    params.proxy_delegate = proxy_delegate();
-    params.host_resolver = host_resolver();
-    params.cert_verifier = cert_verifier();
-    params.cert_transparency_verifier = cert_transparency_verifier();
-    params.ct_policy_enforcer = ct_policy_enforcer();
-    params.transport_security_state = transport_security_state();
-    params.proxy_service = proxy_service();
-    params.ssl_config_service = ssl_config_service();
-    params.http_auth_handler_factory = http_auth_handler_factory();
-    params.http_server_properties = http_server_properties();
-    params.net_log = net_log();
-    params.channel_id_service = channel_id_service();
+      session_params = *http_network_session_params_;
+
+    HttpNetworkSession::Context session_context;
+    if (http_network_session_context_)
+      session_context = *http_network_session_context_;
+    session_context.client_socket_factory = client_socket_factory();
+    session_context.proxy_delegate = proxy_delegate();
+    session_context.host_resolver = host_resolver();
+    session_context.cert_verifier = cert_verifier();
+    session_context.cert_transparency_verifier = cert_transparency_verifier();
+    session_context.ct_policy_enforcer = ct_policy_enforcer();
+    session_context.transport_security_state = transport_security_state();
+    session_context.proxy_service = proxy_service();
+    session_context.ssl_config_service = ssl_config_service();
+    session_context.http_auth_handler_factory = http_auth_handler_factory();
+    session_context.http_server_properties = http_server_properties();
+    session_context.net_log = net_log();
+    session_context.channel_id_service = channel_id_service();
     context_storage_.set_http_network_session(
-        base::MakeUnique<HttpNetworkSession>(params));
+        base::MakeUnique<HttpNetworkSession>(session_params, session_context));
     context_storage_.set_http_transaction_factory(base::MakeUnique<HttpCache>(
         context_storage_.http_network_session(),
         HttpCache::DefaultBackend::InMemory(0), true /* is_main_cache */));
diff --git a/net/url_request/url_request_test_util.h b/net/url_request/url_request_test_util.h
index 9868bcbb..ebd9aad 100644
--- a/net/url_request/url_request_test_util.h
+++ b/net/url_request/url_request_test_util.h
@@ -77,8 +77,13 @@
   }
 
   void set_http_network_session_params(
-      std::unique_ptr<HttpNetworkSession::Params> params) {
-    http_network_session_params_ = std::move(params);
+      std::unique_ptr<HttpNetworkSession::Params> session_params) {
+    http_network_session_params_ = std::move(session_params);
+  }
+
+  void set_http_network_session_context(
+      std::unique_ptr<HttpNetworkSession::Context> session_context) {
+    http_network_session_context_ = std::move(session_context);
   }
 
   void SetSdchManager(std::unique_ptr<SdchManager> sdch_manager) {
@@ -93,10 +98,11 @@
  private:
   bool initialized_ = false;
 
-  // Optional parameters to override default values.  Note that values that
-  // point to other objects the TestURLRequestContext creates will be
-  // overwritten.
+  // Optional parameters to override default values.  Note that values in the
+  // HttpNetworkSession::Context that point to other objects the
+  // TestURLRequestContext creates will be overwritten.
   std::unique_ptr<HttpNetworkSession::Params> http_network_session_params_;
+  std::unique_ptr<HttpNetworkSession::Context> http_network_session_context_;
 
   // Not owned:
   ClientSocketFactory* client_socket_factory_ = nullptr;
diff --git a/net/url_request/url_request_unittest.cc b/net/url_request/url_request_unittest.cc
index 5d299633..3dded3d 100644
--- a/net/url_request/url_request_unittest.cc
+++ b/net/url_request/url_request_unittest.cc
@@ -9506,20 +9506,23 @@
   }
 
   // Now create a new HttpCache with a different ssl_session_cache_shard value.
-  HttpNetworkSession::Params params;
-  params.host_resolver = default_context_.host_resolver();
-  params.cert_verifier = default_context_.cert_verifier();
-  params.transport_security_state = default_context_.transport_security_state();
-  params.cert_transparency_verifier =
+  HttpNetworkSession::Context session_context;
+  session_context.host_resolver = default_context_.host_resolver();
+  session_context.cert_verifier = default_context_.cert_verifier();
+  session_context.transport_security_state =
+      default_context_.transport_security_state();
+  session_context.cert_transparency_verifier =
       default_context_.cert_transparency_verifier();
-  params.ct_policy_enforcer = default_context_.ct_policy_enforcer();
-  params.proxy_service = default_context_.proxy_service();
-  params.ssl_config_service = default_context_.ssl_config_service();
-  params.http_auth_handler_factory =
+  session_context.ct_policy_enforcer = default_context_.ct_policy_enforcer();
+  session_context.proxy_service = default_context_.proxy_service();
+  session_context.ssl_config_service = default_context_.ssl_config_service();
+  session_context.http_auth_handler_factory =
       default_context_.http_auth_handler_factory();
-  params.http_server_properties = default_context_.http_server_properties();
+  session_context.http_server_properties =
+      default_context_.http_server_properties();
 
-  HttpNetworkSession network_session(params);
+  HttpNetworkSession network_session(HttpNetworkSession::Params(),
+                                     session_context);
   std::unique_ptr<HttpCache> cache(
       new HttpCache(&network_session, HttpCache::DefaultBackend::InMemory(0),
                     false /* is_main_cache */));
diff --git a/printing/backend/print_backend_win.cc b/printing/backend/print_backend_win.cc
index 7a657142..ac29e67 100644
--- a/printing/backend/print_backend_win.cc
+++ b/printing/backend/print_backend_win.cc
@@ -11,6 +11,7 @@
 #include <memory>
 
 #include "base/memory/free_deleter.h"
+#include "base/memory/ptr_util.h"
 #include "base/numerics/safe_conversions.h"
 #include "base/strings/string_number_conversions.h"
 #include "base/strings/string_piece.h"
@@ -187,7 +188,8 @@
                nullptr, 0, &bytes_needed, &count_returned);
   if (!bytes_needed)
     return false;
-  std::unique_ptr<BYTE[]> printer_info_buffer(new BYTE[bytes_needed]);
+
+  auto printer_info_buffer = base::MakeUnique<BYTE[]>(bytes_needed);
   if (!EnumPrinters(PRINTER_ENUM_LOCAL | PRINTER_ENUM_CONNECTIONS, nullptr,
                     kLevel, printer_info_buffer.get(), bytes_needed,
                     &bytes_needed, &count_returned)) {
@@ -307,27 +309,29 @@
 bool PrintBackendWin::GetPrinterCapsAndDefaults(
     const std::string& printer_name,
     PrinterCapsAndDefaults* printer_info) {
-  ScopedXPSInitializer xps_initializer;
-  if (!xps_initializer.initialized()) {
-    // TODO(sanjeevr): Handle legacy proxy case (with no prntvpt.dll)
-    return false;
-  }
-  if (!IsValidPrinter(printer_name)) {
-    return false;
-  }
   DCHECK(printer_info);
-  HPTPROVIDER provider = NULL;
+
+  ScopedXPSInitializer xps_initializer;
+  CHECK(xps_initializer.initialized());
+
+  if (!IsValidPrinter(printer_name))
+    return false;
+
+  HPTPROVIDER provider = nullptr;
   std::wstring printer_name_wide = base::UTF8ToWide(printer_name);
   HRESULT hr = XPSModule::OpenProvider(printer_name_wide, 1, &provider);
-  if (provider) {
+  if (!provider)
+    return true;
+
+  {
     base::win::ScopedComPtr<IStream> print_capabilities_stream;
-    hr = CreateStreamOnHGlobal(NULL, TRUE,
+    hr = CreateStreamOnHGlobal(nullptr, TRUE,
                                print_capabilities_stream.GetAddressOf());
     DCHECK(SUCCEEDED(hr));
     if (print_capabilities_stream.Get()) {
       base::win::ScopedBstr error;
       hr = XPSModule::GetPrintCapabilities(
-          provider, NULL, print_capabilities_stream.Get(), error.Receive());
+          provider, nullptr, print_capabilities_stream.Get(), error.Receive());
       DCHECK(SUCCEEDED(hr));
       if (FAILED(hr)) {
         return false;
@@ -340,11 +344,11 @@
     ScopedPrinterHandle printer_handle;
     if (printer_handle.OpenPrinter(printer_name_wide.c_str())) {
       std::unique_ptr<DEVMODE, base::FreeDeleter> devmode_out(
-          CreateDevMode(printer_handle.Get(), NULL));
+          CreateDevMode(printer_handle.Get(), nullptr));
       if (!devmode_out)
         return false;
       base::win::ScopedComPtr<IStream> printer_defaults_stream;
-      hr = CreateStreamOnHGlobal(NULL, TRUE,
+      hr = CreateStreamOnHGlobal(nullptr, TRUE,
                                  printer_defaults_stream.GetAddressOf());
       DCHECK(SUCCEEDED(hr));
       if (printer_defaults_stream.Get()) {
diff --git a/printing/backend/win_helper.h b/printing/backend/win_helper.h
index 05e0fe9..a9090be8 100644
--- a/printing/backend/win_helper.h
+++ b/printing/backend/win_helper.h
@@ -141,6 +141,8 @@
 
  private:
   bool initialized_;
+
+  DISALLOW_COPY_AND_ASSIGN(ScopedXPSInitializer);
 };
 
 // Wrapper class to wrap the XPS Print APIs (these are different from the PTxxx
diff --git a/remoting/ios/app/host_collection_view_cell.mm b/remoting/ios/app/host_collection_view_cell.mm
index 0f3e23b1..7cbab27 100644
--- a/remoting/ios/app/host_collection_view_cell.mm
+++ b/remoting/ios/app/host_collection_view_cell.mm
@@ -102,7 +102,6 @@
   _hostInfo = hostInfo;
 
   _titleLabel.text = _hostInfo.hostName;
-  _statusLabel.text = _hostInfo.status;
 
   _imageView.image = [UIImage imageNamed:@"ic_desktop"];
 
@@ -110,8 +109,11 @@
   // Need to update to the values in the mocks.
   if ([_hostInfo.status isEqualToString:@"ONLINE"]) {
     _imageView.backgroundColor = UIColor.greenColor;
+    _statusLabel.text = @"Online";
   } else {
     _imageView.backgroundColor = UIColor.lightGrayColor;
+    _statusLabel.text =
+        [NSString stringWithFormat:@"Last online: %@", hostInfo.updatedTime];
   }
 }
 
diff --git a/remoting/ios/app/main.mm b/remoting/ios/app/main.mm
index d66bba0..611fee9 100644
--- a/remoting/ios/app/main.mm
+++ b/remoting/ios/app/main.mm
@@ -10,6 +10,7 @@
 
 #include "base/at_exit.h"
 #include "base/command_line.h"
+#include "base/i18n/icu_util.h"
 #import "remoting/ios/app/app_delegate.h"
 
 int main(int argc, char* argv[]) {
@@ -20,6 +21,9 @@
   // Publicize the CommandLine.
   base::CommandLine::Init(argc, argv);
 
+  // Required to find the ICU data file, used by some file_util routines.
+  base::i18n::InitializeICU();
+
 #ifdef DEBUG
   // Set min log level for debug builds.  For some reason this has to be
   // negative.
diff --git a/remoting/ios/domain/host_info.h b/remoting/ios/domain/host_info.h
index e0eafa7..4d8c64921 100644
--- a/remoting/ios/domain/host_info.h
+++ b/remoting/ios/domain/host_info.h
@@ -21,7 +21,7 @@
 @property(nonatomic, copy) NSString* kind;
 @property(nonatomic, copy) NSString* publicKey;
 @property(nonatomic, copy) NSString* status;
-@property(nonatomic, copy) NSDate* updatedTime;
+@property(nonatomic, copy) NSString* updatedTime;
 // True when |status| is @"ONLINE", anything else is False.
 @property(nonatomic, readonly) bool isOnline;
 
diff --git a/remoting/ios/domain/host_info.mm b/remoting/ios/domain/host_info.mm
index e048237..21f55d1d 100644
--- a/remoting/ios/domain/host_info.mm
+++ b/remoting/ios/domain/host_info.mm
@@ -56,12 +56,12 @@
     host.publicKey = [svr objectForKey:@"publicKey"];
     host.status = [svr objectForKey:@"status"];
 
-    NSString* ISO8601DateString = [svr objectForKey:@"updatedTime"];
-    if (ISO8601DateString != nil) {
-      NSDateFormatter* dateFormatter = [[NSDateFormatter alloc] init];
-      [dateFormatter setDateFormat:@"yyyy-MM-dd'T'HH:mm:ss.SSSz"];
-      host.updatedTime = [dateFormatter dateFromString:ISO8601DateString];
-    }
+    //    NSString* ISO8601DateString = [svr objectForKey:@"updatedTime"];
+    //    if (ISO8601DateString != nil) {
+    //      NSDateFormatter* dateFormatter = [[NSDateFormatter alloc] init];
+    //      [dateFormatter setDateFormat:@"yyyy-MM-dd'T'HH:mm:ss.SSSz"];
+    //      host.updatedTime = [dateFormatter dateFromString:ISO8601DateString];
+    //    }
 
     [hostList addObject:host];
   }
diff --git a/remoting/ios/facade/host_info.cc b/remoting/ios/facade/host_info.cc
index 939fc50..a1cf275 100644
--- a/remoting/ios/facade/host_info.cc
+++ b/remoting/ios/facade/host_info.cc
@@ -51,21 +51,6 @@
     return false;
   }
 
-  if (!host_info.GetString("hostOS", &host_os)) {
-    LOG(ERROR) << "hostOS was not found in host_info";
-    return false;
-  }
-
-  if (!host_info.GetString("hostOsVersion", &host_os_version)) {
-    LOG(ERROR) << "hostOsVersion was not found in host_info";
-    return false;
-  }
-
-  if (!host_info.GetString("hostVersion", &host_version)) {
-    LOG(ERROR) << "hostVersion was not found in host_info";
-    return false;
-  }
-
   if (!host_info.GetString("publicKey", &public_key)) {
     LOG(ERROR) << "publicKey was not found for " << host_name;
     return false;
@@ -79,6 +64,17 @@
     return false;
   }
 
+  std::string updated_time_iso;
+  if (host_info.GetString("updatedTime", &updated_time_iso)) {
+    if (!base::Time::FromString(updated_time_iso.c_str(), &updated_time)) {
+      LOG(WARNING) << "Failed to parse updatedTime";
+    }
+  }
+
+  host_info.GetString("hostOs", &host_os);
+  host_info.GetString("hostOsVersion", &host_os_version);
+  host_info.GetString("hostVersion", &host_version);
+
   host_info.GetString("hostOfflineReason", &offline_reason);
 
   return true;
diff --git a/remoting/ios/facade/host_info.h b/remoting/ios/facade/host_info.h
index d2b43a2..d8c5194 100644
--- a/remoting/ios/facade/host_info.h
+++ b/remoting/ios/facade/host_info.h
@@ -8,6 +8,7 @@
 #include <string>
 #include <vector>
 
+#include "base/time/time.h"
 #include "base/values.h"
 
 namespace remoting {
@@ -36,6 +37,7 @@
   HostStatus status = kHostStatusOffline;
   std::string offline_reason;
   std::string public_key;
+  base::Time updated_time;
   std::vector<std::string> token_url_patterns;
 };
 
diff --git a/remoting/ios/facade/host_list_fetcher.cc b/remoting/ios/facade/host_list_fetcher.cc
index 9342399..469cbf3 100644
--- a/remoting/ios/facade/host_list_fetcher.cc
+++ b/remoting/ios/facade/host_list_fetcher.cc
@@ -4,6 +4,7 @@
 
 #include "remoting/ios/facade/host_list_fetcher.h"
 
+#include <algorithm>
 #include <thread>
 
 #include "base/bind.h"
@@ -18,6 +19,27 @@
 
 namespace remoting {
 
+namespace {
+
+// Returns true if |h1| should sort before |h2|.
+bool compareHost(const HostInfo& h1, const HostInfo& h2) {
+  // Online hosts always sort before offline hosts.
+  if (h1.status != h2.status) {
+    return h1.status == HostStatus::kHostStatusOnline;
+  }
+
+  // Sort by host name.
+  int name_compare = h1.host_name.compare(h2.host_name);
+  if (name_compare != 0) {
+    return name_compare < 0;
+  }
+
+  // Sort by last update time if names are identical.
+  return h1.updated_time < h2.updated_time;
+}
+
+}  // namespace
+
 HostListFetcher::HostListFetcher(
     const scoped_refptr<net::URLRequestContextGetter>&
         url_request_context_getter)
@@ -105,6 +127,7 @@
   if (!ProcessResponse(&hostlist)) {
     hostlist.clear();
   }
+  std::sort(hostlist.begin(), hostlist.end(), &compareHost);
   base::ResetAndReturn(&hostlist_callback_).Run(hostlist);
 }
 
diff --git a/remoting/ios/facade/remoting_service.mm b/remoting/ios/facade/remoting_service.mm
index 63be2ed..10096f18 100644
--- a/remoting/ios/facade/remoting_service.mm
+++ b/remoting/ios/facade/remoting_service.mm
@@ -21,6 +21,7 @@
 #import "remoting/ios/facade/remoting_service.h"
 #import "remoting/ios/keychain_wrapper.h"
 
+#include "base/i18n/time_formatting.h"
 #include "base/logging.h"
 #include "base/strings/sys_string_conversions.h"
 #include "net/url_request/url_request_context_getter.h"
@@ -109,6 +110,8 @@
           host.jabberId = base::SysUTF8ToNSString(host_info.host_jid);
           host.publicKey = base::SysUTF8ToNSString(host_info.public_key);
           host.status = base::SysUTF8ToNSString(status);
+          host.updatedTime = base::SysUTF16ToNSString(
+              base::TimeFormatShortDateAndTime(host_info.updated_time));
           [hosts addObject:host];
         }
         _hosts = hosts;
diff --git a/testing/variations/fieldtrial_testing_config.json b/testing/variations/fieldtrial_testing_config.json
index 0f8714a..91cedbb 100644
--- a/testing/variations/fieldtrial_testing_config.json
+++ b/testing/variations/fieldtrial_testing_config.json
@@ -409,6 +409,25 @@
             ]
         }
     ],
+    "CheckerImaging": [
+        {
+            "platforms": [
+                "android",
+                "chromeos",
+                "linux",
+                "mac",
+                "win"
+            ],
+            "experiments": [
+                {
+                    "name": "CheckerImaging",
+                    "enable_features": [
+                        "CheckerImaging"
+                    ]
+                }
+            ]
+        }
+    ],
     "ChildAccountDetection": [
         {
             "platforms": [
@@ -1876,6 +1895,42 @@
             ]
         }
     ],
+    "OmniboxPlaceholderExperiment": [
+        {
+            "platforms": [
+                "android"
+            ],
+            "experiments": [
+                {
+                    "name": "SearchOrTypeUrl"
+                },
+                {
+                    "name": "SearchOrTypeWebsiteName"
+                },
+                {
+                    "name": "SearchTheWeb"
+                },
+                {
+                    "name": "EnterASearchOrWebsite"
+                },
+                {
+                    "name": "SearchNews"
+                },
+                {
+                    "name": "SearchRecipes"
+                },
+                {
+                    "name": "SearchWeather"
+                },
+                {
+                    "name": "Blank"
+                },
+                {
+                    "name": "Default"
+                }
+            ]
+        }
+    ],
     "OutOfProcessPac": [
         {
             "platforms": [
diff --git a/third_party/WebKit/LayoutTests/SlowTests b/third_party/WebKit/LayoutTests/SlowTests
index 88871bfa..52d36d23 100644
--- a/third_party/WebKit/LayoutTests/SlowTests
+++ b/third_party/WebKit/LayoutTests/SlowTests
@@ -386,3 +386,5 @@
 crbug.com/722825 media/controls/video-enter-exit-fullscreen-without-hovering-doesnt-show-controls.html [ Slow ]
 crbug.com/722825 virtual/new-remote-playback-pipeline/media/controls/video-enter-exit-fullscreen-while-hovering-shows-controls.html [ Slow ]
 crbug.com/722825 virtual/new-remote-playback-pipeline/media/controls/video-enter-exit-fullscreen-without-hovering-doesnt-show-controls.html [ Slow ]
+
+crbug.com/719298 fast/dnd/dropEffect-for-effectAllowed.html [ Slow ]
diff --git a/third_party/WebKit/LayoutTests/TestExpectations b/third_party/WebKit/LayoutTests/TestExpectations
index 81658f9..f08c741 100644
--- a/third_party/WebKit/LayoutTests/TestExpectations
+++ b/third_party/WebKit/LayoutTests/TestExpectations
@@ -1619,8 +1619,6 @@
 crbug.com/336604 external/wpt/css/css-flexbox-1/flexbox_visibility-collapse.html [ Failure ]
 crbug.com/249112 external/wpt/css/css-flexbox-1/flex-minimum-width-flex-items-006.xht [ Failure ]
 
-crbug.com/727639 inspector/sources/debugger/source-frame-inline-breakpoint-decorations.html [ NeedsManualRebaseline ]
-
 crbug.com/467127 external/wpt/css/css-flexbox-1/flex-aspect-ratio-img-column-003.html [ Failure ]
 crbug.com/467127 external/wpt/css/css-flexbox-1/flex-aspect-ratio-img-row-002.html [ Failure ]
 crbug.com/467127 external/wpt/css/css-flexbox-1/flex-aspect-ratio-img-row-003.html [ Failure ]
@@ -1677,8 +1675,6 @@
 crbug.com/336604 external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/flexbox/flexbox-collapsed-item-horiz-002.html [ Failure ]
 crbug.com/336604 external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/flexbox/flexbox-collapsed-item-horiz-003.html [ Failure ]
 
-crbug.com/726650 inspector/sources/debugger-ui/function-generator-details.html [ NeedsManualRebaseline ]
-
 # We don't correctly implement aspect ratios for images in Flexbox
 crbug.com/531199 external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/flexbox/flexbox-intrinsic-ratio-001.html [ Failure ]
 crbug.com/531199 external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/flexbox/flexbox-intrinsic-ratio-002.html [ Failure ]
@@ -2681,10 +2677,6 @@
 crbug.com/707359 [ Mac ] fast/css-grid-layout/grid-self-baseline-vertical-rl-04.html [ Failure ]
 crbug.com/707359 [ Mac ] fast/css-grid-layout/grid-self-baseline-vertical-rl-05.html [ Failure ]
 
-# [css-align]
-crbug.com/668639 external/wpt/css/css-align-3/default-alignment/place-items-shorthand-006.html [ Failure ]
-crbug.com/668639 external/wpt/css/css-align-3/self-alignment/place-self-shorthand-006.html [ Failure ]
-
 # [selectors-4]
 crbug.com/706118 external/wpt/css/selectors4/hover-001-manual.html [ Skip ]
 crbug.com/576815 external/wpt/css/selectors4/selectors-dir-selector-ltr-001.html [ Failure ]
diff --git a/third_party/WebKit/LayoutTests/css3/flexbox/css-properties-expected.txt b/third_party/WebKit/LayoutTests/css3/flexbox/css-properties-expected.txt
index 9880226f..8ac700e 100644
--- a/third_party/WebKit/LayoutTests/css3/flexbox/css-properties-expected.txt
+++ b/third_party/WebKit/LayoutTests/css3/flexbox/css-properties-expected.txt
@@ -31,12 +31,12 @@
 PASS flexbox.style.justifyContent is ""
 PASS window.getComputedStyle(flexbox, null).justifyContent is "normal"
 PASS flexbox.style.alignSelf is ""
-PASS window.getComputedStyle(flexbox, null).alignSelf is "normal"
-PASS window.getComputedStyle(document.documentElement, null).alignSelf is "normal"
+PASS window.getComputedStyle(flexbox, null).alignSelf is "auto"
+PASS window.getComputedStyle(document.documentElement, null).alignSelf is "auto"
 PASS flexbox.style.alignSelf is ""
-PASS window.getComputedStyle(flexbox, null).alignSelf is "normal"
+PASS window.getComputedStyle(flexbox, null).alignSelf is "auto"
 PASS flexbox.style.alignSelf is "auto"
-PASS window.getComputedStyle(flexbox, null).alignSelf is "normal"
+PASS window.getComputedStyle(flexbox, null).alignSelf is "auto"
 PASS flexbox.style.alignSelf is "flex-start"
 PASS window.getComputedStyle(flexbox, null).alignSelf is "flex-start"
 PASS flexbox.style.alignSelf is "flex-end"
@@ -48,41 +48,41 @@
 PASS flexbox.style.alignSelf is "baseline"
 PASS window.getComputedStyle(flexbox, null).alignSelf is "baseline"
 PASS flexbox.style.alignSelf is ""
-PASS window.getComputedStyle(flexbox, null).alignSelf is "normal"
+PASS window.getComputedStyle(flexbox, null).alignSelf is "auto"
 PASS flexbox.style.alignItems is ""
 PASS flexitem.style.alignSelf is ""
 PASS window.getComputedStyle(flexbox, null).alignItems is "normal"
-PASS window.getComputedStyle(flexitem, null).alignSelf is "normal"
+PASS window.getComputedStyle(flexitem, null).alignSelf is "auto"
 PASS flexbox.style.alignItems is ""
 PASS flexitem.style.alignSelf is ""
 PASS window.getComputedStyle(flexbox, null).alignItems is "normal"
-PASS window.getComputedStyle(flexitem, null).alignSelf is "normal"
+PASS window.getComputedStyle(flexitem, null).alignSelf is "auto"
 PASS flexbox.style.alignItems is ""
 PASS flexitem.style.alignSelf is ""
 PASS window.getComputedStyle(flexbox, null).alignItems is "normal"
-PASS window.getComputedStyle(flexitem, null).alignSelf is "normal"
+PASS window.getComputedStyle(flexitem, null).alignSelf is "auto"
 PASS flexbox.style.alignItems is "flex-start"
 PASS flexitem.style.alignSelf is ""
 PASS window.getComputedStyle(flexbox, null).alignItems is "flex-start"
-PASS window.getComputedStyle(flexitem, null).alignSelf is "flex-start"
+FAIL window.getComputedStyle(flexitem, null).alignSelf should be flex-start. Was auto.
 PASS flexbox.style.alignItems is "flex-end"
 PASS window.getComputedStyle(flexbox, null).alignItems is "flex-end"
-PASS window.getComputedStyle(flexitem, null).alignSelf is "flex-end"
+FAIL window.getComputedStyle(flexitem, null).alignSelf should be flex-end. Was auto.
 PASS flexbox.style.alignItems is "center"
 PASS window.getComputedStyle(flexbox, null).alignItems is "center"
-PASS window.getComputedStyle(flexitem, null).alignSelf is "center"
+FAIL window.getComputedStyle(flexitem, null).alignSelf should be center. Was auto.
 PASS flexbox.style.alignItems is "stretch"
 PASS window.getComputedStyle(flexbox, null).alignItems is "stretch"
-PASS window.getComputedStyle(flexitem, null).alignSelf is "stretch"
+FAIL window.getComputedStyle(flexitem, null).alignSelf should be stretch. Was auto.
 PASS flexbox.style.alignItems is "baseline"
 PASS window.getComputedStyle(flexbox, null).alignItems is "baseline"
-PASS window.getComputedStyle(flexitem, null).alignSelf is "baseline"
+FAIL window.getComputedStyle(flexitem, null).alignSelf should be baseline. Was auto.
 PASS flexbox.style.alignItems is ""
 PASS window.getComputedStyle(flexbox, null).alignItems is "normal"
-PASS window.getComputedStyle(flexitem, null).alignSelf is "normal"
+PASS window.getComputedStyle(flexitem, null).alignSelf is "auto"
 PASS flexbox.style.alignItems is ""
 PASS window.getComputedStyle(flexbox, null).alignItems is "normal"
-PASS window.getComputedStyle(flexitem, null).alignSelf is "normal"
+PASS window.getComputedStyle(flexitem, null).alignSelf is "auto"
 PASS window.getComputedStyle(detachedFlexbox, null).alignSelf is ""
 PASS window.getComputedStyle(detachedFlexItem, null).alignSelf is ""
 PASS flexbox.style.flexDirection is ""
diff --git a/third_party/WebKit/LayoutTests/css3/flexbox/css-properties.html b/third_party/WebKit/LayoutTests/css3/flexbox/css-properties.html
index b95bb5a1..75e796e3 100644
--- a/third_party/WebKit/LayoutTests/css3/flexbox/css-properties.html
+++ b/third_party/WebKit/LayoutTests/css3/flexbox/css-properties.html
@@ -84,17 +84,17 @@
 shouldBeEqualToString('window.getComputedStyle(flexbox, null).justifyContent', 'normal');
 
 shouldBeEqualToString('flexbox.style.alignSelf', '');
-// The initial value is 'auto', which will be resolved depending on parent's style (except for the 'document' element).
-shouldBeEqualToString('window.getComputedStyle(flexbox, null).alignSelf', 'normal');
-shouldBeEqualToString('window.getComputedStyle(document.documentElement, null).alignSelf', 'normal');
+// The initial value is 'auto'.
+shouldBeEqualToString('window.getComputedStyle(flexbox, null).alignSelf', 'auto');
+shouldBeEqualToString('window.getComputedStyle(document.documentElement, null).alignSelf', 'auto');
 
 flexbox.style.alignSelf = 'foo';
 shouldBeEqualToString('flexbox.style.alignSelf', '');
-shouldBeEqualToString('window.getComputedStyle(flexbox, null).alignSelf', 'normal');
+shouldBeEqualToString('window.getComputedStyle(flexbox, null).alignSelf', 'auto');
 
 flexbox.style.alignSelf = 'auto';
 shouldBeEqualToString('flexbox.style.alignSelf', 'auto');
-shouldBeEqualToString('window.getComputedStyle(flexbox, null).alignSelf', 'normal');
+shouldBeEqualToString('window.getComputedStyle(flexbox, null).alignSelf', 'auto');
 
 flexbox.style.alignSelf = 'flex-start';
 shouldBeEqualToString('flexbox.style.alignSelf', 'flex-start');
@@ -118,26 +118,26 @@
 
 flexbox.style.alignSelf = '';
 shouldBeEqualToString('flexbox.style.alignSelf', '');
-shouldBeEqualToString('window.getComputedStyle(flexbox, null).alignSelf', 'normal');
+shouldBeEqualToString('window.getComputedStyle(flexbox, null).alignSelf', 'auto');
 
 shouldBeEqualToString('flexbox.style.alignItems', '');
 shouldBeEqualToString('flexitem.style.alignSelf', '');
-// The initial value is 'auto', which will be resolved to 'normal' in case of flexbox containers.
+// The initial value is 'auto'.
 shouldBeEqualToString('window.getComputedStyle(flexbox, null).alignItems', 'normal');
-shouldBeEqualToString('window.getComputedStyle(flexitem, null).alignSelf', 'normal');
+shouldBeEqualToString('window.getComputedStyle(flexitem, null).alignSelf', 'auto');
 
 flexbox.style.alignItems = 'foo';
 shouldBeEqualToString('flexbox.style.alignItems', '');
 shouldBeEqualToString('flexitem.style.alignSelf', '');
 shouldBeEqualToString('window.getComputedStyle(flexbox, null).alignItems', 'normal');
-shouldBeEqualToString('window.getComputedStyle(flexitem, null).alignSelf', 'normal');
+shouldBeEqualToString('window.getComputedStyle(flexitem, null).alignSelf', 'auto');
 
 // The 'auto' value is not valid for the align-items property.
 flexbox.style.alignItems = 'auto';
 shouldBeEqualToString('flexbox.style.alignItems', '');
 shouldBeEqualToString('flexitem.style.alignSelf', '');
 shouldBeEqualToString('window.getComputedStyle(flexbox, null).alignItems', 'normal');
-shouldBeEqualToString('window.getComputedStyle(flexitem, null).alignSelf', 'normal');
+shouldBeEqualToString('window.getComputedStyle(flexitem, null).alignSelf', 'auto');
 
 flexbox.style.alignItems = 'flex-start';
 shouldBeEqualToString('flexbox.style.alignItems', 'flex-start');
@@ -168,12 +168,12 @@
 flexbox.style.alignItems = '';
 shouldBeEqualToString('flexbox.style.alignItems', '');
 shouldBeEqualToString('window.getComputedStyle(flexbox, null).alignItems', 'normal');
-shouldBeEqualToString('window.getComputedStyle(flexitem, null).alignSelf', 'normal');
+shouldBeEqualToString('window.getComputedStyle(flexitem, null).alignSelf', 'auto');
 
 flexbox.style.display = 'none';
 shouldBeEqualToString('flexbox.style.alignItems', '');
 shouldBeEqualToString('window.getComputedStyle(flexbox, null).alignItems', 'normal');
-shouldBeEqualToString('window.getComputedStyle(flexitem, null).alignSelf', 'normal');
+shouldBeEqualToString('window.getComputedStyle(flexitem, null).alignSelf', 'auto');
 flexbox.style.display = 'flex';
 
 
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-align-3/default-alignment/place-items-shorthand-006.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-align-3/default-alignment/place-items-shorthand-006.html
index 7aa3e88..4af3ad5 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/css/css-align-3/default-alignment/place-items-shorthand-006.html
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-align-3/default-alignment/place-items-shorthand-006.html
@@ -10,7 +10,7 @@
 <script>
     var values = ["normal", "stretch"].concat(selfPositionValues, baselineValues);
     values.forEach(function(alignValue) {
-        ["", "auto"].concat(values).forEach(function(justifyValue) {
+        [""].concat(values).forEach(function(justifyValue) {
             var value = (alignValue + " " + justifyValue).trim();
             test(function() {
                 checkPlaceShorhand("place-items", alignValue, justifyValue)
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-flexbox-1/align-items-006.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-flexbox-1/align-items-006.html
new file mode 100644
index 0000000..f20c8969
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-flexbox-1/align-items-006.html
@@ -0,0 +1,37 @@
+<!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">
+    <head>
+        <title>CSS Test: A flex container with 'column' direction and 'align-items' property set to 'flex-start'</title>
+        <link rel="author" title="Javier Fernandez Garcia-Boente" href="mailto:jfernandez@igalia.com">
+        <link rel="help" href="http://www.w3.org/TR/css-flexbox-1/#align-items-property" />
+        <link rel="help" href="http://www.w3.org/TR/css-flexbox-1/#flex-direction-property" />
+        <link rel="match" href="reference/align-content-001-ref.html" />
+        <meta name="assert" content="This test checks that 'align-items: flex-start' implies the flex item's 'auto' width to be resolved as 'fit-content'." />
+        <style type="text/css">
+            .block {
+                position: absolute;
+                width: 300px;
+                height: 100px;
+            }
+            #flexbox
+            {
+                font: 50px/1 Ahem;
+                background: green;
+                flex-direction: column;
+                align-items: flex-start;
+                display: flex;
+                width: 300px;
+                height: 100px;
+            }
+        </style>
+    </head>
+    <body>
+        <p>Test passes if there is no red visible on the page.</p>
+        <div class="block">
+            <div style="width: 200px; height: 50px; background: green"></div>
+        </div>
+        <div id="flexbox">
+            <div style="background: red; color: red">XXXX</div>
+        </div>
+    </body>
+</html>
diff --git a/third_party/WebKit/LayoutTests/fast/alignment/alignment-and-anomymous-boxes-expected.html b/third_party/WebKit/LayoutTests/fast/alignment/alignment-and-anomymous-boxes-expected.html
index 008235b..6104f18 100644
--- a/third_party/WebKit/LayoutTests/fast/alignment/alignment-and-anomymous-boxes-expected.html
+++ b/third_party/WebKit/LayoutTests/fast/alignment/alignment-and-anomymous-boxes-expected.html
@@ -8,18 +8,18 @@
 }
 .grid { display: grid; }
 .flex { display: flex; }
-.itemsCenter {
-   align-items: center;
-   justify-items: center;
+.selfCenter {
+   align-self: center;
+   justify-self: center;
 }
 </style>
 
 <p>Grid item created as anonymous box to contain the text element. The text element should be centered in both axis due to the Default Alignment 'center' value on its container.</p>
-<div class="container grid itemsCenter">
-    <div>foobar</div>
+<div class="container grid">
+    <div class="selfCenter">foobar</div>
 </div>
 
-<p>Flex item created as anonymous box to contain the text element. The text element should be centered in both axis due to the Default Alignment 'center' value on its container.</p>
-<div class="container flex itemsCenter">
-    <div>foobar</div>
+<p>Flex item created as anonymous box to contain the text element. The text element should be centered in cross axis due to the Default Alignment 'center' value on its container.</p>
+<div class="container flex">
+    <div class="selfCenter">foobar</div>
 </div>
diff --git a/third_party/WebKit/LayoutTests/fast/alignment/alignment-and-anomymous-boxes.html b/third_party/WebKit/LayoutTests/fast/alignment/alignment-and-anomymous-boxes.html
index f7de8d7..e05e095 100644
--- a/third_party/WebKit/LayoutTests/fast/alignment/alignment-and-anomymous-boxes.html
+++ b/third_party/WebKit/LayoutTests/fast/alignment/alignment-and-anomymous-boxes.html
@@ -19,7 +19,7 @@
     foobar
 </div>
 
-<p>Flex item created as anonymous box to contain the text element. The text element should be centered in both axis due to the Default Alignment 'center' value on its container.</p>
+<p>Flex item created as anonymous box to contain the text element. The text element should be centered in cross axis due to the Default Alignment 'center' value on its container.</p>
 <div class="container flex itemsCenter">
     foobar
 </div>
diff --git a/third_party/WebKit/LayoutTests/fast/alignment/ensure-flexbox-compatibility-with-initial-values-expected.txt b/third_party/WebKit/LayoutTests/fast/alignment/ensure-flexbox-compatibility-with-initial-values-expected.txt
index b1a3b03c5..1e0e745 100644
--- a/third_party/WebKit/LayoutTests/fast/alignment/ensure-flexbox-compatibility-with-initial-values-expected.txt
+++ b/third_party/WebKit/LayoutTests/fast/alignment/ensure-flexbox-compatibility-with-initial-values-expected.txt
@@ -6,37 +6,37 @@
 
 Verifying initial values are supported when grid is ENABLED.
 PASS CSS.supports('align-items', 'normal') is true
-PASS CSS.supports('align-self', 'normal') is true
+PASS CSS.supports('align-self', 'auto') is true
 PASS CSS.supports('align-content', 'normal') is true
 PASS CSS.supports('justify-content', 'normal') is true
 PASS CSS.supports('align-items', 'normal') is true
-PASS CSS.supports('align-self', 'normal') is true
+PASS CSS.supports('align-self', 'auto') is true
 PASS CSS.supports('align-content', 'normal') is true
 PASS CSS.supports('justify-content', 'normal') is true
 PASS CSS.supports('align-items', 'normal') is true
-PASS CSS.supports('align-self', 'normal') is true
+PASS CSS.supports('align-self', 'auto') is true
 PASS CSS.supports('align-content', 'normal') is true
 PASS CSS.supports('justify-content', 'normal') is true
 PASS CSS.supports('align-items', 'normal') is true
-PASS CSS.supports('align-self', 'normal') is true
+PASS CSS.supports('align-self', 'auto') is true
 PASS CSS.supports('align-content', 'normal') is true
 PASS CSS.supports('justify-content', 'normal') is true
 
 Verifying initial values are supported when grid is DISABLED.
 PASS CSS.supports('align-items', 'stretch') is true
-PASS CSS.supports('align-self', 'stretch') is true
+PASS CSS.supports('align-self', 'auto') is true
 PASS CSS.supports('align-content', 'stretch') is true
 PASS CSS.supports('justify-content', 'flex-start') is true
 PASS CSS.supports('align-items', 'stretch') is true
-PASS CSS.supports('align-self', 'stretch') is true
+PASS CSS.supports('align-self', 'auto') is true
 PASS CSS.supports('align-content', 'stretch') is true
 PASS CSS.supports('justify-content', 'flex-start') is true
 PASS CSS.supports('align-items', 'stretch') is true
-PASS CSS.supports('align-self', 'stretch') is true
+PASS CSS.supports('align-self', 'auto') is true
 PASS CSS.supports('align-content', 'stretch') is true
 PASS CSS.supports('justify-content', 'flex-start') is true
 PASS CSS.supports('align-items', 'stretch') is true
-PASS CSS.supports('align-self', 'stretch') is true
+PASS CSS.supports('align-self', 'auto') is true
 PASS CSS.supports('align-content', 'stretch') is true
 PASS CSS.supports('justify-content', 'flex-start') is true
 PASS successfullyParsed is true
diff --git a/third_party/WebKit/LayoutTests/fast/alignment/new-alignment-values-invalid-if-grid-not-enabled.html b/third_party/WebKit/LayoutTests/fast/alignment/new-alignment-values-invalid-if-grid-not-enabled.html
index 5bd8055..b767aa9 100644
--- a/third_party/WebKit/LayoutTests/fast/alignment/new-alignment-values-invalid-if-grid-not-enabled.html
+++ b/third_party/WebKit/LayoutTests/fast/alignment/new-alignment-values-invalid-if-grid-not-enabled.html
@@ -29,10 +29,10 @@
     container.style.webkitAlignItems = value;
     if (gridEnabled) {
         checkValues(container, "alignItems", "align-items", value, computedValue);
-        checkValues(item, "alignSelf", "align-self", "auto", computedValue);
+        checkValues(item, "alignSelf", "align-self", "auto", "auto");
     } else {
         checkValues(container, "alignItems", "align-items", "flex-end", "flex-end");
-        checkValues(item, "alignSelf", "align-self", "auto", "flex-end");
+        checkValues(item, "alignSelf", "align-self", "auto", "auto");
     }
 }
 
diff --git a/third_party/WebKit/LayoutTests/fast/alignment/parse-align-self.html b/third_party/WebKit/LayoutTests/fast/alignment/parse-align-self.html
index 149c1a0..8e81f78 100644
--- a/third_party/WebKit/LayoutTests/fast/alignment/parse-align-self.html
+++ b/third_party/WebKit/LayoutTests/fast/alignment/parse-align-self.html
@@ -16,6 +16,10 @@
     align-self: stretch;
 }
 
+#alignSelfNormal {
+    align-self: normal;
+}
+
 #alignSelfStart {
     align-self: start;
 }
@@ -89,6 +93,7 @@
 <div id="alignSelfFirstBaseline"></div>
 <div id="alignSelfLastBaseline"></div>
 <div id="alignSelfStretch"></div>
+<div id="alignSelfNormal"></div>
 <div id="alignSelfStart"></div>
 <div id="alignSelfEnd"></div>
 <div id="alignSelfCenter"></div>
@@ -120,6 +125,8 @@
     checkValues(alignSelfLastBaseline, "alignSelf", "align-self", "", "last baseline");
     var alignSelfStretch = document.getElementById("alignSelfStretch");
     checkValues(alignSelfStretch, "alignSelf", "align-self", "", "stretch");
+    var alignSelfNormal = document.getElementById("alignSelfNormal");
+    checkValues(alignSelfNormal, "alignSelf", "align-self", "", "normal");
     var alignSelfStart = document.getElementById("alignSelfStart");
     checkValues(alignSelfStart, "alignSelf", "align-self", "", "start");
     var alignSelfEnd = document.getElementById("alignSelfEnd");
@@ -160,7 +167,7 @@
 test(function() {
     element = document.createElement("div");
     document.body.appendChild(element);
-    checkValues(element, "alignSelf", "align-self", "", "normal");
+    checkValues(element, "alignSelf", "align-self", "", "auto");
 }, "Test initial value of align-self through JS");
 
 test(function() {
@@ -186,16 +193,19 @@
     element.style.alignSelf = "self-start";
     checkValues(element, "alignSelf", "align-self",  "self-start", "self-start");
 
+    element.style.alignSelf = "normal";
+    checkValues(element, "alignSelf", "align-self",  "normal", "normal");
+
     element.style.alignSelf = "auto";
-    checkValues(element, "alignSelf", "align-self",  "auto", "normal");
+    checkValues(element, "alignSelf", "align-self",  "auto", "auto");
 
     container.style.display = "flex";
     element.style.alignSelf = "auto";
-    checkValues(element, "alignSelf", "align-self",  "auto", "normal");
+    checkValues(element, "alignSelf", "align-self",  "auto", "auto");
 
     container.style.display = "grid";
     element.style.alignSelf = "auto";
-    checkValues(element, "alignSelf", "align-self",  "auto", "normal");
+    checkValues(element, "alignSelf", "align-self",  "auto", "auto");
 
     element.style.alignSelf = "self-end";
     checkValues(element, "alignSelf", "align-self",  "self-end", "self-end");
@@ -203,7 +213,7 @@
 
 test(function() {
     document.documentElement.style.alignSelf = "auto";
-    checkValues(document.documentElement, "alignSelf", "align-self",  "auto", "normal");
+    checkValues(document.documentElement, "alignSelf", "align-self",  "auto", "auto");
 }, "Test 'auto' value resolution for the root node");
 
 test(function() {
@@ -214,6 +224,9 @@
 
     checkBadValues(element, "alignSelf", "align-self",  "auto safe");
     checkBadValues(element, "alignSelf", "align-self",  "auto left");
+    checkBadValues(element, "alignSelf", "align-self",  "normal unsafe");
+    checkBadValues(element, "alignSelf", "align-self",  "normal stretch");
+    checkBadValues(element, "alignSelf", "align-self",  "baseline normal");
     checkBadValues(element, "alignSelf", "align-self",  "baseline safe");
     checkBadValues(element, "alignSelf", "align-self",  "baseline center");
     checkBadValues(element, "alignSelf", "align-self",  "stretch unsafe");
@@ -239,35 +252,35 @@
 
 test(function() {
     container.style.display = "";
-    checkInitialValues(element, "alignSelf", "align-self", "center", "normal");
+    checkInitialValues(element, "alignSelf", "align-self", "center", "auto");
 }, "Test the value 'initial'");
 
 test(function() {
     container.style.display = "grid";
-    checkInitialValues(element, "alignSelf", "align-self", "left safe", "normal");
+    checkInitialValues(element, "alignSelf", "align-self", "left safe", "auto");
 }, "Test the value 'initial' for grid containers");
 
 test(function() {
     container.style.display = "flex";
-    checkInitialValues(element, "alignSelf", "align-self", "right unsafe", "normal");
+    checkInitialValues(element, "alignSelf", "align-self", "right unsafe", "auto");
 }, "Test the value 'initial' for flex containers");
 
 test(function() {
     container.style.display = "";
     element.style.position = "absolute";
-    checkInitialValues(element, "alignSelf", "align-self", "left", "normal");
+    checkInitialValues(element, "alignSelf", "align-self", "left", "auto");
 }, "Test the value 'initial' for positioned elements");
 
 test(function() {
     container.style.display = "grid";
     element.style.position = "absolute";
-    checkInitialValues(element, "alignSelf", "align-self", "right", "normal");
+    checkInitialValues(element, "alignSelf", "align-self", "right", "auto");
 }, "Test the value 'initial' for positioned elements in grid containers");
 
 test(function() {
     container.style.display = "flex";
     element.style.position = "absolute";
-    checkInitialValues(element, "alignSelf", "align-self", "end", "normal");
+    checkInitialValues(element, "alignSelf", "align-self", "end", "auto");
 }, "Test the value 'initial' for positioned elements in grid containers");
 
 test(function() {
diff --git a/third_party/WebKit/LayoutTests/fast/alignment/parse-alignment-of-root-elements-expected.txt b/third_party/WebKit/LayoutTests/fast/alignment/parse-alignment-of-root-elements-expected.txt
deleted file mode 100644
index 7f36c08..0000000
--- a/third_party/WebKit/LayoutTests/fast/alignment/parse-alignment-of-root-elements-expected.txt
+++ /dev/null
@@ -1,30 +0,0 @@
-CONSOLE MESSAGE: line 17: 
-CONSOLE MESSAGE: line 18: *** Test 'auto' value resolution for the document root node. ***
-CONSOLE MESSAGE: line 96: 
-CONSOLE MESSAGE: line 97: *** Test 'auto' value resolution for the shadow DOM root node. ***
-CONSOLE MESSAGE: line 104: 
-CONSOLE MESSAGE: line 149: 
-CONSOLE MESSAGE: line 150: *** Test 'auto' value resolution for the shadow DOM 'slotted' elements. ***
-This is a testharness.js-based test.
-Harness Error. harness_status.status = 1 , harness_status.message = 1 duplicate test name: "Check out how the DOM's root element align-items's value is used to resolve its children's align-self 'auto' values."
-PASS Check out how the DOM's root element resolves the align-self 'auto' values. 
-PASS Check out how the DOM's root element align-items's value is used to resolve its children's align-self 'auto' values. 
-PASS Check out how the DOM's root element deals with 'auto' value in align-items. 
-PASS Check out how the DOM's root element resolves the justify-self 'auto' values. 
-PASS Check out how the DOM's root element align-items's value is used to resolve its children's align-self 'auto' values. 
-PASS Check out how the DOM's root element deals with 'auto' value in justify-items. 
-PASS Check out how the DOM's root element justify-items's value with 'legacy' keyword is used to resolve any descendant's justify-items 'auto' values. 
-PASS Check out how the DOM's root element recomputes its descendant's style when 'legacy' keyword is removed from its justify-items value. 
-PASS Shadow Node inherits from ShadowHost to resolve the 'auto' values for align-self. 
-PASS Shadow Node inherits from ShadowHost to resolve the 'auto' values for justify-self. 
-PASS Check out how the 'legacy' keyword in justify-items propagates from the DOM Tree to the Shadow Node. 
-PASS Check out how align-self uses the 'shadowHost' as 'slotted' element's parent while 'slot' is not assigned. 
-PASS Check out how justify-self uses the 'shadowHost' as 'slotted' element's parent while 'slot' is not assigned. 
-PASS Check out how the 'legacy' keyword in justify-items affects the 'slotted' elements while 'slot' is not assigned. 
-PASS Check out how align-self uses the 'slot' element's parent (Shadow Node) as 'slotted' element' s parent after the 'slot' is assigned. 
-PASS Check out how justify-self uses the 'slot' element's parent (Shadow Node) as 'slotted' element' s parent after the 'slot' is assigned. 
-PASS Check out how the 'legacy' keyword affects the 'slotted' elements after the 'slot' is assigned. 
-PASS The 'slot' element should not use its parent inside the ShadowDOM tree to resolve the align-self 'auto' values because Blink does not support slots in the flat tree. 
-PASS The 'slot' element should not use its parent inside the ShadowDOM tree to resolve the justify-self 'auto' values because Blink does not support slots in the flat tree. 
-Harness: the test ran to completion.
-
diff --git a/third_party/WebKit/LayoutTests/fast/alignment/parse-alignment-of-root-elements.html b/third_party/WebKit/LayoutTests/fast/alignment/parse-alignment-of-root-elements.html
index f55eb56..2143395 100644
--- a/third_party/WebKit/LayoutTests/fast/alignment/parse-alignment-of-root-elements.html
+++ b/third_party/WebKit/LayoutTests/fast/alignment/parse-alignment-of-root-elements.html
@@ -21,7 +21,7 @@
     document.documentElement.style.alignSelf = "center";
     checkValues(document.documentElement, "alignSelf", "align-self", "center", "center");
     document.documentElement.style.alignSelf = "auto";
-    checkValues(document.documentElement, "alignSelf", "align-self", "auto", "normal");
+    checkValues(document.documentElement, "alignSelf", "align-self", "auto", "auto");
 }, "Check out how the DOM's root element resolves the align-self 'auto' values.");
 
 test(function() {
@@ -30,11 +30,11 @@
     document.body.style.alignItems = "auto"; // The 'auto' value is not valid for align-items.
     document.body.style.alignSelf = "auto";
     checkValues(document.body, "alignItems", "align-items", "", "normal");
-    checkValues(document.body, "alignSelf", "align-self", "auto", "center");
+    checkValues(document.body, "alignSelf", "align-self", "auto", "auto");
     block.style.alignItems = ""; // Default value is 'normal' for align-items.
     block.style.alignSelf = "auto";
     checkValues(block, "alignItems", "align-items", "", "normal");
-    checkValues(block, "alignSelf", "align-self", "auto", "normal");
+    checkValues(block, "alignSelf", "align-self", "auto", "auto");
 }, "Check out how the DOM's root element align-items's value is used to resolve its children's align-self 'auto' values.");
 
 test(function() {
@@ -48,7 +48,7 @@
     document.documentElement.style.justifySelf = "left";
     checkValues(document.documentElement, "justifySelf", "justify-self", "left", "left");
     document.documentElement.style.justifySelf = "auto";
-    checkValues(document.documentElement, "justifySelf", "justify-self", "auto", "normal");
+    checkValues(document.documentElement, "justifySelf", "justify-self", "auto", "auto");
 }, "Check out how the DOM's root element resolves the justify-self 'auto' values.");
 
 test(function() {
@@ -58,18 +58,18 @@
     document.body.style.justifyItems = "auto";
     document.body.style.justifySelf = "auto";
     checkValues(document.body, "justifyItems", "justify-items", "auto", "normal");
-    checkValues(document.body, "justifySelf", "justify-self", "auto", "center");
+    checkValues(document.body, "justifySelf", "justify-self", "auto", "auto");
     block.style.justifyItems = "auto";
     block.style.justifySelf = "auto";
     checkValues(block, "justifyItems", "justify-items",  "auto", "normal");
-    checkValues(block, "justifySelf", "justify-self",  "auto", "normal");
-}, "Check out how the DOM's root element align-items's value is used to resolve its children's align-self 'auto' values.");
+    checkValues(block, "justifySelf", "justify-self",  "auto", "auto");
+}, "Check out how the DOM's root element justify-items's value is used to resolve its children's justify-self 'auto' values.");
 
 test(function() {
     document.documentElement.style.justifyItems = "auto";
     checkValues(document.documentElement, "justifyItems", "justify-items", "auto", "normal");
-    checkValues(document.body, "justifySelf", "justify-self",  "auto", "normal");
-    checkValues(block, "justifySelf", "justify-self",  "auto", "normal");
+    checkValues(document.body, "justifySelf", "justify-self",  "auto", "auto");
+    checkValues(block, "justifySelf", "justify-self",  "auto", "auto");
 }, "Check out how the DOM's root element deals with 'auto' value in justify-items.");
 
 test(function() {
@@ -78,19 +78,19 @@
     document.body.style.justifyItems = "auto";
     document.body.style.justifySelf = "auto";
     checkValues(document.body, "justifyItems", "justify-items",  "auto", "legacy center");
-    checkValues(document.body, "justifySelf", "justify-self",  "auto", "center");
+    checkValues(document.body, "justifySelf", "justify-self",  "auto", "auto");
     block.style.justifyItems = "auto";
     block.style.justifySelf = "auto";
     checkValues(block, "justifyItems", "justify-items",  "auto", "legacy center");
-    checkValues(block, "justifySelf", "justify-self",  "auto", "center");
+    checkValues(block, "justifySelf", "justify-self",  "auto", "auto");
 }, "Check out how the DOM's root element justify-items's value with 'legacy' keyword is used to resolve any descendant's justify-items 'auto' values.");
 
 test(function() {
     document.documentElement.style.justifyItems = "auto";
     checkValues(document.body, "justifyItems", "justify-items",  "auto", "normal");
-    checkValues(document.body, "justifySelf", "justify-self",  "auto", "normal");
+    checkValues(document.body, "justifySelf", "justify-self",  "auto", "auto");
     checkValues(block, "justifyItems", "justify-items",  "auto", "normal");
-    checkValues(block, "justifySelf", "justify-self",  "auto", "normal");
+    checkValues(block, "justifySelf", "justify-self",  "auto", "auto");
 }, "Check out how the DOM's root element recomputes its descendant's style when 'legacy' keyword is removed from its justify-items value.");
 
 console.log("");
@@ -112,7 +112,7 @@
     shadowNode.style.alignItems = "";
     checkValues(shadowNode, "alignItems", "align-items", "", "normal");
     shadowNode.style.alignSelf = "auto";
-    checkValues(shadowNode, "alignSelf", "align-self", "auto", "center");
+    checkValues(shadowNode, "alignSelf", "align-self", "auto", "auto");
 }, "Shadow Node inherits from ShadowHost to resolve the 'auto' values for align-self.");
 
 test(function() {
@@ -123,7 +123,7 @@
     shadowNode.style.justifyItems = "";
     checkValues(shadowNode, "justifyItems", "justify-items", "", "normal");
     shadowNode.style.justifySelf = "auto";
-    checkValues(shadowNode, "justifySelf", "justify-self", "auto", "center");
+    checkValues(shadowNode, "justifySelf", "justify-self", "auto", "auto");
 }, "Shadow Node inherits from ShadowHost to resolve the 'auto' values for justify-self.");
 
 test(function() {
@@ -132,14 +132,14 @@
     shadowNode.style.justifySelf = "auto";
     checkValues(shadowHost, "justifyItems", "justify-items", "auto", "normal");
     checkValues(shadowNode, "justifyItems", "justify-items", "right", "right");
-    checkValues(shadowNode, "justifySelf", "justify-self", "auto", "normal");
+    checkValues(shadowNode, "justifySelf", "justify-self", "auto", "auto");
 
     checkValues(shadowHost, "justifyItems", "justify-items", "auto", "normal");
     document.documentElement.style.justifyItems = "legacy center";
     checkValues(document.documentElement, "justifyItems", "justify-items",  "legacy center", "legacy center");
     checkValues(shadowHost, "justifyItems", "justify-items",  "auto", "legacy center");
     checkValues(shadowNode, "justifyItems", "justify-items", "right", "right");
-    checkValues(shadowNode, "justifySelf", "justify-self", "auto", "center");
+    checkValues(shadowNode, "justifySelf", "justify-self", "auto", "auto");
     shadowNode.style.justifyItems = "auto";
     checkValues(shadowNode, "justifyItems", "justify-items", "auto", "legacy center");
     document.documentElement.style.justifyItems = "auto";
@@ -161,7 +161,7 @@
     slotted.style.alignSelf = "start";
     checkValues(slotted, "alignSelf", "align-self", "start", "start");
     slotted.style.alignSelf = "auto";
-    checkValues(slotted, "alignSelf", "align-self", "auto", "normal");
+    checkValues(slotted, "alignSelf", "align-self", "auto", "auto");
 }, "Check out how align-self uses the 'shadowHost' as 'slotted' element's parent while 'slot' is not assigned.");
 
 test(function() {
@@ -174,7 +174,7 @@
     slotted.style.justifySelf = "start";
     checkValues(slotted, "justifySelf", "justify-self", "start", "start");
     slotted.style.justifySelf = "auto";
-    checkValues(slotted, "justifySelf", "justify-self", "auto", "normal");
+    checkValues(slotted, "justifySelf", "justify-self", "auto", "auto");
 }, "Check out how justify-self uses the 'shadowHost' as 'slotted' element's parent while 'slot' is not assigned.");
 
 test(function() {
@@ -188,11 +188,11 @@
     slotted.style.justifyItems = "auto";
     checkValues(slotted, "justifyItems", "justify-items",  "auto", "normal");
     slotted.style.justifySelf = "auto";
-    checkValues(slotted, "justifySelf", "justify-self",  "auto", "normal");
+    checkValues(slotted, "justifySelf", "justify-self",  "auto", "auto");
     shadowNode.style.justifyItems = "auto";
     checkValues(shadowNode, "justifyItems", "justify-items", "auto", "legacy center");
     checkValues(slotted, "justifyItems", "justify-items", "auto", "normal");
-    checkValues(slotted, "justifySelf", "justify-self", "auto", "normal");
+    checkValues(slotted, "justifySelf", "justify-self", "auto", "auto");
     document.documentElement.style.justifyItems = "auto";
 }, "Check out how the 'legacy' keyword in justify-items affects the 'slotted' elements while 'slot' is not assigned.");
 
@@ -211,7 +211,7 @@
     slotted.style.alignSelf = "start";
     checkValues(slotted, "alignSelf", "align-self", "start", "start");
     slotted.style.alignSelf = "auto";
-    checkValues(slotted, "alignSelf", "align-self", "auto", "right");
+    checkValues(slotted, "alignSelf", "align-self", "auto", "auto");
 }, "Check out how align-self uses the 'slot' element's parent (Shadow Node) as 'slotted' element' s parent after the 'slot' is assigned.");
 
 test(function() {
@@ -224,7 +224,7 @@
     slotted.style.justifySelf = "start";
     checkValues(slotted, "justifySelf", "justify-self", "start", "start");
     slotted.style.justifySelf = "auto";
-    checkValues(slotted, "justifySelf", "justify-self", "auto", "right");
+    checkValues(slotted, "justifySelf", "justify-self", "auto", "auto");
 }, "Check out how justify-self uses the 'slot' element's parent (Shadow Node) as 'slotted' element' s parent after the 'slot' is assigned.");
 
 test(function() {
@@ -238,11 +238,11 @@
     slotted.style.justifyItems = "auto";
     checkValues(slotted, "justifyItems", "justify-items", "auto", "normal"); // Shadow host is not the parent now, but ShadowNode.
     slotted.style.justifySelf = "auto";
-    checkValues(slotted, "justifySelf", "justify-self", "auto", "right"); // Shadow host is not the parent now, but ShadowNode.
+    checkValues(slotted, "justifySelf", "justify-self", "auto", "auto"); // Shadow host is not the parent now, but ShadowNode.
     shadowNode.style.justifyItems = "auto";
     checkValues(shadowNode, "justifyItems", "justify-items", "auto", "legacy center");
     checkValues(slotted, "justifyItems", "justify-items", "auto", "legacy center"); // Now that shadowNode is auto, 'legacy' applies.
-    checkValues(slotted, "justifySelf", "justify-self", "auto", "center"); // Now that shadowNode is auto, 'legacy' applies.
+    checkValues(slotted, "justifySelf", "justify-self", "auto", "auto"); // Now that shadowNode is auto, 'legacy' applies.
     document.documentElement.style.justifyItems = "auto";
 }, "Check out how the 'legacy' keyword affects the 'slotted' elements after the 'slot' is assigned.");
 
@@ -256,7 +256,7 @@
     slot.style.alignSelf = "left";
     checkValues(slot, "alignSelf", "align-self",  "left", "left");
     slot.style.alignSelf = "auto";
-    checkValues(slot, "alignSelf", "align-self",  "auto", "normal");
+    checkValues(slot, "alignSelf", "align-self",  "auto", "auto");
 }, "The 'slot' element should not use its parent inside the ShadowDOM tree to resolve the align-self 'auto' values because Blink does not support slots in the flat tree.");
 
 test(function() {
@@ -270,7 +270,7 @@
     slot.style.justifySelf = "left";
     checkValues(slot, "justifySelf", "justify-self",  "left", "left");
     slot.style.justifySelf = "auto";
-    checkValues(slot, "justifySelf", "justify-self",  "auto", "normal");
+    checkValues(slot, "justifySelf", "justify-self",  "auto", "auto");
 }, "The 'slot' element should not use its parent inside the ShadowDOM tree to resolve the justify-self 'auto' values because Blink does not support slots in the flat tree.");
 
 </script>
diff --git a/third_party/WebKit/LayoutTests/fast/alignment/parse-justify-self.html b/third_party/WebKit/LayoutTests/fast/alignment/parse-justify-self.html
index 4a4b760..4e11e1e 100644
--- a/third_party/WebKit/LayoutTests/fast/alignment/parse-justify-self.html
+++ b/third_party/WebKit/LayoutTests/fast/alignment/parse-justify-self.html
@@ -16,6 +16,10 @@
     justify-self: stretch;
 }
 
+#justifySelfNormal {
+    justify-self: normal;
+}
+
 #justifySelfStart {
     justify-self: start;
 }
@@ -89,6 +93,7 @@
 <div id="justifySelfFirstBaseline"></div>
 <div id="justifySelfLastBaseline"></div>
 <div id="justifySelfStretch"></div>
+<div id="justifySelfNormal"></div>
 <div id="justifySelfStart"></div>
 <div id="justifySelfEnd"></div>
 <div id="justifySelfCenter"></div>
@@ -120,6 +125,8 @@
     checkValues(justifySelfLastBaseline, "justifySelf", "justify-self", "", "last baseline");
     var justifySelfStretch = document.getElementById("justifySelfStretch");
     checkValues(justifySelfStretch, "justifySelf", "justify-self", "", "stretch");
+    var justifySelfNormal = document.getElementById("justifySelfNormal");
+    checkValues(justifySelfNormal, "justifySelf", "justify-self", "", "normal");
     var justifySelfStart = document.getElementById("justifySelfStart");
     checkValues(justifySelfStart, "justifySelf", "justify-self", "", "start");
     var justifySelfEnd = document.getElementById("justifySelfEnd");
@@ -160,7 +167,7 @@
 test(function() {
     element = document.createElement("div");
     document.body.appendChild(element);
-    checkValues(element, "justifySelf", "justify-self", "", "normal");
+    checkValues(element, "justifySelf", "justify-self", "", "auto");
 }, "Test initial value of justify-self through JS");
 
 test(function() {
@@ -186,16 +193,19 @@
     element.style.justifySelf = "self-start";
     checkValues(element, "justifySelf", "justify-self",  "self-start", "self-start");
 
+    element.style.justifySelf = "normal";
+    checkValues(element, "justifySelf", "justify-self",  "normal", "normal");
+
     element.style.justifySelf = "auto";
-    checkValues(element, "justifySelf", "justify-self",  "auto", "normal");
+    checkValues(element, "justifySelf", "justify-self",  "auto", "auto");
 
     container.style.display = "flex";
     element.style.justifySelf = "auto";
-    checkValues(element, "justifySelf", "justify-self",  "auto", "normal");
+    checkValues(element, "justifySelf", "justify-self",  "auto", "auto");
 
     container.style.display = "grid";
     element.style.justifySelf = "auto";
-    checkValues(element, "justifySelf", "justify-self",  "auto", "normal");
+    checkValues(element, "justifySelf", "justify-self",  "auto", "auto");
 
     element.style.justifySelf = "self-end";
     checkValues(element, "justifySelf", "justify-self",  "self-end", "self-end");
@@ -203,7 +213,7 @@
 
 test(function() {
     document.documentElement.style.justifySelf = "auto";
-    checkValues(document.documentElement, "justifySelf", "justify-self",  "auto", "normal");
+    checkValues(document.documentElement, "justifySelf", "justify-self",  "auto", "auto");
 }, "Test 'auto' value resolution for the root node");
 
 test(function() {
@@ -215,6 +225,9 @@
     checkBadValues(element, "justifySelf", "justify-self",  "unsafe auto");
     checkBadValues(element, "justifySelf", "justify-self",  "auto safe");
     checkBadValues(element, "justifySelf", "justify-self",  "auto left");
+    checkBadValues(element, "justifySelf", "justify-self",  "normal unsafe");
+    checkBadValues(element, "justifySelf", "justify-self",  "normal stretch");
+    checkBadValues(element, "justifySelf", "justify-self",  "baseline normal");
     checkBadValues(element, "justifySelf", "justify-self",  "baseline safe");
     checkBadValues(element, "justifySelf", "justify-self",  "baseline center");
     checkBadValues(element, "justifySelf", "justify-self",  "stretch unsafe");
@@ -240,35 +253,35 @@
 
 test(function() {
     container.style.display = "";
-    checkInitialValues(element, "justifySelf", "justify-self", "center", "normal");
+    checkInitialValues(element, "justifySelf", "justify-self", "center", "auto");
 }, "Test the value 'initial'");
 
 test(function() {
     container.style.display = "grid";
-    checkInitialValues(element, "justifySelf", "justify-self", "left safe", "normal");
+    checkInitialValues(element, "justifySelf", "justify-self", "left safe", "auto");
 }, "Test the value 'initial' for grid containers");
 
 test(function() {
     container.style.display = "flex";
-    checkInitialValues(element, "justifySelf", "justify-self", "right unsafe", "normal");
+    checkInitialValues(element, "justifySelf", "justify-self", "right unsafe", "auto");
 }, "Test the value 'initial' for flex containers");
 
 test(function() {
     container.style.display = "";
     element.style.position = "absolute";
-    checkInitialValues(element, "justifySelf", "justify-self", "left", "normal");
+    checkInitialValues(element, "justifySelf", "justify-self", "left", "auto");
 }, "Test the value 'initial' for positioned elements");
 
 test(function() {
     container.style.display = "grid";
     element.style.position = "absolute";
-    checkInitialValues(element, "justifySelf", "justify-self", "right", "normal");
+    checkInitialValues(element, "justifySelf", "justify-self", "right", "auto");
 }, "Test the value 'initial' for positioned elements in grid containers");
 
 test(function() {
     container.style.display = "flex";
     element.style.position = "absolute";
-    checkInitialValues(element, "justifySelf", "justify-self", "end", "normal");
+    checkInitialValues(element, "justifySelf", "justify-self", "end", "auto");
 }, "Test the value 'initial' for positioned elements in grid containers");
 
 test(function() {
diff --git a/third_party/WebKit/LayoutTests/fast/alignment/parse-place-content.html b/third_party/WebKit/LayoutTests/fast/alignment/parse-place-content.html
index 36cf4816..1da45347 100644
--- a/third_party/WebKit/LayoutTests/fast/alignment/parse-place-content.html
+++ b/third_party/WebKit/LayoutTests/fast/alignment/parse-place-content.html
@@ -49,6 +49,9 @@
 #placeContentStartSafe {
     place-content: start safe;
 }
+#placeContentBaselineSafe {
+    place-content: baseline safe;
+}
 #placeContentStartEndLeft {
     place-content: start end left;
 }
@@ -204,8 +207,8 @@
 }, "Test setting 'start safe' as incorrect value through CSS.");
 
 test(function() {
-    checkValues(placeContentStartSafe, "placeContent", "place-content", "", "normal normal");
-    checkPlaceContentValues(placeContentStartSafe, "", "normal", "normal");
+    checkValues(placeContentBaselineSafe, "placeContent", "place-content", "", "normal normal");
+    checkPlaceContentValues(placeContentBaselineSafe, "", "normal", "normal");
 }, "Test setting 'baseline safe' as incorrect value through CSS.");
 
 test(function() {
diff --git a/third_party/WebKit/LayoutTests/fast/alignment/parse-place-items.html b/third_party/WebKit/LayoutTests/fast/alignment/parse-place-items.html
index 407da5cc..712bd1e9 100644
--- a/third_party/WebKit/LayoutTests/fast/alignment/parse-place-items.html
+++ b/third_party/WebKit/LayoutTests/fast/alignment/parse-place-items.html
@@ -58,6 +58,9 @@
 #placeItemsStartSafe {
   place-items: start safe;
 }
+#placeItemsBaselineSafe {
+  place-items: baseline safe;
+}
 #placeItemsStartEndLeft {
   place-items: start end left;
 }
@@ -207,8 +210,8 @@
 }, "Test setting 'start safe' as incorrect value through CSS.");
 
 test(function() {
-  checkValues(placeItemsStartSafe, "placeItems", "place-items", "", "normal normal");
-  checkPlaceItemsValues(placeItemsStartSafe, "", "normal", "normal");
+  checkValues(placeItemsBaselineSafe, "placeItems", "place-items", "", "normal normal");
+  checkPlaceItemsValues(placeItemsBaselineSafe, "", "normal", "normal");
 }, "Test setting 'baseline safe' as incorrect value through CSS.");
 
 test(function() {
@@ -224,16 +227,16 @@
 }, "Test setting values through JS.");
 
 test(function() {
-  checkPlaceItemsValuesBadJS("auto normal", "normal", "normal");
-  checkPlaceItemsValuesBadJS("space-between", "normal", "normal");
-  checkPlaceItemsValuesBadJS("center safe", "normal", "normal");
-  checkPlaceItemsValuesBadJS("center self-start center", "normal", "normal");
-  checkPlaceItemsValuesBadJS("asrt", "normal", "normal");
-  checkPlaceItemsValuesBadJS("auto", "normal", "normal");
-  checkPlaceItemsValuesBadJS("10px", "normal", "normal");
-  checkPlaceItemsValuesBadJS("stretch safe", "normal", "normal");
-  checkPlaceItemsValuesBadJS("self-start start end", "normal", "normal");
-  checkPlaceItemsValuesBadJS("", "normal", "normal");
+  checkPlaceItemsValuesBadJS("auto normal");
+  checkPlaceItemsValuesBadJS("space-between");
+  checkPlaceItemsValuesBadJS("center safe");
+  checkPlaceItemsValuesBadJS("center self-start center");
+  checkPlaceItemsValuesBadJS("asrt", "normal");
+  checkPlaceItemsValuesBadJS("auto", "normal");
+  checkPlaceItemsValuesBadJS("10px", "normal");
+  checkPlaceItemsValuesBadJS("stretch safe");
+  checkPlaceItemsValuesBadJS("self-start start end");
+  checkPlaceItemsValuesBadJS("");
 }, "Test setting incorrect values through JS.");
 
 test(function() {
diff --git a/third_party/WebKit/LayoutTests/fast/alignment/parse-place-self.html b/third_party/WebKit/LayoutTests/fast/alignment/parse-place-self.html
index a8e6c0e..4967bdc 100644
--- a/third_party/WebKit/LayoutTests/fast/alignment/parse-place-self.html
+++ b/third_party/WebKit/LayoutTests/fast/alignment/parse-place-self.html
@@ -58,6 +58,9 @@
 #placeSelfStartSafe {
   place-self: start safe;
 }
+#placeSelfBaselineSafe {
+  place-self: baseline safe;
+}
 #placeSelfStartEndLeft {
   place-self: start end left;
 }
@@ -113,7 +116,7 @@
 {
   element.style.placeSelf = "";
   element.style.placeSelf = value;
-  checkPlaceSelfValues(element, "", "normal", "normal")
+  checkPlaceSelfValues(element, "", "auto", "auto")
 }
 
 test(function() {
@@ -122,8 +125,8 @@
 }, "Test getting the Computed Value of place-self's longhand properties when setting 'normal' value through CSS.");
 
 test(function() {
-  checkValues(placeSelfCenterAuto, "placeSelf", "place-self", "", "center normal");
-  checkPlaceSelfValues(placeSelfCenterAuto, "", "center", "normal");
+  checkValues(placeSelfCenterAuto, "placeSelf", "place-self", "", "center auto");
+  checkPlaceSelfValues(placeSelfCenterAuto, "", "center", "auto");
 }, "Test getting the Computed Value of place-self's longhand properties when setting 'center auto' value through CSS.");
 
 test(function() {
@@ -182,38 +185,38 @@
 }, "Test getting the Computed Value of place-self's longhand properties when setting 'start baseline' value through CSS.");
 
 test(function() {
-  checkValues(placeSelfAuto, "placeSelf", "place-self", "", "normal normal");
-  checkPlaceSelfValues(placeSelfAuto, "", "normal", "normal");
+  checkValues(placeSelfEmpty, "placeSelf", "place-self", "", "auto auto");
+  checkPlaceSelfValues(placeSelfEmpty, "", "auto", "auto");
 }, "Test setting '' as incorrect value through CSS.");
 
 test(function() {
-  checkValues(placeSelfAuto, "placeSelf", "place-self", "", "normal normal");
-  checkPlaceSelfValues(placeSelfAuto, "", "normal", "normal");
+  checkValues(placeSelfAuto, "placeSelf", "place-self", "", "auto auto");
+  checkPlaceSelfValues(placeSelfAuto, "", "auto", "auto");
 }, "Test setting 'auto' as incorrect value through CSS.");
 
 test(function() {
-  checkValues(placeSelfNone, "placeSelf", "place-self", "", "normal normal");
-  checkPlaceSelfValues(placeSelfNone, "", "normal", "normal");
+  checkValues(placeSelfNone, "placeSelf", "place-self", "", "auto auto");
+  checkPlaceSelfValues(placeSelfNone, "", "auto", "auto");
 }, "Test setting 'none' as incorrect value through CSS.");
 
 test(function() {
-  checkValues(placeSelfSafe, "placeSelf", "place-self", "", "normal normal");
-  checkPlaceSelfValues(placeSelfSafe, "", "normal", "normal");
+  checkValues(placeSelfSafe, "placeSelf", "place-self", "", "auto auto");
+  checkPlaceSelfValues(placeSelfSafe, "", "auto", "auto");
 }, "Test setting 'safe' as incorrect value through CSS.");
 
 test(function() {
-  checkValues(placeSelfStartSafe, "placeSelf", "place-self", "", "normal normal");
-  checkPlaceSelfValues(placeSelfStartSafe, "", "normal", "normal");
+  checkValues(placeSelfStartSafe, "placeSelf", "place-self", "", "auto auto");
+  checkPlaceSelfValues(placeSelfStartSafe, "", "auto", "auto");
 }, "Test setting 'start safe' as incorrect value through CSS.");
 
 test(function() {
-  checkValues(placeSelfStartSafe, "placeSelf", "place-self", "", "normal normal");
-  checkPlaceSelfValues(placeSelfStartSafe, "", "normal", "normal");
+  checkValues(placeSelfBaselineSafe, "placeSelf", "place-self", "", "auto auto");
+  checkPlaceSelfValues(placeSelfBaselineSafe, "", "auto", "auto");
 }, "Test setting 'baseline safe' as incorrect value through CSS.");
 
 test(function() {
-  checkValues(placeSelfStartEndLeft, "placeSelf", "place-self", "", "normal normal");
-  checkPlaceSelfValues(placeSelfStartEndLeft, "", "normal", "normal");
+  checkValues(placeSelfStartEndLeft, "placeSelf", "place-self", "", "auto auto");
+  checkPlaceSelfValues(placeSelfStartEndLeft, "", "auto", "auto");
 }, "Test setting 'start end left' as incorrect value through CSS.");
 
 test(function() {
@@ -221,35 +224,36 @@
   checkPlaceSelfValuesJS("center start", "center", "start");
   checkPlaceSelfValuesJS("self-start end", "self-start", "end");
   checkPlaceSelfValuesJS("normal end", "normal", "end");
+  checkPlaceSelfValuesJS("auto right", "auto", "right");
 }, "Test setting values through JS.");
 
 test(function() {
-  checkPlaceSelfValuesBadJS("space-between", "normal", "normal");
-  checkPlaceSelfValuesBadJS("center safe", "normal", "normal");
-  checkPlaceSelfValuesBadJS("center self-start center", "normal", "normal");
-  checkPlaceSelfValuesBadJS("asrt", "normal", "normal");
-  checkPlaceSelfValuesBadJS("10px", "normal", "normal");
-  checkPlaceSelfValuesBadJS("stretch safe", "normal", "normal");
-  checkPlaceSelfValuesBadJS("self-start start end", "normal", "normal");
-  checkPlaceSelfValuesBadJS("", "normal", "normal");
+  checkPlaceSelfValuesBadJS("space-between");
+  checkPlaceSelfValuesBadJS("center safe");
+  checkPlaceSelfValuesBadJS("center self-start center");
+  checkPlaceSelfValuesBadJS("asrt");
+  checkPlaceSelfValuesBadJS("10px");
+  checkPlaceSelfValuesBadJS("stretch safe");
+  checkPlaceSelfValuesBadJS("self-start start end");
+  checkPlaceSelfValuesBadJS("");
 }, "Test setting incorrect values through JS.");
 
 test(function() {
   element = document.createElement("div");
   document.body.appendChild(element);
-  checkValues(element, "placeSelf", "place-self", "", "normal normal");
+  checkValues(element, "placeSelf", "place-self", "", "auto auto");
   element.style.placeSelf = "center";
   checkPlaceSelfValues(element, "center", "center", "center");
   element.style.placeSelf = "initial";
-  checkValues(element, "placeSelf", "place-self", "initial", "normal normal");
-  checkPlaceSelfValues(element, "initial", "normal", "normal");
+  checkValues(element, "placeSelf", "place-self", "initial", "auto auto");
+  checkPlaceSelfValues(element, "initial", "auto", "auto");
 }, "Test the 'initial' value of the place-self shorthand and its longhand properties' Computed value");
 
 test(function() {
   document.body.style.placeSelf = "start";
   var anotherElement = document.createElement("div");
   document.body.appendChild(anotherElement);
-  checkPlaceSelfValues(anotherElement, "", "normal", "normal");
+  checkPlaceSelfValues(anotherElement, "", "auto", "auto");
   anotherElement.style.placeSelf = "inherit";
   checkPlaceSelfValues(anotherElement, "inherit", "start", "start");
 }, "Test the 'inherit' value of the place-self shorthand and its longhand properties' Computed value");
diff --git a/third_party/WebKit/LayoutTests/fast/css/getComputedStyle/computed-style-listing-expected.txt b/third_party/WebKit/LayoutTests/fast/css/getComputedStyle/computed-style-listing-expected.txt
index cdc5172..e1e19f09 100644
--- a/third_party/WebKit/LayoutTests/fast/css/getComputedStyle/computed-style-listing-expected.txt
+++ b/third_party/WebKit/LayoutTests/fast/css/getComputedStyle/computed-style-listing-expected.txt
@@ -60,7 +60,7 @@
 -webkit-writing-mode: horizontal-tb
 align-content: normal
 align-items: normal
-align-self: normal
+align-self: auto
 alignment-baseline: auto
 animation-delay: 0s
 animation-direction: normal
@@ -181,7 +181,7 @@
 isolation: auto
 justify-content: normal
 justify-items: normal
-justify-self: normal
+justify-self: auto
 left: auto
 letter-spacing: normal
 lighting-color: rgb(255, 255, 255)
diff --git a/third_party/WebKit/LayoutTests/fast/css/getComputedStyle/computed-style-without-renderer-listing-expected.txt b/third_party/WebKit/LayoutTests/fast/css/getComputedStyle/computed-style-without-renderer-listing-expected.txt
index 0fc97ee..95a01f87 100644
--- a/third_party/WebKit/LayoutTests/fast/css/getComputedStyle/computed-style-without-renderer-listing-expected.txt
+++ b/third_party/WebKit/LayoutTests/fast/css/getComputedStyle/computed-style-without-renderer-listing-expected.txt
@@ -60,7 +60,7 @@
 -webkit-writing-mode: horizontal-tb
 align-content: normal
 align-items: normal
-align-self: normal
+align-self: auto
 alignment-baseline: auto
 animation-delay: 0s
 animation-direction: normal
@@ -181,7 +181,7 @@
 isolation: auto
 justify-content: normal
 justify-items: normal
-justify-self: normal
+justify-self: auto
 left: auto
 letter-spacing: normal
 lighting-color: rgb(255, 255, 255)
diff --git a/third_party/WebKit/LayoutTests/fast/scroll-behavior/scroll-customization/touch-scroll-customization.html b/third_party/WebKit/LayoutTests/fast/scroll-behavior/scroll-customization/touch-scroll-customization.html
index 05057cd..5248363 100644
--- a/third_party/WebKit/LayoutTests/fast/scroll-behavior/scroll-customization/touch-scroll-customization.html
+++ b/third_party/WebKit/LayoutTests/fast/scroll-behavior/scroll-customization/touch-scroll-customization.html
@@ -204,12 +204,14 @@
       assert_equals(document.scrollingElement.scrollTop, scrollingElementTop, "For scrollingElement on step " + step);
     };
 
+    assertScrollTops(0, 0, 0, 0);
+
     var frame_actions = [
       function() {
         eventSender.gestureFlingStart(10, 10, -1000000, -1000000, "touchscreen");
       },
       flingTest.step_func(function() {
-        assertScrollTops(0, 0, 0, 1);
+        assertScrollTops(100, 0, 0, 1);
       }),
       flingTest.step_func(function() {
         assertScrollTops(100, 0, 0, 2);
diff --git a/third_party/WebKit/LayoutTests/http/tests/inspector-enabled/reattach-after-editing-styles.html b/third_party/WebKit/LayoutTests/http/tests/inspector-enabled/reattach-after-editing-styles.html
index b844dba..92c08ea0 100644
--- a/third_party/WebKit/LayoutTests/http/tests/inspector-enabled/reattach-after-editing-styles.html
+++ b/third_party/WebKit/LayoutTests/http/tests/inspector-enabled/reattach-after-editing-styles.html
@@ -30,80 +30,72 @@
     runTest();
 }
 
-function test()
+async function test()
 {
-    InspectorTest.RuntimeAgent.evaluate("window.didReopen", dispatch);
+    var result = await InspectorTest.RuntimeAgent.evaluate("window.didReopen");
 
-    function dispatch(error, result, exceptionDetails)
-    {
-        if (result.type !== "number") {
-            InspectorTest.addResult("Opening front-end for the first time");
-            testFirstOpen();
-        } else {
-            InspectorTest.addResult("Opening front-end second time");
-            InspectorTest.addResult("Dump styles after inspector was reopened:");
-            dump(InspectorTest.completeTest);
-        }
-    }
-
-    function testFirstOpen()
-    {
+    if (result.type !== "number") {
+        InspectorTest.addResult("Opening front-end for the first time");
         InspectorTest.addResult("Dump initial styles:");
         dump(onStylesDumped);
+    } else {
+        InspectorTest.addResult("Opening front-end second time");
+        InspectorTest.addResult("Dump styles after inspector was reopened:");
+        dump(InspectorTest.completeTest);
+    }
 
-        function onStylesDumped()
-        {
-            treeElement = InspectorTest.getMatchedStylePropertyTreeItem("color");
-            treeElement.startEditing();
-            treeElement.nameElement.textContent = "color";
-            treeElement.nameElement.dispatchEvent(InspectorTest.createKeyEvent("Enter"));
+    function onStylesDumped()
+    {
+        treeElement = InspectorTest.getMatchedStylePropertyTreeItem("color");
+        treeElement.startEditing();
+        treeElement.nameElement.textContent = "color";
+        treeElement.nameElement.dispatchEvent(InspectorTest.createKeyEvent("Enter"));
 
-            // Commit editing.
-            treeElement.valueElement.textContent = "green";
-            treeElement.valueElement.firstChild.select();
-            treeElement.valueElement.dispatchEvent(InspectorTest.createKeyEvent("Enter"));
-            InspectorTest.waitForStyleApplied(onStyleSheetPropertyEdited);
-        }
+        // Commit editing.
+        treeElement.valueElement.textContent = "green";
+        treeElement.valueElement.firstChild.select();
+        treeElement.valueElement.dispatchEvent(InspectorTest.createKeyEvent("Enter"));
+        InspectorTest.waitForStyleApplied(onStyleSheetPropertyEdited);
+    }
 
-        function onStyleSheetPropertyEdited()
-        {
-            treeElement = InspectorTest.getMatchedStylePropertyTreeItem("font-family");
-            treeElement.startEditing();
-            treeElement.nameElement.textContent = "font-family";
-            treeElement.nameElement.dispatchEvent(InspectorTest.createKeyEvent("Enter"));
+    function onStyleSheetPropertyEdited()
+    {
+        treeElement = InspectorTest.getMatchedStylePropertyTreeItem("font-family");
+        treeElement.startEditing();
+        treeElement.nameElement.textContent = "font-family";
+        treeElement.nameElement.dispatchEvent(InspectorTest.createKeyEvent("Enter"));
 
-            // Commit editing.
-            treeElement.valueElement.textContent = "Helvetica";
-            treeElement.valueElement.firstChild.select();
-            treeElement.valueElement.dispatchEvent(InspectorTest.createKeyEvent("Enter"));
-            InspectorTest.waitForStyleApplied(onStyleTagPropertyEdited);
-        }
+        // Commit editing.
+        treeElement.valueElement.textContent = "Helvetica";
+        treeElement.valueElement.firstChild.select();
+        treeElement.valueElement.dispatchEvent(InspectorTest.createKeyEvent("Enter"));
+        InspectorTest.waitForStyleApplied(onStyleTagPropertyEdited);
+    }
 
-        function onStyleTagPropertyEdited()
-        {
-            InspectorTest.addNewRule("#testDiv, my-custom-tag", onFirstRuleAdded);
-        }
+    function onStyleTagPropertyEdited()
+    {
+        InspectorTest.addNewRule("#testDiv, my-custom-tag", onFirstRuleAdded);
+    }
 
-        function onFirstRuleAdded()
-        {
-            InspectorTest.addNewRule("#testDiv, another-custom-tag", onSecondRuleAdded);
-        }
+    function onFirstRuleAdded()
+    {
+        InspectorTest.addNewRule("#testDiv, another-custom-tag", onSecondRuleAdded);
+    }
 
-        function onSecondRuleAdded()
-        {
-            InspectorTest.domModel.undo(onRuleRemoved);
-        }
+    function onSecondRuleAdded()
+    {
+        InspectorTest.domModel.undo().then(onRuleRemoved);
+    }
 
-        function onRuleRemoved()
-        {
-            InspectorTest.selectNodeAndWaitForStyles("other", step4);
-        }
+    function onRuleRemoved()
+    {
+        InspectorTest.selectNodeAndWaitForStyles("other", step4);
+    }
 
-        function step4()
-        {
-            InspectorTest.addResult("Dump styles after editing:");
-            dump(reopenInspector);
-        }
+    function step4()
+    {
+        InspectorTest.addResult("Dump styles after editing:");
+        dump(reopenInspector);
     }
 
     function reopenInspector()
diff --git a/third_party/WebKit/LayoutTests/http/tests/inspector/elements-test.js b/third_party/WebKit/LayoutTests/http/tests/inspector/elements-test.js
index d965cc1..52f778e 100644
--- a/third_party/WebKit/LayoutTests/http/tests/inspector/elements-test.js
+++ b/third_party/WebKit/LayoutTests/http/tests/inspector/elements-test.js
@@ -104,36 +104,22 @@
             callback(null);
     }
 
-    InspectorTest.domModel.requestDocument(documentRequested.bind(this));
-    function documentRequested(doc)
-    {
+    InspectorTest.domModel.requestDocument(doc => {
         pendingRequests++;
         doc.getChildNodes(processChildren.bind(null, doc));
-    }
+    });
 };
 
 InspectorTest.nodeWithId = function(idValue, callback)
 {
-    function nodeIdMatches(node)
-    {
-        return node.getAttribute("id") === idValue;
-    }
-    InspectorTest.findNode(nodeIdMatches, callback);
+    InspectorTest.findNode(node => node.getAttribute("id") === idValue, callback);
 }
 
-InspectorTest.querySelector = function(selector, callback)
+InspectorTest.querySelector = async function(selector, callback)
 {
-    InspectorTest.domModel.requestDocument(documentRequested.bind(this));
-
-    function documentRequested(doc)
-    {
-        InspectorTest.domModel.querySelector(doc.id, selector, nodeSelected);
-    }
-
-    function nodeSelected(nodeId)
-    {
-        callback(InspectorTest.domModel.nodeForId(nodeId));
-    }
+    var doc = await InspectorTest.domModel.requestDocumentPromise();
+    var nodeId = await InspectorTest.domModel.querySelector(doc.id, selector);
+    callback(InspectorTest.domModel.nodeForId(nodeId));
 }
 
 InspectorTest.shadowRootByHostId = function(idValue, callback)
@@ -158,11 +144,7 @@
 InspectorTest.expandedNodeWithId = function(idValue)
 {
     var result;
-    function callback(node)
-    {
-        result = node;
-    }
-    InspectorTest.nodeWithId(idValue, callback);
+    InspectorTest.nodeWithId(idValue, node => result = node);
     return result;
 }
 
@@ -766,7 +748,7 @@
                     InspectorTest.addResult("== Expanded: ==");
                     InspectorTest.dumpElementsTree(testNode);
                 }
-                InspectorTest.domModel.undo(redo);
+                InspectorTest.domModel.undo().then(redo);
             }
         }
 
@@ -782,7 +764,7 @@
                     InspectorTest.addResult("== Expanded: ==");
                     InspectorTest.dumpElementsTree(testNode);
                 }
-                InspectorTest.domModel.redo(done);
+                InspectorTest.domModel.redo().then(done);
             }
         }
 
diff --git a/third_party/WebKit/LayoutTests/inspector/elements/edit/perform-undo-undo.html b/third_party/WebKit/LayoutTests/inspector/elements/edit/perform-undo-undo.html
index ce590be..0c320ad 100644
--- a/third_party/WebKit/LayoutTests/inspector/elements/edit/perform-undo-undo.html
+++ b/third_party/WebKit/LayoutTests/inspector/elements/edit/perform-undo-undo.html
@@ -28,26 +28,15 @@
         containerNode.setAttribute("", "foo=\"bar\"", callback);
     }
 
-    function step3()
+    async function step3()
     {
-        function callback()
-        {
-            InspectorTest.addResult("===== Undo 1 =====");
-            InspectorTest.dumpElementsTree(containerNode);
-            step4();
-        }
-        InspectorTest.domModel.undo(callback);
-    }
+        await InspectorTest.domModel.undo();
+        InspectorTest.addResult("===== Undo 1 =====");
+        InspectorTest.dumpElementsTree(containerNode);
 
-    function step4()
-    {
-        function callback()
-        {
-            InspectorTest.addResult("===== Undo 2 =====");
-            InspectorTest.dumpElementsTree(containerNode);
-            InspectorTest.completeTest();
-        }
-        InspectorTest.domModel.undo(callback);
+        InspectorTest.addResult("===== Undo 2 =====");
+        InspectorTest.dumpElementsTree(containerNode);
+        InspectorTest.completeTest();
     }
 }
 
diff --git a/third_party/WebKit/LayoutTests/inspector/elements/edit/set-outer-html-test.js b/third_party/WebKit/LayoutTests/inspector/elements/edit/set-outer-html-test.js
index d552395..98d8d9f5 100644
--- a/third_party/WebKit/LayoutTests/inspector/elements/edit/set-outer-html-test.js
+++ b/third_party/WebKit/LayoutTests/inspector/elements/edit/set-outer-html-test.js
@@ -15,10 +15,10 @@
     function step2(node)
     {
         InspectorTest.containerId = node.id;
-        InspectorTest.DOMAgent.getOuterHTML(InspectorTest.containerId, step3);
+        InspectorTest.DOMAgent.getOuterHTML(InspectorTest.containerId).then(step3);
     }
 
-    function step3(error, text)
+    function step3(text)
     {
         InspectorTest.containerText = text;
 
@@ -73,41 +73,38 @@
 {
     InspectorTest.innerSetOuterHTML(newText, false, bringBack);
 
-    function bringBack()
+    async function bringBack()
     {
         InspectorTest.addResult("\nBringing things back\n");
-        InspectorTest.domModel.undo(InspectorTest._dumpOuterHTML.bind(InspectorTest, true, next));
+        await InspectorTest.domModel.undo();
+        InspectorTest._dumpOuterHTML(true, next);
     }
 }
 
-InspectorTest.innerSetOuterHTML = function(newText, last, next)
+InspectorTest.innerSetOuterHTML = async function(newText, last, next)
 {
-    InspectorTest.DOMAgent.setOuterHTML(InspectorTest.containerId, newText, InspectorTest._dumpOuterHTML.bind(InspectorTest, last, next));
+    await InspectorTest.DOMAgent.setOuterHTML(InspectorTest.containerId, newText);
+    InspectorTest._dumpOuterHTML(last, next);
 }
 
-InspectorTest._dumpOuterHTML = function(last, next)
+InspectorTest._dumpOuterHTML = async function(last, next)
 {
-    InspectorTest.RuntimeAgent.evaluate("document.getElementById(\"identity\").wrapperIdentity", dumpIdentity);
-    function dumpIdentity(error, result)
-    {
-        InspectorTest.addResult("Wrapper identity: " + result.value);
-        InspectorTest.events.sort();
-        for (var i = 0; i < InspectorTest.events.length; ++i)
-            InspectorTest.addResult(InspectorTest.events[i]);
-        InspectorTest.events = [];
-    }
+    var result = await InspectorTest.RuntimeAgent.evaluate("document.getElementById(\"identity\").wrapperIdentity");
 
-    InspectorTest.DOMAgent.getOuterHTML(InspectorTest.containerId, callback);
+    InspectorTest.addResult("Wrapper identity: " + result.value);
+    InspectorTest.events.sort();
+    for (var i = 0; i < InspectorTest.events.length; ++i)
+        InspectorTest.addResult(InspectorTest.events[i]);
+    InspectorTest.events = [];
 
-    function callback(error, text)
-    {
-        InspectorTest.addResult("==========8<==========");
-        InspectorTest.addResult(text);
-        InspectorTest.addResult("==========>8==========");
-        if (last)
-            InspectorTest.addResult("\n\n\n");
-        next();
-    }
+    var text = await InspectorTest.DOMAgent.getOuterHTML(InspectorTest.containerId);
+
+    InspectorTest.addResult("==========8<==========");
+    InspectorTest.addResult(text);
+    InspectorTest.addResult("==========>8==========");
+    if (last)
+        InspectorTest.addResult("\n\n\n");
+    next();
 }
 
 };
diff --git a/third_party/WebKit/LayoutTests/inspector/elements/edit/undo-dom-edits-2.html b/third_party/WebKit/LayoutTests/inspector/elements/edit/undo-dom-edits-2.html
index 50cfacf6..fc5b542 100644
--- a/third_party/WebKit/LayoutTests/inspector/elements/edit/undo-dom-edits-2.html
+++ b/third_party/WebKit/LayoutTests/inspector/elements/edit/undo-dom-edits-2.html
@@ -20,10 +20,9 @@
     }
     testSuite.push(testSetUp);
 
-
     function testSetAttribute(callback)
     {
-        var node = InspectorTest.expandedNodeWithId("node-to-set-attribute"); 
+        var node = InspectorTest.expandedNodeWithId("node-to-set-attribute");
         node.setAttribute("foo", "bar=\"edited attribute\"", callback);
     }
     testSuite.push(InspectorTest.generateUndoTest(testSetAttribute));
@@ -31,15 +30,15 @@
 
     function testRemoveAttribute(callback)
     {
-        var node = InspectorTest.expandedNodeWithId("node-to-remove-attribute"); 
-        node.removeAttribute("foo", callback);
+        var node = InspectorTest.expandedNodeWithId("node-to-remove-attribute");
+        node.removeAttribute("foo").then(callback);
     }
     testSuite.push(InspectorTest.generateUndoTest(testRemoveAttribute));
 
 
     function testAddAttribute(callback)
     {
-        var node = InspectorTest.expandedNodeWithId("node-to-add-attribute"); 
+        var node = InspectorTest.expandedNodeWithId("node-to-add-attribute");
         node.setAttribute("", "newattr=\"new-value\"", callback);
     }
     testSuite.push(InspectorTest.generateUndoTest(testAddAttribute));
diff --git a/third_party/WebKit/LayoutTests/inspector/elements/elements-panel-search.html b/third_party/WebKit/LayoutTests/inspector/elements/elements-panel-search.html
index 768bdb8..6f3b1f3 100644
--- a/third_party/WebKit/LayoutTests/inspector/elements/elements-panel-search.html
+++ b/third_party/WebKit/LayoutTests/inspector/elements/elements-panel-search.html
@@ -16,32 +16,25 @@
 {
     var omitInnerHTML;
 
-    function searchCallback(next, resultCount)
+    async function searchCallback(next, resultCount)
     {
         if (resultCount == 0) {
             InspectorTest.addResult("Nothing found");
             SDK.DOMModel.cancelSearch();
             next();
+            return;
         }
 
-        for (var i = 0; i < resultCount; ++i)
-            InspectorTest.domModel.searchResult(i, searchResultCallback.bind(this, i + 1 === resultCount));
-
-        function searchResultCallback(isLastItem, node)
-        {
-            node.getOuterHTML(addSearchResult.bind(this, isLastItem));
-        }
-
-        function addSearchResult(isLastItem, error, markupVa_lue)
-        {
+        for (var i = 0; i < resultCount; ++i) {
+            var node = await InspectorTest.domModel.searchResult(i);
+            var markupVa_lue = await node.getOuterHTML();
             if (omitInnerHTML)
                 markupVa_lue = markupVa_lue.substr(0, markupVa_lue.indexOf(">") + 1);
             InspectorTest.addResult(markupVa_lue.split("").join(" "));
-            if (isLastItem) {
-                SDK.DOMModel.cancelSearch();
-                next();
-            }
         }
+
+        SDK.DOMModel.cancelSearch();
+        next();
     }
 
     function setUp(next)
diff --git a/third_party/WebKit/LayoutTests/media/autoplay/document-user-activation.html b/third_party/WebKit/LayoutTests/media/autoplay/document-user-activation.html
new file mode 100644
index 0000000..73a085d
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/media/autoplay/document-user-activation.html
@@ -0,0 +1,216 @@
+<!DOCTYPE html>
+<title>Test document user gesture autoplay policy</title>
+<script src='../../resources/testharness.js'></script>
+<script src='../../resources/testharnessreport.js'></script>
+<script src='../media-file.js'></script>
+<body>
+  <div id='target'>target</div>
+</body>
+<script>
+promise_test(t => {
+  t.add_cleanup(() => {
+    window.internals.settings.setAutoplayPolicy('no-user-gesture-required');
+  });
+
+  window.internals.settings.setAutoplayPolicy('document-user-activation-required');
+
+  var video = document.createElement('video');
+  video.src = findMediaFile('video', '../content/test');
+  return promise_rejects(t, 'NotAllowedError', video.play());
+}, 'Not allowed to autoplay without some sort of user gesture');
+
+promise_test(t => {
+  t.add_cleanup(() => {
+    window.internals.settings.setAutoplayPolicy('no-user-gesture-required');
+  });
+
+  window.internals.settings.setAutoplayPolicy('document-user-activation-required');
+  document.querySelector('#target').focus();
+  eventSender.keyDown('a');
+
+  var video = document.createElement('video');
+  video.src = findMediaFile('video', '../content/test');
+  return video.play();
+}, 'Allowed to autoplay if the document received a key event');
+
+promise_test(t => {
+  t.add_cleanup(() => {
+    window.internals.settings.setAutoplayPolicy('no-user-gesture-required');
+  });
+
+  window.internals.settings.setAutoplayPolicy('document-user-activation-required');
+  var bounds = document.querySelector('#target').getBoundingClientRect();
+  var x = bounds.left + bounds.width / 2;
+  var y = bounds.top + bounds.height / 2;
+  chrome.gpuBenchmarking.pointerActionSequence([{
+    'source': 'mouse',
+    'actions': [
+      { 'name': 'pointerDown', 'x': x, 'y': y },
+      { 'name': 'pointerUp' },
+    ],
+  }]);
+
+  var video = document.createElement('video');
+  video.src = findMediaFile('video', '../content/test');
+  return video.play();
+}, 'Allowed to autoplay if the document received a click');
+
+// TODO(mlamouri): should not be allowed to autoplay if the document only
+// received a mouse down or up.
+
+// TODO(mlamouri): should not be allowed to autoplay if the document only
+// received a mouse wheel event.
+
+promise_test(t => {
+  t.add_cleanup(() => {
+    window.internals.settings.setAutoplayPolicy('no-user-gesture-required');
+  });
+
+  window.internals.settings.setAutoplayPolicy('document-user-activation-required');
+  var bounds = document.querySelector('#target').getBoundingClientRect();
+  var x = bounds.left + bounds.width / 2;
+  var y = bounds.top + bounds.height / 2;
+  chrome.gpuBenchmarking.pointerActionSequence([{
+    'source': 'touch',
+    'actions': [
+      { 'name': 'pointerDown', 'x': x, 'y': y },
+      { 'name': 'pointerUp' },
+    ],
+  }]);
+
+  var video = document.createElement('video');
+  video.src = findMediaFile('video', '../content/test');
+  return video.play();
+}, 'Allowed to autoplay if the document received a tap');
+
+// TODO(mlamouri): should not allowed to autoplay if the document only received
+// a tap down or up.
+
+// TODO(mlamouri): should not allowed to autoplay if the document was scrolled
+// with touch events.
+
+promise_test(t => {
+  t.add_cleanup(() => {
+    window.internals.settings.setAutoplayPolicy('no-user-gesture-required');
+  });
+
+  window.internals.settings.setAutoplayPolicy('document-user-activation-required');
+  var bounds = document.querySelector('#target').getBoundingClientRect();
+  var x = bounds.left + bounds.width / 2;
+  var y = bounds.top + bounds.height / 2;
+  chrome.gpuBenchmarking.pointerActionSequence([{
+    'source': 'touch',
+    'actions': [
+      { 'name': 'pointerDown', 'x': x, 'y': y },
+      { 'name': 'pointerUp' },
+    ],
+  }]);
+
+
+  var video =
+      document.implementation.createHTMLDocument().createElement('video');
+  video.src = findMediaFile('video', '../content/test');
+  document.body.appendChild(video);  // Moved to `window.document`.
+  document.body.removeChild(video);  // To avoid polluting the DOM.
+  return video.play();
+}, 'After being moved to a document with user gesture, autoplay is allowed');
+
+promise_test(t => {
+  t.add_cleanup(() => {
+    window.internals.settings.setAutoplayPolicy('no-user-gesture-required');
+    document.body.removeChild(document.querySelector('iframe'));
+  });
+
+  window.internals.settings.setAutoplayPolicy('document-user-activation-required');
+
+  var iframe = document.createElement('iframe');
+  return new Promise((resolve, reject) => {
+    iframe.addEventListener('load', () => {
+      var bounds = document.querySelector('iframe').getBoundingClientRect();
+      var x = bounds.left + bounds.width / 2;
+      var y = bounds.top + bounds.height / 2;
+      chrome.gpuBenchmarking.pointerActionSequence([{
+        'source': 'touch',
+        'actions': [
+          { 'name': 'pointerDown', 'x': x, 'y': y },
+          { 'name': 'pointerUp' },
+        ],
+      }]);
+
+      var video = document.createElement('video');
+      video.src = findMediaFile('video', '../content/test');
+      video.play().then(resolve, reject);
+    });
+
+    iframe.src = 'resources/document-user-activation-iframe.html';
+    document.body.appendChild(iframe);
+  });
+}, 'Main frame allowed to play if iframe received a gesture');
+
+promise_test(t => {
+  t.add_cleanup(() => {
+    window.internals.settings.setAutoplayPolicy('no-user-gesture-required');
+    document.body.removeChild(document.querySelector('iframe'));
+  });
+
+  window.internals.settings.setAutoplayPolicy('document-user-activation-required');
+
+  var iframe = document.createElement('iframe');
+  return new Promise((resolve, reject) => {
+    iframe.addEventListener('load', () => {
+      var bounds = document.querySelector('iframe').getBoundingClientRect();
+      var x = bounds.left + bounds.width / 2;
+      var y = bounds.top + bounds.height / 2;
+      // TODO(mlamouri): for some reasons, using pointerActanionSequence fails.
+      eventSender.gestureTap(x, y);
+
+      window.addEventListener('message', e => {
+        e.data.result ? resolve() : reject();
+      });
+
+      iframe.contentWindow.postMessage({
+        command: 'play'
+      }, '*');
+    });
+
+    iframe.src = 'resources/document-user-activation-iframe.html';
+    document.body.appendChild(iframe);
+  });
+}, 'iframe allowed to play if it received a gesture');
+
+promise_test(t => {
+  t.add_cleanup(() => {
+    window.internals.settings.setAutoplayPolicy('no-user-gesture-required');
+    document.body.removeChild(document.querySelector('iframe'));
+  });
+
+  window.internals.settings.setAutoplayPolicy('document-user-activation-required');
+
+  var iframe = document.createElement('iframe');
+  return new Promise((resolve, reject) => {
+    iframe.addEventListener('load', () => {
+      var bounds = document.querySelector('#target').getBoundingClientRect();
+      var x = bounds.left + bounds.width / 2;
+      var y = bounds.top + bounds.height / 2;
+      chrome.gpuBenchmarking.pointerActionSequence([{
+        'source': 'mouse',
+        'actions': [
+          { 'name': 'pointerDown', 'x': x, 'y': y },
+          { 'name': 'pointerUp' },
+        ],
+      }]);
+
+      window.addEventListener('message', e => {
+        e.data.result ? reject() : resolve();
+      });
+
+      iframe.contentWindow.postMessage({
+        command: 'play'
+      }, '*');
+    });
+
+    iframe.src = 'resources/document-user-activation-iframe.html';
+    document.body.appendChild(iframe);
+  });
+}, 'iframe is not allowed to autoplay if the main frame received a gesture');
+</script>
diff --git a/third_party/WebKit/LayoutTests/media/autoplay/resources/document-user-activation-iframe.html b/third_party/WebKit/LayoutTests/media/autoplay/resources/document-user-activation-iframe.html
new file mode 100644
index 0000000..74aaf667
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/media/autoplay/resources/document-user-activation-iframe.html
@@ -0,0 +1,15 @@
+<!DOCTYPE html>
+<script>
+window.internals.settings.setAutoplayPolicy('document-user-activation-required');
+
+window.addEventListener('message', e => {
+  if (e.data.command == 'play') {
+    var video = document.createElement('video');
+    video.play();
+    window.parent.postMessage({
+      result: !video.paused
+    }, '*');
+    video.pause();
+  }
+});
+</script>
diff --git a/third_party/WebKit/LayoutTests/svg/css/getComputedStyle-listing-expected.txt b/third_party/WebKit/LayoutTests/svg/css/getComputedStyle-listing-expected.txt
index f69ece8..3f261c2 100644
--- a/third_party/WebKit/LayoutTests/svg/css/getComputedStyle-listing-expected.txt
+++ b/third_party/WebKit/LayoutTests/svg/css/getComputedStyle-listing-expected.txt
@@ -60,7 +60,7 @@
 -webkit-writing-mode: horizontal-tb
 align-content: normal
 align-items: normal
-align-self: normal
+align-self: auto
 alignment-baseline: auto
 animation-delay: 0s
 animation-direction: normal
@@ -181,7 +181,7 @@
 isolation: auto
 justify-content: normal
 justify-items: normal
-justify-self: normal
+justify-self: auto
 left: auto
 letter-spacing: normal
 lighting-color: rgb(255, 255, 255)
diff --git a/third_party/WebKit/Source/bindings/core/v8/V8Initializer.cpp b/third_party/WebKit/Source/bindings/core/v8/V8Initializer.cpp
index fa0ffe8..b9517bb7 100644
--- a/third_party/WebKit/Source/bindings/core/v8/V8Initializer.cpp
+++ b/third_party/WebKit/Source/bindings/core/v8/V8Initializer.cpp
@@ -76,7 +76,7 @@
   int memory_usage_mb = Platform::Current()->ActualMemoryUsageMB();
   DVLOG(1) << "V8 error: " << message << " (" << location
            << ").  Current memory usage: " << memory_usage_mb << " MB";
-  CRASH();
+  IMMEDIATE_CRASH();
 }
 
 static void ReportOOMErrorInMainThread(const char* location, bool is_js_heap) {
@@ -485,7 +485,7 @@
                                      const char* message) {
   // FIXME: We temporarily deal with V8 internal error situations such as
   // out-of-memory by crashing the worker.
-  CRASH();
+  IMMEDIATE_CRASH();
 }
 
 static void MessageHandlerInWorker(v8::Local<v8::Message> message,
diff --git a/third_party/WebKit/Source/bindings/scripts/v8_utilities.py b/third_party/WebKit/Source/bindings/scripts/v8_utilities.py
index c947078..46683d49 100644
--- a/third_party/WebKit/Source/bindings/scripts/v8_utilities.py
+++ b/third_party/WebKit/Source/bindings/scripts/v8_utilities.py
@@ -372,9 +372,11 @@
     extended_attributes = definition_or_member.extended_attributes
     if 'MeasureAs' in extended_attributes:
         includes.add('core/frame/UseCounter.h')
+        includes.add('public/platform/WebFeature.h')
         return lambda suffix: extended_attributes['MeasureAs']
     if 'Measure' in extended_attributes:
         includes.add('core/frame/UseCounter.h')
+        includes.add('public/platform/WebFeature.h')
         measure_as_name = capitalize(definition_or_member.name)
         if interface is not None:
             measure_as_name = '%s_%s' % (capitalize(interface.name), measure_as_name)
diff --git a/third_party/WebKit/Source/bindings/templates/attributes.cpp.tmpl b/third_party/WebKit/Source/bindings/templates/attributes.cpp.tmpl
index 3f614943..854dbff 100644
--- a/third_party/WebKit/Source/bindings/templates/attributes.cpp.tmpl
+++ b/third_party/WebKit/Source/bindings/templates/attributes.cpp.tmpl
@@ -217,11 +217,11 @@
 const v8::FunctionCallbackInfo<v8::Value>& info
 {%- endif %}) {
   {% if attribute.deprecate_as %}
-  Deprecation::CountDeprecation(CurrentExecutionContext(info.GetIsolate()), UseCounter::k{{attribute.deprecate_as}});
+  Deprecation::CountDeprecation(CurrentExecutionContext(info.GetIsolate()), WebFeature::k{{attribute.deprecate_as}});
   {% endif %}
 
   {% if attribute.measure_as %}
-  UseCounter::Count(CurrentExecutionContext(info.GetIsolate()), UseCounter::k{{attribute.measure_as('AttributeGetter')}});
+  UseCounter::Count(CurrentExecutionContext(info.GetIsolate()), WebFeature::k{{attribute.measure_as('AttributeGetter')}});
   {% endif %}
 
   {% if world_suffix in attribute.activity_logging_world_list_for_getter %}
@@ -262,11 +262,11 @@
 {% macro constructor_getter_callback(attribute, world_suffix) %}
 void {{v8_class_or_partial}}::{{attribute.name}}ConstructorGetterCallback{{world_suffix}}(v8::Local<v8::Name> property, const v8::PropertyCallbackInfo<v8::Value>& info) {
   {% if attribute.deprecate_as %}
-  Deprecation::CountDeprecation(CurrentExecutionContext(info.GetIsolate()), UseCounter::k{{attribute.deprecate_as}});
+  Deprecation::CountDeprecation(CurrentExecutionContext(info.GetIsolate()), WebFeature::k{{attribute.deprecate_as}});
   {% endif %}
 
   {% if attribute.measure_as %}
-  UseCounter::Count(CurrentExecutionContext(info.GetIsolate()), UseCounter::k{{attribute.measure_as('ConstructorGetter')}});
+  UseCounter::Count(CurrentExecutionContext(info.GetIsolate()), WebFeature::k{{attribute.measure_as('ConstructorGetter')}});
   {% endif %}
 
   V8ConstructorAttributeGetter(property, info);
@@ -438,11 +438,11 @@
   {% endif %}
 
   {% if attribute.deprecate_as %}
-  Deprecation::CountDeprecation(CurrentExecutionContext(info.GetIsolate()), UseCounter::k{{attribute.deprecate_as}});
+  Deprecation::CountDeprecation(CurrentExecutionContext(info.GetIsolate()), WebFeature::k{{attribute.deprecate_as}});
   {% endif %}
 
   {% if attribute.measure_as %}
-  UseCounter::Count(CurrentExecutionContext(info.GetIsolate()), UseCounter::k{{attribute.measure_as('AttributeSetter')}});
+  UseCounter::Count(CurrentExecutionContext(info.GetIsolate()), WebFeature::k{{attribute.measure_as('AttributeSetter')}});
   {% endif %}
 
   {% if world_suffix in attribute.activity_logging_world_list_for_setter %}
diff --git a/third_party/WebKit/Source/bindings/templates/interface.cpp.tmpl b/third_party/WebKit/Source/bindings/templates/interface.cpp.tmpl
index 7f1f275..d10d8898 100644
--- a/third_party/WebKit/Source/bindings/templates/interface.cpp.tmpl
+++ b/third_party/WebKit/Source/bindings/templates/interface.cpp.tmpl
@@ -632,7 +632,7 @@
 {% if constructors or has_custom_constructor or has_html_constructor %}
 void {{v8_class}}::constructorCallback(const v8::FunctionCallbackInfo<v8::Value>& info) {
   {% if measure_as %}
-  UseCounter::Count(CurrentExecutionContext(info.GetIsolate()), UseCounter::k{{measure_as('Constructor')}});
+  UseCounter::Count(CurrentExecutionContext(info.GetIsolate()), WebFeature::k{{measure_as('Constructor')}});
   {% endif %}
   if (!info.IsConstructCall()) {
     V8ThrowException::ThrowTypeError(info.GetIsolate(), ExceptionMessages::ConstructorNotCallableAsFunction("{{interface_name}}"));
diff --git a/third_party/WebKit/Source/bindings/templates/methods.cpp.tmpl b/third_party/WebKit/Source/bindings/templates/methods.cpp.tmpl
index 6146af2c..d33c46d 100644
--- a/third_party/WebKit/Source/bindings/templates/methods.cpp.tmpl
+++ b/third_party/WebKit/Source/bindings/templates/methods.cpp.tmpl
@@ -340,10 +340,10 @@
   {% set fall_through_to_partial_overloads = not is_partial and overloads.has_partial_overloads %}
 
   {% if overloads.measure_all_as %}
-  UseCounter::Count(CurrentExecutionContext(info.GetIsolate()), UseCounter::k{{overloads.measure_all_as}});
+  UseCounter::Count(CurrentExecutionContext(info.GetIsolate()), WebFeature::k{{overloads.measure_all_as}});
   {% endif %}
   {% if overloads.deprecate_all_as %}
-  Deprecation::CountDeprecation(CurrentExecutionContext(info.GetIsolate()), UseCounter::k{{overloads.deprecate_all_as}});
+  Deprecation::CountDeprecation(CurrentExecutionContext(info.GetIsolate()), WebFeature::k{{overloads.deprecate_all_as}});
   {% endif %}
 
   {# First resolve by length #}
@@ -362,10 +362,10 @@
       {% filter runtime_enabled(not overloads.runtime_enabled_all and method.runtime_enabled_feature_name) %}
       if ({{test}}) {
         {% if method.measure_as and not overloads.measure_all_as %}
-        UseCounter::Count(CurrentExecutionContext(info.GetIsolate()), UseCounter::k{{method.measure_as('Method')}});
+        UseCounter::Count(CurrentExecutionContext(info.GetIsolate()), WebFeature::k{{method.measure_as('Method')}});
         {% endif %}
         {% if method.deprecate_as and not overloads.deprecate_all_as %}
-        Deprecation::CountDeprecation(CurrentExecutionContext(info.GetIsolate()), UseCounter::k{{method.deprecate_as}});
+        Deprecation::CountDeprecation(CurrentExecutionContext(info.GetIsolate()), WebFeature::k{{method.deprecate_as}});
         {% endif %}
         {{method.name}}{{method.overload_index}}Method{{world_suffix}}(info);
         return;
@@ -481,10 +481,10 @@
 void {{v8_class_or_partial}}::{{method.name}}MethodCallback{{world_suffix}}(const v8::FunctionCallbackInfo<v8::Value>& info) {
   {% if not method.overloads %}{# Overloaded methods are measured in overload_resolution_method() #}
   {% if method.measure_as %}
-  UseCounter::Count(CurrentExecutionContext(info.GetIsolate()), UseCounter::k{{method.measure_as('Method')}});
+  UseCounter::Count(CurrentExecutionContext(info.GetIsolate()), WebFeature::k{{method.measure_as('Method')}});
   {% endif %}
   {% if method.deprecate_as %}
-  Deprecation::CountDeprecation(CurrentExecutionContext(info.GetIsolate()), UseCounter::k{{method.deprecate_as}});
+  Deprecation::CountDeprecation(CurrentExecutionContext(info.GetIsolate()), WebFeature::k{{method.deprecate_as}});
   {% endif %}
   {% endif %}{# not method.overloads #}
   {% if world_suffix in method.activity_logging_world_list %}
diff --git a/third_party/WebKit/Source/bindings/tests/results/core/V8TestConstants.cpp b/third_party/WebKit/Source/bindings/tests/results/core/V8TestConstants.cpp
index 2836adb..580af5d 100644
--- a/third_party/WebKit/Source/bindings/tests/results/core/V8TestConstants.cpp
+++ b/third_party/WebKit/Source/bindings/tests/results/core/V8TestConstants.cpp
@@ -22,6 +22,7 @@
 #include "platform/bindings/V8ObjectConstructor.h"
 #include "platform/wtf/GetPtr.h"
 #include "platform/wtf/RefPtr.h"
+#include "public/platform/WebFeature.h"
 
 namespace blink {
 
diff --git a/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterface.cpp b/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterface.cpp
index 9f347ca5..870eb79 100644
--- a/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterface.cpp
+++ b/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterface.cpp
@@ -39,6 +39,7 @@
 #include "platform/bindings/V8PrivateProperty.h"
 #include "platform/wtf/GetPtr.h"
 #include "platform/wtf/RefPtr.h"
+#include "public/platform/WebFeature.h"
 
 namespace blink {
 
@@ -2163,7 +2164,7 @@
 } // namespace TestInterfaceImplementationV8Internal
 
 void V8TestInterface::testInterfaceAttributeAttributeGetterCallback(const v8::FunctionCallbackInfo<v8::Value>& info) {
-  UseCounter::Count(CurrentExecutionContext(info.GetIsolate()), UseCounter::kV8TestInterface_TestInterfaceAttribute_AttributeGetter);
+  UseCounter::Count(CurrentExecutionContext(info.GetIsolate()), WebFeature::kV8TestInterface_TestInterfaceAttribute_AttributeGetter);
 
   TestInterfaceImplementationV8Internal::testInterfaceAttributeAttributeGetter(info);
 }
@@ -2171,7 +2172,7 @@
 void V8TestInterface::testInterfaceAttributeAttributeSetterCallback(const v8::FunctionCallbackInfo<v8::Value>& info) {
   v8::Local<v8::Value> v8Value = info[0];
 
-  UseCounter::Count(CurrentExecutionContext(info.GetIsolate()), UseCounter::kV8TestInterface_TestInterfaceAttribute_AttributeSetter);
+  UseCounter::Count(CurrentExecutionContext(info.GetIsolate()), WebFeature::kV8TestInterface_TestInterfaceAttribute_AttributeSetter);
 
   TestInterfaceImplementationV8Internal::testInterfaceAttributeAttributeSetter(v8Value, info);
 }
diff --git a/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterfaceConstructor.cpp b/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterfaceConstructor.cpp
index 4459708..941fa00 100644
--- a/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterfaceConstructor.cpp
+++ b/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterfaceConstructor.cpp
@@ -26,6 +26,7 @@
 #include "platform/bindings/V8PrivateProperty.h"
 #include "platform/wtf/GetPtr.h"
 #include "platform/wtf/RefPtr.h"
+#include "public/platform/WebFeature.h"
 
 namespace blink {
 
@@ -397,7 +398,7 @@
 }
 
 void V8TestInterfaceConstructor::constructorCallback(const v8::FunctionCallbackInfo<v8::Value>& info) {
-  UseCounter::Count(CurrentExecutionContext(info.GetIsolate()), UseCounter::kTestFeature);
+  UseCounter::Count(CurrentExecutionContext(info.GetIsolate()), WebFeature::kTestFeature);
   if (!info.IsConstructCall()) {
     V8ThrowException::ThrowTypeError(info.GetIsolate(), ExceptionMessages::ConstructorNotCallableAsFunction("TestInterfaceConstructor"));
     return;
diff --git a/third_party/WebKit/Source/bindings/tests/results/core/V8TestObject.cpp b/third_party/WebKit/Source/bindings/tests/results/core/V8TestObject.cpp
index 28bf5056..9c8583a 100644
--- a/third_party/WebKit/Source/bindings/tests/results/core/V8TestObject.cpp
+++ b/third_party/WebKit/Source/bindings/tests/results/core/V8TestObject.cpp
@@ -77,6 +77,7 @@
 #include "platform/bindings/V8PrivateProperty.h"
 #include "platform/wtf/GetPtr.h"
 #include "platform/wtf/RefPtr.h"
+#include "public/platform/WebFeature.h"
 
 namespace blink {
 
@@ -8162,14 +8163,14 @@
   switch (std::min(1, info.Length())) {
     case 0:
       if (true) {
-        UseCounter::Count(CurrentExecutionContext(info.GetIsolate()), UseCounter::kV8TestObject_MeasureOverloadedMethod_Method);
+        UseCounter::Count(CurrentExecutionContext(info.GetIsolate()), WebFeature::kV8TestObject_MeasureOverloadedMethod_Method);
         measureOverloadedMethod1Method(info);
         return;
       }
       break;
     case 1:
       if (true) {
-        UseCounter::Count(CurrentExecutionContext(info.GetIsolate()), UseCounter::kV8TestObject_MeasureOverloadedMethod_Method);
+        UseCounter::Count(CurrentExecutionContext(info.GetIsolate()), WebFeature::kV8TestObject_MeasureOverloadedMethod_Method);
         measureOverloadedMethod2Method(info);
         return;
       }
@@ -8209,14 +8210,14 @@
   switch (std::min(1, info.Length())) {
     case 0:
       if (true) {
-        Deprecation::CountDeprecation(CurrentExecutionContext(info.GetIsolate()), UseCounter::kTestFeatureA);
+        Deprecation::CountDeprecation(CurrentExecutionContext(info.GetIsolate()), WebFeature::kTestFeatureA);
         DeprecateAsOverloadedMethod1Method(info);
         return;
       }
       break;
     case 1:
       if (true) {
-        Deprecation::CountDeprecation(CurrentExecutionContext(info.GetIsolate()), UseCounter::kTestFeatureB);
+        Deprecation::CountDeprecation(CurrentExecutionContext(info.GetIsolate()), WebFeature::kTestFeatureB);
         DeprecateAsOverloadedMethod2Method(info);
         return;
       }
@@ -8252,7 +8253,7 @@
 }
 
 static void DeprecateAsSameValueOverloadedMethodMethod(const v8::FunctionCallbackInfo<v8::Value>& info) {
-  Deprecation::CountDeprecation(CurrentExecutionContext(info.GetIsolate()), UseCounter::kTestFeature);
+  Deprecation::CountDeprecation(CurrentExecutionContext(info.GetIsolate()), WebFeature::kTestFeature);
 
   bool isArityError = false;
   switch (std::min(1, info.Length())) {
@@ -8303,14 +8304,14 @@
   switch (std::min(1, info.Length())) {
     case 0:
       if (true) {
-        UseCounter::Count(CurrentExecutionContext(info.GetIsolate()), UseCounter::kTestFeatureA);
+        UseCounter::Count(CurrentExecutionContext(info.GetIsolate()), WebFeature::kTestFeatureA);
         measureAsOverloadedMethod1Method(info);
         return;
       }
       break;
     case 1:
       if (true) {
-        UseCounter::Count(CurrentExecutionContext(info.GetIsolate()), UseCounter::kTestFeatureB);
+        UseCounter::Count(CurrentExecutionContext(info.GetIsolate()), WebFeature::kTestFeatureB);
         measureAsOverloadedMethod2Method(info);
         return;
       }
@@ -8350,14 +8351,14 @@
   switch (std::min(1, info.Length())) {
     case 0:
       if (true) {
-        UseCounter::Count(CurrentExecutionContext(info.GetIsolate()), UseCounter::kTestFeature);
+        UseCounter::Count(CurrentExecutionContext(info.GetIsolate()), WebFeature::kTestFeature);
         measureAsSameValueOverloadedMethod1Method(info);
         return;
       }
       break;
     case 1:
       if (true) {
-        UseCounter::Count(CurrentExecutionContext(info.GetIsolate()), UseCounter::kTestFeature);
+        UseCounter::Count(CurrentExecutionContext(info.GetIsolate()), WebFeature::kTestFeature);
         measureAsSameValueOverloadedMethod2Method(info);
         return;
       }
@@ -8397,16 +8398,16 @@
   switch (std::min(1, info.Length())) {
     case 0:
       if (true) {
-        UseCounter::Count(CurrentExecutionContext(info.GetIsolate()), UseCounter::kTestFeature);
-        Deprecation::CountDeprecation(CurrentExecutionContext(info.GetIsolate()), UseCounter::kTestFeatureA);
+        UseCounter::Count(CurrentExecutionContext(info.GetIsolate()), WebFeature::kTestFeature);
+        Deprecation::CountDeprecation(CurrentExecutionContext(info.GetIsolate()), WebFeature::kTestFeatureA);
         deprecateAsMeasureAsSameValueOverloadedMethod1Method(info);
         return;
       }
       break;
     case 1:
       if (true) {
-        UseCounter::Count(CurrentExecutionContext(info.GetIsolate()), UseCounter::kTestFeature);
-        Deprecation::CountDeprecation(CurrentExecutionContext(info.GetIsolate()), UseCounter::kTestFeatureB);
+        UseCounter::Count(CurrentExecutionContext(info.GetIsolate()), WebFeature::kTestFeature);
+        Deprecation::CountDeprecation(CurrentExecutionContext(info.GetIsolate()), WebFeature::kTestFeatureB);
         deprecateAsMeasureAsSameValueOverloadedMethod2Method(info);
         return;
       }
@@ -8442,20 +8443,20 @@
 }
 
 static void deprecateAsSameValueMeasureAsOverloadedMethodMethod(const v8::FunctionCallbackInfo<v8::Value>& info) {
-  Deprecation::CountDeprecation(CurrentExecutionContext(info.GetIsolate()), UseCounter::kTestFeature);
+  Deprecation::CountDeprecation(CurrentExecutionContext(info.GetIsolate()), WebFeature::kTestFeature);
 
   bool isArityError = false;
   switch (std::min(1, info.Length())) {
     case 0:
       if (true) {
-        UseCounter::Count(CurrentExecutionContext(info.GetIsolate()), UseCounter::kTestFeatureA);
+        UseCounter::Count(CurrentExecutionContext(info.GetIsolate()), WebFeature::kTestFeatureA);
         deprecateAsSameValueMeasureAsOverloadedMethod1Method(info);
         return;
       }
       break;
     case 1:
       if (true) {
-        UseCounter::Count(CurrentExecutionContext(info.GetIsolate()), UseCounter::kTestFeatureB);
+        UseCounter::Count(CurrentExecutionContext(info.GetIsolate()), WebFeature::kTestFeatureB);
         deprecateAsSameValueMeasureAsOverloadedMethod2Method(info);
         return;
       }
@@ -8491,20 +8492,20 @@
 }
 
 static void deprecateAsSameValueMeasureAsSameValueOverloadedMethodMethod(const v8::FunctionCallbackInfo<v8::Value>& info) {
-  Deprecation::CountDeprecation(CurrentExecutionContext(info.GetIsolate()), UseCounter::kTestFeatureA);
+  Deprecation::CountDeprecation(CurrentExecutionContext(info.GetIsolate()), WebFeature::kTestFeatureA);
 
   bool isArityError = false;
   switch (std::min(1, info.Length())) {
     case 0:
       if (true) {
-        UseCounter::Count(CurrentExecutionContext(info.GetIsolate()), UseCounter::kTestFeatureB);
+        UseCounter::Count(CurrentExecutionContext(info.GetIsolate()), WebFeature::kTestFeatureB);
         deprecateAsSameValueMeasureAsSameValueOverloadedMethod1Method(info);
         return;
       }
       break;
     case 1:
       if (true) {
-        UseCounter::Count(CurrentExecutionContext(info.GetIsolate()), UseCounter::kTestFeatureB);
+        UseCounter::Count(CurrentExecutionContext(info.GetIsolate()), WebFeature::kTestFeatureB);
         deprecateAsSameValueMeasureAsSameValueOverloadedMethod2Method(info);
         return;
       }
@@ -10264,13 +10265,13 @@
 }
 
 void V8TestObject::testInterfaceEmptyConstructorAttributeConstructorGetterCallback(v8::Local<v8::Name> property, const v8::PropertyCallbackInfo<v8::Value>& info) {
-  Deprecation::CountDeprecation(CurrentExecutionContext(info.GetIsolate()), UseCounter::kdeprecatedTestInterfaceEmptyConstructorAttribute);
+  Deprecation::CountDeprecation(CurrentExecutionContext(info.GetIsolate()), WebFeature::kdeprecatedTestInterfaceEmptyConstructorAttribute);
 
   V8ConstructorAttributeGetter(property, info);
 }
 
 void V8TestObject::measureAsFeatureNameTestInterfaceEmptyConstructorAttributeConstructorGetterCallback(v8::Local<v8::Name> property, const v8::PropertyCallbackInfo<v8::Value>& info) {
-  UseCounter::Count(CurrentExecutionContext(info.GetIsolate()), UseCounter::kFeatureName);
+  UseCounter::Count(CurrentExecutionContext(info.GetIsolate()), WebFeature::kFeatureName);
 
   V8ConstructorAttributeGetter(property, info);
 }
@@ -10310,7 +10311,7 @@
 }
 
 void V8TestObject::deprecatedLongAttributeAttributeGetterCallback(const v8::FunctionCallbackInfo<v8::Value>& info) {
-  Deprecation::CountDeprecation(CurrentExecutionContext(info.GetIsolate()), UseCounter::kLongAttribute);
+  Deprecation::CountDeprecation(CurrentExecutionContext(info.GetIsolate()), WebFeature::kLongAttribute);
 
   TestObjectV8Internal::deprecatedLongAttributeAttributeGetter(info);
 }
@@ -10318,7 +10319,7 @@
 void V8TestObject::deprecatedLongAttributeAttributeSetterCallback(const v8::FunctionCallbackInfo<v8::Value>& info) {
   v8::Local<v8::Value> v8Value = info[0];
 
-  Deprecation::CountDeprecation(CurrentExecutionContext(info.GetIsolate()), UseCounter::kLongAttribute);
+  Deprecation::CountDeprecation(CurrentExecutionContext(info.GetIsolate()), WebFeature::kLongAttribute);
 
   TestObjectV8Internal::deprecatedLongAttributeAttributeSetter(v8Value, info);
 }
@@ -10374,7 +10375,7 @@
 }
 
 void V8TestObject::measureAsLongAttributeAttributeGetterCallback(const v8::FunctionCallbackInfo<v8::Value>& info) {
-  UseCounter::Count(CurrentExecutionContext(info.GetIsolate()), UseCounter::kTestFeature);
+  UseCounter::Count(CurrentExecutionContext(info.GetIsolate()), WebFeature::kTestFeature);
 
   TestObjectV8Internal::measureAsLongAttributeAttributeGetter(info);
 }
@@ -10382,7 +10383,7 @@
 void V8TestObject::measureAsLongAttributeAttributeSetterCallback(const v8::FunctionCallbackInfo<v8::Value>& info) {
   v8::Local<v8::Value> v8Value = info[0];
 
-  UseCounter::Count(CurrentExecutionContext(info.GetIsolate()), UseCounter::kTestFeature);
+  UseCounter::Count(CurrentExecutionContext(info.GetIsolate()), WebFeature::kTestFeature);
 
   TestObjectV8Internal::measureAsLongAttributeAttributeSetter(v8Value, info);
 }
@@ -11026,7 +11027,7 @@
 }
 
 void V8TestObject::measuredLongAttributeAttributeGetterCallback(const v8::FunctionCallbackInfo<v8::Value>& info) {
-  UseCounter::Count(CurrentExecutionContext(info.GetIsolate()), UseCounter::kV8TestObject_MeasuredLongAttribute_AttributeGetter);
+  UseCounter::Count(CurrentExecutionContext(info.GetIsolate()), WebFeature::kV8TestObject_MeasuredLongAttribute_AttributeGetter);
 
   TestObjectV8Internal::measuredLongAttributeAttributeGetter(info);
 }
@@ -11034,7 +11035,7 @@
 void V8TestObject::measuredLongAttributeAttributeSetterCallback(const v8::FunctionCallbackInfo<v8::Value>& info) {
   v8::Local<v8::Value> v8Value = info[0];
 
-  UseCounter::Count(CurrentExecutionContext(info.GetIsolate()), UseCounter::kV8TestObject_MeasuredLongAttribute_AttributeSetter);
+  UseCounter::Count(CurrentExecutionContext(info.GetIsolate()), WebFeature::kV8TestObject_MeasuredLongAttribute_AttributeSetter);
 
   TestObjectV8Internal::measuredLongAttributeAttributeSetter(v8Value, info);
 }
@@ -11887,7 +11888,7 @@
 }
 
 void V8TestObject::deprecatedVoidMethodMethodCallback(const v8::FunctionCallbackInfo<v8::Value>& info) {
-  Deprecation::CountDeprecation(CurrentExecutionContext(info.GetIsolate()), UseCounter::kvoidMethod);
+  Deprecation::CountDeprecation(CurrentExecutionContext(info.GetIsolate()), WebFeature::kvoidMethod);
   TestObjectV8Internal::deprecatedVoidMethodMethod(info);
 }
 
@@ -11896,12 +11897,12 @@
 }
 
 void V8TestObject::measureAsVoidMethodMethodCallback(const v8::FunctionCallbackInfo<v8::Value>& info) {
-  UseCounter::Count(CurrentExecutionContext(info.GetIsolate()), UseCounter::kTestFeature);
+  UseCounter::Count(CurrentExecutionContext(info.GetIsolate()), WebFeature::kTestFeature);
   TestObjectV8Internal::measureAsVoidMethodMethod(info);
 }
 
 void V8TestObject::measureMethodMethodCallback(const v8::FunctionCallbackInfo<v8::Value>& info) {
-  UseCounter::Count(CurrentExecutionContext(info.GetIsolate()), UseCounter::kV8TestObject_MeasureMethod_Method);
+  UseCounter::Count(CurrentExecutionContext(info.GetIsolate()), WebFeature::kV8TestObject_MeasureMethod_Method);
   TestObjectV8Internal::measureMethodMethod(info);
 }
 
diff --git a/third_party/WebKit/Source/core/css/CSSPrimitiveValueMappings.h b/third_party/WebKit/Source/core/css/CSSPrimitiveValueMappings.h
index f7ad2ce..99afef7 100644
--- a/third_party/WebKit/Source/core/css/CSSPrimitiveValueMappings.h
+++ b/third_party/WebKit/Source/core/css/CSSPrimitiveValueMappings.h
@@ -2574,9 +2574,7 @@
     : CSSValue(kIdentifierClass) {
   switch (item_position) {
     case kItemPositionAuto:
-      // The 'auto' values might have been already resolved.
-      NOTREACHED();
-      value_id_ = CSSValueNormal;
+      value_id_ = CSSValueAuto;
       break;
     case kItemPositionNormal:
       value_id_ = CSSValueNormal;
diff --git a/third_party/WebKit/Source/core/css/CSSToLengthConversionData.cpp b/third_party/WebKit/Source/core/css/CSSToLengthConversionData.cpp
index 1a4ef71..c75d748 100644
--- a/third_party/WebKit/Source/core/css/CSSToLengthConversionData.cpp
+++ b/third_party/WebKit/Source/core/css/CSSToLengthConversionData.cpp
@@ -100,24 +100,29 @@
   // FIXME: Remove style_ from this class. Plumb viewport and rem unit
   // information through as output parameters on functions involved in length
   // resolution.
-  const_cast<ComputedStyle*>(style_)->SetHasViewportUnits(true);
+  if (style_)
+    const_cast<ComputedStyle*>(style_)->SetHasViewportUnits(true);
   return viewport_size_.Width() / 100;
 }
 double CSSToLengthConversionData::ViewportHeightPercent() const {
-  const_cast<ComputedStyle*>(style_)->SetHasViewportUnits(true);
+  if (style_)
+    const_cast<ComputedStyle*>(style_)->SetHasViewportUnits(true);
   return viewport_size_.Height() / 100;
 }
 double CSSToLengthConversionData::ViewportMinPercent() const {
-  const_cast<ComputedStyle*>(style_)->SetHasViewportUnits(true);
+  if (style_)
+    const_cast<ComputedStyle*>(style_)->SetHasViewportUnits(true);
   return std::min(viewport_size_.Width(), viewport_size_.Height()) / 100;
 }
 double CSSToLengthConversionData::ViewportMaxPercent() const {
-  const_cast<ComputedStyle*>(style_)->SetHasViewportUnits(true);
+  if (style_)
+    const_cast<ComputedStyle*>(style_)->SetHasViewportUnits(true);
   return std::max(viewport_size_.Width(), viewport_size_.Height()) / 100;
 }
 
 float CSSToLengthConversionData::RemFontSize() const {
-  const_cast<ComputedStyle*>(style_)->SetHasRemUnits();
+  if (style_)
+    const_cast<ComputedStyle*>(style_)->SetHasRemUnits();
   return font_sizes_.Rem();
 }
 
diff --git a/third_party/WebKit/Source/core/css/ComputedStyleCSSValueMapping.cpp b/third_party/WebKit/Source/core/css/ComputedStyleCSSValueMapping.cpp
index afd43d17..c437881 100644
--- a/third_party/WebKit/Source/core/css/ComputedStyleCSSValueMapping.cpp
+++ b/third_party/WebKit/Source/core/css/ComputedStyleCSSValueMapping.cpp
@@ -503,13 +503,7 @@
   CSSValueList* result = CSSValueList::CreateSpaceSeparated();
   if (data.PositionType() == kLegacyPosition)
     result->Append(*CSSIdentifierValue::Create(CSSValueLegacy));
-  if (data.GetPosition() == kItemPositionAuto) {
-    // To avoid needing to copy the RareNonInheritedData, we repurpose the
-    // 'auto' flag to not just mean 'auto' prior to running the StyleAdjuster
-    // but also mean 'normal' after running it.
-    result->Append(*CSSIdentifierValue::Create(
-        ComputedStyle::InitialDefaultAlignment().GetPosition()));
-  } else if (data.GetPosition() == kItemPositionBaseline) {
+  if (data.GetPosition() == kItemPositionBaseline) {
     result->Append(
         *CSSValuePair::Create(CSSIdentifierValue::Create(CSSValueBaseline),
                               CSSIdentifierValue::Create(CSSValueBaseline),
@@ -2613,7 +2607,10 @@
     case CSSPropertyIsolation:
       return CSSIdentifierValue::Create(style.Isolation());
     case CSSPropertyJustifyItems:
-      return ValueForItemPositionWithOverflowAlignment(style.JustifyItems());
+      return ValueForItemPositionWithOverflowAlignment(
+          style.JustifyItems().GetPosition() == kItemPositionAuto
+              ? ComputedStyle::InitialDefaultAlignment()
+              : style.JustifyItems());
     case CSSPropertyJustifySelf:
       return ValueForItemPositionWithOverflowAlignment(style.JustifySelf());
     case CSSPropertyLeft:
diff --git a/third_party/WebKit/Source/core/css/resolver/FilterOperationResolver.cpp b/third_party/WebKit/Source/core/css/resolver/FilterOperationResolver.cpp
index 08b4653..0d1f58d 100644
--- a/third_party/WebKit/Source/core/css/resolver/FilterOperationResolver.cpp
+++ b/third_party/WebKit/Source/core/css/resolver/FilterOperationResolver.cpp
@@ -219,8 +219,9 @@
   CSSToLengthConversionData::FontSizes font_sizes(
       kOffScreenCanvasEmFontSize, kOffScreenCanvasRemFontSize, &font);
   CSSToLengthConversionData::ViewportSize viewport_size(0, 0);
-  CSSToLengthConversionData conversion_data(&ComputedStyle::InitialStyle(),
-                                            font_sizes, viewport_size, 1);
+  CSSToLengthConversionData conversion_data(nullptr,  // ComputedStyle
+                                            font_sizes, viewport_size,
+                                            1);  // zoom
 
   for (auto& curr_value : ToCSSValueList(in_value)) {
     if (curr_value->IsURIValue())
diff --git a/third_party/WebKit/Source/core/css/resolver/StyleAdjuster.cpp b/third_party/WebKit/Source/core/css/resolver/StyleAdjuster.cpp
index bb67e278..051088e 100644
--- a/third_party/WebKit/Source/core/css/resolver/StyleAdjuster.cpp
+++ b/third_party/WebKit/Source/core/css/resolver/StyleAdjuster.cpp
@@ -159,38 +159,6 @@
   style.SetPosition(EPosition::kStatic);
 }
 
-void StyleAdjuster::AdjustStyleForAlignment(
-    ComputedStyle& style,
-    const ComputedStyle& layout_parent_style) {
-  // To avoid needing to copy the RareNonInheritedData, we repurpose the 'auto'
-  // flag to not just mean 'auto' prior to running the StyleAdjuster but also
-  // mean 'normal' after running it.
-
-  // If the inherited value of justify-items includes the 'legacy' keyword,
-  // 'auto' computes to the the inherited value.  Otherwise, 'auto' computes to
-  // 'normal'.
-  if (style.JustifyItemsPosition() == kItemPositionAuto) {
-    if (layout_parent_style.JustifyItemsPositionType() == kLegacyPosition)
-      style.SetJustifyItems(layout_parent_style.JustifyItems());
-  }
-
-  // The 'auto' keyword computes the computed value of justify-items on the
-  // parent (minus any legacy keywords), or 'normal' if the box has no parent.
-  if (style.JustifySelfPosition() == kItemPositionAuto) {
-    if (layout_parent_style.JustifyItemsPositionType() == kLegacyPosition)
-      style.SetJustifySelfPosition(layout_parent_style.JustifyItemsPosition());
-    else if (layout_parent_style.JustifyItemsPosition() != kItemPositionAuto)
-      style.SetJustifySelf(layout_parent_style.JustifyItems());
-  }
-
-  // The 'auto' keyword computes the computed value of align-items on the parent
-  // or 'normal' if the box has no parent.
-  if (style.AlignSelfPosition() == kItemPositionAuto &&
-      layout_parent_style.AlignItemsPosition() !=
-          ComputedStyle::InitialDefaultAlignment().GetPosition())
-    style.SetAlignSelf(layout_parent_style.AlignItems());
-}
-
 static void AdjustStyleForHTMLElement(ComputedStyle& style,
                                       HTMLElement& element) {
   // <div> and <span> are the most common elements on the web, we skip all the
@@ -511,7 +479,6 @@
     if (isSVGTextElement(*element))
       style.ClearMultiCol();
   }
-  AdjustStyleForAlignment(style, layout_parent_style);
 
   // If this node is sticky it marks the creation of a sticky subtree, which we
   // must track to properly handle document lifecycle in some cases.
@@ -521,6 +488,14 @@
   // inheritance from the ancestor and there is no harm to setting it again.
   if (style.GetPosition() == EPosition::kSticky)
     style.SetSubtreeIsSticky(true);
+
+  // If the inherited value of justify-items includes the 'legacy' keyword,
+  // 'auto' computes to the the inherited value.  Otherwise, 'auto' computes to
+  // 'normal'.
+  if (style.JustifyItemsPosition() == kItemPositionAuto) {
+    if (parent_style.JustifyItemsPositionType() == kLegacyPosition)
+      style.SetJustifyItems(parent_style.JustifyItems());
+  }
 }
 
 }  // namespace blink
diff --git a/third_party/WebKit/Source/core/css/resolver/StyleAdjuster.h b/third_party/WebKit/Source/core/css/resolver/StyleAdjuster.h
index 9690f9d8..3ca8e7c 100644
--- a/third_party/WebKit/Source/core/css/resolver/StyleAdjuster.h
+++ b/third_party/WebKit/Source/core/css/resolver/StyleAdjuster.h
@@ -42,8 +42,6 @@
                                   const ComputedStyle& layout_parent_style,
                                   Element*);
   static void AdjustStyleForEditing(ComputedStyle&);
-  static void AdjustStyleForAlignment(ComputedStyle&,
-                                      const ComputedStyle& parent_style);
 };
 
 }  // namespace blink
diff --git a/third_party/WebKit/Source/core/dom/Text.cpp b/third_party/WebKit/Source/core/dom/Text.cpp
index bd379c0..c9b0047 100644
--- a/third_party/WebKit/Source/core/dom/Text.cpp
+++ b/third_party/WebKit/Source/core/dom/Text.cpp
@@ -176,7 +176,7 @@
       continue;
     const String& data = ToText(n)->data();
     if (std::numeric_limits<unsigned>::max() - data.length() < result_length)
-      CRASH();
+      IMMEDIATE_CRASH();
     result_length += data.length();
   }
   StringBuilder result;
diff --git a/third_party/WebKit/Source/core/editing/iterators/TextIterator.cpp b/third_party/WebKit/Source/core/editing/iterators/TextIterator.cpp
index f26eed1..b5389df 100644
--- a/third_party/WebKit/Source/core/editing/iterators/TextIterator.cpp
+++ b/third_party/WebKit/Source/core/editing/iterators/TextIterator.cpp
@@ -144,6 +144,7 @@
 
 }  // namespace
 
+// TODO(xiaochengh): Most members should be initialized in-place, not here.
 template <typename Strategy>
 TextIteratorAlgorithm<Strategy>::TextIteratorAlgorithm(
     const EphemeralRangeTemplate<Strategy>& range,
@@ -162,6 +163,7 @@
       end_container_(nullptr),
       end_offset_(0),
       needs_another_newline_(false),
+      needs_handle_replaced_element_(false),
       last_text_node_(nullptr),
       behavior_(AdjustBehaviorFlags<Strategy>(behavior)),
       should_stop_(false),
@@ -273,6 +275,12 @@
   // way, we can also remove the return values of HandleReplaceElement() and
   // HandleNonTextNode(), and make the control flow cleaner.
 
+  if (needs_handle_replaced_element_) {
+    HandleReplacedElement();
+    if (text_state_.PositionNode())
+      return true;
+  }
+
   // Try to emit more text runs if we are handling a text node.
   return text_node_handler_.HandleRemainingTextRuns();
 }
@@ -505,6 +513,8 @@
 
 template <typename Strategy>
 bool TextIteratorAlgorithm<Strategy>::HandleReplacedElement() {
+  needs_handle_replaced_element_ = false;
+
   if (fully_clipped_stack_.Top())
     return false;
 
@@ -522,8 +532,10 @@
   DCHECK_EQ(last_text_node_, text_node_handler_.GetNode());
   if (last_text_node_) {
     if (text_node_handler_.FixLeadingWhiteSpaceForReplacedElement(
-            Strategy::Parent(*last_text_node_)))
-      return false;
+            Strategy::Parent(*last_text_node_))) {
+      needs_handle_replaced_element_ = true;
+      return true;
+    }
   }
 
   if (EntersTextControls() && layout_object->IsTextControl()) {
diff --git a/third_party/WebKit/Source/core/editing/iterators/TextIterator.h b/third_party/WebKit/Source/core/editing/iterators/TextIterator.h
index f631d59..5b3167b 100644
--- a/third_party/WebKit/Source/core/editing/iterators/TextIterator.h
+++ b/third_party/WebKit/Source/core/editing/iterators/TextIterator.h
@@ -217,8 +217,9 @@
   Member<Node> past_end_node_;
 
   // Used when there is still some pending text from the current node; when
-  // these are false and 0, we go back to normal iterating.
+  // these are false, we go back to normal iterating.
   bool needs_another_newline_;
+  bool needs_handle_replaced_element_;
 
   Member<Text> last_text_node_;
 
diff --git a/third_party/WebKit/Source/core/editing/markers/DocumentMarker.cpp b/third_party/WebKit/Source/core/editing/markers/DocumentMarker.cpp
index 1accf9a..44ab1f9 100644
--- a/third_party/WebKit/Source/core/editing/markers/DocumentMarker.cpp
+++ b/third_party/WebKit/Source/core/editing/markers/DocumentMarker.cpp
@@ -30,6 +30,7 @@
 
 #include "core/editing/markers/DocumentMarker.h"
 
+#include "core/editing/markers/TextMatchMarker.h"
 #include "platform/wtf/StdLibExtras.h"
 
 namespace blink {
@@ -62,43 +63,6 @@
   return 0;
 }
 
-class DocumentMarkerTextMatch final : public DocumentMarkerDetails {
- public:
-  static DocumentMarkerTextMatch* Create(DocumentMarker::MatchStatus);
-
-  bool IsActiveMatch() const {
-    return match_status_ == DocumentMarker::MatchStatus::kActive;
-  }
-
-  bool IsTextMatch() const override { return true; }
-
- private:
-  explicit DocumentMarkerTextMatch(DocumentMarker::MatchStatus match_status)
-      : match_status_(match_status) {}
-
-  DocumentMarker::MatchStatus match_status_;
-};
-
-DocumentMarkerTextMatch* DocumentMarkerTextMatch::Create(
-    DocumentMarker::MatchStatus match_status) {
-  DEFINE_STATIC_LOCAL(
-      DocumentMarkerTextMatch, active_instance,
-      (new DocumentMarkerTextMatch(DocumentMarker::MatchStatus::kActive)));
-  DEFINE_STATIC_LOCAL(
-      DocumentMarkerTextMatch, inactive_instance,
-      (new DocumentMarkerTextMatch(DocumentMarker::MatchStatus::kInactive)));
-  return match_status == DocumentMarker::MatchStatus::kActive
-             ? &active_instance
-             : &inactive_instance;
-}
-
-inline DocumentMarkerTextMatch* ToDocumentMarkerTextMatch(
-    DocumentMarkerDetails* details) {
-  if (details && details->IsTextMatch())
-    return static_cast<DocumentMarkerTextMatch*>(details);
-  return 0;
-}
-
 class TextCompositionMarkerDetails final : public DocumentMarkerDetails {
  public:
   static TextCompositionMarkerDetails* Create(Color underline_color,
@@ -140,6 +104,13 @@
 
 DocumentMarker::DocumentMarker(MarkerType type,
                                unsigned start_offset,
+                               unsigned end_offset)
+    : type_(type), start_offset_(start_offset), end_offset_(end_offset) {
+  DCHECK_LT(start_offset, end_offset);
+}
+
+DocumentMarker::DocumentMarker(MarkerType type,
+                               unsigned start_offset,
                                unsigned end_offset,
                                const String& description)
     : type_(type),
@@ -151,14 +122,6 @@
 
 DocumentMarker::DocumentMarker(unsigned start_offset,
                                unsigned end_offset,
-                               DocumentMarker::MatchStatus match_status)
-    : type_(DocumentMarker::kTextMatch),
-      start_offset_(start_offset),
-      end_offset_(end_offset),
-      details_(DocumentMarkerTextMatch::Create(match_status)) {}
-
-DocumentMarker::DocumentMarker(unsigned start_offset,
-                               unsigned end_offset,
                                Color underline_color,
                                bool thick,
                                Color background_color)
@@ -219,11 +182,10 @@
   start_offset_ += delta;
   end_offset_ += delta;
 }
-
 void DocumentMarker::SetIsActiveMatch(bool active) {
-  details_ = DocumentMarkerTextMatch::Create(
-      active ? DocumentMarker::MatchStatus::kActive
-             : DocumentMarker::MatchStatus::kInactive);
+  if (GetType() != DocumentMarker::kTextMatch)
+    return;
+  ToTextMatchMarker(this)->SetIsActiveMatch(active);
 }
 
 const String& DocumentMarker::Description() const {
@@ -234,10 +196,9 @@
 }
 
 bool DocumentMarker::IsActiveMatch() const {
-  if (DocumentMarkerTextMatch* details =
-          ToDocumentMarkerTextMatch(details_.Get()))
-    return details->IsActiveMatch();
-  return false;
+  if (GetType() != DocumentMarker::kTextMatch)
+    return false;
+  return ToTextMatchMarker(this)->IsActiveMatch();
 }
 
 Color DocumentMarker::UnderlineColor() const {
diff --git a/third_party/WebKit/Source/core/editing/markers/DocumentMarker.h b/third_party/WebKit/Source/core/editing/markers/DocumentMarker.h
index 2a1dd7d..97a11558 100644
--- a/third_party/WebKit/Source/core/editing/markers/DocumentMarker.h
+++ b/third_party/WebKit/Source/core/editing/markers/DocumentMarker.h
@@ -174,10 +174,10 @@
   DECLARE_TRACE();
 
  protected:
-  DocumentMarker(unsigned start_offset, unsigned end_offset, MatchStatus);
+  DocumentMarker(MarkerType, unsigned start_offset, unsigned end_offset);
 
  private:
-  MarkerType type_;
+  const MarkerType type_;
   unsigned start_offset_;
   unsigned end_offset_;
   Member<DocumentMarkerDetails> details_;
@@ -197,7 +197,6 @@
   DocumentMarkerDetails() {}
   virtual ~DocumentMarkerDetails();
   virtual bool IsDescription() const { return false; }
-  virtual bool IsTextMatch() const { return false; }
   virtual bool IsComposition() const { return false; }
 
   DEFINE_INLINE_VIRTUAL_TRACE() {}
diff --git a/third_party/WebKit/Source/core/editing/markers/TextMatchMarker.h b/third_party/WebKit/Source/core/editing/markers/TextMatchMarker.h
index 559f1a79..83cb212 100644
--- a/third_party/WebKit/Source/core/editing/markers/TextMatchMarker.h
+++ b/third_party/WebKit/Source/core/editing/markers/TextMatchMarker.h
@@ -40,38 +40,46 @@
   TextMatchMarker(unsigned start_offset,
                   unsigned end_offset,
                   MatchStatus status)
-      : DocumentMarker(start_offset, end_offset, status),
-        state_(State::kInvalid) {}
+      : DocumentMarker(DocumentMarker::kTextMatch, start_offset, end_offset),
+        match_status_(status) {
+    layout_state_ = State::kInvalid;
+  }
 
-  bool IsRendered() const { return state_ == State::kValidNotNull; }
+  bool IsActiveMatch() const { return match_status_ == MatchStatus::kActive; }
+  void SetIsActiveMatch(bool active) {
+    match_status_ = active ? MatchStatus::kActive : MatchStatus::kInactive;
+  }
+
+  bool IsRendered() const { return layout_state_ == State::kValidNotNull; }
   bool Contains(const LayoutPoint& point) const {
-    DCHECK_EQ(state_, State::kValidNotNull);
+    DCHECK_EQ(layout_state_, State::kValidNotNull);
     return rendered_rect_.Contains(point);
   }
   void SetRenderedRect(const LayoutRect& rect) {
-    if (state_ == State::kValidNotNull && rect == rendered_rect_)
+    if (layout_state_ == State::kValidNotNull && rect == rendered_rect_)
       return;
-    state_ = State::kValidNotNull;
+    layout_state_ = State::kValidNotNull;
     rendered_rect_ = rect;
   }
 
   const LayoutRect& RenderedRect() const {
-    DCHECK_EQ(state_, State::kValidNotNull);
+    DCHECK_EQ(layout_state_, State::kValidNotNull);
     return rendered_rect_;
   }
 
   void NullifyRenderedRect() {
-    state_ = State::kValidNull;
+    layout_state_ = State::kValidNull;
     // Now |m_renderedRect| can not be accessed until |setRenderedRect| is
     // called.
   }
 
-  void Invalidate() { state_ = State::kInvalid; }
-  bool IsValid() const { return state_ != State::kInvalid; }
+  void Invalidate() { layout_state_ = State::kInvalid; }
+  bool IsValid() const { return layout_state_ != State::kInvalid; }
 
  private:
+  MatchStatus match_status_;
   LayoutRect rendered_rect_;
-  State state_;
+  State layout_state_;
 };
 
 DEFINE_TYPE_CASTS(TextMatchMarker,
diff --git a/third_party/WebKit/Source/core/frame/Deprecation.h b/third_party/WebKit/Source/core/frame/Deprecation.h
index 0de97b4..7c632620 100644
--- a/third_party/WebKit/Source/core/frame/Deprecation.h
+++ b/third_party/WebKit/Source/core/frame/Deprecation.h
@@ -39,9 +39,22 @@
   //
   // For shared workers and service workers, the ExecutionContext* overload
   // doesn't count the usage but only sends a console warning.
+  // TODO(lunalu): Deprecate UseCounter::Feature by WebFeature
   static void CountDeprecation(const LocalFrame*, UseCounter::Feature);
   static void CountDeprecation(ExecutionContext*, UseCounter::Feature);
   static void CountDeprecation(const Document&, UseCounter::Feature);
+  static void CountDeprecation(const LocalFrame* frame, WebFeature feature) {
+    return CountDeprecation(frame, static_cast<UseCounter::Feature>(feature));
+  }
+  static void CountDeprecation(ExecutionContext* exec_context,
+                               WebFeature feature) {
+    return CountDeprecation(exec_context,
+                            static_cast<UseCounter::Feature>(feature));
+  }
+  static void CountDeprecation(const Document& document, WebFeature feature) {
+    return CountDeprecation(document,
+                            static_cast<UseCounter::Feature>(feature));
+  }
 
   // Count only features if they're being used in an iframe which does not
   // have script access into the top level document.
@@ -50,6 +63,19 @@
   static void CountDeprecationCrossOriginIframe(const Document&,
                                                 UseCounter::Feature);
   static String DeprecationMessage(UseCounter::Feature);
+  static void CountDeprecationCrossOriginIframe(const LocalFrame* frame,
+                                                WebFeature feature) {
+    return CountDeprecationCrossOriginIframe(
+        frame, static_cast<UseCounter::Feature>(feature));
+  }
+  static void CountDeprecationCrossOriginIframe(const Document& document,
+                                                WebFeature feature) {
+    return CountDeprecationCrossOriginIframe(
+        document, static_cast<UseCounter::Feature>(feature));
+  }
+  static String DeprecationMessage(WebFeature feature) {
+    return DeprecationMessage(static_cast<UseCounter::Feature>(feature));
+  }
 
   // Note: this is only public for tests.
   bool IsSuppressed(CSSPropertyID unresolved_property);
diff --git a/third_party/WebKit/Source/core/frame/Frame.cpp b/third_party/WebKit/Source/core/frame/Frame.cpp
index 188c8e13..9299387f 100644
--- a/third_party/WebKit/Source/core/frame/Frame.cpp
+++ b/third_party/WebKit/Source/core/frame/Frame.cpp
@@ -134,14 +134,6 @@
   return GetEmptyChromeClient();
 }
 
-Frame* Frame::FindFrameForNavigation(const AtomicString& name,
-                                     LocalFrame& active_frame) {
-  Frame* frame = Tree().Find(name);
-  if (!frame || !active_frame.CanNavigate(*frame))
-    return nullptr;
-  return frame;
-}
-
 Frame* Frame::FindUnsafeParentScrollPropagationBoundary() {
   Frame* current_frame = this;
   Frame* ancestor_frame = Tree().Parent();
diff --git a/third_party/WebKit/Source/core/frame/Frame.h b/third_party/WebKit/Source/core/frame/Frame.h
index 397a4783..7896db69 100644
--- a/third_party/WebKit/Source/core/frame/Frame.h
+++ b/third_party/WebKit/Source/core/frame/Frame.h
@@ -108,8 +108,6 @@
 
   virtual SecurityContext* GetSecurityContext() const = 0;
 
-  Frame* FindFrameForNavigation(const AtomicString& name,
-                                LocalFrame& active_frame);
   Frame* FindUnsafeParentScrollPropagationBoundary();
 
   // This prepares the Frame for the next commit. It will detach children,
diff --git a/third_party/WebKit/Source/core/frame/LocalFrame.cpp b/third_party/WebKit/Source/core/frame/LocalFrame.cpp
index 24d29958..4f1b795 100644
--- a/third_party/WebKit/Source/core/frame/LocalFrame.cpp
+++ b/third_party/WebKit/Source/core/frame/LocalFrame.cpp
@@ -531,6 +531,14 @@
     has_received_user_gesture_ = false;
 }
 
+Frame* LocalFrame::FindFrameForNavigation(const AtomicString& name,
+                                          LocalFrame& active_frame) {
+  Frame* frame = Tree().Find(name);
+  if (!frame || !active_frame.CanNavigate(*frame))
+    return nullptr;
+  return frame;
+}
+
 LocalWindowProxy* LocalFrame::WindowProxy(DOMWrapperWorld& world) {
   return ToLocalWindowProxy(Frame::GetWindowProxy(world));
 }
diff --git a/third_party/WebKit/Source/core/frame/LocalFrame.h b/third_party/WebKit/Source/core/frame/LocalFrame.h
index f49e7d09..66f54b2 100644
--- a/third_party/WebKit/Source/core/frame/LocalFrame.h
+++ b/third_party/WebKit/Source/core/frame/LocalFrame.h
@@ -128,6 +128,9 @@
   void DetachChildren();
   void DocumentAttached();
 
+  Frame* FindFrameForNavigation(const AtomicString& name,
+                                LocalFrame& active_frame);
+
   // Note: these two functions are not virtual but intentionally shadow the
   // corresponding method in the Frame base class to return the
   // LocalFrame-specific subclass.
diff --git a/third_party/WebKit/Source/core/frame/PRESUBMIT.py b/third_party/WebKit/Source/core/frame/PRESUBMIT.py
index 3d85942..a702108f 100644
--- a/third_party/WebKit/Source/core/frame/PRESUBMIT.py
+++ b/third_party/WebKit/Source/core/frame/PRESUBMIT.py
@@ -52,50 +52,13 @@
     return []
 
 
-def _RunUmaHistogramChecks(input_api, output_api):
-    import sys
-
-    original_sys_path = sys.path
-    try:
-        sys.path = sys.path + [input_api.os_path.join(
-            input_api.PresubmitLocalPath(), '..', '..', '..', '..', '..',
-            'tools', 'metrics', 'histograms')]
-        import update_histogram_enum
-    finally:
-        sys.path = original_sys_path
-
-    source_path = ''
-    for f in input_api.AffectedFiles():
-        if f.LocalPath().endswith('UseCounter.h'):
-            source_path = f.LocalPath()
-            break
-    else:
-        return []
-
-    start_marker = '^enum Feature : uint32_t {'
-    end_marker = '^kNumberOfFeatures'
-    presubmit_error = update_histogram_enum.CheckPresubmitErrors(
-        histogram_enum_name='FeatureObserver',
-        update_script_name='update_use_counter_feature_enum.py',
-        source_enum_path=source_path,
-        start_marker=start_marker,
-        end_marker=end_marker,
-        strip_k_prefix=True)
-    if presubmit_error:
-        return [output_api.PresubmitPromptWarning(presubmit_error,
-                                                  items=[source_path])]
-    return []
-
-
 def CheckChangeOnUpload(input_api, output_api):
     results = []
     results.extend(_RunUseCounterChecks(input_api, output_api))
-    results.extend(_RunUmaHistogramChecks(input_api, output_api))
     return results
 
 
 def CheckChangeOnCommit(input_api, output_api):
     results = []
     results.extend(_RunUseCounterChecks(input_api, output_api))
-    results.extend(_RunUmaHistogramChecks(input_api, output_api))
     return results
diff --git a/third_party/WebKit/Source/core/frame/UseCounter.cpp b/third_party/WebKit/Source/core/frame/UseCounter.cpp
index 3eac83c7..e1136016 100644
--- a/third_party/WebKit/Source/core/frame/UseCounter.cpp
+++ b/third_party/WebKit/Source/core/frame/UseCounter.cpp
@@ -1114,39 +1114,40 @@
   mute_count_--;
 }
 
-void UseCounter::RecordMeasurement(Feature feature) {
+void UseCounter::RecordMeasurement(WebFeature feature) {
   if (mute_count_)
     return;
 
   // PageDestruction is reserved as a scaling factor.
-  DCHECK_NE(kOBSOLETE_PageDestruction, feature);
-  DCHECK_NE(kPageVisits, feature);
-  DCHECK_GE(kNumberOfFeatures, feature);
+  DCHECK_NE(WebFeature::kOBSOLETE_PageDestruction, feature);
+  DCHECK_NE(WebFeature::kPageVisits, feature);
+  DCHECK_GE(WebFeature::kNumberOfFeatures, feature);
 
-  if (!features_recorded_.QuickGet(feature)) {
+  int feature_id = static_cast<int>(feature);
+  if (!features_recorded_.QuickGet(feature_id)) {
     // Note that HTTPArchive tooling looks specifically for this event - see
     // https://github.com/HTTPArchive/httparchive/issues/59
     if (context_ != kDisabledContext) {
       TRACE_EVENT1(TRACE_DISABLED_BY_DEFAULT("blink.feature_usage"),
-                   "FeatureFirstUsed", "feature", feature);
-      FeaturesHistogram().Count(feature);
+                   "FeatureFirstUsed", "feature", feature_id);
+      FeaturesHistogram().Count(feature_id);
       NotifyFeatureCounted(feature);
     }
-    features_recorded_.QuickSet(feature);
+    features_recorded_.QuickSet(feature_id);
   }
   legacy_counter_.CountFeature(feature);
 }
 
-bool UseCounter::HasRecordedMeasurement(Feature feature) const {
+bool UseCounter::HasRecordedMeasurement(WebFeature feature) const {
   if (mute_count_)
     return false;
 
   // PageDestruction is reserved as a scaling factor.
-  DCHECK_NE(kOBSOLETE_PageDestruction, feature);
-  DCHECK_NE(kPageVisits, feature);
-  DCHECK_GE(kNumberOfFeatures, feature);
+  DCHECK_NE(WebFeature::kOBSOLETE_PageDestruction, feature);
+  DCHECK_NE(WebFeature::kPageVisits, feature);
+  DCHECK_GE(WebFeature::kNumberOfFeatures, feature);
 
-  return features_recorded_.QuickGet(feature);
+  return features_recorded_.QuickGet(static_cast<int>(feature));
 }
 
 DEFINE_TRACE(UseCounter) {
@@ -1181,7 +1182,7 @@
   }
 }
 
-void UseCounter::Count(const LocalFrame* frame, Feature feature) {
+void UseCounter::Count(const LocalFrame* frame, WebFeature feature) {
   if (!frame)
     return;
   Page* page = frame->GetPage();
@@ -1191,7 +1192,7 @@
   page->GetUseCounter().Count(feature, frame);
 }
 
-void UseCounter::Count(const Document& document, Feature feature) {
+void UseCounter::Count(const Document& document, WebFeature feature) {
   Count(document.GetFrame(), feature);
 }
 
@@ -1222,15 +1223,17 @@
   return page->GetUseCounter().IsCounted(unresolved_property);
 }
 
-void UseCounter::Count(ExecutionContext* context, Feature feature) {
+void UseCounter::Count(ExecutionContext* context, WebFeature feature) {
   if (!context)
     return;
   if (context->IsDocument()) {
     Count(*ToDocument(context), feature);
     return;
   }
-  if (context->IsWorkerOrWorkletGlobalScope())
-    ToWorkerOrWorkletGlobalScope(context)->CountFeature(feature);
+  if (context->IsWorkerOrWorkletGlobalScope()) {
+    ToWorkerOrWorkletGlobalScope(context)->CountFeature(
+        static_cast<Feature>(feature));
+  }
 }
 
 void UseCounter::CountCrossOriginIframe(const Document& document,
@@ -1260,7 +1263,7 @@
   legacy_counter_.CountCSS(property);
 }
 
-void UseCounter::Count(Feature feature, const LocalFrame* source_frame) {
+void UseCounter::Count(WebFeature feature, const LocalFrame* source_frame) {
   // TODO(rbyers): Report UseCounter to browser process along with page
   // load metrics for sourceFrame  crbug.com/716565
   RecordMeasurement(feature);
@@ -1308,7 +1311,7 @@
   }
 }
 
-void UseCounter::NotifyFeatureCounted(Feature feature) {
+void UseCounter::NotifyFeatureCounted(WebFeature feature) {
   DCHECK(!mute_count_);
   DCHECK_NE(kDisabledContext, context_);
   HeapHashSet<Member<Observer>> to_be_removed;
@@ -1395,8 +1398,8 @@
   UpdateMeasurements();
 }
 
-void UseCounter::LegacyCounter::CountFeature(Feature feature) {
-  feature_bits_.QuickSet(feature);
+void UseCounter::LegacyCounter::CountFeature(WebFeature feature) {
+  feature_bits_.QuickSet(static_cast<int>(feature));
 }
 
 void UseCounter::LegacyCounter::CountCSS(CSSPropertyID property) {
diff --git a/third_party/WebKit/Source/core/frame/UseCounter.h b/third_party/WebKit/Source/core/frame/UseCounter.h
index 8969728..f122aea 100644
--- a/third_party/WebKit/Source/core/frame/UseCounter.h
+++ b/third_party/WebKit/Source/core/frame/UseCounter.h
@@ -35,6 +35,7 @@
 #include "platform/wtf/BitVector.h"
 #include "platform/wtf/Noncopyable.h"
 #include "platform/wtf/text/WTFString.h"
+#include "public/platform/WebFeature.h"
 #include "v8/include/v8.h"
 
 namespace blink {
@@ -78,1555 +79,7 @@
   UseCounter(Context = kDefaultContext);
 
   enum Feature : uint32_t {
-    // Do not change assigned numbers of existing items: add new features
-    // to the end of the list.
-    kOBSOLETE_PageDestruction = 0,
-    kWorkerStart = 4,
-    kSharedWorkerStart = 5,
-    kUnprefixedIndexedDB = 9,
-    kOpenWebDatabase = 10,
-    kUnprefixedRequestAnimationFrame = 13,
-    kPrefixedRequestAnimationFrame = 14,
-    kContentSecurityPolicy = 15,
-    kContentSecurityPolicyReportOnly = 16,
-    kPrefixedTransitionEndEvent = 18,
-    kUnprefixedTransitionEndEvent = 19,
-    kPrefixedAndUnprefixedTransitionEndEvent = 20,
-    kAutoFocusAttribute = 21,
-    kDataListElement = 23,
-    kFormAttribute = 24,
-    kIncrementalAttribute = 25,
-    kInputTypeColor = 26,
-    kInputTypeDate = 27,
-    kInputTypeDateTimeFallback = 29,
-    kInputTypeDateTimeLocal = 30,
-    kInputTypeEmail = 31,
-    kInputTypeMonth = 32,
-    kInputTypeNumber = 33,
-    kInputTypeRange = 34,
-    kInputTypeSearch = 35,
-    kInputTypeTel = 36,
-    kInputTypeTime = 37,
-    kInputTypeURL = 38,
-    kInputTypeWeek = 39,
-    kInputTypeWeekFallback = 40,
-    kListAttribute = 41,
-    kMaxAttribute = 42,
-    kMinAttribute = 43,
-    kPatternAttribute = 44,
-    kPlaceholderAttribute = 45,
-    kPrefixedDirectoryAttribute = 47,
-    kRequiredAttribute = 49,
-    kStepAttribute = 51,
-    kPageVisits = 52,
-    kHTMLMarqueeElement = 53,
-    kReflection = 55,
-    kPrefixedStorageInfo = 57,
-    kDeprecatedFlexboxWebContent = 61,
-    kDeprecatedFlexboxChrome = 62,
-    kDeprecatedFlexboxChromeExtension = 63,
-    kUnprefixedPerformanceTimeline = 65,
-    kUnprefixedUserTiming = 67,
-    kWindowEvent = 69,
-    kContentSecurityPolicyWithBaseElement = 70,
-    kDocumentClear = 74,
-    kXMLDocument = 77,
-    kXSLProcessingInstruction = 78,
-    kXSLTProcessor = 79,
-    kSVGSwitchElement = 80,
-    kDocumentAll = 83,
-    kFormElement = 84,
-    kDemotedFormElement = 85,
-    kSVGAnimationElement = 90,
-    kLineClamp = 96,
-    kSubFrameBeforeUnloadRegistered = 97,
-    kSubFrameBeforeUnloadFired = 98,
-    kConsoleMarkTimeline = 102,
-    kDocumentCreateAttribute = 111,
-    kDocumentCreateAttributeNS = 112,
-    kDocumentXMLEncoding = 115,    // Removed from DOM4.
-    kDocumentXMLStandalone = 116,  // Removed from DOM4.
-    kDocumentXMLVersion = 117,     // Removed from DOM4.
-    kNavigatorProductSub = 123,
-    kNavigatorVendor = 124,
-    kNavigatorVendorSub = 125,
-    kPrefixedAnimationEndEvent = 128,
-    kUnprefixedAnimationEndEvent = 129,
-    kPrefixedAndUnprefixedAnimationEndEvent = 130,
-    kPrefixedAnimationStartEvent = 131,
-    kUnprefixedAnimationStartEvent = 132,
-    kPrefixedAndUnprefixedAnimationStartEvent = 133,
-    kPrefixedAnimationIterationEvent = 134,
-    kUnprefixedAnimationIterationEvent = 135,
-    kPrefixedAndUnprefixedAnimationIterationEvent = 136,
-    kEventReturnValue = 137,  // Legacy IE extension.
-    kSVGSVGElement = 138,
-    kDOMSubtreeModifiedEvent = 143,
-    kDOMNodeInsertedEvent = 144,
-    kDOMNodeRemovedEvent = 145,
-    kDOMNodeRemovedFromDocumentEvent = 146,
-    kDOMNodeInsertedIntoDocumentEvent = 147,
-    kDOMCharacterDataModifiedEvent = 148,
-    kDocumentAllLegacyCall = 150,
-    kGetMatchedCSSRules = 155,
-    kPrefixedAudioDecodedByteCount = 164,
-    kPrefixedVideoDecodedByteCount = 165,
-    kPrefixedVideoSupportsFullscreen = 166,
-    kPrefixedVideoDisplayingFullscreen = 167,
-    kPrefixedVideoEnterFullscreen = 168,
-    kPrefixedVideoExitFullscreen = 169,
-    kPrefixedVideoEnterFullScreen = 170,
-    kPrefixedVideoExitFullScreen = 171,
-    kPrefixedVideoDecodedFrameCount = 172,
-    kPrefixedVideoDroppedFrameCount = 173,
-    kPrefixedElementRequestFullscreen = 176,
-    kPrefixedElementRequestFullScreen = 177,
-    kBarPropLocationbar = 178,
-    kBarPropMenubar = 179,
-    kBarPropPersonalbar = 180,
-    kBarPropScrollbars = 181,
-    kBarPropStatusbar = 182,
-    kBarPropToolbar = 183,
-    kInputTypeEmailMultiple = 184,
-    kInputTypeEmailMaxLength = 185,
-    kInputTypeEmailMultipleMaxLength = 186,
-    kInputTypeText = 190,
-    kInputTypeTextMaxLength = 191,
-    kInputTypePassword = 192,
-    kInputTypePasswordMaxLength = 193,
-    kPrefixedPageVisibility = 196,
-    kDocumentBeforeUnloadRegistered = 200,
-    kDocumentBeforeUnloadFired = 201,
-    kDocumentUnloadRegistered = 202,
-    kDocumentUnloadFired = 203,
-    kSVGLocatableNearestViewportElement = 204,
-    kSVGLocatableFarthestViewportElement = 205,
-    kSVGPointMatrixTransform = 209,
-    kDOMFocusInOutEvent = 211,
-    kFileGetLastModifiedDate = 212,
-    kHTMLElementInnerText = 213,
-    kHTMLElementOuterText = 214,
-    kReplaceDocumentViaJavaScriptURL = 215,
-    kElementPrefixedMatchesSelector = 217,
-    kCSSStyleSheetRules = 219,
-    kCSSStyleSheetAddRule = 220,
-    kCSSStyleSheetRemoveRule = 221,
-    // The above items are available in M33 branch.
-
-    kInitMessageEvent = 222,
-    kPrefixedDevicePixelRatioMediaFeature = 233,
-    kPrefixedMaxDevicePixelRatioMediaFeature = 234,
-    kPrefixedMinDevicePixelRatioMediaFeature = 235,
-    kPrefixedTransform3dMediaFeature = 237,
-    kPrefixedStorageQuota = 240,
-    kResetReferrerPolicy = 243,
-    // Case-insensitivity dropped from specification.
-    kCaseInsensitiveAttrSelectorMatch = 244,
-    kFormNameAccessForImageElement = 246,
-    kFormNameAccessForPastNamesMap = 247,
-    kFormAssociationByParser = 248,
-    kSVGSVGElementInDocument = 250,
-    kSVGDocumentRootElement = 251,
-    kWorkerSubjectToCSP = 257,
-    kWorkerAllowedByChildBlockedByScript = 258,
-    kDeprecatedWebKitGradient = 260,
-    kDeprecatedWebKitLinearGradient = 261,
-    kDeprecatedWebKitRepeatingLinearGradient = 262,
-    kDeprecatedWebKitRadialGradient = 263,
-    kDeprecatedWebKitRepeatingRadialGradient = 264,
-    // The above items are available in M34 branch.
-
-    kTextAutosizing = 274,
-    kHTMLAnchorElementPingAttribute = 276,
-    kSVGClassName = 279,
-    kHTMLMediaElementSeekToFragmentStart = 281,
-    kHTMLMediaElementPauseAtFragmentEnd = 282,
-    kPrefixedWindowURL = 283,
-    kWindowOrientation = 285,
-    kDocumentCaptureEvents = 287,
-    kDocumentReleaseEvents = 288,
-    kWindowCaptureEvents = 289,
-    kWindowReleaseEvents = 290,
-    kDocumentXPathCreateExpression = 295,
-    kDocumentXPathCreateNSResolver = 296,
-    kDocumentXPathEvaluate = 297,
-    kAnimationConstructorKeyframeListEffectObjectTiming = 300,
-    kAnimationConstructorKeyframeListEffectNoTiming = 302,
-    kPrefixedCancelAnimationFrame = 304,
-    kNamedNodeMapGetNamedItem = 306,
-    kNamedNodeMapSetNamedItem = 307,
-    kNamedNodeMapRemoveNamedItem = 308,
-    kNamedNodeMapItem = 309,
-    kNamedNodeMapGetNamedItemNS = 310,
-    kNamedNodeMapSetNamedItemNS = 311,
-    kNamedNodeMapRemoveNamedItemNS = 312,
-    kPrefixedDocumentIsFullscreen = 318,
-    kPrefixedDocumentCurrentFullScreenElement = 320,
-    kPrefixedDocumentCancelFullScreen = 321,
-    kPrefixedDocumentFullscreenEnabled = 322,
-    kPrefixedDocumentFullscreenElement = 323,
-    kPrefixedDocumentExitFullscreen = 324,
-    // The above items are available in M35 branch.
-
-    kSVGForeignObjectElement = 325,
-    kSelectionSetPosition = 327,
-    kAnimationFinishEvent = 328,
-    kSVGSVGElementInXMLDocument = 329,
-    kEventSrcElement = 343,
-    kEventCancelBubble = 344,
-    kEventPath = 345,
-    kNodeIteratorDetach = 347,
-    kEventGetReturnValueTrue = 350,
-    kEventGetReturnValueFalse = 351,
-    kEventSetReturnValueTrue = 352,
-    kEventSetReturnValueFalse = 353,
-    kWindowOffscreenBuffering = 356,
-    kWindowDefaultStatus = 357,
-    kWindowDefaultstatus = 358,
-    kPrefixedTransitionEventConstructor = 361,
-    kPrefixedMutationObserverConstructor = 362,
-    kNotificationPermission = 371,
-    kRangeDetach = 372,
-    kPrefixedFileRelativePath = 386,
-    kDocumentCaretRangeFromPoint = 387,
-    kElementScrollIntoViewIfNeeded = 389,
-    kRangeExpand = 393,
-    kHTMLImageElementX = 396,
-    kHTMLImageElementY = 397,
-    kSelectionBaseNode = 400,
-    kSelectionBaseOffset = 401,
-    kSelectionExtentNode = 402,
-    kSelectionExtentOffset = 403,
-    kSelectionType = 404,
-    kSelectionModify = 405,
-    kSelectionSetBaseAndExtent = 406,
-    kSelectionEmpty = 407,
-    kVTTCue = 409,
-    kVTTCueRender = 410,
-    kVTTCueRenderVertical = 411,
-    kVTTCueRenderSnapToLinesFalse = 412,
-    kVTTCueRenderLineNotAuto = 413,
-    kVTTCueRenderPositionNot50 = 414,
-    kVTTCueRenderSizeNot100 = 415,
-    kVTTCueRenderAlignNotCenter = 416,
-    // The above items are available in M36 branch.
-
-    kElementRequestPointerLock = 417,
-    kVTTCueRenderRtl = 418,
-    kPostMessageFromSecureToInsecure = 419,
-    kPostMessageFromInsecureToSecure = 420,
-    kDocumentExitPointerLock = 421,
-    kDocumentPointerLockElement = 422,
-    kPrefixedCursorZoomIn = 424,
-    kPrefixedCursorZoomOut = 425,
-    kTextEncoderConstructor = 429,
-    kTextEncoderEncode = 430,
-    kTextDecoderConstructor = 431,
-    kTextDecoderDecode = 432,
-    kFocusInOutEvent = 433,
-    kMouseEventMovementX = 434,
-    kMouseEventMovementY = 435,
-    kDocumentFonts = 440,
-    kMixedContentFormsSubmitted = 441,
-    kFormsSubmitted = 442,
-    kHTMLImports = 455,
-    kElementCreateShadowRoot = 456,
-    kDocumentRegisterElement = 457,
-    kEditingAppleInterchangeNewline = 458,
-    kEditingAppleConvertedSpace = 459,
-    kEditingApplePasteAsQuotation = 460,
-    kEditingAppleStyleSpanClass = 461,
-    kHTMLImportsAsyncAttribute = 463,
-    kXMLHttpRequestSynchronous = 465,
-    kCSSSelectorPseudoUnresolved = 466,
-    kCSSSelectorPseudoShadow = 467,
-    kCSSSelectorPseudoContent = 468,
-    kCSSSelectorPseudoHost = 469,
-    kCSSSelectorPseudoHostContext = 470,
-    kCSSDeepCombinator = 471,
-    // The above items are available in M37 branch.
-
-    kUseAsm = 473,
-    kDOMWindowOpen = 475,
-    kDOMWindowOpenFeatures = 476,
-    kAspectRatioFlexItem = 479,
-    kDetailsElement = 480,
-    kDialogElement = 481,
-    kMapElement = 482,
-    kMeterElement = 483,
-    kProgressElement = 484,
-    kWheelEventWheelDeltaX = 491,
-    kWheelEventWheelDeltaY = 492,
-    kWheelEventWheelDelta = 493,
-    kSendBeacon = 494,
-    kSendBeaconQuotaExceeded = 495,
-    kSVGSMILElementInDocument = 501,
-    kMouseEventOffsetX = 502,
-    kMouseEventOffsetY = 503,
-    kMouseEventX = 504,
-    kMouseEventY = 505,
-    kMouseEventFromElement = 506,
-    kMouseEventToElement = 507,
-    kRequestFileSystem = 508,
-    kRequestFileSystemWorker = 509,
-    kRequestFileSystemSyncWorker = 510,
-    kSVGStyleElementTitle = 519,
-    kPictureSourceSrc = 520,
-    // The above items are available in M38 branch.
-
-    kPicture = 521,
-    kSizes = 522,
-    kSrcsetXDescriptor = 523,
-    kSrcsetWDescriptor = 524,
-    kSelectionContainsNode = 525,
-    kXMLExternalResourceLoad = 529,
-    kMixedContentPrivateHostnameInPublicHostname = 530,
-    kLegacyProtocolEmbeddedAsSubresource = 531,
-    kRequestedSubresourceWithEmbeddedCredentials = 532,
-    kNotificationCreated = 533,
-    kNotificationClosed = 534,
-    kNotificationPermissionRequested = 535,
-    kConsoleTimeline = 538,
-    kConsoleTimelineEnd = 539,
-    kSRIElementWithMatchingIntegrityAttribute = 540,
-    kSRIElementWithNonMatchingIntegrityAttribute = 541,
-    kSRIElementWithUnparsableIntegrityAttribute = 542,
-    kV8Animation_StartTime_AttributeGetter = 545,
-    kV8Animation_StartTime_AttributeSetter = 546,
-    kV8Animation_CurrentTime_AttributeGetter = 547,
-    kV8Animation_CurrentTime_AttributeSetter = 548,
-    kV8Animation_PlaybackRate_AttributeGetter = 549,
-    kV8Animation_PlaybackRate_AttributeSetter = 550,
-    kV8Animation_PlayState_AttributeGetter = 551,
-    kV8Animation_Finish_Method = 552,
-    kV8Animation_Play_Method = 553,
-    kV8Animation_Pause_Method = 554,
-    kV8Animation_Reverse_Method = 555,
-    // The above items are available in M39 branch.
-
-    kBreakIterator = 556,
-    kScreenOrientationAngle = 557,
-    kScreenOrientationType = 558,
-    kScreenOrientationLock = 559,
-    kScreenOrientationUnlock = 560,
-    kGeolocationSecureOrigin = 561,
-    kGeolocationInsecureOrigin = 562,
-    kNotificationSecureOrigin = 563,
-    kNotificationInsecureOrigin = 564,
-    kNotificationShowEvent = 565,
-    kSVGTransformListConsolidate = 569,
-    kSVGAnimatedTransformListBaseVal = 570,
-    kQuotedAnimationName = 571,
-    kQuotedKeyframesRule = 572,
-    kSrcsetDroppedCandidate = 573,
-    kWindowPostMessage = 574,
-    kRenderRuby = 576,
-    kScriptElementWithInvalidTypeHasSrc = 578,
-    kXMLHttpRequestSynchronousInNonWorkerOutsideBeforeUnload = 581,
-    kCSSSelectorPseudoScrollbar = 582,
-    kCSSSelectorPseudoScrollbarButton = 583,
-    kCSSSelectorPseudoScrollbarThumb = 584,
-    kCSSSelectorPseudoScrollbarTrack = 585,
-    kCSSSelectorPseudoScrollbarTrackPiece = 586,
-    kLangAttribute = 587,
-    kLangAttributeOnHTML = 588,
-    kLangAttributeOnBody = 589,
-    kLangAttributeDoesNotMatchToUILocale = 590,
-    kInputTypeSubmit = 591,
-    kInputTypeSubmitWithValue = 592,
-    // The above items are available in M40 branch.
-
-    kSetReferrerPolicy = 593,
-    kTextWholeText = 599,
-    kNotificationCloseEvent = 603,
-    kStyleMedia = 606,
-    kStyleMediaType = 607,
-    kStyleMediaMatchMedium = 608,
-    kMixedContentPresent = 609,
-    kMixedContentBlockable = 610,
-    kMixedContentAudio = 611,
-    kMixedContentDownload = 612,
-    kMixedContentFavicon = 613,
-    kMixedContentImage = 614,
-    kMixedContentInternal = 615,
-    kMixedContentPlugin = 616,
-    kMixedContentPrefetch = 617,
-    kMixedContentVideo = 618,
-    kCSSSelectorPseudoFullScreenAncestor = 628,
-    kCSSSelectorPseudoFullScreen = 629,
-    kWebKitCSSMatrix = 630,
-    kAudioContextCreateAnalyser = 631,
-    kAudioContextCreateBiquadFilter = 632,
-    kAudioContextCreateBufferSource = 633,
-    kAudioContextCreateChannelMerger = 634,
-    kAudioContextCreateChannelSplitter = 635,
-    kAudioContextCreateConvolver = 636,
-    kAudioContextCreateDelay = 637,
-    kAudioContextCreateDynamicsCompressor = 638,
-    kAudioContextCreateGain = 639,
-    kAudioContextCreateMediaElementSource = 640,
-    kAudioContextCreateMediaStreamDestination = 641,
-    kAudioContextCreateMediaStreamSource = 642,
-    kAudioContextCreateOscillator = 643,
-    kAudioContextCreatePeriodicWave = 645,
-    kAudioContextCreateScriptProcessor = 646,
-    kAudioContextCreateStereoPanner = 647,
-    kAudioContextCreateWaveShaper = 648,
-    kAudioContextDecodeAudioData = 649,
-    kAudioContextResume = 650,
-    kAudioContextSuspend = 651,
-    kMixedContentInNonHTTPSFrameThatRestrictsMixedContent = 661,
-    kMixedContentInSecureFrameThatDoesNotRestrictMixedContent = 662,
-    kMixedContentWebSocket = 663,
-    kSyntheticKeyframesInCompositedCSSAnimation = 664,
-    kMixedContentFormPresent = 665,
-    kGetUserMediaInsecureOrigin = 666,
-    kGetUserMediaSecureOrigin = 667,
-    // The above items are available in M41 branch.
-
-    kDeviceMotionInsecureOrigin = 668,
-    kDeviceMotionSecureOrigin = 669,
-    kDeviceOrientationInsecureOrigin = 670,
-    kDeviceOrientationSecureOrigin = 671,
-    kSandboxViaIFrame = 672,
-    kSandboxViaCSP = 673,
-    kBlockedSniffingImageToScript = 674,
-    kFetch = 675,
-    kFetchBodyStream = 676,
-    kXMLHttpRequestAsynchronous = 677,
-    kWhiteSpacePreFromXMLSpace = 679,
-    kWhiteSpaceNowrapFromXMLSpace = 680,
-    kSVGSVGElementForceRedraw = 685,
-    kSVGSVGElementSuspendRedraw = 686,
-    kSVGSVGElementUnsuspendRedraw = 687,
-    kSVGSVGElementUnsuspendRedrawAll = 688,
-    kAudioContextClose = 689,
-    kCSSZoomNotEqualToOne = 691,
-    // The above items are available in M42 branch.
-
-    kClientRectListItem = 694,
-    kWindowClientInformation = 695,
-    kWindowFind = 696,
-    kWindowScreenLeft = 697,
-    kWindowScreenTop = 698,
-    kV8Animation_Cancel_Method = 699,
-    kV8Animation_Onfinish_AttributeGetter = 700,
-    kV8Animation_Onfinish_AttributeSetter = 701,
-    kV8Window_WebKitAnimationEvent_ConstructorGetter = 707,
-    kCryptoGetRandomValues = 710,
-    kSubtleCryptoEncrypt = 711,
-    kSubtleCryptoDecrypt = 712,
-    kSubtleCryptoSign = 713,
-    kSubtleCryptoVerify = 714,
-    kSubtleCryptoDigest = 715,
-    kSubtleCryptoGenerateKey = 716,
-    kSubtleCryptoImportKey = 717,
-    kSubtleCryptoExportKey = 718,
-    kSubtleCryptoDeriveBits = 719,
-    kSubtleCryptoDeriveKey = 720,
-    kSubtleCryptoWrapKey = 721,
-    kSubtleCryptoUnwrapKey = 722,
-    kCryptoAlgorithmAesCbc = 723,
-    kCryptoAlgorithmHmac = 724,
-    kCryptoAlgorithmRsaSsaPkcs1v1_5 = 725,
-    kCryptoAlgorithmSha1 = 726,
-    kCryptoAlgorithmSha256 = 727,
-    kCryptoAlgorithmSha384 = 728,
-    kCryptoAlgorithmSha512 = 729,
-    kCryptoAlgorithmAesGcm = 730,
-    kCryptoAlgorithmRsaOaep = 731,
-    kCryptoAlgorithmAesCtr = 732,
-    kCryptoAlgorithmAesKw = 733,
-    kCryptoAlgorithmRsaPss = 734,
-    kCryptoAlgorithmEcdsa = 735,
-    kCryptoAlgorithmEcdh = 736,
-    kCryptoAlgorithmHkdf = 737,
-    kCryptoAlgorithmPbkdf2 = 738,
-    kDocumentSetDomain = 739,
-    kUpgradeInsecureRequestsEnabled = 740,
-    kUpgradeInsecureRequestsUpgradedRequest = 741,
-    kDocumentDesignMode = 742,
-    kGlobalCacheStorage = 743,
-    kNetInfo = 744,
-    kBackgroundSync = 745,
-    kLegacyConst = 748,
-    kV8Permissions_Query_Method = 750,
-    // The above items are available in M43 branch.
-
-    kV8HTMLInputElement_Autocapitalize_AttributeGetter = 754,
-    kV8HTMLInputElement_Autocapitalize_AttributeSetter = 755,
-    kV8HTMLTextAreaElement_Autocapitalize_AttributeGetter = 756,
-    kV8HTMLTextAreaElement_Autocapitalize_AttributeSetter = 757,
-    kSVGHrefBaseVal = 758,
-    kSVGHrefAnimVal = 759,
-    kV8CSSRuleList_Item_Method = 760,
-    kV8MediaList_Item_Method = 761,
-    kV8StyleSheetList_Item_Method = 762,
-    kStyleSheetListAnonymousNamedGetter = 763,
-    kAutocapitalizeAttribute = 764,
-    kFullscreenSecureOrigin = 765,
-    kFullscreenInsecureOrigin = 766,
-    kDialogInSandboxedContext = 767,
-    kSVGSMILAnimationInImageRegardlessOfCache = 768,
-    kPerformanceFrameTiming = 772,
-    kV8Element_Animate_Method = 773,
-    // The above items are available in M44 branch.
-
-    kV8SVGSVGElement_GetElementById_Method = 778,
-    kElementCreateShadowRootMultiple = 779,
-    kV8MessageChannel_Constructor = 780,
-    kV8MessagePort_PostMessage_Method = 781,
-    kV8MessagePort_Start_Method = 782,
-    kV8MessagePort_Close_Method = 783,
-    kMessagePortsTransferred = 784,
-    kCSSKeyframesRuleAnonymousIndexedGetter = 785,
-    kV8Screen_AvailLeft_AttributeGetter = 786,
-    kV8Screen_AvailTop_AttributeGetter = 787,
-    kV8SVGFEConvolveMatrixElement_PreserveAlpha_AttributeGetter = 791,
-    kV8SVGStyleElement_Disabled_AttributeGetter = 798,
-    kV8SVGStyleElement_Disabled_AttributeSetter = 799,
-    kInputTypeFileSecureOrigin = 801,
-    kInputTypeFileInsecureOrigin = 802,
-    kElementAttachShadow = 804,
-    kV8SecurityPolicyViolationEvent_DocumentURI_AttributeGetter = 806,
-    kV8SecurityPolicyViolationEvent_BlockedURI_AttributeGetter = 807,
-    kV8SecurityPolicyViolationEvent_StatusCode_AttributeGetter = 808,
-    kHTMLLinkElementDisabled = 809,
-    kV8HTMLLinkElement_Disabled_AttributeGetter = 810,
-    kV8HTMLLinkElement_Disabled_AttributeSetter = 811,
-    kV8HTMLStyleElement_Disabled_AttributeGetter = 812,
-    kV8HTMLStyleElement_Disabled_AttributeSetter = 813,
-    kV8DOMError_Constructor = 816,
-    kV8DOMError_Name_AttributeGetter = 817,
-    kV8DOMError_Message_AttributeGetter = 818,
-    kTextInputFired = 830,
-    kV8TextEvent_Data_AttributeGetter = 831,
-    kV8TextEvent_InitTextEvent_Method = 832,
-    kClientHintsDPR = 835,
-    kClientHintsResourceWidth = 836,
-    kClientHintsViewportWidth = 837,
-    kSRIElementIntegrityAttributeButIneligible = 838,
-    kFormDataAppendNull = 843,
-    kNonHTMLElementSetAttributeNodeFromHTMLDocumentNameNotLowercase = 845,
-    kNavigatorVibrate = 850,
-    kNavigatorVibrateSubFrame = 851,
-    kV8XPathEvaluator_Constructor = 853,
-    kV8XPathEvaluator_CreateExpression_Method = 854,
-    kV8XPathEvaluator_CreateNSResolver_Method = 855,
-    kV8XPathEvaluator_Evaluate_Method = 856,
-    kRequestMIDIAccess = 857,
-    kV8MouseEvent_LayerX_AttributeGetter = 858,
-    kV8MouseEvent_LayerY_AttributeGetter = 859,
-    kInnerTextWithShadowTree = 860,
-    kSelectionToStringWithShadowTree = 861,
-    kWindowFindWithShadowTree = 862,
-    kV8CompositionEvent_InitCompositionEvent_Method = 863,
-    kV8CustomEvent_InitCustomEvent_Method = 864,
-    kV8DeviceMotionEvent_InitDeviceMotionEvent_Method = 865,
-    kV8DeviceOrientationEvent_InitDeviceOrientationEvent_Method = 866,
-    kV8Event_InitEvent_Method = 867,
-    kV8KeyboardEvent_InitKeyboardEvent_Method = 868,
-    kV8MouseEvent_InitMouseEvent_Method = 869,
-    kV8MutationEvent_InitMutationEvent_Method = 870,
-    kV8StorageEvent_InitStorageEvent_Method = 871,
-    kV8UIEvent_InitUIEvent_Method = 873,
-    kV8Document_CreateTouch_Method = 874,
-    kRequestFileSystemNonWebbyOrigin = 876,
-    kV8MemoryInfo_TotalJSHeapSize_AttributeGetter = 879,
-    kV8MemoryInfo_UsedJSHeapSize_AttributeGetter = 880,
-    kV8MemoryInfo_JSHeapSizeLimit_AttributeGetter = 881,
-    kV8Performance_Timing_AttributeGetter = 882,
-    kV8Performance_Navigation_AttributeGetter = 883,
-    kV8Performance_Memory_AttributeGetter = 884,
-    kV8SharedWorker_WorkerStart_AttributeGetter = 885,
-    // The above items are available in M45 branch.
-
-    kHTMLMediaElementPreloadNone = 892,
-    kHTMLMediaElementPreloadMetadata = 893,
-    kHTMLMediaElementPreloadAuto = 894,
-    kHTMLMediaElementPreloadDefault = 895,
-    kMixedContentBlockableAllowed = 896,
-    kPseudoBeforeAfterForInputElement = 897,
-    kV8Permissions_Revoke_Method = 898,
-    kLinkRelDnsPrefetch = 899,
-    kLinkRelPreconnect = 900,
-    kLinkRelPreload = 901,
-    kLinkHeaderDnsPrefetch = 902,
-    kLinkHeaderPreconnect = 903,
-    kClientHintsMetaAcceptCH = 904,
-    kHTMLElementDeprecatedWidth = 905,
-    kClientHintsContentDPR = 906,
-    kElementAttachShadowOpen = 907,
-    kElementAttachShadowClosed = 908,
-    kAudioParamSetValueAtTime = 909,
-    kAudioParamLinearRampToValueAtTime = 910,
-    kAudioParamExponentialRampToValueAtTime = 911,
-    kAudioParamSetTargetAtTime = 912,
-    kAudioParamSetValueCurveAtTime = 913,
-    kAudioParamCancelScheduledValues = 914,
-    kV8Permissions_Request_Method = 915,
-    kLinkRelPrefetch = 917,
-    kLinkRelPrerender = 918,
-    kLinkRelNext = 919,
-    kCSSValuePrefixedMinContent = 921,
-    kCSSValuePrefixedMaxContent = 922,
-    kCSSValuePrefixedFitContent = 923,
-    kCSSValuePrefixedFillAvailable = 924,
-    kPresentationDefaultRequest = 926,
-    kPresentationAvailabilityChangeEventListener = 927,
-    kPresentationRequestConstructor = 928,
-    kPresentationRequestStart = 929,
-    kPresentationRequestReconnect = 930,
-    kPresentationRequestGetAvailability = 931,
-    kPresentationRequestConnectionAvailableEventListener = 932,
-    kPresentationConnectionTerminate = 933,
-    kPresentationConnectionSend = 934,
-    kPresentationConnectionMessageEventListener = 936,
-    kCSSAnimationsStackedNeutralKeyframe = 937,
-    kReadingCheckedInClickHandler = 938,
-    kFlexboxIntrinsicSizeAlgorithmIsDifferent = 939,
-    // The above items are available in M46 branch.
-
-    kHTMLImportsHasStyleSheets = 940,
-    kNetInfoType = 946,
-    kNetInfoDownlinkMax = 947,
-    kNetInfoOnChange = 948,
-    kNetInfoOnTypeChange = 949,
-    kV8Window_Alert_Method = 950,
-    kV8Window_Confirm_Method = 951,
-    kV8Window_Prompt_Method = 952,
-    kV8Window_Print_Method = 953,
-    kV8Window_RequestIdleCallback_Method = 954,
-    kFlexboxPercentagePaddingVertical = 955,
-    kFlexboxPercentageMarginVertical = 956,
-    kBackspaceNavigatedBack = 957,
-    kBackspaceNavigatedBackAfterFormInteraction = 958,
-    kCSPSourceWildcardWouldMatchExactHost = 959,
-    kCredentialManagerGet = 960,
-    kCredentialManagerGetMediationOptional = 961,
-    kCredentialManagerGetMediationSilent = 962,
-    kCredentialManagerStore = 963,
-    kCredentialManagerRequireUserMediation = 964,
-    // The above items are available in M47 branch.
-
-    kBlockableMixedContentInSubframeBlocked = 966,
-    kAddEventListenerThirdArgumentIsObject = 967,
-    kRemoveEventListenerThirdArgumentIsObject = 968,
-    kCSSAtRuleCharset = 969,
-    kCSSAtRuleFontFace = 970,
-    kCSSAtRuleImport = 971,
-    kCSSAtRuleKeyframes = 972,
-    kCSSAtRuleMedia = 973,
-    kCSSAtRuleNamespace = 974,
-    kCSSAtRulePage = 975,
-    kCSSAtRuleSupports = 976,
-    kCSSAtRuleViewport = 977,
-    kCSSAtRuleWebkitKeyframes = 978,
-    kV8HTMLFieldSetElement_Elements_AttributeGetter = 979,
-    kHTMLMediaElementPreloadForcedNone = 980,
-    kExternalAddSearchProvider = 981,
-    kExternalIsSearchProviderInstalled = 982,
-    kV8Permissions_RequestAll_Method = 983,
-    kDeviceOrientationAbsoluteInsecureOrigin = 987,
-    kDeviceOrientationAbsoluteSecureOrigin = 988,
-    kFontFaceConstructor = 989,
-    kServiceWorkerControlledPage = 990,
-    kMeterElementWithMeterAppearance = 993,
-    kMeterElementWithNoneAppearance = 994,
-    kSelectionAnchorNode = 997,
-    kSelectionAnchorOffset = 998,
-    kSelectionFocusNode = 999,
-    kSelectionFocusOffset = 1000,
-    kSelectionIsCollapsed = 1001,
-    kSelectionRangeCount = 1002,
-    kSelectionGetRangeAt = 1003,
-    kSelectionAddRange = 1004,
-    kSelectionRemoveAllRanges = 1005,
-    kSelectionCollapse = 1006,
-    kSelectionCollapseToStart = 1007,
-    kSelectionCollapseToEnd = 1008,
-    kSelectionExtend = 1009,
-    kSelectionSelectAllChildren = 1010,
-    kSelectionDeleteDromDocument = 1011,
-    kSelectionDOMString = 1012,
-    kInputTypeRangeVerticalAppearance = 1013,
-    // The above items are available in M48 branch.
-
-    kCSSFilterReference = 1014,
-    kCSSFilterGrayscale = 1015,
-    kCSSFilterSepia = 1016,
-    kCSSFilterSaturate = 1017,
-    kCSSFilterHueRotate = 1018,
-    kCSSFilterInvert = 1019,
-    kCSSFilterOpacity = 1020,
-    kCSSFilterBrightness = 1021,
-    kCSSFilterContrast = 1022,
-    kCSSFilterBlur = 1023,
-    kCSSFilterDropShadow = 1024,
-    kBackgroundSyncRegister = 1025,
-    kExecCommandOnInputOrTextarea = 1027,
-    kV8History_ScrollRestoration_AttributeGetter = 1028,
-    kV8History_ScrollRestoration_AttributeSetter = 1029,
-    kSVG1DOMFilter = 1030,
-    kOfflineAudioContextStartRendering = 1031,
-    kOfflineAudioContextSuspend = 1032,
-    kOfflineAudioContextResume = 1033,
-    kSVG1DOMPaintServer = 1035,
-    kSVGSVGElementFragmentSVGView = 1036,
-    kSVGSVGElementFragmentSVGViewElement = 1037,
-    kPresentationConnectionClose = 1038,
-    kSVG1DOMShape = 1039,
-    kSVG1DOMText = 1040,
-    kRTCPeerConnectionConstructorConstraints = 1041,
-    kRTCPeerConnectionConstructorCompliant = 1042,
-    kRTCPeerConnectionCreateOfferLegacyFailureCallback = 1044,
-    kRTCPeerConnectionCreateOfferLegacyConstraints = 1045,
-    kRTCPeerConnectionCreateOfferLegacyOfferOptions = 1046,
-    kRTCPeerConnectionCreateOfferLegacyCompliant = 1047,
-    kRTCPeerConnectionCreateAnswerLegacyFailureCallback = 1049,
-    kRTCPeerConnectionCreateAnswerLegacyConstraints = 1050,
-    kRTCPeerConnectionCreateAnswerLegacyCompliant = 1051,
-    kRTCPeerConnectionSetLocalDescriptionLegacyNoSuccessCallback = 1052,
-    kRTCPeerConnectionSetLocalDescriptionLegacyNoFailureCallback = 1053,
-    kRTCPeerConnectionSetLocalDescriptionLegacyCompliant = 1054,
-    kRTCPeerConnectionSetRemoteDescriptionLegacyNoSuccessCallback = 1055,
-    kRTCPeerConnectionSetRemoteDescriptionLegacyNoFailureCallback = 1056,
-    kRTCPeerConnectionSetRemoteDescriptionLegacyCompliant = 1057,
-    kRTCPeerConnectionGetStatsLegacyNonCompliant = 1058,
-    kNodeFilterIsFunction = 1059,
-    kNodeFilterIsObject = 1060,
-    kCSSSelectorInternalPseudoListBox = 1062,
-    kCSSSelectorInternalMediaControlsOverlayCastButton = 1064,
-    kCSSSelectorInternalPseudoSpatialNavigationFocus = 1065,
-    kSameOriginTextScript = 1066,
-    kSameOriginApplicationScript = 1067,
-    kSameOriginOtherScript = 1068,
-    kCrossOriginTextScript = 1069,
-    kCrossOriginApplicationScript = 1070,
-    kCrossOriginOtherScript = 1071,
-    kSVG1DOMSVGTests = 1072,
-    kDisableRemotePlaybackAttribute = 1074,
-    kV8SloppyMode = 1075,
-    kV8StrictMode = 1076,
-    kV8StrongMode = 1077,
-    kAudioNodeConnectToAudioNode = 1078,
-    kAudioNodeConnectToAudioParam = 1079,
-    kAudioNodeDisconnectFromAudioNode = 1080,
-    kAudioNodeDisconnectFromAudioParam = 1081,
-    kV8CSSFontFaceRule_Style_AttributeGetter = 1082,
-    kSelectionCollapseNull = 1083,
-    kSelectionSetBaseAndExtentNull = 1084,
-    kV8SVGSVGElement_CreateSVGNumber_Method = 1085,
-    kV8SVGSVGElement_CreateSVGLength_Method = 1086,
-    kV8SVGSVGElement_CreateSVGAngle_Method = 1087,
-    kV8SVGSVGElement_CreateSVGPoint_Method = 1088,
-    kV8SVGSVGElement_CreateSVGMatrix_Method = 1089,
-    kV8SVGSVGElement_CreateSVGRect_Method = 1090,
-    kV8SVGSVGElement_CreateSVGTransform_Method = 1091,
-    kV8SVGSVGElement_CreateSVGTransformFromMatrix_Method = 1092,
-    kFormNameAccessForNonDescendantImageElement = 1093,
-    kV8RegExpPrototypeStickyGetter = 1096,
-    kV8RegExpPrototypeToString = 1097,
-    kV8InputDeviceCapabilities_FiresTouchEvents_AttributeGetter = 1098,
-    kDataElement = 1099,
-    kTimeElement = 1100,
-    kSVG1DOMUriReference = 1101,
-    kSVG1DOMZoomAndPan = 1102,
-    kV8SVGGraphicsElement_Transform_AttributeGetter = 1103,
-    kMenuItemElement = 1104,
-    kMenuItemCloseTag = 1105,
-    kSVG1DOMMarkerElement = 1106,
-    kSVG1DOMUseElement = 1107,
-    kSVG1DOMMaskElement = 1108,
-    kV8SVGAElement_Target_AttributeGetter = 1109,
-    kV8SVGClipPathElement_ClipPathUnits_AttributeGetter = 1110,
-    kSVG1DOMFitToViewBox = 1111,
-    kSVG1DOMSVGElement = 1114,
-    kSVG1DOMImageElement = 1115,
-    kSVG1DOMForeignObjectElement = 1116,
-    kAudioContextCreateIIRFilter = 1117,
-    // The above items are available in M49 branch
-
-    kCSSSelectorPseudoSlotted = 1118,
-    kMediaDevicesEnumerateDevices = 1119,
-    kNonSecureSharedWorkerAccessedFromSecureContext = 1120,
-    kSecureSharedWorkerAccessedFromNonSecureContext = 1121,
-    kEventComposedPath = 1123,
-    kLinkHeaderPreload = 1124,
-    kMouseWheelEvent = 1125,
-    kWheelEvent = 1126,
-    kMouseWheelAndWheelEvent = 1127,
-    kBodyScrollsInAdditionToViewport = 1128,
-    kDocumentDesignModeEnabeld = 1129,
-    kContentEditableTrue = 1130,
-    kContentEditableTrueOnHTML = 1131,
-    kContentEditablePlainTextOnly = 1132,
-    kV8RegExpPrototypeUnicodeGetter = 1133,
-    kV8IntlV8Parse = 1134,
-    kV8IntlPattern = 1135,
-    kV8IntlResolved = 1136,
-    kV8PromiseChain = 1137,
-    kV8PromiseAccept = 1138,
-    kV8PromiseDefer = 1139,
-    kEventComposed = 1140,
-    kGeolocationInsecureOriginIframe = 1141,
-    kGeolocationSecureOriginIframe = 1142,
-    kRequestMIDIAccessIframe = 1143,
-    kGetUserMediaInsecureOriginIframe = 1144,
-    kGetUserMediaSecureOriginIframe = 1145,
-    kElementRequestPointerLockIframe = 1146,
-    kNotificationAPIInsecureOriginIframe = 1147,
-    kNotificationAPISecureOriginIframe = 1148,
-    kWebSocket = 1149,
-    kMediaStreamConstraintsNameValue = 1150,
-    kMediaStreamConstraintsFromDictionary = 1151,
-    kMediaStreamConstraintsConformant = 1152,
-    kCSSSelectorIndirectAdjacent = 1153,
-    kCreateImageBitmap = 1156,
-    kPresentationConnectionConnectEventListener = 1157,
-    kPresentationConnectionCloseEventListener = 1158,
-    kPresentationConnectionTerminateEventListener = 1159,
-    kDocumentCreateEventAnimationEvent = 1162,
-    kDocumentCreateEventBeforeUnloadEvent = 1166,
-    kDocumentCreateEventCompositionEvent = 1168,
-    kDocumentCreateEventDragEvent = 1169,
-    kDocumentCreateEventErrorEvent = 1170,
-    kDocumentCreateEventFocusEvent = 1171,
-    kDocumentCreateEventHashChangeEvent = 1172,
-    kDocumentCreateEventMutationEvent = 1173,
-    kDocumentCreateEventPageTransitionEvent = 1174,
-    kDocumentCreateEventPopStateEvent = 1176,
-    kDocumentCreateEventTextEvent = 1182,
-    kDocumentCreateEventTransitionEvent = 1183,
-    kDocumentCreateEventWheelEvent = 1184,
-    kDocumentCreateEventTrackEvent = 1186,
-    kDocumentCreateEventMutationEvents = 1188,
-    kDocumentCreateEventSVGEvents = 1190,
-    kDocumentCreateEventDeviceMotionEvent = 1195,
-    kDocumentCreateEventDeviceOrientationEvent = 1196,
-    kDocumentCreateEventIDBVersionChangeEvent = 1201,
-    kDocumentCreateEventStorageEvent = 1221,
-    kDocumentCreateEventWebGLContextEvent = 1224,
-    kDocumentCreateEventCloseEvent = 1227,
-    kDocumentCreateEventKeyboardEvents = 1228,
-    kHTMLMediaElement = 1229,
-    kHTMLMediaElementInDocument = 1230,
-    kHTMLMediaElementControlsAttribute = 1231,
-    kV8Animation_Oncancel_AttributeGetter = 1233,
-    kV8Animation_Oncancel_AttributeSetter = 1234,
-    kV8HTMLCommentInExternalScript = 1235,
-    kV8HTMLComment = 1236,
-    kV8SloppyModeBlockScopedFunctionRedefinition = 1237,
-    kV8ForInInitializer = 1238,
-    kV8Animation_Id_AttributeGetter = 1239,
-    kV8Animation_Id_AttributeSetter = 1240,
-    kApplicationCacheManifestSelectInsecureOrigin = 1245,
-    kApplicationCacheManifestSelectSecureOrigin = 1246,
-    kApplicationCacheAPIInsecureOrigin = 1247,
-    kApplicationCacheAPISecureOrigin = 1248,
-    // The above items are available in M50 branch
-
-    kCSSAtRuleApply = 1249,
-    kCSSSelectorPseudoAny = 1250,
-    kDocumentAllItemNoArguments = 1252,
-    kDocumentAllItemNamed = 1253,
-    kDocumentAllItemIndexed = 1254,
-    kDocumentAllItemIndexedWithNonNumber = 1255,
-    kDocumentAllLegacyCallNoArguments = 1256,
-    kDocumentAllLegacyCallNamed = 1257,
-    kDocumentAllLegacyCallIndexed = 1258,
-    kDocumentAllLegacyCallIndexedWithNonNumber = 1259,
-    kDocumentAllLegacyCallTwoArguments = 1260,
-    kHTMLLabelElementControlForNonFormAssociatedElement = 1263,
-    kHTMLMediaElementLoadNetworkEmptyNotPaused = 1265,
-    kV8Window_WebkitSpeechGrammar_ConstructorGetter = 1267,
-    kV8Window_WebkitSpeechGrammarList_ConstructorGetter = 1268,
-    kV8Window_WebkitSpeechRecognition_ConstructorGetter = 1269,
-    kV8Window_WebkitSpeechRecognitionError_ConstructorGetter = 1270,
-    kV8Window_WebkitSpeechRecognitionEvent_ConstructorGetter = 1271,
-    kV8Window_SpeechSynthesis_AttributeGetter = 1272,
-    kV8IDBFactory_WebkitGetDatabaseNames_Method = 1273,
-    kImageDocument = 1274,
-    kScriptPassesCSPDynamic = 1275,
-    kCSPWithStrictDynamic = 1277,
-    kScrollAnchored = 1278,
-    kAddEventListenerFourArguments = 1279,
-    kRemoveEventListenerFourArguments = 1280,
-    kSVGCalcModeDiscrete = 1287,
-    kSVGCalcModeLinear = 1288,
-    kSVGCalcModePaced = 1289,
-    kSVGCalcModeSpline = 1290,
-    kFormSubmissionStarted = 1291,
-    kFormValidationStarted = 1292,
-    kFormValidationAbortedSubmission = 1293,
-    kFormValidationShowedMessage = 1294,
-    kWebAnimationsEasingAsFunctionLinear = 1295,
-    kWebAnimationsEasingAsFunctionOther = 1296,
-    // The above items are available in M51 branch
-
-    kV8Document_Images_AttributeGetter = 1297,
-    kV8Document_Embeds_AttributeGetter = 1298,
-    kV8Document_Plugins_AttributeGetter = 1299,
-    kV8Document_Links_AttributeGetter = 1300,
-    kV8Document_Forms_AttributeGetter = 1301,
-    kV8Document_Scripts_AttributeGetter = 1302,
-    kV8Document_Anchors_AttributeGetter = 1303,
-    kV8Document_Applets_AttributeGetter = 1304,
-    kXMLHttpRequestCrossOriginWithCredentials = 1305,
-    kMediaStreamTrackRemote = 1306,
-    kV8Node_IsConnected_AttributeGetter = 1307,
-    kShadowRootDelegatesFocus = 1308,
-    kMixedShadowRootV0AndV1 = 1309,
-    kImageDocumentInFrame = 1310,
-    kMediaDocument = 1311,
-    kMediaDocumentInFrame = 1312,
-    kPluginDocument = 1313,
-    kPluginDocumentInFrame = 1314,
-    kSinkDocument = 1315,
-    kSinkDocumentInFrame = 1316,
-    kTextDocument = 1317,
-    kTextDocumentInFrame = 1318,
-    kViewSourceDocument = 1319,
-    kFileAPINativeLineEndings = 1320,
-    kPointerEventAttributeCount = 1321,
-    kCompositedReplication = 1322,
-    kV8DataTransferItem_WebkitGetAsEntry_Method = 1325,
-    kV8HTMLInputElement_WebkitEntries_AttributeGetter = 1326,
-    kEntry_Filesystem_AttributeGetter_IsolatedFileSystem = 1327,
-    kEntry_GetMetadata_Method_IsolatedFileSystem = 1328,
-    kEntry_MoveTo_Method_IsolatedFileSystem = 1329,
-    kEntry_CopyTo_Method_IsolatedFileSystem = 1330,
-    kEntry_Remove_Method_IsolatedFileSystem = 1331,
-    kEntry_GetParent_Method_IsolatedFileSystem = 1332,
-    kEntry_ToURL_Method_IsolatedFileSystem = 1333,
-    kDuring_Microtask_Alert = 1334,
-    kDuring_Microtask_Confirm = 1335,
-    kDuring_Microtask_Print = 1336,
-    kDuring_Microtask_Prompt = 1337,
-    kDuring_Microtask_SyncXHR = 1338,
-    kCredentialManagerGetReturnedCredential = 1342,
-    kGeolocationInsecureOriginDeprecatedNotRemoved = 1343,
-    kGeolocationInsecureOriginIframeDeprecatedNotRemoved = 1344,
-    kProgressElementWithNoneAppearance = 1345,
-    kProgressElementWithProgressBarAppearance = 1346,
-    kPointerEventAddListenerCount = 1347,
-    kCSSValueAppearanceNone = 1351,
-    kCSSValueAppearanceNotNone = 1352,
-    kCSSValueAppearanceOthers = 1353,
-    kCSSValueAppearanceButton = 1354,
-    kCSSValueAppearanceCaret = 1355,
-    kCSSValueAppearanceCheckbox = 1356,
-    kCSSValueAppearanceMenulist = 1357,
-    kCSSValueAppearanceMenulistButton = 1358,
-    kCSSValueAppearanceListbox = 1359,
-    kCSSValueAppearanceRadio = 1360,
-    kCSSValueAppearanceSearchField = 1361,
-    kCSSValueAppearanceTextField = 1362,
-    kAudioContextCreatePannerAutomated = 1363,
-    kPannerNodeSetPosition = 1364,
-    kPannerNodeSetOrientation = 1365,
-    kAudioListenerSetPosition = 1366,
-    kAudioListenerSetOrientation = 1367,
-    kIntersectionObserver_Constructor = 1368,
-    kDurableStoragePersist = 1369,
-    kDurableStoragePersisted = 1370,
-    kDurableStorageEstimate = 1371,
-    kCSSDeepCombinatorAndShadow = 1375,
-    kOpacityWithPreserve3DQuirk = 1376,
-    kCSSSelectorPseudoReadOnly = 1377,
-    kCSSSelectorPseudoReadWrite = 1378,
-    // The above items are available in M52 branch
-
-    kCSSSelectorPseudoDefined = 1383,
-    kRTCPeerConnectionAddIceCandidatePromise = 1384,
-    kRTCPeerConnectionAddIceCandidateLegacy = 1385,
-    kRTCIceCandidateDefaultSdpMLineIndex = 1386,
-    kMediaStreamConstraintsOldAndNew = 1389,
-    kV8ArrayProtectorDirtied = 1390,
-    kV8ArraySpeciesModified = 1391,
-    kV8ArrayPrototypeConstructorModified = 1392,
-    kV8ArrayInstanceProtoModified = 1393,
-    kV8ArrayInstanceConstructorModified = 1394,
-    kV8LegacyFunctionDeclaration = 1395,
-    kV8RegExpPrototypeSourceGetter = 1396,
-    kV8RegExpPrototypeOldFlagGetter = 1397,
-    kV8DecimalWithLeadingZeroInStrictMode = 1398,
-    kGetUserMediaPrefixed = 1400,
-    kGetUserMediaLegacy = 1401,
-    kGetUserMediaPromise = 1402,
-    kCSSFilterFunctionNoArguments = 1403,
-    kV8LegacyDateParser = 1404,
-    kOpenSearchInsecureOriginInsecureTarget = 1405,
-    kOpenSearchInsecureOriginSecureTarget = 1406,
-    kOpenSearchSecureOriginInsecureTarget = 1407,
-    kOpenSearchSecureOriginSecureTarget = 1408,
-    kRegisterProtocolHandlerSecureOrigin = 1409,
-    kRegisterProtocolHandlerInsecureOrigin = 1410,
-    kCrossOriginWindowAlert = 1411,
-    kCrossOriginWindowConfirm = 1412,
-    kCrossOriginWindowPrompt = 1413,
-    kCrossOriginWindowPrint = 1414,
-    kMediaStreamOnActive = 1415,
-    kMediaStreamOnInactive = 1416,
-    kAddEventListenerPassiveTrue = 1417,
-    kAddEventListenerPassiveFalse = 1418,
-    kCSPReferrerDirective = 1419,
-    kDocumentOpen = 1420,
-    kElementRequestPointerLockInShadow = 1421,
-    kShadowRootPointerLockElement = 1422,
-    kDocumentPointerLockElementInV0Shadow = 1423,
-    kTextAreaMaxLength = 1424,
-    kTextAreaMinLength = 1425,
-    kTopNavigationFromSubFrame = 1426,
-    kPrefixedElementRequestFullscreenInShadow = 1427,
-    kMediaSourceAbortRemove = 1428,
-    kMediaSourceDurationTruncatingBuffered = 1429,
-    kAudioContextCrossOriginIframe = 1430,
-    // The above items are available in M53 branch
-
-    kPointerEventSetCapture = 1431,
-    kPointerEventDispatch = 1432,
-    kMIDIMessageEventReceivedTime = 1433,
-    kSummaryElementWithDisplayBlockAuthorRule = 1434,
-    kV8MediaStream_Active_AttributeGetter = 1435,
-    kBeforeInstallPromptEvent = 1436,
-    kBeforeInstallPromptEventUserChoice = 1437,
-    kBeforeInstallPromptEventPreventDefault = 1438,
-    kBeforeInstallPromptEventPrompt = 1439,
-    kExecCommandAltersHTMLStructure = 1440,
-    kSecureContextCheckPassed = 1441,
-    kSecureContextCheckFailed = 1442,
-    kSecureContextCheckForSandboxedOriginPassed = 1443,
-    kSecureContextCheckForSandboxedOriginFailed = 1444,
-    kV8DefineGetterOrSetterWouldThrow = 1445,
-    kV8FunctionConstructorReturnedUndefined = 1446,
-    kV8BroadcastChannel_Constructor = 1447,
-    kV8BroadcastChannel_PostMessage_Method = 1448,
-    kV8BroadcastChannel_Close_Method = 1449,
-    kTouchStartFired = 1450,
-    kMouseDownFired = 1451,
-    kPointerDownFired = 1452,
-    kPointerDownFiredForTouch = 1453,
-    kPointerEventDispatchPointerDown = 1454,
-    kSVGSMILBeginOrEndEventValue = 1455,
-    kSVGSMILBeginOrEndSyncbaseValue = 1456,
-    kSVGSMILElementInsertedAfterLoad = 1457,
-    kV8VisualViewport_OffsetLeft_AttributeGetter = 1458,
-    kV8VisualViewport_OffsetTop_AttributeGetter = 1459,
-    kV8VisualViewport_PageLeft_AttributeGetter = 1460,
-    kV8VisualViewport_PageTop_AttributeGetter = 1461,
-    kV8VisualViewport_Width_AttributeGetter = 1462,
-    kV8VisualViewport_Height_AttributeGetter = 1463,
-    kV8VisualViewport_Scale_AttributeGetter = 1464,
-    kVisualViewportScrollFired = 1465,
-    kVisualViewportResizeFired = 1466,
-    kNodeGetRootNode = 1467,
-    kSlotChangeEventAddListener = 1468,
-    kCSSValueAppearanceButtonRendered = 1469,
-    kCSSValueAppearanceButtonForAnchor = 1470,
-    kCSSValueAppearanceButtonForButton = 1471,
-    kCSSValueAppearanceButtonForOtherButtons = 1472,
-    kCSSValueAppearanceTextFieldRendered = 1473,
-    kCSSValueAppearanceTextFieldForSearch = 1474,
-    kCSSValueAppearanceTextFieldForTextField = 1475,
-    kRTCPeerConnectionGetStats = 1476,
-    kSVGSMILAnimationAppliedEffect = 1477,
-    kPerformanceResourceTimingSizes = 1478,
-    kEventSourceDocument = 1479,
-    kEventSourceWorker = 1480,
-    kSingleOriginInTimingAllowOrigin = 1481,
-    kMultipleOriginsInTimingAllowOrigin = 1482,
-    kStarInTimingAllowOrigin = 1483,
-    kSVGSMILAdditiveAnimation = 1484,
-    kSendBeaconWithNonSimpleContentType = 1485,
-    kChromeLoadTimesRequestTime = 1486,
-    kChromeLoadTimesStartLoadTime = 1487,
-    kChromeLoadTimesCommitLoadTime = 1488,
-    kChromeLoadTimesFinishDocumentLoadTime = 1489,
-    kChromeLoadTimesFinishLoadTime = 1490,
-    kChromeLoadTimesFirstPaintTime = 1491,
-    kChromeLoadTimesFirstPaintAfterLoadTime = 1492,
-    kChromeLoadTimesNavigationType = 1493,
-    kChromeLoadTimesWasFetchedViaSpdy = 1494,
-    kChromeLoadTimesWasNpnNegotiated = 1495,
-    kChromeLoadTimesNpnNegotiatedProtocol = 1496,
-    kChromeLoadTimesWasAlternateProtocolAvailable = 1497,
-    kChromeLoadTimesConnectionInfo = 1498,
-    kChromeLoadTimesUnknown = 1499,
-    kSVGViewElement = 1500,
-    kWebShareShare = 1501,
-    kAuxclickAddListenerCount = 1502,
-    kHTMLCanvasElement = 1503,
-    kSVGSMILAnimationElementTiming = 1504,
-    kSVGSMILBeginEndAnimationElement = 1505,
-    kSVGSMILPausing = 1506,
-    kSVGSMILCurrentTime = 1507,
-    kHTMLBodyElementOnSelectionChangeAttribute = 1508,
-    kForeignFetchInterception = 1509,
-    kUsbGetDevices = 1519,
-    kUsbRequestDevice = 1520,
-    kUsbDeviceOpen = 1521,
-    kUsbDeviceClose = 1522,
-    kUsbDeviceSelectConfiguration = 1523,
-    kUsbDeviceClaimInterface = 1524,
-    kUsbDeviceReleaseInterface = 1525,
-    kUsbDeviceSelectAlternateInterface = 1526,
-    kUsbDeviceControlTransferIn = 1527,
-    kUsbDeviceControlTransferOut = 1528,
-    kUsbDeviceClearHalt = 1529,
-    kUsbDeviceTransferIn = 1530,
-    kUsbDeviceTransferOut = 1531,
-    kUsbDeviceIsochronousTransferIn = 1532,
-    kUsbDeviceIsochronousTransferOut = 1533,
-    kUsbDeviceReset = 1534,
-    // The above items are available in M54 branch
-
-    kPointerEnterLeaveFired = 1535,
-    kPointerOverOutFired = 1536,
-    kDraggableAttribute = 1539,
-    kCleanScriptElementWithNonce = 1540,
-    kPotentiallyInjectedScriptElementWithNonce = 1541,
-    kPendingStylesheetAddedAfterBodyStarted = 1542,
-    kUntrustedMouseDownEventDispatchedToSelect = 1543,
-    kBlockedSniffingAudioToScript = 1544,
-    kBlockedSniffingVideoToScript = 1545,
-    kBlockedSniffingCSVToScript = 1546,
-    kMetaSetCookie = 1547,
-    kMetaRefresh = 1548,
-    kMetaSetCookieWhenCSPBlocksInlineScript = 1549,
-    kMetaRefreshWhenCSPBlocksInlineScript = 1550,
-    kMiddleClickAutoscrollStart = 1551,
-    kRTCPeerConnectionCreateOfferOptionsOfferToReceive = 1553,
-    kDragAndDropScrollStart = 1554,
-    kPresentationConnectionListConnectionAvailableEventListener = 1555,
-    kWebAudioAutoplayCrossOriginIframe = 1556,
-    kVRGetDisplays = 1558,
-    kXSSAuditorBlockedScript = 1581,
-    kXSSAuditorBlockedEntirePage = 1582,
-    kXSSAuditorDisabled = 1583,
-    kXSSAuditorEnabledFilter = 1584,
-    kXSSAuditorEnabledBlock = 1585,
-    kXSSAuditorInvalid = 1586,
-    kTextInputEventOnInput = 1589,
-    kTextInputEventOnTextArea = 1590,
-    kTextInputEventOnContentEditable = 1591,
-    kTextInputEventOnNotNode = 1592,
-    kWebkitBeforeTextInsertedOnInput = 1593,
-    kWebkitBeforeTextInsertedOnTextArea = 1594,
-    kWebkitBeforeTextInsertedOnContentEditable = 1595,
-    kWebkitBeforeTextInsertedOnNotNode = 1596,
-    kWebkitEditableContentChangedOnInput = 1597,
-    kWebkitEditableContentChangedOnTextArea = 1598,
-    kWebkitEditableContentChangedOnContentEditable = 1599,
-    kWebkitEditableContentChangedOnNotNode = 1600,
-    kV8NavigatorUserMediaError_ConstraintName_AttributeGetter = 1601,
-    kV8HTMLMediaElement_SrcObject_AttributeGetter = 1602,
-    kV8HTMLMediaElement_SrcObject_AttributeSetter = 1603,
-    kCreateObjectURLBlob = 1604,
-    kCreateObjectURLMediaSource = 1605,
-    kCreateObjectURLMediaStream = 1606,
-    kDocumentCreateTouchWindowNull = 1607,
-    kDocumentCreateTouchWindowWrongType = 1608,
-    kDocumentCreateTouchTargetNull = 1609,
-    kDocumentCreateTouchTargetWrongType = 1610,
-    kDocumentCreateTouchMoreThanSevenArguments = 1612,
-    kLongTaskObserver = 1615,
-    kCSSOffsetInEffect = 1617,
-    // The above items are available in M55 branch
-
-    kVRGetDisplaysInsecureOrigin = 1618,
-    kVRRequestPresent = 1619,
-    kVRRequestPresentInsecureOrigin = 1620,
-    kVRDeprecatedFieldOfView = 1621,
-    kVideoInCanvas = 1622,
-    kHiddenAutoplayedVideoInCanvas = 1623,
-    kOffscreenCanvas = 1624,
-    kGamepadPose = 1625,
-    kGamepadHand = 1626,
-    kGamepadDisplayId = 1627,
-    kGamepadButtonTouched = 1628,
-    kGamepadPoseHasOrientation = 1629,
-    kGamepadPoseHasPosition = 1630,
-    kGamepadPosePosition = 1631,
-    kGamepadPoseLinearVelocity = 1632,
-    kGamepadPoseLinearAcceleration = 1633,
-    kGamepadPoseOrientation = 1634,
-    kGamepadPoseAngularVelocity = 1635,
-    kGamepadPoseAngularAcceleration = 1636,
-    kV8RTCDataChannel_MaxRetransmitTime_AttributeGetter = 1638,
-    kV8RTCDataChannel_MaxRetransmits_AttributeGetter = 1639,
-    kV8RTCDataChannel_Reliable_AttributeGetter = 1640,
-    kV8RTCPeerConnection_AddStream_Method = 1641,
-    kV8RTCPeerConnection_CreateDTMFSender_Method = 1642,
-    kV8RTCPeerConnection_GetLocalStreams_Method = 1643,
-    kV8RTCPeerConnection_GetRemoteStreams_Method = 1644,
-    kV8RTCPeerConnection_GetStreamById_Method = 1645,
-    kV8RTCPeerConnection_RemoveStream_Method = 1646,
-    kRTCPeerConnectionCreateDataChannelMaxRetransmitTime = 1648,
-    kRTCPeerConnectionCreateDataChannelMaxRetransmits = 1649,
-    kAudioContextCreateConstantSource = 1650,
-    kWebAudioConstantSourceNode = 1651,
-    kLoopbackEmbeddedInSecureContext = 1652,
-    kLoopbackEmbeddedInNonSecureContext = 1653,
-    kBlinkMacSystemFont = 1654,
-    kRTCIceServerURL = 1656,
-    kRTCIceServerURLs = 1657,
-    kOffscreenCanvasTransferToImageBitmap2D = 1658,
-    kOffscreenCanvasTransferToImageBitmapWebGL = 1659,
-    kOffscreenCanvasCommit2D = 1660,
-    kOffscreenCanvasCommitWebGL = 1661,
-    kRTCConfigurationIceTransportPolicy = 1662,
-    kRTCConfigurationIceTransports = 1664,
-    kDocumentFullscreenElementInV0Shadow = 1665,
-    kScriptWithCSPBypassingSchemeParserInserted = 1666,
-    kScriptWithCSPBypassingSchemeNotParserInserted = 1667,
-    kDocumentCreateElement2ndArgStringHandling = 1668,
-    kV8MediaRecorder_Start_Method = 1669,
-    kWebBluetoothRequestDevice = 1670,
-    kUnitlessPerspectiveInPerspectiveProperty = 1671,
-    kUnitlessPerspectiveInTransformProperty = 1672,
-    kV8RTCSessionDescription_Type_AttributeGetter = 1673,
-    kV8RTCSessionDescription_Type_AttributeSetter = 1674,
-    kV8RTCSessionDescription_Sdp_AttributeGetter = 1675,
-    kV8RTCSessionDescription_Sdp_AttributeSetter = 1676,
-    kRTCSessionDescriptionInitNoType = 1677,
-    kRTCSessionDescriptionInitNoSdp = 1678,
-    kHTMLMediaElementPreloadForcedMetadata = 1679,
-    kGenericSensorStart = 1680,
-    kGenericSensorStop = 1681,
-    kTouchEventPreventedNoTouchAction = 1682,
-    kTouchEventPreventedForcedDocumentPassiveNoTouchAction = 1683,
-    kV8Event_StopPropagation_Method = 1684,
-    kV8Event_StopImmediatePropagation_Method = 1685,
-    kImageCaptureConstructor = 1686,
-    kV8Document_RootScroller_AttributeGetter = 1687,
-    kV8Document_RootScroller_AttributeSetter = 1688,
-    kCustomElementRegistryDefine = 1689,
-    kLinkHeaderServiceWorker = 1690,
-    kCSSShadowPiercingDescendantCombinator = 1691,
-    // The above items are available in M56 branch.
-
-    kCSSFlexibleBox = 1692,
-    kCSSGridLayout = 1693,
-    kFullscreenAllowedByOrientationChange = 1696,
-    kServiceWorkerRespondToNavigationRequestWithRedirectedResponse = 1697,
-    kV8AudioContext_Constructor = 1698,
-    kV8OfflineAudioContext_Constructor = 1699,
-    kAppInstalledEventAddListener = 1700,
-    kAudioContextGetOutputTimestamp = 1701,
-    kV8MediaStreamAudioDestinationNode_Constructor = 1702,
-    kV8AnalyserNode_Constructor = 1703,
-    kV8AudioBuffer_Constructor = 1704,
-    kV8AudioBufferSourceNode_Constructor = 1705,
-    kV8AudioProcessingEvent_Constructor = 1706,
-    kV8BiquadFilterNode_Constructor = 1707,
-    kV8ChannelMergerNode_Constructor = 1708,
-    kV8ChannelSplitterNode_Constructor = 1709,
-    kV8ConstantSourceNode_Constructor = 1710,
-    kV8ConvolverNode_Constructor = 1711,
-    kV8DelayNode_Constructor = 1712,
-    kV8DynamicsCompressorNode_Constructor = 1713,
-    kV8GainNode_Constructor = 1714,
-    kV8IIRFilterNode_Constructor = 1715,
-    kV8MediaElementAudioSourceNode_Constructor = 1716,
-    kV8MediaStreamAudioSourceNode_Constructor = 1717,
-    kV8OfflineAudioCompletionEvent_Constructor = 1718,
-    kV8OscillatorNode_Constructor = 1719,
-    kV8PannerNode_Constructor = 1720,
-    kV8PeriodicWave_Constructor = 1721,
-    kV8StereoPannerNode_Constructor = 1722,
-    kV8WaveShaperNode_Constructor = 1723,
-    kV8Headers_GetAll_Method = 1724,
-    kNavigatorVibrateEngagementNone = 1725,
-    kNavigatorVibrateEngagementMinimal = 1726,
-    kNavigatorVibrateEngagementLow = 1727,
-    kNavigatorVibrateEngagementMedium = 1728,
-    kNavigatorVibrateEngagementHigh = 1729,
-    kNavigatorVibrateEngagementMax = 1730,
-    kAlertEngagementNone = 1731,
-    kAlertEngagementMinimal = 1732,
-    kAlertEngagementLow = 1733,
-    kAlertEngagementMedium = 1734,
-    kAlertEngagementHigh = 1735,
-    kAlertEngagementMax = 1736,
-    kConfirmEngagementNone = 1737,
-    kConfirmEngagementMinimal = 1738,
-    kConfirmEngagementLow = 1739,
-    kConfirmEngagementMedium = 1740,
-    kConfirmEngagementHigh = 1741,
-    kConfirmEngagementMax = 1742,
-    kPromptEngagementNone = 1743,
-    kPromptEngagementMinimal = 1744,
-    kPromptEngagementLow = 1745,
-    kPromptEngagementMedium = 1746,
-    kPromptEngagementHigh = 1747,
-    kPromptEngagementMax = 1748,
-    kTopNavInSandbox = 1749,
-    kTopNavInSandboxWithoutGesture = 1750,
-    kTopNavInSandboxWithPerm = 1751,
-    kTopNavInSandboxWithPermButNoGesture = 1752,
-    kReferrerPolicyHeader = 1753,
-    kHTMLAnchorElementReferrerPolicyAttribute = 1754,
-    kHTMLIFrameElementReferrerPolicyAttribute = 1755,
-    kHTMLImageElementReferrerPolicyAttribute = 1756,
-    kHTMLLinkElementReferrerPolicyAttribute = 1757,
-    kBaseElement = 1758,
-    kBaseWithCrossOriginHref = 1759,
-    kBaseWithDataHref = 1760,
-    kBaseWithNewlinesInTarget = 1761,
-    kBaseWithOpenBracketInTarget = 1762,
-    kBaseWouldBeBlockedByDefaultSrc = 1763,
-    kV8AssigmentExpressionLHSIsCallInSloppy = 1764,
-    kV8AssigmentExpressionLHSIsCallInStrict = 1765,
-    kV8PromiseConstructorReturnedUndefined = 1766,
-    kFormSubmittedWithUnclosedFormControl = 1767,
-    kScrollbarUseVerticalScrollbarButton = 1777,
-    kScrollbarUseVerticalScrollbarThumb = 1778,
-    kScrollbarUseVerticalScrollbarTrack = 1779,
-    kScrollbarUseHorizontalScrollbarButton = 1780,
-    kScrollbarUseHorizontalScrollbarThumb = 1781,
-    kScrollbarUseHorizontalScrollbarTrack = 1782,
-    kHTMLTableCellElementColspan = 1783,
-    kHTMLTableCellElementColspanGreaterThan1000 = 1784,
-    kHTMLTableCellElementColspanGreaterThan8190 = 1785,
-    kSelectionAddRangeIntersect = 1786,
-    kPostMessageFromInsecureToSecureToplevel = 1787,
-    // The above items are available in M57 branch.
-
-    kV8MediaSession_Metadata_AttributeGetter = 1788,
-    kV8MediaSession_Metadata_AttributeSetter = 1789,
-    kV8MediaSession_PlaybackState_AttributeGetter = 1790,
-    kV8MediaSession_PlaybackState_AttributeSetter = 1791,
-    kV8MediaSession_SetActionHandler_Method = 1792,
-    kWebNFCPush = 1793,
-    kWebNFCCancelPush = 1794,
-    kWebNFCWatch = 1795,
-    kWebNFCCancelWatch = 1796,
-    kAudioParamCancelAndHoldAtTime = 1797,
-    kCSSValueUserModifyReadOnly = 1798,
-    kCSSValueUserModifyReadWrite = 1799,
-    kCSSValueUserModifyReadWritePlaintextOnly = 1800,
-    kCSSValueOnDemand = 1802,
-    kServiceWorkerNavigationPreload = 1803,
-    kFullscreenRequestWithPendingElement = 1804,
-    kHTMLIFrameElementAllowfullscreenAttributeSetAfterContentLoad = 1805,
-    kPointerEventSetCaptureOutsideDispatch = 1806,
-    kNotificationPermissionRequestedInsecureOrigin = 1807,
-    kV8DeprecatedStorageInfo_QueryUsageAndQuota_Method = 1808,
-    kV8DeprecatedStorageInfo_RequestQuota_Method = 1809,
-    kV8DeprecatedStorageQuota_QueryUsageAndQuota_Method = 1810,
-    kV8DeprecatedStorageQuota_RequestQuota_Method = 1811,
-    kV8FileReaderSync_Constructor = 1812,
-    kUncancelableTouchEventPreventDefaulted = 1813,
-    kUncancelableTouchEventDueToMainThreadResponsivenessPreventDefaulted = 1814,
-    kV8HTMLVideoElement_Poster_AttributeGetter = 1815,
-    kV8HTMLVideoElement_Poster_AttributeSetter = 1816,
-    kNotificationPermissionRequestedIframe = 1817,
-    kPresentationReceiverInsecureOrigin = 1819,
-    kPresentationReceiverSecureOrigin = 1820,
-    kPresentationRequestInsecureOrigin = 1821,
-    kPresentationRequestSecureOrigin = 1822,
-    kRtcpMuxPolicyNegotiate = 1823,
-    kDOMClobberedVariableAccessed = 1824,
-    kHTMLDocumentCreateProcessingInstruction = 1825,
-    kFetchResponseConstructionWithStream = 1826,
-    kLocationOrigin = 1827,
-    kDocumentOrigin = 1828,
-    kCanvas2DFilter = 1830,
-    kCanvas2DImageSmoothingQuality = 1831,
-    kCanvasToBlob = 1832,
-    kCanvasToDataURL = 1833,
-    kOffscreenCanvasConvertToBlob = 1834,
-    kSVGInCanvas2D = 1835,
-    kSVGInWebGL = 1836,
-    kSelectionFuncionsChangeFocus = 1837,
-    kHTMLObjectElementGetter = 1838,
-    kHTMLObjectElementSetter = 1839,
-    kHTMLEmbedElementGetter = 1840,
-    kHTMLEmbedElementSetter = 1841,
-    kTransformUsesBoxSizeOnSVG = 1842,
-    // The above items are available in M58 branch.
-
-    kScrollByKeyboardArrowKeys = 1843,
-    kScrollByKeyboardPageUpDownKeys = 1844,
-    kScrollByKeyboardHomeEndKeys = 1845,
-    kScrollByKeyboardSpacebarKey = 1846,
-    kScrollByTouch = 1847,
-    kScrollByWheel = 1848,
-    kScheduledActionIgnored = 1849,
-    kGetCanvas2DContextAttributes = 1850,
-    kV8HTMLInputElement_Capture_AttributeGetter = 1851,
-    kV8HTMLInputElement_Capture_AttributeSetter = 1852,
-    kHTMLMediaElementControlsListAttribute = 1853,
-    kHTMLMediaElementControlsListNoDownload = 1854,
-    kHTMLMediaElementControlsListNoFullscreen = 1855,
-    kHTMLMediaElementControlsListNoRemotePlayback = 1856,
-    kPointerEventClickRetargetCausedByCapture = 1857,
-    kVRDisplayDisplayName = 1861,
-    kVREyeParametersOffset = 1862,
-    kVRPoseLinearVelocity = 1863,
-    kVRPoseLinearAcceleration = 1864,
-    kVRPoseAngularVelocity = 1865,
-    kVRPoseAngularAcceleration = 1866,
-    kCSSOverflowPaged = 1867,
-    kChildSrcAllowedWorkerThatScriptSrcBlocked = 1868,
-    kHTMLTableElementPresentationAttributeBackground = 1869,
-    kV8Navigator_GetInstalledRelatedApps_Method = 1870,
-    kNamedAccessOnWindow_ChildBrowsingContext = 1871,
-    kNamedAccessOnWindow_ChildBrowsingContext_CrossOriginNameMismatch = 1872,
-    kV0CustomElementsRegisterHTMLCustomTag = 1873,
-    kV0CustomElementsRegisterHTMLTypeExtension = 1874,
-    kV0CustomElementsRegisterSVGElement = 1875,
-    kV0CustomElementsRegisterEmbedderElement = 1876,
-    kV0CustomElementsCreateCustomTagElement = 1877,
-    kV0CustomElementsCreateTypeExtensionElement = 1878,
-    kV0CustomElementsConstruct = 1879,
-    kV8IDBObserver_Observe_Method = 1880,
-    kV8IDBObserver_Unobserve_Method = 1881,
-    kWebBluetoothRemoteCharacteristicGetDescriptor = 1882,
-    kWebBluetoothRemoteCharacteristicGetDescriptors = 1883,
-    kWebBluetoothRemoteCharacteristicReadValue = 1884,
-    kWebBluetoothRemoteCharacteristicWriteValue = 1885,
-    kWebBluetoothRemoteCharacteristicStartNotifications = 1886,
-    kWebBluetoothRemoteCharacteristicStopNotifications = 1887,
-    kWebBluetoothRemoteDescriptorReadValue = 1888,
-    kWebBluetoothRemoteDescriptorWriteValue = 1889,
-    kWebBluetoothRemoteServerConnect = 1890,
-    kWebBluetoothRemoteServerDisconnect = 1891,
-    kWebBluetoothRemoteServerGetPrimaryService = 1892,
-    kWebBluetoothRemoteServerGetPrimaryServices = 1893,
-    kWebBluetoothRemoteServiceGetCharacteristic = 1894,
-    kWebBluetoothRemoteServiceGetCharacteristics = 1895,
-    kHTMLContentElement = 1896,
-    kHTMLShadowElement = 1897,
-    kHTMLSlotElement = 1898,
-    kAccelerometerConstructor = 1899,
-    kAbsoluteOrientationSensorConstructor = 1900,
-    kAmbientLightSensorConstructor = 1901,
-    kGenericSensorOnActivate = 1902,
-    kGenericSensorOnChange = 1903,
-    kGenericSensorOnError = 1904,
-    kGenericSensorActivated = 1905,
-    kGyroscopeConstructor = 1906,
-    kMagnetometerConstructor = 1907,
-    kOrientationSensorPopulateMatrix = 1908,
-    kWindowOpenWithInvalidURL = 1909,
-    kCrossOriginMainFrameNulledNameAccessed = 1910,
-    kMenuItemElementIconAttribute = 1911,
-    kWebkitCSSMatrixSetMatrixValue = 1912,
-    kWebkitCSSMatrixConstructFromString = 1913,
-    kCanRequestURLHTTPContainingNewline = 1914,
-    kGetGamepads = 1916,
-    kV8SVGPathElement_GetPathSegAtLength_Method = 1917,
-    kMediaStreamConstraintsAudio = 1918,
-    kMediaStreamConstraintsAudioUnconstrained = 1919,
-    kMediaStreamConstraintsVideo = 1920,
-    kMediaStreamConstraintsVideoUnconstrained = 1921,
-    kMediaStreamConstraintsWidth = 1922,
-    kMediaStreamConstraintsHeight = 1923,
-    kMediaStreamConstraintsAspectRatio = 1924,
-    kMediaStreamConstraintsFrameRate = 1925,
-    kMediaStreamConstraintsFacingMode = 1926,
-    kMediaStreamConstraintsVolume = 1927,
-    kMediaStreamConstraintsSampleRate = 1928,
-    kMediaStreamConstraintsSampleSize = 1929,
-    kMediaStreamConstraintsEchoCancellation = 1930,
-    kMediaStreamConstraintsLatency = 1931,
-    kMediaStreamConstraintsChannelCount = 1932,
-    kMediaStreamConstraintsDeviceIdAudio = 1933,
-    kMediaStreamConstraintsDeviceIdVideo = 1934,
-    kMediaStreamConstraintsDisableLocalEcho = 1935,
-    kMediaStreamConstraintsGroupIdAudio = 1936,
-    kMediaStreamConstraintsGroupIdVideo = 1937,
-    kMediaStreamConstraintsVideoKind = 1938,
-    kMediaStreamConstraintsDepthNear = 1939,
-    kMediaStreamConstraintsDepthFar = 1940,
-    kMediaStreamConstraintsFocalLengthX = 1941,
-    kMediaStreamConstraintsFocalLengthY = 1942,
-    kMediaStreamConstraintsMediaStreamSourceAudio = 1943,
-    kMediaStreamConstraintsMediaStreamSourceVideo = 1944,
-    kMediaStreamConstraintsRenderToAssociatedSink = 1945,
-    kMediaStreamConstraintsHotwordEnabled = 1946,
-    kMediaStreamConstraintsGoogEchoCancellation = 1947,
-    kMediaStreamConstraintsGoogExperimentalEchoCancellation = 1948,
-    kMediaStreamConstraintsGoogAutoGainControl = 1949,
-    kMediaStreamConstraintsGoogExperimentalAutoGainControl = 1950,
-    kMediaStreamConstraintsGoogNoiseSuppression = 1951,
-    kMediaStreamConstraintsGoogHighpassFilter = 1952,
-    kMediaStreamConstraintsGoogTypingNoiseDetection = 1953,
-    kMediaStreamConstraintsGoogExperimentalNoiseSuppression = 1954,
-    kMediaStreamConstraintsGoogBeamforming = 1955,
-    kMediaStreamConstraintsGoogArrayGeometry = 1956,
-    kMediaStreamConstraintsGoogAudioMirroring = 1957,
-    kMediaStreamConstraintsGoogDAEchoCancellation = 1958,
-    kMediaStreamConstraintsGoogNoiseReduction = 1959,
-    kMediaStreamConstraintsGoogPowerLineFrequency = 1960,
-    // The above items are available in M59 branch.
-
-    kViewportFixedPositionUnderFilter = 1961,
-    kRequestMIDIAccessWithSysExOption = 1962,
-    kRequestMIDIAccessIframeWithSysExOption = 1963,
-    kGamepadAxes = 1964,
-    kGamepadButtons = 1965,
-    kVibrateWithoutUserGesture = 1966,
-    kDispatchMouseEventOnDisabledFormControl = 1967,
-    kElementNameDOMInvalidHTMLParserValid = 1968,
-    kElementNameDOMValidHTMLParserInvalid = 1969,
-    kGATTServerDisconnectedEvent = 1970,
-    kAnchorClickDispatchForNonConnectedNode = 1971,
-    kHTMLParseErrorNestedForm = 1972,
-    kFontShapingNotDefGlyphObserved = 1973,
-    kPostMessageOutgoingWouldBeBlockedByConnectSrc = 1974,
-    kPostMessageIncomingWouldBeBlockedByConnectSrc = 1975,
-    kPaymentRequestNetworkNameInSupportedMethods = 1976,
-    kCrossOriginPropertyAccess = 1977,
-    kCrossOriginPropertyAccessFromOpener = 1978,
-    kCredentialManagerCreate = 1979,
-    kWebDatabaseCreateDropFTS3Table = 1980,
-    kFieldEditInSecureContext = 1981,
-    kFieldEditInNonSecureContext = 1982,
-    kCredentialManagerCredentialRequestOptionsUnmediated = 1983,
-    kCredentialManagerGetMediationRequired = 1984,
-    kCredentialManagerIdName = 1985,
-    kCredentialManagerPasswordName = 1986,
-    kCredentialManagerAdditionalData = 1987,
-    kCredentialManagerCustomFetch = 1988,
-    kNetInfoRtt = 1989,
-    kNetInfoDownlink = 1990,
-    kShapeDetection_BarcodeDetectorConstructor = 1991,
-    kShapeDetection_FaceDetectorConstructor = 1992,
-    kShapeDetection_TextDetectorConstructor = 1993,
-    kCredentialManagerCredentialRequestOptionsOnlyUnmediated = 1994,
-    kInertAttribute = 1995,
-    kPluginInstanceAccessFromIsolatedWorld = 1996,
-    kPluginInstanceAccessFromMainWorld = 1997,
-    kRequestFullscreenForDialogElement = 1998,
-    kRequestFullscreenForDialogElementInTopLayer = 1999,
-    kShowModalForElementInFullscreenStack = 2000,
-    kThreeValuedPositionBackground = 2001,
-    kThreeValuedPositionBasicShape = 2002,
-    kThreeValuedPositionGradient = 2003,
-    kThreeValuedPositionObjectPosition = 2004,
-    kThreeValuedPositionPerspectiveOrigin = 2005,
-    kUnitlessZeroAngleFilter = 2007,
-    kUnitlessZeroAngleGradient = 2008,
-    kUnitlessZeroAngleOffsetRotate = 2009,
-    kUnitlessZeroAngleTransform = 2010,
-    kHTMLOListElementStartGetterReversedWithoutStartAttribute = 2011,
-    kCredentialManagerPreventSilentAccess = 2012,
-    kNetInfoEffectiveType = 2013,
-    kV8SpeechRecognition_Start_Method = 2014,
-    kTableRowDirectionDifferentFromTable = 2015,
-    kTableSectionDirectionDifferentFromTable = 2016,
-    // The above items are available in M60 branch.
-
-    kClientHintsDeviceRAM = 2017,
-    kCSSRegisterProperty = 2018,
-    // 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
-    // chromium/src/tools/metrics/histograms/ to update the UMA mapping.
-    kNumberOfFeatures,  // This enum value must be last.
+#include "public/platform/UseCounterFeature.def"
   };
 
   // An interface to observe UseCounter changes. Note that this is never
@@ -1637,18 +90,28 @@
     // Notified when a feature is counted for the first time. This should return
     // true if it no longer needs to observe changes so that the counter can
     // remove a reference to the observer and stop notifications.
-    virtual bool OnCountFeature(Feature) = 0;
+    virtual bool OnCountFeature(WebFeature) = 0;
 
     DEFINE_INLINE_VIRTUAL_TRACE() {}
   };
 
   // "count" sets the bit for this feature to 1. Repeated calls are ignored.
-  static void Count(const LocalFrame*, Feature);
-  static void Count(const Document&, Feature);
-  static void Count(ExecutionContext*, Feature);
+  static void Count(const LocalFrame*, WebFeature);
+  static void Count(const Document&, WebFeature);
+  static void Count(ExecutionContext*, WebFeature);
+  // TODO(lunalu): Deprecate Count() that takes UseCounter::Feature.
+  static void Count(const LocalFrame* frame, Feature feature) {
+    return Count(frame, static_cast<WebFeature>(feature));
+  }
+  static void Count(const Document& document, Feature feature) {
+    return Count(document, static_cast<WebFeature>(feature));
+  }
+  static void Count(ExecutionContext* exec_context, Feature feature) {
+    return Count(exec_context, static_cast<WebFeature>(feature));
+  }
 
   void Count(CSSParserMode, CSSPropertyID);
-  void Count(Feature, const LocalFrame*);
+  void Count(WebFeature, const LocalFrame*);
 
   static void CountAnimatedCSS(const Document&, CSSPropertyID);
   void CountAnimatedCSS(CSSPropertyID);
@@ -1682,12 +145,18 @@
   void MuteForInspector();
   void UnmuteForInspector();
 
-  void RecordMeasurement(Feature);
+  void RecordMeasurement(WebFeature);
+  void RecordMeasurement(Feature feature) {
+    return RecordMeasurement(static_cast<WebFeature>(feature));
+  }
 
   // Return whether the feature has been seen since the last page load
   // (except when muted).  Does include features seen in documents which have
   // reporting disabled.
-  bool HasRecordedMeasurement(Feature) const;
+  bool HasRecordedMeasurement(WebFeature) const;
+  bool HasRecordedMeasurement(Feature feature) const {
+    return HasRecordedMeasurement(static_cast<WebFeature>(feature));
+  }
 
   DECLARE_TRACE();
 
@@ -1695,7 +164,7 @@
   // Notifies that a feature is newly counted to |m_observers|. This shouldn't
   // be called when the counter is disabled by |m_muteCount| or when |m_context|
   // if kDisabledContext.
-  void NotifyFeatureCounted(Feature);
+  void NotifyFeatureCounted(WebFeature);
 
   EnumerationHistogram& FeaturesHistogram() const;
   EnumerationHistogram& CssHistogram() const;
@@ -1723,7 +192,7 @@
    public:
     LegacyCounter();
     ~LegacyCounter();
-    void CountFeature(Feature);
+    void CountFeature(WebFeature);
     void CountCSS(CSSPropertyID);
     void UpdateMeasurements();
 
diff --git a/third_party/WebKit/Source/core/frame/UseCounterTest.cpp b/third_party/WebKit/Source/core/frame/UseCounterTest.cpp
index 2afa3c1..9c4a330 100644
--- a/third_party/WebKit/Source/core/frame/UseCounterTest.cpp
+++ b/third_party/WebKit/Source/core/frame/UseCounterTest.cpp
@@ -153,16 +153,14 @@
 
 TEST(UseCounterTest, RecordingFeatures) {
   UseCounter use_counter;
-  HistogramBasicTest<UseCounter::Feature>(
-      kFeaturesHistogramName, kLegacyFeaturesHistogramName, UseCounter::kFetch,
-      UseCounter::kFetchBodyStream,
-      [&](UseCounter::Feature feature) -> bool {
+  HistogramBasicTest<WebFeature>(
+      kFeaturesHistogramName, kLegacyFeaturesHistogramName, WebFeature::kFetch,
+      WebFeature::kFetchBodyStream,
+      [&](WebFeature feature) -> bool {
         return use_counter.HasRecordedMeasurement(feature);
       },
-      [&](UseCounter::Feature feature) {
-        use_counter.RecordMeasurement(feature);
-      },
-      [](UseCounter::Feature feature) -> int { return feature; },
+      [&](WebFeature feature) { use_counter.RecordMeasurement(feature); },
+      [](WebFeature feature) -> int { return static_cast<int>(feature); },
       [&](KURL kurl) { use_counter.DidCommitLoad(kurl); }, kHttpsUrl);
 }
 
@@ -199,32 +197,28 @@
 
 TEST(UseCounterTest, RecordingExtensions) {
   UseCounter use_counter(UseCounter::kExtensionContext);
-  HistogramBasicTest<UseCounter::Feature>(
+  HistogramBasicTest<WebFeature>(
       kExtensionFeaturesHistogramName, kLegacyFeaturesHistogramName,
-      UseCounter::kFetch, UseCounter::kFetchBodyStream,
-      [&](UseCounter::Feature feature) -> bool {
+      WebFeature::kFetch, WebFeature::kFetchBodyStream,
+      [&](WebFeature feature) -> bool {
         return use_counter.HasRecordedMeasurement(feature);
       },
-      [&](UseCounter::Feature feature) {
-        use_counter.RecordMeasurement(feature);
-      },
-      [](UseCounter::Feature feature) -> int { return feature; },
+      [&](WebFeature feature) { use_counter.RecordMeasurement(feature); },
+      [](WebFeature feature) -> int { return static_cast<int>(feature); },
       [&](KURL kurl) { use_counter.DidCommitLoad(kurl); }, kExtensionUrl);
 }
 
 TEST(UseCounterTest, SVGImageContextFeatures) {
   UseCounter use_counter(UseCounter::kSVGImageContext);
-  HistogramBasicTest<UseCounter::Feature>(
+  HistogramBasicTest<WebFeature>(
       kSVGFeaturesHistogramName, kLegacyFeaturesHistogramName,
-      UseCounter::kSVGSMILAdditiveAnimation,
-      UseCounter::kSVGSMILAnimationElementTiming,
-      [&](UseCounter::Feature feature) -> bool {
+      WebFeature::kSVGSMILAdditiveAnimation,
+      WebFeature::kSVGSMILAnimationElementTiming,
+      [&](WebFeature feature) -> bool {
         return use_counter.HasRecordedMeasurement(feature);
       },
-      [&](UseCounter::Feature feature) {
-        use_counter.RecordMeasurement(feature);
-      },
-      [](UseCounter::Feature feature) -> int { return feature; },
+      [&](WebFeature feature) { use_counter.RecordMeasurement(feature); },
+      [](WebFeature feature) -> int { return static_cast<int>(feature); },
       [&](KURL kurl) { use_counter.DidCommitLoad(kurl); }, kSvgUrl);
 }
 
diff --git a/third_party/WebKit/Source/core/html/canvas/CanvasRenderingContextHost.cpp b/third_party/WebKit/Source/core/html/canvas/CanvasRenderingContextHost.cpp
index 8d58c41..01894f6 100644
--- a/third_party/WebKit/Source/core/html/canvas/CanvasRenderingContextHost.cpp
+++ b/third_party/WebKit/Source/core/html/canvas/CanvasRenderingContextHost.cpp
@@ -12,6 +12,7 @@
 
 ScriptPromise CanvasRenderingContextHost::Commit(
     RefPtr<StaticBitmapImage> bitmap_image,
+    const SkIRect& damage_rect,
     bool is_web_gl_software_rendering,
     ScriptState* script_state,
     ExceptionState& exception_state) {
diff --git a/third_party/WebKit/Source/core/html/canvas/CanvasRenderingContextHost.h b/third_party/WebKit/Source/core/html/canvas/CanvasRenderingContextHost.h
index f549804..c16869a 100644
--- a/third_party/WebKit/Source/core/html/canvas/CanvasRenderingContextHost.h
+++ b/third_party/WebKit/Source/core/html/canvas/CanvasRenderingContextHost.h
@@ -41,6 +41,7 @@
   virtual const KURL& GetExecutionContextUrl() const = 0;
 
   virtual ScriptPromise Commit(RefPtr<StaticBitmapImage>,
+                               const SkIRect& damage_rect,
                                bool is_web_gl_software_rendering,
                                ScriptState*,
                                ExceptionState&);
diff --git a/third_party/WebKit/Source/core/html/forms/TextControlInnerElements.cpp b/third_party/WebKit/Source/core/html/forms/TextControlInnerElements.cpp
index 985cf2c..9a41b09 100644
--- a/third_party/WebKit/Source/core/html/forms/TextControlInnerElements.cpp
+++ b/third_party/WebKit/Source/core/html/forms/TextControlInnerElements.cpp
@@ -89,9 +89,6 @@
   style->SetUserModify(EUserModify::kReadOnly);
   style->SetUnique();
 
-  if (const ComputedStyle* parent_style = ParentComputedStyle())
-    StyleAdjuster::AdjustStyleForAlignment(*style, *parent_style);
-
   return style.Release();
 }
 
@@ -149,8 +146,6 @@
   // Using StyleAdjuster::adjustComputedStyle updates unwanted style. We'd like
   // to apply only editing-related and alignment-related.
   StyleAdjuster::AdjustStyleForEditing(*inner_editor_style);
-  if (const ComputedStyle* parent_style = ParentComputedStyle())
-    StyleAdjuster::AdjustStyleForAlignment(*inner_editor_style, *parent_style);
   return inner_editor_style.Release();
 }
 
diff --git a/third_party/WebKit/Source/core/html/media/AutoplayPolicy.cpp b/third_party/WebKit/Source/core/html/media/AutoplayPolicy.cpp
index 67672a98..c25a31b2 100644
--- a/third_party/WebKit/Source/core/html/media/AutoplayPolicy.cpp
+++ b/third_party/WebKit/Source/core/html/media/AutoplayPolicy.cpp
@@ -39,8 +39,8 @@
 }
 
 // Return true if and only if the document settings specifies media playback
-// requires user gesture.
-bool ComputeLockedPendingUserGesture(const Document& document) {
+// requires user gesture on the element.
+bool ComputeLockPendingUserGestureRequired(const Document& document) {
   switch (AutoplayPolicy::GetAutoplayPolicyForDocument(document)) {
     case AutoplayPolicy::Type::kNoUserGestureRequired:
       return false;
@@ -48,6 +48,11 @@
       return IsDocumentCrossOrigin(document);
     case AutoplayPolicy::Type::kUserGestureRequired:
       return true;
+    // kDocumentUserActivationRequired policy does not imply that a user gesture
+    // is required on the element but instead requires a user gesture on the
+    // document, therefore the element is not locked.
+    case AutoplayPolicy::Type::kDocumentUserActivationRequired:
+      return false;
   }
 
   NOTREACHED();
@@ -75,7 +80,7 @@
       autoplay_visibility_observer_(nullptr),
       autoplay_uma_helper_(AutoplayUmaHelper::Create(element)) {
   locked_pending_user_gesture_ =
-      ComputeLockedPendingUserGesture(element->GetDocument());
+      ComputeLockPendingUserGestureRequired(element->GetDocument());
   locked_pending_user_gesture_if_cross_origin_experiment_enabled_ =
       IsDocumentCrossOrigin(element->GetDocument());
 }
@@ -88,9 +93,9 @@
   // If any experiment is enabled, then we want to enable a user gesture by
   // default, otherwise the experiment does nothing.
   bool old_document_requires_user_gesture =
-      ComputeLockedPendingUserGesture(old_document);
+      ComputeLockPendingUserGestureRequired(old_document);
   bool new_document_requires_user_gesture =
-      ComputeLockedPendingUserGesture(element_->GetDocument());
+      ComputeLockPendingUserGestureRequired(element_->GetDocument());
   if (new_document_requires_user_gesture && !old_document_requires_user_gesture)
     locked_pending_user_gesture_ = true;
 
@@ -215,6 +220,13 @@
 }
 
 bool AutoplayPolicy::IsLockedPendingUserGesture() const {
+  if (GetAutoplayPolicyForDocument(element_->GetDocument()) ==
+      AutoplayPolicy::Type::kDocumentUserActivationRequired) {
+    if (!element_->GetDocument().GetFrame())
+      return true;
+    return !element_->GetDocument().GetFrame()->HasReceivedUserGesture();
+  }
+
   return locked_pending_user_gesture_;
 }
 
@@ -231,7 +243,7 @@
 }
 
 bool AutoplayPolicy::IsGestureNeededForPlayback() const {
-  if (!locked_pending_user_gesture_)
+  if (!IsLockedPendingUserGesture())
     return false;
 
   return IsGestureNeededForPlaybackIfPendingUserGestureIsLocked();
diff --git a/third_party/WebKit/Source/core/html/media/AutoplayPolicy.h b/third_party/WebKit/Source/core/html/media/AutoplayPolicy.h
index a47795b3..bf3be2c 100644
--- a/third_party/WebKit/Source/core/html/media/AutoplayPolicy.h
+++ b/third_party/WebKit/Source/core/html/media/AutoplayPolicy.h
@@ -23,8 +23,14 @@
   // Different autoplay policy types.
   enum class Type {
     kNoUserGestureRequired = 0,
+    // A local user gesture on the element is required.
     kUserGestureRequired,
+    // A local user gesture on the element is required when it is in a cross
+    // origin iframe.
     kUserGestureRequiredForCrossOrigin,
+    // The document needs to have received a user activation or received one
+    // before navigating.
+    kDocumentUserActivationRequired,
   };
 
   CORE_EXPORT static Type GetAutoplayPolicyForDocument(const Document&);
diff --git a/third_party/WebKit/Source/core/input/MouseEventManager.cpp b/third_party/WebKit/Source/core/input/MouseEventManager.cpp
index 50f2625..a09bc63 100644
--- a/third_party/WebKit/Source/core/input/MouseEventManager.cpp
+++ b/third_party/WebKit/Source/core/input/MouseEventManager.cpp
@@ -755,6 +755,10 @@
   if (!mouse_pressed_)
     return WebInputEventResult::kNotHandled;
 
+  if (event.Event().pointer_type ==
+      blink::WebPointerProperties::PointerType::kPen)
+    return WebInputEventResult::kNotHandled;
+
   if (HandleDrag(event, DragInitiator::kMouse))
     return WebInputEventResult::kHandledSystem;
 
diff --git a/third_party/WebKit/Source/core/layout/LayoutBox.cpp b/third_party/WebKit/Source/core/layout/LayoutBox.cpp
index 7beb92e..baae320 100644
--- a/third_party/WebKit/Source/core/layout/LayoutBox.cpp
+++ b/third_party/WebKit/Source/core/layout/LayoutBox.cpp
@@ -2850,7 +2850,7 @@
   return StyleRef()
              .ResolvedAlignSelf(
                  ContainingBlock()->SelfAlignmentNormalBehavior(),
-                 IsAnonymous() ? &parent_style : nullptr)
+                 &parent_style)
              .GetPosition() == kItemPositionStretch;
 }
 
@@ -2884,15 +2884,14 @@
     // Flexbox Items, which obviously should have a container.
     return false;
   }
-  const ComputedStyle* parent_style = IsAnonymous() ? cb->Style() : nullptr;
   if (cb->IsHorizontalWritingMode() != IsHorizontalWritingMode())
     return style
                .ResolvedAlignSelf(cb->SelfAlignmentNormalBehavior(this),
-                                  parent_style)
+                                  cb->Style())
                .GetPosition() == kItemPositionStretch;
   return style
              .ResolvedJustifySelf(cb->SelfAlignmentNormalBehavior(this),
-                                  parent_style)
+                                  cb->Style())
              .GetPosition() == kItemPositionStretch;
 }
 
diff --git a/third_party/WebKit/Source/core/layout/LayoutFlexibleBox.cpp b/third_party/WebKit/Source/core/layout/LayoutFlexibleBox.cpp
index 79ca9899..3b10dde9 100644
--- a/third_party/WebKit/Source/core/layout/LayoutFlexibleBox.cpp
+++ b/third_party/WebKit/Source/core/layout/LayoutFlexibleBox.cpp
@@ -325,14 +325,13 @@
   intrinsic_size_along_main_axis_.erase(child);
 }
 
-// TODO (lajava): Is this function still needed ? Every time the flex
-// container's align-items value changes we propagate the diff to its children
-// (see ComputedStyle::stylePropagationDiff).
 void LayoutFlexibleBox::StyleDidChange(StyleDifference diff,
                                        const ComputedStyle* old_style) {
   LayoutBlock::StyleDidChange(diff, old_style);
 
-  if (old_style && old_style->AlignItemsPosition() == kItemPositionStretch &&
+  if (old_style &&
+      old_style->ResolvedAlignItems(SelfAlignmentNormalBehavior())
+              .GetPosition() == kItemPositionStretch &&
       diff.NeedsFullLayout()) {
     // Flex items that were previously stretching need to be relayed out so we
     // can compute new available cross axis space. This is only necessary for
@@ -1706,8 +1705,7 @@
     const LayoutBox& child) const {
   ItemPosition align =
       child.StyleRef()
-          .ResolvedAlignSelf(SelfAlignmentNormalBehavior(),
-                             child.IsAnonymous() ? Style() : nullptr)
+          .ResolvedAlignSelf(SelfAlignmentNormalBehavior(), Style())
           .GetPosition();
   DCHECK_NE(align, kItemPositionAuto);
   DCHECK_NE(align, kItemPositionNormal);
diff --git a/third_party/WebKit/Source/core/layout/LayoutGrid.cpp b/third_party/WebKit/Source/core/layout/LayoutGrid.cpp
index 7fc73fa..99bc7c6 100644
--- a/third_party/WebKit/Source/core/layout/LayoutGrid.cpp
+++ b/third_party/WebKit/Source/core/layout/LayoutGrid.cpp
@@ -97,12 +97,67 @@
   DirtyGrid();
 }
 
+StyleSelfAlignmentData LayoutGrid::SelfAlignmentForChild(
+    GridAxis axis,
+    const LayoutBox& child,
+    const ComputedStyle* style) const {
+  return axis == kGridRowAxis ? JustifySelfForChild(child, style)
+                              : AlignSelfForChild(child, style);
+}
+
+bool LayoutGrid::SelfAlignmentChangedToStretch(GridAxis axis,
+                                               const ComputedStyle& old_style,
+                                               const ComputedStyle& new_style,
+                                               const LayoutBox& child) const {
+  return SelfAlignmentForChild(axis, child, &old_style).GetPosition() !=
+             kItemPositionStretch &&
+         SelfAlignmentForChild(axis, child, &new_style).GetPosition() ==
+             kItemPositionStretch;
+}
+
+bool LayoutGrid::SelfAlignmentChangedFromStretch(GridAxis axis,
+                                                 const ComputedStyle& old_style,
+                                                 const ComputedStyle& new_style,
+                                                 const LayoutBox& child) const {
+  return SelfAlignmentForChild(axis, child, &old_style).GetPosition() ==
+             kItemPositionStretch &&
+         SelfAlignmentForChild(axis, child, &new_style).GetPosition() !=
+             kItemPositionStretch;
+}
+
 void LayoutGrid::StyleDidChange(StyleDifference diff,
                                 const ComputedStyle* old_style) {
   LayoutBlock::StyleDidChange(diff, old_style);
   if (!old_style)
     return;
 
+  const ComputedStyle& new_style = StyleRef();
+  if (old_style &&
+      old_style->ResolvedAlignItems(SelfAlignmentNormalBehavior(this))
+              .GetPosition() == kItemPositionStretch &&
+      diff.NeedsFullLayout()) {
+    // Style changes on the grid container implying stretching (to-stretch) or
+    // shrinking (from-stretch) require the affected items to be laid out again.
+    // These logic only applies to 'stretch' since the rest of the alignment
+    // values don't change the size of the box.
+    // In any case, the items' overrideSize will be cleared and recomputed (if
+    // necessary)  as part of the Grid layout logic, triggered by this style
+    // change.
+    for (LayoutBox* child = FirstInFlowChildBox(); child;
+         child = child->NextInFlowSiblingBox()) {
+      if (SelfAlignmentChangedToStretch(kGridRowAxis, *old_style, new_style,
+                                        *child) ||
+          SelfAlignmentChangedFromStretch(kGridRowAxis, *old_style, new_style,
+                                          *child) ||
+          SelfAlignmentChangedToStretch(kGridColumnAxis, *old_style, new_style,
+                                        *child) ||
+          SelfAlignmentChangedFromStretch(kGridColumnAxis, *old_style,
+                                          new_style, *child)) {
+        child->SetNeedsLayout(LayoutInvalidationReason::kGridChanged);
+      }
+    }
+  }
+
   // FIXME: The following checks could be narrowed down if we kept track of
   // which type of grid items we have:
   // - explicit grid size changes impact negative explicitely positioned and
@@ -1530,29 +1585,21 @@
 }
 
 StyleSelfAlignmentData LayoutGrid::AlignSelfForChild(
-    const LayoutBox& child) const {
-  if (!child.IsAnonymous()) {
-    return child.StyleRef().ResolvedAlignSelf(
-        SelfAlignmentNormalBehavior(&child));
-  }
-  // All the 'auto' values has been solved by the StyleAdjuster, but it's
-  // possible that some grid items generate Anonymous boxes, which need to be
-  // solved during layout.
+    const LayoutBox& child,
+    const ComputedStyle* style) const {
+  if (!style)
+    style = Style();
   return child.StyleRef().ResolvedAlignSelf(SelfAlignmentNormalBehavior(&child),
-                                            Style());
+                                            style);
 }
 
 StyleSelfAlignmentData LayoutGrid::JustifySelfForChild(
-    const LayoutBox& child) const {
-  if (!child.IsAnonymous()) {
-    return child.StyleRef().ResolvedJustifySelf(
-        SelfAlignmentNormalBehavior(&child));
-  }
-  // All the 'auto' values has been solved by the StyleAdjuster, but it's
-  // possible that some grid items generate Anonymous boxes, which need to be
-  // solved during layout.
+    const LayoutBox& child,
+    const ComputedStyle* style) const {
+  if (!style)
+    style = Style();
   return child.StyleRef().ResolvedJustifySelf(
-      SelfAlignmentNormalBehavior(&child), Style());
+      SelfAlignmentNormalBehavior(&child), style);
 }
 
 GridTrackSizingDirection LayoutGrid::FlowAwareDirectionForChild(
@@ -1780,11 +1827,9 @@
 
 bool LayoutGrid::IsBaselineAlignmentForChild(const LayoutBox& child,
                                              GridAxis baseline_axis) const {
-  bool is_column_axis_baseline = baseline_axis == kGridColumnAxis;
-  ItemPosition align = is_column_axis_baseline
-                           ? AlignSelfForChild(child).GetPosition()
-                           : JustifySelfForChild(child).GetPosition();
-  bool has_auto_margins = is_column_axis_baseline
+  ItemPosition align =
+      SelfAlignmentForChild(baseline_axis, child).GetPosition();
+  bool has_auto_margins = baseline_axis == kGridColumnAxis
                               ? HasAutoMarginsInColumnAxis(child)
                               : HasAutoMarginsInRowAxis(child);
   return IsBaselinePosition(align) && !has_auto_margins;
@@ -1804,9 +1849,8 @@
                                            : col_axis_alignment_context_;
   auto* context = contexts_map.at(span.StartLine());
   DCHECK(context);
-  ItemPosition align = is_column_axis_baseline
-                           ? AlignSelfForChild(child).GetPosition()
-                           : JustifySelfForChild(child).GetPosition();
+  ItemPosition align =
+      SelfAlignmentForChild(baseline_axis, child).GetPosition();
   return context->GetSharedGroup(child, align);
 }
 
@@ -1924,9 +1968,8 @@
   auto add_result = contexts_map.insert(span.StartLine(), nullptr);
 
   // Looking for a compatible baseline-sharing group.
-  ItemPosition align = is_column_axis_baseline
-                           ? AlignSelfForChild(child).GetPosition()
-                           : JustifySelfForChild(child).GetPosition();
+  ItemPosition align =
+      SelfAlignmentForChild(baseline_axis, child).GetPosition();
   if (add_result.is_new_entry) {
     add_result.stored_value->value =
         WTF::MakeUnique<BaselineContext>(child, align, ascent, descent);
diff --git a/third_party/WebKit/Source/core/layout/LayoutGrid.h b/third_party/WebKit/Source/core/layout/LayoutGrid.h
index cf5354f..7a82d7a 100644
--- a/third_party/WebKit/Source/core/layout/LayoutGrid.h
+++ b/third_party/WebKit/Source/core/layout/LayoutGrid.h
@@ -128,6 +128,14 @@
                 LayoutObject* before_child = nullptr) override;
   void RemoveChild(LayoutObject*) override;
 
+  bool SelfAlignmentChangedToStretch(GridAxis,
+                                     const ComputedStyle& old_style,
+                                     const ComputedStyle& new_style,
+                                     const LayoutBox&) const;
+  bool SelfAlignmentChangedFromStretch(GridAxis,
+                                       const ComputedStyle& old_style,
+                                       const ComputedStyle& new_style,
+                                       const LayoutBox&) const;
   void StyleDidChange(StyleDifference, const ComputedStyle*) override;
 
   Optional<LayoutUnit> AvailableSpaceForGutters(GridTrackSizingDirection) const;
@@ -212,8 +220,16 @@
   LayoutUnit AvailableAlignmentSpaceForChildBeforeStretching(
       LayoutUnit grid_area_breadth_for_child,
       const LayoutBox&) const;
-  StyleSelfAlignmentData JustifySelfForChild(const LayoutBox&) const;
-  StyleSelfAlignmentData AlignSelfForChild(const LayoutBox&) const;
+  StyleSelfAlignmentData JustifySelfForChild(
+      const LayoutBox&,
+      const ComputedStyle* = nullptr) const;
+  StyleSelfAlignmentData AlignSelfForChild(
+      const LayoutBox&,
+      const ComputedStyle* = nullptr) const;
+  StyleSelfAlignmentData SelfAlignmentForChild(
+      GridAxis,
+      const LayoutBox& child,
+      const ComputedStyle* = nullptr) const;
   void ApplyStretchAlignmentToChildIfNeeded(LayoutBox&);
   bool HasAutoSizeInColumnAxis(const LayoutBox& child) const {
     return IsHorizontalWritingMode() ? child.StyleRef().Height().IsAuto()
diff --git a/third_party/WebKit/Source/core/layout/LayoutTableCell.h b/third_party/WebKit/Source/core/layout/LayoutTableCell.h
index 1380b19..c513017 100644
--- a/third_party/WebKit/Source/core/layout/LayoutTableCell.h
+++ b/third_party/WebKit/Source/core/layout/LayoutTableCell.h
@@ -104,7 +104,7 @@
 
   void SetAbsoluteColumnIndex(unsigned column) {
     if (UNLIKELY(column > kMaxColumnIndex))
-      CRASH();
+      IMMEDIATE_CRASH();
 
     absolute_column_index_ = column;
   }
diff --git a/third_party/WebKit/Source/core/layout/LayoutTableRow.h b/third_party/WebKit/Source/core/layout/LayoutTableRow.h
index 9f81f4c..7d6850eb 100644
--- a/third_party/WebKit/Source/core/layout/LayoutTableRow.h
+++ b/third_party/WebKit/Source/core/layout/LayoutTableRow.h
@@ -86,7 +86,7 @@
 
   void SetRowIndex(unsigned row_index) {
     if (UNLIKELY(row_index > kMaxRowIndex))
-      CRASH();
+      IMMEDIATE_CRASH();
 
     row_index_ = row_index;
   }
diff --git a/third_party/WebKit/Source/core/layout/LayoutText.cpp b/third_party/WebKit/Source/core/layout/LayoutText.cpp
index 961c32a..8753bc1 100644
--- a/third_party/WebKit/Source/core/layout/LayoutText.cpp
+++ b/third_party/WebKit/Source/core/layout/LayoutText.cpp
@@ -110,7 +110,7 @@
   const StringImpl& input = *string->Impl();
 
   if (length >= std::numeric_limits<unsigned>::max())
-    CRASH();
+    IMMEDIATE_CRASH();
 
   StringBuffer<UChar> string_with_previous(length + 1);
   string_with_previous[0] =
diff --git a/third_party/WebKit/Source/core/loader/ProgressTracker.cpp b/third_party/WebKit/Source/core/loader/ProgressTracker.cpp
index 3f867dc4..0e605d65 100644
--- a/third_party/WebKit/Source/core/loader/ProgressTracker.cpp
+++ b/third_party/WebKit/Source/core/loader/ProgressTracker.cpp
@@ -31,6 +31,7 @@
 #include "core/frame/Settings.h"
 #include "core/loader/DocumentLoader.h"
 #include "core/loader/FrameLoader.h"
+#include "core/paint/PaintTiming.h"
 #include "core/probe/CoreProbes.h"
 #include "platform/loader/fetch/Resource.h"
 #include "platform/loader/fetch/ResourceFetcher.h"
@@ -71,6 +72,7 @@
       last_notified_progress_value_(0),
       last_notified_progress_time_(0),
       finished_parsing_(false),
+      did_first_contentful_paint_(false),
       progress_value_(0) {}
 
 ProgressTracker::~ProgressTracker() {}
@@ -95,6 +97,7 @@
   last_notified_progress_value_ = 0;
   last_notified_progress_time_ = 0;
   finished_parsing_ = false;
+  did_first_contentful_paint_ = false;
 }
 
 LocalFrameClient* ProgressTracker::GetLocalFrameClient() const {
@@ -125,6 +128,11 @@
   MaybeSendProgress();
 }
 
+void ProgressTracker::DidFirstContentfulPaint() {
+  did_first_contentful_paint_ = true;
+  MaybeSendProgress();
+}
+
 void ProgressTracker::SendFinalProgress() {
   if (progress_value_ == 1)
     return;
@@ -142,7 +150,7 @@
   // finishes.
   if (frame_->GetSettings()->GetProgressBarCompletion() !=
           ProgressBarCompletion::kLoadEvent &&
-      (finished_parsing_ || priority < kResourceLoadPriorityHigh))
+      (HaveParsedAndPainted() || priority < kResourceLoadPriorityHigh))
     return;
   progress_items_.Set(identifier, WTF::MakeUnique<ProgressItem>(
                                       kProgressItemDefaultEstimatedLength));
@@ -172,13 +180,19 @@
   MaybeSendProgress();
 }
 
+bool ProgressTracker::HaveParsedAndPainted() {
+  return finished_parsing_ && did_first_contentful_paint_;
+}
+
 void ProgressTracker::MaybeSendProgress() {
   if (!frame_->IsLoading())
     return;
 
   progress_value_ = kInitialProgressValue + 0.1;  // +0.1 for committing
   if (finished_parsing_)
-    progress_value_ += 0.2;
+    progress_value_ += 0.1;
+  if (did_first_contentful_paint_)
+    progress_value_ += 0.1;
 
   long long bytes_received = 0;
   long long estimated_bytes_for_pending_requests = 0;
@@ -190,7 +204,7 @@
   DCHECK_GE(estimated_bytes_for_pending_requests, 0);
   DCHECK_GE(estimated_bytes_for_pending_requests, bytes_received);
 
-  if (finished_parsing_) {
+  if (HaveParsedAndPainted()) {
     if (frame_->GetSettings()->GetProgressBarCompletion() ==
         ProgressBarCompletion::kDOMContentLoaded) {
       SendFinalProgress();
diff --git a/third_party/WebKit/Source/core/loader/ProgressTracker.h b/third_party/WebKit/Source/core/loader/ProgressTracker.h
index 405b704..01e4ac75 100644
--- a/third_party/WebKit/Source/core/loader/ProgressTracker.h
+++ b/third_party/WebKit/Source/core/loader/ProgressTracker.h
@@ -63,6 +63,7 @@
   void ProgressCompleted();
 
   void FinishedParsing();
+  void DidFirstContentfulPaint();
 
   void WillStartLoading(unsigned long identifier, ResourceLoadPriority);
   void IncrementProgress(unsigned long identifier, const ResourceResponse&);
@@ -78,10 +79,13 @@
   void SendFinalProgress();
   void Reset();
 
+  bool HaveParsedAndPainted();
+
   Member<LocalFrame> frame_;
   double last_notified_progress_value_;
   double last_notified_progress_time_;
   bool finished_parsing_;
+  bool did_first_contentful_paint_;
   double progress_value_;
 
   HashMap<unsigned long, std::unique_ptr<ProgressItem>> progress_items_;
diff --git a/third_party/WebKit/Source/core/loader/ProgressTrackerTest.cpp b/third_party/WebKit/Source/core/loader/ProgressTrackerTest.cpp
index 5c346f0..cd1b1c9 100644
--- a/third_party/WebKit/Source/core/loader/ProgressTrackerTest.cpp
+++ b/third_party/WebKit/Source/core/loader/ProgressTrackerTest.cpp
@@ -67,7 +67,7 @@
 TEST_F(ProgressTrackerTest, Static) {
   Progress().ProgressStarted(kFrameLoadTypeStandard);
   EXPECT_EQ(0.0, LastProgress());
-  Progress().FinishedParsing();
+  Progress().ProgressCompleted();
   EXPECT_EQ(1.0, LastProgress());
 }
 
@@ -78,11 +78,12 @@
   Progress().IncrementProgress(1ul, 512);
   EXPECT_EQ(0.45, LastProgress());
 
-  // .2 for finishing parsing, .5 for all bytes received.
+  // .2 for committing, .5 for all bytes received.
   Progress().CompleteProgress(1ul);
   EXPECT_EQ(0.7, LastProgress());
 
   Progress().FinishedParsing();
+  Progress().DidFirstContentfulPaint();
   EXPECT_EQ(1.0, LastProgress());
 }
 
@@ -98,8 +99,10 @@
   Progress().CompleteProgress(1ul);
   EXPECT_EQ(0.45, LastProgress());
 
-  // .4 for finishing parsing, .25 out of .5 possible for bytes received.
+  // .4 for finishing parsing/painting,
+  // .25 out of .5 possible for bytes received.
   Progress().FinishedParsing();
+  Progress().DidFirstContentfulPaint();
   EXPECT_EQ(0.65, LastProgress());
 
   Progress().CompleteProgress(2ul);
@@ -113,12 +116,41 @@
   Progress().IncrementProgress(2ul, ResponseHeaders());
   EXPECT_EQ(0.0, LastProgress());
 
-  // .2 for finishing parsing, .5 for all bytes received.
+  // .2 for committing, .5 for all bytes received.
   // Medium priority resource is ignored.
   Progress().CompleteProgress(1ul);
   EXPECT_EQ(0.7, LastProgress());
 
   Progress().FinishedParsing();
+  Progress().DidFirstContentfulPaint();
+  EXPECT_EQ(1.0, LastProgress());
+}
+
+TEST_F(ProgressTrackerTest, FinishParsingBeforeContentfulPaint) {
+  EmulateMainResourceRequestAndResponse();
+
+  // .2 for committing, .5 for all bytes received.
+  Progress().CompleteProgress(1ul);
+  EXPECT_EQ(0.7, LastProgress());
+
+  Progress().FinishedParsing();
+  EXPECT_EQ(0.8, LastProgress());
+
+  Progress().DidFirstContentfulPaint();
+  EXPECT_EQ(1.0, LastProgress());
+}
+
+TEST_F(ProgressTrackerTest, ContentfulPaintBeforeFinishParsing) {
+  EmulateMainResourceRequestAndResponse();
+
+  // .2 for committing, .5 for all bytes received.
+  Progress().CompleteProgress(1ul);
+  EXPECT_EQ(0.7, LastProgress());
+
+  Progress().DidFirstContentfulPaint();
+  EXPECT_EQ(0.8, LastProgress());
+
+  Progress().FinishedParsing();
   EXPECT_EQ(1.0, LastProgress());
 }
 
diff --git a/third_party/WebKit/Source/core/offscreencanvas/OffscreenCanvas.cpp b/third_party/WebKit/Source/core/offscreencanvas/OffscreenCanvas.cpp
index 7fb5e12..deac6cf 100644
--- a/third_party/WebKit/Source/core/offscreencanvas/OffscreenCanvas.cpp
+++ b/third_party/WebKit/Source/core/offscreencanvas/OffscreenCanvas.cpp
@@ -272,6 +272,7 @@
 }
 
 ScriptPromise OffscreenCanvas::Commit(RefPtr<StaticBitmapImage> image,
+                                      const SkIRect& damage_rect,
                                       bool is_web_gl_software_rendering,
                                       ScriptState* script_state,
                                       ExceptionState& exception_state) {
@@ -295,6 +296,8 @@
     if (image) {
       // We defer the submission of commit frames at the end of JS task
       current_frame_ = std::move(image);
+      // union of rects is necessary in case some frames are skipped.
+      current_frame_damage_rect_.join(damage_rect);
       current_frame_is_web_gl_software_rendering_ =
           is_web_gl_software_rendering;
       context_->NeedsFinalizeFrame();
@@ -306,6 +309,7 @@
     // 2. The current frame has been dispatched but the promise is not
     // resolved yet. (m_currentFrame==nullptr)
     current_frame_ = std::move(image);
+    current_frame_damage_rect_.join(damage_rect);
     current_frame_is_web_gl_software_rendering_ = is_web_gl_software_rendering;
   }
 
@@ -316,17 +320,18 @@
   if (current_frame_) {
     // TODO(eseckler): OffscreenCanvas shouldn't dispatch CompositorFrames
     // without a prior BeginFrame.
-    DoCommit(std::move(current_frame_),
-             current_frame_is_web_gl_software_rendering_);
+    DoCommit();
   }
 }
 
-void OffscreenCanvas::DoCommit(RefPtr<StaticBitmapImage> image,
-                               bool is_web_gl_software_rendering) {
+void OffscreenCanvas::DoCommit() {
   TRACE_EVENT0("blink", "OffscreenCanvas::DoCommit");
   double commit_start_time = WTF::MonotonicallyIncreasingTime();
+  DCHECK(current_frame_);
   GetOrCreateFrameDispatcher()->DispatchFrame(
-      std::move(image), commit_start_time, is_web_gl_software_rendering);
+      std::move(current_frame_), commit_start_time, current_frame_damage_rect_,
+      current_frame_is_web_gl_software_rendering_);
+  current_frame_damage_rect_ = SkIRect::MakeEmpty();
 }
 
 void OffscreenCanvas::BeginFrame() {
@@ -338,8 +343,7 @@
     // first and save the promise resolution for later.
     // Then we need to wait for one more frame time to resolve the existing
     // promise.
-    DoCommit(std::move(current_frame_),
-             current_frame_is_web_gl_software_rendering_);
+    DoCommit();
   } else if (commit_promise_resolver_) {
     commit_promise_resolver_->Resolve();
     commit_promise_resolver_.Clear();
diff --git a/third_party/WebKit/Source/core/offscreencanvas/OffscreenCanvas.h b/third_party/WebKit/Source/core/offscreencanvas/OffscreenCanvas.h
index 30ffc96..730feeb3 100644
--- a/third_party/WebKit/Source/core/offscreencanvas/OffscreenCanvas.h
+++ b/third_party/WebKit/Source/core/offscreencanvas/OffscreenCanvas.h
@@ -101,6 +101,7 @@
   }
 
   ScriptPromise Commit(RefPtr<StaticBitmapImage>,
+                       const SkIRect& damage_rect,
                        bool is_web_gl_software_rendering,
                        ScriptState*,
                        ExceptionState&) override;
@@ -158,7 +159,7 @@
  private:
   explicit OffscreenCanvas(const IntSize&);
   OffscreenCanvasFrameDispatcher* GetOrCreateFrameDispatcher();
-  void DoCommit(RefPtr<StaticBitmapImage>, bool is_web_gl_software_rendering);
+  void DoCommit();
   using ContextFactoryVector =
       Vector<std::unique_ptr<CanvasRenderingContextFactory>>;
   static ContextFactoryVector& RenderingContextFactories();
@@ -182,6 +183,7 @@
   Member<ScriptPromiseResolver> commit_promise_resolver_;
   RefPtr<StaticBitmapImage> current_frame_;
   bool current_frame_is_web_gl_software_rendering_ = false;
+  SkIRect current_frame_damage_rect_;
 
   std::unique_ptr<ImageBuffer> image_buffer_;
   bool needs_matrix_clip_restore_ = false;
diff --git a/third_party/WebKit/Source/core/page/FrameTree.cpp b/third_party/WebKit/Source/core/page/FrameTree.cpp
index 9480da0..ea7c652c 100644
--- a/third_party/WebKit/Source/core/page/FrameTree.cpp
+++ b/third_party/WebKit/Source/core/page/FrameTree.cpp
@@ -155,6 +155,9 @@
 }
 
 Frame* FrameTree::Find(const AtomicString& name) const {
+  // Named frame lookup should always be relative to a local frame.
+  DCHECK(this_frame_->IsLocalFrame());
+
   if (EqualIgnoringASCIICase(name, "_self") ||
       EqualIgnoringASCIICase(name, "_current") || name.IsEmpty())
     return this_frame_;
diff --git a/third_party/WebKit/Source/core/paint/PaintTiming.cpp b/third_party/WebKit/Source/core/paint/PaintTiming.cpp
index d1a1121..3e7c53c 100644
--- a/third_party/WebKit/Source/core/paint/PaintTiming.cpp
+++ b/third_party/WebKit/Source/core/paint/PaintTiming.cpp
@@ -9,6 +9,7 @@
 #include "core/frame/LocalFrame.h"
 #include "core/frame/LocalFrameView.h"
 #include "core/loader/DocumentLoader.h"
+#include "core/loader/ProgressTracker.h"
 #include "core/page/ChromeClient.h"
 #include "core/page/Page.h"
 #include "core/timing/DOMWindowPerformance.h"
@@ -161,6 +162,7 @@
   TRACE_EVENT_INSTANT1("loading,rail,devtools.timeline", "firstContentfulPaint",
                        TRACE_EVENT_SCOPE_PROCESS, "frame", GetFrame());
   RegisterNotifySwapTime(PaintEvent::kFirstContentfulPaint);
+  GetFrame()->Loader().Progress().DidFirstContentfulPaint();
 }
 
 void PaintTiming::RegisterNotifySwapTime(PaintEvent event) {
diff --git a/third_party/WebKit/Source/core/style/ComputedStyle.cpp b/third_party/WebKit/Source/core/style/ComputedStyle.cpp
index cee3e96..1fe253cd 100644
--- a/third_party/WebKit/Source/core/style/ComputedStyle.cpp
+++ b/third_party/WebKit/Source/core/style/ComputedStyle.cpp
@@ -199,7 +199,6 @@
   }
 
   if (!old_style->LoadingCustomFontsEqual(*new_style) ||
-      old_style->AlignItems() != new_style->AlignItems() ||
       old_style->JustifyItems() != new_style->JustifyItems())
     return kInherit;
 
@@ -220,9 +219,6 @@
 StyleSelfAlignmentData ResolvedSelfAlignment(
     const StyleSelfAlignmentData& value,
     ItemPosition normal_value_behavior) {
-  // To avoid needing to copy the RareNonInheritedData, we repurpose the 'auto'
-  // flag to not just mean 'auto' prior to running the StyleAdjuster but also
-  // mean 'normal' after running it.
   if (value.GetPosition() == kItemPositionNormal ||
       value.GetPosition() == kItemPositionAuto)
     return {normal_value_behavior, kOverflowAlignmentDefault};
@@ -244,9 +240,6 @@
   if (!parent_style || AlignSelfPosition() != kItemPositionAuto)
     return ResolvedSelfAlignment(AlignSelf(), normal_value_behaviour);
 
-  // We shouldn't need to resolve any 'auto' value in post-adjusment
-  // ComputedStyle, but some layout models can generate anonymous boxes that may
-  // need 'auto' value resolution during layout.
   // The 'auto' keyword computes to the parent's align-items computed value.
   return parent_style->ResolvedAlignItems(normal_value_behaviour);
 }
@@ -266,9 +259,6 @@
   if (!parent_style || JustifySelfPosition() != kItemPositionAuto)
     return ResolvedSelfAlignment(JustifySelf(), normal_value_behaviour);
 
-  // We shouldn't need to resolve any 'auto' value in post-adjusment
-  // ComputedStyle, but some layout models can generate anonymous boxes that may
-  // need 'auto' value resolution during layout.
   // The auto keyword computes to the parent's justify-items computed value.
   return parent_style->ResolvedJustifyItems(normal_value_behaviour);
 }
diff --git a/third_party/WebKit/Source/core/style/ComputedStyleConstants.h b/third_party/WebKit/Source/core/style/ComputedStyleConstants.h
index 7f769ed..d88b7e7d 100644
--- a/third_party/WebKit/Source/core/style/ComputedStyleConstants.h
+++ b/third_party/WebKit/Source/core/style/ComputedStyleConstants.h
@@ -327,8 +327,7 @@
 }
 
 enum ItemPosition {
-  kItemPositionAuto,  // It will mean 'normal' after running the StyleAdjuster
-                      // to avoid resolving the initial values.
+  kItemPositionAuto,
   kItemPositionNormal,
   kItemPositionStretch,
   kItemPositionBaseline,
diff --git a/third_party/WebKit/Source/core/testing/InternalSettings.cpp b/third_party/WebKit/Source/core/testing/InternalSettings.cpp
index 18e7c466f..b3d6d01 100644
--- a/third_party/WebKit/Source/core/testing/InternalSettings.cpp
+++ b/third_party/WebKit/Source/core/testing/InternalSettings.cpp
@@ -545,6 +545,8 @@
     policy = AutoplayPolicy::Type::kUserGestureRequired;
   } else if (policy_str == "user-gesture-required-for-cross-origin") {
     policy = AutoplayPolicy::Type::kUserGestureRequiredForCrossOrigin;
+  } else if (policy_str == "document-user-activation-required") {
+    policy = AutoplayPolicy::Type::kDocumentUserActivationRequired;
   } else {
     exception_state.ThrowDOMException(
         kSyntaxError, "The autoplay policy ('" + policy_str + ")' is invalid.");
diff --git a/third_party/WebKit/Source/core/testing/Internals.cpp b/third_party/WebKit/Source/core/testing/Internals.cpp
index 3b40be5..2ff584b 100644
--- a/third_party/WebKit/Source/core/testing/Internals.cpp
+++ b/third_party/WebKit/Source/core/testing/Internals.cpp
@@ -164,14 +164,13 @@
   WTF_MAKE_NONCOPYABLE(UseCounterObserverImpl);
 
  public:
-  UseCounterObserverImpl(ScriptPromiseResolver* resolver,
-                         UseCounter::Feature feature)
+  UseCounterObserverImpl(ScriptPromiseResolver* resolver, WebFeature feature)
       : resolver_(resolver), feature_(feature) {}
 
-  bool OnCountFeature(UseCounter::Feature feature) final {
+  bool OnCountFeature(WebFeature feature) final {
     if (feature_ != feature)
       return false;
-    resolver_->Resolve(feature);
+    resolver_->Resolve(static_cast<int>(feature));
     return true;
   }
 
@@ -182,7 +181,7 @@
 
  private:
   Member<ScriptPromiseResolver> resolver_;
-  UseCounter::Feature feature_;
+  WebFeature feature_;
 };
 
 }  // namespace
@@ -3217,8 +3216,8 @@
     return promise;
   }
 
-  page->GetUseCounter().AddObserver(
-      new UseCounterObserverImpl(resolver, use_counter_feature));
+  page->GetUseCounter().AddObserver(new UseCounterObserverImpl(
+      resolver, static_cast<WebFeature>(use_counter_feature)));
   return promise;
 }
 
diff --git a/third_party/WebKit/Source/core/xml/XSLTProcessorLibxslt.cpp b/third_party/WebKit/Source/core/xml/XSLTProcessorLibxslt.cpp
index c206f772..d60272e 100644
--- a/third_party/WebKit/Source/core/xml/XSLTProcessorLibxslt.cpp
+++ b/third_party/WebKit/Source/core/xml/XSLTProcessorLibxslt.cpp
@@ -346,15 +346,15 @@
     // Read permissions are checked by docLoaderFunc.
     if (0 != xsltSetSecurityPrefs(security_prefs, XSLT_SECPREF_WRITE_FILE,
                                   xsltSecurityForbid))
-      CRASH();
+      IMMEDIATE_CRASH();
     if (0 != xsltSetSecurityPrefs(security_prefs, XSLT_SECPREF_CREATE_DIRECTORY,
                                   xsltSecurityForbid))
-      CRASH();
+      IMMEDIATE_CRASH();
     if (0 != xsltSetSecurityPrefs(security_prefs, XSLT_SECPREF_WRITE_NETWORK,
                                   xsltSecurityForbid))
-      CRASH();
+      IMMEDIATE_CRASH();
     if (0 != xsltSetCtxtSecurityPrefs(security_prefs, transform_context))
-      CRASH();
+      IMMEDIATE_CRASH();
 
     // <http://bugs.webkit.org/show_bug.cgi?id=16077>: XSLT processor
     // <xsl:sort> algorithm only compares by code point.
diff --git a/third_party/WebKit/Source/devtools/front_end/animation/AnimationModel.js b/third_party/WebKit/Source/devtools/front_end/animation/AnimationModel.js
index b1c2e739..57be8bc 100644
--- a/third_party/WebKit/Source/devtools/front_end/animation/AnimationModel.js
+++ b/third_party/WebKit/Source/devtools/front_end/animation/AnimationModel.js
@@ -120,26 +120,6 @@
   }
 
   /**
-   * @return {!Promise.<number>}
-   */
-  playbackRatePromise() {
-    /**
-     * @param {?Protocol.Error} error
-     * @param {number} playbackRate
-     * @return {number}
-     * @this {!Animation.AnimationModel}
-     */
-    function callback(error, playbackRate) {
-      if (error)
-        return 1;
-      this._playbackRate = playbackRate;
-      return playbackRate;
-    }
-
-    return this._agent.getPlaybackRate(callback.bind(this)).catchException(1);
-  }
-
-  /**
    * @param {number} playbackRate
    */
   setPlaybackRate(playbackRate) {
@@ -353,20 +333,11 @@
   }
 
   /**
-   * @return {!Promise.<?SDK.RemoteObject>}
+   * @return {!Promise<?SDK.RemoteObject>}
    */
   remoteObjectPromise() {
-    /**
-     * @param {?Protocol.Error} error
-     * @param {!Protocol.Runtime.RemoteObject} payload
-     * @return {?SDK.RemoteObject}
-     * @this {!Animation.AnimationModel.Animation}
-     */
-    function callback(error, payload) {
-      return !error ? this._animationModel._runtimeModel.createRemoteObject(payload) : null;
-    }
-
-    return this._animationModel._agent.resolveAnimation(this.id(), callback.bind(this));
+    return this._animationModel._agent.resolveAnimation(this.id()).then(
+        payload => payload && this._animationModel._runtimeModel.createRemoteObject(payload));
   }
 
   /**
@@ -665,24 +636,15 @@
   }
 
   /**
-   * @return {!Promise.<number>}
+   * @return {!Promise<number>}
    */
   currentTimePromise() {
-    /**
-     * @param {?Protocol.Error} error
-     * @param {number} currentTime
-     * @return {number}
-     */
-    function callback(error, currentTime) {
-      return !error ? currentTime : 0;
-    }
-
     var longestAnim = null;
     for (var anim of this._animations) {
       if (!longestAnim || anim.endTime() > longestAnim.endTime())
         longestAnim = anim;
     }
-    return this._animationModel._agent.getCurrentTime(longestAnim.id(), callback).catchException(0);
+    return this._animationModel._agent.getCurrentTime(longestAnim.id()).then(currentTime => currentTime || 0);
   }
 
   /**
diff --git a/third_party/WebKit/Source/devtools/front_end/audits/AuditRules.js b/third_party/WebKit/Source/devtools/front_end/audits/AuditRules.js
index e1c2f58..9c2dae4 100644
--- a/third_party/WebKit/Source/devtools/front_end/audits/AuditRules.js
+++ b/third_party/WebKit/Source/devtools/front_end/audits/AuditRules.js
@@ -464,14 +464,13 @@
             return;
           }
           var effectiveSelector = selectors[i].replace(pseudoSelectorRegexp, '');
-          domModel.querySelector(
-              document.id, effectiveSelector,
-              queryCallback.bind(
+          domModel.querySelector(document.id, effectiveSelector)
+              .then(queryCallback.bind(
                   null, i === selectors.length - 1 ? selectorsCallback.bind(null, styleSheets) : null, selectors[i]));
         }
       }
 
-      domModel.requestDocument(documentLoaded.bind(null, selectors));
+      domModel.requestDocumentPromise().then(documentLoaded.bind(null, selectors));
     }
 
     var styleSheetInfos = cssModel.allStyleSheets();
@@ -925,14 +924,14 @@
         callback(null);
         return;
       }
-      domModel.querySelectorAll(root.id, 'img[src]', getStyles);
+      domModel.querySelectorAll(root.id, 'img[src]').then(getStyles);
     }
 
     if (progress.isCanceled()) {
       callback(null);
       return;
     }
-    domModel.requestDocument(onDocumentAvailable);
+    domModel.requestDocumentPromise().then(onDocumentAvailable);
   }
 };
 
@@ -1027,8 +1026,8 @@
 
       if (!nodeIds)
         return;
-      domModel.querySelectorAll(
-          root.id, 'body link[rel~=\'stylesheet\'][href]', externalStylesheetsReceived.bind(null, root, nodeIds));
+      domModel.querySelectorAll(root.id, 'body link[rel~=\'stylesheet\'][href]')
+          .then(externalStylesheetsReceived.bind(null, root, nodeIds));
     }
 
     /**
@@ -1040,10 +1039,10 @@
         return;
       }
 
-      domModel.querySelectorAll(root.id, 'body style', inlineStylesReceived.bind(null, root));
+      domModel.querySelectorAll(root.id, 'body style').then(inlineStylesReceived.bind(null, root));
     }
 
-    domModel.requestDocument(onDocumentAvailable);
+    domModel.requestDocumentPromise().then(onDocumentAvailable);
   }
 };
 
@@ -1070,51 +1069,33 @@
       return;
     }
 
-    function evalCallback(resultValue) {
-      if (progress.isCanceled()) {
-        callback(null);
-        return;
-      }
-
-      if (!resultValue)
-        return callback(null);
-
-      var lateCssUrls = resultValue[0];
-      var cssBeforeInlineCount = resultValue[1];
-
-      if (lateCssUrls.length) {
-        var entry = result.addChild(
-            Common.UIString(
-                'The following external CSS files were included after an external JavaScript file in the document head. To ensure CSS files are downloaded in parallel, always include external CSS before external JavaScript.'),
-            true);
-        entry.addURLs(lateCssUrls);
-        result.violationCount += lateCssUrls.length;
-      }
-
-      if (cssBeforeInlineCount) {
-        result.addChild(Common.UIString(
-            ' %d inline script block%s found in the head between an external CSS file and another resource. To allow parallel downloading, move the inline script before the external CSS file, or after the next resource.',
-            cssBeforeInlineCount, cssBeforeInlineCount > 1 ? 's were' : ' was'));
-        result.violationCount += cssBeforeInlineCount;
-      }
-      callback(result);
-    }
+    domModel.requestDocumentPromise().then(onDocumentAvailable).then(callback);
 
     /**
-     * @param {!Array.<!Protocol.DOM.NodeId>} lateStyleIds
-     * @param {?Array.<!Protocol.DOM.NodeId>} nodeIds
+     * @param {!SDK.DOMDocument} root
+     * @return {!Promise<?Audits.AuditRuleResult>}
      */
-    function cssBeforeInlineReceived(lateStyleIds, nodeIds) {
-      if (progress.isCanceled()) {
-        callback(null);
-        return;
-      }
+    async function onDocumentAvailable(root) {
+      if (progress.isCanceled())
+        return null;
 
+      var lateStyleIds = await domModel.querySelectorAll(root.id, 'head script[src] ~ link[rel~=\'stylesheet\'][href]');
+
+      if (progress.isCanceled())
+        return null;
+      if (!lateStyleIds)
+        return null;
+
+      var nodeIds =
+          await domModel.querySelectorAll(root.id, 'head link[rel~=\'stylesheet\'][href] ~ script:not([src])');
+
+      if (progress.isCanceled())
+        return null;
       if (!nodeIds)
-        return;
+        return null;
 
       var cssBeforeInlineCount = nodeIds.length;
-      var result = null;
+      var resultValue = null;
       if (lateStyleIds.length || cssBeforeInlineCount) {
         var lateStyleUrls = [];
         for (var i = 0; i < lateStyleIds.length; ++i) {
@@ -1123,44 +1104,38 @@
               Common.ParsedURL.completeURL(lateStyleNode.ownerDocument.baseURL, lateStyleNode.getAttribute('href'));
           lateStyleUrls.push(completeHref || '<empty>');
         }
-        result = [lateStyleUrls, cssBeforeInlineCount];
+        resultValue = [lateStyleUrls, cssBeforeInlineCount];
       }
 
-      evalCallback(result);
-    }
+      if (progress.isCanceled())
+        return null;
+      if (!resultValue)
+        return null;
 
-    /**
-     * @param {!SDK.DOMDocument} root
-     * @param {?Array<!Protocol.DOM.NodeId>} nodeIds
-     */
-    function lateStylesReceived(root, nodeIds) {
-      if (progress.isCanceled()) {
-        callback(null);
-        return;
+      var lateCssUrls = resultValue[0];
+      cssBeforeInlineCount = resultValue[1];
+
+      if (lateCssUrls.length) {
+        var entry = result.addChild(
+            Common.UIString(
+                'The following external CSS files were included after an external JavaScript file in the ' +
+                'document head. To ensure CSS files are downloaded in parallel, always include external CSS ' +
+                'before external JavaScript.'),
+            true);
+        entry.addURLs(lateCssUrls);
+        result.violationCount += lateCssUrls.length;
       }
 
-      if (!nodeIds)
-        return;
-
-      domModel.querySelectorAll(
-          root.id, 'head link[rel~=\'stylesheet\'][href] ~ script:not([src])',
-          cssBeforeInlineReceived.bind(null, nodeIds));
-    }
-
-    /**
-     * @param {!SDK.DOMDocument} root
-     */
-    function onDocumentAvailable(root) {
-      if (progress.isCanceled()) {
-        callback(null);
-        return;
+      if (cssBeforeInlineCount) {
+        result.addChild(Common.UIString(
+            ' %d inline script %s found in the head between an external CSS file and another resource. ' +
+                'To allow parallel downloading, move the inline script before the external CSS file, ' +
+                'or after the next resource.',
+            cssBeforeInlineCount, cssBeforeInlineCount > 1 ? 'blocks were' : 'block was'));
+        result.violationCount += cssBeforeInlineCount;
       }
-
-      domModel.querySelectorAll(
-          root.id, 'head script[src] ~ link[rel~=\'stylesheet\'][href]', lateStylesReceived.bind(null, root));
+      return result;
     }
-
-    domModel.requestDocument(onDocumentAvailable);
   }
 };
 
diff --git a/third_party/WebKit/Source/devtools/front_end/audits2/Audits2Panel.js b/third_party/WebKit/Source/devtools/front_end/audits2/Audits2Panel.js
index 6af2cd3..7e2558b 100644
--- a/third_party/WebKit/Source/devtools/front_end/audits2/Audits2Panel.js
+++ b/third_party/WebKit/Source/devtools/front_end/audits2/Audits2Panel.js
@@ -737,7 +737,7 @@
    * @param {!Element} origElement
    * @param {!DetailsRenderer.NodeDetailsJSON} detailsItem
    */
-  _replaceWithDeferredNodeBlock(origElement, detailsItem) {
+  async _replaceWithDeferredNodeBlock(origElement, detailsItem) {
     var mainTarget = SDK.targetManager.mainTarget();
     if (!this._onMainFrameNavigatedPromise) {
       var resourceTreeModel = mainTarget.model(SDK.ResourceTreeModel);
@@ -746,23 +746,23 @@
       });
     }
 
-    this._onMainFrameNavigatedPromise.then(_ => {
-      var domModel = mainTarget.model(SDK.DOMModel);
-      if (!detailsItem.path)
-        return;
+    await this._onMainFrameNavigatedPromise;
 
-      domModel.pushNodeByPathToFrontend(detailsItem.path, nodeId => {
-        if (!nodeId)
-          return;
-        var node = domModel.nodeForId(nodeId);
-        if (!node)
-          return;
+    var domModel = mainTarget.model(SDK.DOMModel);
+    if (!detailsItem.path)
+      return;
 
-        var element = Components.DOMPresentationUtils.linkifyNodeReference(node, undefined, detailsItem.snippet);
-        origElement.title = '';
-        origElement.textContent = '';
-        origElement.appendChild(element);
-      });
-    });
+    var nodeId = await domModel.pushNodeByPathToFrontend(detailsItem.path);
+
+    if (!nodeId)
+      return;
+    var node = domModel.nodeForId(nodeId);
+    if (!node)
+      return;
+
+    var element = Components.DOMPresentationUtils.linkifyNodeReference(node, undefined, detailsItem.snippet);
+    origElement.title = '';
+    origElement.textContent = '';
+    origElement.appendChild(element);
   }
 };
diff --git a/third_party/WebKit/Source/devtools/front_end/elements/ElementsPanel.js b/third_party/WebKit/Source/devtools/front_end/elements/ElementsPanel.js
index b0780d6..db3f42a 100644
--- a/third_party/WebKit/Source/devtools/front_end/elements/ElementsPanel.js
+++ b/third_party/WebKit/Source/devtools/front_end/elements/ElementsPanel.js
@@ -320,7 +320,7 @@
         if (treeOutline.domModel().existingDocument())
           this._documentUpdated(treeOutline.domModel(), treeOutline.domModel().existingDocument());
         else
-          treeOutline.domModel().requestDocument();
+          treeOutline.domModel().requestDocumentPromise();
       }
     }
   }
@@ -412,7 +412,7 @@
 
     if (!inspectedRootDocument) {
       if (this.isShowing())
-        domModel.requestDocument();
+        domModel.requestDocumentPromise();
       return;
     }
 
@@ -429,20 +429,11 @@
      * @param {?SDK.DOMNode} staleNode
      * @this {Elements.ElementsPanel}
      */
-    function restoreNode(domModel, staleNode) {
+    async function restoreNode(domModel, staleNode) {
       var nodePath = staleNode ? staleNode.path() : null;
-      if (!nodePath) {
-        onNodeRestored.call(this, null);
-        return;
-      }
-      domModel.pushNodeByPathToFrontend(nodePath, onNodeRestored.bind(this));
-    }
 
-    /**
-     * @param {?Protocol.DOM.NodeId} restoredNodeId
-     * @this {Elements.ElementsPanel}
-     */
-    function onNodeRestored(restoredNodeId) {
+      var restoredNodeId = nodePath ? await domModel.pushNodeByPathToFrontend(nodePath) : null;
+
       if (savedSelectedNodeOnReset !== this._selectedNodeOnReset)
         return;
       var node = restoredNodeId ? domModel.nodeForId(restoredNodeId) : null;
@@ -634,18 +625,12 @@
     if (searchResult.node === null)
       return;
 
-    /**
-     * @param {?SDK.DOMNode} node
-     * @this {Elements.ElementsPanel}
-     */
-    function searchCallback(node) {
-      searchResult.node = node;
-      this._highlightCurrentSearchResult();
-    }
-
     if (typeof searchResult.node === 'undefined') {
       // No data for slot, request it.
-      searchResult.domModel.searchResult(searchResult.index, searchCallback.bind(this));
+      searchResult.domModel.searchResult(searchResult.index).then(node => {
+        searchResult.node = node;
+        this._highlightCurrentSearchResult();
+      });
       return;
     }
 
diff --git a/third_party/WebKit/Source/devtools/front_end/elements/ElementsTreeElement.js b/third_party/WebKit/Source/devtools/front_end/elements/ElementsTreeElement.js
index 87cfc378..ffb21338 100644
--- a/third_party/WebKit/Source/devtools/front_end/elements/ElementsTreeElement.js
+++ b/third_party/WebKit/Source/devtools/front_end/elements/ElementsTreeElement.js
@@ -288,7 +288,7 @@
    * @override
    */
   expandRecursively() {
-    this._node.getSubtree(-1, UI.TreeElement.prototype.expandRecursively.bind(this, Number.MAX_VALUE));
+    this._node.getSubtree(-1).then(UI.TreeElement.prototype.expandRecursively.bind(this, Number.MAX_VALUE));
   }
 
   /**
@@ -735,12 +735,12 @@
   /**
    * @param {function(string, string)} commitCallback
    * @param {function()} disposeCallback
-   * @param {?Protocol.Error} error
-   * @param {string} initialValue
+   * @param {?string} maybeInitialValue
    */
-  _startEditingAsHTML(commitCallback, disposeCallback, error, initialValue) {
-    if (error)
+  _startEditingAsHTML(commitCallback, disposeCallback, maybeInitialValue) {
+    if (maybeInitialValue === null)
       return;
+    var initialValue = maybeInitialValue;  // To suppress a compiler warning.
     if (this._editing)
       return;
 
@@ -1595,7 +1595,7 @@
     }
 
     var node = this._node;
-    node.getOuterHTML(this._startEditingAsHTML.bind(this, commitChange, disposeCallback));
+    node.getOuterHTML().then(this._startEditingAsHTML.bind(this, commitChange, disposeCallback));
   }
 
   _copyCSSPath() {
diff --git a/third_party/WebKit/Source/devtools/front_end/elements/ElementsTreeOutline.js b/third_party/WebKit/Source/devtools/front_end/elements/ElementsTreeOutline.js
index a0c0471..322fadc 100644
--- a/third_party/WebKit/Source/devtools/front_end/elements/ElementsTreeOutline.js
+++ b/third_party/WebKit/Source/devtools/front_end/elements/ElementsTreeOutline.js
@@ -1314,18 +1314,12 @@
 
     console.assert(!treeElement.isClosingTag());
 
-    treeElement.node().getChildNodes(childNodesLoaded.bind(this));
-
-    /**
-     * @param {?Array.<!SDK.DOMNode>} children
-     * @this {Elements.ElementsTreeOutline}
-     */
-    function childNodesLoaded(children) {
+    treeElement.node().getChildNodes(children => {
       // FIXME: sort this out, it should not happen.
       if (!children)
         return;
       this._innerUpdateChildren(treeElement);
-    }
+    });
   }
 
   /**
diff --git a/third_party/WebKit/Source/devtools/front_end/layers/LayerTreeModel.js b/third_party/WebKit/Source/devtools/front_end/layers/LayerTreeModel.js
index c39653b..b30d627d 100644
--- a/third_party/WebKit/Source/devtools/front_end/layers/LayerTreeModel.js
+++ b/third_party/WebKit/Source/devtools/front_end/layers/LayerTreeModel.js
@@ -77,26 +77,22 @@
   /**
    * @param {?Array.<!Protocol.LayerTree.Layer>} layers
    */
-  _layerTreeChanged(layers) {
+  async _layerTreeChanged(layers) {
     if (!this._enabled)
       return;
     var layerTree = /** @type {!Layers.AgentLayerTree} */ (this._layerTree);
-    layerTree.setLayers(layers, onLayersSet.bind(this));
 
-    /**
-     * @this {Layers.LayerTreeModel}
-     */
-    function onLayersSet() {
-      for (var layerId in this._lastPaintRectByLayerId) {
-        var lastPaintRect = this._lastPaintRectByLayerId[layerId];
-        var layer = layerTree.layerById(layerId);
-        if (layer)
-          layer._lastPaintRect = lastPaintRect;
-      }
-      this._lastPaintRectByLayerId = {};
+    await layerTree.setLayers(layers);
 
-      this.dispatchEventToListeners(Layers.LayerTreeModel.Events.LayerTreeChanged);
+    for (var layerId in this._lastPaintRectByLayerId) {
+      var lastPaintRect = this._lastPaintRectByLayerId[layerId];
+      var layer = layerTree.layerById(layerId);
+      if (layer)
+        layer._lastPaintRect = lastPaintRect;
     }
+    this._lastPaintRectByLayerId = {};
+
+    this.dispatchEventToListeners(Layers.LayerTreeModel.Events.LayerTreeChanged);
   }
 
   /**
@@ -144,15 +140,14 @@
   }
 
   /**
-   * @param {?Array.<!Protocol.LayerTree.Layer>} payload
-   * @param {function()} callback
+   * @param {?Array<!Protocol.LayerTree.Layer>} payload
+   * @return {!Promise}
    */
-  setLayers(payload, callback) {
+  async setLayers(payload) {
     if (!payload) {
-      onBackendNodeIdsResolved.call(this);
+      this._innerSetLayers(payload);
       return;
     }
-
     var idsToResolve = new Set();
     for (var i = 0; i < payload.length; ++i) {
       var backendNodeId = payload[i].backendNodeId;
@@ -160,15 +155,8 @@
         continue;
       idsToResolve.add(backendNodeId);
     }
-    this.resolveBackendNodeIds(idsToResolve, onBackendNodeIdsResolved.bind(this));
-
-    /**
-     * @this {Layers.AgentLayerTree}
-     */
-    function onBackendNodeIdsResolved() {
-      this._innerSetLayers(payload);
-      callback();
-    }
+    await this.resolveBackendNodeIds(idsToResolve);
+    this._innerSetLayers(payload);
   }
 
   /**
diff --git a/third_party/WebKit/Source/devtools/front_end/screencast/ScreencastView.js b/third_party/WebKit/Source/devtools/front_end/screencast/ScreencastView.js
index 5223400..eb1f441 100644
--- a/third_party/WebKit/Source/devtools/front_end/screencast/ScreencastView.js
+++ b/third_party/WebKit/Source/devtools/front_end/screencast/ScreencastView.js
@@ -215,7 +215,7 @@
   /**
    * @param {!Event} event
    */
-  _handleMouseEvent(event) {
+  async _handleMouseEvent(event) {
     if (this._isGlassPaneActive()) {
       event.consume();
       return;
@@ -234,24 +234,19 @@
     }
 
     var position = this._convertIntoScreenSpace(event);
-    this._domModel.nodeForLocation(
+
+    var node = await this._domModel.nodeForLocation(
         Math.floor(position.x / this._pageScaleFactor + this._scrollOffsetX),
         Math.floor(position.y / this._pageScaleFactor + this._scrollOffsetY),
-        Common.moduleSetting('showUAShadowDOM').get(), callback.bind(this));
+        Common.moduleSetting('showUAShadowDOM').get());
 
-    /**
-     * @param {?SDK.DOMNode} node
-     * @this {Screencast.ScreencastView}
-     */
-    function callback(node) {
-      if (!node)
-        return;
-      if (event.type === 'mousemove') {
-        this.highlightDOMNode(node, this._inspectModeConfig);
-        this._domModel.overlayModel().nodeHighlightRequested(node.id);
-      } else if (event.type === 'click') {
-        Common.Revealer.reveal(node);
-      }
+    if (!node)
+      return;
+    if (event.type === 'mousemove') {
+      this.highlightDOMNode(node, this._inspectModeConfig);
+      this._domModel.overlayModel().nodeHighlightRequested(node.id);
+    } else if (event.type === 'click') {
+      Common.Revealer.reveal(node);
     }
   }
 
@@ -336,13 +331,7 @@
     }
 
     this._node = node;
-    node.boxModel(callback.bind(this));
-
-    /**
-     * @param {?Protocol.DOM.BoxModel} model
-     * @this {Screencast.ScreencastView}
-     */
-    function callback(model) {
+    node.boxModel().then(model => {
       if (!model || !this._pageScaleFactor) {
         this._repaint();
         return;
@@ -350,7 +339,7 @@
       this._model = this._scaleModel(model);
       this._config = config;
       this._repaint();
-    }
+    });
   }
 
   /**
diff --git a/third_party/WebKit/Source/devtools/front_end/sdk/CSSMatchedStyles.js b/third_party/WebKit/Source/devtools/front_end/sdk/CSSMatchedStyles.js
index 061af7ee..e92b00f 100644
--- a/third_party/WebKit/Source/devtools/front_end/sdk/CSSMatchedStyles.js
+++ b/third_party/WebKit/Source/devtools/front_end/sdk/CSSMatchedStyles.js
@@ -192,35 +192,20 @@
     /**
      * @param {!SDK.DOMNode} node
      * @param {string} selectorText
-     * @return {!Promise}
      * @this {SDK.CSSMatchedStyles}
      */
-    function querySelector(node, selectorText) {
+    async function querySelector(node, selectorText) {
       var ownerDocument = node.ownerDocument || null;
       // We assume that "matching" property does not ever change during the
       // MatchedStyleResult's lifetime.
       var map = this._matchingSelectors.get(node.id);
       if ((map && map.has(selectorText)) || !ownerDocument)
-        return Promise.resolve();
+        return;
 
-      var resolve;
-      var promise = new Promise(fulfill => resolve = fulfill);
-      this._node.domModel().querySelectorAll(
-          ownerDocument.id, selectorText, onQueryComplete.bind(this, node, selectorText, resolve));
-      return promise;
-    }
+      var matchingNodeIds = await this._node.domModel().querySelectorAll(ownerDocument.id, selectorText);
 
-    /**
-     * @param {!SDK.DOMNode} node
-     * @param {string} selectorText
-     * @param {function()} callback
-     * @param {?Array<!Protocol.DOM.NodeId>} matchingNodeIds
-     * @this {SDK.CSSMatchedStyles}
-     */
-    function onQueryComplete(node, selectorText, callback, matchingNodeIds) {
       if (matchingNodeIds)
         this._setSelectorMatches(node, selectorText, matchingNodeIds.indexOf(node.id) !== -1);
-      callback();
     }
   }
 
diff --git a/third_party/WebKit/Source/devtools/front_end/sdk/DOMDebuggerModel.js b/third_party/WebKit/Source/devtools/front_end/sdk/DOMDebuggerModel.js
index 6f7b4b85..73c50f4 100644
--- a/third_party/WebKit/Source/devtools/front_end/sdk/DOMDebuggerModel.js
+++ b/third_party/WebKit/Source/devtools/front_end/sdk/DOMDebuggerModel.js
@@ -56,7 +56,7 @@
   }
 
   retrieveDOMBreakpoints() {
-    this._domModel.requestDocument();
+    this._domModel.requestDocumentPromise();
   }
 
   /**
@@ -185,7 +185,7 @@
     var currentURL = this._currentURL();
     for (var breakpoint of this._domBreakpointsSetting.get()) {
       if (breakpoint.url === currentURL)
-        this._domModel.pushNodeByPathToFrontend(breakpoint.path, appendBreakpoint.bind(this, breakpoint));
+        this._domModel.pushNodeByPathToFrontend(breakpoint.path).then(appendBreakpoint.bind(this, breakpoint));
     }
 
     /**
diff --git a/third_party/WebKit/Source/devtools/front_end/sdk/DOMModel.js b/third_party/WebKit/Source/devtools/front_end/sdk/DOMModel.js
index 8457991..d3a4668 100644
--- a/third_party/WebKit/Source/devtools/front_end/sdk/DOMModel.js
+++ b/third_party/WebKit/Source/devtools/front_end/sdk/DOMModel.js
@@ -360,7 +360,12 @@
    * @param {function(?Protocol.Error, number)=} callback
    */
   setNodeName(name, callback) {
-    this._agent.setNodeName(this.id, name, this._domModel._markRevision(this, callback));
+    this._agent.invoke_setNodeName({nodeId: this.id, name}).then(response => {
+      if (!response[Protocol.Error])
+        this._domModel.markUndoableState();
+      if (callback)
+        callback(response[Protocol.Error] || null, response.nodeId);
+    });
   }
 
   /**
@@ -382,7 +387,12 @@
    * @param {function(?Protocol.Error)=} callback
    */
   setNodeValue(value, callback) {
-    this._agent.setNodeValue(this.id, value, this._domModel._markRevision(this, callback));
+    this._agent.invoke_setNodeValue({nodeId: this.id, value}).then(response => {
+      if (!response[Protocol.Error])
+        this._domModel.markUndoableState();
+      if (callback)
+        callback(response[Protocol.Error] || null);
+    });
   }
 
   /**
@@ -400,7 +410,12 @@
    * @param {function(?Protocol.Error)=} callback
    */
   setAttribute(name, text, callback) {
-    this._agent.setAttributesAsText(this.id, text, name, this._domModel._markRevision(this, callback));
+    this._agent.invoke_setAttributesAsText({nodeId: this.id, text, name}).then(response => {
+      if (!response[Protocol.Error])
+        this._domModel.markUndoableState();
+      if (callback)
+        callback(response[Protocol.Error] || null);
+    });
   }
 
   /**
@@ -409,7 +424,12 @@
    * @param {function(?Protocol.Error)=} callback
    */
   setAttributeValue(name, value, callback) {
-    this._agent.setAttributeValue(this.id, name, value, this._domModel._markRevision(this, callback));
+    this._agent.invoke_setAttributeValue({nodeId: this.id, name, value}).then(response => {
+      if (!response[Protocol.Error])
+        this._domModel.markUndoableState();
+      if (callback)
+        callback(response[Protocol.Error] || null);
+    });
   }
 
   /**
@@ -430,73 +450,46 @@
 
   /**
    * @param {string} name
-   * @param {function(?Protocol.Error)=} callback
+   * @return {!Promise}
    */
-  removeAttribute(name, callback) {
-    /**
-     * @param {?Protocol.Error} error
-     * @this {SDK.DOMNode}
-     */
-    function mycallback(error) {
-      if (!error) {
-        delete this._attributesMap[name];
-        for (var i = 0; i < this._attributes.length; ++i) {
-          if (this._attributes[i].name === name) {
-            this._attributes.splice(i, 1);
-            break;
-          }
-        }
-      }
-
-      this._domModel._markRevision(this, callback)(error);
-    }
-    this._agent.removeAttribute(this.id, name, mycallback.bind(this));
+  async removeAttribute(name) {
+    var response = await this._agent.invoke_removeAttribute({nodeId: this.id, name});
+    if (response[Protocol.Error])
+      return;
+    delete this._attributesMap[name];
+    var index = this._attributes.findIndex(attr => attr.name === name);
+    if (index !== -1)
+      this._attributes.splice(index, 1);
+    this._domModel.markUndoableState();
   }
 
   /**
-   * @param {function(?Array.<!SDK.DOMNode>)=} callback
+   * @param {function(?Array<!SDK.DOMNode>)} callback
    */
   getChildNodes(callback) {
     if (this._children) {
-      if (callback)
-        callback(this.children());
+      callback(this.children());
       return;
     }
-
-    /**
-     * @this {SDK.DOMNode}
-     * @param {?Protocol.Error} error
-     */
-    function mycallback(error) {
-      if (callback)
-        callback(error ? null : this.children());
-    }
-
-    this._agent.requestChildNodes(this.id, undefined, mycallback.bind(this));
+    this._agent.invoke_requestChildNodes({nodeId: this.id}).then(response => {
+      callback(response[Protocol.Error] ? null : this.children());
+    });
   }
 
   /**
    * @param {number} depth
-   * @param {function(?Array.<!SDK.DOMNode>)=} callback
+   * @return {!Promise<?Array<!SDK.DOMNode>>}
    */
-  getSubtree(depth, callback) {
-    /**
-     * @this {SDK.DOMNode}
-     * @param {?Protocol.Error} error
-     */
-    function mycallback(error) {
-      if (callback)
-        callback(error ? null : this._children);
-    }
-
-    this._agent.requestChildNodes(this.id, depth, mycallback.bind(this));
+  async getSubtree(depth) {
+    var response = await this._agent.invoke_requestChildNodes({id: this.id, depth});
+    return response[Protocol.Error] ? null : this._children;
   }
 
   /**
-   * @param {function(?Protocol.Error, string)=} callback
+   * @return {!Promise<?string>}
    */
-  getOuterHTML(callback) {
-    this._agent.getOuterHTML(this.id, callback);
+  getOuterHTML() {
+    return this._agent.getOuterHTML(this.id);
   }
 
   /**
@@ -504,27 +497,34 @@
    * @param {function(?Protocol.Error)=} callback
    */
   setOuterHTML(html, callback) {
-    this._agent.setOuterHTML(this.id, html, this._domModel._markRevision(this, callback));
+    this._agent.invoke_setOuterHTML({nodeId: this.id, outerHTML: html}).then(response => {
+      if (!response[Protocol.Error])
+        this._domModel.markUndoableState();
+      if (callback)
+        callback(response[Protocol.Error] || null);
+    });
   }
 
   /**
    * @param {function(?Protocol.Error, !Protocol.DOM.NodeId=)=} callback
    */
   removeNode(callback) {
-    this._agent.removeNode(this.id, this._domModel._markRevision(this, callback));
+    this._agent.invoke_removeNode({nodeId: this.id}).then(response => {
+      if (!response[Protocol.Error])
+        this._domModel.markUndoableState();
+      if (callback)
+        callback(response[Protocol.Error] || null);
+    });
   }
 
   /**
-   * @param {function(?string)=} callback
+   * @return {!Promise<?string>}
    */
-  copyNode(callback) {
-    function copy(error, text) {
-      if (!error)
-        InspectorFrontendHost.copyText(text);
-      if (callback)
-        callback(error ? null : text);
-    }
-    this._agent.getOuterHTML(this.id, copy);
+  async copyNode() {
+    var text = await this._agent.getOuterHTML(this.id);
+    if (text !== null)
+      InspectorFrontendHost.copyText(text);
+    return text;
   }
 
   /**
@@ -745,8 +745,15 @@
    * @param {function(?Protocol.Error, !Protocol.DOM.NodeId=)=} callback
    */
   copyTo(targetNode, anchorNode, callback) {
-    this._agent.copyTo(
-        this.id, targetNode.id, anchorNode ? anchorNode.id : undefined, this._domModel._markRevision(this, callback));
+    this._agent
+        .invoke_copyTo(
+            {nodeId: this.id, targetNodeId: targetNode.id, insertBeforeNodeId: anchorNode ? anchorNode.id : undefined})
+        .then(response => {
+          if (!response[Protocol.Error])
+            this._domModel.markUndoableState();
+          if (callback)
+            callback(response[Protocol.Error] || null, response.nodeId);
+        });
   }
 
   /**
@@ -755,8 +762,15 @@
    * @param {function(?Protocol.Error, !Protocol.DOM.NodeId=)=} callback
    */
   moveTo(targetNode, anchorNode, callback) {
-    this._agent.moveTo(
-        this.id, targetNode.id, anchorNode ? anchorNode.id : undefined, this._domModel._markRevision(this, callback));
+    this._agent
+        .invoke_moveTo(
+            {nodeId: this.id, targetNodeId: targetNode.id, insertBeforeNodeId: anchorNode ? anchorNode.id : undefined})
+        .then(response => {
+          if (!response[Protocol.Error])
+            this._domModel.markUndoableState();
+          if (callback)
+            callback(response[Protocol.Error] || null, response.nodeId);
+        });
   }
 
   /**
@@ -852,51 +866,23 @@
    * @param {function(?SDK.RemoteObject)=} callback
    */
   resolveToObject(objectGroup, callback) {
-    this._agent.resolveNode(this.id, objectGroup, mycallback.bind(this));
-
-    /**
-     * @param {?Protocol.Error} error
-     * @param {!Protocol.Runtime.RemoteObject} object
-     * @this {SDK.DOMNode}
-     */
-    function mycallback(error, object) {
-      if (!callback)
-        return;
-
-      if (error || !object)
-        callback(null);
-      else
-        callback(this._domModel._runtimeModel.createRemoteObject(object));
-    }
+    this.resolveToObjectPromise(objectGroup).then(object => callback && callback(object));
   }
 
   /**
    * @param {string=} objectGroup
-   * @return {!Promise<!SDK.RemoteObject>}
+   * @return {!Promise<?SDK.RemoteObject>}
    */
-  resolveToObjectPromise(objectGroup) {
-    return new Promise(resolveToObject.bind(this));
-    /**
-     * @param {function(?)} fulfill
-     * @param {function(*)} reject
-     * @this {SDK.DOMNode}
-     */
-    function resolveToObject(fulfill, reject) {
-      this.resolveToObject(objectGroup, mycallback);
-      function mycallback(object) {
-        if (object)
-          fulfill(object);
-        else
-          reject(null);
-      }
-    }
+  async resolveToObjectPromise(objectGroup) {
+    var object = await this._agent.resolveNode(this.id, objectGroup);
+    return object && this._domModel._runtimeModel.createRemoteObject(object);
   }
 
   /**
-   * @param {function(?Protocol.DOM.BoxModel)} callback
+   * @return {!Promise<?Protocol.DOM.BoxModel>}
    */
-  boxModel(callback) {
-    this._agent.getBoxModel(this.id, this._domModel._wrapClientCallback(callback));
+  boxModel() {
+    return this._agent.getBoxModel(this.id);
   }
 
   setAsInspectedNode() {
@@ -965,41 +951,17 @@
    * @param {function(?SDK.DOMNode)} callback
    */
   resolve(callback) {
-    if (!this._domModel) {
-      callback(null);
-      return;
-    }
-
-    this._domModel.pushNodesByBackendIdsToFrontend(new Set([this._backendNodeId]), onGotNode.bind(this));
-
-    /**
-     * @param {?Map<number, ?SDK.DOMNode>} nodeIds
-     * @this {SDK.DeferredDOMNode}
-     */
-    function onGotNode(nodeIds) {
-      callback(nodeIds && (nodeIds.get(this._backendNodeId) || null));
-    }
+    this.resolvePromise().then(callback);
   }
 
   /**
-   * @return {!Promise.<!SDK.DOMNode>}
+   * @return {!Promise<?SDK.DOMNode>}
    */
-  resolvePromise() {
-    /**
-     * @param {function(?)} fulfill
-     * @param {function(*)} reject
-     * @this {SDK.DeferredDOMNode}
-     */
-    function resolveNode(fulfill, reject) {
-      /**
-       * @param {?SDK.DOMNode} node
-       */
-      function mycallback(node) {
-        fulfill(node);
-      }
-      this.resolve(mycallback);
-    }
-    return new Promise(resolveNode.bind(this));
+  async resolvePromise() {
+    if (!this._domModel)
+      return null;
+    var nodeIds = await this._domModel.pushNodesByBackendIdsToFrontend(new Set([this._backendNodeId]));
+    return nodeIds && nodeIds.get(this._backendNodeId) || null;
   }
 
   /**
@@ -1064,8 +1026,8 @@
     this._idToDOMNode = {};
     /** @type {?SDK.DOMDocument} */
     this._document = null;
-    /** @type {!Object.<number, boolean>} */
-    this._attributeLoadNodeIds = {};
+    /** @type {!Set<number>} */
+    this._attributeLoadNodeIds = new Set();
     target.registerDOMDispatcher(new SDK.DOMDispatcher(this));
 
     this._runtimeModel = /** @type {!SDK.RuntimeModel} */ (target.model(SDK.RuntimeModel));
@@ -1123,40 +1085,33 @@
   }
 
   /**
-   * @param {function(!SDK.DOMDocument)=} callback
+   * @param {function(!SDK.DOMDocument)} callback
    */
   requestDocument(callback) {
-    if (this._document) {
-      if (callback)
-        callback(this._document);
-      return;
-    }
+    if (this._document)
+      callback(this._document);
+    else
+      this.requestDocumentPromise().then(callback);
+  }
 
-    if (this._pendingDocumentRequestCallbacks) {
-      this._pendingDocumentRequestCallbacks.push(callback);
-      return;
-    }
+  /**
+   * @return {!Promise<!SDK.DOMDocument>}
+   */
+  requestDocumentPromise() {
+    if (this._document)
+      return Promise.resolve(this._document);
+    if (this._pendingDocumentRequestPromise)
+      return this._pendingDocumentRequestPromise;
 
-    this._pendingDocumentRequestCallbacks = [callback];
-
-    /**
-     * @this {SDK.DOMModel}
-     * @param {?Protocol.Error} error
-     * @param {!Protocol.DOM.Node} root
-     */
-    function onDocumentAvailable(error, root) {
-      if (!error)
+    this._pendingDocumentRequestPromise = this._agent.getDocument().then(root => {
+      if (root)
         this._setDocument(root);
-
-      for (var i = 0; i < this._pendingDocumentRequestCallbacks.length; ++i) {
-        var callback = this._pendingDocumentRequestCallbacks[i];
-        if (callback)
-          callback(this._document);
-      }
-      delete this._pendingDocumentRequestCallbacks;
-    }
-
-    this._agent.getDocument(undefined, undefined, onDocumentAvailable.bind(this));
+      delete this._pendingDocumentRequestPromise;
+      if (!this._document)
+        console.error('No document');
+      return this._document;
+    });
+    return this._pendingDocumentRequestPromise;
   }
 
   /**
@@ -1168,52 +1123,39 @@
 
   /**
    * @param {!Protocol.Runtime.RemoteObjectId} objectId
-   * @param {function(?SDK.DOMNode)=} callback
+   * @return {!Promise<?SDK.DOMNode>}
    */
-  pushNodeToFrontend(objectId, callback) {
-    /**
-     * @param {?Protocol.DOM.NodeId} nodeId
-     * @this {!SDK.DOMModel}
-     */
-    function mycallback(nodeId) {
-      callback(nodeId ? this.nodeForId(nodeId) : null);
-    }
-    this._dispatchWhenDocumentAvailable(this._agent.requestNode.bind(this._agent, objectId), mycallback.bind(this));
+  async pushNodeToFrontend(objectId) {
+    await this.requestDocumentPromise();
+    var nodeId = await this._agent.requestNode(objectId);
+    return nodeId ? this.nodeForId(nodeId) : null;
   }
 
   /**
    * @param {string} path
-   * @param {function(?number)} callback
+   * @return {!Promise<?Protocol.DOM.NodeId>}
    */
-  pushNodeByPathToFrontend(path, callback) {
-    this._dispatchWhenDocumentAvailable(this._agent.pushNodeByPathToFrontend.bind(this._agent, path), callback);
+  pushNodeByPathToFrontend(path) {
+    return this.requestDocumentPromise().then(() => this._agent.pushNodeByPathToFrontend(path));
   }
 
   /**
    * @param {!Set<number>} backendNodeIds
-   * @param {function(?Map<number, ?SDK.DOMNode>)} callback
+   * @return {!Promise<?Map<number, ?SDK.DOMNode>>}
    */
-  pushNodesByBackendIdsToFrontend(backendNodeIds, callback) {
+  async pushNodesByBackendIdsToFrontend(backendNodeIds) {
+    await this.requestDocumentPromise();
     var backendNodeIdsArray = backendNodeIds.valuesArray();
-    /**
-     * @param {?Array<!Protocol.DOM.NodeId>} nodeIds
-     * @this {!SDK.DOMModel}
-     */
-    function mycallback(nodeIds) {
-      if (!nodeIds) {
-        callback(null);
-        return;
-      }
-      /** @type {!Map<number, ?SDK.DOMNode>} */
-      var map = new Map();
-      for (var i = 0; i < nodeIds.length; ++i) {
-        if (nodeIds[i])
-          map.set(backendNodeIdsArray[i], this.nodeForId(nodeIds[i]));
-      }
-      callback(map);
+    var nodeIds = await this._agent.pushNodesByBackendIdsToFrontend(backendNodeIdsArray);
+    if (!nodeIds)
+      return null;
+    /** @type {!Map<number, ?SDK.DOMNode>} */
+    var map = new Map();
+    for (var i = 0; i < nodeIds.length; ++i) {
+      if (nodeIds[i])
+        map.set(backendNodeIdsArray[i], this.nodeForId(nodeIds[i]));
     }
-    this._dispatchWhenDocumentAvailable(
-        this._agent.pushNodesByBackendIdsToFrontend.bind(this._agent, backendNodeIdsArray), mycallback.bind(this));
+    return map;
   }
 
   /**
@@ -1235,28 +1177,6 @@
   }
 
   /**
-   * @param {function(function(?Protocol.Error, !T))} func
-   * @param {function(?T)} callback
-   * @template T
-   */
-  _dispatchWhenDocumentAvailable(func, callback) {
-    var callbackWrapper = this._wrapClientCallback(callback);
-
-    /**
-     * @this {SDK.DOMModel}
-     */
-    function onDocumentAvailable() {
-      if (this._document) {
-        func(callbackWrapper);
-      } else {
-        if (callbackWrapper)
-          callbackWrapper('No document');
-      }
-    }
-    this.requestDocument(onDocumentAvailable.bind(this));
-  }
-
-  /**
    * @param {!Protocol.DOM.NodeId} nodeId
    * @param {string} name
    * @param {string} value
@@ -1285,44 +1205,32 @@
   }
 
   /**
-   * @param {!Array.<!Protocol.DOM.NodeId>} nodeIds
+   * @param {!Array<!Protocol.DOM.NodeId>} nodeIds
    */
   _inlineStyleInvalidated(nodeIds) {
-    for (var i = 0; i < nodeIds.length; ++i)
-      this._attributeLoadNodeIds[nodeIds[i]] = true;
-    if ('_loadNodeAttributesTimeout' in this)
-      return;
-    this._loadNodeAttributesTimeout = setTimeout(this._loadNodeAttributes.bind(this), 20);
+    this._attributeLoadNodeIds.addAll(nodeIds);
+    if (!this._loadNodeAttributesTimeout)
+      this._loadNodeAttributesTimeout = setTimeout(this._loadNodeAttributes.bind(this), 20);
   }
 
   _loadNodeAttributes() {
-    /**
-     * @this {SDK.DOMModel}
-     * @param {!Protocol.DOM.NodeId} nodeId
-     * @param {?Protocol.Error} error
-     * @param {!Array.<string>} attributes
-     */
-    function callback(nodeId, error, attributes) {
-      if (error) {
-        // We are calling _loadNodeAttributes asynchronously, it is ok if node is not found.
-        return;
-      }
-      var node = this._idToDOMNode[nodeId];
-      if (node) {
+    delete this._loadNodeAttributesTimeout;
+    for (let nodeId of this._attributeLoadNodeIds) {
+      this._agent.getAttributes(nodeId).then(attributes => {
+        if (!attributes) {
+          // We are calling _loadNodeAttributes asynchronously, it is ok if node is not found.
+          return;
+        }
+        var node = this._idToDOMNode[nodeId];
+        if (!node)
+          return;
         if (node._setAttributesPayload(attributes)) {
           this.dispatchEventToListeners(SDK.DOMModel.Events.AttrModified, {node: node, name: 'style'});
           this._scheduleMutationEvent(node);
         }
-      }
+      });
     }
-
-    delete this._loadNodeAttributesTimeout;
-
-    for (var nodeId in this._attributeLoadNodeIds) {
-      var nodeIdAsNumber = parseInt(nodeId, 10);
-      this._agent.getAttributes(nodeIdAsNumber, callback.bind(this, nodeIdAsNumber));
-    }
-    this._attributeLoadNodeIds = {};
+    this._attributeLoadNodeIds.clear();
   }
 
   /**
@@ -1525,82 +1433,37 @@
    */
   performSearch(query, includeUserAgentShadowDOM, searchCallback) {
     SDK.DOMModel.cancelSearch();
-
-    /**
-     * @param {?Protocol.Error} error
-     * @param {string} searchId
-     * @param {number} resultsCount
-     * @this {SDK.DOMModel}
-     */
-    function callback(error, searchId, resultsCount) {
-      this._searchId = searchId;
-      searchCallback(resultsCount);
-    }
-    this._agent.performSearch(query, includeUserAgentShadowDOM, callback.bind(this));
+    this.performSearchPromise(query, includeUserAgentShadowDOM).then(searchCallback);
   }
 
   /**
    * @param {string} query
    * @param {boolean} includeUserAgentShadowDOM
-   * @return {!Promise.<number>}
+   * @return {!Promise<number>}
    */
-  performSearchPromise(query, includeUserAgentShadowDOM) {
-    return new Promise(performSearch.bind(this));
-
-    /**
-     * @param {function(number)} resolve
-     * @this {SDK.DOMModel}
-     */
-    function performSearch(resolve) {
-      this._agent.performSearch(query, includeUserAgentShadowDOM, callback.bind(this));
-
-      /**
-       * @param {?Protocol.Error} error
-       * @param {string} searchId
-       * @param {number} resultsCount
-       * @this {SDK.DOMModel}
-       */
-      function callback(error, searchId, resultsCount) {
-        if (!error)
-          this._searchId = searchId;
-        resolve(error ? 0 : resultsCount);
-      }
-    }
+  async performSearchPromise(query, includeUserAgentShadowDOM) {
+    var response = await this._agent.invoke_performSearch({query, includeUserAgentShadowDOM});
+    if (!response[Protocol.Error])
+      this._searchId = response.searchId;
+    return response[Protocol.Error] ? 0 : response.resultCount;
   }
 
   /**
    * @param {number} index
-   * @param {?function(?SDK.DOMNode)} callback
+   * @return {!Promise<?SDK.DOMNode>}
    */
-  searchResult(index, callback) {
-    if (this._searchId)
-      this._agent.getSearchResults(this._searchId, index, index + 1, searchResultsCallback.bind(this));
-    else
-      callback(null);
-
-    /**
-     * @param {?Protocol.Error} error
-     * @param {!Array.<number>} nodeIds
-     * @this {SDK.DOMModel}
-     */
-    function searchResultsCallback(error, nodeIds) {
-      if (error) {
-        console.error(error);
-        callback(null);
-        return;
-      }
-      if (nodeIds.length !== 1)
-        return;
-
-      callback(this.nodeForId(nodeIds[0]));
-    }
+  async searchResult(index) {
+    if (!this._searchId)
+      return null;
+    var nodeIds = await this._agent.getSearchResults(this._searchId, index, index + 1);
+    return nodeIds && nodeIds.length === 1 ? this.nodeForId(nodeIds[0]) : null;
   }
 
   _cancelSearch() {
-    if (this._searchId) {
-      this._agent.discardSearchResults(this._searchId);
-      delete this._searchId;
-    }
+    if (!this._searchId)
+      return;
+    this._agent.discardSearchResults(this._searchId);
+    delete this._searchId;
   }
 
   /**
@@ -1608,65 +1471,25 @@
    * @return {!Promise<!Array<string>>}
    */
   classNamesPromise(nodeId) {
-    return new Promise(promiseBody.bind(this));
-
-    /**
-     * @param {function(!Array<string>)} fulfill
-     * @this {SDK.DOMModel}
-     */
-    function promiseBody(fulfill) {
-      this._agent.collectClassNamesFromSubtree(nodeId, classNamesCallback);
-
-      /**
-       * @param {?string} error
-       * @param {?Array<string>} classNames
-       */
-      function classNamesCallback(error, classNames) {
-        if (!error && classNames)
-          fulfill(classNames);
-        else
-          fulfill([]);
-      }
-    }
+    return this._agent.collectClassNamesFromSubtree(nodeId).then(classNames => classNames || []);
   }
 
   /**
    * @param {!Protocol.DOM.NodeId} nodeId
    * @param {string} selectors
-   * @param {function(?Protocol.DOM.NodeId)} callback
+   * @return {!Promise<?Protocol.DOM.NodeId>}
    */
-  querySelector(nodeId, selectors, callback) {
-    this._agent.querySelector(nodeId, selectors, this._wrapClientCallback(callback));
+  querySelector(nodeId, selectors) {
+    return this._agent.querySelector(nodeId, selectors);
   }
 
   /**
    * @param {!Protocol.DOM.NodeId} nodeId
    * @param {string} selectors
-   * @param {function(?Array<!Protocol.DOM.NodeId>)} callback
+   * @return {!Promise<?Array<!Protocol.DOM.NodeId>>}
    */
-  querySelectorAll(nodeId, selectors, callback) {
-    this._agent.querySelectorAll(nodeId, selectors, this._wrapClientCallback(callback));
-  }
-
-  /**
-   * @param {!SDK.DOMNode} node
-   * @param {function(?Protocol.Error, ...)=} callback
-   * @return {function(...)}
-   * @template T
-   */
-  _markRevision(node, callback) {
-    /**
-     * @param {?Protocol.Error} error
-     * @this {SDK.DOMModel}
-     */
-    function wrapperFunction(error) {
-      if (!error)
-        this.markUndoableState();
-
-      if (callback)
-        callback.apply(this, arguments);
-    }
-    return wrapperFunction.bind(this);
+  querySelectorAll(nodeId, selectors) {
+    return this._agent.querySelectorAll(nodeId, selectors);
   }
 
   markUndoableState() {
@@ -1674,40 +1497,28 @@
   }
 
   /**
-   * @param {function(?Protocol.Error)=} callback
+   * @return {!Promise}
    */
-  undo(callback) {
-    this._agent.undo(callback);
+  undo() {
+    return this._agent.undo();
   }
 
   /**
-   * @param {function(?Protocol.Error)=} callback
+   * @return {!Promise}
    */
-  redo(callback) {
-    this._agent.redo(callback);
+  redo() {
+    return this._agent.redo();
   }
 
   /**
    * @param {number} x
    * @param {number} y
    * @param {boolean} includeUserAgentShadowDOM
-   * @param {function(?SDK.DOMNode)} callback
+   * @return {!Promise<?SDK.DOMNode>}
    */
-  nodeForLocation(x, y, includeUserAgentShadowDOM, callback) {
-    this._agent.getNodeForLocation(x, y, includeUserAgentShadowDOM, mycallback.bind(this));
-
-    /**
-     * @param {?Protocol.Error} error
-     * @param {number} nodeId
-     * @this {SDK.DOMModel}
-     */
-    function mycallback(error, nodeId) {
-      if (error) {
-        callback(null);
-        return;
-      }
-      callback(this.nodeForId(nodeId));
-    }
+  nodeForLocation(x, y, includeUserAgentShadowDOM) {
+    return this._agent.getNodeForLocation(x, y, includeUserAgentShadowDOM)
+        .then(nodeId => nodeId ? this.nodeForId(nodeId) : null);
   }
 
   /**
@@ -1715,12 +1526,7 @@
    * @return {!Promise<?SDK.DOMNode>}
    */
   pushObjectAsNodeToFrontend(object) {
-    return new Promise(fulfill => {
-      if (object.isNode())
-        this.pushNodeToFrontend(/** @type {string} */ (object.objectId), fulfill);
-      else
-        fulfill(null);
-    });
+    return object.isNode() ? this.pushNodeToFrontend(/** @type {string} */ (object.objectId)) : Promise.resolve(null);
   }
 
   /**
@@ -1728,23 +1534,7 @@
    * @return {!Promise}
    */
   suspendModel() {
-    return new Promise(promiseBody.bind(this));
-
-    /**
-     * @param {function()} fulfill
-     * @this {SDK.DOMModel}
-     */
-    function promiseBody(fulfill) {
-      this._agent.disable(callback.bind(this));
-
-      /**
-       * @this {SDK.DOMModel}
-       */
-      function callback() {
-        this._setDocument(null);
-        fulfill();
-      }
-    }
+    return this._agent.disable().then(() => this._setDocument(null));
   }
 
   /**
@@ -1752,15 +1542,7 @@
    * @return {!Promise}
    */
   resumeModel() {
-    return new Promise(promiseBody.bind(this));
-
-    /**
-     * @param {function()} fulfill
-     * @this {SDK.DOMModel}
-     */
-    function promiseBody(fulfill) {
-      this._agent.enable(fulfill);
-    }
+    return this._agent.enable();
   }
 };
 
diff --git a/third_party/WebKit/Source/devtools/front_end/sdk/LayerTreeBase.js b/third_party/WebKit/Source/devtools/front_end/sdk/LayerTreeBase.js
index 09ae1781..39f09ea 100644
--- a/third_party/WebKit/Source/devtools/front_end/sdk/LayerTreeBase.js
+++ b/third_party/WebKit/Source/devtools/front_end/sdk/LayerTreeBase.js
@@ -215,27 +215,18 @@
 
   /**
    * @param {!Set<number>} requestedNodeIds
-   * @param {function()} callback
+   * @return {!Promise}
    */
-  resolveBackendNodeIds(requestedNodeIds, callback) {
-    if (!requestedNodeIds.size || !this._domModel) {
-      callback();
+  async resolveBackendNodeIds(requestedNodeIds) {
+    if (!requestedNodeIds.size || !this._domModel)
       return;
-    }
-    if (this._domModel)
-      this._domModel.pushNodesByBackendIdsToFrontend(requestedNodeIds, populateBackendNodeMap.bind(this));
 
-    /**
-     * @this {SDK.LayerTreeBase}
-     * @param {?Map<number, ?SDK.DOMNode>} nodesMap
-     */
-    function populateBackendNodeMap(nodesMap) {
-      if (nodesMap) {
-        for (var nodeId of nodesMap.keysArray())
-          this._backendNodeIdToNode.set(nodeId, nodesMap.get(nodeId) || null);
-      }
-      callback();
-    }
+    var nodesMap = await this._domModel.pushNodesByBackendIdsToFrontend(requestedNodeIds);
+
+    if (!nodesMap)
+      return;
+    for (var nodeId of nodesMap.keysArray())
+      this._backendNodeIdToNode.set(nodeId, nodesMap.get(nodeId) || null);
   }
 
   /**
diff --git a/third_party/WebKit/Source/devtools/front_end/sdk/OverlayModel.js b/third_party/WebKit/Source/devtools/front_end/sdk/OverlayModel.js
index de8d729..e7c5712 100644
--- a/third_party/WebKit/Source/devtools/front_end/sdk/OverlayModel.js
+++ b/third_party/WebKit/Source/devtools/front_end/sdk/OverlayModel.js
@@ -121,13 +121,11 @@
    * @param {!Protocol.Overlay.InspectMode} mode
    * @return {!Promise}
    */
-  setInspectMode(mode) {
-    var requestDocumentPromise = new Promise(fulfill => this._domModel.requestDocument(fulfill));
-    return requestDocumentPromise.then(() => {
-      this._inspectModeEnabled = mode !== Protocol.Overlay.InspectMode.None;
-      this.dispatchEventToListeners(SDK.OverlayModel.Events.InspectModeWillBeToggled, this);
-      return this._highlighter.setInspectMode(mode, this._buildHighlightConfig());
-    });
+  async setInspectMode(mode) {
+    await this._domModel.requestDocumentPromise();
+    this._inspectModeEnabled = mode !== Protocol.Overlay.InspectMode.None;
+    this.dispatchEventToListeners(SDK.OverlayModel.Events.InspectModeWillBeToggled, this);
+    this._highlighter.setInspectMode(mode, this._buildHighlightConfig());
   }
 
   /**
diff --git a/third_party/WebKit/Source/devtools/front_end/timeline/TimelineUIUtils.js b/third_party/WebKit/Source/devtools/front_end/timeline/TimelineUIUtils.js
index 3dcbdab9..51044fd 100644
--- a/third_party/WebKit/Source/devtools/front_end/timeline/TimelineUIUtils.js
+++ b/third_party/WebKit/Source/devtools/front_end/timeline/TimelineUIUtils.js
@@ -757,10 +757,8 @@
         Timeline.TimelineUIUtils._collectInvalidationNodeIds(nodeIdsToResolve, invalidationTrackingEvents);
       if (nodeIdsToResolve.size) {
         var domModel = target.model(SDK.DOMModel);
-        if (domModel) {
-          relatedNodesMap =
-              await new Promise(fulfill => domModel.pushNodesByBackendIdsToFrontend(nodeIdsToResolve, fulfill));
-        }
+        if (domModel)
+          relatedNodesMap = await domModel.pushNodesByBackendIdsToFrontend(nodeIdsToResolve);
       }
     }
 
diff --git a/third_party/WebKit/Source/devtools/front_end/timeline_model/TimelineFrameModel.js b/third_party/WebKit/Source/devtools/front_end/timeline_model/TimelineFrameModel.js
index b9b09a21..a03b32e 100644
--- a/third_party/WebKit/Source/devtools/front_end/timeline_model/TimelineFrameModel.js
+++ b/third_party/WebKit/Source/devtools/front_end/timeline_model/TimelineFrameModel.js
@@ -363,20 +363,20 @@
   /**
    * @return {!Promise<?TimelineModel.TracingLayerTree>}
    */
-  layerTreePromise() {
-    return this._snapshot.objectPromise().then(result => {
-      if (!result)
-        return null;
-      var viewport = result['device_viewport_size'];
-      var tiles = result['active_tiles'];
-      var rootLayer = result['active_tree']['root_layer'];
-      var layers = result['active_tree']['layers'];
-      var layerTree = new TimelineModel.TracingLayerTree(this._target);
-      layerTree.setViewportSize(viewport);
-      layerTree.setTiles(tiles);
-      return new Promise(
-          resolve => layerTree.setLayers(rootLayer, layers, this._paints || [], () => resolve(layerTree)));
-    });
+  async layerTreePromise() {
+    var result = await this._snapshot.objectPromise();
+    if (!result)
+      return null;
+    var viewport = result['device_viewport_size'];
+    var tiles = result['active_tiles'];
+    var rootLayer = result['active_tree']['root_layer'];
+    var layers = result['active_tree']['layers'];
+    var layerTree = new TimelineModel.TracingLayerTree(this._target);
+    layerTree.setViewportSize(viewport);
+    layerTree.setTiles(tiles);
+
+    await layerTree.setLayers(rootLayer, layers, this._paints || []);
+    return layerTree;
   }
 
   /**
diff --git a/third_party/WebKit/Source/devtools/front_end/timeline_model/TracingLayerTree.js b/third_party/WebKit/Source/devtools/front_end/timeline_model/TracingLayerTree.js
index 580a407..2dec8ed 100644
--- a/third_party/WebKit/Source/devtools/front_end/timeline_model/TracingLayerTree.js
+++ b/third_party/WebKit/Source/devtools/front_end/timeline_model/TracingLayerTree.js
@@ -44,9 +44,9 @@
    * @param {?TimelineModel.TracingLayerPayload} root
    * @param {?Array<!TimelineModel.TracingLayerPayload>} layers
    * @param {!Array<!TimelineModel.LayerPaintEvent>} paints
-   * @param {function()} callback
+   * @return {!Promise}
    */
-  setLayers(root, layers, paints, callback) {
+  async setLayers(root, layers, paints) {
     var idsToResolve = new Set();
     if (root) {
       // This is a legacy code path for compatibility, as cc is removing
@@ -56,30 +56,25 @@
       for (var i = 0; i < layers.length; ++i)
         this._extractNodeIdsToResolve(idsToResolve, {}, layers[i]);
     }
-    this.resolveBackendNodeIds(idsToResolve, onBackendNodeIdsResolved.bind(this));
 
-    /**
-     * @this {TimelineModel.TracingLayerTree}
-     */
-    function onBackendNodeIdsResolved() {
-      var oldLayersById = this._layersById;
-      this._layersById = {};
-      this.setContentRoot(null);
-      if (root) {
-        var convertedLayers = this._innerSetLayers(oldLayersById, root);
-        this.setRoot(convertedLayers);
-      } else {
-        var processedLayers = layers.map(this._innerSetLayers.bind(this, oldLayersById));
-        var contentRoot = this.contentRoot();
-        this.setRoot(contentRoot);
-        for (var i = 0; i < processedLayers.length; ++i) {
-          if (processedLayers[i].id() !== contentRoot.id())
-            contentRoot.addChild(processedLayers[i]);
-        }
+    await this.resolveBackendNodeIds(idsToResolve);
+
+    var oldLayersById = this._layersById;
+    this._layersById = {};
+    this.setContentRoot(null);
+    if (root) {
+      var convertedLayers = this._innerSetLayers(oldLayersById, root);
+      this.setRoot(convertedLayers);
+    } else {
+      var processedLayers = layers.map(this._innerSetLayers.bind(this, oldLayersById));
+      var contentRoot = this.contentRoot();
+      this.setRoot(contentRoot);
+      for (var i = 0; i < processedLayers.length; ++i) {
+        if (processedLayers[i].id() !== contentRoot.id())
+          contentRoot.addChild(processedLayers[i]);
       }
-      this._setPaints(paints);
-      callback();
     }
+    this._setPaints(paints);
   }
 
   /**
diff --git a/third_party/WebKit/Source/devtools/scripts/build/generate_protocol_externs.py b/third_party/WebKit/Source/devtools/scripts/build/generate_protocol_externs.py
index 308171f..45713fa 100755
--- a/third_party/WebKit/Source/devtools/scripts/build/generate_protocol_externs.py
+++ b/third_party/WebKit/Source/devtools/scripts/build/generate_protocol_externs.py
@@ -47,11 +47,9 @@
 ref_types = {}
 
 NON_PROMISIFIED_DOMAINS = frozenset([
-    "Animation",
     "ApplicationCache",
     "CacheStorage",
     "CSS",
-    "DOM",
     "DOMDebugger",
     "IndexedDB",
     "LayerTree",
diff --git a/third_party/WebKit/Source/modules/offscreencanvas2d/OffscreenCanvasRenderingContext2D.cpp b/third_party/WebKit/Source/modules/offscreencanvas2d/OffscreenCanvasRenderingContext2D.cpp
index 422387c..53540d8 100644
--- a/third_party/WebKit/Source/modules/offscreencanvas2d/OffscreenCanvasRenderingContext2D.cpp
+++ b/third_party/WebKit/Source/modules/offscreencanvas2d/OffscreenCanvasRenderingContext2D.cpp
@@ -33,7 +33,7 @@
       canvas->SetDisableReadingFromCanvasTrue();
     return;
   }
-
+  dirty_rect_for_commit_.setEmpty();
   WorkerSettings* worker_settings =
       ToWorkerGlobalScope(execution_context)->GetWorkerSettings();
   if (worker_settings && worker_settings->DisableReadingFromCanvas())
@@ -51,7 +51,9 @@
   UseCounter::Feature feature = UseCounter::kOffscreenCanvasCommit2D;
   UseCounter::Count(ExecutionContext::From(script_state), feature);
   bool is_web_gl_software_rendering = false;
-  return host()->Commit(TransferToStaticBitmapImage(),
+  SkIRect damage_rect(dirty_rect_for_commit_);
+  dirty_rect_for_commit_.setEmpty();
+  return host()->Commit(TransferToStaticBitmapImage(), damage_rect,
                         is_web_gl_software_rendering, script_state,
                         exception_state);
 }
@@ -187,7 +189,9 @@
   return GetImageBuffer()->BaseTransform();
 }
 
-void OffscreenCanvasRenderingContext2D::DidDraw(const SkIRect& dirty_rect) {}
+void OffscreenCanvasRenderingContext2D::DidDraw(const SkIRect& dirty_rect) {
+  dirty_rect_for_commit_.join(dirty_rect);
+}
 
 bool OffscreenCanvasRenderingContext2D::StateHasFilter() {
   return GetState().HasFilterForOffscreenCanvas(host()->Size());
diff --git a/third_party/WebKit/Source/modules/offscreencanvas2d/OffscreenCanvasRenderingContext2D.h b/third_party/WebKit/Source/modules/offscreencanvas2d/OffscreenCanvasRenderingContext2D.h
index 3c4f5ad..6d4581d 100644
--- a/third_party/WebKit/Source/modules/offscreencanvas2d/OffscreenCanvasRenderingContext2D.h
+++ b/third_party/WebKit/Source/modules/offscreencanvas2d/OffscreenCanvasRenderingContext2D.h
@@ -115,6 +115,7 @@
   CanvasColorSpace ColorSpace() const override;
   String ColorSpaceAsString() const override;
   CanvasPixelFormat PixelFormat() const override;
+  SkIRect dirty_rect_for_commit_;
 };
 
 DEFINE_TYPE_CASTS(OffscreenCanvasRenderingContext2D,
diff --git a/third_party/WebKit/Source/modules/vr/VRDisplay.cpp b/third_party/WebKit/Source/modules/vr/VRDisplay.cpp
index 450d29d6..faf2fb9 100644
--- a/third_party/WebKit/Source/modules/vr/VRDisplay.cpp
+++ b/third_party/WebKit/Source/modules/vr/VRDisplay.cpp
@@ -748,11 +748,11 @@
 }
 
 void VRDisplay::OnActivate(device::mojom::blink::VRDisplayEventReason reason,
-                           const OnActivateCallback& on_handled) {
+                           OnActivateCallback on_handled) {
   AutoReset<bool> activating(&in_display_activate_, true);
   navigator_vr_->DispatchVREvent(VRDisplayEvent::Create(
       EventTypeNames::vrdisplayactivate, true, false, this, reason));
-  on_handled.Run(!pending_present_request_ && !is_presenting_);
+  std::move(on_handled).Run(!pending_present_request_ && !is_presenting_);
 }
 
 void VRDisplay::OnDeactivate(
diff --git a/third_party/WebKit/Source/modules/vr/VRDisplay.h b/third_party/WebKit/Source/modules/vr/VRDisplay.h
index 68fe6a6..93ca5ee 100644
--- a/third_party/WebKit/Source/modules/vr/VRDisplay.h
+++ b/third_party/WebKit/Source/modules/vr/VRDisplay.h
@@ -131,7 +131,7 @@
   void OnBlur() override;
   void OnFocus() override;
   void OnActivate(device::mojom::blink::VRDisplayEventReason,
-                  const OnActivateCallback& on_handled) override;
+                  OnActivateCallback on_handled) override;
   void OnDeactivate(device::mojom::blink::VRDisplayEventReason) override;
 
   void OnVSync(device::mojom::blink::VRPosePtr,
diff --git a/third_party/WebKit/Source/modules/webgl/WebGLRenderingContextBase.cpp b/third_party/WebKit/Source/modules/webgl/WebGLRenderingContextBase.cpp
index ebfc767..ba6d6e0 100644
--- a/third_party/WebKit/Source/modules/webgl/WebGLRenderingContextBase.cpp
+++ b/third_party/WebKit/Source/modules/webgl/WebGLRenderingContextBase.cpp
@@ -747,16 +747,17 @@
     ExceptionState& exception_state) {
   UseCounter::Feature feature = UseCounter::kOffscreenCanvasCommitWebGL;
   UseCounter::Count(ExecutionContext::From(script_state), feature);
+  int width = GetDrawingBuffer()->Size().Width();
+  int height = GetDrawingBuffer()->Size().Height();
   if (!GetDrawingBuffer()) {
     bool is_web_gl_software_rendering = false;
-    return host()->Commit(nullptr, is_web_gl_software_rendering, script_state,
+    return host()->Commit(nullptr, SkIRect::MakeWH(width, height),
+                          is_web_gl_software_rendering, script_state,
                           exception_state);
   }
 
   RefPtr<StaticBitmapImage> image;
   if (CreationAttributes().preserveDrawingBuffer()) {
-    int width = GetDrawingBuffer()->Size().Width();
-    int height = GetDrawingBuffer()->Size().Height();
     SkImageInfo image_info =
         SkImageInfo::Make(width, height, kRGBA_8888_SkColorType,
                           CreationAttributes().alpha() ? kPremul_SkAlphaType
@@ -767,7 +768,7 @@
   }
 
   return host()->Commit(
-      std::move(image),
+      std::move(image), SkIRect::MakeWH(width, height),
       GetDrawingBuffer()->ContextProvider()->IsSoftwareRendering(),
       script_state, exception_state);
 }
@@ -1052,9 +1053,6 @@
   }
 
   drawing_buffer_ = std::move(buffer);
-  drawing_buffer_->AddNewMailboxCallback(
-      WTF::Bind(&WebGLRenderingContextBase::NotifyCanvasContextChanged,
-                WrapWeakPersistent(this)));
   GetDrawingBuffer()->Bind(GL_FRAMEBUFFER);
   SetupFlags();
 
@@ -1315,7 +1313,6 @@
       ConvertToBaseCallback(std::move(null_closure)));
   GetDrawingBuffer()->ContextProvider()->SetErrorMessageCallback(
       ConvertToBaseCallback(std::move(null_function)));
-  GetDrawingBuffer()->AddNewMailboxCallback(nullptr);
 
   DCHECK(GetDrawingBuffer());
   drawing_buffer_->BeginDestruction();
@@ -1358,13 +1355,6 @@
   probe::didFireWebGLErrorOrWarning(canvas(), message);
 }
 
-void WebGLRenderingContextBase::NotifyCanvasContextChanged() {
-  if (!canvas())
-    return;
-
-  canvas()->NotifyListenersCanvasChanged();
-}
-
 WebGLRenderingContextBase::HowToClear
 WebGLRenderingContextBase::ClearIfComposited(GLbitfield mask) {
   if (isContextLost())
@@ -7532,10 +7522,6 @@
   }
 
   drawing_buffer_ = std::move(buffer);
-  drawing_buffer_->AddNewMailboxCallback(
-      WTF::Bind(&WebGLRenderingContextBase::NotifyCanvasContextChanged,
-                WrapWeakPersistent(this)));
-
   GetDrawingBuffer()->Bind(GL_FRAMEBUFFER);
   lost_context_errors_.clear();
   context_lost_mode_ = kNotLostContext;
diff --git a/third_party/WebKit/Source/modules/webgl/WebGLRenderingContextBase.h b/third_party/WebKit/Source/modules/webgl/WebGLRenderingContextBase.h
index 2aec8a1..a39b881 100644
--- a/third_party/WebKit/Source/modules/webgl/WebGLRenderingContextBase.h
+++ b/third_party/WebKit/Source/modules/webgl/WebGLRenderingContextBase.h
@@ -657,8 +657,6 @@
 
   void OnErrorMessage(const char*, int32_t id);
 
-  void NotifyCanvasContextChanged();
-
   // Query if depth_stencil buffer is supported.
   bool IsDepthStencilSupported() { return is_depth_stencil_supported_; }
 
diff --git a/third_party/WebKit/Source/platform/exported/WebActiveGestureAnimation.cpp b/third_party/WebKit/Source/platform/exported/WebActiveGestureAnimation.cpp
index a1490260..aa3070dc 100644
--- a/third_party/WebKit/Source/platform/exported/WebActiveGestureAnimation.cpp
+++ b/third_party/WebKit/Source/platform/exported/WebActiveGestureAnimation.cpp
@@ -33,20 +33,12 @@
 namespace blink {
 
 std::unique_ptr<WebActiveGestureAnimation>
-WebActiveGestureAnimation::CreateAtAnimationStart(
-    std::unique_ptr<WebGestureCurve> curve,
-    WebGestureCurveTarget* target) {
-  return WTF::WrapUnique(
-      new WebActiveGestureAnimation(std::move(curve), target, 0, true));
-}
-
-std::unique_ptr<WebActiveGestureAnimation>
 WebActiveGestureAnimation::CreateWithTimeOffset(
     std::unique_ptr<WebGestureCurve> curve,
     WebGestureCurveTarget* target,
     double start_time) {
-  return WTF::WrapUnique(new WebActiveGestureAnimation(std::move(curve), target,
-                                                       start_time, false));
+  return WTF::WrapUnique(
+      new WebActiveGestureAnimation(std::move(curve), target, start_time));
 }
 
 WebActiveGestureAnimation::~WebActiveGestureAnimation() {}
@@ -54,18 +46,10 @@
 WebActiveGestureAnimation::WebActiveGestureAnimation(
     std::unique_ptr<WebGestureCurve> curve,
     WebGestureCurveTarget* target,
-    double start_time,
-    bool waiting_for_first_tick)
-    : start_time_(start_time),
-      waiting_for_first_tick_(waiting_for_first_tick),
-      curve_(std::move(curve)),
-      target_(target) {}
+    double start_time)
+    : start_time_(start_time), curve_(std::move(curve)), target_(target) {}
 
 bool WebActiveGestureAnimation::Animate(double time) {
-  if (waiting_for_first_tick_) {
-    start_time_ = time;
-    waiting_for_first_tick_ = false;
-  }
   // All WebGestureCurves assume zero-based time, so we subtract
   // the animation start time before passing to the curve.
   return curve_->Apply(time - start_time_, target_);
diff --git a/third_party/WebKit/Source/platform/exported/WebActiveGestureAnimation.h b/third_party/WebKit/Source/platform/exported/WebActiveGestureAnimation.h
index 45b29d4f..e1adc588 100644
--- a/third_party/WebKit/Source/platform/exported/WebActiveGestureAnimation.h
+++ b/third_party/WebKit/Source/platform/exported/WebActiveGestureAnimation.h
@@ -46,9 +46,6 @@
   WTF_MAKE_NONCOPYABLE(WebActiveGestureAnimation);
 
  public:
-  static std::unique_ptr<WebActiveGestureAnimation> CreateAtAnimationStart(
-      std::unique_ptr<WebGestureCurve>,
-      WebGestureCurveTarget*);
   static std::unique_ptr<WebActiveGestureAnimation> CreateWithTimeOffset(
       std::unique_ptr<WebGestureCurve>,
       WebGestureCurveTarget*,
@@ -61,11 +58,9 @@
   // Assumes a valid WebGestureCurveTarget that outlives the animation.
   WebActiveGestureAnimation(std::unique_ptr<WebGestureCurve>,
                             WebGestureCurveTarget*,
-                            double start_time,
-                            bool waiting_for_first_tick);
+                            double start_time);
 
   double start_time_;
-  bool waiting_for_first_tick_;
   std::unique_ptr<WebGestureCurve> curve_;
   WebGestureCurveTarget* target_;
 };
diff --git a/third_party/WebKit/Source/platform/graphics/GraphicsLayer.cpp b/third_party/WebKit/Source/platform/graphics/GraphicsLayer.cpp
index 7e4c8ac..1f1931d8 100644
--- a/third_party/WebKit/Source/platform/graphics/GraphicsLayer.cpp
+++ b/third_party/WebKit/Source/platform/graphics/GraphicsLayer.cpp
@@ -388,14 +388,14 @@
   if (!g_registered_layer_set)
     g_registered_layer_set = new HashSet<int>;
   if (g_registered_layer_set->Contains(layer->Id()))
-    CRASH();
+    IMMEDIATE_CRASH();
   g_registered_layer_set->insert(layer->Id());
 }
 
 void GraphicsLayer::UnregisterContentsLayer(WebLayer* layer) {
   DCHECK(g_registered_layer_set);
   if (!g_registered_layer_set->Contains(layer->Id()))
-    CRASH();
+    IMMEDIATE_CRASH();
   g_registered_layer_set->erase(layer->Id());
 }
 
@@ -404,7 +404,7 @@
   if (layer) {
     DCHECK(g_registered_layer_set);
     if (!g_registered_layer_set->Contains(layer->Id()))
-      CRASH();
+      IMMEDIATE_CRASH();
     if (contents_layer_id_ != layer->Id()) {
       SetupContentsLayer(layer);
       children_changed = true;
diff --git a/third_party/WebKit/Source/platform/graphics/OffscreenCanvasFrameDispatcher.h b/third_party/WebKit/Source/platform/graphics/OffscreenCanvasFrameDispatcher.h
index 7bfd33e..726af80 100644
--- a/third_party/WebKit/Source/platform/graphics/OffscreenCanvasFrameDispatcher.h
+++ b/third_party/WebKit/Source/platform/graphics/OffscreenCanvasFrameDispatcher.h
@@ -7,6 +7,7 @@
 
 #include "platform/PlatformExport.h"
 #include "platform/WebTaskRunner.h"
+#include "platform/geometry/IntRect.h"
 #include "platform/wtf/RefPtr.h"
 #include "platform/wtf/WeakPtr.h"
 
@@ -24,6 +25,7 @@
   virtual ~OffscreenCanvasFrameDispatcher() {}
   virtual void DispatchFrame(RefPtr<StaticBitmapImage>,
                              double commit_start_time,
+                             const SkIRect& damage_rect,
                              bool is_web_gl_software_rendering) = 0;
   virtual void SetNeedsBeginFrame(bool) = 0;
   virtual void ReclaimResource(unsigned resource_id) = 0;
diff --git a/third_party/WebKit/Source/platform/graphics/OffscreenCanvasFrameDispatcherImpl.cpp b/third_party/WebKit/Source/platform/graphics/OffscreenCanvasFrameDispatcherImpl.cpp
index 554d3bd9..420579c 100644
--- a/third_party/WebKit/Source/platform/graphics/OffscreenCanvasFrameDispatcherImpl.cpp
+++ b/third_party/WebKit/Source/platform/graphics/OffscreenCanvasFrameDispatcherImpl.cpp
@@ -219,6 +219,7 @@
 void OffscreenCanvasFrameDispatcherImpl::DispatchFrame(
     RefPtr<StaticBitmapImage> image,
     double commit_start_time,
+    const SkIRect& damage_rect,
     bool is_web_gl_software_rendering /* This flag is true when WebGL's commit
                                          is called on SwiftShader. */
     ) {
@@ -244,7 +245,10 @@
   const gfx::Rect bounds(width_, height_);
   const int kRenderPassId = 1;
   std::unique_ptr<cc::RenderPass> pass = cc::RenderPass::Create();
-  pass->SetNew(kRenderPassId, bounds, bounds, gfx::Transform());
+  pass->SetNew(kRenderPassId, bounds,
+               gfx::Rect(damage_rect.x(), damage_rect.y(), damage_rect.width(),
+                         damage_rect.height()),
+               gfx::Transform());
 
   cc::SharedQuadState* sqs = pass->CreateAndAppendSharedQuadState();
   sqs->SetAll(gfx::Transform(), bounds, bounds, bounds, false, 1.f,
diff --git a/third_party/WebKit/Source/platform/graphics/OffscreenCanvasFrameDispatcherImpl.h b/third_party/WebKit/Source/platform/graphics/OffscreenCanvasFrameDispatcherImpl.h
index 85f9400..88f205af 100644
--- a/third_party/WebKit/Source/platform/graphics/OffscreenCanvasFrameDispatcherImpl.h
+++ b/third_party/WebKit/Source/platform/graphics/OffscreenCanvasFrameDispatcherImpl.h
@@ -35,6 +35,7 @@
   void SetNeedsBeginFrame(bool) final;
   void DispatchFrame(RefPtr<StaticBitmapImage>,
                      double commit_start_time,
+                     const SkIRect& damage_rect,
                      bool is_web_gl_software_rendering = false) final;
   void ReclaimResource(unsigned resource_id) final;
   void Reshape(int width, int height) final;
diff --git a/third_party/WebKit/Source/platform/graphics/gpu/DrawingBuffer.cpp b/third_party/WebKit/Source/platform/graphics/gpu/DrawingBuffer.cpp
index 070cb6d..acc92e2 100644
--- a/third_party/WebKit/Source/platform/graphics/gpu/DrawingBuffer.cpp
+++ b/third_party/WebKit/Source/platform/graphics/gpu/DrawingBuffer.cpp
@@ -282,9 +282,6 @@
 
   TRACE_EVENT0("blink,rail", "DrawingBuffer::prepareMailbox");
 
-  if (new_mailbox_callback_)
-    (*new_mailbox_callback_)();
-
   // Resolve the multisampled buffer into m_backColorBuffer texture.
   ResolveIfNeeded();
 
diff --git a/third_party/WebKit/Source/platform/graphics/gpu/DrawingBuffer.h b/third_party/WebKit/Source/platform/graphics/gpu/DrawingBuffer.h
index b99c5e7..0bf5aa4 100644
--- a/third_party/WebKit/Source/platform/graphics/gpu/DrawingBuffer.h
+++ b/third_party/WebKit/Source/platform/graphics/gpu/DrawingBuffer.h
@@ -228,10 +228,6 @@
   // Restore all state that may have been dirtied by any call.
   void RestoreAllState();
 
-  void AddNewMailboxCallback(std::unique_ptr<WTF::Closure> closure) {
-    new_mailbox_callback_ = std::move(closure);
-  }
-
   // This class helps implement correct semantics for BlitFramebuffer
   // when the DrawingBuffer is using a CHROMIUM image for its backing
   // store and RGB emulation is in use (basically, macOS only).
@@ -475,8 +471,6 @@
   bool has_implicit_stencil_buffer_ = false;
   bool storage_texture_supported_ = false;
 
-  std::unique_ptr<WTF::Closure> new_mailbox_callback_;
-
   // The current state restorer, which is used to track state dirtying. It is an
   // error to dirty state shared with WebGL while there is no existing state
   // restorer.
diff --git a/third_party/WebKit/Source/platform/graphics/paint/PaintArtifact.cpp b/third_party/WebKit/Source/platform/graphics/paint/PaintArtifact.cpp
index 96d45d91..c53a383 100644
--- a/third_party/WebKit/Source/platform/graphics/paint/PaintArtifact.cpp
+++ b/third_party/WebKit/Source/platform/graphics/paint/PaintArtifact.cpp
@@ -46,38 +46,35 @@
 
 }  // namespace
 
-PaintArtifact::PaintArtifact()
-    : display_item_list_(0), is_suitable_for_gpu_rasterization_(true) {}
+PaintArtifact::PaintArtifact() : display_item_list_(0) {}
 
 PaintArtifact::PaintArtifact(DisplayItemList display_items,
                              Vector<PaintChunk> paint_chunks,
-                             bool is_suitable_for_gpu_rasterization_arg)
+                             int num_slow_paths)
     : display_item_list_(std::move(display_items)),
       paint_chunks_(std::move(paint_chunks)),
-      is_suitable_for_gpu_rasterization_(
-          is_suitable_for_gpu_rasterization_arg) {
+      num_slow_paths_(num_slow_paths) {
   ComputeChunkBoundsAndOpaqueness(display_item_list_, paint_chunks_);
 }
 
 PaintArtifact::PaintArtifact(PaintArtifact&& source)
     : display_item_list_(std::move(source.display_item_list_)),
       paint_chunks_(std::move(source.paint_chunks_)),
-      is_suitable_for_gpu_rasterization_(
-          source.is_suitable_for_gpu_rasterization_) {}
+      num_slow_paths_(source.num_slow_paths_) {}
 
 PaintArtifact::~PaintArtifact() {}
 
 PaintArtifact& PaintArtifact::operator=(PaintArtifact&& source) {
   display_item_list_ = std::move(source.display_item_list_);
   paint_chunks_ = std::move(source.paint_chunks_);
-  is_suitable_for_gpu_rasterization_ =
-      source.is_suitable_for_gpu_rasterization_;
+  num_slow_paths_ = source.num_slow_paths_;
   return *this;
 }
 
 void PaintArtifact::Reset() {
   display_item_list_.Clear();
   paint_chunks_.clear();
+  num_slow_paths_ = 0;
 }
 
 size_t PaintArtifact::ApproximateUnsharedMemoryUsage() const {
@@ -121,7 +118,7 @@
   TRACE_EVENT0("blink,benchmark", "PaintArtifact::appendToWebDisplayItemList");
   for (const DisplayItem& item : display_item_list_)
     item.AppendToWebDisplayItemList(visual_rect_offset, list);
-  list->SetIsSuitableForGpuRasterization(IsSuitableForGpuRasterization());
+  list->SetNumSlowPaths(num_slow_paths_);
 }
 
 }  // namespace blink
diff --git a/third_party/WebKit/Source/platform/graphics/paint/PaintArtifact.h b/third_party/WebKit/Source/platform/graphics/paint/PaintArtifact.h
index 0e55295..5dc48e4 100644
--- a/third_party/WebKit/Source/platform/graphics/paint/PaintArtifact.h
+++ b/third_party/WebKit/Source/platform/graphics/paint/PaintArtifact.h
@@ -36,9 +36,7 @@
 
  public:
   PaintArtifact();
-  PaintArtifact(DisplayItemList,
-                Vector<PaintChunk>,
-                bool is_suitable_for_gpu_rasterization);
+  PaintArtifact(DisplayItemList, Vector<PaintChunk>, int num_slow_paths);
   PaintArtifact(PaintArtifact&&);
   ~PaintArtifact();
 
@@ -59,9 +57,7 @@
     return FindChunkInVectorByDisplayItemIndex(paint_chunks_, index);
   }
 
-  bool IsSuitableForGpuRasterization() const {
-    return is_suitable_for_gpu_rasterization_;
-  }
+  int NumSlowPaths() const { return num_slow_paths_; }
 
   // Resets to an empty paint artifact.
   void Reset();
@@ -90,7 +86,7 @@
  private:
   DisplayItemList display_item_list_;
   Vector<PaintChunk> paint_chunks_;
-  bool is_suitable_for_gpu_rasterization_;
+  int num_slow_paths_ = 0;
 };
 
 }  // namespace blink
diff --git a/third_party/WebKit/Source/platform/graphics/paint/PaintController.cpp b/third_party/WebKit/Source/platform/graphics/paint/PaintController.cpp
index 59f90886..f05ac20e 100644
--- a/third_party/WebKit/Source/platform/graphics/paint/PaintController.cpp
+++ b/third_party/WebKit/Source/platform/graphics/paint/PaintController.cpp
@@ -16,8 +16,6 @@
 #include <stdio.h>
 #endif
 
-static constexpr int kMaxNumberOfSlowPathsBeforeVeto = 5;
-
 namespace blink {
 
 void PaintController::SetTracksRasterInvalidations(bool value) {
@@ -591,9 +589,7 @@
 
   Vector<const DisplayItemClient*> skipped_cache_clients;
   for (const auto& item : new_display_item_list_) {
-    // No reason to continue the analysis once we have a veto.
-    if (num_slow_paths <= kMaxNumberOfSlowPathsBeforeVeto)
-      num_slow_paths += item.NumberOfSlowPaths();
+    num_slow_paths += item.NumberOfSlowPaths();
 
     if (item.IsCacheable()) {
       item.Client().SetDisplayItemsCached(current_cache_generation_);
@@ -615,9 +611,9 @@
     for (const auto& chunk : current_paint_artifact_.PaintChunks())
       raster_invalidation_tracking_info_->map.Remove(&chunk);
   }
-  current_paint_artifact_ = PaintArtifact(
-      std::move(new_display_item_list_), new_paint_chunks_.ReleasePaintChunks(),
-      num_slow_paths <= kMaxNumberOfSlowPathsBeforeVeto);
+  current_paint_artifact_ =
+      PaintArtifact(std::move(new_display_item_list_),
+                    new_paint_chunks_.ReleasePaintChunks(), num_slow_paths);
 
   ResetCurrentListIndices();
   out_of_order_item_indices_.clear();
diff --git a/third_party/WebKit/Source/platform/graphics/paint/PaintControllerTest.cpp b/third_party/WebKit/Source/platform/graphics/paint/PaintControllerTest.cpp
index 1cff8d5..19ac3e00c 100644
--- a/third_party/WebKit/Source/platform/graphics/paint/PaintControllerTest.cpp
+++ b/third_party/WebKit/Source/platform/graphics/paint/PaintControllerTest.cpp
@@ -1908,8 +1908,7 @@
   GraphicsContext context(GetPaintController());
   DrawPath(context, client, kBackgroundDrawingType, 1);
   GetPaintController().CommitNewDisplayItems();
-  EXPECT_TRUE(
-      GetPaintController().GetPaintArtifact().IsSuitableForGpuRasterization());
+  EXPECT_EQ(1, GetPaintController().GetPaintArtifact().NumSlowPaths());
 }
 
 TEST_F(PaintControllerTestBase,
@@ -1919,8 +1918,7 @@
 
   DrawPath(context, client, kBackgroundDrawingType, 50);
   GetPaintController().CommitNewDisplayItems();
-  EXPECT_FALSE(
-      GetPaintController().GetPaintArtifact().IsSuitableForGpuRasterization());
+  EXPECT_EQ(50, GetPaintController().GetPaintArtifact().NumSlowPaths());
 }
 
 TEST_F(PaintControllerTestBase,
@@ -1934,8 +1932,7 @@
 
   GetPaintController().EndSkippingCache();
   GetPaintController().CommitNewDisplayItems();
-  EXPECT_FALSE(
-      GetPaintController().GetPaintArtifact().IsSuitableForGpuRasterization());
+  EXPECT_EQ(50 * 50, GetPaintController().GetPaintArtifact().NumSlowPaths());
 }
 
 TEST_F(PaintControllerTestBase,
@@ -1946,9 +1943,7 @@
     GraphicsContext context(GetPaintController());
     DrawPath(context, client, kBackgroundDrawingType, 50);
     GetPaintController().CommitNewDisplayItems();
-    EXPECT_FALSE(GetPaintController()
-                     .GetPaintArtifact()
-                     .IsSuitableForGpuRasterization());
+    EXPECT_EQ(50, GetPaintController().GetPaintArtifact().NumSlowPaths());
   }
 
   client.SetDisplayItemsUncached();
@@ -1957,9 +1952,7 @@
     GraphicsContext context(GetPaintController());
     DrawPath(context, client, kBackgroundDrawingType, 50);
     GetPaintController().CommitNewDisplayItems();
-    EXPECT_FALSE(GetPaintController()
-                     .GetPaintArtifact()
-                     .IsSuitableForGpuRasterization());
+    EXPECT_EQ(50, GetPaintController().GetPaintArtifact().NumSlowPaths());
   }
 }
 
@@ -1971,18 +1964,14 @@
     GraphicsContext context(GetPaintController());
     DrawPath(context, client, kBackgroundDrawingType, 50);
     GetPaintController().CommitNewDisplayItems();
-    EXPECT_FALSE(GetPaintController()
-                     .GetPaintArtifact()
-                     .IsSuitableForGpuRasterization());
+    EXPECT_EQ(50, GetPaintController().GetPaintArtifact().NumSlowPaths());
   }
 
   {
     GraphicsContext context(GetPaintController());
     DrawPath(context, client, kBackgroundDrawingType, 50);
     GetPaintController().CommitNewDisplayItems();
-    EXPECT_FALSE(GetPaintController()
-                     .GetPaintArtifact()
-                     .IsSuitableForGpuRasterization());
+    EXPECT_EQ(50, GetPaintController().GetPaintArtifact().NumSlowPaths());
   }
 }
 
@@ -1998,14 +1987,12 @@
     DrawPath(context, client, kBackgroundDrawingType, 50);
   }
   GetPaintController().CommitNewDisplayItems();
-  EXPECT_FALSE(
-      GetPaintController().GetPaintArtifact().IsSuitableForGpuRasterization());
+  EXPECT_EQ(50, GetPaintController().GetPaintArtifact().NumSlowPaths());
 
   EXPECT_TRUE(
       SubsequenceRecorder::UseCachedSubsequenceIfPossible(context, container));
   GetPaintController().CommitNewDisplayItems();
-  EXPECT_FALSE(
-      GetPaintController().GetPaintArtifact().IsSuitableForGpuRasterization());
+  EXPECT_EQ(50, GetPaintController().GetPaintArtifact().NumSlowPaths());
 
 #if CHECK_DISPLAY_ITEM_CLIENT_ALIVENESS
   DisplayItemClient::EndShouldKeepAliveAllClients();
@@ -2035,9 +2022,7 @@
     for (int j = 0; j < 50; ++j)
       GetPaintController().CreateAndAppend<EndClipPathDisplayItem>(client);
     GetPaintController().CommitNewDisplayItems();
-    EXPECT_FALSE(GetPaintController()
-                     .GetPaintArtifact()
-                     .IsSuitableForGpuRasterization());
+    EXPECT_EQ(50 * i, GetPaintController().GetPaintArtifact().NumSlowPaths());
   }
 }
 
diff --git a/third_party/WebKit/Source/platform/mac/BlockExceptions.mm b/third_party/WebKit/Source/platform/mac/BlockExceptions.mm
index ac7f8f2..6ae8c89 100644
--- a/third_party/WebKit/Source/platform/mac/BlockExceptions.mm
+++ b/third_party/WebKit/Source/platform/mac/BlockExceptions.mm
@@ -33,7 +33,7 @@
                << [[exception description] UTF8String];
   // This function is marked as NO_RETURN_DUE_TO_ASSERT, but NOTREACHED() and
   // DCHECK(false) are not recognized as NO_RETURN.
-  CRASH();
+  IMMEDIATE_CRASH();
 #else
   NSLog(@"*** WebKit discarding exception: <%@> %@", [exception name],
         [exception reason]);
diff --git a/third_party/WebKit/Source/platform/scheduler/base/task_queue.h b/third_party/WebKit/Source/platform/scheduler/base/task_queue.h
index 8ac280a..237aef3 100644
--- a/third_party/WebKit/Source/platform/scheduler/base/task_queue.h
+++ b/third_party/WebKit/Source/platform/scheduler/base/task_queue.h
@@ -53,12 +53,16 @@
     // explicitly starve other queues. Typically this should only be used for
     // private queues which perform control operations.
     CONTROL_PRIORITY,
-    // Queues with high priority will be selected preferentially over normal or
-    // best effort queues. The selector will ensure that high priority queues
-    // cannot completely starve normal priority queues.
+
+    // The selector will prioritize high over normal and low and normal over
+    // low. However it will ensure neither of the lower priority queues can be
+    // completely starved by higher priority tasks. All three of these queues
+    // will always take priority over and can starve the best effort queue.
     HIGH_PRIORITY,
     // Queues with normal priority are the default.
     NORMAL_PRIORITY,
+    LOW_PRIORITY,
+
     // Queues with best effort priority will only be run if all other queues are
     // empty. They can be starved by the other queues.
     BEST_EFFORT_PRIORITY,
diff --git a/third_party/WebKit/Source/platform/scheduler/base/task_queue_impl.cc b/third_party/WebKit/Source/platform/scheduler/base/task_queue_impl.cc
index 2ead685..8063c89c 100644
--- a/third_party/WebKit/Source/platform/scheduler/base/task_queue_impl.cc
+++ b/third_party/WebKit/Source/platform/scheduler/base/task_queue_impl.cc
@@ -61,6 +61,8 @@
       return "high";
     case NORMAL_PRIORITY:
       return "normal";
+    case LOW_PRIORITY:
+      return "low";
     case BEST_EFFORT_PRIORITY:
       return "best_effort";
     default:
diff --git a/third_party/WebKit/Source/platform/scheduler/base/task_queue_selector.cc b/third_party/WebKit/Source/platform/scheduler/base/task_queue_selector.cc
index 0a24636c..4afaf35 100644
--- a/third_party/WebKit/Source/platform/scheduler/base/task_queue_selector.cc
+++ b/third_party/WebKit/Source/platform/scheduler/base/task_queue_selector.cc
@@ -17,7 +17,8 @@
     : enabled_selector_(this, "enabled"),
       blocked_selector_(this, "blocked"),
       immediate_starvation_count_(0),
-      high_priority_starvation_count_(0),
+      normal_priority_starvation_score_(0),
+      low_priority_starvation_score_(0),
       num_blocked_queues_to_report_(0),
       task_queue_selector_observer_(nullptr) {}
 
@@ -214,10 +215,19 @@
     return true;
   }
 
+  // Select from the low priority queue if we are starving it.
+  if (max_priority > TaskQueue::LOW_PRIORITY &&
+      task_queue_selector_->low_priority_starvation_score_ >=
+          kMaxLowPriorityStarvationScore &&
+      ChooseOldestWithPriority(TaskQueue::LOW_PRIORITY,
+                               out_chose_delayed_over_immediate,
+                               out_work_queue)) {
+    return true;
+  }
   // Select from the normal priority queue if we are starving it.
   if (max_priority > TaskQueue::NORMAL_PRIORITY &&
-      task_queue_selector_->high_priority_starvation_count_ >=
-          kMaxHighPriorityStarvationTasks &&
+      task_queue_selector_->normal_priority_starvation_score_ >=
+          kMaxNormalPriorityStarvationScore &&
       ChooseOldestWithPriority(TaskQueue::NORMAL_PRIORITY,
                                out_chose_delayed_over_immediate,
                                out_work_queue)) {
@@ -326,11 +336,20 @@
     case TaskQueue::CONTROL_PRIORITY:
       break;
     case TaskQueue::HIGH_PRIORITY:
-      high_priority_starvation_count_++;
+      low_priority_starvation_score_ +=
+          kSmallScoreIncrementForLowPriorityStarvation;
+      normal_priority_starvation_score_ +=
+          kSmallScoreIncrementForNormalPriorityStarvation;
       break;
     case TaskQueue::NORMAL_PRIORITY:
+      low_priority_starvation_score_ +=
+          kLargeScoreIncrementForLowPriorityStarvation;
+      normal_priority_starvation_score_ = 0;
+      break;
+    case TaskQueue::LOW_PRIORITY:
     case TaskQueue::BEST_EFFORT_PRIORITY:
-      high_priority_starvation_count_ = 0;
+      low_priority_starvation_score_ = 0;
+      normal_priority_starvation_score_ = 0;
       break;
     default:
       NOTREACHED();
@@ -345,8 +364,10 @@
 void TaskQueueSelector::AsValueInto(
     base::trace_event::TracedValue* state) const {
   DCHECK(main_thread_checker_.CalledOnValidThread());
-  state->SetInteger("high_priority_starvation_count",
-                    high_priority_starvation_count_);
+  state->SetInteger("normal_priority_starvation_score",
+                    normal_priority_starvation_score_);
+  state->SetInteger("low_priority_starvation_score",
+                    low_priority_starvation_score_);
   state->SetInteger("immediate_starvation_count", immediate_starvation_count_);
   state->SetInteger("num_blocked_queues_to_report",
                     num_blocked_queues_to_report_);
diff --git a/third_party/WebKit/Source/platform/scheduler/base/task_queue_selector.h b/third_party/WebKit/Source/platform/scheduler/base/task_queue_selector.h
index 1fd9a60..12a8c20c 100644
--- a/third_party/WebKit/Source/platform/scheduler/base/task_queue_selector.h
+++ b/third_party/WebKit/Source/platform/scheduler/base/task_queue_selector.h
@@ -178,10 +178,29 @@
   void TrySelectingBlockedQueueOverEnabledQueue(
       const WorkQueue& chosen_enabled_queue);
 
-  // Number of high priority tasks which can be run before a normal priority
-  // task should be selected to prevent starvation.
-  // TODO(rmcilroy): Check if this is a good value.
-  static const size_t kMaxHighPriorityStarvationTasks = 5;
+  // Maximum score to accumulate before normal priority tasks are run even in
+  // the presence of high priority tasks.
+  static const size_t kMaxNormalPriorityStarvationScore = 5;
+
+  // Increment to be applied to the normal priority starvation score when a task
+  // should have only a small effect on the score. E.g. A number of high
+  // priority tasks must run before the normal priority queue is considered
+  // starved.
+  static const size_t kSmallScoreIncrementForNormalPriorityStarvation = 1;
+
+  // Maximum score to accumulate before low priority tasks are run even in the
+  // presence of high or normal priority tasks.
+  static const size_t kMaxLowPriorityStarvationScore = 25;
+
+  // Increment to be applied to the low priority starvation score when a task
+  // should have a large effect on the score. E.g. Only a few normal priority
+  // tasks must run before the low priority queue is considered starved.
+  static const size_t kLargeScoreIncrementForLowPriorityStarvation = 5;
+
+  // Increment to be applied to the low priority starvation score when a task
+  // should have only a small effect on the score. E.g. A lot of high priority
+  // tasks must run before the low priority queue is considered starved.
+  static const size_t kSmallScoreIncrementForLowPriorityStarvation = 1;
 
   // Maximum number of delayed tasks tasks which can be run while there's a
   // waiting non-delayed task.
@@ -193,7 +212,8 @@
   PrioritizingSelector enabled_selector_;
   PrioritizingSelector blocked_selector_;
   size_t immediate_starvation_count_;
-  size_t high_priority_starvation_count_;
+  size_t normal_priority_starvation_score_;
+  size_t low_priority_starvation_score_;
   size_t num_blocked_queues_to_report_;
 
   Observer* task_queue_selector_observer_;  // NOT OWNED
diff --git a/third_party/WebKit/Source/platform/scheduler/base/task_queue_selector_unittest.cc b/third_party/WebKit/Source/platform/scheduler/base/task_queue_selector_unittest.cc
index 8e9c04c6..c98d2816 100644
--- a/third_party/WebKit/Source/platform/scheduler/base/task_queue_selector_unittest.cc
+++ b/third_party/WebKit/Source/platform/scheduler/base/task_queue_selector_unittest.cc
@@ -173,13 +173,21 @@
   EXPECT_THAT(PopTasks(), testing::ElementsAre(2, 0, 1, 3, 4));
 }
 
+TEST_F(TaskQueueSelectorTest, TestLowPriority) {
+  size_t queue_order[] = {0, 1, 2, 3, 4};
+  PushTasks(queue_order, 5);
+  selector_.SetQueuePriority(task_queues_[2].get(), TaskQueue::LOW_PRIORITY);
+  EXPECT_THAT(PopTasks(), testing::ElementsAre(0, 1, 3, 4, 2));
+}
+
 TEST_F(TaskQueueSelectorTest, TestBestEffortPriority) {
   size_t queue_order[] = {0, 1, 2, 3, 4};
   PushTasks(queue_order, 5);
   selector_.SetQueuePriority(task_queues_[0].get(),
                              TaskQueue::BEST_EFFORT_PRIORITY);
-  selector_.SetQueuePriority(task_queues_[2].get(), TaskQueue::HIGH_PRIORITY);
-  EXPECT_THAT(PopTasks(), testing::ElementsAre(2, 1, 3, 4, 0));
+  selector_.SetQueuePriority(task_queues_[2].get(), TaskQueue::LOW_PRIORITY);
+  selector_.SetQueuePriority(task_queues_[3].get(), TaskQueue::HIGH_PRIORITY);
+  EXPECT_THAT(PopTasks(), testing::ElementsAre(3, 1, 4, 2, 0));
 }
 
 TEST_F(TaskQueueSelectorTest, TestControlPriority) {
@@ -293,7 +301,7 @@
                              TaskQueue::BEST_EFFORT_PRIORITY);
   for (int i = 0; i < 100; i++) {
     WorkQueue* chosen_work_queue = nullptr;
-    EXPECT_TRUE(selector_.SelectWorkQueueToService(&chosen_work_queue));
+    ASSERT_TRUE(selector_.SelectWorkQueueToService(&chosen_work_queue));
     EXPECT_EQ(task_queues_[3].get(), chosen_work_queue->task_queue());
     // Don't remove task from queue to simulate all queues still being full.
   }
@@ -308,7 +316,7 @@
   size_t counts[] = {0, 0, 0};
   for (int i = 0; i < 100; i++) {
     WorkQueue* chosen_work_queue = nullptr;
-    EXPECT_TRUE(selector_.SelectWorkQueueToService(&chosen_work_queue));
+    ASSERT_TRUE(selector_.SelectWorkQueueToService(&chosen_work_queue));
     size_t chosen_queue_index =
         queue_to_index_map_.find(chosen_work_queue->task_queue())->second;
     counts[chosen_queue_index]++;
@@ -319,6 +327,46 @@
   EXPECT_EQ(0ul, counts[1]);        // Check best effort is starved.
 }
 
+TEST_F(TaskQueueSelectorTest, TestHighPriorityDoesNotStarveNormalOrLow) {
+  size_t queue_order[] = {0, 1, 2};
+  PushTasks(queue_order, 3);
+  selector_.SetQueuePriority(task_queues_[2].get(), TaskQueue::HIGH_PRIORITY);
+  selector_.SetQueuePriority(task_queues_[1].get(), TaskQueue::LOW_PRIORITY);
+  size_t counts[] = {0, 0, 0};
+  for (int i = 0; i < 100; i++) {
+    WorkQueue* chosen_work_queue = nullptr;
+    ASSERT_TRUE(selector_.SelectWorkQueueToService(&chosen_work_queue));
+    size_t chosen_queue_index =
+        queue_to_index_map_.find(chosen_work_queue->task_queue())->second;
+    counts[chosen_queue_index]++;
+    // Don't remove task from queue to simulate all queues still being full.
+  }
+  EXPECT_GT(counts[0], 0ul);        // Check high doesn't starve normal.
+  EXPECT_GT(counts[2], counts[0]);  // Check high gets more chance to run.
+  EXPECT_GT(counts[1], 0ul);        // Check low isn't starved.
+  EXPECT_GT(counts[0], counts[1]);  // Check normal gets more chance to run.
+}
+
+TEST_F(TaskQueueSelectorTest, TestNormalPriorityDoesNotStarveLow) {
+  size_t queue_order[] = {0, 1, 2};
+  PushTasks(queue_order, 3);
+  selector_.SetQueuePriority(task_queues_[0].get(), TaskQueue::LOW_PRIORITY);
+  selector_.SetQueuePriority(task_queues_[1].get(),
+                             TaskQueue::BEST_EFFORT_PRIORITY);
+  size_t counts[] = {0, 0, 0};
+  for (int i = 0; i < 100; i++) {
+    WorkQueue* chosen_work_queue = nullptr;
+    ASSERT_TRUE(selector_.SelectWorkQueueToService(&chosen_work_queue));
+    size_t chosen_queue_index =
+        queue_to_index_map_.find(chosen_work_queue->task_queue())->second;
+    counts[chosen_queue_index]++;
+    // Don't remove task from queue to simulate all queues still being full.
+  }
+  EXPECT_GT(counts[0], 0ul);        // Check normal doesn't starve low.
+  EXPECT_GT(counts[2], counts[0]);  // Check normal gets more chance to run.
+  EXPECT_EQ(0ul, counts[1]);        // Check best effort is starved.
+}
+
 TEST_F(TaskQueueSelectorTest, TestBestEffortGetsStarved) {
   size_t queue_order[] = {0, 1};
   PushTasks(queue_order, 2);
@@ -327,20 +375,20 @@
   EXPECT_EQ(TaskQueue::NORMAL_PRIORITY, task_queues_[1]->GetQueuePriority());
   WorkQueue* chosen_work_queue = nullptr;
   for (int i = 0; i < 100; i++) {
-    EXPECT_TRUE(selector_.SelectWorkQueueToService(&chosen_work_queue));
+    ASSERT_TRUE(selector_.SelectWorkQueueToService(&chosen_work_queue));
     EXPECT_EQ(task_queues_[1].get(), chosen_work_queue->task_queue());
     // Don't remove task from queue to simulate all queues still being full.
   }
   selector_.SetQueuePriority(task_queues_[1].get(), TaskQueue::HIGH_PRIORITY);
   for (int i = 0; i < 100; i++) {
-    EXPECT_TRUE(selector_.SelectWorkQueueToService(&chosen_work_queue));
+    ASSERT_TRUE(selector_.SelectWorkQueueToService(&chosen_work_queue));
     EXPECT_EQ(task_queues_[1].get(), chosen_work_queue->task_queue());
     // Don't remove task from queue to simulate all queues still being full.
   }
   selector_.SetQueuePriority(task_queues_[1].get(),
                              TaskQueue::CONTROL_PRIORITY);
   for (int i = 0; i < 100; i++) {
-    EXPECT_TRUE(selector_.SelectWorkQueueToService(&chosen_work_queue));
+    ASSERT_TRUE(selector_.SelectWorkQueueToService(&chosen_work_queue));
     EXPECT_EQ(task_queues_[1].get(), chosen_work_queue->task_queue());
     // Don't remove task from queue to simulate all queues still being full.
   }
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 046364da8..2cc38716 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
@@ -1039,8 +1039,7 @@
         // seem to be safe. Instead we do that by proxy by deprioritizing
         // compositor tasks. This should be safe since we've already gone to the
         // pain of fixing ordering issues with them.
-        new_policy.compositor_queue_policy.priority =
-            TaskQueue::BEST_EFFORT_PRIORITY;
+        new_policy.compositor_queue_policy.priority = TaskQueue::LOW_PRIORITY;
       }
       break;
 
diff --git a/third_party/WebKit/Source/platform/scheduler/renderer/renderer_scheduler_impl_unittest.cc b/third_party/WebKit/Source/platform/scheduler/renderer/renderer_scheduler_impl_unittest.cc
index 9f0e220f..9571ca3 100644
--- a/third_party/WebKit/Source/platform/scheduler/renderer/renderer_scheduler_impl_unittest.cc
+++ b/third_party/WebKit/Source/platform/scheduler/renderer/renderer_scheduler_impl_unittest.cc
@@ -880,8 +880,8 @@
   RunUntilIdle();
   EXPECT_THAT(run_order,
               testing::ElementsAre(std::string("L1"), std::string("D1"),
-                                   std::string("D2"), std::string("I1"),
-                                   std::string("C1"), std::string("C2")));
+                                   std::string("D2"), std::string("C1"),
+                                   std::string("C2"), std::string("I1")));
   EXPECT_EQ(RendererSchedulerImpl::UseCase::COMPOSITOR_GESTURE,
             CurrentUseCase());
 }
@@ -914,8 +914,8 @@
   RunUntilIdle();
   EXPECT_THAT(run_order,
               testing::ElementsAre(std::string("L1"), std::string("D1"),
-                                   std::string("D2"), std::string("I1"),
-                                   std::string("C1"), std::string("C2")));
+                                   std::string("D2"), std::string("C1"),
+                                   std::string("C2"), std::string("I1")));
   EXPECT_EQ(RendererSchedulerImpl::UseCase::COMPOSITOR_GESTURE,
             CurrentUseCase());
 }
@@ -963,8 +963,8 @@
   RunUntilIdle();
   EXPECT_THAT(run_order,
               testing::ElementsAre(std::string("L1"), std::string("D1"),
-                                   std::string("D2"), std::string("I1"),
-                                   std::string("C1"), std::string("C2")));
+                                   std::string("D2"), std::string("C1"),
+                                   std::string("C2"), std::string("I1")));
   EXPECT_EQ(RendererSchedulerImpl::UseCase::COMPOSITOR_GESTURE,
             CurrentUseCase());
 }
@@ -1072,8 +1072,8 @@
   RunUntilIdle();
   EXPECT_THAT(run_order,
               testing::ElementsAre(std::string("D1"), std::string("D2"),
-                                   std::string("I1"), std::string("C1"),
-                                   std::string("C2")));
+                                   std::string("C1"), std::string("C2"),
+                                   std::string("I1")));
   EXPECT_EQ(RendererSchedulerImpl::UseCase::COMPOSITOR_GESTURE,
             CurrentUseCase());
 }
@@ -1340,8 +1340,8 @@
             CurrentUseCase());
   EXPECT_THAT(run_order,
               testing::ElementsAre(std::string("D1"), std::string("D2"),
-                                   std::string("I1"), std::string("C1"),
-                                   std::string("C2")));
+                                   std::string("C1"), std::string("C2"),
+                                   std::string("I1")));
 }
 
 TEST_F(RendererSchedulerImplTest,
@@ -1443,8 +1443,8 @@
   // Note compositor tasks are not prioritized.
   EXPECT_THAT(run_order,
               testing::ElementsAre(std::string("D1"), std::string("D2"),
-                                   std::string("I1"), std::string("C1"),
-                                   std::string("C2")));
+                                   std::string("C1"), std::string("C2"),
+                                   std::string("I1")));
   EXPECT_EQ(RendererSchedulerImpl::UseCase::COMPOSITOR_GESTURE,
             CurrentUseCase());
 }
@@ -1518,8 +1518,8 @@
   // Note compositor tasks are not prioritized.
   EXPECT_THAT(run_order,
               testing::ElementsAre(std::string("D1"), std::string("D2"),
-                                   std::string("I1"), std::string("C1"),
-                                   std::string("C2")));
+                                   std::string("C1"), std::string("C2"),
+                                   std::string("I1")));
   EXPECT_EQ(RendererSchedulerImpl::UseCase::COMPOSITOR_GESTURE,
             CurrentUseCase());
 }
diff --git a/third_party/WebKit/Source/platform/wtf/Assertions.h b/third_party/WebKit/Source/platform/wtf/Assertions.h
index 33e2b7a..e89a7cd 100644
--- a/third_party/WebKit/Source/platform/wtf/Assertions.h
+++ b/third_party/WebKit/Source/platform/wtf/Assertions.h
@@ -109,17 +109,6 @@
 
 }  // namespace WTF
 
-// CRASH() - Raises a fatal error resulting in program termination and
-// triggering either the debugger or the crash reporter.
-//
-// Use CRASH() in response to known, unrecoverable errors like out-of-memory.
-// Macro is enabled in both debug and release mode.
-// To test for unknown errors and verify assumptions, use ASSERT instead, to
-// avoid impacting performance in release builds.
-#ifndef CRASH
-#define CRASH() IMMEDIATE_CRASH()
-#endif
-
 #define DCHECK_AT(assertion, file, line)                            \
   LAZY_STREAM(logging::LogMessage(file, line, #assertion).stream(), \
               DCHECK_IS_ON() ? !(assertion) : false)
diff --git a/third_party/WebKit/Source/platform/wtf/AssertionsTest.cpp b/third_party/WebKit/Source/platform/wtf/AssertionsTest.cpp
index 930c0283..abaa2a7521 100644
--- a/third_party/WebKit/Source/platform/wtf/AssertionsTest.cpp
+++ b/third_party/WebKit/Source/platform/wtf/AssertionsTest.cpp
@@ -28,7 +28,7 @@
   SECURITY_CHECK(true);
   EXPECT_DEATH_IF_SUPPORTED(SECURITY_CHECK(false), "");
 
-  EXPECT_DEATH_IF_SUPPORTED(CRASH(), "");
+  EXPECT_DEATH_IF_SUPPORTED(IMMEDIATE_CRASH(), "");
   EXPECT_DEATH_IF_SUPPORTED(IMMEDIATE_CRASH(), "");
 };
 
diff --git a/third_party/WebKit/Source/platform/wtf/ThreadSpecific.h b/third_party/WebKit/Source/platform/wtf/ThreadSpecific.h
index 674ad5a..f1582d9 100644
--- a/third_party/WebKit/Source/platform/wtf/ThreadSpecific.h
+++ b/third_party/WebKit/Source/platform/wtf/ThreadSpecific.h
@@ -126,13 +126,13 @@
                                     void (*destructor)(void*)) {
   int error = pthread_key_create(key, destructor);
   if (error)
-    CRASH();
+    IMMEDIATE_CRASH();
 }
 
 inline void ThreadSpecificKeyDelete(ThreadSpecificKey key) {
   int error = pthread_key_delete(key);
   if (error)
-    CRASH();
+    IMMEDIATE_CRASH();
 }
 
 inline void ThreadSpecificSet(ThreadSpecificKey key, void* value) {
@@ -147,7 +147,7 @@
 inline ThreadSpecific<T>::ThreadSpecific() {
   int error = pthread_key_create(&key_, Destroy);
   if (error)
-    CRASH();
+    IMMEDIATE_CRASH();
 }
 
 template <typename T>
@@ -192,11 +192,11 @@
 inline ThreadSpecific<T>::ThreadSpecific() : index_(-1) {
   DWORD tls_key = TlsAlloc();
   if (tls_key == TLS_OUT_OF_INDEXES)
-    CRASH();
+    IMMEDIATE_CRASH();
 
   index_ = InterlockedIncrement(&TlsKeyCount()) - 1;
   if (index_ >= kMaxTlsKeySize)
-    CRASH();
+    IMMEDIATE_CRASH();
   TlsKeys()[index_] = tls_key;
 }
 
diff --git a/third_party/WebKit/Source/platform/wtf/ThreadSpecificWin.cpp b/third_party/WebKit/Source/platform/wtf/ThreadSpecificWin.cpp
index 0bb9504..b54917ec 100644
--- a/third_party/WebKit/Source/platform/wtf/ThreadSpecificWin.cpp
+++ b/third_party/WebKit/Source/platform/wtf/ThreadSpecificWin.cpp
@@ -53,7 +53,7 @@
       : destructor_(destructor) {
     tls_key_ = TlsAlloc();
     if (tls_key_ == TLS_OUT_OF_INDEXES)
-      CRASH();
+      IMMEDIATE_CRASH();
   }
 
   ~PlatformThreadSpecificKey() { TlsFree(tls_key_); }
diff --git a/third_party/WebKit/Source/platform/wtf/text/StringImpl.cpp b/third_party/WebKit/Source/platform/wtf/text/StringImpl.cpp
index 595bc04..10def1fa 100644
--- a/third_party/WebKit/Source/platform/wtf/text/StringImpl.cpp
+++ b/third_party/WebKit/Source/platform/wtf/text/StringImpl.cpp
@@ -651,7 +651,7 @@
     return LowerUnicode();
 
   if (length_ > static_cast<unsigned>(numeric_limits<int32_t>::max()))
-    CRASH();
+    IMMEDIATE_CRASH();
   int length = length_;
 
   RefPtr<StringImpl> upconverted = UpconvertedString();
@@ -677,7 +677,7 @@
     return UpperUnicode();
 
   if (length_ > static_cast<unsigned>(numeric_limits<int32_t>::max()))
-    CRASH();
+    IMMEDIATE_CRASH();
   int length = length_;
 
   RefPtr<StringImpl> upconverted = UpconvertedString();
diff --git a/third_party/WebKit/Source/platform/wtf/text/TextCodecUTF8.cpp b/third_party/WebKit/Source/platform/wtf/text/TextCodecUTF8.cpp
index 32b21a7f..55f0ce5 100644
--- a/third_party/WebKit/Source/platform/wtf/text/TextCodecUTF8.cpp
+++ b/third_party/WebKit/Source/platform/wtf/text/TextCodecUTF8.cpp
@@ -464,7 +464,7 @@
   // Non-BMP characters take two UTF-16 code units and can take up to 4 bytes
   // (2x).
   if (length > std::numeric_limits<size_t>::max() / 3)
-    CRASH();
+    IMMEDIATE_CRASH();
   Vector<uint8_t> bytes(length * 3);
 
   size_t i = 0;
diff --git a/third_party/WebKit/Source/web/WebLocalFrameImpl.cpp b/third_party/WebKit/Source/web/WebLocalFrameImpl.cpp
index acb981d..57bf07ad 100644
--- a/third_party/WebKit/Source/web/WebLocalFrameImpl.cpp
+++ b/third_party/WebKit/Source/web/WebLocalFrameImpl.cpp
@@ -2031,6 +2031,11 @@
   return local_root;
 }
 
+WebFrame* WebLocalFrameImpl::FindFrameByName(const WebString& name) {
+  Frame* result = GetFrame()->Tree().Find(name);
+  return WebFrame::FromFrame(result);
+}
+
 void WebLocalFrameImpl::SendPings(const WebURL& destination_url) {
   DCHECK(GetFrame());
   DCHECK(context_menu_node_.Get());
diff --git a/third_party/WebKit/Source/web/WebLocalFrameImpl.h b/third_party/WebKit/Source/web/WebLocalFrameImpl.h
index 2de42029..3afa6165 100644
--- a/third_party/WebKit/Source/web/WebLocalFrameImpl.h
+++ b/third_party/WebKit/Source/web/WebLocalFrameImpl.h
@@ -248,6 +248,7 @@
   void SetDevToolsAgentClient(WebDevToolsAgentClient*) override;
   WebDevToolsAgent* DevToolsAgent() override;
   WebLocalFrameImpl* LocalRoot() override;
+  WebFrame* FindFrameByName(const WebString& name) override;
   void SendPings(const WebURL& destination_url) override;
   bool DispatchBeforeUnloadEvent(bool) override;
   WebURLRequest RequestFromHistoryItem(const WebHistoryItem&,
diff --git a/third_party/WebKit/Source/web/WebPagePopupImpl.cpp b/third_party/WebKit/Source/web/WebPagePopupImpl.cpp
index eddca3ea..e7aa9b1 100644
--- a/third_party/WebKit/Source/web/WebPagePopupImpl.cpp
+++ b/third_party/WebKit/Source/web/WebPagePopupImpl.cpp
@@ -600,7 +600,7 @@
 
 WebPagePopup* WebPagePopup::Create(WebWidgetClient* client) {
   if (!client)
-    CRASH();
+    IMMEDIATE_CRASH();
   // A WebPagePopupImpl instance usually has two references.
   //  - One owned by the instance itself. It represents the visible widget.
   //  - One owned by a WebViewBase. It's released when the WebViewBase ask the
diff --git a/third_party/WebKit/Source/web/WebViewImpl.cpp b/third_party/WebKit/Source/web/WebViewImpl.cpp
index 9c3803e..f7013a5d 100644
--- a/third_party/WebKit/Source/web/WebViewImpl.cpp
+++ b/third_party/WebKit/Source/web/WebViewImpl.cpp
@@ -698,8 +698,8 @@
                             event.data.fling_start.velocity_y),
               WebSize());
       DCHECK(fling_curve);
-      gesture_animation_ = WebActiveGestureAnimation::CreateAtAnimationStart(
-          std::move(fling_curve), this);
+      gesture_animation_ = WebActiveGestureAnimation::CreateWithTimeOffset(
+          std::move(fling_curve), this, event.TimeStampSeconds());
       MainFrameImpl()->FrameWidget()->ScheduleAnimation();
       event_result = WebInputEventResult::kHandledSystem;
 
@@ -2630,19 +2630,6 @@
   return WebFrame::FromFrame(page_ ? page_->MainFrame() : nullptr);
 }
 
-WebFrame* WebViewImpl::FindFrameByName(const WebString& name,
-                                       WebFrame* relative_to_frame) {
-  // FIXME: Either this should only deal with WebLocalFrames or it should move
-  // to WebFrame.
-  if (!relative_to_frame)
-    relative_to_frame = MainFrame();
-  Frame* frame = ToWebLocalFrameBase(relative_to_frame)->GetFrame();
-  frame = frame->Tree().Find(name);
-  if (!frame || !frame->IsLocalFrame())
-    return nullptr;
-  return WebLocalFrameBase::FromFrame(ToLocalFrame(frame));
-}
-
 WebLocalFrame* WebViewImpl::FocusedFrame() {
   Frame* frame = FocusedCoreFrame();
   // TODO(yabinh): focusedCoreFrame() should always return a local frame, and
diff --git a/third_party/WebKit/Source/web/WebViewImpl.h b/third_party/WebKit/Source/web/WebViewImpl.h
index 126cc4a..6e47532 100644
--- a/third_party/WebKit/Source/web/WebViewImpl.h
+++ b/third_party/WebKit/Source/web/WebViewImpl.h
@@ -173,8 +173,6 @@
                                  float browser_controls_height,
                                  bool browser_controls_shrink_layout) override;
   WebFrame* MainFrame() override;
-  WebFrame* FindFrameByName(const WebString& name,
-                            WebFrame* relative_to_frame) override;
   WebLocalFrame* FocusedFrame() override;
   void SetFocusedFrame(WebFrame*) override;
   void FocusDocumentView(WebFrame*) override;
diff --git a/third_party/WebKit/Source/web/tests/LayoutGeometryMapTest.cpp b/third_party/WebKit/Source/web/tests/LayoutGeometryMapTest.cpp
index 404c9481..1e0d49cf 100644
--- a/third_party/WebKit/Source/web/tests/LayoutGeometryMapTest.cpp
+++ b/third_party/WebKit/Source/web/tests/LayoutGeometryMapTest.cpp
@@ -42,6 +42,8 @@
 #include "public/platform/WebURLLoaderMockFactory.h"
 #include "public/web/WebFrameClient.h"
 #include "testing/gtest/include/gtest/gtest.h"
+#include "web/WebLocalFrameImpl.h"
+#include "web/WebViewImpl.h"
 #include "web/tests/FrameTestHelpers.h"
 
 namespace blink {
@@ -66,11 +68,12 @@
   static LayoutBox* GetFrameElement(const char* iframe_name,
                                     WebView* web_view,
                                     const WTF::AtomicString& element_id) {
-    WebLocalFrameBase* iframe = ToWebLocalFrameBase(
-        web_view->FindFrameByName(WebString::FromUTF8(iframe_name)));
-    if (!iframe)
+    WebFrame* iframe =
+        static_cast<WebViewImpl*>(web_view)->MainFrameImpl()->FindFrameByName(
+            WebString::FromUTF8(iframe_name));
+    if (!iframe || !iframe->IsWebLocalFrame())
       return nullptr;
-    LocalFrame* frame = iframe->GetFrame();
+    LocalFrame* frame = ToWebLocalFrameImpl(iframe)->GetFrame();
     Document* doc = frame->GetDocument();
     Element* element = doc->getElementById(element_id);
     if (!element)
diff --git a/third_party/WebKit/Source/web/tests/WebFrameTest.cpp b/third_party/WebKit/Source/web/tests/WebFrameTest.cpp
index f3be8a7..f7c4a46 100644
--- a/third_party/WebKit/Source/web/tests/WebFrameTest.cpp
+++ b/third_party/WebKit/Source/web/tests/WebFrameTest.cpp
@@ -155,6 +155,7 @@
 #include "v8/include/v8.h"
 #include "web/TextFinder.h"
 #include "web/WebRemoteFrameImpl.h"
+#include "web/WebViewImpl.h"
 #include "web/tests/FrameTestHelpers.h"
 #include "web/tests/sim/SimDisplayItemList.h"
 #include "web/tests/sim/SimRequest.h"
@@ -4379,8 +4380,9 @@
   FrameTestHelpers::PumpPendingRequestsForFrameToLoad(
       web_view_helper.WebView()->MainFrame());
 
-  WebFrame* iframe = web_view_helper.WebView()->FindFrameByName(
-      WebString::FromUTF8("ifr"), nullptr);
+  WebFrame* iframe =
+      web_view_helper.WebView()->MainFrameImpl()->FindFrameByName(
+          WebString::FromUTF8("ifr"));
   ASSERT_TRUE(iframe);
   WebDataSource* iframe_data_source = iframe->DataSource();
   ASSERT_TRUE(iframe_data_source);
diff --git a/third_party/WebKit/public/platform/PRESUBMIT.py b/third_party/WebKit/public/platform/PRESUBMIT.py
new file mode 100644
index 0000000..47110974
--- /dev/null
+++ b/third_party/WebKit/public/platform/PRESUBMIT.py
@@ -0,0 +1,56 @@
+# 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.
+
+"""Blink frame presubmit script
+
+See http://dev.chromium.org/developers/how-tos/depottools/presubmit-scripts
+for more details about the presubmit API built into gcl.
+"""
+
+
+def _RunUmaHistogramChecks(input_api, output_api):  # pylint: disable=C0103
+    import sys
+
+    original_sys_path = sys.path
+    try:
+        sys.path = sys.path + [input_api.os_path.join(
+            input_api.PresubmitLocalPath(), '..', '..', '..', '..',
+            'tools', 'metrics', 'histograms')]
+        import update_histogram_enum  # pylint: disable=F0401
+    finally:
+        sys.path = original_sys_path
+
+    source_path = ''
+    for f in input_api.AffectedFiles():
+        if f.LocalPath().endswith('UseCounterFeature.def'):
+            source_path = f.LocalPath()
+            break
+    else:
+        return []
+
+    start_marker = '^'
+    end_marker = '^kNumberOfFeatures'
+    presubmit_error = update_histogram_enum.CheckPresubmitErrors(
+        histogram_enum_name='FeatureObserver',
+        update_script_name='update_use_counter_feature_enum.py',
+        source_enum_path=source_path,
+        start_marker=start_marker,
+        end_marker=end_marker,
+        strip_k_prefix=True)
+    if presubmit_error:
+        return [output_api.PresubmitPromptWarning(presubmit_error,
+                                                  items=[source_path])]
+    return []
+
+
+def CheckChangeOnUpload(input_api, output_api):  # pylint: disable=C0103
+    results = []
+    results.extend(_RunUmaHistogramChecks(input_api, output_api))
+    return results
+
+
+def CheckChangeOnCommit(input_api, output_api):  # pylint: disable=C0103
+    results = []
+    results.extend(_RunUmaHistogramChecks(input_api, output_api))
+    return results
diff --git a/third_party/WebKit/public/platform/UseCounterFeature.def b/third_party/WebKit/public/platform/UseCounterFeature.def
new file mode 100644
index 0000000..48c769e6
--- /dev/null
+++ b/third_party/WebKit/public/platform/UseCounterFeature.def
@@ -0,0 +1,1557 @@
+// ============ Definition for WebFeature used for UseCounter ===============
+// A WebFeature conceptually represents some particular web-exposed API
+// or code path which can be used/triggered by a web page.
+// TODO(lunalu): Replace occurance of UseCounter::Feature by WebFeature in
+// Blink.
+// TODO(rbyers): Add CSS and animated CSS feature types by making this a
+// more sophisticated class.
+//
+// Do not change assigned numbers of existing items: add new features
+// to the end of the list.
+kOBSOLETE_PageDestruction = 0,
+kWorkerStart = 4,
+kSharedWorkerStart = 5,
+kUnprefixedIndexedDB = 9,
+kOpenWebDatabase = 10,
+kUnprefixedRequestAnimationFrame = 13,
+kPrefixedRequestAnimationFrame = 14,
+kContentSecurityPolicy = 15,
+kContentSecurityPolicyReportOnly = 16,
+kPrefixedTransitionEndEvent = 18,
+kUnprefixedTransitionEndEvent = 19,
+kPrefixedAndUnprefixedTransitionEndEvent = 20,
+kAutoFocusAttribute = 21,
+kDataListElement = 23,
+kFormAttribute = 24,
+kIncrementalAttribute = 25,
+kInputTypeColor = 26,
+kInputTypeDate = 27,
+kInputTypeDateTimeFallback = 29,
+kInputTypeDateTimeLocal = 30,
+kInputTypeEmail = 31,
+kInputTypeMonth = 32,
+kInputTypeNumber = 33,
+kInputTypeRange = 34,
+kInputTypeSearch = 35,
+kInputTypeTel = 36,
+kInputTypeTime = 37,
+kInputTypeURL = 38,
+kInputTypeWeek = 39,
+kInputTypeWeekFallback = 40,
+kListAttribute = 41,
+kMaxAttribute = 42,
+kMinAttribute = 43,
+kPatternAttribute = 44,
+kPlaceholderAttribute = 45,
+kPrefixedDirectoryAttribute = 47,
+kRequiredAttribute = 49,
+kStepAttribute = 51,
+kPageVisits = 52,
+kHTMLMarqueeElement = 53,
+kReflection = 55,
+kPrefixedStorageInfo = 57,
+kDeprecatedFlexboxWebContent = 61,
+kDeprecatedFlexboxChrome = 62,
+kDeprecatedFlexboxChromeExtension = 63,
+kUnprefixedPerformanceTimeline = 65,
+kUnprefixedUserTiming = 67,
+kWindowEvent = 69,
+kContentSecurityPolicyWithBaseElement = 70,
+kDocumentClear = 74,
+kXMLDocument = 77,
+kXSLProcessingInstruction = 78,
+kXSLTProcessor = 79,
+kSVGSwitchElement = 80,
+kDocumentAll = 83,
+kFormElement = 84,
+kDemotedFormElement = 85,
+kSVGAnimationElement = 90,
+kLineClamp = 96,
+kSubFrameBeforeUnloadRegistered = 97,
+kSubFrameBeforeUnloadFired = 98,
+kConsoleMarkTimeline = 102,
+kDocumentCreateAttribute = 111,
+kDocumentCreateAttributeNS = 112,
+kDocumentXMLEncoding = 115,    // Removed from DOM4.
+kDocumentXMLStandalone = 116,  // Removed from DOM4.
+kDocumentXMLVersion = 117,     // Removed from DOM4.
+kNavigatorProductSub = 123,
+kNavigatorVendor = 124,
+kNavigatorVendorSub = 125,
+kPrefixedAnimationEndEvent = 128,
+kUnprefixedAnimationEndEvent = 129,
+kPrefixedAndUnprefixedAnimationEndEvent = 130,
+kPrefixedAnimationStartEvent = 131,
+kUnprefixedAnimationStartEvent = 132,
+kPrefixedAndUnprefixedAnimationStartEvent = 133,
+kPrefixedAnimationIterationEvent = 134,
+kUnprefixedAnimationIterationEvent = 135,
+kPrefixedAndUnprefixedAnimationIterationEvent = 136,
+kEventReturnValue = 137,  // Legacy IE extension.
+kSVGSVGElement = 138,
+kDOMSubtreeModifiedEvent = 143,
+kDOMNodeInsertedEvent = 144,
+kDOMNodeRemovedEvent = 145,
+kDOMNodeRemovedFromDocumentEvent = 146,
+kDOMNodeInsertedIntoDocumentEvent = 147,
+kDOMCharacterDataModifiedEvent = 148,
+kDocumentAllLegacyCall = 150,
+kGetMatchedCSSRules = 155,
+kPrefixedAudioDecodedByteCount = 164,
+kPrefixedVideoDecodedByteCount = 165,
+kPrefixedVideoSupportsFullscreen = 166,
+kPrefixedVideoDisplayingFullscreen = 167,
+kPrefixedVideoEnterFullscreen = 168,
+kPrefixedVideoExitFullscreen = 169,
+kPrefixedVideoEnterFullScreen = 170,
+kPrefixedVideoExitFullScreen = 171,
+kPrefixedVideoDecodedFrameCount = 172,
+kPrefixedVideoDroppedFrameCount = 173,
+kPrefixedElementRequestFullscreen = 176,
+kPrefixedElementRequestFullScreen = 177,
+kBarPropLocationbar = 178,
+kBarPropMenubar = 179,
+kBarPropPersonalbar = 180,
+kBarPropScrollbars = 181,
+kBarPropStatusbar = 182,
+kBarPropToolbar = 183,
+kInputTypeEmailMultiple = 184,
+kInputTypeEmailMaxLength = 185,
+kInputTypeEmailMultipleMaxLength = 186,
+kInputTypeText = 190,
+kInputTypeTextMaxLength = 191,
+kInputTypePassword = 192,
+kInputTypePasswordMaxLength = 193,
+kPrefixedPageVisibility = 196,
+kDocumentBeforeUnloadRegistered = 200,
+kDocumentBeforeUnloadFired = 201,
+kDocumentUnloadRegistered = 202,
+kDocumentUnloadFired = 203,
+kSVGLocatableNearestViewportElement = 204,
+kSVGLocatableFarthestViewportElement = 205,
+kSVGPointMatrixTransform = 209,
+kDOMFocusInOutEvent = 211,
+kFileGetLastModifiedDate = 212,
+kHTMLElementInnerText = 213,
+kHTMLElementOuterText = 214,
+kReplaceDocumentViaJavaScriptURL = 215,
+kElementPrefixedMatchesSelector = 217,
+kCSSStyleSheetRules = 219,
+kCSSStyleSheetAddRule = 220,
+kCSSStyleSheetRemoveRule = 221,
+// The above items are available in M33 branch.
+
+kInitMessageEvent = 222,
+kPrefixedDevicePixelRatioMediaFeature = 233,
+kPrefixedMaxDevicePixelRatioMediaFeature = 234,
+kPrefixedMinDevicePixelRatioMediaFeature = 235,
+kPrefixedTransform3dMediaFeature = 237,
+kPrefixedStorageQuota = 240,
+kResetReferrerPolicy = 243,
+// Case-insensitivity dropped from specification.
+kCaseInsensitiveAttrSelectorMatch = 244,
+kFormNameAccessForImageElement = 246,
+kFormNameAccessForPastNamesMap = 247,
+kFormAssociationByParser = 248,
+kSVGSVGElementInDocument = 250,
+kSVGDocumentRootElement = 251,
+kWorkerSubjectToCSP = 257,
+kWorkerAllowedByChildBlockedByScript = 258,
+kDeprecatedWebKitGradient = 260,
+kDeprecatedWebKitLinearGradient = 261,
+kDeprecatedWebKitRepeatingLinearGradient = 262,
+kDeprecatedWebKitRadialGradient = 263,
+kDeprecatedWebKitRepeatingRadialGradient = 264,
+// The above items are available in M34 branch.
+
+kTextAutosizing = 274,
+kHTMLAnchorElementPingAttribute = 276,
+kSVGClassName = 279,
+kHTMLMediaElementSeekToFragmentStart = 281,
+kHTMLMediaElementPauseAtFragmentEnd = 282,
+kPrefixedWindowURL = 283,
+kWindowOrientation = 285,
+kDocumentCaptureEvents = 287,
+kDocumentReleaseEvents = 288,
+kWindowCaptureEvents = 289,
+kWindowReleaseEvents = 290,
+kDocumentXPathCreateExpression = 295,
+kDocumentXPathCreateNSResolver = 296,
+kDocumentXPathEvaluate = 297,
+kAnimationConstructorKeyframeListEffectObjectTiming = 300,
+kAnimationConstructorKeyframeListEffectNoTiming = 302,
+kPrefixedCancelAnimationFrame = 304,
+kNamedNodeMapGetNamedItem = 306,
+kNamedNodeMapSetNamedItem = 307,
+kNamedNodeMapRemoveNamedItem = 308,
+kNamedNodeMapItem = 309,
+kNamedNodeMapGetNamedItemNS = 310,
+kNamedNodeMapSetNamedItemNS = 311,
+kNamedNodeMapRemoveNamedItemNS = 312,
+kPrefixedDocumentIsFullscreen = 318,
+kPrefixedDocumentCurrentFullScreenElement = 320,
+kPrefixedDocumentCancelFullScreen = 321,
+kPrefixedDocumentFullscreenEnabled = 322,
+kPrefixedDocumentFullscreenElement = 323,
+kPrefixedDocumentExitFullscreen = 324,
+// The above items are available in M35 branch.
+
+kSVGForeignObjectElement = 325,
+kSelectionSetPosition = 327,
+kAnimationFinishEvent = 328,
+kSVGSVGElementInXMLDocument = 329,
+kEventSrcElement = 343,
+kEventCancelBubble = 344,
+kEventPath = 345,
+kNodeIteratorDetach = 347,
+kEventGetReturnValueTrue = 350,
+kEventGetReturnValueFalse = 351,
+kEventSetReturnValueTrue = 352,
+kEventSetReturnValueFalse = 353,
+kWindowOffscreenBuffering = 356,
+kWindowDefaultStatus = 357,
+kWindowDefaultstatus = 358,
+kPrefixedTransitionEventConstructor = 361,
+kPrefixedMutationObserverConstructor = 362,
+kNotificationPermission = 371,
+kRangeDetach = 372,
+kPrefixedFileRelativePath = 386,
+kDocumentCaretRangeFromPoint = 387,
+kElementScrollIntoViewIfNeeded = 389,
+kRangeExpand = 393,
+kHTMLImageElementX = 396,
+kHTMLImageElementY = 397,
+kSelectionBaseNode = 400,
+kSelectionBaseOffset = 401,
+kSelectionExtentNode = 402,
+kSelectionExtentOffset = 403,
+kSelectionType = 404,
+kSelectionModify = 405,
+kSelectionSetBaseAndExtent = 406,
+kSelectionEmpty = 407,
+kVTTCue = 409,
+kVTTCueRender = 410,
+kVTTCueRenderVertical = 411,
+kVTTCueRenderSnapToLinesFalse = 412,
+kVTTCueRenderLineNotAuto = 413,
+kVTTCueRenderPositionNot50 = 414,
+kVTTCueRenderSizeNot100 = 415,
+kVTTCueRenderAlignNotCenter = 416,
+// The above items are available in M36 branch.
+
+kElementRequestPointerLock = 417,
+kVTTCueRenderRtl = 418,
+kPostMessageFromSecureToInsecure = 419,
+kPostMessageFromInsecureToSecure = 420,
+kDocumentExitPointerLock = 421,
+kDocumentPointerLockElement = 422,
+kPrefixedCursorZoomIn = 424,
+kPrefixedCursorZoomOut = 425,
+kTextEncoderConstructor = 429,
+kTextEncoderEncode = 430,
+kTextDecoderConstructor = 431,
+kTextDecoderDecode = 432,
+kFocusInOutEvent = 433,
+kMouseEventMovementX = 434,
+kMouseEventMovementY = 435,
+kDocumentFonts = 440,
+kMixedContentFormsSubmitted = 441,
+kFormsSubmitted = 442,
+kHTMLImports = 455,
+kElementCreateShadowRoot = 456,
+kDocumentRegisterElement = 457,
+kEditingAppleInterchangeNewline = 458,
+kEditingAppleConvertedSpace = 459,
+kEditingApplePasteAsQuotation = 460,
+kEditingAppleStyleSpanClass = 461,
+kHTMLImportsAsyncAttribute = 463,
+kXMLHttpRequestSynchronous = 465,
+kCSSSelectorPseudoUnresolved = 466,
+kCSSSelectorPseudoShadow = 467,
+kCSSSelectorPseudoContent = 468,
+kCSSSelectorPseudoHost = 469,
+kCSSSelectorPseudoHostContext = 470,
+kCSSDeepCombinator = 471,
+// The above items are available in M37 branch.
+
+kUseAsm = 473,
+kDOMWindowOpen = 475,
+kDOMWindowOpenFeatures = 476,
+kAspectRatioFlexItem = 479,
+kDetailsElement = 480,
+kDialogElement = 481,
+kMapElement = 482,
+kMeterElement = 483,
+kProgressElement = 484,
+kWheelEventWheelDeltaX = 491,
+kWheelEventWheelDeltaY = 492,
+kWheelEventWheelDelta = 493,
+kSendBeacon = 494,
+kSendBeaconQuotaExceeded = 495,
+kSVGSMILElementInDocument = 501,
+kMouseEventOffsetX = 502,
+kMouseEventOffsetY = 503,
+kMouseEventX = 504,
+kMouseEventY = 505,
+kMouseEventFromElement = 506,
+kMouseEventToElement = 507,
+kRequestFileSystem = 508,
+kRequestFileSystemWorker = 509,
+kRequestFileSystemSyncWorker = 510,
+kSVGStyleElementTitle = 519,
+kPictureSourceSrc = 520,
+// The above items are available in M38 branch.
+
+kPicture = 521,
+kSizes = 522,
+kSrcsetXDescriptor = 523,
+kSrcsetWDescriptor = 524,
+kSelectionContainsNode = 525,
+kXMLExternalResourceLoad = 529,
+kMixedContentPrivateHostnameInPublicHostname = 530,
+kLegacyProtocolEmbeddedAsSubresource = 531,
+kRequestedSubresourceWithEmbeddedCredentials = 532,
+kNotificationCreated = 533,
+kNotificationClosed = 534,
+kNotificationPermissionRequested = 535,
+kConsoleTimeline = 538,
+kConsoleTimelineEnd = 539,
+kSRIElementWithMatchingIntegrityAttribute = 540,
+kSRIElementWithNonMatchingIntegrityAttribute = 541,
+kSRIElementWithUnparsableIntegrityAttribute = 542,
+kV8Animation_StartTime_AttributeGetter = 545,
+kV8Animation_StartTime_AttributeSetter = 546,
+kV8Animation_CurrentTime_AttributeGetter = 547,
+kV8Animation_CurrentTime_AttributeSetter = 548,
+kV8Animation_PlaybackRate_AttributeGetter = 549,
+kV8Animation_PlaybackRate_AttributeSetter = 550,
+kV8Animation_PlayState_AttributeGetter = 551,
+kV8Animation_Finish_Method = 552,
+kV8Animation_Play_Method = 553,
+kV8Animation_Pause_Method = 554,
+kV8Animation_Reverse_Method = 555,
+// The above items are available in M39 branch.
+
+kBreakIterator = 556,
+kScreenOrientationAngle = 557,
+kScreenOrientationType = 558,
+kScreenOrientationLock = 559,
+kScreenOrientationUnlock = 560,
+kGeolocationSecureOrigin = 561,
+kGeolocationInsecureOrigin = 562,
+kNotificationSecureOrigin = 563,
+kNotificationInsecureOrigin = 564,
+kNotificationShowEvent = 565,
+kSVGTransformListConsolidate = 569,
+kSVGAnimatedTransformListBaseVal = 570,
+kQuotedAnimationName = 571,
+kQuotedKeyframesRule = 572,
+kSrcsetDroppedCandidate = 573,
+kWindowPostMessage = 574,
+kRenderRuby = 576,
+kScriptElementWithInvalidTypeHasSrc = 578,
+kXMLHttpRequestSynchronousInNonWorkerOutsideBeforeUnload = 581,
+kCSSSelectorPseudoScrollbar = 582,
+kCSSSelectorPseudoScrollbarButton = 583,
+kCSSSelectorPseudoScrollbarThumb = 584,
+kCSSSelectorPseudoScrollbarTrack = 585,
+kCSSSelectorPseudoScrollbarTrackPiece = 586,
+kLangAttribute = 587,
+kLangAttributeOnHTML = 588,
+kLangAttributeOnBody = 589,
+kLangAttributeDoesNotMatchToUILocale = 590,
+kInputTypeSubmit = 591,
+kInputTypeSubmitWithValue = 592,
+// The above items are available in M40 branch.
+
+kSetReferrerPolicy = 593,
+kTextWholeText = 599,
+kNotificationCloseEvent = 603,
+kStyleMedia = 606,
+kStyleMediaType = 607,
+kStyleMediaMatchMedium = 608,
+kMixedContentPresent = 609,
+kMixedContentBlockable = 610,
+kMixedContentAudio = 611,
+kMixedContentDownload = 612,
+kMixedContentFavicon = 613,
+kMixedContentImage = 614,
+kMixedContentInternal = 615,
+kMixedContentPlugin = 616,
+kMixedContentPrefetch = 617,
+kMixedContentVideo = 618,
+kCSSSelectorPseudoFullScreenAncestor = 628,
+kCSSSelectorPseudoFullScreen = 629,
+kWebKitCSSMatrix = 630,
+kAudioContextCreateAnalyser = 631,
+kAudioContextCreateBiquadFilter = 632,
+kAudioContextCreateBufferSource = 633,
+kAudioContextCreateChannelMerger = 634,
+kAudioContextCreateChannelSplitter = 635,
+kAudioContextCreateConvolver = 636,
+kAudioContextCreateDelay = 637,
+kAudioContextCreateDynamicsCompressor = 638,
+kAudioContextCreateGain = 639,
+kAudioContextCreateMediaElementSource = 640,
+kAudioContextCreateMediaStreamDestination = 641,
+kAudioContextCreateMediaStreamSource = 642,
+kAudioContextCreateOscillator = 643,
+kAudioContextCreatePeriodicWave = 645,
+kAudioContextCreateScriptProcessor = 646,
+kAudioContextCreateStereoPanner = 647,
+kAudioContextCreateWaveShaper = 648,
+kAudioContextDecodeAudioData = 649,
+kAudioContextResume = 650,
+kAudioContextSuspend = 651,
+kMixedContentInNonHTTPSFrameThatRestrictsMixedContent = 661,
+kMixedContentInSecureFrameThatDoesNotRestrictMixedContent = 662,
+kMixedContentWebSocket = 663,
+kSyntheticKeyframesInCompositedCSSAnimation = 664,
+kMixedContentFormPresent = 665,
+kGetUserMediaInsecureOrigin = 666,
+kGetUserMediaSecureOrigin = 667,
+// The above items are available in M41 branch.
+
+kDeviceMotionInsecureOrigin = 668,
+kDeviceMotionSecureOrigin = 669,
+kDeviceOrientationInsecureOrigin = 670,
+kDeviceOrientationSecureOrigin = 671,
+kSandboxViaIFrame = 672,
+kSandboxViaCSP = 673,
+kBlockedSniffingImageToScript = 674,
+kFetch = 675,
+kFetchBodyStream = 676,
+kXMLHttpRequestAsynchronous = 677,
+kWhiteSpacePreFromXMLSpace = 679,
+kWhiteSpaceNowrapFromXMLSpace = 680,
+kSVGSVGElementForceRedraw = 685,
+kSVGSVGElementSuspendRedraw = 686,
+kSVGSVGElementUnsuspendRedraw = 687,
+kSVGSVGElementUnsuspendRedrawAll = 688,
+kAudioContextClose = 689,
+kCSSZoomNotEqualToOne = 691,
+// The above items are available in M42 branch.
+
+kClientRectListItem = 694,
+kWindowClientInformation = 695,
+kWindowFind = 696,
+kWindowScreenLeft = 697,
+kWindowScreenTop = 698,
+kV8Animation_Cancel_Method = 699,
+kV8Animation_Onfinish_AttributeGetter = 700,
+kV8Animation_Onfinish_AttributeSetter = 701,
+kV8Window_WebKitAnimationEvent_ConstructorGetter = 707,
+kCryptoGetRandomValues = 710,
+kSubtleCryptoEncrypt = 711,
+kSubtleCryptoDecrypt = 712,
+kSubtleCryptoSign = 713,
+kSubtleCryptoVerify = 714,
+kSubtleCryptoDigest = 715,
+kSubtleCryptoGenerateKey = 716,
+kSubtleCryptoImportKey = 717,
+kSubtleCryptoExportKey = 718,
+kSubtleCryptoDeriveBits = 719,
+kSubtleCryptoDeriveKey = 720,
+kSubtleCryptoWrapKey = 721,
+kSubtleCryptoUnwrapKey = 722,
+kCryptoAlgorithmAesCbc = 723,
+kCryptoAlgorithmHmac = 724,
+kCryptoAlgorithmRsaSsaPkcs1v1_5 = 725,
+kCryptoAlgorithmSha1 = 726,
+kCryptoAlgorithmSha256 = 727,
+kCryptoAlgorithmSha384 = 728,
+kCryptoAlgorithmSha512 = 729,
+kCryptoAlgorithmAesGcm = 730,
+kCryptoAlgorithmRsaOaep = 731,
+kCryptoAlgorithmAesCtr = 732,
+kCryptoAlgorithmAesKw = 733,
+kCryptoAlgorithmRsaPss = 734,
+kCryptoAlgorithmEcdsa = 735,
+kCryptoAlgorithmEcdh = 736,
+kCryptoAlgorithmHkdf = 737,
+kCryptoAlgorithmPbkdf2 = 738,
+kDocumentSetDomain = 739,
+kUpgradeInsecureRequestsEnabled = 740,
+kUpgradeInsecureRequestsUpgradedRequest = 741,
+kDocumentDesignMode = 742,
+kGlobalCacheStorage = 743,
+kNetInfo = 744,
+kBackgroundSync = 745,
+kLegacyConst = 748,
+kV8Permissions_Query_Method = 750,
+// The above items are available in M43 branch.
+
+kV8HTMLInputElement_Autocapitalize_AttributeGetter = 754,
+kV8HTMLInputElement_Autocapitalize_AttributeSetter = 755,
+kV8HTMLTextAreaElement_Autocapitalize_AttributeGetter = 756,
+kV8HTMLTextAreaElement_Autocapitalize_AttributeSetter = 757,
+kSVGHrefBaseVal = 758,
+kSVGHrefAnimVal = 759,
+kV8CSSRuleList_Item_Method = 760,
+kV8MediaList_Item_Method = 761,
+kV8StyleSheetList_Item_Method = 762,
+kStyleSheetListAnonymousNamedGetter = 763,
+kAutocapitalizeAttribute = 764,
+kFullscreenSecureOrigin = 765,
+kFullscreenInsecureOrigin = 766,
+kDialogInSandboxedContext = 767,
+kSVGSMILAnimationInImageRegardlessOfCache = 768,
+kPerformanceFrameTiming = 772,
+kV8Element_Animate_Method = 773,
+// The above items are available in M44 branch.
+
+kV8SVGSVGElement_GetElementById_Method = 778,
+kElementCreateShadowRootMultiple = 779,
+kV8MessageChannel_Constructor = 780,
+kV8MessagePort_PostMessage_Method = 781,
+kV8MessagePort_Start_Method = 782,
+kV8MessagePort_Close_Method = 783,
+kMessagePortsTransferred = 784,
+kCSSKeyframesRuleAnonymousIndexedGetter = 785,
+kV8Screen_AvailLeft_AttributeGetter = 786,
+kV8Screen_AvailTop_AttributeGetter = 787,
+kV8SVGFEConvolveMatrixElement_PreserveAlpha_AttributeGetter = 791,
+kV8SVGStyleElement_Disabled_AttributeGetter = 798,
+kV8SVGStyleElement_Disabled_AttributeSetter = 799,
+kInputTypeFileSecureOrigin = 801,
+kInputTypeFileInsecureOrigin = 802,
+kElementAttachShadow = 804,
+kV8SecurityPolicyViolationEvent_DocumentURI_AttributeGetter = 806,
+kV8SecurityPolicyViolationEvent_BlockedURI_AttributeGetter = 807,
+kV8SecurityPolicyViolationEvent_StatusCode_AttributeGetter = 808,
+kHTMLLinkElementDisabled = 809,
+kV8HTMLLinkElement_Disabled_AttributeGetter = 810,
+kV8HTMLLinkElement_Disabled_AttributeSetter = 811,
+kV8HTMLStyleElement_Disabled_AttributeGetter = 812,
+kV8HTMLStyleElement_Disabled_AttributeSetter = 813,
+kV8DOMError_Constructor = 816,
+kV8DOMError_Name_AttributeGetter = 817,
+kV8DOMError_Message_AttributeGetter = 818,
+kTextInputFired = 830,
+kV8TextEvent_Data_AttributeGetter = 831,
+kV8TextEvent_InitTextEvent_Method = 832,
+kClientHintsDPR = 835,
+kClientHintsResourceWidth = 836,
+kClientHintsViewportWidth = 837,
+kSRIElementIntegrityAttributeButIneligible = 838,
+kFormDataAppendNull = 843,
+kNonHTMLElementSetAttributeNodeFromHTMLDocumentNameNotLowercase = 845,
+kNavigatorVibrate = 850,
+kNavigatorVibrateSubFrame = 851,
+kV8XPathEvaluator_Constructor = 853,
+kV8XPathEvaluator_CreateExpression_Method = 854,
+kV8XPathEvaluator_CreateNSResolver_Method = 855,
+kV8XPathEvaluator_Evaluate_Method = 856,
+kRequestMIDIAccess = 857,
+kV8MouseEvent_LayerX_AttributeGetter = 858,
+kV8MouseEvent_LayerY_AttributeGetter = 859,
+kInnerTextWithShadowTree = 860,
+kSelectionToStringWithShadowTree = 861,
+kWindowFindWithShadowTree = 862,
+kV8CompositionEvent_InitCompositionEvent_Method = 863,
+kV8CustomEvent_InitCustomEvent_Method = 864,
+kV8DeviceMotionEvent_InitDeviceMotionEvent_Method = 865,
+kV8DeviceOrientationEvent_InitDeviceOrientationEvent_Method = 866,
+kV8Event_InitEvent_Method = 867,
+kV8KeyboardEvent_InitKeyboardEvent_Method = 868,
+kV8MouseEvent_InitMouseEvent_Method = 869,
+kV8MutationEvent_InitMutationEvent_Method = 870,
+kV8StorageEvent_InitStorageEvent_Method = 871,
+kV8UIEvent_InitUIEvent_Method = 873,
+kV8Document_CreateTouch_Method = 874,
+kRequestFileSystemNonWebbyOrigin = 876,
+kV8MemoryInfo_TotalJSHeapSize_AttributeGetter = 879,
+kV8MemoryInfo_UsedJSHeapSize_AttributeGetter = 880,
+kV8MemoryInfo_JSHeapSizeLimit_AttributeGetter = 881,
+kV8Performance_Timing_AttributeGetter = 882,
+kV8Performance_Navigation_AttributeGetter = 883,
+kV8Performance_Memory_AttributeGetter = 884,
+kV8SharedWorker_WorkerStart_AttributeGetter = 885,
+// The above items are available in M45 branch.
+
+kHTMLMediaElementPreloadNone = 892,
+kHTMLMediaElementPreloadMetadata = 893,
+kHTMLMediaElementPreloadAuto = 894,
+kHTMLMediaElementPreloadDefault = 895,
+kMixedContentBlockableAllowed = 896,
+kPseudoBeforeAfterForInputElement = 897,
+kV8Permissions_Revoke_Method = 898,
+kLinkRelDnsPrefetch = 899,
+kLinkRelPreconnect = 900,
+kLinkRelPreload = 901,
+kLinkHeaderDnsPrefetch = 902,
+kLinkHeaderPreconnect = 903,
+kClientHintsMetaAcceptCH = 904,
+kHTMLElementDeprecatedWidth = 905,
+kClientHintsContentDPR = 906,
+kElementAttachShadowOpen = 907,
+kElementAttachShadowClosed = 908,
+kAudioParamSetValueAtTime = 909,
+kAudioParamLinearRampToValueAtTime = 910,
+kAudioParamExponentialRampToValueAtTime = 911,
+kAudioParamSetTargetAtTime = 912,
+kAudioParamSetValueCurveAtTime = 913,
+kAudioParamCancelScheduledValues = 914,
+kV8Permissions_Request_Method = 915,
+kLinkRelPrefetch = 917,
+kLinkRelPrerender = 918,
+kLinkRelNext = 919,
+kCSSValuePrefixedMinContent = 921,
+kCSSValuePrefixedMaxContent = 922,
+kCSSValuePrefixedFitContent = 923,
+kCSSValuePrefixedFillAvailable = 924,
+kPresentationDefaultRequest = 926,
+kPresentationAvailabilityChangeEventListener = 927,
+kPresentationRequestConstructor = 928,
+kPresentationRequestStart = 929,
+kPresentationRequestReconnect = 930,
+kPresentationRequestGetAvailability = 931,
+kPresentationRequestConnectionAvailableEventListener = 932,
+kPresentationConnectionTerminate = 933,
+kPresentationConnectionSend = 934,
+kPresentationConnectionMessageEventListener = 936,
+kCSSAnimationsStackedNeutralKeyframe = 937,
+kReadingCheckedInClickHandler = 938,
+kFlexboxIntrinsicSizeAlgorithmIsDifferent = 939,
+// The above items are available in M46 branch.
+
+kHTMLImportsHasStyleSheets = 940,
+kNetInfoType = 946,
+kNetInfoDownlinkMax = 947,
+kNetInfoOnChange = 948,
+kNetInfoOnTypeChange = 949,
+kV8Window_Alert_Method = 950,
+kV8Window_Confirm_Method = 951,
+kV8Window_Prompt_Method = 952,
+kV8Window_Print_Method = 953,
+kV8Window_RequestIdleCallback_Method = 954,
+kFlexboxPercentagePaddingVertical = 955,
+kFlexboxPercentageMarginVertical = 956,
+kBackspaceNavigatedBack = 957,
+kBackspaceNavigatedBackAfterFormInteraction = 958,
+kCSPSourceWildcardWouldMatchExactHost = 959,
+kCredentialManagerGet = 960,
+kCredentialManagerGetMediationOptional = 961,
+kCredentialManagerGetMediationSilent = 962,
+kCredentialManagerStore = 963,
+kCredentialManagerRequireUserMediation = 964,
+// The above items are available in M47 branch.
+
+kBlockableMixedContentInSubframeBlocked = 966,
+kAddEventListenerThirdArgumentIsObject = 967,
+kRemoveEventListenerThirdArgumentIsObject = 968,
+kCSSAtRuleCharset = 969,
+kCSSAtRuleFontFace = 970,
+kCSSAtRuleImport = 971,
+kCSSAtRuleKeyframes = 972,
+kCSSAtRuleMedia = 973,
+kCSSAtRuleNamespace = 974,
+kCSSAtRulePage = 975,
+kCSSAtRuleSupports = 976,
+kCSSAtRuleViewport = 977,
+kCSSAtRuleWebkitKeyframes = 978,
+kV8HTMLFieldSetElement_Elements_AttributeGetter = 979,
+kHTMLMediaElementPreloadForcedNone = 980,
+kExternalAddSearchProvider = 981,
+kExternalIsSearchProviderInstalled = 982,
+kV8Permissions_RequestAll_Method = 983,
+kDeviceOrientationAbsoluteInsecureOrigin = 987,
+kDeviceOrientationAbsoluteSecureOrigin = 988,
+kFontFaceConstructor = 989,
+kServiceWorkerControlledPage = 990,
+kMeterElementWithMeterAppearance = 993,
+kMeterElementWithNoneAppearance = 994,
+kSelectionAnchorNode = 997,
+kSelectionAnchorOffset = 998,
+kSelectionFocusNode = 999,
+kSelectionFocusOffset = 1000,
+kSelectionIsCollapsed = 1001,
+kSelectionRangeCount = 1002,
+kSelectionGetRangeAt = 1003,
+kSelectionAddRange = 1004,
+kSelectionRemoveAllRanges = 1005,
+kSelectionCollapse = 1006,
+kSelectionCollapseToStart = 1007,
+kSelectionCollapseToEnd = 1008,
+kSelectionExtend = 1009,
+kSelectionSelectAllChildren = 1010,
+kSelectionDeleteDromDocument = 1011,
+kSelectionDOMString = 1012,
+kInputTypeRangeVerticalAppearance = 1013,
+// The above items are available in M48 branch.
+
+kCSSFilterReference = 1014,
+kCSSFilterGrayscale = 1015,
+kCSSFilterSepia = 1016,
+kCSSFilterSaturate = 1017,
+kCSSFilterHueRotate = 1018,
+kCSSFilterInvert = 1019,
+kCSSFilterOpacity = 1020,
+kCSSFilterBrightness = 1021,
+kCSSFilterContrast = 1022,
+kCSSFilterBlur = 1023,
+kCSSFilterDropShadow = 1024,
+kBackgroundSyncRegister = 1025,
+kExecCommandOnInputOrTextarea = 1027,
+kV8History_ScrollRestoration_AttributeGetter = 1028,
+kV8History_ScrollRestoration_AttributeSetter = 1029,
+kSVG1DOMFilter = 1030,
+kOfflineAudioContextStartRendering = 1031,
+kOfflineAudioContextSuspend = 1032,
+kOfflineAudioContextResume = 1033,
+kSVG1DOMPaintServer = 1035,
+kSVGSVGElementFragmentSVGView = 1036,
+kSVGSVGElementFragmentSVGViewElement = 1037,
+kPresentationConnectionClose = 1038,
+kSVG1DOMShape = 1039,
+kSVG1DOMText = 1040,
+kRTCPeerConnectionConstructorConstraints = 1041,
+kRTCPeerConnectionConstructorCompliant = 1042,
+kRTCPeerConnectionCreateOfferLegacyFailureCallback = 1044,
+kRTCPeerConnectionCreateOfferLegacyConstraints = 1045,
+kRTCPeerConnectionCreateOfferLegacyOfferOptions = 1046,
+kRTCPeerConnectionCreateOfferLegacyCompliant = 1047,
+kRTCPeerConnectionCreateAnswerLegacyFailureCallback = 1049,
+kRTCPeerConnectionCreateAnswerLegacyConstraints = 1050,
+kRTCPeerConnectionCreateAnswerLegacyCompliant = 1051,
+kRTCPeerConnectionSetLocalDescriptionLegacyNoSuccessCallback = 1052,
+kRTCPeerConnectionSetLocalDescriptionLegacyNoFailureCallback = 1053,
+kRTCPeerConnectionSetLocalDescriptionLegacyCompliant = 1054,
+kRTCPeerConnectionSetRemoteDescriptionLegacyNoSuccessCallback = 1055,
+kRTCPeerConnectionSetRemoteDescriptionLegacyNoFailureCallback = 1056,
+kRTCPeerConnectionSetRemoteDescriptionLegacyCompliant = 1057,
+kRTCPeerConnectionGetStatsLegacyNonCompliant = 1058,
+kNodeFilterIsFunction = 1059,
+kNodeFilterIsObject = 1060,
+kCSSSelectorInternalPseudoListBox = 1062,
+kCSSSelectorInternalMediaControlsOverlayCastButton = 1064,
+kCSSSelectorInternalPseudoSpatialNavigationFocus = 1065,
+kSameOriginTextScript = 1066,
+kSameOriginApplicationScript = 1067,
+kSameOriginOtherScript = 1068,
+kCrossOriginTextScript = 1069,
+kCrossOriginApplicationScript = 1070,
+kCrossOriginOtherScript = 1071,
+kSVG1DOMSVGTests = 1072,
+kDisableRemotePlaybackAttribute = 1074,
+kV8SloppyMode = 1075,
+kV8StrictMode = 1076,
+kV8StrongMode = 1077,
+kAudioNodeConnectToAudioNode = 1078,
+kAudioNodeConnectToAudioParam = 1079,
+kAudioNodeDisconnectFromAudioNode = 1080,
+kAudioNodeDisconnectFromAudioParam = 1081,
+kV8CSSFontFaceRule_Style_AttributeGetter = 1082,
+kSelectionCollapseNull = 1083,
+kSelectionSetBaseAndExtentNull = 1084,
+kV8SVGSVGElement_CreateSVGNumber_Method = 1085,
+kV8SVGSVGElement_CreateSVGLength_Method = 1086,
+kV8SVGSVGElement_CreateSVGAngle_Method = 1087,
+kV8SVGSVGElement_CreateSVGPoint_Method = 1088,
+kV8SVGSVGElement_CreateSVGMatrix_Method = 1089,
+kV8SVGSVGElement_CreateSVGRect_Method = 1090,
+kV8SVGSVGElement_CreateSVGTransform_Method = 1091,
+kV8SVGSVGElement_CreateSVGTransformFromMatrix_Method = 1092,
+kFormNameAccessForNonDescendantImageElement = 1093,
+kV8RegExpPrototypeStickyGetter = 1096,
+kV8RegExpPrototypeToString = 1097,
+kV8InputDeviceCapabilities_FiresTouchEvents_AttributeGetter = 1098,
+kDataElement = 1099,
+kTimeElement = 1100,
+kSVG1DOMUriReference = 1101,
+kSVG1DOMZoomAndPan = 1102,
+kV8SVGGraphicsElement_Transform_AttributeGetter = 1103,
+kMenuItemElement = 1104,
+kMenuItemCloseTag = 1105,
+kSVG1DOMMarkerElement = 1106,
+kSVG1DOMUseElement = 1107,
+kSVG1DOMMaskElement = 1108,
+kV8SVGAElement_Target_AttributeGetter = 1109,
+kV8SVGClipPathElement_ClipPathUnits_AttributeGetter = 1110,
+kSVG1DOMFitToViewBox = 1111,
+kSVG1DOMSVGElement = 1114,
+kSVG1DOMImageElement = 1115,
+kSVG1DOMForeignObjectElement = 1116,
+kAudioContextCreateIIRFilter = 1117,
+// The above items are available in M49 branch
+
+kCSSSelectorPseudoSlotted = 1118,
+kMediaDevicesEnumerateDevices = 1119,
+kNonSecureSharedWorkerAccessedFromSecureContext = 1120,
+kSecureSharedWorkerAccessedFromNonSecureContext = 1121,
+kEventComposedPath = 1123,
+kLinkHeaderPreload = 1124,
+kMouseWheelEvent = 1125,
+kWheelEvent = 1126,
+kMouseWheelAndWheelEvent = 1127,
+kBodyScrollsInAdditionToViewport = 1128,
+kDocumentDesignModeEnabeld = 1129,
+kContentEditableTrue = 1130,
+kContentEditableTrueOnHTML = 1131,
+kContentEditablePlainTextOnly = 1132,
+kV8RegExpPrototypeUnicodeGetter = 1133,
+kV8IntlV8Parse = 1134,
+kV8IntlPattern = 1135,
+kV8IntlResolved = 1136,
+kV8PromiseChain = 1137,
+kV8PromiseAccept = 1138,
+kV8PromiseDefer = 1139,
+kEventComposed = 1140,
+kGeolocationInsecureOriginIframe = 1141,
+kGeolocationSecureOriginIframe = 1142,
+kRequestMIDIAccessIframe = 1143,
+kGetUserMediaInsecureOriginIframe = 1144,
+kGetUserMediaSecureOriginIframe = 1145,
+kElementRequestPointerLockIframe = 1146,
+kNotificationAPIInsecureOriginIframe = 1147,
+kNotificationAPISecureOriginIframe = 1148,
+kWebSocket = 1149,
+kMediaStreamConstraintsNameValue = 1150,
+kMediaStreamConstraintsFromDictionary = 1151,
+kMediaStreamConstraintsConformant = 1152,
+kCSSSelectorIndirectAdjacent = 1153,
+kCreateImageBitmap = 1156,
+kPresentationConnectionConnectEventListener = 1157,
+kPresentationConnectionCloseEventListener = 1158,
+kPresentationConnectionTerminateEventListener = 1159,
+kDocumentCreateEventAnimationEvent = 1162,
+kDocumentCreateEventBeforeUnloadEvent = 1166,
+kDocumentCreateEventCompositionEvent = 1168,
+kDocumentCreateEventDragEvent = 1169,
+kDocumentCreateEventErrorEvent = 1170,
+kDocumentCreateEventFocusEvent = 1171,
+kDocumentCreateEventHashChangeEvent = 1172,
+kDocumentCreateEventMutationEvent = 1173,
+kDocumentCreateEventPageTransitionEvent = 1174,
+kDocumentCreateEventPopStateEvent = 1176,
+kDocumentCreateEventTextEvent = 1182,
+kDocumentCreateEventTransitionEvent = 1183,
+kDocumentCreateEventWheelEvent = 1184,
+kDocumentCreateEventTrackEvent = 1186,
+kDocumentCreateEventMutationEvents = 1188,
+kDocumentCreateEventSVGEvents = 1190,
+kDocumentCreateEventDeviceMotionEvent = 1195,
+kDocumentCreateEventDeviceOrientationEvent = 1196,
+kDocumentCreateEventIDBVersionChangeEvent = 1201,
+kDocumentCreateEventStorageEvent = 1221,
+kDocumentCreateEventWebGLContextEvent = 1224,
+kDocumentCreateEventCloseEvent = 1227,
+kDocumentCreateEventKeyboardEvents = 1228,
+kHTMLMediaElement = 1229,
+kHTMLMediaElementInDocument = 1230,
+kHTMLMediaElementControlsAttribute = 1231,
+kV8Animation_Oncancel_AttributeGetter = 1233,
+kV8Animation_Oncancel_AttributeSetter = 1234,
+kV8HTMLCommentInExternalScript = 1235,
+kV8HTMLComment = 1236,
+kV8SloppyModeBlockScopedFunctionRedefinition = 1237,
+kV8ForInInitializer = 1238,
+kV8Animation_Id_AttributeGetter = 1239,
+kV8Animation_Id_AttributeSetter = 1240,
+kApplicationCacheManifestSelectInsecureOrigin = 1245,
+kApplicationCacheManifestSelectSecureOrigin = 1246,
+kApplicationCacheAPIInsecureOrigin = 1247,
+kApplicationCacheAPISecureOrigin = 1248,
+// The above items are available in M50 branch
+
+kCSSAtRuleApply = 1249,
+kCSSSelectorPseudoAny = 1250,
+kDocumentAllItemNoArguments = 1252,
+kDocumentAllItemNamed = 1253,
+kDocumentAllItemIndexed = 1254,
+kDocumentAllItemIndexedWithNonNumber = 1255,
+kDocumentAllLegacyCallNoArguments = 1256,
+kDocumentAllLegacyCallNamed = 1257,
+kDocumentAllLegacyCallIndexed = 1258,
+kDocumentAllLegacyCallIndexedWithNonNumber = 1259,
+kDocumentAllLegacyCallTwoArguments = 1260,
+kHTMLLabelElementControlForNonFormAssociatedElement = 1263,
+kHTMLMediaElementLoadNetworkEmptyNotPaused = 1265,
+kV8Window_WebkitSpeechGrammar_ConstructorGetter = 1267,
+kV8Window_WebkitSpeechGrammarList_ConstructorGetter = 1268,
+kV8Window_WebkitSpeechRecognition_ConstructorGetter = 1269,
+kV8Window_WebkitSpeechRecognitionError_ConstructorGetter = 1270,
+kV8Window_WebkitSpeechRecognitionEvent_ConstructorGetter = 1271,
+kV8Window_SpeechSynthesis_AttributeGetter = 1272,
+kV8IDBFactory_WebkitGetDatabaseNames_Method = 1273,
+kImageDocument = 1274,
+kScriptPassesCSPDynamic = 1275,
+kCSPWithStrictDynamic = 1277,
+kScrollAnchored = 1278,
+kAddEventListenerFourArguments = 1279,
+kRemoveEventListenerFourArguments = 1280,
+kSVGCalcModeDiscrete = 1287,
+kSVGCalcModeLinear = 1288,
+kSVGCalcModePaced = 1289,
+kSVGCalcModeSpline = 1290,
+kFormSubmissionStarted = 1291,
+kFormValidationStarted = 1292,
+kFormValidationAbortedSubmission = 1293,
+kFormValidationShowedMessage = 1294,
+kWebAnimationsEasingAsFunctionLinear = 1295,
+kWebAnimationsEasingAsFunctionOther = 1296,
+// The above items are available in M51 branch
+
+kV8Document_Images_AttributeGetter = 1297,
+kV8Document_Embeds_AttributeGetter = 1298,
+kV8Document_Plugins_AttributeGetter = 1299,
+kV8Document_Links_AttributeGetter = 1300,
+kV8Document_Forms_AttributeGetter = 1301,
+kV8Document_Scripts_AttributeGetter = 1302,
+kV8Document_Anchors_AttributeGetter = 1303,
+kV8Document_Applets_AttributeGetter = 1304,
+kXMLHttpRequestCrossOriginWithCredentials = 1305,
+kMediaStreamTrackRemote = 1306,
+kV8Node_IsConnected_AttributeGetter = 1307,
+kShadowRootDelegatesFocus = 1308,
+kMixedShadowRootV0AndV1 = 1309,
+kImageDocumentInFrame = 1310,
+kMediaDocument = 1311,
+kMediaDocumentInFrame = 1312,
+kPluginDocument = 1313,
+kPluginDocumentInFrame = 1314,
+kSinkDocument = 1315,
+kSinkDocumentInFrame = 1316,
+kTextDocument = 1317,
+kTextDocumentInFrame = 1318,
+kViewSourceDocument = 1319,
+kFileAPINativeLineEndings = 1320,
+kPointerEventAttributeCount = 1321,
+kCompositedReplication = 1322,
+kV8DataTransferItem_WebkitGetAsEntry_Method = 1325,
+kV8HTMLInputElement_WebkitEntries_AttributeGetter = 1326,
+kEntry_Filesystem_AttributeGetter_IsolatedFileSystem = 1327,
+kEntry_GetMetadata_Method_IsolatedFileSystem = 1328,
+kEntry_MoveTo_Method_IsolatedFileSystem = 1329,
+kEntry_CopyTo_Method_IsolatedFileSystem = 1330,
+kEntry_Remove_Method_IsolatedFileSystem = 1331,
+kEntry_GetParent_Method_IsolatedFileSystem = 1332,
+kEntry_ToURL_Method_IsolatedFileSystem = 1333,
+kDuring_Microtask_Alert = 1334,
+kDuring_Microtask_Confirm = 1335,
+kDuring_Microtask_Print = 1336,
+kDuring_Microtask_Prompt = 1337,
+kDuring_Microtask_SyncXHR = 1338,
+kCredentialManagerGetReturnedCredential = 1342,
+kGeolocationInsecureOriginDeprecatedNotRemoved = 1343,
+kGeolocationInsecureOriginIframeDeprecatedNotRemoved = 1344,
+kProgressElementWithNoneAppearance = 1345,
+kProgressElementWithProgressBarAppearance = 1346,
+kPointerEventAddListenerCount = 1347,
+kCSSValueAppearanceNone = 1351,
+kCSSValueAppearanceNotNone = 1352,
+kCSSValueAppearanceOthers = 1353,
+kCSSValueAppearanceButton = 1354,
+kCSSValueAppearanceCaret = 1355,
+kCSSValueAppearanceCheckbox = 1356,
+kCSSValueAppearanceMenulist = 1357,
+kCSSValueAppearanceMenulistButton = 1358,
+kCSSValueAppearanceListbox = 1359,
+kCSSValueAppearanceRadio = 1360,
+kCSSValueAppearanceSearchField = 1361,
+kCSSValueAppearanceTextField = 1362,
+kAudioContextCreatePannerAutomated = 1363,
+kPannerNodeSetPosition = 1364,
+kPannerNodeSetOrientation = 1365,
+kAudioListenerSetPosition = 1366,
+kAudioListenerSetOrientation = 1367,
+kIntersectionObserver_Constructor = 1368,
+kDurableStoragePersist = 1369,
+kDurableStoragePersisted = 1370,
+kDurableStorageEstimate = 1371,
+kCSSDeepCombinatorAndShadow = 1375,
+kOpacityWithPreserve3DQuirk = 1376,
+kCSSSelectorPseudoReadOnly = 1377,
+kCSSSelectorPseudoReadWrite = 1378,
+// The above items are available in M52 branch
+
+kCSSSelectorPseudoDefined = 1383,
+kRTCPeerConnectionAddIceCandidatePromise = 1384,
+kRTCPeerConnectionAddIceCandidateLegacy = 1385,
+kRTCIceCandidateDefaultSdpMLineIndex = 1386,
+kMediaStreamConstraintsOldAndNew = 1389,
+kV8ArrayProtectorDirtied = 1390,
+kV8ArraySpeciesModified = 1391,
+kV8ArrayPrototypeConstructorModified = 1392,
+kV8ArrayInstanceProtoModified = 1393,
+kV8ArrayInstanceConstructorModified = 1394,
+kV8LegacyFunctionDeclaration = 1395,
+kV8RegExpPrototypeSourceGetter = 1396,
+kV8RegExpPrototypeOldFlagGetter = 1397,
+kV8DecimalWithLeadingZeroInStrictMode = 1398,
+kGetUserMediaPrefixed = 1400,
+kGetUserMediaLegacy = 1401,
+kGetUserMediaPromise = 1402,
+kCSSFilterFunctionNoArguments = 1403,
+kV8LegacyDateParser = 1404,
+kOpenSearchInsecureOriginInsecureTarget = 1405,
+kOpenSearchInsecureOriginSecureTarget = 1406,
+kOpenSearchSecureOriginInsecureTarget = 1407,
+kOpenSearchSecureOriginSecureTarget = 1408,
+kRegisterProtocolHandlerSecureOrigin = 1409,
+kRegisterProtocolHandlerInsecureOrigin = 1410,
+kCrossOriginWindowAlert = 1411,
+kCrossOriginWindowConfirm = 1412,
+kCrossOriginWindowPrompt = 1413,
+kCrossOriginWindowPrint = 1414,
+kMediaStreamOnActive = 1415,
+kMediaStreamOnInactive = 1416,
+kAddEventListenerPassiveTrue = 1417,
+kAddEventListenerPassiveFalse = 1418,
+kCSPReferrerDirective = 1419,
+kDocumentOpen = 1420,
+kElementRequestPointerLockInShadow = 1421,
+kShadowRootPointerLockElement = 1422,
+kDocumentPointerLockElementInV0Shadow = 1423,
+kTextAreaMaxLength = 1424,
+kTextAreaMinLength = 1425,
+kTopNavigationFromSubFrame = 1426,
+kPrefixedElementRequestFullscreenInShadow = 1427,
+kMediaSourceAbortRemove = 1428,
+kMediaSourceDurationTruncatingBuffered = 1429,
+kAudioContextCrossOriginIframe = 1430,
+// The above items are available in M53 branch
+
+kPointerEventSetCapture = 1431,
+kPointerEventDispatch = 1432,
+kMIDIMessageEventReceivedTime = 1433,
+kSummaryElementWithDisplayBlockAuthorRule = 1434,
+kV8MediaStream_Active_AttributeGetter = 1435,
+kBeforeInstallPromptEvent = 1436,
+kBeforeInstallPromptEventUserChoice = 1437,
+kBeforeInstallPromptEventPreventDefault = 1438,
+kBeforeInstallPromptEventPrompt = 1439,
+kExecCommandAltersHTMLStructure = 1440,
+kSecureContextCheckPassed = 1441,
+kSecureContextCheckFailed = 1442,
+kSecureContextCheckForSandboxedOriginPassed = 1443,
+kSecureContextCheckForSandboxedOriginFailed = 1444,
+kV8DefineGetterOrSetterWouldThrow = 1445,
+kV8FunctionConstructorReturnedUndefined = 1446,
+kV8BroadcastChannel_Constructor = 1447,
+kV8BroadcastChannel_PostMessage_Method = 1448,
+kV8BroadcastChannel_Close_Method = 1449,
+kTouchStartFired = 1450,
+kMouseDownFired = 1451,
+kPointerDownFired = 1452,
+kPointerDownFiredForTouch = 1453,
+kPointerEventDispatchPointerDown = 1454,
+kSVGSMILBeginOrEndEventValue = 1455,
+kSVGSMILBeginOrEndSyncbaseValue = 1456,
+kSVGSMILElementInsertedAfterLoad = 1457,
+kV8VisualViewport_OffsetLeft_AttributeGetter = 1458,
+kV8VisualViewport_OffsetTop_AttributeGetter = 1459,
+kV8VisualViewport_PageLeft_AttributeGetter = 1460,
+kV8VisualViewport_PageTop_AttributeGetter = 1461,
+kV8VisualViewport_Width_AttributeGetter = 1462,
+kV8VisualViewport_Height_AttributeGetter = 1463,
+kV8VisualViewport_Scale_AttributeGetter = 1464,
+kVisualViewportScrollFired = 1465,
+kVisualViewportResizeFired = 1466,
+kNodeGetRootNode = 1467,
+kSlotChangeEventAddListener = 1468,
+kCSSValueAppearanceButtonRendered = 1469,
+kCSSValueAppearanceButtonForAnchor = 1470,
+kCSSValueAppearanceButtonForButton = 1471,
+kCSSValueAppearanceButtonForOtherButtons = 1472,
+kCSSValueAppearanceTextFieldRendered = 1473,
+kCSSValueAppearanceTextFieldForSearch = 1474,
+kCSSValueAppearanceTextFieldForTextField = 1475,
+kRTCPeerConnectionGetStats = 1476,
+kSVGSMILAnimationAppliedEffect = 1477,
+kPerformanceResourceTimingSizes = 1478,
+kEventSourceDocument = 1479,
+kEventSourceWorker = 1480,
+kSingleOriginInTimingAllowOrigin = 1481,
+kMultipleOriginsInTimingAllowOrigin = 1482,
+kStarInTimingAllowOrigin = 1483,
+kSVGSMILAdditiveAnimation = 1484,
+kSendBeaconWithNonSimpleContentType = 1485,
+kChromeLoadTimesRequestTime = 1486,
+kChromeLoadTimesStartLoadTime = 1487,
+kChromeLoadTimesCommitLoadTime = 1488,
+kChromeLoadTimesFinishDocumentLoadTime = 1489,
+kChromeLoadTimesFinishLoadTime = 1490,
+kChromeLoadTimesFirstPaintTime = 1491,
+kChromeLoadTimesFirstPaintAfterLoadTime = 1492,
+kChromeLoadTimesNavigationType = 1493,
+kChromeLoadTimesWasFetchedViaSpdy = 1494,
+kChromeLoadTimesWasNpnNegotiated = 1495,
+kChromeLoadTimesNpnNegotiatedProtocol = 1496,
+kChromeLoadTimesWasAlternateProtocolAvailable = 1497,
+kChromeLoadTimesConnectionInfo = 1498,
+kChromeLoadTimesUnknown = 1499,
+kSVGViewElement = 1500,
+kWebShareShare = 1501,
+kAuxclickAddListenerCount = 1502,
+kHTMLCanvasElement = 1503,
+kSVGSMILAnimationElementTiming = 1504,
+kSVGSMILBeginEndAnimationElement = 1505,
+kSVGSMILPausing = 1506,
+kSVGSMILCurrentTime = 1507,
+kHTMLBodyElementOnSelectionChangeAttribute = 1508,
+kForeignFetchInterception = 1509,
+kUsbGetDevices = 1519,
+kUsbRequestDevice = 1520,
+kUsbDeviceOpen = 1521,
+kUsbDeviceClose = 1522,
+kUsbDeviceSelectConfiguration = 1523,
+kUsbDeviceClaimInterface = 1524,
+kUsbDeviceReleaseInterface = 1525,
+kUsbDeviceSelectAlternateInterface = 1526,
+kUsbDeviceControlTransferIn = 1527,
+kUsbDeviceControlTransferOut = 1528,
+kUsbDeviceClearHalt = 1529,
+kUsbDeviceTransferIn = 1530,
+kUsbDeviceTransferOut = 1531,
+kUsbDeviceIsochronousTransferIn = 1532,
+kUsbDeviceIsochronousTransferOut = 1533,
+kUsbDeviceReset = 1534,
+// The above items are available in M54 branch
+
+kPointerEnterLeaveFired = 1535,
+kPointerOverOutFired = 1536,
+kDraggableAttribute = 1539,
+kCleanScriptElementWithNonce = 1540,
+kPotentiallyInjectedScriptElementWithNonce = 1541,
+kPendingStylesheetAddedAfterBodyStarted = 1542,
+kUntrustedMouseDownEventDispatchedToSelect = 1543,
+kBlockedSniffingAudioToScript = 1544,
+kBlockedSniffingVideoToScript = 1545,
+kBlockedSniffingCSVToScript = 1546,
+kMetaSetCookie = 1547,
+kMetaRefresh = 1548,
+kMetaSetCookieWhenCSPBlocksInlineScript = 1549,
+kMetaRefreshWhenCSPBlocksInlineScript = 1550,
+kMiddleClickAutoscrollStart = 1551,
+kRTCPeerConnectionCreateOfferOptionsOfferToReceive = 1553,
+kDragAndDropScrollStart = 1554,
+kPresentationConnectionListConnectionAvailableEventListener = 1555,
+kWebAudioAutoplayCrossOriginIframe = 1556,
+kVRGetDisplays = 1558,
+kXSSAuditorBlockedScript = 1581,
+kXSSAuditorBlockedEntirePage = 1582,
+kXSSAuditorDisabled = 1583,
+kXSSAuditorEnabledFilter = 1584,
+kXSSAuditorEnabledBlock = 1585,
+kXSSAuditorInvalid = 1586,
+kTextInputEventOnInput = 1589,
+kTextInputEventOnTextArea = 1590,
+kTextInputEventOnContentEditable = 1591,
+kTextInputEventOnNotNode = 1592,
+kWebkitBeforeTextInsertedOnInput = 1593,
+kWebkitBeforeTextInsertedOnTextArea = 1594,
+kWebkitBeforeTextInsertedOnContentEditable = 1595,
+kWebkitBeforeTextInsertedOnNotNode = 1596,
+kWebkitEditableContentChangedOnInput = 1597,
+kWebkitEditableContentChangedOnTextArea = 1598,
+kWebkitEditableContentChangedOnContentEditable = 1599,
+kWebkitEditableContentChangedOnNotNode = 1600,
+kV8NavigatorUserMediaError_ConstraintName_AttributeGetter = 1601,
+kV8HTMLMediaElement_SrcObject_AttributeGetter = 1602,
+kV8HTMLMediaElement_SrcObject_AttributeSetter = 1603,
+kCreateObjectURLBlob = 1604,
+kCreateObjectURLMediaSource = 1605,
+kCreateObjectURLMediaStream = 1606,
+kDocumentCreateTouchWindowNull = 1607,
+kDocumentCreateTouchWindowWrongType = 1608,
+kDocumentCreateTouchTargetNull = 1609,
+kDocumentCreateTouchTargetWrongType = 1610,
+kDocumentCreateTouchMoreThanSevenArguments = 1612,
+kLongTaskObserver = 1615,
+kCSSOffsetInEffect = 1617,
+// The above items are available in M55 branch
+
+kVRGetDisplaysInsecureOrigin = 1618,
+kVRRequestPresent = 1619,
+kVRRequestPresentInsecureOrigin = 1620,
+kVRDeprecatedFieldOfView = 1621,
+kVideoInCanvas = 1622,
+kHiddenAutoplayedVideoInCanvas = 1623,
+kOffscreenCanvas = 1624,
+kGamepadPose = 1625,
+kGamepadHand = 1626,
+kGamepadDisplayId = 1627,
+kGamepadButtonTouched = 1628,
+kGamepadPoseHasOrientation = 1629,
+kGamepadPoseHasPosition = 1630,
+kGamepadPosePosition = 1631,
+kGamepadPoseLinearVelocity = 1632,
+kGamepadPoseLinearAcceleration = 1633,
+kGamepadPoseOrientation = 1634,
+kGamepadPoseAngularVelocity = 1635,
+kGamepadPoseAngularAcceleration = 1636,
+kV8RTCDataChannel_MaxRetransmitTime_AttributeGetter = 1638,
+kV8RTCDataChannel_MaxRetransmits_AttributeGetter = 1639,
+kV8RTCDataChannel_Reliable_AttributeGetter = 1640,
+kV8RTCPeerConnection_AddStream_Method = 1641,
+kV8RTCPeerConnection_CreateDTMFSender_Method = 1642,
+kV8RTCPeerConnection_GetLocalStreams_Method = 1643,
+kV8RTCPeerConnection_GetRemoteStreams_Method = 1644,
+kV8RTCPeerConnection_GetStreamById_Method = 1645,
+kV8RTCPeerConnection_RemoveStream_Method = 1646,
+kRTCPeerConnectionCreateDataChannelMaxRetransmitTime = 1648,
+kRTCPeerConnectionCreateDataChannelMaxRetransmits = 1649,
+kAudioContextCreateConstantSource = 1650,
+kWebAudioConstantSourceNode = 1651,
+kLoopbackEmbeddedInSecureContext = 1652,
+kLoopbackEmbeddedInNonSecureContext = 1653,
+kBlinkMacSystemFont = 1654,
+kRTCIceServerURL = 1656,
+kRTCIceServerURLs = 1657,
+kOffscreenCanvasTransferToImageBitmap2D = 1658,
+kOffscreenCanvasTransferToImageBitmapWebGL = 1659,
+kOffscreenCanvasCommit2D = 1660,
+kOffscreenCanvasCommitWebGL = 1661,
+kRTCConfigurationIceTransportPolicy = 1662,
+kRTCConfigurationIceTransports = 1664,
+kDocumentFullscreenElementInV0Shadow = 1665,
+kScriptWithCSPBypassingSchemeParserInserted = 1666,
+kScriptWithCSPBypassingSchemeNotParserInserted = 1667,
+kDocumentCreateElement2ndArgStringHandling = 1668,
+kV8MediaRecorder_Start_Method = 1669,
+kWebBluetoothRequestDevice = 1670,
+kUnitlessPerspectiveInPerspectiveProperty = 1671,
+kUnitlessPerspectiveInTransformProperty = 1672,
+kV8RTCSessionDescription_Type_AttributeGetter = 1673,
+kV8RTCSessionDescription_Type_AttributeSetter = 1674,
+kV8RTCSessionDescription_Sdp_AttributeGetter = 1675,
+kV8RTCSessionDescription_Sdp_AttributeSetter = 1676,
+kRTCSessionDescriptionInitNoType = 1677,
+kRTCSessionDescriptionInitNoSdp = 1678,
+kHTMLMediaElementPreloadForcedMetadata = 1679,
+kGenericSensorStart = 1680,
+kGenericSensorStop = 1681,
+kTouchEventPreventedNoTouchAction = 1682,
+kTouchEventPreventedForcedDocumentPassiveNoTouchAction = 1683,
+kV8Event_StopPropagation_Method = 1684,
+kV8Event_StopImmediatePropagation_Method = 1685,
+kImageCaptureConstructor = 1686,
+kV8Document_RootScroller_AttributeGetter = 1687,
+kV8Document_RootScroller_AttributeSetter = 1688,
+kCustomElementRegistryDefine = 1689,
+kLinkHeaderServiceWorker = 1690,
+kCSSShadowPiercingDescendantCombinator = 1691,
+// The above items are available in M56 branch.
+
+kCSSFlexibleBox = 1692,
+kCSSGridLayout = 1693,
+kFullscreenAllowedByOrientationChange = 1696,
+kServiceWorkerRespondToNavigationRequestWithRedirectedResponse = 1697,
+kV8AudioContext_Constructor = 1698,
+kV8OfflineAudioContext_Constructor = 1699,
+kAppInstalledEventAddListener = 1700,
+kAudioContextGetOutputTimestamp = 1701,
+kV8MediaStreamAudioDestinationNode_Constructor = 1702,
+kV8AnalyserNode_Constructor = 1703,
+kV8AudioBuffer_Constructor = 1704,
+kV8AudioBufferSourceNode_Constructor = 1705,
+kV8AudioProcessingEvent_Constructor = 1706,
+kV8BiquadFilterNode_Constructor = 1707,
+kV8ChannelMergerNode_Constructor = 1708,
+kV8ChannelSplitterNode_Constructor = 1709,
+kV8ConstantSourceNode_Constructor = 1710,
+kV8ConvolverNode_Constructor = 1711,
+kV8DelayNode_Constructor = 1712,
+kV8DynamicsCompressorNode_Constructor = 1713,
+kV8GainNode_Constructor = 1714,
+kV8IIRFilterNode_Constructor = 1715,
+kV8MediaElementAudioSourceNode_Constructor = 1716,
+kV8MediaStreamAudioSourceNode_Constructor = 1717,
+kV8OfflineAudioCompletionEvent_Constructor = 1718,
+kV8OscillatorNode_Constructor = 1719,
+kV8PannerNode_Constructor = 1720,
+kV8PeriodicWave_Constructor = 1721,
+kV8StereoPannerNode_Constructor = 1722,
+kV8WaveShaperNode_Constructor = 1723,
+kV8Headers_GetAll_Method = 1724,
+kNavigatorVibrateEngagementNone = 1725,
+kNavigatorVibrateEngagementMinimal = 1726,
+kNavigatorVibrateEngagementLow = 1727,
+kNavigatorVibrateEngagementMedium = 1728,
+kNavigatorVibrateEngagementHigh = 1729,
+kNavigatorVibrateEngagementMax = 1730,
+kAlertEngagementNone = 1731,
+kAlertEngagementMinimal = 1732,
+kAlertEngagementLow = 1733,
+kAlertEngagementMedium = 1734,
+kAlertEngagementHigh = 1735,
+kAlertEngagementMax = 1736,
+kConfirmEngagementNone = 1737,
+kConfirmEngagementMinimal = 1738,
+kConfirmEngagementLow = 1739,
+kConfirmEngagementMedium = 1740,
+kConfirmEngagementHigh = 1741,
+kConfirmEngagementMax = 1742,
+kPromptEngagementNone = 1743,
+kPromptEngagementMinimal = 1744,
+kPromptEngagementLow = 1745,
+kPromptEngagementMedium = 1746,
+kPromptEngagementHigh = 1747,
+kPromptEngagementMax = 1748,
+kTopNavInSandbox = 1749,
+kTopNavInSandboxWithoutGesture = 1750,
+kTopNavInSandboxWithPerm = 1751,
+kTopNavInSandboxWithPermButNoGesture = 1752,
+kReferrerPolicyHeader = 1753,
+kHTMLAnchorElementReferrerPolicyAttribute = 1754,
+kHTMLIFrameElementReferrerPolicyAttribute = 1755,
+kHTMLImageElementReferrerPolicyAttribute = 1756,
+kHTMLLinkElementReferrerPolicyAttribute = 1757,
+kBaseElement = 1758,
+kBaseWithCrossOriginHref = 1759,
+kBaseWithDataHref = 1760,
+kBaseWithNewlinesInTarget = 1761,
+kBaseWithOpenBracketInTarget = 1762,
+kBaseWouldBeBlockedByDefaultSrc = 1763,
+kV8AssigmentExpressionLHSIsCallInSloppy = 1764,
+kV8AssigmentExpressionLHSIsCallInStrict = 1765,
+kV8PromiseConstructorReturnedUndefined = 1766,
+kFormSubmittedWithUnclosedFormControl = 1767,
+kScrollbarUseVerticalScrollbarButton = 1777,
+kScrollbarUseVerticalScrollbarThumb = 1778,
+kScrollbarUseVerticalScrollbarTrack = 1779,
+kScrollbarUseHorizontalScrollbarButton = 1780,
+kScrollbarUseHorizontalScrollbarThumb = 1781,
+kScrollbarUseHorizontalScrollbarTrack = 1782,
+kHTMLTableCellElementColspan = 1783,
+kHTMLTableCellElementColspanGreaterThan1000 = 1784,
+kHTMLTableCellElementColspanGreaterThan8190 = 1785,
+kSelectionAddRangeIntersect = 1786,
+kPostMessageFromInsecureToSecureToplevel = 1787,
+// The above items are available in M57 branch.
+
+kV8MediaSession_Metadata_AttributeGetter = 1788,
+kV8MediaSession_Metadata_AttributeSetter = 1789,
+kV8MediaSession_PlaybackState_AttributeGetter = 1790,
+kV8MediaSession_PlaybackState_AttributeSetter = 1791,
+kV8MediaSession_SetActionHandler_Method = 1792,
+kWebNFCPush = 1793,
+kWebNFCCancelPush = 1794,
+kWebNFCWatch = 1795,
+kWebNFCCancelWatch = 1796,
+kAudioParamCancelAndHoldAtTime = 1797,
+kCSSValueUserModifyReadOnly = 1798,
+kCSSValueUserModifyReadWrite = 1799,
+kCSSValueUserModifyReadWritePlaintextOnly = 1800,
+kCSSValueOnDemand = 1802,
+kServiceWorkerNavigationPreload = 1803,
+kFullscreenRequestWithPendingElement = 1804,
+kHTMLIFrameElementAllowfullscreenAttributeSetAfterContentLoad = 1805,
+kPointerEventSetCaptureOutsideDispatch = 1806,
+kNotificationPermissionRequestedInsecureOrigin = 1807,
+kV8DeprecatedStorageInfo_QueryUsageAndQuota_Method = 1808,
+kV8DeprecatedStorageInfo_RequestQuota_Method = 1809,
+kV8DeprecatedStorageQuota_QueryUsageAndQuota_Method = 1810,
+kV8DeprecatedStorageQuota_RequestQuota_Method = 1811,
+kV8FileReaderSync_Constructor = 1812,
+kUncancelableTouchEventPreventDefaulted = 1813,
+kUncancelableTouchEventDueToMainThreadResponsivenessPreventDefaulted = 1814,
+kV8HTMLVideoElement_Poster_AttributeGetter = 1815,
+kV8HTMLVideoElement_Poster_AttributeSetter = 1816,
+kNotificationPermissionRequestedIframe = 1817,
+kPresentationReceiverInsecureOrigin = 1819,
+kPresentationReceiverSecureOrigin = 1820,
+kPresentationRequestInsecureOrigin = 1821,
+kPresentationRequestSecureOrigin = 1822,
+kRtcpMuxPolicyNegotiate = 1823,
+kDOMClobberedVariableAccessed = 1824,
+kHTMLDocumentCreateProcessingInstruction = 1825,
+kFetchResponseConstructionWithStream = 1826,
+kLocationOrigin = 1827,
+kDocumentOrigin = 1828,
+kCanvas2DFilter = 1830,
+kCanvas2DImageSmoothingQuality = 1831,
+kCanvasToBlob = 1832,
+kCanvasToDataURL = 1833,
+kOffscreenCanvasConvertToBlob = 1834,
+kSVGInCanvas2D = 1835,
+kSVGInWebGL = 1836,
+kSelectionFuncionsChangeFocus = 1837,
+kHTMLObjectElementGetter = 1838,
+kHTMLObjectElementSetter = 1839,
+kHTMLEmbedElementGetter = 1840,
+kHTMLEmbedElementSetter = 1841,
+kTransformUsesBoxSizeOnSVG = 1842,
+// The above items are available in M58 branch.
+
+kScrollByKeyboardArrowKeys = 1843,
+kScrollByKeyboardPageUpDownKeys = 1844,
+kScrollByKeyboardHomeEndKeys = 1845,
+kScrollByKeyboardSpacebarKey = 1846,
+kScrollByTouch = 1847,
+kScrollByWheel = 1848,
+kScheduledActionIgnored = 1849,
+kGetCanvas2DContextAttributes = 1850,
+kV8HTMLInputElement_Capture_AttributeGetter = 1851,
+kV8HTMLInputElement_Capture_AttributeSetter = 1852,
+kHTMLMediaElementControlsListAttribute = 1853,
+kHTMLMediaElementControlsListNoDownload = 1854,
+kHTMLMediaElementControlsListNoFullscreen = 1855,
+kHTMLMediaElementControlsListNoRemotePlayback = 1856,
+kPointerEventClickRetargetCausedByCapture = 1857,
+kVRDisplayDisplayName = 1861,
+kVREyeParametersOffset = 1862,
+kVRPoseLinearVelocity = 1863,
+kVRPoseLinearAcceleration = 1864,
+kVRPoseAngularVelocity = 1865,
+kVRPoseAngularAcceleration = 1866,
+kCSSOverflowPaged = 1867,
+kChildSrcAllowedWorkerThatScriptSrcBlocked = 1868,
+kHTMLTableElementPresentationAttributeBackground = 1869,
+kV8Navigator_GetInstalledRelatedApps_Method = 1870,
+kNamedAccessOnWindow_ChildBrowsingContext = 1871,
+kNamedAccessOnWindow_ChildBrowsingContext_CrossOriginNameMismatch = 1872,
+kV0CustomElementsRegisterHTMLCustomTag = 1873,
+kV0CustomElementsRegisterHTMLTypeExtension = 1874,
+kV0CustomElementsRegisterSVGElement = 1875,
+kV0CustomElementsRegisterEmbedderElement = 1876,
+kV0CustomElementsCreateCustomTagElement = 1877,
+kV0CustomElementsCreateTypeExtensionElement = 1878,
+kV0CustomElementsConstruct = 1879,
+kV8IDBObserver_Observe_Method = 1880,
+kV8IDBObserver_Unobserve_Method = 1881,
+kWebBluetoothRemoteCharacteristicGetDescriptor = 1882,
+kWebBluetoothRemoteCharacteristicGetDescriptors = 1883,
+kWebBluetoothRemoteCharacteristicReadValue = 1884,
+kWebBluetoothRemoteCharacteristicWriteValue = 1885,
+kWebBluetoothRemoteCharacteristicStartNotifications = 1886,
+kWebBluetoothRemoteCharacteristicStopNotifications = 1887,
+kWebBluetoothRemoteDescriptorReadValue = 1888,
+kWebBluetoothRemoteDescriptorWriteValue = 1889,
+kWebBluetoothRemoteServerConnect = 1890,
+kWebBluetoothRemoteServerDisconnect = 1891,
+kWebBluetoothRemoteServerGetPrimaryService = 1892,
+kWebBluetoothRemoteServerGetPrimaryServices = 1893,
+kWebBluetoothRemoteServiceGetCharacteristic = 1894,
+kWebBluetoothRemoteServiceGetCharacteristics = 1895,
+kHTMLContentElement = 1896,
+kHTMLShadowElement = 1897,
+kHTMLSlotElement = 1898,
+kAccelerometerConstructor = 1899,
+kAbsoluteOrientationSensorConstructor = 1900,
+kAmbientLightSensorConstructor = 1901,
+kGenericSensorOnActivate = 1902,
+kGenericSensorOnChange = 1903,
+kGenericSensorOnError = 1904,
+kGenericSensorActivated = 1905,
+kGyroscopeConstructor = 1906,
+kMagnetometerConstructor = 1907,
+kOrientationSensorPopulateMatrix = 1908,
+kWindowOpenWithInvalidURL = 1909,
+kCrossOriginMainFrameNulledNameAccessed = 1910,
+kMenuItemElementIconAttribute = 1911,
+kWebkitCSSMatrixSetMatrixValue = 1912,
+kWebkitCSSMatrixConstructFromString = 1913,
+kCanRequestURLHTTPContainingNewline = 1914,
+kGetGamepads = 1916,
+kV8SVGPathElement_GetPathSegAtLength_Method = 1917,
+kMediaStreamConstraintsAudio = 1918,
+kMediaStreamConstraintsAudioUnconstrained = 1919,
+kMediaStreamConstraintsVideo = 1920,
+kMediaStreamConstraintsVideoUnconstrained = 1921,
+kMediaStreamConstraintsWidth = 1922,
+kMediaStreamConstraintsHeight = 1923,
+kMediaStreamConstraintsAspectRatio = 1924,
+kMediaStreamConstraintsFrameRate = 1925,
+kMediaStreamConstraintsFacingMode = 1926,
+kMediaStreamConstraintsVolume = 1927,
+kMediaStreamConstraintsSampleRate = 1928,
+kMediaStreamConstraintsSampleSize = 1929,
+kMediaStreamConstraintsEchoCancellation = 1930,
+kMediaStreamConstraintsLatency = 1931,
+kMediaStreamConstraintsChannelCount = 1932,
+kMediaStreamConstraintsDeviceIdAudio = 1933,
+kMediaStreamConstraintsDeviceIdVideo = 1934,
+kMediaStreamConstraintsDisableLocalEcho = 1935,
+kMediaStreamConstraintsGroupIdAudio = 1936,
+kMediaStreamConstraintsGroupIdVideo = 1937,
+kMediaStreamConstraintsVideoKind = 1938,
+kMediaStreamConstraintsDepthNear = 1939,
+kMediaStreamConstraintsDepthFar = 1940,
+kMediaStreamConstraintsFocalLengthX = 1941,
+kMediaStreamConstraintsFocalLengthY = 1942,
+kMediaStreamConstraintsMediaStreamSourceAudio = 1943,
+kMediaStreamConstraintsMediaStreamSourceVideo = 1944,
+kMediaStreamConstraintsRenderToAssociatedSink = 1945,
+kMediaStreamConstraintsHotwordEnabled = 1946,
+kMediaStreamConstraintsGoogEchoCancellation = 1947,
+kMediaStreamConstraintsGoogExperimentalEchoCancellation = 1948,
+kMediaStreamConstraintsGoogAutoGainControl = 1949,
+kMediaStreamConstraintsGoogExperimentalAutoGainControl = 1950,
+kMediaStreamConstraintsGoogNoiseSuppression = 1951,
+kMediaStreamConstraintsGoogHighpassFilter = 1952,
+kMediaStreamConstraintsGoogTypingNoiseDetection = 1953,
+kMediaStreamConstraintsGoogExperimentalNoiseSuppression = 1954,
+kMediaStreamConstraintsGoogBeamforming = 1955,
+kMediaStreamConstraintsGoogArrayGeometry = 1956,
+kMediaStreamConstraintsGoogAudioMirroring = 1957,
+kMediaStreamConstraintsGoogDAEchoCancellation = 1958,
+kMediaStreamConstraintsGoogNoiseReduction = 1959,
+kMediaStreamConstraintsGoogPowerLineFrequency = 1960,
+// The above items are available in M59 branch.
+
+kViewportFixedPositionUnderFilter = 1961,
+kRequestMIDIAccessWithSysExOption = 1962,
+kRequestMIDIAccessIframeWithSysExOption = 1963,
+kGamepadAxes = 1964,
+kGamepadButtons = 1965,
+kVibrateWithoutUserGesture = 1966,
+kDispatchMouseEventOnDisabledFormControl = 1967,
+kElementNameDOMInvalidHTMLParserValid = 1968,
+kElementNameDOMValidHTMLParserInvalid = 1969,
+kGATTServerDisconnectedEvent = 1970,
+kAnchorClickDispatchForNonConnectedNode = 1971,
+kHTMLParseErrorNestedForm = 1972,
+kFontShapingNotDefGlyphObserved = 1973,
+kPostMessageOutgoingWouldBeBlockedByConnectSrc = 1974,
+kPostMessageIncomingWouldBeBlockedByConnectSrc = 1975,
+kPaymentRequestNetworkNameInSupportedMethods = 1976,
+kCrossOriginPropertyAccess = 1977,
+kCrossOriginPropertyAccessFromOpener = 1978,
+kCredentialManagerCreate = 1979,
+kWebDatabaseCreateDropFTS3Table = 1980,
+kFieldEditInSecureContext = 1981,
+kFieldEditInNonSecureContext = 1982,
+kCredentialManagerCredentialRequestOptionsUnmediated = 1983,
+kCredentialManagerGetMediationRequired = 1984,
+kCredentialManagerIdName = 1985,
+kCredentialManagerPasswordName = 1986,
+kCredentialManagerAdditionalData = 1987,
+kCredentialManagerCustomFetch = 1988,
+kNetInfoRtt = 1989,
+kNetInfoDownlink = 1990,
+kShapeDetection_BarcodeDetectorConstructor = 1991,
+kShapeDetection_FaceDetectorConstructor = 1992,
+kShapeDetection_TextDetectorConstructor = 1993,
+kCredentialManagerCredentialRequestOptionsOnlyUnmediated = 1994,
+kInertAttribute = 1995,
+kPluginInstanceAccessFromIsolatedWorld = 1996,
+kPluginInstanceAccessFromMainWorld = 1997,
+kRequestFullscreenForDialogElement = 1998,
+kRequestFullscreenForDialogElementInTopLayer = 1999,
+kShowModalForElementInFullscreenStack = 2000,
+kThreeValuedPositionBackground = 2001,
+kThreeValuedPositionBasicShape = 2002,
+kThreeValuedPositionGradient = 2003,
+kThreeValuedPositionObjectPosition = 2004,
+kThreeValuedPositionPerspectiveOrigin = 2005,
+kUnitlessZeroAngleFilter = 2007,
+kUnitlessZeroAngleGradient = 2008,
+kUnitlessZeroAngleOffsetRotate = 2009,
+kUnitlessZeroAngleTransform = 2010,
+kHTMLOListElementStartGetterReversedWithoutStartAttribute = 2011,
+kCredentialManagerPreventSilentAccess = 2012,
+kNetInfoEffectiveType = 2013,
+kV8SpeechRecognition_Start_Method = 2014,
+kTableRowDirectionDifferentFromTable = 2015,
+kTableSectionDirectionDifferentFromTable = 2016,
+// The above items are available in M60 branch.
+
+kClientHintsDeviceRAM = 2017,
+kCSSRegisterProperty = 2018,
+// 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
+// chromium/src/tools/metrics/histograms/ to update the UMA mapping.
+kNumberOfFeatures,  // This enum value must be last.
diff --git a/third_party/WebKit/public/platform/WebDisplayItemList.h b/third_party/WebKit/public/platform/WebDisplayItemList.h
index 351e962a..ca3ddc50 100644
--- a/third_party/WebKit/public/platform/WebDisplayItemList.h
+++ b/third_party/WebKit/public/platform/WebDisplayItemList.h
@@ -67,7 +67,7 @@
                                 ScrollContainerId) {}
   virtual void AppendEndScrollItem() {}
 
-  virtual void SetIsSuitableForGpuRasterization(bool is_suitable) {}
+  virtual void SetNumSlowPaths(int num_slow_paths) {}
 };
 
 }  // namespace blink
diff --git a/third_party/WebKit/public/platform/WebFeature.h b/third_party/WebKit/public/platform/WebFeature.h
new file mode 100644
index 0000000..0acc877
--- /dev/null
+++ b/third_party/WebKit/public/platform/WebFeature.h
@@ -0,0 +1,18 @@
+#ifndef WebFeature_h
+#define WebFeature_h
+
+namespace blink {
+
+// A WebFeature conceptually represents some particular web-exposed API
+// or code path which can be used/triggered by a web page.
+// TODO(lunalu): Replace occurance of UseCounter::Feature by WebFeature in
+// Blink.
+// TODO(rbyers): Add CSS and animated CSS feature types by making this a
+// more sophisticated class.
+enum class WebFeature : uint32_t {
+#include "UseCounterFeature.def"
+};
+
+}  // namespace blink
+
+#endif  // WebFeature_h
diff --git a/third_party/WebKit/public/web/WebLocalFrame.h b/third_party/WebKit/public/web/WebLocalFrame.h
index 1b3565d..434e0f6 100644
--- a/third_party/WebKit/public/web/WebLocalFrame.h
+++ b/third_party/WebKit/public/web/WebLocalFrame.h
@@ -116,6 +116,11 @@
   // Get the highest-level LocalFrame in this frame's in-process subtree.
   virtual WebLocalFrame* LocalRoot() = 0;
 
+  // Returns the frame identified by the given name.  This method supports
+  // pseudo-names like _self, _top, and _blank and otherwise performs the same
+  // kind of lookup what |window.open(..., name)| would in Javascript.
+  virtual WebFrame* FindFrameByName(const WebString& name) = 0;
+
   // Navigation Ping --------------------------------------------------------
 
   virtual void SendPings(const WebURL& destination_url) = 0;
diff --git a/third_party/WebKit/public/web/WebSettings.h b/third_party/WebKit/public/web/WebSettings.h
index 8d919ad..1abd400f 100644
--- a/third_party/WebKit/public/web/WebSettings.h
+++ b/third_party/WebKit/public/web/WebSettings.h
@@ -119,6 +119,7 @@
     kNoUserGestureRequired = 0,
     kUserGestureRequired,
     kUserGestureRequiredForCrossOrigin,
+    kDocumentUserActivationRequired,
   };
 
   // Sets value of a setting by its string identifier from Settings.in and
diff --git a/third_party/WebKit/public/web/WebView.h b/third_party/WebKit/public/web/WebView.h
index 04b8b90..d65c955 100644
--- a/third_party/WebKit/public/web/WebView.h
+++ b/third_party/WebKit/public/web/WebView.h
@@ -174,15 +174,6 @@
 
   virtual WebFrame* MainFrame() = 0;
 
-  // Returns the frame identified by the given name.  This method
-  // supports pseudo-names like _self, _top, and _blank.  It traverses
-  // the entire frame tree containing this tree looking for a frame that
-  // matches the given name.  If the optional relativeToFrame parameter
-  // is specified, then the search begins with the given frame and its
-  // children.
-  virtual WebFrame* FindFrameByName(const WebString& name,
-                                    WebFrame* relative_to_frame = 0) = 0;
-
   // Focus ---------------------------------------------------------------
 
   virtual WebLocalFrame* FocusedFrame() = 0;
diff --git a/third_party/closure_compiler/externs/developer_private.js b/third_party/closure_compiler/externs/developer_private.js
index b26a655d..68f81838 100644
--- a/third_party/closure_compiler/externs/developer_private.js
+++ b/third_party/closure_compiler/externs/developer_private.js
@@ -379,8 +379,7 @@
  *   fileAccess: (boolean|undefined),
  *   incognitoAccess: (boolean|undefined),
  *   errorCollection: (boolean|undefined),
- *   runOnAllUrls: (boolean|undefined),
- *   showActionButton: (boolean|undefined)
+ *   runOnAllUrls: (boolean|undefined)
  * }}
  * @see https://developer.chrome.com/extensions/developerPrivate#type-ExtensionConfigurationUpdate
  */
diff --git a/third_party/libvpx/README.chromium b/third_party/libvpx/README.chromium
index 04399d3d..50fa43b 100644
--- a/third_party/libvpx/README.chromium
+++ b/third_party/libvpx/README.chromium
@@ -5,9 +5,9 @@
 License File: source/libvpx/LICENSE
 Security Critical: yes
 
-Date: Monday May 22 2017
+Date: Tuesday May 30 2017
 Branch: master
-Commit: b3bf91bdc60220c004a22d21c867cc392e684b81
+Commit: b9649d240768cdcfc233960056aafb9ed1a3db14
 
 Description:
 Contains the sources used to compile libvpx binaries used by Google Chrome and
diff --git a/third_party/libvpx/libvpx_srcs.gni b/third_party/libvpx/libvpx_srcs.gni
index 08b2a5c..e0cbe6b4 100644
--- a/third_party/libvpx/libvpx_srcs.gni
+++ b/third_party/libvpx/libvpx_srcs.gni
@@ -54,6 +54,8 @@
   "//third_party/libvpx/source/libvpx/vp8/common/rtcd.c",
   "//third_party/libvpx/source/libvpx/vp8/common/setupintrarecon.c",
   "//third_party/libvpx/source/libvpx/vp8/common/setupintrarecon.h",
+  "//third_party/libvpx/source/libvpx/vp8/common/skin_detection.c",
+  "//third_party/libvpx/source/libvpx/vp8/common/skin_detection.h",
   "//third_party/libvpx/source/libvpx/vp8/common/swapyv12buffer.c",
   "//third_party/libvpx/source/libvpx/vp8/common/swapyv12buffer.h",
   "//third_party/libvpx/source/libvpx/vp8/common/systemdependent.h",
@@ -505,6 +507,8 @@
   "//third_party/libvpx/source/libvpx/vp8/common/rtcd.c",
   "//third_party/libvpx/source/libvpx/vp8/common/setupintrarecon.c",
   "//third_party/libvpx/source/libvpx/vp8/common/setupintrarecon.h",
+  "//third_party/libvpx/source/libvpx/vp8/common/skin_detection.c",
+  "//third_party/libvpx/source/libvpx/vp8/common/skin_detection.h",
   "//third_party/libvpx/source/libvpx/vp8/common/swapyv12buffer.c",
   "//third_party/libvpx/source/libvpx/vp8/common/swapyv12buffer.h",
   "//third_party/libvpx/source/libvpx/vp8/common/systemdependent.h",
@@ -963,6 +967,8 @@
   "//third_party/libvpx/source/libvpx/vp8/common/rtcd.c",
   "//third_party/libvpx/source/libvpx/vp8/common/setupintrarecon.c",
   "//third_party/libvpx/source/libvpx/vp8/common/setupintrarecon.h",
+  "//third_party/libvpx/source/libvpx/vp8/common/skin_detection.c",
+  "//third_party/libvpx/source/libvpx/vp8/common/skin_detection.h",
   "//third_party/libvpx/source/libvpx/vp8/common/swapyv12buffer.c",
   "//third_party/libvpx/source/libvpx/vp8/common/swapyv12buffer.h",
   "//third_party/libvpx/source/libvpx/vp8/common/systemdependent.h",
@@ -1315,6 +1321,8 @@
   "//third_party/libvpx/source/libvpx/vp8/common/rtcd.c",
   "//third_party/libvpx/source/libvpx/vp8/common/setupintrarecon.c",
   "//third_party/libvpx/source/libvpx/vp8/common/setupintrarecon.h",
+  "//third_party/libvpx/source/libvpx/vp8/common/skin_detection.c",
+  "//third_party/libvpx/source/libvpx/vp8/common/skin_detection.h",
   "//third_party/libvpx/source/libvpx/vp8/common/swapyv12buffer.c",
   "//third_party/libvpx/source/libvpx/vp8/common/swapyv12buffer.h",
   "//third_party/libvpx/source/libvpx/vp8/common/systemdependent.h",
@@ -1698,6 +1706,8 @@
   "//third_party/libvpx/source/libvpx/vp8/common/rtcd.c",
   "//third_party/libvpx/source/libvpx/vp8/common/setupintrarecon.c",
   "//third_party/libvpx/source/libvpx/vp8/common/setupintrarecon.h",
+  "//third_party/libvpx/source/libvpx/vp8/common/skin_detection.c",
+  "//third_party/libvpx/source/libvpx/vp8/common/skin_detection.h",
   "//third_party/libvpx/source/libvpx/vp8/common/swapyv12buffer.c",
   "//third_party/libvpx/source/libvpx/vp8/common/swapyv12buffer.h",
   "//third_party/libvpx/source/libvpx/vp8/common/systemdependent.h",
@@ -2113,6 +2123,8 @@
   "//third_party/libvpx/source/libvpx/vp8/common/rtcd.c",
   "//third_party/libvpx/source/libvpx/vp8/common/setupintrarecon.c",
   "//third_party/libvpx/source/libvpx/vp8/common/setupintrarecon.h",
+  "//third_party/libvpx/source/libvpx/vp8/common/skin_detection.c",
+  "//third_party/libvpx/source/libvpx/vp8/common/skin_detection.h",
   "//third_party/libvpx/source/libvpx/vp8/common/swapyv12buffer.c",
   "//third_party/libvpx/source/libvpx/vp8/common/swapyv12buffer.h",
   "//third_party/libvpx/source/libvpx/vp8/common/systemdependent.h",
@@ -2488,6 +2500,8 @@
   "//third_party/libvpx/source/libvpx/vp8/common/rtcd.c",
   "//third_party/libvpx/source/libvpx/vp8/common/setupintrarecon.c",
   "//third_party/libvpx/source/libvpx/vp8/common/setupintrarecon.h",
+  "//third_party/libvpx/source/libvpx/vp8/common/skin_detection.c",
+  "//third_party/libvpx/source/libvpx/vp8/common/skin_detection.h",
   "//third_party/libvpx/source/libvpx/vp8/common/swapyv12buffer.c",
   "//third_party/libvpx/source/libvpx/vp8/common/swapyv12buffer.h",
   "//third_party/libvpx/source/libvpx/vp8/common/systemdependent.h",
@@ -2822,6 +2836,8 @@
   "//third_party/libvpx/source/libvpx/vp8/common/rtcd.c",
   "//third_party/libvpx/source/libvpx/vp8/common/setupintrarecon.c",
   "//third_party/libvpx/source/libvpx/vp8/common/setupintrarecon.h",
+  "//third_party/libvpx/source/libvpx/vp8/common/skin_detection.c",
+  "//third_party/libvpx/source/libvpx/vp8/common/skin_detection.h",
   "//third_party/libvpx/source/libvpx/vp8/common/swapyv12buffer.c",
   "//third_party/libvpx/source/libvpx/vp8/common/swapyv12buffer.h",
   "//third_party/libvpx/source/libvpx/vp8/common/systemdependent.h",
@@ -3156,6 +3172,8 @@
   "//third_party/libvpx/source/libvpx/vp8/common/rtcd.c",
   "//third_party/libvpx/source/libvpx/vp8/common/setupintrarecon.c",
   "//third_party/libvpx/source/libvpx/vp8/common/setupintrarecon.h",
+  "//third_party/libvpx/source/libvpx/vp8/common/skin_detection.c",
+  "//third_party/libvpx/source/libvpx/vp8/common/skin_detection.h",
   "//third_party/libvpx/source/libvpx/vp8/common/swapyv12buffer.c",
   "//third_party/libvpx/source/libvpx/vp8/common/swapyv12buffer.h",
   "//third_party/libvpx/source/libvpx/vp8/common/systemdependent.h",
diff --git a/third_party/libvpx/source/config/ios/arm-neon/vpx_dsp_rtcd.h b/third_party/libvpx/source/config/ios/arm-neon/vpx_dsp_rtcd.h
index 61c4f1f..4b3c5be 100644
--- a/third_party/libvpx/source/config/ios/arm-neon/vpx_dsp_rtcd.h
+++ b/third_party/libvpx/source/config/ios/arm-neon/vpx_dsp_rtcd.h
@@ -634,43 +634,56 @@
 #define vpx_scaled_vert vpx_scaled_vert_c
 
 uint32_t vpx_sub_pixel_avg_variance16x16_c(const uint8_t *src_ptr, int source_stride, int xoffset, int  yoffset, const uint8_t *ref_ptr, int ref_stride, uint32_t *sse, const uint8_t *second_pred);
-#define vpx_sub_pixel_avg_variance16x16 vpx_sub_pixel_avg_variance16x16_c
+uint32_t vpx_sub_pixel_avg_variance16x16_neon(const uint8_t *src_ptr, int source_stride, int xoffset, int  yoffset, const uint8_t *ref_ptr, int ref_stride, uint32_t *sse, const uint8_t *second_pred);
+#define vpx_sub_pixel_avg_variance16x16 vpx_sub_pixel_avg_variance16x16_neon
 
 uint32_t vpx_sub_pixel_avg_variance16x32_c(const uint8_t *src_ptr, int source_stride, int xoffset, int  yoffset, const uint8_t *ref_ptr, int ref_stride, uint32_t *sse, const uint8_t *second_pred);
-#define vpx_sub_pixel_avg_variance16x32 vpx_sub_pixel_avg_variance16x32_c
+uint32_t vpx_sub_pixel_avg_variance16x32_neon(const uint8_t *src_ptr, int source_stride, int xoffset, int  yoffset, const uint8_t *ref_ptr, int ref_stride, uint32_t *sse, const uint8_t *second_pred);
+#define vpx_sub_pixel_avg_variance16x32 vpx_sub_pixel_avg_variance16x32_neon
 
 uint32_t vpx_sub_pixel_avg_variance16x8_c(const uint8_t *src_ptr, int source_stride, int xoffset, int  yoffset, const uint8_t *ref_ptr, int ref_stride, uint32_t *sse, const uint8_t *second_pred);
-#define vpx_sub_pixel_avg_variance16x8 vpx_sub_pixel_avg_variance16x8_c
+uint32_t vpx_sub_pixel_avg_variance16x8_neon(const uint8_t *src_ptr, int source_stride, int xoffset, int  yoffset, const uint8_t *ref_ptr, int ref_stride, uint32_t *sse, const uint8_t *second_pred);
+#define vpx_sub_pixel_avg_variance16x8 vpx_sub_pixel_avg_variance16x8_neon
 
 uint32_t vpx_sub_pixel_avg_variance32x16_c(const uint8_t *src_ptr, int source_stride, int xoffset, int  yoffset, const uint8_t *ref_ptr, int ref_stride, uint32_t *sse, const uint8_t *second_pred);
-#define vpx_sub_pixel_avg_variance32x16 vpx_sub_pixel_avg_variance32x16_c
+uint32_t vpx_sub_pixel_avg_variance32x16_neon(const uint8_t *src_ptr, int source_stride, int xoffset, int  yoffset, const uint8_t *ref_ptr, int ref_stride, uint32_t *sse, const uint8_t *second_pred);
+#define vpx_sub_pixel_avg_variance32x16 vpx_sub_pixel_avg_variance32x16_neon
 
 uint32_t vpx_sub_pixel_avg_variance32x32_c(const uint8_t *src_ptr, int source_stride, int xoffset, int  yoffset, const uint8_t *ref_ptr, int ref_stride, uint32_t *sse, const uint8_t *second_pred);
-#define vpx_sub_pixel_avg_variance32x32 vpx_sub_pixel_avg_variance32x32_c
+uint32_t vpx_sub_pixel_avg_variance32x32_neon(const uint8_t *src_ptr, int source_stride, int xoffset, int  yoffset, const uint8_t *ref_ptr, int ref_stride, uint32_t *sse, const uint8_t *second_pred);
+#define vpx_sub_pixel_avg_variance32x32 vpx_sub_pixel_avg_variance32x32_neon
 
 uint32_t vpx_sub_pixel_avg_variance32x64_c(const uint8_t *src_ptr, int source_stride, int xoffset, int  yoffset, const uint8_t *ref_ptr, int ref_stride, uint32_t *sse, const uint8_t *second_pred);
-#define vpx_sub_pixel_avg_variance32x64 vpx_sub_pixel_avg_variance32x64_c
+uint32_t vpx_sub_pixel_avg_variance32x64_neon(const uint8_t *src_ptr, int source_stride, int xoffset, int  yoffset, const uint8_t *ref_ptr, int ref_stride, uint32_t *sse, const uint8_t *second_pred);
+#define vpx_sub_pixel_avg_variance32x64 vpx_sub_pixel_avg_variance32x64_neon
 
 uint32_t vpx_sub_pixel_avg_variance4x4_c(const uint8_t *src_ptr, int source_stride, int xoffset, int  yoffset, const uint8_t *ref_ptr, int ref_stride, uint32_t *sse, const uint8_t *second_pred);
-#define vpx_sub_pixel_avg_variance4x4 vpx_sub_pixel_avg_variance4x4_c
+uint32_t vpx_sub_pixel_avg_variance4x4_neon(const uint8_t *src_ptr, int source_stride, int xoffset, int  yoffset, const uint8_t *ref_ptr, int ref_stride, uint32_t *sse, const uint8_t *second_pred);
+#define vpx_sub_pixel_avg_variance4x4 vpx_sub_pixel_avg_variance4x4_neon
 
 uint32_t vpx_sub_pixel_avg_variance4x8_c(const uint8_t *src_ptr, int source_stride, int xoffset, int  yoffset, const uint8_t *ref_ptr, int ref_stride, uint32_t *sse, const uint8_t *second_pred);
-#define vpx_sub_pixel_avg_variance4x8 vpx_sub_pixel_avg_variance4x8_c
+uint32_t vpx_sub_pixel_avg_variance4x8_neon(const uint8_t *src_ptr, int source_stride, int xoffset, int  yoffset, const uint8_t *ref_ptr, int ref_stride, uint32_t *sse, const uint8_t *second_pred);
+#define vpx_sub_pixel_avg_variance4x8 vpx_sub_pixel_avg_variance4x8_neon
 
 uint32_t vpx_sub_pixel_avg_variance64x32_c(const uint8_t *src_ptr, int source_stride, int xoffset, int  yoffset, const uint8_t *ref_ptr, int ref_stride, uint32_t *sse, const uint8_t *second_pred);
-#define vpx_sub_pixel_avg_variance64x32 vpx_sub_pixel_avg_variance64x32_c
+uint32_t vpx_sub_pixel_avg_variance64x32_neon(const uint8_t *src_ptr, int source_stride, int xoffset, int  yoffset, const uint8_t *ref_ptr, int ref_stride, uint32_t *sse, const uint8_t *second_pred);
+#define vpx_sub_pixel_avg_variance64x32 vpx_sub_pixel_avg_variance64x32_neon
 
 uint32_t vpx_sub_pixel_avg_variance64x64_c(const uint8_t *src_ptr, int source_stride, int xoffset, int  yoffset, const uint8_t *ref_ptr, int ref_stride, uint32_t *sse, const uint8_t *second_pred);
-#define vpx_sub_pixel_avg_variance64x64 vpx_sub_pixel_avg_variance64x64_c
+uint32_t vpx_sub_pixel_avg_variance64x64_neon(const uint8_t *src_ptr, int source_stride, int xoffset, int  yoffset, const uint8_t *ref_ptr, int ref_stride, uint32_t *sse, const uint8_t *second_pred);
+#define vpx_sub_pixel_avg_variance64x64 vpx_sub_pixel_avg_variance64x64_neon
 
 uint32_t vpx_sub_pixel_avg_variance8x16_c(const uint8_t *src_ptr, int source_stride, int xoffset, int  yoffset, const uint8_t *ref_ptr, int ref_stride, uint32_t *sse, const uint8_t *second_pred);
-#define vpx_sub_pixel_avg_variance8x16 vpx_sub_pixel_avg_variance8x16_c
+uint32_t vpx_sub_pixel_avg_variance8x16_neon(const uint8_t *src_ptr, int source_stride, int xoffset, int  yoffset, const uint8_t *ref_ptr, int ref_stride, uint32_t *sse, const uint8_t *second_pred);
+#define vpx_sub_pixel_avg_variance8x16 vpx_sub_pixel_avg_variance8x16_neon
 
 uint32_t vpx_sub_pixel_avg_variance8x4_c(const uint8_t *src_ptr, int source_stride, int xoffset, int  yoffset, const uint8_t *ref_ptr, int ref_stride, uint32_t *sse, const uint8_t *second_pred);
-#define vpx_sub_pixel_avg_variance8x4 vpx_sub_pixel_avg_variance8x4_c
+uint32_t vpx_sub_pixel_avg_variance8x4_neon(const uint8_t *src_ptr, int source_stride, int xoffset, int  yoffset, const uint8_t *ref_ptr, int ref_stride, uint32_t *sse, const uint8_t *second_pred);
+#define vpx_sub_pixel_avg_variance8x4 vpx_sub_pixel_avg_variance8x4_neon
 
 uint32_t vpx_sub_pixel_avg_variance8x8_c(const uint8_t *src_ptr, int source_stride, int xoffset, int  yoffset, const uint8_t *ref_ptr, int ref_stride, uint32_t *sse, const uint8_t *second_pred);
-#define vpx_sub_pixel_avg_variance8x8 vpx_sub_pixel_avg_variance8x8_c
+uint32_t vpx_sub_pixel_avg_variance8x8_neon(const uint8_t *src_ptr, int source_stride, int xoffset, int  yoffset, const uint8_t *ref_ptr, int ref_stride, uint32_t *sse, const uint8_t *second_pred);
+#define vpx_sub_pixel_avg_variance8x8 vpx_sub_pixel_avg_variance8x8_neon
 
 uint32_t vpx_sub_pixel_variance16x16_c(const uint8_t *src_ptr, int source_stride, int xoffset, int  yoffset, const uint8_t *ref_ptr, int ref_stride, uint32_t *sse);
 uint32_t vpx_sub_pixel_variance16x16_neon(const uint8_t *src_ptr, int source_stride, int xoffset, int  yoffset, const uint8_t *ref_ptr, int ref_stride, uint32_t *sse);
@@ -697,10 +710,12 @@
 #define vpx_sub_pixel_variance32x64 vpx_sub_pixel_variance32x64_neon
 
 uint32_t vpx_sub_pixel_variance4x4_c(const uint8_t *src_ptr, int source_stride, int xoffset, int  yoffset, const uint8_t *ref_ptr, int ref_stride, uint32_t *sse);
-#define vpx_sub_pixel_variance4x4 vpx_sub_pixel_variance4x4_c
+uint32_t vpx_sub_pixel_variance4x4_neon(const uint8_t *src_ptr, int source_stride, int xoffset, int  yoffset, const uint8_t *ref_ptr, int ref_stride, uint32_t *sse);
+#define vpx_sub_pixel_variance4x4 vpx_sub_pixel_variance4x4_neon
 
 uint32_t vpx_sub_pixel_variance4x8_c(const uint8_t *src_ptr, int source_stride, int xoffset, int  yoffset, const uint8_t *ref_ptr, int ref_stride, uint32_t *sse);
-#define vpx_sub_pixel_variance4x8 vpx_sub_pixel_variance4x8_c
+uint32_t vpx_sub_pixel_variance4x8_neon(const uint8_t *src_ptr, int source_stride, int xoffset, int  yoffset, const uint8_t *ref_ptr, int ref_stride, uint32_t *sse);
+#define vpx_sub_pixel_variance4x8 vpx_sub_pixel_variance4x8_neon
 
 uint32_t vpx_sub_pixel_variance64x32_c(const uint8_t *src_ptr, int source_stride, int xoffset, int  yoffset, const uint8_t *ref_ptr, int ref_stride, uint32_t *sse);
 uint32_t vpx_sub_pixel_variance64x32_neon(const uint8_t *src_ptr, int source_stride, int xoffset, int  yoffset, const uint8_t *ref_ptr, int ref_stride, uint32_t *sse);
@@ -786,10 +801,12 @@
 #define vpx_variance32x64 vpx_variance32x64_neon
 
 unsigned int vpx_variance4x4_c(const uint8_t *src_ptr, int source_stride, const uint8_t *ref_ptr, int ref_stride, unsigned int *sse);
-#define vpx_variance4x4 vpx_variance4x4_c
+unsigned int vpx_variance4x4_neon(const uint8_t *src_ptr, int source_stride, const uint8_t *ref_ptr, int ref_stride, unsigned int *sse);
+#define vpx_variance4x4 vpx_variance4x4_neon
 
 unsigned int vpx_variance4x8_c(const uint8_t *src_ptr, int source_stride, const uint8_t *ref_ptr, int ref_stride, unsigned int *sse);
-#define vpx_variance4x8 vpx_variance4x8_c
+unsigned int vpx_variance4x8_neon(const uint8_t *src_ptr, int source_stride, const uint8_t *ref_ptr, int ref_stride, unsigned int *sse);
+#define vpx_variance4x8 vpx_variance4x8_neon
 
 unsigned int vpx_variance64x32_c(const uint8_t *src_ptr, int source_stride, const uint8_t *ref_ptr, int ref_stride, unsigned int *sse);
 unsigned int vpx_variance64x32_neon(const uint8_t *src_ptr, int source_stride, const uint8_t *ref_ptr, int ref_stride, unsigned int *sse);
diff --git a/third_party/libvpx/source/config/ios/arm-neon/vpx_scale_rtcd.h b/third_party/libvpx/source/config/ios/arm-neon/vpx_scale_rtcd.h
index a1564b7..515ce27 100644
--- a/third_party/libvpx/source/config/ios/arm-neon/vpx_scale_rtcd.h
+++ b/third_party/libvpx/source/config/ios/arm-neon/vpx_scale_rtcd.h
@@ -46,6 +46,9 @@
 void vpx_extend_frame_inner_borders_c(struct yv12_buffer_config *ybf);
 #define vpx_extend_frame_inner_borders vpx_extend_frame_inner_borders_c
 
+void vpx_yv12_copy_frame_c(const struct yv12_buffer_config *src_ybc, struct yv12_buffer_config *dst_ybc);
+#define vpx_yv12_copy_frame vpx_yv12_copy_frame_c
+
 void vpx_yv12_copy_y_c(const struct yv12_buffer_config *src_ybc, struct yv12_buffer_config *dst_ybc);
 #define vpx_yv12_copy_y vpx_yv12_copy_y_c
 
diff --git a/third_party/libvpx/source/config/ios/arm64/vpx_dsp_rtcd.h b/third_party/libvpx/source/config/ios/arm64/vpx_dsp_rtcd.h
index 61c4f1f..4b3c5be 100644
--- a/third_party/libvpx/source/config/ios/arm64/vpx_dsp_rtcd.h
+++ b/third_party/libvpx/source/config/ios/arm64/vpx_dsp_rtcd.h
@@ -634,43 +634,56 @@
 #define vpx_scaled_vert vpx_scaled_vert_c
 
 uint32_t vpx_sub_pixel_avg_variance16x16_c(const uint8_t *src_ptr, int source_stride, int xoffset, int  yoffset, const uint8_t *ref_ptr, int ref_stride, uint32_t *sse, const uint8_t *second_pred);
-#define vpx_sub_pixel_avg_variance16x16 vpx_sub_pixel_avg_variance16x16_c
+uint32_t vpx_sub_pixel_avg_variance16x16_neon(const uint8_t *src_ptr, int source_stride, int xoffset, int  yoffset, const uint8_t *ref_ptr, int ref_stride, uint32_t *sse, const uint8_t *second_pred);
+#define vpx_sub_pixel_avg_variance16x16 vpx_sub_pixel_avg_variance16x16_neon
 
 uint32_t vpx_sub_pixel_avg_variance16x32_c(const uint8_t *src_ptr, int source_stride, int xoffset, int  yoffset, const uint8_t *ref_ptr, int ref_stride, uint32_t *sse, const uint8_t *second_pred);
-#define vpx_sub_pixel_avg_variance16x32 vpx_sub_pixel_avg_variance16x32_c
+uint32_t vpx_sub_pixel_avg_variance16x32_neon(const uint8_t *src_ptr, int source_stride, int xoffset, int  yoffset, const uint8_t *ref_ptr, int ref_stride, uint32_t *sse, const uint8_t *second_pred);
+#define vpx_sub_pixel_avg_variance16x32 vpx_sub_pixel_avg_variance16x32_neon
 
 uint32_t vpx_sub_pixel_avg_variance16x8_c(const uint8_t *src_ptr, int source_stride, int xoffset, int  yoffset, const uint8_t *ref_ptr, int ref_stride, uint32_t *sse, const uint8_t *second_pred);
-#define vpx_sub_pixel_avg_variance16x8 vpx_sub_pixel_avg_variance16x8_c
+uint32_t vpx_sub_pixel_avg_variance16x8_neon(const uint8_t *src_ptr, int source_stride, int xoffset, int  yoffset, const uint8_t *ref_ptr, int ref_stride, uint32_t *sse, const uint8_t *second_pred);
+#define vpx_sub_pixel_avg_variance16x8 vpx_sub_pixel_avg_variance16x8_neon
 
 uint32_t vpx_sub_pixel_avg_variance32x16_c(const uint8_t *src_ptr, int source_stride, int xoffset, int  yoffset, const uint8_t *ref_ptr, int ref_stride, uint32_t *sse, const uint8_t *second_pred);
-#define vpx_sub_pixel_avg_variance32x16 vpx_sub_pixel_avg_variance32x16_c
+uint32_t vpx_sub_pixel_avg_variance32x16_neon(const uint8_t *src_ptr, int source_stride, int xoffset, int  yoffset, const uint8_t *ref_ptr, int ref_stride, uint32_t *sse, const uint8_t *second_pred);
+#define vpx_sub_pixel_avg_variance32x16 vpx_sub_pixel_avg_variance32x16_neon
 
 uint32_t vpx_sub_pixel_avg_variance32x32_c(const uint8_t *src_ptr, int source_stride, int xoffset, int  yoffset, const uint8_t *ref_ptr, int ref_stride, uint32_t *sse, const uint8_t *second_pred);
-#define vpx_sub_pixel_avg_variance32x32 vpx_sub_pixel_avg_variance32x32_c
+uint32_t vpx_sub_pixel_avg_variance32x32_neon(const uint8_t *src_ptr, int source_stride, int xoffset, int  yoffset, const uint8_t *ref_ptr, int ref_stride, uint32_t *sse, const uint8_t *second_pred);
+#define vpx_sub_pixel_avg_variance32x32 vpx_sub_pixel_avg_variance32x32_neon
 
 uint32_t vpx_sub_pixel_avg_variance32x64_c(const uint8_t *src_ptr, int source_stride, int xoffset, int  yoffset, const uint8_t *ref_ptr, int ref_stride, uint32_t *sse, const uint8_t *second_pred);
-#define vpx_sub_pixel_avg_variance32x64 vpx_sub_pixel_avg_variance32x64_c
+uint32_t vpx_sub_pixel_avg_variance32x64_neon(const uint8_t *src_ptr, int source_stride, int xoffset, int  yoffset, const uint8_t *ref_ptr, int ref_stride, uint32_t *sse, const uint8_t *second_pred);
+#define vpx_sub_pixel_avg_variance32x64 vpx_sub_pixel_avg_variance32x64_neon
 
 uint32_t vpx_sub_pixel_avg_variance4x4_c(const uint8_t *src_ptr, int source_stride, int xoffset, int  yoffset, const uint8_t *ref_ptr, int ref_stride, uint32_t *sse, const uint8_t *second_pred);
-#define vpx_sub_pixel_avg_variance4x4 vpx_sub_pixel_avg_variance4x4_c
+uint32_t vpx_sub_pixel_avg_variance4x4_neon(const uint8_t *src_ptr, int source_stride, int xoffset, int  yoffset, const uint8_t *ref_ptr, int ref_stride, uint32_t *sse, const uint8_t *second_pred);
+#define vpx_sub_pixel_avg_variance4x4 vpx_sub_pixel_avg_variance4x4_neon
 
 uint32_t vpx_sub_pixel_avg_variance4x8_c(const uint8_t *src_ptr, int source_stride, int xoffset, int  yoffset, const uint8_t *ref_ptr, int ref_stride, uint32_t *sse, const uint8_t *second_pred);
-#define vpx_sub_pixel_avg_variance4x8 vpx_sub_pixel_avg_variance4x8_c
+uint32_t vpx_sub_pixel_avg_variance4x8_neon(const uint8_t *src_ptr, int source_stride, int xoffset, int  yoffset, const uint8_t *ref_ptr, int ref_stride, uint32_t *sse, const uint8_t *second_pred);
+#define vpx_sub_pixel_avg_variance4x8 vpx_sub_pixel_avg_variance4x8_neon
 
 uint32_t vpx_sub_pixel_avg_variance64x32_c(const uint8_t *src_ptr, int source_stride, int xoffset, int  yoffset, const uint8_t *ref_ptr, int ref_stride, uint32_t *sse, const uint8_t *second_pred);
-#define vpx_sub_pixel_avg_variance64x32 vpx_sub_pixel_avg_variance64x32_c
+uint32_t vpx_sub_pixel_avg_variance64x32_neon(const uint8_t *src_ptr, int source_stride, int xoffset, int  yoffset, const uint8_t *ref_ptr, int ref_stride, uint32_t *sse, const uint8_t *second_pred);
+#define vpx_sub_pixel_avg_variance64x32 vpx_sub_pixel_avg_variance64x32_neon
 
 uint32_t vpx_sub_pixel_avg_variance64x64_c(const uint8_t *src_ptr, int source_stride, int xoffset, int  yoffset, const uint8_t *ref_ptr, int ref_stride, uint32_t *sse, const uint8_t *second_pred);
-#define vpx_sub_pixel_avg_variance64x64 vpx_sub_pixel_avg_variance64x64_c
+uint32_t vpx_sub_pixel_avg_variance64x64_neon(const uint8_t *src_ptr, int source_stride, int xoffset, int  yoffset, const uint8_t *ref_ptr, int ref_stride, uint32_t *sse, const uint8_t *second_pred);
+#define vpx_sub_pixel_avg_variance64x64 vpx_sub_pixel_avg_variance64x64_neon
 
 uint32_t vpx_sub_pixel_avg_variance8x16_c(const uint8_t *src_ptr, int source_stride, int xoffset, int  yoffset, const uint8_t *ref_ptr, int ref_stride, uint32_t *sse, const uint8_t *second_pred);
-#define vpx_sub_pixel_avg_variance8x16 vpx_sub_pixel_avg_variance8x16_c
+uint32_t vpx_sub_pixel_avg_variance8x16_neon(const uint8_t *src_ptr, int source_stride, int xoffset, int  yoffset, const uint8_t *ref_ptr, int ref_stride, uint32_t *sse, const uint8_t *second_pred);
+#define vpx_sub_pixel_avg_variance8x16 vpx_sub_pixel_avg_variance8x16_neon
 
 uint32_t vpx_sub_pixel_avg_variance8x4_c(const uint8_t *src_ptr, int source_stride, int xoffset, int  yoffset, const uint8_t *ref_ptr, int ref_stride, uint32_t *sse, const uint8_t *second_pred);
-#define vpx_sub_pixel_avg_variance8x4 vpx_sub_pixel_avg_variance8x4_c
+uint32_t vpx_sub_pixel_avg_variance8x4_neon(const uint8_t *src_ptr, int source_stride, int xoffset, int  yoffset, const uint8_t *ref_ptr, int ref_stride, uint32_t *sse, const uint8_t *second_pred);
+#define vpx_sub_pixel_avg_variance8x4 vpx_sub_pixel_avg_variance8x4_neon
 
 uint32_t vpx_sub_pixel_avg_variance8x8_c(const uint8_t *src_ptr, int source_stride, int xoffset, int  yoffset, const uint8_t *ref_ptr, int ref_stride, uint32_t *sse, const uint8_t *second_pred);
-#define vpx_sub_pixel_avg_variance8x8 vpx_sub_pixel_avg_variance8x8_c
+uint32_t vpx_sub_pixel_avg_variance8x8_neon(const uint8_t *src_ptr, int source_stride, int xoffset, int  yoffset, const uint8_t *ref_ptr, int ref_stride, uint32_t *sse, const uint8_t *second_pred);
+#define vpx_sub_pixel_avg_variance8x8 vpx_sub_pixel_avg_variance8x8_neon
 
 uint32_t vpx_sub_pixel_variance16x16_c(const uint8_t *src_ptr, int source_stride, int xoffset, int  yoffset, const uint8_t *ref_ptr, int ref_stride, uint32_t *sse);
 uint32_t vpx_sub_pixel_variance16x16_neon(const uint8_t *src_ptr, int source_stride, int xoffset, int  yoffset, const uint8_t *ref_ptr, int ref_stride, uint32_t *sse);
@@ -697,10 +710,12 @@
 #define vpx_sub_pixel_variance32x64 vpx_sub_pixel_variance32x64_neon
 
 uint32_t vpx_sub_pixel_variance4x4_c(const uint8_t *src_ptr, int source_stride, int xoffset, int  yoffset, const uint8_t *ref_ptr, int ref_stride, uint32_t *sse);
-#define vpx_sub_pixel_variance4x4 vpx_sub_pixel_variance4x4_c
+uint32_t vpx_sub_pixel_variance4x4_neon(const uint8_t *src_ptr, int source_stride, int xoffset, int  yoffset, const uint8_t *ref_ptr, int ref_stride, uint32_t *sse);
+#define vpx_sub_pixel_variance4x4 vpx_sub_pixel_variance4x4_neon
 
 uint32_t vpx_sub_pixel_variance4x8_c(const uint8_t *src_ptr, int source_stride, int xoffset, int  yoffset, const uint8_t *ref_ptr, int ref_stride, uint32_t *sse);
-#define vpx_sub_pixel_variance4x8 vpx_sub_pixel_variance4x8_c
+uint32_t vpx_sub_pixel_variance4x8_neon(const uint8_t *src_ptr, int source_stride, int xoffset, int  yoffset, const uint8_t *ref_ptr, int ref_stride, uint32_t *sse);
+#define vpx_sub_pixel_variance4x8 vpx_sub_pixel_variance4x8_neon
 
 uint32_t vpx_sub_pixel_variance64x32_c(const uint8_t *src_ptr, int source_stride, int xoffset, int  yoffset, const uint8_t *ref_ptr, int ref_stride, uint32_t *sse);
 uint32_t vpx_sub_pixel_variance64x32_neon(const uint8_t *src_ptr, int source_stride, int xoffset, int  yoffset, const uint8_t *ref_ptr, int ref_stride, uint32_t *sse);
@@ -786,10 +801,12 @@
 #define vpx_variance32x64 vpx_variance32x64_neon
 
 unsigned int vpx_variance4x4_c(const uint8_t *src_ptr, int source_stride, const uint8_t *ref_ptr, int ref_stride, unsigned int *sse);
-#define vpx_variance4x4 vpx_variance4x4_c
+unsigned int vpx_variance4x4_neon(const uint8_t *src_ptr, int source_stride, const uint8_t *ref_ptr, int ref_stride, unsigned int *sse);
+#define vpx_variance4x4 vpx_variance4x4_neon
 
 unsigned int vpx_variance4x8_c(const uint8_t *src_ptr, int source_stride, const uint8_t *ref_ptr, int ref_stride, unsigned int *sse);
-#define vpx_variance4x8 vpx_variance4x8_c
+unsigned int vpx_variance4x8_neon(const uint8_t *src_ptr, int source_stride, const uint8_t *ref_ptr, int ref_stride, unsigned int *sse);
+#define vpx_variance4x8 vpx_variance4x8_neon
 
 unsigned int vpx_variance64x32_c(const uint8_t *src_ptr, int source_stride, const uint8_t *ref_ptr, int ref_stride, unsigned int *sse);
 unsigned int vpx_variance64x32_neon(const uint8_t *src_ptr, int source_stride, const uint8_t *ref_ptr, int ref_stride, unsigned int *sse);
diff --git a/third_party/libvpx/source/config/ios/arm64/vpx_scale_rtcd.h b/third_party/libvpx/source/config/ios/arm64/vpx_scale_rtcd.h
index a1564b7..515ce27 100644
--- a/third_party/libvpx/source/config/ios/arm64/vpx_scale_rtcd.h
+++ b/third_party/libvpx/source/config/ios/arm64/vpx_scale_rtcd.h
@@ -46,6 +46,9 @@
 void vpx_extend_frame_inner_borders_c(struct yv12_buffer_config *ybf);
 #define vpx_extend_frame_inner_borders vpx_extend_frame_inner_borders_c
 
+void vpx_yv12_copy_frame_c(const struct yv12_buffer_config *src_ybc, struct yv12_buffer_config *dst_ybc);
+#define vpx_yv12_copy_frame vpx_yv12_copy_frame_c
+
 void vpx_yv12_copy_y_c(const struct yv12_buffer_config *src_ybc, struct yv12_buffer_config *dst_ybc);
 #define vpx_yv12_copy_y vpx_yv12_copy_y_c
 
diff --git a/third_party/libvpx/source/config/linux/arm-neon-cpu-detect/vpx_dsp_rtcd.h b/third_party/libvpx/source/config/linux/arm-neon-cpu-detect/vpx_dsp_rtcd.h
index c818a51..cfcf57d 100644
--- a/third_party/libvpx/source/config/linux/arm-neon-cpu-detect/vpx_dsp_rtcd.h
+++ b/third_party/libvpx/source/config/linux/arm-neon-cpu-detect/vpx_dsp_rtcd.h
@@ -634,43 +634,56 @@
 #define vpx_scaled_vert vpx_scaled_vert_c
 
 uint32_t vpx_sub_pixel_avg_variance16x16_c(const uint8_t *src_ptr, int source_stride, int xoffset, int  yoffset, const uint8_t *ref_ptr, int ref_stride, uint32_t *sse, const uint8_t *second_pred);
-#define vpx_sub_pixel_avg_variance16x16 vpx_sub_pixel_avg_variance16x16_c
+uint32_t vpx_sub_pixel_avg_variance16x16_neon(const uint8_t *src_ptr, int source_stride, int xoffset, int  yoffset, const uint8_t *ref_ptr, int ref_stride, uint32_t *sse, const uint8_t *second_pred);
+RTCD_EXTERN uint32_t (*vpx_sub_pixel_avg_variance16x16)(const uint8_t *src_ptr, int source_stride, int xoffset, int  yoffset, const uint8_t *ref_ptr, int ref_stride, uint32_t *sse, const uint8_t *second_pred);
 
 uint32_t vpx_sub_pixel_avg_variance16x32_c(const uint8_t *src_ptr, int source_stride, int xoffset, int  yoffset, const uint8_t *ref_ptr, int ref_stride, uint32_t *sse, const uint8_t *second_pred);
-#define vpx_sub_pixel_avg_variance16x32 vpx_sub_pixel_avg_variance16x32_c
+uint32_t vpx_sub_pixel_avg_variance16x32_neon(const uint8_t *src_ptr, int source_stride, int xoffset, int  yoffset, const uint8_t *ref_ptr, int ref_stride, uint32_t *sse, const uint8_t *second_pred);
+RTCD_EXTERN uint32_t (*vpx_sub_pixel_avg_variance16x32)(const uint8_t *src_ptr, int source_stride, int xoffset, int  yoffset, const uint8_t *ref_ptr, int ref_stride, uint32_t *sse, const uint8_t *second_pred);
 
 uint32_t vpx_sub_pixel_avg_variance16x8_c(const uint8_t *src_ptr, int source_stride, int xoffset, int  yoffset, const uint8_t *ref_ptr, int ref_stride, uint32_t *sse, const uint8_t *second_pred);
-#define vpx_sub_pixel_avg_variance16x8 vpx_sub_pixel_avg_variance16x8_c
+uint32_t vpx_sub_pixel_avg_variance16x8_neon(const uint8_t *src_ptr, int source_stride, int xoffset, int  yoffset, const uint8_t *ref_ptr, int ref_stride, uint32_t *sse, const uint8_t *second_pred);
+RTCD_EXTERN uint32_t (*vpx_sub_pixel_avg_variance16x8)(const uint8_t *src_ptr, int source_stride, int xoffset, int  yoffset, const uint8_t *ref_ptr, int ref_stride, uint32_t *sse, const uint8_t *second_pred);
 
 uint32_t vpx_sub_pixel_avg_variance32x16_c(const uint8_t *src_ptr, int source_stride, int xoffset, int  yoffset, const uint8_t *ref_ptr, int ref_stride, uint32_t *sse, const uint8_t *second_pred);
-#define vpx_sub_pixel_avg_variance32x16 vpx_sub_pixel_avg_variance32x16_c
+uint32_t vpx_sub_pixel_avg_variance32x16_neon(const uint8_t *src_ptr, int source_stride, int xoffset, int  yoffset, const uint8_t *ref_ptr, int ref_stride, uint32_t *sse, const uint8_t *second_pred);
+RTCD_EXTERN uint32_t (*vpx_sub_pixel_avg_variance32x16)(const uint8_t *src_ptr, int source_stride, int xoffset, int  yoffset, const uint8_t *ref_ptr, int ref_stride, uint32_t *sse, const uint8_t *second_pred);
 
 uint32_t vpx_sub_pixel_avg_variance32x32_c(const uint8_t *src_ptr, int source_stride, int xoffset, int  yoffset, const uint8_t *ref_ptr, int ref_stride, uint32_t *sse, const uint8_t *second_pred);
-#define vpx_sub_pixel_avg_variance32x32 vpx_sub_pixel_avg_variance32x32_c
+uint32_t vpx_sub_pixel_avg_variance32x32_neon(const uint8_t *src_ptr, int source_stride, int xoffset, int  yoffset, const uint8_t *ref_ptr, int ref_stride, uint32_t *sse, const uint8_t *second_pred);
+RTCD_EXTERN uint32_t (*vpx_sub_pixel_avg_variance32x32)(const uint8_t *src_ptr, int source_stride, int xoffset, int  yoffset, const uint8_t *ref_ptr, int ref_stride, uint32_t *sse, const uint8_t *second_pred);
 
 uint32_t vpx_sub_pixel_avg_variance32x64_c(const uint8_t *src_ptr, int source_stride, int xoffset, int  yoffset, const uint8_t *ref_ptr, int ref_stride, uint32_t *sse, const uint8_t *second_pred);
-#define vpx_sub_pixel_avg_variance32x64 vpx_sub_pixel_avg_variance32x64_c
+uint32_t vpx_sub_pixel_avg_variance32x64_neon(const uint8_t *src_ptr, int source_stride, int xoffset, int  yoffset, const uint8_t *ref_ptr, int ref_stride, uint32_t *sse, const uint8_t *second_pred);
+RTCD_EXTERN uint32_t (*vpx_sub_pixel_avg_variance32x64)(const uint8_t *src_ptr, int source_stride, int xoffset, int  yoffset, const uint8_t *ref_ptr, int ref_stride, uint32_t *sse, const uint8_t *second_pred);
 
 uint32_t vpx_sub_pixel_avg_variance4x4_c(const uint8_t *src_ptr, int source_stride, int xoffset, int  yoffset, const uint8_t *ref_ptr, int ref_stride, uint32_t *sse, const uint8_t *second_pred);
-#define vpx_sub_pixel_avg_variance4x4 vpx_sub_pixel_avg_variance4x4_c
+uint32_t vpx_sub_pixel_avg_variance4x4_neon(const uint8_t *src_ptr, int source_stride, int xoffset, int  yoffset, const uint8_t *ref_ptr, int ref_stride, uint32_t *sse, const uint8_t *second_pred);
+RTCD_EXTERN uint32_t (*vpx_sub_pixel_avg_variance4x4)(const uint8_t *src_ptr, int source_stride, int xoffset, int  yoffset, const uint8_t *ref_ptr, int ref_stride, uint32_t *sse, const uint8_t *second_pred);
 
 uint32_t vpx_sub_pixel_avg_variance4x8_c(const uint8_t *src_ptr, int source_stride, int xoffset, int  yoffset, const uint8_t *ref_ptr, int ref_stride, uint32_t *sse, const uint8_t *second_pred);
-#define vpx_sub_pixel_avg_variance4x8 vpx_sub_pixel_avg_variance4x8_c
+uint32_t vpx_sub_pixel_avg_variance4x8_neon(const uint8_t *src_ptr, int source_stride, int xoffset, int  yoffset, const uint8_t *ref_ptr, int ref_stride, uint32_t *sse, const uint8_t *second_pred);
+RTCD_EXTERN uint32_t (*vpx_sub_pixel_avg_variance4x8)(const uint8_t *src_ptr, int source_stride, int xoffset, int  yoffset, const uint8_t *ref_ptr, int ref_stride, uint32_t *sse, const uint8_t *second_pred);
 
 uint32_t vpx_sub_pixel_avg_variance64x32_c(const uint8_t *src_ptr, int source_stride, int xoffset, int  yoffset, const uint8_t *ref_ptr, int ref_stride, uint32_t *sse, const uint8_t *second_pred);
-#define vpx_sub_pixel_avg_variance64x32 vpx_sub_pixel_avg_variance64x32_c
+uint32_t vpx_sub_pixel_avg_variance64x32_neon(const uint8_t *src_ptr, int source_stride, int xoffset, int  yoffset, const uint8_t *ref_ptr, int ref_stride, uint32_t *sse, const uint8_t *second_pred);
+RTCD_EXTERN uint32_t (*vpx_sub_pixel_avg_variance64x32)(const uint8_t *src_ptr, int source_stride, int xoffset, int  yoffset, const uint8_t *ref_ptr, int ref_stride, uint32_t *sse, const uint8_t *second_pred);
 
 uint32_t vpx_sub_pixel_avg_variance64x64_c(const uint8_t *src_ptr, int source_stride, int xoffset, int  yoffset, const uint8_t *ref_ptr, int ref_stride, uint32_t *sse, const uint8_t *second_pred);
-#define vpx_sub_pixel_avg_variance64x64 vpx_sub_pixel_avg_variance64x64_c
+uint32_t vpx_sub_pixel_avg_variance64x64_neon(const uint8_t *src_ptr, int source_stride, int xoffset, int  yoffset, const uint8_t *ref_ptr, int ref_stride, uint32_t *sse, const uint8_t *second_pred);
+RTCD_EXTERN uint32_t (*vpx_sub_pixel_avg_variance64x64)(const uint8_t *src_ptr, int source_stride, int xoffset, int  yoffset, const uint8_t *ref_ptr, int ref_stride, uint32_t *sse, const uint8_t *second_pred);
 
 uint32_t vpx_sub_pixel_avg_variance8x16_c(const uint8_t *src_ptr, int source_stride, int xoffset, int  yoffset, const uint8_t *ref_ptr, int ref_stride, uint32_t *sse, const uint8_t *second_pred);
-#define vpx_sub_pixel_avg_variance8x16 vpx_sub_pixel_avg_variance8x16_c
+uint32_t vpx_sub_pixel_avg_variance8x16_neon(const uint8_t *src_ptr, int source_stride, int xoffset, int  yoffset, const uint8_t *ref_ptr, int ref_stride, uint32_t *sse, const uint8_t *second_pred);
+RTCD_EXTERN uint32_t (*vpx_sub_pixel_avg_variance8x16)(const uint8_t *src_ptr, int source_stride, int xoffset, int  yoffset, const uint8_t *ref_ptr, int ref_stride, uint32_t *sse, const uint8_t *second_pred);
 
 uint32_t vpx_sub_pixel_avg_variance8x4_c(const uint8_t *src_ptr, int source_stride, int xoffset, int  yoffset, const uint8_t *ref_ptr, int ref_stride, uint32_t *sse, const uint8_t *second_pred);
-#define vpx_sub_pixel_avg_variance8x4 vpx_sub_pixel_avg_variance8x4_c
+uint32_t vpx_sub_pixel_avg_variance8x4_neon(const uint8_t *src_ptr, int source_stride, int xoffset, int  yoffset, const uint8_t *ref_ptr, int ref_stride, uint32_t *sse, const uint8_t *second_pred);
+RTCD_EXTERN uint32_t (*vpx_sub_pixel_avg_variance8x4)(const uint8_t *src_ptr, int source_stride, int xoffset, int  yoffset, const uint8_t *ref_ptr, int ref_stride, uint32_t *sse, const uint8_t *second_pred);
 
 uint32_t vpx_sub_pixel_avg_variance8x8_c(const uint8_t *src_ptr, int source_stride, int xoffset, int  yoffset, const uint8_t *ref_ptr, int ref_stride, uint32_t *sse, const uint8_t *second_pred);
-#define vpx_sub_pixel_avg_variance8x8 vpx_sub_pixel_avg_variance8x8_c
+uint32_t vpx_sub_pixel_avg_variance8x8_neon(const uint8_t *src_ptr, int source_stride, int xoffset, int  yoffset, const uint8_t *ref_ptr, int ref_stride, uint32_t *sse, const uint8_t *second_pred);
+RTCD_EXTERN uint32_t (*vpx_sub_pixel_avg_variance8x8)(const uint8_t *src_ptr, int source_stride, int xoffset, int  yoffset, const uint8_t *ref_ptr, int ref_stride, uint32_t *sse, const uint8_t *second_pred);
 
 uint32_t vpx_sub_pixel_variance16x16_c(const uint8_t *src_ptr, int source_stride, int xoffset, int  yoffset, const uint8_t *ref_ptr, int ref_stride, uint32_t *sse);
 uint32_t vpx_sub_pixel_variance16x16_neon(const uint8_t *src_ptr, int source_stride, int xoffset, int  yoffset, const uint8_t *ref_ptr, int ref_stride, uint32_t *sse);
@@ -697,10 +710,12 @@
 RTCD_EXTERN uint32_t (*vpx_sub_pixel_variance32x64)(const uint8_t *src_ptr, int source_stride, int xoffset, int  yoffset, const uint8_t *ref_ptr, int ref_stride, uint32_t *sse);
 
 uint32_t vpx_sub_pixel_variance4x4_c(const uint8_t *src_ptr, int source_stride, int xoffset, int  yoffset, const uint8_t *ref_ptr, int ref_stride, uint32_t *sse);
-#define vpx_sub_pixel_variance4x4 vpx_sub_pixel_variance4x4_c
+uint32_t vpx_sub_pixel_variance4x4_neon(const uint8_t *src_ptr, int source_stride, int xoffset, int  yoffset, const uint8_t *ref_ptr, int ref_stride, uint32_t *sse);
+RTCD_EXTERN uint32_t (*vpx_sub_pixel_variance4x4)(const uint8_t *src_ptr, int source_stride, int xoffset, int  yoffset, const uint8_t *ref_ptr, int ref_stride, uint32_t *sse);
 
 uint32_t vpx_sub_pixel_variance4x8_c(const uint8_t *src_ptr, int source_stride, int xoffset, int  yoffset, const uint8_t *ref_ptr, int ref_stride, uint32_t *sse);
-#define vpx_sub_pixel_variance4x8 vpx_sub_pixel_variance4x8_c
+uint32_t vpx_sub_pixel_variance4x8_neon(const uint8_t *src_ptr, int source_stride, int xoffset, int  yoffset, const uint8_t *ref_ptr, int ref_stride, uint32_t *sse);
+RTCD_EXTERN uint32_t (*vpx_sub_pixel_variance4x8)(const uint8_t *src_ptr, int source_stride, int xoffset, int  yoffset, const uint8_t *ref_ptr, int ref_stride, uint32_t *sse);
 
 uint32_t vpx_sub_pixel_variance64x32_c(const uint8_t *src_ptr, int source_stride, int xoffset, int  yoffset, const uint8_t *ref_ptr, int ref_stride, uint32_t *sse);
 uint32_t vpx_sub_pixel_variance64x32_neon(const uint8_t *src_ptr, int source_stride, int xoffset, int  yoffset, const uint8_t *ref_ptr, int ref_stride, uint32_t *sse);
@@ -786,10 +801,12 @@
 RTCD_EXTERN unsigned int (*vpx_variance32x64)(const uint8_t *src_ptr, int source_stride, const uint8_t *ref_ptr, int ref_stride, unsigned int *sse);
 
 unsigned int vpx_variance4x4_c(const uint8_t *src_ptr, int source_stride, const uint8_t *ref_ptr, int ref_stride, unsigned int *sse);
-#define vpx_variance4x4 vpx_variance4x4_c
+unsigned int vpx_variance4x4_neon(const uint8_t *src_ptr, int source_stride, const uint8_t *ref_ptr, int ref_stride, unsigned int *sse);
+RTCD_EXTERN unsigned int (*vpx_variance4x4)(const uint8_t *src_ptr, int source_stride, const uint8_t *ref_ptr, int ref_stride, unsigned int *sse);
 
 unsigned int vpx_variance4x8_c(const uint8_t *src_ptr, int source_stride, const uint8_t *ref_ptr, int ref_stride, unsigned int *sse);
-#define vpx_variance4x8 vpx_variance4x8_c
+unsigned int vpx_variance4x8_neon(const uint8_t *src_ptr, int source_stride, const uint8_t *ref_ptr, int ref_stride, unsigned int *sse);
+RTCD_EXTERN unsigned int (*vpx_variance4x8)(const uint8_t *src_ptr, int source_stride, const uint8_t *ref_ptr, int ref_stride, unsigned int *sse);
 
 unsigned int vpx_variance64x32_c(const uint8_t *src_ptr, int source_stride, const uint8_t *ref_ptr, int ref_stride, unsigned int *sse);
 unsigned int vpx_variance64x32_neon(const uint8_t *src_ptr, int source_stride, const uint8_t *ref_ptr, int ref_stride, unsigned int *sse);
@@ -1008,6 +1025,32 @@
     if (flags & HAS_NEON) vpx_sad8x8 = vpx_sad8x8_neon;
     vpx_satd = vpx_satd_c;
     if (flags & HAS_NEON) vpx_satd = vpx_satd_neon;
+    vpx_sub_pixel_avg_variance16x16 = vpx_sub_pixel_avg_variance16x16_c;
+    if (flags & HAS_NEON) vpx_sub_pixel_avg_variance16x16 = vpx_sub_pixel_avg_variance16x16_neon;
+    vpx_sub_pixel_avg_variance16x32 = vpx_sub_pixel_avg_variance16x32_c;
+    if (flags & HAS_NEON) vpx_sub_pixel_avg_variance16x32 = vpx_sub_pixel_avg_variance16x32_neon;
+    vpx_sub_pixel_avg_variance16x8 = vpx_sub_pixel_avg_variance16x8_c;
+    if (flags & HAS_NEON) vpx_sub_pixel_avg_variance16x8 = vpx_sub_pixel_avg_variance16x8_neon;
+    vpx_sub_pixel_avg_variance32x16 = vpx_sub_pixel_avg_variance32x16_c;
+    if (flags & HAS_NEON) vpx_sub_pixel_avg_variance32x16 = vpx_sub_pixel_avg_variance32x16_neon;
+    vpx_sub_pixel_avg_variance32x32 = vpx_sub_pixel_avg_variance32x32_c;
+    if (flags & HAS_NEON) vpx_sub_pixel_avg_variance32x32 = vpx_sub_pixel_avg_variance32x32_neon;
+    vpx_sub_pixel_avg_variance32x64 = vpx_sub_pixel_avg_variance32x64_c;
+    if (flags & HAS_NEON) vpx_sub_pixel_avg_variance32x64 = vpx_sub_pixel_avg_variance32x64_neon;
+    vpx_sub_pixel_avg_variance4x4 = vpx_sub_pixel_avg_variance4x4_c;
+    if (flags & HAS_NEON) vpx_sub_pixel_avg_variance4x4 = vpx_sub_pixel_avg_variance4x4_neon;
+    vpx_sub_pixel_avg_variance4x8 = vpx_sub_pixel_avg_variance4x8_c;
+    if (flags & HAS_NEON) vpx_sub_pixel_avg_variance4x8 = vpx_sub_pixel_avg_variance4x8_neon;
+    vpx_sub_pixel_avg_variance64x32 = vpx_sub_pixel_avg_variance64x32_c;
+    if (flags & HAS_NEON) vpx_sub_pixel_avg_variance64x32 = vpx_sub_pixel_avg_variance64x32_neon;
+    vpx_sub_pixel_avg_variance64x64 = vpx_sub_pixel_avg_variance64x64_c;
+    if (flags & HAS_NEON) vpx_sub_pixel_avg_variance64x64 = vpx_sub_pixel_avg_variance64x64_neon;
+    vpx_sub_pixel_avg_variance8x16 = vpx_sub_pixel_avg_variance8x16_c;
+    if (flags & HAS_NEON) vpx_sub_pixel_avg_variance8x16 = vpx_sub_pixel_avg_variance8x16_neon;
+    vpx_sub_pixel_avg_variance8x4 = vpx_sub_pixel_avg_variance8x4_c;
+    if (flags & HAS_NEON) vpx_sub_pixel_avg_variance8x4 = vpx_sub_pixel_avg_variance8x4_neon;
+    vpx_sub_pixel_avg_variance8x8 = vpx_sub_pixel_avg_variance8x8_c;
+    if (flags & HAS_NEON) vpx_sub_pixel_avg_variance8x8 = vpx_sub_pixel_avg_variance8x8_neon;
     vpx_sub_pixel_variance16x16 = vpx_sub_pixel_variance16x16_c;
     if (flags & HAS_NEON) vpx_sub_pixel_variance16x16 = vpx_sub_pixel_variance16x16_neon;
     vpx_sub_pixel_variance16x32 = vpx_sub_pixel_variance16x32_c;
@@ -1020,6 +1063,10 @@
     if (flags & HAS_NEON) vpx_sub_pixel_variance32x32 = vpx_sub_pixel_variance32x32_neon;
     vpx_sub_pixel_variance32x64 = vpx_sub_pixel_variance32x64_c;
     if (flags & HAS_NEON) vpx_sub_pixel_variance32x64 = vpx_sub_pixel_variance32x64_neon;
+    vpx_sub_pixel_variance4x4 = vpx_sub_pixel_variance4x4_c;
+    if (flags & HAS_NEON) vpx_sub_pixel_variance4x4 = vpx_sub_pixel_variance4x4_neon;
+    vpx_sub_pixel_variance4x8 = vpx_sub_pixel_variance4x8_c;
+    if (flags & HAS_NEON) vpx_sub_pixel_variance4x8 = vpx_sub_pixel_variance4x8_neon;
     vpx_sub_pixel_variance64x32 = vpx_sub_pixel_variance64x32_c;
     if (flags & HAS_NEON) vpx_sub_pixel_variance64x32 = vpx_sub_pixel_variance64x32_neon;
     vpx_sub_pixel_variance64x64 = vpx_sub_pixel_variance64x64_c;
@@ -1060,6 +1107,10 @@
     if (flags & HAS_NEON) vpx_variance32x32 = vpx_variance32x32_neon;
     vpx_variance32x64 = vpx_variance32x64_c;
     if (flags & HAS_NEON) vpx_variance32x64 = vpx_variance32x64_neon;
+    vpx_variance4x4 = vpx_variance4x4_c;
+    if (flags & HAS_NEON) vpx_variance4x4 = vpx_variance4x4_neon;
+    vpx_variance4x8 = vpx_variance4x8_c;
+    if (flags & HAS_NEON) vpx_variance4x8 = vpx_variance4x8_neon;
     vpx_variance64x32 = vpx_variance64x32_c;
     if (flags & HAS_NEON) vpx_variance64x32 = vpx_variance64x32_neon;
     vpx_variance64x64 = vpx_variance64x64_c;
diff --git a/third_party/libvpx/source/config/linux/arm-neon-cpu-detect/vpx_scale_rtcd.h b/third_party/libvpx/source/config/linux/arm-neon-cpu-detect/vpx_scale_rtcd.h
index a1564b7..515ce27 100644
--- a/third_party/libvpx/source/config/linux/arm-neon-cpu-detect/vpx_scale_rtcd.h
+++ b/third_party/libvpx/source/config/linux/arm-neon-cpu-detect/vpx_scale_rtcd.h
@@ -46,6 +46,9 @@
 void vpx_extend_frame_inner_borders_c(struct yv12_buffer_config *ybf);
 #define vpx_extend_frame_inner_borders vpx_extend_frame_inner_borders_c
 
+void vpx_yv12_copy_frame_c(const struct yv12_buffer_config *src_ybc, struct yv12_buffer_config *dst_ybc);
+#define vpx_yv12_copy_frame vpx_yv12_copy_frame_c
+
 void vpx_yv12_copy_y_c(const struct yv12_buffer_config *src_ybc, struct yv12_buffer_config *dst_ybc);
 #define vpx_yv12_copy_y vpx_yv12_copy_y_c
 
diff --git a/third_party/libvpx/source/config/linux/arm-neon/vpx_dsp_rtcd.h b/third_party/libvpx/source/config/linux/arm-neon/vpx_dsp_rtcd.h
index 61c4f1f..4b3c5be 100644
--- a/third_party/libvpx/source/config/linux/arm-neon/vpx_dsp_rtcd.h
+++ b/third_party/libvpx/source/config/linux/arm-neon/vpx_dsp_rtcd.h
@@ -634,43 +634,56 @@
 #define vpx_scaled_vert vpx_scaled_vert_c
 
 uint32_t vpx_sub_pixel_avg_variance16x16_c(const uint8_t *src_ptr, int source_stride, int xoffset, int  yoffset, const uint8_t *ref_ptr, int ref_stride, uint32_t *sse, const uint8_t *second_pred);
-#define vpx_sub_pixel_avg_variance16x16 vpx_sub_pixel_avg_variance16x16_c
+uint32_t vpx_sub_pixel_avg_variance16x16_neon(const uint8_t *src_ptr, int source_stride, int xoffset, int  yoffset, const uint8_t *ref_ptr, int ref_stride, uint32_t *sse, const uint8_t *second_pred);
+#define vpx_sub_pixel_avg_variance16x16 vpx_sub_pixel_avg_variance16x16_neon
 
 uint32_t vpx_sub_pixel_avg_variance16x32_c(const uint8_t *src_ptr, int source_stride, int xoffset, int  yoffset, const uint8_t *ref_ptr, int ref_stride, uint32_t *sse, const uint8_t *second_pred);
-#define vpx_sub_pixel_avg_variance16x32 vpx_sub_pixel_avg_variance16x32_c
+uint32_t vpx_sub_pixel_avg_variance16x32_neon(const uint8_t *src_ptr, int source_stride, int xoffset, int  yoffset, const uint8_t *ref_ptr, int ref_stride, uint32_t *sse, const uint8_t *second_pred);
+#define vpx_sub_pixel_avg_variance16x32 vpx_sub_pixel_avg_variance16x32_neon
 
 uint32_t vpx_sub_pixel_avg_variance16x8_c(const uint8_t *src_ptr, int source_stride, int xoffset, int  yoffset, const uint8_t *ref_ptr, int ref_stride, uint32_t *sse, const uint8_t *second_pred);
-#define vpx_sub_pixel_avg_variance16x8 vpx_sub_pixel_avg_variance16x8_c
+uint32_t vpx_sub_pixel_avg_variance16x8_neon(const uint8_t *src_ptr, int source_stride, int xoffset, int  yoffset, const uint8_t *ref_ptr, int ref_stride, uint32_t *sse, const uint8_t *second_pred);
+#define vpx_sub_pixel_avg_variance16x8 vpx_sub_pixel_avg_variance16x8_neon
 
 uint32_t vpx_sub_pixel_avg_variance32x16_c(const uint8_t *src_ptr, int source_stride, int xoffset, int  yoffset, const uint8_t *ref_ptr, int ref_stride, uint32_t *sse, const uint8_t *second_pred);
-#define vpx_sub_pixel_avg_variance32x16 vpx_sub_pixel_avg_variance32x16_c
+uint32_t vpx_sub_pixel_avg_variance32x16_neon(const uint8_t *src_ptr, int source_stride, int xoffset, int  yoffset, const uint8_t *ref_ptr, int ref_stride, uint32_t *sse, const uint8_t *second_pred);
+#define vpx_sub_pixel_avg_variance32x16 vpx_sub_pixel_avg_variance32x16_neon
 
 uint32_t vpx_sub_pixel_avg_variance32x32_c(const uint8_t *src_ptr, int source_stride, int xoffset, int  yoffset, const uint8_t *ref_ptr, int ref_stride, uint32_t *sse, const uint8_t *second_pred);
-#define vpx_sub_pixel_avg_variance32x32 vpx_sub_pixel_avg_variance32x32_c
+uint32_t vpx_sub_pixel_avg_variance32x32_neon(const uint8_t *src_ptr, int source_stride, int xoffset, int  yoffset, const uint8_t *ref_ptr, int ref_stride, uint32_t *sse, const uint8_t *second_pred);
+#define vpx_sub_pixel_avg_variance32x32 vpx_sub_pixel_avg_variance32x32_neon
 
 uint32_t vpx_sub_pixel_avg_variance32x64_c(const uint8_t *src_ptr, int source_stride, int xoffset, int  yoffset, const uint8_t *ref_ptr, int ref_stride, uint32_t *sse, const uint8_t *second_pred);
-#define vpx_sub_pixel_avg_variance32x64 vpx_sub_pixel_avg_variance32x64_c
+uint32_t vpx_sub_pixel_avg_variance32x64_neon(const uint8_t *src_ptr, int source_stride, int xoffset, int  yoffset, const uint8_t *ref_ptr, int ref_stride, uint32_t *sse, const uint8_t *second_pred);
+#define vpx_sub_pixel_avg_variance32x64 vpx_sub_pixel_avg_variance32x64_neon
 
 uint32_t vpx_sub_pixel_avg_variance4x4_c(const uint8_t *src_ptr, int source_stride, int xoffset, int  yoffset, const uint8_t *ref_ptr, int ref_stride, uint32_t *sse, const uint8_t *second_pred);
-#define vpx_sub_pixel_avg_variance4x4 vpx_sub_pixel_avg_variance4x4_c
+uint32_t vpx_sub_pixel_avg_variance4x4_neon(const uint8_t *src_ptr, int source_stride, int xoffset, int  yoffset, const uint8_t *ref_ptr, int ref_stride, uint32_t *sse, const uint8_t *second_pred);
+#define vpx_sub_pixel_avg_variance4x4 vpx_sub_pixel_avg_variance4x4_neon
 
 uint32_t vpx_sub_pixel_avg_variance4x8_c(const uint8_t *src_ptr, int source_stride, int xoffset, int  yoffset, const uint8_t *ref_ptr, int ref_stride, uint32_t *sse, const uint8_t *second_pred);
-#define vpx_sub_pixel_avg_variance4x8 vpx_sub_pixel_avg_variance4x8_c
+uint32_t vpx_sub_pixel_avg_variance4x8_neon(const uint8_t *src_ptr, int source_stride, int xoffset, int  yoffset, const uint8_t *ref_ptr, int ref_stride, uint32_t *sse, const uint8_t *second_pred);
+#define vpx_sub_pixel_avg_variance4x8 vpx_sub_pixel_avg_variance4x8_neon
 
 uint32_t vpx_sub_pixel_avg_variance64x32_c(const uint8_t *src_ptr, int source_stride, int xoffset, int  yoffset, const uint8_t *ref_ptr, int ref_stride, uint32_t *sse, const uint8_t *second_pred);
-#define vpx_sub_pixel_avg_variance64x32 vpx_sub_pixel_avg_variance64x32_c
+uint32_t vpx_sub_pixel_avg_variance64x32_neon(const uint8_t *src_ptr, int source_stride, int xoffset, int  yoffset, const uint8_t *ref_ptr, int ref_stride, uint32_t *sse, const uint8_t *second_pred);
+#define vpx_sub_pixel_avg_variance64x32 vpx_sub_pixel_avg_variance64x32_neon
 
 uint32_t vpx_sub_pixel_avg_variance64x64_c(const uint8_t *src_ptr, int source_stride, int xoffset, int  yoffset, const uint8_t *ref_ptr, int ref_stride, uint32_t *sse, const uint8_t *second_pred);
-#define vpx_sub_pixel_avg_variance64x64 vpx_sub_pixel_avg_variance64x64_c
+uint32_t vpx_sub_pixel_avg_variance64x64_neon(const uint8_t *src_ptr, int source_stride, int xoffset, int  yoffset, const uint8_t *ref_ptr, int ref_stride, uint32_t *sse, const uint8_t *second_pred);
+#define vpx_sub_pixel_avg_variance64x64 vpx_sub_pixel_avg_variance64x64_neon
 
 uint32_t vpx_sub_pixel_avg_variance8x16_c(const uint8_t *src_ptr, int source_stride, int xoffset, int  yoffset, const uint8_t *ref_ptr, int ref_stride, uint32_t *sse, const uint8_t *second_pred);
-#define vpx_sub_pixel_avg_variance8x16 vpx_sub_pixel_avg_variance8x16_c
+uint32_t vpx_sub_pixel_avg_variance8x16_neon(const uint8_t *src_ptr, int source_stride, int xoffset, int  yoffset, const uint8_t *ref_ptr, int ref_stride, uint32_t *sse, const uint8_t *second_pred);
+#define vpx_sub_pixel_avg_variance8x16 vpx_sub_pixel_avg_variance8x16_neon
 
 uint32_t vpx_sub_pixel_avg_variance8x4_c(const uint8_t *src_ptr, int source_stride, int xoffset, int  yoffset, const uint8_t *ref_ptr, int ref_stride, uint32_t *sse, const uint8_t *second_pred);
-#define vpx_sub_pixel_avg_variance8x4 vpx_sub_pixel_avg_variance8x4_c
+uint32_t vpx_sub_pixel_avg_variance8x4_neon(const uint8_t *src_ptr, int source_stride, int xoffset, int  yoffset, const uint8_t *ref_ptr, int ref_stride, uint32_t *sse, const uint8_t *second_pred);
+#define vpx_sub_pixel_avg_variance8x4 vpx_sub_pixel_avg_variance8x4_neon
 
 uint32_t vpx_sub_pixel_avg_variance8x8_c(const uint8_t *src_ptr, int source_stride, int xoffset, int  yoffset, const uint8_t *ref_ptr, int ref_stride, uint32_t *sse, const uint8_t *second_pred);
-#define vpx_sub_pixel_avg_variance8x8 vpx_sub_pixel_avg_variance8x8_c
+uint32_t vpx_sub_pixel_avg_variance8x8_neon(const uint8_t *src_ptr, int source_stride, int xoffset, int  yoffset, const uint8_t *ref_ptr, int ref_stride, uint32_t *sse, const uint8_t *second_pred);
+#define vpx_sub_pixel_avg_variance8x8 vpx_sub_pixel_avg_variance8x8_neon
 
 uint32_t vpx_sub_pixel_variance16x16_c(const uint8_t *src_ptr, int source_stride, int xoffset, int  yoffset, const uint8_t *ref_ptr, int ref_stride, uint32_t *sse);
 uint32_t vpx_sub_pixel_variance16x16_neon(const uint8_t *src_ptr, int source_stride, int xoffset, int  yoffset, const uint8_t *ref_ptr, int ref_stride, uint32_t *sse);
@@ -697,10 +710,12 @@
 #define vpx_sub_pixel_variance32x64 vpx_sub_pixel_variance32x64_neon
 
 uint32_t vpx_sub_pixel_variance4x4_c(const uint8_t *src_ptr, int source_stride, int xoffset, int  yoffset, const uint8_t *ref_ptr, int ref_stride, uint32_t *sse);
-#define vpx_sub_pixel_variance4x4 vpx_sub_pixel_variance4x4_c
+uint32_t vpx_sub_pixel_variance4x4_neon(const uint8_t *src_ptr, int source_stride, int xoffset, int  yoffset, const uint8_t *ref_ptr, int ref_stride, uint32_t *sse);
+#define vpx_sub_pixel_variance4x4 vpx_sub_pixel_variance4x4_neon
 
 uint32_t vpx_sub_pixel_variance4x8_c(const uint8_t *src_ptr, int source_stride, int xoffset, int  yoffset, const uint8_t *ref_ptr, int ref_stride, uint32_t *sse);
-#define vpx_sub_pixel_variance4x8 vpx_sub_pixel_variance4x8_c
+uint32_t vpx_sub_pixel_variance4x8_neon(const uint8_t *src_ptr, int source_stride, int xoffset, int  yoffset, const uint8_t *ref_ptr, int ref_stride, uint32_t *sse);
+#define vpx_sub_pixel_variance4x8 vpx_sub_pixel_variance4x8_neon
 
 uint32_t vpx_sub_pixel_variance64x32_c(const uint8_t *src_ptr, int source_stride, int xoffset, int  yoffset, const uint8_t *ref_ptr, int ref_stride, uint32_t *sse);
 uint32_t vpx_sub_pixel_variance64x32_neon(const uint8_t *src_ptr, int source_stride, int xoffset, int  yoffset, const uint8_t *ref_ptr, int ref_stride, uint32_t *sse);
@@ -786,10 +801,12 @@
 #define vpx_variance32x64 vpx_variance32x64_neon
 
 unsigned int vpx_variance4x4_c(const uint8_t *src_ptr, int source_stride, const uint8_t *ref_ptr, int ref_stride, unsigned int *sse);
-#define vpx_variance4x4 vpx_variance4x4_c
+unsigned int vpx_variance4x4_neon(const uint8_t *src_ptr, int source_stride, const uint8_t *ref_ptr, int ref_stride, unsigned int *sse);
+#define vpx_variance4x4 vpx_variance4x4_neon
 
 unsigned int vpx_variance4x8_c(const uint8_t *src_ptr, int source_stride, const uint8_t *ref_ptr, int ref_stride, unsigned int *sse);
-#define vpx_variance4x8 vpx_variance4x8_c
+unsigned int vpx_variance4x8_neon(const uint8_t *src_ptr, int source_stride, const uint8_t *ref_ptr, int ref_stride, unsigned int *sse);
+#define vpx_variance4x8 vpx_variance4x8_neon
 
 unsigned int vpx_variance64x32_c(const uint8_t *src_ptr, int source_stride, const uint8_t *ref_ptr, int ref_stride, unsigned int *sse);
 unsigned int vpx_variance64x32_neon(const uint8_t *src_ptr, int source_stride, const uint8_t *ref_ptr, int ref_stride, unsigned int *sse);
diff --git a/third_party/libvpx/source/config/linux/arm-neon/vpx_scale_rtcd.h b/third_party/libvpx/source/config/linux/arm-neon/vpx_scale_rtcd.h
index a1564b7..515ce27 100644
--- a/third_party/libvpx/source/config/linux/arm-neon/vpx_scale_rtcd.h
+++ b/third_party/libvpx/source/config/linux/arm-neon/vpx_scale_rtcd.h
@@ -46,6 +46,9 @@
 void vpx_extend_frame_inner_borders_c(struct yv12_buffer_config *ybf);
 #define vpx_extend_frame_inner_borders vpx_extend_frame_inner_borders_c
 
+void vpx_yv12_copy_frame_c(const struct yv12_buffer_config *src_ybc, struct yv12_buffer_config *dst_ybc);
+#define vpx_yv12_copy_frame vpx_yv12_copy_frame_c
+
 void vpx_yv12_copy_y_c(const struct yv12_buffer_config *src_ybc, struct yv12_buffer_config *dst_ybc);
 #define vpx_yv12_copy_y vpx_yv12_copy_y_c
 
diff --git a/third_party/libvpx/source/config/linux/arm/vpx_scale_rtcd.h b/third_party/libvpx/source/config/linux/arm/vpx_scale_rtcd.h
index a1564b7..515ce27 100644
--- a/third_party/libvpx/source/config/linux/arm/vpx_scale_rtcd.h
+++ b/third_party/libvpx/source/config/linux/arm/vpx_scale_rtcd.h
@@ -46,6 +46,9 @@
 void vpx_extend_frame_inner_borders_c(struct yv12_buffer_config *ybf);
 #define vpx_extend_frame_inner_borders vpx_extend_frame_inner_borders_c
 
+void vpx_yv12_copy_frame_c(const struct yv12_buffer_config *src_ybc, struct yv12_buffer_config *dst_ybc);
+#define vpx_yv12_copy_frame vpx_yv12_copy_frame_c
+
 void vpx_yv12_copy_y_c(const struct yv12_buffer_config *src_ybc, struct yv12_buffer_config *dst_ybc);
 #define vpx_yv12_copy_y vpx_yv12_copy_y_c
 
diff --git a/third_party/libvpx/source/config/linux/arm64/vpx_dsp_rtcd.h b/third_party/libvpx/source/config/linux/arm64/vpx_dsp_rtcd.h
index 61c4f1f..4b3c5be 100644
--- a/third_party/libvpx/source/config/linux/arm64/vpx_dsp_rtcd.h
+++ b/third_party/libvpx/source/config/linux/arm64/vpx_dsp_rtcd.h
@@ -634,43 +634,56 @@
 #define vpx_scaled_vert vpx_scaled_vert_c
 
 uint32_t vpx_sub_pixel_avg_variance16x16_c(const uint8_t *src_ptr, int source_stride, int xoffset, int  yoffset, const uint8_t *ref_ptr, int ref_stride, uint32_t *sse, const uint8_t *second_pred);
-#define vpx_sub_pixel_avg_variance16x16 vpx_sub_pixel_avg_variance16x16_c
+uint32_t vpx_sub_pixel_avg_variance16x16_neon(const uint8_t *src_ptr, int source_stride, int xoffset, int  yoffset, const uint8_t *ref_ptr, int ref_stride, uint32_t *sse, const uint8_t *second_pred);
+#define vpx_sub_pixel_avg_variance16x16 vpx_sub_pixel_avg_variance16x16_neon
 
 uint32_t vpx_sub_pixel_avg_variance16x32_c(const uint8_t *src_ptr, int source_stride, int xoffset, int  yoffset, const uint8_t *ref_ptr, int ref_stride, uint32_t *sse, const uint8_t *second_pred);
-#define vpx_sub_pixel_avg_variance16x32 vpx_sub_pixel_avg_variance16x32_c
+uint32_t vpx_sub_pixel_avg_variance16x32_neon(const uint8_t *src_ptr, int source_stride, int xoffset, int  yoffset, const uint8_t *ref_ptr, int ref_stride, uint32_t *sse, const uint8_t *second_pred);
+#define vpx_sub_pixel_avg_variance16x32 vpx_sub_pixel_avg_variance16x32_neon
 
 uint32_t vpx_sub_pixel_avg_variance16x8_c(const uint8_t *src_ptr, int source_stride, int xoffset, int  yoffset, const uint8_t *ref_ptr, int ref_stride, uint32_t *sse, const uint8_t *second_pred);
-#define vpx_sub_pixel_avg_variance16x8 vpx_sub_pixel_avg_variance16x8_c
+uint32_t vpx_sub_pixel_avg_variance16x8_neon(const uint8_t *src_ptr, int source_stride, int xoffset, int  yoffset, const uint8_t *ref_ptr, int ref_stride, uint32_t *sse, const uint8_t *second_pred);
+#define vpx_sub_pixel_avg_variance16x8 vpx_sub_pixel_avg_variance16x8_neon
 
 uint32_t vpx_sub_pixel_avg_variance32x16_c(const uint8_t *src_ptr, int source_stride, int xoffset, int  yoffset, const uint8_t *ref_ptr, int ref_stride, uint32_t *sse, const uint8_t *second_pred);
-#define vpx_sub_pixel_avg_variance32x16 vpx_sub_pixel_avg_variance32x16_c
+uint32_t vpx_sub_pixel_avg_variance32x16_neon(const uint8_t *src_ptr, int source_stride, int xoffset, int  yoffset, const uint8_t *ref_ptr, int ref_stride, uint32_t *sse, const uint8_t *second_pred);
+#define vpx_sub_pixel_avg_variance32x16 vpx_sub_pixel_avg_variance32x16_neon
 
 uint32_t vpx_sub_pixel_avg_variance32x32_c(const uint8_t *src_ptr, int source_stride, int xoffset, int  yoffset, const uint8_t *ref_ptr, int ref_stride, uint32_t *sse, const uint8_t *second_pred);
-#define vpx_sub_pixel_avg_variance32x32 vpx_sub_pixel_avg_variance32x32_c
+uint32_t vpx_sub_pixel_avg_variance32x32_neon(const uint8_t *src_ptr, int source_stride, int xoffset, int  yoffset, const uint8_t *ref_ptr, int ref_stride, uint32_t *sse, const uint8_t *second_pred);
+#define vpx_sub_pixel_avg_variance32x32 vpx_sub_pixel_avg_variance32x32_neon
 
 uint32_t vpx_sub_pixel_avg_variance32x64_c(const uint8_t *src_ptr, int source_stride, int xoffset, int  yoffset, const uint8_t *ref_ptr, int ref_stride, uint32_t *sse, const uint8_t *second_pred);
-#define vpx_sub_pixel_avg_variance32x64 vpx_sub_pixel_avg_variance32x64_c
+uint32_t vpx_sub_pixel_avg_variance32x64_neon(const uint8_t *src_ptr, int source_stride, int xoffset, int  yoffset, const uint8_t *ref_ptr, int ref_stride, uint32_t *sse, const uint8_t *second_pred);
+#define vpx_sub_pixel_avg_variance32x64 vpx_sub_pixel_avg_variance32x64_neon
 
 uint32_t vpx_sub_pixel_avg_variance4x4_c(const uint8_t *src_ptr, int source_stride, int xoffset, int  yoffset, const uint8_t *ref_ptr, int ref_stride, uint32_t *sse, const uint8_t *second_pred);
-#define vpx_sub_pixel_avg_variance4x4 vpx_sub_pixel_avg_variance4x4_c
+uint32_t vpx_sub_pixel_avg_variance4x4_neon(const uint8_t *src_ptr, int source_stride, int xoffset, int  yoffset, const uint8_t *ref_ptr, int ref_stride, uint32_t *sse, const uint8_t *second_pred);
+#define vpx_sub_pixel_avg_variance4x4 vpx_sub_pixel_avg_variance4x4_neon
 
 uint32_t vpx_sub_pixel_avg_variance4x8_c(const uint8_t *src_ptr, int source_stride, int xoffset, int  yoffset, const uint8_t *ref_ptr, int ref_stride, uint32_t *sse, const uint8_t *second_pred);
-#define vpx_sub_pixel_avg_variance4x8 vpx_sub_pixel_avg_variance4x8_c
+uint32_t vpx_sub_pixel_avg_variance4x8_neon(const uint8_t *src_ptr, int source_stride, int xoffset, int  yoffset, const uint8_t *ref_ptr, int ref_stride, uint32_t *sse, const uint8_t *second_pred);
+#define vpx_sub_pixel_avg_variance4x8 vpx_sub_pixel_avg_variance4x8_neon
 
 uint32_t vpx_sub_pixel_avg_variance64x32_c(const uint8_t *src_ptr, int source_stride, int xoffset, int  yoffset, const uint8_t *ref_ptr, int ref_stride, uint32_t *sse, const uint8_t *second_pred);
-#define vpx_sub_pixel_avg_variance64x32 vpx_sub_pixel_avg_variance64x32_c
+uint32_t vpx_sub_pixel_avg_variance64x32_neon(const uint8_t *src_ptr, int source_stride, int xoffset, int  yoffset, const uint8_t *ref_ptr, int ref_stride, uint32_t *sse, const uint8_t *second_pred);
+#define vpx_sub_pixel_avg_variance64x32 vpx_sub_pixel_avg_variance64x32_neon
 
 uint32_t vpx_sub_pixel_avg_variance64x64_c(const uint8_t *src_ptr, int source_stride, int xoffset, int  yoffset, const uint8_t *ref_ptr, int ref_stride, uint32_t *sse, const uint8_t *second_pred);
-#define vpx_sub_pixel_avg_variance64x64 vpx_sub_pixel_avg_variance64x64_c
+uint32_t vpx_sub_pixel_avg_variance64x64_neon(const uint8_t *src_ptr, int source_stride, int xoffset, int  yoffset, const uint8_t *ref_ptr, int ref_stride, uint32_t *sse, const uint8_t *second_pred);
+#define vpx_sub_pixel_avg_variance64x64 vpx_sub_pixel_avg_variance64x64_neon
 
 uint32_t vpx_sub_pixel_avg_variance8x16_c(const uint8_t *src_ptr, int source_stride, int xoffset, int  yoffset, const uint8_t *ref_ptr, int ref_stride, uint32_t *sse, const uint8_t *second_pred);
-#define vpx_sub_pixel_avg_variance8x16 vpx_sub_pixel_avg_variance8x16_c
+uint32_t vpx_sub_pixel_avg_variance8x16_neon(const uint8_t *src_ptr, int source_stride, int xoffset, int  yoffset, const uint8_t *ref_ptr, int ref_stride, uint32_t *sse, const uint8_t *second_pred);
+#define vpx_sub_pixel_avg_variance8x16 vpx_sub_pixel_avg_variance8x16_neon
 
 uint32_t vpx_sub_pixel_avg_variance8x4_c(const uint8_t *src_ptr, int source_stride, int xoffset, int  yoffset, const uint8_t *ref_ptr, int ref_stride, uint32_t *sse, const uint8_t *second_pred);
-#define vpx_sub_pixel_avg_variance8x4 vpx_sub_pixel_avg_variance8x4_c
+uint32_t vpx_sub_pixel_avg_variance8x4_neon(const uint8_t *src_ptr, int source_stride, int xoffset, int  yoffset, const uint8_t *ref_ptr, int ref_stride, uint32_t *sse, const uint8_t *second_pred);
+#define vpx_sub_pixel_avg_variance8x4 vpx_sub_pixel_avg_variance8x4_neon
 
 uint32_t vpx_sub_pixel_avg_variance8x8_c(const uint8_t *src_ptr, int source_stride, int xoffset, int  yoffset, const uint8_t *ref_ptr, int ref_stride, uint32_t *sse, const uint8_t *second_pred);
-#define vpx_sub_pixel_avg_variance8x8 vpx_sub_pixel_avg_variance8x8_c
+uint32_t vpx_sub_pixel_avg_variance8x8_neon(const uint8_t *src_ptr, int source_stride, int xoffset, int  yoffset, const uint8_t *ref_ptr, int ref_stride, uint32_t *sse, const uint8_t *second_pred);
+#define vpx_sub_pixel_avg_variance8x8 vpx_sub_pixel_avg_variance8x8_neon
 
 uint32_t vpx_sub_pixel_variance16x16_c(const uint8_t *src_ptr, int source_stride, int xoffset, int  yoffset, const uint8_t *ref_ptr, int ref_stride, uint32_t *sse);
 uint32_t vpx_sub_pixel_variance16x16_neon(const uint8_t *src_ptr, int source_stride, int xoffset, int  yoffset, const uint8_t *ref_ptr, int ref_stride, uint32_t *sse);
@@ -697,10 +710,12 @@
 #define vpx_sub_pixel_variance32x64 vpx_sub_pixel_variance32x64_neon
 
 uint32_t vpx_sub_pixel_variance4x4_c(const uint8_t *src_ptr, int source_stride, int xoffset, int  yoffset, const uint8_t *ref_ptr, int ref_stride, uint32_t *sse);
-#define vpx_sub_pixel_variance4x4 vpx_sub_pixel_variance4x4_c
+uint32_t vpx_sub_pixel_variance4x4_neon(const uint8_t *src_ptr, int source_stride, int xoffset, int  yoffset, const uint8_t *ref_ptr, int ref_stride, uint32_t *sse);
+#define vpx_sub_pixel_variance4x4 vpx_sub_pixel_variance4x4_neon
 
 uint32_t vpx_sub_pixel_variance4x8_c(const uint8_t *src_ptr, int source_stride, int xoffset, int  yoffset, const uint8_t *ref_ptr, int ref_stride, uint32_t *sse);
-#define vpx_sub_pixel_variance4x8 vpx_sub_pixel_variance4x8_c
+uint32_t vpx_sub_pixel_variance4x8_neon(const uint8_t *src_ptr, int source_stride, int xoffset, int  yoffset, const uint8_t *ref_ptr, int ref_stride, uint32_t *sse);
+#define vpx_sub_pixel_variance4x8 vpx_sub_pixel_variance4x8_neon
 
 uint32_t vpx_sub_pixel_variance64x32_c(const uint8_t *src_ptr, int source_stride, int xoffset, int  yoffset, const uint8_t *ref_ptr, int ref_stride, uint32_t *sse);
 uint32_t vpx_sub_pixel_variance64x32_neon(const uint8_t *src_ptr, int source_stride, int xoffset, int  yoffset, const uint8_t *ref_ptr, int ref_stride, uint32_t *sse);
@@ -786,10 +801,12 @@
 #define vpx_variance32x64 vpx_variance32x64_neon
 
 unsigned int vpx_variance4x4_c(const uint8_t *src_ptr, int source_stride, const uint8_t *ref_ptr, int ref_stride, unsigned int *sse);
-#define vpx_variance4x4 vpx_variance4x4_c
+unsigned int vpx_variance4x4_neon(const uint8_t *src_ptr, int source_stride, const uint8_t *ref_ptr, int ref_stride, unsigned int *sse);
+#define vpx_variance4x4 vpx_variance4x4_neon
 
 unsigned int vpx_variance4x8_c(const uint8_t *src_ptr, int source_stride, const uint8_t *ref_ptr, int ref_stride, unsigned int *sse);
-#define vpx_variance4x8 vpx_variance4x8_c
+unsigned int vpx_variance4x8_neon(const uint8_t *src_ptr, int source_stride, const uint8_t *ref_ptr, int ref_stride, unsigned int *sse);
+#define vpx_variance4x8 vpx_variance4x8_neon
 
 unsigned int vpx_variance64x32_c(const uint8_t *src_ptr, int source_stride, const uint8_t *ref_ptr, int ref_stride, unsigned int *sse);
 unsigned int vpx_variance64x32_neon(const uint8_t *src_ptr, int source_stride, const uint8_t *ref_ptr, int ref_stride, unsigned int *sse);
diff --git a/third_party/libvpx/source/config/linux/arm64/vpx_scale_rtcd.h b/third_party/libvpx/source/config/linux/arm64/vpx_scale_rtcd.h
index a1564b7..515ce27 100644
--- a/third_party/libvpx/source/config/linux/arm64/vpx_scale_rtcd.h
+++ b/third_party/libvpx/source/config/linux/arm64/vpx_scale_rtcd.h
@@ -46,6 +46,9 @@
 void vpx_extend_frame_inner_borders_c(struct yv12_buffer_config *ybf);
 #define vpx_extend_frame_inner_borders vpx_extend_frame_inner_borders_c
 
+void vpx_yv12_copy_frame_c(const struct yv12_buffer_config *src_ybc, struct yv12_buffer_config *dst_ybc);
+#define vpx_yv12_copy_frame vpx_yv12_copy_frame_c
+
 void vpx_yv12_copy_y_c(const struct yv12_buffer_config *src_ybc, struct yv12_buffer_config *dst_ybc);
 #define vpx_yv12_copy_y vpx_yv12_copy_y_c
 
diff --git a/third_party/libvpx/source/config/linux/generic/vpx_scale_rtcd.h b/third_party/libvpx/source/config/linux/generic/vpx_scale_rtcd.h
index f419cc7..0098208 100644
--- a/third_party/libvpx/source/config/linux/generic/vpx_scale_rtcd.h
+++ b/third_party/libvpx/source/config/linux/generic/vpx_scale_rtcd.h
@@ -46,6 +46,9 @@
 void vpx_extend_frame_inner_borders_c(struct yv12_buffer_config *ybf);
 #define vpx_extend_frame_inner_borders vpx_extend_frame_inner_borders_c
 
+void vpx_yv12_copy_frame_c(const struct yv12_buffer_config *src_ybc, struct yv12_buffer_config *dst_ybc);
+#define vpx_yv12_copy_frame vpx_yv12_copy_frame_c
+
 void vpx_yv12_copy_y_c(const struct yv12_buffer_config *src_ybc, struct yv12_buffer_config *dst_ybc);
 #define vpx_yv12_copy_y vpx_yv12_copy_y_c
 
diff --git a/third_party/libvpx/source/config/linux/ia32/vpx_dsp_rtcd.h b/third_party/libvpx/source/config/linux/ia32/vpx_dsp_rtcd.h
index 49450cda..8c3e3237 100644
--- a/third_party/libvpx/source/config/linux/ia32/vpx_dsp_rtcd.h
+++ b/third_party/libvpx/source/config/linux/ia32/vpx_dsp_rtcd.h
@@ -1029,7 +1029,8 @@
 RTCD_EXTERN void (*vpx_highbd_idct16x16_10_add)(const tran_low_t *input, uint16_t *dest, int stride, int bd);
 
 void vpx_highbd_idct16x16_1_add_c(const tran_low_t *input, uint16_t *dest, int stride, int bd);
-#define vpx_highbd_idct16x16_1_add vpx_highbd_idct16x16_1_add_c
+void vpx_highbd_idct16x16_1_add_sse2(const tran_low_t *input, uint16_t *dest, int stride, int bd);
+RTCD_EXTERN void (*vpx_highbd_idct16x16_1_add)(const tran_low_t *input, uint16_t *dest, int stride, int bd);
 
 void vpx_highbd_idct16x16_256_add_c(const tran_low_t *input, uint16_t *dest, int stride, int bd);
 void vpx_highbd_idct16x16_256_add_sse2(const tran_low_t *input, uint16_t *dest, int stride, int bd);
@@ -1057,14 +1058,16 @@
 RTCD_EXTERN void (*vpx_highbd_idct4x4_16_add)(const tran_low_t *input, uint16_t *dest, int stride, int bd);
 
 void vpx_highbd_idct4x4_1_add_c(const tran_low_t *input, uint16_t *dest, int stride, int bd);
-#define vpx_highbd_idct4x4_1_add vpx_highbd_idct4x4_1_add_c
+void vpx_highbd_idct4x4_1_add_sse2(const tran_low_t *input, uint16_t *dest, int stride, int bd);
+RTCD_EXTERN void (*vpx_highbd_idct4x4_1_add)(const tran_low_t *input, uint16_t *dest, int stride, int bd);
 
 void vpx_highbd_idct8x8_12_add_c(const tran_low_t *input, uint16_t *dest, int stride, int bd);
 void vpx_highbd_idct8x8_12_add_sse2(const tran_low_t *input, uint16_t *dest, int stride, int bd);
 RTCD_EXTERN void (*vpx_highbd_idct8x8_12_add)(const tran_low_t *input, uint16_t *dest, int stride, int bd);
 
 void vpx_highbd_idct8x8_1_add_c(const tran_low_t *input, uint16_t *dest, int stride, int bd);
-#define vpx_highbd_idct8x8_1_add vpx_highbd_idct8x8_1_add_c
+void vpx_highbd_idct8x8_1_add_sse2(const tran_low_t *input, uint16_t *dest, int stride, int bd);
+RTCD_EXTERN void (*vpx_highbd_idct8x8_1_add)(const tran_low_t *input, uint16_t *dest, int stride, int bd);
 
 void vpx_highbd_idct8x8_64_add_c(const tran_low_t *input, uint16_t *dest, int stride, int bd);
 void vpx_highbd_idct8x8_64_add_sse2(const tran_low_t *input, uint16_t *dest, int stride, int bd);
@@ -2409,6 +2412,8 @@
     if (flags & HAS_SSE2) vpx_highbd_fdct8x8 = vpx_highbd_fdct8x8_sse2;
     vpx_highbd_idct16x16_10_add = vpx_highbd_idct16x16_10_add_c;
     if (flags & HAS_SSE2) vpx_highbd_idct16x16_10_add = vpx_highbd_idct16x16_10_add_sse2;
+    vpx_highbd_idct16x16_1_add = vpx_highbd_idct16x16_1_add_c;
+    if (flags & HAS_SSE2) vpx_highbd_idct16x16_1_add = vpx_highbd_idct16x16_1_add_sse2;
     vpx_highbd_idct16x16_256_add = vpx_highbd_idct16x16_256_add_c;
     if (flags & HAS_SSE2) vpx_highbd_idct16x16_256_add = vpx_highbd_idct16x16_256_add_sse2;
     vpx_highbd_idct16x16_38_add = vpx_highbd_idct16x16_38_add_c;
@@ -2417,8 +2422,12 @@
     if (flags & HAS_SSE2) vpx_highbd_idct32x32_1_add = vpx_highbd_idct32x32_1_add_sse2;
     vpx_highbd_idct4x4_16_add = vpx_highbd_idct4x4_16_add_c;
     if (flags & HAS_SSE2) vpx_highbd_idct4x4_16_add = vpx_highbd_idct4x4_16_add_sse2;
+    vpx_highbd_idct4x4_1_add = vpx_highbd_idct4x4_1_add_c;
+    if (flags & HAS_SSE2) vpx_highbd_idct4x4_1_add = vpx_highbd_idct4x4_1_add_sse2;
     vpx_highbd_idct8x8_12_add = vpx_highbd_idct8x8_12_add_c;
     if (flags & HAS_SSE2) vpx_highbd_idct8x8_12_add = vpx_highbd_idct8x8_12_add_sse2;
+    vpx_highbd_idct8x8_1_add = vpx_highbd_idct8x8_1_add_c;
+    if (flags & HAS_SSE2) vpx_highbd_idct8x8_1_add = vpx_highbd_idct8x8_1_add_sse2;
     vpx_highbd_idct8x8_64_add = vpx_highbd_idct8x8_64_add_c;
     if (flags & HAS_SSE2) vpx_highbd_idct8x8_64_add = vpx_highbd_idct8x8_64_add_sse2;
     vpx_highbd_lpf_horizontal_16 = vpx_highbd_lpf_horizontal_16_c;
diff --git a/third_party/libvpx/source/config/linux/ia32/vpx_scale_rtcd.h b/third_party/libvpx/source/config/linux/ia32/vpx_scale_rtcd.h
index ddf7d01..ada0f6d 100644
--- a/third_party/libvpx/source/config/linux/ia32/vpx_scale_rtcd.h
+++ b/third_party/libvpx/source/config/linux/ia32/vpx_scale_rtcd.h
@@ -46,6 +46,9 @@
 void vpx_extend_frame_inner_borders_c(struct yv12_buffer_config *ybf);
 #define vpx_extend_frame_inner_borders vpx_extend_frame_inner_borders_c
 
+void vpx_yv12_copy_frame_c(const struct yv12_buffer_config *src_ybc, struct yv12_buffer_config *dst_ybc);
+#define vpx_yv12_copy_frame vpx_yv12_copy_frame_c
+
 void vpx_yv12_copy_y_c(const struct yv12_buffer_config *src_ybc, struct yv12_buffer_config *dst_ybc);
 #define vpx_yv12_copy_y vpx_yv12_copy_y_c
 
diff --git a/third_party/libvpx/source/config/linux/mips64el/vpx_scale_rtcd.h b/third_party/libvpx/source/config/linux/mips64el/vpx_scale_rtcd.h
index f419cc7..0098208 100644
--- a/third_party/libvpx/source/config/linux/mips64el/vpx_scale_rtcd.h
+++ b/third_party/libvpx/source/config/linux/mips64el/vpx_scale_rtcd.h
@@ -46,6 +46,9 @@
 void vpx_extend_frame_inner_borders_c(struct yv12_buffer_config *ybf);
 #define vpx_extend_frame_inner_borders vpx_extend_frame_inner_borders_c
 
+void vpx_yv12_copy_frame_c(const struct yv12_buffer_config *src_ybc, struct yv12_buffer_config *dst_ybc);
+#define vpx_yv12_copy_frame vpx_yv12_copy_frame_c
+
 void vpx_yv12_copy_y_c(const struct yv12_buffer_config *src_ybc, struct yv12_buffer_config *dst_ybc);
 #define vpx_yv12_copy_y vpx_yv12_copy_y_c
 
diff --git a/third_party/libvpx/source/config/linux/mipsel/vpx_scale_rtcd.h b/third_party/libvpx/source/config/linux/mipsel/vpx_scale_rtcd.h
index f419cc7..0098208 100644
--- a/third_party/libvpx/source/config/linux/mipsel/vpx_scale_rtcd.h
+++ b/third_party/libvpx/source/config/linux/mipsel/vpx_scale_rtcd.h
@@ -46,6 +46,9 @@
 void vpx_extend_frame_inner_borders_c(struct yv12_buffer_config *ybf);
 #define vpx_extend_frame_inner_borders vpx_extend_frame_inner_borders_c
 
+void vpx_yv12_copy_frame_c(const struct yv12_buffer_config *src_ybc, struct yv12_buffer_config *dst_ybc);
+#define vpx_yv12_copy_frame vpx_yv12_copy_frame_c
+
 void vpx_yv12_copy_y_c(const struct yv12_buffer_config *src_ybc, struct yv12_buffer_config *dst_ybc);
 #define vpx_yv12_copy_y vpx_yv12_copy_y_c
 
diff --git a/third_party/libvpx/source/config/linux/x64/vpx_dsp_rtcd.h b/third_party/libvpx/source/config/linux/x64/vpx_dsp_rtcd.h
index b2403c3..77c3cc12 100644
--- a/third_party/libvpx/source/config/linux/x64/vpx_dsp_rtcd.h
+++ b/third_party/libvpx/source/config/linux/x64/vpx_dsp_rtcd.h
@@ -1036,7 +1036,8 @@
 #define vpx_highbd_idct16x16_10_add vpx_highbd_idct16x16_10_add_sse2
 
 void vpx_highbd_idct16x16_1_add_c(const tran_low_t *input, uint16_t *dest, int stride, int bd);
-#define vpx_highbd_idct16x16_1_add vpx_highbd_idct16x16_1_add_c
+void vpx_highbd_idct16x16_1_add_sse2(const tran_low_t *input, uint16_t *dest, int stride, int bd);
+#define vpx_highbd_idct16x16_1_add vpx_highbd_idct16x16_1_add_sse2
 
 void vpx_highbd_idct16x16_256_add_c(const tran_low_t *input, uint16_t *dest, int stride, int bd);
 void vpx_highbd_idct16x16_256_add_sse2(const tran_low_t *input, uint16_t *dest, int stride, int bd);
@@ -1064,14 +1065,16 @@
 #define vpx_highbd_idct4x4_16_add vpx_highbd_idct4x4_16_add_sse2
 
 void vpx_highbd_idct4x4_1_add_c(const tran_low_t *input, uint16_t *dest, int stride, int bd);
-#define vpx_highbd_idct4x4_1_add vpx_highbd_idct4x4_1_add_c
+void vpx_highbd_idct4x4_1_add_sse2(const tran_low_t *input, uint16_t *dest, int stride, int bd);
+#define vpx_highbd_idct4x4_1_add vpx_highbd_idct4x4_1_add_sse2
 
 void vpx_highbd_idct8x8_12_add_c(const tran_low_t *input, uint16_t *dest, int stride, int bd);
 void vpx_highbd_idct8x8_12_add_sse2(const tran_low_t *input, uint16_t *dest, int stride, int bd);
 #define vpx_highbd_idct8x8_12_add vpx_highbd_idct8x8_12_add_sse2
 
 void vpx_highbd_idct8x8_1_add_c(const tran_low_t *input, uint16_t *dest, int stride, int bd);
-#define vpx_highbd_idct8x8_1_add vpx_highbd_idct8x8_1_add_c
+void vpx_highbd_idct8x8_1_add_sse2(const tran_low_t *input, uint16_t *dest, int stride, int bd);
+#define vpx_highbd_idct8x8_1_add vpx_highbd_idct8x8_1_add_sse2
 
 void vpx_highbd_idct8x8_64_add_c(const tran_low_t *input, uint16_t *dest, int stride, int bd);
 void vpx_highbd_idct8x8_64_add_sse2(const tran_low_t *input, uint16_t *dest, int stride, int bd);
diff --git a/third_party/libvpx/source/config/linux/x64/vpx_scale_rtcd.h b/third_party/libvpx/source/config/linux/x64/vpx_scale_rtcd.h
index ddf7d01..ada0f6d 100644
--- a/third_party/libvpx/source/config/linux/x64/vpx_scale_rtcd.h
+++ b/third_party/libvpx/source/config/linux/x64/vpx_scale_rtcd.h
@@ -46,6 +46,9 @@
 void vpx_extend_frame_inner_borders_c(struct yv12_buffer_config *ybf);
 #define vpx_extend_frame_inner_borders vpx_extend_frame_inner_borders_c
 
+void vpx_yv12_copy_frame_c(const struct yv12_buffer_config *src_ybc, struct yv12_buffer_config *dst_ybc);
+#define vpx_yv12_copy_frame vpx_yv12_copy_frame_c
+
 void vpx_yv12_copy_y_c(const struct yv12_buffer_config *src_ybc, struct yv12_buffer_config *dst_ybc);
 #define vpx_yv12_copy_y vpx_yv12_copy_y_c
 
diff --git a/third_party/libvpx/source/config/mac/ia32/vpx_dsp_rtcd.h b/third_party/libvpx/source/config/mac/ia32/vpx_dsp_rtcd.h
index 49450cda..8c3e3237 100644
--- a/third_party/libvpx/source/config/mac/ia32/vpx_dsp_rtcd.h
+++ b/third_party/libvpx/source/config/mac/ia32/vpx_dsp_rtcd.h
@@ -1029,7 +1029,8 @@
 RTCD_EXTERN void (*vpx_highbd_idct16x16_10_add)(const tran_low_t *input, uint16_t *dest, int stride, int bd);
 
 void vpx_highbd_idct16x16_1_add_c(const tran_low_t *input, uint16_t *dest, int stride, int bd);
-#define vpx_highbd_idct16x16_1_add vpx_highbd_idct16x16_1_add_c
+void vpx_highbd_idct16x16_1_add_sse2(const tran_low_t *input, uint16_t *dest, int stride, int bd);
+RTCD_EXTERN void (*vpx_highbd_idct16x16_1_add)(const tran_low_t *input, uint16_t *dest, int stride, int bd);
 
 void vpx_highbd_idct16x16_256_add_c(const tran_low_t *input, uint16_t *dest, int stride, int bd);
 void vpx_highbd_idct16x16_256_add_sse2(const tran_low_t *input, uint16_t *dest, int stride, int bd);
@@ -1057,14 +1058,16 @@
 RTCD_EXTERN void (*vpx_highbd_idct4x4_16_add)(const tran_low_t *input, uint16_t *dest, int stride, int bd);
 
 void vpx_highbd_idct4x4_1_add_c(const tran_low_t *input, uint16_t *dest, int stride, int bd);
-#define vpx_highbd_idct4x4_1_add vpx_highbd_idct4x4_1_add_c
+void vpx_highbd_idct4x4_1_add_sse2(const tran_low_t *input, uint16_t *dest, int stride, int bd);
+RTCD_EXTERN void (*vpx_highbd_idct4x4_1_add)(const tran_low_t *input, uint16_t *dest, int stride, int bd);
 
 void vpx_highbd_idct8x8_12_add_c(const tran_low_t *input, uint16_t *dest, int stride, int bd);
 void vpx_highbd_idct8x8_12_add_sse2(const tran_low_t *input, uint16_t *dest, int stride, int bd);
 RTCD_EXTERN void (*vpx_highbd_idct8x8_12_add)(const tran_low_t *input, uint16_t *dest, int stride, int bd);
 
 void vpx_highbd_idct8x8_1_add_c(const tran_low_t *input, uint16_t *dest, int stride, int bd);
-#define vpx_highbd_idct8x8_1_add vpx_highbd_idct8x8_1_add_c
+void vpx_highbd_idct8x8_1_add_sse2(const tran_low_t *input, uint16_t *dest, int stride, int bd);
+RTCD_EXTERN void (*vpx_highbd_idct8x8_1_add)(const tran_low_t *input, uint16_t *dest, int stride, int bd);
 
 void vpx_highbd_idct8x8_64_add_c(const tran_low_t *input, uint16_t *dest, int stride, int bd);
 void vpx_highbd_idct8x8_64_add_sse2(const tran_low_t *input, uint16_t *dest, int stride, int bd);
@@ -2409,6 +2412,8 @@
     if (flags & HAS_SSE2) vpx_highbd_fdct8x8 = vpx_highbd_fdct8x8_sse2;
     vpx_highbd_idct16x16_10_add = vpx_highbd_idct16x16_10_add_c;
     if (flags & HAS_SSE2) vpx_highbd_idct16x16_10_add = vpx_highbd_idct16x16_10_add_sse2;
+    vpx_highbd_idct16x16_1_add = vpx_highbd_idct16x16_1_add_c;
+    if (flags & HAS_SSE2) vpx_highbd_idct16x16_1_add = vpx_highbd_idct16x16_1_add_sse2;
     vpx_highbd_idct16x16_256_add = vpx_highbd_idct16x16_256_add_c;
     if (flags & HAS_SSE2) vpx_highbd_idct16x16_256_add = vpx_highbd_idct16x16_256_add_sse2;
     vpx_highbd_idct16x16_38_add = vpx_highbd_idct16x16_38_add_c;
@@ -2417,8 +2422,12 @@
     if (flags & HAS_SSE2) vpx_highbd_idct32x32_1_add = vpx_highbd_idct32x32_1_add_sse2;
     vpx_highbd_idct4x4_16_add = vpx_highbd_idct4x4_16_add_c;
     if (flags & HAS_SSE2) vpx_highbd_idct4x4_16_add = vpx_highbd_idct4x4_16_add_sse2;
+    vpx_highbd_idct4x4_1_add = vpx_highbd_idct4x4_1_add_c;
+    if (flags & HAS_SSE2) vpx_highbd_idct4x4_1_add = vpx_highbd_idct4x4_1_add_sse2;
     vpx_highbd_idct8x8_12_add = vpx_highbd_idct8x8_12_add_c;
     if (flags & HAS_SSE2) vpx_highbd_idct8x8_12_add = vpx_highbd_idct8x8_12_add_sse2;
+    vpx_highbd_idct8x8_1_add = vpx_highbd_idct8x8_1_add_c;
+    if (flags & HAS_SSE2) vpx_highbd_idct8x8_1_add = vpx_highbd_idct8x8_1_add_sse2;
     vpx_highbd_idct8x8_64_add = vpx_highbd_idct8x8_64_add_c;
     if (flags & HAS_SSE2) vpx_highbd_idct8x8_64_add = vpx_highbd_idct8x8_64_add_sse2;
     vpx_highbd_lpf_horizontal_16 = vpx_highbd_lpf_horizontal_16_c;
diff --git a/third_party/libvpx/source/config/mac/ia32/vpx_scale_rtcd.h b/third_party/libvpx/source/config/mac/ia32/vpx_scale_rtcd.h
index ddf7d01..ada0f6d 100644
--- a/third_party/libvpx/source/config/mac/ia32/vpx_scale_rtcd.h
+++ b/third_party/libvpx/source/config/mac/ia32/vpx_scale_rtcd.h
@@ -46,6 +46,9 @@
 void vpx_extend_frame_inner_borders_c(struct yv12_buffer_config *ybf);
 #define vpx_extend_frame_inner_borders vpx_extend_frame_inner_borders_c
 
+void vpx_yv12_copy_frame_c(const struct yv12_buffer_config *src_ybc, struct yv12_buffer_config *dst_ybc);
+#define vpx_yv12_copy_frame vpx_yv12_copy_frame_c
+
 void vpx_yv12_copy_y_c(const struct yv12_buffer_config *src_ybc, struct yv12_buffer_config *dst_ybc);
 #define vpx_yv12_copy_y vpx_yv12_copy_y_c
 
diff --git a/third_party/libvpx/source/config/mac/x64/vpx_dsp_rtcd.h b/third_party/libvpx/source/config/mac/x64/vpx_dsp_rtcd.h
index b2403c3..77c3cc12 100644
--- a/third_party/libvpx/source/config/mac/x64/vpx_dsp_rtcd.h
+++ b/third_party/libvpx/source/config/mac/x64/vpx_dsp_rtcd.h
@@ -1036,7 +1036,8 @@
 #define vpx_highbd_idct16x16_10_add vpx_highbd_idct16x16_10_add_sse2
 
 void vpx_highbd_idct16x16_1_add_c(const tran_low_t *input, uint16_t *dest, int stride, int bd);
-#define vpx_highbd_idct16x16_1_add vpx_highbd_idct16x16_1_add_c
+void vpx_highbd_idct16x16_1_add_sse2(const tran_low_t *input, uint16_t *dest, int stride, int bd);
+#define vpx_highbd_idct16x16_1_add vpx_highbd_idct16x16_1_add_sse2
 
 void vpx_highbd_idct16x16_256_add_c(const tran_low_t *input, uint16_t *dest, int stride, int bd);
 void vpx_highbd_idct16x16_256_add_sse2(const tran_low_t *input, uint16_t *dest, int stride, int bd);
@@ -1064,14 +1065,16 @@
 #define vpx_highbd_idct4x4_16_add vpx_highbd_idct4x4_16_add_sse2
 
 void vpx_highbd_idct4x4_1_add_c(const tran_low_t *input, uint16_t *dest, int stride, int bd);
-#define vpx_highbd_idct4x4_1_add vpx_highbd_idct4x4_1_add_c
+void vpx_highbd_idct4x4_1_add_sse2(const tran_low_t *input, uint16_t *dest, int stride, int bd);
+#define vpx_highbd_idct4x4_1_add vpx_highbd_idct4x4_1_add_sse2
 
 void vpx_highbd_idct8x8_12_add_c(const tran_low_t *input, uint16_t *dest, int stride, int bd);
 void vpx_highbd_idct8x8_12_add_sse2(const tran_low_t *input, uint16_t *dest, int stride, int bd);
 #define vpx_highbd_idct8x8_12_add vpx_highbd_idct8x8_12_add_sse2
 
 void vpx_highbd_idct8x8_1_add_c(const tran_low_t *input, uint16_t *dest, int stride, int bd);
-#define vpx_highbd_idct8x8_1_add vpx_highbd_idct8x8_1_add_c
+void vpx_highbd_idct8x8_1_add_sse2(const tran_low_t *input, uint16_t *dest, int stride, int bd);
+#define vpx_highbd_idct8x8_1_add vpx_highbd_idct8x8_1_add_sse2
 
 void vpx_highbd_idct8x8_64_add_c(const tran_low_t *input, uint16_t *dest, int stride, int bd);
 void vpx_highbd_idct8x8_64_add_sse2(const tran_low_t *input, uint16_t *dest, int stride, int bd);
diff --git a/third_party/libvpx/source/config/mac/x64/vpx_scale_rtcd.h b/third_party/libvpx/source/config/mac/x64/vpx_scale_rtcd.h
index ddf7d01..ada0f6d 100644
--- a/third_party/libvpx/source/config/mac/x64/vpx_scale_rtcd.h
+++ b/third_party/libvpx/source/config/mac/x64/vpx_scale_rtcd.h
@@ -46,6 +46,9 @@
 void vpx_extend_frame_inner_borders_c(struct yv12_buffer_config *ybf);
 #define vpx_extend_frame_inner_borders vpx_extend_frame_inner_borders_c
 
+void vpx_yv12_copy_frame_c(const struct yv12_buffer_config *src_ybc, struct yv12_buffer_config *dst_ybc);
+#define vpx_yv12_copy_frame vpx_yv12_copy_frame_c
+
 void vpx_yv12_copy_y_c(const struct yv12_buffer_config *src_ybc, struct yv12_buffer_config *dst_ybc);
 #define vpx_yv12_copy_y vpx_yv12_copy_y_c
 
diff --git a/third_party/libvpx/source/config/nacl/vpx_scale_rtcd.h b/third_party/libvpx/source/config/nacl/vpx_scale_rtcd.h
index f419cc7..0098208 100644
--- a/third_party/libvpx/source/config/nacl/vpx_scale_rtcd.h
+++ b/third_party/libvpx/source/config/nacl/vpx_scale_rtcd.h
@@ -46,6 +46,9 @@
 void vpx_extend_frame_inner_borders_c(struct yv12_buffer_config *ybf);
 #define vpx_extend_frame_inner_borders vpx_extend_frame_inner_borders_c
 
+void vpx_yv12_copy_frame_c(const struct yv12_buffer_config *src_ybc, struct yv12_buffer_config *dst_ybc);
+#define vpx_yv12_copy_frame vpx_yv12_copy_frame_c
+
 void vpx_yv12_copy_y_c(const struct yv12_buffer_config *src_ybc, struct yv12_buffer_config *dst_ybc);
 #define vpx_yv12_copy_y vpx_yv12_copy_y_c
 
diff --git a/third_party/libvpx/source/config/vpx_version.h b/third_party/libvpx/source/config/vpx_version.h
index e8dde9d..1204fe1 100644
--- a/third_party/libvpx/source/config/vpx_version.h
+++ b/third_party/libvpx/source/config/vpx_version.h
@@ -1,7 +1,7 @@
 #define VERSION_MAJOR  1
 #define VERSION_MINOR  6
 #define VERSION_PATCH  1
-#define VERSION_EXTRA  "657-gb3bf91bdc"
+#define VERSION_EXTRA  "691-gb9649d240"
 #define VERSION_PACKED ((VERSION_MAJOR<<16)|(VERSION_MINOR<<8)|(VERSION_PATCH))
-#define VERSION_STRING_NOSP "v1.6.1-657-gb3bf91bdc"
-#define VERSION_STRING      " v1.6.1-657-gb3bf91bdc"
+#define VERSION_STRING_NOSP "v1.6.1-691-gb9649d240"
+#define VERSION_STRING      " v1.6.1-691-gb9649d240"
diff --git a/third_party/libvpx/source/config/win/ia32/vpx_dsp_rtcd.h b/third_party/libvpx/source/config/win/ia32/vpx_dsp_rtcd.h
index 49450cda..8c3e3237 100644
--- a/third_party/libvpx/source/config/win/ia32/vpx_dsp_rtcd.h
+++ b/third_party/libvpx/source/config/win/ia32/vpx_dsp_rtcd.h
@@ -1029,7 +1029,8 @@
 RTCD_EXTERN void (*vpx_highbd_idct16x16_10_add)(const tran_low_t *input, uint16_t *dest, int stride, int bd);
 
 void vpx_highbd_idct16x16_1_add_c(const tran_low_t *input, uint16_t *dest, int stride, int bd);
-#define vpx_highbd_idct16x16_1_add vpx_highbd_idct16x16_1_add_c
+void vpx_highbd_idct16x16_1_add_sse2(const tran_low_t *input, uint16_t *dest, int stride, int bd);
+RTCD_EXTERN void (*vpx_highbd_idct16x16_1_add)(const tran_low_t *input, uint16_t *dest, int stride, int bd);
 
 void vpx_highbd_idct16x16_256_add_c(const tran_low_t *input, uint16_t *dest, int stride, int bd);
 void vpx_highbd_idct16x16_256_add_sse2(const tran_low_t *input, uint16_t *dest, int stride, int bd);
@@ -1057,14 +1058,16 @@
 RTCD_EXTERN void (*vpx_highbd_idct4x4_16_add)(const tran_low_t *input, uint16_t *dest, int stride, int bd);
 
 void vpx_highbd_idct4x4_1_add_c(const tran_low_t *input, uint16_t *dest, int stride, int bd);
-#define vpx_highbd_idct4x4_1_add vpx_highbd_idct4x4_1_add_c
+void vpx_highbd_idct4x4_1_add_sse2(const tran_low_t *input, uint16_t *dest, int stride, int bd);
+RTCD_EXTERN void (*vpx_highbd_idct4x4_1_add)(const tran_low_t *input, uint16_t *dest, int stride, int bd);
 
 void vpx_highbd_idct8x8_12_add_c(const tran_low_t *input, uint16_t *dest, int stride, int bd);
 void vpx_highbd_idct8x8_12_add_sse2(const tran_low_t *input, uint16_t *dest, int stride, int bd);
 RTCD_EXTERN void (*vpx_highbd_idct8x8_12_add)(const tran_low_t *input, uint16_t *dest, int stride, int bd);
 
 void vpx_highbd_idct8x8_1_add_c(const tran_low_t *input, uint16_t *dest, int stride, int bd);
-#define vpx_highbd_idct8x8_1_add vpx_highbd_idct8x8_1_add_c
+void vpx_highbd_idct8x8_1_add_sse2(const tran_low_t *input, uint16_t *dest, int stride, int bd);
+RTCD_EXTERN void (*vpx_highbd_idct8x8_1_add)(const tran_low_t *input, uint16_t *dest, int stride, int bd);
 
 void vpx_highbd_idct8x8_64_add_c(const tran_low_t *input, uint16_t *dest, int stride, int bd);
 void vpx_highbd_idct8x8_64_add_sse2(const tran_low_t *input, uint16_t *dest, int stride, int bd);
@@ -2409,6 +2412,8 @@
     if (flags & HAS_SSE2) vpx_highbd_fdct8x8 = vpx_highbd_fdct8x8_sse2;
     vpx_highbd_idct16x16_10_add = vpx_highbd_idct16x16_10_add_c;
     if (flags & HAS_SSE2) vpx_highbd_idct16x16_10_add = vpx_highbd_idct16x16_10_add_sse2;
+    vpx_highbd_idct16x16_1_add = vpx_highbd_idct16x16_1_add_c;
+    if (flags & HAS_SSE2) vpx_highbd_idct16x16_1_add = vpx_highbd_idct16x16_1_add_sse2;
     vpx_highbd_idct16x16_256_add = vpx_highbd_idct16x16_256_add_c;
     if (flags & HAS_SSE2) vpx_highbd_idct16x16_256_add = vpx_highbd_idct16x16_256_add_sse2;
     vpx_highbd_idct16x16_38_add = vpx_highbd_idct16x16_38_add_c;
@@ -2417,8 +2422,12 @@
     if (flags & HAS_SSE2) vpx_highbd_idct32x32_1_add = vpx_highbd_idct32x32_1_add_sse2;
     vpx_highbd_idct4x4_16_add = vpx_highbd_idct4x4_16_add_c;
     if (flags & HAS_SSE2) vpx_highbd_idct4x4_16_add = vpx_highbd_idct4x4_16_add_sse2;
+    vpx_highbd_idct4x4_1_add = vpx_highbd_idct4x4_1_add_c;
+    if (flags & HAS_SSE2) vpx_highbd_idct4x4_1_add = vpx_highbd_idct4x4_1_add_sse2;
     vpx_highbd_idct8x8_12_add = vpx_highbd_idct8x8_12_add_c;
     if (flags & HAS_SSE2) vpx_highbd_idct8x8_12_add = vpx_highbd_idct8x8_12_add_sse2;
+    vpx_highbd_idct8x8_1_add = vpx_highbd_idct8x8_1_add_c;
+    if (flags & HAS_SSE2) vpx_highbd_idct8x8_1_add = vpx_highbd_idct8x8_1_add_sse2;
     vpx_highbd_idct8x8_64_add = vpx_highbd_idct8x8_64_add_c;
     if (flags & HAS_SSE2) vpx_highbd_idct8x8_64_add = vpx_highbd_idct8x8_64_add_sse2;
     vpx_highbd_lpf_horizontal_16 = vpx_highbd_lpf_horizontal_16_c;
diff --git a/third_party/libvpx/source/config/win/ia32/vpx_scale_rtcd.h b/third_party/libvpx/source/config/win/ia32/vpx_scale_rtcd.h
index ddf7d01..ada0f6d 100644
--- a/third_party/libvpx/source/config/win/ia32/vpx_scale_rtcd.h
+++ b/third_party/libvpx/source/config/win/ia32/vpx_scale_rtcd.h
@@ -46,6 +46,9 @@
 void vpx_extend_frame_inner_borders_c(struct yv12_buffer_config *ybf);
 #define vpx_extend_frame_inner_borders vpx_extend_frame_inner_borders_c
 
+void vpx_yv12_copy_frame_c(const struct yv12_buffer_config *src_ybc, struct yv12_buffer_config *dst_ybc);
+#define vpx_yv12_copy_frame vpx_yv12_copy_frame_c
+
 void vpx_yv12_copy_y_c(const struct yv12_buffer_config *src_ybc, struct yv12_buffer_config *dst_ybc);
 #define vpx_yv12_copy_y vpx_yv12_copy_y_c
 
diff --git a/third_party/libvpx/source/config/win/x64/vpx_dsp_rtcd.h b/third_party/libvpx/source/config/win/x64/vpx_dsp_rtcd.h
index b2403c3..77c3cc12 100644
--- a/third_party/libvpx/source/config/win/x64/vpx_dsp_rtcd.h
+++ b/third_party/libvpx/source/config/win/x64/vpx_dsp_rtcd.h
@@ -1036,7 +1036,8 @@
 #define vpx_highbd_idct16x16_10_add vpx_highbd_idct16x16_10_add_sse2
 
 void vpx_highbd_idct16x16_1_add_c(const tran_low_t *input, uint16_t *dest, int stride, int bd);
-#define vpx_highbd_idct16x16_1_add vpx_highbd_idct16x16_1_add_c
+void vpx_highbd_idct16x16_1_add_sse2(const tran_low_t *input, uint16_t *dest, int stride, int bd);
+#define vpx_highbd_idct16x16_1_add vpx_highbd_idct16x16_1_add_sse2
 
 void vpx_highbd_idct16x16_256_add_c(const tran_low_t *input, uint16_t *dest, int stride, int bd);
 void vpx_highbd_idct16x16_256_add_sse2(const tran_low_t *input, uint16_t *dest, int stride, int bd);
@@ -1064,14 +1065,16 @@
 #define vpx_highbd_idct4x4_16_add vpx_highbd_idct4x4_16_add_sse2
 
 void vpx_highbd_idct4x4_1_add_c(const tran_low_t *input, uint16_t *dest, int stride, int bd);
-#define vpx_highbd_idct4x4_1_add vpx_highbd_idct4x4_1_add_c
+void vpx_highbd_idct4x4_1_add_sse2(const tran_low_t *input, uint16_t *dest, int stride, int bd);
+#define vpx_highbd_idct4x4_1_add vpx_highbd_idct4x4_1_add_sse2
 
 void vpx_highbd_idct8x8_12_add_c(const tran_low_t *input, uint16_t *dest, int stride, int bd);
 void vpx_highbd_idct8x8_12_add_sse2(const tran_low_t *input, uint16_t *dest, int stride, int bd);
 #define vpx_highbd_idct8x8_12_add vpx_highbd_idct8x8_12_add_sse2
 
 void vpx_highbd_idct8x8_1_add_c(const tran_low_t *input, uint16_t *dest, int stride, int bd);
-#define vpx_highbd_idct8x8_1_add vpx_highbd_idct8x8_1_add_c
+void vpx_highbd_idct8x8_1_add_sse2(const tran_low_t *input, uint16_t *dest, int stride, int bd);
+#define vpx_highbd_idct8x8_1_add vpx_highbd_idct8x8_1_add_sse2
 
 void vpx_highbd_idct8x8_64_add_c(const tran_low_t *input, uint16_t *dest, int stride, int bd);
 void vpx_highbd_idct8x8_64_add_sse2(const tran_low_t *input, uint16_t *dest, int stride, int bd);
diff --git a/third_party/libvpx/source/config/win/x64/vpx_scale_rtcd.h b/third_party/libvpx/source/config/win/x64/vpx_scale_rtcd.h
index ddf7d01..ada0f6d 100644
--- a/third_party/libvpx/source/config/win/x64/vpx_scale_rtcd.h
+++ b/third_party/libvpx/source/config/win/x64/vpx_scale_rtcd.h
@@ -46,6 +46,9 @@
 void vpx_extend_frame_inner_borders_c(struct yv12_buffer_config *ybf);
 #define vpx_extend_frame_inner_borders vpx_extend_frame_inner_borders_c
 
+void vpx_yv12_copy_frame_c(const struct yv12_buffer_config *src_ybc, struct yv12_buffer_config *dst_ybc);
+#define vpx_yv12_copy_frame vpx_yv12_copy_frame_c
+
 void vpx_yv12_copy_y_c(const struct yv12_buffer_config *src_ybc, struct yv12_buffer_config *dst_ybc);
 #define vpx_yv12_copy_y vpx_yv12_copy_y_c
 
diff --git a/tools/android/eclipse/.classpath b/tools/android/eclipse/.classpath
index 17a0858..e933cd8 100644
--- a/tools/android/eclipse/.classpath
+++ b/tools/android/eclipse/.classpath
@@ -174,6 +174,7 @@
     <classpathentry kind="src" path="out/Debug/gen/enums/offline_page_model_enums_java"/>
     <classpathentry kind="src" path="out/Debug/gen/enums/page_info_connection_type_java"/>
     <classpathentry kind="src" path="out/Debug/gen/enums/page_transition_types_java"/>
+    <classpathentry kind="src" path="out/Debug/gen/enums/payments_journey_logger_enum_java"/>
     <classpathentry kind="src" path="out/Debug/gen/enums/popup_item_type_java"/>
     <classpathentry kind="src" path="out/Debug/gen/enums/private_key_types_java"/>
     <classpathentry kind="src" path="out/Debug/gen/enums/profile_account_management_metrics_java"/>
diff --git a/tools/chrome_proxy/webdriver/video.py b/tools/chrome_proxy/webdriver/video.py
index ec0f648..7b203bef1 100644
--- a/tools/chrome_proxy/webdriver/video.py
+++ b/tools/chrome_proxy/webdriver/video.py
@@ -152,12 +152,24 @@
     self.instrumentedVideoTest('http://check.googlezip.net/cacheable/video/buck_bunny_640x360_24fps_video.html')
 
   # Check the audio volume of a compressed video.
-  @NotAndroid
+  #
+  # This test makes some assumptions about the way audio is decoded and
+  # processed in JavaScript on different platforms. Despite getting the same
+  # video bytes from the proxy across all platforms, different data is generated
+  # out of the window.AudioContext object. As of May 2017, there were only two
+  # known datasets, the second occuring on all tested Android devices. If this
+  # test fails on a new or different platform, examine whether the expected data
+  # is drastically different. See crbug.com/723031 for more information.
   @Slow
   def testVideoAudio(self):
-    self.instrumentedVideoTest('http://check.googlezip.net/cacheable/video/buck_bunny_640x360_24fps_audio.html')
+    alt_data = None
+    is_android = ParseFlags().android
+    if is_android:
+      alt_data = 'data/buck_bunny_640x360_24fps.mp4.expected_volume_alt.json'
+    self.instrumentedVideoTest('http://check.googlezip.net/cacheable/video/buck_bunny_640x360_24fps_audio.html',
+      alt_data=alt_data, needs_click=is_android)
 
-  def instrumentedVideoTest(self, url):
+  def instrumentedVideoTest(self, url, alt_data=None, needs_click=False):
     """Run an instrumented video test. The given page is reloaded up to some
     maximum number of times until a compressed video is seen by ChromeDriver by
     inspecting the network logs. Once that happens, test.ready is set and that
@@ -184,7 +196,11 @@
             time.sleep(1)
       if attempts >= max_attempts:
         self.fail('Could not get a compressed video after %d tries' % attempts)
+      if alt_data != None:
+        t.ExecuteJavascriptStatement('test.expectedVolumeSrc = "%s"' % alt_data)
       t.ExecuteJavascriptStatement('test.ready = true')
+      if needs_click:
+        t.FindElement(By.ID, 'video').click()
       waitTimeQuery = 'test.waitTime'
       if ParseFlags().android:
         waitTimeQuery = 'test.androidWaitTime'
@@ -192,9 +208,9 @@
       t.WaitForJavascriptExpression('test.metrics.complete', wait_time)
       metrics = t.ExecuteJavascriptStatement('test.metrics')
       if not metrics['complete']:
-        raise Exception('Test not complete after %d seconds.' % wait_time)
+        self.fail('Test not complete after %d seconds.' % wait_time)
       if metrics['failed']:
-        raise Exception('Test failed!')
+        self.fail('Test failed! ' + metrics['detailedStatus'])
 
   # Make sure YouTube autoplays.
   def testYoutube(self):
diff --git a/tools/metrics/histograms/enums.xml b/tools/metrics/histograms/enums.xml
index 09c8bd5..db43539 100644
--- a/tools/metrics/histograms/enums.xml
+++ b/tools/metrics/histograms/enums.xml
@@ -13029,7 +13029,7 @@
 </enum>
 
 <enum name="FeatureObserver" type="int">
-<!-- Generated from third_party/WebKit/Source/core/frame/UseCounter.h -->
+<!-- Generated from third_party/WebKit/public/platform/UseCounterFeature.def -->
 
   <int value="0" label="OBSOLETE_PageDestruction"/>
   <int value="1" label="LegacyNotifications"/>
@@ -26237,6 +26237,10 @@
     Save operation failed because an interstitial page (i.e. page warning of
     expired certificates or improper dev signatures) was detected.
   </int>
+  <int value="11" label="Archive folder missing">
+    Save operation failed because there's no available archive folder for the
+    page and the attemp to create the archive folder also failed.
+  </int>
 </enum>
 
 <enum name="OfflinePagesSharedPageWasOffline" type="int">
diff --git a/tools/metrics/histograms/histograms.xml b/tools/metrics/histograms/histograms.xml
index 81ea290..1073cb0 100644
--- a/tools/metrics/histograms/histograms.xml
+++ b/tools/metrics/histograms/histograms.xml
@@ -87846,6 +87846,12 @@
   <affected-histogram name="Net.QuicSession.ConnectionCloseErrorCodeServer"/>
 </histogram_suffixes>
 
+<histogram_suffixes name="HighDownloadBandwidth" separator=".">
+  <suffix name="HighDownloadBandwidth" label="download with high bandwidth."/>
+  <affected-histogram name="Download.Parallelizable.DownloadTime"/>
+  <affected-histogram name="Download.Parallelizable.FileSize"/>
+</histogram_suffixes>
+
 <histogram_suffixes name="HistogramInconsistencies" separator=".">
   <suffix name="Cronet" label="Cronet histograms."/>
   <affected-histogram name="Histogram.InconsistenciesBrowser"/>
@@ -90127,6 +90133,7 @@
     </obsolete>
   </suffix>
   <affected-histogram name="Net.HttpContentLength"/>
+  <affected-histogram name="Net.HttpOriginalContentLength"/>
 </histogram_suffixes>
 
 <histogram_suffixes name="NetHttpContentLengthType2" separator=".">
@@ -90142,6 +90149,8 @@
       label="Bytes of traffic that passed through the Data Reduction Proxy"/>
   <affected-histogram name="Net.HttpContentLength.Http"/>
   <affected-histogram name="Net.HttpContentLength.Https"/>
+  <affected-histogram name="Net.HttpOriginalContentLength.Http"/>
+  <affected-histogram name="Net.HttpOriginalContentLength.Https"/>
 </histogram_suffixes>
 
 <histogram_suffixes name="NetHttpContentLengthType3" separator=".">
@@ -90907,6 +90916,13 @@
   </affected-histogram>
 </histogram_suffixes>
 
+<histogram_suffixes name="PageLoadMetricsAfterBuffering" separator=".">
+  <suffix name="AfterBuffering"
+      label="Recorded after buffering of timing updates in the browser
+             process has completed."/>
+  <affected-histogram name="PageLoad.Internal.OutOfOrderInterFrameTiming"/>
+</histogram_suffixes>
+
 <histogram_suffixes name="PageLoadMetricsAfterPaint" separator=".">
   <suffix name="AfterPaint"
       label="Limited to the duration of time starting after first paint, for
diff --git a/tools/metrics/histograms/update_use_counter_feature_enum.py b/tools/metrics/histograms/update_use_counter_feature_enum.py
index a0bf042d..4213288 100755
--- a/tools/metrics/histograms/update_use_counter_feature_enum.py
+++ b/tools/metrics/histograms/update_use_counter_feature_enum.py
@@ -32,9 +32,9 @@
                     'https://github.com/GoogleChrome/chromium-dashboard')
   options, args = parser.parse_args()
 
-  source_path = 'third_party/WebKit/Source/core/frame/UseCounter.h'
+  source_path = 'third_party/WebKit/public/platform/UseCounterFeature.def'
 
-  START_MARKER = '^enum Feature : uint32_t {'
+  START_MARKER = '^'
   END_MARKER = '^kNumberOfFeatures'
 
   if options.dashboard:
diff --git a/tools/metrics/ukm/ukm.xml b/tools/metrics/ukm/ukm.xml
index c3640cba..4e73c79 100644
--- a/tools/metrics/ukm/ukm.xml
+++ b/tools/metrics/ukm/ukm.xml
@@ -26,7 +26,7 @@
 </event>
 
 <event name="Autofill.DeveloperEngagement">
-  <owner>csashi@google.com</owner>
+  <owner>jiahuiguo@google.com</owner>
   <summary>
     Recorded when we parse a form to log whether developer has used autocomplete
     markup or UPI-VPA hints. The value is a bitmask of
@@ -36,7 +36,7 @@
 </event>
 
 <event name="Autofill.FormSubmitted">
-  <owner>csashi@google.com</owner>
+  <owner>jiahuiguo@google.com</owner>
   <summary>
     Recorded when user submits a form.
   </summary>
@@ -54,7 +54,7 @@
 </event>
 
 <event name="Autofill.InteractedWithForm">
-  <owner>csashi@google.com</owner>
+  <owner>jiahuiguo@google.com</owner>
   <summary>
     Recorded when we parse a form to log form metadata and autofill settings
     that apply to all subsequent events for this form.
@@ -77,7 +77,7 @@
 </event>
 
 <event name="Autofill.SelectedMaskedServerCard">
-  <owner>csashi@google.com</owner>
+  <owner>jiahuiguo@google.com</owner>
   <metric name="MillisecondsSinceFormParsed">
     <summary>
       Time since form parse.
@@ -86,7 +86,7 @@
 </event>
 
 <event name="Autofill.SuggestionFilled">
-  <owner>csashi@google.com</owner>
+  <owner>jiahuiguo@google.com</owner>
   <summary>
     Recorded when user selects a suggestion and we fill the form with that
     suggestion.
@@ -105,7 +105,7 @@
 </event>
 
 <event name="Autofill.SuggestionsShown">
-  <owner>csashi@google.com</owner>
+  <owner>jiahuiguo@google.com</owner>
   <summary>
     Recorded when a suggestion is shown to user.
   </summary>
@@ -134,7 +134,7 @@
 </event>
 
 <event name="Autofill.TextFieldDidChange">
-  <owner>csashi@google.com</owner>
+  <owner>jiahuiguo@google.com</owner>
   <summary>
     Recorded when user edits a text field. The text field may have been
     autofilled.
@@ -296,24 +296,93 @@
 <event name="PageLoad" singular="True">
   <owner>bmcquade@chromium.org</owner>
   <summary>
-    Recorded when Pageload observer events fire.
+    Core metrics associated with web page loads.
   </summary>
   <metric name="DocumentTiming.NavigationToDOMContentLoadedEventFired">
     <summary>
-      Time from navigation to dom content loaded in ms.
+      Measures the time in milliseconds from navigation timing's navigation
+      start to the time the DOMContentLoaded event is fired, for main frame
+      documents.
     </summary>
   </metric>
-  <metric name="DocumentTiming.NavigationToLoadEventFired"/>
-  <metric name="Experimental.PaintTiming.NavigationToFirstMeaningfulPaint"/>
-  <metric name="Navigation.PageTransition"/>
-  <metric name="Net.EffectiveConnectionType.OnNavigationStart"/>
-  <metric name="Net.ErrorCode.OnFailedProvisionalLoad"/>
-  <metric name="PageTiming.ForegroundDuration"/>
-  <metric name="PageTiming.NavigationToFailedProvisionalLoad"/>
-  <metric name="PaintTiming.NavigationToFirstContentfulPaint"/>
+  <metric name="DocumentTiming.NavigationToLoadEventFired">
+    <summary>
+      Measures the time in milliseconds from navigation timing's navigation
+      start to the time the load event is fired, for main frame documents.
+    </summary>
+  </metric>
+  <metric name="Experimental.PaintTiming.NavigationToFirstMeaningfulPaint">
+    <summary>
+      Measures the time in milliseconds from navigation timing's navigation
+      start to the first meaningful paint (http://bit.ly/ttfmp-doc), for main
+      frame documents.
+    </summary>
+  </metric>
+  <metric name="Navigation.PageTransition">
+    <summary>
+      The |ui::PageTransition| for the main frame navigation of this page load.
+    </summary>
+  </metric>
+  <metric name="Net.EffectiveConnectionType.OnNavigationStart">
+    <summary>
+      The |net::EffectiveConnectionType| at the time the navigation for this
+      page load was initiated.
+    </summary>
+  </metric>
+  <metric name="Net.ErrorCode.OnFailedProvisionalLoad">
+    <summary>
+      The |net::Error| code for this page load. Only logged for failed
+      provisional navigations.
+    </summary>
+  </metric>
+  <metric name="Net.HttpRttEstimate.OnNavigationStart">
+    <summary>
+      The HTTP round trip time estimate for this page load, at the time the
+      navigation for this page load was initiated.
+    </summary>
+  </metric>
+  <metric name="Net.TransportRttEstimate.OnNavigationStart">
+    <summary>
+      The transport round trip time estimate for this page load, at the time the
+      navigation for this page load was initiated.
+    </summary>
+  </metric>
+  <metric name="PageTiming.ForegroundDuration">
+    <summary>
+      For page loads that start in the foreground, measures the duration of time
+      in milliseconds until one of the following events occurs: the load of the
+      main resource fails, the page load is stopped, the tab hosting the page is
+      closed, the render process hosting the page goes away, a new navigation
+      which later commits is initiated in the same tab, or the tab hosting the
+      page is backgrounded. This metric has a very long tail, for pages that
+      spend a long period of time in the foreground. As such, use of the mean or
+      tail values are not recommended.
+    </summary>
+  </metric>
+  <metric name="PageTiming.NavigationToFailedProvisionalLoad">
+    <summary>
+      Measures the time in milliseconds from navigation timing's navigation
+      start to the time the provisional load failed. Only measures provisional
+      loads that failed in the foreground.
+    </summary>
+  </metric>
+  <metric name="PaintTiming.NavigationToFirstContentfulPaint">
+    <summary>
+      Measures the time in milliseconds from navigation timing's navigation
+      start to the time when the page first paints content. A contentful paint
+      includes a paint of text, image, SVG, or canvas.
+    </summary>
+  </metric>
+  <metric name="PaintTiming.NavigationToFirstPaint">
+    <summary>
+      Measures the time in milliseconds from navigation timing's navigation
+      start to the time the first paint is performed.
+    </summary>
+  </metric>
   <metric name="ParseTiming.NavigationToParseStart">
     <summary>
-      Time from navigation to parse start in ms.
+      Measures the time in milliseconds from navigation timing's navigation
+      start to the time the parser started, for main frame documents.
     </summary>
   </metric>
 </event>
diff --git a/tools/perf/benchmarks/system_health_smoke_test.py b/tools/perf/benchmarks/system_health_smoke_test.py
index 2918184..0ca7d624 100644
--- a/tools/perf/benchmarks/system_health_smoke_test.py
+++ b/tools/perf/benchmarks/system_health_smoke_test.py
@@ -64,6 +64,14 @@
 
   # crbug.com/699966
   'benchmarks.system_health_smoke_test.SystemHealthBenchmarkSmokeTest.system_health.memory_desktop.multitab:misc:typical24', # pylint: disable=line-too-long
+  # crbug.com/725923
+  'benchmarks.system_health_smoke_test.SystemHealthBenchmarkSmokeTest.system_health.memory_desktop.load:social:facebook', # pylint: disable=line-too-long
+  'benchmarks.system_health_smoke_test.SystemHealthBenchmarkSmokeTest.system_health.memory_desktop.load:media:flickr', # pylint: disable=line-too-long
+  'benchmarks.system_health_smoke_test.SystemHealthBenchmarkSmokeTest.system_health.memory_desktop.load:social:tumblr', # pylint: disable=line-too-long
+  'benchmarks.system_health_smoke_test.SystemHealthBenchmarkSmokeTest.system_health.memory_desktop.load:social:twitter', # pylint: disable=line-too-long
+  'benchmarks.system_health_smoke_test.SystemHealthBenchmarkSmokeTest.system_health.memory_mobile.load:social:facebook', # pylint: disable=line-too-long
+  'benchmarks.system_health_smoke_test.SystemHealthBenchmarkSmokeTest.system_health.memory_mobile.load:social:tumblr', # pylint: disable=line-too-long
+  'benchmarks.system_health_smoke_test.SystemHealthBenchmarkSmokeTest.system_health.memory_mobile.load:social:pinterest', # pylint: disable=line-too-long
 })
 
 
diff --git a/tools/perf/page_sets/data/mobile_infinite_scroll.json b/tools/perf/page_sets/data/mobile_infinite_scroll.json
index ecfb92d..a8bd5f7 100644
--- a/tools/perf/page_sets/data/mobile_infinite_scroll.json
+++ b/tools/perf/page_sets/data/mobile_infinite_scroll.json
@@ -21,4 +21,4 @@
     },
     "description": "Describes the Web Page Replay archives for a story set. Don't edit by hand! Use record_wpr for updating.",
     "platform_specific": true
-}
\ No newline at end of file
+}
diff --git a/tools/perf/page_sets/data/system_health_desktop.json b/tools/perf/page_sets/data/system_health_desktop.json
index 58d9359..801b9cc8 100644
--- a/tools/perf/page_sets/data/system_health_desktop.json
+++ b/tools/perf/page_sets/data/system_health_desktop.json
@@ -45,6 +45,21 @@
         "browse:tools:maps": {
             "DEFAULT": "system_health_desktop_052.wpr"
         },
+        "browse:tech:discourse_infinite_scroll": {
+            "DEFAULT": "infinite_scroll_004.wpr"
+        },
+        "browse:social:facebook_infinite_scroll": {
+            "DEFAULT": "infinite_scroll_001.wpr"
+        },
+        "browse:media:flickr_infinite_scroll": {
+            "DEFAULT": "infinite_scroll_003.wpr"
+        },
+        "browse:social:tumblr_infinite_scroll": {
+            "DEFAULT": "infinite_scroll_002.wpr"
+        },
+        "browse:social:twitter_infinite_scroll": {
+            "DEFAULT": "infinite_scroll_000.wpr"
+        },
         "load:games:alphabetty": {
             "DEFAULT": "system_health_desktop_005.wpr"
         },
@@ -195,4 +210,4 @@
     },
     "description": "Describes the Web Page Replay archives for a story set. Don't edit by hand! Use record_wpr for updating.",
     "platform_specific": true
-}
\ No newline at end of file
+}
diff --git a/tools/perf/page_sets/data/system_health_mobile.json b/tools/perf/page_sets/data/system_health_mobile.json
index 42ece62..172e415 100644
--- a/tools/perf/page_sets/data/system_health_mobile.json
+++ b/tools/perf/page_sets/data/system_health_mobile.json
@@ -84,6 +84,21 @@
         "browse:tools:maps": {
             "DEFAULT": "system_health_mobile_059.wpr"
         },
+        "browse:tech:discourse_infinite_scroll": {
+            "DEFAULT": "mobile_infinite_scroll_000.wpr"
+        },
+        "browse:social:facebook_infinite_scroll": {
+            "DEFAULT": "mobile_infinite_scroll_000.wpr"
+        },
+        "browse:media:flickr_infinite_scroll": {
+            "DEFAULT": "mobile_infinite_scroll_000.wpr"
+        },
+        "browse:social:pinterest_infinite_scroll": {
+            "DEFAULT": "mobile_infinite_scroll_001.wpr"
+        },
+        "browse:social:tumblr_infinite_scroll": {
+            "DEFAULT": "mobile_infinite_scroll_000.wpr"
+        },
         "load:games:bubbles": {
             "DEFAULT": "system_health_mobile_005.wpr"
         },
@@ -219,4 +234,4 @@
     },
     "description": "Describes the Web Page Replay archives for a story set. Don't edit by hand! Use record_wpr for updating.",
     "platform_specific": true
-}
\ No newline at end of file
+}
diff --git a/tools/perf/page_sets/loading_mobile.py b/tools/perf/page_sets/loading_mobile.py
index d3030b8a..fc970a91 100644
--- a/tools/perf/page_sets/loading_mobile.py
+++ b/tools/perf/page_sets/loading_mobile.py
@@ -19,7 +19,8 @@
   def __init__(self, cache_temperatures=None, traffic_settings=None):
     super(LoadingMobileStorySet, self).__init__(
         archive_data_file='data/loading_mobile.json',
-        cloud_storage_bucket=story.PARTNER_BUCKET)
+        cloud_storage_bucket=story.PARTNER_BUCKET,
+        verify_names=True)
 
     if cache_temperatures is None:
       cache_temperatures = [cache_temperature_module.ANY]
@@ -28,105 +29,127 @@
       traffic_settings = [traffic_setting_module.NONE]
 
     self.AddStories(['global'], [
-      'https://www.google.com/search?q=flower#q=flower+delivery',
-      'https://www.youtube.com/watch?v=MU3YuvNRhVY',
+      ('https://www.google.com/search?q=flower#q=flower+delivery',
+       'GoogleRedirectToGoogleJapan'),
+      ('https://www.youtube.com/watch?v=MU3YuvNRhVY', 'Youtube'),
       # pylint: disable=line-too-long
-      'https://www.google.co.in/search?q=%E0%A4%AB%E0%A5%82%E0%A4%B2&rct=j#q=%E0%A4%AB%E0%A5%82%E0%A4%B2+%E0%A4%B5%E0%A4%BF%E0%A4%A4%E0%A4%B0%E0%A4%A3',
-      'https://www.google.com.br/search?q=flor#q=Entrega+de+flores&start=10',
+      ('https://www.google.co.in/search?q=%E0%A4%AB%E0%A5%82%E0%A4%B2&rct=j#q=%E0%A4%AB%E0%A5%82%E0%A4%B2+%E0%A4%B5%E0%A4%BF%E0%A4%A4%E0%A4%B0%E0%A4%A3',
+       'GoogleIndia'),
+      ('https://www.google.com.br/search?q=flor#q=Entrega+de+flores&start=10',
+       'GoogleBrazil'),
       # Disabled because of crbug.com/653775
       # pylint: disable=line-too-long
-      # 'https://googleblog.blogspot.jp/2016/02/building-safer-web-for-everyone.html',
-      'https://www.google.co.id/#q=pengiriman+bunga',
-      'https://m.facebook.com/?soft=messages',
+      # ('https://googleblog.blogspot.jp/2016/02/building-safer-web-for-everyone.html',
+      #  'Blogspot'),
+      ('https://www.google.co.id/#q=pengiriman+bunga', 'GoogleIndonesia'),
+      ('https://m.facebook.com/?soft=messages', 'Facebook'),
       # Disabled because of crbug.com/656861
       # pylint: disable=line-too-long
-      # 'http://g1.globo.com/politica/noticia/2016/02/maioria-do-stf-autoriza-fisco-obter-dados-bancarios-sem-decisao-judicial.html',
+      # ('http://g1.globo.com/politica/noticia/2016/02/maioria-do-stf-autoriza-fisco-obter-dados-bancarios-sem-decisao-judicial.html',
+      #  'G1'),
       # pylint: disable=line-too-long
-      'https://m.baidu.com/s?word=%E9%B2%9C%E8%8A%B1%E9%80%9F%E9%80%92&oq=%E9%B2%9C%E8%8A%B1',
+      ('https://m.baidu.com/s?word=%E9%B2%9C%E8%8A%B1%E9%80%9F%E9%80%92&oq=%E9%B2%9C%E8%8A%B1',
+       'Baidu'),
       # pylint: disable=line-too-long
-      'http://news.yahoo.com/were-top-10-most-visited-us-national-parks-105323727.html',
-      'https://en.m.wikipedia.org/wiki/Solo_Foods',
+      ('http://news.yahoo.com/were-top-10-most-visited-us-national-parks-105323727.html',
+       'YahooNews'),
+      ('https://en.m.wikipedia.org/wiki/Solo_Foods', 'Wikipedia'),
       # pylint: disable=line-too-long
-      'http://noticias.bol.uol.com.br/ultimas-noticias/brasil/2016/08/03/tufao-nida-nao-deixa-vitimas-mas-prejuizos-de-us-43-milhoes.htm',
+      ('http://noticias.bol.uol.com.br/ultimas-noticias/brasil/2016/08/03/tufao-nida-nao-deixa-vitimas-mas-prejuizos-de-us-43-milhoes.htm',
+       'BOLNoticias'),
       # Disabled because of crbug.com/653775
       # pylint: disable=line-too-long
-      # 'http://m.detik.com/finance/read/2016/02/19/151843/3146351/1034/ekspor-tambang-mentah-mau-dibuka-lagi-kalau-sudah-bangun-smelter-bagaimana',
-      'http://www.amazon.com/gp/aw/s/ref=is_s/189-8585431-1246432?k=shoes',
+      # ('http://m.detik.com/finance/read/2016/02/19/151843/3146351/1034/ekspor-tambang-mentah-mau-dibuka-lagi-kalau-sudah-bangun-smelter-bagaimana',
+      #  'Detik'),
+      ('http://www.amazon.com/gp/aw/s/ref=is_s/189-8585431-1246432?k=shoes',
+       'Amazon'),
       # pylint: disable=line-too-long
-      'http://m.tribunnews.com/superskor/2016/08/03/ribuan-polisi-dikerahkan-mengawal-bonek',
-      'http://xw.qq.com/news/20160803025029/NEW2016080302502901',
+      ('http://m.tribunnews.com/superskor/2016/08/03/ribuan-polisi-dikerahkan-mengawal-bonek',
+       'TribunNews'),
+      ('http://xw.qq.com/news/20160803025029/NEW2016080302502901', 'QQNews'),
       # pylint: disable=line-too-long
-      'http://m.kaskus.co.id/thread/57a03a3214088d91068b4567/inilah-akibat-bersikap-overprotektif-terhadap-anak/?ref=homelanding&med=hot_thread',
-      'http://www.dailymotion.com/video/x3d1kj5_fallout-4-review_videogames',
-      'https://mobile.twitter.com/scottjehl/status/760618697727803394',
-      'http://m.kapanlagi.com/lirik/artis/anji/kata_siapa/',
+      ('http://m.kaskus.co.id/thread/57a03a3214088d91068b4567/inilah-akibat-bersikap-overprotektif-terhadap-anak/?ref=homelanding&med=hot_thread',
+       'Kaskus'),
+      ('http://www.dailymotion.com/video/x3d1kj5_fallout-4-review_videogames',
+       'Dailymotion'),
+      ('https://mobile.twitter.com/scottjehl/status/760618697727803394',
+       'Twitter'),
+      ('http://m.kapanlagi.com/lirik/artis/anji/kata_siapa/',
+       'KapanLagi'),
       # pylint: disable=line-too-long
-      'http://olx.co.id/iklan/iphone-6s-64-rose-gold-warna-favorite-IDiSdm5.html#5310a118c3;promoted',
+      ('http://olx.co.id/iklan/iphone-6s-64-rose-gold-warna-favorite-IDiSdm5.html#5310a118c3;promoted',
+       'OLX'),
       # pylint: disable=line-too-long
-      'http://enquiry.indianrail.gov.in/mntes/MntesServlet?action=MainMenu&subAction=excep&excpType=EC',
+      ('http://enquiry.indianrail.gov.in/mntes/MntesServlet?action=MainMenu&subAction=excep&excpType=EC',
+       'EnquiryIndianRail'),
     ], cache_temperatures, traffic_settings)
 
     self.AddStories(['pwa'], [
       # pylint: disable=line-too-long
-      'https://www.flipkart.com/big-wing-casuals/p/itmemeageyfn6m9z?lid=LSTSHOEMEAGURG2PHPW18FTBN&pid=SHOEMEAGURG2PHPW',
-      'https://smp.suumo.jp/mansion/tokyo/sc_104/cond/?moreCond=1',
+      ('https://www.flipkart.com/big-wing-casuals/p/itmemeageyfn6m9z?lid=LSTSHOEMEAGURG2PHPW18FTBN&pid=SHOEMEAGURG2PHPW',
+       'FlipKart'),
+      ('https://smp.suumo.jp/mansion/tokyo/sc_104/cond/?moreCond=1',
+       'Suumo'),
       # Disabled because of crbug.com/653775
-      # 'https://airhorner.com',
-      'https://guitar-tuner.appspot.com',
+      # 'https://airhorner.com', 'AirHorner'),
+      ('https://guitar-tuner.appspot.com', 'GuitarTuner'),
       # Disabled because of crbug.com/653775
-      # 'https://busrouter.sg',
-      'https://andreasbovens.github.io/inbox-attack/',
-      'https://voice-memos.appspot.com',
+      # ('https://busrouter.sg', 'BusRouter'),
+      ('https://andreasbovens.github.io/inbox-attack/',
+       'InboxAttack'),
+      ('https://voice-memos.appspot.com', 'VoiceMemos'),
       # Disabled because of crbug.com/653775
-      # 'https://wiki-offline.jakearchibald.com/',
-      'https://dev.opera.com/',
-      'https://www.pokedex.org/',
-      'https://2048-opera-pwa.surge.sh/',
-      'https://jakearchibald.github.io/trained-to-thrill/',
-      'https://townwork.net',
-      'https://flipboard.com/topic/yoga',
+      # ('https://wiki-offline.jakearchibald.com/',
+      #  'WikiOffline'),
+      ('https://dev.opera.com/', 'DevOpera'),
+      ('https://www.pokedex.org/', 'Pokedex'),
+      ('https://2048-opera-pwa.surge.sh/', '2048'),
+      ('https://jakearchibald.github.io/trained-to-thrill/',
+       'TrainedToThrill'),
+      ('https://townwork.net', 'TownWork'),
+      ('https://flipboard.com/topic/yoga', 'FlipBoard'),
     ], cache_temperatures, traffic_settings)
 
     self.AddStories(['tough_ttfmp'], [
-      'http://www.localmoxie.com',
-      'http://www.dawn.com',
-      'http://www.thairath.co.th',
+      ('http://www.localmoxie.com', 'LocalMoxie'),
+      ('http://www.dawn.com', 'Dawn'),
+      ('http://www.thairath.co.th', 'Thairath'),
       # Disabled to avoid Nexus5X bot timeout crbug.com/702175
-      # 'http://www.hashocean.com',
-      # 'http://www.163.com',
+      # ('http://www.hashocean.com', 'HashOcean'),
+      # ('http://www.163.com', '163'),
     ], cache_temperatures, traffic_settings)
 
     self.AddStories(['easy_ttfmp'], [
-      'http://www.slideshare.net',
-      'http://www.bradesco.com.br',
-      'http://www.gsshop.com',
+      ('http://www.slideshare.net', 'SlideShare'),
+      ('http://www.bradesco.com.br', 'Bradesco'),
+      ('http://www.gsshop.com', 'GSShop'),
       # Disabled to avoid Nexus5X bot timeout crbug.com/702175
-      # 'http://www.sbs.co.kr',
-      # 'http://www.futura-sciences.com',
+      # ('http://www.sbs.co.kr', 'SBS'),
+      # ('http://www.futura-sciences.com', 'FuturaSciences'),
     ], cache_temperatures, traffic_settings)
 
     self.AddStories(['tough_tti'], [
-      'http://www.thestar.com.my',
-      'http://www.58pic.com',
-      'http://www.hongkiat.com',
+      ('http://www.thestar.com.my', 'TheStar'),
+      ('http://www.58pic.com', '58Pic'),
+      ('http://www.hongkiat.com', 'Hongkiat'),
       # Disabled to avoid Nexus5X bot timeout crbug.com/702175
-      # 'http://www.ebs.in',
-      # 'http://www.ibicn.com',
+      # ('http://www.ebs.in', 'EBS'),
+      # ('http://www.ibicn.com', 'IBI'),
     ], cache_temperatures, traffic_settings)
 
     self.AddStories(['easy_tti'], [
-      'http://www.dramaq.com.tw',
-      'http://www.locanto.in',
-      'http://www.francetvinfo.fr',
+      ('http://www.dramaq.com.tw', 'Dramaq'),
+      ('http://www.locanto.in', 'Locanto'),
+      ('http://www.francetvinfo.fr', 'FranceTVInfo'),
       # Disabled to avoid Nexus5X bot timeout crbug.com/702175
-      # 'http://www.gfk.com',
-      # 'http://www.mlsmatrix.com'
+      # ('http://www.gfk.com', 'GFK'),
+      # ('http://www.mlsmatrix.com' 'MLSMatrix'),
     ], cache_temperatures, traffic_settings)
 
   def AddStories(self, tags, urls, cache_temperatures, traffic_settings):
-    for url in urls:
+    for url, name in urls:
       for temp in cache_temperatures:
         for traffic in traffic_settings:
-          self.AddStory(page_cycler_story.PageCyclerStory(url, self,
+          self.AddStory(page_cycler_story.PageCyclerStory(url, self, name=name,
               shared_page_state_class=shared_page_state.SharedMobilePageState,
               cache_temperature=temp, traffic_setting=traffic, tags=tags))
diff --git a/tools/perf/page_sets/system_health/browsing_stories.py b/tools/perf/page_sets/system_health/browsing_stories.py
index 79fe111f..a5a25cc 100644
--- a/tools/perf/page_sets/system_health/browsing_stories.py
+++ b/tools/perf/page_sets/system_health/browsing_stories.py
@@ -7,6 +7,7 @@
 from page_sets.system_health import story_tags
 from page_sets.system_health import system_health_story
 
+from page_sets.login_helpers import facebook_login
 from page_sets.login_helpers import pinterest_login
 
 from telemetry import decorators
@@ -784,3 +785,134 @@
     action_runner.RepeatableBrowserDrivenScroll(
         x_scroll_distance_ratio = 1, y_scroll_distance_ratio = 0,
         repeat_count=3, speed=500, timeout=120)
+
+
+##############################################################################
+# Browsing stories with infinite scrolling
+##############################################################################
+
+
+class _InfiniteScrollStory(system_health_story.SystemHealthStory):
+  SUPPORTED_PLATFORMS = platforms.ALL_PLATFORMS
+
+  SCROLL_DISTANCE = 25000
+  SCROLL_STEP = 1000
+  MAX_SCROLL_RETRIES = 3
+  TIME_BEFORE_SCROLL_RETRY_IN_SECONDS = 1
+  TIME_TO_WAIT_BEFORE_STARTING_IN_SECONDS = 5
+
+  def __init__(self, story_set, take_memory_measurement):
+    super(_InfiniteScrollStory, self).__init__(story_set,
+        take_memory_measurement)
+    self.script_to_evaluate_on_commit = '''
+        window.WebSocket = undefined;
+        window.Worker = undefined;
+        window.performance = undefined;'''
+
+  def _DidLoadDocument(self, action_runner):
+    action_runner.WaitForJavaScriptCondition(
+      'document.body != null && '
+      'document.body.scrollHeight > window.innerHeight && '
+      '!document.body.addEventListener("touchstart", function() {})')
+    action_runner.Wait(self.TIME_TO_WAIT_BEFORE_STARTING_IN_SECONDS)
+    self._Scroll(action_runner, self.SCROLL_DISTANCE, self.SCROLL_STEP)
+
+
+  def _Scroll(self, action_runner, distance, step_size):
+    """ This function scrolls the webpage by the given scroll distance in
+    multiple steps, where each step (except the last one) has the given size.
+
+    If scrolling gets stuck, the functions retries scrolling MAX_SCROLL_RETRIES
+    times waiting TIME_BEFORE_SCROLL_RETRY_IN_SECONDS seconds between retries.
+    """
+    remaining = distance - action_runner.EvaluateJavaScript('window.scrollY')
+    retry_count = 0
+    # Scroll until the window.scrollY is within 1 pixel of the target distance.
+    while remaining > 1:
+      action_runner.ScrollPage(distance=min(remaining, step_size) + 1)
+      new_remaining = (distance -
+          action_runner.EvaluateJavaScript('window.scrollY'))
+      if remaining <= new_remaining:
+        # Scrolling is stuck. This can happen if the page is loading
+        # resources. Give the page some time and retry scrolling.
+        if retry_count == self.MAX_SCROLL_RETRIES:
+          raise Exception('Scrolling stuck at %d' % remaining)
+        retry_count += 1
+        action_runner.Wait(self.TIME_BEFORE_SCROLL_RETRY_IN_SECONDS)
+      else:
+        retry_count = 0
+        remaining = new_remaining
+
+  @classmethod
+  def GenerateStoryDescription(cls):
+    return 'Load %s then make a very long scroll.' % cls.URL
+
+
+@decorators.Disabled('win')  # crbug.com/728152
+class DiscourseDesktopStory(_InfiniteScrollStory):
+  NAME = 'browse:tech:discourse_infinite_scroll'
+  URL = ('https://meta.discourse.org/t/the-official-discourse-tags-plugin-discourse-tagging/26482')
+  SUPPORTED_PLATFORMS = platforms.DESKTOP_ONLY
+  TAGS = [story_tags.INFINITE_SCROLL]
+
+
+class DiscourseMobileStory(_InfiniteScrollStory):
+  NAME = 'browse:tech:discourse_infinite_scroll'
+  URL = ('https://meta.discourse.org/t/the-official-discourse-tags-plugin-discourse-tagging/26482')
+  SUPPORTED_PLATFORMS = platforms.MOBILE_ONLY
+  SCROLL_DISTANCE = 15000
+  TAGS = [story_tags.INFINITE_SCROLL]
+
+
+@decorators.Disabled('win')  # crbug.com/728152
+class FacebookScrollDesktopStory(_InfiniteScrollStory):
+  NAME = 'browse:social:facebook_infinite_scroll'
+  URL = 'https://www.facebook.com/shakira'
+  SUPPORTED_PLATFORMS = platforms.DESKTOP_ONLY
+  TAGS = [story_tags.INFINITE_SCROLL]
+
+
+@decorators.Disabled('all')  # crbug.com/727835
+class FacebookScrollMobileStory(_InfiniteScrollStory):
+  NAME = 'browse:social:facebook_infinite_scroll'
+  URL = 'https://m.facebook.com/shakira'
+  SUPPORTED_PLATFORMS = platforms.MOBILE_ONLY
+
+  def _Login(self, action_runner):
+    facebook_login.LoginWithMobileSite(
+        action_runner, 'facebook3', self.credentials_path)
+
+
+class FlickrDesktopStory(_InfiniteScrollStory):
+  NAME = 'browse:media:flickr_infinite_scroll'
+  URL = 'https://www.flickr.com/explore'
+  SUPPORTED_PLATFORMS = platforms.DESKTOP_ONLY
+  TAGS = [story_tags.INFINITE_SCROLL]
+
+
+class FlickrMobileStory(_InfiniteScrollStory):
+  NAME = 'browse:media:flickr_infinite_scroll'
+  URL = 'https://www.flickr.com/explore'
+  SUPPORTED_PLATFORMS = platforms.MOBILE_ONLY
+  SCROLL_DISTANCE = 10000
+  TAGS = [story_tags.INFINITE_SCROLL]
+
+
+class PinterestMobileStory(_InfiniteScrollStory):
+  NAME = 'browse:social:pinterest_infinite_scroll'
+  URL = 'https://www.pinterest.com/all'
+  SUPPORTED_PLATFORMS = platforms.MOBILE_ONLY
+  TAGS = [story_tags.INFINITE_SCROLL]
+
+
+class TumblrStory(_InfiniteScrollStory):
+  NAME = 'browse:social:tumblr_infinite_scroll'
+  URL = 'http://techcrunch.tumblr.com/'  # This page doesn't support HTTPS.
+  TAGS = [story_tags.INFINITE_SCROLL]
+
+
+class TwitterScrollDesktopStory(_InfiniteScrollStory):
+  NAME = 'browse:social:twitter_infinite_scroll'
+  URL = 'https://twitter.com/taylorswift13'
+  SUPPORTED_PLATFORMS = platforms.DESKTOP_ONLY
+  TAGS = [story_tags.INFINITE_SCROLL]
diff --git a/tools/perf/page_sets/system_health/story_tags.py b/tools/perf/page_sets/system_health/story_tags.py
index 4458165..e296808cd 100644
--- a/tools/perf/page_sets/system_health/story_tags.py
+++ b/tools/perf/page_sets/system_health/story_tags.py
@@ -22,6 +22,7 @@
     'extension', 'Story has browser with extension installed.')
 IMAGES = Tag(
     'images', 'Story has sites with heavy uses of images.')
+INFINITE_SCROLL = Tag('infinite_scroll', 'Story has infinite scroll action.')
 INTERNATIONAL = Tag(
     'international', 'Story has navigations to websites with content in non '
     'English languages.')
diff --git a/tools/traffic_annotation/auditor/traffic_annotation_auditor.py b/tools/traffic_annotation/auditor/traffic_annotation_auditor.py
index 631b6dc3..54a83c3 100755
--- a/tools/traffic_annotation/auditor/traffic_annotation_auditor.py
+++ b/tools/traffic_annotation/auditor/traffic_annotation_auditor.py
@@ -1,5 +1,5 @@
 #!/usr/bin/env python
-# Copyright (c) 2017 The Chromium Authors. All rights reserved.
+# 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.
 
@@ -7,9 +7,14 @@
 Please refer to README.md for running steps."""
 
 import argparse
+import datetime
 import os
 import subprocess
 import sys
+import tempfile
+
+from traffic_annotation_file_filter import TrafficAnnotationFileFilter
+
 
 # These two lines are required to import protobuf from third_party directory
 # instead of the one installed with python.
@@ -40,35 +45,40 @@
   return _RecursiveHash(unique_id) if len(unique_id) else -1
 
 
-def _RunClangTool(src_dir, build_dir, path_filters):
+def _RunClangTool(src_dir, build_dir, path_filters, prefilter_files):
   """Executes the clang tool to extract annotations.
   Args:
     src_dir: str Path to the src directory of Chrome.
     build_dir: str Path to the build directory.
     path_filters: list of str List of paths to source directories for
         extraction.
+    prefilter_files: bool Flag stating if source files should be first filtered
+        using annotation related keywords and then given to clang tool.
 
   Returns:
-    raw_annotations: str Output of clang tool (extracted content and metadata of
-        annotations).
+    str Output of clang tool (extracted content and metadata of annotations).
   """
-  raw_annotations = ""
-  for path in path_filters:
-    args = [
+  args = [
         src_dir + "/tools/clang/scripts/run_tool.py",
         "--generate-compdb",
         "--tool=traffic_annotation_extractor",
-        "-p", build_dir,
-        path]
-    if sys.platform == "win32":
+        "-p=" + build_dir]
+  if sys.platform == "win32":
       args.insert(0, "python")
-    command = subprocess.Popen(args, stdout=subprocess.PIPE,
-                               stderr=subprocess.PIPE)
-    stdout_text, stderr_text = command.communicate()
-    raw_annotations += stdout_text
-    if stderr_text:
-      print stderr_text
-  return raw_annotations
+
+  if prefilter_files:
+    file_filter = TrafficAnnotationFileFilter(False)
+    for path in path_filters:
+      args += file_filter.GetFilteredFilesList(path)
+  else:
+    args += path_filters
+
+  command = subprocess.Popen(args, stdout=subprocess.PIPE,
+                              stderr=subprocess.PIPE)
+  stdout_text, stderr_text = command.communicate()
+  if stderr_text:
+    print stderr_text
+  return stdout_text
 
 
 def _ParsRawAnnotations(raw_annotations):
@@ -123,9 +133,9 @@
         source.line = int(lines[current + 3])
         unique_id = lines[current + 5]
 
-        new_metadata = {'function_type': lines[current + 4],
-                        'extra_id': lines[current + 6],
-                        'unique_id_hash': _ComputeStringHash(unique_id)}
+        new_metadata = {"function_type": lines[current + 4],
+                        "extra_id": lines[current + 6],
+                        "unique_id_hash": _ComputeStringHash(unique_id)}
         # Extract serialized proto.
         current += 7
         annotation_text = ""
@@ -195,7 +205,7 @@
     errors: list of str List of all extraction errors.
     file_path: str File path to the brief summary file.
   """
-  with open(file_path, 'w') as summary_file:
+  with open(file_path, "w") as summary_file:
     if errors:
       summary_file.write("Errors:\n%s\n\n" % "\n".join(errors))
     if len(annotations.network_traffic_annotation):
@@ -215,37 +225,40 @@
       of _ParsRawAnnotations function.
     file_path: str File path to the brief summary file.
   """
-  with open(file_path, 'w') as summary_file:
-    for annotation, meta in zip(annotations.network_traffic_annotation,
-                                metadata):
-      summary_file.write(
-          "%s,%s\n" % (annotation.unique_id, meta['unique_id_hash']))
-    for keyword in ("test", "test_partial", "undefined", "missing"):
-      summary_file.write(
-          "%s,%s\n" % (keyword, _ComputeStringHash(keyword)))
+  hash_list = []
+  for annotation, meta in zip(annotations.network_traffic_annotation, metadata):
+    hash_list += ["%s,%s" % (annotation.unique_id, meta["unique_id_hash"])]
+  for keyword in ("test", "test_partial", "undefined", "missing"):
+    hash_list += ["%s,%s" % (keyword, _ComputeStringHash(keyword))]
+  open(file_path, "w").write("\n".join(sorted(hash_list)))
 
 
 def main():
-  parser = argparse.ArgumentParser(description='Traffic Annotation Auditor.')
-  parser.add_argument('--build-dir',
-                      help='Path to the build directory.')
-  parser.add_argument('--extractor-output',
-                      help='Optional path to the temporary file that extracted '
-                           'annotations will be stored into.')
-  parser.add_argument('--extractor-input',
-                      help='Optional path to the file that temporary extracted '
-                           'annotations are already stored in. If this is '
-                           'provided, clang tool is not run and this is used '
-                           'as input.')
-  parser.add_argument('--summary-file',
-                      help='Path to the output file with all annotations.')
-  parser.add_argument('--hash-codes-file',
-                      help='Path to the output file with the list of unique '
-                           'ids and their hash codes.')
-  parser.add_argument('path_filters',
-                      nargs='*',
-                      help='Optional paths to filter what files the tool is '
-                           'run on.')
+  parser = argparse.ArgumentParser(description="Traffic Annotation Auditor.")
+  parser.add_argument("--build-dir",
+                      help="Path to the build directory.")
+  parser.add_argument("--extractor-output",
+                      help="Optional path to the temporary file that extracted "
+                           "annotations will be stored into.")
+  parser.add_argument("--extractor-input",
+                      help="Optional path to the file that temporary extracted "
+                           "annotations are already stored in. If this is "
+                           "provided, clang tool is not run and this is used "
+                           "as input.")
+  parser.add_argument("--summary-file",
+                      help="Path to the output file with all annotations.")
+  parser.add_argument("--hash-codes-file",
+                      help="Path to the output file with the list of unique "
+                           "ids and their hash codes.")
+  parser.add_argument("path_filters",
+                      nargs="*",
+                      help="Optional paths to filter what files the tool is "
+                           "run on.",
+                      default=[""])
+  parser.add_argument("--prefilter-files", action="store_true",
+                      help="Checks source files for patterns of annotations "
+                           "and network functions that may require annotation "
+                           "and limits running clang tool only on them.")
   args = parser.parse_args()
 
   if not args.summary_file and not args.hash_codes_file:
@@ -253,7 +266,7 @@
 
   # If a pre-extracted input file is provided, load it.
   if args.extractor_input:
-    with open(args.extractor_input, 'r') as raw_file:
+    with open(args.extractor_input, "r") as raw_file:
       raw_annotations = raw_file.read()
   else:
     # Either extacted input file or build directory should be provided.
@@ -267,10 +280,10 @@
     chrome_source = os.path.abspath(os.path.join(os.path.dirname(
         os.path.realpath(__file__)), "..", "..", ".."))
     raw_annotations = _RunClangTool(chrome_source, args.build_dir,
-        args.path_filters if args.path_filters else ["./"])
+        args.path_filters, args.prefilter_files)
 
   if args.extractor_output:
-    with open(args.extractor_output, 'w') as raw_file:
+    with open(args.extractor_output, "w") as raw_file:
       raw_file.write(raw_annotations)
 
   annotations, metadata, errors = _ParsRawAnnotations(raw_annotations)
@@ -290,5 +303,5 @@
   return 0
 
 
-if __name__ == '__main__':
+if __name__ == "__main__":
   sys.exit(main())
diff --git a/tools/traffic_annotation/auditor/traffic_annotation_file_filter.py b/tools/traffic_annotation/auditor/traffic_annotation_file_filter.py
new file mode 100755
index 0000000..f00daf1
--- /dev/null
+++ b/tools/traffic_annotation/auditor/traffic_annotation_file_filter.py
@@ -0,0 +1,84 @@
+#!/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 os.path
+import re
+import subprocess
+import sys
+
+
+def _GetFilesFromGit():
+  """Gets the list of files in the git repository."""
+  args = []
+  if sys.platform == 'win32':
+    args.append('git.bat')
+  else:
+    args.append('git')
+  args.append('ls-files')
+  command = subprocess.Popen(args, stdout=subprocess.PIPE)
+  output, _ = command.communicate()
+  return [os.path.realpath(p) for p in output.splitlines()]
+
+
+class TrafficAnnotationFileFilter():
+  KEYWORDS = [
+    'network_traffic_annotation',
+    'network_traffic_annotation_test_helper',
+    'NetworkTrafficAnnotationTag',
+    'PartialNetworkTrafficAnnotationTag',
+    'DefineNetworkTrafficAnnotation',
+    'DefinePartialNetworkTrafficAnnotation',
+    'CompleteNetworkTrafficAnnotation',
+    'BranchedCompleteNetworkTrafficAnnotation',
+    'NO_TRAFFIC_ANNOTATION_YET',
+    'NO_PARTIAL_TRAFFIC_ANNOTATION_YET',
+    'MISSING_TRAFFIC_ANNOTATION',
+    'TRAFFIC_ANNOTATION_FOR_TESTS',
+    'PARTIAL_TRAFFIC_ANNOTATION_FOR_TESTS',
+    'SSLClientSocket',  # SSLClientSocket::
+    'TCPClientSocket',  # TCPClientSocket::
+    'UDPClientSocket',  # UDPClientSocket::
+    'URLFetcher::Create',  # This one is used with class as it's too generic.
+    'CreateDatagramClientSocket',  # ClientSocketFactory::
+    'CreateSSLClientSocket',  # ClientSocketFactory::
+    'CreateTransportClientSocket',  # ClientSocketFactory::
+    'CreateRequest',  # URLRequestContext::
+  ]
+
+  def __init__(self,
+               skip_tests=True):
+    """Creates a new TrafficAnnotationFileFilter.
+
+    Args:
+      skip_tests: bool Flag stating if test files should be returned or not.
+    """
+    assert(all(re.match('^[A-Za-z:_]+$', keyword) for keyword in self.KEYWORDS))
+    self.content_matcher = re.compile('.*(' + '|'.join(self.KEYWORDS) + ').*')
+    self.file_name_matcher = re.compile(
+        '^(?!.*?test)^.*(\.cc|\.mm)$' if skip_tests else
+        '^.*(\.cc|\.mm)$')
+    self.git_files = filter(lambda x: self.FileIsRelevantContent(x),
+                            _GetFilesFromGit())
+
+  def FileIsRelevantContent(self, filename):
+    if self.file_name_matcher.match(filename):
+      with open(filename, 'r') as in_file:
+        for line in in_file:
+          if self.content_matcher.match(line):
+            return True
+    return False
+
+
+  def GetFilteredFilesList(self, dir_name='/'):
+    """Returns the list of relevant files in given directory.
+    Args:
+      dir_name: str The directory to search for relevant files, e.g.
+         'chrome/browser'. All child directories would also be searched.
+
+    Returns:
+      list of str List of relevant files
+    """
+    matcher = re.compile(os.path.abspath(dir_name) + '/.*')
+    return filter(matcher.match, self.git_files)
diff --git a/tools/web_dev_style/js_checker.py b/tools/web_dev_style/js_checker.py
index 46cb6fc1..79e0895 100644
--- a/tools/web_dev_style/js_checker.py
+++ b/tools/web_dev_style/js_checker.py
@@ -52,12 +52,6 @@
     return self.RegexCheck(i, line, r"((?:Array|Object|Promise)\.<)",
         "Don't use a dot after generics (Object.<T> should be Object<T>).")
 
-  def GetElementByIdCheck(self, i, line):
-    """Checks for use of 'document.getElementById' instead of '$'."""
-    return self.RegexCheck(i, line, r"(document\.getElementById)\('",
-        "Use $('id') or getSVGElement('id') from chrome://resources/js/util.js "
-        "instead of document.getElementById('id')")
-
   def InheritDocCheck(self, i, line):
     """Checks for use of '@inheritDoc' instead of '@override'."""
     return self.RegexCheck(i, line, r"\* (@inheritDoc)",
@@ -68,7 +62,7 @@
     return self.RegexCheck(i, line, r"(?<!this)(\.\$)[\[\.]",
         "Please only use this.$.localId, not element.$.localId")
 
-  def RunEsLintChecks(self, affected_js_files):
+  def RunEsLintChecks(self, affected_js_files, format='stylish'):
     """Runs lint checks using ESLint. The ESLint rules being applied are defined
        in the .eslintrc.js configuration file.
     """
@@ -95,6 +89,7 @@
     output = node.RunNode([
         node_modules.PathToEsLint(),
         '--color',
+        '--format', format,
         '--ignore-pattern \'!.eslintrc.js\'',
         ' '.join(affected_js_files_paths)])
 
@@ -141,7 +136,6 @@
             self.ChromeSendCheck(i, line),
             self.CommentIfAndIncludeCheck(i, line),
             self.ConstCheck(i, line),
-            self.GetElementByIdCheck(i, line),
             self.EndJsDocCommentCheck(i, line),
             self.ExtraDotInGenericCheck(i, line),
             self.InheritDocCheck(i, line),
diff --git a/tools/web_dev_style/js_checker_eslint_test.py b/tools/web_dev_style/js_checker_eslint_test.py
new file mode 100755
index 0000000..1309c06
--- /dev/null
+++ b/tools/web_dev_style/js_checker_eslint_test.py
@@ -0,0 +1,49 @@
+#!/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 js_checker
+import json
+import os
+import sys
+import unittest
+import tempfile
+
+
+_HERE_PATH = os.path.dirname(__file__)
+sys.path.append(os.path.join(_HERE_PATH, '..', '..'))
+
+from PRESUBMIT_test_mocks import MockInputApi, MockOutputApi, MockFile
+
+
+class JsCheckerEsLintTest(unittest.TestCase):
+  def tearDown(self):
+    os.remove(self._tmp_file)
+
+  def testGetElementByIdCheck(self):
+    tmp_args = {'suffix': '.js', 'dir': _HERE_PATH, 'delete': False}
+    with tempfile.NamedTemporaryFile(**tmp_args) as f:
+      self._tmp_file = f.name
+      f.write('var a = document.getElementById(\'foo\');')
+
+    input_api = MockInputApi()
+    input_api.files = [MockFile(os.path.abspath(self._tmp_file), '')]
+    input_api.presubmit_local_path = _HERE_PATH
+
+    checker = js_checker.JSChecker(input_api, MockOutputApi())
+    results_json = checker.RunEsLintChecks(
+        input_api.AffectedFiles(), format='json')
+    self.assertEqual(1, len(results_json))
+
+    results = json.loads(results_json[0].message)
+    self.assertEqual(1, len(results))
+
+    self.assertEqual(1, len(results[0].get('messages')))
+    message = results[0].get('messages')[0]
+    self.assertEqual('no-restricted-properties', message.get('ruleId'))
+    self.assertEqual(1, message.get('line'))
+
+
+if __name__ == '__main__':
+  unittest.main()
diff --git a/tools/web_dev_style/js_checker_test.py b/tools/web_dev_style/js_checker_test.py
index 72f9954..428c7824 100755
--- a/tools/web_dev_style/js_checker_test.py
+++ b/tools/web_dev_style/js_checker_test.py
@@ -203,49 +203,6 @@
     for line in lines:
       self.ShouldFailExtraDotInGenericCheck(line)
 
-  def ShouldFailGetElementByIdCheck(self, line):
-    """Checks that the 'getElementById' checker flags |line| as a style
-       error.
-    """
-    error = self.checker.GetElementByIdCheck(1, line)
-    self.assertNotEqual('', error,
-        'Should be flagged as style error: ' + line)
-    self.assertEqual(test_util.GetHighlight(line, error),
-                     'document.getElementById')
-
-  def ShouldPassGetElementByIdCheck(self, line):
-    """Checks that the 'getElementById' checker doesn't flag |line| as a style
-       error.
-    """
-    self.assertEqual('', self.checker.GetElementByIdCheck(1, line),
-        'Should not be flagged as style error: ' + line)
-
-  def testGetElementByIdFails(self):
-    lines = [
-        "document.getElementById('foo');",
-        "  document.getElementById('foo');",
-        "var x = document.getElementById('foo');",
-        "if (document.getElementById('foo').hidden) {",
-    ]
-    for line in lines:
-      self.ShouldFailGetElementByIdCheck(line)
-
-  def testGetElementByIdPasses(self):
-    lines = [
-        "elem.ownerDocument.getElementById('foo');",
-        "  elem.ownerDocument.getElementById('foo');",
-        "var x = elem.ownerDocument.getElementById('foo');",
-        "if (elem.ownerDocument.getElementById('foo').hidden) {",
-        "doc.getElementById('foo');",
-        "  doc.getElementById('foo');",
-        "cr.doc.getElementById('foo');",
-        "  cr.doc.getElementById('foo');",
-        "var x = doc.getElementById('foo');",
-        "if (doc.getElementById('foo').hidden) {",
-    ]
-    for line in lines:
-      self.ShouldPassGetElementByIdCheck(line)
-
   def ShouldFailInheritDocCheck(self, line):
     """Checks that the '@inheritDoc' checker flags |line| as a style error."""
     error = self.checker.InheritDocCheck(1, line)
diff --git a/ui/app_list/BUILD.gn b/ui/app_list/BUILD.gn
index dd99897..ce45400 100644
--- a/ui/app_list/BUILD.gn
+++ b/ui/app_list/BUILD.gn
@@ -140,6 +140,8 @@
       "views/search_result_actions_view.cc",
       "views/search_result_actions_view.h",
       "views/search_result_actions_view_delegate.h",
+      "views/search_result_answer_card_view.cc",
+      "views/search_result_answer_card_view.h",
       "views/search_result_container_view.cc",
       "views/search_result_container_view.h",
       "views/search_result_list_view.cc",
diff --git a/ui/app_list/views/contents_view.cc b/ui/app_list/views/contents_view.cc
index aad1125..bb8218b 100644
--- a/ui/app_list/views/contents_view.cc
+++ b/ui/app_list/views/contents_view.cc
@@ -17,56 +17,23 @@
 #include "ui/app_list/views/apps_grid_view.h"
 #include "ui/app_list/views/custom_launcher_page_view.h"
 #include "ui/app_list/views/search_box_view.h"
+#include "ui/app_list/views/search_result_answer_card_view.h"
 #include "ui/app_list/views/search_result_list_view.h"
 #include "ui/app_list/views/search_result_page_view.h"
 #include "ui/app_list/views/search_result_tile_item_list_view.h"
 #include "ui/app_list/views/start_page_view.h"
 #include "ui/events/event.h"
-#include "ui/views/layout/box_layout.h"
 #include "ui/views/view_model.h"
 #include "ui/views/widget/widget.h"
 
 namespace app_list {
 
-namespace {
-
-// Container of the search answer view.
-class SearchAnswerContainerView : public views::View {
- public:
-  explicit SearchAnswerContainerView(views::View* search_results_page_view)
-      : search_results_page_view_(search_results_page_view) {
-    views::BoxLayout* answer_container_layout =
-        new views::BoxLayout(views::BoxLayout::kHorizontal, 0, 0, 0);
-    answer_container_layout->set_main_axis_alignment(
-        views::BoxLayout::MAIN_AXIS_ALIGNMENT_CENTER);
-    SetLayoutManager(answer_container_layout);
-  }
-
-  // views::View overrides:
-  void ChildPreferredSizeChanged(View* child) override {
-    if (visible())
-      search_results_page_view_->Layout();
-  }
-
-  const char* GetClassName() const override {
-    return "SearchAnswerContainerView";
-  }
-
- private:
-  views::View* const search_results_page_view_;
-
-  DISALLOW_COPY_AND_ASSIGN(SearchAnswerContainerView);
-};
-
-}  // namespace
-
 ContentsView::ContentsView(AppListMainView* app_list_main_view)
     : model_(nullptr),
       apps_container_view_(nullptr),
       search_results_page_view_(nullptr),
       start_page_view_(nullptr),
       custom_page_view_(nullptr),
-      search_answer_container_view_(nullptr),
       app_list_main_view_(app_list_main_view),
       page_before_search_(0) {
   pagination_model_.SetTransitionDurations(kPageTransitionDurationInMs,
@@ -76,8 +43,6 @@
 
 ContentsView::~ContentsView() {
   pagination_model_.RemoveObserver(this);
-  if (model_)
-    model_->RemoveObserver(this);
 }
 
 void ContentsView::Init(AppListModel* model) {
@@ -104,14 +69,14 @@
   // Search results UI.
   search_results_page_view_ = new SearchResultPageView();
 
-  // Search answer container UI.
-  search_answer_container_view_ =
-      new SearchAnswerContainerView(search_results_page_view_);
-  search_answer_container_view_->SetVisible(false);
-  views::View* search_answer_view = view_delegate->GetSearchAnswerWebView();
-  if (search_answer_view)
-    search_answer_container_view_->AddChildView(search_answer_view);
-  search_results_page_view_->AddChildView(search_answer_container_view_);
+  // Search result containers.
+  views::View* const search_answer_view =
+      view_delegate->GetSearchAnswerWebView();
+  if (search_answer_view) {
+    search_results_page_view_->AddSearchResultContainerView(
+        nullptr, new SearchResultAnswerCardView(
+                     model_, search_results_page_view_, search_answer_view));
+  }
 
   AppListModel::SearchResults* results = view_delegate->GetModel()->results();
   search_results_page_view_->AddSearchResultContainerView(
@@ -142,8 +107,6 @@
   pagination_model_.SelectPage(initial_page_index, false);
 
   ActivePageChanged();
-
-  model_->AddObserver(this);
 }
 
 void ContentsView::CancelDrag() {
@@ -524,12 +487,4 @@
   UpdatePageBounds();
 }
 
-void ContentsView::OnSearchAnswerAvailableChanged(bool has_answer) {
-  if (has_answer == search_answer_container_view_->visible())
-    return;
-
-  search_answer_container_view_->SetVisible(has_answer);
-  search_results_page_view_->Layout();
-}
-
 }  // namespace app_list
diff --git a/ui/app_list/views/contents_view.h b/ui/app_list/views/contents_view.h
index 435ff00..62a52cd2 100644
--- a/ui/app_list/views/contents_view.h
+++ b/ui/app_list/views/contents_view.h
@@ -13,7 +13,6 @@
 #include "base/macros.h"
 #include "ui/app_list/app_list_export.h"
 #include "ui/app_list/app_list_model.h"
-#include "ui/app_list/app_list_model_observer.h"
 #include "ui/app_list/pagination_model.h"
 #include "ui/app_list/pagination_model_observer.h"
 #include "ui/views/view.h"
@@ -43,8 +42,7 @@
 // interface for switching between launcher pages, and animates the transition
 // between them.
 class APP_LIST_EXPORT ContentsView : public views::View,
-                                     public PaginationModelObserver,
-                                     public AppListModelObserver {
+                                     public PaginationModelObserver {
  public:
   explicit ContentsView(AppListMainView* app_list_main_view);
   ~ContentsView() override;
@@ -136,9 +134,6 @@
   void TransitionStarted() override;
   void TransitionChanged() override;
 
-  // Overridden from AppListModelObserver:
-  void OnSearchAnswerAvailableChanged(bool has_answer) override;
-
  private:
   // Sets the active launcher page, accounting for whether the change is for
   // search results.
@@ -190,10 +185,6 @@
   StartPageView* start_page_view_;
   CustomLauncherPageView* custom_page_view_;
 
-  // Unowned pointer to the container of the search answer web view. This
-  // container view is a sub-view of search_results_page_view_.
-  View* search_answer_container_view_;
-
   // The child page views. Owned by the views hierarchy.
   std::vector<AppListPage*> app_list_pages_;
 
diff --git a/ui/app_list/views/search_result_answer_card_view.cc b/ui/app_list/views/search_result_answer_card_view.cc
new file mode 100644
index 0000000..5991853
--- /dev/null
+++ b/ui/app_list/views/search_result_answer_card_view.cc
@@ -0,0 +1,145 @@
+// 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/app_list/views/search_result_answer_card_view.h"
+
+#include "ui/app_list/app_list_constants.h"
+#include "ui/app_list/app_list_features.h"
+#include "ui/app_list/views/search_result_page_view.h"
+#include "ui/views/background.h"
+#include "ui/views/controls/button/custom_button.h"
+#include "ui/views/layout/box_layout.h"
+#include "ui/views/layout/fill_layout.h"
+
+namespace app_list {
+
+namespace {
+
+// Answer card relevance is high to always have it first.
+constexpr double kSearchAnswerCardRelevance = 100;
+
+}  // namespace
+
+// Container of the search answer view.
+class SearchResultAnswerCardView::SearchAnswerContainerView
+    : public views::CustomButton {
+ public:
+  explicit SearchAnswerContainerView(views::View* search_results_page_view)
+      : CustomButton(nullptr),
+        search_results_page_view_(search_results_page_view) {
+    // Center the card horizontally in the container.
+    views::BoxLayout* answer_container_layout =
+        new views::BoxLayout(views::BoxLayout::kHorizontal, 0, 0, 0);
+    answer_container_layout->set_main_axis_alignment(
+        views::BoxLayout::MAIN_AXIS_ALIGNMENT_CENTER);
+    SetLayoutManager(answer_container_layout);
+  }
+
+  void SetSelected(bool selected) {
+    if (selected == selected_)
+      return;
+    selected_ = selected;
+    UpdateBackgroundColor();
+  }
+
+  // views::CustomButton overrides:
+  void ChildPreferredSizeChanged(View* child) override {
+    // Card size changed.
+    if (visible())
+      search_results_page_view_->Layout();
+  }
+
+  int GetHeightForWidth(int w) const override {
+    return visible() ? CustomButton::GetHeightForWidth(w) : 0;
+  }
+
+  const char* GetClassName() const override {
+    return "SearchAnswerContainerView";
+  }
+
+  void StateChanged(ButtonState old_state) override { UpdateBackgroundColor(); }
+
+ private:
+  void UpdateBackgroundColor() {
+    views::Background* background = nullptr;
+
+    if (selected_) {
+      background = views::Background::CreateSolidBackground(kSelectedColor);
+    } else if (state() == STATE_HOVERED || state() == STATE_PRESSED) {
+      background = views::Background::CreateSolidBackground(kHighlightedColor);
+    }
+
+    set_background(background);
+    SchedulePaint();
+  }
+
+  views::View* const search_results_page_view_;
+  bool selected_ = false;
+
+  DISALLOW_COPY_AND_ASSIGN(SearchAnswerContainerView);
+};
+
+SearchResultAnswerCardView::SearchResultAnswerCardView(
+    AppListModel* model,
+    SearchResultPageView* search_results_page_view,
+    views::View* search_answer_view)
+    : model_(model),
+      search_answer_container_view_(
+          new SearchAnswerContainerView(search_results_page_view)) {
+  search_answer_container_view_->SetVisible(false);
+  search_answer_container_view_->AddChildView(search_answer_view);
+  AddChildView(search_answer_container_view_);
+  model->AddObserver(this);
+  SetLayoutManager(new views::FillLayout);
+}
+
+SearchResultAnswerCardView::~SearchResultAnswerCardView() {
+  model_->RemoveObserver(this);
+}
+
+const char* SearchResultAnswerCardView::GetClassName() const {
+  return "SearchResultAnswerCardView";
+}
+
+void SearchResultAnswerCardView::OnContainerSelected(
+    bool from_bottom,
+    bool directional_movement) {
+  if (num_results() == 0)
+    return;
+
+  SetSelectedIndex(0);
+}
+
+int SearchResultAnswerCardView::GetYSize() {
+  return num_results();
+}
+
+int SearchResultAnswerCardView::DoUpdate() {
+  const bool have_result = search_answer_container_view_->visible();
+  set_container_score(have_result ? kSearchAnswerCardRelevance : 0);
+  return have_result ? 1 : 0;
+}
+
+void SearchResultAnswerCardView::UpdateSelectedIndex(int old_selected,
+                                                     int new_selected) {
+  if (new_selected == old_selected)
+    return;
+
+  const bool is_selected = new_selected == 0;
+  search_answer_container_view_->SetSelected(is_selected);
+  if (is_selected)
+    NotifyAccessibilityEvent(ui::AX_EVENT_SELECTION, true);
+}
+
+void SearchResultAnswerCardView::OnSearchAnswerAvailableChanged(
+    bool has_answer) {
+  const bool visible = has_answer && !features::IsAnswerCardDarkRunEnabled();
+  if (visible == search_answer_container_view_->visible())
+    return;
+
+  search_answer_container_view_->SetVisible(visible);
+  ScheduleUpdate();
+}
+
+}  // namespace app_list
diff --git a/ui/app_list/views/search_result_answer_card_view.h b/ui/app_list/views/search_result_answer_card_view.h
new file mode 100644
index 0000000..745b5fad
--- /dev/null
+++ b/ui/app_list/views/search_result_answer_card_view.h
@@ -0,0 +1,55 @@
+// 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 UI_APP_LIST_VIEWS_SEARCH_RESULT_ANSWER_CARD_VIEW_H_
+#define UI_APP_LIST_VIEWS_SEARCH_RESULT_ANSWER_CARD_VIEW_H_
+
+#include "ui/app_list/app_list_model_observer.h"
+#include "ui/app_list/views/search_result_container_view.h"
+
+namespace app_list {
+
+class AppListModel;
+class SearchResultPageView;
+
+// Result container for the search answer card.
+class APP_LIST_EXPORT SearchResultAnswerCardView
+    : public SearchResultContainerView,
+      public AppListModelObserver {
+ public:
+  SearchResultAnswerCardView(AppListModel* model,
+                             SearchResultPageView* search_results_page_view,
+                             views::View* search_answer_view);
+  ~SearchResultAnswerCardView() override;
+
+ private:
+  class SearchAnswerContainerView;
+
+  // Overridden from views::View:
+  const char* GetClassName() const override;
+
+  // Overridden from SearchResultContainerView:
+  void OnContainerSelected(bool from_bottom,
+                           bool directional_movement) override;
+  void NotifyFirstResultYIndex(int y_index) override {}
+  int GetYSize() override;
+  int DoUpdate() override;
+  void UpdateSelectedIndex(int old_selected, int new_selected) override;
+
+  // Overridden from AppListModelObserver
+  void OnSearchAnswerAvailableChanged(bool has_answer) override;
+
+  // Unowned pointer to application list model.
+  AppListModel* const model_;
+
+  // Pointer to the container of the search answer; owned by the view hierarchy.
+  // It's visible iff we have a search answer result.
+  SearchAnswerContainerView* const search_answer_container_view_;
+
+  DISALLOW_COPY_AND_ASSIGN(SearchResultAnswerCardView);
+};
+
+}  // namespace app_list
+
+#endif  // UI_APP_LIST_VIEWS_SEARCH_RESULT_ANSWER_CARD_VIEW_H_
diff --git a/ui/app_list/views/search_result_container_view.h b/ui/app_list/views/search_result_container_view.h
index b5f8496..19c02c13 100644
--- a/ui/app_list/views/search_result_container_view.h
+++ b/ui/app_list/views/search_result_container_view.h
@@ -84,11 +84,12 @@
   virtual void OnContainerSelected(bool from_bottom,
                                    bool directional_movement) = 0;
 
- private:
+ protected:
   // Schedules an Update call using |update_factory_|. Do nothing if there is a
   // pending call.
   void ScheduleUpdate();
 
+ private:
   // Updates UI with model. Returns the number of visible results.
   virtual int DoUpdate() = 0;
 
diff --git a/ui/aura/mus/property_utils.cc b/ui/aura/mus/property_utils.cc
index 089826e..b9ffba18 100644
--- a/ui/aura/mus/property_utils.cc
+++ b/ui/aura/mus/property_utils.cc
@@ -12,7 +12,7 @@
 namespace aura {
 namespace {
 
-client::WindowType UiWindowTypeToWmWindowType(ui::mojom::WindowType type) {
+client::WindowType UiWindowTypeToWindowType(ui::mojom::WindowType type) {
   switch (type) {
     case ui::mojom::WindowType::WINDOW:
       return client::WINDOW_TYPE_NORMAL;
@@ -40,7 +40,7 @@
 
 void SetWindowType(Window* window, ui::mojom::WindowType window_type) {
   window->SetProperty(client::kWindowTypeKey, window_type);
-  window->SetType(UiWindowTypeToWmWindowType(window_type));
+  window->SetType(UiWindowTypeToWindowType(window_type));
 }
 
 }  // namespace aura
diff --git a/ui/gl/gl_surface_glx.cc b/ui/gl/gl_surface_glx.cc
index 2543994..4c0afc9 100644
--- a/ui/gl/gl_surface_glx.cc
+++ b/ui/gl/gl_surface_glx.cc
@@ -18,8 +18,8 @@
 #include "base/single_thread_task_runner.h"
 #include "base/synchronization/cancellation_flag.h"
 #include "base/synchronization/lock.h"
-#include "base/threading/non_thread_safe.h"
 #include "base/threading/thread.h"
+#include "base/threading/thread_checker.h"
 #include "base/threading/thread_task_runner_handle.h"
 #include "base/time/time.h"
 #include "base/trace_event/trace_event.h"
@@ -171,7 +171,6 @@
 };
 
 class SGIVideoSyncThread : public base::Thread,
-                           public base::NonThreadSafe,
                            public base::RefCounted<SGIVideoSyncThread> {
  public:
   static scoped_refptr<SGIVideoSyncThread> Create() {
@@ -186,17 +185,19 @@
   friend class base::RefCounted<SGIVideoSyncThread>;
 
   SGIVideoSyncThread() : base::Thread("SGI_video_sync") {
-    DCHECK(CalledOnValidThread());
+    DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
   }
 
   ~SGIVideoSyncThread() override {
-    DCHECK(CalledOnValidThread());
+    DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
     g_video_sync_thread = nullptr;
     Stop();
   }
 
   static SGIVideoSyncThread* g_video_sync_thread;
 
+  THREAD_CHECKER(thread_checker_);
+
   DISALLOW_COPY_AND_ASSIGN(SGIVideoSyncThread);
 };
 
diff --git a/ui/resources/default_100_percent/common/window_bubble_shadow_small.png b/ui/resources/default_100_percent/common/window_bubble_shadow_small.png
deleted file mode 100644
index 9a7b851..0000000
--- a/ui/resources/default_100_percent/common/window_bubble_shadow_small.png
+++ /dev/null
Binary files differ
diff --git a/ui/resources/default_100_percent/common/window_shadow_active.png b/ui/resources/default_100_percent/common/window_shadow_active.png
deleted file mode 100644
index 14c4522..0000000
--- a/ui/resources/default_100_percent/common/window_shadow_active.png
+++ /dev/null
Binary files differ
diff --git a/ui/resources/default_100_percent/common/window_shadow_inactive.png b/ui/resources/default_100_percent/common/window_shadow_inactive.png
deleted file mode 100644
index 2204f7a..0000000
--- a/ui/resources/default_100_percent/common/window_shadow_inactive.png
+++ /dev/null
Binary files differ
diff --git a/ui/resources/default_200_percent/common/window_bubble_shadow_small.png b/ui/resources/default_200_percent/common/window_bubble_shadow_small.png
deleted file mode 100644
index 8753541..0000000
--- a/ui/resources/default_200_percent/common/window_bubble_shadow_small.png
+++ /dev/null
Binary files differ
diff --git a/ui/resources/default_200_percent/common/window_shadow_active.png b/ui/resources/default_200_percent/common/window_shadow_active.png
deleted file mode 100644
index 7ba2a85..0000000
--- a/ui/resources/default_200_percent/common/window_shadow_active.png
+++ /dev/null
Binary files differ
diff --git a/ui/resources/default_200_percent/common/window_shadow_inactive.png b/ui/resources/default_200_percent/common/window_shadow_inactive.png
deleted file mode 100644
index c2d3ee8..0000000
--- a/ui/resources/default_200_percent/common/window_shadow_inactive.png
+++ /dev/null
Binary files differ
diff --git a/ui/resources/ui_resources.grd b/ui/resources/ui_resources.grd
index 20cba9c..54eff09 100644
--- a/ui/resources/ui_resources.grd
+++ b/ui/resources/ui_resources.grd
@@ -78,11 +78,6 @@
         <structure type="chrome_scaled_image" name="IDR_AURA_CURSOR_GRAB" file="common/pointers/fleur.png" />
         <structure type="chrome_scaled_image" name="IDR_AURA_CURSOR_GRABBING" file="common/pointers/hand3.png" />
       </if>
-      <if expr="use_aura">
-        <structure type="chrome_scaled_image" name="IDR_AURA_SHADOW_ACTIVE" file="common/window_shadow_active.png" />
-        <structure type="chrome_scaled_image" name="IDR_AURA_SHADOW_INACTIVE" file="common/window_shadow_inactive.png" />
-        <structure type="chrome_scaled_image" name="IDR_WINDOW_BUBBLE_SHADOW_SMALL" file="common/window_bubble_shadow_small.png" />
-      </if>
       <structure type="chrome_scaled_image" name="IDR_CLOSE_2" file="close_2.png" />
       <structure type="chrome_scaled_image" name="IDR_CLOSE_2_H" file="close_2_hover.png" />
       <structure type="chrome_scaled_image" name="IDR_CLOSE_2_MASK" file="close_2_mask.png" />
diff --git a/ui/views/controls/webview/BUILD.gn b/ui/views/controls/webview/BUILD.gn
index b8daeebab..2836c31 100644
--- a/ui/views/controls/webview/BUILD.gn
+++ b/ui/views/controls/webview/BUILD.gn
@@ -8,6 +8,8 @@
     "unhandled_keyboard_event_handler.h",
     "unhandled_keyboard_event_handler_mac.mm",
     "unhandled_keyboard_event_handler_win.cc",
+    "web_contents_set_background_color.cc",
+    "web_contents_set_background_color.h",
     "web_dialog_view.cc",
     "web_dialog_view.h",
     "webview.cc",
diff --git a/chrome/browser/chromeos/login/ui/web_contents_set_background_color.cc b/ui/views/controls/webview/web_contents_set_background_color.cc
similarity index 85%
rename from chrome/browser/chromeos/login/ui/web_contents_set_background_color.cc
rename to ui/views/controls/webview/web_contents_set_background_color.cc
index 6b57011..e5de0e42 100644
--- a/chrome/browser/chromeos/login/ui/web_contents_set_background_color.cc
+++ b/ui/views/controls/webview/web_contents_set_background_color.cc
@@ -1,17 +1,17 @@
-// Copyright 2016 The Chromium Authors. All rights reserved.
+// 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/chromeos/login/ui/web_contents_set_background_color.h"
+#include "ui/views/controls/webview/web_contents_set_background_color.h"
 
 #include "base/memory/ptr_util.h"
 #include "content/public/browser/render_view_host.h"
 #include "content/public/browser/render_widget_host.h"
 #include "content/public/browser/render_widget_host_view.h"
 
-DEFINE_WEB_CONTENTS_USER_DATA_KEY(chromeos::WebContentsSetBackgroundColor);
+DEFINE_WEB_CONTENTS_USER_DATA_KEY(views::WebContentsSetBackgroundColor);
 
-namespace chromeos {
+namespace views {
 
 // static
 void WebContentsSetBackgroundColor::CreateForWebContentsWithColor(
@@ -54,4 +54,4 @@
   new_host->GetWidget()->GetView()->SetBackgroundColor(color_);
 }
 
-}  // namespace chromeos
+}  // namespace views
diff --git a/chrome/browser/chromeos/login/ui/web_contents_set_background_color.h b/ui/views/controls/webview/web_contents_set_background_color.h
similarity index 72%
rename from chrome/browser/chromeos/login/ui/web_contents_set_background_color.h
rename to ui/views/controls/webview/web_contents_set_background_color.h
index 024d310..e10a3a3 100644
--- a/chrome/browser/chromeos/login/ui/web_contents_set_background_color.h
+++ b/ui/views/controls/webview/web_contents_set_background_color.h
@@ -2,16 +2,17 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef CHROME_BROWSER_CHROMEOS_LOGIN_UI_WEB_CONTENTS_SET_BACKGROUND_COLOR_H_
-#define CHROME_BROWSER_CHROMEOS_LOGIN_UI_WEB_CONTENTS_SET_BACKGROUND_COLOR_H_
+#ifndef UI_VIEWS_CONTROLS_WEBVIEW_WEB_CONTENTS_SET_BACKGROUND_COLOR_H_
+#define UI_VIEWS_CONTROLS_WEBVIEW_WEB_CONTENTS_SET_BACKGROUND_COLOR_H_
 
 #include "content/public/browser/web_contents_observer.h"
 #include "content/public/browser/web_contents_user_data.h"
+#include "ui/views/controls/webview/webview_export.h"
 
 // Defined in SkColor.h (32-bit ARGB color).
 using SkColor = unsigned int;
 
-namespace chromeos {
+namespace views {
 
 // Ensures that the background color of a given WebContents instance is always
 // set to a given color value.
@@ -19,8 +20,9 @@
     : public content::WebContentsObserver,
       public content::WebContentsUserData<WebContentsSetBackgroundColor> {
  public:
-  static void CreateForWebContentsWithColor(content::WebContents* web_contents,
-                                            SkColor color);
+  WEBVIEW_EXPORT static void CreateForWebContentsWithColor(
+      content::WebContents* web_contents,
+      SkColor color);
 
   ~WebContentsSetBackgroundColor() override;
 
@@ -39,6 +41,6 @@
   DISALLOW_COPY_AND_ASSIGN(WebContentsSetBackgroundColor);
 };
 
-}  // namespace chromeos
+}  // namespace views
 
-#endif  // CHROME_BROWSER_CHROMEOS_LOGIN_UI_WEB_CONTENTS_SET_BACKGROUND_COLOR_H_
+#endif  // UI_VIEWS_CONTROLS_WEBVIEW_WEB_CONTENTS_SET_BACKGROUND_COLOR_H_
diff --git a/ui/views/focus/focus_manager.cc b/ui/views/focus/focus_manager.cc
index 740a4c7..03a3d6a 100644
--- a/ui/views/focus/focus_manager.cc
+++ b/ui/views/focus/focus_manager.cc
@@ -5,13 +5,9 @@
 #include "ui/views/focus/focus_manager.h"
 
 #include <algorithm>
-#include <cstring>
 #include <vector>
 
 #include "base/auto_reset.h"
-#include "base/debug/alias.h"
-#include "base/debug/dump_without_crashing.h"
-#include "base/debug/stack_trace.h"
 #include "base/logging.h"
 #include "ui/base/accelerators/accelerator.h"
 #include "ui/base/ime/input_method.h"
@@ -28,16 +24,6 @@
 #include "ui/views/widget/widget_delegate.h"
 
 namespace views {
-namespace {
-
-#if defined(OS_CHROMEOS)
-// Crash appears to be specific to chromeos, so only log there.
-bool should_log_focused_view = true;
-#else
-bool should_log_focused_view = false;
-#endif
-
-}  // namespace
 
 bool FocusManager::arrow_key_traversal_enabled_ = false;
 
@@ -355,12 +341,6 @@
   if (focused_view_) {
     focused_view_->AddObserver(this);
     focused_view_->Focus();
-    if (should_log_focused_view) {
-      stack_when_focused_view_set_ =
-          base::MakeUnique<base::debug::StackTrace>();
-    }
-  } else {
-    stack_when_focused_view_set_.reset();
   }
 
   for (FocusChangeListener& observer : focus_change_listeners_)
@@ -593,33 +573,6 @@
 
 void FocusManager::OnViewIsDeleting(View* view) {
   CHECK_EQ(view, focused_view_);
-
-  // Widget forwards the appropriate calls such that we should never end up
-  // here. None-the-less crashes indicate we are. This logs the stack once when
-  // this happens.
-  // TODO(sky): remove when cause of 687232 is found.
-  if (stack_when_focused_view_set_ && should_log_focused_view) {
-    should_log_focused_view = false;
-    size_t stack_size = 0u;
-    const void* const* instruction_pointers =
-        stack_when_focused_view_set_->Addresses(&stack_size);
-    static constexpr size_t kMaxStackSize = 100;
-    const void* instruction_pointers_copy[kMaxStackSize];
-    // Insert markers bracketing the crash to make it easier to locate.
-    memset(&instruction_pointers_copy[0], 0xAB,
-           sizeof(instruction_pointers_copy[0]));
-    const size_t last_marker_index =
-        std::min(kMaxStackSize - 1, stack_size + 1);
-    memset(&instruction_pointers_copy[last_marker_index], 0xAB,
-           sizeof(instruction_pointers_copy[last_marker_index]));
-    std::memcpy(&instruction_pointers_copy[1], instruction_pointers,
-                std::min(kMaxStackSize - 2, stack_size) * sizeof(const void*));
-    base::debug::Alias(&stack_size);
-    base::debug::Alias(&instruction_pointers_copy);
-    base::debug::DumpWithoutCrashing();
-    stack_when_focused_view_set_.reset();
-  }
-
   focused_view_->RemoveObserver(this);
   focused_view_ = nullptr;
 }
diff --git a/ui/views/focus/focus_manager.h b/ui/views/focus/focus_manager.h
index 5f91273d..0741d5a 100644
--- a/ui/views/focus/focus_manager.h
+++ b/ui/views/focus/focus_manager.h
@@ -71,12 +71,6 @@
 // Note that FocusTraversable views do not have to be RootViews:
 // AccessibleToolbarView is FocusTraversable.
 
-namespace base {
-namespace debug {
-class StackTrace;
-}
-}
-
 namespace ui {
 class Accelerator;
 class AcceleratorTarget;
@@ -355,9 +349,6 @@
   // The view that currently is focused.
   View* focused_view_ = nullptr;
 
-  // TODO(sky): remove, used for debugging 687232.
-  std::unique_ptr<base::debug::StackTrace> stack_when_focused_view_set_;
-
   // The AcceleratorManager this FocusManager is associated with.
   ui::AcceleratorManager accelerator_manager_;