diff --git a/BUILD.gn b/BUILD.gn
index a63acc2..2f5e693 100644
--- a/BUILD.gn
+++ b/BUILD.gn
@@ -163,6 +163,7 @@
       "//content/test:content_perftests",
       "//content/test:content_unittests",
       "//device:device_unittests",
+      "//google_apis/gcm:mcs_probe",
       "//gpu:gpu_unittests",
       "//gpu/ipc/service:gpu_ipc_service_unittests",
       "//ipc:ipc_tests",
@@ -414,7 +415,6 @@
       "//device:device_unittests",
       "//gin:gin_shell",
       "//gin:gin_unittests",
-      "//google_apis/gcm:mcs_probe",
       "//gpu:gl_tests",
       "//gpu:gpu_perftests",
       "//ipc:ipc_perftests",
diff --git a/DEPS b/DEPS
index 3aa0222..1667d1b 100644
--- a/DEPS
+++ b/DEPS
@@ -44,7 +44,7 @@
   # 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': '7d459498f126a580e55979a9b1c4a80119644d3f',
+  'v8_revision': 'c092edbb88f4317058ebc952420e366911db6777',
   # 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.
@@ -96,7 +96,7 @@
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling catapult
   # and whatever else without interference from each other.
-  'catapult_revision': '24245dde6fc83c8881775a3d2556797f5bba287b',
+  'catapult_revision': 'e6ad06342efb08256f35c2605ac9c3be87a3e770',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling libFuzzer
   # and whatever else without interference from each other.
diff --git a/WATCHLISTS b/WATCHLISTS
index 0a791b11..543f139d 100644
--- a/WATCHLISTS
+++ b/WATCHLISTS
@@ -293,7 +293,8 @@
       'filepath': 'chrome_elf',
     },
     'chrome_grc': {
-      'filepath': 'services/resource_coordinator',
+      'filepath': 'chrome/browser/resource_coordinator/'\
+                  '|services/resource_coordinator/',
     },
     'chrome_views': {
       'filepath': 'chrome/browser/ui/views',
@@ -2062,7 +2063,6 @@
                 'skanuj+watch@chromium.org'],
     'ios': ['ios-reviews@chromium.org'],
     'ios_chrome': ['ios-reviews+chrome@chromium.org',
-                   'pkl@chromium.org',
                    'noyau+watch@chromium.org',
                    'marq+watch@chromium.org'],
     'ios_clean': ['ios-reviews+clean@chromium.org',
diff --git a/android_webview/browser/net/aw_url_request_context_getter.cc b/android_webview/browser/net/aw_url_request_context_getter.cc
index f8479ef..0f4c68aa 100644
--- a/android_webview/browser/net/aw_url_request_context_getter.cc
+++ b/android_webview/browser/net/aw_url_request_context_getter.cc
@@ -39,6 +39,7 @@
 #include "net/http/http_auth_handler_factory.h"
 #include "net/http/http_auth_preferences.h"
 #include "net/http/http_cache.h"
+#include "net/http/http_network_session.h"
 #include "net/http/http_stream_factory.h"
 #include "net/log/net_log.h"
 #include "net/net_features.h"
@@ -83,7 +84,7 @@
 }
 
 void ApplyCmdlineOverridesToNetworkSessionParams(
-    net::URLRequestContextBuilder::HttpNetworkSessionParams* params) {
+    net::HttpNetworkSession::Params* params) {
   int value;
   const base::CommandLine& command_line =
       *base::CommandLine::ForCurrentProcess();
@@ -255,8 +256,7 @@
   builder.SetFileTaskRunner(
       BrowserThread::GetTaskRunnerForThread(BrowserThread::CACHE));
 
-  net::URLRequestContextBuilder::HttpNetworkSessionParams
-      network_session_params;
+  net::HttpNetworkSession::Params network_session_params;
   ApplyCmdlineOverridesToNetworkSessionParams(&network_session_params);
   builder.set_http_network_session_params(network_session_params);
   builder.SetSpdyAndQuicEnabled(true, false);
diff --git a/ash/BUILD.gn b/ash/BUILD.gn
index 0f948df..5df23998 100644
--- a/ash/BUILD.gn
+++ b/ash/BUILD.gn
@@ -820,9 +820,6 @@
     "wm/workspace_controller.cc",
     "wm/workspace_controller.h",
     "wm_display_observer.h",
-    "wm_transient_window_observer.h",
-    "wm_window.cc",
-    "wm_window.h",
   ]
 
   configs += [ "//build/config:precompiled_headers" ]
diff --git a/ash/aura/shell_port_classic.cc b/ash/aura/shell_port_classic.cc
index 4603cb5..acea8770 100644
--- a/ash/aura/shell_port_classic.cc
+++ b/ash/aura/shell_port_classic.cc
@@ -33,7 +33,6 @@
 #include "ash/wm/window_util.h"
 #include "ash/wm/workspace/workspace_event_handler_aura.h"
 #include "ash/wm_display_observer.h"
-#include "ash/wm_window.h"
 #include "base/memory/ptr_util.h"
 #include "ui/aura/env.h"
 #include "ui/display/manager/chromeos/default_touch_transform_setter.h"
@@ -150,13 +149,8 @@
   return Shell::Get()->cursor_manager()->IsMouseEventsEnabled();
 }
 
-std::vector<WmWindow*> ShellPortClassic::GetAllRootWindows() {
-  aura::Window::Windows root_windows =
-      Shell::Get()->window_tree_host_manager()->GetAllRootWindows();
-  std::vector<WmWindow*> wm_windows(root_windows.size());
-  for (size_t i = 0; i < root_windows.size(); ++i)
-    wm_windows[i] = WmWindow::Get(root_windows[i]);
-  return wm_windows;
+std::vector<aura::Window*> ShellPortClassic::GetAllRootWindows() {
+  return Shell::Get()->window_tree_host_manager()->GetAllRootWindows();
 }
 
 void ShellPortClassic::RecordUserMetricsAction(UserMetricsAction action) {
diff --git a/ash/aura/shell_port_classic.h b/ash/aura/shell_port_classic.h
index e63ae5b..af54fbf 100644
--- a/ash/aura/shell_port_classic.h
+++ b/ash/aura/shell_port_classic.h
@@ -54,7 +54,7 @@
   void HideCursor() override;
   void SetGlobalOverrideCursor(base::Optional<ui::CursorData> cursor) override;
   bool IsMouseEventsEnabled() override;
-  std::vector<WmWindow*> GetAllRootWindows() override;
+  std::vector<aura::Window*> GetAllRootWindows() override;
   void RecordGestureAction(GestureActionType action) override;
   void RecordUserMetricsAction(UserMetricsAction action) override;
   void RecordTaskSwitchMetric(TaskSwitchSource source) override;
diff --git a/ash/mus/bridge/shell_port_mash.cc b/ash/mus/bridge/shell_port_mash.cc
index 40cc6d9..46c4bc9 100644
--- a/ash/mus/bridge/shell_port_mash.cc
+++ b/ash/mus/bridge/shell_port_mash.cc
@@ -51,7 +51,6 @@
 #include "ash/wm/window_util.h"
 #include "ash/wm/workspace/workspace_event_handler_aura.h"
 #include "ash/wm_display_observer.h"
-#include "ash/wm_window.h"
 #include "base/command_line.h"
 #include "base/memory/ptr_util.h"
 #include "components/user_manager/user_info_impl.h"
@@ -271,19 +270,14 @@
   return true;
 }
 
-std::vector<WmWindow*> ShellPortMash::GetAllRootWindows() {
-  if (GetAshConfig() == Config::MUS) {
-    aura::Window::Windows root_windows =
-        Shell::Get()->window_tree_host_manager()->GetAllRootWindows();
-    std::vector<WmWindow*> wm_windows(root_windows.size());
-    for (size_t i = 0; i < root_windows.size(); ++i)
-      wm_windows[i] = WmWindow::Get(root_windows[i]);
-    return wm_windows;
-  }
-  std::vector<WmWindow*> root_windows;
+std::vector<aura::Window*> ShellPortMash::GetAllRootWindows() {
+  if (GetAshConfig() == Config::MUS)
+    return Shell::Get()->window_tree_host_manager()->GetAllRootWindows();
+
+  aura::Window::Windows root_windows;
   for (RootWindowController* root_window_controller :
        RootWindowController::root_window_controllers()) {
-    root_windows.push_back(root_window_controller->GetWindow());
+    root_windows.push_back(root_window_controller->GetRootWindow());
   }
   return root_windows;
 }
diff --git a/ash/mus/bridge/shell_port_mash.h b/ash/mus/bridge/shell_port_mash.h
index 99d1b65..262c93ee 100644
--- a/ash/mus/bridge/shell_port_mash.h
+++ b/ash/mus/bridge/shell_port_mash.h
@@ -78,7 +78,7 @@
   void HideCursor() override;
   void SetGlobalOverrideCursor(base::Optional<ui::CursorData> cursor) override;
   bool IsMouseEventsEnabled() override;
-  std::vector<WmWindow*> GetAllRootWindows() override;
+  std::vector<aura::Window*> GetAllRootWindows() override;
   void RecordGestureAction(GestureActionType action) override;
   void RecordUserMetricsAction(UserMetricsAction action) override;
   void RecordTaskSwitchMetric(TaskSwitchSource source) override;
diff --git a/ash/root_window_controller.cc b/ash/root_window_controller.cc
index 70ca0ef2..ec3e336 100644
--- a/ash/root_window_controller.cc
+++ b/ash/root_window_controller.cc
@@ -55,7 +55,6 @@
 #include "ash/wm/window_util.h"
 #include "ash/wm/workspace/workspace_layout_manager.h"
 #include "ash/wm/workspace_controller.h"
-#include "ash/wm_window.h"
 #include "base/command_line.h"
 #include "base/macros.h"
 #include "base/memory/ptr_util.h"
@@ -344,10 +343,6 @@
   return GetHost()->window();
 }
 
-const WmWindow* RootWindowController::GetWindow() const {
-  return WmWindow::Get(GetRootWindow());
-}
-
 wm::WorkspaceWindowState RootWindowController::GetWorkspaceWindowState() {
   return workspace_controller_ ? workspace_controller()->GetWindowState()
                                : wm::WORKSPACE_WINDOW_STATE_DEFAULT;
@@ -482,11 +477,6 @@
   return window_tree_host_->window()->GetChildById(container_id);
 }
 
-const WmWindow* RootWindowController::GetWmContainer(int container_id) const {
-  const aura::Window* window = GetContainer(container_id);
-  return WmWindow::Get(window);
-}
-
 void RootWindowController::SetWallpaperWidgetController(
     WallpaperWidgetController* controller) {
   wallpaper_widget_controller_.reset(controller);
diff --git a/ash/root_window_controller.h b/ash/root_window_controller.h
index 904d6689..f97dce28 100644
--- a/ash/root_window_controller.h
+++ b/ash/root_window_controller.h
@@ -63,7 +63,6 @@
 class TouchHudDebug;
 class TouchHudProjection;
 class WallpaperWidgetController;
-class WmWindow;
 class WorkspaceController;
 
 namespace mus {
@@ -125,13 +124,6 @@
   aura::Window* GetRootWindow();
   const aura::Window* GetRootWindow() const;
 
-  // TODO(sky): remove these. http://crbug.com/671246.
-  WmWindow* GetWindow() {
-    return const_cast<WmWindow*>(
-        const_cast<const RootWindowController*>(this)->GetWindow());
-  }
-  const WmWindow* GetWindow() const;
-
   WorkspaceController* workspace_controller() {
     return workspace_controller_.get();
   }
@@ -207,14 +199,6 @@
   aura::Window* GetContainer(int container_id);
   const aura::Window* GetContainer(int container_id) const;
 
-  // TODO(sky): remove these. http://crbug.com/671246.
-  WmWindow* GetWmContainer(int container_id) {
-    return const_cast<WmWindow*>(
-        const_cast<const RootWindowController*>(this)->GetWmContainer(
-            container_id));
-  }
-  const WmWindow* GetWmContainer(int container_id) const;
-
   WallpaperWidgetController* wallpaper_widget_controller() {
     return wallpaper_widget_controller_.get();
   }
diff --git a/ash/rotator/screen_rotation_animator_unittest.cc b/ash/rotator/screen_rotation_animator_unittest.cc
index fa65898..dfcacde 100644
--- a/ash/rotator/screen_rotation_animator_unittest.cc
+++ b/ash/rotator/screen_rotation_animator_unittest.cc
@@ -11,8 +11,12 @@
 #include "ash/rotator/test/screen_rotation_animator_test_api.h"
 #include "ash/shell.h"
 #include "ash/shell_port.h"
+#include "ash/system/overview/overview_button_tray.h"
+#include "ash/system/status_area_widget.h"
 #include "ash/test/ash_test_base.h"
 #include "ash/test/ash_test_helper.h"
+#include "ash/test/status_area_widget_test_helper.h"
+#include "ash/wm/maximize_mode/maximize_mode_controller.h"
 #include "base/callback_forward.h"
 #include "base/command_line.h"
 #include "base/memory/ptr_util.h"
@@ -42,6 +46,11 @@
       display::Display::RotationSource::ROTATION_SOURCE_USER);
 }
 
+OverviewButtonTray* GetTray() {
+  return StatusAreaWidgetTestHelper::GetStatusAreaWidget()
+      ->overview_button_tray();
+}
+
 class AnimationObserver : public ScreenRotationAnimatorObserver {
  public:
   AnimationObserver() {}
@@ -392,6 +401,36 @@
   EXPECT_EQ(display::Display::ROTATE_270, GetDisplayRotation(display_id()));
 }
 
+// Test that slow screen rotation animation will not interrupt hide animation.
+// The OverviewButton should be hidden.
+TEST_F(ScreenRotationAnimatorSlowAnimationTest,
+       OverviewButtonTrayHideAnimationAlwaysCompletes) {
+  // TODO(wutao): needs GetDisplayInfo http://crbug.com/622480.
+  if (Shell::GetAshConfig() == Config::MASH) {
+    ASSERT_TRUE(ShellPort::Get()->GetDisplayInfo(display_id()).id() !=
+                display_id());
+    return;
+  }
+
+  Shell::Get()->maximize_mode_controller()->EnableMaximizeModeWindowManager(
+      true);
+
+  // Long duration for hide animation, to allow it to be interrupted.
+  ui::ScopedAnimationDurationScaleMode hide_duration(
+      ui::ScopedAnimationDurationScaleMode::SLOW_DURATION);
+  GetTray()->SetVisible(false);
+
+  // ScreenRotationAnimator copies the current layers, and deletes them upon
+  // completion. Allow its animation to complete first.
+  ui::ScopedAnimationDurationScaleMode rotate_duration(
+      ui::ScopedAnimationDurationScaleMode::ZERO_DURATION);
+  SetDisplayRotation(display_id(), display::Display::ROTATE_0);
+  animator()->Rotate(display::Display::ROTATE_90,
+                     display::Display::RotationSource::ROTATION_SOURCE_USER);
+
+  EXPECT_FALSE(GetTray()->visible());
+}
+
 // Test enable smooth screen rotation code path.
 TEST_F(ScreenRotationAnimatorSmoothAnimationTest,
        RotatesToDifferentRotationWithCopyCallback) {
@@ -543,4 +582,40 @@
   EXPECT_EQ(secondary_display_id, display_manager()->GetDisplayAt(0).id());
 }
 
+// Test that smooth screen rotation animation will not interrupt hide animation.
+// The OverviewButton should be hidden.
+TEST_F(ScreenRotationAnimatorSmoothAnimationTest,
+       OverviewButtonTrayHideAnimationAlwaysCompletes) {
+  // TODO(wutao): needs GetDisplayInfo http://crbug.com/622480.
+  if (Shell::GetAshConfig() == Config::MASH) {
+    ASSERT_TRUE(ShellPort::Get()->GetDisplayInfo(display_id()).id() !=
+                display_id());
+    return;
+  }
+
+  Shell::Get()->maximize_mode_controller()->EnableMaximizeModeWindowManager(
+      true);
+
+  // Long duration for hide animation, to allow it to be interrupted.
+  ui::ScopedAnimationDurationScaleMode hide_duration(
+      ui::ScopedAnimationDurationScaleMode::SLOW_DURATION);
+  GetTray()->SetVisible(false);
+
+  // Allow ScreenRotationAnimator animation to complete first.
+  ui::ScopedAnimationDurationScaleMode rotate_duration(
+      ui::ScopedAnimationDurationScaleMode::ZERO_DURATION);
+  SetScreenRotationAnimator(
+      display_manager()->GetDisplayAt(0).id(), run_loop_->QuitWhenIdleClosure(),
+      base::Bind(
+          &ScreenRotationAnimatorSmoothAnimationTest::QuitWaitForCopyCallback,
+          base::Unretained(this)));
+  SetDisplayRotation(display_id(), display::Display::ROTATE_0);
+  animator()->Rotate(display::Display::ROTATE_90,
+                     display::Display::RotationSource::ROTATION_SOURCE_USER);
+  WaitForCopyCallback();
+
+  GetTray()->layer()->GetAnimator()->StopAnimating();
+  EXPECT_FALSE(GetTray()->visible());
+}
+
 }  // namespace ash
diff --git a/ash/shell.cc b/ash/shell.cc
index c12b790b..132265c 100644
--- a/ash/shell.cc
+++ b/ash/shell.cc
@@ -117,7 +117,6 @@
 #include "ash/wm/window_properties.h"
 #include "ash/wm/window_util.h"
 #include "ash/wm/workspace_controller.h"
-#include "ash/wm_window.h"
 #include "base/bind.h"
 #include "base/bind_helpers.h"
 #include "base/command_line.h"
@@ -258,8 +257,11 @@
 Shell::RootWindowControllerList Shell::GetAllRootWindowControllers() {
   CHECK(HasInstance());
   RootWindowControllerList root_window_controllers;
-  for (WmWindow* root_window : instance_->shell_port_->GetAllRootWindows())
-    root_window_controllers.push_back(root_window->GetRootWindowController());
+  for (aura::Window* root_window :
+       instance_->shell_port_->GetAllRootWindows()) {
+    root_window_controllers.push_back(
+        RootWindowController::ForWindow(root_window));
+  }
   return root_window_controllers;
 }
 
@@ -290,10 +292,7 @@
 // static
 aura::Window::Windows Shell::GetAllRootWindows() {
   CHECK(HasInstance());
-  aura::Window::Windows windows;
-  for (WmWindow* window : instance_->shell_port_->GetAllRootWindows())
-    windows.push_back(window->aura_window());
-  return windows;
+  return instance_->shell_port_->GetAllRootWindows();
 }
 
 // static
@@ -386,8 +385,8 @@
 }
 
 void Shell::UpdateShelfVisibility() {
-  for (WmWindow* root : shell_port_->GetAllRootWindows())
-    root->GetRootWindowController()->shelf()->UpdateVisibilityState();
+  for (auto* root_window_controller : GetAllRootWindowControllers())
+    root_window_controller->shelf()->UpdateVisibilityState();
 }
 
 PrefService* Shell::GetActiveUserPrefService() const {
@@ -480,10 +479,8 @@
 }
 
 void Shell::UpdateAfterLoginStatusChange(LoginStatus status) {
-  for (WmWindow* root_window : shell_port_->GetAllRootWindows()) {
-    root_window->GetRootWindowController()->UpdateAfterLoginStatusChange(
-        status);
-  }
+  for (auto* root_window_controller : GetAllRootWindowControllers())
+    root_window_controller->UpdateAfterLoginStatusChange(status);
 }
 
 void Shell::NotifyMaximizeModeStarted() {
@@ -663,8 +660,8 @@
 
   // Destroy SystemTrayDelegate before destroying the status area(s). Make sure
   // to deinitialize the shelf first, as it is initialized after the delegate.
-  for (WmWindow* root : shell_port_->GetAllRootWindows())
-    root->GetRootWindowController()->shelf()->ShutdownShelfWidget();
+  for (auto* root_window_controller : GetAllRootWindowControllers())
+    root_window_controller->shelf()->ShutdownShelfWidget();
   tray_bluetooth_helper_.reset();
   DeleteSystemTrayDelegate();
 
@@ -1167,8 +1164,7 @@
 }
 
 void Shell::CloseAllRootWindowChildWindows() {
-  for (WmWindow* wm_root_window : shell_port_->GetAllRootWindows()) {
-    aura::Window* root_window = wm_root_window->aura_window();
+  for (aura::Window* root_window : shell_port_->GetAllRootWindows()) {
     RootWindowController* controller = GetRootWindowController(root_window);
     if (controller) {
       controller->CloseChildWindows();
diff --git a/ash/shell_port.cc b/ash/shell_port.cc
index f6463630..ecb13fa 100644
--- a/ash/shell_port.cc
+++ b/ash/shell_port.cc
@@ -15,10 +15,11 @@
 #include "ash/shell_delegate.h"
 #include "ash/wm/root_window_finder.h"
 #include "ash/wm/system_modal_container_layout_manager.h"
-#include "ash/wm_window.h"
 #include "base/bind.h"
 #include "base/logging.h"
 #include "base/memory/ptr_util.h"
+#include "ui/aura/client/aura_constants.h"
+#include "ui/aura/window.h"
 #include "ui/display/display.h"
 
 namespace ash {
@@ -79,13 +80,15 @@
 
   // Traverse all system modal containers, and find its direct child window
   // with "SystemModal" setting, and visible.
-  for (WmWindow* root : GetAllRootWindows()) {
-    WmWindow* system_modal =
-        root->GetChildByShellWindowId(kShellWindowId_SystemModalContainer);
+  for (aura::Window* root : GetAllRootWindows()) {
+    aura::Window* system_modal =
+        root->GetChildById(kShellWindowId_SystemModalContainer);
     if (!system_modal)
       continue;
-    for (const WmWindow* child : system_modal->GetChildren()) {
-      if (child->IsSystemModal() && child->GetTargetVisibility()) {
+    for (const aura::Window* child : system_modal->children()) {
+      if (child->GetProperty(aura::client::kModalKey) ==
+              ui::MODAL_TYPE_SYSTEM &&
+          child->layer()->GetTargetVisibility()) {
         return true;
       }
     }
diff --git a/ash/shell_port.h b/ash/shell_port.h
index 23c8c7d..441dac1 100644
--- a/ash/shell_port.h
+++ b/ash/shell_port.h
@@ -52,7 +52,6 @@
 class WindowCycleEventFilter;
 class WindowResizer;
 class WmDisplayObserver;
-class WmWindow;
 class WorkspaceEventHandler;
 
 enum class Config;
@@ -146,7 +145,7 @@
       base::Optional<ui::CursorData> cursor) = 0;
   virtual bool IsMouseEventsEnabled() = 0;
 
-  virtual std::vector<WmWindow*> GetAllRootWindows() = 0;
+  virtual std::vector<aura::Window*> GetAllRootWindows() = 0;
 
   virtual void RecordGestureAction(GestureActionType action) = 0;
   virtual void RecordUserMetricsAction(UserMetricsAction action) = 0;
diff --git a/ash/system/overview/overview_button_tray_unittest.cc b/ash/system/overview/overview_button_tray_unittest.cc
index 44cb7ea..f1fcd237 100644
--- a/ash/system/overview/overview_button_tray_unittest.cc
+++ b/ash/system/overview/overview_button_tray_unittest.cc
@@ -4,6 +4,7 @@
 
 #include "ash/system/overview/overview_button_tray.h"
 
+#include "ash/display/window_tree_host_manager.h"
 #include "ash/login_status.h"
 #include "ash/public/cpp/config.h"
 #include "ash/public/cpp/shelf_types.h"
@@ -31,6 +32,7 @@
 #include "ui/events/event_constants.h"
 #include "ui/events/gestures/gesture_types.h"
 #include "ui/views/controls/image_view.h"
+#include "ui/wm/core/window_util.h"
 
 namespace ash {
 
@@ -256,11 +258,20 @@
   EXPECT_FALSE(GetTray()->is_active());
 }
 
-// Test that when a hide animation is aborted via deletion, that the
-// OverviewButton is still hidden.
+// Test that a hide animation can complete.
 TEST_F(OverviewButtonTrayTest, HideAnimationAlwaysCompletes) {
-  // TODO: disabled as ScreenRotationAnimator does not work in mash,
-  // http://crbug.com/696754.
+  Shell::Get()->maximize_mode_controller()->EnableMaximizeModeWindowManager(
+      true);
+  EXPECT_TRUE(GetTray()->visible());
+  GetTray()->SetVisible(false);
+  EXPECT_FALSE(GetTray()->visible());
+}
+
+// Test that when a hide animation is aborted via deletion, the
+// OverviewButton is still hidden.
+TEST_F(OverviewButtonTrayTest, HideAnimationAlwaysCompletesOnDelete) {
+  // TODO(wutao): disabled as GetRootWindowForDisplayId does not work in mash,
+  // http://crbug.com/706589.
   if (Shell::GetAshConfig() == Config::MASH)
     return;
 
@@ -273,16 +284,14 @@
           ui::ScopedAnimationDurationScaleMode::SLOW_DURATION));
   GetTray()->SetVisible(false);
 
-  // ScreenRotationAnimator copies the current layers, and deletes them upon
-  // completion. Allow its animation to complete first.
-  std::unique_ptr<ui::ScopedAnimationDurationScaleMode> rotate_duration(
-      new ui::ScopedAnimationDurationScaleMode(
-          ui::ScopedAnimationDurationScaleMode::ZERO_DURATION));
-  ash::ScreenRotationAnimator(display::Display::InternalDisplayId())
-      .Rotate(display::Display::ROTATE_270,
-              display::Display::ROTATION_SOURCE_ACTIVE);
+  aura::Window* root_window =
+      Shell::Get()->window_tree_host_manager()->GetRootWindowForDisplayId(
+          display::Screen::GetScreen()->GetPrimaryDisplay().id());
+  // Colone and delete the old layer tree.
+  std::unique_ptr<ui::LayerTreeOwner> old_layer_tree_owner =
+      ::wm::RecreateLayers(root_window);
+  old_layer_tree_owner.reset();
 
-  RunAllPendingInMessageLoop();
   EXPECT_FALSE(GetTray()->visible());
 }
 
diff --git a/ash/wm_transient_window_observer.h b/ash/wm_transient_window_observer.h
deleted file mode 100644
index 0916f4e..0000000
--- a/ash/wm_transient_window_observer.h
+++ /dev/null
@@ -1,25 +0,0 @@
-// Copyright 2016 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef ASH_WM_TRANSIENT_WINDOW_OBSERVER_H_
-#define ASH_WM_TRANSIENT_WINDOW_OBSERVER_H_
-
-#include "ash/ash_export.h"
-
-namespace ash {
-
-class WmWindow;
-
-class ASH_EXPORT WmTransientWindowObserver {
- public:
-  virtual void OnTransientChildAdded(WmWindow* window, WmWindow* transient) {}
-  virtual void OnTransientChildRemoved(WmWindow* window, WmWindow* transient) {}
-
- protected:
-  virtual ~WmTransientWindowObserver() {}
-};
-
-}  // namespace ash
-
-#endif  // ASH_WM_TRANSIENT_WINDOW_OBSERVER_H_
diff --git a/ash/wm_window.cc b/ash/wm_window.cc
deleted file mode 100644
index aea1e78..0000000
--- a/ash/wm_window.cc
+++ /dev/null
@@ -1,539 +0,0 @@
-// Copyright 2016 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "ash/wm_window.h"
-
-#include "ash/ash_constants.h"
-#include "ash/public/cpp/config.h"
-#include "ash/public/cpp/shell_window_ids.h"
-#include "ash/public/cpp/window_properties.h"
-#include "ash/root_window_controller.h"
-#include "ash/shell.h"
-#include "ash/wm/resize_handle_window_targeter.h"
-#include "ash/wm/widget_finder.h"
-#include "ash/wm/window_animations.h"
-#include "ash/wm/window_properties.h"
-#include "ash/wm/window_state.h"
-#include "ash/wm/window_util.h"
-#include "ash/wm_transient_window_observer.h"
-#include "base/memory/ptr_util.h"
-#include "services/ui/public/interfaces/window_manager_constants.mojom.h"
-#include "ui/aura/client/aura_constants.h"
-#include "ui/aura/client/focus_client.h"
-#include "ui/aura/client/window_parenting_client.h"
-#include "ui/aura/layout_manager.h"
-#include "ui/aura/mus/window_manager_delegate.h"
-#include "ui/aura/mus/window_mus.h"
-#include "ui/aura/mus/window_tree_client.h"
-#include "ui/aura/window.h"
-#include "ui/aura/window_delegate.h"
-#include "ui/aura/window_observer.h"
-#include "ui/base/class_property.h"
-#include "ui/base/hit_test.h"
-#include "ui/compositor/layer_tree_owner.h"
-#include "ui/compositor/scoped_layer_animation_settings.h"
-#include "ui/display/screen.h"
-#include "ui/gfx/geometry/insets.h"
-#include "ui/views/widget/widget.h"
-#include "ui/views/widget/widget_delegate.h"
-#include "ui/wm/core/coordinate_conversion.h"
-#include "ui/wm/core/easy_resize_window_targeter.h"
-#include "ui/wm/core/ime_util_chromeos.h"
-#include "ui/wm/core/transient_window_manager.h"
-#include "ui/wm/core/visibility_controller.h"
-#include "ui/wm/core/window_util.h"
-
-DECLARE_UI_CLASS_PROPERTY_TYPE(ash::WmWindow*);
-
-namespace ash {
-namespace {
-DEFINE_OWNED_UI_CLASS_PROPERTY_KEY(WmWindow, kWmWindowKey, nullptr);
-
-static_assert(aura::Window::kInitialId == kShellWindowId_Invalid,
-              "ids must match");
-
-}  // namespace
-
-WmWindow::~WmWindow() {
-  if (added_transient_observer_)
-    ::wm::TransientWindowManager::Get(window_)->RemoveObserver(this);
-}
-
-// static
-const WmWindow* WmWindow::Get(const aura::Window* window) {
-  if (!window)
-    return nullptr;
-
-  const WmWindow* wm_window = window->GetProperty(kWmWindowKey);
-  if (wm_window)
-    return wm_window;
-  // WmWindow is owned by the aura::Window.
-  // TODO(sky): fix constness.
-  return new WmWindow(const_cast<aura::Window*>(window));
-}
-
-// static
-std::vector<WmWindow*> WmWindow::FromAuraWindows(
-    const std::vector<aura::Window*>& aura_windows) {
-  std::vector<WmWindow*> result(aura_windows.size());
-  for (size_t i = 0; i < aura_windows.size(); ++i)
-    result[i] = Get(aura_windows[i]);
-  return result;
-}
-
-// static
-std::vector<aura::Window*> WmWindow::ToAuraWindows(
-    const std::vector<WmWindow*>& windows) {
-  std::vector<aura::Window*> result(windows.size());
-  for (size_t i = 0; i < windows.size(); ++i)
-    result[i] = WmWindow::GetAuraWindow(windows[i]);
-  return result;
-}
-
-// static
-const aura::Window* WmWindow::GetAuraWindow(const WmWindow* wm_window) {
-  return wm_window ? static_cast<const WmWindow*>(wm_window)->aura_window()
-                   : nullptr;
-}
-
-void WmWindow::Destroy() {
-  delete window_;
-  // WARNING: this has been deleted.
-}
-
-const WmWindow* WmWindow::GetRootWindow() const {
-  return Get(window_->GetRootWindow());
-}
-
-RootWindowController* WmWindow::GetRootWindowController() {
-  aura::Window* root = window_->GetRootWindow();
-  return root ? RootWindowController::ForWindow(root) : nullptr;
-}
-
-aura::client::WindowType WmWindow::GetType() const {
-  return window_->type();
-}
-
-int WmWindow::GetAppType() const {
-  return window_->GetProperty(aura::client::kAppType);
-}
-
-void WmWindow::SetAppType(int app_type) const {
-  window_->SetProperty(aura::client::kAppType, app_type);
-}
-
-ui::Layer* WmWindow::GetLayer() {
-  return window_->layer();
-}
-
-bool WmWindow::GetLayerTargetVisibility() {
-  return GetLayer()->GetTargetVisibility();
-}
-
-bool WmWindow::GetLayerVisible() {
-  return GetLayer()->visible();
-}
-
-display::Display WmWindow::GetDisplayNearestWindow() {
-  return display::Screen::GetScreen()->GetDisplayNearestWindow(window_);
-}
-
-bool WmWindow::HasNonClientArea() {
-  return window_->delegate() ? true : false;
-}
-
-int WmWindow::GetNonClientComponent(const gfx::Point& location) {
-  return wm::GetNonClientComponent(window_, location);
-}
-
-gfx::Point WmWindow::ConvertPointToTarget(const WmWindow* target,
-                                          const gfx::Point& point) const {
-  gfx::Point result(point);
-  aura::Window::ConvertPointToTarget(window_, GetAuraWindow(target), &result);
-  return result;
-}
-
-gfx::Point WmWindow::ConvertPointToScreen(const gfx::Point& point) const {
-  gfx::Point result(point);
-  ::wm::ConvertPointToScreen(window_, &result);
-  return result;
-}
-
-gfx::Point WmWindow::ConvertPointFromScreen(const gfx::Point& point) const {
-  gfx::Point result(point);
-  ::wm::ConvertPointFromScreen(window_, &result);
-  return result;
-}
-
-gfx::Rect WmWindow::ConvertRectToScreen(const gfx::Rect& rect) const {
-  gfx::Rect result(rect);
-  ::wm::ConvertRectToScreen(window_, &result);
-  return result;
-}
-
-gfx::Rect WmWindow::ConvertRectFromScreen(const gfx::Rect& rect) const {
-  gfx::Rect result(rect);
-  ::wm::ConvertRectFromScreen(window_, &result);
-  return result;
-}
-
-gfx::Size WmWindow::GetMinimumSize() const {
-  return window_->delegate() ? window_->delegate()->GetMinimumSize()
-                             : gfx::Size();
-}
-
-gfx::Size WmWindow::GetMaximumSize() const {
-  return window_->delegate() ? window_->delegate()->GetMaximumSize()
-                             : gfx::Size();
-}
-
-bool WmWindow::GetTargetVisibility() const {
-  return window_->TargetVisibility();
-}
-
-bool WmWindow::IsVisible() const {
-  return window_->IsVisible();
-}
-
-void WmWindow::SetOpacity(float opacity) {
-  window_->layer()->SetOpacity(opacity);
-}
-
-float WmWindow::GetTargetOpacity() const {
-  return window_->layer()->GetTargetOpacity();
-}
-
-gfx::Rect WmWindow::GetMinimizeAnimationTargetBoundsInScreen() const {
-  return ash::GetMinimizeAnimationTargetBoundsInScreen(window_);
-}
-
-void WmWindow::SetTransform(const gfx::Transform& transform) {
-  window_->SetTransform(transform);
-}
-
-gfx::Transform WmWindow::GetTargetTransform() const {
-  return window_->layer()->GetTargetTransform();
-}
-
-bool WmWindow::IsSystemModal() const {
-  return window_->GetProperty(aura::client::kModalKey) == ui::MODAL_TYPE_SYSTEM;
-}
-
-const wm::WindowState* WmWindow::GetWindowState() const {
-  return ash::wm::GetWindowState(window_);
-}
-
-WmWindow* WmWindow::GetToplevelWindow() {
-  return Get(window_->GetToplevelWindow());
-}
-
-WmWindow* WmWindow::GetToplevelWindowForFocus() {
-  return Get(::wm::GetToplevelWindow(window_));
-}
-
-void WmWindow::SetParentUsingContext(WmWindow* context,
-                                     const gfx::Rect& screen_bounds) {
-  aura::client::ParentWindowWithContext(window_, GetAuraWindow(context),
-                                        screen_bounds);
-}
-
-void WmWindow::AddChild(WmWindow* window) {
-  window_->AddChild(GetAuraWindow(window));
-}
-
-void WmWindow::RemoveChild(WmWindow* child) {
-  window_->RemoveChild(GetAuraWindow(child));
-}
-
-const WmWindow* WmWindow::GetParent() const {
-  return Get(window_->parent());
-}
-
-const WmWindow* WmWindow::GetTransientParent() const {
-  return Get(::wm::GetTransientParent(window_));
-}
-
-std::vector<WmWindow*> WmWindow::GetTransientChildren() {
-  return FromAuraWindows(::wm::GetTransientChildren(window_));
-}
-
-bool WmWindow::MoveToEventRoot(const ui::Event& event) {
-  return ash::wm::MoveWindowToEventRoot(window_, event);
-}
-
-void WmWindow::SetVisibilityChangesAnimated() {
-  ::wm::SetWindowVisibilityChangesAnimated(window_);
-}
-
-void WmWindow::SetVisibilityAnimationType(int type) {
-  ::wm::SetWindowVisibilityAnimationType(window_, type);
-}
-
-void WmWindow::SetVisibilityAnimationDuration(base::TimeDelta delta) {
-  ::wm::SetWindowVisibilityAnimationDuration(window_, delta);
-}
-
-void WmWindow::SetVisibilityAnimationTransition(
-    ::wm::WindowVisibilityAnimationTransition transition) {
-  ::wm::SetWindowVisibilityAnimationTransition(window_, transition);
-}
-
-void WmWindow::Animate(::wm::WindowAnimationType type) {
-  ::wm::AnimateWindow(window_, type);
-}
-
-void WmWindow::StopAnimatingProperty(
-    ui::LayerAnimationElement::AnimatableProperty property) {
-  window_->layer()->GetAnimator()->StopAnimatingProperty(property);
-}
-
-void WmWindow::SetChildWindowVisibilityChangesAnimated() {
-  ::wm::SetChildWindowVisibilityChangesAnimated(window_);
-}
-
-void WmWindow::SetMasksToBounds(bool value) {
-  window_->layer()->SetMasksToBounds(value);
-}
-
-void WmWindow::SetBounds(const gfx::Rect& bounds) {
-  window_->SetBounds(bounds);
-}
-
-void WmWindow::SetBoundsWithTransitionDelay(const gfx::Rect& bounds,
-                                            base::TimeDelta delta) {
-  if (::wm::WindowAnimationsDisabled(window_)) {
-    window_->SetBounds(bounds);
-    return;
-  }
-
-  ui::ScopedLayerAnimationSettings settings(window_->layer()->GetAnimator());
-  settings.SetTransitionDuration(delta);
-  window_->SetBounds(bounds);
-}
-
-void WmWindow::SetBoundsInScreen(const gfx::Rect& bounds_in_screen,
-                                 const display::Display& dst_display) {
-  window_->SetBoundsInScreen(bounds_in_screen, dst_display);
-}
-
-gfx::Rect WmWindow::GetBoundsInScreen() const {
-  return window_->GetBoundsInScreen();
-}
-
-const gfx::Rect& WmWindow::GetBounds() const {
-  return window_->bounds();
-}
-
-gfx::Rect WmWindow::GetTargetBounds() {
-  return window_->GetTargetBounds();
-}
-
-void WmWindow::ClearRestoreBounds() {
-  window_->ClearProperty(aura::client::kRestoreBoundsKey);
-  window_->ClearProperty(::wm::kVirtualKeyboardRestoreBoundsKey);
-}
-
-void WmWindow::SetRestoreBoundsInScreen(const gfx::Rect& bounds) {
-  window_->SetProperty(aura::client::kRestoreBoundsKey, new gfx::Rect(bounds));
-}
-
-gfx::Rect WmWindow::GetRestoreBoundsInScreen() const {
-  gfx::Rect* bounds = window_->GetProperty(aura::client::kRestoreBoundsKey);
-  return bounds ? *bounds : gfx::Rect();
-}
-
-bool WmWindow::Contains(const WmWindow* other) const {
-  return other ? window_->Contains(static_cast<const WmWindow*>(other)->window_)
-               : false;
-}
-
-void WmWindow::SetShowState(ui::WindowShowState show_state) {
-  window_->SetProperty(aura::client::kShowStateKey, show_state);
-}
-
-ui::WindowShowState WmWindow::GetShowState() const {
-  return window_->GetProperty(aura::client::kShowStateKey);
-}
-
-void WmWindow::SetPreFullscreenShowState(ui::WindowShowState show_state) {
-  // We should never store the ui::SHOW_STATE_MINIMIZED as the show state before
-  // fullscreen.
-  DCHECK_NE(show_state, ui::SHOW_STATE_MINIMIZED);
-  window_->SetProperty(aura::client::kPreFullscreenShowStateKey, show_state);
-}
-
-void WmWindow::SetLockedToRoot(bool value) {
-  window_->SetProperty(kLockedToRootKey, value);
-}
-
-bool WmWindow::IsLockedToRoot() const {
-  return window_->GetProperty(kLockedToRootKey);
-}
-
-void WmWindow::SetCapture() {
-  window_->SetCapture();
-}
-
-bool WmWindow::HasCapture() {
-  return window_->HasCapture();
-}
-
-void WmWindow::ReleaseCapture() {
-  window_->ReleaseCapture();
-}
-
-bool WmWindow::HasRestoreBounds() const {
-  return window_->GetProperty(aura::client::kRestoreBoundsKey) != nullptr;
-}
-
-bool WmWindow::CanMaximize() const {
-  return (window_->GetProperty(aura::client::kResizeBehaviorKey) &
-          ui::mojom::kResizeBehaviorCanMaximize) != 0;
-}
-
-bool WmWindow::CanMinimize() const {
-  return (window_->GetProperty(aura::client::kResizeBehaviorKey) &
-          ui::mojom::kResizeBehaviorCanMinimize) != 0;
-}
-
-bool WmWindow::CanResize() const {
-  return (window_->GetProperty(aura::client::kResizeBehaviorKey) &
-          ui::mojom::kResizeBehaviorCanResize) != 0;
-}
-
-bool WmWindow::CanActivate() const {
-  // TODO(sky): for aura-mus need to key off CanFocus() as well, which is not
-  // currently mirrored to ash.
-  return ::wm::CanActivateWindow(window_);
-}
-
-void WmWindow::StackChildAtTop(WmWindow* child) {
-  window_->StackChildAtTop(GetAuraWindow(child));
-}
-
-void WmWindow::StackChildAtBottom(WmWindow* child) {
-  window_->StackChildAtBottom(GetAuraWindow(child));
-}
-
-void WmWindow::StackChildAbove(WmWindow* child, WmWindow* target) {
-  window_->StackChildAbove(GetAuraWindow(child), GetAuraWindow(target));
-}
-
-void WmWindow::StackChildBelow(WmWindow* child, WmWindow* target) {
-  window_->StackChildBelow(GetAuraWindow(child), GetAuraWindow(target));
-}
-
-void WmWindow::SetAlwaysOnTop(bool value) {
-  window_->SetProperty(aura::client::kAlwaysOnTopKey, value);
-}
-
-bool WmWindow::IsAlwaysOnTop() const {
-  return window_->GetProperty(aura::client::kAlwaysOnTopKey);
-}
-
-void WmWindow::Hide() {
-  window_->Hide();
-}
-
-void WmWindow::Show() {
-  window_->Show();
-}
-
-void WmWindow::SetFocused() {
-  aura::client::GetFocusClient(window_)->FocusWindow(window_);
-}
-
-bool WmWindow::IsFocused() const {
-  return window_->HasFocus();
-}
-
-bool WmWindow::IsActive() const {
-  return wm::IsActiveWindow(window_);
-}
-
-void WmWindow::Activate() {
-  wm::ActivateWindow(window_);
-}
-
-void WmWindow::Deactivate() {
-  wm::DeactivateWindow(window_);
-}
-
-void WmWindow::SetFullscreen(bool fullscreen) {
-  ::wm::SetWindowFullscreen(window_, fullscreen);
-}
-
-void WmWindow::Maximize() {
-  window_->SetProperty(aura::client::kShowStateKey, ui::SHOW_STATE_MAXIMIZED);
-}
-
-void WmWindow::Minimize() {
-  window_->SetProperty(aura::client::kShowStateKey, ui::SHOW_STATE_MINIMIZED);
-}
-
-void WmWindow::Unminimize() {
-  window_->SetProperty(
-      aura::client::kShowStateKey,
-      window_->GetProperty(aura::client::kPreMinimizedShowStateKey));
-  window_->ClearProperty(aura::client::kPreMinimizedShowStateKey);
-}
-
-std::vector<WmWindow*> WmWindow::GetChildren() {
-  return FromAuraWindows(window_->children());
-}
-
-WmWindow* WmWindow::GetChildByShellWindowId(int id) {
-  return Get(window_->GetChildById(id));
-}
-
-void WmWindow::SetBoundsInScreenBehaviorForChildren(
-    BoundsInScreenBehavior behavior) {
-  window_->SetProperty(
-      kUsesScreenCoordinatesKey,
-      behavior == BoundsInScreenBehavior::USE_SCREEN_COORDINATES);
-}
-
-void WmWindow::SetSnapsChildrenToPhysicalPixelBoundary() {
-  wm::SetSnapsChildrenToPhysicalPixelBoundary(window_);
-}
-
-void WmWindow::SnapToPixelBoundaryIfNecessary() {
-  wm::SnapWindowToPixelBoundary(window_);
-}
-
-void WmWindow::AddTransientWindowObserver(WmTransientWindowObserver* observer) {
-  if (!added_transient_observer_) {
-    added_transient_observer_ = true;
-    ::wm::TransientWindowManager::Get(window_)->AddObserver(this);
-  }
-  transient_observers_.AddObserver(observer);
-}
-
-void WmWindow::RemoveTransientWindowObserver(
-    WmTransientWindowObserver* observer) {
-  transient_observers_.RemoveObserver(observer);
-  if (added_transient_observer_ &&
-      !transient_observers_.might_have_observers()) {
-    added_transient_observer_ = false;
-    ::wm::TransientWindowManager::Get(window_)->RemoveObserver(this);
-  }
-}
-
-WmWindow::WmWindow(aura::Window* window) : window_(window) {
-  window_->SetProperty(kWmWindowKey, this);
-}
-
-void WmWindow::OnTransientChildAdded(aura::Window* window,
-                                     aura::Window* transient) {
-  for (auto& observer : transient_observers_)
-    observer.OnTransientChildAdded(this, Get(transient));
-}
-
-void WmWindow::OnTransientChildRemoved(aura::Window* window,
-                                       aura::Window* transient) {
-  for (auto& observer : transient_observers_)
-    observer.OnTransientChildRemoved(this, Get(transient));
-}
-
-}  // namespace ash
diff --git a/ash/wm_window.h b/ash/wm_window.h
deleted file mode 100644
index decd178..0000000
--- a/ash/wm_window.h
+++ /dev/null
@@ -1,295 +0,0 @@
-// Copyright 2016 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef ASH_WM_WINDOW_H_
-#define ASH_WM_WINDOW_H_
-
-#include <memory>
-#include <vector>
-
-#include "ash/ash_export.h"
-#include "base/macros.h"
-#include "base/observer_list.h"
-#include "base/strings/string16.h"
-#include "base/time/time.h"
-#include "ui/aura/client/window_types.h"
-#include "ui/base/ui_base_types.h"
-#include "ui/compositor/layer_animation_element.h"
-#include "ui/wm/core/transient_window_observer.h"
-#include "ui/wm/core/window_animations.h"
-
-namespace display {
-class Display;
-}
-
-namespace gfx {
-class Point;
-class Rect;
-class Size;
-class Transform;
-}
-
-namespace ui {
-class Layer;
-}
-
-namespace ash {
-
-class RootWindowController;
-class WmTransientWindowObserver;
-enum class WmWindowProperty;
-
-namespace wm {
-class WindowState;
-}
-
-// WmWindow abstracts away differences between ash running in classic mode
-// and ash running with aura-mus.
-//
-// WmWindow is tied to the life of the underlying aura::Window. Use the
-// static Get() function to obtain a WmWindow from an aura::Window.
-class ASH_EXPORT WmWindow : public ::wm::TransientWindowObserver {
- public:
-  // See comments in SetBoundsInScreen().
-  enum class BoundsInScreenBehavior {
-    USE_LOCAL_COORDINATES,
-    USE_SCREEN_COORDINATES,
-  };
-
-  using Windows = std::vector<WmWindow*>;
-
-  // NOTE: this class is owned by the corresponding window. You shouldn't delete
-  // TODO(sky): friend deleter and make private.
-  ~WmWindow() override;
-
-  // Returns a WmWindow for an aura::Window, creating if necessary. |window| may
-  // be null, in which case null is returned.
-  static WmWindow* Get(aura::Window* window) {
-    return const_cast<WmWindow*>(Get(const_cast<const aura::Window*>(window)));
-  }
-  static const WmWindow* Get(const aura::Window* window);
-
-  static std::vector<WmWindow*> FromAuraWindows(
-      const std::vector<aura::Window*>& aura_windows);
-  static std::vector<aura::Window*> ToAuraWindows(
-      const std::vector<WmWindow*>& windows);
-
-  // Convenience for wm_window->aura_window(). Returns null if |wm_window| is
-  // null.
-  static aura::Window* GetAuraWindow(WmWindow* wm_window) {
-    return const_cast<aura::Window*>(
-        GetAuraWindow(const_cast<const WmWindow*>(wm_window)));
-  }
-  static const aura::Window* GetAuraWindow(const WmWindow* wm_window);
-
-  aura::Window* aura_window() { return window_; }
-  const aura::Window* aura_window() const { return window_; }
-
-  void Destroy();
-
-  WmWindow* GetRootWindow() {
-    return const_cast<WmWindow*>(
-        const_cast<const WmWindow*>(this)->GetRootWindow());
-  }
-  const WmWindow* GetRootWindow() const;
-  RootWindowController* GetRootWindowController();
-
-  // See shell_window_ids.h for list of known ids.
-  WmWindow* GetChildByShellWindowId(int id);
-
-  aura::client::WindowType GetType() const;
-  int GetAppType() const;
-  void SetAppType(int app_type) const;
-
-  ui::Layer* GetLayer();
-
-  // TODO(sky): these are temporary until GetLayer() always returns non-null.
-  bool GetLayerTargetVisibility();
-  bool GetLayerVisible();
-
-  display::Display GetDisplayNearestWindow();
-
-  bool HasNonClientArea();
-  int GetNonClientComponent(const gfx::Point& location);
-  gfx::Point ConvertPointToTarget(const WmWindow* target,
-                                  const gfx::Point& point) const;
-
-  gfx::Point ConvertPointToScreen(const gfx::Point& point) const;
-  gfx::Point ConvertPointFromScreen(const gfx::Point& point) const;
-  gfx::Rect ConvertRectToScreen(const gfx::Rect& rect) const;
-  gfx::Rect ConvertRectFromScreen(const gfx::Rect& rect) const;
-
-  gfx::Size GetMinimumSize() const;
-  gfx::Size GetMaximumSize() const;
-
-  // Returns the visibility requested by this window. IsVisible() takes into
-  // account the visibility of the layer and ancestors, where as this tracks
-  // whether Show() without a Hide() has been invoked.
-  bool GetTargetVisibility() const;
-
-  bool IsVisible() const;
-
-  void SetOpacity(float opacity);
-  float GetTargetOpacity() const;
-
-  gfx::Rect GetMinimizeAnimationTargetBoundsInScreen() const;
-
-  void SetTransform(const gfx::Transform& transform);
-  gfx::Transform GetTargetTransform() const;
-
-  bool IsSystemModal() const;
-
-  wm::WindowState* GetWindowState() {
-    return const_cast<wm::WindowState*>(
-        const_cast<const WmWindow*>(this)->GetWindowState());
-  }
-  const wm::WindowState* GetWindowState() const;
-
-  // The implementation of this matches aura::Window::GetToplevelWindow().
-  WmWindow* GetToplevelWindow();
-
-  // The implementation of this matches
-  // wm::ActivationClient::GetToplevelWindow().
-  WmWindow* GetToplevelWindowForFocus();
-
-  // See aura::client::ParentWindowWithContext() for details of what this does.
-  void SetParentUsingContext(WmWindow* context, const gfx::Rect& screen_bounds);
-  void AddChild(WmWindow* window);
-  void RemoveChild(WmWindow* child);
-
-  WmWindow* GetParent() {
-    return const_cast<WmWindow*>(
-        const_cast<const WmWindow*>(this)->GetParent());
-  }
-  const WmWindow* GetParent() const;
-
-  WmWindow* GetTransientParent() {
-    return const_cast<WmWindow*>(
-        const_cast<const WmWindow*>(this)->GetTransientParent());
-  }
-  const WmWindow* GetTransientParent() const;
-  std::vector<WmWindow*> GetTransientChildren();
-
-  // Moves this to the display where |event| occurred; returns true if moved.
-  bool MoveToEventRoot(const ui::Event& event);
-
-  // See wm::SetWindowVisibilityChangesAnimated() for details on what this
-  // does.
-  void SetVisibilityChangesAnimated();
-  // |type| is WindowVisibilityAnimationType. Has to be an int to match aura.
-  void SetVisibilityAnimationType(int type);
-  void SetVisibilityAnimationDuration(base::TimeDelta delta);
-  void SetVisibilityAnimationTransition(
-      ::wm::WindowVisibilityAnimationTransition transition);
-  void Animate(::wm::WindowAnimationType type);
-  void StopAnimatingProperty(
-      ui::LayerAnimationElement::AnimatableProperty property);
-  void SetChildWindowVisibilityChangesAnimated();
-
-  // See description in ui::Layer.
-  void SetMasksToBounds(bool value);
-  void SetBounds(const gfx::Rect& bounds);
-  void SetBoundsWithTransitionDelay(const gfx::Rect& bounds,
-                                    base::TimeDelta delta);
-
-  // Sets the bounds in two distinct ways. The exact behavior is dictated by
-  // the value of BoundsInScreenBehavior set on the parent:
-  //
-  // USE_LOCAL_COORDINATES: the bounds are applied as is to the window. In other
-  //   words this behaves the same as if SetBounds(bounds_in_screen) was used.
-  //   This is the default.
-  // USE_SCREEN_COORDINATES: the bounds are actual screen bounds and converted
-  //   from the display. In this case the window may move to a different
-  //   display if allowed (see SetLockedToRoot()).
-  void SetBoundsInScreen(const gfx::Rect& bounds_in_screen,
-                         const display::Display& dst_display);
-  gfx::Rect GetBoundsInScreen() const;
-  const gfx::Rect& GetBounds() const;
-  gfx::Rect GetTargetBounds();
-  void ClearRestoreBounds();
-  void SetRestoreBoundsInScreen(const gfx::Rect& bounds);
-  gfx::Rect GetRestoreBoundsInScreen() const;
-
-  bool Contains(const WmWindow* other) const;
-
-  void SetShowState(ui::WindowShowState show_state);
-  ui::WindowShowState GetShowState() const;
-
-  void SetPreFullscreenShowState(ui::WindowShowState show_state);
-
-  // If |value| is true the window can not be moved to another root, regardless
-  // of the bounds set on it.
-  void SetLockedToRoot(bool value);
-  bool IsLockedToRoot() const;
-
-  void SetCapture();
-  bool HasCapture();
-  void ReleaseCapture();
-
-  bool HasRestoreBounds() const;
-  bool CanMaximize() const;
-  bool CanMinimize() const;
-  bool CanResize() const;
-  bool CanActivate() const;
-
-  void StackChildAtTop(WmWindow* child);
-  void StackChildAtBottom(WmWindow* child);
-  void StackChildAbove(WmWindow* child, WmWindow* target);
-  void StackChildBelow(WmWindow* child, WmWindow* target);
-
-  void SetAlwaysOnTop(bool value);
-  bool IsAlwaysOnTop() const;
-
-  void Hide();
-  void Show();
-
-  void SetFocused();
-  bool IsFocused() const;
-
-  bool IsActive() const;
-  void Activate();
-  void Deactivate();
-
-  void SetFullscreen(bool fullscreen);
-
-  void Maximize();
-  void Minimize();
-  void Unminimize();
-
-  std::vector<WmWindow*> GetChildren();
-
-  // See description in SetBoundsInScreen().
-  void SetBoundsInScreenBehaviorForChildren(BoundsInScreenBehavior behavior);
-
-  // See description of SnapToPixelBoundaryIfNecessary().
-  void SetSnapsChildrenToPhysicalPixelBoundary();
-
-  // If an ancestor has been set to snap children to pixel boundaries, then
-  // snaps the layer associated with this window to the layer associated with
-  // the ancestor.
-  void SnapToPixelBoundaryIfNecessary();
-
-  void AddTransientWindowObserver(WmTransientWindowObserver* observer);
-  void RemoveTransientWindowObserver(WmTransientWindowObserver* observer);
-
- private:
-  explicit WmWindow(aura::Window* window);
-
-  // ::wm::TransientWindowObserver overrides:
-  void OnTransientChildAdded(aura::Window* window,
-                             aura::Window* transient) override;
-  void OnTransientChildRemoved(aura::Window* window,
-                               aura::Window* transient) override;
-
-  aura::Window* window_;
-
-  bool added_transient_observer_ = false;
-  base::ObserverList<WmTransientWindowObserver> transient_observers_;
-
-  DISALLOW_COPY_AND_ASSIGN(WmWindow);
-};
-
-}  // namespace ash
-
-#endif  // ASH_WM_WINDOW_H_
diff --git a/build/fuchsia/create_test_runner_script.py b/build/fuchsia/create_test_runner_script.py
index d6e067b..c85e7ce 100755
--- a/build/fuchsia/create_test_runner_script.py
+++ b/build/fuchsia/create_test_runner_script.py
@@ -10,14 +10,37 @@
 
 import argparse
 import os
-import pipes
 import re
 import sys
 
 
 SCRIPT_TEMPLATE = """\
-#!/bin/sh
-exec {test_runner_path} {test_runner_args} "$@"
+#!/usr/bin/env python
+#
+# This file was generated by build/fuchsia/create_test_runner_script.py
+
+import os
+import sys
+
+def main():
+  script_directory = os.path.dirname(__file__)
+
+  def ResolvePath(path):
+    \"\"\"Returns an absolute filepath given a path relative to this script.
+    \"\"\"
+    return os.path.abspath(os.path.join(script_directory, path))
+
+  test_runner_path = ResolvePath('{test_runner_path}')
+  test_runner_args = {test_runner_args}
+  test_runner_path_args = {test_runner_path_args}
+  for arg, path in test_runner_path_args:
+    test_runner_args.extend([arg, ResolvePath(path)])
+
+  os.execv(test_runner_path,
+           [test_runner_path] + test_runner_args + sys.argv[1:])
+
+if __name__ == '__main__':
+  sys.exit(main())
 """
 
 
@@ -55,27 +78,30 @@
   group.add_argument('--test-name')
   args, test_runner_args = parser.parse_known_args(args)
 
-  def ResolvePath(path):
-    return os.path.abspath(os.path.join(
-        os.path.dirname(args.script_output_path), '..', path))
+  def RelativizePathToScript(path):
+    """Returns the path relative to the output script directory."""
+    return os.path.relpath(path, os.path.dirname(args.script_output_path))
 
   test_runner_path = args.test_runner_path or os.path.join(
       os.path.dirname(__file__), 'test_runner.py')
-  test_runner_path = ResolvePath(test_runner_path)
+  test_runner_path = RelativizePathToScript(test_runner_path)
 
+  test_runner_path_args = []
   if args.output_directory:
-    test_runner_args.extend(
-        ['--output-directory', ResolvePath(args.output_directory)])
+    test_runner_path_args.append(
+        ('--output-directory', RelativizePathToScript(args.output_directory)))
   if args.runtime_deps_path:
-    test_runner_args.extend(
-        ['--runtime-deps-path', ResolvePath(args.runtime_deps_path)])
+    test_runner_path_args.append(
+        ('--runtime-deps-path', RelativizePathToScript(args.runtime_deps_path)))
   if args.test_name:
-    test_runner_args.extend(['--test-name', args.test_name])
+    test_runner_path_args.append(
+        ('--test-name', RelativizePathToScript(args.test_name)))
 
   with open(args.script_output_path, 'w') as script:
     script.write(SCRIPT_TEMPLATE.format(
-        test_runner_path=test_runner_path,
-        test_runner_args=' '.join(pipes.quote(x) for x in test_runner_args)))
+        test_runner_path=str(test_runner_path),
+        test_runner_args=str(test_runner_args),
+        test_runner_path_args=str(test_runner_path_args)))
 
   os.chmod(args.script_output_path, 0750)
 
diff --git a/build/fuchsia/test_runner.py b/build/fuchsia/test_runner.py
index d79fdae..8df94d23 100755
--- a/build/fuchsia/test_runner.py
+++ b/build/fuchsia/test_runner.py
@@ -4,15 +4,198 @@
 # Use of this source code is governed by a BSD-style license that can be
 # found in the LICENSE file.
 
-"""Stub for script that will run a Fuchsia binary on QEMU or hardware."""
+"""Packages a user.bootfs for a Fuchsia QEMU image, pulling in the runtime
+dependencies of a test binary, and then uses QEMU from the Fuchsia SDK to run
+it. Does not yet implement running on real hardware, or symbolization of
+crashes."""
 
+import argparse
+import os
+import subprocess
 import sys
+import tempfile
+
+
+DIR_SOURCE_ROOT = os.path.abspath(
+    os.path.join(os.path.dirname(__file__), os.pardir, os.pardir))
+SDK_ROOT = os.path.join(DIR_SOURCE_ROOT, 'third_party', 'fuchsia-sdk')
+
+
+def RunAndCheck(dry_run, args):
+  if dry_run:
+    print 'Run:', args
+  else:
+    subprocess.check_call(args)
+
+
+def DumpFile(dry_run, name, description):
+  """Prints out the contents of |name| if |dry_run|."""
+  if not dry_run:
+    return
+  print
+  print 'Contents of %s (for %s)' % (name, description)
+  print '-' * 80
+  with open(name) as f:
+    sys.stdout.write(f.read())
+  print '-' * 80
+
+
+def MakeTargetImageName(common_prefix, output_directory, location):
+  """Generates the relative path name to be used in the file system image.
+  common_prefix: a prefix of both output_directory and location that
+                 be removed.
+  output_directory: an optional prefix on location that will also be removed.
+  location: the file path to relativize.
+
+  Examples:
+
+  >>> MakeTargetImageName(common_prefix='/work/cr/src/',
+  ...                     output_directory='/work/cr/src/out/fuch',
+  ...                     location='/work/cr/src/base/test/data/xyz.json')
+  'base/test/data/xyz.json'
+
+  >>> MakeTargetImageName(common_prefix='/work/cr/src/',
+  ...                     output_directory='/work/cr/src/out/fuch',
+  ...                     location='/work/cr/src/out/fuch/icudtl.dat')
+  'icudtl.dat'
+  """
+  assert output_directory.startswith(common_prefix)
+  output_dir_no_common_prefix = output_directory[len(common_prefix):]
+  assert location.startswith(common_prefix)
+  loc = location[len(common_prefix):]
+  if loc.startswith(output_dir_no_common_prefix):
+    loc = loc[len(output_dir_no_common_prefix)+1:]
+  return loc
+
+
+def AddToManifest(manifest_file, target_name, source, mapper):
+  """Appends |source| to the given |manifest_file| (a file object) in a format
+  suitable for consumption by mkbootfs.
+
+  If |source| is a file it's directly added. If |source| is a directory, its
+  contents are recursively added.
+
+  |source| must exist on disk at the time this function is called.
+  """
+  if os.path.isdir(source):
+    files = [os.path.join(dp, f) for dp, dn, fn in os.walk(source) for f in fn]
+    for f in files:
+      # We pass None as the mapper because this should never recurse a 2nd time.
+      AddToManifest(manifest_file, mapper(f), f, None)
+  elif os.path.exists(source):
+    manifest_file.write('%s=%s\n' % (target_name, source))
+  else:
+    raise Exception('%s does not exist' % source)
+
+
+def BuildBootfs(output_directory, runtime_deps_path, test_name, gtest_filter,
+                dry_run):
+  with open(runtime_deps_path) as f:
+    lines = f.readlines()
+
+  locations_to_add = [os.path.abspath(os.path.join(output_directory, x.strip()))
+                      for x in lines]
+  locations_to_add.append(
+      os.path.abspath(os.path.join(output_directory, test_name)))
+
+  common_prefix = os.path.commonprefix(locations_to_add)
+  target_source_pairs = zip(
+      [MakeTargetImageName(common_prefix, output_directory, loc)
+       for loc in locations_to_add],
+      locations_to_add)
+
+  # Add extra .so's that are required for running to system/lib
+  sysroot_libs = [
+    'libc++abi.so.1',
+    'libc++.so.2',
+    'libunwind.so.1',
+  ]
+  sysroot_lib_path = os.path.join(SDK_ROOT, 'sysroot', 'x86_64-fuchsia', 'lib')
+  for lib in sysroot_libs:
+    target_source_pairs.append(
+        ('lib/' + lib, os.path.join(sysroot_lib_path, lib)))
+
+  # Generate a little script that runs the test binaries and then shuts down
+  # QEMU.
+  autorun_file = tempfile.NamedTemporaryFile()
+  autorun_file.write('#!/bin/sh\n')
+  autorun_file.write('/system/' + os.path.basename(test_name))
+  autorun_file.write(' --test-launcher-retry-limit=0')
+  if gtest_filter:
+    autorun_file.write(' --gtest_filter=' + gtest_filter)
+  autorun_file.write('\n')
+  autorun_file.write('dm poweroff\n')
+  autorun_file.flush()
+  os.chmod(autorun_file.name, 0750)
+  DumpFile(dry_run, autorun_file.name, 'autorun')
+  target_source_pairs.append(('autorun', autorun_file.name))
+
+  # Generate an initial.config for application_manager that tells it to run
+  # our autorun script with sh.
+  initial_config_file = tempfile.NamedTemporaryFile()
+  initial_config_file.write('''{
+  "initial-apps": [
+    [ "file:///boot/bin/sh", "/system/autorun" ]
+  ]
+}
+''')
+  initial_config_file.flush()
+  DumpFile(dry_run, initial_config_file.name, 'initial.config')
+  target_source_pairs.append(('data/application_manager/initial.config',
+                              initial_config_file.name))
+
+  manifest_file = tempfile.NamedTemporaryFile()
+  bootfs_name = runtime_deps_path + '.bootfs'
+
+  for target, source in target_source_pairs:
+    AddToManifest(manifest_file.file, target, source,
+                  lambda x: MakeTargetImageName(
+                                common_prefix, output_directory, x))
+
+  mkbootfs_path = os.path.join(SDK_ROOT, 'tools', 'mkbootfs')
+
+  manifest_file.flush()
+  DumpFile(dry_run, manifest_file.name, 'manifest')
+  RunAndCheck(dry_run,
+              [mkbootfs_path, '-o', bootfs_name,
+               '--target=boot', os.path.join(SDK_ROOT, 'bootdata.bin'),
+               '--target=system', manifest_file.name,
+              ])
+  print 'Wrote bootfs to', bootfs_name
+  return bootfs_name
 
 
 def main():
-  print sys.argv
-  print 'TODO(fuchsia): Implement test runner. https://crbug.com/706592.'
-  return 1
+  parser = argparse.ArgumentParser()
+  parser.add_argument('--dry-run', '-n', action='store_true', default=False,
+                      help="Just print commands, don't execute them.")
+  parser.add_argument('--output-directory',
+                      type=os.path.realpath,
+                      help=('Path to the directory in which build files are'
+                            ' located (must include build type).'))
+  parser.add_argument('--runtime-deps-path',
+                      type=os.path.realpath,
+                      help='Runtime data dependency file from GN.')
+  parser.add_argument('--test-name',
+                      type=os.path.realpath,
+                      help='Name of the the test')
+  parser.add_argument('--gtest_filter',
+                      help='GTest filter to use in place of any default')
+  args = parser.parse_args()
+
+  bootfs = BuildBootfs(args.output_directory, args.runtime_deps_path,
+                       args.test_name, args.gtest_filter, args.dry_run)
+
+  qemu_path = os.path.join(SDK_ROOT, 'qemu', 'bin', 'qemu-system-x86_64')
+
+  RunAndCheck(args.dry_run,
+      [qemu_path, '-m', '2048', '-nographic', '-net', 'none', '-smp', '4',
+       '-machine', 'q35', '-kernel',
+       os.path.join(SDK_ROOT, 'kernel', 'magenta.bin'),
+       '-cpu', 'Haswell,+smap,-check', '-initrd', bootfs,
+       '-append', 'TERM=xterm-256color'])
+
+  return 0
 
 
 if __name__ == '__main__':
diff --git a/cc/output/renderer_settings.cc b/cc/output/renderer_settings.cc
index acfc693..1f4f821 100644
--- a/cc/output/renderer_settings.cc
+++ b/cc/output/renderer_settings.cc
@@ -4,15 +4,9 @@
 
 #include "cc/output/renderer_settings.h"
 
-#include <limits>
-
-#include "base/logging.h"
-#include "cc/resources/platform_color.h"
-
 namespace cc {
 
-RendererSettings::RendererSettings()
-    : preferred_tile_format(PlatformColor::BestTextureFormat()) {}
+RendererSettings::RendererSettings() = default;
 
 RendererSettings::RendererSettings(const RendererSettings& other) = default;
 
diff --git a/cc/output/renderer_settings.h b/cc/output/renderer_settings.h
index 913aa2d..9dcdec0 100644
--- a/cc/output/renderer_settings.h
+++ b/cc/output/renderer_settings.h
@@ -9,7 +9,6 @@
 
 #include "cc/cc_export.h"
 #include "cc/output/buffer_to_texture_target_map.h"
-#include "cc/resources/resource_format.h"
 
 namespace cc {
 
@@ -34,7 +33,6 @@
   int highp_threshold_min = 0;
   size_t texture_id_allocation_chunk_size = 64;
   bool use_gpu_memory_buffer_resources = false;
-  ResourceFormat preferred_tile_format;
   BufferToTextureTargetMap buffer_to_texture_target_map;
 
   // Determines whether we disallow non-exact matches when finding resources
diff --git a/cc/trees/layer_tree_host_impl.cc b/cc/trees/layer_tree_host_impl.cc
index 75acee7..fbe68d2 100644
--- a/cc/trees/layer_tree_host_impl.cc
+++ b/cc/trees/layer_tree_host_impl.cc
@@ -2243,12 +2243,12 @@
   if (use_gpu_rasterization_) {
     image_decode_cache_ = base::MakeUnique<GpuImageDecodeCache>(
         compositor_frame_sink_->worker_context_provider(),
-        settings_.renderer_settings.preferred_tile_format,
+        settings_.preferred_tile_format,
         settings_.decoded_image_working_set_budget_bytes,
         settings_.decoded_image_cache_budget_bytes);
   } else {
     image_decode_cache_ = base::MakeUnique<SoftwareImageDecodeCache>(
-        settings_.renderer_settings.preferred_tile_format,
+        settings_.preferred_tile_format,
         settings_.decoded_image_working_set_budget_bytes);
   }
 
@@ -2310,7 +2310,7 @@
     *raster_buffer_provider = base::MakeUnique<GpuRasterBufferProvider>(
         compositor_context_provider, worker_context_provider,
         resource_provider_.get(), settings_.use_distance_field_text,
-        msaa_sample_count, settings_.renderer_settings.preferred_tile_format,
+        msaa_sample_count, settings_.preferred_tile_format,
         settings_.async_worker_context_enabled);
     return;
   }
@@ -2332,8 +2332,7 @@
         settings_.disallow_non_exact_resource_reuse);
 
     *raster_buffer_provider = ZeroCopyRasterBufferProvider::Create(
-        resource_provider_.get(),
-        settings_.renderer_settings.preferred_tile_format);
+        resource_provider_.get(), settings_.preferred_tile_format);
     return;
   }
 
@@ -2351,8 +2350,7 @@
       GetTaskRunner(), compositor_context_provider, worker_context_provider,
       resource_provider_.get(), max_copy_texture_chromium_size,
       settings_.use_partial_raster, settings_.max_staging_buffer_usage_in_bytes,
-      settings_.renderer_settings.preferred_tile_format,
-      settings_.async_worker_context_enabled);
+      settings_.preferred_tile_format, settings_.async_worker_context_enabled);
 }
 
 void LayerTreeHostImpl::SetLayerTreeMutator(
diff --git a/cc/trees/layer_tree_settings.cc b/cc/trees/layer_tree_settings.cc
index 2b8531c9..b11b107 100644
--- a/cc/trees/layer_tree_settings.cc
+++ b/cc/trees/layer_tree_settings.cc
@@ -4,6 +4,7 @@
 
 #include "cc/trees/layer_tree_settings.h"
 
+#include "cc/resources/platform_color.h"
 #include "third_party/khronos/GLES2/gl2.h"
 
 namespace cc {
@@ -17,7 +18,8 @@
                         ManagedMemoryPolicy::kDefaultNumResourcesLimit),
       software_memory_policy(128 * 1024 * 1024,
                              gpu::MemoryAllocation::CUTOFF_ALLOW_NICE_TO_HAVE,
-                             ManagedMemoryPolicy::kDefaultNumResourcesLimit) {}
+                             ManagedMemoryPolicy::kDefaultNumResourcesLimit),
+      preferred_tile_format(PlatformColor::BestTextureFormat()) {}
 
 LayerTreeSettings::LayerTreeSettings(const LayerTreeSettings& other) = default;
 LayerTreeSettings::~LayerTreeSettings() = default;
diff --git a/cc/trees/layer_tree_settings.h b/cc/trees/layer_tree_settings.h
index 9320c84..63eb99f 100644
--- a/cc/trees/layer_tree_settings.h
+++ b/cc/trees/layer_tree_settings.h
@@ -14,6 +14,7 @@
 #include "cc/debug/layer_tree_debug_state.h"
 #include "cc/output/managed_memory_policy.h"
 #include "cc/output/renderer_settings.h"
+#include "cc/resources/resource_format.h"
 #include "cc/scheduler/scheduler_settings.h"
 #include "cc/tiles/tile_manager_settings.h"
 #include "third_party/skia/include/core/SkColor.h"
@@ -87,6 +88,7 @@
   size_t decoded_image_working_set_budget_bytes = 128 * 1024 * 1024;
   int max_preraster_distance_in_screen_pixels = 1000;
   BufferToTextureTargetMap buffer_to_texture_target_map;
+  ResourceFormat preferred_tile_format;
 
   bool enable_color_correct_rasterization = false;
 
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/omnibox/LocationBarLayout.java b/chrome/android/java/src/org/chromium/chrome/browser/omnibox/LocationBarLayout.java
index 65cac29..efa3c8dc 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/omnibox/LocationBarLayout.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/omnibox/LocationBarLayout.java
@@ -1153,16 +1153,11 @@
                     mRequestSuggestions = null;
 
                     if (getCurrentTab() == null
-                            && (mBottomSheet == null || mToolbarDataProvider.isIncognito())) {
+                            && (mBottomSheet == null || !mBottomSheet.isShowingNewTab())) {
                         return;
                     }
 
-                    // If the bottom sheet is not null, the current tab will be null when the
-                    // NTP UI is showing. Use the original profile rather than the tab profile
-                    // in that scenario.
-                    Profile profile = getCurrentTab() != null
-                            ? getCurrentTab().getProfile()
-                            : Profile.getLastUsedProfile().getOriginalProfile();
+                    Profile profile = getToolbarDataProvider().getProfile();
                     String url = getCurrentTab() != null ? getCurrentTab().getUrl()
                                                          : UrlConstants.NTP_URL;
                     mAutocomplete.start(profile, url, textWithoutAutocomplete, preventAutocomplete);
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/permissions/OWNERS b/chrome/android/java/src/org/chromium/chrome/browser/permissions/OWNERS
new file mode 100644
index 0000000..05c118d
--- /dev/null
+++ b/chrome/android/java/src/org/chromium/chrome/browser/permissions/OWNERS
@@ -0,0 +1,3 @@
+dominickn@chromium.org
+
+# COMPONENT: UI>Browser>Permissions>Prompts
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/preferences/datareduction/DataReductionMainMenuFooter.java b/chrome/android/java/src/org/chromium/chrome/browser/preferences/datareduction/DataReductionMainMenuFooter.java
index 20eea20..e893b40 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/preferences/datareduction/DataReductionMainMenuFooter.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/preferences/datareduction/DataReductionMainMenuFooter.java
@@ -22,8 +22,12 @@
 import org.chromium.base.ApiCompatibilityUtils;
 import org.chromium.base.metrics.RecordUserAction;
 import org.chromium.chrome.R;
+import org.chromium.chrome.browser.feature_engagement_tracker.FeatureEngagementTrackerFactory;
 import org.chromium.chrome.browser.net.spdyproxy.DataReductionProxySettings;
 import org.chromium.chrome.browser.preferences.PreferencesLauncher;
+import org.chromium.chrome.browser.profiles.Profile;
+import org.chromium.components.feature_engagement_tracker.EventConstants;
+import org.chromium.components.feature_engagement_tracker.FeatureEngagementTracker;
 import org.chromium.third_party.android.datausagechart.ChartDataUsageView;
 
 /**
@@ -104,5 +108,10 @@
         RecordUserAction.record("MobileMenuDataSaverOpened");
         intent.putExtra(DataReductionPreferences.FROM_MAIN_MENU, true);
         getContext().startActivity(intent);
+
+        FeatureEngagementTracker tracker =
+                FeatureEngagementTrackerFactory.getFeatureEngagementTrackerForProfile(
+                        Profile.getLastUsedProfile());
+        tracker.notifyEvent(EventConstants.DATA_SAVER_DETAIL_OPENED);
     }
 }
\ No newline at end of file
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/tab/Tab.java b/chrome/android/java/src/org/chromium/chrome/browser/tab/Tab.java
index 8596a0ec..7369e2a7 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/tab/Tab.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/tab/Tab.java
@@ -59,10 +59,12 @@
 import org.chromium.chrome.browser.customtabs.CustomTabActivity;
 import org.chromium.chrome.browser.document.ChromeLauncherActivity;
 import org.chromium.chrome.browser.download.ChromeDownloadDelegate;
+import org.chromium.chrome.browser.feature_engagement_tracker.FeatureEngagementTrackerFactory;
 import org.chromium.chrome.browser.fullscreen.FullscreenManager;
 import org.chromium.chrome.browser.help.HelpAndFeedback;
 import org.chromium.chrome.browser.infobar.InfoBarContainer;
 import org.chromium.chrome.browser.media.ui.MediaSessionTabHelper;
+import org.chromium.chrome.browser.net.spdyproxy.DataReductionProxySettings;
 import org.chromium.chrome.browser.ntp.NativePageAssassin;
 import org.chromium.chrome.browser.ntp.NativePageFactory;
 import org.chromium.chrome.browser.offlinepages.OfflinePageUtils;
@@ -84,6 +86,8 @@
 import org.chromium.chrome.browser.util.ColorUtils;
 import org.chromium.chrome.browser.util.FeatureUtilities;
 import org.chromium.components.dom_distiller.core.DomDistillerUrlUtils;
+import org.chromium.components.feature_engagement_tracker.EventConstants;
+import org.chromium.components.feature_engagement_tracker.FeatureEngagementTracker;
 import org.chromium.components.navigation_interception.InterceptNavigationDelegate;
 import org.chromium.components.security_state.ConnectionSecurityLevel;
 import org.chromium.components.sync.SyncConstants;
@@ -360,6 +364,15 @@
      */
     private int mSadTabSuccessiveRefreshCounter;
 
+    /**
+     * Stores total data saved at the start of a page load. Used to calculate delta at the end of
+     * page load, which is just an estimate of the data saved for the current page load since there
+     * may be multiple pages loading at the same time. This estimate is used to get an idea of how
+     * widely used the data saver feature is for a particular user at a time (i.e. not since the
+     * user started using Chrome).
+     */
+    private long mDataSavedOnStartPageLoad;
+
     private final int mDefaultThemeColor;
     private int mThemeColor;
 
@@ -1498,6 +1511,9 @@
         updateTitle();
         removeSadTabIfPresent();
 
+        mDataSavedOnStartPageLoad =
+                DataReductionProxySettings.getInstance().getContentLengthSavedInHistorySummary();
+
         if (mIsRendererUnresponsive) handleRendererResponsive();
 
         if (mTabUma != null) mTabUma.onPageLoadStarted();
@@ -1524,6 +1540,17 @@
 
         for (TabObserver observer : mObservers) observer.onPageLoadFinished(this);
         mIsBeingRestored = false;
+
+        long dataSaved =
+                DataReductionProxySettings.getInstance().getContentLengthSavedInHistorySummary()
+                - mDataSavedOnStartPageLoad;
+
+        if (dataSaved > 0) {
+            FeatureEngagementTracker tracker =
+                    FeatureEngagementTrackerFactory.getFeatureEngagementTrackerForProfile(
+                            Profile.getLastUsedProfile());
+            tracker.notifyEvent(EventConstants.DATA_SAVED_ON_PAGE_LOAD);
+        }
     }
 
     /**
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/toolbar/ToolbarManager.java b/chrome/android/java/src/org/chromium/chrome/browser/toolbar/ToolbarManager.java
index adfe894..d6d4e143b 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/toolbar/ToolbarManager.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/toolbar/ToolbarManager.java
@@ -49,6 +49,7 @@
 import org.chromium.chrome.browser.feature_engagement_tracker.FeatureEngagementTrackerFactory;
 import org.chromium.chrome.browser.fullscreen.BrowserStateBrowserControlsVisibilityDelegate;
 import org.chromium.chrome.browser.fullscreen.FullscreenManager;
+import org.chromium.chrome.browser.net.spdyproxy.DataReductionProxySettings;
 import org.chromium.chrome.browser.ntp.IncognitoNewTabPage;
 import org.chromium.chrome.browser.ntp.NativePageFactory;
 import org.chromium.chrome.browser.ntp.NewTabPage;
@@ -938,6 +939,13 @@
             public void run() {
                 RecordUserAction.record("MobileToolbarShowMenu");
                 mToolbar.onMenuShown();
+
+                if (DataReductionProxySettings.getInstance().isDataReductionProxyEnabled()) {
+                    FeatureEngagementTracker tracker =
+                            FeatureEngagementTrackerFactory.getFeatureEngagementTrackerForProfile(
+                                    Profile.getLastUsedProfile());
+                    tracker.notifyEvent(EventConstants.OVERFLOW_OPENED_WITH_DATA_SAVER_SHOWN);
+                }
             }
         });
     }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/vr_shell/VrShellImpl.java b/chrome/android/java/src/org/chromium/chrome/browser/vr_shell/VrShellImpl.java
index 8bcd63c..9ed4e76 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/vr_shell/VrShellImpl.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/vr_shell/VrShellImpl.java
@@ -287,13 +287,7 @@
                 inCct, getGvrApi().getNativeGvrContext(), mReprojectedRendering);
 
         // Set the UI and content sizes before we load the UI.
-        if (forWebVr) {
-            DisplayAndroid primaryDisplay = DisplayAndroid.getNonMultiDisplay(mActivity);
-            setContentCssSize(
-                    primaryDisplay.getDisplayWidth(), primaryDisplay.getDisplayHeight(), WEBVR_DPR);
-        } else {
-            setContentCssSize(DEFAULT_CONTENT_WIDTH, DEFAULT_CONTENT_HEIGHT, DEFAULT_DPR);
-        }
+        updateWebVrDisplaySize(forWebVr);
 
         swapToForegroundTab();
         createTabList();
@@ -487,6 +481,18 @@
     public void setWebVrModeEnabled(boolean enabled) {
         mContentVrWindowAndroid.setVSyncPaused(enabled);
         nativeSetWebVrMode(mNativeVrShell, enabled);
+
+        updateWebVrDisplaySize(enabled);
+    }
+
+    private void updateWebVrDisplaySize(boolean inWebVr) {
+        if (inWebVr) {
+            DisplayAndroid primaryDisplay = DisplayAndroid.getNonMultiDisplay(mActivity);
+            setContentCssSize(
+                    primaryDisplay.getDisplayWidth(), primaryDisplay.getDisplayHeight(), WEBVR_DPR);
+        } else {
+            setContentCssSize(DEFAULT_CONTENT_WIDTH, DEFAULT_CONTENT_HEIGHT, DEFAULT_DPR);
+        }
     }
 
     @Override
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/widget/bottomsheet/BottomSheet.java b/chrome/android/java/src/org/chromium/chrome/browser/widget/bottomsheet/BottomSheet.java
index d2072780a..858f570 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/widget/bottomsheet/BottomSheet.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/widget/bottomsheet/BottomSheet.java
@@ -326,22 +326,15 @@
             // Allow the bottom sheet's content to be scrolled up without dragging the sheet down.
             if (!isTouchEventInToolbar(e2) && isSheetInMaxPosition && mSheetContent != null
                     && mSheetContent.getVerticalScrollOffset() > 0) {
-                mIsScrolling = false;
                 return false;
             }
 
             // If the sheet is in the max position, don't move the sheet if the scroll is upward.
             // Instead, allow the sheet's content to handle it if it needs to.
-            if (isSheetInMaxPosition && distanceY > 0) {
-                mIsScrolling = false;
-                return false;
-            }
+            if (isSheetInMaxPosition && distanceY > 0) return false;
 
             // Similarly, if the sheet is in the min position, don't move if the scroll is downward.
-            if (currentShownRatio <= getPeekRatio() && distanceY < 0) {
-                mIsScrolling = false;
-                return false;
-            }
+            if (currentShownRatio <= getPeekRatio() && distanceY < 0) return false;
 
             float newOffset = getSheetOffsetFromBottom() + distanceY;
             boolean wasOpenBeforeSwipe = mIsSheetOpen;
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/permissions/OWNERS b/chrome/android/javatests/src/org/chromium/chrome/browser/permissions/OWNERS
new file mode 100644
index 0000000..05c118d
--- /dev/null
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/permissions/OWNERS
@@ -0,0 +1,3 @@
+dominickn@chromium.org
+
+# COMPONENT: UI>Browser>Permissions>Prompts
diff --git a/chrome/app/chromeos_strings.grdp b/chrome/app/chromeos_strings.grdp
index 77e3323..45d37a4b 100644
--- a/chrome/app/chromeos_strings.grdp
+++ b/chrome/app/chromeos_strings.grdp
@@ -2325,7 +2325,7 @@
     Activation of '<ph name="name">$1<ex>Generic Wireless</ex></ph>' requires a network connection.
   </message>
 
-  <!-- Strings shown within tether notifications -->
+  <!-- Strings shown within Tether notifications -->
   <message name="IDS_TETHER_NOTIFICATION_CONNECTION_FAILED_TITLE" desc="Title of the notification shown to the user when an attempt to tether to another device has failed.">
     Instant Tethering connection failed
   </message>
@@ -2347,11 +2347,11 @@
   <message name="IDS_TETHER_NOTIFICATION_WIFI_AVAILABLE_MULTIPLE_DEVICES_MESSAGE" desc="Message shown as part of the notification shown to the user when multiple tether hotspots are available via multiple nearby devices.">
     Data connection available
   </message>
-  <message name="IDS_TETHER_NOTIFICATION_SET_UP_NEEDED_TITLE" desc="Title of the notification shown to the user when set up is needed on another device to start tethering.">
-    Finish setting up connection on your <ph name="PHONE_NAME">$1<ex>Google Pixel XL</ex></ph>
+  <message name="IDS_TETHER_NOTIFICATION_SETUP_REQUIRED_TITLE" desc="Title of the notification shown to the user when set up is needed on another device to start tethering.">
+    Set up connection on your <ph name="PHONE_NAME">$1<ex>Google Pixel XL</ex></ph>
   </message>
-  <message name="IDS_TETHER_NOTIFICATION_SET_UP_NEEDED_MESSAGE" desc="Message shown as part of the notification shown to the user when set up is needed on another device to start tethering.">
-    Tap the notification on your Pixel to set up a private Wi-Fi connection that can be used by this device.
+  <message name="IDS_TETHER_NOTIFICATION_SETUP_REQUIRED_MESSAGE" desc="Message shown as part of the notification shown to the user when set up is needed on another device to start tethering.">
+    Tap the notification on your <ph name="PHONE_NAME">$1<ex>Google Pixel XL</ex></ph> to set up the mobile hotspot that can be used by this device.
   </message>
 
   <!-- Options strings -->
@@ -3909,7 +3909,7 @@
   <message name="IDS_NETWORK_TYPE_ETHERNET" desc="The ethernet network type.">
     Ethernet
   </message>
-  <message name="IDS_NETWORK_TYPE_TETHER" desc="The tether network type.">
+  <message name="IDS_NETWORK_TYPE_TETHER" desc="The Tether network type.">
     Tether
   </message>
   <message name="IDS_NETWORK_TYPE_WIFI" desc="The wifi network type.">
diff --git a/chrome/browser/BUILD.gn b/chrome/browser/BUILD.gn
index 1f71e2b..2159a8a 100644
--- a/chrome/browser/BUILD.gn
+++ b/chrome/browser/BUILD.gn
@@ -2184,6 +2184,8 @@
       "android/offline_pages/request_coordinator_factory.h",
       "offline_pages/background_loader_offliner.cc",
       "offline_pages/background_loader_offliner.h",
+      "offline_pages/prefetch/offline_metrics_collector_impl.cc",
+      "offline_pages/prefetch/offline_metrics_collector_impl.h",
       "offline_pages/prefetch/prefetch_service_factory.cc",
       "offline_pages/prefetch/prefetch_service_factory.h",
     ]
diff --git a/chrome/browser/about_flags.cc b/chrome/browser/about_flags.cc
index 0ae1b11..c505095 100644
--- a/chrome/browser/about_flags.cc
+++ b/chrome/browser/about_flags.cc
@@ -36,7 +36,6 @@
 #include "chrome/common/chrome_switches.h"
 #include "chrome/common/features.h"
 #include "chrome/common/pause_tabs_field_trial.h"
-#include "chrome/grit/chromium_strings.h"
 #include "components/autofill/core/browser/autofill_experiments.h"
 #include "components/autofill/core/common/autofill_switches.h"
 #include "components/autofill/core/common/autofill_util.h"
@@ -69,7 +68,6 @@
 #include "components/spellcheck/common/spellcheck_switches.h"
 #include "components/spellcheck/spellcheck_build_features.h"
 #include "components/ssl_config/ssl_config_switches.h"
-#include "components/strings/grit/components_strings.h"
 #include "components/suggestions/features.h"
 #include "components/sync/driver/sync_driver_switches.h"
 #include "components/tracing/common/tracing_switches.h"
diff --git a/chrome/browser/android/devtools_server.cc b/chrome/browser/android/devtools_server.cc
index 4f9502c..02d29cc 100644
--- a/chrome/browser/android/devtools_server.cc
+++ b/chrome/browser/android/devtools_server.cc
@@ -25,7 +25,6 @@
 #include "chrome/browser/ui/android/tab_model/tab_model.h"
 #include "chrome/browser/ui/android/tab_model/tab_model_list.h"
 #include "chrome/common/chrome_content_client.h"
-#include "chrome/grit/browser_resources.h"
 #include "components/version_info/version_info.h"
 #include "content/public/browser/android/devtools_auth.h"
 #include "content/public/browser/browser_thread.h"
diff --git a/chrome/browser/android/download/download_manager_service.cc b/chrome/browser/android/download/download_manager_service.cc
index 2be42f9..8fb0b47 100644
--- a/chrome/browser/android/download/download_manager_service.cc
+++ b/chrome/browser/android/download/download_manager_service.cc
@@ -15,7 +15,6 @@
 #include "chrome/browser/download/download_core_service.h"
 #include "chrome/browser/download/download_core_service_factory.h"
 #include "chrome/browser/profiles/profile_manager.h"
-#include "chrome/grit/generated_resources.h"
 #include "components/mime_util/mime_util.h"
 #include "components/variations/variations_associated_data.h"
 #include "content/public/browser/browser_context.h"
diff --git a/chrome/browser/android/preferences/pref_service_bridge.cc b/chrome/browser/android/preferences/pref_service_bridge.cc
index ab47a4f..fbba31d 100644
--- a/chrome/browser/android/preferences/pref_service_bridge.cc
+++ b/chrome/browser/android/preferences/pref_service_bridge.cc
@@ -33,7 +33,6 @@
 #include "chrome/browser/ui/android/android_about_app_info.h"
 #include "chrome/common/chrome_features.h"
 #include "chrome/common/pref_names.h"
-#include "chrome/grit/locale_settings.h"
 #include "components/browsing_data/core/browsing_data_utils.h"
 #include "components/browsing_data/core/pref_names.h"
 #include "components/content_settings/core/browser/host_content_settings_map.h"
diff --git a/chrome/browser/app_controller_mac_unittest.mm b/chrome/browser/app_controller_mac_unittest.mm
index da14d701..0e41e6f 100644
--- a/chrome/browser/app_controller_mac_unittest.mm
+++ b/chrome/browser/app_controller_mac_unittest.mm
@@ -17,8 +17,6 @@
 #include "chrome/browser/sync/profile_sync_service_factory.h"
 #include "chrome/common/chrome_constants.h"
 #include "chrome/common/pref_names.h"
-#include "chrome/grit/chromium_strings.h"
-#include "chrome/grit/generated_resources.h"
 #include "chrome/test/base/testing_browser_process.h"
 #include "chrome/test/base/testing_profile.h"
 #include "chrome/test/base/testing_profile_manager.h"
diff --git a/chrome/browser/autofill/android/personal_data_manager_android.cc b/chrome/browser/autofill/android/personal_data_manager_android.cc
index 86f9097..875e77d 100644
--- a/chrome/browser/autofill/android/personal_data_manager_android.cc
+++ b/chrome/browser/autofill/android/personal_data_manager_android.cc
@@ -37,7 +37,6 @@
 #include "components/autofill/core/common/autofill_constants.h"
 #include "components/autofill/core/common/autofill_pref_names.h"
 #include "components/autofill/core/common/autofill_switches.h"
-#include "components/grit/components_scaled_resources.h"
 #include "components/prefs/pref_service.h"
 #include "content/public/browser/web_contents.h"
 #include "jni/PersonalDataManager_jni.h"
diff --git a/chrome/browser/chrome_browser_field_trials_desktop.cc b/chrome/browser/chrome_browser_field_trials_desktop.cc
index 638d2d3..6892f34 100644
--- a/chrome/browser/chrome_browser_field_trials_desktop.cc
+++ b/chrome/browser/chrome_browser_field_trials_desktop.cc
@@ -26,6 +26,7 @@
 #include "chrome/common/chrome_switches.h"
 #include "components/browser_watcher/features.h"
 #include "components/browser_watcher/stability_paths.h"
+#include "components/metrics/persistent_system_profile.h"
 #include "components/variations/variations_associated_data.h"
 #include "content/public/common/content_switches.h"
 #include "media/media_features.h"
@@ -191,6 +192,12 @@
         browser_watcher::kInitFlushParam, false);
     if (should_flush)
       ::FlushViewOfFile(global_tracker->allocator()->data(), 0U);
+
+    // Store a copy of the system profile in this allocator. There will be some
+    // delay before this gets populated, perhaps as much as a minute. Because
+    // of this, there is no need to flush it here.
+    metrics::GlobalPersistentSystemProfile::GetInstance()
+        ->RegisterPersistentAllocator(global_tracker->allocator());
   }
 }
 #endif  // defined(OS_WIN)
diff --git a/chrome/browser/chrome_quota_permission_context.cc b/chrome/browser/chrome_quota_permission_context.cc
index 10a6510..59718057 100644
--- a/chrome/browser/chrome_quota_permission_context.cc
+++ b/chrome/browser/chrome_quota_permission_context.cc
@@ -17,7 +17,6 @@
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/tab_contents/tab_util.h"
 #include "chrome/grit/generated_resources.h"
-#include "chrome/grit/locale_settings.h"
 #include "components/url_formatter/elide_url.h"
 #include "content/public/browser/browser_thread.h"
 #include "content/public/browser/navigation_details.h"
diff --git a/chrome/browser/chromeos/app_mode/kiosk_external_updater.cc b/chrome/browser/chromeos/app_mode/kiosk_external_updater.cc
index a9d0d37d..aac2d07 100644
--- a/chrome/browser/chromeos/app_mode/kiosk_external_updater.cc
+++ b/chrome/browser/chromeos/app_mode/kiosk_external_updater.cc
@@ -14,7 +14,6 @@
 #include "base/version.h"
 #include "chrome/browser/chromeos/app_mode/kiosk_app_manager.h"
 #include "chrome/browser/chromeos/ui/kiosk_external_update_notification.h"
-#include "chrome/grit/chromium_strings.h"
 #include "chrome/grit/generated_resources.h"
 #include "components/version_info/version_info.h"
 #include "content/public/browser/browser_thread.h"
diff --git a/chrome/browser/chromeos/arc/notification/arc_provision_notification_service.cc b/chrome/browser/chromeos/arc/notification/arc_provision_notification_service.cc
index 15b22b6..f0f4ce4 100644
--- a/chrome/browser/chromeos/arc/notification/arc_provision_notification_service.cc
+++ b/chrome/browser/chromeos/arc/notification/arc_provision_notification_service.cc
@@ -10,7 +10,6 @@
 #include "base/memory/ptr_util.h"
 #include "base/strings/utf_string_conversions.h"
 #include "chrome/browser/chromeos/arc/arc_util.h"
-#include "chrome/grit/component_extension_resources.h"
 #include "chrome/grit/generated_resources.h"
 #include "chrome/grit/theme_resources.h"
 #include "components/signin/core/account_id/account_id.h"
diff --git a/chrome/browser/chromeos/extensions/file_manager/private_api_strings.cc b/chrome/browser/chromeos/extensions/file_manager/private_api_strings.cc
index 97bd3df..b90d8c9 100644
--- a/chrome/browser/chromeos/extensions/file_manager/private_api_strings.cc
+++ b/chrome/browser/chromeos/extensions/file_manager/private_api_strings.cc
@@ -17,7 +17,6 @@
 #include "extensions/common/extension_l10n_util.h"
 #include "ui/base/l10n/l10n_util.h"
 #include "ui/base/webui/web_ui_util.h"
-#include "ui/strings/grit/app_locale_settings.h"
 
 namespace {
 
diff --git a/chrome/browser/chromeos/external_protocol_dialog.cc b/chrome/browser/chromeos/external_protocol_dialog.cc
index b38194d..e0c7f6d 100644
--- a/chrome/browser/chromeos/external_protocol_dialog.cc
+++ b/chrome/browser/chromeos/external_protocol_dialog.cc
@@ -10,7 +10,6 @@
 #include "chrome/browser/ui/browser_dialogs.h"
 #include "chrome/grit/chromium_strings.h"
 #include "chrome/grit/generated_resources.h"
-#include "components/strings/grit/components_strings.h"
 #include "content/public/browser/web_contents.h"
 #include "ui/base/l10n/l10n_util.h"
 #include "ui/gfx/text_elider.h"
diff --git a/chrome/browser/chromeos/hats/hats_notification_controller.cc b/chrome/browser/chromeos/hats/hats_notification_controller.cc
index 81cdf1b..f5eab12 100644
--- a/chrome/browser/chromeos/hats/hats_notification_controller.cc
+++ b/chrome/browser/chromeos/hats/hats_notification_controller.cc
@@ -21,7 +21,6 @@
 #include "chrome/browser/search/suggestions/image_decoder_impl.h"
 #include "chrome/common/chrome_features.h"
 #include "chrome/common/pref_names.h"
-#include "chrome/grit/theme_resources.h"
 #include "chromeos/chromeos_switches.h"
 #include "chromeos/network/network_state.h"
 #include "components/image_fetcher/core/image_fetcher_impl.h"
diff --git a/chrome/browser/chromeos/input_method/component_extension_ime_manager_impl.cc b/chrome/browser/chromeos/input_method/component_extension_ime_manager_impl.cc
index 4ca3831b..fe160978 100644
--- a/chrome/browser/chromeos/input_method/component_extension_ime_manager_impl.cc
+++ b/chrome/browser/chromeos/input_method/component_extension_ime_manager_impl.cc
@@ -22,7 +22,6 @@
 #include "chrome/common/chrome_paths.h"
 #include "chrome/common/extensions/extension_constants.h"
 #include "chrome/grit/browser_resources.h"
-#include "chrome/grit/generated_resources.h"
 #include "content/public/browser/browser_thread.h"
 #include "extensions/browser/extension_pref_value_map.h"
 #include "extensions/browser/extension_pref_value_map_factory.h"
diff --git a/chrome/browser/chromeos/login/app_launch_signin_screen.cc b/chrome/browser/chromeos/login/app_launch_signin_screen.cc
index 0fec808..882252e 100644
--- a/chrome/browser/chromeos/login/app_launch_signin_screen.cc
+++ b/chrome/browser/chromeos/login/app_launch_signin_screen.cc
@@ -230,7 +230,7 @@
     users_list.Append(std::move(user_dict));
   }
 
-  webui_handler_->LoadUsers(users_list, false);
+  webui_handler_->LoadUsers(users, users_list);
 }
 
 void AppLaunchSigninScreen::CheckUserStatus(const AccountId& account_id) {}
diff --git a/chrome/browser/chromeos/login/screens/chrome_user_selection_screen.cc b/chrome/browser/chromeos/login/screens/chrome_user_selection_screen.cc
index f912b35..0f2b0461 100644
--- a/chrome/browser/chromeos/login/screens/chrome_user_selection_screen.cc
+++ b/chrome/browser/chromeos/login/screens/chrome_user_selection_screen.cc
@@ -51,9 +51,8 @@
   }
 }
 
-void ChromeUserSelectionScreen::Init(const user_manager::UserList& users,
-                                     bool show_guest) {
-  UserSelectionScreen::Init(users, show_guest);
+void ChromeUserSelectionScreen::Init(const user_manager::UserList& users) {
+  UserSelectionScreen::Init(users);
 
   // Retrieve the current policy for all users.
   for (user_manager::UserList::const_iterator it = users.begin();
diff --git a/chrome/browser/chromeos/login/screens/chrome_user_selection_screen.h b/chrome/browser/chromeos/login/screens/chrome_user_selection_screen.h
index 11ab0d3..05e89a2 100644
--- a/chrome/browser/chromeos/login/screens/chrome_user_selection_screen.h
+++ b/chrome/browser/chromeos/login/screens/chrome_user_selection_screen.h
@@ -27,7 +27,7 @@
   ~ChromeUserSelectionScreen() override;
 
   // UserSelectionScreen:
-  void Init(const user_manager::UserList& users, bool show_guest) override;
+  void Init(const user_manager::UserList& users) override;
   void SendUserList() override;
 
   // policy::DeviceLocalAccountPolicyService::Observer:
diff --git a/chrome/browser/chromeos/login/screens/user_selection_screen.cc b/chrome/browser/chromeos/login/screens/user_selection_screen.cc
index 7678705..4b534fa 100644
--- a/chrome/browser/chromeos/login/screens/user_selection_screen.cc
+++ b/chrome/browser/chromeos/login/screens/user_selection_screen.cc
@@ -399,10 +399,8 @@
   view_ = view;
 }
 
-void UserSelectionScreen::Init(const user_manager::UserList& users,
-                               bool show_guest) {
+void UserSelectionScreen::Init(const user_manager::UserList& users) {
   users_ = users;
-  show_guest_ = show_guest;
 
   ui::UserActivityDetector* activity_detector = ui::UserActivityDetector::Get();
   if (activity_detector && !activity_detector->HasObserver(this))
@@ -540,7 +538,7 @@
     users_list.Append(std::move(user_dict));
   }
 
-  handler_->LoadUsers(users_list, show_guest_);
+  handler_->LoadUsers(users_to_send, users_list);
 }
 
 void UserSelectionScreen::HandleGetUsers() {
diff --git a/chrome/browser/chromeos/login/screens/user_selection_screen.h b/chrome/browser/chromeos/login/screens/user_selection_screen.h
index 6ca9958..2ec76b28 100644
--- a/chrome/browser/chromeos/login/screens/user_selection_screen.h
+++ b/chrome/browser/chromeos/login/screens/user_selection_screen.h
@@ -47,7 +47,7 @@
       const AccountId& owner,
       bool is_signin_to_add);
 
-  virtual void Init(const user_manager::UserList& users, bool show_guest);
+  virtual void Init(const user_manager::UserList& users);
   void OnUserImageChanged(const user_manager::User& user);
   void OnBeforeUserRemoved(const AccountId& account_id);
   void OnUserRemoved(const AccountId& account_id);
@@ -134,9 +134,6 @@
   LoginDisplayWebUIHandler* handler_ = nullptr;
   LoginDisplay::Delegate* login_display_delegate_ = nullptr;
 
-  // Whether to show guest login.
-  bool show_guest_ = false;
-
   // Purpose of the screen (see constants in OobeUI).
   const std::string display_type_;
 
diff --git a/chrome/browser/chromeos/login/signin_screen_controller.cc b/chrome/browser/chromeos/login/signin_screen_controller.cc
index 4b22d52..b8ea0af4 100644
--- a/chrome/browser/chromeos/login/signin_screen_controller.cc
+++ b/chrome/browser/chromeos/login/signin_screen_controller.cc
@@ -49,11 +49,10 @@
   instance_ = nullptr;
 }
 
-void SignInScreenController::Init(const user_manager::UserList& users,
-                                  bool show_guest) {
+void SignInScreenController::Init(const user_manager::UserList& users) {
   // TODO(antrim) : This dependency should be inverted, screen should ask about
   // users.
-  user_selection_screen_->Init(users, show_guest);
+  user_selection_screen_->Init(users);
 }
 
 void SignInScreenController::OnSigninScreenReady() {
diff --git a/chrome/browser/chromeos/login/signin_screen_controller.h b/chrome/browser/chromeos/login/signin_screen_controller.h
index 8765693..53cc8dea 100644
--- a/chrome/browser/chromeos/login/signin_screen_controller.h
+++ b/chrome/browser/chromeos/login/signin_screen_controller.h
@@ -44,7 +44,7 @@
 
   // Set up the list of users for user selection screen.
   // TODO(antrim): replace with querying for this data.
-  void Init(const user_manager::UserList& users, bool show_guest);
+  void Init(const user_manager::UserList& users);
 
   // Called when signin screen is ready.
   void OnSigninScreenReady();
diff --git a/chrome/browser/chromeos/login/ui/webui_login_display.cc b/chrome/browser/chromeos/login/ui/webui_login_display.cc
index a63b03b..b583afc 100644
--- a/chrome/browser/chromeos/login/ui/webui_login_display.cc
+++ b/chrome/browser/chromeos/login/ui/webui_login_display.cc
@@ -15,7 +15,6 @@
 #include "chrome/browser/chromeos/login/users/wallpaper/wallpaper_manager.h"
 #include "chrome/browser/profiles/profile_manager.h"
 #include "chrome/browser/ui/browser_window.h"
-#include "chrome/grit/chromium_strings.h"
 #include "chrome/grit/generated_resources.h"
 #include "components/signin/core/account_id/account_id.h"
 #include "components/strings/grit/components_strings.h"
@@ -55,7 +54,7 @@
                              bool allow_new_user) {
   // Testing that the delegate has been set.
   DCHECK(delegate_);
-  SignInScreenController::Get()->Init(users, show_guest);
+  SignInScreenController::Get()->Init(users);
   show_guest_ = show_guest;
   show_users_changed_ = (show_users_ != show_users);
   show_users_ = show_users;
diff --git a/chrome/browser/chromeos/login/users/chrome_user_manager_impl.cc b/chrome/browser/chromeos/login/users/chrome_user_manager_impl.cc
index 495331f..aca917c 100644
--- a/chrome/browser/chromeos/login/users/chrome_user_manager_impl.cc
+++ b/chrome/browser/chromeos/login/users/chrome_user_manager_impl.cc
@@ -87,8 +87,6 @@
 #include "content/public/browser/notification_service.h"
 #include "ui/base/l10n/l10n_util.h"
 #include "ui/base/resource/resource_bundle.h"
-#include "ui/chromeos/resources/grit/ui_chromeos_resources.h"
-#include "ui/chromeos/strings/grit/ui_chromeos_strings.h"
 #include "ui/gfx/image/image_skia.h"
 #include "ui/wm/core/wm_core_switches.h"
 
diff --git a/chrome/browser/chromeos/net/tether_notification_presenter.cc b/chrome/browser/chromeos/net/tether_notification_presenter.cc
index 3d3bf51..3648c3a 100644
--- a/chrome/browser/chromeos/net/tether_notification_presenter.cc
+++ b/chrome/browser/chromeos/net/tether_notification_presenter.cc
@@ -53,6 +53,11 @@
         "cros_tether_notification_ids.potential_hotspot";
 
 // static
+constexpr const char
+    TetherNotificationPresenter::kSetupRequiredNotificationId[] =
+        "cros_tether_notification_ids.setup_required";
+
+// static
 std::unique_ptr<message_center::Notification>
 TetherNotificationPresenter::CreateNotification(const std::string& id,
                                                 const base::string16& title,
@@ -140,6 +145,27 @@
       std::string(kPotentialHotspotNotificationId), false /* by_user */);
 }
 
+void TetherNotificationPresenter::NotifySetupRequired(
+    const std::string& device_name) {
+  PA_LOG(INFO) << "Displaying \"setup required\" notification. Notification "
+               << "ID = " << kSetupRequiredNotificationId;
+
+  ShowNotification(CreateNotification(
+      std::string(kSetupRequiredNotificationId),
+      l10n_util::GetStringFUTF16(IDS_TETHER_NOTIFICATION_SETUP_REQUIRED_TITLE,
+                                 base::ASCIIToUTF16(device_name)),
+      l10n_util::GetStringFUTF16(IDS_TETHER_NOTIFICATION_SETUP_REQUIRED_MESSAGE,
+                                 base::ASCIIToUTF16(device_name))));
+}
+
+void TetherNotificationPresenter::RemoveSetupRequiredNotification() {
+  PA_LOG(INFO) << "Removing \"setup required\" dialog. "
+               << "Notification ID = " << kSetupRequiredNotificationId;
+
+  message_center_->RemoveNotification(std::string(kSetupRequiredNotificationId),
+                                      false /* by_user */);
+}
+
 void TetherNotificationPresenter::NotifyConnectionToHostFailed() {
   PA_LOG(INFO) << "Displaying \"connection attempt failed\" notification. "
                << "Notification ID = " << kActiveHostNotificationId;
diff --git a/chrome/browser/chromeos/net/tether_notification_presenter.h b/chrome/browser/chromeos/net/tether_notification_presenter.h
index b5fad9c..53f0548 100644
--- a/chrome/browser/chromeos/net/tether_notification_presenter.h
+++ b/chrome/browser/chromeos/net/tether_notification_presenter.h
@@ -47,6 +47,8 @@
       const cryptauth::RemoteDevice& remote_device) override;
   void NotifyMultiplePotentialHotspotsNearby() override;
   void RemovePotentialHotspotNotification() override;
+  void NotifySetupRequired(const std::string& device_name) override;
+  void RemoveSetupRequiredNotification() override;
   void NotifyConnectionToHostFailed() override;
   void RemoveConnectionToHostFailedNotification() override;
 
@@ -69,6 +71,7 @@
   static const char kTetherNotifierId[];
   static const char kPotentialHotspotNotificationId[];
   static const char kActiveHostNotificationId[];
+  static const char kSetupRequiredNotificationId[];
 
   static std::unique_ptr<message_center::Notification> CreateNotification(
       const std::string& id,
diff --git a/chrome/browser/chromeos/net/tether_notification_presenter_unittest.cc b/chrome/browser/chromeos/net/tether_notification_presenter_unittest.cc
index 58d6d75..beeeb53 100644
--- a/chrome/browser/chromeos/net/tether_notification_presenter_unittest.cc
+++ b/chrome/browser/chromeos/net/tether_notification_presenter_unittest.cc
@@ -187,6 +187,11 @@
         TetherNotificationPresenter::kPotentialHotspotNotificationId);
   }
 
+  std::string GetSetupRequiredNotificationId() {
+    return std::string(
+        TetherNotificationPresenter::kSetupRequiredNotificationId);
+  }
+
   void VerifySettingsOpened() {
     EXPECT_EQ(profile_.get(), test_settings_ui_delegate_->last_profile());
     EXPECT_EQ("networks?type=Tether",
@@ -250,6 +255,24 @@
   VerifySettingsOpened();
 }
 
+TEST_F(TetherNotificationPresenterTest, TestSetupRequiredNotification) {
+  EXPECT_FALSE(test_message_center_->FindVisibleNotificationById(
+      GetSetupRequiredNotificationId()));
+  notification_presenter_->NotifySetupRequired(test_device_.name);
+
+  message_center::Notification* notification =
+      test_message_center_->FindVisibleNotificationById(
+          GetSetupRequiredNotificationId());
+  EXPECT_TRUE(notification);
+  EXPECT_EQ(GetSetupRequiredNotificationId(), notification->id());
+
+  EXPECT_EQ(1u, test_message_center_->GetNumNotifications());
+  notification_presenter_->RemoveSetupRequiredNotification();
+  EXPECT_FALSE(test_message_center_->FindVisibleNotificationById(
+      GetSetupRequiredNotificationId()));
+  EXPECT_EQ(0u, test_message_center_->GetNumNotifications());
+}
+
 TEST_F(TetherNotificationPresenterTest,
        TestSinglePotentialHotspotNotification_RemoveProgrammatically) {
   EXPECT_FALSE(test_message_center_->FindVisibleNotificationById(
diff --git a/chrome/browser/chromeos/printing/printers_manager_unittest.cc b/chrome/browser/chromeos/printing/printers_manager_unittest.cc
index f1d4bbde..d73860c 100644
--- a/chrome/browser/chromeos/printing/printers_manager_unittest.cc
+++ b/chrome/browser/chromeos/printing/printers_manager_unittest.cc
@@ -86,43 +86,32 @@
 
 class PrintersManagerTest : public testing::Test {
  protected:
-  PrintersManagerTest() : profile_(base::MakeUnique<TestingProfile>()) {
-    thread_bundle_ = base::MakeUnique<content::TestBrowserThreadBundle>();
-
-    auto sync_bridge = base::MakeUnique<PrintersSyncBridge>(
-        base::Bind(&syncer::ModelTypeStore::CreateInMemoryStoreForTest,
-                   syncer::PRINTERS),
-        base::BindRepeating(
-            base::IgnoreResult(&base::debug::DumpWithoutCrashing)));
-
-    manager_ = base::MakeUnique<PrintersManager>(profile_.get(),
-                                                 std::move(sync_bridge));
-
+  PrintersManagerTest()
+      : manager_(
+            &profile_,
+            base::MakeUnique<PrintersSyncBridge>(
+                base::Bind(&syncer::ModelTypeStore::CreateInMemoryStoreForTest,
+                           syncer::PRINTERS),
+                base::BindRepeating(
+                    base::IgnoreResult(&base::debug::DumpWithoutCrashing)))) {
     base::RunLoop().RunUntilIdle();
   }
 
-  ~PrintersManagerTest() override {
-    manager_.reset();
+  // Must outlive |profile_|.
+  content::TestBrowserThreadBundle thread_bundle_;
 
-    // Explicitly release the profile before the thread_bundle.  Otherwise, the
-    // profile destructor throws an error.
-    profile_.reset();
-    thread_bundle_.reset();
-  }
+  // Must outlive |manager_|.
+  TestingProfile profile_;
 
-  std::unique_ptr<TestingProfile> profile_;
-  std::unique_ptr<PrintersManager> manager_;
-
- private:
-  std::unique_ptr<content::TestBrowserThreadBundle> thread_bundle_;
+  PrintersManager manager_;
 };
 
 TEST_F(PrintersManagerTest, AddPrinter) {
   LoggingObserver observer;
-  manager_->AddObserver(&observer);
-  manager_->RegisterPrinter(base::MakeUnique<Printer>(kPrinterId));
+  manager_.AddObserver(&observer);
+  manager_.RegisterPrinter(base::MakeUnique<Printer>(kPrinterId));
 
-  auto printers = manager_->GetPrinters();
+  auto printers = manager_.GetPrinters();
   ASSERT_EQ(1U, printers.size());
   EXPECT_EQ(kPrinterId, printers[0]->id());
   EXPECT_EQ(Printer::Source::SRC_USER_PREFS, printers[0]->source());
@@ -132,25 +121,25 @@
 }
 
 TEST_F(PrintersManagerTest, UpdatePrinterAssignsId) {
-  manager_->RegisterPrinter(base::MakeUnique<Printer>());
+  manager_.RegisterPrinter(base::MakeUnique<Printer>());
 
-  auto printers = manager_->GetPrinters();
+  auto printers = manager_.GetPrinters();
   ASSERT_EQ(1U, printers.size());
   EXPECT_FALSE(printers[0]->id().empty());
 }
 
 TEST_F(PrintersManagerTest, UpdatePrinter) {
-  manager_->RegisterPrinter(base::MakeUnique<Printer>(kPrinterId));
+  manager_.RegisterPrinter(base::MakeUnique<Printer>(kPrinterId));
   auto updated_printer = base::MakeUnique<Printer>(kPrinterId);
   updated_printer->set_uri(kUri);
 
   // Register observer so it only receives the update event.
   LoggingObserver observer;
-  manager_->AddObserver(&observer);
+  manager_.AddObserver(&observer);
 
-  manager_->RegisterPrinter(std::move(updated_printer));
+  manager_.RegisterPrinter(std::move(updated_printer));
 
-  auto printers = manager_->GetPrinters();
+  auto printers = manager_.GetPrinters();
   ASSERT_EQ(1U, printers.size());
   EXPECT_EQ(kUri, printers[0]->uri());
 
@@ -159,13 +148,13 @@
 }
 
 TEST_F(PrintersManagerTest, RemovePrinter) {
-  manager_->RegisterPrinter(base::MakeUnique<Printer>("OtherUUID"));
-  manager_->RegisterPrinter(base::MakeUnique<Printer>(kPrinterId));
-  manager_->RegisterPrinter(base::MakeUnique<Printer>());
+  manager_.RegisterPrinter(base::MakeUnique<Printer>("OtherUUID"));
+  manager_.RegisterPrinter(base::MakeUnique<Printer>(kPrinterId));
+  manager_.RegisterPrinter(base::MakeUnique<Printer>());
 
-  manager_->RemovePrinter(kPrinterId);
+  manager_.RemovePrinter(kPrinterId);
 
-  auto printers = manager_->GetPrinters();
+  auto printers = manager_.GetPrinters();
   ASSERT_EQ(2U, printers.size());
   EXPECT_NE(kPrinterId, printers.at(0)->id());
   EXPECT_NE(kPrinterId, printers.at(1)->id());
@@ -195,11 +184,11 @@
   value->AppendString(second_printer);
 
   sync_preferences::TestingPrefServiceSyncable* prefs =
-      profile_->GetTestingPrefService();
+      profile_.GetTestingPrefService();
   // TestingPrefSyncableService assumes ownership of |value|.
   prefs->SetManagedPref(prefs::kRecommendedNativePrinters, std::move(value));
 
-  auto printers = manager_->GetRecommendedPrinters();
+  auto printers = manager_.GetRecommendedPrinters();
   ASSERT_EQ(2U, printers.size());
   EXPECT_EQ("Color Laser", printers[0]->display_name());
   EXPECT_EQ("ipp://192.168.1.5", printers[1]->uri());
@@ -212,14 +201,14 @@
   value->AppendString(printer);
 
   sync_preferences::TestingPrefServiceSyncable* prefs =
-      profile_->GetTestingPrefService();
+      profile_.GetTestingPrefService();
   // TestingPrefSyncableService assumes ownership of |value|.
   prefs->SetManagedPref(prefs::kRecommendedNativePrinters, std::move(value));
 
-  auto printers = manager_->GetRecommendedPrinters();
+  auto printers = manager_.GetRecommendedPrinters();
 
   const Printer& from_list = *(printers.front());
-  std::unique_ptr<Printer> retrieved = manager_->GetPrinter(from_list.id());
+  std::unique_ptr<Printer> retrieved = manager_.GetPrinter(from_list.id());
 
   EXPECT_EQ(from_list.id(), retrieved->id());
   EXPECT_EQ("LexaPrint", from_list.display_name());
@@ -228,21 +217,21 @@
 
 TEST_F(PrintersManagerTest, PrinterNotInstalled) {
   Printer printer(kPrinterId, base::Time::FromInternalValue(1000));
-  EXPECT_FALSE(manager_->IsConfigurationCurrent(printer));
+  EXPECT_FALSE(manager_.IsConfigurationCurrent(printer));
 }
 
 TEST_F(PrintersManagerTest, PrinterIsInstalled) {
   Printer printer(kPrinterId, base::Time::FromInternalValue(1000));
-  manager_->PrinterInstalled(printer);
-  EXPECT_TRUE(manager_->IsConfigurationCurrent(printer));
+  manager_.PrinterInstalled(printer);
+  EXPECT_TRUE(manager_.IsConfigurationCurrent(printer));
 }
 
 TEST_F(PrintersManagerTest, UpdatedPrinterConfiguration) {
   Printer printer(kPrinterId, base::Time::FromInternalValue(1000));
-  manager_->PrinterInstalled(printer);
+  manager_.PrinterInstalled(printer);
 
   Printer updated_printer(kPrinterId, base::Time::FromInternalValue(2000));
-  EXPECT_FALSE(manager_->IsConfigurationCurrent(updated_printer));
+  EXPECT_FALSE(manager_.IsConfigurationCurrent(updated_printer));
 }
 
 }  // namespace chromeos
diff --git a/chrome/browser/chromeos/ui/low_disk_notification_unittest.cc b/chrome/browser/chromeos/ui/low_disk_notification_unittest.cc
index abe580c..25b4c3b 100644
--- a/chrome/browser/chromeos/ui/low_disk_notification_unittest.cc
+++ b/chrome/browser/chromeos/ui/low_disk_notification_unittest.cc
@@ -14,7 +14,6 @@
 #include "testing/gtest/include/gtest/gtest.h"
 #include "ui/base/l10n/l10n_util.h"
 #include "ui/base/resource/resource_bundle.h"
-#include "ui/chromeos/resources/grit/ui_chromeos_resources.h"
 #include "ui/message_center/fake_message_center.h"
 #include "ui/message_center/message_center.h"
 
diff --git a/chrome/browser/chromeos/ui/request_pin_view.cc b/chrome/browser/chromeos/ui/request_pin_view.cc
index f7d2af3..6b62ac3 100644
--- a/chrome/browser/chromeos/ui/request_pin_view.cc
+++ b/chrome/browser/chromeos/ui/request_pin_view.cc
@@ -13,7 +13,6 @@
 #include "chrome/browser/chromeos/options/passphrase_textfield.h"
 #include "chrome/browser/ui/browser_dialogs.h"
 #include "chrome/grit/generated_resources.h"
-#include "chrome/grit/theme_resources.h"
 #include "ui/base/l10n/l10n_util.h"
 #include "ui/base/resource/resource_bundle.h"
 #include "ui/events/event.h"
diff --git a/chrome/browser/download/download_request_infobar_delegate_android.cc b/chrome/browser/download/download_request_infobar_delegate_android.cc
index 3663757..f0f7004 100644
--- a/chrome/browser/download/download_request_infobar_delegate_android.cc
+++ b/chrome/browser/download/download_request_infobar_delegate_android.cc
@@ -7,7 +7,6 @@
 #include "chrome/browser/android/android_theme_resources.h"
 #include "chrome/browser/infobars/infobar_service.h"
 #include "chrome/grit/generated_resources.h"
-#include "chrome/grit/theme_resources.h"
 #include "components/infobars/core/infobar.h"
 #include "ui/base/l10n/l10n_util.h"
 
diff --git a/chrome/browser/download/notification/download_item_notification.cc b/chrome/browser/download/notification/download_item_notification.cc
index d80905b..bf2b284 100644
--- a/chrome/browser/download/notification/download_item_notification.cc
+++ b/chrome/browser/download/notification/download_item_notification.cc
@@ -24,7 +24,6 @@
 #include "chrome/common/url_constants.h"
 #include "chrome/grit/chromium_strings.h"
 #include "chrome/grit/generated_resources.h"
-#include "chrome/grit/theme_resources.h"
 #include "components/mime_util/mime_util.h"
 #include "components/url_formatter/elide_url.h"
 #include "content/public/browser/browser_context.h"
diff --git a/chrome/browser/download/notification/download_notification_browsertest.cc b/chrome/browser/download/notification/download_notification_browsertest.cc
index 5bc9c42..51890e2 100644
--- a/chrome/browser/download/notification/download_notification_browsertest.cc
+++ b/chrome/browser/download/notification/download_notification_browsertest.cc
@@ -23,9 +23,7 @@
 #include "chrome/common/chrome_paths.h"
 #include "chrome/common/chrome_switches.h"
 #include "chrome/common/pref_names.h"
-#include "chrome/grit/chromium_strings.h"
 #include "chrome/grit/generated_resources.h"
-#include "chrome/grit/theme_resources.h"
 #include "chrome/test/base/in_process_browser_test.h"
 #include "chrome/test/base/ui_test_utils.h"
 #include "chromeos/chromeos_switches.h"
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 94d1f9042c..d541949 100644
--- a/chrome/browser/extensions/api/developer_private/developer_private_api.cc
+++ b/chrome/browser/extensions/api/developer_private/developer_private_api.cc
@@ -77,7 +77,6 @@
 #include "extensions/common/manifest_handlers/options_page_info.h"
 #include "extensions/common/manifest_url_handlers.h"
 #include "extensions/common/permissions/permissions_data.h"
-#include "extensions/grit/extensions_browser_resources.h"
 #include "storage/browser/fileapi/external_mount_points.h"
 #include "storage/browser/fileapi/file_system_context.h"
 #include "storage/browser/fileapi/file_system_operation.h"
diff --git a/chrome/browser/extensions/extension_context_menu_model.cc b/chrome/browser/extensions/extension_context_menu_model.cc
index e6b12de..be8a997 100644
--- a/chrome/browser/extensions/extension_context_menu_model.cc
+++ b/chrome/browser/extensions/extension_context_menu_model.cc
@@ -28,8 +28,6 @@
 #include "chrome/common/url_constants.h"
 #include "chrome/grit/chromium_strings.h"
 #include "chrome/grit/generated_resources.h"
-#include "chrome/grit/theme_resources.h"
-#include "components/grit/components_scaled_resources.h"
 #include "components/prefs/pref_service.h"
 #include "content/public/browser/web_contents.h"
 #include "content/public/common/context_menu_params.h"
diff --git a/chrome/browser/extensions/extension_disabled_ui.cc b/chrome/browser/extensions/extension_disabled_ui.cc
index a940570..50c997e 100644
--- a/chrome/browser/extensions/extension_disabled_ui.cc
+++ b/chrome/browser/extensions/extension_disabled_ui.cc
@@ -28,7 +28,6 @@
 #include "chrome/browser/ui/global_error/global_error_service.h"
 #include "chrome/browser/ui/global_error/global_error_service_factory.h"
 #include "chrome/browser/ui/tabs/tab_strip_model.h"
-#include "chrome/grit/chromium_strings.h"
 #include "chrome/grit/generated_resources.h"
 #include "components/strings/grit/components_strings.h"
 #include "content/public/browser/notification_details.h"
diff --git a/chrome/browser/extensions/extension_install_prompt.cc b/chrome/browser/extensions/extension_install_prompt.cc
index dcd7117..e485705 100644
--- a/chrome/browser/extensions/extension_install_prompt.cc
+++ b/chrome/browser/extensions/extension_install_prompt.cc
@@ -19,7 +19,6 @@
 #include "chrome/browser/extensions/permissions_updater.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/ui/extensions/extension_install_ui_factory.h"
-#include "chrome/grit/chromium_strings.h"
 #include "chrome/grit/generated_resources.h"
 #include "chrome/grit/theme_resources.h"
 #include "components/strings/grit/components_strings.h"
diff --git a/chrome/browser/extensions/proxy_overridden_bubble_delegate.cc b/chrome/browser/extensions/proxy_overridden_bubble_delegate.cc
index 1d05de2..23eeb81 100644
--- a/chrome/browser/extensions/proxy_overridden_bubble_delegate.cc
+++ b/chrome/browser/extensions/proxy_overridden_bubble_delegate.cc
@@ -12,7 +12,6 @@
 #include "chrome/browser/ui/browser.h"
 #include "chrome/common/url_constants.h"
 #include "chrome/grit/generated_resources.h"
-#include "components/strings/grit/components_strings.h"
 #include "extensions/browser/extension_prefs.h"
 #include "extensions/browser/extension_registry.h"
 #include "extensions/browser/extension_system.h"
diff --git a/chrome/browser/extensions/settings_api_bubble_delegate.cc b/chrome/browser/extensions/settings_api_bubble_delegate.cc
index 8fb398e..d64bc7c 100644
--- a/chrome/browser/extensions/settings_api_bubble_delegate.cc
+++ b/chrome/browser/extensions/settings_api_bubble_delegate.cc
@@ -15,7 +15,6 @@
 #include "chrome/common/url_constants.h"
 #include "chrome/grit/chromium_strings.h"
 #include "chrome/grit/generated_resources.h"
-#include "components/strings/grit/components_strings.h"
 #include "extensions/browser/extension_prefs.h"
 #include "extensions/browser/extension_registry.h"
 #include "extensions/browser/extension_system.h"
diff --git a/chrome/browser/extensions/suspicious_extension_bubble_delegate.cc b/chrome/browser/extensions/suspicious_extension_bubble_delegate.cc
index 504c937..ae0a617 100644
--- a/chrome/browser/extensions/suspicious_extension_bubble_delegate.cc
+++ b/chrome/browser/extensions/suspicious_extension_bubble_delegate.cc
@@ -13,7 +13,6 @@
 #include "chrome/common/url_constants.h"
 #include "chrome/grit/chromium_strings.h"
 #include "chrome/grit/generated_resources.h"
-#include "components/strings/grit/components_strings.h"
 #include "extensions/browser/extension_prefs.h"
 #include "extensions/browser/extension_system.h"
 #include "extensions/common/extension.h"
diff --git a/chrome/browser/extensions/theme_installed_infobar_delegate.cc b/chrome/browser/extensions/theme_installed_infobar_delegate.cc
index 9451f23..16d349d 100644
--- a/chrome/browser/extensions/theme_installed_infobar_delegate.cc
+++ b/chrome/browser/extensions/theme_installed_infobar_delegate.cc
@@ -20,7 +20,6 @@
 #include "chrome/browser/ui/browser_finder.h"
 #include "chrome/browser/ui/tabs/tab_strip_model.h"
 #include "chrome/grit/generated_resources.h"
-#include "chrome/grit/theme_resources.h"
 #include "components/infobars/core/infobar.h"
 #include "content/public/browser/notification_source.h"
 #include "extensions/browser/extension_system.h"
diff --git a/chrome/browser/extensions/warning_badge_service.cc b/chrome/browser/extensions/warning_badge_service.cc
index 130443e3..749aee9 100644
--- a/chrome/browser/extensions/warning_badge_service.cc
+++ b/chrome/browser/extensions/warning_badge_service.cc
@@ -17,6 +17,7 @@
 #include "chrome/browser/ui/global_error/global_error_service.h"
 #include "chrome/browser/ui/global_error/global_error_service_factory.h"
 #include "chrome/grit/generated_resources.h"
+#include "content/public/browser/browser_thread.h"
 #include "ui/base/l10n/l10n_util.h"
 
 namespace extensions {
@@ -101,11 +102,12 @@
 
 WarningBadgeService::WarningBadgeService(Profile* profile)
     : profile_(profile), warning_service_observer_(this) {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
   warning_service_observer_.Add(WarningService::Get(profile_));
 }
 
 WarningBadgeService::~WarningBadgeService() {
+  DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
 }
 
 // static
@@ -115,7 +117,7 @@
 }
 
 void WarningBadgeService::SuppressCurrentWarnings() {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
   size_t old_size = suppressed_warnings_.size();
 
   const WarningSet& warnings = GetCurrentWarnings();
@@ -131,7 +133,7 @@
 
 void WarningBadgeService::ExtensionWarningsChanged(
     const ExtensionIdSet& affected_extensions) {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
   UpdateBadgeStatus();
 }
 
diff --git a/chrome/browser/extensions/warning_badge_service.h b/chrome/browser/extensions/warning_badge_service.h
index f0ea904..61d39c8b 100644
--- a/chrome/browser/extensions/warning_badge_service.h
+++ b/chrome/browser/extensions/warning_badge_service.h
@@ -7,7 +7,6 @@
 
 #include "base/compiler_specific.h"
 #include "base/macros.h"
-#include "base/threading/non_thread_safe.h"
 #include "components/keyed_service/core/keyed_service.h"
 #include "extensions/browser/warning_service.h"
 #include "extensions/browser/warning_set.h"
@@ -19,8 +18,7 @@
 // A service that is responsible for showing an extension warning badge on the
 // wrench menu.
 class WarningBadgeService : public KeyedService,
-                            public WarningService::Observer,
-                            public base::NonThreadSafe {
+                            public WarningService::Observer {
  public:
   explicit WarningBadgeService(Profile* profile);
   ~WarningBadgeService() override;
diff --git a/chrome/browser/first_run/first_run_internal_win.cc b/chrome/browser/first_run/first_run_internal_win.cc
index 5b949c71..1429c63f0 100644
--- a/chrome/browser/first_run/first_run_internal_win.cc
+++ b/chrome/browser/first_run/first_run_internal_win.cc
@@ -22,7 +22,6 @@
 #include "chrome/common/chrome_constants.h"
 #include "chrome/common/chrome_paths.h"
 #include "chrome/common/chrome_switches.h"
-#include "chrome/grit/locale_settings.h"
 #include "chrome/installer/util/google_update_settings.h"
 #include "chrome/installer/util/install_util.h"
 #include "chrome/installer/util/master_preferences.h"
diff --git a/chrome/browser/gpu/three_d_api_observer.cc b/chrome/browser/gpu/three_d_api_observer.cc
index ee5aa8e..cb6a5db 100644
--- a/chrome/browser/gpu/three_d_api_observer.cc
+++ b/chrome/browser/gpu/three_d_api_observer.cc
@@ -12,7 +12,6 @@
 #include "chrome/grit/theme_resources.h"
 #include "components/infobars/core/confirm_infobar_delegate.h"
 #include "components/infobars/core/infobar.h"
-#include "components/strings/grit/components_strings.h"
 #include "content/public/browser/gpu_data_manager.h"
 #include "ui/base/l10n/l10n_util.h"
 
diff --git a/chrome/browser/memory_details.cc b/chrome/browser/memory_details.cc
index 356fffc..15a9106 100644
--- a/chrome/browser/memory_details.cc
+++ b/chrome/browser/memory_details.cc
@@ -16,7 +16,6 @@
 #include "base/task_scheduler/post_task.h"
 #include "build/build_config.h"
 #include "chrome/browser/profiles/profile.h"
-#include "chrome/grit/generated_resources.h"
 #include "components/nacl/common/nacl_process_type.h"
 #include "components/strings/grit/components_strings.h"
 #include "content/public/browser/browser_child_process_host_iterator.h"
diff --git a/chrome/browser/metrics/first_web_contents_profiler.cc b/chrome/browser/metrics/first_web_contents_profiler.cc
index e67831b..dc87c1f 100644
--- a/chrome/browser/metrics/first_web_contents_profiler.cc
+++ b/chrome/browser/metrics/first_web_contents_profiler.cc
@@ -19,6 +19,8 @@
 #include "components/metrics/proto/profiler_event.pb.h"
 #include "components/startup_metric_utils/browser/startup_metric_utils.h"
 #include "content/public/browser/navigation_handle.h"
+#include "content/public/browser/render_frame_host.h"
+#include "content/public/browser/render_process_host.h"
 #include "content/public/browser/web_contents.h"
 #include "content/public/browser/web_contents_observer.h"
 #include "content/public/common/browser_side_navigation_policy.h"
@@ -106,7 +108,10 @@
 
   collected_paint_metric_ = true;
   startup_metric_utils::RecordFirstWebContentsNonEmptyPaint(
-      base::TimeTicks::Now());
+      base::TimeTicks::Now(), web_contents()
+                                  ->GetMainFrame()
+                                  ->GetProcess()
+                                  ->GetInitTimeForNavigationMetrics());
 
   metrics::TrackingSynchronizer::OnProfilingPhaseCompleted(
       metrics::ProfilerEventProto::EVENT_FIRST_NONEMPTY_PAINT);
diff --git a/chrome/browser/metrics/startup_metrics_browsertest.cc b/chrome/browser/metrics/startup_metrics_browsertest.cc
index 71932af..ab9258f 100644
--- a/chrome/browser/metrics/startup_metrics_browsertest.cc
+++ b/chrome/browser/metrics/startup_metrics_browsertest.cc
@@ -23,6 +23,7 @@
     "Startup.FirstWebContents.MainNavigationFinished",
     "Startup.FirstWebContents.MainNavigationStart",
     "Startup.FirstWebContents.NonEmptyPaint2",
+    "Startup.FirstWebContents.RenderProcessHostInit.ToNonEmptyPaint",
 
     // The following histograms depend on normal browser startup through
     // BrowserMain and are as such not caught by this browser test.
diff --git a/chrome/browser/offline_pages/prefetch/offline_metrics_collector_impl.cc b/chrome/browser/offline_pages/prefetch/offline_metrics_collector_impl.cc
new file mode 100644
index 0000000..b1e59748d
--- /dev/null
+++ b/chrome/browser/offline_pages/prefetch/offline_metrics_collector_impl.cc
@@ -0,0 +1,17 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/offline_pages/prefetch/offline_metrics_collector_impl.h"
+
+namespace offline_pages {
+
+// TODO(dimich): Implement this.
+OfflineMetricsCollectorImpl::OfflineMetricsCollectorImpl() {}
+OfflineMetricsCollectorImpl::~OfflineMetricsCollectorImpl() {}
+void OfflineMetricsCollectorImpl::OnAppStartupOrResume() {}
+void OfflineMetricsCollectorImpl::OnSuccessfulNavigationOnline() {}
+void OfflineMetricsCollectorImpl::OnSuccessfulNavigationOffline() {}
+void OfflineMetricsCollectorImpl::ReportAccumulatedStats() {}
+
+}  // namespace offline_pages
diff --git a/chrome/browser/offline_pages/prefetch/offline_metrics_collector_impl.h b/chrome/browser/offline_pages/prefetch/offline_metrics_collector_impl.h
new file mode 100644
index 0000000..496aee7
--- /dev/null
+++ b/chrome/browser/offline_pages/prefetch/offline_metrics_collector_impl.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 CHROME_BROWSER_OFFLINE_PAGES_PREFETCH_OFFLINE_METRICS_COLLECTOR_IMPL_H_
+#define CHROME_BROWSER_OFFLINE_PAGES_PREFETCH_OFFLINE_METRICS_COLLECTOR_IMPL_H_
+
+#include <memory>
+
+#include "base/macros.h"
+#include "components/offline_pages/core/prefetch/offline_metrics_collector.h"
+
+namespace offline_pages {
+
+class OfflineMetricsCollectorImpl : public OfflineMetricsCollector {
+ public:
+  OfflineMetricsCollectorImpl();
+  ~OfflineMetricsCollectorImpl() override;
+
+  // OfflineMetricsCollector implementation.
+  void OnAppStartupOrResume() override;
+  void OnSuccessfulNavigationOnline() override;
+  void OnSuccessfulNavigationOffline() override;
+  void ReportAccumulatedStats() override;
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(OfflineMetricsCollectorImpl);
+};
+
+}  // namespace offline_pages
+
+#endif  // CHROME_BROWSER_OFFLINE_PAGES_PREFETCH_OFFLINE_METRICS_COLLECTOR_IMPL_H_
diff --git a/chrome/browser/offline_pages/prefetch/prefetch_service_factory.cc b/chrome/browser/offline_pages/prefetch/prefetch_service_factory.cc
index 76e0722..94a3a02 100644
--- a/chrome/browser/offline_pages/prefetch/prefetch_service_factory.cc
+++ b/chrome/browser/offline_pages/prefetch/prefetch_service_factory.cc
@@ -6,6 +6,7 @@
 
 #include "base/memory/ptr_util.h"
 #include "base/memory/singleton.h"
+#include "chrome/browser/offline_pages/prefetch/offline_metrics_collector_impl.h"
 #include "components/keyed_service/content/browser_context_dependency_manager.h"
 #include "components/offline_pages/core/prefetch/prefetch_gcm_app_handler.h"
 #include "components/offline_pages/core/prefetch/prefetch_service_impl.h"
@@ -31,7 +32,12 @@
 
 KeyedService* PrefetchServiceFactory::BuildServiceInstanceFor(
     content::BrowserContext* context) const {
-  return new PrefetchServiceImpl(base::MakeUnique<PrefetchGCMAppHandler>());
+  auto prefetch_gcm_app_handler = base::MakeUnique<PrefetchGCMAppHandler>();
+  auto offline_metrics_collector =
+      base::MakeUnique<OfflineMetricsCollectorImpl>();
+
+  return new PrefetchServiceImpl(std::move(prefetch_gcm_app_handler),
+                                 std::move(offline_metrics_collector));
 }
 
 }  // namespace offline_pages
diff --git a/chrome/browser/password_manager/save_password_infobar_delegate_android.cc b/chrome/browser/password_manager/save_password_infobar_delegate_android.cc
index 5282d24..0ae082b 100644
--- a/chrome/browser/password_manager/save_password_infobar_delegate_android.cc
+++ b/chrome/browser/password_manager/save_password_infobar_delegate_android.cc
@@ -12,9 +12,7 @@
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/sync/profile_sync_service_factory.h"
 #include "chrome/browser/ui/passwords/manage_passwords_view_utils.h"
-#include "chrome/grit/chromium_strings.h"
 #include "chrome/grit/generated_resources.h"
-#include "chrome/grit/theme_resources.h"
 #include "components/browser_sync/profile_sync_service.h"
 #include "components/infobars/core/infobar.h"
 #include "components/infobars/core/infobar_manager.h"
diff --git a/chrome/browser/permissions/grouped_permission_infobar_delegate_android.cc b/chrome/browser/permissions/grouped_permission_infobar_delegate_android.cc
index aa098ea..77f92e5b4 100644
--- a/chrome/browser/permissions/grouped_permission_infobar_delegate_android.cc
+++ b/chrome/browser/permissions/grouped_permission_infobar_delegate_android.cc
@@ -12,7 +12,6 @@
 #include "chrome/browser/permissions/permission_util.h"
 #include "chrome/browser/ui/android/infobars/grouped_permission_infobar.h"
 #include "chrome/grit/generated_resources.h"
-#include "chrome/grit/theme_resources.h"
 #include "components/infobars/core/infobar.h"
 #include "components/url_formatter/elide_url.h"
 #include "ui/base/l10n/l10n_util.h"
diff --git a/chrome/browser/permissions/mock_permission_request.cc b/chrome/browser/permissions/mock_permission_request.cc
index c489a3a..ae21796 100644
--- a/chrome/browser/permissions/mock_permission_request.cc
+++ b/chrome/browser/permissions/mock_permission_request.cc
@@ -6,7 +6,6 @@
 
 #include "base/strings/string16.h"
 #include "base/strings/utf_string_conversions.h"
-#include "chrome/grit/theme_resources.h"
 #include "ui/vector_icons/vector_icons.h"
 
 MockPermissionRequest::MockPermissionRequest()
diff --git a/chrome/browser/platform_util_win.cc b/chrome/browser/platform_util_win.cc
index 67a0827b3b..e34ddfa 100644
--- a/chrome/browser/platform_util_win.cc
+++ b/chrome/browser/platform_util_win.cc
@@ -22,8 +22,6 @@
 #include "base/win/registry.h"
 #include "base/win/scoped_co_mem.h"
 #include "base/win/scoped_comptr.h"
-#include "base/win/windows_version.h"
-#include "chrome/browser/lifetime/application_lifetime.h"
 #include "chrome/browser/platform_util_internal.h"
 #include "content/public/browser/browser_thread.h"
 #include "ui/base/win/shell.h"
@@ -43,36 +41,6 @@
   if (dir.empty())
     return;
 
-  typedef HRESULT (WINAPI *SHOpenFolderAndSelectItemsFuncPtr)(
-      PCIDLIST_ABSOLUTE pidl_Folder,
-      UINT cidl,
-      PCUITEMID_CHILD_ARRAY pidls,
-      DWORD flags);
-
-  static SHOpenFolderAndSelectItemsFuncPtr open_folder_and_select_itemsPtr =
-      nullptr;
-  static bool initialize_open_folder_proc = true;
-  if (initialize_open_folder_proc) {
-    initialize_open_folder_proc = false;
-    // The SHOpenFolderAndSelectItems API is exposed by shell32 version 6
-    // and does not exist in Win2K. We attempt to retrieve this function export
-    // from shell32 and if it does not exist, we just invoke ShellExecute to
-    // open the folder thus losing the functionality to select the item in
-    // the process.
-    HMODULE shell32_base = GetModuleHandle(L"shell32.dll");
-    if (!shell32_base) {
-      NOTREACHED() << " " << __func__ << "(): Can't open shell32.dll";
-      return;
-    }
-    open_folder_and_select_itemsPtr =
-        reinterpret_cast<SHOpenFolderAndSelectItemsFuncPtr>
-            (GetProcAddress(shell32_base, "SHOpenFolderAndSelectItems"));
-  }
-  if (!open_folder_and_select_itemsPtr) {
-    ShellExecute(NULL, L"open", dir.value().c_str(), NULL, NULL, SW_SHOW);
-    return;
-  }
-
   base::win::ScopedComPtr<IShellFolder> desktop;
   HRESULT hr = SHGetDesktopFolder(desktop.GetAddressOf());
   if (FAILED(hr))
@@ -92,11 +60,9 @@
   if (FAILED(hr))
     return;
 
-  const ITEMIDLIST* highlight[] = { file_item };
+  const ITEMIDLIST* highlight[] = {file_item};
 
-  hr = (*open_folder_and_select_itemsPtr)(dir_item, arraysize(highlight),
-                                          highlight, NULL);
-
+  hr = SHOpenFolderAndSelectItems(dir_item, arraysize(highlight), highlight, 0);
   if (FAILED(hr)) {
     // On some systems, the above call mysteriously fails with "file not
     // found" even though the file is there.  In these cases, ShellExecute()
@@ -111,22 +77,6 @@
   }
 }
 
-// Old ShellExecute crashes the process when the command for a given scheme
-// is empty. This function tells if it is.
-bool ValidateShellCommandForScheme(const std::string& scheme) {
-  base::win::RegKey key;
-  base::string16 registry_path = base::ASCIIToUTF16(scheme) +
-                                 L"\\shell\\open\\command";
-  key.Open(HKEY_CLASSES_ROOT, registry_path.c_str(), KEY_READ);
-  if (!key.Valid())
-    return false;
-  DWORD size = 0;
-  key.ReadValue(NULL, NULL, &size, NULL);
-  if (size <= 2)
-    return false;
-  return true;
-}
-
 void OpenExternalOnWorkerThread(const GURL& url) {
   base::ThreadRestrictions::AssertIOAllowed();
   // Quote the input scheme to be sure that the command does not have
@@ -140,23 +90,17 @@
   // "Some versions of windows (Win2k before SP3, Win XP before SP1) crash in
   // ShellExecute on long URLs (bug 161357 on bugzilla.mozilla.org). IE 5 and 6
   // support URLS of 2083 chars in length, 2K is safe."
+  //
+  // It may be possible to increase this. https://crbug.com/727909
   const size_t kMaxUrlLength = 2048;
-  if (escaped_url.length() > kMaxUrlLength) {
-    NOTREACHED();
+  if (escaped_url.length() > kMaxUrlLength)
     return;
-  }
-
-  if (base::win::GetVersion() < base::win::VERSION_WIN7) {
-    if (!ValidateShellCommandForScheme(url.scheme()))
-      return;
-  }
 
   if (reinterpret_cast<ULONG_PTR>(ShellExecuteA(NULL, "open",
                                                 escaped_url.c_str(), NULL, NULL,
                                                 SW_SHOWNORMAL)) <= 32) {
-    // We fail to execute the call. We could display a message to the user.
-    // TODO(nsylvain): we should also add a dialog to warn on errors. See
-    // bug 1136923.
+    // On failure, it may be good to display a message to the user.
+    // https://crbug.com/727913
     return;
   }
 }
diff --git a/chrome/browser/plugins/plugin_infobar_delegates.cc b/chrome/browser/plugins/plugin_infobar_delegates.cc
index 6c4d83c..71744ae 100644
--- a/chrome/browser/plugins/plugin_infobar_delegates.cc
+++ b/chrome/browser/plugins/plugin_infobar_delegates.cc
@@ -22,10 +22,7 @@
 #include "chrome/browser/ui/browser_commands.h"
 #include "chrome/common/features.h"
 #include "chrome/common/url_constants.h"
-#include "chrome/grit/chromium_strings.h"
 #include "chrome/grit/generated_resources.h"
-#include "chrome/grit/locale_settings.h"
-#include "chrome/grit/theme_resources.h"
 #include "components/google/core/browser/google_util.h"
 #include "components/infobars/core/infobar.h"
 #include "components/strings/grit/components_strings.h"
diff --git a/chrome/browser/plugins/plugin_observer.cc b/chrome/browser/plugins/plugin_observer.cc
index 24e82e2e..6f939ac7 100644
--- a/chrome/browser/plugins/plugin_observer.cc
+++ b/chrome/browser/plugins/plugin_observer.cc
@@ -28,7 +28,6 @@
 #include "chrome/common/features.h"
 #include "chrome/common/render_messages.h"
 #include "chrome/grit/generated_resources.h"
-#include "chrome/grit/theme_resources.h"
 #include "components/component_updater/component_updater_service.h"
 #include "components/content_settings/core/browser/host_content_settings_map.h"
 #include "components/infobars/core/confirm_infobar_delegate.h"
diff --git a/chrome/browser/prerender/prerender_nostate_prefetch_browsertest.cc b/chrome/browser/prerender/prerender_nostate_prefetch_browsertest.cc
index f162de6a..4b6e6df 100644
--- a/chrome/browser/prerender/prerender_nostate_prefetch_browsertest.cc
+++ b/chrome/browser/prerender/prerender_nostate_prefetch_browsertest.cc
@@ -23,7 +23,6 @@
 #include "chrome/browser/ui/browser_commands.h"
 #include "chrome/browser/ui/tabs/tab_strip_model.h"
 #include "chrome/common/chrome_switches.h"
-#include "chrome/grit/generated_resources.h"
 #include "chrome/test/base/ui_test_utils.h"
 #include "content/public/browser/appcache_service.h"
 #include "content/public/browser/render_process_host.h"
diff --git a/chrome/browser/profiles/avatar_menu.cc b/chrome/browser/profiles/avatar_menu.cc
index 43ed71ae..a02c35b 100644
--- a/chrome/browser/profiles/avatar_menu.cc
+++ b/chrome/browser/profiles/avatar_menu.cc
@@ -26,7 +26,6 @@
 #include "chrome/common/chrome_switches.h"
 #include "chrome/common/features.h"
 #include "chrome/grit/generated_resources.h"
-#include "chrome/grit/theme_resources.h"
 #include "components/signin/core/common/profile_management_switches.h"
 #include "content/public/browser/browser_thread.h"
 #include "content/public/browser/notification_service.h"
diff --git a/chrome/browser/renderer_context_menu/render_view_context_menu_browsertest.cc b/chrome/browser/renderer_context_menu/render_view_context_menu_browsertest.cc
index e65f661..c90176f4 100644
--- a/chrome/browser/renderer_context_menu/render_view_context_menu_browsertest.cc
+++ b/chrome/browser/renderer_context_menu/render_view_context_menu_browsertest.cc
@@ -35,7 +35,6 @@
 #include "chrome/browser/ui/tabs/tab_strip_model.h"
 #include "chrome/common/render_messages.h"
 #include "chrome/common/thumbnail_capturer.mojom.h"
-#include "chrome/grit/generated_resources.h"
 #include "chrome/test/base/in_process_browser_test.h"
 #include "chrome/test/base/search_test_utils.h"
 #include "chrome/test/base/ui_test_utils.h"
diff --git a/chrome/browser/renderer_context_menu/spelling_bubble_model.cc b/chrome/browser/renderer_context_menu/spelling_bubble_model.cc
index 585aa5a..49fb126 100644
--- a/chrome/browser/renderer_context_menu/spelling_bubble_model.cc
+++ b/chrome/browser/renderer_context_menu/spelling_bubble_model.cc
@@ -9,7 +9,6 @@
 #include "chrome/common/url_constants.h"
 #include "chrome/grit/chromium_strings.h"
 #include "chrome/grit/generated_resources.h"
-#include "chrome/grit/theme_resources.h"
 #include "components/prefs/pref_service.h"
 #include "components/spellcheck/browser/pref_names.h"
 #include "components/strings/grit/components_strings.h"
diff --git a/chrome/browser/resources/about_sys/about_sys.html b/chrome/browser/resources/about_sys/about_sys.html
index 9b1cd36..796eb29 100644
--- a/chrome/browser/resources/about_sys/about_sys.html
+++ b/chrome/browser/resources/about_sys/about_sys.html
@@ -1,8 +1,8 @@
 <!doctype html>
-<html id="t" i18n-values="dir:textdirection;lang:language">
+<html id="t" dir="$i18n{textdirection}" lang="$i18n{language}">
   <head>
     <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
-    <title i18n-content="title"></title>
+    <title>$i18n{title}</title>
     <link rel="stylesheet" href="chrome://resources/css/text_defaults.css">
     <link rel="stylesheet" href="about_sys.css">
     <script src="chrome://resources/js/util.js"></script>
@@ -12,16 +12,16 @@
   </head>
   <body>
     <div id="header">
-      <h1 i18n-content="title"></h1>
-      <p i18n-content="description"></p>
+      <h1>$i18n{title}</h1>
+      <p>$i18n{description}</p>
     </div>
     <div id="content">
-      <h2 id="tableTitle" i18n-content="tableTitle"></h2>
+      <h2 id="tableTitle">$i18n{tableTitle}</h2>
       <div id="anchor" jscontent="anchor"></div>
-      <button id="expandAll" class="global-button" i18n-content="expandAllBtn">
+      <button id="expandAll" class="global-button">$i18n{expandAllBtn}</button>
+      <button id="collapseAll" class="global-button">
+        $i18n{collapseAllBtn}
       </button>
-      <button id="collapseAll" class="global-button"
-          i18n-content="collapseAllBtn"></button>
       <p id="status"></p>
       <table class="list" id="details">
         <tr jsselect="details">
diff --git a/chrome/browser/resources/md_bookmarks/list.js b/chrome/browser/resources/md_bookmarks/list.js
index 75810ea..f960e2e 100644
--- a/chrome/browser/resources/md_bookmarks/list.js
+++ b/chrome/browser/resources/md_bookmarks/list.js
@@ -73,7 +73,9 @@
         return {id: id};
       });
     } else {
-      var splices = Polymer.ArraySplice.calculateSplices(newValue, oldValue);
+      var splices = Polymer.ArraySplice.calculateSplices(
+          /** @type {!Array<string>} */ (newValue),
+          /** @type {!Array<string>} */ (oldValue));
       splices.forEach(function(splice) {
         // TODO(calamity): Could use notifySplices to improve performance here.
         var additions =
diff --git a/chrome/browser/resources/md_bookmarks/types.js b/chrome/browser/resources/md_bookmarks/types.js
index d8f9986..d766e35 100644
--- a/chrome/browser/resources/md_bookmarks/types.js
+++ b/chrome/browser/resources/md_bookmarks/types.js
@@ -93,39 +93,3 @@
 
 /** @param {!BookmarksPageState} newState */
 StoreObserver.prototype.onStateChanged = function(newState) {};
-
-// TODO(calamity): Remove once
-// https://github.com/google/closure-compiler/pull/2495 is merged.
-Polymer.ArraySplice = {};
-
-/**
- * Returns an array of splice records indicating the minimum edits required
- * to transform the `previous` array into the `current` array.
- *
- * Splice records are ordered by index and contain the following fields:
- * - `index`: index where edit started
- * - `removed`: array of removed items from this index
- * - `addedCount`: number of items added at this index
- *
- * This function is based on the Levenshtein "minimum edit distance"
- * algorithm. Note that updates are treated as removal followed by addition.
- *
- * The worst-case time complexity of this algorithm is `O(l * p)`
- *   l: The length of the current array
- *   p: The length of the previous array
- *
- * However, the worst-case complexity is reduced by an `O(n)` optimization
- * to detect any shared prefix & suffix between the two arrays and only
- * perform the more expensive minimum edit distance calculation over the
- * non-shared portions of the arrays.
- *
- * @param {Array} current The "changed" array for which splices will be
- * calculated.
- * @param {Array} previous The "unchanged" original array to compare
- * `current` against to determine the splices.
- * @return {Array} Returns an array of splice record objects. Each of these
- * contains: `index` the location where the splice occurred; `removed`
- * the array of removed items from this location; `addedCount` the number
- * of items added at this location.
- */
-Polymer.ArraySplice.calculateSplices = function(current, previous) {};
diff --git a/chrome/browser/resources/settings/controls/controlled_button.html b/chrome/browser/resources/settings/controls/controlled_button.html
index b2c7925..5cc109a 100644
--- a/chrome/browser/resources/settings/controls/controlled_button.html
+++ b/chrome/browser/resources/settings/controls/controlled_button.html
@@ -13,6 +13,8 @@
     <style include="settings-shared">
       :host {
         --justify-margin: 8px;
+        -webkit-margin-end: calc(var(--settings-button-edge-spacing) * -1);
+        -webkit-margin-start: calc(var(--settings-button-edge-spacing) * -1);
         align-items: center;
         display: flex;
       }
diff --git a/chrome/browser/resources/settings/internet_page/internet_known_networks_page.js b/chrome/browser/resources/settings/internet_page/internet_known_networks_page.js
index 839f413..cc333ac 100644
--- a/chrome/browser/resources/settings/internet_page/internet_known_networks_page.js
+++ b/chrome/browser/resources/settings/internet_page/internet_known_networks_page.js
@@ -15,7 +15,7 @@
   properties: {
     /**
      * The type of networks to list.
-     * @type {chrome.networkingPrivate.NetworkType}
+     * @type {CrOnc.Type}
      */
     networkType: {
       type: String,
diff --git a/chrome/browser/resources/settings/internet_page/internet_page.js b/chrome/browser/resources/settings/internet_page/internet_page.js
index 22cd5ee..45d9bee3 100644
--- a/chrome/browser/resources/settings/internet_page/internet_page.js
+++ b/chrome/browser/resources/settings/internet_page/internet_page.js
@@ -30,7 +30,7 @@
 
     /**
      * The device state for each network device type. Set by network-summary.
-     * @type {!Object<chrome.networkingPrivate.DeviceStateProperties>|undefined}
+     * @type {!Object<!CrOnc.DeviceStateProperties>|undefined}
      * @private
      */
     deviceStates: {
@@ -392,13 +392,12 @@
   },
 
   /**
-   * @param {!chrome.networkingPrivate.DeviceStateProperties} deviceState
+   * @param {!CrOnc.DeviceStateProperties} deviceState
    * @return {boolean}
    * @private
    */
   deviceIsEnabled_: function(deviceState) {
-    return !!deviceState &&
-        deviceState.State == chrome.networkingPrivate.DeviceStateType.ENABLED;
+    return !!deviceState && deviceState.State == CrOnc.DeviceState.ENABLED;
   },
 
   /**
@@ -449,7 +448,7 @@
         }
         console.error(
             'Unexpected networkingPrivate.startConnect error: ' + message +
-                ' For: ' + properties.GUID);
+            ' For: ' + properties.GUID);
       }
     });
   },
diff --git a/chrome/browser/resources/settings/internet_page/internet_subpage.js b/chrome/browser/resources/settings/internet_page/internet_subpage.js
index 9aa2ccec..71ef109 100644
--- a/chrome/browser/resources/settings/internet_page/internet_subpage.js
+++ b/chrome/browser/resources/settings/internet_page/internet_subpage.js
@@ -7,9 +7,6 @@
  * WiMAX, or virtual networks.
  */
 
-/** @typedef {chrome.networkingPrivate.DeviceStateProperties} */
-var DeviceStateProperties;
-
 Polymer({
   is: 'settings-internet-subpage',
 
@@ -29,12 +26,9 @@
 
     /**
      * Device state for the network type.
-     * @type {?DeviceStateProperties}
+     * @type {!CrOnc.DeviceStateProperties|undefined}
      */
-    deviceState: {
-      type: Object,
-      value: null,
-    },
+    deviceState: Object,
 
     /** @type {!chrome.networkingPrivate.GlobalPolicy|undefined} */
     globalPolicy: Object,
@@ -204,17 +198,16 @@
   },
 
   /**
-   * @param {!DeviceStateProperties|undefined} deviceState
+   * @param {!CrOnc.DeviceStateProperties|undefined} deviceState
    * @return {boolean} Whether or not the device state is enabled.
    * @private
    */
   deviceIsEnabled_: function(deviceState) {
-    return !!deviceState &&
-        deviceState.State == chrome.networkingPrivate.DeviceStateType.ENABLED;
+    return !!deviceState && deviceState.State == CrOnc.DeviceState.ENABLED;
   },
 
   /**
-   * @param {!DeviceStateProperties|undefined} deviceState
+   * @param {!CrOnc.DeviceStateProperties|undefined} deviceState
    * @param {string} onstr
    * @param {string} offstr
    * @return {string}
@@ -225,7 +218,7 @@
   },
 
   /**
-   * @param {?DeviceStateProperties} deviceState
+   * @param {!CrOnc.DeviceStateProperties|undefined} deviceState
    * @return {boolean}
    * @private
    */
@@ -235,18 +228,16 @@
   },
 
   /**
-   * @param {?DeviceStateProperties} deviceState
+   * @param {!CrOnc.DeviceStateProperties|undefined} deviceState
    * @return {boolean}
    * @private
    */
   enableToggleIsEnabled_: function(deviceState) {
-    return !!deviceState &&
-        deviceState.State !=
-        chrome.networkingPrivate.DeviceStateType.PROHIBITED;
+    return !!deviceState && deviceState.State != CrOnc.DeviceState.PROHIBITED;
   },
 
   /**
-   * @param {!DeviceStateProperties} deviceState
+   * @param {!CrOnc.DeviceStateProperties|undefined} deviceState
    * @return {string}
    * @private
    */
@@ -286,7 +277,7 @@
   },
 
   /**
-   * @param {!DeviceStateProperties} deviceState
+   * @param {!CrOnc.DeviceStateProperties|undefined} deviceState
    * @param {!chrome.networkingPrivate.GlobalPolicy} globalPolicy
    * @return {boolean}
    * @private
@@ -320,12 +311,12 @@
   },
 
   /**
-   * @param {!DeviceStateProperties} deviceState
+   * @param {!CrOnc.DeviceStateProperties|undefined} deviceState
    * @return {boolean}
    * @private
    */
   knownNetworksIsVisible_: function(deviceState) {
-    return deviceState && deviceState.Type == CrOnc.Type.WI_FI;
+    return !!deviceState && deviceState.Type == CrOnc.Type.WI_FI;
   },
 
   /**
diff --git a/chrome/browser/resources/settings/internet_page/network_summary.js b/chrome/browser/resources/settings/internet_page/network_summary.js
index 0c587b91..3ef2ccb9a 100644
--- a/chrome/browser/resources/settings/internet_page/network_summary.js
+++ b/chrome/browser/resources/settings/internet_page/network_summary.js
@@ -7,27 +7,24 @@
  * by type: Ethernet, WiFi, Cellular, WiMAX, and VPN.
  */
 
-/** @typedef {chrome.networkingPrivate.DeviceStateProperties} */
-var DeviceStateProperties;
-
 /**
  * @typedef {{
- *   Ethernet: (DeviceStateProperties|undefined),
- *   WiFi: (DeviceStateProperties|undefined),
- *   Cellular: (DeviceStateProperties|undefined),
- *   WiMAX: (DeviceStateProperties|undefined),
- *   VPN: (DeviceStateProperties|undefined)
+ *   Ethernet: (!CrOnc.DeviceStateProperties|undefined),
+ *   WiFi: (!CrOnc.DeviceStateProperties|undefined),
+ *   Cellular: (!CrOnc.DeviceStateProperties|undefined),
+ *   WiMAX: (!CrOnc.DeviceStateProperties|undefined),
+ *   VPN: (!CrOnc.DeviceStateProperties|undefined)
  * }}
  */
 var DeviceStateObject;
 
 /**
  * @typedef {{
- *   Ethernet: (Array<CrOnc.NetworkStateProperties>|undefined),
- *   WiFi: (Array<CrOnc.NetworkStateProperties>|undefined),
- *   Cellular: (Array<CrOnc.NetworkStateProperties>|undefined),
- *   WiMAX: (Array<CrOnc.NetworkStateProperties>|undefined),
- *   VPN: (Array<CrOnc.NetworkStateProperties>|undefined)
+ *   Ethernet: (Array<!CrOnc.NetworkStateProperties>|undefined),
+ *   WiFi: (Array<!CrOnc.NetworkStateProperties>|undefined),
+ *   Cellular: (Array<!CrOnc.NetworkStateProperties>|undefined),
+ *   WiMAX: (Array<!CrOnc.NetworkStateProperties>|undefined),
+ *   VPN: (Array<!CrOnc.NetworkStateProperties>|undefined)
  * }}
  */
 var NetworkStateListObject;
@@ -50,7 +47,7 @@
 
     /**
      * Interface for networkingPrivate calls, passed from internet_page.
-     * @type {NetworkingPrivate}
+     * @type {!NetworkingPrivate}
      */
     networkingPrivate: Object,
 
@@ -58,16 +55,13 @@
      * The device state for each network device type. We initialize this to
      * include a disabled WiFi type since WiFi is always present. This reduces
      * the amount of visual change on first load.
-     * @private {DeviceStateObject}
+     * @private {!DeviceStateObject}
      */
     deviceStates: {
       type: Object,
       value: function() {
         return {
-          WiFi: {
-            Type: chrome.networkingPrivate.NetworkType.WI_FI,
-            State: chrome.networkingPrivate.DeviceStateType.DISABLED
-          },
+          WiFi: {Type: CrOnc.Type.WI_FI, State: CrOnc.DeviceState.DISABLED},
         };
       },
       notify: true,
@@ -81,13 +75,13 @@
     activeNetworkStates_: {
       type: Array,
       value: function() {
-        return [{GUID: '', Type: chrome.networkingPrivate.NetworkType.WI_FI}];
+        return [{GUID: '', Type: CrOnc.Type.WI_FI}];
       },
     },
 
     /**
      * List of network state data for each network type.
-     * @private {NetworkStateListObject}
+     * @private {!NetworkStateListObject}
      */
     networkStateLists_: {
       type: Object,
@@ -99,30 +93,26 @@
 
   /**
    * Listener function for chrome.networkingPrivate.onNetworkListChanged event.
-   * @type {?function(!Array<string>)}
-   * @private
+   * @private {?function(!Array<string>)}
    */
   networkListChangedListener_: null,
 
   /**
    * Listener function for chrome.networkingPrivate.onDeviceStateListChanged
    * event.
-   * @type {?function(!Array<string>)}
-   * @private
+   * @private {?function(!Array<string>)}
    */
   deviceStateListChangedListener_: null,
 
   /**
    * Listener function for chrome.networkingPrivate.onNetworksChanged event.
-   * @type {?function(!Array<string>)}
-   * @private
+   * @private {?function(!Array<string>)}
    */
   networksChangedListener_: null,
 
   /**
    * Set of GUIDs identifying active networks, one for each type.
-   * @type {?Set<string>}
-   * @private
+   * @private {?Set<string>}
    */
   activeNetworkIds_: null,
 
@@ -194,7 +184,7 @@
   /**
    * networkingPrivate.getState event callback for an active state.
    * @param {string} id The id of the requested state.
-   * @param {!chrome.networkingPrivate.NetworkStateProperties} state
+   * @param {!CrOnc.NetworkStateProperties} state
    * @private
    */
   getActiveStateCallback_: function(id, state) {
@@ -243,18 +233,17 @@
    * Requests the list of network states from Chrome. Updates
    * activeNetworkStates and networkStateLists once the results are returned
    * from Chrome.
-   * @param {!Array<!DeviceStateProperties>=} opt_deviceStates
-   *     Optional list of state properties for all available devices.
+   * @param {!Array<!CrOnc.DeviceStateProperties>} deviceStates
    * @private
    */
-  getNetworkStates_: function(opt_deviceStates) {
+  getNetworkStates_: function(deviceStates) {
     var filter = {
-      networkType: chrome.networkingPrivate.NetworkType.ALL,
+      networkType: CrOnc.Type.ALL,
       visible: true,
       configured: false
     };
     this.networkingPrivate.getNetworks(filter, function(networkStates) {
-      this.updateNetworkStates_(networkStates, opt_deviceStates);
+      this.updateNetworkStates_(networkStates, deviceStates);
     }.bind(this));
   },
 
@@ -262,21 +251,14 @@
    * Called after network states are received from getNetworks.
    * @param {!Array<!CrOnc.NetworkStateProperties>} networkStates The state
    *     properties for all visible networks.
-   * @param {!Array<!DeviceStateProperties>=} opt_deviceStates
-   *     Optional list of state properties for all available devices. If not
-   *     defined the existing list of device states will be used.
+   * @param {!Array<!CrOnc.DeviceStateProperties>} deviceStates
    * @private
    */
-  updateNetworkStates_: function(networkStates, opt_deviceStates) {
-    var newDeviceStates;
-    if (opt_deviceStates) {
-      newDeviceStates = /** @type {!DeviceStateObject} */ ({});
-      for (var i = 0; i < opt_deviceStates.length; ++i) {
-        var state = opt_deviceStates[i];
-        newDeviceStates[state.Type] = state;
-      }
-    } else {
-      newDeviceStates = Object.assign({}, this.deviceStates);
+  updateNetworkStates_: function(networkStates, deviceStates) {
+    var newDeviceStates = /** @type {!DeviceStateObject} */ ({});
+    for (var i = 0; i < deviceStates.length; ++i) {
+      var state = deviceStates[i];
+      newDeviceStates[state.Type] = state;
     }
 
     // Clear any current networks.
@@ -310,10 +292,10 @@
 
     // Create a VPN entry in deviceStates if there are any VPN networks.
     if (newNetworkStateLists.VPN && newNetworkStateLists.VPN.length > 0) {
-      newDeviceStates.VPN = /** @type {DeviceStateProperties} */ ({
+      newDeviceStates.VPN = {
         Type: CrOnc.Type.VPN,
-        State: chrome.networkingPrivate.DeviceStateType.ENABLED
-      });
+        State: CrOnc.DeviceState.ENABLED
+      };
     }
 
     // Push the active networks onto newActiveNetworkStates in order based on
@@ -331,7 +313,7 @@
         continue;
       var state = activeNetworkStatesByType.get(type) || {GUID: '', Type: type};
       if (state.Source === undefined &&
-          device.State == chrome.networkingPrivate.DeviceStateType.PROHIBITED) {
+          device.State == CrOnc.DeviceState.PROHIBITED) {
         // Prohibited technologies are enforced by the device policy.
         state.Source = CrOnc.Source.DEVICE_POLICY;
       }
diff --git a/chrome/browser/resources/settings/internet_page/network_summary_item.html b/chrome/browser/resources/settings/internet_page/network_summary_item.html
index e1bc202e..6a0b7f3 100644
--- a/chrome/browser/resources/settings/internet_page/network_summary_item.html
+++ b/chrome/browser/resources/settings/internet_page/network_summary_item.html
@@ -59,7 +59,8 @@
         </cr-policy-indicator>
       </template>
 
-      <template is="dom-if" if="[[showDetailsIsVisible_(deviceState)]]">
+      <template is="dom-if" if="[[showDetailsIsVisible_(activeNetworkState,
+          deviceState, networkStateList)]]">
         <button class="subpage-arrow" is="paper-icon-button-light"
             aria-label$="[[getDetailsA11yString_(activeNetworkState,
                 deviceState, networkStateList)]]">
diff --git a/chrome/browser/resources/settings/internet_page/network_summary_item.js b/chrome/browser/resources/settings/internet_page/network_summary_item.js
index b16ea0b..f688f05 100644
--- a/chrome/browser/resources/settings/internet_page/network_summary_item.js
+++ b/chrome/browser/resources/settings/internet_page/network_summary_item.js
@@ -7,9 +7,6 @@
  * type and a list of networks for that type.
  */
 
-/** @typedef {chrome.networkingPrivate.DeviceStateProperties} */
-var DeviceStateProperties;
-
 Polymer({
   is: 'network-summary-item',
 
@@ -17,8 +14,9 @@
 
   properties: {
     /**
-     * Device state for the network type.
-     * @type {!DeviceStateProperties|undefined}
+     * Device state for the network type. This might briefly be undefined if a
+     * device becomes unavailable.
+     * @type {!CrOnc.DeviceStateProperties|undefined}
      */
     deviceState: Object,
 
@@ -55,26 +53,22 @@
   },
 
   /**
+   * @param {!CrOnc.NetworkStateProperties} activeNetworkState
+   * @param {!CrOnc.DeviceStateProperties|undefined} deviceState
    * @return {string}
    * @private
    */
-  getNetworkStateText_: function() {
-    var network = this.activeNetworkState;
-    var state = network.ConnectionState;
-    var name = CrOnc.getNetworkName(network);
+  getNetworkStateText_: function(activeNetworkState, deviceState) {
+    var state = activeNetworkState.ConnectionState;
+    var name = CrOnc.getNetworkName(activeNetworkState);
     if (state)
       return this.getConnectionStateText_(state, name);
-    var deviceState = this.deviceState;
     if (deviceState) {
-      if (deviceState.State ==
-          chrome.networkingPrivate.DeviceStateType.ENABLING) {
+      if (deviceState.State == CrOnc.DeviceState.ENABLING)
         return this.i18n('internetDeviceEnabling');
-      }
-      if (deviceState.Type == CrOnc.Type.CELLULAR &&
-          this.deviceState.Scanning) {
+      if (deviceState.Type == CrOnc.Type.CELLULAR && this.deviceState.Scanning)
         return this.i18n('internetMobileSearching');
-      }
-      if (deviceState.State == chrome.networkingPrivate.DeviceStateType.ENABLED)
+      if (deviceState.State == CrOnc.DeviceState.ENABLED)
         return CrOncStrings.networkListItemNotConnected;
     }
     return this.i18n('deviceOff');
@@ -102,40 +96,43 @@
   },
 
   /**
+   * @param {!CrOnc.NetworkStateProperties} activeNetworkState
    * @return {boolean}
    * @private
    */
-  showPolicyIndicator_: function() {
-    var network = this.activeNetworkState;
-    return network.ConnectionState == CrOnc.ConnectionState.CONNECTED ||
-        this.isPolicySource(network.Source);
+  showPolicyIndicator_: function(activeNetworkState) {
+    return activeNetworkState.ConnectionState ==
+        CrOnc.ConnectionState.CONNECTED ||
+        this.isPolicySource(activeNetworkState.Source);
   },
 
   /**
    * Show the <network-siminfo> element if this is a disabled and locked
    * cellular device.
+   * @param {!CrOnc.DeviceStateProperties|undefined} deviceState
    * @return {boolean}
    * @private
    */
-  showSimInfo_: function() {
-    var device = this.deviceState;
-    if (device.Type != CrOnc.Type.CELLULAR ||
-        this.deviceIsEnabled_(this.deviceState)) {
+  showSimInfo_: function(deviceState) {
+    if (!deviceState || deviceState.Type != CrOnc.Type.CELLULAR ||
+        this.deviceIsEnabled_(deviceState)) {
       return false;
     }
-    return device.SimPresent === false ||
-        device.SimLockType == CrOnc.LockType.PIN ||
-        device.SimLockType == CrOnc.LockType.PUK;
+    return deviceState.SimPresent === false ||
+        deviceState.SimLockType == CrOnc.LockType.PIN ||
+        deviceState.SimLockType == CrOnc.LockType.PUK;
   },
 
   /**
    * Returns a NetworkProperties object for <network-siminfo> built from
    * the device properties (since there will be no active network).
-   * @param {!DeviceStateProperties} deviceState
-   * @return {!CrOnc.NetworkProperties}
+   * @param {!CrOnc.DeviceStateProperties|undefined} deviceState
+   * @return {!CrOnc.NetworkProperties|undefined}
    * @private
    */
   getCellularState_: function(deviceState) {
+    if (!deviceState)
+      return undefined;
     return {
       GUID: '',
       Type: CrOnc.Type.CELLULAR,
@@ -150,37 +147,35 @@
   },
 
   /**
-   * @param {!DeviceStateProperties|undefined} deviceState
+   * @param {!CrOnc.DeviceStateProperties|undefined} deviceState
    * @return {boolean} Whether or not the device state is enabled.
    * @private
    */
   deviceIsEnabled_: function(deviceState) {
-    return !!deviceState &&
-        deviceState.State == chrome.networkingPrivate.DeviceStateType.ENABLED;
+    return !!deviceState && deviceState.State == CrOnc.DeviceState.ENABLED;
   },
 
   /**
-   * @param {!DeviceStateProperties} deviceState
+   * @param {!CrOnc.DeviceStateProperties|undefined} deviceState
    * @return {boolean}
    * @private
    */
   enableToggleIsVisible_: function(deviceState) {
-    return deviceState.Type != CrOnc.Type.ETHERNET &&
+    return !!deviceState && deviceState.Type != CrOnc.Type.ETHERNET &&
         deviceState.Type != CrOnc.Type.VPN;
   },
 
   /**
-   * @param {!DeviceStateProperties} deviceState
+   * @param {!CrOnc.DeviceStateProperties|undefined} deviceState
    * @return {boolean}
    * @private
    */
   enableToggleIsEnabled_: function(deviceState) {
-    return deviceState.State !=
-        chrome.networkingPrivate.DeviceStateType.PROHIBITED;
+    return !!deviceState && deviceState.State != CrOnc.DeviceState.PROHIBITED;
   },
 
   /**
-   * @param {!DeviceStateProperties} deviceState
+   * @param {!CrOnc.DeviceStateProperties|undefined} deviceState
    * @return {string}
    * @private
    */
@@ -202,25 +197,34 @@
   },
 
   /**
+   * @param {!CrOnc.NetworkStateProperties} activeNetworkState
+   * @param {!CrOnc.DeviceStateProperties|undefined} deviceState
+   * @param {!Array<!CrOnc.NetworkStateProperties>} networkStateList
    * @return {boolean}
    * @private
    */
-  showDetailsIsVisible_: function() {
-    return this.deviceIsEnabled_(this.deviceState) &&
-        (!!this.activeNetworkState.GUID || this.networkStateList.length > 0);
+  showDetailsIsVisible_: function(
+      activeNetworkState, deviceState, networkStateList) {
+    return this.deviceIsEnabled_(deviceState) &&
+        (!!activeNetworkState.GUID || networkStateList.length > 0);
   },
 
   /**
+   * @param {!CrOnc.DeviceStateProperties|undefined} deviceState
+   * @param {!Array<!CrOnc.NetworkStateProperties>} networkStateList
    * @return {boolean}
    * @private
    */
-  shouldShowList_: function() {
-    var minlen = (this.deviceState.Type == CrOnc.Type.WI_FI ||
-                  this.deviceState.Type == CrOnc.Type.VPN ||
-                  this.deviceState.Type == CrOnc.Type.TETHER) ?
+  shouldShowSubpage_: function(deviceState, networkStateList) {
+    if (!deviceState)
+      return false;
+    var type = deviceState.Type;
+    var minlen = (deviceState.Type == CrOnc.Type.WI_FI ||
+                  deviceState.Type == CrOnc.Type.VPN ||
+                  deviceState.Type == CrOnc.Type.TETHER) ?
         1 :
         2;
-    return this.networkStateList.length >= minlen;
+    return networkStateList.length >= minlen;
   },
 
   /**
@@ -232,7 +236,8 @@
       this.fire(
           'device-enabled-toggled',
           {enabled: true, type: this.deviceState.Type});
-    } else if (this.shouldShowList_()) {
+    } else if (this.shouldShowSubpage_(
+                   this.deviceState, this.networkStateList)) {
       this.fire('show-networks', this.deviceState);
     } else if (this.activeNetworkState.GUID) {
       this.fire('show-detail', this.activeNetworkState);
@@ -243,18 +248,22 @@
   },
 
   /**
+   * @param {!CrOnc.NetworkStateProperties} activeNetworkState
+   * @param {!CrOnc.DeviceStateProperties|undefined} deviceState
+   * @param {!Array<!CrOnc.NetworkStateProperties>} networkStateList
    * @return {string}
    * @private
    */
-  getDetailsA11yString_: function() {
-    if (!this.shouldShowList_()) {
-      if (this.activeNetworkState.GUID) {
-        return CrOnc.getNetworkName(this.activeNetworkState);
-      } else if (this.networkStateList.length > 0) {
-        return CrOnc.getNetworkName(this.networkStateList[0]);
+  getDetailsA11yString_: function(
+      activeNetworkState, deviceState, networkStateList) {
+    if (!this.shouldShowSubpage_(deviceState, networkStateList)) {
+      if (activeNetworkState.GUID) {
+        return CrOnc.getNetworkName(activeNetworkState);
+      } else if (networkStateList.length > 0) {
+        return CrOnc.getNetworkName(networkStateList[0]);
       }
     }
-    return this.i18n('OncType' + this.deviceState.Type);
+    return this.i18n('OncType' + deviceState.Type);
   },
 
   /**
diff --git a/chrome/browser/resources/settings/on_startup_page/startup_urls_page.html b/chrome/browser/resources/settings/on_startup_page/startup_urls_page.html
index 155ded00..37243091 100644
--- a/chrome/browser/resources/settings/on_startup_page/startup_urls_page.html
+++ b/chrome/browser/resources/settings/on_startup_page/startup_urls_page.html
@@ -22,6 +22,10 @@
         max-height: 395px;  /** Enough height to show six entries. */
       }
 
+      #container {
+        overflow: visible;  /* Allow ripple to go outside of the row. */
+      }
+
       #container iron-list > settings-startup-url-entry:not(:first-of-type) {
         border-top: var(--settings-separator-line);
       }
diff --git a/chrome/browser/resources/settings/passwords_and_forms_page/passwords_shared_css.html b/chrome/browser/resources/settings/passwords_and_forms_page/passwords_shared_css.html
index f5056b1..1430a4af 100644
--- a/chrome/browser/resources/settings/passwords_and_forms_page/passwords_shared_css.html
+++ b/chrome/browser/resources/settings/passwords_and_forms_page/passwords_shared_css.html
@@ -7,12 +7,6 @@
         flex-direction: column;
       }
 
-      paper-icon-button {
-        @apply(--cr-paper-icon-button-margin);
-        color: var(--paper-grey-600);
-        flex-shrink: 0;
-      }
-
       .list-with-header > div:first-of-type {
         border-top: var(--settings-separator-line);
       }
@@ -32,7 +26,7 @@
         display: flex;
         flex: 2;
       }
-      
+
       .password-field {
         background-color: transparent;
         border: none;
diff --git a/chrome/browser/resources/settings/settings_page/main_page_behavior.js b/chrome/browser/resources/settings/settings_page/main_page_behavior.js
index 331e9d5..04b70c97 100644
--- a/chrome/browser/resources/settings/settings_page/main_page_behavior.js
+++ b/chrome/browser/resources/settings/settings_page/main_page_behavior.js
@@ -92,10 +92,17 @@
 
     // For previously uncreated pages (including on first load), allow the page
     // to render before scrolling to or expanding the section.
-    if (!oldRoute || this.scrollHeight == 0)
+    if (!oldRoute) {
+      this.fire('hide-container');
+      setTimeout(function() {
+        this.fire('show-container');
+        this.tryTransitionToSection_(scrollToSection, true);
+      }.bind(this));
+    } else if (this.scrollHeight == 0) {
       setTimeout(this.tryTransitionToSection_.bind(this, scrollToSection));
-    else
+    } else {
       this.tryTransitionToSection_(scrollToSection);
+    }
   },
 
   /**
@@ -118,9 +125,10 @@
    * section is quickly shown, without getting the page into a broken state --
    * if currentRoute changes in between calls, just transition to the new route.
    * @param {boolean} scrollToSection
+   * @param {boolean=} immediate Whether to instantly expand instead of animate.
    * @private
    */
-  tryTransitionToSection_: function(scrollToSection) {
+  tryTransitionToSection_: function(scrollToSection, immediate) {
     var currentRoute = settings.getCurrentRoute();
     var currentSection = this.getSection(currentRoute.section);
 
@@ -145,10 +153,14 @@
       }
     } else if (currentSection) {
       // Expand the section into a subpage or scroll to it on the main page.
-      if (currentRoute.isSubpage())
-        promise = this.expandSection_(currentSection);
-      else if (scrollToSection)
+      if (currentRoute.isSubpage()) {
+        if (immediate)
+          this.expandSectionImmediate_(currentSection);
+        else
+          promise = this.expandSection_(currentSection);
+      } else if (scrollToSection) {
         currentSection.scrollIntoView();
+      }
     } else if (
         this.tagName == 'SETTINGS-BASIC-PAGE' &&
         settings.Route.ADVANCED.contains(currentRoute) &&
@@ -156,13 +168,19 @@
         // ADVANCED, otherwise tryTransitionToSection_ will recurse endlessly.
         !currentRoute.isNavigableDialog) {
       assert(currentRoute.section);
+      // Hide the container again while Advanced Page template is being loaded.
+      this.fire('hide-container');
       promise = this.$$('#advancedPageTemplate').get();
     }
 
     // When this animation ends, another may be necessary. Call this function
     // again after the promise resolves.
-    if (promise)
-      promise.then(this.tryTransitionToSection_.bind(this, scrollToSection));
+    if (promise) {
+      promise.then(this.tryTransitionToSection_.bind(this, scrollToSection))
+          .then(function() {
+            this.fire('show-container');
+          }.bind(this));
+    }
   },
 
   /**
@@ -204,6 +222,19 @@
   },
 
   /**
+   * Immediately expand the card in |section| to fill the page.
+   * @param {!SettingsSectionElement} section
+   * @private
+   */
+  expandSectionImmediate_: function(section) {
+    assert(this.scroller);
+    section.immediateExpand(this.scroller);
+    this.finishedExpanding_(section);
+    // TODO(scottchen): iron-list inside subpages need this to render correctly.
+    this.fire('resize');
+  },
+
+  /**
    * Animates the card in |section|, expanding it to fill the page.
    * @param {!SettingsSectionElement} section
    * @return {!Promise} Resolved when the transition is finished or canceled.
@@ -211,7 +242,6 @@
    */
   expandSection_: function(section) {
     assert(this.scroller);
-
     if (!section.canAnimateExpand()) {
       // Try to wait for the section to be created.
       return new Promise(function(resolve, reject) {
@@ -228,28 +258,33 @@
 
     this.currentAnimation_ = section.animateExpand(this.scroller);
 
-    var finished;
-    return this.currentAnimation_.finished.then(function() {
-      // Hide other sections and scroll to the top of the subpage.
-      this.classList.add('showing-subpage');
-      this.toggleOtherSectionsHidden_(section.section, true);
-      this.scroller.scrollTop = 0;
-      section.setFrozen(false);
+    return this.currentAnimation_.finished
+        .then(
+            function() {
+              this.finishedExpanding_(section);
+            }.bind(this),
+            function() {
+              // The animation was canceled; restore the section and scroll
+              // position.
+              section.setFrozen(false);
+              this.scroller.scrollTop = this.origScrollTop_;
+            }.bind(this))
+        .then(function() {
+          this.fire('freeze-scroll', false);
+          this.currentAnimation_ = null;
+        }.bind(this));
+  },
 
-      // Notify that the page is fully expanded.
-      this.fire('subpage-expand');
+  /** @private */
+  finishedExpanding_: function(section) {
+    // Hide other sections and scroll to the top of the subpage.
+    this.classList.add('showing-subpage');
+    this.toggleOtherSectionsHidden_(section.section, true);
+    this.scroller.scrollTop = 0;
+    section.setFrozen(false);
 
-      finished = true;
-    }.bind(this), function() {
-      // The animation was canceled; restore the section and scroll position.
-      section.setFrozen(false);
-      this.scroller.scrollTop = this.origScrollTop_;
-
-      finished = false;
-    }.bind(this)).then(function() {
-      this.fire('freeze-scroll', false);
-      this.currentAnimation_ = null;
-    }.bind(this));
+    // Notify that the page is fully expanded.
+    this.fire('subpage-expand');
   },
 
   /**
diff --git a/chrome/browser/resources/settings/settings_page/settings_section.js b/chrome/browser/resources/settings/settings_page/settings_section.js
index 0fe5074..a291461 100644
--- a/chrome/browser/resources/settings/settings_page/settings_section.js
+++ b/chrome/browser/resources/settings/settings_page/settings_section.js
@@ -99,6 +99,17 @@
         !this.classList.contains('expanded') && this.$.card.clientHeight > 0;
   },
 
+  immediateExpand: function(container) {
+    // Target position is the container's top edge in the viewport.
+    var containerTop = container.getBoundingClientRect().top;
+
+    this.$.card.position = 'fixed';
+    this.$.card.top = containerTop + 'px';
+    this.$.card.height = 'calc(100% - ' + containerTop + 'px)';
+
+    this.classList.add('expanded');
+  },
+
   /**
    * Animates the section expanding to fill the container. The section is fixed
    * in the viewport during the animation, making it safe to adjust the rest of
diff --git a/chrome/browser/resources/settings/settings_shared_css.html b/chrome/browser/resources/settings/settings_shared_css.html
index f5a4653..54203faf 100644
--- a/chrome/browser/resources/settings/settings_shared_css.html
+++ b/chrome/browser/resources/settings/settings_shared_css.html
@@ -27,6 +27,18 @@
        --iron-icon-fill-color: var(--google-green-500);
       }
 
+      paper-icon-button {
+        -webkit-margin-end: var(--cr-icon-ripple-margin);
+        -webkit-margin-start: 16px;
+        color: var(--paper-grey-600);
+        flex-shrink: 0;
+      }
+
+      .separator + button[is='paper-icon-button-light'],
+      .separator + paper-icon-button {
+        -webkit-margin-start: var(--cr-icon-ripple-margin));
+      }
+
       /* See notes in .primary-button.
        * TODO(dschuyler): Remove unnecessary .secondary-button references. */
       paper-button {
@@ -50,8 +62,19 @@
         background-color: var(--paper-grey-300);
       }
 
-      .settings-box paper-button {
+      /* If a button is at the end of the row, shift it to overlap the end of
+       * the row. */
+      .settings-box paper-button:last-of-type {
         -webkit-margin-end: calc(var(--settings-button-edge-spacing) * -1);
+      }
+
+      /* Space out multiple buttons in the same row. */
+      .settings-box paper-button + paper-button {
+        -webkit-margin-start: 16px;
+      }
+
+      /* Adjust the margin between the separator and the first button. */
+      .settings-box .separator + paper-button {
         -webkit-margin-start: calc(var(--settings-button-edge-spacing) * -1);
       }
 
diff --git a/chrome/browser/resources/settings/settings_ui/settings_ui.js b/chrome/browser/resources/settings/settings_ui/settings_ui.js
index 09c363c..707e8c82f 100644
--- a/chrome/browser/resources/settings/settings_ui/settings_ui.js
+++ b/chrome/browser/resources/settings/settings_ui/settings_ui.js
@@ -158,6 +158,14 @@
 
     this.showAndroidApps_ = loadTimeData.valueExists('androidAppsAllowed') &&
         loadTimeData.getBoolean('androidAppsAllowed');
+
+    this.addEventListener('show-container', function() {
+      this.$.container.style.visibility = 'visible';
+    }.bind(this));
+
+    this.addEventListener('hide-container', function() {
+      this.$.container.style.visibility = 'hidden';
+    }.bind(this));
   },
 
   /** @private {?IntersectionObserver} */
diff --git a/chrome/browser/resources_util_unittest.cc b/chrome/browser/resources_util_unittest.cc
index 5cc3853..e1ce86b9 100644
--- a/chrome/browser/resources_util_unittest.cc
+++ b/chrome/browser/resources_util_unittest.cc
@@ -8,7 +8,6 @@
 
 #include "base/macros.h"
 #include "build/build_config.h"
-#include "chrome/grit/theme_resources.h"
 #include "components/grit/components_scaled_resources.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "ui/resources/grit/ui_resources.h"
diff --git a/chrome/browser/safe_browsing/safe_browsing_blocking_page_unittest.cc b/chrome/browser/safe_browsing/safe_browsing_blocking_page_unittest.cc
index 9f19b8d..b4078913 100644
--- a/chrome/browser/safe_browsing/safe_browsing_blocking_page_unittest.cc
+++ b/chrome/browser/safe_browsing/safe_browsing_blocking_page_unittest.cc
@@ -14,7 +14,6 @@
 #include "chrome/test/base/chrome_render_view_host_test_harness.h"
 #include "chrome/test/base/testing_browser_process.h"
 #include "chrome/test/base/testing_profile.h"
-#include "components/grit/components_resources.h"
 #include "components/prefs/pref_service.h"
 #include "components/safe_browsing/browser/threat_details.h"
 #include "components/safe_browsing/common/safe_browsing_prefs.h"
diff --git a/chrome/browser/safe_browsing/settings_reset_prompt/settings_reset_prompt_controller.cc b/chrome/browser/safe_browsing/settings_reset_prompt/settings_reset_prompt_controller.cc
index 24d2a22..6a1cacd 100644
--- a/chrome/browser/safe_browsing/settings_reset_prompt/settings_reset_prompt_controller.cc
+++ b/chrome/browser/safe_browsing/settings_reset_prompt/settings_reset_prompt_controller.cc
@@ -20,7 +20,6 @@
 #include "chrome/browser/ui/browser.h"
 #include "chrome/browser/ui/browser_finder.h"
 #include "chrome/browser/ui/browser_window.h"
-#include "chrome/grit/chromium_strings.h"
 #include "chrome/grit/generated_resources.h"
 #include "components/url_formatter/elide_url.h"
 #include "content/public/browser/browser_thread.h"
diff --git a/chrome/browser/search/local_ntp_source.cc b/chrome/browser/search/local_ntp_source.cc
index 3e2a821c..3a10143 100644
--- a/chrome/browser/search/local_ntp_source.cc
+++ b/chrome/browser/search/local_ntp_source.cc
@@ -32,7 +32,6 @@
 #include "chrome/common/url_constants.h"
 #include "chrome/grit/browser_resources.h"
 #include "chrome/grit/generated_resources.h"
-#include "chrome/grit/theme_resources.h"
 #include "components/search_engines/template_url_service.h"
 #include "components/search_engines/template_url_service_observer.h"
 #include "components/strings/grit/components_strings.h"
diff --git a/chrome/browser/signin/signin_ui_util.cc b/chrome/browser/signin/signin_ui_util.cc
index fd894ec..d3f7aaf 100644
--- a/chrome/browser/signin/signin_ui_util.cc
+++ b/chrome/browser/signin/signin_ui_util.cc
@@ -17,14 +17,11 @@
 #include "chrome/browser/ui/browser_navigator.h"
 #include "chrome/browser/ui/browser_navigator_params.h"
 #include "chrome/common/pref_names.h"
-#include "chrome/grit/chromium_strings.h"
-#include "chrome/grit/generated_resources.h"
 #include "components/browser_sync/profile_sync_service.h"
 #include "components/prefs/pref_service.h"
 #include "components/signin/core/browser/account_tracker_service.h"
 #include "components/signin/core/browser/signin_manager.h"
 #include "components/signin/core/common/profile_management_switches.h"
-#include "components/strings/grit/components_strings.h"
 #include "components/user_manager/user_manager.h"
 #include "ui/base/l10n/l10n_util.h"
 #include "ui/gfx/font_list.h"
diff --git a/chrome/browser/sync/sync_ui_util.cc b/chrome/browser/sync/sync_ui_util.cc
index 0a4e259c..ce4e1fe 100644
--- a/chrome/browser/sync/sync_ui_util.cc
+++ b/chrome/browser/sync/sync_ui_util.cc
@@ -26,7 +26,6 @@
 #include "chrome/common/url_constants.h"
 #include "chrome/grit/chromium_strings.h"
 #include "chrome/grit/generated_resources.h"
-#include "chrome/grit/locale_settings.h"
 #include "components/browser_sync/profile_sync_service.h"
 #include "components/prefs/pref_service.h"
 #include "components/signin/core/browser/signin_error_controller.h"
diff --git a/chrome/browser/sync/sync_ui_util_unittest.cc b/chrome/browser/sync/sync_ui_util_unittest.cc
index 57d94f5..0077699 100644
--- a/chrome/browser/sync/sync_ui_util_unittest.cc
+++ b/chrome/browser/sync/sync_ui_util_unittest.cc
@@ -17,7 +17,6 @@
 #include "chrome/browser/signin/signin_manager_factory.h"
 #include "chrome/browser/sync/profile_sync_test_util.h"
 #include "chrome/browser/sync/sync_ui_util.h"
-#include "chrome/grit/generated_resources.h"
 #include "chrome/test/base/testing_profile.h"
 #include "components/browser_sync/profile_sync_service_mock.h"
 #include "components/signin/core/browser/fake_auth_status_provider.h"
diff --git a/chrome/browser/themes/browser_theme_pack.cc b/chrome/browser/themes/browser_theme_pack.cc
index 9205d3a..a352c67 100644
--- a/chrome/browser/themes/browser_theme_pack.cc
+++ b/chrome/browser/themes/browser_theme_pack.cc
@@ -37,7 +37,6 @@
 #include "ui/gfx/image/image_skia.h"
 #include "ui/gfx/image/image_skia_operations.h"
 #include "ui/gfx/skia_util.h"
-#include "ui/resources/grit/ui_resources.h"
 
 using content::BrowserThread;
 using extensions::Extension;
diff --git a/chrome/browser/themes/theme_properties.cc b/chrome/browser/themes/theme_properties.cc
index 92c0123..b04c65bc 100644
--- a/chrome/browser/themes/theme_properties.cc
+++ b/chrome/browser/themes/theme_properties.cc
@@ -12,10 +12,8 @@
 #include "build/build_config.h"
 #include "chrome/browser/themes/browser_theme_pack.h"
 #include "chrome/common/chrome_features.h"
-#include "chrome/grit/theme_resources.h"
 #include "ui/base/material_design/material_design_controller.h"
 #include "ui/gfx/color_palette.h"
-#include "ui/resources/grit/ui_resources.h"
 
 namespace {
 
diff --git a/chrome/browser/ui/android/page_info/connection_info_popup_android.cc b/chrome/browser/ui/android/page_info/connection_info_popup_android.cc
index b36826f..6ea9590 100644
--- a/chrome/browser/ui/android/page_info/connection_info_popup_android.cc
+++ b/chrome/browser/ui/android/page_info/connection_info_popup_android.cc
@@ -12,7 +12,6 @@
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/ssl/security_state_tab_helper.h"
 #include "chrome/browser/ui/page_info/page_info.h"
-#include "chrome/grit/generated_resources.h"
 #include "components/security_state/core/security_state.h"
 #include "components/strings/grit/components_strings.h"
 #include "content/public/browser/browser_context.h"
diff --git a/chrome/browser/ui/app_list/extension_app_item.cc b/chrome/browser/ui/app_list/extension_app_item.cc
index a945dc4..d468724 100644
--- a/chrome/browser/ui/app_list/extension_app_item.cc
+++ b/chrome/browser/ui/app_list/extension_app_item.cc
@@ -19,7 +19,6 @@
 #include "chrome/browser/ui/extensions/extension_enable_flow.h"
 #include "chrome/common/extensions/extension_constants.h"
 #include "chrome/common/extensions/extension_metrics.h"
-#include "chrome/grit/theme_resources.h"
 #include "components/prefs/pref_service.h"
 #include "components/sync/model/string_ordinal.h"
 #include "extensions/browser/app_sorting.h"
diff --git a/chrome/browser/ui/app_list/search/search_resource_manager.cc b/chrome/browser/ui/app_list/search/search_resource_manager.cc
index ed1745fe..fcf3fa4 100644
--- a/chrome/browser/ui/app_list/search/search_resource_manager.cc
+++ b/chrome/browser/ui/app_list/search/search_resource_manager.cc
@@ -8,7 +8,6 @@
 #include "chrome/browser/ui/app_list/start_page_service.h"
 #include "chrome/grit/generated_resources.h"
 #include "chrome/grit/theme_resources.h"
-#include "components/grit/components_scaled_resources.h"
 #include "ui/app_list/search_box_model.h"
 #include "ui/app_list/speech_ui_model.h"
 #include "ui/base/l10n/l10n_util.h"
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 a0f9487b..2246036a 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
@@ -73,11 +73,6 @@
   DISALLOW_COPY_AND_ASSIGN(SearchAnswerWebView);
 };
 
-bool IsCardSizeOk(const gfx::Size& size) {
-  return size.width() <= features::AnswerCardMaxWidth() &&
-         size.height() <= features::AnswerCardMaxHeight();
-}
-
 }  // namespace
 
 SearchAnswerWebContentsDelegate::SearchAnswerWebContentsDelegate(
@@ -132,7 +127,6 @@
   model_->SetSearchAnswerAvailable(false);
   current_request_url_ = GURL();
   server_request_start_time_ = answer_loaded_time_ = base::TimeTicks();
-  is_card_size_ok_ = false;
 
   if (model_->search_box()->is_voice_query()) {
     // No need to send a server request and show a card because launcher
@@ -170,9 +164,7 @@
 void SearchAnswerWebContentsDelegate::UpdatePreferredSize(
     content::WebContents* web_contents,
     const gfx::Size& pref_size) {
-  is_card_size_ok_ =
-      IsCardSizeOk(pref_size) || features::IsAnswerCardDarkRunEnabled();
-  model_->SetSearchAnswerAvailable(is_card_size_ok_ && received_answer_ &&
+  model_->SetSearchAnswerAvailable(received_answer_ && IsCardSizeOk() &&
                                    !web_contents_->IsLoading());
   web_view_->SetPreferredSize(pref_size);
   if (!answer_loaded_time_.is_null()) {
@@ -254,7 +246,7 @@
   if (!received_answer_)
     return;
 
-  if (is_card_size_ok_)
+  if (IsCardSizeOk())
     model_->SetSearchAnswerAvailable(true);
   answer_loaded_time_ = base::TimeTicks::Now();
   UMA_HISTOGRAM_TIMES("SearchAnswer.LoadingTime",
@@ -272,6 +264,15 @@
   Update();
 }
 
+bool SearchAnswerWebContentsDelegate::IsCardSizeOk() const {
+  if (features::IsAnswerCardDarkRunEnabled())
+    return true;
+
+  const gfx::Size size = web_contents_->GetPreferredSize();
+  return size.width() <= features::AnswerCardMaxWidth() &&
+         size.height() <= features::AnswerCardMaxHeight();
+}
+
 void SearchAnswerWebContentsDelegate::RecordReceivedAnswerFinalResult() {
   // Recording whether a server response with an answer contains a card of a
   // fitting size, or a too large one. Cannot do this in DidStopLoading() or
@@ -281,10 +282,9 @@
     return;
 
   RecordRequestResult(
-      is_card_size_ok_
-          ? SearchAnswerRequestResult::REQUEST_RESULT_RECEIVED_ANSWER
-          : SearchAnswerRequestResult::
-                REQUEST_RESULT_RECEIVED_ANSWER_TOO_LARGE);
+      IsCardSizeOk() ? SearchAnswerRequestResult::REQUEST_RESULT_RECEIVED_ANSWER
+                     : SearchAnswerRequestResult::
+                           REQUEST_RESULT_RECEIVED_ANSWER_TOO_LARGE);
 }
 
 }  // namespace app_list
diff --git a/chrome/browser/ui/app_list/search_answer_web_contents_delegate.h b/chrome/browser/ui/app_list/search_answer_web_contents_delegate.h
index 824e4ec..b56c8531 100644
--- a/chrome/browser/ui/app_list/search_answer_web_contents_delegate.h
+++ b/chrome/browser/ui/app_list/search_answer_web_contents_delegate.h
@@ -66,6 +66,7 @@
   void OnSearchEngineIsGoogleChanged(bool is_google) override;
 
  private:
+  bool IsCardSizeOk() const;
   void RecordReceivedAnswerFinalResult();
 
   // Unowned pointer to the associated profile.
@@ -100,9 +101,6 @@
   // response contains an answer.
   bool dark_run_received_answer_ = false;
 
-  // Whether the answer card dimensions are not too large.
-  bool is_card_size_ok_ = false;
-
   DISALLOW_COPY_AND_ASSIGN(SearchAnswerWebContentsDelegate);
 };
 
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 359bf41..f2b20a0 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
@@ -27,7 +27,6 @@
 #include "chrome/browser/ui/tabs/tab_strip_model.h"
 #include "chrome/browser/web_applications/web_app.h"
 #include "chrome/common/extensions/extension_constants.h"
-#include "chrome/grit/chromium_strings.h"
 #include "chrome/grit/generated_resources.h"
 #include "components/strings/grit/components_strings.h"
 #include "content/public/browser/web_contents.h"
diff --git a/chrome/browser/ui/ash/system_tray_delegate_chromeos.cc b/chrome/browser/ui/ash/system_tray_delegate_chromeos.cc
index 8231fbdc..630dbdb7 100644
--- a/chrome/browser/ui/ash/system_tray_delegate_chromeos.cc
+++ b/chrome/browser/ui/ash/system_tray_delegate_chromeos.cc
@@ -49,7 +49,6 @@
 #include "chrome/common/features.h"
 #include "chrome/common/pref_names.h"
 #include "chrome/grit/generated_resources.h"
-#include "chrome/grit/locale_settings.h"
 #include "chromeos/login/login_state.h"
 #include "chromeos/network/portal_detector/network_portal_detector.h"
 #include "components/google/core/browser/google_util.h"
diff --git a/chrome/browser/ui/autofill/password_generation_popup_controller_impl.cc b/chrome/browser/ui/autofill/password_generation_popup_controller_impl.cc
index c4a4fd8..bf704cd 100644
--- a/chrome/browser/ui/autofill/password_generation_popup_controller_impl.cc
+++ b/chrome/browser/ui/autofill/password_generation_popup_controller_impl.cc
@@ -19,7 +19,6 @@
 #include "chrome/browser/ui/browser_navigator_params.h"
 #include "chrome/common/url_constants.h"
 #include "chrome/grit/chromium_strings.h"
-#include "chrome/grit/generated_resources.h"
 #include "components/autofill/content/browser/content_autofill_driver.h"
 #include "components/autofill/content/browser/content_autofill_driver_factory.h"
 #include "components/autofill/core/browser/password_generator.h"
diff --git a/chrome/browser/ui/bookmarks/bookmark_utils_desktop.cc b/chrome/browser/ui/bookmarks/bookmark_utils_desktop.cc
index d429ad7..f8115749 100644
--- a/chrome/browser/ui/bookmarks/bookmark_utils_desktop.cc
+++ b/chrome/browser/ui/bookmarks/bookmark_utils_desktop.cc
@@ -48,7 +48,6 @@
 #endif
 
 #if defined(OS_WIN)
-#include "chrome/grit/theme_resources.h"
 #include "ui/base/material_design/material_design_controller.h"
 #include "ui/base/resource/resource_bundle.h"
 #endif
diff --git a/chrome/browser/ui/browser.cc b/chrome/browser/ui/browser.cc
index 92f9f79..c94dca161 100644
--- a/chrome/browser/ui/browser.cc
+++ b/chrome/browser/ui/browser.cc
@@ -154,8 +154,6 @@
 #include "chrome/common/ssl_insecure_content.h"
 #include "chrome/common/url_constants.h"
 #include "chrome/grit/chromium_strings.h"
-#include "chrome/grit/generated_resources.h"
-#include "chrome/grit/locale_settings.h"
 #include "components/bookmarks/browser/bookmark_model.h"
 #include "components/bookmarks/browser/bookmark_utils.h"
 #include "components/bookmarks/common/bookmark_pref_names.h"
diff --git a/chrome/browser/ui/cocoa/autofill/card_unmask_prompt_view_bridge.mm b/chrome/browser/ui/cocoa/autofill/card_unmask_prompt_view_bridge.mm
index b35f4e07..7a0b713 100644
--- a/chrome/browser/ui/cocoa/autofill/card_unmask_prompt_view_bridge.mm
+++ b/chrome/browser/ui/cocoa/autofill/card_unmask_prompt_view_bridge.mm
@@ -21,9 +21,7 @@
 #import "chrome/browser/ui/cocoa/l10n_util.h"
 #import "chrome/browser/ui/cocoa/spinner_view.h"
 #include "chrome/browser/ui/cocoa/themed_window.h"
-#include "chrome/grit/generated_resources.h"
 #include "components/autofill/core/browser/ui/card_unmask_prompt_controller.h"
-#include "components/grit/components_scaled_resources.h"
 #include "components/strings/grit/components_strings.h"
 #include "content/public/browser/web_contents.h"
 #include "skia/ext/skia_utils_mac.h"
diff --git a/chrome/browser/ui/cocoa/bookmarks/bookmark_all_tabs_controller.mm b/chrome/browser/ui/cocoa/bookmarks/bookmark_all_tabs_controller.mm
index 22b4d811..6dd4ac6 100644
--- a/chrome/browser/ui/cocoa/bookmarks/bookmark_all_tabs_controller.mm
+++ b/chrome/browser/ui/cocoa/bookmarks/bookmark_all_tabs_controller.mm
@@ -10,7 +10,6 @@
 #include "chrome/browser/ui/browser_tabstrip.h"
 #include "chrome/browser/ui/cocoa/last_active_browser_cocoa.h"
 #include "chrome/browser/ui/tabs/tab_strip_model.h"
-#include "chrome/grit/generated_resources.h"
 #include "components/bookmarks/browser/bookmark_model.h"
 #include "components/strings/grit/components_strings.h"
 #include "content/public/browser/web_contents.h"
diff --git a/chrome/browser/ui/cocoa/bookmarks/bookmark_bar_controller.mm b/chrome/browser/ui/cocoa/bookmarks/bookmark_bar_controller.mm
index a0f22b0..ce61c46c 100644
--- a/chrome/browser/ui/cocoa/bookmarks/bookmark_bar_controller.mm
+++ b/chrome/browser/ui/cocoa/bookmarks/bookmark_bar_controller.mm
@@ -76,7 +76,6 @@
 #include "ui/gfx/image/image.h"
 #include "ui/gfx/image/image_skia_util_mac.h"
 #include "ui/gfx/paint_vector_icon.h"
-#include "ui/resources/grit/ui_resources.h"
 
 using base::UserMetricsAction;
 using bookmarks::BookmarkBarLayout;
diff --git a/chrome/browser/ui/cocoa/bookmarks/bookmark_editor_base_controller.mm b/chrome/browser/ui/cocoa/bookmarks/bookmark_editor_base_controller.mm
index 5432432c..e1721311 100644
--- a/chrome/browser/ui/cocoa/bookmarks/bookmark_editor_base_controller.mm
+++ b/chrome/browser/ui/cocoa/bookmarks/bookmark_editor_base_controller.mm
@@ -20,7 +20,6 @@
 #import "chrome/browser/ui/cocoa/bookmarks/bookmark_name_folder_controller.h"
 #import "chrome/browser/ui/cocoa/bookmarks/bookmark_tree_browser_cell.h"
 #import "chrome/browser/ui/cocoa/browser_window_controller.h"
-#include "chrome/grit/generated_resources.h"
 #include "components/bookmarks/browser/bookmark_model.h"
 #include "components/bookmarks/managed/managed_bookmark_service.h"
 #include "components/strings/grit/components_strings.h"
diff --git a/chrome/browser/ui/cocoa/bookmarks/bookmark_editor_base_controller_unittest.mm b/chrome/browser/ui/cocoa/bookmarks/bookmark_editor_base_controller_unittest.mm
index 98d5d3b..73c777c 100644
--- a/chrome/browser/ui/cocoa/bookmarks/bookmark_editor_base_controller_unittest.mm
+++ b/chrome/browser/ui/cocoa/bookmarks/bookmark_editor_base_controller_unittest.mm
@@ -9,7 +9,6 @@
 #include "chrome/browser/bookmarks/bookmark_model_factory.h"
 #import "chrome/browser/ui/cocoa/bookmarks/bookmark_editor_controller.h"
 #include "chrome/browser/ui/cocoa/test/cocoa_profile_test.h"
-#include "chrome/grit/generated_resources.h"
 #include "chrome/test/base/test_browser_window.h"
 #include "chrome/test/base/testing_profile.h"
 #include "components/bookmarks/browser/bookmark_model.h"
diff --git a/chrome/browser/ui/cocoa/bookmarks/bookmark_menu_bridge_unittest.mm b/chrome/browser/ui/cocoa/bookmarks/bookmark_menu_bridge_unittest.mm
index 6a03901..0177358 100644
--- a/chrome/browser/ui/cocoa/bookmarks/bookmark_menu_bridge_unittest.mm
+++ b/chrome/browser/ui/cocoa/bookmarks/bookmark_menu_bridge_unittest.mm
@@ -10,7 +10,6 @@
 #include "chrome/app/chrome_command_ids.h"
 #include "chrome/browser/ui/cocoa/bookmarks/bookmark_menu_bridge.h"
 #include "chrome/browser/ui/cocoa/test/cocoa_profile_test.h"
-#include "chrome/grit/generated_resources.h"
 #include "chrome/test/base/testing_profile.h"
 #include "components/bookmarks/browser/bookmark_model.h"
 #include "testing/gtest/include/gtest/gtest.h"
diff --git a/chrome/browser/ui/cocoa/bookmarks/bookmark_name_folder_controller.mm b/chrome/browser/ui/cocoa/bookmarks/bookmark_name_folder_controller.mm
index ded2f66..0ec930e 100644
--- a/chrome/browser/ui/cocoa/bookmarks/bookmark_name_folder_controller.mm
+++ b/chrome/browser/ui/cocoa/bookmarks/bookmark_name_folder_controller.mm
@@ -9,7 +9,6 @@
 #include "chrome/browser/bookmarks/bookmark_model_factory.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/ui/cocoa/bookmarks/bookmark_model_observer_for_cocoa.h"
-#include "chrome/grit/generated_resources.h"
 #include "components/strings/grit/components_strings.h"
 #include "ui/base/l10n/l10n_util.h"
 #include "ui/base/l10n/l10n_util_mac.h"
diff --git a/chrome/browser/ui/cocoa/extensions/browser_action_button.mm b/chrome/browser/ui/cocoa/extensions/browser_action_button.mm
index 18312c17..7cc9c45 100644
--- a/chrome/browser/ui/cocoa/extensions/browser_action_button.mm
+++ b/chrome/browser/ui/cocoa/extensions/browser_action_button.mm
@@ -23,7 +23,6 @@
 #include "chrome/browser/ui/toolbar/toolbar_action_view_controller.h"
 #include "chrome/browser/ui/toolbar/toolbar_action_view_delegate.h"
 #include "chrome/browser/ui/toolbar/toolbar_actions_bar.h"
-#include "chrome/grit/theme_resources.h"
 #include "skia/ext/skia_utils_mac.h"
 #import "third_party/google_toolbox_for_mac/src/AppKit/GTMNSAnimation+Duration.h"
 #import "ui/base/cocoa/menu_controller.h"
diff --git a/chrome/browser/ui/cocoa/extensions/toolbar_actions_bar_bubble_mac_unittest.mm b/chrome/browser/ui/cocoa/extensions/toolbar_actions_bar_bubble_mac_unittest.mm
index 97c5f6d0..638c94a4 100644
--- a/chrome/browser/ui/cocoa/extensions/toolbar_actions_bar_bubble_mac_unittest.mm
+++ b/chrome/browser/ui/cocoa/extensions/toolbar_actions_bar_bubble_mac_unittest.mm
@@ -13,7 +13,6 @@
 #include "chrome/browser/ui/cocoa/test/run_loop_testing.h"
 #include "chrome/browser/ui/toolbar/test_toolbar_actions_bar_bubble_delegate.h"
 #include "chrome/grit/generated_resources.h"
-#include "components/grit/components_scaled_resources.h"
 #include "ui/base/l10n/l10n_util.h"
 #import "ui/events/test/cocoa_test_event_utils.h"
 #include "ui/vector_icons/vector_icons.h"
diff --git a/chrome/browser/ui/cocoa/external_protocol_dialog_cocoa.mm b/chrome/browser/ui/cocoa/external_protocol_dialog_cocoa.mm
index e3d7b8f..6f26067f 100644
--- a/chrome/browser/ui/cocoa/external_protocol_dialog_cocoa.mm
+++ b/chrome/browser/ui/cocoa/external_protocol_dialog_cocoa.mm
@@ -12,7 +12,6 @@
 #include "chrome/browser/tab_contents/tab_util.h"
 #include "chrome/grit/chromium_strings.h"
 #include "chrome/grit/generated_resources.h"
-#include "components/strings/grit/components_strings.h"
 #include "ui/base/l10n/l10n_util_mac.h"
 #include "ui/gfx/text_elider.h"
 
diff --git a/chrome/browser/ui/cocoa/find_bar/find_bar_cocoa_controller.mm b/chrome/browser/ui/cocoa/find_bar/find_bar_cocoa_controller.mm
index 5195ecc..70013f04 100644
--- a/chrome/browser/ui/cocoa/find_bar/find_bar_cocoa_controller.mm
+++ b/chrome/browser/ui/cocoa/find_bar/find_bar_cocoa_controller.mm
@@ -33,7 +33,6 @@
 #include "ui/base/resource/resource_bundle.h"
 #include "ui/gfx/image/image_skia_util_mac.h"
 #include "ui/gfx/paint_vector_icon.h"
-#include "ui/resources/grit/ui_resources.h"
 
 using content::NativeWebKeyboardEvent;
 
diff --git a/chrome/browser/ui/cocoa/first_run_dialog_controller.mm b/chrome/browser/ui/cocoa/first_run_dialog_controller.mm
index 0793a05..96ca4f5e 100644
--- a/chrome/browser/ui/cocoa/first_run_dialog_controller.mm
+++ b/chrome/browser/ui/cocoa/first_run_dialog_controller.mm
@@ -9,7 +9,6 @@
 #include "chrome/browser/ui/cocoa/l10n_util.h"
 #include "chrome/grit/chromium_strings.h"
 #include "chrome/grit/generated_resources.h"
-#include "components/strings/grit/components_strings.h"
 #include "ui/base/cocoa/controls/button_utils.h"
 #include "ui/base/cocoa/controls/textfield_utils.h"
 #include "ui/base/l10n/l10n_util.h"
diff --git a/chrome/browser/ui/cocoa/history_menu_bridge.mm b/chrome/browser/ui/cocoa/history_menu_bridge.mm
index 904ff50..d79d437 100644
--- a/chrome/browser/ui/cocoa/history_menu_bridge.mm
+++ b/chrome/browser/ui/cocoa/history_menu_bridge.mm
@@ -19,7 +19,6 @@
 #include "chrome/browser/sessions/tab_restore_service_factory.h"
 #import "chrome/browser/ui/cocoa/history_menu_cocoa_controller.h"
 #include "chrome/grit/generated_resources.h"
-#include "chrome/grit/theme_resources.h"
 #include "components/grit/components_scaled_resources.h"
 #include "ui/base/l10n/l10n_util.h"
 #include "ui/base/resource/resource_bundle.h"
diff --git a/chrome/browser/ui/cocoa/infobars/infobar_controller.mm b/chrome/browser/ui/cocoa/infobars/infobar_controller.mm
index 965f5f18..b495a2c 100644
--- a/chrome/browser/ui/cocoa/infobars/infobar_controller.mm
+++ b/chrome/browser/ui/cocoa/infobars/infobar_controller.mm
@@ -17,14 +17,12 @@
 #import "chrome/browser/ui/cocoa/infobars/infobar_gradient_view.h"
 #include "chrome/browser/ui/cocoa/l10n_util.h"
 #import "chrome/browser/ui/cocoa/location_bar/location_bar_view_mac.h"
-#include "chrome/grit/generated_resources.h"
 #include "chrome/grit/theme_resources.h"
 #include "components/strings/grit/components_strings.h"
 #import "ui/base/cocoa/controls/hyperlink_text_view.h"
 #include "ui/base/l10n/l10n_util_mac.h"
 #include "ui/base/material_design/material_design_controller.h"
 #include "ui/gfx/image/image.h"
-#include "ui/resources/grit/ui_resources.h"
 
 @interface InfoBarController ()
 // Sets |label_| based on |labelPlaceholder_|, sets |labelPlaceholder_| to nil.
diff --git a/chrome/browser/ui/cocoa/location_bar/autocomplete_text_field_cell.mm b/chrome/browser/ui/cocoa/location_bar/autocomplete_text_field_cell.mm
index b4d3a57..3b642be 100644
--- a/chrome/browser/ui/cocoa/location_bar/autocomplete_text_field_cell.mm
+++ b/chrome/browser/ui/cocoa/location_bar/autocomplete_text_field_cell.mm
@@ -15,7 +15,6 @@
 #import "chrome/browser/ui/cocoa/location_bar/autocomplete_text_field.h"
 #import "chrome/browser/ui/cocoa/location_bar/location_bar_decoration.h"
 #import "chrome/browser/ui/cocoa/themed_window.h"
-#include "chrome/grit/theme_resources.h"
 #import "extensions/common/feature_switch.h"
 #import "third_party/mozilla/NSPasteboard+Utils.h"
 #import "ui/base/cocoa/appkit_utils.h"
diff --git a/chrome/browser/ui/cocoa/location_bar/content_setting_decoration.mm b/chrome/browser/ui/cocoa/location_bar/content_setting_decoration.mm
index 9bed979..160f4ff 100644
--- a/chrome/browser/ui/cocoa/location_bar/content_setting_decoration.mm
+++ b/chrome/browser/ui/cocoa/location_bar/content_setting_decoration.mm
@@ -20,7 +20,6 @@
 #import "chrome/browser/ui/cocoa/themed_window.h"
 #include "chrome/browser/ui/content_settings/content_setting_bubble_model.h"
 #include "chrome/browser/ui/content_settings/content_setting_image_model.h"
-#include "chrome/grit/theme_resources.h"
 #include "components/prefs/pref_service.h"
 #include "content/public/browser/web_contents.h"
 #include "skia/ext/skia_utils_mac.h"
diff --git a/chrome/browser/ui/cocoa/location_bar/location_bar_view_mac.mm b/chrome/browser/ui/cocoa/location_bar/location_bar_view_mac.mm
index 34466be..66bf15cd 100644
--- a/chrome/browser/ui/cocoa/location_bar/location_bar_view_mac.mm
+++ b/chrome/browser/ui/cocoa/location_bar/location_bar_view_mac.mm
@@ -48,9 +48,7 @@
 #include "chrome/browser/ui/tabs/tab_strip_model.h"
 #include "chrome/common/pref_names.h"
 #include "chrome/grit/chromium_strings.h"
-#include "chrome/grit/theme_resources.h"
 #include "components/bookmarks/common/bookmark_pref_names.h"
-#include "components/grit/components_scaled_resources.h"
 #import "components/omnibox/browser/omnibox_popup_model.h"
 #include "components/prefs/pref_service.h"
 #include "components/search_engines/template_url.h"
diff --git a/chrome/browser/ui/cocoa/location_bar/star_decoration.mm b/chrome/browser/ui/cocoa/location_bar/star_decoration.mm
index 245da9fa..c0ef97149 100644
--- a/chrome/browser/ui/cocoa/location_bar/star_decoration.mm
+++ b/chrome/browser/ui/cocoa/location_bar/star_decoration.mm
@@ -9,7 +9,6 @@
 #import "chrome/browser/ui/cocoa/omnibox/omnibox_view_mac.h"
 #import "chrome/browser/ui/cocoa/themed_window.h"
 #include "chrome/grit/generated_resources.h"
-#include "chrome/grit/theme_resources.h"
 #include "components/strings/grit/components_strings.h"
 #include "components/toolbar/vector_icons.h"
 #include "ui/base/l10n/l10n_util_mac.h"
diff --git a/chrome/browser/ui/cocoa/location_bar/translate_decoration.mm b/chrome/browser/ui/cocoa/location_bar/translate_decoration.mm
index 34b6ea1..d6b2cabab 100644
--- a/chrome/browser/ui/cocoa/location_bar/translate_decoration.mm
+++ b/chrome/browser/ui/cocoa/location_bar/translate_decoration.mm
@@ -9,7 +9,6 @@
 #include "chrome/browser/command_updater.h"
 #import "chrome/browser/ui/cocoa/omnibox/omnibox_view_mac.h"
 #include "chrome/grit/generated_resources.h"
-#include "chrome/grit/theme_resources.h"
 #include "ui/base/l10n/l10n_util_mac.h"
 #include "ui/base/material_design/material_design_controller.h"
 
diff --git a/chrome/browser/ui/cocoa/location_bar/zoom_decoration.mm b/chrome/browser/ui/cocoa/location_bar/zoom_decoration.mm
index 96a056e..807dc21 100644
--- a/chrome/browser/ui/cocoa/location_bar/zoom_decoration.mm
+++ b/chrome/browser/ui/cocoa/location_bar/zoom_decoration.mm
@@ -17,7 +17,6 @@
 #import "chrome/browser/ui/cocoa/location_bar/location_bar_view_mac.h"
 #import "chrome/browser/ui/cocoa/omnibox/omnibox_view_mac.h"
 #include "chrome/grit/generated_resources.h"
-#include "chrome/grit/theme_resources.h"
 #include "components/zoom/zoom_controller.h"
 #include "ui/base/cocoa/cocoa_base_utils.h"
 #include "ui/base/l10n/l10n_util_mac.h"
diff --git a/chrome/browser/ui/cocoa/omnibox/omnibox_popup_view_mac.mm b/chrome/browser/ui/cocoa/omnibox/omnibox_popup_view_mac.mm
index 40066e8d..797ca910 100644
--- a/chrome/browser/ui/cocoa/omnibox/omnibox_popup_view_mac.mm
+++ b/chrome/browser/ui/cocoa/omnibox/omnibox_popup_view_mac.mm
@@ -15,7 +15,6 @@
 #import "chrome/browser/ui/cocoa/omnibox/omnibox_popup_cell.h"
 #import "chrome/browser/ui/cocoa/omnibox/omnibox_popup_separator_view.h"
 #include "chrome/browser/ui/cocoa/omnibox/omnibox_view_mac.h"
-#include "chrome/grit/theme_resources.h"
 #include "components/omnibox/browser/autocomplete_match.h"
 #include "components/omnibox/browser/autocomplete_match_type.h"
 #include "components/omnibox/browser/omnibox_edit_model.h"
diff --git a/chrome/browser/ui/cocoa/omnibox/omnibox_view_mac.mm b/chrome/browser/ui/cocoa/omnibox/omnibox_view_mac.mm
index d307900..4296eb52 100644
--- a/chrome/browser/ui/cocoa/omnibox/omnibox_view_mac.mm
+++ b/chrome/browser/ui/cocoa/omnibox/omnibox_view_mac.mm
@@ -25,8 +25,6 @@
 #include "chrome/browser/ui/omnibox/chrome_omnibox_client.h"
 #include "chrome/browser/ui/omnibox/clipboard_utils.h"
 #include "chrome/grit/generated_resources.h"
-#include "chrome/grit/theme_resources.h"
-#include "components/grit/components_scaled_resources.h"
 #include "components/omnibox/browser/autocomplete_input.h"
 #include "components/omnibox/browser/autocomplete_match.h"
 #include "components/omnibox/browser/omnibox_edit_controller.h"
diff --git a/chrome/browser/ui/cocoa/one_click_signin_view_controller.mm b/chrome/browser/ui/cocoa/one_click_signin_view_controller.mm
index 7c63ce0..753e521 100644
--- a/chrome/browser/ui/cocoa/one_click_signin_view_controller.mm
+++ b/chrome/browser/ui/cocoa/one_click_signin_view_controller.mm
@@ -10,7 +10,6 @@
 #import "chrome/browser/ui/cocoa/chrome_style.h"
 #include "chrome/common/url_constants.h"
 #include "chrome/grit/chromium_strings.h"
-#include "chrome/grit/generated_resources.h"
 #include "components/signin/core/browser/signin_metrics.h"
 #include "components/strings/grit/components_strings.h"
 #include "content/public/browser/web_contents.h"
diff --git a/chrome/browser/ui/cocoa/page_info/page_info_bubble_controller.mm b/chrome/browser/ui/cocoa/page_info/page_info_bubble_controller.mm
index c5c727c..e237b99 100644
--- a/chrome/browser/ui/cocoa/page_info/page_info_bubble_controller.mm
+++ b/chrome/browser/ui/cocoa/page_info/page_info_bubble_controller.mm
@@ -25,8 +25,6 @@
 #include "chrome/browser/ui/page_info/permission_menu_model.h"
 #import "chrome/browser/ui/tab_dialogs.h"
 #include "chrome/common/url_constants.h"
-#include "chrome/grit/chromium_strings.h"
-#include "chrome/grit/generated_resources.h"
 #include "chrome/grit/theme_resources.h"
 #include "components/strings/grit/components_chromium_strings.h"
 #include "components/strings/grit/components_strings.h"
diff --git a/chrome/browser/ui/cocoa/passwords/account_chooser_view_controller.mm b/chrome/browser/ui/cocoa/passwords/account_chooser_view_controller.mm
index 692b9dc..ce5b937 100644
--- a/chrome/browser/ui/cocoa/passwords/account_chooser_view_controller.mm
+++ b/chrome/browser/ui/cocoa/passwords/account_chooser_view_controller.mm
@@ -16,7 +16,6 @@
 #include "chrome/browser/ui/passwords/password_dialog_controller.h"
 #include "chrome/browser/ui/passwords/password_dialog_prompts.h"
 #include "chrome/grit/generated_resources.h"
-#include "chrome/grit/theme_resources.h"
 #include "components/autofill/core/common/password_form.h"
 #include "components/password_manager/core/common/credential_manager_types.h"
 #include "skia/ext/skia_utils_mac.h"
diff --git a/chrome/browser/ui/cocoa/passwords/confirmation_password_saved_view_controller.mm b/chrome/browser/ui/cocoa/passwords/confirmation_password_saved_view_controller.mm
index e24db77f..115dac3b 100644
--- a/chrome/browser/ui/cocoa/passwords/confirmation_password_saved_view_controller.mm
+++ b/chrome/browser/ui/cocoa/passwords/confirmation_password_saved_view_controller.mm
@@ -10,7 +10,6 @@
 #include "chrome/browser/ui/cocoa/chrome_style.h"
 #import "chrome/browser/ui/cocoa/passwords/passwords_bubble_utils.h"
 #include "chrome/browser/ui/passwords/manage_passwords_bubble_model.h"
-#include "chrome/grit/generated_resources.h"
 #include "components/strings/grit/components_strings.h"
 #include "skia/ext/skia_utils_mac.h"
 #import "third_party/google_toolbox_for_mac/src/AppKit/GTMUILocalizerAndLayoutTweaker.h"
diff --git a/chrome/browser/ui/cocoa/passwords/pending_password_view_controller.mm b/chrome/browser/ui/cocoa/passwords/pending_password_view_controller.mm
index 5f05955..82ca03c 100644
--- a/chrome/browser/ui/cocoa/passwords/pending_password_view_controller.mm
+++ b/chrome/browser/ui/cocoa/passwords/pending_password_view_controller.mm
@@ -12,7 +12,6 @@
 #import "chrome/browser/ui/cocoa/hover_close_button.h"
 #import "chrome/browser/ui/cocoa/passwords/passwords_bubble_utils.h"
 #include "chrome/browser/ui/passwords/manage_passwords_bubble_model.h"
-#include "chrome/grit/generated_resources.h"
 #include "skia/ext/skia_utils_mac.h"
 #import "ui/base/cocoa/controls/hyperlink_text_view.h"
 #include "ui/base/l10n/l10n_util.h"
diff --git a/chrome/browser/ui/cocoa/profiles/avatar_button_controller.mm b/chrome/browser/ui/cocoa/profiles/avatar_button_controller.mm
index 0be5d23..69a1cd0 100644
--- a/chrome/browser/ui/cocoa/profiles/avatar_button_controller.mm
+++ b/chrome/browser/ui/cocoa/profiles/avatar_button_controller.mm
@@ -20,7 +20,6 @@
 #import "chrome/browser/ui/cocoa/browser_window_controller.h"
 #import "chrome/browser/ui/cocoa/profiles/avatar_button.h"
 #include "chrome/grit/generated_resources.h"
-#include "chrome/grit/theme_resources.h"
 #include "components/signin/core/common/profile_management_switches.h"
 #include "skia/ext/skia_utils_mac.h"
 #import "ui/base/cocoa/appkit_utils.h"
diff --git a/chrome/browser/ui/cocoa/profiles/avatar_button_controller_unittest.mm b/chrome/browser/ui/cocoa/profiles/avatar_button_controller_unittest.mm
index 08baac5..66db9c1 100644
--- a/chrome/browser/ui/cocoa/profiles/avatar_button_controller_unittest.mm
+++ b/chrome/browser/ui/cocoa/profiles/avatar_button_controller_unittest.mm
@@ -17,8 +17,6 @@
 #import "chrome/browser/ui/cocoa/profiles/profile_chooser_controller.h"
 #include "chrome/browser/ui/cocoa/test/cocoa_profile_test.h"
 #include "chrome/common/chrome_switches.h"
-#include "chrome/grit/generated_resources.h"
-#include "chrome/grit/theme_resources.h"
 #include "components/signin/core/common/profile_management_switches.h"
 #import "testing/gtest_mac.h"
 #include "ui/base/material_design/material_design_controller.h"
diff --git a/chrome/browser/ui/cocoa/profiles/avatar_icon_controller.mm b/chrome/browser/ui/cocoa/profiles/avatar_icon_controller.mm
index 9e3b0ac..b9dc866 100644
--- a/chrome/browser/ui/cocoa/profiles/avatar_icon_controller.mm
+++ b/chrome/browser/ui/cocoa/profiles/avatar_icon_controller.mm
@@ -13,7 +13,6 @@
 #include "chrome/browser/profiles/profile_avatar_icon_util.h"
 #include "chrome/browser/ui/browser.h"
 #include "chrome/grit/generated_resources.h"
-#include "chrome/grit/theme_resources.h"
 #include "ui/base/l10n/l10n_util_mac.h"
 #include "ui/base/material_design/material_design_controller.h"
 #include "ui/base/resource/resource_bundle.h"
diff --git a/chrome/browser/ui/cocoa/tab_contents/favicon_util_mac.mm b/chrome/browser/ui/cocoa/tab_contents/favicon_util_mac.mm
index 4a0ea98..d6b8435e 100644
--- a/chrome/browser/ui/cocoa/tab_contents/favicon_util_mac.mm
+++ b/chrome/browser/ui/cocoa/tab_contents/favicon_util_mac.mm
@@ -14,7 +14,6 @@
 #include "ui/gfx/image/image.h"
 #include "ui/gfx/image/image_skia_util_mac.h"
 #include "ui/gfx/paint_vector_icon.h"
-#include "ui/resources/grit/ui_resources.h"
 
 namespace {
 
diff --git a/chrome/browser/ui/cocoa/toolbar/reload_button_cocoa.mm b/chrome/browser/ui/cocoa/toolbar/reload_button_cocoa.mm
index 942994f..c55c973c 100644
--- a/chrome/browser/ui/cocoa/toolbar/reload_button_cocoa.mm
+++ b/chrome/browser/ui/cocoa/toolbar/reload_button_cocoa.mm
@@ -14,7 +14,6 @@
 #import "chrome/browser/ui/cocoa/themed_window.h"
 #import "chrome/browser/ui/cocoa/view_id_util.h"
 #include "chrome/grit/generated_resources.h"
-#include "chrome/grit/theme_resources.h"
 #include "ui/base/accelerators/platform_accelerator_cocoa.h"
 #include "ui/base/l10n/l10n_util.h"
 #include "ui/base/l10n/l10n_util_mac.h"
diff --git a/chrome/browser/ui/cocoa/toolbar/toolbar_controller.mm b/chrome/browser/ui/cocoa/toolbar/toolbar_controller.mm
index 5146ca8..f5feee6 100644
--- a/chrome/browser/ui/cocoa/toolbar/toolbar_controller.mm
+++ b/chrome/browser/ui/cocoa/toolbar/toolbar_controller.mm
@@ -57,7 +57,6 @@
 #include "chrome/common/pref_names.h"
 #include "chrome/grit/chromium_strings.h"
 #include "chrome/grit/generated_resources.h"
-#include "chrome/grit/theme_resources.h"
 #include "components/metrics/proto/omnibox_event.pb.h"
 #include "components/omnibox/browser/autocomplete_classifier.h"
 #include "components/omnibox/browser/autocomplete_match.h"
diff --git a/chrome/browser/ui/confirm_bubble_model.cc b/chrome/browser/ui/confirm_bubble_model.cc
index 316f0b5..cba0156 100644
--- a/chrome/browser/ui/confirm_bubble_model.cc
+++ b/chrome/browser/ui/confirm_bubble_model.cc
@@ -5,7 +5,6 @@
 #include "chrome/browser/ui/confirm_bubble_model.h"
 
 #include "base/logging.h"
-#include "chrome/grit/generated_resources.h"
 #include "components/strings/grit/components_strings.h"
 #include "ui/base/l10n/l10n_util.h"
 
diff --git a/chrome/browser/ui/exclusive_access/exclusive_access_bubble_type.cc b/chrome/browser/ui/exclusive_access/exclusive_access_bubble_type.cc
index 5f2b063..9fa188d 100644
--- a/chrome/browser/ui/exclusive_access/exclusive_access_bubble_type.cc
+++ b/chrome/browser/ui/exclusive_access/exclusive_access_bubble_type.cc
@@ -12,7 +12,6 @@
 #include "extensions/common/extension.h"
 #include "extensions/common/extension_set.h"
 #include "ui/base/l10n/l10n_util.h"
-#include "ui/strings/grit/ui_strings.h"
 
 namespace exclusive_access_bubble {
 
diff --git a/chrome/browser/ui/extensions/extension_install_ui_default.cc b/chrome/browser/ui/extensions/extension_install_ui_default.cc
index 93dbebc..53fda5b 100644
--- a/chrome/browser/ui/extensions/extension_install_ui_default.cc
+++ b/chrome/browser/ui/extensions/extension_install_ui_default.cc
@@ -26,7 +26,6 @@
 #include "chrome/browser/ui/simple_message_box.h"
 #include "chrome/browser/ui/singleton_tabs.h"
 #include "chrome/browser/ui/tabs/tab_strip_model.h"
-#include "chrome/grit/generated_resources.h"
 #include "components/infobars/core/confirm_infobar_delegate.h"
 #include "components/infobars/core/infobar.h"
 #include "components/strings/grit/components_strings.h"
diff --git a/chrome/browser/ui/extensions/extension_message_bubble_bridge.cc b/chrome/browser/ui/extensions/extension_message_bubble_bridge.cc
index a60d365..6cf1aed 100644
--- a/chrome/browser/ui/extensions/extension_message_bubble_bridge.cc
+++ b/chrome/browser/ui/extensions/extension_message_bubble_bridge.cc
@@ -10,7 +10,6 @@
 #include "chrome/browser/extensions/extension_message_bubble_controller.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/grit/generated_resources.h"
-#include "components/grit/components_scaled_resources.h"
 #include "extensions/browser/extension_registry.h"
 #include "ui/base/l10n/l10n_util.h"
 #include "ui/vector_icons/vector_icons.h"
diff --git a/chrome/browser/ui/extensions/extension_message_bubble_bridge_unittest.cc b/chrome/browser/ui/extensions/extension_message_bubble_bridge_unittest.cc
index 36e188c..037df80d 100644
--- a/chrome/browser/ui/extensions/extension_message_bubble_bridge_unittest.cc
+++ b/chrome/browser/ui/extensions/extension_message_bubble_bridge_unittest.cc
@@ -23,7 +23,6 @@
 #include "chrome/test/base/test_browser_window.h"
 #include "chrome/test/base/testing_profile.h"
 #include "components/crx_file/id_util.h"
-#include "components/grit/components_scaled_resources.h"
 #include "components/keyed_service/core/keyed_service.h"
 #include "components/strings/grit/components_strings.h"
 #include "content/public/browser/browser_context.h"
diff --git a/chrome/browser/ui/external_protocol_dialog_delegate.cc b/chrome/browser/ui/external_protocol_dialog_delegate.cc
index 925c834..a0079ac 100644
--- a/chrome/browser/ui/external_protocol_dialog_delegate.cc
+++ b/chrome/browser/ui/external_protocol_dialog_delegate.cc
@@ -9,7 +9,6 @@
 #include "chrome/browser/tab_contents/tab_util.h"
 #include "chrome/grit/chromium_strings.h"
 #include "chrome/grit/generated_resources.h"
-#include "components/strings/grit/components_strings.h"
 #include "ui/base/l10n/l10n_util.h"
 #include "ui/gfx/text_elider.h"
 
diff --git a/chrome/browser/ui/hung_plugin_tab_helper.cc b/chrome/browser/ui/hung_plugin_tab_helper.cc
index a57296b..e8fd91f2 100644
--- a/chrome/browser/ui/hung_plugin_tab_helper.cc
+++ b/chrome/browser/ui/hung_plugin_tab_helper.cc
@@ -18,7 +18,6 @@
 #include "chrome/common/channel_info.h"
 #include "chrome/common/crash_keys.h"
 #include "chrome/grit/generated_resources.h"
-#include "chrome/grit/theme_resources.h"
 #include "components/infobars/core/confirm_infobar_delegate.h"
 #include "components/infobars/core/infobar.h"
 #include "components/version_info/version_info.h"
diff --git a/chrome/browser/ui/libgtkui/gtk_ui.cc b/chrome/browser/ui/libgtkui/gtk_ui.cc
index cef1ef06..eb8eb01 100644
--- a/chrome/browser/ui/libgtkui/gtk_ui.cc
+++ b/chrome/browser/ui/libgtkui/gtk_ui.cc
@@ -37,8 +37,6 @@
 #include "chrome/browser/ui/libgtkui/skia_utils_gtk.h"
 #include "chrome/browser/ui/libgtkui/unity_service.h"
 #include "chrome/browser/ui/libgtkui/x11_input_method_context_impl_gtk.h"
-#include "chrome/grit/theme_resources.h"
-#include "components/grit/components_scaled_resources.h"
 #include "printing/features/features.h"
 #include "third_party/skia/include/core/SkBitmap.h"
 #include "third_party/skia/include/core/SkCanvas.h"
@@ -56,7 +54,6 @@
 #include "ui/gfx/skia_util.h"
 #include "ui/gfx/x/x11_types.h"
 #include "ui/native_theme/native_theme.h"
-#include "ui/resources/grit/ui_resources.h"
 #include "ui/views/controls/button/blue_button.h"
 #include "ui/views/controls/button/label_button.h"
 #include "ui/views/controls/button/label_button_border.h"
diff --git a/chrome/browser/ui/libgtkui/select_file_dialog_impl_kde.cc b/chrome/browser/ui/libgtkui/select_file_dialog_impl_kde.cc
index 74a35bbd..53e4230 100644
--- a/chrome/browser/ui/libgtkui/select_file_dialog_impl_kde.cc
+++ b/chrome/browser/ui/libgtkui/select_file_dialog_impl_kde.cc
@@ -23,7 +23,6 @@
 #include "base/strings/utf_string_conversions.h"
 #include "base/threading/thread_restrictions.h"
 #include "chrome/browser/ui/libgtkui/select_file_dialog_impl.h"
-#include "chrome/grit/generated_resources.h"
 #include "content/public/browser/browser_thread.h"
 #include "ui/aura/window_tree_host.h"
 #include "ui/base/l10n/l10n_util.h"
diff --git a/chrome/browser/ui/login/login_handler.cc b/chrome/browser/ui/login/login_handler.cc
index 5dac247..651a0dd 100644
--- a/chrome/browser/ui/login/login_handler.cc
+++ b/chrome/browser/ui/login/login_handler.cc
@@ -18,7 +18,6 @@
 #include "chrome/browser/prerender/prerender_contents.h"
 #include "chrome/browser/tab_contents/tab_util.h"
 #include "chrome/browser/ui/login/login_interstitial_delegate.h"
-#include "chrome/grit/generated_resources.h"
 #include "components/password_manager/core/browser/browser_save_password_progress_logger.h"
 #include "components/password_manager/core/browser/log_manager.h"
 #include "components/password_manager/core/browser/password_manager.h"
diff --git a/chrome/browser/ui/page_info/page_info_infobar_delegate.cc b/chrome/browser/ui/page_info/page_info_infobar_delegate.cc
index 0ce07815..c577ca9 100644
--- a/chrome/browser/ui/page_info/page_info_infobar_delegate.cc
+++ b/chrome/browser/ui/page_info/page_info_infobar_delegate.cc
@@ -9,7 +9,6 @@
 #include "build/build_config.h"
 #include "chrome/app/vector_icons/vector_icons.h"
 #include "chrome/browser/infobars/infobar_service.h"
-#include "chrome/grit/theme_resources.h"
 #include "components/infobars/core/infobar.h"
 #include "components/strings/grit/components_strings.h"
 #include "content/public/browser/web_contents.h"
diff --git a/chrome/browser/ui/page_info/page_info_ui.cc b/chrome/browser/ui/page_info/page_info_ui.cc
index ec27675..42d6e90 100644
--- a/chrome/browser/ui/page_info/page_info_ui.cc
+++ b/chrome/browser/ui/page_info/page_info_ui.cc
@@ -16,7 +16,6 @@
 #include "chrome/browser/plugins/plugins_field_trial.h"
 #include "chrome/common/chrome_features.h"
 #include "chrome/common/chrome_switches.h"
-#include "chrome/grit/chromium_strings.h"
 #include "chrome/grit/generated_resources.h"
 #include "chrome/grit/theme_resources.h"
 #include "components/strings/grit/components_chromium_strings.h"
diff --git a/chrome/browser/ui/page_info/permission_menu_model_unittest.cc b/chrome/browser/ui/page_info/permission_menu_model_unittest.cc
index 5a55581b..33c8e62 100644
--- a/chrome/browser/ui/page_info/permission_menu_model_unittest.cc
+++ b/chrome/browser/ui/page_info/permission_menu_model_unittest.cc
@@ -3,7 +3,6 @@
 // found in the LICENSE file.
 
 #include "chrome/browser/ui/page_info/permission_menu_model.h"
-#include "chrome/grit/generated_resources.h"
 #include "chrome/test/base/testing_profile.h"
 #include "content/public/test/test_browser_thread_bundle.h"
 #include "testing/gtest/include/gtest/gtest.h"
diff --git a/chrome/browser/ui/passwords/manage_passwords_bubble_model.cc b/chrome/browser/ui/passwords/manage_passwords_bubble_model.cc
index 0916618..6d0dce9 100644
--- a/chrome/browser/ui/passwords/manage_passwords_bubble_model.cc
+++ b/chrome/browser/ui/passwords/manage_passwords_bubble_model.cc
@@ -19,7 +19,6 @@
 #include "chrome/browser/sync/profile_sync_service_factory.h"
 #include "chrome/browser/ui/passwords/manage_passwords_view_utils.h"
 #include "chrome/browser/ui/passwords/passwords_model_delegate.h"
-#include "chrome/grit/chromium_strings.h"
 #include "chrome/grit/generated_resources.h"
 #include "components/browser_sync/profile_sync_service.h"
 #include "components/password_manager/core/browser/password_bubble_experiment.h"
diff --git a/chrome/browser/ui/prefs/prefs_tab_helper.cc b/chrome/browser/ui/prefs/prefs_tab_helper.cc
index 175e4db3..cafaf26 100644
--- a/chrome/browser/ui/prefs/prefs_tab_helper.cc
+++ b/chrome/browser/ui/prefs/prefs_tab_helper.cc
@@ -27,7 +27,6 @@
 #include "chrome/common/pref_font_webkit_names.h"
 #include "chrome/common/pref_names.h"
 #include "chrome/common/pref_names_util.h"
-#include "chrome/grit/locale_settings.h"
 #include "chrome/grit/platform_locale_settings.h"
 #include "components/keyed_service/content/browser_context_dependency_manager.h"
 #include "components/keyed_service/content/browser_context_keyed_service_factory.h"
diff --git a/chrome/browser/ui/search_engines/template_url_table_model.cc b/chrome/browser/ui/search_engines/template_url_table_model.cc
index da2c345..d764a17 100644
--- a/chrome/browser/ui/search_engines/template_url_table_model.cc
+++ b/chrome/browser/ui/search_engines/template_url_table_model.cc
@@ -15,7 +15,6 @@
 #include "components/search_engines/template_url_service.h"
 #include "ui/base/l10n/l10n_util.h"
 #include "ui/base/models/table_model_observer.h"
-#include "ui/resources/grit/ui_resources.h"
 
 // Group IDs used by TemplateURLTableModel.
 static const int kMainGroupID = 0;
diff --git a/chrome/browser/ui/startup/automation_infobar_delegate.cc b/chrome/browser/ui/startup/automation_infobar_delegate.cc
index c7da2cd..26fc04cd 100644
--- a/chrome/browser/ui/startup/automation_infobar_delegate.cc
+++ b/chrome/browser/ui/startup/automation_infobar_delegate.cc
@@ -8,7 +8,6 @@
 #include "chrome/browser/ui/browser.h"
 #include "chrome/grit/generated_resources.h"
 #include "components/infobars/core/infobar.h"
-#include "components/strings/grit/components_strings.h"
 #include "ui/base/l10n/l10n_util.h"
 
 // static
diff --git a/chrome/browser/ui/startup/obsolete_system_infobar_delegate.cc b/chrome/browser/ui/startup/obsolete_system_infobar_delegate.cc
index 2b2cb945..15800640 100644
--- a/chrome/browser/ui/startup/obsolete_system_infobar_delegate.cc
+++ b/chrome/browser/ui/startup/obsolete_system_infobar_delegate.cc
@@ -9,7 +9,6 @@
 #include "chrome/browser/obsolete_system/obsolete_system.h"
 #include "chrome/common/pref_names.h"
 #include "chrome/common/url_constants.h"
-#include "chrome/grit/chromium_strings.h"
 #include "components/infobars/core/infobar.h"
 #include "components/prefs/pref_service.h"
 #include "components/strings/grit/components_strings.h"
diff --git a/chrome/browser/ui/startup/session_crashed_infobar_delegate.cc b/chrome/browser/ui/startup/session_crashed_infobar_delegate.cc
index 1bf73f7..f52be5a 100644
--- a/chrome/browser/ui/startup/session_crashed_infobar_delegate.cc
+++ b/chrome/browser/ui/startup/session_crashed_infobar_delegate.cc
@@ -14,8 +14,6 @@
 #include "chrome/browser/ui/browser_finder.h"
 #include "chrome/browser/ui/tabs/tab_strip_model.h"
 #include "chrome/common/url_constants.h"
-#include "chrome/grit/chromium_strings.h"
-#include "chrome/grit/generated_resources.h"
 #include "components/infobars/core/infobar.h"
 #include "components/strings/grit/components_chromium_strings.h"
 #include "components/strings/grit/components_strings.h"
diff --git a/chrome/browser/ui/startup/startup_tab_provider.cc b/chrome/browser/ui/startup/startup_tab_provider.cc
index 83ace6e..9035c01 100644
--- a/chrome/browser/ui/startup/startup_tab_provider.cc
+++ b/chrome/browser/ui/startup/startup_tab_provider.cc
@@ -17,7 +17,6 @@
 #include "chrome/browser/ui/tabs/tab_strip_model.h"
 #include "chrome/common/pref_names.h"
 #include "chrome/common/url_constants.h"
-#include "chrome/grit/locale_settings.h"
 #include "components/prefs/pref_service.h"
 #include "components/signin/core/browser/signin_manager.h"
 #include "net/base/url_util.h"
diff --git a/chrome/browser/ui/sync/one_click_signin_sync_starter.cc b/chrome/browser/ui/sync/one_click_signin_sync_starter.cc
index 4531a48..3373b31 100644
--- a/chrome/browser/ui/sync/one_click_signin_sync_starter.cc
+++ b/chrome/browser/ui/sync/one_click_signin_sync_starter.cc
@@ -32,7 +32,6 @@
 #include "chrome/browser/ui/tabs/tab_strip_model.h"
 #include "chrome/browser/ui/webui/signin/login_ui_service_factory.h"
 #include "chrome/common/url_constants.h"
-#include "chrome/grit/chromium_strings.h"
 #include "chrome/grit/generated_resources.h"
 #include "components/browser_sync/profile_sync_service.h"
 #include "components/prefs/pref_service.h"
diff --git a/chrome/browser/ui/tabs/tab_utils.cc b/chrome/browser/ui/tabs/tab_utils.cc
index 4c198704..0d434468 100644
--- a/chrome/browser/ui/tabs/tab_utils.cc
+++ b/chrome/browser/ui/tabs/tab_utils.cc
@@ -28,7 +28,6 @@
 #include "ui/native_theme/native_theme.h"
 
 #if defined(OS_MACOSX)
-#include "chrome/grit/theme_resources.h"
 #include "ui/base/resource/resource_bundle.h"
 #endif
 
diff --git a/chrome/browser/ui/toolbar/toolbar_actions_bar.cc b/chrome/browser/ui/toolbar/toolbar_actions_bar.cc
index 1f76ec09..c94054b 100644
--- a/chrome/browser/ui/toolbar/toolbar_actions_bar.cc
+++ b/chrome/browser/ui/toolbar/toolbar_actions_bar.cc
@@ -28,7 +28,6 @@
 #include "chrome/browser/ui/toolbar/toolbar_actions_bar_delegate.h"
 #include "chrome/browser/ui/toolbar/toolbar_actions_bar_observer.h"
 #include "chrome/common/pref_names.h"
-#include "chrome/grit/theme_resources.h"
 #include "components/crx_file/id_util.h"
 #include "components/pref_registry/pref_registry_syncable.h"
 #include "extensions/browser/extension_system.h"
diff --git a/chrome/browser/ui/views/apps/app_info_dialog/app_info_dialog_views.cc b/chrome/browser/ui/views/apps/app_info_dialog/app_info_dialog_views.cc
index 5d38c6b..fa269fe 100644
--- a/chrome/browser/ui/views/apps/app_info_dialog/app_info_dialog_views.cc
+++ b/chrome/browser/ui/views/apps/app_info_dialog/app_info_dialog_views.cc
@@ -30,7 +30,6 @@
 #include "ui/views/border.h"
 #include "ui/views/controls/scroll_view.h"
 #include "ui/views/layout/box_layout.h"
-#include "ui/views/layout/layout_constants.h"
 #include "ui/views/widget/widget.h"
 #include "ui/views/window/dialog_delegate.h"
 
diff --git a/chrome/browser/ui/views/apps/app_info_dialog/app_info_footer_panel.cc b/chrome/browser/ui/views/apps/app_info_dialog/app_info_footer_panel.cc
index 825c43d..c834d03 100644
--- a/chrome/browser/ui/views/apps/app_info_dialog/app_info_footer_panel.cc
+++ b/chrome/browser/ui/views/apps/app_info_dialog/app_info_footer_panel.cc
@@ -6,6 +6,7 @@
 
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/ui/browser_dialogs.h"
+#include "chrome/browser/ui/views/harmony/chrome_layout_provider.h"
 #include "chrome/common/extensions/extension_constants.h"
 #include "chrome/grit/generated_resources.h"
 #include "extensions/browser/extension_system.h"
@@ -16,7 +17,6 @@
 #include "ui/events/event.h"
 #include "ui/views/controls/button/md_text_button.h"
 #include "ui/views/layout/box_layout.h"
-#include "ui/views/layout/layout_constants.h"
 #include "ui/views/view.h"
 #include "ui/views/widget/widget.h"
 
@@ -38,10 +38,15 @@
       weak_ptr_factory_(this) {
   CreateButtons();
 
-  SetLayoutManager(new views::BoxLayout(views::BoxLayout::kHorizontal,
-                                        views::kButtonHEdgeMargin,
-                                        views::kButtonVEdgeMargin,
-                                        views::kRelatedButtonHSpacing));
+  ChromeLayoutProvider* provider = ChromeLayoutProvider::Get();
+
+  SetLayoutManager(new views::BoxLayout(
+      views::BoxLayout::kHorizontal,
+      provider->GetDistanceMetric(
+          views::DISTANCE_DIALOG_CONTENTS_HORIZONTAL_MARGIN),
+      provider->GetDistanceMetric(
+          views::DISTANCE_DIALOG_CONTENTS_VERTICAL_MARGIN),
+      provider->GetDistanceMetric(views::DISTANCE_RELATED_BUTTON_HORIZONTAL)));
 
   LayoutButtons();
 }
diff --git a/chrome/browser/ui/views/apps/app_info_dialog/app_info_header_panel.cc b/chrome/browser/ui/views/apps/app_info_dialog/app_info_header_panel.cc
index 1768567..949b194 100644
--- a/chrome/browser/ui/views/apps/app_info_dialog/app_info_header_panel.cc
+++ b/chrome/browser/ui/views/apps/app_info_dialog/app_info_header_panel.cc
@@ -11,6 +11,7 @@
 #include "chrome/browser/extensions/extension_service.h"
 #include "chrome/browser/extensions/extension_util.h"
 #include "chrome/browser/profiles/profile.h"
+#include "chrome/browser/ui/views/harmony/chrome_layout_provider.h"
 #include "chrome/common/extensions/extension_constants.h"
 #include "chrome/grit/generated_resources.h"
 #include "extensions/browser/extension_system.h"
@@ -35,7 +36,6 @@
 #include "ui/views/controls/link.h"
 #include "ui/views/layout/box_layout.h"
 #include "ui/views/layout/grid_layout.h"
-#include "ui/views/layout/layout_constants.h"
 #include "ui/views/view.h"
 
 namespace {
@@ -49,11 +49,15 @@
                                        const extensions::Extension* app)
     : AppInfoPanel(profile, app),
       weak_ptr_factory_(this) {
-  SetLayoutManager(
-      new views::BoxLayout(views::BoxLayout::kHorizontal,
-                           views::kButtonHEdgeMargin,
-                           views::kButtonVEdgeMargin,
-                           views::kRelatedControlHorizontalSpacing));
+  ChromeLayoutProvider* provider = ChromeLayoutProvider::Get();
+
+  SetLayoutManager(new views::BoxLayout(
+      views::BoxLayout::kHorizontal,
+      provider->GetDistanceMetric(
+          views::DISTANCE_DIALOG_CONTENTS_HORIZONTAL_MARGIN),
+      provider->GetDistanceMetric(
+          views::DISTANCE_DIALOG_CONTENTS_VERTICAL_MARGIN),
+      provider->GetDistanceMetric(views::DISTANCE_RELATED_CONTROL_HORIZONTAL)));
 
   CreateControls();
 }
diff --git a/chrome/browser/ui/views/apps/app_info_dialog/app_info_panel.cc b/chrome/browser/ui/views/apps/app_info_dialog/app_info_panel.cc
index f4131a1..b23dbc0f 100644
--- a/chrome/browser/ui/views/apps/app_info_dialog/app_info_panel.cc
+++ b/chrome/browser/ui/views/apps/app_info_dialog/app_info_panel.cc
@@ -6,10 +6,10 @@
 
 #include "chrome/browser/ui/browser_navigator.h"
 #include "chrome/browser/ui/browser_navigator_params.h"
+#include "chrome/browser/ui/views/harmony/chrome_layout_provider.h"
 #include "ui/base/resource/resource_bundle.h"
 #include "ui/views/controls/label.h"
 #include "ui/views/layout/box_layout.h"
-#include "ui/views/layout/layout_constants.h"
 #include "ui/views/widget/widget.h"
 #include "url/gurl.h"
 
@@ -52,7 +52,8 @@
 }
 
 views::View* AppInfoPanel::CreateVerticalStack() const {
-  return CreateVerticalStack(views::kRelatedControlVerticalSpacing);
+  return CreateVerticalStack(ChromeLayoutProvider::Get()->GetDistanceMetric(
+      views::DISTANCE_RELATED_CONTROL_VERTICAL));
 }
 
 views::View* AppInfoPanel::CreateHorizontalStack(int child_spacing) const {
diff --git a/chrome/browser/ui/views/apps/app_info_dialog/app_info_permissions_panel.cc b/chrome/browser/ui/views/apps/app_info_dialog/app_info_permissions_panel.cc
index 6cf4d30..18d72ac 100644
--- a/chrome/browser/ui/views/apps/app_info_dialog/app_info_permissions_panel.cc
+++ b/chrome/browser/ui/views/apps/app_info_dialog/app_info_permissions_panel.cc
@@ -13,6 +13,7 @@
 #include "base/strings/string_split.h"
 #include "chrome/browser/apps/app_load_service.h"
 #include "chrome/browser/profiles/profile.h"
+#include "chrome/browser/ui/views/harmony/chrome_layout_provider.h"
 #include "chrome/grit/generated_resources.h"
 #include "extensions/browser/api/device_permissions_manager.h"
 #include "extensions/common/extension.h"
@@ -28,7 +29,6 @@
 #include "ui/views/controls/label.h"
 #include "ui/views/layout/box_layout.h"
 #include "ui/views/layout/grid_layout.h"
-#include "ui/views/layout/layout_constants.h"
 #include "ui/views/view.h"
 
 namespace {
@@ -171,8 +171,10 @@
                                  views::Label* permission_label,
                                  RevokeButton* revoke_button) {
     // Add a padding row before every item except the first.
-    if (has_children())
-      layout_->AddPaddingRow(0, views::kRelatedControlVerticalSpacing);
+    if (has_children()) {
+      layout_->AddPaddingRow(0, ChromeLayoutProvider::Get()->GetDistanceMetric(
+                                    views::DISTANCE_RELATED_CONTROL_VERTICAL));
+    }
 
     const base::char16 bullet_point[] = {0x2022, 0};
     views::Label* bullet_label = new views::Label(base::string16(bullet_point));
@@ -199,10 +201,10 @@
     Profile* profile,
     const extensions::Extension* app)
     : AppInfoPanel(profile, app) {
-  SetLayoutManager(new views::BoxLayout(views::BoxLayout::kVertical,
-                                        0,
-                                        0,
-                                        views::kRelatedControlVerticalSpacing));
+  SetLayoutManager(
+      new views::BoxLayout(views::BoxLayout::kVertical, 0, 0,
+                           ChromeLayoutProvider::Get()->GetDistanceMetric(
+                               views::DISTANCE_RELATED_CONTROL_VERTICAL)));
 
   CreatePermissionsList();
 }
diff --git a/chrome/browser/ui/views/apps/app_info_dialog/app_info_summary_panel.cc b/chrome/browser/ui/views/apps/app_info_dialog/app_info_summary_panel.cc
index 4af7c77..908cf5d 100644
--- a/chrome/browser/ui/views/apps/app_info_dialog/app_info_summary_panel.cc
+++ b/chrome/browser/ui/views/apps/app_info_dialog/app_info_summary_panel.cc
@@ -18,6 +18,7 @@
 #include "chrome/browser/extensions/extension_util.h"
 #include "chrome/browser/extensions/launch_util.h"
 #include "chrome/browser/profiles/profile.h"
+#include "chrome/browser/ui/views/harmony/chrome_layout_provider.h"
 #include "chrome/common/extensions/extension_constants.h"
 #include "chrome/grit/generated_resources.h"
 #include "extensions/browser/extension_prefs.h"
@@ -33,7 +34,6 @@
 #include "ui/views/controls/label.h"
 #include "ui/views/controls/link.h"
 #include "ui/views/layout/box_layout.h"
-#include "ui/views/layout/layout_constants.h"
 #include "ui/views/view.h"
 
 // A model for a combobox selecting the launch options for a hosted app.
@@ -139,10 +139,10 @@
       licenses_link_(NULL),
       launch_options_combobox_(NULL),
       weak_ptr_factory_(this) {
-  SetLayoutManager(new views::BoxLayout(views::BoxLayout::kVertical,
-                                        0,
-                                        0,
-                                        views::kRelatedControlVerticalSpacing));
+  SetLayoutManager(
+      new views::BoxLayout(views::BoxLayout::kVertical, 0, 0,
+                           ChromeLayoutProvider::Get()->GetDistanceMetric(
+                               views::DISTANCE_RELATED_CONTROL_VERTICAL)));
 
   AddSubviews();
 }
@@ -156,10 +156,9 @@
     views::View* vertical_stack) {
   views::View* description_and_labels_stack = new views::View();
   description_and_labels_stack->SetLayoutManager(
-      new views::BoxLayout(views::BoxLayout::kVertical,
-                           0,
-                           0,
-                           views::kRelatedControlSmallVerticalSpacing));
+      new views::BoxLayout(views::BoxLayout::kVertical, 0, 0,
+                           ChromeLayoutProvider::Get()->GetDistanceMetric(
+                               DISTANCE_RELATED_CONTROL_VERTICAL_SMALL)));
 
   if (!app_->description().empty()) {
     // TODO(sashab): Clip the app's description to 4 lines, and use Label's
@@ -202,7 +201,8 @@
     return;
 
   views::View* details_list =
-      CreateVerticalStack(views::kRelatedControlSmallVerticalSpacing);
+      CreateVerticalStack(ChromeLayoutProvider::Get()->GetDistanceMetric(
+          DISTANCE_RELATED_CONTROL_VERTICAL_SMALL));
 
   // Add the size.
   views::Label* size_title = new views::Label(
@@ -252,7 +252,8 @@
       l10n_util::GetStringUTF16(IDS_APPLICATION_INFO_APP_OVERVIEW_TITLE)));
 
   views::View* vertical_stack =
-      CreateVerticalStack(views::kUnrelatedControlVerticalSpacing);
+      CreateVerticalStack(ChromeLayoutProvider::Get()->GetDistanceMetric(
+          DISTANCE_UNRELATED_CONTROL_VERTICAL));
   AddChildView(vertical_stack);
 
   AddDescriptionAndLinksControl(vertical_stack);
diff --git a/chrome/browser/ui/views/apps/app_info_dialog/arc_app_info_links_panel.cc b/chrome/browser/ui/views/apps/app_info_dialog/arc_app_info_links_panel.cc
index 6c520ca..3c90b3e 100644
--- a/chrome/browser/ui/views/apps/app_info_dialog/arc_app_info_links_panel.cc
+++ b/chrome/browser/ui/views/apps/app_info_dialog/arc_app_info_links_panel.cc
@@ -6,12 +6,12 @@
 
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/ui/app_list/arc/arc_app_utils.h"
+#include "chrome/browser/ui/views/harmony/chrome_layout_provider.h"
 #include "chrome/grit/generated_resources.h"
 #include "components/arc/common/app.mojom.h"
 #include "ui/base/l10n/l10n_util.h"
 #include "ui/views/controls/link.h"
 #include "ui/views/layout/box_layout.h"
-#include "ui/views/layout/layout_constants.h"
 #include "ui/views/view.h"
 
 namespace {
@@ -23,8 +23,10 @@
     : AppInfoPanel(profile, app),
       app_list_observer_(this),
       manage_link_(nullptr) {
-  SetLayoutManager(new views::BoxLayout(views::BoxLayout::kVertical, 0, 0,
-                                        views::kRelatedControlVerticalSpacing));
+  SetLayoutManager(
+      new views::BoxLayout(views::BoxLayout::kVertical, 0, 0,
+                           ChromeLayoutProvider::Get()->GetDistanceMetric(
+                               views::DISTANCE_RELATED_CONTROL_VERTICAL)));
   manage_link_ = new views::Link(
       l10n_util::GetStringUTF16(IDS_ARC_APPLICATION_INFO_MANAGE_LINK));
   manage_link_->SetHorizontalAlignment(gfx::ALIGN_LEFT);
diff --git a/chrome/browser/ui/views/autofill/card_unmask_prompt_views.cc b/chrome/browser/ui/views/autofill/card_unmask_prompt_views.cc
index 7e0f9b9..1758bc0 100644
--- a/chrome/browser/ui/views/autofill/card_unmask_prompt_views.cc
+++ b/chrome/browser/ui/views/autofill/card_unmask_prompt_views.cc
@@ -11,8 +11,6 @@
 #include "chrome/browser/ui/autofill/create_card_unmask_prompt_view.h"
 #include "chrome/browser/ui/browser_dialogs.h"
 #include "chrome/browser/ui/views/autofill/view_util.h"
-#include "chrome/grit/generated_resources.h"
-#include "chrome/grit/theme_resources.h"
 #include "components/autofill/core/browser/ui/card_unmask_prompt_controller.h"
 #include "components/constrained_window/constrained_window_views.h"
 #include "components/strings/grit/components_strings.h"
diff --git a/chrome/browser/ui/views/collected_cookies_views.cc b/chrome/browser/ui/views/collected_cookies_views.cc
index 47a0a59..0a13cfd 100644
--- a/chrome/browser/ui/views/collected_cookies_views.cc
+++ b/chrome/browser/ui/views/collected_cookies_views.cc
@@ -25,7 +25,6 @@
 #include "chrome/browser/ui/views/harmony/chrome_layout_provider.h"
 #include "chrome/common/pref_names.h"
 #include "chrome/grit/generated_resources.h"
-#include "chrome/grit/locale_settings.h"
 #include "chrome/grit/theme_resources.h"
 #include "components/constrained_window/constrained_window_views.h"
 #include "components/content_settings/core/browser/cookie_settings.h"
diff --git a/chrome/browser/ui/views/critical_notification_bubble_view.cc b/chrome/browser/ui/views/critical_notification_bubble_view.cc
index 847f889..e473094 100644
--- a/chrome/browser/ui/views/critical_notification_bubble_view.cc
+++ b/chrome/browser/ui/views/critical_notification_bubble_view.cc
@@ -12,9 +12,7 @@
 #include "chrome/browser/upgrade_detector.h"
 #include "chrome/common/pref_names.h"
 #include "chrome/grit/chromium_strings.h"
-#include "chrome/grit/generated_resources.h"
 #include "chrome/grit/locale_settings.h"
-#include "chrome/grit/theme_resources.h"
 #include "components/prefs/pref_service.h"
 #include "ui/accessibility/ax_node_data.h"
 #include "ui/base/l10n/l10n_util.h"
diff --git a/chrome/browser/ui/views/desktop_ios_promotion/desktop_ios_promotion_footnote_view.cc b/chrome/browser/ui/views/desktop_ios_promotion/desktop_ios_promotion_footnote_view.cc
index 13fe4c3..8b6bfe9 100644
--- a/chrome/browser/ui/views/desktop_ios_promotion/desktop_ios_promotion_footnote_view.cc
+++ b/chrome/browser/ui/views/desktop_ios_promotion/desktop_ios_promotion_footnote_view.cc
@@ -18,7 +18,6 @@
 #include "ui/gfx/font.h"
 #include "ui/views/controls/styled_label.h"
 #include "ui/views/layout/fill_layout.h"
-#include "ui/views/layout/layout_constants.h"
 
 DesktopIOSPromotionFootnoteView::DesktopIOSPromotionFootnoteView(
     Profile* profile,
diff --git a/chrome/browser/ui/views/download/download_shelf_view.cc b/chrome/browser/ui/views/download/download_shelf_view.cc
index c55fa61..541bbdb 100644
--- a/chrome/browser/ui/views/download/download_shelf_view.cc
+++ b/chrome/browser/ui/views/download/download_shelf_view.cc
@@ -20,7 +20,6 @@
 #include "chrome/browser/ui/views/download/download_item_view.h"
 #include "chrome/browser/ui/views/frame/browser_view.h"
 #include "chrome/grit/generated_resources.h"
-#include "chrome/grit/theme_resources.h"
 #include "components/strings/grit/components_strings.h"
 #include "content/public/browser/download_item.h"
 #include "content/public/browser/download_manager.h"
@@ -30,7 +29,6 @@
 #include "ui/base/theme_provider.h"
 #include "ui/gfx/animation/slide_animation.h"
 #include "ui/gfx/canvas.h"
-#include "ui/resources/grit/ui_resources.h"
 #include "ui/vector_icons/vector_icons.h"
 #include "ui/views/background.h"
 #include "ui/views/border.h"
diff --git a/chrome/browser/ui/views/external_protocol_dialog.cc b/chrome/browser/ui/views/external_protocol_dialog.cc
index d3c505d..82432d92 100644
--- a/chrome/browser/ui/views/external_protocol_dialog.cc
+++ b/chrome/browser/ui/views/external_protocol_dialog.cc
@@ -12,7 +12,6 @@
 #include "chrome/browser/tab_contents/tab_util.h"
 #include "chrome/browser/ui/browser_dialogs.h"
 #include "chrome/browser/ui/external_protocol_dialog_delegate.h"
-#include "chrome/grit/generated_resources.h"
 #include "components/constrained_window/constrained_window_views.h"
 #include "content/public/browser/web_contents.h"
 #include "ui/base/l10n/l10n_util.h"
diff --git a/chrome/browser/ui/views/first_run_dialog.cc b/chrome/browser/ui/views/first_run_dialog.cc
index a90d687..548ab4a 100644
--- a/chrome/browser/ui/views/first_run_dialog.cc
+++ b/chrome/browser/ui/views/first_run_dialog.cc
@@ -18,7 +18,6 @@
 #include "chrome/common/url_constants.h"
 #include "chrome/grit/chromium_strings.h"
 #include "chrome/grit/generated_resources.h"
-#include "chrome/grit/locale_settings.h"
 #include "components/strings/grit/components_strings.h"
 #include "ui/aura/env.h"
 #include "ui/aura/window.h"
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 360f4fab..c348f62 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
@@ -44,7 +44,6 @@
 #include "ui/gfx/image/image_skia.h"
 #include "ui/gfx/scoped_canvas.h"
 #include "ui/views/controls/label.h"
-#include "ui/views/layout/layout_constants.h"
 #include "ui/views/widget/widget.h"
 #include "ui/views/widget/widget_delegate.h"
 
diff --git a/chrome/browser/ui/views/frame/browser_non_client_frame_view_mus.cc b/chrome/browser/ui/views/frame/browser_non_client_frame_view_mus.cc
index 2bc51461..191623f 100644
--- a/chrome/browser/ui/views/frame/browser_non_client_frame_view_mus.cc
+++ b/chrome/browser/ui/views/frame/browser_non_client_frame_view_mus.cc
@@ -35,7 +35,6 @@
 #include "ui/gfx/image/image_skia.h"
 #include "ui/gfx/scoped_canvas.h"
 #include "ui/views/controls/label.h"
-#include "ui/views/layout/layout_constants.h"
 #include "ui/views/mus/desktop_window_tree_host_mus.h"
 #include "ui/views/mus/window_manager_frame_values.h"
 #include "ui/views/widget/widget.h"
diff --git a/chrome/browser/ui/views/frame/browser_view.cc b/chrome/browser/ui/views/frame/browser_view.cc
index 1a2486d..de4fdc63 100644
--- a/chrome/browser/ui/views/frame/browser_view.cc
+++ b/chrome/browser/ui/views/frame/browser_view.cc
@@ -99,9 +99,7 @@
 #include "chrome/common/features.h"
 #include "chrome/common/pref_names.h"
 #include "chrome/common/url_constants.h"
-#include "chrome/grit/chromium_strings.h"
 #include "chrome/grit/generated_resources.h"
-#include "chrome/grit/locale_settings.h"
 #include "chrome/grit/theme_resources.h"
 #include "components/app_modal/app_modal_dialog_queue.h"
 #include "components/app_modal/javascript_app_modal_dialog.h"
@@ -135,7 +133,6 @@
 #include "ui/gfx/geometry/rect_conversions.h"
 #include "ui/gfx/scoped_canvas.h"
 #include "ui/native_theme/native_theme_dark_aura.h"
-#include "ui/strings/grit/ui_strings.h"
 #include "ui/views/controls/button/menu_button.h"
 #include "ui/views/controls/textfield/textfield.h"
 #include "ui/views/controls/webview/webview.h"
diff --git a/chrome/browser/ui/views/ime/ime_window_frame_view.cc b/chrome/browser/ui/views/ime/ime_window_frame_view.cc
index 6b413a5..6962dcc 100644
--- a/chrome/browser/ui/views/ime/ime_window_frame_view.cc
+++ b/chrome/browser/ui/views/ime/ime_window_frame_view.cc
@@ -6,18 +6,15 @@
 
 #include "chrome/browser/ui/views/ime/ime_window_view.h"
 #include "chrome/grit/browser_resources.h"
-#include "chrome/grit/theme_resources.h"
 #include "content/public/browser/web_contents.h"
 #include "ui/base/hit_test.h"
 #include "ui/base/resource/resource_bundle.h"
 #include "ui/gfx/canvas.h"
 #include "ui/gfx/font_list.h"
 #include "ui/gfx/path.h"
-#include "ui/resources/grit/ui_resources.h"
 #include "ui/views/controls/button/image_button.h"
 #include "ui/views/controls/image_view.h"
 #include "ui/views/controls/label.h"
-#include "ui/views/resources/grit/views_resources.h"
 #include "ui/views/widget/widget.h"
 #include "ui/views/widget/widget_delegate.h"
 
diff --git a/chrome/browser/ui/views/infobars/infobar_view.cc b/chrome/browser/ui/views/infobars/infobar_view.cc
index ecdb2ba0..2327752 100644
--- a/chrome/browser/ui/views/infobars/infobar_view.cc
+++ b/chrome/browser/ui/views/infobars/infobar_view.cc
@@ -14,7 +14,6 @@
 #include "chrome/browser/ui/views/harmony/chrome_layout_provider.h"
 #include "chrome/browser/ui/views/infobars/infobar_background.h"
 #include "chrome/grit/generated_resources.h"
-#include "chrome/grit/theme_resources.h"
 #include "components/infobars/core/infobar_delegate.h"
 #include "components/strings/grit/components_strings.h"
 #include "third_party/skia/include/effects/SkGradientShader.h"
diff --git a/chrome/browser/ui/views/location_bar/content_setting_image_view.cc b/chrome/browser/ui/views/location_bar/content_setting_image_view.cc
index f1a2f749..2ce9aa7 100644
--- a/chrome/browser/ui/views/location_bar/content_setting_image_view.cc
+++ b/chrome/browser/ui/views/location_bar/content_setting_image_view.cc
@@ -10,7 +10,6 @@
 #include "chrome/browser/ui/content_settings/content_setting_image_model.h"
 #include "chrome/browser/ui/views/content_setting_bubble_contents.h"
 #include "chrome/browser/ui/views/location_bar/location_bar_view.h"
-#include "chrome/grit/theme_resources.h"
 #include "ui/base/l10n/l10n_util.h"
 #include "ui/base/material_design/material_design_controller.h"
 #include "ui/base/theme_provider.h"
diff --git a/chrome/browser/ui/views/location_bar/location_bar_view.cc b/chrome/browser/ui/views/location_bar/location_bar_view.cc
index e9ec8b6..066eb09c 100644
--- a/chrome/browser/ui/views/location_bar/location_bar_view.cc
+++ b/chrome/browser/ui/views/location_bar/location_bar_view.cc
@@ -47,11 +47,8 @@
 #include "chrome/browser/ui/views/translate/translate_bubble_view.h"
 #include "chrome/browser/ui/views/translate/translate_icon_view.h"
 #include "chrome/grit/chromium_strings.h"
-#include "chrome/grit/generated_resources.h"
-#include "chrome/grit/theme_resources.h"
 #include "components/bookmarks/common/bookmark_pref_names.h"
 #include "components/favicon/content/content_favicon_driver.h"
-#include "components/grit/components_scaled_resources.h"
 #include "components/omnibox/browser/omnibox_popup_model.h"
 #include "components/omnibox/browser/omnibox_popup_view.h"
 #include "components/prefs/pref_service.h"
diff --git a/chrome/browser/ui/views/location_bar/location_icon_view.cc b/chrome/browser/ui/views/location_bar/location_icon_view.cc
index 1ada6ed..7e54f00 100644
--- a/chrome/browser/ui/views/location_bar/location_icon_view.cc
+++ b/chrome/browser/ui/views/location_bar/location_icon_view.cc
@@ -8,8 +8,6 @@
 #include "chrome/browser/ui/views/location_bar/location_bar_view.h"
 #include "chrome/browser/ui/views/page_info/page_info_bubble_view.h"
 #include "chrome/grit/generated_resources.h"
-#include "chrome/grit/theme_resources.h"
-#include "components/grit/components_scaled_resources.h"
 #include "components/omnibox/browser/omnibox_edit_model.h"
 #include "content/public/browser/web_contents.h"
 #include "ui/accessibility/ax_node_data.h"
diff --git a/chrome/browser/ui/views/new_back_shortcut_bubble.cc b/chrome/browser/ui/views/new_back_shortcut_bubble.cc
index 4c5528c..92e54f0 100644
--- a/chrome/browser/ui/views/new_back_shortcut_bubble.cc
+++ b/chrome/browser/ui/views/new_back_shortcut_bubble.cc
@@ -19,7 +19,6 @@
 #include "ui/gfx/animation/slide_animation.h"
 #include "ui/gfx/geometry/rect.h"
 #include "ui/gfx/geometry/size.h"
-#include "ui/strings/grit/ui_strings.h"
 #include "ui/views/border.h"
 #include "ui/views/view.h"
 #include "ui/views/widget/widget.h"
diff --git a/chrome/browser/ui/views/omnibox/omnibox_result_view.cc b/chrome/browser/ui/views/omnibox/omnibox_result_view.cc
index a64ff359..ce33862 100644
--- a/chrome/browser/ui/views/omnibox/omnibox_result_view.cc
+++ b/chrome/browser/ui/views/omnibox/omnibox_result_view.cc
@@ -27,7 +27,6 @@
 #include "chrome/browser/ui/views/location_bar/location_bar_view.h"
 #include "chrome/browser/ui/views/omnibox/omnibox_popup_contents_view.h"
 #include "chrome/grit/generated_resources.h"
-#include "components/grit/components_scaled_resources.h"
 #include "components/omnibox/browser/omnibox_field_trial.h"
 #include "components/omnibox/browser/omnibox_popup_model.h"
 #include "components/omnibox/browser/vector_icons.h"
diff --git a/chrome/browser/ui/views/page_info/page_info_bubble_view.cc b/chrome/browser/ui/views/page_info/page_info_bubble_view.cc
index 54b9e1b..71e22e32 100644
--- a/chrome/browser/ui/views/page_info/page_info_bubble_view.cc
+++ b/chrome/browser/ui/views/page_info/page_info_bubble_view.cc
@@ -29,8 +29,6 @@
 #include "chrome/browser/ui/views/page_info/non_accessible_image_view.h"
 #include "chrome/browser/ui/views/page_info/permission_selector_row.h"
 #include "chrome/common/url_constants.h"
-#include "chrome/grit/chromium_strings.h"
-#include "chrome/grit/generated_resources.h"
 #include "chrome/grit/theme_resources.h"
 #include "components/content_settings/core/common/content_settings_types.h"
 #include "components/strings/grit/components_chromium_strings.h"
@@ -45,7 +43,6 @@
 #include "ui/gfx/font_list.h"
 #include "ui/gfx/geometry/insets.h"
 #include "ui/gfx/image/image.h"
-#include "ui/resources/grit/ui_resources.h"
 #include "ui/views/border.h"
 #include "ui/views/controls/button/image_button.h"
 #include "ui/views/controls/button/md_text_button.h"
diff --git a/chrome/browser/ui/views/page_info/permission_selector_row.cc b/chrome/browser/ui/views/page_info/permission_selector_row.cc
index 9d8fd37..b9407fc 100644
--- a/chrome/browser/ui/views/page_info/permission_selector_row.cc
+++ b/chrome/browser/ui/views/page_info/permission_selector_row.cc
@@ -12,7 +12,6 @@
 #include "chrome/browser/ui/views/harmony/chrome_typography.h"
 #include "chrome/browser/ui/views/page_info/non_accessible_image_view.h"
 #include "chrome/browser/ui/views/page_info/page_info_bubble_view.h"
-#include "chrome/grit/generated_resources.h"
 #include "ui/accessibility/ax_node_data.h"
 #include "ui/base/material_design/material_design_controller.h"
 #include "ui/base/models/combobox_model.h"
diff --git a/chrome/browser/ui/views/passwords/credentials_item_view.cc b/chrome/browser/ui/views/passwords/credentials_item_view.cc
index 905d4a2a47..30371af 100644
--- a/chrome/browser/ui/views/passwords/credentials_item_view.cc
+++ b/chrome/browser/ui/views/passwords/credentials_item_view.cc
@@ -9,7 +9,6 @@
 #include "chrome/browser/ui/passwords/manage_passwords_view_utils.h"
 #include "chrome/browser/ui/views/harmony/chrome_layout_provider.h"
 #include "chrome/browser/ui/views/harmony/chrome_typography.h"
-#include "chrome/grit/generated_resources.h"
 #include "chrome/grit/theme_resources.h"
 #include "components/autofill/core/common/password_form.h"
 #include "ui/base/resource/resource_bundle.h"
diff --git a/chrome/browser/ui/views/payments/editor_view_controller.cc b/chrome/browser/ui/views/payments/editor_view_controller.cc
index 8d61281..ceee69e 100644
--- a/chrome/browser/ui/views/payments/editor_view_controller.cc
+++ b/chrome/browser/ui/views/payments/editor_view_controller.cc
@@ -17,7 +17,6 @@
 #include "chrome/browser/ui/views/payments/payment_request_views_util.h"
 #include "chrome/browser/ui/views/payments/validating_combobox.h"
 #include "chrome/browser/ui/views/payments/validating_textfield.h"
-#include "chrome/grit/generated_resources.h"
 #include "components/strings/grit/components_strings.h"
 #include "ui/base/ime/text_input_type.h"
 #include "ui/base/l10n/l10n_util.h"
diff --git a/chrome/browser/ui/views/payments/order_summary_view_controller.cc b/chrome/browser/ui/views/payments/order_summary_view_controller.cc
index 3c5ebc5e..731ca2f 100644
--- a/chrome/browser/ui/views/payments/order_summary_view_controller.cc
+++ b/chrome/browser/ui/views/payments/order_summary_view_controller.cc
@@ -15,7 +15,6 @@
 #include "chrome/browser/ui/views/payments/payment_request_dialog_view.h"
 #include "chrome/browser/ui/views/payments/payment_request_dialog_view_ids.h"
 #include "chrome/browser/ui/views/payments/payment_request_views_util.h"
-#include "chrome/grit/generated_resources.h"
 #include "components/payments/core/currency_formatter.h"
 #include "components/strings/grit/components_strings.h"
 #include "ui/base/l10n/l10n_util.h"
diff --git a/chrome/browser/ui/views/payments/payment_sheet_view_controller.cc b/chrome/browser/ui/views/payments/payment_sheet_view_controller.cc
index b345ff4b..704d942 100644
--- a/chrome/browser/ui/views/payments/payment_sheet_view_controller.cc
+++ b/chrome/browser/ui/views/payments/payment_sheet_view_controller.cc
@@ -24,7 +24,6 @@
 #include "chrome/browser/ui/views/payments/payment_request_dialog_view_ids.h"
 #include "chrome/browser/ui/views/payments/payment_request_row_view.h"
 #include "chrome/browser/ui/views/payments/payment_request_views_util.h"
-#include "chrome/grit/generated_resources.h"
 #include "components/autofill/core/browser/field_types.h"
 #include "components/autofill/core/browser/personal_data_manager.h"
 #include "components/payments/content/payment_request_spec.h"
diff --git a/chrome/browser/ui/views/sync/one_click_signin_dialog_view.cc b/chrome/browser/ui/views/sync/one_click_signin_dialog_view.cc
index 7a181e6..3caf029 100644
--- a/chrome/browser/ui/views/sync/one_click_signin_dialog_view.cc
+++ b/chrome/browser/ui/views/sync/one_click_signin_dialog_view.cc
@@ -19,7 +19,6 @@
 #include "ui/base/l10n/l10n_util.h"
 #include "ui/base/resource/resource_bundle.h"
 #include "ui/events/keycodes/keyboard_codes.h"
-#include "ui/resources/grit/ui_resources.h"
 #include "ui/views/controls/button/image_button.h"
 #include "ui/views/controls/button/label_button.h"
 #include "ui/views/controls/image_view.h"
diff --git a/chrome/browser/ui/views/tab_icon_view.cc b/chrome/browser/ui/views/tab_icon_view.cc
index d9975ef4..fd618f3 100644
--- a/chrome/browser/ui/views/tab_icon_view.cc
+++ b/chrome/browser/ui/views/tab_icon_view.cc
@@ -22,7 +22,6 @@
 #include "ui/gfx/favicon_size.h"
 #include "ui/gfx/paint_throbber.h"
 #include "ui/native_theme/native_theme.h"
-#include "ui/resources/grit/ui_resources.h"
 
 #if defined(OS_WIN)
 #include "chrome/browser/win/app_icon.h"
diff --git a/chrome/browser/ui/views/toolbar/app_menu_button.cc b/chrome/browser/ui/views/toolbar/app_menu_button.cc
index 461e0ac..e51aa27 100644
--- a/chrome/browser/ui/views/toolbar/app_menu_button.cc
+++ b/chrome/browser/ui/views/toolbar/app_menu_button.cc
@@ -25,7 +25,6 @@
 #include "chrome/browser/ui/views/toolbar/toolbar_button.h"
 #include "chrome/browser/ui/views/toolbar/toolbar_view.h"
 #include "chrome/common/chrome_switches.h"
-#include "chrome/grit/theme_resources.h"
 #include "ui/base/resource/resource_bundle.h"
 #include "ui/base/theme_provider.h"
 #include "ui/gfx/canvas.h"
diff --git a/chrome/browser/ui/views/toolbar/browser_actions_container.cc b/chrome/browser/ui/views/toolbar/browser_actions_container.cc
index e43acdb7..03a12da 100644
--- a/chrome/browser/ui/views/toolbar/browser_actions_container.cc
+++ b/chrome/browser/ui/views/toolbar/browser_actions_container.cc
@@ -34,7 +34,6 @@
 #include "ui/base/resource/resource_bundle.h"
 #include "ui/gfx/canvas.h"
 #include "ui/gfx/geometry/rect.h"
-#include "ui/resources/grit/ui_resources.h"
 #include "ui/views/bubble/bubble_dialog_delegate.h"
 #include "ui/views/controls/resize_area.h"
 #include "ui/views/painter.h"
diff --git a/chrome/browser/ui/views/toolbar/reload_button.cc b/chrome/browser/ui/views/toolbar/reload_button.cc
index f37faae..ee50d12 100644
--- a/chrome/browser/ui/views/toolbar/reload_button.cc
+++ b/chrome/browser/ui/views/toolbar/reload_button.cc
@@ -13,7 +13,6 @@
 #include "chrome/browser/command_updater.h"
 #include "chrome/browser/themes/theme_properties.h"
 #include "chrome/grit/generated_resources.h"
-#include "chrome/grit/theme_resources.h"
 #include "ui/base/l10n/l10n_util.h"
 #include "ui/base/models/simple_menu_model.h"
 #include "ui/base/theme_provider.h"
diff --git a/chrome/browser/ui/views/toolbar/toolbar_action_view.cc b/chrome/browser/ui/views/toolbar/toolbar_action_view.cc
index b685866..5fae9cd 100644
--- a/chrome/browser/ui/views/toolbar/toolbar_action_view.cc
+++ b/chrome/browser/ui/views/toolbar/toolbar_action_view.cc
@@ -106,6 +106,10 @@
       ThemeProperties::COLOR_TOOLBAR_BUTTON_ICON);
 }
 
+bool ToolbarActionView::ShouldUseFloodFillInkDrop() const {
+  return delegate_->ShownInsideMenu();
+}
+
 std::unique_ptr<views::InkDrop> ToolbarActionView::CreateInkDrop() {
   std::unique_ptr<views::InkDropImpl> ink_drop =
       CustomButton::CreateDefaultInkDropImpl();
diff --git a/chrome/browser/ui/views/toolbar/toolbar_action_view.h b/chrome/browser/ui/views/toolbar/toolbar_action_view.h
index ff3e6536..e200ed6 100644
--- a/chrome/browser/ui/views/toolbar/toolbar_action_view.h
+++ b/chrome/browser/ui/views/toolbar/toolbar_action_view.h
@@ -64,6 +64,7 @@
       const override;
   bool IsTriggerableEvent(const ui::Event& event) override;
   SkColor GetInkDropBaseColor() const override;
+  bool ShouldUseFloodFillInkDrop() const override;
   std::unique_ptr<views::InkDrop> CreateInkDrop() override;
 
   // ToolbarActionViewDelegateViews:
diff --git a/chrome/browser/ui/views/toolbar/toolbar_actions_bar_bubble_views_unittest.cc b/chrome/browser/ui/views/toolbar/toolbar_actions_bar_bubble_views_unittest.cc
index 8517dca..16089f0 100644
--- a/chrome/browser/ui/views/toolbar/toolbar_actions_bar_bubble_views_unittest.cc
+++ b/chrome/browser/ui/views/toolbar/toolbar_actions_bar_bubble_views_unittest.cc
@@ -13,7 +13,6 @@
 #include "chrome/browser/ui/toolbar/toolbar_actions_bar_bubble_delegate.h"
 #include "chrome/browser/ui/views/harmony/chrome_layout_provider.h"
 #include "chrome/grit/generated_resources.h"
-#include "components/grit/components_scaled_resources.h"
 #include "ui/base/l10n/l10n_util.h"
 #include "ui/base/resource/resource_bundle.h"
 #include "ui/events/event_utils.h"
diff --git a/chrome/browser/ui/views/toolbar/toolbar_view.cc b/chrome/browser/ui/views/toolbar/toolbar_view.cc
index 348c2c3..8fe09989 100644
--- a/chrome/browser/ui/views/toolbar/toolbar_view.cc
+++ b/chrome/browser/ui/views/toolbar/toolbar_view.cc
@@ -49,7 +49,6 @@
 #include "chrome/common/pref_names.h"
 #include "chrome/grit/chromium_strings.h"
 #include "chrome/grit/generated_resources.h"
-#include "chrome/grit/theme_resources.h"
 #include "components/omnibox/browser/omnibox_view.h"
 #include "components/prefs/pref_service.h"
 #include "components/strings/grit/components_strings.h"
diff --git a/chrome/browser/ui/views/try_chrome_dialog_view.cc b/chrome/browser/ui/views/try_chrome_dialog_view.cc
index efd5bfb..7a361551 100644
--- a/chrome/browser/ui/views/try_chrome_dialog_view.cc
+++ b/chrome/browser/ui/views/try_chrome_dialog_view.cc
@@ -14,7 +14,6 @@
 #include "chrome/browser/process_singleton.h"
 #include "chrome/browser/ui/views/harmony/chrome_layout_provider.h"
 #include "chrome/grit/chromium_strings.h"
-#include "chrome/grit/generated_resources.h"
 #include "chrome/grit/theme_resources.h"
 #include "chrome/install_static/install_util.h"
 #include "chrome/installer/util/user_experiment.h"
diff --git a/chrome/browser/ui/views/webshare/webshare_target_picker_view.cc b/chrome/browser/ui/views/webshare/webshare_target_picker_view.cc
index 74dff10..7c479a6 100644
--- a/chrome/browser/ui/views/webshare/webshare_target_picker_view.cc
+++ b/chrome/browser/ui/views/webshare/webshare_target_picker_view.cc
@@ -15,7 +15,6 @@
 #include "ui/views/controls/label.h"
 #include "ui/views/controls/table/table_view.h"
 #include "ui/views/layout/box_layout.h"
-#include "ui/views/layout/layout_constants.h"
 #include "ui/views/window/dialog_client_view.h"
 #include "url/gurl.h"
 
diff --git a/chrome/browser/ui/webui/about_ui.cc b/chrome/browser/ui/webui/about_ui.cc
index f3922f5..c3f0cc3 100644
--- a/chrome/browser/ui/webui/about_ui.cc
+++ b/chrome/browser/ui/webui/about_ui.cc
@@ -49,7 +49,6 @@
 #include "chrome/grit/browser_resources.h"
 #include "chrome/grit/chromium_strings.h"
 #include "chrome/grit/generated_resources.h"
-#include "chrome/grit/locale_settings.h"
 #include "components/grit/components_resources.h"
 #include "components/strings/grit/components_locale_settings.h"
 #include "content/public/browser/browser_thread.h"
diff --git a/chrome/browser/ui/webui/chromeos/login/encryption_migration_screen_handler.cc b/chrome/browser/ui/webui/chromeos/login/encryption_migration_screen_handler.cc
index e47c7ad1..f6e284a1 100644
--- a/chrome/browser/ui/webui/chromeos/login/encryption_migration_screen_handler.cc
+++ b/chrome/browser/ui/webui/chromeos/login/encryption_migration_screen_handler.cc
@@ -29,6 +29,7 @@
 #include "chromeos/dbus/dbus_thread_manager.h"
 #include "chromeos/dbus/power_manager/power_supply_properties.pb.h"
 #include "chromeos/dbus/power_manager_client.h"
+#include "chromeos/dbus/power_policy_controller.h"
 #include "components/login/localized_values_builder.h"
 #include "components/user_manager/user_manager.h"
 #include "content/public/browser/browser_thread.h"
@@ -282,11 +283,14 @@
   if (state == UIState::READY)
     DBusThreadManager::Get()->GetPowerManagerClient()->RequestStatusUpdate();
 
-  // We should block power save during migration.
-  if (state == UIState::MIGRATING)
+  // We should block power save and not shut down on lid close during migration.
+  if (state == UIState::MIGRATING) {
     StartBlockingPowerSave();
-  else
+    PowerPolicyController::Get()->SetEncryptionMigrationActive(true);
+  } else {
     StopBlockingPowerSave();
+    PowerPolicyController::Get()->SetEncryptionMigrationActive(false);
+  }
 }
 
 void EncryptionMigrationScreenHandler::CheckAvailableStorage() {
diff --git a/chrome/browser/ui/webui/chromeos/login/signin_screen_handler.cc b/chrome/browser/ui/webui/chromeos/login/signin_screen_handler.cc
index a412f9b7..29426e30 100644
--- a/chrome/browser/ui/webui/chromeos/login/signin_screen_handler.cc
+++ b/chrome/browser/ui/webui/chromeos/login/signin_screen_handler.cc
@@ -72,7 +72,6 @@
 #include "chrome/common/channel_info.h"
 #include "chrome/common/pref_names.h"
 #include "chrome/common/url_constants.h"
-#include "chrome/grit/chromium_strings.h"
 #include "chrome/grit/generated_resources.h"
 #include "chromeos/chromeos_switches.h"
 #include "chromeos/dbus/dbus_thread_manager.h"
@@ -723,7 +722,7 @@
     OnShowAddUser();
   } else {
     // Populates account picker. Animation is turned off for now until we
-    // figure out how to make it fast enough.
+    // figure out how to make it fast enough. This will call LoadUsers.
     delegate_->HandleGetUsers();
 
     // Reset Caps Lock state when login screen is shown.
@@ -1340,8 +1339,8 @@
     delegate_->ShowKioskAutolaunchScreen();
 }
 
-void SigninScreenHandler::LoadUsers(const base::ListValue& users_list,
-                                    bool showGuest) {
+void SigninScreenHandler::LoadUsers(const user_manager::UserList& users,
+                                    const base::ListValue& users_list) {
   CallJSOrDefer("login.AccountPickerScreen.loadUsers", users_list,
                 delegate_->IsShowGuest());
 }
diff --git a/chrome/browser/ui/webui/chromeos/login/signin_screen_handler.h b/chrome/browser/ui/webui/chromeos/login/signin_screen_handler.h
index df423f5..d5256e2 100644
--- a/chrome/browser/ui/webui/chromeos/login/signin_screen_handler.h
+++ b/chrome/browser/ui/webui/chromeos/login/signin_screen_handler.h
@@ -109,8 +109,9 @@
                                         const std::string& password) = 0;
   virtual void ShowWhitelistCheckFailedError() = 0;
   virtual void ShowUnrecoverableCrypthomeErrorDialog() = 0;
-  virtual void LoadUsers(const base::ListValue& users_list,
-                         bool show_guest) = 0;
+  virtual void LoadUsers(const user_manager::UserList& users,
+                         const base::ListValue& users_list) = 0;
+
  protected:
   virtual ~LoginDisplayWebUIHandler() {}
 };
@@ -342,7 +343,8 @@
                                 const std::string& password) override;
   void ShowWhitelistCheckFailedError() override;
   void ShowUnrecoverableCrypthomeErrorDialog() override;
-  void LoadUsers(const base::ListValue& users_list, bool show_guest) override;
+  void LoadUsers(const user_manager::UserList& users,
+                 const base::ListValue& users_list) override;
 
   // content::NotificationObserver implementation:
   void Observe(int type,
diff --git a/chrome/browser/ui/webui/chromeos/mobile_setup_ui.cc b/chrome/browser/ui/webui/chromeos/mobile_setup_ui.cc
index 26089fd..58d4d25 100644
--- a/chrome/browser/ui/webui/chromeos/mobile_setup_ui.cc
+++ b/chrome/browser/ui/webui/chromeos/mobile_setup_ui.cc
@@ -31,7 +31,6 @@
 #include "chrome/common/url_constants.h"
 #include "chrome/grit/browser_resources.h"
 #include "chrome/grit/generated_resources.h"
-#include "chrome/grit/locale_settings.h"
 #include "chromeos/network/device_state.h"
 #include "chromeos/network/network_configuration_handler.h"
 #include "chromeos/network/network_event_log.h"
diff --git a/chrome/browser/ui/webui/chromeos/network_ui.cc b/chrome/browser/ui/webui/chromeos/network_ui.cc
index 5cdb9f79..46ca4649 100644
--- a/chrome/browser/ui/webui/chromeos/network_ui.cc
+++ b/chrome/browser/ui/webui/chromeos/network_ui.cc
@@ -28,7 +28,6 @@
 #include "content/public/browser/web_ui_message_handler.h"
 #include "third_party/cros_system_api/dbus/service_constants.h"
 #include "ui/base/l10n/l10n_util.h"
-#include "ui/chromeos/strings/grit/ui_chromeos_strings.h"
 
 namespace chromeos {
 
diff --git a/chrome/browser/ui/webui/crashes_ui.cc b/chrome/browser/ui/webui/crashes_ui.cc
index e2d64ce..730f03d6 100644
--- a/chrome/browser/ui/webui/crashes_ui.cc
+++ b/chrome/browser/ui/webui/crashes_ui.cc
@@ -20,14 +20,10 @@
 #include "chrome/browser/metrics/metrics_reporting_state.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/common/url_constants.h"
-#include "chrome/grit/browser_resources.h"
 #include "chrome/grit/chromium_strings.h"
-#include "chrome/grit/generated_resources.h"
 #include "components/crash/core/browser/crashes_ui_util.h"
 #include "components/grit/components_resources.h"
 #include "components/grit/components_scaled_resources.h"
-#include "components/strings/grit/components_chromium_strings.h"
-#include "components/strings/grit/components_strings.h"
 #include "components/version_info/version_info.h"
 #include "content/public/browser/web_contents.h"
 #include "content/public/browser/web_ui.h"
diff --git a/chrome/browser/ui/webui/extensions/extension_settings_handler.cc b/chrome/browser/ui/webui/extensions/extension_settings_handler.cc
index e26eb13f..a62c8587 100644
--- a/chrome/browser/ui/webui/extensions/extension_settings_handler.cc
+++ b/chrome/browser/ui/webui/extensions/extension_settings_handler.cc
@@ -16,10 +16,8 @@
 #include "chrome/common/features.h"
 #include "chrome/common/pref_names.h"
 #include "chrome/common/url_constants.h"
-#include "chrome/grit/browser_resources.h"
 #include "chrome/grit/chromium_strings.h"
 #include "chrome/grit/generated_resources.h"
-#include "chrome/grit/theme_resources.h"
 #include "components/google/core/browser/google_util.h"
 #include "components/pref_registry/pref_registry_syncable.h"
 #include "components/prefs/pref_service.h"
diff --git a/chrome/browser/ui/webui/help/help_ui.cc b/chrome/browser/ui/webui/help/help_ui.cc
index 440fc72..94301b6 100644
--- a/chrome/browser/ui/webui/help/help_ui.cc
+++ b/chrome/browser/ui/webui/help/help_ui.cc
@@ -9,7 +9,6 @@
 #include "chrome/browser/ui/webui/help/help_handler.h"
 #include "chrome/common/url_constants.h"
 #include "chrome/grit/browser_resources.h"
-#include "chrome/grit/theme_resources.h"
 #include "content/public/browser/web_contents.h"
 #include "content/public/browser/web_ui.h"
 #include "content/public/browser/web_ui_data_source.h"
diff --git a/chrome/browser/ui/webui/log_web_ui_url_browsertest.cc b/chrome/browser/ui/webui/log_web_ui_url_browsertest.cc
index 07c45f3..24acac8 100644
--- a/chrome/browser/ui/webui/log_web_ui_url_browsertest.cc
+++ b/chrome/browser/ui/webui/log_web_ui_url_browsertest.cc
@@ -20,7 +20,6 @@
 #include "chrome/grit/generated_resources.h"
 #include "chrome/test/base/in_process_browser_test.h"
 #include "chrome/test/base/ui_test_utils.h"
-#include "components/strings/grit/components_strings.h"
 #include "content/public/common/url_constants.h"
 #include "content/public/test/browser_test_utils.h"
 #include "extensions/features/features.h"
diff --git a/chrome/browser/ui/webui/md_history_ui.cc b/chrome/browser/ui/webui/md_history_ui.cc
index 381cde7..1f55adc 100644
--- a/chrome/browser/ui/webui/md_history_ui.cc
+++ b/chrome/browser/ui/webui/md_history_ui.cc
@@ -21,7 +21,6 @@
 #include "chrome/grit/browser_resources.h"
 #include "chrome/grit/generated_resources.h"
 #include "chrome/grit/locale_settings.h"
-#include "chrome/grit/theme_resources.h"
 #include "components/pref_registry/pref_registry_syncable.h"
 #include "components/prefs/pref_service.h"
 #include "components/search/search.h"
diff --git a/chrome/browser/ui/webui/nacl_ui.cc b/chrome/browser/ui/webui/nacl_ui.cc
index 22a2027..e1863f2 100644
--- a/chrome/browser/ui/webui/nacl_ui.cc
+++ b/chrome/browser/ui/webui/nacl_ui.cc
@@ -36,7 +36,6 @@
 #include "chrome/common/url_constants.h"
 #include "chrome/grit/browser_resources.h"
 #include "chrome/grit/chromium_strings.h"
-#include "chrome/grit/generated_resources.h"
 #include "components/strings/grit/components_strings.h"
 #include "components/version_info/version_info.h"
 #include "content/public/browser/browser_thread.h"
diff --git a/chrome/browser/ui/webui/ntp/ntp_resource_cache.cc b/chrome/browser/ui/webui/ntp/ntp_resource_cache.cc
index 444478c..b3a4a3ff 100644
--- a/chrome/browser/ui/webui/ntp/ntp_resource_cache.cc
+++ b/chrome/browser/ui/webui/ntp/ntp_resource_cache.cc
@@ -32,7 +32,6 @@
 #include "chrome/grit/browser_resources.h"
 #include "chrome/grit/chromium_strings.h"
 #include "chrome/grit/generated_resources.h"
-#include "chrome/grit/locale_settings.h"
 #include "chrome/grit/theme_resources.h"
 #include "components/bookmarks/common/bookmark_pref_names.h"
 #include "components/google/core/browser/google_util.h"
diff --git a/chrome/browser/ui/webui/options/chromeos/cros_language_options_handler.cc b/chrome/browser/ui/webui/options/chromeos/cros_language_options_handler.cc
index 1c938f22..183fcde 100644
--- a/chrome/browser/ui/webui/options/chromeos/cros_language_options_handler.cc
+++ b/chrome/browser/ui/webui/options/chromeos/cros_language_options_handler.cc
@@ -27,7 +27,6 @@
 #include "chrome/browser/ui/browser_window.h"
 #include "chrome/browser/ui/tabs/tab_strip_model.h"
 #include "chrome/browser/ui/webui/chromeos/login/l10n_util.h"
-#include "chrome/grit/chromium_strings.h"
 #include "chrome/grit/generated_resources.h"
 #include "components/strings/grit/components_strings.h"
 #include "components/user_manager/user_manager.h"
diff --git a/chrome/browser/ui/webui/options/chromeos/power_handler.cc b/chrome/browser/ui/webui/options/chromeos/power_handler.cc
index 8cd2cb2..d522183 100644
--- a/chrome/browser/ui/webui/options/chromeos/power_handler.cc
+++ b/chrome/browser/ui/webui/options/chromeos/power_handler.cc
@@ -6,7 +6,6 @@
 
 #include <utility>
 
-#include "ash/resources/grit/ash_resources.h"
 #include "base/bind.h"
 #include "base/bind_helpers.h"
 #include "base/strings/string_number_conversions.h"
diff --git a/chrome/browser/ui/webui/options/chromeos/proxy_handler.cc b/chrome/browser/ui/webui/options/chromeos/proxy_handler.cc
index 72c066e7..6a6a7062 100644
--- a/chrome/browser/ui/webui/options/chromeos/proxy_handler.cc
+++ b/chrome/browser/ui/webui/options/chromeos/proxy_handler.cc
@@ -13,7 +13,6 @@
 #include "chrome/browser/chromeos/system/input_device_settings.h"
 #include "chrome/common/chrome_constants.h"
 #include "chrome/grit/generated_resources.h"
-#include "chrome/grit/locale_settings.h"
 #include "chromeos/chromeos_constants.h"
 #include "content/public/browser/web_ui.h"
 #include "ui/base/l10n/l10n_util.h"
diff --git a/chrome/browser/ui/webui/options/core_options_handler.cc b/chrome/browser/ui/webui/options/core_options_handler.cc
index ec45725b..45ca990 100644
--- a/chrome/browser/ui/webui/options/core_options_handler.cc
+++ b/chrome/browser/ui/webui/options/core_options_handler.cc
@@ -29,7 +29,6 @@
 #include "chrome/common/url_constants.h"
 #include "chrome/grit/chromium_strings.h"
 #include "chrome/grit/generated_resources.h"
-#include "chrome/grit/locale_settings.h"
 #include "components/proxy_config/proxy_config_pref_names.h"
 #include "components/strings/grit/components_strings.h"
 #include "components/url_formatter/url_fixer.h"
diff --git a/chrome/browser/ui/webui/options/options_ui.cc b/chrome/browser/ui/webui/options/options_ui.cc
index 4fea4576..5695a69 100644
--- a/chrome/browser/ui/webui/options/options_ui.cc
+++ b/chrome/browser/ui/webui/options/options_ui.cc
@@ -54,9 +54,7 @@
 #include "chrome/common/features.h"
 #include "chrome/common/url_constants.h"
 #include "chrome/grit/generated_resources.h"
-#include "chrome/grit/locale_settings.h"
 #include "chrome/grit/options_resources.h"
-#include "chrome/grit/theme_resources.h"
 #include "components/omnibox/browser/autocomplete_match.h"
 #include "components/omnibox/browser/autocomplete_result.h"
 #include "components/strings/grit/components_strings.h"
diff --git a/chrome/browser/ui/webui/options/sync_setup_handler.cc b/chrome/browser/ui/webui/options/sync_setup_handler.cc
index 6c4e9b6..de91eaf7 100644
--- a/chrome/browser/ui/webui/options/sync_setup_handler.cc
+++ b/chrome/browser/ui/webui/options/sync_setup_handler.cc
@@ -38,7 +38,6 @@
 #include "chrome/common/url_constants.h"
 #include "chrome/grit/chromium_strings.h"
 #include "chrome/grit/generated_resources.h"
-#include "chrome/grit/locale_settings.h"
 #include "components/autofill/core/common/autofill_constants.h"
 #include "components/autofill/core/common/autofill_pref_names.h"
 #include "components/browser_sync/profile_sync_service.h"
diff --git a/chrome/browser/ui/webui/policy_material_design_ui.cc b/chrome/browser/ui/webui/policy_material_design_ui.cc
index 7948c1c..d6f0ccc 100644
--- a/chrome/browser/ui/webui/policy_material_design_ui.cc
+++ b/chrome/browser/ui/webui/policy_material_design_ui.cc
@@ -79,7 +79,7 @@
     if (tags[i] != policy::RISK_TAG_NONE)
       list->AppendString(kPolicyRiskTags[tags[i]].key);
   }
-  names->Set(name, std::move(list));
+  names->SetWithoutPathExpansion(name, std::move(list));
 }
 
 void PolicyMaterialDesignUIHandler::SendPolicyNames() const {
diff --git a/chrome/browser/ui/webui/policy_ui_browsertest.cc b/chrome/browser/ui/webui/policy_ui_browsertest.cc
index 5514daf..38dbbb4 100644
--- a/chrome/browser/ui/webui/policy_ui_browsertest.cc
+++ b/chrome/browser/ui/webui/policy_ui_browsertest.cc
@@ -241,6 +241,12 @@
              policy::POLICY_SCOPE_USER, policy::POLICY_SOURCE_PLATFORM,
              base::MakeUnique<base::Value>(true), nullptr);
   expected_values[kUnknownPolicy] = "true";
+  const std::string kUnknownPolicyWithDots = "no.such.thing";
+  values.Set(kUnknownPolicyWithDots, policy::POLICY_LEVEL_MANDATORY,
+             policy::POLICY_SCOPE_USER, policy::POLICY_SOURCE_PLATFORM,
+             base::MakeUnique<base::Value>("blub"), nullptr);
+  expected_values[kUnknownPolicyWithDots] = "blub";
+
   UpdateProviderPolicy(values);
 
   // Expect that the policy table contains, in order:
@@ -273,6 +279,11 @@
                              "Platform",
                              values.Get(kUnknownPolicy),
                              true));
+  expected_policies.insert(
+      expected_policies.begin() + first_unset_position++,
+      PopulateExpectedPolicy(
+          kUnknownPolicyWithDots, expected_values[kUnknownPolicyWithDots],
+          "Platform", values.Get(kUnknownPolicyWithDots), true));
 
   // Retrieve the contents of the policy table from the UI and verify that it
   // matches the expectation.
diff --git a/chrome/browser/ui/webui/policy_ui_handler.cc b/chrome/browser/ui/webui/policy_ui_handler.cc
index 5ea1cbb..dc40f06 100644
--- a/chrome/browser/ui/webui/policy_ui_handler.cc
+++ b/chrome/browser/ui/webui/policy_ui_handler.cc
@@ -27,8 +27,6 @@
 #include "chrome/browser/policy/schema_registry_service.h"
 #include "chrome/browser/policy/schema_registry_service_factory.h"
 #include "chrome/browser/profiles/profile.h"
-#include "chrome/grit/policy_resources.h"
-#include "chrome/grit/policy_resources_map.h"
 #include "components/policy/core/browser/browser_policy_connector.h"
 #include "components/policy/core/browser/cloud/message_util.h"
 #include "components/policy/core/browser/configuration_policy_handler_list.h"
@@ -631,7 +629,7 @@
 
 void PolicyUIHandler::AddPolicyName(const std::string& name,
                                     base::DictionaryValue* names) const {
-    names->SetBoolean(name, true);
+  names->SetBooleanWithoutPathExpansion(name, true);
 }
 
 void PolicyUIHandler::SendPolicyNames() const {
@@ -738,7 +736,7 @@
     base::string16 error = errors->GetErrors(entry.first);
     if (!error.empty())
       value->SetString("error", error);
-    values->Set(entry.first, std::move(value));
+    values->SetWithoutPathExpansion(entry.first, std::move(value));
   }
 }
 
diff --git a/chrome/browser/ui/webui/settings/chromeos/device_power_handler.cc b/chrome/browser/ui/webui/settings/chromeos/device_power_handler.cc
index 535e9418..fd724b2 100644
--- a/chrome/browser/ui/webui/settings/chromeos/device_power_handler.cc
+++ b/chrome/browser/ui/webui/settings/chromeos/device_power_handler.cc
@@ -7,7 +7,6 @@
 #include <memory>
 #include <utility>
 
-#include "ash/resources/grit/ash_resources.h"
 #include "base/bind.h"
 #include "base/bind_helpers.h"
 #include "base/strings/string_number_conversions.h"
diff --git a/chrome/browser/ui/webui/settings/md_settings_localized_strings_provider.cc b/chrome/browser/ui/webui/settings/md_settings_localized_strings_provider.cc
index be7a0af..87c4040 100644
--- a/chrome/browser/ui/webui/settings/md_settings_localized_strings_provider.cc
+++ b/chrome/browser/ui/webui/settings/md_settings_localized_strings_provider.cc
@@ -44,7 +44,6 @@
 #include "chromeos/chromeos_switches.h"
 #include "components/user_manager/user.h"
 #include "components/user_manager/user_manager.h"
-#include "ui/chromeos/strings/grit/ui_chromeos_strings.h"
 #include "ui/display/display_switches.h"
 #else
 #include "chrome/browser/ui/webui/settings/system_handler.h"
diff --git a/chrome/browser/ui/webui/settings/settings_import_data_handler.cc b/chrome/browser/ui/webui/settings/settings_import_data_handler.cc
index a29576c..a0a37b8a 100644
--- a/chrome/browser/ui/webui/settings/settings_import_data_handler.cc
+++ b/chrome/browser/ui/webui/settings/settings_import_data_handler.cc
@@ -27,8 +27,6 @@
 #include "chrome/browser/ui/browser_window.h"
 #include "chrome/browser/ui/chrome_select_file_policy.h"
 #include "chrome/common/pref_names.h"
-#include "chrome/grit/chromium_strings.h"
-#include "chrome/grit/generated_resources.h"
 #include "content/public/browser/browser_thread.h"
 #include "content/public/browser/web_ui.h"
 
diff --git a/chrome/browser/ui/webui/signin/inline_login_handler_impl.cc b/chrome/browser/ui/webui/signin/inline_login_handler_impl.cc
index 2dde2ab..7b77dde 100644
--- a/chrome/browser/ui/webui/signin/inline_login_handler_impl.cc
+++ b/chrome/browser/ui/webui/signin/inline_login_handler_impl.cc
@@ -60,7 +60,6 @@
 #include "components/signin/core/browser/signin_investigator.h"
 #include "components/signin/core/browser/signin_metrics.h"
 #include "components/signin/core/common/signin_pref_names.h"
-#include "components/strings/grit/components_strings.h"
 #include "content/public/browser/navigation_handle.h"
 #include "content/public/browser/storage_partition.h"
 #include "content/public/browser/web_ui.h"
diff --git a/chrome/browser/ui/webui/signin/md_user_manager_ui.cc b/chrome/browser/ui/webui/signin/md_user_manager_ui.cc
index f208584..e7fbef7 100644
--- a/chrome/browser/ui/webui/signin/md_user_manager_ui.cc
+++ b/chrome/browser/ui/webui/signin/md_user_manager_ui.cc
@@ -18,7 +18,6 @@
 #include "chrome/common/features.h"
 #include "chrome/common/url_constants.h"
 #include "chrome/grit/browser_resources.h"
-#include "chrome/grit/settings_resources.h"
 #include "content/public/browser/web_ui.h"
 #include "content/public/browser/web_ui_data_source.h"
 #include "ui/base/resource/resource_bundle.h"
diff --git a/chrome/browser/ui/webui/signin/signin_email_confirmation_dialog.cc b/chrome/browser/ui/webui/signin/signin_email_confirmation_dialog.cc
index 2af9a84..5183239 100644
--- a/chrome/browser/ui/webui/signin/signin_email_confirmation_dialog.cc
+++ b/chrome/browser/ui/webui/signin/signin_email_confirmation_dialog.cc
@@ -13,8 +13,6 @@
 #include "chrome/browser/ui/browser_dialogs.h"
 #include "chrome/browser/ui/webui/signin/signin_email_confirmation_ui.h"
 #include "chrome/common/url_constants.h"
-#include "chrome/grit/browser_resources.h"
-#include "chrome/grit/generated_resources.h"
 #include "content/public/browser/web_contents.h"
 #include "content/public/browser/web_contents_observer.h"
 #include "content/public/browser/web_ui.h"
diff --git a/chrome/browser/ui/webui/version_ui.cc b/chrome/browser/ui/webui/version_ui.cc
index 632d0ea..81fe7b3 100644
--- a/chrome/browser/ui/webui/version_ui.cc
+++ b/chrome/browser/ui/webui/version_ui.cc
@@ -14,12 +14,10 @@
 #include "chrome/common/channel_info.h"
 #include "chrome/common/chrome_content_client.h"
 #include "chrome/common/url_constants.h"
-#include "chrome/grit/browser_resources.h"
 #include "chrome/grit/chromium_strings.h"
 #include "chrome/grit/generated_resources.h"
 #include "chrome/install_static/install_details.h"
 #include "components/grit/components_resources.h"
-#include "components/strings/grit/components_chromium_strings.h"
 #include "components/strings/grit/components_strings.h"
 #include "components/version_info/version_info.h"
 #include "components/version_ui/version_ui_constants.h"
diff --git a/chrome/browser/ui/webui/webapks_ui.cc b/chrome/browser/ui/webui/webapks_ui.cc
index d71329302..bb6b6176 100644
--- a/chrome/browser/ui/webui/webapks_ui.cc
+++ b/chrome/browser/ui/webui/webapks_ui.cc
@@ -11,7 +11,6 @@
 #include "chrome/browser/ui/webui/webapks_handler.h"
 #include "chrome/common/url_constants.h"
 #include "chrome/grit/webapks_ui_resources.h"
-#include "components/grit/components_resources.h"
 #include "content/public/browser/web_ui.h"
 #include "content/public/browser/web_ui_data_source.h"
 
diff --git a/chrome/browser/ui/webui/welcome_win10_ui.cc b/chrome/browser/ui/webui/welcome_win10_ui.cc
index 8628e5b9..c5741b98 100644
--- a/chrome/browser/ui/webui/welcome_win10_ui.cc
+++ b/chrome/browser/ui/webui/welcome_win10_ui.cc
@@ -18,7 +18,6 @@
 #include "chrome/grit/chrome_unscaled_resources.h"
 #include "chrome/grit/chromium_strings.h"
 #include "chrome/grit/generated_resources.h"
-#include "chrome/grit/theme_resources.h"
 #include "components/prefs/pref_service.h"
 #include "content/public/browser/web_ui_data_source.h"
 #include "net/base/url_util.h"
diff --git a/chrome/browser/web_applications/web_app_mac.mm b/chrome/browser/web_applications/web_app_mac.mm
index 45ebd5a..178a16b90 100644
--- a/chrome/browser/web_applications/web_app_mac.mm
+++ b/chrome/browser/web_applications/web_app_mac.mm
@@ -46,7 +46,6 @@
 #include "chrome/common/chrome_switches.h"
 #import "chrome/common/mac/app_mode_common.h"
 #include "chrome/grit/chrome_unscaled_resources.h"
-#include "chrome/grit/generated_resources.h"
 #include "components/crx_file/id_util.h"
 #include "components/version_info/version_info.h"
 #include "content/public/browser/browser_thread.h"
diff --git a/chrome/common/extensions/chrome_extensions_client.cc b/chrome/common/extensions/chrome_extensions_client.cc
index ec7f902..5b08d48 100644
--- a/chrome/common/extensions/chrome_extensions_client.cc
+++ b/chrome/common/extensions/chrome_extensions_client.cc
@@ -27,7 +27,6 @@
 #include "chrome/common/url_constants.h"
 #include "chrome/grit/chromium_strings.h"
 #include "chrome/grit/common_resources.h"
-#include "chrome/grit/generated_resources.h"
 #include "components/version_info/version_info.h"
 #include "content/public/common/url_constants.h"
 #include "extensions/common/api/generated_schemas.h"
diff --git a/chrome/common/extensions/permissions/chrome_permission_message_provider.cc b/chrome/common/extensions/permissions/chrome_permission_message_provider.cc
index e239514..d0afe3b 100644
--- a/chrome/common/extensions/permissions/chrome_permission_message_provider.cc
+++ b/chrome/common/extensions/permissions/chrome_permission_message_provider.cc
@@ -11,13 +11,11 @@
 #include "base/strings/string_util.h"
 #include "base/strings/utf_string_conversions.h"
 #include "chrome/common/extensions/permissions/chrome_permission_message_rules.h"
-#include "chrome/grit/generated_resources.h"
 #include "extensions/common/extensions_client.h"
 #include "extensions/common/permissions/permission_message_util.h"
 #include "extensions/common/permissions/permission_set.h"
 #include "extensions/common/url_pattern.h"
 #include "extensions/common/url_pattern_set.h"
-#include "extensions/strings/grit/extensions_strings.h"
 #include "url/gurl.h"
 
 namespace extensions {
diff --git a/chrome/renderer/chrome_content_renderer_client.cc b/chrome/renderer/chrome_content_renderer_client.cc
index 59cd0a21..1ef52dd4 100644
--- a/chrome/renderer/chrome_content_renderer_client.cc
+++ b/chrome/renderer/chrome_content_renderer_client.cc
@@ -38,7 +38,6 @@
 #include "chrome/common/url_constants.h"
 #include "chrome/grit/chromium_strings.h"
 #include "chrome/grit/generated_resources.h"
-#include "chrome/grit/locale_settings.h"
 #include "chrome/grit/renderer_resources.h"
 #include "chrome/renderer/app_categorizer.h"
 #include "chrome/renderer/benchmarking_extension.h"
diff --git a/chrome/renderer/plugins/non_loadable_plugin_placeholder.cc b/chrome/renderer/plugins/non_loadable_plugin_placeholder.cc
index b6e550a..9ae428a 100644
--- a/chrome/renderer/plugins/non_loadable_plugin_placeholder.cc
+++ b/chrome/renderer/plugins/non_loadable_plugin_placeholder.cc
@@ -7,7 +7,6 @@
 #include "base/files/file_path.h"
 #include "base/values.h"
 #include "chrome/common/render_messages.h"
-#include "chrome/grit/generated_resources.h"
 #include "chrome/grit/renderer_resources.h"
 #include "components/plugins/renderer/plugin_placeholder.h"
 #include "components/strings/grit/components_strings.h"
diff --git a/chrome/test/chromedriver/test/run_py_tests.py b/chrome/test/chromedriver/test/run_py_tests.py
index 4e914bb2..ac414e1 100755
--- a/chrome/test/chromedriver/test/run_py_tests.py
+++ b/chrome/test/chromedriver/test/run_py_tests.py
@@ -219,6 +219,11 @@
         'ChromeDriverTest.testClickElementAfterNavigation',
         'ChromeDriverTest.testGetLogOnWindowWithAlert',
         'ChromeDriverTest.testUnexpectedAlertOpenExceptionMessage',
+        # The WebView shell that we test against (on Kitkat) does not yet
+        # support Network.setCookie DevTools command.
+        # TODO(gmanikpure): reenable when it does.
+        'ChromeDriverTest.testGetHttpOnlyCookie',
+        'ChromeDriverLogTest.testDisablingDriverLogsSuppressesChromeDriverLog',
     ]
 )
 
diff --git a/chrome/test/data/extensions/api_test/cast_streaming/performance.js b/chrome/test/data/extensions/api_test/cast_streaming/performance.js
index a2935ec..d9c9cd9d 100644
--- a/chrome/test/data/extensions/api_test/cast_streaming/performance.js
+++ b/chrome/test/data/extensions/api_test/cast_streaming/performance.js
@@ -2,10 +2,16 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-// Run a cast v2 mirroring session for 10 seconds.
+// Run a cast v2 mirroring session for 15 seconds.
 
 chrome.test.runTests([
   function sendTestPatterns() {
+    const kMaxFrameRate = 30;
+    const kCallbackTimeoutMillis = 10000;
+    const kTestRunTimeMillis = 15000;
+
+    const rtpStream = chrome.cast.streaming.rtpStream;
+
     // The receive port changes between browser_test invocations, and is passed
     // as an query parameter in the URL.
     let recvPort;
@@ -25,67 +31,114 @@
       return;
     }
 
-    const kMaxFrameRate = 30;
-    chrome.tabCapture.capture(
-        { video: true,
-          audio: true,
-          videoConstraints: {
-              mandatory: autoThrottling ? ({
-                  minWidth: 320,
-                  minHeight: 180,
-                  maxWidth: 1920,
-                  maxHeight: 1080,
-                  maxFrameRate: kMaxFrameRate,
-                  enableAutoThrottling: true
-              }) : ({
-                  minWidth: 1920,
-                  minHeight: 1080,
-                  maxWidth: 1920,
-                  maxHeight: 1080,
-                  maxFrameRate: kMaxFrameRate,
-              })
+    // Start capture and wait up to kCallbackTimeoutMillis for it to start.
+    const startCapturePromise = new Promise((resolve, reject) => {
+      const timeoutId = setTimeout(() => {
+        reject(Error('chrome.tabCapture.capture() did not call back'));
+      }, kCallbackTimeoutMillis);
+
+      const captureOptions = {
+        video: true,
+        audio: true,
+        videoConstraints: {
+          mandatory: {
+            minWidth: autoThrottling ? 320 : 1920,
+            minHeight: autoThrottling ? 180 : 1080,
+            maxWidth: 1920,
+            maxHeight: 1080,
+            maxFrameRate: kMaxFrameRate,
+            enableAutoThrottling: autoThrottling,
           }
-        },
-        captureStream => {
-          if (!captureStream) {
-            chrome.test.fail(chrome.runtime.lastError.message || 'null stream');
-            return;
+        }
+      };
+      chrome.tabCapture.capture(captureOptions, captureStream => {
+        clearTimeout(timeoutId);
+        if (captureStream) {
+          console.log('Started tab capture.');
+          resolve(captureStream);
+        } else {
+          if (chrome.runtime.lastError) {
+            reject(chrome.runtime.lastError);
+          } else {
+            reject(Error('null stream'));
           }
+        }
+      });
+    });
 
-          chrome.cast.streaming.session.create(
-              captureStream.getAudioTracks()[0],
-              captureStream.getVideoTracks()[0],
-              (audioId, videoId, udpId) => {
-                chrome.cast.streaming.udpTransport.setDestination(
-                    udpId, { address: "127.0.0.1", port: recvPort } );
-                const rtpStream = chrome.cast.streaming.rtpStream;
-                rtpStream.onError.addListener(() => {
-                  chrome.test.fail('RTP stream error');
-                });
-                const audioParams = rtpStream.getSupportedParams(audioId)[0];
-                audioParams.payload.aesKey = aesKey;
-                audioParams.payload.aesIvMask = aesIvMask;
-                rtpStream.start(audioId, audioParams);
-                const videoParams = rtpStream.getSupportedParams(videoId)[0];
-                videoParams.payload.clockRate = kMaxFrameRate;
-                videoParams.payload.aesKey = aesKey;
-                videoParams.payload.aesIvMask = aesIvMask;
-                rtpStream.start(videoId, videoParams);
-                setTimeout(() => {
-                  chrome.test.succeed();
+    // Then, start Cast Streaming and wait up to kCallbackTimeoutMillis for it
+    // to start.
+    const startStreamingPromise = startCapturePromise.then(captureStream => {
+      return new Promise((resolve, reject) => {
+        const timeoutId = setTimeout(() => {
+          reject(Error(
+            'chrome.cast.streaming.session.create() did not call back'));
+        }, kCallbackTimeoutMillis);
 
-                  rtpStream.stop(audioId);
-                  rtpStream.stop(videoId);
-                  rtpStream.destroy(audioId);
-                  rtpStream.destroy(videoId);
+        chrome.cast.streaming.session.create(
+            captureStream.getAudioTracks()[0],
+            captureStream.getVideoTracks()[0],
+            (audioId, videoId, udpId) => {
+          clearTimeout(timeoutId);
 
-                  const tracks = captureStream.getTracks();
-                  for (let i = 0; i < tracks.length; ++i) {
-                    tracks[i].stop();
-                  }
-                  chrome.test.assertFalse(captureStream.active);
-                }, 15000);  // 15 seconds
-              });
+          try {
+            chrome.cast.streaming.udpTransport.setDestination(
+                udpId, { address: "127.0.0.1", port: recvPort } );
+            rtpStream.onError.addListener(() => {
+              chrome.test.fail('RTP stream error');
+            });
+            const audioParams = rtpStream.getSupportedParams(audioId)[0];
+            audioParams.payload.aesKey = aesKey;
+            audioParams.payload.aesIvMask = aesIvMask;
+            rtpStream.start(audioId, audioParams);
+            const videoParams = rtpStream.getSupportedParams(videoId)[0];
+            videoParams.payload.clockRate = kMaxFrameRate;
+            videoParams.payload.aesKey = aesKey;
+            videoParams.payload.aesIvMask = aesIvMask;
+            rtpStream.start(videoId, videoParams);
+
+            console.log('Started Cast Streaming.');
+            resolve([captureStream, audioId, videoId, udpId]);
+          } catch (error) {
+            reject(error);
+          }
         });
+      });
+    });
+
+    // Then, let the test run for kTestRunTimeMillis, and then shut down the RTP
+    // streams and MediaStreamTracks.
+    const doneTestingPromise = startStreamingPromise.then(
+        ([captureStream, audioId, videoId, udpId]) => {
+      return new Promise(resolve => {
+        console.log(`Running test for ${kTestRunTimeMillis} ms.`);
+        setTimeout(resolve, kTestRunTimeMillis);
+      }).then(() => {
+        rtpStream.stop(audioId);
+        rtpStream.stop(videoId);
+        rtpStream.destroy(audioId);
+        rtpStream.destroy(videoId);
+
+        chrome.cast.streaming.udpTransport.destroy(udpId);
+
+        const tracks = captureStream.getTracks();
+        for (let i = 0; i < tracks.length; ++i) {
+          tracks[i].stop();
+        }
+      });
+    });
+
+    // If all of the above completed without error, the test run has succeeded.
+    // Otherwise, flag that the test has failed with the cause.
+    doneTestingPromise.then(() => {
+      chrome.test.succeed();
+    }).catch(error => {
+      if (typeof error === 'object' &&
+          ('stack' in error || 'message' in error)) {
+        chrome.test.fail(error.stack || error.message);
+      } else {
+        chrome.test.fail(String(error));
+      }
+    });
   }
 ]);
diff --git a/chrome/test/data/webui/print_preview/print_preview.js b/chrome/test/data/webui/print_preview/print_preview.js
index fbc893c7..8c16737 100644
--- a/chrome/test/data/webui/print_preview/print_preview.js
+++ b/chrome/test/data/webui/print_preview/print_preview.js
@@ -295,288 +295,6 @@
           loadTimeData.getBoolean('printPdfAsImageEnabled'));
 }
 
-
-// Page layout has zero top and bottom margins. Hide header and footer option.
-TEST_F('PrintPreviewWebUITest',
-       'ZeroTopAndBottomMarginsHideHeaderFooter',
-       function() {
-  this.setInitialSettings();
-  this.nativeLayer_.whenCalled('getInitialSettings').then(
-      function() {
-        this.setLocalDestinations();
-        this.setCapabilities(getCddTemplate("FooDevice"));
-
-        var otherOptions = $('other-options-settings');
-        var headerFooter =
-            otherOptions.querySelector('#header-footer-container');
-
-        // Check that options are collapsed (section is visible, because duplex
-        // is available).
-        checkSectionVisible(otherOptions, true);
-        checkElementDisplayed(headerFooter, false);
-
-        this.expandMoreSettings();
-
-        checkElementDisplayed(headerFooter, true);
-
-        this.printPreview_.printTicketStore_.marginsType.updateValue(
-            print_preview.ticket_items.MarginsTypeValue.CUSTOM);
-        this.printPreview_.printTicketStore_.customMargins.updateValue(
-            new print_preview.Margins(0, 36, 0, 36));
-
-        checkElementDisplayed(headerFooter, false);
-
-        this.waitForAnimationToEnd('more-settings');
-      }.bind(this));
-});
-
-// Page layout has zero top and half-inch bottom margin. Show header and footer
-// option.
-TEST_F('PrintPreviewWebUITest',
-       'ZeroTopAndNonZeroBottomMarginShowHeaderFooter',
-       function() {
-  this.setInitialSettings();
-  this.nativeLayer_.whenCalled('getInitialSettings').then(
-      function() {
-        this.setLocalDestinations();
-        this.setCapabilities(getCddTemplate("FooDevice"));
-
-        var otherOptions = $('other-options-settings');
-        var headerFooter =
-            otherOptions.querySelector('#header-footer-container');
-
-        // Check that options are collapsed (section is visible, because duplex
-        // is available).
-        checkSectionVisible(otherOptions, true);
-        checkElementDisplayed(headerFooter, false);
-
-        this.expandMoreSettings();
-
-        checkElementDisplayed(headerFooter, true);
-
-        this.printPreview_.printTicketStore_.marginsType.updateValue(
-            print_preview.ticket_items.MarginsTypeValue.CUSTOM);
-        this.printPreview_.printTicketStore_.customMargins.updateValue(
-            new print_preview.Margins(0, 36, 36, 36));
-
-        checkElementDisplayed(headerFooter, true);
-
-        this.waitForAnimationToEnd('more-settings');
-      }.bind(this));
-});
-
-// Check header footer availability with small (label) page size.
-TEST_F('PrintPreviewWebUITest', 'SmallPaperSizeHeaderFooter', function() {
-  this.setInitialSettings();
-  this.nativeLayer_.whenCalled('getInitialSettings').then(
-      function() {
-        this.setLocalDestinations();
-        var device = getCddTemplate("FooDevice");
-        device.capabilities.printer.media_size = {
-          "option": [
-            {"name": "SmallLabel", "width_microns": 38100,
-              "height_microns": 12700, "is_default": false},
-            {"name": "BigLabel", "width_microns": 50800,
-              "height_microns": 76200, "is_default": true}
-          ]
-        };
-        this.setCapabilities(device);
-
-        var otherOptions = $('other-options-settings');
-        var headerFooter =
-            otherOptions.querySelector('#header-footer-container');
-
-        // Check that options are collapsed (section is visible, because duplex
-        // is available).
-        checkSectionVisible(otherOptions, true);
-        checkElementDisplayed(headerFooter, false);
-
-        this.expandMoreSettings();
-
-        // Big label should have header/footer
-        checkElementDisplayed(headerFooter, true);
-
-        // Small label should not
-        this.printPreview_.printTicketStore_.mediaSize.updateValue(
-            device.capabilities.printer.media_size.option[0]);
-        checkElementDisplayed(headerFooter, false);
-
-        // Oriented in landscape, there should be enough space for
-        // header/footer.
-        this.printPreview_.printTicketStore_.landscape.updateValue(true);
-        checkElementDisplayed(headerFooter, true);
-
-        this.waitForAnimationToEnd('more-settings');
-      }.bind(this));
-});
-
-// Test that the color settings, one option, standard monochrome.
-TEST_F('PrintPreviewWebUITest', 'TestColorSettingsMonochrome', function() {
-  this.setInitialSettings();
-  this.nativeLayer_.whenCalled('getInitialSettings').then(
-      function() {
-        this.setLocalDestinations();
-
-        // Only one option, standard monochrome.
-        var device = getCddTemplate("FooDevice");
-        device.capabilities.printer.color = {
-          "option": [
-            {"is_default": true, "type": "STANDARD_MONOCHROME"}
-          ]
-        };
-        this.setCapabilities(device);
-
-        checkSectionVisible($('color-settings'), false);
-
-        this.waitForAnimationToEnd('more-settings');
-      }.bind(this));
-});
-
-// Test that the color settings, one option, custom monochrome.
-TEST_F('PrintPreviewWebUITest', 'TestColorSettingsCustomMonochrome',
-    function() {
-  this.setInitialSettings();
-  this.nativeLayer_.whenCalled('getInitialSettings').then(
-      function() {
-        this.setLocalDestinations();
-
-        // Only one option, standard monochrome.
-        var device = getCddTemplate("FooDevice");
-        device.capabilities.printer.color = {
-          "option": [
-            {"is_default": true, "type": "CUSTOM_MONOCHROME",
-             "vendor_id": "42"}
-          ]
-        };
-        this.setCapabilities(device);
-
-        checkSectionVisible($('color-settings'), false);
-
-        this.waitForAnimationToEnd('more-settings');
-      }.bind(this));
-});
-
-// Test that the color settings, one option, standard color.
-TEST_F('PrintPreviewWebUITest', 'TestColorSettingsColor', function() {
-  this.setInitialSettings();
-  this.nativeLayer_.whenCalled('getInitialSettings').then(
-      function() {
-        this.setLocalDestinations();
-
-        var device = getCddTemplate("FooDevice");
-        device.capabilities.printer.color = {
-          "option": [
-            {"is_default": true, "type": "STANDARD_COLOR"}
-          ]
-        };
-        this.setCapabilities(device);
-
-        checkSectionVisible($('color-settings'), false);
-
-        this.waitForAnimationToEnd('more-settings');
-      }.bind(this));
-});
-
-// Test that the color settings, one option, custom color.
-TEST_F('PrintPreviewWebUITest', 'TestColorSettingsCustomColor', function() {
-  this.setInitialSettings();
-  this.nativeLayer_.whenCalled('getInitialSettings').then(
-      function() {
-        this.setLocalDestinations();
-
-        var device = getCddTemplate("FooDevice");
-        device.capabilities.printer.color = {
-          "option": [
-            {"is_default": true, "type": "CUSTOM_COLOR", "vendor_id": "42"}
-          ]
-        };
-        this.setCapabilities(device);
-
-        checkSectionVisible($('color-settings'), false);
-
-        this.waitForAnimationToEnd('more-settings');
-      }.bind(this));
-});
-
-// Test that the color settings, two options, both standard, defaults to color.
-TEST_F('PrintPreviewWebUITest', 'TestColorSettingsBothStandardDefaultColor',
-    function() {
-  this.setInitialSettings();
-  this.nativeLayer_.whenCalled('getInitialSettings').then(
-      function() {
-        this.setLocalDestinations();
-
-        var device = getCddTemplate("FooDevice");
-        device.capabilities.printer.color = {
-          "option": [
-            {"type": "STANDARD_MONOCHROME"},
-            {"is_default": true, "type": "STANDARD_COLOR"}
-          ]
-        };
-        this.setCapabilities(device);
-
-        checkSectionVisible($('color-settings'), true);
-        expectEquals(
-            'color',
-            $('color-settings').querySelector('.color-settings-select').value);
-
-        this.waitForAnimationToEnd('more-settings');
-      }.bind(this));
-});
-
-// Test that the color settings, two options, both standard, defaults to
-// monochrome.
-TEST_F('PrintPreviewWebUITest',
-    'TestColorSettingsBothStandardDefaultMonochrome', function() {
-  this.setInitialSettings();
-  this.nativeLayer_.whenCalled('getInitialSettings').then(
-      function() {
-        this.setLocalDestinations();
-
-        var device = getCddTemplate("FooDevice");
-        device.capabilities.printer.color = {
-          "option": [
-            {"is_default": true, "type": "STANDARD_MONOCHROME"},
-            {"type": "STANDARD_COLOR"}
-          ]
-        };
-        this.setCapabilities(device);
-
-        checkSectionVisible($('color-settings'), true);
-        expectEquals(
-            'bw',
-            $('color-settings').querySelector('.color-settings-select').value);
-
-        this.waitForAnimationToEnd('more-settings');
-      }.bind(this));
-});
-
-// Test that the color settings, two options, both custom, defaults to color.
-TEST_F('PrintPreviewWebUITest',
-    'TestColorSettingsBothCustomDefaultColor', function() {
-  this.setInitialSettings();
-  this.nativeLayer_.whenCalled('getInitialSettings').then(
-      function() {
-        this.setLocalDestinations();
-
-        var device = getCddTemplate("FooDevice");
-        device.capabilities.printer.color = {
-          "option": [
-            {"type": "CUSTOM_MONOCHROME", "vendor_id": "42"},
-            {"is_default": true, "type": "CUSTOM_COLOR", "vendor_id": "43"}
-          ]
-        };
-        this.setCapabilities(device);
-
-        checkSectionVisible($('color-settings'), true);
-        expectEquals(
-            'color',
-            $('color-settings').querySelector('.color-settings-select').value);
-
-        this.waitForAnimationToEnd('more-settings');
-      }.bind(this));
-});
-
 // Test to verify that duplex settings are set according to the printer
 // capabilities.
 TEST_F('PrintPreviewWebUITest', 'TestDuplexSettingsTrue', function() {
diff --git a/chrome/test/data/webui/print_preview/print_preview_tests.js b/chrome/test/data/webui/print_preview/print_preview_tests.js
index aa6243d..8610103 100644
--- a/chrome/test/data/webui/print_preview/print_preview_tests.js
+++ b/chrome/test/data/webui/print_preview/print_preview_tests.js
@@ -737,35 +737,302 @@
     // Page layout has half-inch margins. Show header and footer option.
     test('PageLayoutHasMarginsShowHeaderFooter', function() {
       setInitialSettings();
-      nativeLayer.whenCalled('getInitialSettings').then(
+      return nativeLayer.whenCalled('getInitialSettings').then(function() {
+        setLocalDestinations();
+        setCapabilities(getCddTemplate('FooDevice'));
+
+        var otherOptions = $('other-options-settings');
+        var headerFooter =
+            otherOptions.querySelector('#header-footer-container');
+
+        // Check that options are collapsed (section is visible, because
+        // duplex is available).
+        checkSectionVisible(otherOptions, true);
+        checkElementDisplayed(headerFooter, false);
+
+        expandMoreSettings();
+
+        checkElementDisplayed(headerFooter, true);
+
+        printPreview.printTicketStore_.marginsType.updateValue(
+            print_preview.ticket_items.MarginsTypeValue.CUSTOM);
+        printPreview.printTicketStore_.customMargins.updateValue(
+            new print_preview.Margins(36, 36, 36, 36));
+
+        checkElementDisplayed(headerFooter, true);
+
+        return whenAnimationDone('more-settings');
+      });
+    });
+
+
+    // Page layout has zero top and bottom margins. Hide header and footer
+    // option.
+    test('ZeroTopAndBottomMarginsHideHeaderFooter', function() {
+      setInitialSettings();
+      return nativeLayer.whenCalled('getInitialSettings').then(function() {
+        setLocalDestinations();
+        setCapabilities(getCddTemplate('FooDevice'));
+
+        var otherOptions = $('other-options-settings');
+        var headerFooter =
+            otherOptions.querySelector('#header-footer-container');
+
+        // Check that options are collapsed (section is visible, because duplex
+        // is available).
+        checkSectionVisible(otherOptions, true);
+        checkElementDisplayed(headerFooter, false);
+
+        expandMoreSettings();
+
+        checkElementDisplayed(headerFooter, true);
+
+        printPreview.printTicketStore_.marginsType.updateValue(
+            print_preview.ticket_items.MarginsTypeValue.CUSTOM);
+        printPreview.printTicketStore_.customMargins.updateValue(
+            new print_preview.Margins(0, 36, 0, 36));
+
+        checkElementDisplayed(headerFooter, false);
+
+        return whenAnimationDone('more-settings');
+      });
+    });
+
+    // Page layout has zero top and half-inch bottom margin. Show header and
+    // footer option.
+    test('ZeroTopAndNonZeroBottomMarginShowHeaderFooter', function() {
+      setInitialSettings();
+      return nativeLayer.whenCalled('getInitialSettings').then(function() {
+        setLocalDestinations();
+        setCapabilities(getCddTemplate('FooDevice'));
+
+        var otherOptions = $('other-options-settings');
+        var headerFooter =
+            otherOptions.querySelector('#header-footer-container');
+
+        // Check that options are collapsed (section is visible, because duplex
+        // is available).
+        checkSectionVisible(otherOptions, true);
+        checkElementDisplayed(headerFooter, false);
+
+        expandMoreSettings();
+
+        checkElementDisplayed(headerFooter, true);
+
+        printPreview.printTicketStore_.marginsType.updateValue(
+            print_preview.ticket_items.MarginsTypeValue.CUSTOM);
+        printPreview.printTicketStore_.customMargins.updateValue(
+            new print_preview.Margins(0, 36, 36, 36));
+
+        checkElementDisplayed(headerFooter, true);
+
+        return whenAnimationDone('more-settings');
+      });
+    });
+
+    // Check header footer availability with small (label) page size.
+    test('SmallPaperSizeHeaderFooter', function() {
+      setInitialSettings();
+      return nativeLayer.whenCalled('getInitialSettings').then(function() {
+        setLocalDestinations();
+        var device = getCddTemplate('FooDevice');
+        device.capabilities.printer.media_size = {
+          'option': [
+            {'name': 'SmallLabel', 'width_microns': 38100,
+              'height_microns': 12700, 'is_default': false},
+            {'name': 'BigLabel', 'width_microns': 50800,
+              'height_microns': 76200, 'is_default': true}
+          ]
+        };
+        setCapabilities(device);
+
+        var otherOptions = $('other-options-settings');
+        var headerFooter =
+            otherOptions.querySelector('#header-footer-container');
+
+        // Check that options are collapsed (section is visible, because duplex
+        // is available).
+        checkSectionVisible(otherOptions, true);
+        checkElementDisplayed(headerFooter, false);
+
+        expandMoreSettings();
+
+        // Big label should have header/footer
+        checkElementDisplayed(headerFooter, true);
+
+        // Small label should not
+        printPreview.printTicketStore_.mediaSize.updateValue(
+            device.capabilities.printer.media_size.option[0]);
+        checkElementDisplayed(headerFooter, false);
+
+        // Oriented in landscape, there should be enough space for
+        // header/footer.
+        printPreview.printTicketStore_.landscape.updateValue(true);
+        checkElementDisplayed(headerFooter, true);
+
+        return whenAnimationDone('more-settings');
+      });
+    });
+
+    // Test that the color settings, one option, standard monochrome.
+    test('TestColorSettingsMonochrome', function() {
+      setInitialSettings();
+      return nativeLayer.whenCalled('getInitialSettings').then(function() {
+        setLocalDestinations();
+
+        // Only one option, standard monochrome.
+        var device = getCddTemplate('FooDevice');
+        device.capabilities.printer.color = {
+          'option': [
+            {'is_default': true, 'type': 'STANDARD_MONOCHROME'}
+          ]
+        };
+        setCapabilities(device);
+
+        checkSectionVisible($('color-settings'), false);
+
+        return whenAnimationDone('more-settings');
+      });
+    });
+
+    // Test that the color settings, one option, custom monochrome.
+    test('TestColorSettingsCustomMonochrome', function() {
+      setInitialSettings();
+      return nativeLayer.whenCalled('getInitialSettings').then(function() {
+        setLocalDestinations();
+
+        // Only one option, standard monochrome.
+        var device = getCddTemplate('FooDevice');
+        device.capabilities.printer.color = {
+          'option': [
+            {'is_default': true, 'type': 'CUSTOM_MONOCHROME',
+             'vendor_id': '42'}
+          ]
+        };
+        setCapabilities(device);
+
+        checkSectionVisible($('color-settings'), false);
+
+        return whenAnimationDone('more-settings');
+      });
+    });
+
+    // Test that the color settings, one option, standard color.
+    test('TestColorSettingsColor', function() {
+      setInitialSettings();
+      return nativeLayer.whenCalled('getInitialSettings').then(function() {
+        setLocalDestinations();
+
+        var device = getCddTemplate('FooDevice');
+        device.capabilities.printer.color = {
+          'option': [
+            {'is_default': true, 'type': 'STANDARD_COLOR'}
+          ]
+        };
+        setCapabilities(device);
+
+        checkSectionVisible($('color-settings'), false);
+
+        return whenAnimationDone('more-settings');
+      });
+    });
+
+    // Test that the color settings, one option, custom color.
+    test('TestColorSettingsCustomColor', function() {
+      setInitialSettings();
+      return nativeLayer.whenCalled('getInitialSettings').then(function() {
+        setLocalDestinations();
+
+        var device = getCddTemplate('FooDevice');
+        device.capabilities.printer.color = {
+          'option': [
+            {'is_default': true, 'type': 'CUSTOM_COLOR', 'vendor_id': '42'}
+          ]
+        };
+        setCapabilities(device);
+
+        checkSectionVisible($('color-settings'), false);
+
+        return whenAnimationDone('more-settings');
+      });
+    });
+
+    // Test that the color settings, two options, both standard, defaults to
+    // color.
+    test('TestColorSettingsBothStandardDefaultColor', function() {
+      setInitialSettings();
+      return nativeLayer.whenCalled('getInitialSettings').then(function() {
+        setLocalDestinations();
+
+        var device = getCddTemplate('FooDevice');
+        device.capabilities.printer.color = {
+          'option': [
+            {'type': 'STANDARD_MONOCHROME'},
+            {'is_default': true, 'type': 'STANDARD_COLOR'}
+          ]
+        };
+        setCapabilities(device);
+
+        checkSectionVisible($('color-settings'), true);
+        expectEquals(
+            'color',
+            $('color-settings').querySelector('.color-settings-select').value);
+
+        return whenAnimationDone('more-settings');
+      });
+    });
+
+    // Test that the color settings, two options, both standard, defaults to
+    // monochrome.
+    test('TestColorSettingsBothStandardDefaultMonochrome', function() {
+      setInitialSettings();
+      return nativeLayer.whenCalled('getInitialSettings').then(function() {
+        setLocalDestinations();
+
+        var device = getCddTemplate('FooDevice');
+        device.capabilities.printer.color = {
+          'option': [
+            {'is_default': true, 'type': 'STANDARD_MONOCHROME'},
+            {'type': 'STANDARD_COLOR'}
+          ]
+        };
+        setCapabilities(device);
+
+        checkSectionVisible($('color-settings'), true);
+        expectEquals(
+            'bw',
+            $('color-settings').querySelector('.color-settings-select').value);
+
+        return whenAnimationDone('more-settings');
+      });
+    });
+
+    // Test that the color settings, two options, both custom, defaults to
+    // color.
+    test('TestColorSettingsBothCustomDefaultColor', function() {
+      setInitialSettings();
+      return nativeLayer.whenCalled('getInitialSettings').then(
           function() {
             setLocalDestinations();
-            setCapabilities(getCddTemplate('FooDevice'));
 
-            var otherOptions = $('other-options-settings');
-            var headerFooter =
-                otherOptions.querySelector('#header-footer-container');
+            var device = getCddTemplate('FooDevice');
+            device.capabilities.printer.color = {
+              'option': [
+                {'type': 'CUSTOM_MONOCHROME', 'vendor_id': '42'},
+                {'is_default': true, 'type': 'CUSTOM_COLOR', 'vendor_id': '43'}
+              ]
+            };
+            setCapabilities(device);
 
-            // Check that options are collapsed (section is visible, because
-            // duplex is available).
-            checkSectionVisible(otherOptions, true);
-            checkElementDisplayed(headerFooter, false);
-
-            expandMoreSettings();
-
-            checkElementDisplayed(headerFooter, true);
-
-            printPreview.printTicketStore_.marginsType.updateValue(
-                print_preview.ticket_items.MarginsTypeValue.CUSTOM);
-            printPreview.printTicketStore_.customMargins.updateValue(
-                new print_preview.Margins(36, 36, 36, 36));
-
-            checkElementDisplayed(headerFooter, true);
+            checkSectionVisible($('color-settings'), true);
+            expectEquals(
+                'color',
+                $('color-settings').querySelector(
+                    '.color-settings-select').value);
 
             return whenAnimationDone('more-settings');
           });
-    });
-
+        });
 
   });
 });
diff --git a/chrome/test/data/webui/print_preview/print_preview_ui_browsertest.js b/chrome/test/data/webui/print_preview/print_preview_ui_browsertest.js
index f723d49..740c11a 100644
--- a/chrome/test/data/webui/print_preview/print_preview_ui_browsertest.js
+++ b/chrome/test/data/webui/print_preview/print_preview_ui_browsertest.js
@@ -61,71 +61,36 @@
   ],
 };
 
-TEST_F('PrintPreviewUIBrowserTest', 'PrinterList', function() {
-  mocha.grep(/PrinterList\b/).run();
+// Run each mocha test in isolation (within a new TEST_F() call).
+[
+  'PrinterList',
+  'PrinterListCloudEmpty',
+  'RestoreLocalDestination',
+  'RestoreMultipleDestinations',
+  'DefaultDestinationSelectionRules',
+  'SystemDialogLinkIsHiddenInAppKioskMode',
+  'SectionsDisabled',
+  'PrintToPDFSelectedCapabilities',
+  'SourceIsHTMLCapabilities',
+  'SourceIsPDFCapabilities',
+  'ScalingUnchecksFitToPage',
+  'CheckNumCopiesPrintPreset',
+  'CheckDuplexPrintPreset',
+  'CustomMarginsControlsCheck',
+  'PageLayoutHasNoMarginsHideHeaderFooter',
+  'PageLayoutHasMarginsShowHeaderFooter',
+  'ZeroTopAndBottomMarginsHideHeaderFooter',
+  'ZeroTopAndNonZeroBottomMarginShowHeaderFooter',
+  'SmallPaperSizeHeaderFooter',
+  'TestColorSettingsMonochrome',
+  'TestColorSettingsCustomMonochrome',
+  'TestColorSettingsColor',
+  'TestColorSettingsCustomColor',
+  'TestColorSettingsBothStandardDefaultColor',
+  'TestColorSettingsBothStandardDefaultMonochrome',
+  'TestColorSettingsBothCustomDefaultColor',
+].forEach(function(testName) {
+  TEST_F('PrintPreviewUIBrowserTest', testName, function() {
+    mocha.grep(new RegExp(testName + '\\b')).run();
+  });
 });
-
-TEST_F('PrintPreviewUIBrowserTest', 'PrinterListCloudEmpty', function() {
-  mocha.grep(/PrinterListCloudEmpty\b/).run();
-});
-
-TEST_F('PrintPreviewUIBrowserTest', 'RestoreLocalDestination', function() {
-  mocha.grep(/RestoreLocalDestination\b/).run();
-});
-
-TEST_F('PrintPreviewUIBrowserTest', 'RestoreMultipleDestinations', function() {
-  mocha.grep(/RestoreMultipleDestinations\b/).run();
-});
-
-TEST_F('PrintPreviewUIBrowserTest', 'DefaultDestinationSelectionRules',
-    function() {
-      mocha.grep(/DefaultDestinationSelectionRules\b/).run();
-    });
-
-TEST_F('PrintPreviewUIBrowserTest', 'SystemDialogLinkIsHiddenInAppKioskMode',
-    function() {
-      mocha.grep(/SystemDialogLinkIsHiddenInAppKioskMode\b/).run();
-    });
-
-TEST_F('PrintPreviewUIBrowserTest', 'SectionsDisabled', function() {
-  mocha.grep(/SectionsDisabled\b/).run();
-});
-
-TEST_F('PrintPreviewUIBrowserTest', 'PrintToPDFSelectedCapabilities',
-    function() {
-      mocha.grep(/PrintToPDFSelectedCapabilities\b/).run();
-    });
-
-TEST_F('PrintPreviewUIBrowserTest', 'SourceIsHTMLCapabilities', function() {
-  mocha.grep(/SourceIsHTMLCapabilities\b/).run();
-});
-
-TEST_F('PrintPreviewUIBrowserTest', 'SourceIsPDFCapabilities', function() {
-  mocha.grep(/SourceIsPDFCapabilities\b/).run();
-});
-
-TEST_F('PrintPreviewUIBrowserTest', 'ScalingUnchecksFitToPage', function() {
-  mocha.grep(/ScalingUnchecksFitToPage\b/).run();
-});
-
-TEST_F('PrintPreviewUIBrowserTest', 'CheckNumCopiesPrintPreset', function() {
-  mocha.grep(/CheckNumCopiesPrintPreset\b/).run();
-});
-
-TEST_F('PrintPreviewUIBrowserTest', 'CheckDuplexPrintPreset', function() {
-  mocha.grep(/CheckDuplexPrintPreset\b/).run();
-});
-
-TEST_F('PrintPreviewUIBrowserTest', 'CustomMarginsControlsCheck', function() {
-  mocha.grep(/CustomMarginsControlsCheck\b/).run();
-});
-
-TEST_F('PrintPreviewUIBrowserTest', 'PageLayoutHasNoMarginsHideHeaderFooter',
-    function() {
-      mocha.grep(/PageLayoutHasNoMarginsHideHeaderFooter\b/).run();
-    });
-
-TEST_F('PrintPreviewUIBrowserTest', 'PageLayoutHasMarginsShowHeaderFooter',
-    function() {
-      mocha.grep(/PageLayoutHasMarginsShowHeaderFooter\b/).run();
-    });
diff --git a/chrome/test/data/webui/settings/settings_main_test.js b/chrome/test/data/webui/settings/settings_main_test.js
index 4db5a623..590af52 100644
--- a/chrome/test/data/webui/settings/settings_main_test.js
+++ b/chrome/test/data/webui/settings/settings_main_test.js
@@ -193,26 +193,29 @@
       /**
        * Asserts the visibility of the basic and advanced pages after exiting
        * search mode.
-       * @param {string} Expected 'display' value for the basic page.
        * @param {string} Expected 'display' value for the advanced page.
        * @return {!Promise}
        */
-      function assertPageVisibilityAfterSearch(
-          expectedBasic, expectedAdvanced) {
+      function assertAdvancedVisibilityAfterSearch(expectedAdvanced) {
         searchManager.setMatchesFound(true);
-        return settingsMain.searchContents('Query1').then(function() {
-          searchManager.setMatchesFound(false);
-          return settingsMain.searchContents('');
-        }).then(function() {
-          return assertPageVisibility(expectedBasic, expectedAdvanced);
-        });
+        return settingsMain.searchContents('Query1')
+            .then(function() {
+              searchManager.setMatchesFound(false);
+              return settingsMain.searchContents('');
+            })
+            .then(function() {
+              // Imitate behavior of clearing search.
+              settings.navigateTo(settings.Route.BASIC);
+              Polymer.dom.flush();
+              return assertPageVisibility('block', expectedAdvanced);
+            });
       }
 
       test('exiting search mode, advanced collapsed', function() {
         // Simulating searching while the advanced page is collapsed.
         settingsMain.currentRouteChanged(settings.Route.BASIC);
         Polymer.dom.flush();
-        return assertPageVisibilityAfterSearch('block', 'none');
+        return assertAdvancedVisibilityAfterSearch('none');
       });
 
       // Ensure that clearing the search results restores both "basic" and
@@ -221,7 +224,7 @@
       test('exiting search mode, advanced expanded', function() {
         settings.navigateTo(settings.Route.SITE_SETTINGS);
         Polymer.dom.flush();
-        return assertPageVisibilityAfterSearch('block', 'block');
+        return assertAdvancedVisibilityAfterSearch('block');
       });
 
       // Ensure that searching, then entering a subpage, then going back
diff --git a/chrome/test/media_router/media_router_integration_browsertest.cc b/chrome/test/media_router/media_router_integration_browsertest.cc
index 8358165..0604c6d 100644
--- a/chrome/test/media_router/media_router_integration_browsertest.cc
+++ b/chrome/test/media_router/media_router_integration_browsertest.cc
@@ -163,12 +163,16 @@
   ASSERT_TRUE(passed) << error_message;
 }
 
-WebContents* MediaRouterIntegrationBrowserTest::StartSessionWithTestPageNow() {
+void MediaRouterIntegrationBrowserTest::StartSessionAndAssertNotFoundError() {
   OpenTestPage(FILE_PATH_LITERAL("basic_test.html"));
   WebContents* web_contents = GetActiveWebContents();
   CHECK(web_contents);
   StartSession(web_contents);
-  return web_contents;
+
+  // Wait for any sinks to be displayed.
+  Wait(base::TimeDelta::FromSeconds(1));
+  GetControllerForShownDialog(web_contents)->HideMediaRouterDialog();
+  CheckStartFailed(web_contents, "NotFoundError", "No screens found.");
 }
 
 WebContents*
@@ -632,18 +636,13 @@
 IN_PROC_BROWSER_TEST_F(MediaRouterIntegrationBrowserTest,
                        MANUAL_Fail_StartCancelledNoSinks) {
   SetTestData(FILE_PATH_LITERAL("no_sinks.json"));
-  WebContents* web_contents = StartSessionWithTestPageNow();
-  GetControllerForShownDialog(web_contents)->HideMediaRouterDialog();
-  CheckStartFailed(web_contents, "NotFoundError", "No screens found.");
+  StartSessionAndAssertNotFoundError();
 }
 
 IN_PROC_BROWSER_TEST_F(MediaRouterIntegrationBrowserTest,
                        MANUAL_Fail_StartCancelledNoSupportedSinks) {
   SetTestData(FILE_PATH_LITERAL("no_supported_sinks.json"));
-  WebContents* web_contents = StartSessionWithTestPageNow();
-  WaitUntilSinkDiscoveredOnUI();
-  GetControllerForShownDialog(web_contents)->HideMediaRouterDialog();
-  CheckStartFailed(web_contents, "NotFoundError", "No screens found.");
+  StartSessionAndAssertNotFoundError();
 }
 
 void MediaRouterIntegrationIncognitoBrowserTest::InstallAndEnableMRExtension() {
diff --git a/chrome/test/media_router/media_router_integration_browsertest.h b/chrome/test/media_router/media_router_integration_browsertest.h
index a7888de..a813450 100644
--- a/chrome/test/media_router/media_router_integration_browsertest.h
+++ b/chrome/test/media_router/media_router_integration_browsertest.h
@@ -74,8 +74,10 @@
 
   void CheckDialogRemainsOpen(content::WebContents* web_contents);
 
-  // Opens "basic_test.html," and starts a presentation.
-  content::WebContents* StartSessionWithTestPageNow();
+  // Opens "basic_test.html" and asserts that attempting to start a presentation
+  // fails with NotFoundError due to no sinks available.
+  void StartSessionAndAssertNotFoundError();
+
   // Opens "basic_test.html," waits for sinks to be available, and starts a
   // presentation.
   content::WebContents* StartSessionWithTestPageAndSink();
diff --git a/chrome/test/media_router/media_router_one_ua_integration_browsertest.cc b/chrome/test/media_router/media_router_one_ua_integration_browsertest.cc
index 609680d..faeba8b 100644
--- a/chrome/test/media_router/media_router_one_ua_integration_browsertest.cc
+++ b/chrome/test/media_router/media_router_one_ua_integration_browsertest.cc
@@ -20,7 +20,7 @@
     "initiateCloseFromReceiverPage();";
 }
 
-class MediaRouterOneUAIntegrationBrowserTest
+class MediaRouterIntegrationOneUABrowserTest
     : public MediaRouterIntegrationBrowserTest {
  public:
   void SetUpOnMainThread() override {
@@ -42,38 +42,38 @@
   }
 };
 
-IN_PROC_BROWSER_TEST_F(MediaRouterOneUAIntegrationBrowserTest, MANUAL_Basic) {
+IN_PROC_BROWSER_TEST_F(MediaRouterIntegrationOneUABrowserTest, MANUAL_Basic) {
   RunBasicTest();
 }
 
-IN_PROC_BROWSER_TEST_F(MediaRouterOneUAIntegrationBrowserTest,
+IN_PROC_BROWSER_TEST_F(MediaRouterIntegrationOneUABrowserTest,
                        MANUAL_SendAndOnMessage) {
   RunSendMessageTest("foo");
 }
 
-IN_PROC_BROWSER_TEST_F(MediaRouterOneUAIntegrationBrowserTest,
+IN_PROC_BROWSER_TEST_F(MediaRouterIntegrationOneUABrowserTest,
                        MANUAL_ReceiverCloseConnection) {
   WebContents* web_contents = StartSessionWithTestPageAndChooseSink();
   CheckSessionValidity(web_contents);
   ExecuteJavaScriptAPI(web_contents, kInitiateCloseFromReceiverPageScript);
 }
 
-IN_PROC_BROWSER_TEST_F(MediaRouterOneUAIntegrationBrowserTest,
+IN_PROC_BROWSER_TEST_F(MediaRouterIntegrationOneUABrowserTest,
                        MANUAL_Fail_SendMessage) {
   RunFailToSendMessageTest();
 }
 
-IN_PROC_BROWSER_TEST_F(MediaRouterOneUAIntegrationBrowserTest,
+IN_PROC_BROWSER_TEST_F(MediaRouterIntegrationOneUABrowserTest,
                        MANUAL_ReconnectSession) {
   RunReconnectSessionTest();
 }
 
-IN_PROC_BROWSER_TEST_F(MediaRouterOneUAIntegrationBrowserTest,
+IN_PROC_BROWSER_TEST_F(MediaRouterIntegrationOneUABrowserTest,
                        MANUAL_ReconnectSessionSameTab) {
   RunReconnectSessionSameTabTest();
 }
 
-class MediaRouterOneUANoReceiverIntegrationBrowserTest
+class MediaRouterIntegrationOneUANoReceiverBrowserTest
     : public MediaRouterIntegrationBrowserTest {
  public:
   GURL GetTestPageUrl(const base::FilePath& full_path) override {
@@ -82,22 +82,22 @@
   }
 };
 
-IN_PROC_BROWSER_TEST_F(MediaRouterOneUANoReceiverIntegrationBrowserTest,
+IN_PROC_BROWSER_TEST_F(MediaRouterIntegrationOneUANoReceiverBrowserTest,
                        MANUAL_Basic) {
   RunBasicTest();
 }
 
-IN_PROC_BROWSER_TEST_F(MediaRouterOneUANoReceiverIntegrationBrowserTest,
+IN_PROC_BROWSER_TEST_F(MediaRouterIntegrationOneUANoReceiverBrowserTest,
                        MANUAL_Fail_SendMessage) {
   RunFailToSendMessageTest();
 }
 
-IN_PROC_BROWSER_TEST_F(MediaRouterOneUANoReceiverIntegrationBrowserTest,
+IN_PROC_BROWSER_TEST_F(MediaRouterIntegrationOneUANoReceiverBrowserTest,
                        MANUAL_ReconnectSession) {
   RunReconnectSessionTest();
 }
 
-IN_PROC_BROWSER_TEST_F(MediaRouterOneUANoReceiverIntegrationBrowserTest,
+IN_PROC_BROWSER_TEST_F(MediaRouterIntegrationOneUANoReceiverBrowserTest,
                        MANUAL_ReconnectSessionSameTab) {
   RunReconnectSessionSameTabTest();
 }
diff --git a/chrome/test/vr/perf/latency/android_webvr_latency_test.py b/chrome/test/vr/perf/latency/android_webvr_latency_test.py
index 18dc58a..6608dc5 100644
--- a/chrome/test/vr/perf/latency/android_webvr_latency_test.py
+++ b/chrome/test/vr/perf/latency/android_webvr_latency_test.py
@@ -18,10 +18,15 @@
   """Android implementation of the WebVR latency test."""
   def __init__(self, args):
     super(AndroidWebVrLatencyTest, self).__init__(args)
+    # Swarming stuff seems to routinely kill off adbd once a minute or so,
+    # which often causes adb's startup message to appear in the output. We need
+    # to remove this before getting the device name
+    # TODO(bsheedy): Look into preventing adbd from being killed altogether
+    # instead of working around it
     self._device_name = self._Adb(['shell', 'getprop',
-                                  'ro.product.name']).strip()
+                                   'ro.product.name']).strip().split('\n')[-1]
 
-  def _Setup(self):
+  def _OneTimeSetup(self):
     self._Adb(['root'])
 
     # Install the latest VrCore and Chrome APKs
@@ -40,11 +45,13 @@
     self._Adb(['shell', 'input', 'keyevent', 'KEYCODE_WAKEUP'])
     time.sleep(1)
 
+
+  def _Setup(self, url):
     # Start Chrome
     self._Adb(['shell', 'am', 'start',
                '-a', 'android.intent.action.MAIN',
                '-n', 'org.chromium.chrome/com.google.android.apps.chrome.Main',
-               self._flicker_app_url])
+               url])
     time.sleep(10)
 
     # Tap the center of the screen to start presenting.
@@ -71,6 +78,10 @@
     # Exit VR and close Chrome
     self._Adb(['shell', 'input', 'keyevent', 'KEYCODE_BACK'])
     self._Adb(['shell', 'am', 'force-stop', 'org.chromium.chrome'])
+
+  def _OneTimeTeardown(self):
+    # Perform teardown again in case an exception was thrown
+    self._Teardown()
     # Turn off the screen
     self._Adb(['shell', 'input', 'keyevent', 'KEYCODE_POWER'])
 
diff --git a/chrome/test/vr/perf/latency/robot_arm.py b/chrome/test/vr/perf/latency/robot_arm.py
index d62bef9..052b961 100644
--- a/chrome/test/vr/perf/latency/robot_arm.py
+++ b/chrome/test/vr/perf/latency/robot_arm.py
@@ -44,3 +44,7 @@
     if not self._connection:
       return
     self._connection.write('0\n')
+    # The manual usage instructions are printed over the serial connection
+    # every time we send a command - long test runs can result in the buffer
+    # filling up and causing the arm to hang, so periodically clear the buffer.
+    self._connection.flushInput()
diff --git a/chrome/test/vr/perf/latency/run_latency_test.py b/chrome/test/vr/perf/latency/run_latency_test.py
index ea1d04f..cd96b164 100644
--- a/chrome/test/vr/perf/latency/run_latency_test.py
+++ b/chrome/test/vr/perf/latency/run_latency_test.py
@@ -18,11 +18,6 @@
 import os
 import sys
 
-# TODO(bsheedy): See about having versioned copies of the flicker app
-# instead of using personal github.
-DEFAULT_FLICKER_APP_URL = ('https://weableandbob.github.io/Motopho/'
-                           'flicker_apps/webvr/webvr-flicker-app-klaus.html?'
-                           'polyfill=0\&canvasClickPresents=1')
 DEFAULT_ADB_PATH = os.path.realpath('../../third_party/android_tools/sdk/'
                                     'platform-tools/adb')
 # TODO(bsheedy): See about adding tool via DEPS instead of relying on it
@@ -64,11 +59,15 @@
                            'saved to')
   parser.add_argument('--num-samples',
                       default=DEFAULT_NUM_SAMPLES,
+                      type=int,
                       help='The number of times to run the test before '
                            'the results are averaged')
   parser.add_argument('--url',
-                      default=DEFAULT_FLICKER_APP_URL,
-                      help='The URL of the flicker app to use')
+                      action='append',
+                      default=[],
+                      dest='urls',
+                      help='The URL of a flicker app to use. Defaults to a '
+                           'set of URLs with various CPU and GPU loads')
   parser.add_argument('-v', '--verbose',
                       dest='verbose_count', default=0, action='count',
                       help='Verbose level (multiple times for more)')
@@ -103,7 +102,7 @@
     raise NotImplementedError('WebVR not currently supported on Windows')
   else:
     raise RuntimeError('Given platform %s not recognized' % args.platform)
-  latency_test.RunTest()
+  latency_test.RunTests()
 
 
 if __name__ == '__main__':
diff --git a/chrome/test/vr/perf/latency/webvr_latency_test.py b/chrome/test/vr/perf/latency/webvr_latency_test.py
index 0a289a07..4f69c287 100644
--- a/chrome/test/vr/perf/latency/webvr_latency_test.py
+++ b/chrome/test/vr/perf/latency/webvr_latency_test.py
@@ -16,7 +16,35 @@
 import time
 
 
-MOTOPHO_THREAD_TIMEOUT = 30
+MOTOPHO_THREAD_TIMEOUT = 15
+DEFAULT_URLS = [
+    # TODO(bsheedy): See about having versioned copies of the flicker app
+    # instead of using personal github.
+    # Purely a flicker app - no additional CPU/GPU load
+    'https://weableandbob.github.io/Motopho/'
+    'flicker_apps/webvr/webvr-flicker-app-klaus.html?'
+    'polyfill=0\&canvasClickPresents=1',
+    # URLs that render 3D scenes in addition to the Motopho patch
+    # Heavy CPU load, moderate GPU load
+    'https://webvr.info/samples/test-slow-render.html?'
+    'latencyPatch=1\&canvasClickPresents=1\&'
+    'heavyGpu=1\&workTime=20\&cubeCount=8\&cubeScale=0.4',
+    # Moderate CPU load, light GPU load
+    'https://webvr.info/samples/test-slow-render.html?'
+    'latencyPatch=1\&canvasClickPresents=1\&'
+    'heavyGpu=1\&workTime=12\&cubeCount=8\&cubeScale=0.3',
+    # Light CPU load, moderate GPU load
+    'https://webvr.info/samples/test-slow-render.html?'
+    'latencyPatch=1\&canvasClickPresents=1\&'
+    'heavyGpu=1\&workTime=5\&cubeCount=8\&cubeScale=0.4',
+    # Heavy CPU load, very light GPU load
+    'https://webvr.info/samples/test-slow-render.html?'
+    'latencyPatch=1\&canvasClickPresents=1\&'
+    'workTime=20',
+    # No additional CPU load, very light GPU load
+    'https://webvr.info/samples/test-slow-render.html?'
+    'latencyPatch=1\&canvasClickPresents=1',
+]
 
 
 def GetTtyDevices(tty_pattern, vendor_ids):
@@ -69,31 +97,48 @@
   def __init__(self, args):
     self.args = args
     self._num_samples = args.num_samples
-    self._flicker_app_url = args.url
+    self._test_urls = args.urls or DEFAULT_URLS
     assert (self._num_samples > 0),'Number of samples must be greater than 0'
     self._device_name = 'generic_device'
+    self._test_results = {}
 
     # Connect to the Arduino that drives the servos
     devices = GetTtyDevices(r'ttyACM\d+', [0x2a03, 0x2341])
     assert (len(devices) == 1),'Found %d devices, expected 1' % len(devices)
     self.robot_arm = ra.RobotArm(devices[0])
 
-  def RunTest(self):
-    """Runs the steps to start Chrome, measure/save latency, and clean up."""
-    self._Setup()
-    self._Run()
-    self._Teardown()
+  def RunTests(self):
+    """Runs latency tests on all the URLs provided to the test on creation.
 
-  def _Setup(self):
-    """Perform any platform-specific setup."""
+    Repeatedly runs the steps to start Chrome, measure/store latency, and
+    clean up before storing all results to a single file for dashboard
+    uploading.
+    """
+    try:
+      self._OneTimeSetup()
+      for url in self._test_urls:
+        self._Setup(url)
+        self._Run(url)
+        self._Teardown()
+      self._SaveResultsToFile()
+    finally:
+      self._OneTimeTeardown()
+
+  def _OneTimeSetup(self):
+    """Performs any platform-specific setup once before any tests."""
     raise NotImplementedError(
         'Platform-specific setup must be implemented in subclass')
 
-  def _Run(self):
+  def _Setup(self, url):
+    """Performs any platform-specific setup before each test."""
+    raise NotImplementedError(
+        'Platform-specific setup must be implemented in subclass')
+
+  def _Run(self, url):
     """Run the latency test.
 
     Handles the actual latency measurement, which is identical across
-    different platforms, as well as result saving.
+    different platforms, as well as result storing.
     """
     # Motopho scripts use relative paths, so switch to the Motopho directory
     os.chdir(self.args.motopho_path)
@@ -119,12 +164,18 @@
                       'Motopho may need to be replugged.')
       self.robot_arm.StopAllMovement()
       time.sleep(1)
-    self._SaveResults(motopho_thread.latencies, motopho_thread.correlations)
+    self._StoreResults(motopho_thread.latencies, motopho_thread.correlations,
+                       url)
 
   def _Teardown(self):
-    """Performs any platform-specific teardown."""
+    """Performs any platform-specific teardown after each test."""
     raise NotImplementedError(
-        'Platform-specific setup must be implemented in subclass')
+        'Platform-specific teardown must be implemented in subclass')
+
+  def _OneTimeTeardown(self):
+    """Performs any platform-specific teardown after all tests."""
+    raise NotImplementedError(
+        'Platform-specific teardown must be implemented in sublcass')
 
   def _RunCommand(self, cmd):
     """Runs the given cmd list and returns its output.
@@ -144,52 +195,88 @@
     raise NotImplementedError(
         'Command-line flag setting must be implemented in subclass')
 
-  def _SaveResults(self, latencies, correlations):
-    """Saves the results to a JSON file.
+  def _StoreResults(self, latencies, correlations, url):
+    """Temporarily stores the results of a test.
 
-    Saved JSON object is compatible with Chrome perf dashboard if
-    put in as the 'chart_data' value. Also logs the raw data and its
-    average/standard deviation.
+    Stores the given results in memory to be later retrieved and written to
+    a file in _SaveResultsToFile once all tests are done. Also logs the raw
+    data and its average/standard deviation.
     """
     avg_latency = sum(latencies) / len(latencies)
     std_latency = numpy.std(latencies)
     avg_correlation = sum(correlations) / len(correlations)
     std_correlation = numpy.std(correlations)
-    logging.info('Raw latencies: %s\nRaw correlations: %s\n'
+    logging.info('\nURL: %s\n'
+                 'Raw latencies: %s\nRaw correlations: %s\n'
                  'Avg latency: %f +/- %f\nAvg correlation: %f +/- %f',
-                 str(latencies), str(correlations), avg_latency, std_latency,
-                 avg_correlation, std_correlation)
+                 url, str(latencies), str(correlations), avg_latency,
+                 std_latency, avg_correlation, std_correlation)
 
+    self._test_results[url] = {
+        'correlations': correlations,
+        'std_correlation': std_correlation,
+        'latencies': latencies,
+        'std_latency': std_latency,
+    }
+
+  def _SaveResultsToFile(self):
     if not (self.args.output_dir and os.path.isdir(self.args.output_dir)):
       logging.warning('No output directory set, not saving results to file')
       return
 
+    correlation_string = self._device_name + '_correlation'
+    latency_string = self._device_name + '_latency'
+    charts = {
+        correlation_string: {
+            'summary': {
+                'improvement_direction': 'up',
+                'name': correlation_string,
+                'std': 0.0,
+                'type': 'list_of_scalar_values',
+                'units': '',
+                'values': [],
+            }
+        },
+        latency_string: {
+            'summary': {
+                'improvement_direction': 'down',
+                'name': latency_string,
+                'std': 0.0,
+                'type': 'list_of_scalar_values',
+                'units': 'ms',
+                'values': [],
+            }
+        }
+    }
+    for url, results in self._test_results.iteritems():
+      charts[correlation_string][url] = {
+          'improvement_direction': 'up',
+          'name': correlation_string,
+          'std': results['std_correlation'],
+          'type': 'list_of_scalar_values',
+          'units': '',
+          'values': results['correlations'],
+      }
+
+      charts[correlation_string]['summary']['values'].extend(
+          results['correlations'])
+
+      charts[latency_string][url] = {
+          'improvement_direction': 'down',
+          'name': latency_string,
+          'std': results['std_latency'],
+          'type': 'list_of_scalar_values',
+          'units': 'ms',
+          'values': results['latencies'],
+      }
+
+      charts[latency_string]['summary']['values'].extend(results['latencies'])
+
     results = {
       'format_version': '1.0',
       'benchmark_name': 'webvr_latency',
       'benchmark_description': 'Measures the motion-to-photon latency of WebVR',
-      'charts': {
-        'correlation': {
-          'summary': {
-            'improvement_direction': 'up',
-            'name': 'correlation',
-            'std': std_correlation,
-            'type': 'list_of_scalar_values',
-            'units': '',
-            'values': correlations,
-          },
-        },
-        'latency': {
-          'summary': {
-            'improvement_direction': 'down',
-            'name': 'latency',
-            'std': std_latency,
-            'type': 'list_of_scalar_values',
-            'units': 'ms',
-            'values': latencies,
-          },
-        }
-      }
+      'charts': charts,
     }
 
     with file(os.path.join(self.args.output_dir,
diff --git a/chromeos/components/tether/fake_notification_presenter.cc b/chromeos/components/tether/fake_notification_presenter.cc
index fe8dc6a..5106769 100644
--- a/chromeos/components/tether/fake_notification_presenter.cc
+++ b/chromeos/components/tether/fake_notification_presenter.cc
@@ -16,6 +16,7 @@
     : NotificationPresenter(),
       potential_hotspot_state_(
           PotentialHotspotNotificationState::NO_HOTSPOT_NOTIFICATION_SHOWN),
+      is_setup_required_notification_shown_(false),
       is_connection_failed_notification_shown_(false) {}
 
 FakeNotificationPresenter::~FakeNotificationPresenter() {}
@@ -44,6 +45,15 @@
       PotentialHotspotNotificationState::NO_HOTSPOT_NOTIFICATION_SHOWN;
 }
 
+void FakeNotificationPresenter::NotifySetupRequired(
+    const std::string& device_name) {
+  is_setup_required_notification_shown_ = true;
+}
+
+void FakeNotificationPresenter::RemoveSetupRequiredNotification() {
+  is_setup_required_notification_shown_ = false;
+}
+
 void FakeNotificationPresenter::NotifyConnectionToHostFailed() {
   is_connection_failed_notification_shown_ = true;
 }
diff --git a/chromeos/components/tether/fake_notification_presenter.h b/chromeos/components/tether/fake_notification_presenter.h
index 4501c0d..cf985f91 100644
--- a/chromeos/components/tether/fake_notification_presenter.h
+++ b/chromeos/components/tether/fake_notification_presenter.h
@@ -34,6 +34,10 @@
   // SINGLE_HOTSPOT_NEARBY_SHOWN when called.
   cryptauth::RemoteDevice& GetPotentialHotspotRemoteDevice();
 
+  bool is_setup_required_notification_shown() {
+    return is_setup_required_notification_shown_;
+  }
+
   bool is_connection_failed_notification_shown() {
     return is_connection_failed_notification_shown_;
   }
@@ -43,12 +47,15 @@
       const cryptauth::RemoteDevice& remote_device) override;
   void NotifyMultiplePotentialHotspotsNearby() override;
   void RemovePotentialHotspotNotification() override;
+  void NotifySetupRequired(const std::string& device_name) override;
+  void RemoveSetupRequiredNotification() override;
   void NotifyConnectionToHostFailed() override;
   void RemoveConnectionToHostFailedNotification() override;
 
  private:
   PotentialHotspotNotificationState potential_hotspot_state_;
   cryptauth::RemoteDevice potential_hotspot_remote_device_;
+  bool is_setup_required_notification_shown_;
   bool is_connection_failed_notification_shown_;
 
   DISALLOW_COPY_AND_ASSIGN(FakeNotificationPresenter);
diff --git a/chromeos/components/tether/host_scanner_operation.cc b/chromeos/components/tether/host_scanner_operation.cc
index 3f9d016..e4d272ae9 100644
--- a/chromeos/components/tether/host_scanner_operation.cc
+++ b/chromeos/components/tether/host_scanner_operation.cc
@@ -94,10 +94,10 @@
 HostScannerOperation::ScannedDeviceInfo::ScannedDeviceInfo(
     const cryptauth::RemoteDevice& remote_device,
     const DeviceStatus& device_status,
-    bool set_up_required)
+    bool setup_required)
     : remote_device(remote_device),
       device_status(device_status),
-      set_up_required(set_up_required) {}
+      setup_required(setup_required) {}
 
 HostScannerOperation::ScannedDeviceInfo::~ScannedDeviceInfo() {}
 
@@ -106,7 +106,7 @@
   return first.remote_device == second.remote_device &&
          first.device_status.SerializeAsString() ==
              second.device_status.SerializeAsString() &&
-         first.set_up_required == second.set_up_required;
+         first.setup_required == second.setup_required;
 }
 
 HostScannerOperation::HostScannerOperation(
@@ -162,21 +162,21 @@
                  << remote_device.GetTruncatedDeviceIdForLogs() << " which "
                  << "indicates that tethering is not available.";
   } else {
-    bool set_up_required =
+    bool setup_required =
         response->response_code() ==
         TetherAvailabilityResponse_ResponseCode::
             TetherAvailabilityResponse_ResponseCode_SETUP_NEEDED;
 
     PA_LOG(INFO) << "Received TetherAvailabilityResponse from device with ID "
                  << remote_device.GetTruncatedDeviceIdForLogs() << " which "
-                 << "indicates that tethering is available. set_up_required = "
-                 << set_up_required;
+                 << "indicates that tethering is available. setup_required = "
+                 << setup_required;
 
     tether_host_response_recorder_->RecordSuccessfulTetherAvailabilityResponse(
         remote_device);
 
     scanned_device_list_so_far_.push_back(ScannedDeviceInfo(
-        remote_device, response->device_status(), set_up_required));
+        remote_device, response->device_status(), setup_required));
     NotifyObserversOfScannedDeviceList(false /* is_final_scan_result */);
   }
 
diff --git a/chromeos/components/tether/host_scanner_operation.h b/chromeos/components/tether/host_scanner_operation.h
index 6dcfa3d10..bae437d 100644
--- a/chromeos/components/tether/host_scanner_operation.h
+++ b/chromeos/components/tether/host_scanner_operation.h
@@ -55,7 +55,7 @@
   struct ScannedDeviceInfo {
     ScannedDeviceInfo(const cryptauth::RemoteDevice& remote_device,
                       const DeviceStatus& device_status,
-                      bool set_up_required);
+                      bool setup_required);
     ~ScannedDeviceInfo();
 
     friend bool operator==(const ScannedDeviceInfo& first,
@@ -63,7 +63,7 @@
 
     cryptauth::RemoteDevice remote_device;
     DeviceStatus device_status;
-    bool set_up_required;
+    bool setup_required;
   };
 
   class Observer {
diff --git a/chromeos/components/tether/host_scanner_operation_unittest.cc b/chromeos/components/tether/host_scanner_operation_unittest.cc
index cf1e553..b0690bb1f1 100644
--- a/chromeos/components/tether/host_scanner_operation_unittest.cc
+++ b/chromeos/components/tether/host_scanner_operation_unittest.cc
@@ -178,12 +178,12 @@
         response_code ==
         TetherAvailabilityResponse_ResponseCode::
             TetherAvailabilityResponse_ResponseCode_TETHER_AVAILABLE;
-    bool set_up_required =
+    bool setup_required =
         response_code ==
         TetherAvailabilityResponse_ResponseCode::
             TetherAvailabilityResponse_ResponseCode_SETUP_NEEDED;
-    if (tether_available || set_up_required) {
-      // If tether is available or set up is needed, the observer callback
+    if (tether_available || setup_required) {
+      // If tether is available or setup is required, the observer callback
       // should be invoked with an updated list.
       EXPECT_EQ(num_scanned_device_results_so_far + 1,
                 test_observer_->scanned_devices_so_far.size());
@@ -193,7 +193,7 @@
               [test_observer_->scanned_devices_so_far.size() - 1];
       EXPECT_EQ(cell_provider_name,
                 last_received_info.device_status.cell_provider());
-      EXPECT_EQ(set_up_required, last_received_info.set_up_required);
+      EXPECT_EQ(setup_required, last_received_info.setup_required);
     }
 
     EXPECT_EQ(expected_to_be_last_scan_result,
@@ -247,7 +247,7 @@
           TetherAvailabilityResponse_ResponseCode_TETHER_AVAILABLE);
 }
 
-TEST_F(HostScannerOperationTest, TestOperation_OneDevice_SetupNeeded) {
+TEST_F(HostScannerOperationTest, TestOperation_OneDevice_SetupRequired) {
   EXPECT_CALL(*mock_tether_host_response_recorder_,
               RecordSuccessfulTetherAvailabilityResponse(test_devices_[0]));
 
@@ -374,4 +374,4 @@
 
 }  // namespace tether
 
-}  // namespace cryptauth
+}  // namespace chromeos
diff --git a/chromeos/components/tether/notification_presenter.h b/chromeos/components/tether/notification_presenter.h
index 49b6713..f59bd24 100644
--- a/chromeos/components/tether/notification_presenter.h
+++ b/chromeos/components/tether/notification_presenter.h
@@ -32,6 +32,14 @@
   // notification is not currently displayed.
   virtual void RemovePotentialHotspotNotification() = 0;
 
+  // Notifies the user that the device they are connecting to requires
+  // first time setup and must be interacted with.
+  virtual void NotifySetupRequired(const std::string& device_name) = 0;
+
+  // Removes the notification created by NotifyFirstTimeSetupRequired(), or does
+  // nothing if that notification is not currently displayed.
+  virtual void RemoveSetupRequiredNotification() = 0;
+
   // Notifies the user that the connection attempt has failed.
   virtual void NotifyConnectionToHostFailed() = 0;
 
diff --git a/chromeos/dbus/power_policy_controller.cc b/chromeos/dbus/power_policy_controller.cc
index 783d17f..1996e2f 100644
--- a/chromeos/dbus/power_policy_controller.cc
+++ b/chromeos/dbus/power_policy_controller.cc
@@ -276,12 +276,21 @@
   SendCurrentPolicy();
 }
 
+void PowerPolicyController::SetEncryptionMigrationActive(bool active) {
+  if (encryption_migration_active_ == active)
+    return;
+
+  encryption_migration_active_ = active;
+  SendCurrentPolicy();
+}
+
 PowerPolicyController::PowerPolicyController(PowerManagerClient* client)
     : client_(client),
       prefs_were_set_(false),
       honor_screen_wake_locks_(true),
       next_wake_lock_id_(1),
-      chrome_is_exiting_(false) {
+      chrome_is_exiting_(false),
+      encryption_migration_active_(false) {
   DCHECK(client_);
   client_->AddObserver(this);
 }
@@ -367,6 +376,15 @@
     }
   }
 
+  if (encryption_migration_active_ &&
+      policy.lid_closed_action() !=
+          power_manager::PowerManagementPolicy_Action_DO_NOTHING) {
+    policy.set_lid_closed_action(
+        power_manager::PowerManagementPolicy_Action_SUSPEND);
+    causes +=
+        std::string((causes.empty() ? "" : ", ")) + "encryption migration";
+  }
+
   // To avoid a race in the case where the user asks Chrome to sign out
   // and then immediately closes the lid, override the lid-closed action
   // so the system will stay awake while Chrome is exiting. When Chrome
diff --git a/chromeos/dbus/power_policy_controller.h b/chromeos/dbus/power_policy_controller.h
index 3d89a23a..530360f 100644
--- a/chromeos/dbus/power_policy_controller.h
+++ b/chromeos/dbus/power_policy_controller.h
@@ -112,6 +112,12 @@
   // down.
   void NotifyChromeIsExiting();
 
+  // Adjusts policy when the migration of a user homedir to a new
+  // encryption format starts or stops. While migration is active,
+  // the lid-closed action is overridden to ensure the system
+  // doesn't shut down.
+  void SetEncryptionMigrationActive(bool active);
+
   // PowerManagerClient::Observer implementation:
   void PowerManagerRestarted() override;
 
@@ -173,6 +179,9 @@
   // True if Chrome is in the process of exiting.
   bool chrome_is_exiting_;
 
+  // True if a user homedir is in the process of migrating encryption formats.
+  bool encryption_migration_active_;
+
   DISALLOW_COPY_AND_ASSIGN(PowerPolicyController);
 };
 
diff --git a/chromeos/dbus/power_policy_controller_unittest.cc b/chromeos/dbus/power_policy_controller_unittest.cc
index 255117e..acff4a36 100644
--- a/chromeos/dbus/power_policy_controller_unittest.cc
+++ b/chromeos/dbus/power_policy_controller_unittest.cc
@@ -375,4 +375,32 @@
                 fake_power_client_->policy()));
 }
 
+TEST_F(PowerPolicyControllerTest, SuspendOnLidClosedWhileSignedOut) {
+  PowerPolicyController::PrefValues prefs;
+  policy_controller_->ApplyPrefs(prefs);
+  const power_manager::PowerManagementPolicy kDefaultPolicy =
+      fake_power_client_->policy();
+
+  prefs.lid_closed_action = PowerPolicyController::ACTION_SHUT_DOWN;
+  policy_controller_->ApplyPrefs(prefs);
+
+  power_manager::PowerManagementPolicy expected_policy;
+  expected_policy = kDefaultPolicy;
+  expected_policy.set_lid_closed_action(
+      power_manager::PowerManagementPolicy_Action_SHUT_DOWN);
+  // Sanity check
+  EXPECT_EQ(PowerPolicyController::GetPolicyDebugString(expected_policy),
+            PowerPolicyController::GetPolicyDebugString(
+                fake_power_client_->policy()));
+
+  policy_controller_->SetEncryptionMigrationActive(true);
+  expected_policy.set_lid_closed_action(
+      power_manager::PowerManagementPolicy_Action_SUSPEND);
+  expected_policy.set_reason("Prefs, encryption migration");
+  // Lid-closed action successfully changed to "suspend".
+  EXPECT_EQ(PowerPolicyController::GetPolicyDebugString(expected_policy),
+            PowerPolicyController::GetPolicyDebugString(
+                fake_power_client_->policy()));
+}
+
 }  // namespace chromeos
diff --git a/components/cronet/PRESUBMIT.py b/components/cronet/PRESUBMIT.py
index e89d975b..7c553d7 100644
--- a/components/cronet/PRESUBMIT.py
+++ b/components/cronet/PRESUBMIT.py
@@ -85,23 +85,6 @@
   return _RunUnittests(input_api, output_api)
 
 
-def _GetTryMasters(project, change):
-  return {
-    'master.tryserver.chromium.android': {
-      'android_cronet_tester': [],
-     },
-  }
-
-
-def GetPreferredTryMasters(project, change):
-  # TODO(nick, dcheng): Using the value of _GetTryMasters() instead of an empty
-  # value here would cause 'git cl try' to include the Cronet trybot,
-  # which would be nice. But it has the side effect of replacing, rather than
-  # augmenting, the default set of try servers. Re-enable this when we figure
-  # out a way to augment the default set.
-  return {}
-
-
 def PostUploadHook(cl, change, output_api):
   """git cl upload will call this hook after the issue is created/modified.
 
diff --git a/components/feature_engagement_tracker/internal/never_availability_model.cc b/components/feature_engagement_tracker/internal/never_availability_model.cc
index 4a69f7a..55ecbe5 100644
--- a/components/feature_engagement_tracker/internal/never_availability_model.cc
+++ b/components/feature_engagement_tracker/internal/never_availability_model.cc
@@ -4,20 +4,30 @@
 
 #include "components/feature_engagement_tracker/internal/never_availability_model.h"
 
+#include <utility>
+
 #include "base/callback.h"
 #include "base/optional.h"
+#include "base/sequenced_task_runner.h"
+#include "base/single_thread_task_runner.h"
+#include "base/threading/thread_task_runner_handle.h"
 
 namespace feature_engagement_tracker {
 
-NeverAvailabilityModel::NeverAvailabilityModel() = default;
+NeverAvailabilityModel::NeverAvailabilityModel() : ready_(false) {}
 
 NeverAvailabilityModel::~NeverAvailabilityModel() = default;
 
 void NeverAvailabilityModel::Initialize(OnInitializedCallback callback,
-                                        uint32_t current_day) {}
+                                        uint32_t current_day) {
+  base::ThreadTaskRunnerHandle::Get()->PostTask(
+      FROM_HERE,
+      base::BindOnce(&NeverAvailabilityModel::ForwardedOnInitializedCallback,
+                     base::Unretained(this), std::move(callback)));
+}
 
 bool NeverAvailabilityModel::IsReady() const {
-  return false;
+  return ready_;
 }
 
 base::Optional<uint32_t> NeverAvailabilityModel::GetAvailability(
@@ -25,4 +35,11 @@
   return base::nullopt;
 }
 
+void NeverAvailabilityModel::ForwardedOnInitializedCallback(
+    OnInitializedCallback callback) {
+  base::ThreadTaskRunnerHandle::Get()->PostTask(
+      FROM_HERE, base::BindOnce(std::move(callback), true));
+  ready_ = true;
+}
+
 }  // namespace feature_engagement_tracker
diff --git a/components/feature_engagement_tracker/internal/never_availability_model.h b/components/feature_engagement_tracker/internal/never_availability_model.h
index 0010cf1..1a64a5d 100644
--- a/components/feature_engagement_tracker/internal/never_availability_model.h
+++ b/components/feature_engagement_tracker/internal/never_availability_model.h
@@ -12,7 +12,8 @@
 
 namespace feature_engagement_tracker {
 
-// An AvailabilityModel that never has any data, and is never ready.
+// An AvailabilityModel that never has any data, and is ready after having been
+// initialized.
 class NeverAvailabilityModel : public AvailabilityModel {
  public:
   NeverAvailabilityModel();
@@ -26,6 +27,14 @@
       const base::Feature& feature) const override;
 
  private:
+  // Sets |ready_| to true and posts the result to |callback|. This method
+  // exists to ensure that |ready_| is not updated directly in the
+  // Initialize(...) method.
+  void ForwardedOnInitializedCallback(OnInitializedCallback callback);
+
+  // Whether the model has been successfully initialized.
+  bool ready_;
+
   DISALLOW_COPY_AND_ASSIGN(NeverAvailabilityModel);
 };
 
diff --git a/components/feature_engagement_tracker/internal/never_availability_model_unittest.cc b/components/feature_engagement_tracker/internal/never_availability_model_unittest.cc
index bf396b5..a1c143c 100644
--- a/components/feature_engagement_tracker/internal/never_availability_model_unittest.cc
+++ b/components/feature_engagement_tracker/internal/never_availability_model_unittest.cc
@@ -4,8 +4,11 @@
 
 #include "components/feature_engagement_tracker/internal/never_availability_model.h"
 
+#include "base/bind.h"
 #include "base/feature_list.h"
+#include "base/message_loop/message_loop.h"
 #include "base/optional.h"
+#include "base/run_loop.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
 namespace feature_engagement_tracker {
@@ -21,10 +24,15 @@
  public:
   NeverAvailabilityModelTest() = default;
 
+  void OnInitializedCallback(bool success) { success_ = success; }
+
  protected:
   NeverAvailabilityModel availability_model_;
+  base::Optional<bool> success_;
 
  private:
+  base::MessageLoop message_loop_;
+
   DISALLOW_COPY_AND_ASSIGN(NeverAvailabilityModelTest);
 };
 
@@ -35,6 +43,31 @@
             availability_model_.GetAvailability(kTestFeatureFoo));
   EXPECT_EQ(base::nullopt,
             availability_model_.GetAvailability(kTestFeatureBar));
+
+  availability_model_.Initialize(
+      base::BindOnce(&NeverAvailabilityModelTest::OnInitializedCallback,
+                     base::Unretained(this)),
+      14u);
+  base::RunLoop().RunUntilIdle();
+
+  EXPECT_EQ(base::nullopt,
+            availability_model_.GetAvailability(kTestFeatureFoo));
+  EXPECT_EQ(base::nullopt,
+            availability_model_.GetAvailability(kTestFeatureBar));
+}
+
+TEST_F(NeverAvailabilityModelTest, ShouldBeReadyAfterInitialization) {
+  EXPECT_FALSE(availability_model_.IsReady());
+  availability_model_.Initialize(
+      base::BindOnce(&NeverAvailabilityModelTest::OnInitializedCallback,
+                     base::Unretained(this)),
+      14u);
+  EXPECT_FALSE(availability_model_.IsReady());
+  EXPECT_FALSE(success_.has_value());
+  base::RunLoop().RunUntilIdle();
+  EXPECT_TRUE(availability_model_.IsReady());
+  ASSERT_TRUE(success_.has_value());
+  EXPECT_TRUE(success_.value());
 }
 
 }  // namespace feature_engagement_tracker
diff --git a/components/feature_engagement_tracker/public/android/java/src/org/chromium/components/feature_engagement_tracker/EventConstants.java b/components/feature_engagement_tracker/public/android/java/src/org/chromium/components/feature_engagement_tracker/EventConstants.java
index 2bf3976..24f03f2 100644
--- a/components/feature_engagement_tracker/public/android/java/src/org/chromium/components/feature_engagement_tracker/EventConstants.java
+++ b/components/feature_engagement_tracker/public/android/java/src/org/chromium/components/feature_engagement_tracker/EventConstants.java
@@ -34,6 +34,22 @@
     public static final String DATA_SAVER_PREVIEW_INFOBAR_SHOWN = "data_saver_preview_opened";
 
     /**
+     * Data was saved when page loaded.
+     */
+    public static final String DATA_SAVED_ON_PAGE_LOAD = "data_saved_page_load";
+
+    /**
+     * The overflow menu was opened.
+     */
+    public static final String OVERFLOW_OPENED_WITH_DATA_SAVER_SHOWN =
+            "overflow_opened_data_saver_shown";
+
+    /**
+     * The data saver footer was used (tapped).
+     */
+    public static final String DATA_SAVER_DETAIL_OPENED = "data_saver_overview_opened";
+
+    /**
      * Do not instantiate.
      */
     private EventConstants() {}
diff --git a/components/offline_pages/core/prefetch/BUILD.gn b/components/offline_pages/core/prefetch/BUILD.gn
index 58ca40a7..f46c044 100644
--- a/components/offline_pages/core/prefetch/BUILD.gn
+++ b/components/offline_pages/core/prefetch/BUILD.gn
@@ -13,6 +13,7 @@
     "generate_page_bundle_request.h",
     "get_operation_request.cc",
     "get_operation_request.h",
+    "offline_metrics_collector.h",
     "prefetch_dispatcher.h",
     "prefetch_dispatcher_impl.cc",
     "prefetch_dispatcher_impl.h",
diff --git a/components/offline_pages/core/prefetch/offline_metrics_collector.h b/components/offline_pages/core/prefetch/offline_metrics_collector.h
new file mode 100644
index 0000000..b11212e8
--- /dev/null
+++ b/components/offline_pages/core/prefetch/offline_metrics_collector.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_OFFLINE_PAGES_CORE_PREFETCH_OFFLINE_METRICS_COLLECTOR_H_
+#define COMPONENTS_OFFLINE_PAGES_CORE_PREFETCH_OFFLINE_METRICS_COLLECTOR_H_
+
+namespace offline_pages {
+
+// Observes various events and collects the data in order to classify
+// a day as 'offline', 'online' etc. Keeps the accumulated counters of each day
+// type until it is a good moment to report it (most often on a connected day).
+// The actual reporting is done by UMA.
+class OfflineMetricsCollector {
+ public:
+  virtual ~OfflineMetricsCollector() = default;
+
+  // Chrome started up or was (as on Android) brought from background to
+  // foreground. A day when this happened is a day the browser was used.
+  virtual void OnAppStartupOrResume() = 0;
+
+  // Successful online navigation committed. A day when this happens is counted
+  // as 'connected' day.
+  virtual void OnSuccessfulNavigationOnline() = 0;
+
+  // Successful navigation to an offline page happened. A day when it happens is
+  // at least a 'offline_content' day
+  virtual void OnSuccessfulNavigationOffline() = 0;
+
+  // Uses UMA to report the accumulated classification for the days past.
+  virtual void ReportAccumulatedStats() = 0;
+};
+
+}  // namespace offline_pages
+
+#endif  // COMPONENTS_OFFLINE_PAGES_CORE_PREFETCH_OFFLINE_METRICS_COLLECTOR_H_
diff --git a/components/offline_pages/core/prefetch/prefetch_service.h b/components/offline_pages/core/prefetch/prefetch_service.h
index 5731dd25..e8ceecc 100644
--- a/components/offline_pages/core/prefetch/prefetch_service.h
+++ b/components/offline_pages/core/prefetch/prefetch_service.h
@@ -13,6 +13,7 @@
 
 namespace offline_pages {
 
+class OfflineMetricsCollector;
 class PrefetchDispatcher;
 class PrefetchGCMHandler;
 
@@ -22,7 +23,13 @@
  public:
   ~PrefetchService() override = default;
 
+  // Subobjects that are created and owned by this service. Creation should be
+  // lightweight, all heavy work must be done on-demand only.
+  // The service manages lifetime, hookup and initialization of Prefetch
+  // system that consists of multiple specialized objects, all vended by this
+  // service. All pointers are raw and are always valid.
   virtual PrefetchDispatcher* GetDispatcher() = 0;
+  virtual OfflineMetricsCollector* GetOfflineMetricsCollector() = 0;
   virtual PrefetchGCMHandler* GetPrefetchGCMHandler() = 0;
 
   // Called at construction of the ContentSuggestionsService to begin observing
diff --git a/components/offline_pages/core/prefetch/prefetch_service_impl.cc b/components/offline_pages/core/prefetch/prefetch_service_impl.cc
index bf3a027..4f557e5e 100644
--- a/components/offline_pages/core/prefetch/prefetch_service_impl.cc
+++ b/components/offline_pages/core/prefetch/prefetch_service_impl.cc
@@ -7,29 +7,36 @@
 #include <utility>
 
 #include "base/memory/ptr_util.h"
+#include "components/offline_pages/core/prefetch/offline_metrics_collector.h"
 #include "components/offline_pages/core/prefetch/prefetch_dispatcher_impl.h"
 
 namespace offline_pages {
 
 PrefetchServiceImpl::PrefetchServiceImpl(
-    std::unique_ptr<PrefetchGCMHandler> gcm_handler)
+    std::unique_ptr<PrefetchGCMHandler> gcm_handler,
+    std::unique_ptr<OfflineMetricsCollector> offline_metrics_collector)
     : gcm_handler_(std::move(gcm_handler)),
-      dispatcher_(base::MakeUnique<PrefetchDispatcherImpl>()) {}
+      dispatcher_(base::MakeUnique<PrefetchDispatcherImpl>()),
+      offline_metrics_collector_(std::move(offline_metrics_collector)) {}
 
 PrefetchServiceImpl::~PrefetchServiceImpl() = default;
 
-PrefetchGCMHandler* PrefetchServiceImpl::GetPrefetchGCMHandler() {
-  return gcm_handler_.get();
+void PrefetchServiceImpl::ObserveContentSuggestionsService(
+    ntp_snippets::ContentSuggestionsService* service) {
+  suggested_articles_observer_ =
+      base::MakeUnique<SuggestedArticlesObserver>(service, this);
 }
 
 PrefetchDispatcher* PrefetchServiceImpl::GetDispatcher() {
   return dispatcher_.get();
 }
 
-void PrefetchServiceImpl::ObserveContentSuggestionsService(
-    ntp_snippets::ContentSuggestionsService* service) {
-  suggested_articles_observer_ =
-      base::MakeUnique<SuggestedArticlesObserver>(service, this);
+OfflineMetricsCollector* PrefetchServiceImpl::GetOfflineMetricsCollector() {
+  return offline_metrics_collector_.get();
+}
+
+PrefetchGCMHandler* PrefetchServiceImpl::GetPrefetchGCMHandler() {
+  return gcm_handler_.get();
 }
 
 void PrefetchServiceImpl::Shutdown() {}
diff --git a/components/offline_pages/core/prefetch/prefetch_service_impl.h b/components/offline_pages/core/prefetch/prefetch_service_impl.h
index cb50f9421..bcc2152 100644
--- a/components/offline_pages/core/prefetch/prefetch_service_impl.h
+++ b/components/offline_pages/core/prefetch/prefetch_service_impl.h
@@ -20,13 +20,16 @@
 
 class PrefetchServiceImpl : public PrefetchService {
  public:
-  PrefetchServiceImpl(std::unique_ptr<PrefetchGCMHandler> gcm_handler);
+  PrefetchServiceImpl(
+      std::unique_ptr<PrefetchGCMHandler> gcm_handler,
+      std::unique_ptr<OfflineMetricsCollector> offline_metrics_collector);
   ~PrefetchServiceImpl() override;
 
   // PrefetchService implementation:
   void ObserveContentSuggestionsService(
       ntp_snippets::ContentSuggestionsService* service) override;
   PrefetchDispatcher* GetDispatcher() override;
+  OfflineMetricsCollector* GetOfflineMetricsCollector() override;
   PrefetchGCMHandler* GetPrefetchGCMHandler() override;
 
   // KeyedService implementation:
@@ -36,6 +39,7 @@
   std::unique_ptr<SuggestedArticlesObserver> suggested_articles_observer_;
   std::unique_ptr<PrefetchGCMHandler> gcm_handler_;
   std::unique_ptr<PrefetchDispatcher> dispatcher_;
+  std::unique_ptr<OfflineMetricsCollector> offline_metrics_collector_;
 
   DISALLOW_COPY_AND_ASSIGN(PrefetchServiceImpl);
 };
diff --git a/components/offline_pages/core/prefetch/suggested_articles_observer_unittest.cc b/components/offline_pages/core/prefetch/suggested_articles_observer_unittest.cc
index 99595db..f813d52 100644
--- a/components/offline_pages/core/prefetch/suggested_articles_observer_unittest.cc
+++ b/components/offline_pages/core/prefetch/suggested_articles_observer_unittest.cc
@@ -67,11 +67,15 @@
  public:
   TestingPrefetchService() = default;
 
-  PrefetchGCMHandler* GetPrefetchGCMHandler() override { return nullptr; }
-  PrefetchDispatcher* GetDispatcher() override { return &dispatcher; };
   void ObserveContentSuggestionsService(
       ntp_snippets::ContentSuggestionsService* content_suggestions_service)
       override {}
+  PrefetchDispatcher* GetDispatcher() override { return &dispatcher; };
+  OfflineMetricsCollector* GetOfflineMetricsCollector() override {
+    return nullptr;
+  }
+  PrefetchGCMHandler* GetPrefetchGCMHandler() override { return nullptr; }
+
   TestingPrefetchDispatcher dispatcher;
 };
 }  // namespace
diff --git a/components/startup_metric_utils/browser/startup_metric_utils.cc b/components/startup_metric_utils/browser/startup_metric_utils.cc
index 8d9e466..f55f890 100644
--- a/components/startup_metric_utils/browser/startup_metric_utils.cc
+++ b/components/startup_metric_utils/browser/startup_metric_utils.cc
@@ -718,9 +718,11 @@
       g_process_creation_ticks.Get(), ticks);
 }
 
-void RecordFirstWebContentsNonEmptyPaint(base::TimeTicks ticks) {
+void RecordFirstWebContentsNonEmptyPaint(
+    base::TimeTicks now,
+    base::TimeTicks render_process_host_init_time) {
   static bool is_first_call = true;
-  if (!is_first_call || ticks.is_null())
+  if (!is_first_call || now.is_null())
     return;
   is_first_call = false;
 
@@ -735,11 +737,16 @@
       metrics::CallStackProfileMetricsProvider::FIRST_NONEMPTY_PAINT);
   UMA_HISTOGRAM_AND_TRACE_WITH_TEMPERATURE_AND_SAME_VERSION_COUNT(
       UMA_HISTOGRAM_LONG_TIMES_100, "Startup.FirstWebContents.NonEmptyPaint2",
-      g_process_creation_ticks.Get(), ticks);
+      g_process_creation_ticks.Get(), now);
   UMA_HISTOGRAM_WITH_TEMPERATURE(
       UMA_HISTOGRAM_LONG_TIMES_100,
       "Startup.BrowserMessageLoopStart.To.NonEmptyPaint2",
-      ticks - g_message_loop_start_ticks.Get());
+      now - g_message_loop_start_ticks.Get());
+
+  UMA_HISTOGRAM_WITH_TEMPERATURE(
+      UMA_HISTOGRAM_LONG_TIMES_100,
+      "Startup.FirstWebContents.RenderProcessHostInit.ToNonEmptyPaint",
+      now - render_process_host_init_time);
 }
 
 void RecordFirstWebContentsMainNavigationStart(base::TimeTicks ticks,
diff --git a/components/startup_metric_utils/browser/startup_metric_utils.h b/components/startup_metric_utils/browser/startup_metric_utils.h
index 2e6fd0d..6066d71 100644
--- a/components/startup_metric_utils/browser/startup_metric_utils.h
+++ b/components/startup_metric_utils/browser/startup_metric_utils.h
@@ -83,8 +83,10 @@
 void RecordFirstWebContentsMainFrameLoad(base::TimeTicks ticks);
 
 // Call this with the time when the first web contents had a non-empty paint,
-// only if the first web contents was unimpended in its attempt to do so.
-void RecordFirstWebContentsNonEmptyPaint(base::TimeTicks ticks);
+// only if the first web contents was unimpeded in its attempt to do so.
+void RecordFirstWebContentsNonEmptyPaint(
+    base::TimeTicks now,
+    base::TimeTicks render_process_host_init_time);
 
 // Call this with the time when the first web contents began navigating its main
 // frame. Adds a suffix to its metrics according to |workload|.
diff --git a/content/browser/frame_host/PRESUBMIT.py b/content/browser/frame_host/PRESUBMIT.py
index fd53c7ea4..d5a8742 100644
--- a/content/browser/frame_host/PRESUBMIT.py
+++ b/content/browser/frame_host/PRESUBMIT.py
@@ -7,26 +7,6 @@
 for more details about the presubmit API built into depot_tools.
 """
 
-import re
-
-
-def _GetTryMasters(project, change):
-  return {
-    'master.tryserver.chromium.linux': {
-      'linux_site_isolation': [],
-     },
-  }
-
-
-def GetPreferredTryMasters(project, change):
-  # TODO(nick, dcheng): Using the value of _GetTryMasters() instead of an empty
-  # value here would cause 'git cl try' to include the site isolation trybots,
-  # which would be nice. But it has the side effect of replacing, rather than
-  # augmenting, the default set of try servers. Re-enable this when we figure
-  # out a way to augment the default set.
-  return {}
-
-
 def PostUploadHook(cl, change, output_api):
   """git cl upload will call this hook after the issue is created/modified.
 
@@ -39,3 +19,4 @@
       'master.tryserver.chromium.linux:linux_site_isolation'
     ],
     'Automatically added site isolation trybots to run tests on CQ.')
+
diff --git a/content/browser/indexed_db/database_impl.cc b/content/browser/indexed_db/database_impl.cc
index 61887172..4b72469d 100644
--- a/content/browser/indexed_db/database_impl.cc
+++ b/content/browser/indexed_db/database_impl.cc
@@ -6,6 +6,7 @@
 
 #include "base/memory/ptr_util.h"
 #include "base/metrics/histogram_macros.h"
+#include "base/numerics/safe_math.h"
 #include "base/sequenced_task_runner.h"
 #include "base/threading/thread_checker.h"
 #include "base/threading/thread_task_runner_handle.h"
@@ -281,6 +282,7 @@
 
   std::vector<std::unique_ptr<storage::BlobDataHandle>> handles(
       value->blob_or_file_info.size());
+  base::CheckedNumeric<uint64_t> total_blob_size = 0;
   std::vector<IndexedDBBlobInfo> blob_info(value->blob_or_file_info.size());
   for (size_t i = 0; i < value->blob_or_file_info.size(); ++i) {
     ::indexed_db::mojom::BlobInfoPtr& info = value->blob_or_file_info[i];
@@ -303,9 +305,9 @@
                                 base::Passed(&callbacks), error));
       return;
     }
-    UMA_HISTOGRAM_MEMORY_KB("Storage.IndexedDB.PutBlobSizeKB",
-                            handle->size() / 1024ull);
-
+    uint64_t size = handle->size();
+    UMA_HISTOGRAM_MEMORY_KB("Storage.IndexedDB.PutBlobSizeKB", size / 1024ull);
+    total_blob_size += size;
     handles[i] = std::move(handle);
 
     if (info->file) {
@@ -325,7 +327,15 @@
       blob_info[i] = IndexedDBBlobInfo(info->uuid, info->mime_type, info->size);
     }
   }
-
+  UMA_HISTOGRAM_COUNTS_1000("WebCore.IndexedDB.PutBlobsCount",
+                            blob_info.size());
+  uint64_t blob_size = 0;
+  total_blob_size.AssignIfValid(&blob_size);
+  if (blob_size != 0) {
+    // 1KB to 1GB.
+    UMA_HISTOGRAM_COUNTS_1M("WebCore.IndexedDB.PutBlobsTotalSize",
+                            blob_size / 1024);
+  }
   idb_runner_->PostTask(
       FROM_HERE,
       base::Bind(&IDBThreadHelper::Put, base::Unretained(helper_),
@@ -665,7 +675,12 @@
   if (!transaction)
     return;
 
-  uint64_t commit_size = mojo_value->bits.size();
+  // Value size recorded in IDBObjectStore before we can auto-wrap in a blob.
+  // 1KB to 10MB.
+  UMA_HISTOGRAM_COUNTS_10000("WebCore.IndexedDB.PutKeySize",
+                             key.size_estimate() / 1024);
+
+  uint64_t commit_size = mojo_value->bits.size() + key.size_estimate();
   IndexedDBValue value;
   swap(value.bits, mojo_value->bits);
   swap(value.blob_info, blob_info);
diff --git a/content/browser/indexed_db/indexed_db_backing_store.cc b/content/browser/indexed_db/indexed_db_backing_store.cc
index 7711662..64d2291 100644
--- a/content/browser/indexed_db/indexed_db_backing_store.cc
+++ b/content/browser/indexed_db/indexed_db_backing_store.cc
@@ -4364,6 +4364,11 @@
   transaction_ = NULL;
 }
 
+uint64_t IndexedDBBackingStore::Transaction::GetTransactionSize() {
+  DCHECK(transaction_);
+  return transaction_->GetTransactionSize();
+}
+
 IndexedDBBackingStore::BlobChangeRecord::BlobChangeRecord(
     const std::string& key,
     int64_t object_store_id)
diff --git a/content/browser/indexed_db/indexed_db_backing_store.h b/content/browser/indexed_db/indexed_db_backing_store.h
index 58d4003..3c04dabc 100644
--- a/content/browser/indexed_db/indexed_db_backing_store.h
+++ b/content/browser/indexed_db/indexed_db_backing_store.h
@@ -169,6 +169,8 @@
 
     LevelDBTransaction* transaction() { return transaction_.get(); }
 
+    virtual uint64_t GetTransactionSize();
+
     leveldb::Status GetBlobInfoForRecord(
         int64_t database_id,
         const std::string& object_store_data_key,
diff --git a/content/browser/indexed_db/indexed_db_fake_backing_store.cc b/content/browser/indexed_db/indexed_db_fake_backing_store.cc
index d89073d..2eaea3ea 100644
--- a/content/browser/indexed_db/indexed_db_fake_backing_store.cc
+++ b/content/browser/indexed_db/indexed_db_fake_backing_store.cc
@@ -224,6 +224,9 @@
 leveldb::Status IndexedDBFakeBackingStore::FakeTransaction::CommitPhaseTwo() {
   return result_;
 }
+uint64_t IndexedDBFakeBackingStore::FakeTransaction::GetTransactionSize() {
+  return 0;
+}
 void IndexedDBFakeBackingStore::FakeTransaction::Rollback() {}
 
 }  // namespace content
diff --git a/content/browser/indexed_db/indexed_db_fake_backing_store.h b/content/browser/indexed_db/indexed_db_fake_backing_store.h
index d8d81242..cc16603f 100644
--- a/content/browser/indexed_db/indexed_db_fake_backing_store.h
+++ b/content/browser/indexed_db/indexed_db_fake_backing_store.h
@@ -147,6 +147,7 @@
     void Begin() override;
     leveldb::Status CommitPhaseOne(scoped_refptr<BlobWriteCallback>) override;
     leveldb::Status CommitPhaseTwo() override;
+    uint64_t GetTransactionSize() override;
     void Rollback() override;
 
    private:
diff --git a/content/browser/indexed_db/indexed_db_transaction.cc b/content/browser/indexed_db/indexed_db_transaction.cc
index 5fe8767..e1a3a5b 100644
--- a/content/browser/indexed_db/indexed_db_transaction.cc
+++ b/content/browser/indexed_db/indexed_db_transaction.cc
@@ -381,6 +381,32 @@
   if (!used_) {
     committed = true;
   } else {
+    base::TimeDelta active_time = base::Time::Now() - diagnostics_.start_time;
+    uint64_t size = transaction_->GetTransactionSize() / 1024;
+    switch (mode_) {
+      case blink::kWebIDBTransactionModeReadOnly:
+        UMA_HISTOGRAM_MEDIUM_TIMES(
+            "WebCore.IndexedDB.Transaction.ReadOnly.TimeActive", active_time);
+        UMA_HISTOGRAM_MEMORY_KB(
+            "WebCore.IndexedDB.Transaction.ReadOnly.SizeOnCommit", size);
+        break;
+      case blink::kWebIDBTransactionModeReadWrite:
+        UMA_HISTOGRAM_MEDIUM_TIMES(
+            "WebCore.IndexedDB.Transaction.ReadWrite.TimeActive", active_time);
+        UMA_HISTOGRAM_MEMORY_KB(
+            "WebCore.IndexedDB.Transaction.ReadWrite.SizeOnCommit", size);
+        break;
+      case blink::kWebIDBTransactionModeVersionChange:
+        UMA_HISTOGRAM_MEDIUM_TIMES(
+            "WebCore.IndexedDB.Transaction.VersionChange.TimeActive",
+            active_time);
+        UMA_HISTOGRAM_MEMORY_KB(
+            "WebCore.IndexedDB.Transaction.VersionChange.SizeOnCommit", size);
+        break;
+      default:
+        NOTREACHED();
+    }
+
     s = transaction_->CommitPhaseTwo();
     committed = s.ok();
   }
diff --git a/content/browser/indexed_db/leveldb/leveldb_transaction.cc b/content/browser/indexed_db/leveldb/leveldb_transaction.cc
index 252059f..b2e83c4 100644
--- a/content/browser/indexed_db/leveldb/leveldb_transaction.cc
+++ b/content/browser/indexed_db/leveldb/leveldb_transaction.cc
@@ -26,7 +26,6 @@
   return (open ? comparator->Compare(key, end) < 0
                : comparator->Compare(key, end) <= 0);
 }
-
 }  // namespace
 
 namespace content {
@@ -51,6 +50,7 @@
 
   if (it == data_.end()) {
     std::unique_ptr<Record> record = base::MakeUnique<Record>();
+    size_ += SizeOfRecordInMap(key.size()) + value->size();
     record->key.assign(key.begin(), key.end() - key.begin());
     record->value.swap(*value);
     record->deleted = deleted;
@@ -58,7 +58,9 @@
     NotifyIterators();
     return;
   }
+  size_ += value->size();
   it->second->value.swap(*value);
+  size_ -= value->size();
   it->second->deleted = deleted;
 }
 
@@ -163,6 +165,10 @@
   return base::WrapUnique(new DataIterator(transaction));
 }
 
+constexpr uint64_t LevelDBTransaction::SizeOfRecordInMap(size_t key_size) {
+  return sizeof(Record) + key_size * 2;
+}
+
 bool LevelDBTransaction::DataIterator::IsValid() const {
   return iterator_ != data_->end();
 }
@@ -374,11 +380,14 @@
 void LevelDBTransaction::TransactionIterator::Delete() {
   DCHECK(IsValid());
   if (current_ == data_iterator_.get()) {
+    transaction_->size_ -= data_iterator_->Value().size();
     data_iterator_->Delete();
   } else {
     std::unique_ptr<Record> record = base::MakeUnique<Record>();
     record->key = Key().as_string();
     record->deleted = true;
+    transaction_->size_ +=
+        LevelDBTransaction::SizeOfRecordInMap(record->key.size());
     transaction_->data_[record->key] = std::move(record);
   }
 }
diff --git a/content/browser/indexed_db/leveldb/leveldb_transaction.h b/content/browser/indexed_db/leveldb/leveldb_transaction.h
index 19181f0..5586fd3 100644
--- a/content/browser/indexed_db/leveldb/leveldb_transaction.h
+++ b/content/browser/indexed_db/leveldb/leveldb_transaction.h
@@ -40,6 +40,8 @@
 
   std::unique_ptr<LevelDBIterator> CreateIterator();
 
+  uint64_t GetTransactionSize() const { return size_; }
+
  protected:
   virtual ~LevelDBTransaction();
   explicit LevelDBTransaction(LevelDBDatabase* db);
@@ -49,7 +51,7 @@
   friend class base::RefCounted<LevelDBTransaction>;
   friend class LevelDBTransactionRangeTest;
   friend class LevelDBTransactionTest;
-  FRIEND_TEST_ALL_PREFIXES(LevelDBTransactionTest, GetAndPut);
+  FRIEND_TEST_ALL_PREFIXES(LevelDBTransactionTest, GetPutDelete);
   FRIEND_TEST_ALL_PREFIXES(LevelDBTransactionTest, Commit);
   FRIEND_TEST_ALL_PREFIXES(LevelDBTransactionTest, Iterator);
 
@@ -60,6 +62,7 @@
     std::string value;
     bool deleted = false;
   };
+  static constexpr uint64_t SizeOfRecordInMap(size_t key_size);
 
   class Comparator {
    public:
@@ -164,6 +167,7 @@
   const LevelDBComparator* comparator_;
   Comparator data_comparator_;
   DataType data_;
+  uint64_t size_ = 0ull;
   bool finished_ = false;
   std::set<TransactionIterator*> iterators_;
 
diff --git a/content/browser/indexed_db/leveldb/leveldb_transaction_unittest.cc b/content/browser/indexed_db/leveldb/leveldb_transaction_unittest.cc
index d4870f1..3428346e 100644
--- a/content/browser/indexed_db/leveldb/leveldb_transaction_unittest.cc
+++ b/content/browser/indexed_db/leveldb/leveldb_transaction_unittest.cc
@@ -106,6 +106,10 @@
     return new LevelDBTransaction(db());
   }
 
+  static constexpr size_t SizeOfRecord() {
+    return sizeof(LevelDBTransaction::Record);
+  }
+
  private:
   base::ScopedTempDir temp_directory_;
   SimpleComparator comparator_;
@@ -114,7 +118,7 @@
   DISALLOW_COPY_AND_ASSIGN(LevelDBTransactionTest);
 };
 
-TEST_F(LevelDBTransactionTest, GetAndPut) {
+TEST_F(LevelDBTransactionTest, GetPutDelete) {
   leveldb::Status status;
 
   const std::string key("key");
@@ -150,12 +154,19 @@
 
   const std::string another_key("another key");
   const std::string another_value("another value");
+  EXPECT_EQ(0ull, transaction->GetTransactionSize());
   TransactionPut(transaction.get(), another_key, another_value);
+  EXPECT_EQ(SizeOfRecord() + another_key.size() * 2 + another_value.size(),
+            transaction->GetTransactionSize());
 
   status = transaction->Get(another_key, &got_value, &found);
   EXPECT_TRUE(status.ok());
   EXPECT_TRUE(found);
   EXPECT_EQ(Compare(got_value, another_value), 0);
+
+  transaction->Remove(another_key);
+  EXPECT_EQ(SizeOfRecord() + another_key.size() * 2,
+            transaction->GetTransactionSize());
 }
 
 TEST_F(LevelDBTransactionTest, Iterator) {
diff --git a/content/browser/resources/gpu/info_view.html b/content/browser/resources/gpu/info_view.html
index b1cef9c..7d9954b 100644
--- a/content/browser/resources/gpu/info_view.html
+++ b/content/browser/resources/gpu/info_view.html
@@ -5,6 +5,14 @@
 -->
 <tabpanel id="info-view">
   <div>
+    <span>
+      <i>
+        Note: To properly save this page, select the "Webpage, Complete" option
+        in the Save File dialog.
+      </i>
+    </span>
+  </div>
+  <div>
     <h3>Graphics Feature Status</h3>
     <ul class="feature-status-list">
     </ul>
diff --git a/content/browser/resources/media/client_renderer.js b/content/browser/resources/media/client_renderer.js
index adfa319a..63c7dcf 100644
--- a/content/browser/resources/media/client_renderer.js
+++ b/content/browser/resources/media/client_renderer.js
@@ -29,10 +29,7 @@
     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);
@@ -217,8 +214,9 @@
       var copyButtonElement =
           document.getElementById('video-capture-capabilities-copy-button');
       copyButtonElement.onclick = function() {
-        this.showClipboard(JSON.stringify(videoCaptureCapabilities, null, 2));
-      }.bind(this);
+        window.prompt('Copy to clipboard: Ctrl+C, Enter',
+                      JSON.stringify(videoCaptureCapabilities))
+      }
 
       var videoTableBodyElement  =
           document.getElementById('video-capture-capabilities-tbody');
@@ -298,7 +296,7 @@
       }
 
       var fragment = document.createDocumentFragment();
-      for (var id in components) {
+      for (id in components) {
         var li = document.createElement('li');
         var button_cb = this.selectAudioComponent_.bind(
                 this, componentType, id, components[id]);
@@ -341,7 +339,7 @@
 
       var hasPlayers = false;
       var fragment = document.createDocumentFragment();
-      for (var id in players) {
+      for (id in players) {
         hasPlayers = true;
         var player = players[id];
         var usableName = player.properties.name ||
@@ -421,7 +419,7 @@
 
     saveLog_: function() {
       var strippedPlayers = []
-      for (var id in this.players) {
+      for (id in this.players) {
         var p = this.players[id];
         strippedPlayers.push({properties: p.properties, events: p.allEvents});
       }
@@ -498,17 +496,6 @@
       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;
@@ -525,7 +512,17 @@
         stringBuffer.push('\n');
       }
 
-      this.showClipboard(stringBuffer.join(''));
+      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);
+      };
     },
 
     onTextChange_: function(event) {
diff --git a/content/browser/resources/media/manager.js b/content/browser/resources/media/manager.js
index f07ecb3e..983cca5 100644
--- a/content/browser/resources/media/manager.js
+++ b/content/browser/resources/media/manager.js
@@ -17,18 +17,6 @@
     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 33f969d..7b2c43f 100644
--- a/content/browser/resources/media/media_internals.css
+++ b/content/browser/resources/media/media_internals.css
@@ -123,14 +123,17 @@
   list-style-type: none;
 }
 
-#clipboard-dialog {
-  top: 0;
-  bottom: 0;
+#clipboard-textarea {
+  position: absolute;
+  width: 50%;
+  height: 50%;
+
+  left: 25%;
+  top: 25%;
 }
 
-::backdrop {
-  background-color: #000;
-  opacity: 0.5;
+.hiddenClipboard {
+  display: none;
 }
 
 .timestamp {
diff --git a/content/browser/resources/media/media_internals.html b/content/browser/resources/media/media_internals.html
index fc16569..5ceeec2c 100644
--- a/content/browser/resources/media/media_internals.html
+++ b/content/browser/resources/media/media_internals.html
@@ -29,7 +29,6 @@
       <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>
@@ -69,7 +68,6 @@
         <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>
@@ -121,9 +119,7 @@
       </tabpanel>
     </tabpanels>
   </tabbox>
-  <dialog id="clipboard-dialog">
-    <textarea id="clipboard-textarea" rows="30" cols="80"></textarea>
-  </dialog>
+  <textarea id="clipboard-textarea" class="hiddenClipboard"></textarea>
   <script src="media_internals.js"></script>
 </body>
 </html>
diff --git a/content/browser/web_contents_binding_set_browsertest.cc b/content/browser/web_contents_binding_set_browsertest.cc
index 970a9831..63435d1 100644
--- a/content/browser/web_contents_binding_set_browsertest.cc
+++ b/content/browser/web_contents_binding_set_browsertest.cc
@@ -9,16 +9,27 @@
 #include "content/public/test/browser_test_utils.h"
 #include "content/public/test/content_browser_test.h"
 #include "content/public/test/content_browser_test_utils.h"
+#include "content/public/test/test_utils.h"
 #include "content/public/test/web_contents_binding_set_test_binder.h"
 #include "content/shell/browser/shell.h"
 #include "content/test/test_browser_associated_interfaces.mojom.h"
+#include "net/dns/mock_host_resolver.h"
 
 namespace content {
 
-using WebContentsBindingSetBrowserTest = ContentBrowserTest;
-
 namespace {
 
+const char kTestHost1[] = "foo.com";
+const char kTestHost2[] = "bar.com";
+
+class WebContentsBindingSetBrowserTest : public ContentBrowserTest {
+ public:
+  void SetUpOnMainThread() override {
+    host_resolver()->AddRule(kTestHost1, "127.0.0.1");
+    host_resolver()->AddRule(kTestHost2, "127.0.0.1");
+  }
+};
+
 class TestInterfaceBinder : public WebContentsBindingSetTestBinder<
                                 mojom::BrowserAssociatedInterfaceTestDriver> {
  public:
@@ -38,6 +49,19 @@
   DISALLOW_COPY_AND_ASSIGN(TestInterfaceBinder);
 };
 
+class TestFrameInterfaceBinder : public mojom::WebContentsFrameBindingSetTest {
+ public:
+  explicit TestFrameInterfaceBinder(WebContents* web_contents)
+      : bindings_(web_contents, this) {}
+  ~TestFrameInterfaceBinder() override {}
+
+ private:
+  // mojom::WebContentsFrameBindingSetTest:
+  void Ping(PingCallback callback) override { NOTREACHED(); }
+
+  WebContentsFrameBindingSet<mojom::WebContentsFrameBindingSetTest> bindings_;
+};
+
 }  // namespace
 
 IN_PROC_BROWSER_TEST_F(WebContentsBindingSetBrowserTest, OverrideForTesting) {
@@ -68,4 +92,36 @@
   run_loop.Run();
 }
 
+IN_PROC_BROWSER_TEST_F(WebContentsBindingSetBrowserTest, CloseOnFrameDeletion) {
+  EXPECT_TRUE(embedded_test_server()->Start());
+  EXPECT_TRUE(NavigateToURL(
+      shell(), embedded_test_server()->GetURL(kTestHost1, "/hello.html")));
+
+  // Simulate an inbound request on the navigated main frame.
+  auto* web_contents = shell()->web_contents();
+  TestFrameInterfaceBinder binder(web_contents);
+  mojom::WebContentsFrameBindingSetTestAssociatedPtr override_client;
+  static_cast<WebContentsImpl*>(web_contents)
+      ->OnAssociatedInterfaceRequest(
+          web_contents->GetMainFrame(),
+          mojom::WebContentsFrameBindingSetTest::Name_,
+          mojo::MakeIsolatedRequest(&override_client).PassHandle());
+
+  base::RunLoop run_loop;
+  override_client.set_connection_error_handler(run_loop.QuitClosure());
+
+  // Now navigate the WebContents elsewhere, eventually tearing down the old
+  // main frame.
+  RenderFrameDeletedObserver deleted_observer(web_contents->GetMainFrame());
+  EXPECT_TRUE(NavigateToURL(
+      shell(), embedded_test_server()->GetURL(kTestHost2, "/title2.html")));
+  deleted_observer.WaitUntilDeleted();
+
+  // Verify that this message never reaches the binding for the old frame. If it
+  // does, the impl will hit a DCHECK. The RunLoop terminates when the client is
+  // disconnected.
+  override_client->Ping(base::Bind([] {}));
+  run_loop.Run();
+}
+
 }  // namespace content
diff --git a/content/network/network_context.cc b/content/network/network_context.cc
index 4eeab3b0..4cafa634a 100644
--- a/content/network/network_context.cc
+++ b/content/network/network_context.cc
@@ -14,6 +14,7 @@
 #include "content/public/common/content_switches.h"
 #include "net/dns/host_resolver.h"
 #include "net/dns/mapped_host_resolver.h"
+#include "net/http/http_network_session.h"
 #include "net/proxy/proxy_config.h"
 #include "net/proxy/proxy_config_service_fixed.h"
 #include "net/url_request/url_request_context.h"
@@ -25,7 +26,7 @@
 
 std::unique_ptr<net::URLRequestContext> MakeURLRequestContext() {
   net::URLRequestContextBuilder builder;
-  net::URLRequestContextBuilder::HttpNetworkSessionParams params;
+  net::HttpNetworkSession::Params params;
   const base::CommandLine* command_line =
       base::CommandLine::ForCurrentProcess();
   if (command_line->HasSwitch(switches::kIgnoreCertificateErrors))
diff --git a/content/public/browser/web_contents_binding_set.h b/content/public/browser/web_contents_binding_set.h
index b5c3791..0b56e88 100644
--- a/content/public/browser/web_contents_binding_set.h
+++ b/content/public/browser/web_contents_binding_set.h
@@ -13,6 +13,7 @@
 #include "base/memory/ptr_util.h"
 #include "content/common/content_export.h"
 #include "content/public/browser/web_contents.h"
+#include "content/public/browser/web_contents_observer.h"
 #include "mojo/public/cpp/bindings/associated_binding_set.h"
 #include "mojo/public/cpp/bindings/associated_interface_request.h"
 #include "mojo/public/cpp/bindings/scoped_interface_endpoint_handle.h"
@@ -113,8 +114,9 @@
  public:
   WebContentsFrameBindingSet(WebContents* web_contents, Interface* impl)
       : WebContentsBindingSet(
-          web_contents, Interface::Name_,
-          base::MakeUnique<FrameInterfaceBinder>(this, impl)) {}
+            web_contents,
+            Interface::Name_,
+            base::MakeUnique<FrameInterfaceBinder>(this, web_contents, impl)) {}
   ~WebContentsFrameBindingSet() {}
 
   // Returns the RenderFrameHost currently targeted by a message dispatch to
@@ -130,10 +132,12 @@
   }
 
  private:
-  class FrameInterfaceBinder : public Binder {
+  class FrameInterfaceBinder : public Binder, public WebContentsObserver {
    public:
     FrameInterfaceBinder(WebContentsFrameBindingSet* binding_set,
-                         Interface* impl) : impl_(impl) {
+                         WebContents* web_contents,
+                         Interface* impl)
+        : WebContentsObserver(web_contents), impl_(impl) {
       bindings_.set_pre_dispatch_handler(
           base::Bind(&WebContentsFrameBindingSet::WillDispatchForContext,
                      base::Unretained(binding_set)));
@@ -145,13 +149,26 @@
     void OnRequestForFrame(
         RenderFrameHost* render_frame_host,
         mojo::ScopedInterfaceEndpointHandle handle) override {
-      bindings_.AddBinding(
+      auto id = bindings_.AddBinding(
           impl_, mojo::AssociatedInterfaceRequest<Interface>(std::move(handle)),
           render_frame_host);
+      frame_to_bindings_map_[render_frame_host].push_back(id);
+    }
+
+    // WebContentsObserver:
+    void RenderFrameDeleted(RenderFrameHost* render_frame_host) override {
+      auto it = frame_to_bindings_map_.find(render_frame_host);
+      if (it == frame_to_bindings_map_.end())
+        return;
+      for (auto id : it->second)
+        bindings_.RemoveBinding(id);
+      frame_to_bindings_map_.erase(it);
     }
 
     Interface* const impl_;
     mojo::AssociatedBindingSet<Interface, RenderFrameHost*> bindings_;
+    std::map<RenderFrameHost*, std::vector<mojo::BindingId>>
+        frame_to_bindings_map_;
 
     DISALLOW_COPY_AND_ASSIGN(FrameInterfaceBinder);
   };
diff --git a/content/public/renderer/render_frame.h b/content/public/renderer/render_frame.h
index 0400092..2ff0b2c 100644
--- a/content/public/renderer/render_frame.h
+++ b/content/public/renderer/render_frame.h
@@ -94,7 +94,10 @@
   };
 
   // Returns the RenderFrame given a WebFrame.
+  // TODO(https://crbug.com/416660): Remove this, as RenderFrames only
+  // correspond to WebLocalFrames.
   static RenderFrame* FromWebFrame(blink::WebFrame* web_frame);
+  static RenderFrame* FromWebFrame(blink::WebLocalFrame* web_frame);
 
   // Returns the RenderFrame given a routing id.
   static RenderFrame* FromRoutingID(int routing_id);
diff --git a/content/renderer/gpu/render_widget_compositor.cc b/content/renderer/gpu/render_widget_compositor.cc
index 41c7bbc6..e979d11d 100644
--- a/content/renderer/gpu/render_widget_compositor.cc
+++ b/content/renderer/gpu/render_widget_compositor.cc
@@ -477,7 +477,7 @@
     // and are disabled for Android WebView as it doesn't support the format.
     if (!cmd.HasSwitch(switches::kDisableRGBA4444Textures) &&
         base::SysInfo::AmountOfPhysicalMemoryMB() <= 512)
-      settings.renderer_settings.preferred_tile_format = cc::RGBA_4444;
+      settings.preferred_tile_format = cc::RGBA_4444;
   } else {
     // On other devices we have increased memory excessively to avoid
     // raster-on-demand already, so now we reserve 50% _only_ to avoid
@@ -528,11 +528,11 @@
 
   if (cmd.HasSwitch(switches::kEnableRGBA4444Textures) &&
       !cmd.HasSwitch(switches::kDisableRGBA4444Textures)) {
-    settings.renderer_settings.preferred_tile_format = cc::RGBA_4444;
+    settings.preferred_tile_format = cc::RGBA_4444;
   }
 
   if (cmd.HasSwitch(cc::switches::kEnableTileCompression)) {
-    settings.renderer_settings.preferred_tile_format = cc::ETC1;
+    settings.preferred_tile_format = cc::ETC1;
   }
 
   settings.max_staging_buffer_usage_in_bytes = 32 * 1024 * 1024;  // 32MB
diff --git a/content/renderer/input/input_handler_manager.cc b/content/renderer/input/input_handler_manager.cc
index 258e910..05f5c06 100644
--- a/content/renderer/input/input_handler_manager.cc
+++ b/content/renderer/input/input_handler_manager.cc
@@ -223,8 +223,8 @@
   InputHandlerProxy* proxy = it->second->input_handler_proxy();
   proxy->HandleInputEventWithLatencyInfo(
       std::move(input_event), latency_info,
-      base::Bind(&InputHandlerManager::DidHandleInputEventAndOverscroll,
-                 weak_ptr_factory_.GetWeakPtr(), callback));
+      base::BindOnce(&InputHandlerManager::DidHandleInputEventAndOverscroll,
+                     weak_ptr_factory_.GetWeakPtr(), callback));
 }
 
 void InputHandlerManager::QueueClosureForMainThreadEventQueue(
diff --git a/content/renderer/render_frame_impl.cc b/content/renderer/render_frame_impl.cc
index a6ebbfb0..3cbb833 100644
--- a/content/renderer/render_frame_impl.cc
+++ b/content/renderer/render_frame_impl.cc
@@ -1055,6 +1055,11 @@
 }
 
 // static
+RenderFrame* RenderFrame::FromWebFrame(blink::WebLocalFrame* web_frame) {
+  return RenderFrameImpl::FromWebFrame(web_frame);
+}
+
+// static
 void RenderFrame::ForEach(RenderFrameVisitor* visitor) {
   FrameMap* frames = g_frame_map.Pointer();
   for (FrameMap::iterator it = frames->begin(); it != frames->end(); ++it) {
diff --git a/content/test/test_browser_associated_interfaces.mojom b/content/test/test_browser_associated_interfaces.mojom
index cc18873..4e994a1 100644
--- a/content/test/test_browser_associated_interfaces.mojom
+++ b/content/test/test_browser_associated_interfaces.mojom
@@ -8,3 +8,7 @@
   ExpectString(string expected);
   RequestQuit() => ();
 };
+
+interface WebContentsFrameBindingSetTest {
+  Ping() => ();
+};
diff --git a/google_apis/gcm/tools/mcs_probe.cc b/google_apis/gcm/tools/mcs_probe.cc
index 28d69363..00f9b71 100644
--- a/google_apis/gcm/tools/mcs_probe.cc
+++ b/google_apis/gcm/tools/mcs_probe.cc
@@ -195,7 +195,11 @@
                                 ,
                             std::string()
 #endif
-                                ) {
+#if defined(OS_CHROMEOS)
+                                ,
+                            true
+#endif
+                            ) {
   }
   bool IsSupportedScheme(const std::string& scheme) const override {
     return scheme == std::string(net::kBasicAuthScheme);
diff --git a/ios/chrome/browser/crash_report/crash_report_helper.mm b/ios/chrome/browser/crash_report/crash_report_helper.mm
index b67b01f..bbb5fcb 100644
--- a/ios/chrome/browser/crash_report/crash_report_helper.mm
+++ b/ios/chrome/browser/crash_report/crash_report_helper.mm
@@ -25,6 +25,7 @@
 #import "ios/chrome/browser/tabs/tab_model.h"
 #import "ios/chrome/browser/tabs/tab_model_observer.h"
 #include "ios/web/public/browser_state.h"
+#import "ios/web/public/navigation_item.h"
 #include "ios/web/public/web_state/web_state.h"
 #include "ios/web/public/web_thread.h"
 #import "net/base/mac/url_conversions.h"
@@ -215,9 +216,13 @@
     didChangeActiveTab:(Tab*)newTab
            previousTab:(Tab*)previousTab
                atIndex:(NSUInteger)modelIndex {
-  [self recordURL:base::SysUTF8ToNSString(newTab.url.spec())
+  web::NavigationItem* pendingItem =
+      newTab.webState->GetNavigationManager()->GetPendingItem();
+  const GURL& URL =
+      pendingItem ? pendingItem->GetURL() : newTab.lastCommittedURL;
+  [self recordURL:base::SysUTF8ToNSString(URL.spec())
          forTabId:newTab.tabId
-          pending:NO];
+          pending:pendingItem ? YES : NO];
 }
 
 // Empty method left in place in case jailbreakers are swizzling this.
diff --git a/ios/chrome/browser/ui/side_swipe/card_side_swipe_view.mm b/ios/chrome/browser/ui/side_swipe/card_side_swipe_view.mm
index 8bff8e2..ad05f4a8 100644
--- a/ios/chrome/browser/ui/side_swipe/card_side_swipe_view.mm
+++ b/ios/chrome/browser/ui/side_swipe/card_side_swipe_view.mm
@@ -227,7 +227,7 @@
   [card setHidden:NO];
 
   Tab* tab = [model_ tabAtIndex:index];
-  BOOL isNTP = tab.url.host() == kChromeUINewTabHost;
+  BOOL isNTP = tab.lastCommittedURL.host() == kChromeUINewTabHost;
   [toolbarController updateToolbarForSideSwipeSnapshot:tab];
   UIImage* toolbarView = CaptureViewWithOption([toolbarController view],
                                                [[UIScreen mainScreen] scale],
diff --git a/ios/chrome/browser/web/visible_url_egtest.mm b/ios/chrome/browser/web/visible_url_egtest.mm
index e97e233..e9050920 100644
--- a/ios/chrome/browser/web/visible_url_egtest.mm
+++ b/ios/chrome/browser/web/visible_url_egtest.mm
@@ -402,8 +402,8 @@
   // pending URL.
   [[EarlGrey selectElementWithMatcher:chrome_test_util::BackButton()]
       performAction:grey_tap()];
-  GREYAssert([self waitForServerToReceiveRequestWithURL:_testURL1],
-             @"Last request URL: %@", self.lastRequestURLSpec);
+  // TODO(crbug.com/724560): Re-evaluate if necessary to check receiving URL1
+  // request here.
   [[EarlGrey selectElementWithMatcher:OmniboxText(_testURL2.GetContent())]
       assertWithMatcher:grey_notNil()];
 
@@ -432,8 +432,8 @@
   // even though URL1 is a pending URL.
   [[EarlGrey selectElementWithMatcher:chrome_test_util::BackButton()]
       performAction:grey_tap()];
-  GREYAssert([self waitForServerToReceiveRequestWithURL:_testURL1],
-             @"Last request URL: %@", self.lastRequestURLSpec);
+  // TODO(crbug.com/724560): Re-evaluate if necessary to check receiving URL1
+  // request here.
   [[EarlGrey selectElementWithMatcher:OmniboxText(_testURL2.GetContent())]
       assertWithMatcher:grey_notNil()];
 
diff --git a/ios/clean/chrome/browser/ui/toolbar/toolbar_coordinator.mm b/ios/clean/chrome/browser/ui/toolbar/toolbar_coordinator.mm
index 52845a7..8b892dcc 100644
--- a/ios/clean/chrome/browser/ui/toolbar/toolbar_coordinator.mm
+++ b/ios/clean/chrome/browser/ui/toolbar/toolbar_coordinator.mm
@@ -113,6 +113,7 @@
       [[ToolsMenuConfiguration alloc] initWithDisplayView:nil];
   menuConfiguration.inTabSwitcher = NO;
   toolsCoordinator.toolsMenuConfiguration = menuConfiguration;
+  toolsCoordinator.webState = self.webState;
   [toolsCoordinator start];
   self.toolsMenuCoordinator = toolsCoordinator;
 }
diff --git a/ios/clean/chrome/browser/ui/tools/BUILD.gn b/ios/clean/chrome/browser/ui/tools/BUILD.gn
index 7ffdbb6..ec73e9bf 100644
--- a/ios/clean/chrome/browser/ui/tools/BUILD.gn
+++ b/ios/clean/chrome/browser/ui/tools/BUILD.gn
@@ -27,6 +27,7 @@
     "//ios/shared/chrome/browser/ui/browser_list",
     "//ios/shared/chrome/browser/ui/coordinators",
     "//ios/shared/chrome/browser/ui/tools_menu",
+    "//ios/web",
     "//ui/base",
   ]
 }
@@ -69,9 +70,13 @@
   deps = [
     ":tools",
     ":tools_ui",
+    "//base",
     "//base/test:test_support",
     "//ios/chrome/test/base",
+    "//ios/shared/chrome/browser/ui/toolbar:test_support",
     "//ios/shared/chrome/browser/ui/tools_menu",
+    "//ios/web",
+    "//ios/web:test_support",
     "//testing/gtest",
     "//third_party/ocmock",
   ]
diff --git a/ios/clean/chrome/browser/ui/tools/menu_view_controller.mm b/ios/clean/chrome/browser/ui/tools/menu_view_controller.mm
index ef10a23..81e8c123 100644
--- a/ios/clean/chrome/browser/ui/tools/menu_view_controller.mm
+++ b/ios/clean/chrome/browser/ui/tools/menu_view_controller.mm
@@ -83,9 +83,6 @@
   self.menuScrollView.translatesAutoresizingMaskIntoConstraints = NO;
   [self.view addSubview:self.menuScrollView];
 
-  // PLACEHOLDER: Hardcoded value until the mediator observes the Webstate.
-  self.currentPageLoading = NO;
-
   [self setupCloseMenuButton];
   [self setupMenuStackView];
   [self setupConstraints];
@@ -253,4 +250,17 @@
   self.displayOverflowControls = displayOverflowControls;
 }
 
+- (void)setIsLoading:(BOOL)isLoading {
+  self.currentPageLoading = isLoading;
+}
+
+- (void)setCurrentPageLoading:(BOOL)currentPageLoading {
+  _currentPageLoading = currentPageLoading;
+  // If the OverflowButtons have been initialized update their visibility.
+  if (self.toolbarOverflowStackView) {
+    self.toolbarOverflowStackView.reloadButton.hidden = currentPageLoading;
+    self.toolbarOverflowStackView.stopButton.hidden = !currentPageLoading;
+  }
+}
+
 @end
diff --git a/ios/clean/chrome/browser/ui/tools/tools_consumer.h b/ios/clean/chrome/browser/ui/tools/tools_consumer.h
index 7855f90..eba8519 100644
--- a/ios/clean/chrome/browser/ui/tools/tools_consumer.h
+++ b/ios/clean/chrome/browser/ui/tools/tools_consumer.h
@@ -17,6 +17,8 @@
 // Sets a flag so the consumer knows if it should display the Menu overflow
 // controls.
 - (void)setDisplayOverflowControls:(BOOL)displayOverflowControls;
+// Updates the tools menu overflow controls with the current loading state.
+- (void)setIsLoading:(BOOL)isLoading;
 @end
 
 #endif  // IOS_CLEAN_CHROME_BROWSER_UI_TOOLS_TOOLS_CONSUMER_H_
diff --git a/ios/clean/chrome/browser/ui/tools/tools_coordinator.h b/ios/clean/chrome/browser/ui/tools/tools_coordinator.h
index 457392d6..b7b89fe 100644
--- a/ios/clean/chrome/browser/ui/tools/tools_coordinator.h
+++ b/ios/clean/chrome/browser/ui/tools/tools_coordinator.h
@@ -8,11 +8,18 @@
 #import "ios/shared/chrome/browser/ui/coordinators/browser_coordinator.h"
 
 @class ToolsMenuConfiguration;
+namespace web {
+class WebState;
+}
 
 // Coordinator that shows an inteface for the user to select a
 // tool or action to use.
 @interface ToolsCoordinator : BrowserCoordinator
-@property(nonatomic, strong) ToolsMenuConfiguration* toolsMenuConfiguration;
+// The current Toolbar configuration for this coordinator.
+@property(nonatomic, strong, nonnull)
+    ToolsMenuConfiguration* toolsMenuConfiguration;
+// The web state this ToolbarCoordinator is handling.
+@property(nonatomic, assign, nullable) web::WebState* webState;
 @end
 
 #endif  // IOS_CLEAN_CHROME_BROWSER_UI_TOOLS_TOOLS_COORDINATOR_H_
diff --git a/ios/clean/chrome/browser/ui/tools/tools_coordinator.mm b/ios/clean/chrome/browser/ui/tools/tools_coordinator.mm
index 5e13f6d4..bc1c573 100644
--- a/ios/clean/chrome/browser/ui/tools/tools_coordinator.mm
+++ b/ios/clean/chrome/browser/ui/tools/tools_coordinator.mm
@@ -23,6 +23,7 @@
 @synthesize viewController = _viewController;
 @synthesize mediator = _mediator;
 @synthesize toolsMenuConfiguration = _toolsMenuConfiguration;
+@synthesize webState = _webState;
 
 #pragma mark - BrowserCoordinator
 
@@ -33,10 +34,22 @@
   self.viewController.dispatcher = static_cast<id>(self.browser->dispatcher());
   self.mediator =
       [[ToolsMediator alloc] initWithConsumer:self.viewController
-                             andConfiguration:self.toolsMenuConfiguration];
+                                configuration:self.toolsMenuConfiguration];
+  if (self.webState) {
+    self.mediator.webState = self.webState;
+  }
   [super start];
 }
 
+#pragma mark - Setters
+
+- (void)setWebState:(web::WebState*)webState {
+  _webState = webState;
+  if (self.mediator) {
+    self.mediator.webState = self.webState;
+  }
+}
+
 #pragma mark - UIViewControllerTransitioningDelegate
 
 - (id<UIViewControllerAnimatedTransitioning>)
diff --git a/ios/clean/chrome/browser/ui/tools/tools_mediator.h b/ios/clean/chrome/browser/ui/tools/tools_mediator.h
index d13f54d9..de0fefa8 100644
--- a/ios/clean/chrome/browser/ui/tools/tools_mediator.h
+++ b/ios/clean/chrome/browser/ui/tools/tools_mediator.h
@@ -9,14 +9,22 @@
 
 @protocol ToolsConsumer;
 @class ToolsMenuConfiguration;
+namespace web {
+class WebState;
+}
 
 // A mediator object that sets a ToolsMenuVC appeareance based on various data
 // sources.
 @interface ToolsMediator : NSObject
-- (instancetype)initWithConsumer:(id<ToolsConsumer>)consumer
-                andConfiguration:(ToolsMenuConfiguration*)menuConfiguration
+- (nullable instancetype)initWithConsumer:(nonnull id<ToolsConsumer>)consumer
+                            configuration:(nonnull ToolsMenuConfiguration*)
+                                              menuConfiguration
     NS_DESIGNATED_INITIALIZER;
-- (instancetype)init NS_UNAVAILABLE;
+- (nullable instancetype)init NS_UNAVAILABLE;
+
+// The WebState whose properties this object mediates. This can change during
+// the lifetime of this object and may be null.
+@property(nonatomic, assign, nullable) web::WebState* webState;
 @end
 
 #endif  // IOS_CLEAN_CHROME_BROWSER_UI_TOOLS_TOOLS_MEDIATOR_H_
diff --git a/ios/clean/chrome/browser/ui/tools/tools_mediator.mm b/ios/clean/chrome/browser/ui/tools/tools_mediator.mm
index 2153e22..0c80ca8 100644
--- a/ios/clean/chrome/browser/ui/tools/tools_mediator.mm
+++ b/ios/clean/chrome/browser/ui/tools/tools_mediator.mm
@@ -5,17 +5,20 @@
 #import "ios/clean/chrome/browser/ui/tools/tools_mediator.h"
 
 #include "base/macros.h"
+#include "base/memory/ptr_util.h"
 #import "ios/clean/chrome/browser/ui/tools/tools_consumer.h"
 #import "ios/clean/chrome/browser/ui/tools/tools_menu_item.h"
 #import "ios/clean/chrome/browser/ui/tools/tools_menu_model.h"
 #import "ios/shared/chrome/browser/ui/tools_menu/tools_menu_configuration.h"
+#include "ios/web/public/web_state/web_state.h"
+#import "ios/web/public/web_state/web_state_observer_bridge.h"
 #include "ui/base/l10n/l10n_util.h"
 
 #if !defined(__has_feature) || !__has_feature(objc_arc)
 #error "This file requires ARC support."
 #endif
 
-@interface ToolsMediator ()
+@interface ToolsMediator ()<CRWWebStateObserver>
 @property(nonatomic, strong) id<ToolsConsumer> consumer;
 @property(nonatomic, strong) ToolsMenuConfiguration* toolsMenuConfiguration;
 @property(nonatomic, strong) NSMutableArray* menuItems;
@@ -25,17 +28,19 @@
 // Checks if a specific Menu Item should be visible for the current
 // configuration.
 - (BOOL)itemIsVisibleForCurrentConfiguration:(const MenuModelItem)modelItem;
-
 @end
 
-@implementation ToolsMediator
+@implementation ToolsMediator {
+  std::unique_ptr<web::WebStateObserverBridge> _webStateObserver;
+}
 
 @synthesize consumer = _consumer;
 @synthesize toolsMenuConfiguration = _toolsMenuConfiguration;
 @synthesize menuItems = _menuItems;
+@synthesize webState = _webState;
 
 - (instancetype)initWithConsumer:(id<ToolsConsumer>)consumer
-                andConfiguration:(ToolsMenuConfiguration*)menuConfiguration {
+                   configuration:(ToolsMenuConfiguration*)menuConfiguration {
   self = [super init];
   if (self) {
     self.toolsMenuConfiguration = menuConfiguration;
@@ -44,16 +49,37 @@
   return self;
 }
 
+#pragma mark - Setters
+
 - (void)setConsumer:(id<ToolsConsumer>)consumer {
   _consumer = consumer;
-
   [self populateMenuItems];
-
   [_consumer setToolsMenuItems:self.menuItems];
   [_consumer
       setDisplayOverflowControls:!self.toolsMenuConfiguration.isInTabSwitcher];
 }
 
+- (void)setWebState:(web::WebState*)webState {
+  _webState = webState;
+  // In the tab switcher, there's no overflow controls to update, so the
+  // WebState isn't observed.
+  if (!self.toolsMenuConfiguration.isInTabSwitcher) {
+    _webStateObserver =
+        base::MakeUnique<web::WebStateObserverBridge>(_webState, self);
+    [self.consumer setIsLoading:self.webState->IsLoading()];
+  }
+}
+
+#pragma mark - CRWWebStateObserver
+
+- (void)webStateDidStartLoading:(web::WebState*)webState {
+  [self.consumer setIsLoading:self.webState->IsLoading()];
+}
+
+- (void)webStateDidStopLoading:(web::WebState*)webState {
+  [self.consumer setIsLoading:self.webState->IsLoading()];
+}
+
 #pragma mark - Private Methods
 
 - (void)populateMenuItems {
diff --git a/ios/clean/chrome/browser/ui/tools/tools_mediator_unittest.mm b/ios/clean/chrome/browser/ui/tools/tools_mediator_unittest.mm
index 0d94cd5..06e1434 100644
--- a/ios/clean/chrome/browser/ui/tools/tools_mediator_unittest.mm
+++ b/ios/clean/chrome/browser/ui/tools/tools_mediator_unittest.mm
@@ -4,10 +4,14 @@
 
 #import "ios/clean/chrome/browser/ui/tools/tools_mediator.h"
 
+#include "base/memory/ptr_util.h"
 #import "ios/clean/chrome/browser/ui/tools/tools_consumer.h"
 #import "ios/clean/chrome/browser/ui/tools/tools_mediator_private.h"
 #import "ios/clean/chrome/browser/ui/tools/tools_menu_item.h"
+#import "ios/shared/chrome/browser/ui/toolbar/toolbar_test_util.h"
 #import "ios/shared/chrome/browser/ui/tools_menu/tools_menu_configuration.h"
+#import "ios/web/public/test/fakes/test_web_state.h"
+#import "ios/web/public/web_state/web_state_observer_bridge.h"
 #include "testing/gtest_mac.h"
 #include "testing/platform_test.h"
 #import "third_party/ocmock/OCMock/OCMock.h"
@@ -20,84 +24,152 @@
 namespace {
 
 class ToolsMediatorTest : public PlatformTest {
+ public:
+  ToolsMediatorTest()
+      : consumer_(OCMProtocolMock(@protocol(ToolsConsumer))),
+        configuration_(
+            [[ToolsMenuConfiguration alloc] initWithDisplayView:nil]),
+        navigation_manager(base::MakeUnique<ToolbarTestNavigationManager>()) {
+    navigation_manager_ = navigation_manager.get();
+    test_web_state_.SetNavigationManager(std::move(navigation_manager));
+  }
+
  protected:
   ToolsMediator* mediator_;
+  id consumer_;
+  ToolsMenuConfiguration* configuration_;
+  ToolbarTestWebState test_web_state_;
+  ToolbarTestNavigationManager* navigation_manager_;
+
+ private:
+  std::unique_ptr<ToolbarTestNavigationManager> navigation_manager;
 };
 
 TEST_F(ToolsMediatorTest, TestShowOverFlowControls) {
-  id consumer = OCMProtocolMock(@protocol(ToolsConsumer));
-  id configuration = OCMClassMock([ToolsMenuConfiguration class]);
-  OCMStub([configuration isInTabSwitcher]).andReturn(YES);
+  configuration_.inTabSwitcher = YES;
+  mediator_ = [[ToolsMediator alloc] initWithConsumer:consumer_
+                                        configuration:configuration_];
 
-  mediator_ = [[ToolsMediator alloc] initWithConsumer:consumer
-                                     andConfiguration:configuration];
-
-  [[consumer verify] setToolsMenuItems:[OCMArg any]];
-  [[consumer verify] setDisplayOverflowControls:NO];
+  [[consumer_ verify] setToolsMenuItems:[OCMArg any]];
+  [[consumer_ verify] setDisplayOverflowControls:NO];
 }
 
 TEST_F(ToolsMediatorTest, TestHideOverFlowControls) {
-  id consumer = OCMProtocolMock(@protocol(ToolsConsumer));
-  id configuration = OCMClassMock([ToolsMenuConfiguration class]);
-  OCMStub([configuration isInTabSwitcher]).andReturn(NO);
+  configuration_.inTabSwitcher = NO;
 
-  mediator_ = [[ToolsMediator alloc] initWithConsumer:consumer
-                                     andConfiguration:configuration];
+  mediator_ = [[ToolsMediator alloc] initWithConsumer:consumer_
+                                        configuration:configuration_];
 
-  [[consumer verify] setToolsMenuItems:[OCMArg any]];
-  [[consumer verify] setDisplayOverflowControls:YES];
+  [[consumer_ verify] setToolsMenuItems:[OCMArg any]];
+  [[consumer_ verify] setDisplayOverflowControls:YES];
 }
 
 TEST_F(ToolsMediatorTest, TestMenuItemsForNonTabSwitcherNonIncognito) {
-  id consumer = OCMProtocolMock(@protocol(ToolsConsumer));
-  id configuration = OCMClassMock([ToolsMenuConfiguration class]);
-  OCMStub([configuration isInTabSwitcher]).andReturn(NO);
-  OCMStub([configuration isInIncognito]).andReturn(NO);
+  configuration_.inTabSwitcher = NO;
+  configuration_.inIncognito = NO;
 
-  mediator_ = [[ToolsMediator alloc] initWithConsumer:consumer
-                                     andConfiguration:configuration];
+  mediator_ = [[ToolsMediator alloc] initWithConsumer:consumer_
+                                        configuration:configuration_];
 
   EXPECT_EQ(7ul, [mediator_.menuItemsArray count]);
 }
 
 TEST_F(ToolsMediatorTest, TestMenuItemsForNonTabSwitcherIncognito) {
-  id consumer = OCMProtocolMock(@protocol(ToolsConsumer));
-  id configuration = OCMClassMock([ToolsMenuConfiguration class]);
-  OCMStub([configuration isInTabSwitcher]).andReturn(NO);
-  OCMStub([configuration isInIncognito]).andReturn(YES);
+  configuration_.inTabSwitcher = NO;
+  configuration_.inIncognito = YES;
 
-  mediator_ = [[ToolsMediator alloc] initWithConsumer:consumer
-                                     andConfiguration:configuration];
+  mediator_ = [[ToolsMediator alloc] initWithConsumer:consumer_
+                                        configuration:configuration_];
 
   EXPECT_EQ(7ul, [mediator_.menuItemsArray count]);
 }
 
-TEST_F(ToolsMediatorTest, TestMenuItemsForTabSwitcherNonIncognito) {
-  id consumer = OCMProtocolMock(@protocol(ToolsConsumer));
-  id configuration = OCMClassMock([ToolsMenuConfiguration class]);
-  OCMStub([configuration isInTabSwitcher]).andReturn(YES);
-  OCMStub([configuration isInIncognito]).andReturn(YES);
+TEST_F(ToolsMediatorTest, TestMenuItemsForTabSwitcherIncognito) {
+  configuration_.inTabSwitcher = YES;
+  configuration_.inIncognito = YES;
 
-  mediator_ = [[ToolsMediator alloc] initWithConsumer:consumer
-                                     andConfiguration:configuration];
+  mediator_ = [[ToolsMediator alloc] initWithConsumer:consumer_
+                                        configuration:configuration_];
 
   ToolsMenuItem* closeAllTabsItem = mediator_.menuItemsArray[2];
   EXPECT_NSEQ(@"Close All Incognito Tabs", closeAllTabsItem.title);
   EXPECT_EQ(5ul, [mediator_.menuItemsArray count]);
 }
 
-TEST_F(ToolsMediatorTest, TestMenuItemsForTabSwitcherIncognito) {
-  id consumer = OCMProtocolMock(@protocol(ToolsConsumer));
-  id configuration = OCMClassMock([ToolsMenuConfiguration class]);
-  OCMStub([configuration isInTabSwitcher]).andReturn(YES);
-  OCMStub([configuration isInIncognito]).andReturn(NO);
+TEST_F(ToolsMediatorTest, TestMenuItemsForTabSwitcherNonIncognito) {
+  configuration_.inTabSwitcher = YES;
+  configuration_.inIncognito = NO;
 
-  mediator_ = [[ToolsMediator alloc] initWithConsumer:consumer
-                                     andConfiguration:configuration];
+  mediator_ = [[ToolsMediator alloc] initWithConsumer:consumer_
+                                        configuration:configuration_];
 
   ToolsMenuItem* closeAllTabsItem = mediator_.menuItemsArray[2];
   EXPECT_NSEQ(@"Close All Tabs", closeAllTabsItem.title);
   EXPECT_EQ(5ul, [mediator_.menuItemsArray count]);
 }
 
+TEST_F(ToolsMediatorTest, TestDontUpdateConsumerLoadingState) {
+  configuration_.inTabSwitcher = NO;
+  [[consumer_ reject] setIsLoading:YES];
+  [[consumer_ reject] setIsLoading:NO];
+
+  mediator_ = [[ToolsMediator alloc] initWithConsumer:consumer_
+                                        configuration:configuration_];
+}
+
+TEST_F(ToolsMediatorTest, TestDontUpdateConsumerLoadingStateInTabSwitcher) {
+  configuration_.inTabSwitcher = YES;
+  [[consumer_ reject] setIsLoading:YES];
+  [[consumer_ reject] setIsLoading:NO];
+
+  mediator_ = [[ToolsMediator alloc] initWithConsumer:consumer_
+                                        configuration:configuration_];
+}
+
+TEST_F(ToolsMediatorTest, TestUpdateConsumerLoadingState) {
+  configuration_.inTabSwitcher = NO;
+  mediator_ = [[ToolsMediator alloc] initWithConsumer:consumer_
+                                        configuration:configuration_];
+  test_web_state_.SetLoading(false);
+  mediator_.webState = &test_web_state_;
+  [[consumer_ verify] setIsLoading:NO];
+  test_web_state_.SetLoading(true);
+  [[consumer_ verify] setIsLoading:YES];
+}
+
+TEST_F(ToolsMediatorTest, TestUpdateConsumerLoadingStateInverse) {
+  configuration_.inTabSwitcher = NO;
+  mediator_ = [[ToolsMediator alloc] initWithConsumer:consumer_
+                                        configuration:configuration_];
+  test_web_state_.SetLoading(true);
+  mediator_.webState = &test_web_state_;
+  [[consumer_ verify] setIsLoading:YES];
+  test_web_state_.SetLoading(false);
+  [[consumer_ verify] setIsLoading:NO];
+}
+
+TEST_F(ToolsMediatorTest, TestUpdateConsumerLoadingStateInTabSwitcher) {
+  configuration_.inTabSwitcher = YES;
+  [[consumer_ reject] setIsLoading:NO];
+  [[consumer_ reject] setIsLoading:YES];
+
+  mediator_ = [[ToolsMediator alloc] initWithConsumer:consumer_
+                                        configuration:configuration_];
+  test_web_state_.SetLoading(false);
+  mediator_.webState = &test_web_state_;
+  test_web_state_.SetLoading(true);
+}
+
+TEST_F(ToolsMediatorTest, TestUpdateConsumerLoadingStateInverseInTabSwitcher) {
+  configuration_.inTabSwitcher = YES;
+  [[consumer_ reject] setIsLoading:NO];
+  [[consumer_ reject] setIsLoading:YES];
+
+  mediator_ = [[ToolsMediator alloc] initWithConsumer:consumer_
+                                        configuration:configuration_];
+  test_web_state_.SetLoading(true);
+  mediator_.webState = &test_web_state_;
+  test_web_state_.SetLoading(false);
+}
+
 }  // namespace
diff --git a/mojo/public/cpp/system/handle.h b/mojo/public/cpp/system/handle.h
index 781944eb..aef3c23 100644
--- a/mojo/public/cpp/system/handle.h
+++ b/mojo/public/cpp/system/handle.h
@@ -39,9 +39,9 @@
 // |ScopedHandleBase<HandleType>| is a templated scoped wrapper, for the handle
 // types above (in the same sense that a C++11 |unique_ptr<T>| is a scoped
 // wrapper for a |T*|). It provides lifetime management, closing its owned
-// handle on destruction. It also provides (emulated) move semantics, again
-// along the lines of C++11's |unique_ptr| (and exactly like Chromium's
-// |scoped_ptr|).
+// handle on destruction. It also provides move semantics, again along the lines
+// of C++11's |unique_ptr|. A moved-from |ScopedHandleBase<HandleType>| sets its
+// handle value to MOJO_HANDLE_INVALID.
 //
 // |ScopedHandle| is just (a typedef of) a |ScopedHandleBase<Handle>|.
 // Similarly, |ScopedMessagePipeHandle| is just a
diff --git a/net/dns/host_cache.cc b/net/dns/host_cache.cc
index 0026c02..c1dbbda9 100644
--- a/net/dns/host_cache.cc
+++ b/net/dns/host_cache.cc
@@ -4,15 +4,19 @@
 
 #include "net/dns/host_cache.h"
 
+#include <utility>
+
 #include "base/logging.h"
 #include "base/memory/ptr_util.h"
 #include "base/metrics/field_trial.h"
 #include "base/metrics/histogram_macros.h"
 #include "base/strings/string_number_conversions.h"
 #include "base/trace_event/trace_event.h"
+#include "base/values.h"
 #include "net/base/net_errors.h"
 #include "net/base/trace_constants.h"
 #include "net/dns/dns_util.h"
+#include "net/log/net_log.h"
 
 namespace net {
 
@@ -27,6 +31,31 @@
 #define CACHE_HISTOGRAM_ENUM(name, value, max) \
   UMA_HISTOGRAM_ENUMERATION("DNS.HostCache." name, value, max)
 
+// String constants for dictionary keys.
+const char kHostnameKey[] = "hostname";
+const char kAddressFamilyKey[] = "address_family";
+const char kFlagsKey[] = "flags";
+const char kExpirationKey[] = "expiration";
+const char kTtlKey[] = "ttl";
+const char kNetworkChangesKey[] = "network_changes";
+const char kErrorKey[] = "error";
+const char kAddressesKey[] = "addresses";
+
+bool AddressListFromListValue(base::ListValue* value, AddressList* list) {
+  list->clear();
+  for (base::ListValue::const_iterator it = value->begin(); it != value->end();
+       it++) {
+    IPAddress address;
+    std::string addr_string;
+    if (!it->GetAsString(&addr_string) ||
+        !address.AssignFromIPLiteral(addr_string)) {
+      return false;
+    }
+    list->push_back(IPEndPoint(address, 0));
+  }
+  return true;
+}
+
 }  // namespace
 
 // Used in histograms; do not modify existing values.
@@ -80,6 +109,18 @@
       total_hits_(0),
       stale_hits_(0) {}
 
+HostCache::Entry::Entry(int error,
+                        const AddressList& addresses,
+                        base::TimeTicks expires,
+                        int network_changes)
+    : error_(error),
+      addresses_(addresses),
+      ttl_(base::TimeDelta::FromSeconds(-1)),
+      expires_(expires),
+      network_changes_(network_changes),
+      total_hits_(0),
+      stale_hits_(0) {}
+
 bool HostCache::Entry::IsStale(base::TimeTicks now, int network_changes) const {
   EntryStaleness stale;
   stale.expired_by = now - expires_;
@@ -182,10 +223,13 @@
     RecordSet(SET_INSERT, now, nullptr, entry);
   }
 
+  AddEntry(Key(key), Entry(entry, now, ttl, network_changes_));
+}
+
+void HostCache::AddEntry(const Key& key, const Entry& entry) {
   DCHECK_GT(max_entries_, size());
   DCHECK_EQ(0u, entries_.count(key));
-  entries_.insert(
-      std::make_pair(Key(key), Entry(entry, now, ttl, network_changes_)));
+  entries_.insert(std::make_pair(key, entry));
   DCHECK_GE(max_entries_, size());
 }
 
@@ -221,6 +265,110 @@
   }
 }
 
+std::unique_ptr<base::ListValue> HostCache::GetAsListValue(
+    bool include_staleness) const {
+  std::unique_ptr<base::ListValue> entry_list(new base::ListValue());
+
+  for (const auto& pair : entries_) {
+    const Key& key = pair.first;
+    const Entry& entry = pair.second;
+
+    std::unique_ptr<base::DictionaryValue> entry_dict(
+        new base::DictionaryValue());
+
+    entry_dict->SetString(kHostnameKey, key.hostname);
+    entry_dict->SetInteger(kAddressFamilyKey,
+                           static_cast<int>(key.address_family));
+    entry_dict->SetInteger(kFlagsKey, key.host_resolver_flags);
+
+    if (include_staleness) {
+      entry_dict->SetString(kExpirationKey,
+                            NetLog::TickCountToString(entry.expires()));
+      entry_dict->SetInteger(kTtlKey, entry.ttl().InMilliseconds());
+      entry_dict->SetInteger(kNetworkChangesKey, entry.network_changes());
+    } else {
+      // Convert expiration time in TimeTicks to Time for serialization, using a
+      // string because base::Value doesn't handle 64-bit integers.
+      base::Time expiration_time =
+          base::Time::Now() - (base::TimeTicks::Now() - entry.expires());
+      entry_dict->SetString(
+          kExpirationKey,
+          base::Int64ToString(expiration_time.ToInternalValue()));
+    }
+
+    if (entry.error() != OK) {
+      entry_dict->SetInteger(kErrorKey, entry.error());
+    } else {
+      const AddressList& addresses = entry.addresses();
+      // Append all of the resolved addresses.
+      auto addresses_value = base::MakeUnique<base::ListValue>();
+      for (size_t i = 0; i < addresses.size(); ++i)
+        addresses_value->AppendString(addresses[i].ToStringWithoutPort());
+      entry_dict->SetList(kAddressesKey, std::move(addresses_value));
+    }
+
+    entry_list->Append(std::move(entry_dict));
+  }
+
+  return entry_list;
+}
+
+// TODO(mgersh): Add histograms to track failures.
+bool HostCache::RestoreFromListValue(base::ListValue& old_cache) {
+  for (base::ListValue::iterator it = old_cache.begin(); it != old_cache.end();
+       it++) {
+    base::DictionaryValue* entry_dict;
+    if (!it->GetAsDictionary(&entry_dict))
+      return false;
+
+    std::string hostname;
+    int address_family;
+    HostResolverFlags flags;
+    int error = OK;
+    std::string expiration;
+    base::ListValue empty_list;
+    base::ListValue* addresses_value = &empty_list;
+    AddressList address_list;
+
+    if (!entry_dict->GetString(kHostnameKey, &hostname) ||
+        !entry_dict->GetInteger(kFlagsKey, &flags) ||
+        !entry_dict->GetInteger(kAddressFamilyKey, &address_family) ||
+        !entry_dict->GetString(kExpirationKey, &expiration)) {
+      return false;
+    }
+
+    // Only one of these fields should be in the dictionary.
+    if (!entry_dict->GetInteger(kErrorKey, &error) &&
+        !entry_dict->GetList(kAddressesKey, &addresses_value)) {
+      return false;
+    }
+
+    int64_t time_internal;
+    if (!base::StringToInt64(expiration, &time_internal))
+      return false;
+
+    base::TimeTicks expiration_time =
+        base::TimeTicks::Now() -
+        (base::Time::Now() - base::Time::FromInternalValue(time_internal));
+
+    Key key(hostname, static_cast<AddressFamily>(address_family), flags);
+    if (error == OK &&
+        !AddressListFromListValue(addresses_value, &address_list)) {
+      return false;
+    }
+
+    // If the key is already in the cache, assume it's more recent and don't
+    // replace the entry. If the cache is already full, don't bother
+    // prioritizing what to evict, just stop restoring.
+    auto found = entries_.find(key);
+    if (found == entries_.end() && size() < max_entries_) {
+      AddEntry(key, Entry(error, address_list, expiration_time,
+                          network_changes_ - 1));
+    }
+  }
+  return true;
+}
+
 size_t HostCache::size() const {
   DCHECK(CalledOnValidThread());
   return entries_.size();
diff --git a/net/dns/host_cache.h b/net/dns/host_cache.h
index 37cf204..c0ba456 100644
--- a/net/dns/host_cache.h
+++ b/net/dns/host_cache.h
@@ -8,6 +8,7 @@
 #include <stddef.h>
 
 #include <functional>
+#include <map>
 #include <memory>
 #include <string>
 #include <tuple>
@@ -22,6 +23,10 @@
 #include "net/base/net_export.h"
 #include "net/dns/dns_util.h"
 
+namespace base {
+class ListValue;
+}
+
 namespace net {
 
 // Cache used by HostResolver to map hostnames to their resolved result.
@@ -90,6 +95,11 @@
           base::TimeDelta ttl,
           int network_changes);
 
+    Entry(int error,
+          const AddressList& addresses,
+          base::TimeTicks expires,
+          int network_changes);
+
     int total_hits() const { return total_hits_; }
     int stale_hits() const { return stale_hits_; }
 
@@ -155,6 +165,14 @@
   void ClearForHosts(
       const base::Callback<bool(const std::string&)>& host_filter);
 
+  // Returns the contents of the cache represented as a base::ListValue for
+  // serialization.
+  std::unique_ptr<base::ListValue> GetAsListValue(bool include_staleness) const;
+  // Takes a base::ListValue representing cache entries and stores them in the
+  // cache, skipping any that already have entries. Returns true on success,
+  // false on failure.
+  bool RestoreFromListValue(base::ListValue& old_cache);
+
   // Returns the number of entries in the cache.
   size_t size() const;
 
@@ -191,6 +209,8 @@
   bool caching_is_disabled() const { return max_entries_ == 0; }
 
   void EvictOneEntry(base::TimeTicks now);
+  // Helper to insert an Entry into the cache.
+  void AddEntry(const Key& key, const Entry& entry);
 
   // Map from hostname (presumably in lowercase canonicalized format) to
   // a resolved result entry.
diff --git a/net/dns/host_cache_unittest.cc b/net/dns/host_cache_unittest.cc
index 5f35f2e..15a43e3c 100644
--- a/net/dns/host_cache_unittest.cc
+++ b/net/dns/host_cache_unittest.cc
@@ -12,6 +12,7 @@
 #include "base/stl_util.h"
 #include "base/strings/string_util.h"
 #include "base/strings/stringprintf.h"
+#include "base/values.h"
 #include "net/base/net_errors.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
@@ -640,4 +641,115 @@
   }
 }
 
+TEST(HostCacheTest, SerializeAndDeserialize) {
+  const base::TimeDelta kTTL = base::TimeDelta::FromSeconds(10);
+
+  HostCache cache(kMaxCacheEntries);
+
+  // Start at t=0.
+  base::TimeTicks now;
+
+  HostCache::Key key1 = Key("foobar.com");
+  HostCache::Key key2 = Key("foobar2.com");
+  HostCache::Key key3 = Key("foobar3.com");
+  HostCache::Key key4 = Key("foobar4.com");
+
+  IPAddress address_ipv4(1, 2, 3, 4);
+  IPAddress address_ipv6(0x20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
+  IPEndPoint endpoint_ipv4(address_ipv4, 0);
+  IPEndPoint endpoint_ipv6(address_ipv6, 0);
+
+  HostCache::Entry entry1 = HostCache::Entry(OK, AddressList(endpoint_ipv4));
+  AddressList addresses2 = AddressList(endpoint_ipv6);
+  addresses2.push_back(endpoint_ipv4);
+  HostCache::Entry entry2 = HostCache::Entry(OK, addresses2);
+  HostCache::Entry entry3 = HostCache::Entry(OK, AddressList(endpoint_ipv6));
+  HostCache::Entry entry4 = HostCache::Entry(OK, AddressList(endpoint_ipv4));
+
+  EXPECT_EQ(0u, cache.size());
+
+  // Add an entry for "foobar.com" at t=0.
+  EXPECT_FALSE(cache.Lookup(key1, now));
+  cache.Set(key1, entry1, now, kTTL);
+  EXPECT_TRUE(cache.Lookup(key1, now));
+  EXPECT_TRUE(cache.Lookup(key1, now)->error() == entry1.error());
+
+  EXPECT_EQ(1u, cache.size());
+
+  // Advance to t=5.
+  now += base::TimeDelta::FromSeconds(5);
+
+  // Add entries for "foobar2.com" and "foobar3.com" at t=5.
+  EXPECT_FALSE(cache.Lookup(key2, now));
+  cache.Set(key2, entry2, now, kTTL);
+  EXPECT_TRUE(cache.Lookup(key2, now));
+  EXPECT_EQ(2u, cache.size());
+
+  EXPECT_FALSE(cache.Lookup(key3, now));
+  cache.Set(key3, entry3, now, kTTL);
+  EXPECT_TRUE(cache.Lookup(key3, now));
+  EXPECT_EQ(3u, cache.size());
+
+  // Advance to t=12, ansd serialize the cache.
+  now += base::TimeDelta::FromSeconds(7);
+
+  std::unique_ptr<base::ListValue> serialized_cache =
+      cache.GetAsListValue(/*include_staleness=*/false);
+  HostCache restored_cache(kMaxCacheEntries);
+
+  // Add entries for "foobar3.com" and "foobar4.com" to the cache before
+  // restoring it. The "foobar3.com" result is different from the original.
+  EXPECT_FALSE(restored_cache.Lookup(key3, now));
+  restored_cache.Set(key3, entry1, now, kTTL);
+  EXPECT_TRUE(restored_cache.Lookup(key3, now));
+  EXPECT_EQ(1u, restored_cache.size());
+
+  EXPECT_FALSE(restored_cache.Lookup(key4, now));
+  restored_cache.Set(key4, entry4, now, kTTL);
+  EXPECT_TRUE(restored_cache.Lookup(key4, now));
+  EXPECT_EQ(2u, restored_cache.size());
+
+  restored_cache.RestoreFromListValue(*serialized_cache);
+
+  HostCache::EntryStaleness stale;
+
+  // The "foobar.com" entry is stale due to both network changes and expiration
+  // time.
+  EXPECT_FALSE(restored_cache.Lookup(key1, now));
+  const HostCache::Entry* result1 =
+      restored_cache.LookupStale(key1, now, &stale);
+  EXPECT_TRUE(result1);
+  EXPECT_EQ(1u, result1->addresses().size());
+  EXPECT_EQ(address_ipv4, result1->addresses().front().address());
+  EXPECT_EQ(1, stale.network_changes);
+  // Time to TimeTicks conversion is fuzzy, so just check that expected and
+  // actual expiration times are close.
+  EXPECT_GT(base::TimeDelta::FromMilliseconds(1),
+            (base::TimeDelta::FromSeconds(2) - stale.expired_by).magnitude());
+
+  // The "foobar2.com" entry is stale only due to network changes.
+  EXPECT_FALSE(restored_cache.Lookup(key2, now));
+  const HostCache::Entry* result2 =
+      restored_cache.LookupStale(key2, now, &stale);
+  EXPECT_TRUE(result2);
+  EXPECT_EQ(2u, result2->addresses().size());
+  EXPECT_EQ(address_ipv6, result2->addresses().front().address());
+  EXPECT_EQ(address_ipv4, result2->addresses().back().address());
+  EXPECT_EQ(1, stale.network_changes);
+  EXPECT_GT(base::TimeDelta::FromMilliseconds(1),
+            (base::TimeDelta::FromSeconds(-3) - stale.expired_by).magnitude());
+
+  // The "foobar3.com" entry is the new one, not the restored one.
+  const HostCache::Entry* result3 = restored_cache.Lookup(key3, now);
+  EXPECT_TRUE(result3);
+  EXPECT_EQ(1u, result3->addresses().size());
+  EXPECT_EQ(address_ipv4, result3->addresses().front().address());
+
+  // The "foobar4.com" entry is still present and usable.
+  const HostCache::Entry* result4 = restored_cache.Lookup(key4, now);
+  EXPECT_TRUE(result4);
+  EXPECT_EQ(1u, result4->addresses().size());
+  EXPECT_EQ(address_ipv4, result4->addresses().front().address());
+}
+
 }  // namespace net
diff --git a/net/log/net_log_util.cc b/net/log/net_log_util.cc
index 85b5460..cc42645 100644
--- a/net/log/net_log_util.cc
+++ b/net/log/net_log_util.cc
@@ -384,38 +384,8 @@
                                   static_cast<int>(cache->max_entries()));
       cache_info_dict->SetInteger("network_changes", cache->network_changes());
 
-      base::ListValue* entry_list = new base::ListValue();
-
-      for (const auto& pair : cache->entries()) {
-        const HostCache::Key& key = pair.first;
-        const HostCache::Entry& entry = pair.second;
-
-        std::unique_ptr<base::DictionaryValue> entry_dict(
-            new base::DictionaryValue());
-
-        entry_dict->SetString("hostname", key.hostname);
-        entry_dict->SetInteger("address_family",
-                               static_cast<int>(key.address_family));
-        entry_dict->SetString("expiration",
-                              NetLog::TickCountToString(entry.expires()));
-        entry_dict->SetInteger("ttl", entry.ttl().InMilliseconds());
-        entry_dict->SetInteger("network_changes", entry.network_changes());
-
-        if (entry.error() != OK) {
-          entry_dict->SetInteger("error", entry.error());
-        } else {
-          const AddressList& addresses = entry.addresses();
-          // Append all of the resolved addresses.
-          base::ListValue* address_list = new base::ListValue();
-          for (size_t i = 0; i < addresses.size(); ++i)
-            address_list->AppendString(addresses[i].ToStringWithoutPort());
-          entry_dict->Set("addresses", address_list);
-        }
-
-        entry_list->Append(std::move(entry_dict));
-      }
-
-      cache_info_dict->Set("entries", entry_list);
+      cache_info_dict->Set("entries",
+                           cache->GetAsListValue(/*include_staleness=*/true));
       dict->Set("cache", cache_info_dict);
       net_info_dict->Set(NetInfoSourceToString(NET_INFO_HOST_RESOLVER),
                          std::move(dict));
diff --git a/net/quic/chromium/bidirectional_stream_quic_impl.cc b/net/quic/chromium/bidirectional_stream_quic_impl.cc
index e2301e7..8a714f0 100644
--- a/net/quic/chromium/bidirectional_stream_quic_impl.cc
+++ b/net/quic/chromium/bidirectional_stream_quic_impl.cc
@@ -98,8 +98,12 @@
 
   CreateSpdyHeadersFromHttpRequest(
       http_request_info, http_request_info.extra_headers, true, &headers);
+  // Sending the request might result in |this| being deleted.
+  auto guard = weak_factory_.GetWeakPtr();
   size_t headers_bytes_sent = stream_->WriteHeaders(
       std::move(headers), request_info_->end_stream_on_headers, nullptr);
+  if (!guard.get())
+    return;
   headers_bytes_sent_ += headers_bytes_sent;
   has_sent_headers_ = true;
 }
@@ -264,16 +268,12 @@
   DCHECK(rv == OK || !stream_);
   if (rv == OK) {
     stream_ = session_->ReleaseStream(this);
+
+    base::ThreadTaskRunnerHandle::Get()->PostTask(
+        FROM_HERE, base::Bind(&BidirectionalStreamQuicImpl::ReadInitialHeaders,
+                              weak_factory_.GetWeakPtr()));
+
     NotifyStreamReady();
-
-    rv = stream_->ReadInitialHeaders(
-        &initial_headers_,
-        base::Bind(&BidirectionalStreamQuicImpl::OnReadInitialHeadersComplete,
-                   weak_factory_.GetWeakPtr()));
-    if (rv == ERR_IO_PENDING)
-      return;
-
-    OnReadInitialHeadersComplete(rv);
   } else {
     NotifyError(rv);
   }
@@ -306,6 +306,16 @@
     delegate_->OnHeadersReceived(initial_headers_);
 }
 
+void BidirectionalStreamQuicImpl::ReadInitialHeaders() {
+  int rv = stream_->ReadInitialHeaders(
+      &initial_headers_,
+      base::Bind(&BidirectionalStreamQuicImpl::OnReadInitialHeadersComplete,
+                 weak_factory_.GetWeakPtr()));
+
+  if (rv != ERR_IO_PENDING)
+    OnReadInitialHeadersComplete(rv);
+}
+
 void BidirectionalStreamQuicImpl::ReadTrailingHeaders() {
   int rv = stream_->ReadTrailingHeaders(
       &trailing_headers_,
@@ -362,7 +372,11 @@
 
 void BidirectionalStreamQuicImpl::NotifyStreamReady() {
   if (send_request_headers_automatically_) {
+    // Sending the request might result in |this| being deleted.
+    auto guard = weak_factory_.GetWeakPtr();
     SendRequestHeaders();
+    if (!guard.get())
+      return;
   }
   if (delegate_)
     delegate_->OnStreamReady(has_sent_headers_);
diff --git a/net/quic/chromium/bidirectional_stream_quic_impl.h b/net/quic/chromium/bidirectional_stream_quic_impl.h
index 3b25309..36129e1 100644
--- a/net/quic/chromium/bidirectional_stream_quic_impl.h
+++ b/net/quic/chromium/bidirectional_stream_quic_impl.h
@@ -63,6 +63,7 @@
 
   void OnStreamReady(int rv);
   void OnSendDataComplete(int rv);
+  void ReadInitialHeaders();
   void OnReadInitialHeadersComplete(int rv);
   void ReadTrailingHeaders();
   void OnReadTrailingHeadersComplete(int rv);
diff --git a/net/quic/chromium/bidirectional_stream_quic_impl_unittest.cc b/net/quic/chromium/bidirectional_stream_quic_impl_unittest.cc
index 9eaa5452..5b6ecded 100644
--- a/net/quic/chromium/bidirectional_stream_quic_impl_unittest.cc
+++ b/net/quic/chromium/bidirectional_stream_quic_impl_unittest.cc
@@ -285,6 +285,7 @@
  public:
   // Specifies in which callback the stream can be deleted.
   enum Phase {
+    ON_STREAM_READY,
     ON_HEADERS_RECEIVED,
     ON_DATA_READ,
     ON_TRAILERS_RECEIVED,
@@ -295,13 +296,18 @@
       : TestDelegateBase(buf, buf_len), phase_(phase) {}
   ~DeleteStreamDelegate() override {}
 
+  void OnStreamReady(bool request_headers_sent) override {
+    TestDelegateBase::OnStreamReady(request_headers_sent);
+    if (phase_ == ON_STREAM_READY)
+      DeleteStream();
+  }
+
   void OnHeadersReceived(const SpdyHeaderBlock& response_headers) override {
     // Make a copy of |response_headers| before the stream is deleted, since
     // the headers are owned by the stream.
     SpdyHeaderBlock headers_copy = response_headers.Clone();
-    if (phase_ == ON_HEADERS_RECEIVED) {
+    if (phase_ == ON_HEADERS_RECEIVED)
       DeleteStream();
-    }
     TestDelegateBase::OnHeadersReceived(headers_copy);
   }
 
@@ -398,6 +404,11 @@
     writes_.push_back(PacketToWrite(SYNCHRONOUS, packet.release()));
   }
 
+  // Adds a write error to the list of expected writes.
+  void AddWriteError(IoMode mode, int rv) {
+    writes_.push_back(PacketToWrite(mode, rv));
+  }
+
   void ProcessPacket(std::unique_ptr<QuicReceivedPacket> packet) {
     connection_->ProcessUdpPacket(
         QuicSocketAddress(QuicSocketAddressImpl(self_addr_)),
@@ -594,20 +605,29 @@
 
   std::unique_ptr<QuicReceivedPacket> ConstructClientRstStreamPacket(
       QuicPacketNumber packet_number) {
-    return ConstructRstStreamCancelledPacket(packet_number, 0, &client_maker_);
+    return ConstructRstStreamCancelledPacket(packet_number, !kIncludeVersion, 0,
+                                             &client_maker_);
   }
 
   std::unique_ptr<QuicReceivedPacket> ConstructServerRstStreamPacket(
       QuicPacketNumber packet_number) {
-    return ConstructRstStreamCancelledPacket(packet_number, 0, &server_maker_);
+    return ConstructRstStreamCancelledPacket(packet_number, !kIncludeVersion, 0,
+                                             &server_maker_);
+  }
+
+  std::unique_ptr<QuicReceivedPacket> ConstructClientEarlyRstStreamPacket(
+      QuicPacketNumber packet_number) {
+    return ConstructRstStreamCancelledPacket(packet_number, kIncludeVersion, 0,
+                                             &client_maker_);
   }
 
   std::unique_ptr<QuicReceivedPacket> ConstructRstStreamCancelledPacket(
       QuicPacketNumber packet_number,
+      bool include_version,
       size_t bytes_written,
       QuicTestPacketMaker* maker) {
     std::unique_ptr<QuicReceivedPacket> packet(
-        maker->MakeRstPacket(packet_number, !kIncludeVersion, stream_id_,
+        maker->MakeRstPacket(packet_number, include_version, stream_id_,
                              QUIC_STREAM_CANCELLED, bytes_written));
     DVLOG(2) << "packet(" << packet_number << "): " << std::endl
              << QuicTextUtils::HexDump(packet->AsStringPiece());
@@ -1609,6 +1629,61 @@
             delegate->GetTotalReceivedBytes());
 }
 
+TEST_P(BidirectionalStreamQuicImplTest, SessionCloseDuringOnStreamReady) {
+  SetRequest("POST", "/", DEFAULT_PRIORITY);
+  QuicStreamOffset header_stream_offset = 0;
+  AddWrite(ConstructInitialSettingsPacket(1, &header_stream_offset));
+  AddWriteError(SYNCHRONOUS, ERR_CONNECTION_REFUSED);
+
+  Initialize();
+
+  BidirectionalStreamRequestInfo request;
+  request.method = "POST";
+  request.url = GURL("http://www.google.com/");
+  request.end_stream_on_headers = false;
+  request.priority = DEFAULT_PRIORITY;
+
+  scoped_refptr<IOBuffer> read_buffer(new IOBuffer(kReadBufferSize));
+  std::unique_ptr<DeleteStreamDelegate> delegate(new DeleteStreamDelegate(
+      read_buffer.get(), kReadBufferSize, DeleteStreamDelegate::ON_FAILED));
+  delegate->Start(&request, net_log().bound(), session()->CreateHandle());
+  ConfirmHandshake();
+  delegate->WaitUntilNextCallback();  // OnStreamReady
+
+  EXPECT_EQ(0, delegate->on_data_read_count());
+  EXPECT_EQ(0, delegate->on_data_sent_count());
+}
+
+TEST_P(BidirectionalStreamQuicImplTest, DeleteStreamDuringOnStreamReady) {
+  SetRequest("POST", "/", DEFAULT_PRIORITY);
+  size_t spdy_request_headers_frame_length;
+  QuicStreamOffset header_stream_offset = 0;
+  AddWrite(ConstructInitialSettingsPacket(1, &header_stream_offset));
+  AddWrite(ConstructRequestHeadersPacketInner(
+      2, GetNthClientInitiatedStreamId(0), !kFin, DEFAULT_PRIORITY,
+      &spdy_request_headers_frame_length, &header_stream_offset));
+  AddWrite(ConstructClientEarlyRstStreamPacket(3));
+
+  Initialize();
+
+  BidirectionalStreamRequestInfo request;
+  request.method = "POST";
+  request.url = GURL("http://www.google.com/");
+  request.end_stream_on_headers = false;
+  request.priority = DEFAULT_PRIORITY;
+
+  scoped_refptr<IOBuffer> read_buffer(new IOBuffer(kReadBufferSize));
+  std::unique_ptr<DeleteStreamDelegate> delegate(
+      new DeleteStreamDelegate(read_buffer.get(), kReadBufferSize,
+                               DeleteStreamDelegate::ON_STREAM_READY));
+  delegate->Start(&request, net_log().bound(), session()->CreateHandle());
+  ConfirmHandshake();
+  delegate->WaitUntilNextCallback();  // OnStreamReady
+
+  EXPECT_EQ(0, delegate->on_data_read_count());
+  EXPECT_EQ(0, delegate->on_data_sent_count());
+}
+
 TEST_P(BidirectionalStreamQuicImplTest, DeleteStreamAfterReadData) {
   SetRequest("POST", "/", DEFAULT_PRIORITY);
   size_t spdy_request_headers_frame_length;
diff --git a/net/url_request/url_request_context_builder.cc b/net/url_request/url_request_context_builder.cc
index d0b7aa5..da93630 100644
--- a/net/url_request/url_request_context_builder.cc
+++ b/net/url_request/url_request_context_builder.cc
@@ -192,51 +192,6 @@
       max_size(0) {}
 URLRequestContextBuilder::HttpCacheParams::~HttpCacheParams() {}
 
-URLRequestContextBuilder::HttpNetworkSessionParams::HttpNetworkSessionParams()
-    : ignore_certificate_errors(false),
-      testing_fixed_http_port(0),
-      testing_fixed_https_port(0),
-      enable_http2(true),
-      enable_quic(false),
-      quic_max_server_configs_stored_in_properties(0),
-      quic_close_sessions_on_ip_change(false),
-      quic_idle_connection_timeout_seconds(kIdleConnectionTimeoutSeconds),
-      quic_migrate_sessions_on_network_change(false),
-      quic_migrate_sessions_early(false),
-      quic_disable_bidirectional_streams(false),
-      quic_race_cert_verification(false) {}
-
-URLRequestContextBuilder::HttpNetworkSessionParams::~HttpNetworkSessionParams()
-{}
-
-void URLRequestContextBuilder::HttpNetworkSessionParams::ConfigureSessionParams(
-    HttpNetworkSession::Params* network_session_params) const {
-  network_session_params->host_mapping_rules = host_mapping_rules;
-  network_session_params->ignore_certificate_errors = ignore_certificate_errors;
-  network_session_params->testing_fixed_http_port = testing_fixed_http_port;
-  network_session_params->testing_fixed_https_port = testing_fixed_https_port;
-
-  network_session_params->enable_http2 = enable_http2;
-
-  network_session_params->enable_quic = enable_quic;
-  network_session_params->quic_user_agent_id = quic_user_agent_id;
-  network_session_params->quic_max_server_configs_stored_in_properties =
-      quic_max_server_configs_stored_in_properties;
-  network_session_params->quic_connection_options = quic_connection_options;
-  network_session_params->quic_close_sessions_on_ip_change =
-      quic_close_sessions_on_ip_change;
-  network_session_params->quic_idle_connection_timeout_seconds =
-      quic_idle_connection_timeout_seconds;
-  network_session_params->quic_migrate_sessions_on_network_change =
-      quic_migrate_sessions_on_network_change;
-  network_session_params->quic_migrate_sessions_early =
-      quic_migrate_sessions_early;
-  network_session_params->quic_disable_bidirectional_streams =
-      quic_disable_bidirectional_streams;
-  network_session_params->quic_race_cert_verification =
-      quic_race_cert_verification;
-}
-
 URLRequestContextBuilder::URLRequestContextBuilder()
     : name_(nullptr),
       enable_brotli_(false),
@@ -457,8 +412,6 @@
 
   HttpNetworkSession::Context network_session_context;
   SetHttpNetworkSessionComponents(context.get(), &network_session_context);
-  HttpNetworkSession::Params network_session_params;
-  http_network_session_params_.ConfigureSessionParams(&network_session_params);
 
   if (proxy_delegate_) {
     network_session_context.proxy_delegate = proxy_delegate_.get();
@@ -470,7 +423,7 @@
   }
 
   storage->set_http_network_session(base::MakeUnique<HttpNetworkSession>(
-      network_session_params, network_session_context));
+      http_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 a8b3d24..90ed04c 100644
--- a/net/url_request/url_request_context_builder.h
+++ b/net/url_request/url_request_context_builder.h
@@ -49,7 +49,6 @@
 class ChannelIDService;
 class CookieStore;
 class CTVerifier;
-class HostMappingRules;
 class HttpAuthHandlerFactory;
 class HttpServerProperties;
 class NetworkQualityEstimator;
@@ -84,33 +83,6 @@
     base::FilePath path;
   };
 
-  struct NET_EXPORT HttpNetworkSessionParams {
-    HttpNetworkSessionParams();
-    ~HttpNetworkSessionParams();
-
-    // Configutes |params| to match the settings in |this|.
-    // TODO(mmenke):  Temporary utility function. Once everything is using a
-    // URLRequestContextBuilder, can make this no longer publicly accessible.
-    void ConfigureSessionParams(HttpNetworkSession::Params* params) const;
-
-    // These fields mirror those in HttpNetworkSession::Params;
-    HostMappingRules host_mapping_rules;
-    bool ignore_certificate_errors;
-    uint16_t testing_fixed_http_port;
-    uint16_t testing_fixed_https_port;
-    bool enable_http2;
-    bool enable_quic;
-    std::string quic_user_agent_id;
-    int quic_max_server_configs_stored_in_properties;
-    QuicTagVector quic_connection_options;
-    bool quic_close_sessions_on_ip_change;
-    int quic_idle_connection_timeout_seconds;
-    bool quic_migrate_sessions_on_network_change;
-    bool quic_migrate_sessions_early;
-    bool quic_disable_bidirectional_streams;
-    bool quic_race_cert_verification;
-  };
-
   URLRequestContextBuilder();
   virtual ~URLRequestContextBuilder();
 
@@ -226,7 +198,7 @@
 
   // Override default HttpNetworkSession::Params settings.
   void set_http_network_session_params(
-      const HttpNetworkSessionParams& http_network_session_params) {
+      const HttpNetworkSession::Params& http_network_session_params) {
     http_network_session_params_ = http_network_session_params;
   }
 
@@ -371,7 +343,7 @@
 
   scoped_refptr<base::SingleThreadTaskRunner> file_task_runner_;
   HttpCacheParams http_cache_params_;
-  HttpNetworkSessionParams http_network_session_params_;
+  HttpNetworkSession::Params http_network_session_params_;
   base::FilePath transport_security_persister_path_;
   NetLog* net_log_;
   std::unique_ptr<HostResolver> host_resolver_;
diff --git a/storage/browser/blob/blob_memory_controller.cc b/storage/browser/blob/blob_memory_controller.cc
index 27370be..cc9e85d6 100644
--- a/storage/browser/blob/blob_memory_controller.cc
+++ b/storage/browser/blob/blob_memory_controller.cc
@@ -952,8 +952,10 @@
 void BlobMemoryController::OnMemoryPressure(
     base::MemoryPressureListener::MemoryPressureLevel memory_pressure_level) {
   auto time_from_last_evicion = base::TimeTicks::Now() - last_eviction_time_;
-  if (time_from_last_evicion.InSeconds() < kMinSecondsForPressureEvictions)
+  if (last_eviction_time_ != base::TimeTicks() &&
+      time_from_last_evicion.InSeconds() < kMinSecondsForPressureEvictions) {
     return;
+  }
 
   MaybeScheduleEvictionUntilSystemHealthy(memory_pressure_level);
 }
diff --git a/testing/buildbot/filters/ash_unittests_mash.filter b/testing/buildbot/filters/ash_unittests_mash.filter
index 6cd495d1..1b27996 100644
--- a/testing/buildbot/filters/ash_unittests_mash.filter
+++ b/testing/buildbot/filters/ash_unittests_mash.filter
@@ -168,6 +168,7 @@
 -MultiWindowResizeControllerTest.Drag
 -MultiWindowResizeControllerTest.IsOverWindows
 -MultiWindowResizeControllerTest.Three
+-OverviewButtonTrayTest.HideAnimationAlwaysCompletesOnDelete
 -OverviewGestureHandlerTest.HorizontalScrollInOverview
 -OverviewGestureHandlerTest.HorizontalScrollnOverview
 -OverviewGestureHandlerTest.ScrollUpDownWithoutReleasing
@@ -229,6 +230,19 @@
 -ScreenPositionControllerTest.ConvertHostPointToScreenRotate
 -ScreenPositionControllerTest.ConvertHostPointToScreenUIScale
 -ScreenPositionControllerTest.ConvertToScreenWhileRemovingSecondaryDisplay
+-ScreenRotationAnimatorSlowAnimationTest.OverviewButtonTrayHideAnimationAlwaysCompletes
+-ScreenRotationAnimatorSlowAnimationTest.RotatesDuringRotation
+-ScreenRotationAnimatorSlowAnimationTest.RotatesToDifferentRotation
+-ScreenRotationAnimatorSlowAnimationTest.ShouldCompleteAnimations
+-ScreenRotationAnimatorSlowAnimationTest.ShouldNotifyObserver
+-ScreenRotationAnimatorSlowAnimationTest.ShouldNotifyObserverOnce
+-ScreenRotationAnimatorSlowAnimationTest.ShouldNotRotateTheSameRotation
+-ScreenRotationAnimatorSmoothAnimationTest.OverviewButtonTrayHideAnimationAlwaysCompletes
+-ScreenRotationAnimatorSmoothAnimationTest.RemoveExternalPrimaryDisplayBeforeFirstCopyCallback
+-ScreenRotationAnimatorSmoothAnimationTest.RemoveExternalPrimaryDisplayBeforeSecondCopyCallback
+-ScreenRotationAnimatorSmoothAnimationTest.RemoveExternalSecondaryDisplayBeforeFirstCopyCallback
+-ScreenRotationAnimatorSmoothAnimationTest.RemoveExternalSecondaryDisplayBeforeSecondCopyCallback
+-ScreenRotationAnimatorSmoothAnimationTest.RotatesToDifferentRotationWithCopyCallback
 -ScreenshotControllerTest.BreaksCapture
 -ScreenshotControllerTest.MultipleDisplays
 -SystemGestureEventFilterTest.ControlWindowGetsMultiFingerGestureEvents
diff --git a/testing/buildbot/filters/ash_unittests_mus.filter b/testing/buildbot/filters/ash_unittests_mus.filter
index a35f43c..378a84f 100644
--- a/testing/buildbot/filters/ash_unittests_mus.filter
+++ b/testing/buildbot/filters/ash_unittests_mus.filter
@@ -64,6 +64,7 @@
 -ResizeShadowAndCursorTest.MaximizeRestore
 -ResizeShadowAndCursorTest.MouseDrag
 -ResizeShadowAndCursorTest.MouseHover
+-ScreenRotationAnimatorSmoothAnimationTest.OverviewButtonTrayHideAnimationAlwaysCompletes
 -ScreenRotationAnimatorSmoothAnimationTest.RotatesToDifferentRotationWithCopyCallback
 -ScreenRotationAnimatorSmoothAnimationTest.RemoveExternalSecondaryDisplayBeforeSecondCopyCallback
 -ScreenRotationAnimatorSmoothAnimationTest.RemoveExternalPrimaryDisplayBeforeSecondCopyCallback
diff --git a/testing/variations/fieldtrial_testing_config.json b/testing/variations/fieldtrial_testing_config.json
index 91cedbb..a97de45 100644
--- a/testing/variations/fieldtrial_testing_config.json
+++ b/testing/variations/fieldtrial_testing_config.json
@@ -475,6 +475,21 @@
             ]
         }
     ],
+    "ContextualSearch": [
+        {
+            "platforms": [
+                "android"
+            ],
+            "experiments": [
+                {
+                    "name": "Default",
+                    "params": {
+                        "enable_ranker_logging": "true"
+                    }
+                }
+            ]
+        }
+    ],
     "CopylessPaste": [
         {
             "platforms": [
diff --git a/third_party/WebKit/LayoutTests/FlagExpectations/enable-network-service b/third_party/WebKit/LayoutTests/FlagExpectations/enable-network-service
index b764ccd..ad43abf1 100644
--- a/third_party/WebKit/LayoutTests/FlagExpectations/enable-network-service
+++ b/third_party/WebKit/LayoutTests/FlagExpectations/enable-network-service
@@ -2737,7 +2737,6 @@
 Bug(none) http/tests/serviceworker/chromium/windowclient-focus.html [ Failure ]
 Bug(none) http/tests/serviceworker/chromium/xhr-is-not-exposed-to-service-workers.html [ Failure ]
 Bug(none) http/tests/serviceworker/immutable-prototype-serviceworker.html [ Failure ]
-Bug(none) http/tests/serviceworker/indexeddb.html [ Failure ]
 Bug(none) http/tests/serviceworker/insecure-parent-frame.html [ Failure ]
 Bug(none) http/tests/serviceworker/navigation-preload/chromium/navigation-preload-after-gc.html [ Failure ]
 Bug(none) http/tests/serviceworker/navigation-preload/chromium/navigation-preload-resource-timing.html [ Failure ]
@@ -4594,7 +4593,6 @@
 Bug(none) virtual/mojo-loading/http/tests/serviceworker/chromium/windowclient-focus.html [ Failure ]
 Bug(none) virtual/mojo-loading/http/tests/serviceworker/chromium/xhr-is-not-exposed-to-service-workers.html [ Failure ]
 Bug(none) virtual/mojo-loading/http/tests/serviceworker/immutable-prototype-serviceworker.html [ Failure Timeout ]
-Bug(none) virtual/mojo-loading/http/tests/serviceworker/indexeddb.html [ Failure ]
 Bug(none) virtual/mojo-loading/http/tests/serviceworker/insecure-parent-frame.html [ Failure ]
 Bug(none) virtual/mojo-loading/http/tests/serviceworker/navigation-preload/chromium/navigation-preload-after-gc.html [ Failure ]
 Bug(none) virtual/mojo-loading/http/tests/serviceworker/navigation-preload/chromium/navigation-preload-resource-timing.html [ Failure ]
@@ -5166,7 +5164,6 @@
 Bug(none) virtual/off-main-thread-fetch/http/tests/serviceworker/chromium/windowclient-focus.html [ Failure ]
 Bug(none) virtual/off-main-thread-fetch/http/tests/serviceworker/chromium/xhr-is-not-exposed-to-service-workers.html [ Failure ]
 Bug(none) virtual/off-main-thread-fetch/http/tests/serviceworker/immutable-prototype-serviceworker.html [ Failure ]
-Bug(none) virtual/off-main-thread-fetch/http/tests/serviceworker/indexeddb.html [ Failure ]
 Bug(none) virtual/off-main-thread-fetch/http/tests/serviceworker/insecure-parent-frame.html [ Failure ]
 Bug(none) virtual/off-main-thread-fetch/http/tests/serviceworker/navigation-preload/chromium/navigation-preload-after-gc.html [ Failure ]
 Bug(none) virtual/off-main-thread-fetch/http/tests/serviceworker/navigation-preload/chromium/navigation-preload-resource-timing.html [ Failure ]
diff --git a/third_party/WebKit/LayoutTests/external/wpt/service-workers/service-worker/indexeddb.https.html b/third_party/WebKit/LayoutTests/external/wpt/service-workers/service-worker/indexeddb.https.html
index 4de2bc4..be9be49 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/service-workers/service-worker/indexeddb.https.html
+++ b/third_party/WebKit/LayoutTests/external/wpt/service-workers/service-worker/indexeddb.https.html
@@ -4,32 +4,75 @@
 <script src="/resources/testharnessreport.js"></script>
 <script src="resources/test-helpers.sub.js"></script>
 <script>
-async_test(function(t) {
-    var scope = 'resources/blank.html';
-    service_worker_unregister_and_register(
-      t, 'resources/indexeddb-worker.js', scope)
-    .then(function(registration) {
-        var sw = registration.installing;
-        var messageChannel = new MessageChannel();
-        messageChannel.port1.onmessage = t.step_func(onMessage);
-        sw.postMessage({port: messageChannel.port2}, [messageChannel.port2]);
-      })
-    .catch(unreached_rejection(t));
-
-    function onMessage() {
+function readDB() {
+  return new Promise(function(resolve, reject) {
       var openRequest = indexedDB.open('db');
-      openRequest.onsuccess = t.step_func(function() {
+
+      openRequest.onerror = reject;
+      openRequest.onsuccess = function() {
           var db = openRequest.result;
           var tx = db.transaction('store');
           var store = tx.objectStore('store');
           var getRequest = store.get('key');
-          getRequest.onsuccess = t.step_func(function() {
-              assert_equals(
-                getRequest.result, 'value',
-                'The get() result should match what the worker put().');
-              service_worker_unregister_and_done(t, scope);
-            });
+
+          getRequest.onerror = function() {
+              db.close();
+              reject(getRequest.error);
+            };
+          getRequest.onsuccess = function() {
+              db.close();
+              resolve(getRequest.result);
+            };
+        };
+    });
+}
+
+function send(worker, action) {
+  return new Promise(function(resolve, reject) {
+      var messageChannel = new MessageChannel();
+      messageChannel.port1.onmessage = function(event) {
+          if (event.data.type === 'error') {
+            reject(event.data.reason);
+          }
+
+          resolve();
+        };
+
+      worker.postMessage(
+        {action: action, port: messageChannel.port2},
+        [messageChannel.port2]);
+    });
+}
+
+promise_test(function(t) {
+    var scope = 'resources/blank.html';
+
+    return service_worker_unregister_and_register(
+        t, 'resources/indexeddb-worker.js', scope)
+      .then(function(registration) {
+          var worker = registration.installing;
+
+          promise_test(function() {
+              return registration.unregister();
+            }, 'clean up: registration');
+
+          return send(worker, 'create')
+            .then(function() {
+                promise_test(function() {
+                  return new Promise(function(resolve, reject) {
+                        var delete_request = indexedDB.deleteDatabase('db');
+
+                        delete_request.onsuccess = resolve;
+                        delete_request.onerror = reject;
+                      });
+                    }, 'clean up: database');
+              })
+            .then(readDB)
+            .then(function(value) {
+                assert_equals(
+                  value, 'value',
+                  'The get() result should match what the worker put().');
+              });
         });
-    }
   }, 'Verify Indexed DB operation in a Service Worker');
 </script>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/service-workers/service-worker/resources/indexeddb-worker.js b/third_party/WebKit/LayoutTests/external/wpt/service-workers/service-worker/resources/indexeddb-worker.js
index ef89550..9add4768 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/service-workers/service-worker/resources/indexeddb-worker.js
+++ b/third_party/WebKit/LayoutTests/external/wpt/service-workers/service-worker/resources/indexeddb-worker.js
@@ -1,26 +1,57 @@
-var port;
 self.addEventListener('message', function(e) {
     var message = e.data;
-    if ('port' in message)
-      doIndexedDBTest(message.port);
+    if (message.action === 'create') {
+      e.waitUntil(deleteDB()
+          .then(doIndexedDBTest)
+          .then(function() {
+              message.port.postMessage({ type: 'created' });
+            })
+          .catch(function(reason) {
+              message.port.postMessage({ type: 'error', value: reason });
+            }));
+    } else if (message.action === 'cleanup') {
+      e.waitUntil(deleteDB()
+          .then(function() {
+              message.port.postMessage({ type: 'done' });
+            })
+          .catch(function(reason) {
+              message.port.postMessage({ type: 'error', value: reason });
+            }));
+    }
   });
 
+function deleteDB() {
+  return new Promise(function(resolve, reject) {
+      var delete_request = indexedDB.deleteDatabase('db');
+
+      delete_request.onsuccess = resolve;
+      delete_request.onerror = reject;
+    });
+}
+
 function doIndexedDBTest(port) {
-  var delete_request = indexedDB.deleteDatabase('db');
-  delete_request.onsuccess = function() {
-    var open_request = indexedDB.open('db');
-    open_request.onupgradeneeded = function() {
-      var db = open_request.result;
-      db.createObjectStore('store');
-    };
-    open_request.onsuccess = function() {
-      var db = open_request.result;
-      var tx = db.transaction('store', 'readwrite');
-      var store = tx.objectStore('store');
-      store.put('value', 'key');
-      tx.oncomplete = function() {
-        port.postMessage('done');
+  return new Promise(function(resolve, reject) {
+      var open_request = indexedDB.open('db');
+
+      open_request.onerror = reject;
+      open_request.onupgradeneeded = function() {
+        var db = open_request.result;
+        db.createObjectStore('store');
       };
-    };
-  };
+      open_request.onsuccess = function() {
+        var db = open_request.result;
+        var tx = db.transaction('store', 'readwrite');
+        var store = tx.objectStore('store');
+        store.put('value', 'key');
+
+        tx.onerror = function() {
+            db.close();
+            reject(tx.error);
+          };
+        tx.oncomplete = function() {
+            db.close();
+            resolve();
+          };
+      };
+    });
 }
diff --git a/third_party/WebKit/LayoutTests/http/tests/serviceworker/indexeddb.html b/third_party/WebKit/LayoutTests/http/tests/serviceworker/indexeddb.html
deleted file mode 100644
index aab7c901..0000000
--- a/third_party/WebKit/LayoutTests/http/tests/serviceworker/indexeddb.html
+++ /dev/null
@@ -1,35 +0,0 @@
-<!DOCTYPE html>
-<title>Service Worker: Indexed DB</title>
-<script src="../resources/testharness.js"></script>
-<script src="../resources/testharnessreport.js"></script>
-<script src="resources/test-helpers.js"></script>
-<script>
-async_test(function(t) {
-    var scope = 'resources/blank.html';
-    service_worker_unregister_and_register(
-      t, 'resources/indexeddb-worker.js', scope)
-    .then(function(registration) {
-        var sw = registration.installing;
-        var messageChannel = new MessageChannel();
-        messageChannel.port1.onmessage = t.step_func(onMessage);
-        sw.postMessage({port: messageChannel.port2}, [messageChannel.port2]);
-      })
-    .catch(unreached_rejection(t));
-    
-    function onMessage() {
-      var openRequest = indexedDB.open('db');
-      openRequest.onsuccess = t.step_func(function() {
-          var db = openRequest.result;
-          var tx = db.transaction('store');
-          var store = tx.objectStore('store');
-          var getRequest = store.get('key');
-          getRequest.onsuccess = t.step_func(function() {
-              assert_equals(
-                getRequest.result, 'value',
-                'The get() result should match what the worker put().');
-              service_worker_unregister_and_done(t, scope);
-            });
-        });
-    }
-  }, 'Verify Indexed DB operation in a Service Worker');
-</script>
diff --git a/third_party/WebKit/LayoutTests/http/tests/serviceworker/resources/indexeddb-worker.js b/third_party/WebKit/LayoutTests/http/tests/serviceworker/resources/indexeddb-worker.js
deleted file mode 100644
index d138e54..0000000
--- a/third_party/WebKit/LayoutTests/http/tests/serviceworker/resources/indexeddb-worker.js
+++ /dev/null
@@ -1,28 +0,0 @@
-self.addEventListener('message', function(e) {
-    var message = e.data;
-    if ('port' in message)
-      e.waitUntil(doIndexedDBTest(message.port));
-  });
-
-function doIndexedDBTest(port) {
-  return new Promise(function(resolve) {
-    var delete_request = indexedDB.deleteDatabase('db');
-    delete_request.onsuccess = function() {
-      var open_request = indexedDB.open('db');
-      open_request.onupgradeneeded = function() {
-        var db = open_request.result;
-        db.createObjectStore('store');
-      };
-      open_request.onsuccess = function() {
-        var db = open_request.result;
-        var tx = db.transaction('store', 'readwrite');
-        var store = tx.objectStore('store');
-        store.put('value', 'key');
-        tx.oncomplete = function() {
-          port.postMessage('done');
-          resolve();
-        };
-      };
-    };
-  });
-}
diff --git a/third_party/WebKit/LayoutTests/webaudio/BiquadFilter/tail-time-allpass.html b/third_party/WebKit/LayoutTests/webaudio/BiquadFilter/tail-time-allpass.html
new file mode 100644
index 0000000..b902f42
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/webaudio/BiquadFilter/tail-time-allpass.html
@@ -0,0 +1,103 @@
+<!doctype html>
+<html>
+  <head>
+    <title>Test Biquad Tail-Time</title>
+    <script src="../../resources/testharness.js"></script>
+    <script src="../../resources/testharnessreport.js"></script>
+    <script src="../resources/audit-util.js"></script>
+    <script src="../resources/audit.js"></script>
+    <script src="../resources/biquad-filters.js"></script>
+    <script src="test-tail-time.js"></script>
+  </head>
+
+  <body>
+    <script>
+      let audit = Audit.createTaskRunner();
+
+      let sampleRate = 16384;
+      let renderSeconds = 1;
+      let renderFrames = renderSeconds * sampleRate;
+
+      // For an allpass filter:
+      //   b0 = 1 - alpha
+      //   b1 = -2*cos(w0)
+      //   b2 = 1 + alpha
+      //   a0 = 1 + alpha
+      //   a1 = -2*cos(w0)
+      //   a2 = 1 - alpha
+      //
+      // where alpha = sin(w0)/(2*Q) and w0 = 2*%pi*f0/Fs.
+      //
+      // Equivalently a1 = -2*cos(w0)/(1+alpha), a2 = (1-alpha)/(1+alpha).  The
+      // poles of this filter are at
+      //
+      //   (2*Q*cos(w0) +/- sqrt(1-4*Q^2)*sin(w0))/(2*Q + sin(w0))
+      //
+      // Thus, if 1-4*Q^2 < 0, the poles are complex.  For 1-4*Q^2 > 0, the
+      // poles are real and distinct.  For 1-4*Q^2 = 0, there are two identical
+      // real poles.
+
+      // Array of tests to run.  |descripton| is the task description for
+      // audit.define.  |parameters| is option for |testTailTime|.
+      let tests = [
+        {
+          description:
+              {label: 'allpass-complex-roots', description: 'complex roots'},
+          parameters: {
+            prefix: 'Complex roots',
+            // Choose a fairly large Q to make the tail long.  Frequency is
+            // fairly arbitrary.
+            filterOptions: {type: 'allpass', Q: 200, frequency: sampleRate / 4},
+            // This filter the actual real tail frame is 2317, and the node
+            // computed frame is 2316.81.  Thus, the tail output should be
+            // exactly 0.
+            threshold: 0
+          }
+        },
+        {
+          description: {
+            label: 'allpass-real-distinct-roots',
+            description: 'real distinct roots'
+          },
+          parameters: {
+            prefix: 'Distinct roots',
+            filterOptions: {
+              type: 'allpass',
+              Q: 0.001,
+              frequency: sampleRate / 8,
+            },
+            // With this particular filter, the real tail frame is 4822, but
+            // the node way overestimates it to be 7136.  Thus, the actual
+            // tail frames won't be exactly zero.
+            threshold: 1 / 32768
+          }
+        },
+        {
+          description: {
+            label: 'allpass-repeated-roots',
+            description: 'repeated real root'
+          },
+          parameters: {
+            prefix: 'Repeated roots',
+            // 1-4*Q^2 = 0 iff Q = 1/2.
+            filterOptions: {type: 'allpass', Q: 0.5, frequency: sampleRate / 8},
+            // The node estimated tail time is 16.8 frames, but the actual is
+            // 106.  Thus, the outupt should be exactly 0.
+            threshold: 0
+          }
+        }
+      ];
+
+      // Define an appropriate task for each test.
+      tests.forEach(entry => {
+        audit.define(entry.description, (task, should) => {
+          let context = new OfflineAudioContext(1, renderFrames, sampleRate);
+          testTailTime(should, context, entry.parameters)
+              .then(() => task.done());
+        });
+      });
+
+      audit.run();
+    </script>
+  </body>
+</html>
diff --git a/third_party/WebKit/LayoutTests/webaudio/BiquadFilter/tail-time-bandpass.html b/third_party/WebKit/LayoutTests/webaudio/BiquadFilter/tail-time-bandpass.html
new file mode 100644
index 0000000..6eb0ad1
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/webaudio/BiquadFilter/tail-time-bandpass.html
@@ -0,0 +1,95 @@
+<!doctype html>
+<html>
+  <head>
+    <title>Test Biquad Tail-Time</title>
+    <script src="../../resources/testharness.js"></script>
+    <script src="../../resources/testharnessreport.js"></script>
+    <script src="../resources/audit-util.js"></script>
+    <script src="../resources/audit.js"></script>
+    <script src="../resources/biquad-filters.js"></script>
+    <script src="test-tail-time.js"></script>
+  </head>
+
+  <body>
+    <script>
+      let audit = Audit.createTaskRunner();
+
+      let sampleRate = 16384;
+      let renderSeconds = 1;
+      let renderFrames = renderSeconds * sampleRate;
+
+      // For a bandpass filter:
+      //   b0 = alpha
+      //   b1 = 0
+      //   b2 = -alpha
+      //   a0 = 1 + alpha
+      //   a1 = -2*cos(w0)
+      //   a2 = 1 - alpha
+      //
+      // where alpha = sin(w0)/(2*Q) and w0 = 2*%pi*f0/Fs.
+      //
+      // Equivalently a1 = -2*cos(w0)/(1+alpha), a2 = (1-alpha)/(1+alpha).  The
+      // poles of this filter are at
+      //
+      //   (2*Q*cos(w0) +/- sqrt(1-4*Q^2)*sin(w0))/(2*Q + sin(w0))
+      //
+      // Thus, if 1-4*Q^2 < 0, the poles are complex.  For 1-4*Q^2 > 0, the
+      // poles are real and distinct.  For 1-4*Q^2 = 0, there are two identical
+      // real poles.
+
+      // Array of tests to run.  |descripton| is the task description for
+      // audit.define.  |parameters| is option for |testTailTime|.
+      let tests = [
+        {
+          descripton:
+              {label: 'bpf-complex-roots', description: 'complex roots'},
+          parameters: {
+            prefix: 'BPF complex roots',
+            filterOptions:
+                {type: 'bandpass', Q: 200, frequency: sampleRate / 4},
+            // The node estimated tail frame is 2039.55, which matches the
+            // true tail frame so output should be exactly 0
+            threshold: 0
+          }
+        },
+        {
+          descripton: {
+            label: 'bpf-real-distinct-roots',
+            description: 'real distinct roots'
+          },
+          parameters: {
+            prefix: 'BPF real distinct roots',
+            filterOptions:
+                {type: 'bandpass', Q: 0.001, frequency: sampleRate / 4},
+            // The node estimated tail frame is 2437, which matches the
+            // true tail frame so output should be exactly 0
+            threshold: 0
+          }
+        },
+        {
+          descripton:
+              {label: 'bpf-repeated-roots', description: 'repeated real root'},
+          parameters: {
+            prefix: 'BPF repeated roots',
+            filterOptions:
+                {type: 'bandpass', Q: 0.5, frequency: sampleRate / 8},
+            // The node estimated tail frame is 15.9, which matches the true
+            // tail frame so output should be exactly 0
+            threshold: 0
+          }
+        }
+      ];
+
+      // Define an appropriate task for each test.
+      tests.forEach(entry => {
+        audit.define(entry.descripton, (task, should) => {
+          let context = new OfflineAudioContext(1, renderFrames, sampleRate);
+          testTailTime(should, context, entry.parameters)
+              .then(() => task.done());
+        });
+      });
+
+      audit.run();
+    </script>
+  </body>
+</html>
diff --git a/third_party/WebKit/LayoutTests/webaudio/BiquadFilter/tail-time-highpass.html b/third_party/WebKit/LayoutTests/webaudio/BiquadFilter/tail-time-highpass.html
new file mode 100644
index 0000000..90bd15a3
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/webaudio/BiquadFilter/tail-time-highpass.html
@@ -0,0 +1,116 @@
+<!doctype html>
+<html>
+  <head>
+    <title>Test Biquad Tail-Time</title>
+    <script src="../../resources/testharness.js"></script>
+    <script src="../../resources/testharnessreport.js"></script>
+    <script src="../resources/audit-util.js"></script>
+    <script src="../resources/audit.js"></script>
+    <script src="../resources/biquad-filters.js"></script>
+    <script src="test-tail-time.js"></script>
+  </head>
+
+  <body>
+    <script>
+      let audit = Audit.createTaskRunner();
+
+      let sampleRate = 16384;
+      let renderSeconds = 1;
+      let renderFrames = renderSeconds * sampleRate;
+
+      // For a highpass filter:
+      //   b0 = (1+cos(w0))/2
+      //   b1 = -(1+cos(w0))
+      //   b2 = (1+cos(w0))/2
+      //   a0 = 1 + alpha
+      //   a1 = -2*cos(w0)
+      //   a2 = 1 - alpha
+      //
+      // where alpha = sin(w0)/(2*10^(Q/20)) and w0 = 2*%pi*f0/Fs.
+      //
+      // Equivalently a1 = -2*cos(w0)/(1+alpha), a2 = (1-alpha)/(1+alpha).  The
+      // poles of this filter are at
+      //
+      //   cos(w0)/(1+alpha) +/- sqrt(alpha^2-sin(w0)^2)/(1+alpha)
+      //
+      // But alpha^2-sin(w0)^2 = sin(w0)^2*(1/4/10^(Q/10) - 1).  Thus the poles
+      // are complex if 1/4/10^(Q/10) < 1; real distinct if 1/4/10^(Q/10) > 1;
+      // and repeated if 1/4/10^(Q/10) = 1.
+
+      // Array of tests to run.  |descripton| is the task description for
+      // audit.define.  |parameters| is option for |testTailTime|.
+      let tests = [
+        {
+          descripton:
+              {label: 'hpf-complex-roots', description: 'complex roots'},
+          parameters: {
+            prefix: 'HPF complex roots',
+            filterOptions: {type: 'highpass', Q: 40, frequency: sampleRate / 4},
+            // Node computed tail frame is 2079.4, which matches the actual tail
+            // frome so output should be exactly 0.
+            threshold: 0
+          }
+        },
+        {
+          descripton: {
+            label: 'hpf-real-distinct-roots',
+            description: 'real distinct roots'
+          },
+          parameters: {
+            prefix: 'HPF real distinct roots',
+            filterOptions:
+                {type: 'highpass', Q: -50, frequency: sampleRate / 8},
+            // With these filter parameters, the real tail time is 408, but
+            // the node overestimates it to be 2367.  Thus, the actual tail
+            // frames won't be exactly zero.
+            threshold: 1 / 32768
+          }
+        },
+        {
+          descripton:
+              {label: 'hpf-repeated-root', description: 'repeated real root'},
+          parameters: {
+            prefix: 'HPF repeated roots (approximately)',
+            // For a repeated root, we need 1/4/10^(Q/10) = 1, or Q =
+            // -10*log(4)/log(10). This isn't exactly representable as a float,
+            // so the roots might not actually be repeated.  In fact the roots
+            // are complex at 6.40239e-5*exp(i*1.570596).
+            filterOptions: {
+              type: 'highpass',
+              Q: -10 * Math.log10(4),
+              frequency: sampleRate / 4
+            },
+            // Node computed tail frame is 2.9, which matches the actual tail
+            // frome so output should be exactly 0.
+            threshold: 0
+          }
+        },
+        {
+          descripton: {label: 'hpf-real-roots-2', description: 'complex roots'},
+          parameters: {
+            prefix: 'HPF repeated roots 2',
+            // This tests an extreme case where approximate impulse response is
+            // h(n) = C*r^(n-1) and C < 1/32768.  Thus, the impulse response is
+            // always less than the response threshold of 1/32768.
+            filterOptions:
+                {type: 'highpass', Q: -100, frequency: sampleRate / 4},
+            // Node computed tail frame is 0, which matches the actual tail
+            // frame so output should be exactly 0.
+            threshold: 0
+          }
+        }
+      ];
+
+      // Define an appropriate task for each test.
+      tests.forEach(entry => {
+        audit.define(entry.descripton, (task, should) => {
+          let context = new OfflineAudioContext(1, renderFrames, sampleRate);
+          testTailTime(should, context, entry.parameters)
+              .then(() => task.done());
+        });
+      });
+
+      audit.run();
+    </script>
+  </body>
+</html>
diff --git a/third_party/WebKit/LayoutTests/webaudio/BiquadFilter/tail-time-highshelf.html b/third_party/WebKit/LayoutTests/webaudio/BiquadFilter/tail-time-highshelf.html
new file mode 100644
index 0000000..0b3a2ae
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/webaudio/BiquadFilter/tail-time-highshelf.html
@@ -0,0 +1,81 @@
+<!doctype html>
+<html>
+  <head>
+    <title>Test Biquad Tail-Time</title>
+    <script src="../../resources/testharness.js"></script>
+    <script src="../../resources/testharnessreport.js"></script>
+    <script src="../resources/audit-util.js"></script>
+    <script src="../resources/audit.js"></script>
+    <script src="../resources/biquad-filters.js"></script>
+    <script src="test-tail-time.js"></script>
+  </head>
+
+  <body>
+    <script>
+      let audit = Audit.createTaskRunner();
+
+      let sampleRate = 16384;
+      let renderSeconds = 1;
+      let renderFrames = renderSeconds * sampleRate;
+
+      // For a highshelf filter:
+      //   b0 = A*[(A+1)+(A−1)*cos(w0)+2*as*sqrt(A)]
+      //   b1 = 2*A*[(A-1)+(A+1)*cos(w0)]
+      //   b2 = A*[(A+1)+(A−1)*cos(w0)-2*as*sqrt(A)]
+      //   a0 = (A+1)-(A-1)*cos(w0)+2*as*sqrt(A)
+      //   a1 = -2*[(A-1)-(A+1)*cos(w0)]
+      //   a2 = (A+1)-(A-1)*cos(w0)-2*as*sqrt(A)
+      //
+      // where as = sin(w0)/sqrt(2), w0 = 2*%pi*f0/Fs, and A = 10^(G/40)
+      //
+      // The poles of this filter are
+      //
+      //   -a2/(2*a0) +/- sqrt(a1^2-4*a0*a2)/(2*a0).
+      //
+      // Thus, the poles depend on the sign of d = a1^2-4*a0*a2 =
+      // 16*A*(as^2-sin(w0)^2) = -8*A*sin(w0)^2.  Thus, the poles are always
+      // complex except if w0 = 0, in which case there is a repeated pole at 0.
+
+      // Array of tests to run.  |descripton| is the task description for
+      // audit.define.  |parameters| is option for |testTailTime|.
+      let tests = [
+        {
+          descripton:
+              {label: 'highshelf-complex-roots', description: 'complex roots'},
+          parameters: {
+            prefix: 'Highshelf complex roots',
+            filterOptions:
+                {type: 'highshelf', gain: 40, frequency: sampleRate / 8},
+            // Node computed tail frame is 18.6 frames, which matches the actual
+            // tail, so tail output should be exactly zero.
+            threshold: 0
+          }
+        },
+        {
+          descripton: {
+            label: 'highshelf-repeated-roots',
+            description: 'repeated real root'
+          },
+          parameters: {
+            prefix: 'Highshelf repeated roots',
+            filterOptions: {type: 'highshelf', gain: 40, frequency: 0},
+            // Node computed tail frame is 2 frames, which matches the actual
+            // tail, so tail output should be exactly zero.
+            threshold: 0
+          }
+        },
+      ];
+
+      // Define an appropriate task for each test.
+      tests.forEach(entry => {
+        audit.define(entry.descripton, (task, should) => {
+          let context = new OfflineAudioContext(1, renderFrames, sampleRate);
+          testTailTime(should, context, entry.parameters)
+              .then(() => task.done());
+        });
+      });
+
+      audit.run();
+    </script>
+  </body>
+</html>
diff --git a/third_party/WebKit/LayoutTests/webaudio/BiquadFilter/tail-time-lowpass.html b/third_party/WebKit/LayoutTests/webaudio/BiquadFilter/tail-time-lowpass.html
new file mode 100644
index 0000000..dc042637
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/webaudio/BiquadFilter/tail-time-lowpass.html
@@ -0,0 +1,168 @@
+<!doctype html>
+<html>
+  <head>
+    <title>Test Biquad Tail-Time</title>
+    <script src="../../resources/testharness.js"></script>
+    <script src="../../resources/testharnessreport.js"></script>
+    <script src="../resources/audit-util.js"></script>
+    <script src="../resources/audit.js"></script>
+    <script src="../resources/biquad-filters.js"></script>
+    <script src="test-tail-time.js"></script>
+  </head>
+
+  <body>
+    <script>
+      let audit = Audit.createTaskRunner();
+
+      let sampleRate = 16384;
+      let renderSeconds = 1;
+
+      // For a lowpass filter:
+      //   b0 = (1-cos(w0))/2
+      //   b1 = 1-cos(w0)
+      //   b2 = (1-cos(w0))/2
+      //   a0 = 1 + alpha
+      //   a1 = -2*cos(w0)
+      //   a2 = 1 - alpha
+      //
+      // where alpha = sin(w0)/(2*10^(Q/20)) and w0 = 2*%pi*f0/Fs.
+      //
+      // Equivalently a1 = -2*cos(w0)/(1+alpha), a2 = (1-alpha)/(1+alpha).  The
+      // poles of this filter are at
+      //
+      //   cos(w0)/(1+alpha) +/- sqrt(alpha^2-sin(w0)^2)/(1+alpha)
+      //
+      // But alpha^2-sin(w0)^2 = sin(w0)^2*(1/4/10^(Q/10) - 1).  Thus the poles
+      // are complex if 1/4/10^(Q/10) < 1; real distinct if 1/4/10^(Q/10) > 1;
+      // and repeated if 1/4/10^(Q/10) = 1.
+
+      // Array of tests to run.  |descripton| is the task description for
+      // audit.define.  |parameters| is option for |testTailTime|.
+      let tests = [
+        {
+          descripton:
+              {label: 'lpf-complex-roots', description: 'complex roots'},
+          sampleRate: sampleRate,
+          renderDuration: renderSeconds,
+          parameters: {
+            prefix: 'LPF complex roots',
+            filterOptions: {type: 'lowpass', Q: 40, frequency: sampleRate / 4}
+          },
+          // Node computed tail frame is 2079.4 which matches the real tail, so
+          // tail output should be exactly 0.
+          threshold: 0,
+        },
+        {
+          descripton: {
+            label: 'lpf-real-distinct-roots',
+            description: 'real distinct roots'
+          },
+          sampleRate: sampleRate,
+          renderDuration: renderSeconds,
+          parameters: {
+            prefix: 'LPF real distinct roots',
+            filterOptions:
+                {type: 'lowpass', Q: -50, frequency: sampleRate / 8}
+          },
+          // Node computed tail frame is 1699 which matches the real tail, so
+          // tail output should be exactly 0.
+          threshold: 0,
+        },
+        {
+          descripton:
+              {label: 'lpf-repeated-root', description: 'repeated real root'},
+          sampleRate: sampleRate,
+          renderDuration: renderSeconds,
+          parameters: {
+            prefix: 'LPF repeated roots (approximately)',
+            // For a repeated root, we need 1/4/10^(Q/10) = 1, or Q =
+            // -10*log(4)/log(10). This isn't exactly representable as a float,
+            // we the roots might not actually be repeated.  In fact the roots
+            // are actually complex at 6.402396e-5*exp(i*1.570796).
+            filterOptions: {
+              type: 'lowpass',
+              Q: -10 * Math.log10(4),
+              frequency: sampleRate / 4
+            }
+          },
+          // Node computed tail frame is 2.9 which matches the real tail, so
+          // tail output should be exactly 0.
+          threshold: 0,
+        },
+        {
+          descripton: {label: 'lpf-real-roots-2', description: 'complex roots'},
+          sampleRate: sampleRate,
+          renderDuration: renderSeconds,
+          parameters: {
+            prefix: 'LPF repeated roots 2',
+            // This tests an extreme case where approximate impulse response is
+            // h(n) = C*r^(n-1) and C < 1/32768.  Thus, the impulse response is
+            // always less than the response threshold of 1/32768.
+            filterOptions:
+                {type: 'lowpass', Q: -100, frequency: sampleRate / 4}
+          },
+          // Node computed tail frame is 0 which matches the real tail, so
+          // tail output should be exactly 0.
+          threshold: 0,
+        },
+        {
+          descripton: 'huge tail',
+          // The BiquadFilter has an internal maximum tail of 30 sec so we want
+          // to render for at least 30 sec to test this.  Use the smallest
+          // sample rate we can to limit memory and CPU usage!
+          sampleRate: 3000,
+          renderDuration: 31,
+          parameters: {
+            prefix: 'LPF repeated roots (approximately)',
+            hugeTaileTime: true,
+            // For the record, for this lowpass filter, the computed tail time
+            // is approximately 2830.23 sec, with poles at
+            // 0.999998960442086*exp(i*0.209439510236777). This is very close to
+            // being marginally stable.
+            filterOptions: {
+              type: 'lowpass',
+              Q: 100,
+              frequency: 100,
+            },
+            // Node computed tail frame is 8.49069e6 which is clamped to 30 sec
+            // so tail output should be exactly 0 after 30 sec.
+            threshold: 0,
+          },
+        },
+        {
+          descripton: 'ginormous tail',
+          // Or this lowpass filter, the complex poles are actually computed to
+          // be on the unit circle so the tail infinite.  This just tests that
+          // nothing bad happens in computing the tail time. Thus, any small
+          // sample rate and short duration for the test; the results aren't
+          // really interesting. (But they must pass, of course!)
+          sampleRate: 3000,
+          renderDuration: 0.25,
+          parameters: {
+            prefix: 'LPF repeated roots (approximately)',
+            filterOptions: {
+              type: 'lowpass',
+              Q: 500,
+              frequency: 100,
+            },
+          },
+          // Node computed tail frame is 90000 which matches the real tail, so
+          // tail output should be exactly 0.
+          threshold: 0,
+        }
+      ]
+
+      // Define an appropriate task for each test.
+      tests.forEach(entry => {
+        audit.define(entry.descripton, (task, should) => {
+          let context = new OfflineAudioContext(
+              1, entry.renderDuration * entry.sampleRate, entry.sampleRate);
+          testTailTime(should, context, entry.parameters)
+              .then(() => task.done());
+        });
+      });
+
+      audit.run();
+    </script>
+  </body>
+</html>
diff --git a/third_party/WebKit/LayoutTests/webaudio/BiquadFilter/tail-time-lowshelf.html b/third_party/WebKit/LayoutTests/webaudio/BiquadFilter/tail-time-lowshelf.html
new file mode 100644
index 0000000..b8af1f3
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/webaudio/BiquadFilter/tail-time-lowshelf.html
@@ -0,0 +1,83 @@
+<!doctype html>
+<html>
+  <head>
+    <title>Test Biquad Tail-Time</title>
+    <script src="../../resources/testharness.js"></script>
+    <script src="../../resources/testharnessreport.js"></script>
+    <script src="../resources/audit-util.js"></script>
+    <script src="../resources/audit.js"></script>
+    <script src="../resources/biquad-filters.js"></script>
+    <script src="test-tail-time.js"></script>
+  </head>
+
+  <body>
+    <script>
+      let audit = Audit.createTaskRunner();
+
+      let sampleRate = 16384;
+      let renderSeconds = 1;
+      let renderFrames = renderSeconds * sampleRate;
+      let renderQuantumFrames = 128;
+
+      // For a lowshelf filter:
+      //   b0 = A*[(A+1)−(A−1)*cos(w0)+2*as*sqrt(A)]
+      //   b1 = 2*A*[(A+1)-(A-1)*cos(w0)]
+      //   b2 = A*[(A+1)−(A−1)*cos(w0)-2*as*sqrt(A)]
+      //   a0 = (A+1)+(A-1)*cos(w0)+2*as*sqrt(A)
+      //   a1 = -2*[(A-1)+(A+1)*cos(w0)]
+      //   a2 = (A+1)+(A-1)*cos(w0)-2*as*sqrt(A)
+      //
+      // where as = sin(w0)/sqrt(2), w0 = 2*%pi*f0/Fs, and A = 10^(G/40)
+      //
+      // The poles of this filter are
+      //
+      //   -a2/(2*a0) +/- sqrt(a1^2-4*a0*a2)/(2*a0).
+      //
+      // Thus, the poles depend on the sign of d = a1^2-4*a0*a2 =
+      // 16*A*(as^2-sin(w0)^2) = -8*A*sin(w0)^2.  Thus, the poles are always
+      // complex except if w0 = 0, in which case there is a repeated pole at 0.
+
+      // Array of tests to run.  |descripton| is the task description for
+      // audit.define.  |parameters| is option for |testTailTime|.
+      let tests = [
+        {
+          descripton:
+              {label: 'lowshelf-complex-roots', description: 'complex roots'},
+          parameters: {
+            prefix: 'Lowshelf complex roots',
+            filterOptions:
+                {type: 'lowshelf', gain: 40, frequency: sampleRate / 8},
+            // Node computed tail frame is 75.5 frames, which matches the actual
+            // tail, so tail output should be exactly zero.
+            threshold: 0
+          },
+        },
+        {
+          descripton: {
+            label: 'lowshelf-repeated-roots',
+            description: 'repeated real root'
+          },
+          parameters: {
+            prefix: 'Lowshelf repeated roots',
+            filterOptions:
+                {type: 'lowshelf', Q: 1 / 20, gain: 40, frequency: 0},
+            // Node computed tail frame is 2 frames, which matches the actual
+            // tail, so tail output should be exactly zero.
+            threshold: 0
+          },
+        },
+      ];
+
+      // Define an appropriate task for each test.
+      tests.forEach(entry => {
+        audit.define(entry.descripton, (task, should) => {
+          let context = new OfflineAudioContext(1, renderFrames, sampleRate);
+          testTailTime(should, context, entry.parameters)
+              .then(() => task.done());
+        });
+      });
+
+      audit.run();
+    </script>
+  </body>
+</html>
diff --git a/third_party/WebKit/LayoutTests/webaudio/BiquadFilter/tail-time-notch.html b/third_party/WebKit/LayoutTests/webaudio/BiquadFilter/tail-time-notch.html
new file mode 100644
index 0000000..0b38d4bc
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/webaudio/BiquadFilter/tail-time-notch.html
@@ -0,0 +1,98 @@
+<!doctype html>
+<html>
+  <head>
+    <title>Test Biquad Tail-Time</title>
+    <script src="../../resources/testharness.js"></script>
+    <script src="../../resources/testharnessreport.js"></script>
+    <script src="../resources/audit-util.js"></script>
+    <script src="../resources/audit.js"></script>
+    <script src="../resources/biquad-filters.js"></script>
+    <script src="test-tail-time.js"></script>
+  </head>
+
+  <body>
+    <script>
+      let audit = Audit.createTaskRunner();
+
+      let sampleRate = 16384;
+      let renderSeconds = 1;
+      let renderFrames = renderSeconds * sampleRate;
+      let renderQuantumFrames = 128;
+
+      // For a notch filter:
+      //   b0 = 1
+      //   b1 = -2*cos(w0)
+      //   b2 = 1
+      //   a0 = 1 + alpha
+      //   a1 = -2*cos(w0)
+      //   a2 = 1 - alpha
+      //
+      // where alpha = sin(w0)/(2*Q) and w0 = 2*%pi*f0/Fs.
+      //
+      // Equivalently a1 = -2*cos(w0)/(1+alpha), a2 = (1-alpha)/(1+alpha).  The
+      // poles of this filter are at
+      //
+      //   (2*Q*cos(w0) +/- sqrt(1-4*Q^2)*sin(w0))/(2*Q + sin(w0))
+      //
+      // Thus, if 1-4*Q^2 < 0, the poles are complex.  For 1-4*Q^2 > 0, the
+      // poles are real and distinct.  For 1-4*Q^2 = 0, there are two identical
+      // real poles.
+
+      // Array of tests to run.  |descripton| is the task description for
+      // audit.define.  |parameters| is option for |testTailTime|.
+      let tests = [
+        {
+          descripton:
+              {label: 'notch-complex-roots', description: 'complex roots'},
+          parameters: {
+            prefix: 'Notch complex roots',
+            filterOptions: {type: 'notch', Q: 200, frequency: sampleRate / 4},
+            // Node computed tail frame is 2039.5 frames, which matches the
+            // actual tail, so tail output should be exactly zero.
+            threshold: 0
+          },
+        },
+        {
+          descripton: {
+            label: 'notch-real-distinct-roots',
+            description: 'real distinct roots'
+          },
+          parameters: {
+            prefix: 'Notch real distinct roots',
+            filterOptions: {type: 'notch', Q: 0.001, frequency: sampleRate / 4},
+            // Node computed tail frame is 2437 frames, which matches the actual
+            // tail, so tail output should be exactly zero.
+            threshold: 0
+          },
+        },
+        {
+          descripton: {
+            label: 'notch-repeated-roots',
+            description: 'repeated real root'
+          },
+          parameters: {
+            prefix: 'Notch repeated roots',
+            // Note that while the roots are mathematically repeated,
+            // numerical roundoff in compute the filter coefficients causes
+            // the resulting filter to have roots at 0 and 6.123e-17.
+            filterOptions: {type: 'notch', Q: 0.5, frequency: sampleRate / 4},
+            // Node computed tail frame is 2 frames, which matches the actual
+            // tail, so tail output should be exactly zero.
+            threshold: 0
+          }
+        },
+      ];
+
+      // Define an appropriate task for each test.
+      tests.forEach(entry => {
+        audit.define(entry.descripton, (task, should) => {
+          let context = new OfflineAudioContext(1, renderFrames, sampleRate);
+          testTailTime(should, context, entry.parameters)
+              .then(() => task.done());
+        });
+      });
+
+      audit.run();
+    </script>
+  </body>
+</html>
diff --git a/third_party/WebKit/LayoutTests/webaudio/BiquadFilter/tail-time-peaking.html b/third_party/WebKit/LayoutTests/webaudio/BiquadFilter/tail-time-peaking.html
new file mode 100644
index 0000000..973d8361
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/webaudio/BiquadFilter/tail-time-peaking.html
@@ -0,0 +1,115 @@
+<!doctype html>
+<html>
+  <head>
+    <title>Test Biquad Tail-Time</title>
+    <script src="../../resources/testharness.js"></script>
+    <script src="../../resources/testharnessreport.js"></script>
+    <script src="../resources/audit-util.js"></script>
+    <script src="../resources/audit.js"></script>
+    <script src="../resources/biquad-filters.js"></script>
+    <script src="test-tail-time.js"></script>
+  </head>
+
+  <body>
+    <script>
+      let audit = Audit.createTaskRunner();
+
+      let sampleRate = 16384;
+      let renderSeconds = 1;
+      let renderFrames = renderSeconds * sampleRate;
+
+      // For a peaking filter:
+      //   b0 = 1 - alpha*A
+      //   b1 = -2*cos(w0)
+      //   b2 = 1 + alpha*A
+      //   a0 = 1 + alpha/A
+      //   a1 = -2*cos(w0)
+      //   a2 = 1 - alpha/A
+      //
+      // where alpha = sin(w0)/(2*Q), w0 = 2*%pi*f0/Fs, and A = 10^(G/40)
+      //
+      // Equivalently a1 = -2*cos(w0)/(1+alpha/A), a2 = (1-alpha/A)/(1+alpha/A).
+      // The poles of this filter are at
+      //
+      //   A*cos(w0)/(A + alpha) +/- sqrt(alpha^2-A^2*sin(w0)^2)/(A + alpha)
+      //
+      // But alpha^2-A^2*sin(w0)^2 = sin(w0)^2*(1/4/Q^2-1).
+      // Thus, the poles are complex if 1/(4*Q^2) < A^2; real and distinct if
+      // 1/(4*Q^2)>A^2; and repeated if 1/(4*Q^2) = A^2 or w0 = 0.
+
+      // Array of tests to run.  |descripton| is the task description for
+      // audit.define.  |parameters| is option for |testTailTime|.
+      let tests = [
+        {
+          descripton:
+              {label: 'peaking-complex-roots', description: 'complex roots'},
+          parameters: {
+            prefix: 'Peaking complex roots',
+            // A gain of 40 gives A = 10.
+            filterOptions:
+                {type: 'peaking', Q: 10, gain: 40, frequency: sampleRate / 4},
+            // Node computed tail frame is 2077.4 frames, which matches the
+            // actual tail, so tail output should be exactly zero.
+            threshold: 0
+          }
+        },
+        {
+          descripton: {
+            label: 'peaking-real-distinct-roots',
+            description: 'real distinct roots'
+          },
+          parameters: {
+            prefix: 'Peaking real distinct roots',
+            filterOptions: {
+              type: 'peaking',
+              Q: 0.001,
+              gain: 40,
+              frequency: sampleRate / 4
+            },
+            // Node computed tail frame is 588 frames, which matches the actual
+            // tail, so tail output should be exactly zero.
+            threshold: 0
+          }
+        },
+        {
+          descripton: {
+            label: 'peaking-repeated-roots',
+            description: 'repeated real root'
+          },
+          parameters: {
+            prefix: 'Peaking repeated roots',
+            filterOptions:
+                {type: 'peaking', Q: 1 / 2, gain: 0, frequency: sampleRate / 8},
+            // Node computed tail frame is 0 frames, which matches the actual
+            // tail, so tail output should be exactly zero.
+            threshold: 0
+
+          }
+        },
+        {
+          descripton: {
+            label: 'peaking-repeated-roots 2',
+            description: 'repeated real root'
+          },
+          parameters: {
+            prefix: 'Peaking repeated roots 2',
+            filterOptions: {type: 'peaking', Q: 1, gain: 40, frequency: 0},
+            // Node computed tail frame is 1 frames, which matches the actual
+            // tail, so tail output should be exactly zero.
+            threshold: 0
+          }
+        }
+      ];
+
+      // Define an appropriate task for each test.
+      tests.forEach(entry => {
+        audit.define(entry.descripton, (task, should) => {
+          let context = new OfflineAudioContext(1, renderFrames, sampleRate);
+          testTailTime(should, context, entry.parameters).then(() => task.done());
+        });
+      });
+
+      audit.run();
+    </script>
+  </body>
+</html>
diff --git a/third_party/WebKit/LayoutTests/webaudio/BiquadFilter/test-tail-time.js b/third_party/WebKit/LayoutTests/webaudio/BiquadFilter/test-tail-time.js
new file mode 100644
index 0000000..94f1449
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/webaudio/BiquadFilter/test-tail-time.js
@@ -0,0 +1,90 @@
+function testTailTime(should, context, options) {
+  let src = new ConstantSourceNode(context, {offset: 1});
+  let f = new BiquadFilterNode(context, options.filterOptions);
+
+  src.connect(f).connect(context.destination);
+  src.start();
+  src.stop(1 / context.sampleRate);
+
+  let expectedTailFrame = computeTailFrame(f);
+
+  // The internal Biquad time computation limits he tail time to a
+  // maximum of 30 sec. We need to limit the computed tail frame to
+  // that limit as well.
+  expectedTailFrame = Math.min(expectedTailFrame, 30 * context.sampleRate);
+
+  return context.startRendering().then(renderedBuffer => {
+    let s = renderedBuffer.getChannelData(0);
+    let prefix = options.prefix + ': Biquad(' +
+        JSON.stringify(options.filterOptions) + ')';
+
+    // Round actual tail frame to a render boundary
+    let quantumIndex = Math.floor(expectedTailFrame / RENDER_QUANTUM_FRAMES);
+    let expectedTailBoundary = RENDER_QUANTUM_FRAMES * quantumIndex;
+
+    // Find the actual tail frame.  That is, the last point where the
+    // output is not zero.
+    let actualTailFrame;
+
+    for (actualTailFrame = s.length; actualTailFrame > 0; --actualTailFrame) {
+      if (Math.abs(s[actualTailFrame - 1]) > 0)
+        break;
+    }
+
+    should(actualTailFrame, `${prefix}: Actual Tail Frame ${actualTailFrame}`)
+        .beGreaterThanOrEqualTo(expectedTailFrame);
+
+    // Verify each render quanta is not identically zero up to the
+    // boundary.
+    for (let k = 0; k <= quantumIndex; ++k) {
+      let firstFrame = RENDER_QUANTUM_FRAMES * k;
+      let lastFrame = firstFrame + RENDER_QUANTUM_FRAMES - 1;
+      should(
+          s.slice(firstFrame, lastFrame + 1),
+          `${prefix}: output[${firstFrame}:${lastFrame}]`)
+          .notBeConstantValueOf(0);
+    }
+    // The frames after the tail should be zero.  Because the
+    // implementation uses approximations to simplify the
+    // computations, the nodes tail time may be greater than the real
+    // impulse response tail.  Thus, we just verify that the output
+    // over the tail is less than the tail threshold value.
+    let zero = new Float32Array(s.length);
+    should(
+        s.slice(expectedTailBoundary + RENDER_QUANTUM_FRAMES + 256),
+        prefix + ': output[' +
+            (expectedTailBoundary + RENDER_QUANTUM_FRAMES + 256) + ':]')
+        .beCloseToArray(
+            zero.slice(expectedTailBoundary + RENDER_QUANTUM_FRAMES + 256),
+            {absoluteThreshold: options.threshold || 0});
+  })
+}
+
+function computeTailFrame(filterNode) {
+  // Compute the impuluse response for the filter |filterNode| by
+  // filtering the impulse directly ourself.
+  let coef = createFilter(
+      filterNode.type,
+      filterNode.frequency.value / filterNode.context.sampleRate * 2,
+      filterNode.Q.value, filterNode.gain.value);
+
+  let impulse = new Float32Array(filterNode.context.length);
+  impulse[0] = 1;
+
+  let filtered = filterData(coef, impulse, impulse.length);
+
+  // Compute the magnitude and find out where the imuplse is small enough.
+  let tailFrame = 0;
+  if (Math.abs(filtered[filtered.length - 1]) >= 1 / 32768) {
+    tailFrame = filtered.length - 1;
+  } else {
+    for (let k = filtered.length - 1; k >= 0; --k) {
+      if (Math.abs(filtered[k]) >= 1 / 32768) {
+        tailFrame = k + 1;
+        break;
+      }
+    }
+  }
+
+  return tailFrame;
+}
diff --git a/third_party/WebKit/LayoutTests/webaudio/resources/audit-util.js b/third_party/WebKit/LayoutTests/webaudio/resources/audit-util.js
index 671bcf1..1e39c87 100644
--- a/third_party/WebKit/LayoutTests/webaudio/resources/audit-util.js
+++ b/third_party/WebKit/LayoutTests/webaudio/resources/audit-util.js
@@ -8,6 +8,8 @@
  *                test.
  */
 
+// How many frames in a WebAudio render quantum.
+let RENDER_QUANTUM_FRAMES = 128;
 
 function writeString(s, a, offset) {
   for (let i = 0; i < s.length; ++i) {
diff --git a/third_party/WebKit/Source/core/dom/Document.cpp b/third_party/WebKit/Source/core/dom/Document.cpp
index fd004e14..9f5222e9 100644
--- a/third_party/WebKit/Source/core/dom/Document.cpp
+++ b/third_party/WebKit/Source/core/dom/Document.cpp
@@ -1748,7 +1748,7 @@
     return true;
   if (ChildNeedsStyleInvalidation())
     return true;
-  if (GetLayoutViewItem().WasNotifiedOfSubtreeChange())
+  if (GetLayoutView() && GetLayoutView()->WasNotifiedOfSubtreeChange())
     return true;
   return false;
 }
diff --git a/third_party/WebKit/Source/core/exported/WebFactory.h b/third_party/WebKit/Source/core/exported/WebFactory.h
index 49a4385..db544cc 100644
--- a/third_party/WebKit/Source/core/exported/WebFactory.h
+++ b/third_party/WebKit/Source/core/exported/WebFactory.h
@@ -19,15 +19,16 @@
 // This class will be removed once all implementations are in core/ or modules/.
 class CORE_EXPORT WebFactory {
  public:
-  // Takes ownership of |factory|.
-  // TODO(sashab): Make this method private to WebKit.cpp.
-  static void SetInstance(WebFactory&);
   static WebFactory& GetInstance();
 
   virtual ChromeClient* CreateChromeClient(WebViewBase*) const = 0;
   virtual WebViewBase* CreateWebViewBase(WebViewClient*,
                                          WebPageVisibilityState) const = 0;
 
+ protected:
+  // Takes ownership of |factory|.
+  static void SetInstance(WebFactory&);
+
  private:
   static WebFactory* factory_instance_;
 };
diff --git a/third_party/WebKit/Source/core/frame/ResizeViewportAnchor.cpp b/third_party/WebKit/Source/core/frame/ResizeViewportAnchor.cpp
index c57caf71..ca19c476 100644
--- a/third_party/WebKit/Source/core/frame/ResizeViewportAnchor.cpp
+++ b/third_party/WebKit/Source/core/frame/ResizeViewportAnchor.cpp
@@ -15,8 +15,8 @@
 
 void ResizeViewportAnchor::ResizeFrameView(IntSize size) {
   LocalFrameView* frame_view = RootFrameView();
-  // TODO(szager): Remove this CHECK if it doesn't show up in crash reports.
-  CHECK(frame_view);
+  if (!frame_view)
+    return;
 
   ScrollableArea* root_viewport = frame_view->GetScrollableArea();
   ScrollOffset offset = root_viewport->GetScrollOffset();
diff --git a/third_party/WebKit/Source/devtools/front_end/Images/src/audits_logo_bw.svg b/third_party/WebKit/Source/devtools/front_end/Images/src/audits_logo_bw.svg
deleted file mode 100644
index a4958e2..0000000
--- a/third_party/WebKit/Source/devtools/front_end/Images/src/audits_logo_bw.svg
+++ /dev/null
@@ -1,5 +0,0 @@
-<?xml version="1.0" encoding="UTF-8" standalone="no"?>
-<svg xmlns="http://www.w3.org/2000/svg" width="96" height="96" viewBox="0 0 48 48">
-  <title>audits_logo_48_final</title>
-  <path d="M33 11c0-1.674-1.827-3.134-4.538-3.909a4.5 4.5 0 1 0-8.923 0C16.826 7.866 15 9.326 15 11h18zM16.97 6h-5.974A2.997 2.997 0 0 0 8 9.007v33.986A2.999 2.999 0 0 0 10.996 46h26.008A2.997 2.997 0 0 0 40 42.993V9.007A2.999 2.999 0 0 0 37.004 6h-5.975c1.584.778 2.793 1.815 3.44 3h.534C36.106 9 37 9.892 37 11v30c0 1.105-.895 2-1.997 2H12.997A1.996 1.996 0 0 1 11 41V11c0-1.105.895-2 1.997-2h.534c.647-1.185 1.856-2.222 3.44-3zm4.305 25.62l1.058 1.082 1.073-1.067 9.114-9.072-2.116-2.126-8.036 8.01-3.295-3.371-2.146 2.097 4.348 4.447zM24 8a1.5 1.5 0 1 0 0-3 1.5 1.5 0 0 0 0 3z" fill="#CCC" fill-rule="evenodd" />
-</svg>
diff --git a/third_party/WebKit/Source/devtools/front_end/Images/src/optimize_png.hashes b/third_party/WebKit/Source/devtools/front_end/Images/src/optimize_png.hashes
index 71cf093..d5471cee 100644
--- a/third_party/WebKit/Source/devtools/front_end/Images/src/optimize_png.hashes
+++ b/third_party/WebKit/Source/devtools/front_end/Images/src/optimize_png.hashes
@@ -8,6 +8,5 @@
     "mediumIcons.svg": "e63ac6385b0a6efb783d9838517e5e44",
     "breakpoint.svg": "69cd92d807259c022791112809b97799",
     "treeoutlineTriangles.svg": "017d2f89437df0afc6b9cd5ff43735d9",
-    "audits_logo_bw.svg": "203dcb2ba32ef0f4595ad45bb8feffab",
-    "chevrons.svg": "79b4b527771e30b6388ce664077b3409",
+    "chevrons.svg": "79b4b527771e30b6388ce664077b3409"
 }
diff --git a/third_party/WebKit/Source/devtools/front_end/Images/src/svg2png.hashes b/third_party/WebKit/Source/devtools/front_end/Images/src/svg2png.hashes
index 71cf093..0e2cd86 100644
--- a/third_party/WebKit/Source/devtools/front_end/Images/src/svg2png.hashes
+++ b/third_party/WebKit/Source/devtools/front_end/Images/src/svg2png.hashes
@@ -8,6 +8,5 @@
     "mediumIcons.svg": "e63ac6385b0a6efb783d9838517e5e44",
     "breakpoint.svg": "69cd92d807259c022791112809b97799",
     "treeoutlineTriangles.svg": "017d2f89437df0afc6b9cd5ff43735d9",
-    "audits_logo_bw.svg": "203dcb2ba32ef0f4595ad45bb8feffab",
-    "chevrons.svg": "79b4b527771e30b6388ce664077b3409",
-}
+    "chevrons.svg": "79b4b527771e30b6388ce664077b3409"
+}
\ No newline at end of file
diff --git a/third_party/WebKit/Source/modules/indexeddb/IDBCursor.cpp b/third_party/WebKit/Source/modules/indexeddb/IDBCursor.cpp
index edd99eee..cdc551f7 100644
--- a/third_party/WebKit/Source/modules/indexeddb/IDBCursor.cpp
+++ b/third_party/WebKit/Source/modules/indexeddb/IDBCursor.cpp
@@ -102,8 +102,7 @@
 IDBRequest* IDBCursor::update(ScriptState* script_state,
                               const ScriptValue& value,
                               ExceptionState& exception_state) {
-  IDB_TRACE("IDBCursor::update");
-
+  IDB_TRACE("IDBCursor::updateRequestSetup");
   if (!transaction_->IsActive()) {
     exception_state.ThrowDOMException(kTransactionInactiveError,
                                       transaction_->InactiveErrorMessage());
@@ -138,7 +137,8 @@
 }
 
 void IDBCursor::advance(unsigned count, ExceptionState& exception_state) {
-  IDB_TRACE("IDBCursor::advance");
+  IDB_TRACE("IDBCursor::advanceRequestSetup");
+  IDBRequest::AsyncTraceState metrics("IDBCursor::advance", this);
   if (!count) {
     exception_state.ThrowTypeError(
         "A count argument with value 0 (zero) was supplied, must be greater "
@@ -162,6 +162,7 @@
   }
 
   request_->SetPendingCursor(this);
+  request_->AssignNewMetrics(std::move(metrics));
   got_value_ = false;
   backend_->Advance(count, request_->CreateWebCallbacks().release());
 }
@@ -169,7 +170,8 @@
 void IDBCursor::continueFunction(ScriptState* script_state,
                                  const ScriptValue& key_value,
                                  ExceptionState& exception_state) {
-  IDB_TRACE("IDBCursor::continue");
+  IDB_TRACE("IDBCursor::continueRequestSetup");
+  IDBRequest::AsyncTraceState metrics("IDBCursor::continue", this);
 
   if (!transaction_->IsActive()) {
     exception_state.ThrowDOMException(kTransactionInactiveError,
@@ -198,14 +200,15 @@
                                       IDBDatabase::kNotValidKeyErrorMessage);
     return;
   }
-  Continue(key, nullptr, exception_state);
+  Continue(key, nullptr, std::move(metrics), exception_state);
 }
 
 void IDBCursor::continuePrimaryKey(ScriptState* script_state,
                                    const ScriptValue& key_value,
                                    const ScriptValue& primary_key_value,
                                    ExceptionState& exception_state) {
-  IDB_TRACE("IDBCursor::continuePrimaryKey");
+  IDB_TRACE("IDBCursor::continuePrimaryKeyRequestSetup");
+  IDBRequest::AsyncTraceState metrics("IDBCursor::continuePrimaryKey", this);
 
   if (!transaction_->IsActive()) {
     exception_state.ThrowDOMException(kTransactionInactiveError,
@@ -258,11 +261,12 @@
     return;
   }
 
-  Continue(key, primary_key, exception_state);
+  Continue(key, primary_key, std::move(metrics), exception_state);
 }
 
 void IDBCursor::Continue(IDBKey* key,
                          IDBKey* primary_key,
+                         IDBRequest::AsyncTraceState metrics,
                          ExceptionState& exception_state) {
   DCHECK(transaction_->IsActive());
   DCHECK(got_value_);
@@ -300,6 +304,7 @@
   // means the callback will be on the original context openCursor was called
   // on. Is this right?
   request_->SetPendingCursor(this);
+  request_->AssignNewMetrics(std::move(metrics));
   got_value_ = false;
   backend_->Continue(key, primary_key,
                      request_->CreateWebCallbacks().release());
@@ -307,7 +312,8 @@
 
 IDBRequest* IDBCursor::deleteFunction(ScriptState* script_state,
                                       ExceptionState& exception_state) {
-  IDB_TRACE("IDBCursor::delete");
+  IDB_TRACE("IDBCursor::deleteRequestSetup");
+  IDBRequest::AsyncTraceState metrics("IDBCursor::delete", this);
   if (!transaction_->IsActive()) {
     exception_state.ThrowDOMException(kTransactionInactiveError,
                                       transaction_->InactiveErrorMessage());
@@ -343,8 +349,9 @@
   IDBKeyRange* key_range = IDBKeyRange::only(primary_key_, exception_state);
   DCHECK(!exception_state.HadException());
 
-  IDBRequest* request = IDBRequest::Create(script_state, IDBAny::Create(this),
-                                           transaction_.Get());
+  IDBRequest* request =
+      IDBRequest::Create(script_state, IDBAny::Create(this), transaction_.Get(),
+                         std::move(metrics));
   transaction_->BackendDB()->DeleteRange(
       transaction_->Id(), EffectiveObjectStore()->Id(), key_range,
       request->CreateWebCallbacks().release());
diff --git a/third_party/WebKit/Source/modules/indexeddb/IDBCursor.h b/third_party/WebKit/Source/modules/indexeddb/IDBCursor.h
index 5c60148c..8483405 100644
--- a/third_party/WebKit/Source/modules/indexeddb/IDBCursor.h
+++ b/third_party/WebKit/Source/modules/indexeddb/IDBCursor.h
@@ -87,7 +87,10 @@
   bool isPrimaryKeyDirty() const { return primary_key_dirty_; }
   bool isValueDirty() const { return value_dirty_; }
 
-  void Continue(IDBKey*, IDBKey* primary_key, ExceptionState&);
+  void Continue(IDBKey*,
+                IDBKey* primary_key,
+                IDBRequest::AsyncTraceState,
+                ExceptionState&);
   void PostSuccessHandlerCallback();
   bool IsDeleted() const;
   void Close();
diff --git a/third_party/WebKit/Source/modules/indexeddb/IDBFactory.cpp b/third_party/WebKit/Source/modules/indexeddb/IDBFactory.cpp
index 29c07634..8af2527d 100644
--- a/third_party/WebKit/Source/modules/indexeddb/IDBFactory.cpp
+++ b/third_party/WebKit/Source/modules/indexeddb/IDBFactory.cpp
@@ -65,6 +65,10 @@
 
 IDBRequest* IDBFactory::GetDatabaseNames(ScriptState* script_state,
                                          ExceptionState& exception_state) {
+  IDB_TRACE("IDBFactory::getDatabaseNamesRequestSetup");
+  IDBRequest::AsyncTraceState metrics("IDBFactory::getDatabaseNames", this);
+  IDBRequest* request = IDBRequest::Create(script_state, IDBAny::CreateNull(),
+                                           nullptr, std::move(metrics));
   // TODO(jsbell): Used only by inspector; remove unneeded checks/exceptions?
   if (!IsContextValid(ExecutionContext::From(script_state)))
     return nullptr;
@@ -76,9 +80,6 @@
     return nullptr;
   }
 
-  IDBRequest* request =
-      IDBRequest::Create(script_state, IDBAny::CreateNull(), nullptr);
-
   if (!IndexedDBClient::From(ExecutionContext::From(script_state))
            ->AllowIndexedDB(ExecutionContext::From(script_state),
                             "Database Listing")) {
diff --git a/third_party/WebKit/Source/modules/indexeddb/IDBIndex.cpp b/third_party/WebKit/Source/modules/indexeddb/IDBIndex.cpp
index 17d620a..39b2f9a 100644
--- a/third_party/WebKit/Source/modules/indexeddb/IDBIndex.cpp
+++ b/third_party/WebKit/Source/modules/indexeddb/IDBIndex.cpp
@@ -115,7 +115,8 @@
                                  const ScriptValue& range,
                                  const String& direction_string,
                                  ExceptionState& exception_state) {
-  IDB_TRACE("IDBIndex::openCursor");
+  IDB_TRACE("IDBIndex::openCursorRequestSetup");
+  IDBRequest::AsyncTraceState metrics("IDBIndex::openCursor", this);
   if (IsDeleted()) {
     exception_state.ThrowDOMException(kInvalidStateError,
                                       IDBDatabase::kIndexDeletedErrorMessage);
@@ -139,14 +140,16 @@
     return nullptr;
   }
 
-  return openCursor(script_state, key_range, direction);
+  return openCursor(script_state, key_range, direction, std::move(metrics));
 }
 
 IDBRequest* IDBIndex::openCursor(ScriptState* script_state,
                                  IDBKeyRange* key_range,
-                                 WebIDBCursorDirection direction) {
-  IDBRequest* request = IDBRequest::Create(script_state, IDBAny::Create(this),
-                                           transaction_.Get());
+                                 WebIDBCursorDirection direction,
+                                 IDBRequest::AsyncTraceState metrics) {
+  IDBRequest* request =
+      IDBRequest::Create(script_state, IDBAny::Create(this), transaction_.Get(),
+                         std::move(metrics));
   request->SetCursorDetails(IndexedDB::kCursorKeyAndValue, direction);
   BackendDB()->OpenCursor(transaction_->Id(), object_store_->Id(), Id(),
                           key_range, direction, false, kWebIDBTaskTypeNormal,
@@ -157,7 +160,8 @@
 IDBRequest* IDBIndex::count(ScriptState* script_state,
                             const ScriptValue& range,
                             ExceptionState& exception_state) {
-  IDB_TRACE("IDBIndex::count");
+  IDB_TRACE("IDBIndex::countRequestSetup");
+  IDBRequest::AsyncTraceState metrics("IDBIndex::count", this);
   if (IsDeleted()) {
     exception_state.ThrowDOMException(kInvalidStateError,
                                       IDBDatabase::kIndexDeletedErrorMessage);
@@ -180,8 +184,9 @@
     return nullptr;
   }
 
-  IDBRequest* request = IDBRequest::Create(script_state, IDBAny::Create(this),
-                                           transaction_.Get());
+  IDBRequest* request =
+      IDBRequest::Create(script_state, IDBAny::Create(this), transaction_.Get(),
+                         std::move(metrics));
   BackendDB()->Count(transaction_->Id(), object_store_->Id(), Id(), key_range,
                      request->CreateWebCallbacks().release());
   return request;
@@ -191,7 +196,8 @@
                                     const ScriptValue& range,
                                     const String& direction_string,
                                     ExceptionState& exception_state) {
-  IDB_TRACE("IDBIndex::openKeyCursor");
+  IDB_TRACE("IDBIndex::openKeyCursorRequestSetup");
+  IDBRequest::AsyncTraceState metrics("IDBIndex::openKeyCursor", this);
   if (IsDeleted()) {
     exception_state.ThrowDOMException(kInvalidStateError,
                                       IDBDatabase::kIndexDeletedErrorMessage);
@@ -214,8 +220,9 @@
     return nullptr;
   }
 
-  IDBRequest* request = IDBRequest::Create(script_state, IDBAny::Create(this),
-                                           transaction_.Get());
+  IDBRequest* request =
+      IDBRequest::Create(script_state, IDBAny::Create(this), transaction_.Get(),
+                         std::move(metrics));
   request->SetCursorDetails(IndexedDB::kCursorKeyOnly, direction);
   BackendDB()->OpenCursor(transaction_->Id(), object_store_->Id(), Id(),
                           key_range, direction, true, kWebIDBTaskTypeNormal,
@@ -226,7 +233,7 @@
 IDBRequest* IDBIndex::get(ScriptState* script_state,
                           const ScriptValue& key,
                           ExceptionState& exception_state) {
-  IDB_TRACE("IDBIndex::get");
+  IDB_TRACE("IDBIndex::getRequestSetup");
   return GetInternal(script_state, key, exception_state, false);
 }
 
@@ -241,7 +248,7 @@
                              const ScriptValue& range,
                              unsigned long max_count,
                              ExceptionState& exception_state) {
-  IDB_TRACE("IDBIndex::getAll");
+  IDB_TRACE("IDBIndex::getAllRequestSetup");
   return GetAllInternal(script_state, range, max_count, exception_state, false);
 }
 
@@ -256,7 +263,7 @@
                                  const ScriptValue& range,
                                  uint32_t max_count,
                                  ExceptionState& exception_state) {
-  IDB_TRACE("IDBIndex::getAllKeys");
+  IDB_TRACE("IDBIndex::getAllKeysRequestSetup");
   return GetAllInternal(script_state, range, max_count, exception_state,
                         /*key_only=*/true);
 }
@@ -264,7 +271,7 @@
 IDBRequest* IDBIndex::getKey(ScriptState* script_state,
                              const ScriptValue& key,
                              ExceptionState& exception_state) {
-  IDB_TRACE("IDBIndex::getKey");
+  IDB_TRACE("IDBIndex::getKeyRequestSetup");
   return GetInternal(script_state, key, exception_state, true);
 }
 
@@ -272,6 +279,8 @@
                                   const ScriptValue& key,
                                   ExceptionState& exception_state,
                                   bool key_only) {
+  IDBRequest::AsyncTraceState metrics(
+      key_only ? "IDBIndex::getKey" : "IDBIndex::get", this);
   if (IsDeleted()) {
     exception_state.ThrowDOMException(kInvalidStateError,
                                       IDBDatabase::kIndexDeletedErrorMessage);
@@ -298,8 +307,9 @@
     return nullptr;
   }
 
-  IDBRequest* request = IDBRequest::Create(script_state, IDBAny::Create(this),
-                                           transaction_.Get());
+  IDBRequest* request =
+      IDBRequest::Create(script_state, IDBAny::Create(this), transaction_.Get(),
+                         std::move(metrics));
   BackendDB()->Get(transaction_->Id(), object_store_->Id(), Id(), key_range,
                    key_only, request->CreateWebCallbacks().release());
   return request;
@@ -310,6 +320,8 @@
                                      unsigned long max_count,
                                      ExceptionState& exception_state,
                                      bool key_only) {
+  IDBRequest::AsyncTraceState metrics(
+      key_only ? "IDBIndex::getAllKeys" : "IDBIndex::getAll", this);
   if (!max_count)
     max_count = std::numeric_limits<uint32_t>::max();
 
@@ -334,8 +346,9 @@
     return nullptr;
   }
 
-  IDBRequest* request = IDBRequest::Create(script_state, IDBAny::Create(this),
-                                           transaction_.Get());
+  IDBRequest* request =
+      IDBRequest::Create(script_state, IDBAny::Create(this), transaction_.Get(),
+                         std::move(metrics));
   BackendDB()->GetAll(transaction_->Id(), object_store_->Id(), Id(), key_range,
                       max_count, key_only,
                       request->CreateWebCallbacks().release());
diff --git a/third_party/WebKit/Source/modules/indexeddb/IDBIndex.h b/third_party/WebKit/Source/modules/indexeddb/IDBIndex.h
index 1fc714e..1338bcc 100644
--- a/third_party/WebKit/Source/modules/indexeddb/IDBIndex.h
+++ b/third_party/WebKit/Source/modules/indexeddb/IDBIndex.h
@@ -111,7 +111,11 @@
   void RevertMetadata(RefPtr<IDBIndexMetadata> old_metadata);
 
   // Used internally and by InspectorIndexedDBAgent:
-  IDBRequest* openCursor(ScriptState*, IDBKeyRange*, WebIDBCursorDirection);
+  IDBRequest* openCursor(
+      ScriptState*,
+      IDBKeyRange*,
+      WebIDBCursorDirection,
+      IDBRequest::AsyncTraceState = IDBRequest::AsyncTraceState());
 
   WebIDBDatabase* BackendDB() const;
 
diff --git a/third_party/WebKit/Source/modules/indexeddb/IDBObjectStore.cpp b/third_party/WebKit/Source/modules/indexeddb/IDBObjectStore.cpp
index 3ee7671c..ae56bd5 100644
--- a/third_party/WebKit/Source/modules/indexeddb/IDBObjectStore.cpp
+++ b/third_party/WebKit/Source/modules/indexeddb/IDBObjectStore.cpp
@@ -44,6 +44,7 @@
 #include "platform/Histogram.h"
 #include "platform/SharedBuffer.h"
 #include "platform/bindings/ScriptState.h"
+#include "platform/wtf/PtrUtil.h"
 #include "platform/wtf/RefPtr.h"
 #include "public/platform/WebBlobInfo.h"
 #include "public/platform/WebData.h"
@@ -129,7 +130,8 @@
 IDBRequest* IDBObjectStore::get(ScriptState* script_state,
                                 const ScriptValue& key,
                                 ExceptionState& exception_state) {
-  IDB_TRACE("IDBObjectStore::get");
+  IDB_TRACE("IDBObjectStore::getRequestSetup");
+  IDBRequest::AsyncTraceState metrics("IDBObjectStore::get", this);
   if (IsDeleted()) {
     exception_state.ThrowDOMException(
         kInvalidStateError, IDBDatabase::kObjectStoreDeletedErrorMessage);
@@ -155,8 +157,9 @@
     return nullptr;
   }
 
-  IDBRequest* request = IDBRequest::Create(script_state, IDBAny::Create(this),
-                                           transaction_.Get());
+  IDBRequest* request =
+      IDBRequest::Create(script_state, IDBAny::Create(this), transaction_.Get(),
+                         std::move(metrics));
   BackendDB()->Get(transaction_->Id(), Id(), IDBIndexMetadata::kInvalidId,
                    key_range, /*key_only=*/false,
                    request->CreateWebCallbacks().release());
@@ -166,7 +169,8 @@
 IDBRequest* IDBObjectStore::getKey(ScriptState* script_state,
                                    const ScriptValue& key,
                                    ExceptionState& exception_state) {
-  IDB_TRACE("IDBObjectStore::getKey");
+  IDB_TRACE("IDBObjectStore::getKeyRequestSetup");
+  IDBRequest::AsyncTraceState metrics("IDBObjectStore::getKey", this);
   if (IsDeleted()) {
     exception_state.ThrowDOMException(
         kInvalidStateError, IDBDatabase::kObjectStoreDeletedErrorMessage);
@@ -192,8 +196,9 @@
     return nullptr;
   }
 
-  IDBRequest* request = IDBRequest::Create(script_state, IDBAny::Create(this),
-                                           transaction_.Get());
+  IDBRequest* request =
+      IDBRequest::Create(script_state, IDBAny::Create(this), transaction_.Get(),
+                         std::move(metrics));
   BackendDB()->Get(transaction_->Id(), Id(), IDBIndexMetadata::kInvalidId,
                    key_range, /*key_only=*/true,
                    request->CreateWebCallbacks().release());
@@ -211,7 +216,8 @@
                                    const ScriptValue& key_range,
                                    unsigned long max_count,
                                    ExceptionState& exception_state) {
-  IDB_TRACE("IDBObjectStore::getAll");
+  IDB_TRACE("IDBObjectStore::getAllRequestSetup");
+  IDBRequest::AsyncTraceState metrics("IDBObjectStore::getAll", this);
   if (!max_count)
     max_count = std::numeric_limits<uint32_t>::max();
 
@@ -235,8 +241,9 @@
     return nullptr;
   }
 
-  IDBRequest* request = IDBRequest::Create(script_state, IDBAny::Create(this),
-                                           transaction_.Get());
+  IDBRequest* request =
+      IDBRequest::Create(script_state, IDBAny::Create(this), transaction_.Get(),
+                         std::move(metrics));
   BackendDB()->GetAll(transaction_->Id(), Id(), IDBIndexMetadata::kInvalidId,
                       range, max_count, false,
                       request->CreateWebCallbacks().release());
@@ -254,7 +261,8 @@
                                        const ScriptValue& key_range,
                                        unsigned long max_count,
                                        ExceptionState& exception_state) {
-  IDB_TRACE("IDBObjectStore::getAll");
+  IDB_TRACE("IDBObjectStore::getAllKeysRequestSetup");
+  IDBRequest::AsyncTraceState metrics("IDBObjectStore::getAllKeys", this);
   if (!max_count)
     max_count = std::numeric_limits<uint32_t>::max();
 
@@ -278,8 +286,9 @@
     return nullptr;
   }
 
-  IDBRequest* request = IDBRequest::Create(script_state, IDBAny::Create(this),
-                                           transaction_.Get());
+  IDBRequest* request =
+      IDBRequest::Create(script_state, IDBAny::Create(this), transaction_.Get(),
+                         std::move(metrics));
   BackendDB()->GetAll(transaction_->Id(), Id(), IDBIndexMetadata::kInvalidId,
                       range, max_count, true,
                       request->CreateWebCallbacks().release());
@@ -324,7 +333,7 @@
                                 const ScriptValue& value,
                                 const ScriptValue& key,
                                 ExceptionState& exception_state) {
-  IDB_TRACE("IDBObjectStore::add");
+  IDB_TRACE("IDBObjectStore::addRequestSetup");
   return put(script_state, kWebIDBPutModeAddOnly, IDBAny::Create(this), value,
              key, exception_state);
 }
@@ -333,7 +342,7 @@
                                 const ScriptValue& value,
                                 const ScriptValue& key,
                                 ExceptionState& exception_state) {
-  IDB_TRACE("IDBObjectStore::put");
+  IDB_TRACE("IDBObjectStore::putRequestSetup");
   return put(script_state, kWebIDBPutModeAddOrUpdate, IDBAny::Create(this),
              value, key, exception_state);
 }
@@ -359,6 +368,19 @@
                                 const ScriptValue& value,
                                 IDBKey* key,
                                 ExceptionState& exception_state) {
+  const char* tracing_name = nullptr;
+  switch (put_mode) {
+    case kWebIDBPutModeAddOrUpdate:
+      tracing_name = "IDBObjectStore::put";
+      break;
+    case kWebIDBPutModeAddOnly:
+      tracing_name = "IDBObjectStore::add";
+      break;
+    case kWebIDBPutModeCursorUpdate:
+      tracing_name = "IDBCursor::update";
+      break;
+  }
+  IDBRequest::AsyncTraceState metrics(tracing_name, this);
   if (IsDeleted()) {
     exception_state.ThrowDOMException(
         kInvalidStateError, IDBDatabase::kObjectStoreDeletedErrorMessage);
@@ -494,9 +516,11 @@
     index_ids.push_back(it.key);
     index_keys.push_back(keys);
   }
+  UMA_HISTOGRAM_MEMORY_KB("WebCore.IndexedDB.PutValueSize",
+                          value_wrapper.DataLengthBeforeWrapInBytes() / 1024);
 
-  IDBRequest* request =
-      IDBRequest::Create(script_state, source, transaction_.Get());
+  IDBRequest* request = IDBRequest::Create(
+      script_state, source, transaction_.Get(), std::move(metrics));
 
   value_wrapper.ExtractBlobDataHandles(request->transit_blob_handles());
   value_wrapper.WrapIfBiggerThan(IDBValueWrapper::kWrapThreshold);
@@ -513,7 +537,8 @@
 IDBRequest* IDBObjectStore::deleteFunction(ScriptState* script_state,
                                            const ScriptValue& key,
                                            ExceptionState& exception_state) {
-  IDB_TRACE("IDBObjectStore::delete");
+  IDB_TRACE("IDBObjectStore::deleteRequestSetup");
+  IDBRequest::AsyncTraceState metrics("IDBObjectStore::delete", this);
   if (IsDeleted()) {
     exception_state.ThrowDOMException(
         kInvalidStateError, IDBDatabase::kObjectStoreDeletedErrorMessage);
@@ -545,8 +570,9 @@
     return nullptr;
   }
 
-  IDBRequest* request = IDBRequest::Create(script_state, IDBAny::Create(this),
-                                           transaction_.Get());
+  IDBRequest* request =
+      IDBRequest::Create(script_state, IDBAny::Create(this), transaction_.Get(),
+                         std::move(metrics));
   BackendDB()->DeleteRange(transaction_->Id(), Id(), key_range,
                            request->CreateWebCallbacks().release());
   return request;
@@ -554,7 +580,8 @@
 
 IDBRequest* IDBObjectStore::clear(ScriptState* script_state,
                                   ExceptionState& exception_state) {
-  IDB_TRACE("IDBObjectStore::clear");
+  IDB_TRACE("IDBObjectStore::clearRequestSetup");
+  IDBRequest::AsyncTraceState metrics("IDBObjectStore::clear", this);
   if (IsDeleted()) {
     exception_state.ThrowDOMException(
         kInvalidStateError, IDBDatabase::kObjectStoreDeletedErrorMessage);
@@ -576,8 +603,9 @@
     return nullptr;
   }
 
-  IDBRequest* request = IDBRequest::Create(script_state, IDBAny::Create(this),
-                                           transaction_.Get());
+  IDBRequest* request =
+      IDBRequest::Create(script_state, IDBAny::Create(this), transaction_.Get(),
+                         std::move(metrics));
   BackendDB()->Clear(transaction_->Id(), Id(),
                      request->CreateWebCallbacks().release());
   return request;
@@ -629,6 +657,7 @@
   void handleEvent(ExecutionContext* execution_context, Event* event) override {
     if (!script_state_->ContextIsValid())
       return;
+    IDB_TRACE("IDBObjectStore::IndexPopulator::handleEvent");
 
     DCHECK_EQ(ExecutionContext::From(script_state_.Get()), execution_context);
     DCHECK_EQ(event->type(), EventTypeNames::success);
@@ -648,7 +677,9 @@
     Vector<int64_t> index_ids;
     index_ids.push_back(IndexMetadata().id);
     if (cursor && !cursor->IsDeleted()) {
-      cursor->Continue(nullptr, nullptr, ASSERT_NO_EXCEPTION);
+      cursor->Continue(nullptr, nullptr,
+                       IDBRequest::AsyncTraceState("IDBCursor::continue", this),
+                       ASSERT_NO_EXCEPTION);
 
       IDBKey* primary_key = cursor->IdbPrimaryKey();
       ScriptValue value = cursor->value(script_state_.Get());
@@ -685,7 +716,8 @@
                                       const IDBKeyPath& key_path,
                                       const IDBIndexParameters& options,
                                       ExceptionState& exception_state) {
-  IDB_TRACE("IDBObjectStore::createIndex");
+  IDB_TRACE("IDBObjectStore::createIndexRequestSetup");
+  IDBRequest::AsyncTraceState metrics("IDBObjectStore::createIndex", this);
   if (!transaction_->IsVersionChange()) {
     exception_state.ThrowDOMException(
         kInvalidStateError,
@@ -743,7 +775,7 @@
 
   IDBRequest* index_request =
       openCursor(script_state, nullptr, kWebIDBCursorDirectionNext,
-                 kWebIDBTaskTypePreemptive);
+                 kWebIDBTaskTypePreemptive, std::move(metrics));
   index_request->PreventPropagation();
 
   // This is kept alive by being the success handler of the request, which is in
@@ -835,7 +867,8 @@
                                        const ScriptValue& range,
                                        const String& direction_string,
                                        ExceptionState& exception_state) {
-  IDB_TRACE("IDBObjectStore::openCursor");
+  IDB_TRACE("IDBObjectStore::openCursorRequestSetup");
+  IDBRequest::AsyncTraceState metrics("IDBObjectStore::openCursor", this);
   if (IsDeleted()) {
     exception_state.ThrowDOMException(
         kInvalidStateError, IDBDatabase::kObjectStoreDeletedErrorMessage);
@@ -860,15 +893,18 @@
     return nullptr;
   }
 
-  return openCursor(script_state, key_range, direction, kWebIDBTaskTypeNormal);
+  return openCursor(script_state, key_range, direction, kWebIDBTaskTypeNormal,
+                    std::move(metrics));
 }
 
 IDBRequest* IDBObjectStore::openCursor(ScriptState* script_state,
                                        IDBKeyRange* range,
                                        WebIDBCursorDirection direction,
-                                       WebIDBTaskType task_type) {
-  IDBRequest* request = IDBRequest::Create(script_state, IDBAny::Create(this),
-                                           transaction_.Get());
+                                       WebIDBTaskType task_type,
+                                       IDBRequest::AsyncTraceState metrics) {
+  IDBRequest* request =
+      IDBRequest::Create(script_state, IDBAny::Create(this), transaction_.Get(),
+                         std::move(metrics));
   request->SetCursorDetails(IndexedDB::kCursorKeyAndValue, direction);
 
   BackendDB()->OpenCursor(transaction_->Id(), Id(),
@@ -881,7 +917,8 @@
                                           const ScriptValue& range,
                                           const String& direction_string,
                                           ExceptionState& exception_state) {
-  IDB_TRACE("IDBObjectStore::openKeyCursor");
+  IDB_TRACE("IDBObjectStore::openKeyCursorRequestSetup");
+  IDBRequest::AsyncTraceState metrics("IDBObjectStore::openKeyCursor", this);
   if (IsDeleted()) {
     exception_state.ThrowDOMException(
         kInvalidStateError, IDBDatabase::kObjectStoreDeletedErrorMessage);
@@ -906,8 +943,9 @@
     return nullptr;
   }
 
-  IDBRequest* request = IDBRequest::Create(script_state, IDBAny::Create(this),
-                                           transaction_.Get());
+  IDBRequest* request =
+      IDBRequest::Create(script_state, IDBAny::Create(this), transaction_.Get(),
+                         std::move(metrics));
   request->SetCursorDetails(IndexedDB::kCursorKeyOnly, direction);
 
   BackendDB()->OpenCursor(transaction_->Id(), Id(),
@@ -920,7 +958,8 @@
 IDBRequest* IDBObjectStore::count(ScriptState* script_state,
                                   const ScriptValue& range,
                                   ExceptionState& exception_state) {
-  IDB_TRACE("IDBObjectStore::count");
+  IDB_TRACE("IDBObjectStore::countRequestSetup");
+  IDBRequest::AsyncTraceState metrics("IDBObjectStore::count", this);
   if (IsDeleted()) {
     exception_state.ThrowDOMException(
         kInvalidStateError, IDBDatabase::kObjectStoreDeletedErrorMessage);
@@ -943,8 +982,9 @@
     return nullptr;
   }
 
-  IDBRequest* request = IDBRequest::Create(script_state, IDBAny::Create(this),
-                                           transaction_.Get());
+  IDBRequest* request =
+      IDBRequest::Create(script_state, IDBAny::Create(this), transaction_.Get(),
+                         std::move(metrics));
   BackendDB()->Count(transaction_->Id(), Id(), IDBIndexMetadata::kInvalidId,
                      key_range, request->CreateWebCallbacks().release());
   return request;
diff --git a/third_party/WebKit/Source/modules/indexeddb/IDBObjectStore.h b/third_party/WebKit/Source/modules/indexeddb/IDBObjectStore.h
index d88dbc3..f91df7e 100644
--- a/third_party/WebKit/Source/modules/indexeddb/IDBObjectStore.h
+++ b/third_party/WebKit/Source/modules/indexeddb/IDBObjectStore.h
@@ -129,10 +129,12 @@
                   ExceptionState&);
 
   // Used internally and by InspectorIndexedDBAgent:
-  IDBRequest* openCursor(ScriptState*,
-                         IDBKeyRange*,
-                         WebIDBCursorDirection,
-                         WebIDBTaskType = kWebIDBTaskTypeNormal);
+  IDBRequest* openCursor(
+      ScriptState*,
+      IDBKeyRange*,
+      WebIDBCursorDirection,
+      WebIDBTaskType = kWebIDBTaskTypeNormal,
+      IDBRequest::AsyncTraceState = IDBRequest::AsyncTraceState());
 
   void MarkDeleted();
   bool IsDeleted() const { return deleted_; }
diff --git a/third_party/WebKit/Source/modules/indexeddb/IDBOpenDBRequest.cpp b/third_party/WebKit/Source/modules/indexeddb/IDBOpenDBRequest.cpp
index cd8aae0..b4f6cbbb 100644
--- a/third_party/WebKit/Source/modules/indexeddb/IDBOpenDBRequest.cpp
+++ b/third_party/WebKit/Source/modules/indexeddb/IDBOpenDBRequest.cpp
@@ -53,7 +53,10 @@
                                    IDBDatabaseCallbacks* callbacks,
                                    int64_t transaction_id,
                                    int64_t version)
-    : IDBRequest(script_state, IDBAny::CreateNull(), nullptr),
+    : IDBRequest(script_state,
+                 IDBAny::CreateNull(),
+                 nullptr,
+                 IDBRequest::AsyncTraceState()),
       database_callbacks_(callbacks),
       transaction_id_(transaction_id),
       version_(version) {
diff --git a/third_party/WebKit/Source/modules/indexeddb/IDBRequest.cpp b/third_party/WebKit/Source/modules/indexeddb/IDBRequest.cpp
index df734dd4..0f25f71 100644
--- a/third_party/WebKit/Source/modules/indexeddb/IDBRequest.cpp
+++ b/third_party/WebKit/Source/modules/indexeddb/IDBRequest.cpp
@@ -48,6 +48,7 @@
 #include "modules/indexeddb/IDBValue.h"
 #include "modules/indexeddb/IDBValueWrapping.h"
 #include "modules/indexeddb/WebIDBCallbacksImpl.h"
+#include "platform/Histogram.h"
 #include "platform/SharedBuffer.h"
 #include "platform/heap/Handle.h"
 #include "platform/wtf/PtrUtil.h"
@@ -57,10 +58,29 @@
 
 namespace blink {
 
+IDBRequest::AsyncTraceState::AsyncTraceState(const char* tracing_name, void* id)
+    : tracing_name_(tracing_name), id_(id) {
+  if (tracing_name_)
+    TRACE_EVENT_ASYNC_BEGIN0("IndexedDB", tracing_name_, id);
+}
+
+void IDBRequest::AsyncTraceState::RecordAndReset() {
+  if (tracing_name_)
+    TRACE_EVENT_ASYNC_END0("IndexedDB", tracing_name_, id_);
+  tracing_name_ = nullptr;
+}
+
+IDBRequest::AsyncTraceState::~AsyncTraceState() {
+  if (tracing_name_)
+    TRACE_EVENT_ASYNC_END0("IndexedDB", tracing_name_, id_);
+}
+
 IDBRequest* IDBRequest::Create(ScriptState* script_state,
                                IDBAny* source,
-                               IDBTransaction* transaction) {
-  IDBRequest* request = new IDBRequest(script_state, source, transaction);
+                               IDBTransaction* transaction,
+                               IDBRequest::AsyncTraceState metrics) {
+  IDBRequest* request =
+      new IDBRequest(script_state, source, transaction, std::move(metrics));
   request->SuspendIfNeeded();
   // Requests associated with IDBFactory (open/deleteDatabase/getDatabaseNames)
   // do not have an associated transaction.
@@ -71,15 +91,17 @@
 
 IDBRequest::IDBRequest(ScriptState* script_state,
                        IDBAny* source,
-                       IDBTransaction* transaction)
+                       IDBTransaction* transaction,
+                       AsyncTraceState metrics)
     : SuspendableObject(ExecutionContext::From(script_state)),
       transaction_(transaction),
       isolate_(script_state->GetIsolate()),
-      source_(source) {}
+      source_(source),
+      metrics_(std::move(metrics)) {}
 
 IDBRequest::~IDBRequest() {
-  DCHECK(ready_state_ == DONE || ready_state_ == kEarlyDeath ||
-         !GetExecutionContext());
+  DCHECK((ready_state_ == DONE && !metrics_.is_valid()) ||
+         ready_state_ == kEarlyDeath || !GetExecutionContext());
 }
 
 DEFINE_TRACE(IDBRequest) {
@@ -346,24 +368,30 @@
 
 void IDBRequest::EnqueueResponse(DOMException* error) {
   IDB_TRACE("IDBRequest::EnqueueResponse(DOMException)");
-  if (!ShouldEnqueueEvent())
+  if (!ShouldEnqueueEvent()) {
+    metrics_.RecordAndReset();
     return;
+  }
 
   error_ = error;
   SetResult(IDBAny::CreateUndefined());
   pending_cursor_.Clear();
   EnqueueEvent(Event::CreateCancelableBubble(EventTypeNames::error));
+  metrics_.RecordAndReset();
 }
 
 void IDBRequest::EnqueueResponse(const Vector<String>& string_list) {
   IDB_TRACE("IDBRequest::onSuccess(StringList)");
-  if (!ShouldEnqueueEvent())
+  if (!ShouldEnqueueEvent()) {
+    metrics_.RecordAndReset();
     return;
+  }
 
   DOMStringList* dom_string_list = DOMStringList::Create();
   for (size_t i = 0; i < string_list.size(); ++i)
     dom_string_list->Append(string_list[i]);
   EnqueueResultInternal(IDBAny::Create(dom_string_list));
+  metrics_.RecordAndReset();
 }
 
 void IDBRequest::EnqueueResponse(std::unique_ptr<WebIDBCursor> backend,
@@ -371,8 +399,10 @@
                                  IDBKey* primary_key,
                                  RefPtr<IDBValue>&& value) {
   IDB_TRACE("IDBRequest::EnqueueResponse(IDBCursor)");
-  if (!ShouldEnqueueEvent())
+  if (!ShouldEnqueueEvent()) {
+    metrics_.RecordAndReset();
     return;
+  }
 
   DCHECK(!pending_cursor_);
   IDBCursor* cursor = nullptr;
@@ -390,26 +420,33 @@
       NOTREACHED();
   }
   SetResultCursor(cursor, key, primary_key, std::move(value));
+  metrics_.RecordAndReset();
 }
 
 void IDBRequest::EnqueueResponse(IDBKey* idb_key) {
   IDB_TRACE("IDBRequest::EnqueueResponse(IDBKey)");
-  if (!ShouldEnqueueEvent())
+  if (!ShouldEnqueueEvent()) {
+    metrics_.RecordAndReset();
     return;
+  }
 
   if (idb_key && idb_key->IsValid())
     EnqueueResultInternal(IDBAny::Create(idb_key));
   else
     EnqueueResultInternal(IDBAny::CreateUndefined());
+  metrics_.RecordAndReset();
 }
 
 void IDBRequest::EnqueueResponse(const Vector<RefPtr<IDBValue>>& values) {
   IDB_TRACE("IDBRequest::EnqueueResponse([IDBValue])");
-  if (!ShouldEnqueueEvent())
+  if (!ShouldEnqueueEvent()) {
+    metrics_.RecordAndReset();
     return;
+  }
 
   AckReceivedBlobs(values);
   EnqueueResultInternal(IDBAny::Create(values));
+  metrics_.RecordAndReset();
 }
 
 #if DCHECK_IS_ON()
@@ -426,8 +463,10 @@
 
 void IDBRequest::EnqueueResponse(RefPtr<IDBValue>&& value) {
   IDB_TRACE("IDBRequest::EnqueueResponse(IDBValue)");
-  if (!ShouldEnqueueEvent())
+  if (!ShouldEnqueueEvent()) {
+    metrics_.RecordAndReset();
     return;
+  }
 
   AckReceivedBlobs(value.Get());
 
@@ -445,20 +484,27 @@
 #endif
 
   EnqueueResultInternal(IDBAny::Create(std::move(value)));
+  metrics_.RecordAndReset();
 }
 
 void IDBRequest::EnqueueResponse(int64_t value) {
   IDB_TRACE("IDBRequest::EnqueueResponse(int64_t)");
-  if (!ShouldEnqueueEvent())
+  if (!ShouldEnqueueEvent()) {
+    metrics_.RecordAndReset();
     return;
+  }
   EnqueueResultInternal(IDBAny::Create(value));
+  metrics_.RecordAndReset();
 }
 
 void IDBRequest::EnqueueResponse() {
   IDB_TRACE("IDBRequest::EnqueueResponse()");
-  if (!ShouldEnqueueEvent())
+  if (!ShouldEnqueueEvent()) {
+    metrics_.RecordAndReset();
     return;
+  }
   EnqueueResultInternal(IDBAny::CreateUndefined());
+  metrics_.RecordAndReset();
 }
 
 void IDBRequest::EnqueueResultInternal(IDBAny* result) {
@@ -478,12 +524,15 @@
                                  IDBKey* primary_key,
                                  RefPtr<IDBValue>&& value) {
   IDB_TRACE("IDBRequest::EnqueueResponse(IDBKey, IDBKey primaryKey, IDBValue)");
-  if (!ShouldEnqueueEvent())
+  if (!ShouldEnqueueEvent()) {
+    metrics_.RecordAndReset();
     return;
+  }
 
   DCHECK(pending_cursor_);
   SetResultCursor(pending_cursor_.Release(), key, primary_key,
                   std::move(value));
+  metrics_.RecordAndReset();
 }
 
 bool IDBRequest::HasPendingActivity() const {
diff --git a/third_party/WebKit/Source/modules/indexeddb/IDBRequest.h b/third_party/WebKit/Source/modules/indexeddb/IDBRequest.h
index 200b824..5c7483f 100644
--- a/third_party/WebKit/Source/modules/indexeddb/IDBRequest.h
+++ b/third_party/WebKit/Source/modules/indexeddb/IDBRequest.h
@@ -31,6 +31,7 @@
 
 #include <memory>
 
+#include "base/macros.h"
 #include "bindings/core/v8/ScriptValue.h"
 #include "core/dom/DOMStringList.h"
 #include "core/dom/SuspendableObject.h"
@@ -47,6 +48,7 @@
 #include "platform/heap/Handle.h"
 #include "platform/wtf/HashMap.h"
 #include "platform/wtf/RefPtr.h"
+#include "platform/wtf/Time.h"
 #include "public/platform/WebBlobInfo.h"
 #include "public/platform/modules/indexeddb/WebIDBCursor.h"
 #include "public/platform/modules/indexeddb/WebIDBTypes.h"
@@ -66,7 +68,39 @@
   USING_GARBAGE_COLLECTED_MIXIN(IDBRequest);
 
  public:
-  static IDBRequest* Create(ScriptState*, IDBAny* source, IDBTransaction*);
+  // Records async tracing, starting on contruction and ending on destruction or
+  // a call to |RecordAndReset()|.
+  class AsyncTraceState {
+   public:
+    AsyncTraceState() {}
+    AsyncTraceState(const char* tracing_name, void*);
+    ~AsyncTraceState();
+    AsyncTraceState(AsyncTraceState&& other) {
+      this->tracing_name_ = other.tracing_name_;
+      this->id_ = other.id_;
+      other.tracing_name_ = nullptr;
+    }
+    AsyncTraceState& operator=(AsyncTraceState&& rhs) {
+      this->tracing_name_ = rhs.tracing_name_;
+      this->id_ = rhs.id_;
+      rhs.tracing_name_ = nullptr;
+      return *this;
+    }
+
+    bool is_valid() const { return tracing_name_; }
+    void RecordAndReset();
+
+   private:
+    const char* tracing_name_ = nullptr;
+    void* id_;
+
+    DISALLOW_COPY_AND_ASSIGN(AsyncTraceState);
+  };
+
+  static IDBRequest* Create(ScriptState*,
+                            IDBAny* source,
+                            IDBTransaction*,
+                            AsyncTraceState);
   ~IDBRequest() override;
   DECLARE_VIRTUAL_TRACE();
 
@@ -218,8 +252,13 @@
   inline IDBRequestQueueItem* QueueItem() const { return queue_item_; }
 #endif  // DCHECK_IS_ON()
 
+  void AssignNewMetrics(AsyncTraceState metrics) {
+    DCHECK(!metrics_.is_valid());
+    metrics_ = std::move(metrics);
+  }
+
  protected:
-  IDBRequest(ScriptState*, IDBAny* source, IDBTransaction*);
+  IDBRequest(ScriptState*, IDBAny* source, IDBTransaction*, AsyncTraceState);
   void EnqueueEvent(Event*);
   void DequeueEvent(Event*);
   virtual bool ShouldEnqueueEvent() const;
@@ -265,10 +304,14 @@
   void EnqueueResponse(const Vector<RefPtr<IDBValue>>&);
   void EnqueueResponse();
 
+  void ClearPutOperationBlobs() { transit_blob_handles_.clear(); }
+
   Member<IDBAny> source_;
   Member<IDBAny> result_;
   Member<DOMException> error_;
 
+  AsyncTraceState metrics_;
+
   bool has_pending_activity_ = true;
   HeapVector<Member<Event>> enqueued_events_;
 
diff --git a/third_party/WebKit/Source/modules/indexeddb/IDBRequestTest.cpp b/third_party/WebKit/Source/modules/indexeddb/IDBRequestTest.cpp
index 62abb92..0f2e9073 100644
--- a/third_party/WebKit/Source/modules/indexeddb/IDBRequestTest.cpp
+++ b/third_party/WebKit/Source/modules/indexeddb/IDBRequestTest.cpp
@@ -147,8 +147,10 @@
   ASSERT_TRUE(!scope.GetExceptionState().HadException());
   ASSERT_TRUE(transaction_);
 
-  IDBRequest* request = IDBRequest::Create(
-      scope.GetScriptState(), IDBAny::CreateUndefined(), transaction_.Get());
+  IDBRequest* request =
+      IDBRequest::Create(scope.GetScriptState(), IDBAny::CreateUndefined(),
+                         transaction_.Get(), IDBRequest::AsyncTraceState());
+
   EXPECT_EQ(request->readyState(), "pending");
   ASSERT_TRUE(!scope.GetExceptionState().HadException());
   ASSERT_TRUE(request->transaction());
@@ -166,8 +168,9 @@
   ASSERT_TRUE(!scope.GetExceptionState().HadException());
   ASSERT_TRUE(transaction_);
 
-  IDBRequest* request = IDBRequest::Create(
-      scope.GetScriptState(), IDBAny::CreateUndefined(), transaction_.Get());
+  IDBRequest* request =
+      IDBRequest::Create(scope.GetScriptState(), IDBAny::CreateUndefined(),
+                         transaction_.Get(), IDBRequest::AsyncTraceState());
   ASSERT_TRUE(!scope.GetExceptionState().HadException());
   ASSERT_TRUE(request->transaction());
   request->HandleResponse(CreateIDBValue(scope.GetIsolate(), false));
@@ -185,8 +188,9 @@
   ASSERT_TRUE(!scope.GetExceptionState().HadException());
   ASSERT_TRUE(transaction_);
 
-  IDBRequest* request = IDBRequest::Create(
-      scope.GetScriptState(), IDBAny::CreateUndefined(), transaction_.Get());
+  IDBRequest* request =
+      IDBRequest::Create(scope.GetScriptState(), IDBAny::CreateUndefined(),
+                         transaction_.Get(), IDBRequest::AsyncTraceState());
   EXPECT_EQ(request->readyState(), "pending");
   ASSERT_TRUE(!scope.GetExceptionState().HadException());
   ASSERT_TRUE(request->transaction());
@@ -207,10 +211,12 @@
   ASSERT_TRUE(!scope.GetExceptionState().HadException());
   ASSERT_TRUE(transaction_);
 
-  IDBRequest* request1 = IDBRequest::Create(
-      scope.GetScriptState(), IDBAny::CreateUndefined(), transaction_.Get());
-  IDBRequest* request2 = IDBRequest::Create(
-      scope.GetScriptState(), IDBAny::CreateUndefined(), transaction_.Get());
+  IDBRequest* request1 =
+      IDBRequest::Create(scope.GetScriptState(), IDBAny::CreateUndefined(),
+                         transaction_.Get(), IDBRequest::AsyncTraceState());
+  IDBRequest* request2 =
+      IDBRequest::Create(scope.GetScriptState(), IDBAny::CreateUndefined(),
+                         transaction_.Get(), IDBRequest::AsyncTraceState());
   EXPECT_EQ(request1->readyState(), "pending");
   EXPECT_EQ(request2->readyState(), "pending");
   ASSERT_TRUE(!scope.GetExceptionState().HadException());
@@ -230,8 +236,9 @@
 TEST_F(IDBRequestTest, AbortErrorAfterAbort) {
   V8TestingScope scope;
   IDBTransaction* transaction = nullptr;
-  IDBRequest* request = IDBRequest::Create(
-      scope.GetScriptState(), IDBAny::CreateUndefined(), transaction);
+  IDBRequest* request =
+      IDBRequest::Create(scope.GetScriptState(), IDBAny::CreateUndefined(),
+                         transaction, IDBRequest::AsyncTraceState());
   EXPECT_EQ(request->readyState(), "pending");
 
   // Simulate the IDBTransaction having received OnAbort from back end and
diff --git a/third_party/WebKit/Source/modules/indexeddb/IDBTransactionTest.cpp b/third_party/WebKit/Source/modules/indexeddb/IDBTransactionTest.cpp
index b4ef86e..99c276caf 100644
--- a/third_party/WebKit/Source/modules/indexeddb/IDBTransactionTest.cpp
+++ b/third_party/WebKit/Source/modules/indexeddb/IDBTransactionTest.cpp
@@ -148,8 +148,10 @@
   ThreadState::Current()->CollectAllGarbage();
   EXPECT_EQ(1u, live_transactions.size());
 
-  Persistent<IDBRequest> request = IDBRequest::Create(
-      scope.GetScriptState(), IDBAny::CreateUndefined(), transaction_.Get());
+  Persistent<IDBRequest> request =
+      IDBRequest::Create(scope.GetScriptState(), IDBAny::CreateUndefined(),
+                         transaction_.Get(), IDBRequest::AsyncTraceState());
+
   DeactivateNewTransactions(scope.GetIsolate());
 
   request.Clear();  // The transaction is holding onto the request.
@@ -178,8 +180,9 @@
   ThreadState::Current()->CollectAllGarbage();
   EXPECT_EQ(1U, live_transactions.size());
 
-  Persistent<IDBRequest> request = IDBRequest::Create(
-      scope.GetScriptState(), IDBAny::CreateUndefined(), transaction_.Get());
+  Persistent<IDBRequest> request =
+      IDBRequest::Create(scope.GetScriptState(), IDBAny::CreateUndefined(),
+                         transaction_.Get(), IDBRequest::AsyncTraceState());
   DeactivateNewTransactions(scope.GetIsolate());
 
   // This response should result in an event being enqueued immediately.
@@ -216,8 +219,9 @@
   ThreadState::Current()->CollectAllGarbage();
   EXPECT_EQ(1U, live_transactions.size());
 
-  Persistent<IDBRequest> request = IDBRequest::Create(
-      scope.GetScriptState(), IDBAny::CreateUndefined(), transaction_.Get());
+  Persistent<IDBRequest> request =
+      IDBRequest::Create(scope.GetScriptState(), IDBAny::CreateUndefined(),
+                         transaction_.Get(), IDBRequest::AsyncTraceState());
   DeactivateNewTransactions(scope.GetIsolate());
 
   request->HandleResponse(CreateIDBValue(scope.GetIsolate(), true));
@@ -250,10 +254,12 @@
   ThreadState::Current()->CollectAllGarbage();
   EXPECT_EQ(1U, live_transactions.size());
 
-  Persistent<IDBRequest> request1 = IDBRequest::Create(
-      scope.GetScriptState(), IDBAny::CreateUndefined(), transaction_.Get());
-  Persistent<IDBRequest> request2 = IDBRequest::Create(
-      scope.GetScriptState(), IDBAny::CreateUndefined(), transaction_.Get());
+  Persistent<IDBRequest> request1 =
+      IDBRequest::Create(scope.GetScriptState(), IDBAny::CreateUndefined(),
+                         transaction_.Get(), IDBRequest::AsyncTraceState());
+  Persistent<IDBRequest> request2 =
+      IDBRequest::Create(scope.GetScriptState(), IDBAny::CreateUndefined(),
+                         transaction_.Get(), IDBRequest::AsyncTraceState());
   DeactivateNewTransactions(scope.GetIsolate());
 
   request1->HandleResponse(CreateIDBValue(scope.GetIsolate(), true));
diff --git a/third_party/WebKit/Source/modules/indexeddb/IDBValueWrapping.cpp b/third_party/WebKit/Source/modules/indexeddb/IDBValueWrapping.cpp
index a834b6a..36969a7 100644
--- a/third_party/WebKit/Source/modules/indexeddb/IDBValueWrapping.cpp
+++ b/third_party/WebKit/Source/modules/indexeddb/IDBValueWrapping.cpp
@@ -67,7 +67,8 @@
 
   serialized_value_ = SerializedScriptValue::Serialize(isolate, value, options,
                                                        exception_state);
-
+  if (serialized_value_)
+    original_data_length_ = serialized_value_->DataLengthInBytes();
 #if DCHECK_IS_ON()
   if (exception_state.HadException())
     had_exception_ = true;
diff --git a/third_party/WebKit/Source/modules/indexeddb/IDBValueWrapping.h b/third_party/WebKit/Source/modules/indexeddb/IDBValueWrapping.h
index a1e806e2..b00045e 100644
--- a/third_party/WebKit/Source/modules/indexeddb/IDBValueWrapping.h
+++ b/third_party/WebKit/Source/modules/indexeddb/IDBValueWrapping.h
@@ -111,6 +111,8 @@
     return blob_info_;
   }
 
+  size_t DataLengthBeforeWrapInBytes() { return original_data_length_; }
+
   // Default threshold for WrapIfBiggerThan().
   //
   // This should be tuned to achieve a compromise between short-term IndexedDB
@@ -132,6 +134,7 @@
   RefPtr<BlobDataHandle> wrapper_handle_;
   Vector<WebBlobInfo> blob_info_;
   Vector<char> wire_bytes_;
+  size_t original_data_length_ = 0;
 #if DCHECK_IS_ON()
   bool had_exception_ = false;
   bool wrap_called_ = false;
diff --git a/third_party/WebKit/Source/modules/indexeddb/InspectorIndexedDBAgent.cpp b/third_party/WebKit/Source/modules/indexeddb/InspectorIndexedDBAgent.cpp
index d6bba00..3c48ed3 100644
--- a/third_party/WebKit/Source/modules/indexeddb/InspectorIndexedDBAgent.cpp
+++ b/third_party/WebKit/Source/modules/indexeddb/InspectorIndexedDBAgent.cpp
@@ -566,7 +566,8 @@
     // Continue cursor before making injected script calls, otherwise
     // transaction might be finished.
     DummyExceptionStateForTesting exception_state;
-    idb_cursor->Continue(nullptr, nullptr, exception_state);
+    idb_cursor->Continue(nullptr, nullptr, IDBRequest::AsyncTraceState(),
+                         exception_state);
     if (exception_state.HadException()) {
       request_callback_->sendFailure(
           Response::Error("Could not continue cursor."));
diff --git a/third_party/WebKit/Source/modules/webaudio/BiquadDSPKernel.cpp b/third_party/WebKit/Source/modules/webaudio/BiquadDSPKernel.cpp
index 85fda7f..1b2c73d 100644
--- a/third_party/WebKit/Source/modules/webaudio/BiquadDSPKernel.cpp
+++ b/third_party/WebKit/Source/modules/webaudio/BiquadDSPKernel.cpp
@@ -31,13 +31,6 @@
 
 namespace blink {
 
-// FIXME: As a recursive linear filter, depending on its parameters, a biquad
-// filter can have an infinite tailTime. In practice, Biquad filters do not
-// usually (except for very high resonance values) have a tailTime of longer
-// than approx. 200ms. This value could possibly be calculated based on the
-// settings of the Biquad.
-static const double kMaxBiquadDelayTime = 0.2;
-
 void BiquadDSPKernel::UpdateCoefficientsIfNecessary(int frames_to_process) {
   if (GetBiquadProcessor()->FilterCoefficientsDirty()) {
     float cutoff_frequency[AudioUtilities::kRenderQuantumFrames];
@@ -121,6 +114,23 @@
         break;
     }
   }
+
+  UpdateTailTime(number_of_frames - 1);
+}
+
+void BiquadDSPKernel::UpdateTailTime(int coef_index) {
+  // A reasonable upper limit for the tail time.  While it's easy to
+  // create biquad filters whose tail time can be much larger than
+  // this, limit the maximum to this value so that we don't keep such
+  // nodes alive "forever".
+  // TODO: What is a reasonable upper limit?
+  const double kMaxTailTime = 30;
+
+  double sample_rate = SampleRate();
+  double tail =
+      biquad_.TailFrame(coef_index, kMaxTailTime * sample_rate) / sample_rate;
+
+  tail_time_ = clampTo(tail, 0.0, kMaxTailTime);
 }
 
 void BiquadDSPKernel::Process(const float* source,
@@ -199,7 +209,7 @@
 }
 
 double BiquadDSPKernel::TailTime() const {
-  return kMaxBiquadDelayTime;
+  return tail_time_;
 }
 
 double BiquadDSPKernel::LatencyTime() const {
diff --git a/third_party/WebKit/Source/modules/webaudio/BiquadDSPKernel.h b/third_party/WebKit/Source/modules/webaudio/BiquadDSPKernel.h
index efeb3eb0..915bf2e 100644
--- a/third_party/WebKit/Source/modules/webaudio/BiquadDSPKernel.h
+++ b/third_party/WebKit/Source/modules/webaudio/BiquadDSPKernel.h
@@ -40,7 +40,8 @@
 class BiquadDSPKernel final : public AudioDSPKernel {
  public:
   explicit BiquadDSPKernel(BiquadProcessor* processor)
-      : AudioDSPKernel(processor) {}
+      : AudioDSPKernel(processor),
+        tail_time_(std::numeric_limits<double>::infinity()) {}
 
   // AudioDSPKernel
   void Process(const float* source,
@@ -75,8 +76,15 @@
                           const float* detune);
 
  private:
+  // Compute the tail time using the BiquadFilter coefficients at
+  // index |coef_index|.
+  void UpdateTailTime(int coef_index);
+
   // Synchronize process() with getting and setting the filter coefficients.
   mutable Mutex process_lock_;
+
+  // The current tail time for biquad filter.
+  double tail_time_;
 };
 
 }  // namespace blink
diff --git a/third_party/WebKit/Source/platform/audio/Biquad.cpp b/third_party/WebKit/Source/platform/audio/Biquad.cpp
index 64d6b26..8505bda 100644
--- a/third_party/WebKit/Source/platform/audio/Biquad.cpp
+++ b/third_party/WebKit/Source/platform/audio/Biquad.cpp
@@ -591,4 +591,298 @@
   }
 }
 
+static double RepeatedRootResponse(double n,
+                                   double c1,
+                                   double c2,
+                                   double r,
+                                   double log_eps) {
+  // The response is h(n) = r^(n-2)*[c1*(n+1)*r^2+c2]. We're looking
+  // for n such that |h(n)| = eps.  Equivalently, we want a root
+  // of the equation log(|h(n)|) - log(eps) = 0 or
+  //
+  //   (n-2)*log(r) + log(|c1*(n+1)*r^2+c2|) - log(eps)
+  //
+  // This helps with finding a nuemrical solution because this
+  // approximately linearizes the response for large n.
+
+  return (n - 2) * log(r) + log(fabs(c1 * (n + 1) * r * r + c2)) - log_eps;
+}
+
+// Regula Falsi root finder, Illinois variant
+// (https://en.wikipedia.org/wiki/False_position_method#The_Illinois_algorithm).
+//
+// This finds a root of the repeated root response where the root is
+// assumed to lie between |low| and |high|.  The response is given by
+// |c1|, |c2|, and |r| as determined by |RepeatedRootResponse|.
+// |log_eps| is the log the the maximum allowed amplitude in the
+// response.
+static double RootFinder(double low,
+                         double high,
+                         double log_eps,
+                         double c1,
+                         double c2,
+                         double r) {
+  // Desired accuray of the root (in frames).  This doesn't need to be
+  // super-accurate, so half frame is good enough, and should be less
+  // than 1 because the algorithm may prematurely terminate.
+  const double kAccuracyThreshold = 0.5;
+  // Max number of iterations to do.  If we haven't converged by now,
+  // just return whatever we've found.
+  const int kMaxIterations = 10;
+
+  int side = 0;
+  double root = 0;
+  double f_low = RepeatedRootResponse(low, c1, c2, r, log_eps);
+  double f_high = RepeatedRootResponse(high, c1, c2, r, log_eps);
+
+  // The function values must be finite and have opposite signs!
+  DCHECK(std::isfinite(f_low));
+  DCHECK(std::isfinite(f_high));
+  DCHECK_LE(f_low * f_high, 0);
+
+  int iteration;
+  for (iteration = 0; iteration < kMaxIterations; ++iteration) {
+    root = (f_low * high - f_high * low) / (f_low - f_high);
+    if (fabs(high - low) < kAccuracyThreshold * fabs(high + low))
+      break;
+    double fr = RepeatedRootResponse(root, c1, c2, r, log_eps);
+
+    DCHECK(std::isfinite(fr));
+
+    if (fr * f_high > 0) {
+      // fr and f_high have same sign.  Copy root to f_high
+      high = root;
+      f_high = fr;
+      side = -1;
+    } else if (f_low * fr > 0) {
+      // fr and f_low have same sign. Copy root to f_low
+      low = root;
+      f_low = fr;
+      if (side == 1)
+        f_high /= 2;
+      side = 1;
+    } else {
+      // f_low * fr looks like zero, so assume we've converged.
+      break;
+    }
+  }
+
+  // Want to know if the max number of iterations is ever exceeded so
+  // we can understand why that happened.
+  DCHECK_LT(iteration, kMaxIterations);
+
+  return root;
+}
+
+double Biquad::TailFrame(int coef_index, double max_frame) {
+  // The Biquad filter is given by
+  //
+  //   H(z) = (b0 + b1/z + b2/z^2)/(1 + a1/z + a2/z^2).
+  //
+  // To compute the tail time, compute the impulse response, h(n), of
+  // H(z), which we can do analytically.  From this impulse response,
+  // find the value n0 where |h(n)| <= eps for n >= n0.
+  //
+  // Assume first that the two poles of H(z) are not repeated, say r1
+  // and r2.  Then, we can compute a partial fraction expansion of
+  // H(z):
+  //
+  //   H(z) = (b0+b1/z+b2/z^2)/[(1-r1/z)*(1-r2/z)]
+  //        = b0 + C2/(z-r2) - C1/(z-r1)
+  //
+  //  where
+  //    C2 = (b0*r2^2+b1*r2+b2)/(r2-r1)
+  //    C1 = (b0*r1^2+b1*r1+b2)/(r2-r1)
+  //
+  // Expand H(z) then this in powers of 1/z gives:
+  //
+  //   H(z) = b0 -(C2/r2+C1/r1) + sum(C2*r2^(i-1)/z^i + C1*r1^(i-1)/z^i)
+  //
+  // Thus, for n > 1 (we don't care about small n),
+  //
+  //   h(n) = C2*r2^(n-1) + C1*r1^(n-1)
+  //
+  // We need to find n0 such that |h(n)| < eps for n > n0.
+  //
+  // Case 1: r1 and r2 are real and distinct, with |r1|>=|r2|.
+  //
+  // Then
+  //
+  //   h(n) = C1*r1^(n-1)*(1 + C2/C1*(r2/r1)^(n-1))
+  //
+  // so
+  //
+  //   |h(n)| = |C1|*|r|^(n-1)*|1+C2/C1*(r2/r1)^(n-1)|
+  //          <= |C1|*|r|^(n-1)*[1 + |C2/C1|*|r2/r1|^(n-1)]
+  //          <= |C1|*|r|^(n-1)*[1 + |C2/C1|]
+  //
+  // by using the triangle inequality and the fact that |r2|<=|r1|.
+  // And we want |h(n)|<=eps which is true if
+  //
+  //   |C1|*|r|^(n-1)*[1 + |C2/C1|] <= eps
+  //
+  // or
+  //
+  //   n >= 1 + log(eps/C)/log(|r1|)
+  //
+  // where C = |C1|*[1+|C2/C1|] = |C1| + |C2|.
+  //
+  // Case 2: r1 and r2 are complex
+  //
+  // Thne we can write r1=r*exp(i*p) and r2=r*exp(-i*p).  So,
+  //
+  //   |h(n)| = |C2*r^(n-1)*exp(-i*p*(n-1)) + C1*r^(n-1)*exp(i*p*(n-1))|
+  //          = |C1|*r^(n-1)*|1 + C2/C1*exp(-i*p*(n-1))/exp(i*n*(n-1))|
+  //          <= |C1|*r^(n-1)*[1 + |C2/C1|]
+  //
+  // Again, this is easily solved to give
+  //
+  //   n >= 1 + log(eps/C)/log(r)
+  //
+  // where C = |C1|*[1+|C2/C1|] = |C1| + |C2|.
+  //
+  // Case 3: Repeated roots, r1=r2=r.
+  //
+  // In this case,
+  //
+  //   H(z) = (b0+b1/z+b2/z^2)/[(1-r/z)^2
+  //
+  // Expanding this in powers of 1/z gives:
+  //
+  //   H(z) = C1*sum((i+1)*r^i/z^i) - C2 * sum(r^(i-2)/z^i) + b2/r^2
+  //        = b2/r^2 + sum([C1*(i+1)*r^i + C2*r^(i-2)]/z^i)
+  // where
+  //   C1 = (b0*r^2+b1*r+b2)/r^2
+  //   C2 = b1*r+2*b2
+  //
+  // Thus, the impulse response is
+  //
+  //   h(n) = C1*(n+1)*r^n + C2*r^(n-2)
+  //        = r^(n-2)*[C1*(n+1)*r^2+C2]
+  //
+  // So
+  //
+  //   |h(n)| = |r|^(n-2)*|C1*(n+1)*r^2+C2|
+  //
+  // To find n such that |h(n)| < eps, we need a numerical method in
+  // general, so there's no real reason to simplify this or use other
+  // approximations.  Just solve |h(n)|=eps directly.
+  //
+  // Thus, for an set of filter coefficients, we can compute the tail
+  // time.
+  //
+
+  // If the maximum amplitude of the impulse response is less than
+  // this, we assume that we've reached the tail of the response.
+  // Currently, this means that the impulse is less than 1 bit of a
+  // 16-bit PCM value.
+  const double kMaxTailAmplitude = 1 / 32768.0;
+
+  // Find the roots of 1+a1/z+a2/z^2 = 0.  Or equivalently,
+  // z^2+a1*z+a2 = 0.  From the quadratic formula the roots are
+  // (-a1+/-sqrt(a1^2-4*a2))/2.
+
+  double a1 = a1_[coef_index];
+  double a2 = a2_[coef_index];
+  double b0 = b0_[coef_index];
+  double b1 = b1_[coef_index];
+  double b2 = b2_[coef_index];
+
+  double tail_frame = 0;
+  double discrim = a1 * a1 - 4 * a2;
+
+  if (discrim > 0) {
+    // Compute the real roots so that r1 has the largest magnitude.
+    double r1;
+    double r2;
+    if (a1 < 0) {
+      r1 = (-a1 + sqrt(discrim)) / 2;
+    } else {
+      r1 = (-a1 - sqrt(discrim)) / 2;
+    }
+    r2 = a2 / r1;
+
+    double c1 = (b0 * r1 * r1 + b1 * r1 + b2) / (r2 - r1);
+    double c2 = (b0 * r2 * r2 + b1 * r2 + b2) / (r2 - r1);
+
+    DCHECK(std::isfinite(r1));
+    DCHECK(std::isfinite(r2));
+    DCHECK(std::isfinite(c1));
+    DCHECK(std::isfinite(c2));
+
+    // It's possible for kMaxTailAmplitude to be greater than c1 + c2.
+    // This may produce a negative tail frame.  Just clamp the tail
+    // frame to 0.
+    tail_frame = clampTo(
+        1 + log(kMaxTailAmplitude / (fabs(c1) + fabs(c2))) / log(r1), 0);
+
+    DCHECK(std::isfinite(tail_frame));
+  } else if (discrim < 0) {
+    // Two complex roots.
+    // One root is -a1/2 + i*sqrt(-discrim)/2.
+    double x = -a1 / 2;
+    double y = sqrt(-discrim) / 2;
+    std::complex<double> r1(x, y);
+    std::complex<double> r2(x, -y);
+    double r = hypot(x, y);
+
+    DCHECK(std::isfinite(r));
+
+    // It's possible for r to be 1. (LPF with Q very large can cause this.)
+    if (r == 1) {
+      tail_frame = max_frame;
+    } else {
+      double c1 = abs((b0 * r1 * r1 + b1 * r1 + b2) / (r2 - r1));
+      double c2 = abs((b0 * r2 * r2 + b1 * r2 + b2) / (r2 - r1));
+
+      DCHECK(std::isfinite(c1));
+      DCHECK(std::isfinite(c2));
+
+      tail_frame = 1 + log(kMaxTailAmplitude / (c1 + c2)) / log(r);
+      DCHECK(std::isfinite(tail_frame));
+    }
+  } else {
+    // Repeated roots.  This should be pretty rare because all the
+    // coefficients need to be just the right values to get a
+    // discriminant of exactly zero.
+    double r = -a1 / 2;
+
+    if (r == 0) {
+      // Double pole at 0.  This just delays the signal by 2 frames,
+      // so set the tail frame to 2.
+      tail_frame = 2;
+    } else {
+      double c1 = (b0 * r * r + b1 * r + b2) / (r * r);
+      double c2 = b1 * r + 2 * b2;
+
+      DCHECK(std::isfinite(c1));
+      DCHECK(std::isfinite(c2));
+
+      // It can happen that c1=c2=0.  This basically means that H(z) =
+      // constant, which is the limiting case for several of the
+      // biquad filters.
+      if (c1 == 0 && c2 == 0) {
+        tail_frame = 0;
+      } else {
+        // The function c*(n+1)*r^n is not monotonic, but it's easy to
+        // find the max point since the derivative is
+        // c*r^n*(1+(n+1)*log(r)).  This has a root at
+        // -(1+log(r))/log(r). so we can start our search from that
+        // point to max_frames.
+
+        double low = clampTo(-(1 + log(r)) / log(r), 1.0,
+                             static_cast<double>(max_frame - 1));
+        double high = max_frame;
+
+        DCHECK(std::isfinite(low));
+        DCHECK(std::isfinite(high));
+
+        tail_frame = RootFinder(low, high, log(kMaxTailAmplitude), c1, c2, r);
+      }
+    }
+  }
+
+  return tail_frame;
+}
+
 }  // namespace blink
diff --git a/third_party/WebKit/Source/platform/audio/Biquad.h b/third_party/WebKit/Source/platform/audio/Biquad.h
index 7a6bde19..9d51ba3 100644
--- a/third_party/WebKit/Source/platform/audio/Biquad.h
+++ b/third_party/WebKit/Source/platform/audio/Biquad.h
@@ -70,6 +70,13 @@
   // Resets filter state
   void Reset();
 
+  // Compute tail frame based on the filter coefficents at index
+  // |coef_index|.  The tail frame is the frame number where the
+  // impulse response of the filter falls below a threshold value.
+  // The maximum allowed frame value is given by |max_frame|.  This
+  // limits how much work is done in computing the frame numer.
+  double TailFrame(int coef_index, double max_frame);
+
   // Filter response at a set of n frequencies. The magnitude and
   // phase response are returned in magResponse and phaseResponse.
   // The phase response is in radians.
diff --git a/third_party/WebKit/Source/web/WebAXObject.cpp b/third_party/WebKit/Source/web/WebAXObject.cpp
index de6fcdd..35c332a 100644
--- a/third_party/WebKit/Source/web/WebAXObject.cpp
+++ b/third_party/WebKit/Source/web/WebAXObject.cpp
@@ -160,9 +160,7 @@
 bool WebAXObject::UpdateLayoutAndCheckValidity() {
   if (!IsDetached()) {
     Document* document = private_->GetDocument();
-    // TODO(szager): Investigate whether/why document->IsDetached() can be
-    // true when this->IsDetached() is false.
-    if (!document || !document->View() || document->IsDetached())
+    if (!document || !document->View())
       return false;
     document->View()->UpdateLifecycleToCompositingCleanPlusScrolling();
   }
diff --git a/third_party/WebKit/Source/web/WebFactoryImpl.cpp b/third_party/WebKit/Source/web/WebFactoryImpl.cpp
index 5d76ce5a..779e1727 100644
--- a/third_party/WebKit/Source/web/WebFactoryImpl.cpp
+++ b/third_party/WebKit/Source/web/WebFactoryImpl.cpp
@@ -8,6 +8,10 @@
 
 namespace blink {
 
+void WebFactoryImpl::Initialize() {
+  WebFactory::SetInstance(*(new WebFactoryImpl()));
+}
+
 ChromeClient* WebFactoryImpl::CreateChromeClient(WebViewBase* view) const {
   return ChromeClientImpl::Create(view);
 }
diff --git a/third_party/WebKit/Source/web/WebFactoryImpl.h b/third_party/WebKit/Source/web/WebFactoryImpl.h
index a341ce83..4d13eae2 100644
--- a/third_party/WebKit/Source/web/WebFactoryImpl.h
+++ b/third_party/WebKit/Source/web/WebFactoryImpl.h
@@ -14,6 +14,9 @@
   WebFactoryImpl() {}
   ~WebFactoryImpl() {}
 
+  // Sets WebFactory to have a new instance of WebFactoryImpl.
+  static void Initialize();
+
   ChromeClient* CreateChromeClient(WebViewBase*) const override;
   WebViewBase* CreateWebViewBase(WebViewClient*,
                                  WebPageVisibilityState) const override;
diff --git a/third_party/WebKit/Source/web/WebKit.cpp b/third_party/WebKit/Source/web/WebKit.cpp
index b988a098..1f5cc5b 100644
--- a/third_party/WebKit/Source/web/WebKit.cpp
+++ b/third_party/WebKit/Source/web/WebKit.cpp
@@ -85,7 +85,7 @@
 
   GetModulesInitializer().Initialize();
 
-  WebFactory::SetInstance(*(new WebFactoryImpl()));
+  WebFactoryImpl::Initialize();
 
   // currentThread is null if we are running on a thread without a message loop.
   if (WebThread* current_thread = platform->CurrentThread()) {
diff --git a/third_party/WebKit/Source/web/tests/WebFrameTest.cpp b/third_party/WebKit/Source/web/tests/WebFrameTest.cpp
index f7c4a46..a28fe61 100644
--- a/third_party/WebKit/Source/web/tests/WebFrameTest.cpp
+++ b/third_party/WebKit/Source/web/tests/WebFrameTest.cpp
@@ -169,6 +169,12 @@
 
 namespace blink {
 
+#if defined(THREAD_SANITIZER)
+#define DISABLE_ON_TSAN(test_name) DISABLED_##test_name
+#else
+#define DISABLE_ON_TSAN(test_name) test_name
+#endif  // defined(THREAD_SANITIZER)
+
 ::std::ostream& operator<<(::std::ostream& os, const WebFloatSize& size) {
   return os << "WebFloatSize: [" << size.width << ", " << size.height << "]";
 }
@@ -10455,7 +10461,7 @@
   web_view_impl->MainFrameImpl()->SendOrientationChangeEvent();
 }
 
-TEST_F(WebFrameTest, MaxFramesDetach) {
+TEST_F(WebFrameTest, DISABLE_ON_TSAN(MaxFramesDetach)) {
   RegisterMockedHttpURLLoad("max-frames-detach.html");
   FrameTestHelpers::WebViewHelper web_view_helper;
   WebViewBase* web_view_impl = web_view_helper.InitializeAndLoad(
@@ -11678,7 +11684,7 @@
 
 // Make sure overlay scrollbars on non-composited scrollers fade out and set
 // the hidden bit as needed.
-TEST_F(WebFrameTest, TestNonCompositedOverlayScrollbarsFade) {
+TEST_F(WebFrameTest, DISABLE_ON_TSAN(TestNonCompositedOverlayScrollbarsFade)) {
   FrameTestHelpers::WebViewHelper web_view_helper;
   WebViewBase* web_view_impl = web_view_helper.Initialize(
       true, nullptr, nullptr, nullptr, &DisableCompositing);
diff --git a/third_party/WebKit/Tools/Scripts/webkitpy/w3c/chromium_commit.py b/third_party/WebKit/Tools/Scripts/webkitpy/w3c/chromium_commit.py
index 75aa0b8..3ffc268c 100644
--- a/third_party/WebKit/Tools/Scripts/webkitpy/w3c/chromium_commit.py
+++ b/third_party/WebKit/Tools/Scripts/webkitpy/w3c/chromium_commit.py
@@ -93,7 +93,7 @@
     def change_id(self):
         return self.host.executive.run_command([
             'git', 'footers', '--key', 'Change-Id', self.sha
-        ], cwd=self.absolute_chromium_dir)
+        ], cwd=self.absolute_chromium_dir).strip()
 
     def filtered_changed_files(self):
         """Makes a patch with just changes in files in the WPT dir for a given commit."""
diff --git a/third_party/WebKit/Tools/Scripts/webkitpy/w3c/test_exporter_unittest.py b/third_party/WebKit/Tools/Scripts/webkitpy/w3c/test_exporter_unittest.py
index c0241d4..cd2404db 100644
--- a/third_party/WebKit/Tools/Scripts/webkitpy/w3c/test_exporter_unittest.py
+++ b/third_party/WebKit/Tools/Scripts/webkitpy/w3c/test_exporter_unittest.py
@@ -254,9 +254,16 @@
 
     def test_attempts_to_merge_landed_gerrit_cl(self):
         host = MockHost()
-        host.executive = mock_git_commands({
-            'footers': 'decafbad',
-        })
+
+        def mock_command(args):
+            if args[1] != 'footers':
+                return ''
+            if args[2] == '--key':
+                return 'decafbad\n'
+            elif args[2] == '--position':
+                return 'refs/heads/master@{#475994}'
+
+        host.executive = MockExecutive(run_command_fn=mock_command)
         test_exporter = TestExporter(host, 'gh-username', 'gh-token', gerrit_user=None,
                                      gerrit_token=None, dry_run=False)
         test_exporter.wpt_github = MockWPTGitHub(pull_requests=[
@@ -273,6 +280,7 @@
 
         self.assertEqual(test_exporter.wpt_github.calls, [
             'pr_with_position',
+            'pr_with_change_id',
             'get_pr_branch',
             'merge_pull_request',
             'delete_remote_branch',
diff --git a/third_party/closure_compiler/README.chromium b/third_party/closure_compiler/README.chromium
index 3310da2c..c4a320f41 100644
--- a/third_party/closure_compiler/README.chromium
+++ b/third_party/closure_compiler/README.chromium
@@ -3,7 +3,7 @@
 URL: http://github.com/google/closure-compiler
 Version: v20150729-236-gad656a1
 Date: 2015/08/26 08:46
-Revision: ee44867683988d37c9cdb1b5c9557fe984c87135
+Revision: e061fc7bd4ac37730534828a9484d528fcd80eb5
 License: Apache 2.0
 License File: LICENSE
 Security Critical: no
diff --git a/third_party/closure_compiler/compiler/compiler.jar b/third_party/closure_compiler/compiler/compiler.jar
index 79d2f04..b0ed94a 100644
--- a/third_party/closure_compiler/compiler/compiler.jar
+++ b/third_party/closure_compiler/compiler/compiler.jar
Binary files differ
diff --git a/third_party/closure_compiler/externs/chrome_extensions.js b/third_party/closure_compiler/externs/chrome_extensions.js
index 967607d..9b3ec6df 100644
--- a/third_party/closure_compiler/externs/chrome_extensions.js
+++ b/third_party/closure_compiler/externs/chrome_extensions.js
@@ -2670,6 +2670,14 @@
 
 
 /**
+ * @see https://developer.chrome.com/extensions/tabs#method-discard
+ * @param {number|function(!Tab): void} tabIdOrCallback
+ * @param {function(!Tab): void=} opt_callback
+ */
+chrome.tabs.discard;
+
+
+/**
  * @see https://developer.chrome.com/extensions/tabs#method-executeScript
  * @param {number|!chrome.tabs.InjectDetails} tabIdOrDetails
  *     Either the id of the tab in which to run the script, or an object
@@ -2731,6 +2739,34 @@
 
 
 /**
+ * @see https://developer.chrome.com/extensions/tabs#method-getZoom
+ * @param {number|function(number): void} tabIdOrCallback
+ * @param {function(number): void=} opt_callback
+ * @return {undefined}
+ */
+chrome.tabs.getZoom = function(tabIdOrCallback, opt_callback) {};
+
+
+/**
+ * @see https://developer.chrome.com/extensions/tabs#type-ZoomSettings
+ * @typedef {?{
+ *   mode: (string|undefined),
+ *   scope: (string|undefined),
+ *   defaultZoomFactor: (number|undefined),
+ * }}
+ */
+chrome.tabs.ZoomSettings;
+
+
+/**
+ * @see https://developer.chrome.com/extensions/tabs#method-getZoomSettings
+ * @param {number|function(!chrome.tabs.ZoomSettings): void} tabIdOrCallback
+ * @param {function(!chrome.tabs.ZoomSettings): void=} opt_callback
+ */
+chrome.tabs.getZoomSettings = function(tabIdOrCallback, opt_callback) {};
+
+
+/**
  * @typedef {?{
  *   windowId: (number|undefined),
  *   tabs: (number|!Array<number>)
@@ -2894,6 +2930,28 @@
 
 
 /**
+ * @see https://developer.chrome.com/extensions/tabs#method-setZoom
+ * @param {number} tabIdOrZoomFactor
+ * @param {(number|function(): void)=} opt_zoomFactorOrCallback
+ * @param {function(): void=} opt_callback
+ * @return {undefined}
+ */
+chrome.tabs.setZoom = function(
+    tabIdOrZoomFactor, opt_zoomFactorOrCallback, opt_callback) {};
+
+
+/**
+ * @see https://developer.chrome.com/extensions/tabs#method-setZoomSettings
+ * @param {number|!chrome.tabs.ZoomSettings} tabIdOrZoomSettings
+ * @param {(!chrome.tabs.ZoomSettings|function(): void)=}
+ *     opt_zoomSettingsOrCallback
+ * @param {function(): void=} opt_callback
+ */
+chrome.tabs.setZoomSettings = function(
+    tabIdOrZoomSettings, opt_zoomSettingsOrCallback, opt_callback) {};
+
+
+/**
  * @typedef {?{
  *   url: (string|undefined),
  *   active: (boolean|undefined),
@@ -2986,6 +3044,13 @@
 
 
 /**
+ * @see https://developer.chrome.com/extensions/tabs#event-onZoomChange
+ * @type {!ChromeObjectEvent}
+ */
+chrome.tabs.onZoomChange;
+
+
+/**
  * @see https://developer.chrome.com/extensions/topSites
  * @const
  */
@@ -4484,8 +4549,19 @@
 chrome.identity = {};
 
 
+/** @typedef {?{id: string}} */
+chrome.identity.AccountInfo;
+
+
 /**
- * @param {(chrome.identity.TokenDetails|function(string=): void)}
+ * @param {function(!Array<!chrome.identity.AccountInfo>): void} callback
+ * @return {undefined}
+ */
+chrome.identity.getAccounts = function(callback) {};
+
+
+/**
+ * @param {(!chrome.identity.TokenDetails|function(string=): void)}
  *     detailsOrCallback Token options or a callback function if no options are
  *     specified.
  * @param {function(string=): void=} opt_callback A callback function if options
@@ -4495,31 +4571,37 @@
 chrome.identity.getAuthToken = function(detailsOrCallback, opt_callback) {};
 
 
-/** @typedef {{interactive: (boolean|undefined)}} */
+/**
+ * @typedef {?{
+ *   interactive: (boolean|undefined),
+ *   account: (!chrome.identity.AccountInfo|undefined),
+ *   scopes: (!Array<string>|undefined)
+ * }}
+ */
 chrome.identity.TokenDetails;
 
 
 /**
- * @param {chrome.identity.InvalidTokenDetails} details
- * @param {function(): void} callback
+ * @param {!chrome.identity.InvalidTokenDetails} details
+ * @param {function(): void=} opt_callback
  * @return {undefined}
  */
-chrome.identity.removeCachedAuthToken = function(details, callback) {};
+chrome.identity.removeCachedAuthToken = function(details, opt_callback) {};
 
 
-/** @typedef {{token: string}} */
+/** @typedef {?{token: string}} */
 chrome.identity.InvalidTokenDetails;
 
 
 /**
- * @param {chrome.identity.WebAuthFlowDetails} details
+ * @param {!chrome.identity.WebAuthFlowDetails} details
  * @param {function(string=): void} callback
  * @return {undefined}
  */
 chrome.identity.launchWebAuthFlow = function(details, callback) {};
 
 
-/** @typedef {{url: string, interactive: (boolean|undefined)}} */
+/** @typedef {?{url: string, interactive: (boolean|undefined)}} */
 chrome.identity.WebAuthFlowDetails;
 
 
@@ -4530,7 +4612,41 @@
 chrome.identity.getProfileUserInfo = function(callback) {};
 
 
-/** @type {!ChromeEvent} */
+
+/** @constructor */
+chrome.identity.OnSignInChangedEvent = function() {}
+
+
+/**
+ * @param {function(!chrome.identity.AccountInfo, boolean):void} callback
+ * @return {undefined}
+ */
+chrome.identity.OnSignInChangedEvent.prototype.addListener =
+    function(callback) {};
+
+
+/**
+ * @param {function(!chrome.identity.AccountInfo, boolean):void} callback
+ * @return {undefined}
+ */
+chrome.identity.OnSignInChangedEvent.prototype.removeListener =
+    function(callback) {};
+
+
+/**
+ * @param {function(!chrome.identity.AccountInfo, boolean):void} callback
+ * @return {boolean}
+ */
+chrome.identity.OnSignInChangedEvent.prototype.hasListener =
+    function(callback) {};
+
+
+/** @return {boolean} */
+chrome.identity.OnSignInChangedEvent.prototype.hasListeners =
+    function() {};
+
+
+/** @type {!chrome.identity.OnSignInChangedEvent} */
 chrome.identity.onSignInChanged;
 
 
@@ -5830,7 +5946,68 @@
 
 
 /**
- * @param {function(!Object)} callback
+ * @interface
+ * @see https://developer.chrome.com/extensions/system_cpu#method-getInfo
+ */
+chrome.system.cpu.CpuInformation = function() {};
+
+
+/** @type {number} */
+chrome.system.cpu.CpuInformation.prototype.numOfProcessors;
+
+
+/** @type {string} */
+chrome.system.cpu.CpuInformation.prototype.archName;
+
+
+/** @type {string} */
+chrome.system.cpu.CpuInformation.prototype.modelName;
+
+
+/** @type {!Array<string>} */
+chrome.system.cpu.CpuInformation.prototype.features;
+
+
+/** @type {!Array<!chrome.system.cpu.ProcessorInformation>} */
+chrome.system.cpu.CpuInformation.prototype.processors;
+
+
+/**
+ * This field is expected to roll out in ChromeOS 60. See the following link
+ * for the implementing CL. https://codereview.chromium.org/2802593005/
+ *
+ * TODO(b/38111360): Remove above documentation when this is released.
+ *
+ * @type {!Array<number>|undefined}
+ */
+chrome.system.cpu.CpuInformation.prototype.temperatures;
+
+
+/**
+ * @interface
+ * @see https://developer.chrome.com/extensions/system_cpu#method-getInfo
+ */
+chrome.system.cpu.ProcessorInformation = function() {};
+
+
+/** @type {number} */
+chrome.system.cpu.ProcessorInformation.prototype.user;
+
+
+/** @type {number} */
+chrome.system.cpu.ProcessorInformation.prototype.kernel;
+
+
+/** @type {number} */
+chrome.system.cpu.ProcessorInformation.prototype.idle;
+
+
+/** @type {number} */
+chrome.system.cpu.ProcessorInformation.prototype.total;
+
+
+/**
+ * @param {function(!chrome.system.cpu.CpuInformation)} callback
  * @return {undefined}
  */
 chrome.system.cpu.getInfo = function(callback) {};
@@ -5843,110 +6020,253 @@
 chrome.system.display = {};
 
 
-/** @type {!ChromeEvent} */
-chrome.system.display.onDisplayChanged;
-
-
-
 /**
- * @constructor
- */
-chrome.system.display.Bounds = function() {};
-
-
-/** @type {number} */
-chrome.system.display.Bounds.prototype.left;
-
-
-/** @type {number} */
-chrome.system.display.Bounds.prototype.top;
-
-
-/** @type {number} */
-chrome.system.display.Bounds.prototype.width;
-
-
-/** @type {number} */
-chrome.system.display.Bounds.prototype.height;
-
-
-/**
- * @typedef {{
- *   left: (number|undefined),
- *   top: (number|undefined),
- *   right: (number|undefined),
- *   bottom: (number|undefined)
+ * @typedef {!{
+ *   left: number,
+ *   top: number,
+ *   width: number,
+ *   height: number
  * }}
+ * @see https://developer.chrome.com/extensions/system.display#type-Bounds
+ */
+chrome.system.display.Bounds;
+
+
+/**
+ * @typedef {!{
+ *   left: number,
+ *   top: number,
+ *   right: number,
+ *   bottom: number
+ * }}
+ * @see https://developer.chrome.com/extensions/system.display#type-Insets
  */
 chrome.system.display.Insets;
 
 
+/**
+ * @typedef {!{
+ *   x: number,
+ *   y: number
+ * }}
+ * @see https://developer.chrome.com/extensions/system.display#type-Point
+ */
+chrome.system.display.Point;
+
 
 /**
+ * @typedef {!{
+ *   width: number,
+ *   height: number,
+ *   widthInNativePixels: number,
+ *   heightInNativePixels: number,
+ *   uiScale: number,
+ *   deviceScaleFactor: number,
+ *   isNative: boolean,
+ *   isSelected: boolean
+ * }}
+ * @see https://developer.chrome.com/extensions/system.display#type-DisplayMode
+ */
+chrome.system.display.DisplayMode;
+
+
+/**
+ * @typedef {!{
+ *   id: string,
+ *   parentId: string,
+ *   position: string,
+ *   offset: number
+ * }}
+ * @see https://developer.chrome.com/extensions/system.display#type-DisplayLayout
+ */
+chrome.system.display.DisplayLayout;
+
+
+
+/**
+ * An undocumented type that defines the objects passed to getInfo()'s callback.
  * @constructor
  */
-chrome.system.display.DisplayInfo = function() {};
+chrome.system.display.DisplayUnitInfo = function() {};
 
 
 /** @type {string} */
-chrome.system.display.DisplayInfo.prototype.id;
+chrome.system.display.DisplayUnitInfo.prototype.id;
 
 
 /** @type {string} */
-chrome.system.display.DisplayInfo.prototype.name;
+chrome.system.display.DisplayUnitInfo.prototype.name;
 
 
 /** @type {string} */
-chrome.system.display.DisplayInfo.prototype.mirroringSourceId;
+chrome.system.display.DisplayUnitInfo.prototype.mirroringSourceId;
 
 
 /** @type {boolean} */
-chrome.system.display.DisplayInfo.prototype.isPrimary;
+chrome.system.display.DisplayUnitInfo.prototype.isPrimary;
 
 
 /** @type {boolean} */
-chrome.system.display.DisplayInfo.prototype.isInternal;
+chrome.system.display.DisplayUnitInfo.prototype.isInternal;
 
 
 /** @type {boolean} */
-chrome.system.display.DisplayInfo.prototype.isEnabled;
+chrome.system.display.DisplayUnitInfo.prototype.isEnabled;
 
 
 /** @type {number} */
-chrome.system.display.DisplayInfo.prototype.dpiX;
+chrome.system.display.DisplayUnitInfo.prototype.dpiX;
 
 
 /** @type {number} */
-chrome.system.display.DisplayInfo.prototype.dpiY;
+chrome.system.display.DisplayUnitInfo.prototype.dpiY;
 
 
 /** @type {number} */
-chrome.system.display.DisplayInfo.prototype.rotation;
+chrome.system.display.DisplayUnitInfo.prototype.rotation;
 
 
 /** @type {!chrome.system.display.Bounds} */
-chrome.system.display.DisplayInfo.prototype.bounds;
+chrome.system.display.DisplayUnitInfo.prototype.bounds;
 
 
 /** @type {!chrome.system.display.Insets} */
-chrome.system.display.DisplayInfo.prototype.overscan;
+chrome.system.display.DisplayUnitInfo.prototype.overscan;
 
 
 /** @type {!chrome.system.display.Bounds} */
-chrome.system.display.DisplayInfo.prototype.workArea;
+chrome.system.display.DisplayUnitInfo.prototype.workArea;
+
+
+/** @type {!Array<!chrome.system.display.DisplayMode>} */
+chrome.system.display.DisplayUnitInfo.prototype.modes;
+
+
+/** @type {boolean} */
+chrome.system.display.DisplayUnitInfo.prototype.hasTouchSupport;
 
 
 /**
- * @typedef {{
- *   mirroringSourceId: (string|undefined),
- *   isPrimary: (boolean|undefined),
- *   overscan: (!chrome.system.display.Insets|undefined),
- *   rotation: (number|undefined),
- *   boundsOriginX: (number|undefined),
- *   boundsOriginY: (number|undefined)
- * }}
+ * @param {function(!Array<!Object>):void} callback Callbacks must declare their
+ *     param to be an array of objects since there is no defined type. To
+ *     achieve stronger type checking, cast the objects to
+ *     chrome.system.display.DisplayUnitInfo. Called with an array of objects
+ *     representing display info.
+ * @return {undefined}
+ * @see https://developer.chrome.com/extensions/system.display#method-getInfo
  */
-chrome.system.display.SettableDisplayInfo;
+chrome.system.display.getInfo = function(callback) {};
+
+
+/**
+ * @param {function(!Array<!chrome.system.display.DisplayLayout>):void} callback
+ *     The callback to invoke with the results.
+ * @see https://developer.chrome.com/extensions/system.display#method-getDisplayLayout
+ */
+chrome.system.display.getDisplayLayout = function(callback) {};
+
+
+/**
+ * @param {string} id The display's unique identifier.
+ * @param {!Object} info The information about display properties that should be
+ *     changed. A property will be changed only if a new value for it is
+ *     specified in info.
+ * @param {function():void=} callback Empty function called when the function
+ *     finishes. To find out whether the function succeeded, runtime.lastError
+ *     should be queried.
+ * @see https://developer.chrome.com/extensions/system.display#method-setDisplayProperties
+ */
+chrome.system.display.setDisplayProperties = function(id, info, callback) {};
+
+
+/**
+ * @param {!Array<!chrome.system.display.DisplayLayout>} layouts The layout
+ *     information, required for all displays except the primary display.
+ * @param {function():void=} callback Empty function called when the function
+ *     finishes. To find out whether the function succeeded, runtime.lastError
+ *     should be queried.
+ * @see https://developer.chrome.com/extensions/system.display#method-setDisplayLayout
+ */
+chrome.system.display.setDisplayLayout = function(layouts, callback) {};
+
+
+/**
+ * @param {boolean} enabled True if unified desktop should be enabled.
+ * @see https://developer.chrome.com/extensions/system.display#method-enableUnifiedDesktop
+ */
+chrome.system.display.enableUnifiedDesktop = function(enabled) {};
+
+
+/**
+ * @param {string} id The display's unique identifier.
+ * @see https://developer.chrome.com/extensions/system.display#method-overscanCalibrationStart
+ */
+chrome.system.display.overscanCalibrationStart = function(id) {};
+
+
+/**
+ * @param {string} id The display's unique identifier.
+ * @param {!chrome.system.display.Insets} delta The amount to change the
+ *     overscan insets.
+ * @see https://developer.chrome.com/extensions/system.display#method-overscanCalibrationAdjust
+ */
+chrome.system.display.overscanCalibrationAdjust = function(id, delta) {};
+
+
+/**
+ * @param {string} id The display's unique identifier.
+ * @see https://developer.chrome.com/extensions/system.display#method-overscanCalibrationReset
+ */
+chrome.system.display.overscanCalibrationReset = function(id) {};
+
+
+/**
+ * @param {string} id The display's unique identifier.
+ * @see https://developer.chrome.com/extensions/system.display#method-overscanCalibrationComplete
+ */
+chrome.system.display.overscanCalibrationComplete = function(id) {};
+
+
+/**
+ * @param {string} id The display's unique identifier.
+ * @param {function(boolean):void=} callback Optional callback to inform the
+ *     caller that the touch calibration has ended. The argument of the callback
+ *     informs if the calibration was a success or not.
+ * @see https://developer.chrome.com/extensions/system.display#method-showNativeTouchCalibration
+ */
+chrome.system.display.showNativeTouchCalibration = function(id, callback) {};
+
+
+/**
+ * @param {string} id The display's unique identifier.
+ * @see https://developer.chrome.com/extensions/system.display#method-startCustomTouchCalibration
+ */
+chrome.system.display.startCustomTouchCalibration = function(id) {};
+
+
+/**
+ * @param {!Object} pairs The pairs of point used to calibrate the display.
+ * @param {!chrome.system.display.Bounds} bounds Bounds of the display when the
+ *     touch calibration was performed. |bounds.left| and |bounds.top| values
+ *     are ignored.
+ * @see https://developer.chrome.com/extensions/system.display#method-completeCustomTouchCalibration
+ */
+chrome.system.display.completeCustomTouchCalibration = function(pairs, bounds) {
+};
+
+
+/**
+ * @param {string} id The display's unique identifier.
+ * @see https://developer.chrome.com/extensions/system.display#method-clearTouchCalibration
+ */
+chrome.system.display.clearTouchCalibration = function(id) {};
+
+
+/**
+ * @type {!ChromeEvent}
+ * @see https://developer.chrome.com/extensions/system.display#event-onDisplayChanged
+ */
+chrome.system.display.onDisplayChanged;
 
 
 chrome.types = {};
@@ -5961,25 +6281,6 @@
 chrome.types.ImageDetails;
 
 
-/**
- * @param {function(!Array<!chrome.system.display.DisplayInfo>)}
- *     callback Called with an array of objects representing display info.
- * @return {undefined}
- */
-chrome.system.display.getInfo = function(callback) {};
-
-
-/**
- * @param {string} id The display's unique identifier.
- * @param {!chrome.system.display.SettableDisplayInfo} info The information
- *     about display properties that should be changed.
- * @param {function()=} opt_callback The callback to execute when the display
- *     info has been changed.
- * @return {undefined}
- */
-chrome.system.display.setDisplayProperties =
-    function(id, info, opt_callback) {};
-
 
 /**
  * @const
diff --git a/third_party/closure_compiler/externs/polymer-1.0.js b/third_party/closure_compiler/externs/polymer-1.0.js
index f3113ebf..4f3edae 100644
--- a/third_party/closure_compiler/externs/polymer-1.0.js
+++ b/third_party/closure_compiler/externs/polymer-1.0.js
@@ -184,7 +184,7 @@
 /**
  * Notifies the event binding system of a change to a property.
  * @param  {string} path  The path to set.
- * @param  {*}      value The value to send in the update notification.
+ * @param  {*=} value The value to send in the update notification.
  * @param {boolean=} fromAbove When true, specifies that the change came from
  *     above this element and thus upward notification is not necessary.
  * @return {boolean} True if notification actually took place, based on a dirty
@@ -550,6 +550,21 @@
  */
 Polymer.Gestures.findOriginalTarget = function(ev) {};
 
+/**
+ * @type {!Object}
+ */
+Polymer.Gestures.gestures = {};
+
+/**
+ * @type {!Object}
+ */
+Polymer.Gestures.gestures.tap = {};
+
+/**
+ * Reset the tap gesture's state manually
+ * @type {function()}
+ */
+Polymer.Gestures.gestures.tap.reset = function() {};
 
 /**
  * @param {number} handle
@@ -662,6 +677,14 @@
 PolymerElement.prototype.customStyle;
 
 /**
+ * Convenience method for creating an element and configuring it.
+ * @param {string} tagName HTML tag name
+ * @param {IObject<string, *>=} properties Object of properties to configure on the instance
+ * @return {!Element}
+ */
+PolymerElement.prototype.create = function(tagName, properties) {};
+
+/**
  * Returns the computed style value for the given property.
  * @param {string} property
  * @return {string} the computed value
@@ -728,6 +751,12 @@
  */
 PolymerElement.prototype._propertySetter = function(path, value) {};
 
+/**
+ * Do not call this function.
+ *
+ * @param {string} path .
+ */
+PolymerElement.prototype._notifyChange = function(path) {};
 
 /**
  * A Polymer DOM API for manipulating DOM such that local DOM and light DOM
@@ -1095,7 +1124,7 @@
   ctor: function() {},
 
   /**
-   * @param {?Object} model
+   * @param {?Object=} model
    * @return {?Element}
    */
   stamp: function(model) {},
@@ -1481,3 +1510,65 @@
   /** @return {?Element} Element in local dom by id. */
   _getDOMRef: function(title){}
 }
+
+/** @const */
+Polymer.ArraySplice = {};
+
+/**
+ * Returns an array of splice records indicating the minimum edits required
+ * to transform the `previous` array into the `current` array.
+ *
+ * Splice records are ordered by index and contain the following fields:
+ * - `index`: index where edit started
+ * - `removed`: array of removed items from this index
+ * - `addedCount`: number of items added at this index
+ *
+ * This function is based on the Levenshtein "minimum edit distance"
+ * algorithm. Note that updates are treated as removal followed by addition.
+ *
+ * The worst-case time complexity of this algorithm is `O(l * p)`
+ *   l: The length of the current array
+ *   p: The length of the previous array
+ *
+ * However, the worst-case complexity is reduced by an `O(n)` optimization
+ * to detect any shared prefix & suffix between the two arrays and only
+ * perform the more expensive minimum edit distance calculation over the
+ * non-shared portions of the arrays.
+ *
+ * @param {!Array} current The "changed" array for which splices will be
+ * calculated.
+ * @param {!Array} previous The "unchanged" original array to compare
+ * `current` against to determine the splices.
+ * @return {!Array} Returns an array of splice record objects. Each of these
+ * contains: `index` the location where the splice occurred; `removed`
+ * the array of removed items from this location; `addedCount` the number
+ * of items added at this location.
+ */
+Polymer.ArraySplice.calculateSplices = function(current, previous) {};
+
+/**
+ * @constructor @extends {PolymerElement}
+ */
+Polymer.DomModule = function() {};
+
+/**
+ * Retrieves the dom specified by `selector` in the module specified by
+ * `id`. For example, this.import('foo', 'img');
+ * @param {string} id
+ * @param {string=} opt_selector
+ * @return {?HTMLElement} Returns the dom which matches `selector` in the module
+ * at the specified `id`.
+ */
+Polymer.DomModule.import = function(id, opt_selector) {};
+
+/**
+ * For compatibility with both Polymer 1.0 and 2.0, code may check for certain
+ * objects and properties which don't exist in Polymer 1.0.
+ *
+ * We give those objects and properties the `undefined` type here, because
+ * the dependency tree will either contain these externs and Polymer 1.0 or
+ * it will contain Polymer 2.0 which defines the full types.
+ */
+
+/** @type {undefined} */
+var ShadyDOM;
diff --git a/tools/mb/mb_config.pyl b/tools/mb/mb_config.pyl
index 6e598d4c..210951c 100644
--- a/tools/mb/mb_config.pyl
+++ b/tools/mb/mb_config.pyl
@@ -27,8 +27,8 @@
       'Android': 'android_without_codecs_release_bot_minimal_symbols',
       'Linux x64': 'release_bot',
       'Mac': 'release_bot_mac_strip',
-      'Win': 'release_bot_x86',
-      'Win x64': 'release_bot',
+      'Win': 'release_bot_x86_minimal_symbols',
+      'Win x64': 'release_bot_minimal_symbols',
     },
 
     'chromium.android': {
@@ -79,7 +79,7 @@
     },
 
     'chromium.chromedriver': {
-      'Win7': 'release_bot_x86',
+      'Win7': 'release_bot_x86_minimal_symbols',
       'Mac 10.6': 'release_bot',
       'Linux': 'release_bot',
       'Linux32': 'release_bot_x86',
@@ -130,9 +130,9 @@
         '2': 'official_optimize_chrome_pgo_phase_2',
       },
       'Chromium Windows Analyze': 'windows_analyze',
-      'CrWin7Goma': 'release_bot_x86',
+      'CrWin7Goma': 'release_bot_x86_minimal_symbols',
       'CrWin7Goma(clbr)': 'shared_release_bot_x86',
-      'CrWin7Goma(dbg)': 'debug_bot_x86',
+      'CrWin7Goma(dbg)': 'debug_bot_x86_minimal_symbols',
       'CrWin7Goma(dll)': 'shared_release_bot_x86',
 
       # if CrWinClang is modified, please update CrWinClangGoma in the same way.
@@ -142,7 +142,7 @@
       'CrWinClang64': 'clang_official_release_bot_minimal_symbols',
       'CrWinClang64(dll)': 'clang_shared_release_bot_dcheck',
       'CrWinClangGoma': 'clang_official_optimize_release_bot_minimal_symbols_x86',
-      'CrWinGoma': 'release_bot_x86',
+      'CrWinGoma': 'release_bot_x86_minimal_symbols',
       'CrWinGoma(dll)': 'shared_release_bot_x86',
       'CrWinGoma(loc)': 'shared_release_bot_x86',
       'ClangToTAndroidASan': 'android_clang_tot_asan',
@@ -183,7 +183,7 @@
       'Headless Linux (dbg)': 'headless_linux_debug_bot',
       'MD Top Chrome ChromeOS material-hybrid': 'chromeos_with_codecs_debug_bot',
       'MD Top Chrome ChromeOS non-material': 'chromeos_with_codecs_debug_bot',
-      'MD Top Chrome Win material': 'debug_bot',
+      'MD Top Chrome Win material': 'debug_bot_minimal_symbols',
       'MD Top Chrome Linux material': 'debug_bot',
       'LTO Linux': 'official_goma_thin_lto_use_lld',
       'LTO Linux Perf': 'official_goma_thin_lto_use_lld',
@@ -202,7 +202,7 @@
       'Mac deterministic (dbg)': 'debug_bot',
       'Mojo ChromiumOS': 'chromeos_with_codecs_ozone_release_trybot',
       'Mojo Linux': 'release_bot',
-      'Mojo Windows': 'release_bot_x86',
+      'Mojo Windows': 'release_bot_x86_minimal_symbols',
       'Ozone Linux': 'release_bot_ozone_linux',
       'Site Isolation Android': 'android_release_bot_minimal_symbols_arm64',
       'Site Isolation Linux': 'release_trybot',
@@ -211,16 +211,16 @@
       'UBSanVptr Linux': 'ubsan_vptr_release_bot',
       'WebKit Linux - RandomOrder': 'release_bot',
       'WebKit Mac - RandomOrder': 'release_bot',
-      'WebKit Win - RandomOrder': 'release_bot_x86',
+      'WebKit Win - RandomOrder': 'release_bot_x86_minimal_symbols',
       'Win 10 Fast Ring': 'release_trybot',
-      'Windows deterministic': 'release_bot_x86',
+      'Windows deterministic': 'release_bot_x86_minimal_symbols',
       'Windows Clang deterministic': 'clang_release_bot_minimal_symbols_x86',
     },
 
     'chromium.goma': {
       'Chromium Linux Goma Staging': 'release_bot',
       'Chromium Mac Goma Staging': 'release_bot',
-      'CrWinGomaStaging': 'release_bot_x86',
+      'CrWinGomaStaging': 'release_bot_x86_minimal_symbols',
     },
 
     'chromium.gpu': {
@@ -229,8 +229,8 @@
       'GPU Mac Builder (dbg)': 'gpu_tests_debug_trybot',
       'GPU Linux Builder (dbg)': 'gpu_tests_debug_trybot',
       'GPU Linux Builder': 'gpu_tests_release_trybot',
-      'GPU Win Builder': 'gpu_tests_release_trybot_x86',
-      'GPU Win Builder (dbg)': 'gpu_tests_debug_trybot_x86',
+      'GPU Win Builder': 'gpu_tests_release_trybot_x86_minimal_symbols',
+      'GPU Win Builder (dbg)': 'gpu_tests_debug_trybot_x86_minimal_symbols',
     },
 
     'chromium.gpu.fyi': {
@@ -353,7 +353,7 @@
       'Android N5X Swarm': 'android_release_bot_minimal_symbols_arm64',
       'Linux Swarm': 'release_bot',
       'Mac Swarm': 'release_bot_mac_strip',
-      'Windows Swarm': 'release_bot_x86',
+      'Windows Swarm': 'release_bot_x86_minimal_symbols',
     },
 
     'client.nacl.sdk': {
@@ -362,8 +362,8 @@
       'linux-sdk-multirel': 'release_bot',
       'mac-sdk-multi': 'release_bot',
       'mac-sdk-multirel': 'release_bot',
-      'windows-sdk-multi': 'release_bot_x86',
-      'windows-sdk-multirel': 'release_bot_x86',
+      'windows-sdk-multi': 'release_bot_x86_minimal_symbols',
+      'windows-sdk-multirel': 'release_bot_x86_minimal_symbols',
     },
 
     'client.v8.chromium': {
@@ -386,8 +386,8 @@
       'V8-Blink Linux 64 - ignition': 'release_bot',
       'V8-Blink Linux 64 (dbg)': 'debug_bot',
       'V8-Blink Mac': 'release_bot',
-      'V8-Blink Win': 'release_bot_x86',
-      'Win Release (NVIDIA)': 'gpu_tests_release_trybot_x86',
+      'V8-Blink Win': 'release_bot_x86_minimal_symbols',
+      'Win Release (NVIDIA)': 'gpu_tests_release_trybot_x86_minimal_symbols',
     },
 
     'chromium.webkit': {
@@ -402,10 +402,10 @@
       'WebKit Mac10.11 (retina)': 'release_bot',
       'WebKit Mac10.12': 'release_bot',
       'WebKit Mac10.9': 'release_bot',
-      'WebKit Win Builder (dbg)': 'debug_bot_x86',
-      'WebKit Win Builder': 'release_bot_x86',
-      'WebKit Win x64 Builder (dbg)': 'debug_bot',
-      'WebKit Win x64 Builder': 'release_bot',
+      'WebKit Win Builder (dbg)': 'debug_bot_x86_minimal_symbols',
+      'WebKit Win Builder': 'release_bot_x86_minimal_symbols',
+      'WebKit Win x64 Builder (dbg)': 'debug_bot_minimal_symbols',
+      'WebKit Win x64 Builder': 'release_bot_minimal_symbols',
     },
 
     'chromium.webrtc': {
@@ -425,10 +425,10 @@
 
     'chromium.win': {
       # Windows bots take too long to link w/ full symbols and time out.
-      'Win Builder': 'release_bot_x86',
-      'Win Builder (dbg)': 'debug_bot_x86',
-      'Win x64 Builder': 'release_bot',
-      'Win x64 Builder (dbg)': 'debug_bot',
+      'Win Builder': 'release_bot_x86_minimal_symbols',
+      'Win Builder (dbg)': 'debug_bot_x86_minimal_symbols',
+      'Win x64 Builder': 'release_bot_minimal_symbols',
+      'Win x64 Builder (dbg)': 'debug_bot_minimal_symbols',
       'WinClang64 (dbg)': 'win_clang_debug_bot',
     },
 
@@ -436,7 +436,7 @@
       'Linux Canary': 'debug_bot',
       'Linux Dev': 'debug_bot',
       'Mac Dev': 'debug_bot',
-      'Windows Dev': 'debug_bot',
+      'Windows Dev': 'debug_bot_minimal_symbols',
     },
 
     'tryserver.blink': {
@@ -457,11 +457,11 @@
       'mac10.11_blink_rel': 'release_bot_minimal_symbols',
       'mac10.11_retina_blink_rel': 'release_bot_minimal_symbols',
       'mac10.12_blink_rel': 'release_bot_minimal_symbols',
-      'win7_blink_compile_dbg': 'debug_trybot_x86',
-      'win7_blink_compile_rel': 'release_bot_x86',
-      'win7_blink_dbg': 'debug_trybot_x86',
-      'win7_blink_rel': 'release_bot_x86',
-      'win10_blink_rel': 'release_bot_x86',
+      'win7_blink_compile_dbg': 'debug_trybot_x86_minimal_symbols',
+      'win7_blink_compile_rel': 'release_bot_x86_minimal_symbols',
+      'win7_blink_dbg': 'debug_trybot_x86_minimal_symbols',
+      'win7_blink_rel': 'release_bot_x86_minimal_symbols',
+      'win10_blink_rel': 'release_bot_x86_minimal_symbols',
     },
 
     'tryserver.chromium.android': {
@@ -626,23 +626,23 @@
     'tryserver.chromium.win': {
       'win10_chromium_x64_rel_ng': 'release_trybot',
       'win10_chromium_x64_rel_ng_exp': 'release_trybot',
-      'win8_chromium_gn_upload': 'release_bot_x86',
+      'win8_chromium_gn_upload': 'release_bot_x86_minimal_symbols',
       'win_x64_archive': 'release_trybot',
       'win_archive': 'release_trybot_x86',
-      'win_chromium_compile_dbg_ng': 'debug_trybot_x86',
-      'win_chromium_compile_rel_ng': 'gpu_tests_release_trybot_x86',
-      'win_chromium_dbg_ng': 'debug_trybot_x86',
-      'win_chromium_rel_ng': 'gpu_tests_release_trybot_x86',
+      'win_chromium_compile_dbg_ng': 'debug_trybot_x86_minimal_symbols',
+      'win_chromium_compile_rel_ng': 'gpu_tests_release_trybot_x86_minimal_symbols',
+      'win_chromium_dbg_ng': 'debug_trybot_x86_minimal_symbols',
+      'win_chromium_rel_ng': 'gpu_tests_release_trybot_x86_minimal_symbols',
       'win_chromium_syzyasan_rel': 'syzyasan_no_pch_release_x86',
-      'win_chromium_x64_rel_ng': 'release_trybot',
+      'win_chromium_x64_rel_ng': 'release_trybot_minimal_symbols',
       'win_clang': 'win_clang_debug_bot',
       'win_clang_dbg': 'clang_debug_trybot_x86',
       'win_clang_rel': 'clang_official_release_trybot_x86',
       'win_clang_x64_dbg': 'win_clang_debug_bot',
       'win_clang_x64_rel': 'clang_official_release_trybot',
       'win_mojo': 'release_trybot_x86',
-      'win_nacl_sdk': 'release_bot_x86',
-      'win_nacl_sdk_build': 'release_bot_x86',
+      'win_nacl_sdk': 'release_bot_x86_minimal_symbols',
+      'win_nacl_sdk_build': 'release_bot_x86_minimal_symbols',
       'win_optional_gpu_tests_rel': 'gpu_tests_deqp_gles_release_trybot_x86',
       'win_pgo': {
         '1': 'official_optimize_chrome_pgo_phase_1_x86',
@@ -1181,6 +1181,12 @@
       'debug_bot', 'x86',
     ],
 
+    # compiler.gni implicitly sets symbol_level=1 on Windows if goma is enabled,
+    # if MSVC is used.  Explicitly set it here so that it's set consistently for
+    # both MSVC and clang.
+    'debug_bot_minimal_symbols': [ 'debug_bot', 'minimal_symbols' ],
+    'debug_bot_x86_minimal_symbols': [ 'debug_bot', 'x86', 'minimal_symbols' ],
+
     'debug_libfuzzer_asan': [
       'debug', 'libfuzzer', 'asan', 'chromeos_codecs', 'pdf_xfa', 'disable_nacl',
     ],
@@ -1193,6 +1199,10 @@
       'debug_trybot', 'x86',
     ],
 
+    'debug_trybot_x86_minimal_symbols': [
+      'debug_trybot', 'x86',
+    ],
+
     'gpu_fyi_tests_chromeos_ozone_release_trybot': [
       'gpu_fyi_tests', 'release_trybot', 'ozone', 'ozone_linux', 'system_gbm_libdrm',
     ],
@@ -1234,27 +1244,29 @@
     ],
 
     'gpu_tests_deqp_gles_release_trybot': [
-      'gpu_fyi_tests', 'release_trybot',
+      # TODO(thakis): Remove no_clang once https://crbug.com/727437 is fixed.
+      'gpu_fyi_tests', 'release_trybot', 'no_clang',
     ],
 
     'gpu_tests_deqp_gles_release_trybot_x86': [
-      'gpu_fyi_tests', 'release_trybot', 'x86',
+      # TODO(thakis): Remove no_clang once https://crbug.com/727437 is fixed.
+      'gpu_fyi_tests', 'release_trybot', 'x86', 'no_clang',
     ],
 
     'gpu_tests_debug_trybot': [
       'gpu_tests', 'debug_trybot',
     ],
 
-    'gpu_tests_debug_trybot_x86': [
-      'gpu_tests', 'debug_trybot', 'x86',
+    'gpu_tests_debug_trybot_x86_minimal_symbols': [
+      'gpu_tests', 'debug_trybot', 'x86', 'minimal_symbols',
     ],
 
     'gpu_tests_release_trybot': [
       'gpu_tests', 'release_trybot',
     ],
 
-    'gpu_tests_release_trybot_x86': [
-      'gpu_tests', 'release_trybot', 'x86',
+    'gpu_tests_release_trybot_x86_minimal_symbols': [
+      'gpu_tests', 'release_trybot', 'x86', 'minimal_symbols',
     ],
 
     'gpu_tests_release_bot': [
@@ -1384,14 +1396,16 @@
       'release_bot', 'mac_strip',
     ],
 
-    'release_bot_minimal_symbols': [
-      'release_bot', 'minimal_symbols',
-    ],
-
     'release_bot_x86': [
       'release_bot', 'x86',
     ],
 
+    # compiler.gni implicitly sets symbol_level=1 on Windows if goma is enabled,
+    # if MSVC is used.  Explicitly set it here so that it's set consistently for
+    # both MSVC and clang.
+    'release_bot_minimal_symbols': [ 'release_bot', 'minimal_symbols' ],
+    'release_bot_x86_minimal_symbols': [ 'release_bot', 'x86', 'minimal_symbols' ],
+
     'release_libfuzzer_asan': [
       'release', 'libfuzzer', 'asan', 'chromeos_codecs', 'pdf_xfa', 'disable_nacl', 'optimize_for_fuzzing',
     ],
@@ -1416,6 +1430,10 @@
       'release_trybot',
     ],
 
+    'release_trybot_minimal_symbols': [
+      'release_trybot', 'minimal_symbols',
+    ],
+
     'release_trybot_arm': [
       'release_trybot', 'arm',
     ],
@@ -1595,6 +1613,10 @@
       'gn_args': 'is_clang=true',
     },
 
+    'no_clang': {
+      'gn_args': 'is_clang=false',
+    },
+
     'cronet': {
       'gn_args': ('disable_file_support=true disable_ftp_support=true '
                   'enable_websockets=false use_platform_icu_alternatives=true '
diff --git a/tools/metrics/histograms/histograms.xml b/tools/metrics/histograms/histograms.xml
index 1073cb0..f9d012fc 100644
--- a/tools/metrics/histograms/histograms.xml
+++ b/tools/metrics/histograms/histograms.xml
@@ -72121,6 +72121,16 @@
   </summary>
 </histogram>
 
+<histogram
+    name="Startup.FirstWebContents.RenderProcessHostInit.ToNonEmptyPaint"
+    units="ms">
+  <owner>hans@chromium.org</owner>
+  <summary>
+    Time between RenderFrameHostImpl::Init and
+    Startup.FirstWebContents.NonEmptyPaint2.
+  </summary>
+</histogram>
+
 <histogram name="Startup.FirstWebContents.UINotResponsive" units="ms">
   <obsolete>
     Deprecated 10/2015.
@@ -81630,6 +81640,39 @@
   </summary>
 </histogram>
 
+<histogram name="WebCore.IndexedDB.PutBlobsCount" units="blobs">
+  <owner>dmurph@chromium.org</owner>
+  <summary>
+    The number of blobs being saved in an IndexedDB object store 'put'
+    operation. Recorded for every 'put' operation.
+  </summary>
+</histogram>
+
+<histogram name="WebCore.IndexedDB.PutBlobsTotalSize" units="KB">
+  <owner>dmurph@chromium.org</owner>
+  <summary>
+    The total size of the blobs being saved in an IndexedDB object store 'put'
+    operation. Recorded for every 'put' operation, except when there are no
+    attached blobs or a blob has an unknown size.
+  </summary>
+</histogram>
+
+<histogram name="WebCore.IndexedDB.PutKeySize" units="KB">
+  <owner>dmurph@chromium.org</owner>
+  <summary>
+    The size of the IndexedDB key used in an IndexedDB object store 'put'
+    operation. Recorded for every 'put' operation.
+  </summary>
+</histogram>
+
+<histogram name="WebCore.IndexedDB.PutValueSize" units="KB">
+  <owner>dmurph@chromium.org</owner>
+  <summary>
+    The size of the IndexedDB value used in an IndexedDB object store 'put'
+    operation. Recorded for every 'put' operation.
+  </summary>
+</histogram>
+
 <histogram name="WebCore.IndexedDB.Schema.Index.KeyPathType"
     enum="IDBKeyPathType">
   <owner>jsbell@chromium.org</owner>
@@ -81673,6 +81716,66 @@
   </summary>
 </histogram>
 
+<histogram name="WebCore.IndexedDB.Transaction.ReadOnly.SizeOnCommit"
+    units="KB">
+  <owner>dmurph@chromium.org</owner>
+  <summary>
+    The total temporary size of an IndexedDB ReadOnly Transaction. Since this is
+    a readonly transaction, the size should only be &gt;0 when the transaction
+    is removing tombstone index keys. Recorded on transaction commit.
+  </summary>
+</histogram>
+
+<histogram name="WebCore.IndexedDB.Transaction.ReadOnly.TimeActive" units="ms">
+  <owner>dmurph@chromium.org</owner>
+  <summary>
+    The time it takes for an IndexedDB ReadOnly Transaction to commit, starting
+    from when it starts executing tasks (when it is scheduled). Recorded on
+    transaction commit.
+  </summary>
+</histogram>
+
+<histogram name="WebCore.IndexedDB.Transaction.ReadWrite.SizeOnCommit"
+    units="KB">
+  <owner>dmurph@chromium.org</owner>
+  <summary>
+    The total temporary size of an IndexedDB ReadWrite Transaction. This is the
+    memory that is temporarily stored before writing to disk. Recorded on
+    transaction commit.
+  </summary>
+</histogram>
+
+<histogram name="WebCore.IndexedDB.Transaction.ReadWrite.TimeActive" units="ms">
+  <owner>dmurph@chromium.org</owner>
+  <summary>
+    The time it takes for an IndexedDB ReadWrite Transaction to commit, starting
+    from when it starts executing tasks (when it is scheduled). Recorded on
+    transaction commit.
+  </summary>
+</histogram>
+
+<histogram name="WebCore.IndexedDB.Transaction.VersionChange.SizeOnCommit"
+    units="KB">
+  <owner>dmurph@chromium.org</owner>
+  <summary>
+    The total temporary size of an IndexedDB VersionChange Transaction. This is
+    the memory that is temporarily stored before writing to disk. Version change
+    transactions happen when creating a database or updating a current database
+    schema. Recorded on transaction commit.
+  </summary>
+</histogram>
+
+<histogram name="WebCore.IndexedDB.Transaction.VersionChange.TimeActive"
+    units="ms">
+  <owner>dmurph@chromium.org</owner>
+  <summary>
+    The time it takes for an IndexedDB VersionChange Transaction to commit,
+    starting from when it starts executing tasks (when it is scheduled). Version
+    change transactions happen when creating a database or updating a current
+    database schema. Recorded on transaction commit.
+  </summary>
+</histogram>
+
 <histogram name="WebCore.IndexedDB.TransactionAbortReason" enum="IDBException">
   <owner>dmurph@chromium.org</owner>
   <summary>
@@ -93815,6 +93918,8 @@
       name="Startup.FirstWebContents.MainNavigationStart.SingleTab"/>
   <affected-histogram name="Startup.FirstWebContents.NonEmptyPaint"/>
   <affected-histogram name="Startup.FirstWebContents.NonEmptyPaint2"/>
+  <affected-histogram
+      name="Startup.FirstWebContents.RenderProcessHostInit.ToNonEmptyPaint"/>
   <affected-histogram name="Startup.LoadTime.ExeMainToDllMain"/>
   <affected-histogram name="Startup.LoadTime.ExeMainToDllMain2"/>
   <affected-histogram name="Startup.LoadTime.ProcessCreateToDllMain"/>
diff --git a/tools/perf/benchmarks/system_health.py b/tools/perf/benchmarks/system_health.py
index 4f32001..b963e6d1 100644
--- a/tools/perf/benchmarks/system_health.py
+++ b/tools/perf/benchmarks/system_health.py
@@ -35,13 +35,14 @@
 
   def CreateTimelineBasedMeasurementOptions(self):
     options = timeline_based_measurement.Options(
-        chrome_trace_category_filter.ChromeTraceCategoryFilter())
-    options.config.chrome_trace_config.category_filter.AddFilterString('rail')
+        chrome_trace_category_filter.ChromeTraceCategoryFilter(
+            filter_string='rail,toplevel'))
     options.config.enable_battor_trace = True
     options.config.enable_chrome_trace = True
     options.config.enable_cpu_trace = True
     options.SetTimelineBasedMetrics([
         'clockSyncLatencyMetric',
+        'cpuTimeMetric',
         'powerMetric',
         'tracingMetric'
     ])
diff --git a/tools/perf/page_sets/system_health/browsing_stories.py b/tools/perf/page_sets/system_health/browsing_stories.py
index a5a25cc..a896721 100644
--- a/tools/perf/page_sets/system_health/browsing_stories.py
+++ b/tools/perf/page_sets/system_health/browsing_stories.py
@@ -848,7 +848,7 @@
     return 'Load %s then make a very long scroll.' % cls.URL
 
 
-@decorators.Disabled('win')  # crbug.com/728152
+@decorators.Disabled('win', 'linux')  # 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')
diff --git a/tools/resources/list_unused_grit_header.py b/tools/resources/list_unused_grit_header.py
index 49cf088..2980310 100755
--- a/tools/resources/list_unused_grit_header.py
+++ b/tools/resources/list_unused_grit_header.py
@@ -16,7 +16,7 @@
 
 from find_unused_resources import GetBaseResourceId
 
-IF_ELSE_TAGS = ('if', 'else')
+IF_ELSE_THEN_TAGS = ('if', 'else', 'then')
 
 
 def Usage(prog_name):
@@ -45,7 +45,7 @@
   for child in node.getchildren():
     if child.tag == resource_tag:
       resources.append(child.attrib['name'])
-    elif child.tag in IF_ELSE_TAGS:
+    elif child.tag in IF_ELSE_THEN_TAGS:
       resources.extend(GetResourcesForNode(child, parent_file, resource_tag))
     elif child.tag == 'part':
       parent_dir = os.path.dirname(parent_file)
@@ -120,7 +120,7 @@
       if child.attrib['type'] == 'rc_header':
         assert output_file is None
         output_file = child.attrib['filename']
-    elif child.tag in IF_ELSE_TAGS:
+    elif child.tag in IF_ELSE_THEN_TAGS:
       child_output_file = GetOutputFileForNode(child)
       if not child_output_file:
         continue
@@ -169,7 +169,7 @@
   # To be more thorough, one would need to run a pre-processor.
   SPECIAL_KEYWORDS = (
       '#include "ui_localizer_table.h"',  # ui_localizer.mm
-      'DEFINE_RESOURCE_ID',  # chrome/browser/android/resource_mapper.cc
+      'DECLARE_RESOURCE_ID',  # chrome/browser/android/resource_mapper.cc
       )
   with open(filename, 'rb') as f:
     grit_header_line = grit_header + '"\n'
@@ -203,8 +203,9 @@
   tree = xml.etree.ElementTree.parse(grd_file)
   grit_header = GetOutputHeaderFile(tree)
   if not grit_header:
-    print 'Error: %s does not generate any output headers.' % grit_header
+    print 'Error: %s does not generate any output headers.' % grd_file
     return 1
+
   resources = GetResourcesForGrdFile(tree, grd_file)
 
   files_with_unneeded_grit_includes = []
diff --git a/ui/compositor/compositor.cc b/ui/compositor/compositor.cc
index 1e04fce..30eff8c7 100644
--- a/ui/compositor/compositor.cc
+++ b/ui/compositor/compositor.cc
@@ -142,6 +142,8 @@
 
   settings.buffer_to_texture_target_map =
       context_factory_->GetRendererSettings().buffer_to_texture_target_map;
+  if (command_line->HasSwitch(switches::kUIEnableRGBA4444Textures))
+    settings.preferred_tile_format = cc::RGBA_4444;
 
   settings.gpu_memory_policy.bytes_limit_when_visible = 512 * 1024 * 1024;
   settings.gpu_memory_policy.priority_cutoff_when_visible =
diff --git a/ui/compositor/compositor_util.cc b/ui/compositor/compositor_util.cc
index 39109bc9..886e7aa 100644
--- a/ui/compositor/compositor_util.cc
+++ b/ui/compositor/compositor_util.cc
@@ -28,8 +28,6 @@
       command_line->HasSwitch(cc::switches::kGlCompositedTextureQuadBorder);
   renderer_settings.show_overdraw_feedback =
       command_line->HasSwitch(cc::switches::kShowOverdrawFeedback);
-  if (command_line->HasSwitch(switches::kUIEnableRGBA4444Textures))
-    renderer_settings.preferred_tile_format = cc::RGBA_4444;
   renderer_settings.enable_color_correct_rendering =
       command_line->HasSwitch(switches::kEnableColorCorrectRendering) ||
       command_line->HasSwitch(switches::kEnableHDR);
diff --git a/ui/events/blink/event_with_callback.cc b/ui/events/blink/event_with_callback.cc
index 8fc9a88e..39793f4e 100644
--- a/ui/events/blink/event_with_callback.cc
+++ b/ui/events/blink/event_with_callback.cc
@@ -18,12 +18,12 @@
     WebScopedInputEvent event,
     const LatencyInfo& latency,
     base::TimeTicks timestamp_now,
-    const InputHandlerProxy::EventDispositionCallback& callback)
+    InputHandlerProxy::EventDispositionCallback callback)
     : event_(WebInputEventTraits::Clone(*event)),
       latency_(latency),
       creation_timestamp_(timestamp_now),
       last_coalesced_timestamp_(timestamp_now) {
-  original_events_.emplace_back(std::move(event), callback);
+  original_events_.emplace_back(std::move(event), std::move(callback));
 }
 
 EventWithCallback::EventWithCallback(
@@ -78,15 +78,16 @@
       did_overscroll_params_copy =
           base::MakeUnique<DidOverscrollParams>(*did_overscroll_params);
     }
-    original_event.callback_.Run(disposition, std::move(original_event.event_),
-                                 latency, std::move(did_overscroll_params));
+    std::move(original_event.callback_)
+        .Run(disposition, std::move(original_event.event_), latency,
+             std::move(did_overscroll_params));
   }
 }
 
 EventWithCallback::OriginalEventWithCallback::OriginalEventWithCallback(
     WebScopedInputEvent event,
-    const InputHandlerProxy::EventDispositionCallback& callback)
-    : event_(std::move(event)), callback_(callback) {}
+    InputHandlerProxy::EventDispositionCallback callback)
+    : event_(std::move(event)), callback_(std::move(callback)) {}
 
 EventWithCallback::OriginalEventWithCallback::~OriginalEventWithCallback() {}
 
diff --git a/ui/events/blink/event_with_callback.h b/ui/events/blink/event_with_callback.h
index f56c63d..774b8e8 100644
--- a/ui/events/blink/event_with_callback.h
+++ b/ui/events/blink/event_with_callback.h
@@ -21,18 +21,17 @@
   struct OriginalEventWithCallback {
     OriginalEventWithCallback(
         WebScopedInputEvent event,
-        const InputHandlerProxy::EventDispositionCallback& callback);
+        InputHandlerProxy::EventDispositionCallback callback);
     ~OriginalEventWithCallback();
     WebScopedInputEvent event_;
     InputHandlerProxy::EventDispositionCallback callback_;
   };
   using OriginalEventList = std::list<OriginalEventWithCallback>;
 
-  EventWithCallback(
-      WebScopedInputEvent event,
-      const LatencyInfo& latency,
-      base::TimeTicks timestamp_now,
-      const InputHandlerProxy::EventDispositionCallback& callback);
+  EventWithCallback(WebScopedInputEvent event,
+                    const LatencyInfo& latency,
+                    base::TimeTicks timestamp_now,
+                    InputHandlerProxy::EventDispositionCallback callback);
   EventWithCallback(WebScopedInputEvent event,
                     const LatencyInfo& latency,
                     base::TimeTicks creation_timestamp,
diff --git a/ui/events/blink/input_handler_proxy.cc b/ui/events/blink/input_handler_proxy.cc
index 1ed5980..7ef9ca6 100644
--- a/ui/events/blink/input_handler_proxy.cc
+++ b/ui/events/blink/input_handler_proxy.cc
@@ -297,7 +297,7 @@
 void InputHandlerProxy::HandleInputEventWithLatencyInfo(
     WebScopedInputEvent event,
     const LatencyInfo& latency_info,
-    const EventDispositionCallback& callback) {
+    EventDispositionCallback callback) {
   DCHECK(input_handler_);
 
   if (uma_latency_reporting_enabled_)
@@ -310,7 +310,8 @@
 
   std::unique_ptr<EventWithCallback> event_with_callback =
       base::MakeUnique<EventWithCallback>(std::move(event), latency_info,
-                                          tick_clock_->NowTicks(), callback);
+                                          tick_clock_->NowTicks(),
+                                          std::move(callback));
 
   // Note: Other input can race ahead of gesture input as they don't have to go
   // through the queue, but we believe it's OK to do so.
diff --git a/ui/events/blink/input_handler_proxy.h b/ui/events/blink/input_handler_proxy.h
index 49daedf..0db37a1 100644
--- a/ui/events/blink/input_handler_proxy.h
+++ b/ui/events/blink/input_handler_proxy.h
@@ -71,14 +71,13 @@
     DROP_EVENT
   };
   using EventDispositionCallback =
-      base::Callback<void(EventDisposition,
-                          WebScopedInputEvent WebInputEvent,
-                          const LatencyInfo&,
-                          std::unique_ptr<ui::DidOverscrollParams>)>;
-  void HandleInputEventWithLatencyInfo(
-      WebScopedInputEvent event,
-      const LatencyInfo& latency_info,
-      const EventDispositionCallback& callback);
+      base::OnceCallback<void(EventDisposition,
+                              WebScopedInputEvent WebInputEvent,
+                              const LatencyInfo&,
+                              std::unique_ptr<ui::DidOverscrollParams>)>;
+  void HandleInputEventWithLatencyInfo(WebScopedInputEvent event,
+                                       const LatencyInfo& latency_info,
+                                       EventDispositionCallback callback);
   EventDisposition HandleInputEvent(const blink::WebInputEvent& event);
 
   // cc::InputHandlerClient implementation.
diff --git a/ui/webui/resources/cr_elements/cr_dialog/cr_dialog.html b/ui/webui/resources/cr_elements/cr_dialog/cr_dialog.html
index 8e8038df..ef1106a2 100644
--- a/ui/webui/resources/cr_elements/cr_dialog/cr_dialog.html
+++ b/ui/webui/resources/cr_elements/cr_dialog/cr_dialog.html
@@ -16,7 +16,7 @@
         box-shadow: 0 0 16px rgba(0, 0, 0, 0.12),
                     0 16px 16px rgba(0, 0, 0, 0.24);
         color: inherit;
-        overflow: scroll;
+        overflow: auto;
         padding: 0;
         top: 0;
         width: 512px;
diff --git a/ui/webui/resources/cr_elements/network/cr_onc_types.js b/ui/webui/resources/cr_elements/network/cr_onc_types.js
index 82cf270..8382119 100644
--- a/ui/webui/resources/cr_elements/network/cr_onc_types.js
+++ b/ui/webui/resources/cr_elements/network/cr_onc_types.js
@@ -71,6 +71,9 @@
 /** @typedef {chrome.networkingPrivate.CellularSimState} */
 CrOnc.CellularSimState;
 
+/** @typedef {chrome.networkingPrivate.DeviceStateProperties} */
+CrOnc.DeviceStateProperties;
+
 /** @typedef {chrome.networkingPrivate.IPConfigProperties} */
 CrOnc.IPConfigProperties;
 
@@ -107,6 +110,9 @@
 CrOnc.ConnectionState = chrome.networkingPrivate.ConnectionStateType;
 
 /** @enum {string} */
+CrOnc.DeviceState = chrome.networkingPrivate.DeviceStateType;
+
+/** @enum {string} */
 CrOnc.IPConfigType = chrome.networkingPrivate.IPConfigType;
 
 /** @enum {string} */
diff --git a/ui/webui/resources/cr_elements/shared_style_css.html b/ui/webui/resources/cr_elements/shared_style_css.html
index 092881f..0c318c9 100644
--- a/ui/webui/resources/cr_elements/shared_style_css.html
+++ b/ui/webui/resources/cr_elements/shared_style_css.html
@@ -49,7 +49,8 @@
       }
 
       button[is='paper-icon-button-light'] {
-        @apply(--cr-paper-icon-button-margin);
+        -webkit-margin-end: var(--cr-icon-ripple-margin);
+        -webkit-margin-start: 16px;
         background-position: center;
         background-repeat: no-repeat;
         background-size: var(--cr-icon-size);
diff --git a/ui/webui/resources/cr_elements/shared_vars_css.html b/ui/webui/resources/cr_elements/shared_vars_css.html
index fe197c05..41a0089b7 100644
--- a/ui/webui/resources/cr_elements/shared_vars_css.html
+++ b/ui/webui/resources/cr_elements/shared_vars_css.html
@@ -24,10 +24,12 @@
       width: var(--cr-icon-size);
     }
 
+    --cr-icon-ripple-margin: calc(var(--cr-icon-ripple-padding) * -1);
+
     --cr-paper-icon-button-margin: {
       /* Shift button so ripple overlaps the end of the row. */
-      -webkit-margin-end: calc(var(--cr-icon-ripple-padding) * -1);
-      -webkit-margin-start: calc(var(--cr-icon-ripple-padding) * -1);
+      -webkit-margin-end: var(--cr-icon-ripple-margin);
+      -webkit-margin-start: var(--cr-icon-ripple-margin);
     }
 
     --cr-selectable-focus: {