diff --git a/DEPS b/DEPS
index 5c231cb..c2b84cf 100644
--- a/DEPS
+++ b/DEPS
@@ -86,7 +86,7 @@
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling ANGLE
   # and whatever else without interference from each other.
-  'angle_revision': 'f5be5bafa6f6376f20131c5c03b23a21b2ff6f80',
+  'angle_revision': '614dd0f537d4cc1d0390e7cfa0691c3f0c698399',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling build tools
   # and whatever else without interference from each other.
@@ -283,7 +283,7 @@
     Var('boringssl_git') + '/boringssl.git' + '@' +  Var('boringssl_revision'),
 
   'src/third_party/breakpad/breakpad':
-    Var('chromium_git') + '/breakpad/breakpad.git' + '@' + '8a0edac9abfec72e0a86aebd6a0a38761c7c8962',
+    Var('chromium_git') + '/breakpad/breakpad.git' + '@' + 'a61afe7a3e865f1da7ff7185184fe23977c2adca',
 
   'src/third_party/catapult':
     Var('chromium_git') + '/catapult.git' + '@' + Var('catapult_revision'),
diff --git a/ash/BUILD.gn b/ash/BUILD.gn
index ee187bf..656d31f 100644
--- a/ash/BUILD.gn
+++ b/ash/BUILD.gn
@@ -1709,8 +1709,6 @@
   sources = [
     "accessibility/test_accessibility_controller_client.cc",
     "accessibility/test_accessibility_controller_client.h",
-    "accessibility/test_accessibility_delegate.cc",
-    "accessibility/test_accessibility_delegate.h",
     "app_list/test_app_list_presenter_impl.cc",
     "app_list/test_app_list_presenter_impl.h",
     "display/display_configuration_controller_test_api.cc",
diff --git a/ash/accessibility/accessibility_controller.cc b/ash/accessibility/accessibility_controller.cc
index 8da5d7f..092dbfe 100644
--- a/ash/accessibility/accessibility_controller.cc
+++ b/ash/accessibility/accessibility_controller.cc
@@ -123,6 +123,17 @@
     client_->TriggerAccessibilityAlert(alert);
 }
 
+void AccessibilityController::PlayEarcon(int32_t sound_key) {
+  if (client_)
+    client_->PlayEarcon(sound_key);
+}
+
+void AccessibilityController::PlayShutdownSound(
+    base::OnceCallback<void(base::TimeDelta)> callback) {
+  if (client_)
+    client_->PlayShutdownSound(std::move(callback));
+}
+
 void AccessibilityController::SetClient(
     mojom::AccessibilityControllerClientPtr client) {
   client_ = std::move(client);
diff --git a/ash/accessibility/accessibility_controller.h b/ash/accessibility/accessibility_controller.h
index be6c88b2..67f6f507 100644
--- a/ash/accessibility/accessibility_controller.h
+++ b/ash/accessibility/accessibility_controller.h
@@ -12,6 +12,7 @@
 #include "ash/public/interfaces/accessibility_controller.mojom.h"
 #include "ash/session/session_observer.h"
 #include "base/macros.h"
+#include "base/time/time.h"
 #include "mojo/public/cpp/bindings/binding.h"
 
 class PrefChangeRegistrar;
@@ -52,6 +53,15 @@
   // Triggers an accessibility alert to give the user feedback.
   void TriggerAccessibilityAlert(mojom::AccessibilityAlert alert);
 
+  // Plays an earcon. Earcons are brief and distinctive sounds that indicate
+  // that their mapped event has occurred. The |sound_key| enums can be found in
+  // chromeos/audio/chromeos_sounds.h.
+  void PlayEarcon(int32_t sound_key);
+
+  // Initiates play of shutdown sound. The base::TimeDelta parameter gets the
+  // shutdown duration.
+  void PlayShutdownSound(base::OnceCallback<void(base::TimeDelta)> callback);
+
   // mojom::AccessibilityController:
   void SetClient(mojom::AccessibilityControllerClientPtr client) override;
 
diff --git a/ash/accessibility/accessibility_controller_unittest.cc b/ash/accessibility/accessibility_controller_unittest.cc
index b441e91..d7e5cc30 100644
--- a/ash/accessibility/accessibility_controller_unittest.cc
+++ b/ash/accessibility/accessibility_controller_unittest.cc
@@ -4,6 +4,7 @@
 
 #include "ash/accessibility/accessibility_controller.h"
 
+#include "ash/accessibility/test_accessibility_controller_client.h"
 #include "ash/ash_constants.h"
 #include "ash/public/cpp/ash_pref_names.h"
 #include "ash/session/session_controller.h"
@@ -15,6 +16,10 @@
 
 namespace ash {
 
+void CopyResult(base::TimeDelta* dest, base::TimeDelta src) {
+  *dest = src;
+}
+
 class TestAccessibilityObserver : public AccessibilityObserver {
  public:
   TestAccessibilityObserver() = default;
@@ -122,6 +127,22 @@
   Shell::Get()->system_tray_notifier()->RemoveAccessibilityObserver(&observer);
 }
 
+// Tests that ash's controller gets shutdown sound duration properly from
+// remote client.
+TEST_F(AccessibilityControllerTest, GetShutdownSoundDuration) {
+  AccessibilityController* controller =
+      Shell::Get()->accessibility_controller();
+  TestAccessibilityControllerClient client;
+  controller->SetClient(client.CreateInterfacePtrAndBind());
+
+  base::TimeDelta sound_duration;
+  controller->PlayShutdownSound(
+      base::BindOnce(&CopyResult, base::Unretained(&sound_duration)));
+  controller->FlushMojoForTest();
+  EXPECT_EQ(TestAccessibilityControllerClient::kShutdownSoundDuration,
+            sound_duration);
+}
+
 using AccessibilityControllerSigninTest = NoSessionAshTestBase;
 
 TEST_F(AccessibilityControllerSigninTest, SigninScreenPrefs) {
diff --git a/ash/accessibility/accessibility_delegate.h b/ash/accessibility/accessibility_delegate.h
index 15870f0b..7bd54ef3 100644
--- a/ash/accessibility/accessibility_delegate.h
+++ b/ash/accessibility/accessibility_delegate.h
@@ -119,14 +119,6 @@
   // Play tick sound indicating spoken feedback will be toggled after countdown.
   virtual void PlaySpokenFeedbackToggleCountdown(int tick_count) = 0;
 
-  // Plays an earcon. Earcons are brief and distinctive sounds that indicate
-  // when their mapped event has occurred. The sound key enums can be found in
-  // chromeos/audio/chromeos_sounds.h.
-  virtual void PlayEarcon(int sound_key) = 0;
-
-  // Initiates play of shutdown sound and returns it's duration.
-  virtual base::TimeDelta PlayShutdownSound() const = 0;
-
   // Forward an accessibility gesture from the touch exploration controller to
   // ChromeVox.
   virtual void HandleAccessibilityGesture(ui::AXGesture gesture) = 0;
diff --git a/ash/accessibility/default_accessibility_delegate.cc b/ash/accessibility/default_accessibility_delegate.cc
index f3e6183..6d31eb4 100644
--- a/ash/accessibility/default_accessibility_delegate.cc
+++ b/ash/accessibility/default_accessibility_delegate.cc
@@ -133,12 +133,6 @@
 void DefaultAccessibilityDelegate::PlaySpokenFeedbackToggleCountdown(
     int tick_count) {}
 
-void DefaultAccessibilityDelegate::PlayEarcon(int sound_key) {}
-
-base::TimeDelta DefaultAccessibilityDelegate::PlayShutdownSound() const {
-  return base::TimeDelta();
-}
-
 void DefaultAccessibilityDelegate::HandleAccessibilityGesture(
     ui::AXGesture gesture) {}
 
diff --git a/ash/accessibility/default_accessibility_delegate.h b/ash/accessibility/default_accessibility_delegate.h
index 74ca6f193..a64d9425 100644
--- a/ash/accessibility/default_accessibility_delegate.h
+++ b/ash/accessibility/default_accessibility_delegate.h
@@ -47,8 +47,6 @@
   double GetSavedScreenMagnifierScale() override;
   bool ShouldToggleSpokenFeedbackViaTouch() override;
   void PlaySpokenFeedbackToggleCountdown(int tick_count) override;
-  void PlayEarcon(int sound_key) override;
-  base::TimeDelta PlayShutdownSound() const override;
   void HandleAccessibilityGesture(ui::AXGesture gesture) override;
 
  private:
diff --git a/ash/accessibility/test_accessibility_controller_client.cc b/ash/accessibility/test_accessibility_controller_client.cc
index faa5d60..e95099e 100644
--- a/ash/accessibility/test_accessibility_controller_client.cc
+++ b/ash/accessibility/test_accessibility_controller_client.cc
@@ -6,6 +6,9 @@
 
 namespace ash {
 
+constexpr base::TimeDelta
+    TestAccessibilityControllerClient::kShutdownSoundDuration;
+
 TestAccessibilityControllerClient::TestAccessibilityControllerClient()
     : binding_(this) {}
 
@@ -24,4 +27,19 @@
   last_a11y_alert_ = alert;
 }
 
+void TestAccessibilityControllerClient::PlayEarcon(int32_t sound_key) {
+  sound_key_ = sound_key;
+}
+
+void TestAccessibilityControllerClient::PlayShutdownSound(
+    PlayShutdownSoundCallback callback) {
+  std::move(callback).Run(kShutdownSoundDuration);
+}
+
+int32_t TestAccessibilityControllerClient::GetPlayedEarconAndReset() {
+  int32_t tmp = sound_key_;
+  sound_key_ = -1;
+  return tmp;
+}
+
 }  // namespace ash
diff --git a/ash/accessibility/test_accessibility_controller_client.h b/ash/accessibility/test_accessibility_controller_client.h
index 2ba2e7f..8f29d7c 100644
--- a/ash/accessibility/test_accessibility_controller_client.h
+++ b/ash/accessibility/test_accessibility_controller_client.h
@@ -7,6 +7,7 @@
 
 #include "ash/public/interfaces/accessibility_controller.mojom.h"
 #include "base/macros.h"
+#include "base/time/time.h"
 #include "mojo/public/cpp/bindings/binding.h"
 
 namespace ash {
@@ -20,16 +21,25 @@
   TestAccessibilityControllerClient();
   ~TestAccessibilityControllerClient() override;
 
+  static constexpr base::TimeDelta kShutdownSoundDuration =
+      base::TimeDelta::FromMilliseconds(1000);
+
   mojom::AccessibilityControllerClientPtr CreateInterfacePtrAndBind();
 
   // mojom::AccessibilityControllerClient:
   void TriggerAccessibilityAlert(mojom::AccessibilityAlert alert) override;
+  void PlayEarcon(int32_t sound_key) override;
+  void PlayShutdownSound(PlayShutdownSoundCallback callback) override;
+
+  int32_t GetPlayedEarconAndReset();
 
   mojom::AccessibilityAlert last_a11y_alert() const { return last_a11y_alert_; }
 
  private:
   mojom::AccessibilityAlert last_a11y_alert_ = mojom::AccessibilityAlert::NONE;
 
+  int32_t sound_key_ = -1;
+
   mojo::Binding<mojom::AccessibilityControllerClient> binding_;
 
   DISALLOW_COPY_AND_ASSIGN(TestAccessibilityControllerClient);
diff --git a/ash/accessibility/test_accessibility_delegate.cc b/ash/accessibility/test_accessibility_delegate.cc
deleted file mode 100644
index db580139..0000000
--- a/ash/accessibility/test_accessibility_delegate.cc
+++ /dev/null
@@ -1,19 +0,0 @@
-// Copyright 2017 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "ash/accessibility/test_accessibility_delegate.h"
-
-namespace ash {
-
-void TestAccessibilityDelegate::PlayEarcon(int sound_key) {
-  sound_key_ = sound_key;
-}
-
-int TestAccessibilityDelegate::GetPlayedEarconAndReset() {
-  int tmp = sound_key_;
-  sound_key_ = -1;
-  return tmp;
-}
-
-}  // namespace ash
diff --git a/ash/accessibility/test_accessibility_delegate.h b/ash/accessibility/test_accessibility_delegate.h
deleted file mode 100644
index 4b47a56..0000000
--- a/ash/accessibility/test_accessibility_delegate.h
+++ /dev/null
@@ -1,31 +0,0 @@
-// Copyright 2017 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef ASH_ACCESSIBILITY_TEST_ACCESSIBILITY_DELEGATE_H_
-#define ASH_ACCESSIBILITY_TEST_ACCESSIBILITY_DELEGATE_H_
-
-#include "ash/accessibility/default_accessibility_delegate.h"
-#include "base/macros.h"
-
-namespace ash {
-
-class TestAccessibilityDelegate : public DefaultAccessibilityDelegate {
- public:
-  TestAccessibilityDelegate() {}
-  ~TestAccessibilityDelegate() override {}
-
-  // AccessibilityDelegate:
-  void PlayEarcon(int sound_key) override;
-
-  int GetPlayedEarconAndReset();
-
- private:
-  int sound_key_ = -1;
-
-  DISALLOW_COPY_AND_ASSIGN(TestAccessibilityDelegate);
-};
-
-}  // namespace ash
-
-#endif  // ASH_ACCESSIBILITY_TEST_ACCESSIBILITY_DELEGATE_H_
diff --git a/ash/ash_touch_exploration_manager_chromeos.cc b/ash/ash_touch_exploration_manager_chromeos.cc
index a453885..287a457 100644
--- a/ash/ash_touch_exploration_manager_chromeos.cc
+++ b/ash/ash_touch_exploration_manager_chromeos.cc
@@ -7,6 +7,7 @@
 #include <memory>
 #include <vector>
 
+#include "ash/accessibility/accessibility_controller.h"
 #include "ash/accessibility/accessibility_delegate.h"
 #include "ash/accessibility/accessibility_focus_ring_controller.h"
 #include "ash/keyboard/keyboard_observer_register.h"
@@ -76,23 +77,23 @@
     return;
   if (!audio_handler_->IsOutputMuted() &&
       audio_handler_->GetOutputVolumePercent() != 100) {
-    Shell::Get()->accessibility_delegate()->PlayEarcon(
+    Shell::Get()->accessibility_controller()->PlayEarcon(
         chromeos::SOUND_VOLUME_ADJUST);
   }
 }
 
 void AshTouchExplorationManager::PlayPassthroughEarcon() {
-  Shell::Get()->accessibility_delegate()->PlayEarcon(
+  Shell::Get()->accessibility_controller()->PlayEarcon(
       chromeos::SOUND_PASSTHROUGH);
 }
 
 void AshTouchExplorationManager::PlayExitScreenEarcon() {
-  Shell::Get()->accessibility_delegate()->PlayEarcon(
+  Shell::Get()->accessibility_controller()->PlayEarcon(
       chromeos::SOUND_EXIT_SCREEN);
 }
 
 void AshTouchExplorationManager::PlayEnterScreenEarcon() {
-  Shell::Get()->accessibility_delegate()->PlayEarcon(
+  Shell::Get()->accessibility_controller()->PlayEarcon(
       chromeos::SOUND_ENTER_SCREEN);
 }
 
@@ -129,7 +130,7 @@
 }
 
 void AshTouchExplorationManager::PlayTouchTypeEarcon() {
-  Shell::Get()->accessibility_delegate()->PlayEarcon(
+  Shell::Get()->accessibility_controller()->PlayEarcon(
       chromeos::SOUND_TOUCH_TYPE);
 }
 
diff --git a/ash/public/interfaces/accessibility_controller.mojom b/ash/public/interfaces/accessibility_controller.mojom
index c73f7a6..c78a0fec 100644
--- a/ash/public/interfaces/accessibility_controller.mojom
+++ b/ash/public/interfaces/accessibility_controller.mojom
@@ -4,6 +4,8 @@
 
 module ash.mojom;
 
+import "mojo/common/time.mojom";
+
 // Alert sent to the accessibility api.
 enum AccessibilityAlert {
   // Default value, indicates no accessibility alert.
@@ -47,4 +49,14 @@
 interface AccessibilityControllerClient {
   // Triggers an accessibility alert to give the user feedback.
   TriggerAccessibilityAlert(AccessibilityAlert alert);
+
+  // Plays an earcon. Earcons are brief and distinctive sounds that indicate
+  // that their mapped event has occurred. The |sound_key| enums can be found in
+  // chromeos/audio/chromeos_sounds.h. This method exists because the browser
+  // owns all media playback.
+  PlayEarcon(int32 sound_key);
+
+  // Initiates play of shutdown sound and returns sound duration. This method
+  // exists because the browser owns all media playback.
+  PlayShutdownSound() => (mojo.common.mojom.TimeDelta sound_duration);
 };
diff --git a/ash/test_shell_delegate.cc b/ash/test_shell_delegate.cc
index 10247c2..7e61d26 100644
--- a/ash/test_shell_delegate.cc
+++ b/ash/test_shell_delegate.cc
@@ -4,7 +4,7 @@
 
 #include "ash/test_shell_delegate.h"
 
-#include "ash/accessibility/test_accessibility_delegate.h"
+#include "ash/accessibility/default_accessibility_delegate.h"
 #include "ash/keyboard/test_keyboard_ui.h"
 #include "ash/system/tray/system_tray_notifier.h"
 #include "ash/test_screenshot_delegate.h"
@@ -59,7 +59,7 @@
 }
 
 AccessibilityDelegate* TestShellDelegate::CreateAccessibilityDelegate() {
-  return new TestAccessibilityDelegate();
+  return new DefaultAccessibilityDelegate;
 }
 
 base::string16 TestShellDelegate::GetProductName() const {
diff --git a/ash/wm/lock_state_controller.cc b/ash/wm/lock_state_controller.cc
index c56275c..6e50ac9 100644
--- a/ash/wm/lock_state_controller.cc
+++ b/ash/wm/lock_state_controller.cc
@@ -8,7 +8,7 @@
 #include <string>
 #include <utility>
 
-#include "ash/accessibility/accessibility_delegate.h"
+#include "ash/accessibility/accessibility_controller.h"
 #include "ash/cancel_mode.h"
 #include "ash/public/cpp/shell_window_ids.h"
 #include "ash/public/interfaces/shutdown.mojom.h"
@@ -310,18 +310,22 @@
     duration +=
         animator_->GetDuration(SessionStateAnimator::ANIMATION_SPEED_SHUTDOWN);
   }
-
-  base::TimeDelta sound_duration =
-      Shell::Get()->accessibility_delegate()->PlayShutdownSound();
-  sound_duration =
-      std::min(sound_duration,
-               base::TimeDelta::FromMilliseconds(kMaxShutdownSoundDurationMs));
-  duration = std::max(duration, sound_duration);
-
-  real_shutdown_timer_.Start(
-      FROM_HERE, duration,
-      base::Bind(&LockStateController::OnRealPowerTimeout,
-                 base::Unretained(this)));
+  // Play and get shutdown sound duration from chrome in |sound_duration|. And
+  // start real shutdown after a delay of |duration|.
+  Shell::Get()->accessibility_controller()->PlayShutdownSound(base::BindOnce(
+      [](base::WeakPtr<LockStateController> self, base::TimeDelta duration,
+         base::TimeDelta sound_duration) {
+        if (!self)
+          return;
+        sound_duration = std::min(
+            sound_duration,
+            base::TimeDelta::FromMilliseconds(kMaxShutdownSoundDurationMs));
+        duration = std::max(duration, sound_duration);
+        self->real_shutdown_timer_.Start(
+            FROM_HERE, duration, self.get(),
+            &LockStateController::OnRealPowerTimeout);
+      },
+      weak_ptr_factory_.GetWeakPtr(), duration));
 }
 
 void LockStateController::OnRealPowerTimeout() {
diff --git a/ash/wm/lock_state_controller_unittest.cc b/ash/wm/lock_state_controller_unittest.cc
index 8be973b..6ae558ee 100644
--- a/ash/wm/lock_state_controller_unittest.cc
+++ b/ash/wm/lock_state_controller_unittest.cc
@@ -7,6 +7,8 @@
 #include <memory>
 #include <utility>
 
+#include "ash/accessibility/accessibility_controller.h"
+#include "ash/accessibility/test_accessibility_controller_client.h"
 #include "ash/public/cpp/ash_switches.h"
 #include "ash/public/cpp/config.h"
 #include "ash/session/session_controller.h"
@@ -74,6 +76,9 @@
     test_animator_ = new TestSessionStateAnimator;
     lock_state_controller_->set_animator_for_test(test_animator_);
     lock_state_test_api_->set_shutdown_controller(&test_shutdown_controller_);
+
+    a11y_controller_ = Shell::Get()->accessibility_controller();
+    a11y_controller_->SetClient(a11y_client_.CreateInterfacePtrAndBind());
   }
 
  protected:
@@ -264,8 +269,13 @@
     lock_state_controller_->OnLockScreenHide(closure);
   }
 
+  // Simulate that shutdown sound duration callback is done.
+  void ShutdownSoundPlayed() { a11y_controller_->FlushMojoForTest(); }
+
   TestShutdownController test_shutdown_controller_;
   TestSessionStateAnimator* test_animator_ = nullptr;  // not owned
+  AccessibilityController* a11y_controller_;
+  TestAccessibilityControllerClient a11y_client_;
 
  private:
   DISALLOW_COPY_AND_ASSIGN(LockStateControllerTest);
@@ -320,6 +330,7 @@
   if (Shell::GetAshConfig() != Config::MASH)
     EXPECT_FALSE(cursor_visible());
 
+  ShutdownSoundPlayed();
   EXPECT_TRUE(lock_state_test_api_->real_shutdown_timer_is_running());
   lock_state_test_api_->trigger_real_shutdown_timeout();
   EXPECT_EQ(1, NumShutdownRequests());
@@ -333,6 +344,7 @@
   PressPowerButton();
   ExpectShutdownAnimationStarted();
 
+  ShutdownSoundPlayed();
   EXPECT_TRUE(lock_state_test_api_->real_shutdown_timer_is_running());
 }
 
@@ -344,6 +356,7 @@
   PressPowerButton();
   ExpectShutdownAnimationStarted();
 
+  ShutdownSoundPlayed();
   EXPECT_TRUE(lock_state_test_api_->real_shutdown_timer_is_running());
 }
 
@@ -378,6 +391,7 @@
   ExpectShutdownAnimationFinished();
   lock_state_test_api_->trigger_shutdown_timeout();
 
+  ShutdownSoundPlayed();
   EXPECT_TRUE(lock_state_test_api_->real_shutdown_timer_is_running());
   EXPECT_EQ(0, NumShutdownRequests());
 
@@ -539,6 +553,7 @@
   ExpectShutdownAnimationFinished();
   lock_state_test_api_->trigger_shutdown_timeout();
 
+  ShutdownSoundPlayed();
   EXPECT_TRUE(lock_state_test_api_->real_shutdown_timer_is_running());
   EXPECT_EQ(0, NumShutdownRequests());
   lock_state_test_api_->trigger_real_shutdown_timeout();
@@ -754,6 +769,7 @@
     EXPECT_FALSE(cursor_visible());
 
   EXPECT_EQ(0, NumShutdownRequests());
+  ShutdownSoundPlayed();
   EXPECT_TRUE(lock_state_test_api_->real_shutdown_timer_is_running());
   lock_state_test_api_->trigger_real_shutdown_timeout();
   EXPECT_EQ(1, NumShutdownRequests());
@@ -779,6 +795,7 @@
     EXPECT_FALSE(cursor_visible());
 
   EXPECT_EQ(0, NumShutdownRequests());
+  ShutdownSoundPlayed();
   EXPECT_TRUE(lock_state_test_api_->real_shutdown_timer_is_running());
   lock_state_test_api_->trigger_real_shutdown_timeout();
   EXPECT_EQ(1, NumShutdownRequests());
diff --git a/ash/wm/workspace/backdrop_controller.cc b/ash/wm/workspace/backdrop_controller.cc
index 87785864c..4a62110 100644
--- a/ash/wm/workspace/backdrop_controller.cc
+++ b/ash/wm/workspace/backdrop_controller.cc
@@ -6,6 +6,7 @@
 
 #include <memory>
 
+#include "ash/accessibility/accessibility_controller.h"
 #include "ash/accessibility/accessibility_delegate.h"
 #include "ash/public/cpp/app_types.h"
 #include "ash/public/cpp/shell_window_ids.h"
@@ -47,7 +48,7 @@
         case ui::ET_GESTURE_BEGIN:
         case ui::ET_SCROLL:
         case ui::ET_SCROLL_FLING_START:
-          Shell::Get()->accessibility_delegate()->PlayEarcon(
+          Shell::Get()->accessibility_controller()->PlayEarcon(
               chromeos::SOUND_VOLUME_ADJUST);
           break;
         default:
diff --git a/ash/wm/workspace/workspace_layout_manager_unittest.cc b/ash/wm/workspace/workspace_layout_manager_unittest.cc
index a2d2763..b24cc0d4 100644
--- a/ash/wm/workspace/workspace_layout_manager_unittest.cc
+++ b/ash/wm/workspace/workspace_layout_manager_unittest.cc
@@ -7,7 +7,9 @@
 #include <string>
 #include <utility>
 
-#include "ash/accessibility/test_accessibility_delegate.h"
+#include "ash/accessibility/accessibility_controller.h"
+#include "ash/accessibility/accessibility_delegate.h"
+#include "ash/accessibility/test_accessibility_controller_client.h"
 #include "ash/app_list/test_app_list_presenter_impl.h"
 #include "ash/frame/custom_frame_view_ash.h"
 #include "ash/public/cpp/app_types.h"
@@ -1302,9 +1304,10 @@
 TEST_F(WorkspaceLayoutManagerBackdropTest, SpokenFeedbackFullscreenBackground) {
   WorkspaceController* wc = ShellTestApi(Shell::Get()).workspace_controller();
   WorkspaceControllerTestApi test_helper(wc);
-  TestAccessibilityDelegate* accessibility_delegate =
-      static_cast<TestAccessibilityDelegate*>(
-          Shell::Get()->accessibility_delegate());
+  AccessibilityController* controller =
+      Shell::Get()->accessibility_controller();
+  TestAccessibilityControllerClient client;
+  controller->SetClient(client.CreateInterfacePtrAndBind());
 
   aura::test::TestWindowDelegate delegate;
   std::unique_ptr<aura::Window> window(CreateTestWindowInShellWithDelegate(
@@ -1318,11 +1321,13 @@
 
   generator.MoveMouseTo(300, 300);
   generator.ClickLeftButton();
-  EXPECT_EQ(kNoSoundKey, accessibility_delegate->GetPlayedEarconAndReset());
+  controller->FlushMojoForTest();
+  EXPECT_EQ(kNoSoundKey, client.GetPlayedEarconAndReset());
 
   generator.MoveMouseRelativeTo(window.get(), 10, 10);
   generator.ClickLeftButton();
-  EXPECT_EQ(kNoSoundKey, accessibility_delegate->GetPlayedEarconAndReset());
+  controller->FlushMojoForTest();
+  EXPECT_EQ(kNoSoundKey, client.GetPlayedEarconAndReset());
 
   // Enable spoken feedback.
   Shell::Get()->accessibility_delegate()->ToggleSpokenFeedback(
@@ -1334,12 +1339,13 @@
 
   generator.MoveMouseTo(300, 300);
   generator.ClickLeftButton();
-  EXPECT_EQ(chromeos::SOUND_VOLUME_ADJUST,
-            accessibility_delegate->GetPlayedEarconAndReset());
+  controller->FlushMojoForTest();
+  EXPECT_EQ(chromeos::SOUND_VOLUME_ADJUST, client.GetPlayedEarconAndReset());
 
   generator.MoveMouseRelativeTo(window.get(), 10, 10);
   generator.ClickLeftButton();
-  EXPECT_EQ(kNoSoundKey, accessibility_delegate->GetPlayedEarconAndReset());
+  controller->FlushMojoForTest();
+  EXPECT_EQ(kNoSoundKey, client.GetPlayedEarconAndReset());
 
   // Disable spoken feedback. Shadow underlay is restored.
   Shell::Get()->accessibility_delegate()->ToggleSpokenFeedback(
@@ -1351,11 +1357,13 @@
 
   generator.MoveMouseTo(300, 300);
   generator.ClickLeftButton();
-  EXPECT_EQ(kNoSoundKey, accessibility_delegate->GetPlayedEarconAndReset());
+  controller->FlushMojoForTest();
+  EXPECT_EQ(kNoSoundKey, client.GetPlayedEarconAndReset());
 
   generator.MoveMouseTo(70, 70);
   generator.ClickLeftButton();
-  EXPECT_EQ(kNoSoundKey, accessibility_delegate->GetPlayedEarconAndReset());
+  controller->FlushMojoForTest();
+  EXPECT_EQ(kNoSoundKey, client.GetPlayedEarconAndReset());
 }
 
 TEST_F(WorkspaceLayoutManagerBackdropTest,
@@ -1438,14 +1446,17 @@
 TEST_F(WorkspaceLayoutManagerBackdropTest, SpokenFeedbackForArc) {
   WorkspaceController* wc = ShellTestApi(Shell::Get()).workspace_controller();
   WorkspaceControllerTestApi test_helper(wc);
-  TestAccessibilityDelegate* accessibility_delegate =
-      static_cast<TestAccessibilityDelegate*>(
-          Shell::Get()->accessibility_delegate());
+  AccessibilityController* controller =
+      Shell::Get()->accessibility_controller();
+  TestAccessibilityControllerClient client;
+  controller->SetClient(client.CreateInterfacePtrAndBind());
 
-  accessibility_delegate->ToggleSpokenFeedback(A11Y_NOTIFICATION_NONE);
+  Shell::Get()->accessibility_delegate()->ToggleSpokenFeedback(
+      A11Y_NOTIFICATION_NONE);
   Shell::Get()->system_tray_notifier()->NotifyAccessibilityStatusChanged(
       A11Y_NOTIFICATION_NONE);
-  EXPECT_TRUE(accessibility_delegate->IsSpokenFeedbackEnabled());
+  EXPECT_TRUE(
+      Shell::Get()->accessibility_delegate()->IsSpokenFeedbackEnabled());
 
   aura::test::TestWindowDelegate delegate;
   std::unique_ptr<aura::Window> window_arc(CreateTestWindowInShellWithDelegate(
@@ -1474,12 +1485,13 @@
   ui::test::EventGenerator& generator = GetEventGenerator();
   generator.MoveMouseTo(300, 300);
   generator.ClickLeftButton();
-  EXPECT_EQ(chromeos::SOUND_VOLUME_ADJUST,
-            accessibility_delegate->GetPlayedEarconAndReset());
+  controller->FlushMojoForTest();
+  EXPECT_EQ(chromeos::SOUND_VOLUME_ADJUST, client.GetPlayedEarconAndReset());
 
   generator.MoveMouseTo(70, 70);
   generator.ClickLeftButton();
-  EXPECT_EQ(kNoSoundKey, accessibility_delegate->GetPlayedEarconAndReset());
+  controller->FlushMojoForTest();
+  EXPECT_EQ(kNoSoundKey, client.GetPlayedEarconAndReset());
 }
 
 class WorkspaceLayoutManagerKeyboardTest : public AshTestBase {
diff --git a/chrome/VERSION b/chrome/VERSION
index 6b9dd7f..d654e4f1 100644
--- a/chrome/VERSION
+++ b/chrome/VERSION
@@ -1,4 +1,4 @@
 MAJOR=65
 MINOR=0
-BUILD=3285
+BUILD=3286
 PATCH=0
diff --git a/chrome/browser/chromeos/accessibility/accessibility_manager.cc b/chrome/browser/chromeos/accessibility/accessibility_manager.cc
index eac1f79..f53dc7d 100644
--- a/chrome/browser/chromeos/accessibility/accessibility_manager.cc
+++ b/chrome/browser/chromeos/accessibility/accessibility_manager.cc
@@ -101,11 +101,11 @@
 namespace {
 
 // When this flag is set, system sounds will not be played.
-const char kAshDisableSystemSounds[] = "ash-disable-system-sounds";
+constexpr char kAshDisableSystemSounds[] = "ash-disable-system-sounds";
 
-static chromeos::AccessibilityManager* g_accessibility_manager = NULL;
+static chromeos::AccessibilityManager* g_accessibility_manager = nullptr;
 
-static BrailleController* g_braille_controller_for_test = NULL;
+static BrailleController* g_braille_controller_for_test = nullptr;
 
 BrailleController* GetBrailleController() {
   if (g_braille_controller_for_test)
@@ -537,7 +537,7 @@
   base::CommandLine* cl = base::CommandLine::ForCurrentProcess();
   if (cl->HasSwitch(kAshDisableSystemSounds))
     return false;
-  if (option == PlaySoundOption::SPOKEN_FEEDBACK_ENABLED &&
+  if (option == PlaySoundOption::ONLY_IF_SPOKEN_FEEDBACK_ENABLED &&
       !IsSpokenFeedbackEnabled()) {
     return false;
   }
@@ -1250,8 +1250,10 @@
 }
 
 base::TimeDelta AccessibilityManager::PlayShutdownSound() {
-  if (!PlayEarcon(SOUND_SHUTDOWN, PlaySoundOption::SPOKEN_FEEDBACK_ENABLED))
+  if (!PlayEarcon(SOUND_SHUTDOWN,
+                  PlaySoundOption::ONLY_IF_SPOKEN_FEEDBACK_ENABLED)) {
     return base::TimeDelta();
+  }
   return media::SoundsManager::Get()->GetDuration(SOUND_SHUTDOWN);
 }
 
@@ -1446,6 +1448,7 @@
 void AccessibilityManager::PostUnloadChromeVox() {
   // Do any teardown work needed immediately after ChromeVox actually unloads.
   PlayEarcon(SOUND_SPOKEN_FEEDBACK_DISABLED, PlaySoundOption::ALWAYS);
+
   // Clear the accessibility focus ring.
   ash::AccessibilityFocusRingController::GetInstance()->SetFocusRing(
       std::vector<gfx::Rect>(),
diff --git a/chrome/browser/chromeos/accessibility/accessibility_manager.h b/chrome/browser/chromeos/accessibility/accessibility_manager.h
index 728c8a7..54d25fa 100644
--- a/chrome/browser/chromeos/accessibility/accessibility_manager.h
+++ b/chrome/browser/chromeos/accessibility/accessibility_manager.h
@@ -79,10 +79,12 @@
 class ChromeVoxPanelWidgetObserver;
 
 enum class PlaySoundOption {
-  ALWAYS = 0,               // The sound is always played.
-  SPOKEN_FEEDBACK_ENABLED,  // The sound is played only if spoken feedback is
-                            // enabled, or --ash-enable-system-sounds flag is
-                            // used.
+  // The sound is always played.
+  ALWAYS = 0,
+
+  // The sound is played only if spoken feedback is enabled, or
+  // --ash-enable-system-sounds flag is used.
+  ONLY_IF_SPOKEN_FEEDBACK_ENABLED,
 };
 
 // AccessibilityManager changes the statuses of accessibility features
@@ -264,7 +266,7 @@
   void OnViewFocusedInArc(const gfx::Rect& bounds_in_screen);
 
   // Plays an earcon. Earcons are brief and distinctive sounds that indicate
-  // when their mapped event has occurred. The sound key enums can be found in
+  // the their mapped event has occurred. The |sound_key| enums can be found in
   // chromeos/audio/chromeos_sounds.h.
   bool PlayEarcon(int sound_key, PlaySoundOption option);
 
diff --git a/chrome/browser/chromeos/file_manager/volume_manager_unittest.cc b/chrome/browser/chromeos/file_manager/volume_manager_unittest.cc
index 464ee23e..8d05fb7 100644
--- a/chrome/browser/chromeos/file_manager/volume_manager_unittest.cc
+++ b/chrome/browser/chromeos/file_manager/volume_manager_unittest.cc
@@ -6,7 +6,9 @@
 
 #include <stddef.h>
 
+#include <memory>
 #include <string>
+#include <utility>
 #include <vector>
 
 #include "base/macros.h"
@@ -16,7 +18,6 @@
 #include "chrome/browser/chromeos/file_manager/fake_disk_mount_manager.h"
 #include "chrome/browser/chromeos/file_manager/volume_manager_observer.h"
 #include "chrome/browser/chromeos/file_system_provider/fake_extension_provider.h"
-#include "chrome/browser/chromeos/file_system_provider/fake_provided_file_system.h"
 #include "chrome/browser/chromeos/file_system_provider/service.h"
 #include "chrome/common/pref_names.h"
 #include "chrome/test/base/testing_profile.h"
@@ -182,9 +183,6 @@
               file_system_provider_service_.get(),
               base::Bind(&ProfileEnvironment::GetFakeMtpStorageInfo,
                          base::Unretained(this)))) {
-      file_system_provider_service_->SetExtensionProviderForTesting(
-          std::make_unique<
-              chromeos::file_system_provider::FakeExtensionProvider>());
     }
 
     Profile* profile() const { return profile_.get(); }
diff --git a/chrome/browser/chromeos/file_system_provider/extension_provider.cc b/chrome/browser/chromeos/file_system_provider/extension_provider.cc
index 86a14a4..971a9ea 100644
--- a/chrome/browser/chromeos/file_system_provider/extension_provider.cc
+++ b/chrome/browser/chromeos/file_system_provider/extension_provider.cc
@@ -11,7 +11,6 @@
 
 #include "base/memory/ptr_util.h"
 #include "chrome/browser/chromeos/file_system_provider/provided_file_system.h"
-#include "chrome/browser/chromeos/file_system_provider/service.h"
 #include "chrome/browser/chromeos/file_system_provider/throttled_file_system.h"
 #include "chrome/browser/profiles/profile.h"
 #include "extensions/browser/extension_registry.h"
@@ -23,12 +22,10 @@
 
 // Returns boolean indicating success. result->capabilities contains the
 // capabilites of the extension.
-bool GetProvidingExtensionInfo(const std::string& extension_id,
+bool GetProvidingExtensionInfo(const extensions::ExtensionId& extension_id,
                                ProvidingExtensionInfo* result,
-                               Profile* profile) {
+                               extensions::ExtensionRegistry* registry) {
   DCHECK(result);
-  extensions::ExtensionRegistry* const registry =
-      extensions::ExtensionRegistry::Get(profile);
   DCHECK(registry);
 
   const extensions::Extension* const extension = registry->GetExtensionById(
@@ -50,6 +47,22 @@
 
 }  // namespace
 
+ProvidingExtensionInfo::ProvidingExtensionInfo() = default;
+
+ProvidingExtensionInfo::~ProvidingExtensionInfo() = default;
+
+// static
+std::unique_ptr<ProviderInterface> ExtensionProvider::Create(
+    extensions::ExtensionRegistry* registry,
+    const extensions::ExtensionId& extension_id) {
+  ProvidingExtensionInfo info;
+  if (!GetProvidingExtensionInfo(extension_id, &info, registry))
+    return nullptr;
+
+  return std::unique_ptr<ProviderInterface>(
+      new ExtensionProvider(extension_id, info));
+}
+
 std::unique_ptr<ProvidedFileSystemInterface>
 ExtensionProvider::CreateProvidedFileSystem(
     Profile* profile,
@@ -59,24 +72,23 @@
       std::make_unique<ProvidedFileSystem>(profile, file_system_info));
 }
 
-bool ExtensionProvider::GetCapabilities(Profile* profile,
-                                        const ProviderId& provider_id,
-                                        Capabilities& result) {
-  ProvidingExtensionInfo providing_extension_info;
-
-  // TODO(baileyberro): Change this so error is not swallowed once
-  // bug is resolved (crrev.com/c/767629).
-  bool success = GetProvidingExtensionInfo(provider_id.GetExtensionId(),
-                                           &providing_extension_info, profile);
-
-  result = Capabilities(providing_extension_info.capabilities.configurable(),
-                        providing_extension_info.capabilities.watchable(),
-                        providing_extension_info.capabilities.multiple_mounts(),
-                        providing_extension_info.capabilities.source());
-  return success;
+const Capabilities& ExtensionProvider::GetCapabilities() const {
+  return capabilities_;
 }
 
-ExtensionProvider::ExtensionProvider() {}
+const ProviderId& ExtensionProvider::GetId() const {
+  return provider_id_;
+}
+
+ExtensionProvider::ExtensionProvider(
+    const extensions::ExtensionId& extension_id,
+    const ProvidingExtensionInfo& info)
+    : provider_id_(ProviderId::CreateFromExtensionId(extension_id)) {
+  capabilities_.configurable = info.capabilities.configurable();
+  capabilities_.watchable = info.capabilities.watchable();
+  capabilities_.multiple_mounts = info.capabilities.multiple_mounts();
+  capabilities_.source = info.capabilities.source();
+}
 
 }  // namespace file_system_provider
 }  // namespace chromeos
diff --git a/chrome/browser/chromeos/file_system_provider/extension_provider.h b/chrome/browser/chromeos/file_system_provider/extension_provider.h
index ce74411..c84594820 100644
--- a/chrome/browser/chromeos/file_system_provider/extension_provider.h
+++ b/chrome/browser/chromeos/file_system_provider/extension_provider.h
@@ -6,30 +6,55 @@
 #define CHROME_BROWSER_CHROMEOS_FILE_SYSTEM_PROVIDER_EXTENSION_PROVIDER_H_
 
 #include <memory>
+#include <string>
 
+#include "chrome/browser/chromeos/file_system_provider/provided_file_system_info.h"
 #include "chrome/browser/chromeos/file_system_provider/provided_file_system_interface.h"
 #include "chrome/browser/chromeos/file_system_provider/provider_interface.h"
+#include "extensions/common/extension_id.h"
 
 class Profile;
 
+namespace extensions {
+class ExtensionRegistry;
+}  // namespace extensions
+
 namespace chromeos {
 namespace file_system_provider {
 
-class ProvidedFileSystemInfo;
-class ProviderId;
+// Holds information for a providing extension.
+struct ProvidingExtensionInfo {
+  ProvidingExtensionInfo();
+  ~ProvidingExtensionInfo();
+
+  extensions::ExtensionId extension_id;
+  std::string name;
+  extensions::FileSystemProviderCapabilities capabilities;
+};
 
 class ExtensionProvider : public ProviderInterface {
  public:
-  ExtensionProvider();
   ~ExtensionProvider() override {}
 
+  // Returns a provider instance for the specified extension. If the extension
+  // cannot be a providing extension, returns nullptr.
+  static std::unique_ptr<ProviderInterface> Create(
+      extensions::ExtensionRegistry* registry,
+      const extensions::ExtensionId& extension_id);
+
   // ProviderInterface overrides.
   std::unique_ptr<ProvidedFileSystemInterface> CreateProvidedFileSystem(
       Profile* profile,
       const ProvidedFileSystemInfo& file_system_info) override;
-  bool GetCapabilities(Profile* profile,
-                       const ProviderId& provider_id,
-                       Capabilities& result) override;
+  const Capabilities& GetCapabilities() const override;
+  const ProviderId& GetId() const override;
+
+ private:
+  ExtensionProvider(const extensions::ExtensionId& extension_id,
+                    const ProvidingExtensionInfo& info);
+
+  ProviderId provider_id_;
+  Capabilities capabilities_;
 };
 
 }  // namespace file_system_provider
diff --git a/chrome/browser/chromeos/file_system_provider/fake_extension_provider.cc b/chrome/browser/chromeos/file_system_provider/fake_extension_provider.cc
index aa53a8e6..c7bcc9df 100644
--- a/chrome/browser/chromeos/file_system_provider/fake_extension_provider.cc
+++ b/chrome/browser/chromeos/file_system_provider/fake_extension_provider.cc
@@ -12,13 +12,21 @@
 #include "base/memory/ptr_util.h"
 #include "chrome/browser/chromeos/file_system_provider/fake_provided_file_system.h"
 #include "chrome/browser/chromeos/file_system_provider/service.h"
-#include "chrome/browser/profiles/profile.h"
 #include "extensions/browser/extension_registry.h"
 #include "extensions/common/permissions/permissions_data.h"
 
 namespace chromeos {
 namespace file_system_provider {
 
+// static
+std::unique_ptr<ProviderInterface> FakeExtensionProvider::Create(
+    const extensions::ExtensionId& extension_id) {
+  Capabilities default_capabilities(false, false, false,
+                                    extensions::SOURCE_NETWORK);
+  return std::unique_ptr<ProviderInterface>(
+      new FakeExtensionProvider(extension_id, default_capabilities));
+}
+
 // Factory callback, to be used in Service::SetFileSystemFactory(). The
 // |event_router| argument can be NULL.
 std::unique_ptr<ProvidedFileSystemInterface>
@@ -29,7 +37,19 @@
   return std::make_unique<FakeProvidedFileSystem>(file_system_info);
 }
 
-FakeExtensionProvider::FakeExtensionProvider() {}
+const Capabilities& FakeExtensionProvider::GetCapabilities() const {
+  return capabilities_;
+}
+
+const ProviderId& FakeExtensionProvider::GetId() const {
+  return provider_id_;
+}
+
+FakeExtensionProvider::FakeExtensionProvider(
+    const extensions::ExtensionId& extension_id,
+    const Capabilities& capabilities)
+    : provider_id_(ProviderId::CreateFromExtensionId(extension_id)),
+      capabilities_(capabilities) {}
 
 }  // namespace file_system_provider
 }  // namespace chromeos
diff --git a/chrome/browser/chromeos/file_system_provider/fake_extension_provider.h b/chrome/browser/chromeos/file_system_provider/fake_extension_provider.h
index ace46c6..71c91f5 100644
--- a/chrome/browser/chromeos/file_system_provider/fake_extension_provider.h
+++ b/chrome/browser/chromeos/file_system_provider/fake_extension_provider.h
@@ -10,23 +10,35 @@
 #include "chrome/browser/chromeos/file_system_provider/extension_provider.h"
 #include "chrome/browser/chromeos/file_system_provider/provided_file_system_interface.h"
 #include "chrome/browser/chromeos/file_system_provider/provider_interface.h"
+#include "extensions/common/extension_id.h"
 
 class Profile;
 
 namespace chromeos {
 namespace file_system_provider {
 
-class ProvidedFileSystemInfo;
-
-class FakeExtensionProvider : public ExtensionProvider {
+class FakeExtensionProvider : public ProviderInterface {
  public:
-  FakeExtensionProvider();
   ~FakeExtensionProvider() override {}
 
-  // ExtensionProvider override.
+  // Returns a fake provider instance for the specified extension. The extension
+  // doesn't have to exist.
+  static std::unique_ptr<ProviderInterface> Create(
+      const extensions::ExtensionId& extension_id);
+
+  // ProviderInterface overrides.
   std::unique_ptr<ProvidedFileSystemInterface> CreateProvidedFileSystem(
       Profile* profile,
       const ProvidedFileSystemInfo& file_system_info) override;
+  const Capabilities& GetCapabilities() const override;
+  const ProviderId& GetId() const override;
+
+ protected:
+  FakeExtensionProvider(const extensions::ExtensionId& extension_id,
+                        const Capabilities& capabilities);
+
+  ProviderId provider_id_;
+  Capabilities capabilities_;
 };
 
 }  // namespace file_system_provider
diff --git a/chrome/browser/chromeos/file_system_provider/fileapi/file_stream_reader_unittest.cc b/chrome/browser/chromeos/file_system_provider/fileapi/file_stream_reader_unittest.cc
index babb8bc..c9ac9ba2 100644
--- a/chrome/browser/chromeos/file_system_provider/fileapi/file_stream_reader_unittest.cc
+++ b/chrome/browser/chromeos/file_system_provider/fileapi/file_stream_reader_unittest.cc
@@ -92,8 +92,7 @@
     profile_ = profile_manager_->CreateTestingProfile("testing-profile");
 
     Service* service = Service::Get(profile_);  // Owned by its factory.
-    service->SetExtensionProviderForTesting(
-        std::make_unique<FakeExtensionProvider>());
+    service->RegisterProvider(FakeExtensionProvider::Create(kExtensionId));
 
     const base::File::Error result = service->MountFileSystem(
         kProviderId, MountOptions(kFileSystemId, "Testing File System"));
diff --git a/chrome/browser/chromeos/file_system_provider/fileapi/file_stream_writer_unittest.cc b/chrome/browser/chromeos/file_system_provider/fileapi/file_stream_writer_unittest.cc
index 768fbb2..d4545f13 100644
--- a/chrome/browser/chromeos/file_system_provider/fileapi/file_stream_writer_unittest.cc
+++ b/chrome/browser/chromeos/file_system_provider/fileapi/file_stream_writer_unittest.cc
@@ -74,8 +74,7 @@
     profile_ = profile_manager_->CreateTestingProfile("testing-profile");
 
     Service* service = Service::Get(profile_);  // Owned by its factory.
-    service->SetExtensionProviderForTesting(
-        std::make_unique<FakeExtensionProvider>());
+    service->RegisterProvider(FakeExtensionProvider::Create(kExtensionId));
 
     const base::File::Error result = service->MountFileSystem(
         kProviderId, MountOptions(kFileSystemId, "Testing File System"));
diff --git a/chrome/browser/chromeos/file_system_provider/fileapi/provider_async_file_util_unittest.cc b/chrome/browser/chromeos/file_system_provider/fileapi/provider_async_file_util_unittest.cc
index d07eb2e..f76f647 100644
--- a/chrome/browser/chromeos/file_system_provider/fileapi/provider_async_file_util_unittest.cc
+++ b/chrome/browser/chromeos/file_system_provider/fileapi/provider_async_file_util_unittest.cc
@@ -130,8 +130,7 @@
         content::CreateFileSystemContextForTesting(NULL, data_dir_.GetPath());
 
     Service* service = Service::Get(profile_);  // Owned by its factory.
-    service->SetExtensionProviderForTesting(
-        std::make_unique<FakeExtensionProvider>());
+    service->RegisterProvider(FakeExtensionProvider::Create(kExtensionId));
 
     const base::File::Error result = service->MountFileSystem(
         kProviderId, MountOptions(kFileSystemId, "Testing File System"));
diff --git a/chrome/browser/chromeos/file_system_provider/mount_path_util_unittest.cc b/chrome/browser/chromeos/file_system_provider/mount_path_util_unittest.cc
index 6e4bdf1f..7e1f9e9 100644
--- a/chrome/browser/chromeos/file_system_provider/mount_path_util_unittest.cc
+++ b/chrome/browser/chromeos/file_system_provider/mount_path_util_unittest.cc
@@ -77,8 +77,8 @@
     user_manager_->AddUser(
         AccountId::FromUserEmail(profile_->GetProfileUserName()));
     file_system_provider_service_ = Service::Get(profile_);
-    file_system_provider_service_->SetExtensionProviderForTesting(
-        std::make_unique<FakeExtensionProvider>());
+    file_system_provider_service_->RegisterProvider(
+        FakeExtensionProvider::Create(kExtensionId));
   }
 
   content::TestBrowserThreadBundle thread_bundle_;
diff --git a/chrome/browser/chromeos/file_system_provider/provided_file_system_info.cc b/chrome/browser/chromeos/file_system_provider/provided_file_system_info.cc
index 7140f92a..f41adf2 100644
--- a/chrome/browser/chromeos/file_system_provider/provided_file_system_info.cc
+++ b/chrome/browser/chromeos/file_system_provider/provided_file_system_info.cc
@@ -61,6 +61,11 @@
   return type_ == other.GetType() && internal_id_ == other.GetIdUnsafe();
 }
 
+bool ProviderId::operator<(const ProviderId& other) const {
+  return std::tie(type_, internal_id_) <
+         std::tie(other.type_, other.internal_id_);
+}
+
 MountOptions::MountOptions()
     : writable(false),
       supports_notify_tag(false),
diff --git a/chrome/browser/chromeos/file_system_provider/provided_file_system_info.h b/chrome/browser/chromeos/file_system_provider/provided_file_system_info.h
index ff6f5952..de5199f45 100644
--- a/chrome/browser/chromeos/file_system_provider/provided_file_system_info.h
+++ b/chrome/browser/chromeos/file_system_provider/provided_file_system_info.h
@@ -46,6 +46,7 @@
   ProviderType GetType() const;
 
   bool operator==(const ProviderId& other) const;
+  bool operator<(const ProviderId& other) const;
 
  private:
   ProviderId(const std::string& internal_id, ProviderType provider_type);
diff --git a/chrome/browser/chromeos/file_system_provider/provider_interface.h b/chrome/browser/chromeos/file_system_provider/provider_interface.h
index 22eb6a6..1070f30d 100644
--- a/chrome/browser/chromeos/file_system_provider/provider_interface.h
+++ b/chrome/browser/chromeos/file_system_provider/provider_interface.h
@@ -7,6 +7,8 @@
 #include <memory>
 #include <string>
 
+#include "chrome/browser/chromeos/file_system_provider/provided_file_system_info.h"
+#include "chrome/browser/profiles/profile.h"
 #include "chrome/common/extensions/api/file_system_provider_capabilities/file_system_provider_capabilities_handler.h"
 
 class Profile;
@@ -15,7 +17,6 @@
 namespace file_system_provider {
 
 class ProvidedFileSystemInterface;
-class ProvidedFileSystemInfo;
 class ProviderId;
 
 struct Capabilities {
@@ -27,7 +28,12 @@
         watchable(watchable),
         multiple_mounts(multiple_mounts),
         source(source) {}
-  Capabilities() = default;
+  Capabilities()
+      : configurable(false),
+        watchable(false),
+        multiple_mounts(false),
+        source(extensions::SOURCE_NETWORK) {}
+
   bool configurable;
   bool watchable;
   bool multiple_mounts;
@@ -43,10 +49,11 @@
       Profile* profile,
       const ProvidedFileSystemInfo& file_system_info) = 0;
 
-  // Returns the capabilites of file system with |provider_id|.
-  virtual bool GetCapabilities(Profile* profile,
-                               const ProviderId& provider_id,
-                               Capabilities& result) = 0;
+  // Returns the capabilites of the provider.
+  virtual const Capabilities& GetCapabilities() const = 0;
+
+  // Returns id of this provider.
+  virtual const ProviderId& GetId() const = 0;
 };
 
 }  // namespace file_system_provider
diff --git a/chrome/browser/chromeos/file_system_provider/service.cc b/chrome/browser/chromeos/file_system_provider/service.cc
index 0d8c7455..e488229 100644
--- a/chrome/browser/chromeos/file_system_provider/service.cc
+++ b/chrome/browser/chromeos/file_system_provider/service.cc
@@ -38,19 +38,11 @@
 
 }  // namespace
 
-ProvidingExtensionInfo::ProvidingExtensionInfo() {
-}
-
-ProvidingExtensionInfo::~ProvidingExtensionInfo() {
-}
-
 Service::Service(Profile* profile,
                  extensions::ExtensionRegistry* extension_registry)
     : profile_(profile),
       extension_registry_(extension_registry),
       registry_(new Registry(profile)),
-      extension_provider_(
-          std::make_unique<ExtensionProvider>(ExtensionProvider())),
       weak_ptr_factory_(this) {
   extension_registry_->AddObserver(this);
 }
@@ -94,12 +86,6 @@
   observers_.RemoveObserver(observer);
 }
 
-void Service::SetExtensionProviderForTesting(
-    std::unique_ptr<ProviderInterface> provider) {
-  DCHECK(provider);
-  extension_provider_ = std::move(provider);
-}
-
 void Service::SetRegistryForTesting(
     std::unique_ptr<RegistryInterface> registry) {
   DCHECK(registry);
@@ -117,17 +103,23 @@
     MountContext context) {
   DCHECK(thread_checker_.CalledOnValidThread());
 
+  ProviderInterface* const provider = GetProvider(provider_id);
+  if (!provider) {
+    for (auto& observer : observers_) {
+      observer.OnProvidedFileSystemMount(
+          ProvidedFileSystemInfo(), context,
+          base::File::FILE_ERROR_INVALID_OPERATION);
+    }
+    return base::File::FILE_ERROR_INVALID_OPERATION;
+  }
+
   // The mount point path and name are unique per system, since they are system
   // wide. This is necessary for copying between profiles.
   const base::FilePath& mount_path =
       util::GetMountPath(profile_, provider_id, options.file_system_id);
   const std::string mount_point_name = mount_path.BaseName().AsUTF8Unsafe();
 
-  ProvidingExtensionInfo provider_info;
-  // TODO(mtomasz): Set up a testing extension in unit tests.
-  ProviderInterface* provider = GetProvider(provider_id);
-  Capabilities capabilities;
-  provider->GetCapabilities(profile_, provider_id, capabilities);
+  Capabilities capabilities = provider->GetCapabilities();
   // Store the file system descriptor. Use the mount point name as the file
   // system provider file system id.
   // Examples:
@@ -357,7 +349,17 @@
 void Service::OnExtensionUnloaded(content::BrowserContext* browser_context,
                                   const extensions::Extension* extension,
                                   extensions::UnloadedExtensionReason reason) {
-  // Unmount all of the provided file systems associated with this extension.
+  ProviderId provider_id = ProviderId::CreateFromExtensionId(extension->id());
+  UnregisterProvider(
+      provider_id,
+      reason == extensions::UnloadedExtensionReason::PROFILE_SHUTDOWN
+          ? UNMOUNT_REASON_SHUTDOWN
+          : UNMOUNT_REASON_USER);
+}
+
+void Service::UnmountFileSystems(const ProviderId& provider_id,
+                                 UnmountReason reason) {
+  // Unmount all of the provided file systems associated with this provider.
   auto it = file_system_map_.begin();
   while (it != file_system_map_.end()) {
     const ProvidedFileSystemInfo& file_system_info =
@@ -365,20 +367,31 @@
     // Advance the iterator beforehand, otherwise it will become invalidated
     // by the UnmountFileSystem() call.
     ++it;
-    if (file_system_info.provider_id().GetExtensionId() == extension->id()) {
-      const base::File::Error unmount_result = UnmountFileSystem(
-          file_system_info.provider_id(), file_system_info.file_system_id(),
-          reason == extensions::UnloadedExtensionReason::PROFILE_SHUTDOWN
-              ? UNMOUNT_REASON_SHUTDOWN
-              : UNMOUNT_REASON_USER);
+    if (file_system_info.provider_id() == provider_id) {
+      const base::File::Error unmount_result =
+          UnmountFileSystem(file_system_info.provider_id(),
+                            file_system_info.file_system_id(), reason);
       DCHECK_EQ(base::File::FILE_OK, unmount_result);
     }
   }
 }
 
+void Service::UnregisterProvider(const ProviderId& provider_id,
+                                 UnmountReason reason) {
+  UnmountFileSystems(provider_id, reason);
+  provider_map_.erase(provider_id);
+}
+
 void Service::OnExtensionLoaded(content::BrowserContext* browser_context,
                                 const extensions::Extension* extension) {
-  ProviderId provider_id = ProviderId::CreateFromExtensionId(extension->id());
+  // If the extension is a provider, then register it.
+  std::unique_ptr<ProviderInterface> provider =
+      ExtensionProvider::Create(extension_registry_, extension->id());
+  if (provider)
+    RegisterProvider(std::move(provider));
+}
+
+void Service::RestoreFileSystems(const ProviderId& provider_id) {
   std::unique_ptr<RegistryInterface::RestoredFileSystems>
       restored_file_systems = registry_->RestoreFileSystems(provider_id);
 
@@ -457,21 +470,17 @@
   registry_->RememberFileSystem(file_system_info, watchers);
 }
 
-void Service::RegisterNativeProvider(
-    const ProviderId& provider_id,
-    std::unique_ptr<ProviderInterface> provider) {
-  DCHECK_EQ(ProviderId::NATIVE, provider_id.GetType());
-  native_provider_map_[provider_id.GetNativeId()] = std::move(provider);
+void Service::RegisterProvider(std::unique_ptr<ProviderInterface> provider) {
+  ProviderId provider_id = provider->GetId();
+  provider_map_[provider_id] = std::move(provider);
+  RestoreFileSystems(provider_id);
 }
 
 ProviderInterface* Service::GetProvider(const ProviderId& provider_id) {
   DCHECK_NE(ProviderId::INVALID, provider_id.GetType());
-
-  if (provider_id.GetType() == ProviderId::EXTENSION)
-    return extension_provider_.get();
-
-  auto it = native_provider_map_.find(provider_id.GetNativeId());
-  DCHECK(it != native_provider_map_.end());
+  auto it = provider_map_.find(provider_id);
+  if (it == provider_map_.end())
+    return nullptr;
 
   return it->second.get();
 }
diff --git a/chrome/browser/chromeos/file_system_provider/service.h b/chrome/browser/chromeos/file_system_provider/service.h
index 9fcdfd3c7..efa9c22 100644
--- a/chrome/browser/chromeos/file_system_provider/service.h
+++ b/chrome/browser/chromeos/file_system_provider/service.h
@@ -34,6 +34,7 @@
 #include "content/public/browser/browser_context.h"
 #include "extensions/browser/extension_registry_observer.h"
 #include "extensions/common/extension.h"
+#include "extensions/common/extension_id.h"
 #include "storage/browser/fileapi/watcher_manager.h"
 
 namespace extensions {
@@ -55,27 +56,12 @@
 // Registers preferences to remember registered file systems between reboots.
 void RegisterProfilePrefs(user_prefs::PrefRegistrySyncable* registry);
 
-// Holds information for a providing extension.
-struct ProvidingExtensionInfo {
-  ProvidingExtensionInfo();
-  ~ProvidingExtensionInfo();
-
-  std::string extension_id;
-  std::string name;
-  extensions::FileSystemProviderCapabilities capabilities;
-};
-
 // Manages and registers the file system provider service. Maintains provided
 // file systems.
 class Service : public KeyedService,
                 public extensions::ExtensionRegistryObserver,
                 public ProvidedFileSystemObserver {
  public:
-  typedef base::Callback<std::unique_ptr<ProvidedFileSystemInterface>(
-      Profile* profile,
-      const ProvidedFileSystemInfo& file_system_info)>
-      FileSystemFactoryCallback;
-
   // Reason for unmounting. In case of UNMOUNT_REASON_SHUTDOWN, the file system
   // will be remounted automatically after a reboot. In case of
   // UNMOUNT_REASON_USER it will be permanently unmounted.
@@ -90,11 +76,6 @@
   // KeyedService:
   void Shutdown() override;
 
-  // Sets a custom ProvidedFileSystemInterface factory. Used by unit tests,
-  // where an event router is not available.
-  void SetExtensionProviderForTesting(
-      std::unique_ptr<ProviderInterface> provider);
-
   // Sets a custom Registry implementation. Used by unit tests.
   void SetRegistryForTesting(std::unique_ptr<RegistryInterface> registry);
 
@@ -171,9 +152,13 @@
   void OnWatcherListChanged(const ProvidedFileSystemInfo& file_system_info,
                             const Watchers& watchers) override;
 
-  // Registers a FileSystemFactory for the passed |provider_id|.
-  void RegisterNativeProvider(const ProviderId& provider_id,
-                              std::unique_ptr<ProviderInterface> provider);
+  // Registers a provider. Restores all remembered mounts.
+  void RegisterProvider(std::unique_ptr<ProviderInterface> provider);
+
+  // Unregisters a provider. Unmounts all currently mounted file systems.
+  // If the reason is UNMOUNT_REASON_USER then they will not be automatically
+  // restored on the next registration.
+  void UnregisterProvider(const ProviderId& provider_id, UnmountReason reason);
 
  private:
   FRIEND_TEST_ALL_PREFIXES(FileSystemProviderServiceTest, RememberFileSystem);
@@ -207,7 +192,13 @@
   // |provider_id| provided file system.
   void RestoreFileSystems(const ProviderId& provider_id);
 
-  // Returns a file system provider for the passed |provider_id|.
+  // Unmounts all currently mounted file systems for this provider. If
+  // reason is UNMOUNT_REASON_USER then the file systems will not be remembered
+  // for automagical remount in the future.
+  void UnmountFileSystems(const ProviderId& provider_id, UnmountReason reason);
+
+  // Returns a file system provider for the passed |provider_id|. If not found
+  // then returns nullptr.
   ProviderInterface* GetProvider(const ProviderId& provider_id);
 
   Profile* profile_;
@@ -218,9 +209,7 @@
   std::map<std::string, FileSystemKey> mount_point_name_to_key_map_;
   std::unique_ptr<RegistryInterface> registry_;
   base::ThreadChecker thread_checker_;
-  std::unordered_map<std::string, std::unique_ptr<ProviderInterface>>
-      native_provider_map_;
-  std::unique_ptr<ProviderInterface> extension_provider_;
+  std::map<ProviderId, std::unique_ptr<ProviderInterface>> provider_map_;
 
   base::WeakPtrFactory<Service> weak_ptr_factory_;
   DISALLOW_COPY_AND_ASSIGN(Service);
diff --git a/chrome/browser/chromeos/file_system_provider/service_unittest.cc b/chrome/browser/chromeos/file_system_provider/service_unittest.cc
index 1c64b38..b249617 100644
--- a/chrome/browser/chromeos/file_system_provider/service_unittest.cc
+++ b/chrome/browser/chromeos/file_system_provider/service_unittest.cc
@@ -42,8 +42,8 @@
 namespace file_system_provider {
 namespace {
 
-const ProviderId kProviderId =
-    ProviderId::CreateFromExtensionId("mbflcebpggnecokmikipoihdbecnjfoj");
+const extensions::ExtensionId kExtensionId = "mbflcebpggnecokmikipoihdbecnjfoj";
+const ProviderId kProviderId = ProviderId::CreateFromExtensionId(kExtensionId);
 const char kDisplayName[] = "Camera Pictures";
 const ProviderId kCustomProviderId =
     ProviderId::CreateFromNativeId("custom provider id");
@@ -54,54 +54,35 @@
 const char kFileSystemId[] = "camera/pictures/id .!@#$%^&*()_+";
 
 // Creates a fake extension with the specified |extension_id|.
+// TODO(mtomasz): Use the extension builder.
 scoped_refptr<extensions::Extension> CreateFakeExtension(
     const std::string& extension_id) {
   base::DictionaryValue manifest;
   std::string error;
   manifest.SetKey(extensions::manifest_keys::kVersion, base::Value("1.0.0.0"));
   manifest.SetKey(extensions::manifest_keys::kName, base::Value("unused"));
-  return extensions::Extension::Create(base::FilePath(),
-                                       extensions::Manifest::UNPACKED,
-                                       manifest,
-                                       extensions::Extension::NO_FLAGS,
-                                       extension_id,
-                                       &error);
+
+  std::unique_ptr<base::ListValue> permissions_list(new base::ListValue());
+  permissions_list->AppendString("fileSystemProvider");
+  manifest.Set(extensions::manifest_keys::kPermissions,
+               std::move(permissions_list));
+
+  std::unique_ptr<base::DictionaryValue> capabilities(
+      new base::DictionaryValue);
+  capabilities->SetString("source", "network");
+  manifest.Set(extensions::manifest_keys::kFileSystemProviderCapabilities,
+               std::move(capabilities));
+
+  scoped_refptr<extensions::Extension> extension =
+      extensions::Extension::Create(
+          base::FilePath(), extensions::Manifest::UNPACKED, manifest,
+          extensions::Extension::NO_FLAGS, extension_id, &error);
+  EXPECT_TRUE(extension) << error;
+  return extension;
 }
 
 }  // namespace
 
-class FakeDefaultExtensionProvider : public FakeExtensionProvider {
- public:
-  std::unique_ptr<ProvidedFileSystemInterface> CreateProvidedFileSystem(
-      Profile* profile,
-      const ProvidedFileSystemInfo& file_system_info) override {
-    called_default_factory = true;
-    return std::make_unique<FakeProvidedFileSystem>(file_system_info);
-  }
-
-  static bool called_default_factory;
-};
-bool FakeDefaultExtensionProvider::called_default_factory = false;
-
-class FakeNativeProvider : public ProviderInterface {
- public:
-  // ProviderInterface overrides
-  std::unique_ptr<ProvidedFileSystemInterface> CreateProvidedFileSystem(
-      Profile* profile,
-      const ProvidedFileSystemInfo& file_system_info) override {
-    called_custom_factory = true;
-    return std::make_unique<FakeProvidedFileSystem>(file_system_info);
-  }
-  bool GetCapabilities(Profile* profile,
-                       const ProviderId& provider_id,
-                       Capabilities& result) override {
-    result = Capabilities(false, false, false, extensions::SOURCE_NETWORK);
-    return true;
-  }
-  static bool called_custom_factory;
-};
-bool FakeNativeProvider::called_custom_factory = false;
-
 class FileSystemProviderServiceTest : public testing::Test {
  protected:
   FileSystemProviderServiceTest() : profile_(NULL) {}
@@ -119,14 +100,8 @@
     user_manager_enabler_ = std::make_unique<user_manager::ScopedUserManager>(
         base::WrapUnique(user_manager_));
     extension_registry_.reset(new extensions::ExtensionRegistry(profile_));
-
     service_.reset(new Service(profile_, extension_registry_.get()));
 
-    service_->SetExtensionProviderForTesting(
-        std::make_unique<FakeExtensionProvider>());
-
-    extension_ = CreateFakeExtension(kProviderId.GetExtensionId());
-
     registry_ = new FakeRegistry;
     // Passes ownership to the service instance.
     service_->SetRegistryForTesting(base::WrapUnique(registry_));
@@ -147,38 +122,14 @@
   std::unique_ptr<user_manager::ScopedUserManager> user_manager_enabler_;
   std::unique_ptr<extensions::ExtensionRegistry> extension_registry_;
   std::unique_ptr<Service> service_;
-  scoped_refptr<extensions::Extension> extension_;
   FakeRegistry* registry_;  // Owned by Service.
   Watcher fake_watcher_;
-  bool called_default_factory_;
-  bool called_custom_factory_;
 };
 
-TEST_F(FileSystemProviderServiceTest, RegisterFileSystemProvider) {
-  service_->RegisterNativeProvider(kCustomProviderId,
-                                   std::make_unique<FakeNativeProvider>());
-  service_->SetExtensionProviderForTesting(
-      std::make_unique<FakeDefaultExtensionProvider>());
-
-  FakeNativeProvider::called_custom_factory = false;
-  FakeDefaultExtensionProvider::called_default_factory = false;
-
-  EXPECT_EQ(base::File::FILE_OK,
-            service_->MountFileSystem(
-                kProviderId, MountOptions(kFileSystemId, kDisplayName)));
-
-  EXPECT_TRUE(FakeDefaultExtensionProvider::called_default_factory);
-
-  EXPECT_EQ(base::File::FILE_OK,
-            service_->MountFileSystem(
-                kCustomProviderId, MountOptions(kFileSystemId, kDisplayName)));
-
-  EXPECT_TRUE(FakeNativeProvider::called_custom_factory);
-}
-
 TEST_F(FileSystemProviderServiceTest, MountFileSystem) {
   LoggingObserver observer;
   service_->AddObserver(&observer);
+  service_->RegisterProvider(FakeExtensionProvider::Create(kExtensionId));
 
   EXPECT_EQ(base::File::FILE_OK,
             service_->MountFileSystem(
@@ -210,6 +161,7 @@
        MountFileSystem_WritableAndSupportsNotifyTag) {
   LoggingObserver observer;
   service_->AddObserver(&observer);
+  service_->RegisterProvider(FakeExtensionProvider::Create(kExtensionId));
 
   MountOptions options(kFileSystemId, kDisplayName);
   options.writable = true;
@@ -231,6 +183,7 @@
 TEST_F(FileSystemProviderServiceTest, MountFileSystem_UniqueIds) {
   LoggingObserver observer;
   service_->AddObserver(&observer);
+  service_->RegisterProvider(FakeExtensionProvider::Create(kExtensionId));
 
   EXPECT_EQ(base::File::FILE_OK,
             service_->MountFileSystem(
@@ -253,6 +206,7 @@
 TEST_F(FileSystemProviderServiceTest, MountFileSystem_StressTest) {
   LoggingObserver observer;
   service_->AddObserver(&observer);
+  service_->RegisterProvider(FakeExtensionProvider::Create(kExtensionId));
 
   const size_t kMaxFileSystems = 16;
   for (size_t i = 0; i < kMaxFileSystems; ++i) {
@@ -284,6 +238,8 @@
   LoggingObserver observer;
   service_->AddObserver(&observer);
 
+  service_->RegisterProvider(FakeExtensionProvider::Create(kExtensionId));
+
   EXPECT_EQ(base::File::FILE_OK,
             service_->MountFileSystem(
                 kProviderId, MountOptions(kFileSystemId, kDisplayName)));
@@ -310,13 +266,18 @@
   LoggingObserver observer;
   service_->AddObserver(&observer);
 
+  scoped_refptr<extensions::Extension> extension =
+      CreateFakeExtension(kExtensionId);
+  extension_registry_->AddEnabled(extension);
+  service_->OnExtensionLoaded(profile_, extension.get());
+
   EXPECT_EQ(base::File::FILE_OK,
             service_->MountFileSystem(
                 kProviderId, MountOptions(kFileSystemId, kDisplayName)));
   ASSERT_EQ(1u, observer.mounts.size());
 
   // Directly call the observer's method.
-  service_->OnExtensionUnloaded(profile_, extension_.get(),
+  service_->OnExtensionUnloaded(profile_, extension.get(),
                                 extensions::UnloadedExtensionReason::DISABLE);
 
   ASSERT_EQ(1u, observer.unmounts.size());
@@ -336,6 +297,7 @@
 TEST_F(FileSystemProviderServiceTest, UnmountFileSystem_WrongExtensionId) {
   LoggingObserver observer;
   service_->AddObserver(&observer);
+  service_->RegisterProvider(FakeExtensionProvider::Create(kExtensionId));
 
   const ProviderId kWrongProviderId =
       ProviderId::CreateFromExtensionId("helloworldhelloworldhelloworldhe");
@@ -377,8 +339,12 @@
 
   EXPECT_EQ(0u, observer.mounts.size());
 
+  scoped_refptr<extensions::Extension> extension =
+      CreateFakeExtension(kExtensionId);
+  extension_registry_->AddEnabled(extension);
+
   // Directly call the observer's method.
-  service_->OnExtensionLoaded(profile_, extension_.get());
+  service_->OnExtensionLoaded(profile_, extension.get());
 
   ASSERT_EQ(1u, observer.mounts.size());
   EXPECT_EQ(base::File::FILE_OK, observer.mounts[0].error());
@@ -419,6 +385,7 @@
 TEST_F(FileSystemProviderServiceTest, DoNotRememberNonPersistent) {
   LoggingObserver observer;
   service_->AddObserver(&observer);
+  service_->RegisterProvider(FakeExtensionProvider::Create(kExtensionId));
 
   EXPECT_FALSE(registry_->file_system_info());
   EXPECT_FALSE(registry_->watchers());
@@ -437,6 +404,7 @@
 TEST_F(FileSystemProviderServiceTest, RememberFileSystem_OnMount) {
   LoggingObserver observer;
   service_->AddObserver(&observer);
+  service_->RegisterProvider(FakeExtensionProvider::Create(kExtensionId));
 
   EXPECT_FALSE(registry_->file_system_info());
   EXPECT_FALSE(registry_->watchers());
@@ -462,6 +430,7 @@
 TEST_F(FileSystemProviderServiceTest, RememberFileSystem_OnUnmountOnShutdown) {
   LoggingObserver observer;
   service_->AddObserver(&observer);
+  service_->RegisterProvider(FakeExtensionProvider::Create(kExtensionId));
 
   {
     EXPECT_FALSE(registry_->file_system_info());
@@ -491,6 +460,7 @@
 TEST_F(FileSystemProviderServiceTest, RememberFileSystem_OnUnmountByUser) {
   LoggingObserver observer;
   service_->AddObserver(&observer);
+  service_->RegisterProvider(FakeExtensionProvider::Create(kExtensionId));
 
   {
     EXPECT_FALSE(registry_->file_system_info());
diff --git a/chrome/browser/chromeos/login/lock/screen_locker.cc b/chrome/browser/chromeos/login/lock/screen_locker.cc
index de71ef7..1e78a27 100644
--- a/chrome/browser/chromeos/login/lock/screen_locker.cc
+++ b/chrome/browser/chromeos/login/lock/screen_locker.cc
@@ -434,7 +434,7 @@
   delegate_->OnAshLockAnimationFinished();
 
   AccessibilityManager::Get()->PlayEarcon(
-      chromeos::SOUND_LOCK, PlaySoundOption::SPOKEN_FEEDBACK_ENABLED);
+      SOUND_LOCK, PlaySoundOption::ONLY_IF_SPOKEN_FEEDBACK_ENABLED);
 }
 
 void ScreenLocker::ClearErrors() {
@@ -560,7 +560,7 @@
   VLOG(1) << "Deleting ScreenLocker " << screen_locker_;
 
   AccessibilityManager::Get()->PlayEarcon(
-      SOUND_UNLOCK, PlaySoundOption::SPOKEN_FEEDBACK_ENABLED);
+      SOUND_UNLOCK, PlaySoundOption::ONLY_IF_SPOKEN_FEEDBACK_ENABLED);
 
   delete screen_locker_;
   screen_locker_ = nullptr;
diff --git a/chrome/browser/chromeos/smb_client/smb_service.cc b/chrome/browser/chromeos/smb_client/smb_service.cc
index aeacc8c..79c00b6 100644
--- a/chrome/browser/chromeos/smb_client/smb_service.cc
+++ b/chrome/browser/chromeos/smb_client/smb_service.cc
@@ -12,19 +12,18 @@
 namespace chromeos {
 namespace smb_client {
 
-file_system_provider::ProviderId kSmbProviderId =
-    ProviderId::CreateFromNativeId("smb");
-
-SmbService::SmbService(Profile* profile) : profile_(profile) {
-  GetProviderService()->RegisterNativeProvider(
-      kSmbProviderId, std::make_unique<SmbService>(profile));
+SmbService::SmbService(Profile* profile)
+    : profile_(profile),
+      provider_id_(ProviderId::CreateFromNativeId("smb")),
+      capabilities_(false, false, false, extensions::SOURCE_NETWORK) {
+  GetProviderService()->RegisterProvider(std::make_unique<SmbService>(profile));
 }
 
 SmbService::~SmbService() {}
 
 base::File::Error SmbService::Mount(
     const file_system_provider::MountOptions& options) {
-  return GetProviderService()->MountFileSystem(kSmbProviderId, options);
+  return GetProviderService()->MountFileSystem(provider_id_, options);
 }
 
 Service* SmbService::GetProviderService() const {
@@ -39,11 +38,12 @@
   return std::make_unique<SmbFileSystem>(file_system_info);
 }
 
-bool SmbService::GetCapabilities(Profile* profile,
-                                 const ProviderId& provider_id,
-                                 Capabilities& result) {
-  result = Capabilities(false, false, false, extensions::SOURCE_NETWORK);
-  return true;
+const Capabilities& SmbService::GetCapabilities() const {
+  return capabilities_;
+}
+
+const ProviderId& SmbService::GetId() const {
+  return provider_id_;
 }
 
 }  // namespace smb_client
diff --git a/chrome/browser/chromeos/smb_client/smb_service.h b/chrome/browser/chromeos/smb_client/smb_service.h
index 6a37a6dd..ad8afba9 100644
--- a/chrome/browser/chromeos/smb_client/smb_service.h
+++ b/chrome/browser/chromeos/smb_client/smb_service.h
@@ -5,6 +5,8 @@
 #ifndef CHROME_BROWSER_CHROMEOS_SMB_CLIENT_SMB_SERVICE_H_
 #define CHROME_BROWSER_CHROMEOS_SMB_CLIENT_SMB_SERVICE_H_
 
+#include <memory>
+
 #include "base/files/file.h"
 #include "base/macros.h"
 #include "chrome/browser/chromeos/file_system_provider/provided_file_system_info.h"
@@ -33,18 +35,19 @@
   // file_system_provider::Service::MountFileSystem().
   base::File::Error Mount(const file_system_provider::MountOptions& options);
 
-  // ProviderInterface overrides
+  // ProviderInterface overrides.
   std::unique_ptr<ProvidedFileSystemInterface> CreateProvidedFileSystem(
       Profile* profile,
       const ProvidedFileSystemInfo& file_system_info) override;
-  bool GetCapabilities(Profile* profile,
-                       const ProviderId& provider_id,
-                       Capabilities& result) override;
+  const Capabilities& GetCapabilities() const override;
+  const ProviderId& GetId() const override;
 
  private:
   Service* GetProviderService() const;
 
   Profile* profile_;
+  ProviderId provider_id_;
+  Capabilities capabilities_;
 
   DISALLOW_COPY_AND_ASSIGN(SmbService);
 };
diff --git a/chrome/browser/chromeos/smb_client/smb_service_unittest.cc b/chrome/browser/chromeos/smb_client/smb_service_unittest.cc
index 3ee6d49e..69cd94b 100644
--- a/chrome/browser/chromeos/smb_client/smb_service_unittest.cc
+++ b/chrome/browser/chromeos/smb_client/smb_service_unittest.cc
@@ -5,10 +5,11 @@
 #include "chrome/browser/chromeos/smb_client/smb_service.h"
 
 #include <stddef.h>
+
 #include <memory>
+#include <utility>
 
 #include "base/memory/ptr_util.h"
-#include "chrome/browser/chromeos/file_system_provider/fake_extension_provider.h"
 #include "chrome/browser/chromeos/file_system_provider/fake_provided_file_system.h"
 #include "chrome/browser/chromeos/file_system_provider/fake_registry.h"
 #include "chrome/browser/chromeos/file_system_provider/provided_file_system_info.h"
@@ -47,8 +48,6 @@
         std::make_unique<extensions::ExtensionRegistry>(profile_);
     fsp_service_ = std::make_unique<file_system_provider::Service>(
         profile_, extension_registry_.get());
-    fsp_service_->SetExtensionProviderForTesting(
-        std::make_unique<file_system_provider::FakeExtensionProvider>());
 
     fsp_service_->SetRegistryForTesting(
         std::make_unique<file_system_provider::FakeRegistry>());
diff --git a/chrome/browser/cryptauth/chrome_cryptauth_service.cc b/chrome/browser/cryptauth/chrome_cryptauth_service.cc
index f1402b2..e7f57e5 100644
--- a/chrome/browser/cryptauth/chrome_cryptauth_service.cc
+++ b/chrome/browser/cryptauth/chrome_cryptauth_service.cc
@@ -215,9 +215,20 @@
       device_manager_(std::move(device_manager)),
       profile_(profile),
       token_service_(token_service),
-      signin_manager_(signin_manager) {
+      signin_manager_(signin_manager),
+      weak_ptr_factory_(this) {
   gcm_manager_->StartListening();
 
+  registrar_.Init(profile_->GetPrefs());
+  registrar_.Add(prefs::kEasyUnlockAllowed,
+                 base::Bind(&ChromeCryptAuthService::OnPrefsChanged,
+                            weak_ptr_factory_.GetWeakPtr()));
+#if defined(OS_CHROMEOS)
+  registrar_.Add(prefs::kInstantTetheringAllowed,
+                 base::Bind(&ChromeCryptAuthService::OnPrefsChanged,
+                            weak_ptr_factory_.GetWeakPtr()));
+#endif  // defined(OS_CHROMEOS)
+
   if (!signin_manager_->IsAuthenticated()) {
     PA_LOG(INFO) << "Profile is not authenticated yet; "
                  << "waiting before starting CryptAuth managers.";
@@ -235,7 +246,7 @@
 
   // Profile is authenticated and there is a refresh token available for the
   // authenticated account id.
-  PerformEnrollmentAndDeviceSync();
+  PerformEnrollmentAndDeviceSyncIfPossible();
 }
 
 ChromeCryptAuthService::~ChromeCryptAuthService() {}
@@ -299,20 +310,26 @@
     return;
   }
 
-  PerformEnrollmentAndDeviceSync();
+  PerformEnrollmentAndDeviceSyncIfPossible();
 }
 
 void ChromeCryptAuthService::OnRefreshTokenAvailable(
     const std::string& account_id) {
   if (account_id == GetAccountId()) {
     token_service_->RemoveObserver(this);
-    PerformEnrollmentAndDeviceSync();
+    PerformEnrollmentAndDeviceSyncIfPossible();
   }
 }
 
-void ChromeCryptAuthService::PerformEnrollmentAndDeviceSync() {
+void ChromeCryptAuthService::PerformEnrollmentAndDeviceSyncIfPossible() {
   DCHECK(signin_manager_->IsAuthenticated());
   DCHECK(token_service_->RefreshTokenIsAvailable(GetAccountId()));
+
+  if (!IsEnrollmentAllowedByPolicy()) {
+    PA_LOG(INFO) << "CryptAuth enrollment is disabled by enterprise policy.";
+    return;
+  }
+
   if (enrollment_manager_->IsEnrollmentValid()) {
     device_manager_->Start();
   } else {
@@ -325,3 +342,21 @@
   // order to schedule the next enrollment attempt.
   enrollment_manager_->Start();
 }
+
+bool ChromeCryptAuthService::IsEnrollmentAllowedByPolicy() {
+  // We allow CryptAuth enrollments if at least one of the features which
+  // depends on CryptAuth is enabled by enterprise policy.
+  PrefService* pref_service = profile_->GetPrefs();
+  bool is_allowed = pref_service->GetBoolean(prefs::kEasyUnlockAllowed);
+#if defined(OS_CHROMEOS)
+  is_allowed |= pref_service->GetBoolean(prefs::kInstantTetheringAllowed);
+#endif  // defined(OS_CHROMEOS)
+  return is_allowed;
+}
+
+void ChromeCryptAuthService::OnPrefsChanged() {
+  // Note: We only start the CryptAuth services if a feature was toggled on. In
+  // the inverse case, we simply leave the services running until the user logs
+  // off.
+  PerformEnrollmentAndDeviceSyncIfPossible();
+}
diff --git a/chrome/browser/cryptauth/chrome_cryptauth_service.h b/chrome/browser/cryptauth/chrome_cryptauth_service.h
index 478cea7e..0425fdaf 100644
--- a/chrome/browser/cryptauth/chrome_cryptauth_service.h
+++ b/chrome/browser/cryptauth/chrome_cryptauth_service.h
@@ -8,10 +8,12 @@
 #include <memory>
 
 #include "base/macros.h"
+#include "base/memory/weak_ptr.h"
 #include "components/cryptauth/cryptauth_enrollment_manager.h"
 #include "components/cryptauth/cryptauth_service.h"
 #include "components/cryptauth/proto/cryptauth_api.pb.h"
 #include "components/keyed_service/core/keyed_service.h"
+#include "components/prefs/pref_change_registrar.h"
 #include "components/signin/core/browser/signin_manager_base.h"
 #include "google_apis/gaia/oauth2_token_service.h"
 
@@ -69,7 +71,9 @@
   void GoogleSigninSucceeded(const std::string& account_id,
                              const std::string& username) override;
 
-  void PerformEnrollmentAndDeviceSync();
+  void PerformEnrollmentAndDeviceSyncIfPossible();
+  bool IsEnrollmentAllowedByPolicy();
+  void OnPrefsChanged();
 
   std::unique_ptr<cryptauth::CryptAuthGCMManager> gcm_manager_;
   std::unique_ptr<cryptauth::CryptAuthEnrollmentManager> enrollment_manager_;
@@ -77,6 +81,9 @@
   Profile* profile_;
   OAuth2TokenService* token_service_;
   SigninManagerBase* signin_manager_;
+  PrefChangeRegistrar registrar_;
+
+  base::WeakPtrFactory<ChromeCryptAuthService> weak_ptr_factory_;
 
   DISALLOW_COPY_AND_ASSIGN(ChromeCryptAuthService);
 };
diff --git a/chrome/browser/extensions/bookmark_app_navigation_throttle.cc b/chrome/browser/extensions/bookmark_app_navigation_throttle.cc
index 4be418c71..2ca70d3b 100644
--- a/chrome/browser/extensions/bookmark_app_navigation_throttle.cc
+++ b/chrome/browser/extensions/bookmark_app_navigation_throttle.cc
@@ -139,15 +139,18 @@
   //
   // TODO(crbug.com/789051): Possibly fall through to the logic below to
   // open target in app window, if it belongs to an app.
-  if (is_redirect &&
-      PageTransitionCoreTypeIs(transition_type,
-                               ui::PAGE_TRANSITION_AUTO_BOOKMARK) &&
-      GetAppForWindow() != GetTargetApp()) {
-    DVLOG(1) << "Out-of-scope navigation during launch. Opening in Chrome.";
-    Browser* browser = chrome::FindBrowserWithWebContents(
-        navigation_handle()->GetWebContents());
-    DCHECK(browser);
-    chrome::OpenInChrome(browser);
+  if (is_redirect && PageTransitionCoreTypeIs(
+                         transition_type, ui::PAGE_TRANSITION_AUTO_BOOKMARK)) {
+    auto app_for_window = GetAppForWindow();
+    // If GetAppForWindow returned nullptr, we are already in the browser, so
+    // don't open a new tab.
+    if (app_for_window && app_for_window != GetTargetApp()) {
+      DVLOG(1) << "Out-of-scope navigation during launch. Opening in Chrome.";
+      Browser* browser = chrome::FindBrowserWithWebContents(
+          navigation_handle()->GetWebContents());
+      DCHECK(browser);
+      chrome::OpenInChrome(browser);
+    }
   }
 
   if (!PageTransitionCoreTypeIs(transition_type, ui::PAGE_TRANSITION_LINK) &&
diff --git a/chrome/browser/extensions/bookmark_app_navigation_throttle_browsertest.cc b/chrome/browser/extensions/bookmark_app_navigation_throttle_browsertest.cc
index 34dd3e0..1b9fdc6 100644
--- a/chrome/browser/extensions/bookmark_app_navigation_throttle_browsertest.cc
+++ b/chrome/browser/extensions/bookmark_app_navigation_throttle_browsertest.cc
@@ -18,6 +18,7 @@
 #include "chrome/browser/ui/tabs/tab_strip_model.h"
 #include "chrome/browser/web_applications/web_app.h"
 #include "chrome/common/chrome_features.h"
+#include "chrome/common/extensions/manifest_handlers/app_launch_info.h"
 #include "chrome/common/web_application_info.h"
 #include "chrome/test/base/ui_test_utils.h"
 #include "content/public/browser/navigation_controller.h"
@@ -309,6 +310,26 @@
     test_bookmark_app_ = InstallBookmarkApp(web_app_info);
   }
 
+  // Installs a Bookmark App that immediately redirects to a URL with
+  // |target_host| and |target_path|.
+  const Extension* InstallImmediateRedirectingApp(
+      const std::string& target_host,
+      const std::string& target_path) {
+    EXPECT_TRUE(embedded_test_server()->Start());
+    const GURL target_url =
+        embedded_test_server()->GetURL(target_host, target_path);
+
+    WebApplicationInfo web_app_info;
+    web_app_info.app_url = embedded_test_server()->GetURL(
+        kAppUrlHost, CreateServerRedirect(target_url));
+    web_app_info.scope = embedded_test_server()->GetURL(kAppUrlHost, "/");
+    web_app_info.title = base::UTF8ToUTF16("Redirecting Test app");
+    web_app_info.description = base::UTF8ToUTF16("Test description");
+    web_app_info.open_as_window = true;
+
+    return InstallBookmarkApp(web_app_info);
+  }
+
   Browser* OpenTestBookmarkApp() {
     GURL app_url = embedded_test_server()->GetURL(kAppUrlHost, kAppUrlPath);
     auto observer = GetTestNavigationObserver(app_url);
@@ -888,19 +909,8 @@
 
   GURL initial_url = initial_tab->GetLastCommittedURL();
 
-  // Install and launch an App that immediately redirects to an out-of-scope
-  // URL i.e. the launching page URL.
-  ASSERT_TRUE(embedded_test_server()->Start());
-
-  WebApplicationInfo web_app_info;
-  web_app_info.app_url = embedded_test_server()->GetURL(
-      kAppUrlHost, CreateServerRedirect(GetLaunchingPageURL()));
-  web_app_info.scope = embedded_test_server()->GetURL(kAppUrlHost, "/");
-  web_app_info.title = base::UTF8ToUTF16("Redirecting Test app");
-  web_app_info.description = base::UTF8ToUTF16("Test description");
-  web_app_info.open_as_window = true;
-
-  const Extension* redirecting_app = InstallBookmarkApp(web_app_info);
+  const Extension* redirecting_app =
+      InstallImmediateRedirectingApp(kLaunchingPageHost, kLaunchingPagePath);
 
   auto observer = GetTestNavigationObserver(GetLaunchingPageURL());
   LaunchAppBrowser(redirecting_app);
@@ -1262,6 +1272,45 @@
                  in_scope_url, LinkTarget::SELF, GetParam()));
 }
 
+// Tests that in-browser navigations with all the following characteristics
+// don't open a new app window or move the tab:
+//  1. Are to in-scope URLs
+//  2. Result in a AUTO_BOOKMARK transtion
+//  3. Redirect to another in-scope URL.
+//
+// Clicking on sites in the New Tab Page is one of the ways to trigger this
+// type of navigation.
+IN_PROC_BROWSER_TEST_F(BookmarkAppNavigationThrottleBrowserTest,
+                       AutoBookmarkInScopeRedirect) {
+  const Extension* app =
+      InstallImmediateRedirectingApp(kAppUrlHost, kInScopeUrlPath);
+
+  const GURL app_url = AppLaunchInfo::GetFullLaunchURL(app);
+  NavigateParams params(browser(), app_url, ui::PAGE_TRANSITION_AUTO_BOOKMARK);
+  TestTabActionDoesNotOpenAppWindow(
+      embedded_test_server()->GetURL(kAppUrlHost, kInScopeUrlPath),
+      base::Bind(&NavigateToURLWrapper, &params));
+}
+
+// Tests that in-browser navigations with all the following characteristics
+// don't open a new app window or move the tab:
+//  1. Are to in-scope URLs
+//  2. Result in a AUTO_BOOKMARK transtion
+//  3. Redirect to an out-of-scope URL.
+//
+// Clicking on sites in the New Tab Page is one of the ways to trigger this
+// type of navigation.
+IN_PROC_BROWSER_TEST_F(BookmarkAppNavigationThrottleBrowserTest,
+                       AutoBookmarkOutOfScopeRedirect) {
+  const Extension* app =
+      InstallImmediateRedirectingApp(kLaunchingPageHost, kLaunchingPagePath);
+
+  const GURL app_url = AppLaunchInfo::GetFullLaunchURL(app);
+  NavigateParams params(browser(), app_url, ui::PAGE_TRANSITION_AUTO_BOOKMARK);
+  TestTabActionDoesNotOpenAppWindow(GetLaunchingPageURL(),
+                                    base::Bind(&NavigateToURLWrapper, &params));
+}
+
 // Tests that clicking links inside the app to in-scope URLs doesn't open new
 // browser windows.
 IN_PROC_BROWSER_TEST_P(BookmarkAppNavigationThrottleLinkBrowserTest,
diff --git a/chrome/browser/printing/cloud_print/privet_http.h b/chrome/browser/printing/cloud_print/privet_http.h
index a684e42..39d182f 100644
--- a/chrome/browser/printing/cloud_print/privet_http.h
+++ b/chrome/browser/printing/cloud_print/privet_http.h
@@ -61,7 +61,7 @@
       PrivetURLFetcher::Delegate* delegate) = 0;
 
   virtual void RefreshPrivetToken(
-      const PrivetURLFetcher::TokenCallback& token_callback) = 0;
+      PrivetURLFetcher::TokenCallback token_callback) = 0;
 };
 
 class PrivetDataReadOperation {
diff --git a/chrome/browser/printing/cloud_print/privet_http_impl.cc b/chrome/browser/printing/cloud_print/privet_http_impl.cc
index ae282e6..c680e5e4 100644
--- a/chrome/browser/printing/cloud_print/privet_http_impl.cc
+++ b/chrome/browser/printing/cloud_print/privet_http_impl.cc
@@ -218,8 +218,8 @@
 }
 
 void PrivetRegisterOperationImpl::OnNeedPrivetToken(
-    const PrivetURLFetcher::TokenCallback& callback) {
-  privet_client_->RefreshPrivetToken(callback);
+    PrivetURLFetcher::TokenCallback callback) {
+  privet_client_->RefreshPrivetToken(std::move(callback));
 }
 
 void PrivetRegisterOperationImpl::SendRequest(const std::string& action) {
@@ -297,9 +297,8 @@
 }
 
 void PrivetRegisterOperationImpl::StartInfoOperation() {
-  info_operation_ = privet_client_->CreateInfoOperation(
-      base::Bind(&PrivetRegisterOperationImpl::OnPrivetInfoDone,
-                 base::Unretained(this)));
+  info_operation_ = privet_client_->CreateInfoOperation(base::BindRepeating(
+      &PrivetRegisterOperationImpl::OnPrivetInfoDone, base::Unretained(this)));
   info_operation_->Start();
 }
 
@@ -369,8 +368,8 @@
 }
 
 void PrivetJSONOperationImpl::OnNeedPrivetToken(
-    const PrivetURLFetcher::TokenCallback& callback) {
-  privet_client_->RefreshPrivetToken(callback);
+    PrivetURLFetcher::TokenCallback callback) {
+  privet_client_->RefreshPrivetToken(std::move(callback));
 }
 
 #if BUILDFLAG(ENABLE_PRINT_PREVIEW)
@@ -395,8 +394,8 @@
   // We need to get the /info response so we can know which APIs are available.
   // TODO(noamsml): Use cached info when available.
   info_operation_ = privet_client_->CreateInfoOperation(
-      base::Bind(&PrivetLocalPrintOperationImpl::OnPrivetInfoDone,
-                 base::Unretained(this)));
+      base::BindRepeating(&PrivetLocalPrintOperationImpl::OnPrivetInfoDone,
+                          base::Unretained(this)));
   info_operation_->Start();
 
   started_ = true;
@@ -621,8 +620,8 @@
 }
 
 void PrivetLocalPrintOperationImpl::OnNeedPrivetToken(
-    const PrivetURLFetcher::TokenCallback& callback) {
-  privet_client_->RefreshPrivetToken(callback);
+    PrivetURLFetcher::TokenCallback callback) {
+  privet_client_->RefreshPrivetToken(std::move(callback));
 }
 
 void PrivetLocalPrintOperationImpl::SetData(
@@ -722,35 +721,32 @@
 }
 
 void PrivetHTTPClientImpl::RefreshPrivetToken(
-    const PrivetURLFetcher::TokenCallback& callback) {
-  token_callbacks_.push_back(callback);
+    PrivetURLFetcher::TokenCallback callback) {
+  token_callbacks_.push_back(std::move(callback));
 
-  if (!info_operation_) {
-    info_operation_ = CreateInfoOperation(
-        base::Bind(&PrivetHTTPClientImpl::OnPrivetInfoDone,
-                   base::Unretained(this)));
-    info_operation_->Start();
-  }
+  if (info_operation_)
+    return;
+
+  info_operation_ = CreateInfoOperation(base::BindRepeating(
+      &PrivetHTTPClientImpl::OnPrivetInfoDone, base::Unretained(this)));
+  info_operation_->Start();
 }
 
 void PrivetHTTPClientImpl::OnPrivetInfoDone(
     const base::DictionaryValue* value) {
   info_operation_.reset();
-  std::string token;
 
   // If this does not succeed, token will be empty, and an empty string
   // is our sentinel value, since empty X-Privet-Tokens are not allowed.
-  if (value) {
+  std::string token;
+  if (value)
     value->GetString(kPrivetInfoKeyToken, &token);
-  }
 
   TokenCallbackVector token_callbacks;
   token_callbacks_.swap(token_callbacks);
 
-  for (TokenCallbackVector::iterator i = token_callbacks.begin();
-       i != token_callbacks.end(); i++) {
-    i->Run(token);
-  }
+  for (auto& callback : token_callbacks)
+    std::move(callback).Run(token);
 }
 
 PrivetV1HTTPClientImpl::PrivetV1HTTPClientImpl(
diff --git a/chrome/browser/printing/cloud_print/privet_http_impl.h b/chrome/browser/printing/cloud_print/privet_http_impl.h
index d70977b..fe6ed04 100644
--- a/chrome/browser/printing/cloud_print/privet_http_impl.h
+++ b/chrome/browser/printing/cloud_print/privet_http_impl.h
@@ -65,8 +65,7 @@
                     const base::DictionaryValue& value,
                     bool has_error) override;
 
-  void OnNeedPrivetToken(
-      const PrivetURLFetcher::TokenCallback& callback) override;
+  void OnNeedPrivetToken(PrivetURLFetcher::TokenCallback callback) override;
 
   PrivetHTTPClient* GetHTTPClient() override;
 
@@ -131,8 +130,7 @@
   void OnParsedJson(PrivetURLFetcher* fetcher,
                     const base::DictionaryValue& value,
                     bool has_error) override;
-  void OnNeedPrivetToken(
-      const PrivetURLFetcher::TokenCallback& callback) override;
+  void OnNeedPrivetToken(PrivetURLFetcher::TokenCallback callback) override;
 
  private:
   PrivetHTTPClient* privet_client_;
@@ -170,8 +168,7 @@
   void OnParsedJson(PrivetURLFetcher* fetcher,
                     const base::DictionaryValue& value,
                     bool has_error) override;
-  void OnNeedPrivetToken(
-      const PrivetURLFetcher::TokenCallback& callback) override;
+  void OnNeedPrivetToken(PrivetURLFetcher::TokenCallback callback) override;
 
  private:
   typedef base::Callback<void(bool, const base::DictionaryValue* value)>
@@ -239,10 +236,10 @@
       net::URLFetcher::RequestType request_type,
       PrivetURLFetcher::Delegate* delegate) override;
   void RefreshPrivetToken(
-      const PrivetURLFetcher::TokenCallback& token_callback) override;
+      PrivetURLFetcher::TokenCallback token_callback) override;
 
  private:
-  typedef std::vector<PrivetURLFetcher::TokenCallback> TokenCallbackVector;
+  using TokenCallbackVector = std::vector<PrivetURLFetcher::TokenCallback>;
 
   void OnPrivetInfoDone(const base::DictionaryValue* value);
 
diff --git a/chrome/browser/printing/cloud_print/privet_http_unittest.cc b/chrome/browser/printing/cloud_print/privet_http_unittest.cc
index 13f22abb..fb32bdfa 100644
--- a/chrome/browser/printing/cloud_print/privet_http_unittest.cc
+++ b/chrome/browser/printing/cloud_print/privet_http_unittest.cc
@@ -1056,9 +1056,8 @@
         "test", server_->host_port_pair(), context_getter_);
   }
 
-  void OnNeedPrivetToken(
-      const PrivetURLFetcher::TokenCallback& callback) override {
-    callback.Run("abc");
+  void OnNeedPrivetToken(PrivetURLFetcher::TokenCallback callback) override {
+    std::move(callback).Run("abc");
   }
 
   void OnError(int response_code, PrivetURLFetcher::ErrorType error) override {
diff --git a/chrome/browser/printing/cloud_print/privet_url_fetcher.cc b/chrome/browser/printing/cloud_print/privet_url_fetcher.cc
index 0b1de91..28dcfe2 100644
--- a/chrome/browser/printing/cloud_print/privet_url_fetcher.cc
+++ b/chrome/browser/printing/cloud_print/privet_url_fetcher.cc
@@ -58,8 +58,7 @@
 
 }  // namespace
 
-void PrivetURLFetcher::Delegate::OnNeedPrivetToken(
-    const TokenCallback& callback) {
+void PrivetURLFetcher::Delegate::OnNeedPrivetToken(TokenCallback callback) {
   OnError(0, TOKEN_ERROR);
 }
 
diff --git a/chrome/browser/printing/cloud_print/privet_url_fetcher.h b/chrome/browser/printing/cloud_print/privet_url_fetcher.h
index 4309d248..7dbffc66 100644
--- a/chrome/browser/printing/cloud_print/privet_url_fetcher.h
+++ b/chrome/browser/printing/cloud_print/privet_url_fetcher.h
@@ -38,7 +38,7 @@
     UNKNOWN_ERROR,
   };
 
-  typedef base::Callback<void(const std::string& /*token*/)> TokenCallback;
+  using TokenCallback = base::OnceCallback<void(const std::string& /*token*/)>;
 
   class Delegate {
    public:
@@ -46,7 +46,7 @@
 
     // If you do not implement this method for PrivetV1 callers, you will always
     // get a TOKEN_ERROR error when your token is invalid.
-    virtual void OnNeedPrivetToken(const TokenCallback& callback);
+    virtual void OnNeedPrivetToken(TokenCallback callback);
 
     // |response_code| is only needed for RESPONSE_CODE_ERROR.
     virtual void OnError(int response_code, ErrorType error) = 0;
diff --git a/chrome/browser/printing/cloud_print/privet_url_fetcher_unittest.cc b/chrome/browser/printing/cloud_print/privet_url_fetcher_unittest.cc
index 1bc11ec..fab7d9b 100644
--- a/chrome/browser/printing/cloud_print/privet_url_fetcher_unittest.cc
+++ b/chrome/browser/printing/cloud_print/privet_url_fetcher_unittest.cc
@@ -55,9 +55,7 @@
 
   MOCK_METHOD1(OnParsedJsonInternal, void(bool has_error));
 
-  virtual void OnNeedPrivetToken(
-      const PrivetURLFetcher::TokenCallback& callback) {
-  }
+  virtual void OnNeedPrivetToken(PrivetURLFetcher::TokenCallback callback) {}
 
   bool OnRawData(bool response_is_file,
                  const std::string& data,
diff --git a/chrome/browser/safe_browsing/client_side_detection_host.cc b/chrome/browser/safe_browsing/client_side_detection_host.cc
index e95c7df..05a8b9d 100644
--- a/chrome/browser/safe_browsing/client_side_detection_host.cc
+++ b/chrome/browser/safe_browsing/client_side_detection_host.cc
@@ -32,7 +32,6 @@
 #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/resource_request_details.h"
 #include "content/public/browser/web_contents.h"
 #include "content/public/common/frame_navigate_params.h"
 #include "content/public/common/url_constants.h"
@@ -41,7 +40,6 @@
 
 using content::BrowserThread;
 using content::NavigationEntry;
-using content::ResourceRequestDetails;
 using content::ResourceType;
 using content::WebContents;
 
diff --git a/chrome/browser/safe_browsing/client_side_detection_host.h b/chrome/browser/safe_browsing/client_side_detection_host.h
index 9b69802..4161994 100644
--- a/chrome/browser/safe_browsing/client_side_detection_host.h
+++ b/chrome/browser/safe_browsing/client_side_detection_host.h
@@ -16,7 +16,6 @@
 #include "chrome/browser/safe_browsing/browser_feature_extractor.h"
 #include "chrome/browser/safe_browsing/ui_manager.h"
 #include "components/safe_browsing/db/database_manager.h"
-#include "content/public/browser/resource_request_details.h"
 #include "content/public/browser/web_contents_observer.h"
 #include "url/gurl.h"
 
diff --git a/chrome/browser/ui/ash/accessibility/accessibility_controller_client.cc b/chrome/browser/ui/ash/accessibility/accessibility_controller_client.cc
index 0e755863..b4a3076d 100644
--- a/chrome/browser/ui/ash/accessibility/accessibility_controller_client.cc
+++ b/chrome/browser/ui/ash/accessibility/accessibility_controller_client.cc
@@ -5,6 +5,7 @@
 #include "chrome/browser/ui/ash/accessibility/accessibility_controller_client.h"
 
 #include "ash/public/interfaces/constants.mojom.h"
+#include "chrome/browser/chromeos/accessibility/accessibility_manager.h"
 #include "chrome/browser/profiles/profile_manager.h"
 #include "chrome/browser/ui/aura/accessibility/automation_manager_aura.h"
 #include "chrome/grit/generated_resources.h"
@@ -14,8 +15,6 @@
 
 namespace {
 
-AccessibilityControllerClient* g_instance = nullptr;
-
 void SetAutomationManagerEnabled(content::BrowserContext* context,
                                  bool enabled) {
   DCHECK(context);
@@ -29,20 +28,9 @@
 }  // namespace
 
 AccessibilityControllerClient::AccessibilityControllerClient()
-    : binding_(this) {
-  DCHECK(!g_instance);
-  g_instance = this;
-}
+    : binding_(this) {}
 
-AccessibilityControllerClient::~AccessibilityControllerClient() {
-  DCHECK_EQ(this, g_instance);
-  g_instance = nullptr;
-}
-
-// static
-AccessibilityControllerClient* AccessibilityControllerClient::Get() {
-  return g_instance;
-}
+AccessibilityControllerClient::~AccessibilityControllerClient() = default;
 
 void AccessibilityControllerClient::Init() {
   content::ServiceManagerConnection::GetForProcess()
@@ -59,8 +47,6 @@
 
 void AccessibilityControllerClient::TriggerAccessibilityAlert(
     ash::mojom::AccessibilityAlert alert) {
-  last_a11y_alert_for_test_ = alert;
-
   Profile* profile = ProfileManager::GetActiveUserProfile();
   if (!profile)
     return;
@@ -115,6 +101,18 @@
   }
 }
 
+void AccessibilityControllerClient::PlayEarcon(int32_t sound_key) {
+  chromeos::AccessibilityManager::Get()->PlayEarcon(
+      sound_key, chromeos::PlaySoundOption::ONLY_IF_SPOKEN_FEEDBACK_ENABLED);
+}
+
+void AccessibilityControllerClient::PlayShutdownSound(
+    PlayShutdownSoundCallback callback) {
+  base::TimeDelta sound_duration =
+      chromeos::AccessibilityManager::Get()->PlayShutdownSound();
+  std::move(callback).Run(sound_duration);
+}
+
 void AccessibilityControllerClient::FlushForTesting() {
   accessibility_controller_.FlushForTesting();
 }
diff --git a/chrome/browser/ui/ash/accessibility/accessibility_controller_client.h b/chrome/browser/ui/ash/accessibility/accessibility_controller_client.h
index 8a96354..43805e0 100644
--- a/chrome/browser/ui/ash/accessibility/accessibility_controller_client.h
+++ b/chrome/browser/ui/ash/accessibility/accessibility_controller_client.h
@@ -16,8 +16,6 @@
   AccessibilityControllerClient();
   ~AccessibilityControllerClient() override;
 
-  static AccessibilityControllerClient* Get();
-
   // Initializes and connects to ash.
   void Init();
 
@@ -26,14 +24,12 @@
 
   // ash::mojom::AccessibilityControllerClient:
   void TriggerAccessibilityAlert(ash::mojom::AccessibilityAlert alert) override;
+  void PlayEarcon(int32_t sound_key) override;
+  void PlayShutdownSound(PlayShutdownSoundCallback callback) override;
 
   // Flushes the mojo pipe to ash.
   void FlushForTesting();
 
-  ash::mojom::AccessibilityAlert last_a11y_alert_for_test() const {
-    return last_a11y_alert_for_test_;
-  }
-
  private:
   // Binds this object to its mojo interface and sets it as the ash client.
   void BindAndSetClient();
@@ -45,9 +41,6 @@
   // keeps the pipe alive to receive mojo return values.
   ash::mojom::AccessibilityControllerPtr accessibility_controller_;
 
-  ash::mojom::AccessibilityAlert last_a11y_alert_for_test_ =
-      ash::mojom::AccessibilityAlert::NONE;
-
   DISALLOW_COPY_AND_ASSIGN(AccessibilityControllerClient);
 };
 
diff --git a/chrome/browser/ui/ash/accessibility/accessibility_controller_client_unittest.cc b/chrome/browser/ui/ash/accessibility/accessibility_controller_client_unittest.cc
index babf090..9962436 100644
--- a/chrome/browser/ui/ash/accessibility/accessibility_controller_client_unittest.cc
+++ b/chrome/browser/ui/ash/accessibility/accessibility_controller_client_unittest.cc
@@ -6,12 +6,22 @@
 
 #include "ash/public/interfaces/accessibility_controller.mojom.h"
 #include "base/macros.h"
+#include "base/run_loop.h"
 #include "base/test/scoped_task_environment.h"
+#include "base/time/time.h"
+#include "chromeos/audio/chromeos_sounds.h"
 #include "mojo/public/cpp/bindings/binding.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
 namespace {
 
+constexpr base::TimeDelta kShutdownSoundDuration =
+    base::TimeDelta::FromMilliseconds(1000);
+
+void CopyResult(base::TimeDelta* dest, base::TimeDelta src) {
+  *dest = src;
+}
+
 class TestAccessibilityController : ash::mojom::AccessibilityController {
  public:
   TestAccessibilityController() : binding_(this) {}
@@ -37,6 +47,36 @@
   DISALLOW_COPY_AND_ASSIGN(TestAccessibilityController);
 };
 
+class FakeAccessibilityControllerClient : public AccessibilityControllerClient {
+ public:
+  FakeAccessibilityControllerClient() = default;
+  ~FakeAccessibilityControllerClient() override = default;
+
+  // AccessibilityControllerClient:
+  void TriggerAccessibilityAlert(
+      ash::mojom::AccessibilityAlert alert) override {
+    last_a11y_alert_ = alert;
+  }
+
+  void PlayEarcon(int32_t sound_key) override { last_sound_key_ = sound_key; }
+
+  void PlayShutdownSound(PlayShutdownSoundCallback callback) override {
+    std::move(callback).Run(kShutdownSoundDuration);
+  }
+
+  ash::mojom::AccessibilityAlert last_a11y_alert() const {
+    return last_a11y_alert_;
+  }
+  int32_t last_sound_key() const { return last_sound_key_; }
+
+ private:
+  ash::mojom::AccessibilityAlert last_a11y_alert_ =
+      ash::mojom::AccessibilityAlert::NONE;
+  int32_t last_sound_key_ = -1;
+
+  DISALLOW_COPY_AND_ASSIGN(FakeAccessibilityControllerClient);
+};
+
 }  // namespace
 
 class AccessibilityControllerClientTest : public testing::Test {
@@ -50,19 +90,30 @@
   DISALLOW_COPY_AND_ASSIGN(AccessibilityControllerClientTest);
 };
 
-TEST_F(AccessibilityControllerClientTest, TriggerAccessibilityAlert) {
-  AccessibilityControllerClient client;
+TEST_F(AccessibilityControllerClientTest, MethodCalls) {
+  FakeAccessibilityControllerClient client;
   TestAccessibilityController controller;
   client.InitForTesting(controller.CreateInterfacePtr());
   client.FlushForTesting();
 
-  // Tests that singleton was initialized and client is set.
-  EXPECT_EQ(&client, AccessibilityControllerClient::Get());
+  // Tests client is set.
   EXPECT_TRUE(controller.was_client_set());
 
   // Tests TriggerAccessibilityAlert method call.
   const ash::mojom::AccessibilityAlert alert =
       ash::mojom::AccessibilityAlert::SCREEN_ON;
   client.TriggerAccessibilityAlert(alert);
-  EXPECT_EQ(alert, client.last_a11y_alert_for_test());
-}
\ No newline at end of file
+  EXPECT_EQ(alert, client.last_a11y_alert());
+
+  // Tests PlayEarcon method call.
+  const int32_t sound_key = chromeos::SOUND_SHUTDOWN;
+  client.PlayEarcon(sound_key);
+  EXPECT_EQ(sound_key, client.last_sound_key());
+
+  // Tests PlayShutdownSound method call.
+  base::TimeDelta sound_duration;
+  client.PlayShutdownSound(
+      base::BindOnce(&CopyResult, base::Unretained(&sound_duration)));
+  base::RunLoop().RunUntilIdle();
+  EXPECT_EQ(kShutdownSoundDuration, sound_duration);
+}
diff --git a/chrome/browser/ui/ash/chrome_shell_delegate.cc b/chrome/browser/ui/ash/chrome_shell_delegate.cc
index 3a5e5fb..8cd1d09 100644
--- a/chrome/browser/ui/ash/chrome_shell_delegate.cc
+++ b/chrome/browser/ui/ash/chrome_shell_delegate.cc
@@ -261,16 +261,6 @@
     AccessibilityManager::Get()->PlaySpokenFeedbackToggleCountdown(tick_count);
   }
 
-  void PlayEarcon(int sound_key) override {
-    DCHECK(AccessibilityManager::Get());
-    AccessibilityManager::Get()->PlayEarcon(
-        sound_key, chromeos::PlaySoundOption::SPOKEN_FEEDBACK_ENABLED);
-  }
-
-  base::TimeDelta PlayShutdownSound() const override {
-    return AccessibilityManager::Get()->PlayShutdownSound();
-  }
-
   void HandleAccessibilityGesture(ui::AXGesture gesture) override {
     AccessibilityManager::Get()->HandleAccessibilityGesture(gesture);
   }
diff --git a/chrome/browser/ui/ash/volume_controller.cc b/chrome/browser/ui/ash/volume_controller.cc
index 58902850..ae61bf1 100644
--- a/chrome/browser/ui/ash/volume_controller.cc
+++ b/chrome/browser/ui/ash/volume_controller.cc
@@ -31,7 +31,7 @@
   if (VolumeAdjustSoundEnabled()) {
     chromeos::AccessibilityManager::Get()->PlayEarcon(
         chromeos::SOUND_VOLUME_ADJUST,
-        chromeos::PlaySoundOption::SPOKEN_FEEDBACK_ENABLED);
+        chromeos::PlaySoundOption::ONLY_IF_SPOKEN_FEEDBACK_ENABLED);
   }
 }
 
diff --git a/chrome/browser/ui/webui/chromeos/login/supervised_user_creation_screen_handler.cc b/chrome/browser/ui/webui/chromeos/login/supervised_user_creation_screen_handler.cc
index 1ba0ad3..eb2b0eb 100644
--- a/chrome/browser/ui/webui/chromeos/login/supervised_user_creation_screen_handler.cc
+++ b/chrome/browser/ui/webui/chromeos/login/supervised_user_creation_screen_handler.cc
@@ -423,12 +423,12 @@
 
 void SupervisedUserCreationScreenHandler::HandleTakePhoto() {
   AccessibilityManager::Get()->PlayEarcon(
-      SOUND_CAMERA_SNAP, PlaySoundOption::SPOKEN_FEEDBACK_ENABLED);
+      SOUND_CAMERA_SNAP, PlaySoundOption::ONLY_IF_SPOKEN_FEEDBACK_ENABLED);
 }
 
 void SupervisedUserCreationScreenHandler::HandleDiscardPhoto() {
   AccessibilityManager::Get()->PlayEarcon(
-      SOUND_OBJECT_DELETE, PlaySoundOption::SPOKEN_FEEDBACK_ENABLED);
+      SOUND_OBJECT_DELETE, PlaySoundOption::ONLY_IF_SPOKEN_FEEDBACK_ENABLED);
 }
 
 void SupervisedUserCreationScreenHandler::HandleSelectImage(
diff --git a/chrome/browser/ui/webui/chromeos/login/user_image_screen_handler.cc b/chrome/browser/ui/webui/chromeos/login/user_image_screen_handler.cc
index 9f0f540..5fb1f0b 100644
--- a/chrome/browser/ui/webui/chromeos/login/user_image_screen_handler.cc
+++ b/chrome/browser/ui/webui/chromeos/login/user_image_screen_handler.cc
@@ -137,7 +137,7 @@
 
 void UserImageScreenHandler::HandlePhotoTaken(const std::string& image_url) {
   AccessibilityManager::Get()->PlayEarcon(
-      SOUND_CAMERA_SNAP, PlaySoundOption::SPOKEN_FEEDBACK_ENABLED);
+      SOUND_CAMERA_SNAP, PlaySoundOption::ONLY_IF_SPOKEN_FEEDBACK_ENABLED);
 
   std::string raw_data;
   base::StringPiece url(image_url);
@@ -155,7 +155,7 @@
 
 void UserImageScreenHandler::HandleDiscardPhoto() {
   AccessibilityManager::Get()->PlayEarcon(
-      SOUND_OBJECT_DELETE, PlaySoundOption::SPOKEN_FEEDBACK_ENABLED);
+      SOUND_OBJECT_DELETE, PlaySoundOption::ONLY_IF_SPOKEN_FEEDBACK_ENABLED);
 }
 
 void UserImageScreenHandler::HandleSelectImage(const std::string& image_type,
diff --git a/chrome/browser/ui/webui/settings/chromeos/change_picture_handler.cc b/chrome/browser/ui/webui/settings/chromeos/change_picture_handler.cc
index 9cb364e..3601355 100644
--- a/chrome/browser/ui/webui/settings/chromeos/change_picture_handler.cc
+++ b/chrome/browser/ui/webui/settings/chromeos/change_picture_handler.cc
@@ -164,13 +164,13 @@
 void ChangePictureHandler::HandleDiscardPhoto(const base::ListValue* args) {
   DCHECK(args->empty());
   AccessibilityManager::Get()->PlayEarcon(
-      SOUND_OBJECT_DELETE, PlaySoundOption::SPOKEN_FEEDBACK_ENABLED);
+      SOUND_OBJECT_DELETE, PlaySoundOption::ONLY_IF_SPOKEN_FEEDBACK_ENABLED);
 }
 
 void ChangePictureHandler::HandlePhotoTaken(const base::ListValue* args) {
   DCHECK_CURRENTLY_ON(BrowserThread::UI);
   AccessibilityManager::Get()->PlayEarcon(
-      SOUND_CAMERA_SNAP, PlaySoundOption::SPOKEN_FEEDBACK_ENABLED);
+      SOUND_CAMERA_SNAP, PlaySoundOption::ONLY_IF_SPOKEN_FEEDBACK_ENABLED);
 
   std::string image_url;
   if (!args || args->GetSize() != 1 || !args->GetString(0, &image_url))
diff --git a/content/browser/loader/loader_delegate.h b/content/browser/loader/loader_delegate.h
index fed8520..08ebf70 100644
--- a/content/browser/loader/loader_delegate.h
+++ b/content/browser/loader/loader_delegate.h
@@ -11,7 +11,6 @@
 
 #include "base/time/time.h"
 #include "content/common/content_export.h"
-#include "content/public/browser/resource_request_details.h"
 #include "content/public/browser/resource_request_info.h"
 #include "net/base/load_states.h"
 
@@ -40,11 +39,6 @@
       uint64_t upload_position,
       uint64_t upload_size) = 0;
 
-  // Notification that a response has been received for a resource request.
-  virtual void DidGetResourceResponseStart(
-      const ResourceRequestInfo::WebContentsGetter& web_contents_getter,
-      std::unique_ptr<ResourceRequestDetails> details) = 0;
-
   // Called when the network stack started handling the navigation request.
   virtual void LogResourceRequestTime(base::TimeTicks timestamp,
                                       int render_process_id,
diff --git a/content/browser/loader/resource_dispatcher_host_impl.cc b/content/browser/loader/resource_dispatcher_host_impl.cc
index 867154b..1f876b2 100644
--- a/content/browser/loader/resource_dispatcher_host_impl.cc
+++ b/content/browser/loader/resource_dispatcher_host_impl.cc
@@ -84,7 +84,6 @@
 #include "content/public/browser/navigation_ui_data.h"
 #include "content/public/browser/plugin_service.h"
 #include "content/public/browser/resource_dispatcher_host_delegate.h"
-#include "content/public/browser/resource_request_details.h"
 #include "content/public/browser/resource_throttle.h"
 #include "content/public/browser/stream_handle.h"
 #include "content/public/browser/stream_info.h"
@@ -647,18 +646,6 @@
 
   if (delegate_)
     delegate_->OnResponseStarted(request, info->GetContext(), response);
-
-  // Don't notify WebContents observers for requests known to be
-  // downloads; they aren't really associated with the Webcontents.
-  // Note that not all downloads are known before content sniffing.
-  if (info->IsDownload())
-    return;
-
-  // Notify the observers on the UI thread.
-  std::unique_ptr<ResourceRequestDetails> detail(new ResourceRequestDetails(
-      request, !!request->ssl_info().cert));
-  loader_delegate_->DidGetResourceResponseStart(
-      info->GetWebContentsGetterForRequest(), std::move(detail));
 }
 
 void ResourceDispatcherHostImpl::DidFinishLoading(ResourceLoader* loader) {
diff --git a/content/browser/loader_delegate_impl.cc b/content/browser/loader_delegate_impl.cc
index 22b22a1..4bb2b24 100644
--- a/content/browser/loader_delegate_impl.cc
+++ b/content/browser/loader_delegate_impl.cc
@@ -14,15 +14,6 @@
 
 namespace {
 
-void DidGetResourceResponseStartOnUI(
-    const ResourceRequestInfo::WebContentsGetter& web_contents_getter,
-    std::unique_ptr<ResourceRequestDetails> details) {
-  WebContentsImpl* web_contents =
-      static_cast<WebContentsImpl*>(web_contents_getter.Run());
-  if (web_contents)
-    web_contents->DidGetResourceResponseStart(*details.get());
-}
-
 // This method is called in the UI thread to send the timestamp of a resource
 // request to the respective Navigator (for an UMA histogram).
 void DidGetLogResourceRequestTimeOnUI(base::TimeTicks timestamp,
@@ -54,16 +45,6 @@
       url, load_state, upload_position, upload_size);
 }
 
-void LoaderDelegateImpl::DidGetResourceResponseStart(
-    const ResourceRequestInfo::WebContentsGetter& web_contents_getter,
-    std::unique_ptr<ResourceRequestDetails> details) {
-  DCHECK_CURRENTLY_ON(BrowserThread::IO);
-  BrowserThread::PostTask(
-      BrowserThread::UI, FROM_HERE,
-      base::BindOnce(&DidGetResourceResponseStartOnUI, web_contents_getter,
-                     base::Passed(std::move(details))));
-}
-
 void LoaderDelegateImpl::LogResourceRequestTime(base::TimeTicks timestamp,
                                                 int render_process_id,
                                                 int render_frame_id,
diff --git a/content/browser/loader_delegate_impl.h b/content/browser/loader_delegate_impl.h
index df3f311..6905aec3 100644
--- a/content/browser/loader_delegate_impl.h
+++ b/content/browser/loader_delegate_impl.h
@@ -21,9 +21,6 @@
       const net::LoadStateWithParam& load_state,
       uint64_t upload_position,
       uint64_t upload_size) override;
-  void DidGetResourceResponseStart(
-      const ResourceRequestInfo::WebContentsGetter& web_contents_getter,
-      std::unique_ptr<ResourceRequestDetails> details) override;
   void LogResourceRequestTime(base::TimeTicks timestamp,
                               int render_process_id,
                               int render_frame_id,
diff --git a/content/browser/renderer_host/render_widget_host_view_base.cc b/content/browser/renderer_host/render_widget_host_view_base.cc
index 34248e7..b25b0d94 100644
--- a/content/browser/renderer_host/render_widget_host_view_base.cc
+++ b/content/browser/renderer_host/render_widget_host_view_base.cc
@@ -546,9 +546,11 @@
 }
 
 void RenderWidgetHostViewBase::OnChildFrameDestroyed(int routing_id) {
-  DCHECK(render_widget_window_tree_client_);
   pending_embeds_.erase(routing_id);
-  render_widget_window_tree_client_->DestroyFrame(routing_id);
+  // Tests may not create |render_widget_window_tree_client_| (tests don't
+  // necessarily create RenderWidgetHostViewAura).
+  if (render_widget_window_tree_client_)
+    render_widget_window_tree_client_->DestroyFrame(routing_id);
 }
 #endif
 
@@ -569,8 +571,10 @@
   if (iter == pending_embeds_.end() || iter->second != embed_id)
     return;
   pending_embeds_.erase(iter);
-  DCHECK(render_widget_window_tree_client_);
-  render_widget_window_tree_client_->Embed(routing_id, token);
+  // Tests may not create |render_widget_window_tree_client_| (tests don't
+  // necessarily create RenderWidgetHostViewAura).
+  if (render_widget_window_tree_client_)
+    render_widget_window_tree_client_->Embed(routing_id, token);
 }
 
 void RenderWidgetHostViewBase::ScheduleEmbed(
diff --git a/content/browser/web_contents/web_contents_impl.cc b/content/browser/web_contents/web_contents_impl.cc
index d4779318..f22cf700 100644
--- a/content/browser/web_contents/web_contents_impl.cc
+++ b/content/browser/web_contents/web_contents_impl.cc
@@ -104,7 +104,6 @@
 #include "content/public/browser/notification_service.h"
 #include "content/public/browser/notification_types.h"
 #include "content/public/browser/render_widget_host_iterator.h"
-#include "content/public/browser/resource_request_details.h"
 #include "content/public/browser/restore_type.h"
 #include "content/public/browser/security_style_explanations.h"
 #include "content/public/browser/ssl_status.h"
@@ -3422,11 +3421,6 @@
   }
 }
 
-void WebContentsImpl::DidGetResourceResponseStart(
-    const ResourceRequestDetails& details) {
-  SetNotWaitingForResponse();
-}
-
 void WebContentsImpl::NotifyWebContentsFocused(
     RenderWidgetHost* render_widget_host) {
   for (auto& observer : observers_)
@@ -3693,9 +3687,14 @@
   for (auto& observer : observers_)
     observer.ReadyToCommitNavigation(navigation_handle);
 
+  if (navigation_handle->IsSameDocument())
+    return;
+
   controller_.ssl_manager()->DidStartResourceResponse(
       navigation_handle->GetURL(),
       net::IsCertStatusError(navigation_handle->GetSSLInfo().cert_status));
+
+  SetNotWaitingForResponse();
 }
 
 void WebContentsImpl::DidFinishNavigation(NavigationHandle* navigation_handle) {
@@ -4010,6 +4009,7 @@
   }
 
   controller_.ssl_manager()->DidStartResourceResponse(url, cert_status);
+  SetNotWaitingForResponse();
 }
 
 #if defined(OS_ANDROID)
diff --git a/content/browser/web_contents/web_contents_impl.h b/content/browser/web_contents/web_contents_impl.h
index 781f815..b4ca68a 100644
--- a/content/browser/web_contents/web_contents_impl.h
+++ b/content/browser/web_contents/web_contents_impl.h
@@ -100,7 +100,6 @@
 struct FaviconURL;
 struct LoadNotificationDetails;
 struct MHTMLGenerationParams;
-struct ResourceRequestDetails;
 
 namespace mojom {
 class CreateNewWindowParams;
@@ -211,10 +210,6 @@
                         uint64_t upload_position,
                         uint64_t upload_size);
 
-  // A response has been received for a resource request.
-  void DidGetResourceResponseStart(
-      const ResourceRequestDetails& details);
-
   // Notify observers that the web contents has been focused.
   void NotifyWebContentsFocused(RenderWidgetHost* render_widget_host);
 
diff --git a/content/browser/web_contents/web_contents_impl_unittest.cc b/content/browser/web_contents/web_contents_impl_unittest.cc
index e5d23f1..183999c9 100644
--- a/content/browser/web_contents/web_contents_impl_unittest.cc
+++ b/content/browser/web_contents/web_contents_impl_unittest.cc
@@ -374,7 +374,6 @@
 
   main_test_rfh()->SendNavigateWithParams(&params);
 
-  EXPECT_TRUE(contents()->IsWaitingForResponse());
   contents()->UpdateTitle(main_test_rfh(),
                           base::ASCIIToUTF16("    Lots O' Whitespace\n"),
                           base::i18n::LEFT_TO_RIGHT);
diff --git a/content/public/browser/BUILD.gn b/content/public/browser/BUILD.gn
index 38a96ef7..fbd4017 100644
--- a/content/public/browser/BUILD.gn
+++ b/content/public/browser/BUILD.gn
@@ -230,8 +230,6 @@
     "resource_dispatcher_host_delegate.h",
     "resource_dispatcher_host_login_delegate.h",
     "resource_hints.h",
-    "resource_request_details.cc",
-    "resource_request_details.h",
     "resource_request_info.h",
     "resource_throttle.cc",
     "resource_throttle.h",
diff --git a/content/public/browser/resource_request_details.cc b/content/public/browser/resource_request_details.cc
deleted file mode 100644
index 759915cf4..0000000
--- a/content/public/browser/resource_request_details.cc
+++ /dev/null
@@ -1,34 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "content/public/browser/resource_request_details.h"
-
-#include "content/public/browser/resource_request_info.h"
-#include "net/http/http_response_headers.h"
-#include "net/url_request/url_request.h"
-
-namespace content {
-
-ResourceRequestDetails::ResourceRequestDetails(const net::URLRequest* request,
-                                               bool has_certificate)
-    : url(request->url()),
-      original_url(request->original_url()),
-      method(request->method()),
-      referrer(request->referrer()),
-      has_upload(request->has_upload()),
-      load_flags(request->load_flags()),
-      status(request->status()),
-      has_certificate(has_certificate),
-      ssl_cert_status(request->ssl_info().cert_status),
-      socket_address(request->GetSocketAddress()) {
-  const ResourceRequestInfo* info = ResourceRequestInfo::ForRequest(request);
-  resource_type = info->GetResourceType();
-  http_response_code =
-      request->response_info().headers.get() ?
-          request->response_info().headers.get()->response_code() : -1;
-}
-
-ResourceRequestDetails::~ResourceRequestDetails() {}
-
-}  // namespace content
diff --git a/content/public/browser/resource_request_details.h b/content/public/browser/resource_request_details.h
deleted file mode 100644
index 06b1401..0000000
--- a/content/public/browser/resource_request_details.h
+++ /dev/null
@@ -1,48 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CONTENT_PUBLIC_BROWSER_RESOURCE_REQUEST_DETAILS_H_
-#define CONTENT_PUBLIC_BROWSER_RESOURCE_REQUEST_DETAILS_H_
-
-#include <string>
-
-#include "content/public/common/resource_type.h"
-#include "net/base/host_port_pair.h"
-#include "net/cert/cert_status_flags.h"
-#include "net/url_request/url_request_status.h"
-#include "url/gurl.h"
-
-namespace net {
-class URLRequest;
-}
-
-namespace content {
-
-// The ResourceRequestDetails object contains additional details about a
-// resource request notification. It copies many of the publicly accessible
-// member variables of net::URLRequest, but exists on the UI thread.
-struct ResourceRequestDetails {
-  ResourceRequestDetails(const net::URLRequest* request, bool has_certificate);
-
-  virtual ~ResourceRequestDetails();
-
-  GURL url;
-  GURL original_url;
-  std::string method;
-  std::string referrer;
-  bool has_upload;
-  int load_flags;
-  net::URLRequestStatus status;
-  bool has_certificate;
-  net::CertStatus ssl_cert_status;
-  ResourceType resource_type;
-  net::HostPortPair socket_address;
-  // HTTP response code. See HttpResponseHeaders::response_code().
-  // -1 if there are no response headers yet.
-  int http_response_code;
-};
-
-}  // namespace content
-
-#endif  // CONTENT_PUBLIC_BROWSER_RESOURCE_REQUEST_DETAILS_H_
diff --git a/content/renderer/gpu/render_widget_compositor.cc b/content/renderer/gpu/render_widget_compositor.cc
index 26698834a..3b266c56 100644
--- a/content/renderer/gpu/render_widget_compositor.cc
+++ b/content/renderer/gpu/render_widget_compositor.cc
@@ -1010,7 +1010,7 @@
   layout_and_paint_async_callback_ = callback;
 
   if (CompositeIsSynchronous()) {
-    base::ThreadTaskRunnerHandle::Get()->PostTask(
+    layer_tree_host_->GetTaskRunnerProvider()->MainThreadTaskRunner()->PostTask(
         FROM_HERE,
         base::BindOnce(&RenderWidgetCompositor::LayoutAndUpdateLayers,
                        weak_factory_.GetWeakPtr()));
@@ -1071,7 +1071,7 @@
   // be installed after layout which will happen as a part of the commit, for
   // widgets that delay the creation of their output surface.
   if (CompositeIsSynchronous()) {
-    base::ThreadTaskRunnerHandle::Get()->PostTask(
+    layer_tree_host_->GetTaskRunnerProvider()->MainThreadTaskRunner()->PostTask(
         FROM_HERE,
         base::BindOnce(&RenderWidgetCompositor::SynchronouslyComposite,
                        weak_factory_.GetWeakPtr()));
@@ -1152,7 +1152,7 @@
   // in this case we actually need a commit to transfer the decode requests to
   // the impl side. So, force a commit to happen.
   if (CompositeIsSynchronous()) {
-    base::ThreadTaskRunnerHandle::Get()->PostTask(
+    layer_tree_host_->GetTaskRunnerProvider()->MainThreadTaskRunner()->PostTask(
         FROM_HERE,
         base::BindOnce(&RenderWidgetCompositor::SynchronouslyComposite,
                        weak_factory_.GetWeakPtr()));
@@ -1228,7 +1228,7 @@
     return;
   }
   layer_tree_frame_sink_request_failed_while_invisible_ = false;
-  base::ThreadTaskRunnerHandle::Get()->PostTask(
+  layer_tree_host_->GetTaskRunnerProvider()->MainThreadTaskRunner()->PostTask(
       FROM_HERE,
       base::BindOnce(&RenderWidgetCompositor::RequestNewLayerTreeFrameSink,
                      weak_factory_.GetWeakPtr()));
@@ -1292,7 +1292,8 @@
 
 void RenderWidgetCompositor::NotifySwapTime(ReportTimeCallback callback) {
   QueueSwapPromise(std::make_unique<ReportTimeSwapPromise>(
-      std::move(callback), base::ThreadTaskRunnerHandle::Get()));
+      std::move(callback),
+      layer_tree_host_->GetTaskRunnerProvider()->MainThreadTaskRunner()));
 }
 
 void RenderWidgetCompositor::RequestBeginMainFrameNotExpected(bool new_state) {
diff --git a/content/test/test_render_view_host.h b/content/test/test_render_view_host.h
index 40be8de51..2605e82 100644
--- a/content/test/test_render_view_host.h
+++ b/content/test/test_render_view_host.h
@@ -131,7 +131,11 @@
   void reset_did_change_compositor_frame_sink() {
     did_change_compositor_frame_sink_ = false;
   }
-
+#if defined(USE_AURA)
+  void ScheduleEmbed(ui::mojom::WindowTreeClientPtr client,
+                     base::OnceCallback<void(const base::UnguessableToken&)>
+                         callback) override {}
+#endif
   // viz::HostFrameSinkClient implementation.
   void OnFirstSurfaceActivation(const viz::SurfaceInfo& surface_info) override;
   void OnFrameTokenChanged(uint32_t frame_token) override;
diff --git a/extensions/browser/guest_view/web_view/web_view_guest.cc b/extensions/browser/guest_view/web_view/web_view_guest.cc
index f5e04fd..82d3d5e 100644
--- a/extensions/browser/guest_view/web_view/web_view_guest.cc
+++ b/extensions/browser/guest_view/web_view/web_view_guest.cc
@@ -33,7 +33,6 @@
 #include "content/public/browser/render_view_host.h"
 #include "content/public/browser/render_widget_host.h"
 #include "content/public/browser/render_widget_host_view.h"
-#include "content/public/browser/resource_request_details.h"
 #include "content/public/browser/site_instance.h"
 #include "content/public/browser/storage_partition.h"
 #include "content/public/browser/web_contents.h"
diff --git a/net/dns/dns_protocol.h b/net/dns/dns_protocol.h
index 1493167..71ed31c 100644
--- a/net/dns/dns_protocol.h
+++ b/net/dns/dns_protocol.h
@@ -119,7 +119,6 @@
 // https://www.iana.org/assignments/dns-parameters/dns-parameters.xhtml#dns-parameters-4
 static const uint16_t kTypeA = 1;
 static const uint16_t kTypeCNAME = 5;
-static const uint16_t kTypeSOA = 6;
 static const uint16_t kTypePTR = 12;
 static const uint16_t kTypeTXT = 16;
 static const uint16_t kTypeAAAA = 28;
diff --git a/net/dns/dns_response.cc b/net/dns/dns_response.cc
index 167bb01..79c1d5c 100644
--- a/net/dns/dns_response.cc
+++ b/net/dns/dns_response.cc
@@ -298,14 +298,6 @@
   DnsRecordParser parser = Parser();
   DnsResourceRecord record;
   unsigned ancount = answer_count();
-  if (rcode() == dns_protocol::kRcodeNXDOMAIN ||
-      (ancount == 0 && rcode() == dns_protocol::kRcodeNOERROR)) {
-    // NXDOMAIN or NODATA case respecively.
-    if (parser.ReadRecord(&record) && record.type == dns_protocol::kTypeSOA) {
-      ttl_sec = std::min(ttl_sec, record.ttl);
-    }
-  }
-
   for (unsigned i = 0; i < ancount; ++i) {
     if (!parser.ReadRecord(&record))
       return DNS_MALFORMED_RESPONSE;
@@ -337,6 +329,8 @@
     }
   }
 
+  // TODO(szym): Extract TTL for NODATA results. http://crbug.com/115051
+
   // getcanonname in eglibc returns the first owner name of an A or AAAA RR.
   // If the response passed all the checks so far, then |expected_name| is it.
   *addr_list = AddressList::CreateFromIPAddressList(ip_addresses,
diff --git a/net/dns/dns_test_util.cc b/net/dns/dns_test_util.cc
index 4ebb589..d043a01 100644
--- a/net/dns/dns_test_util.cc
+++ b/net/dns/dns_test_util.cc
@@ -94,7 +94,6 @@
  private:
   void Finish() {
     switch (result_.type) {
-      case MockDnsClientRule::NODOMAIN:
       case MockDnsClientRule::EMPTY:
       case MockDnsClientRule::OK: {
         std::string qname;
@@ -108,44 +107,34 @@
         dns_protocol::Header* header =
             reinterpret_cast<dns_protocol::Header*>(buffer);
         header->flags |= dns_protocol::kFlagResponse;
-        if (MockDnsClientRule::NODOMAIN == result_.type) {
-          header->flags |= base::HostToNet16(dns_protocol::kRcodeNXDOMAIN);
-        }
 
-        const uint16_t kPointerToQueryName =
-            static_cast<uint16_t>(0xc000 | sizeof(*header));
+        if (MockDnsClientRule::OK == result_.type) {
+          const uint16_t kPointerToQueryName =
+              static_cast<uint16_t>(0xc000 | sizeof(*header));
 
-        const uint32_t kTTL = 86400;  // One day.
+          const uint32_t kTTL = 86400;  // One day.
 
-        // Size of RDATA which is a IPv4 or IPv6 address.
-        if (MockDnsClientRule::OK == result_.type)
+          // Size of RDATA which is a IPv4 or IPv6 address.
           EXPECT_TRUE(result_.ip.IsValid());
-        size_t rdata_size = result_.ip.size();
+          size_t rdata_size = result_.ip.size();
 
-        // 12 is the sum of sizes of the compressed name reference, TYPE,
-        // CLASS, TTL and RDLENGTH.
-        size_t answer_size = 12 + rdata_size;
+          // 12 is the sum of sizes of the compressed name reference, TYPE,
+          // CLASS, TTL and RDLENGTH.
+          size_t answer_size = 12 + rdata_size;
 
-        // Write the answer using the expected IP address.
-        header->ancount =
-            base::HostToNet16(MockDnsClientRule::OK == result_.type ? 1 : 0);
-        base::BigEndianWriter writer(buffer + nbytes, answer_size);
-        writer.WriteU16(kPointerToQueryName);
-        writer.WriteU16(MockDnsClientRule::OK == result_.type
-                            ? qtype_
-                            : dns_protocol::kTypeSOA);
-        writer.WriteU16(dns_protocol::kClassIN);
-        writer.WriteU32(kTTL);
-        writer.WriteU16(static_cast<uint16_t>(rdata_size));
-        writer.WriteBytes(result_.ip.bytes().data(), rdata_size);
-        nbytes += answer_size;
-
-        EXPECT_TRUE(response.InitParse(nbytes, query));
-        if (MockDnsClientRule::NODOMAIN == result_.type) {
-          callback_.Run(this, ERR_NAME_NOT_RESOLVED, &response);
-        } else {
-          callback_.Run(this, OK, &response);
+          // Write the answer using the expected IP address.
+          header->ancount = base::HostToNet16(1);
+          base::BigEndianWriter writer(buffer + nbytes, answer_size);
+          writer.WriteU16(kPointerToQueryName);
+          writer.WriteU16(qtype_);
+          writer.WriteU16(dns_protocol::kClassIN);
+          writer.WriteU32(kTTL);
+          writer.WriteU16(static_cast<uint16_t>(rdata_size));
+          writer.WriteBytes(result_.ip.bytes().data(), rdata_size);
+          nbytes += answer_size;
         }
+        EXPECT_TRUE(response.InitParse(nbytes, query));
+        callback_.Run(this, OK, &response);
       } break;
       case MockDnsClientRule::FAIL:
         callback_.Run(this, ERR_NAME_NOT_RESOLVED, NULL);
diff --git a/net/dns/dns_test_util.h b/net/dns/dns_test_util.h
index e1ca44f..133c33f 100644
--- a/net/dns/dns_test_util.h
+++ b/net/dns/dns_test_util.h
@@ -159,12 +159,11 @@
 
 struct MockDnsClientRule {
   enum ResultType {
-    NODOMAIN,  // Fail asynchronously with ERR_NAME_NOT_RESOLVED and NXDOMAIN.
-    FAIL,      // Fail asynchronously with ERR_NAME_NOT_RESOLVED.
-    TIMEOUT,   // Fail asynchronously with ERR_DNS_TIMEOUT.
-    EMPTY,     // Return an empty response.
-    OK,  // Return an IP address (the accompanying IP is an argument in the
-         // Result structure, or understood as localhost when unspecified).
+    FAIL,     // Fail asynchronously with ERR_NAME_NOT_RESOLVED.
+    TIMEOUT,  // Fail asynchronously with ERR_DNS_TIMEOUT.
+    EMPTY,    // Return an empty response.
+    OK,       // Return an IP address (the accompanying IP is an argument in the
+              // Result structure, or understood as localhost when unspecified).
   };
 
   struct Result {
diff --git a/net/dns/dns_transaction.cc b/net/dns/dns_transaction.cc
index 1cf17a3..42c2d4b 100644
--- a/net/dns/dns_transaction.cc
+++ b/net/dns/dns_transaction.cc
@@ -268,6 +268,7 @@
     }
     if (response_->flags() & dns_protocol::kFlagTC)
       return ERR_DNS_SERVER_REQUIRES_TCP;
+    // TODO(szym): Extract TTL for NXDOMAIN results. http://crbug.com/115051
     if (response_->rcode() == dns_protocol::kRcodeNXDOMAIN)
       return ERR_NAME_NOT_RESOLVED;
     if (response_->rcode() != dns_protocol::kRcodeNOERROR)
@@ -894,7 +895,7 @@
           if (!qnames_.empty())
             qnames_.pop_front();
           if (qnames_.empty()) {
-            return result;
+            return AttemptResult(ERR_NAME_NOT_RESOLVED, NULL);
           } else {
             result = StartQuery();
           }
diff --git a/net/dns/host_resolver_impl.cc b/net/dns/host_resolver_impl.cc
index a4185d5..b9854252 100644
--- a/net/dns/host_resolver_impl.cc
+++ b/net/dns/host_resolver_impl.cc
@@ -1024,8 +1024,6 @@
     StartAAAA();
   }
 
-  base::TimeDelta ttl() { return ttl_; }
-
  private:
   void StartA() {
     DCHECK(!transaction_a_);
@@ -1058,9 +1056,7 @@
                              const DnsResponse* response) {
     DCHECK(transaction);
     base::TimeDelta duration = base::TimeTicks::Now() - start_time;
-
-    if (net_error != OK && !(net_error == ERR_NAME_NOT_RESOLVED && response &&
-                             response->IsValid())) {
+    if (net_error != OK) {
       UMA_HISTOGRAM_LONG_TIMES_100("AsyncDNS.TransactionFailure", duration);
       OnFailure(net_error, DnsResponse::DNS_PARSE_OK);
       return;
@@ -1163,9 +1159,8 @@
     net_log_.EndEvent(
         NetLogEventType::HOST_RESOLVER_IMPL_DNS_TASK,
         base::Bind(&NetLogDnsTaskFailedCallback, net_error, result));
-    delegate_->OnDnsTaskComplete(
-        task_start_time_, net_error, AddressList(),
-        num_completed_transactions_ > 0 ? ttl_ : base::TimeDelta());
+    delegate_->OnDnsTaskComplete(task_start_time_, net_error, AddressList(),
+                                 base::TimeDelta());
   }
 
   void OnSuccess(const AddressList& addr_list) {
@@ -1593,16 +1588,7 @@
       StartProcTask();
     } else {
       UmaAsyncDnsResolveStatus(RESOLVE_STATUS_FAIL);
-      // If the ttl is max, we didn't get one from the record, so set it to 0
-      base::TimeDelta ttl =
-          dns_task->ttl() < base::TimeDelta::FromSeconds(
-                                std::numeric_limits<uint32_t>::max())
-              ? dns_task->ttl()
-              : base::TimeDelta::FromSeconds(0);
-      CompleteRequests(
-          HostCache::Entry(net_error, AddressList(),
-                           HostCache::Entry::Source::SOURCE_UNKNOWN, ttl),
-          ttl);
+      CompleteRequestsWithError(net_error);
     }
   }
 
diff --git a/net/dns/host_resolver_impl_unittest.cc b/net/dns/host_resolver_impl_unittest.cc
index 591bd88..7f557e8 100644
--- a/net/dns/host_resolver_impl_unittest.cc
+++ b/net/dns/host_resolver_impl_unittest.cc
@@ -1652,10 +1652,6 @@
  protected:
   // testing::Test implementation:
   void SetUp() override {
-    AddDnsRule("nodomain", dns_protocol::kTypeA, MockDnsClientRule::NODOMAIN,
-               false);
-    AddDnsRule("nodomain", dns_protocol::kTypeAAAA, MockDnsClientRule::NODOMAIN,
-               false);
     AddDnsRule("nx", dns_protocol::kTypeA, MockDnsClientRule::FAIL, false);
     AddDnsRule("nx", dns_protocol::kTypeAAAA, MockDnsClientRule::FAIL, false);
     AddDnsRule("ok", dns_protocol::kTypeA, MockDnsClientRule::OK, false);
@@ -2692,37 +2688,6 @@
   EXPECT_TRUE(requests_[5]->HasOneAddress("::2", 80));
 }
 
-TEST_F(HostResolverImplDnsTest, NotFoundTTL) {
-  CreateResolver();
-  set_fallback_to_proctask(false);
-  ChangeDnsConfig(CreateValidDnsConfig());
-  // NODATA
-  Request* request = CreateRequest("empty");
-  EXPECT_THAT(request->Resolve(), IsError(ERR_IO_PENDING));
-  EXPECT_THAT(request->WaitForResult(), IsError(ERR_NAME_NOT_RESOLVED));
-  EXPECT_THAT(request->NumberOfAddresses(), 0);
-  HostCache::Key key(request->info().hostname(), ADDRESS_FAMILY_UNSPECIFIED, 0);
-  HostCache::EntryStaleness staleness;
-  const HostCache::Entry* cache_entry =
-      resolver_->GetHostCache()->Lookup(key, base::TimeTicks::Now());
-  EXPECT_TRUE(!!cache_entry);
-  EXPECT_TRUE(cache_entry->has_ttl());
-  EXPECT_THAT(cache_entry->ttl(), base::TimeDelta::FromSeconds(86400));
-
-  // NXDOMAIN
-  request = CreateRequest("nodomain");
-  EXPECT_THAT(request->Resolve(), IsError(ERR_IO_PENDING));
-  EXPECT_THAT(request->WaitForResult(), IsError(ERR_NAME_NOT_RESOLVED));
-  EXPECT_THAT(request->NumberOfAddresses(), 0);
-  HostCache::Key nxkey(request->info().hostname(), ADDRESS_FAMILY_UNSPECIFIED,
-                       0);
-  cache_entry =
-      resolver_->GetHostCache()->Lookup(nxkey, base::TimeTicks::Now());
-  EXPECT_TRUE(!!cache_entry);
-  EXPECT_TRUE(cache_entry->has_ttl());
-  EXPECT_THAT(cache_entry->ttl(), base::TimeDelta::FromSeconds(86400));
-}
-
 TEST_F(HostResolverImplTest, ResolveLocalHostname) {
   AddressList addresses;
 
diff --git a/testing/buildbot/filters/mojo.fyi.network_content_browsertests.filter b/testing/buildbot/filters/mojo.fyi.network_content_browsertests.filter
index e799263..7ebb2ac 100644
--- a/testing/buildbot/filters/mojo.fyi.network_content_browsertests.filter
+++ b/testing/buildbot/filters/mojo.fyi.network_content_browsertests.filter
@@ -104,11 +104,6 @@
 # service process crash.
 -ResourceDispatcherHostBrowserTest.SyncXMLHttpRequest_Cancelled
 
-# http://crbug.com/783981
-# This test should just be removed once we remove
-# WebContentsObserver::DidGetResourceResponseStart.
--WebContentsImplBrowserTest.DidGetResourceResponseStartUpdatesWaitingState
-
 # http://crbug.com/783990
 # Add support for http auth.
 -WorkerFetchTest.SharedWorkerHttpAuth/0
diff --git a/third_party/WebKit/LayoutTests/FlagExpectations/root-layer-scrolls b/third_party/WebKit/LayoutTests/FlagExpectations/root-layer-scrolls
index 0c37942..ed377354 100644
--- a/third_party/WebKit/LayoutTests/FlagExpectations/root-layer-scrolls
+++ b/third_party/WebKit/LayoutTests/FlagExpectations/root-layer-scrolls
@@ -3,7 +3,6 @@
 crbug.com/417782 compositing/squashing/squash-above-fixed-1.html [ Failure ]
 crbug.com/417782 compositing/squashing/squash-above-fixed-3.html [ Failure ]
 crbug.com/417782 compositing/visibility/visibility-image-layers-dynamic.html [ Failure ]
-crbug.com/417782 [ Linux Mac ] fast/dom/horizontal-scrollbar-when-dir-change.html [ Failure ]
 crbug.com/417782 fast/dom/rtl-scroll-to-leftmost-and-resize.html [ Failure ]
 crbug.com/417782 fast/dom/scroll-reveal-left-overflow.html [ Failure ]
 crbug.com/417782 fast/dom/scroll-reveal-top-overflow.html [ Failure ]
diff --git a/third_party/WebKit/Source/core/frame/LocalFrameView.cpp b/third_party/WebKit/Source/core/frame/LocalFrameView.cpp
index 4dd81f6..1e3f35c8 100644
--- a/third_party/WebKit/Source/core/frame/LocalFrameView.cpp
+++ b/third_party/WebKit/Source/core/frame/LocalFrameView.cpp
@@ -749,11 +749,6 @@
     return;
 
   page->GetChromeClient().ContentsSizeChanged(frame_.Get(), size);
-
-  // Ensure the scrollToFragmentAnchor is called before
-  // restoreScrollPositionAndViewState when reload
-  ScrollToFragmentAnchor();
-  GetFrame().Loader().RestoreScrollPositionAndViewState();
 }
 
 void LocalFrameView::AdjustViewSize() {
@@ -2627,7 +2622,10 @@
     scrolling_coordinator->NotifyGeometryChanged(this);
   }
 
+  // If we're restoring a scroll position from history, that takes precedence
+  // over scrolling to the anchor in the URL.
   ScrollToFragmentAnchor();
+  GetFrame().Loader().RestoreScrollPositionAndViewState();
   SendResizeEventIfNeeded();
 }
 
diff --git a/third_party/WebKit/Source/core/paint/PaintLayerScrollableArea.cpp b/third_party/WebKit/Source/core/paint/PaintLayerScrollableArea.cpp
index b2bb849..96904eb 100644
--- a/third_party/WebKit/Source/core/paint/PaintLayerScrollableArea.cpp
+++ b/third_party/WebKit/Source/core/paint/PaintLayerScrollableArea.cpp
@@ -954,6 +954,7 @@
     return;
   }
 
+  UpdateScrollDimensions();
   if (ScrollOriginChanged())
     SetScrollOffsetUnconditionally(ClampScrollOffset(GetScrollOffset()));
   else
diff --git a/third_party/WebKit/Source/devtools/front_end/sources/DebuggerPausedMessage.js b/third_party/WebKit/Source/devtools/front_end/sources/DebuggerPausedMessage.js
index 2452db4..aac5118 100644
--- a/third_party/WebKit/Source/devtools/front_end/sources/DebuggerPausedMessage.js
+++ b/third_party/WebKit/Source/devtools/front_end/sources/DebuggerPausedMessage.js
@@ -19,14 +19,6 @@
   }
 
   /**
-   * @param {string} description
-   */
-  static _descriptionWithoutStack(description) {
-    var firstCallFrame = /^\s+at\s/m.exec(description);
-    return firstCallFrame ? description.substring(0, firstCallFrame.index) : description;
-  }
-
-  /**
    * @param {?SDK.DebuggerPausedDetails} details
    * @param {!Bindings.DebuggerWorkspaceBinding} debuggerWorkspaceBinding
    * @param {!Bindings.BreakpointManager} breakpointManager
@@ -55,13 +47,12 @@
       messageWrapper = buildWrapper(Common.UIString('Paused on XHR or fetch'), details.auxData['url'] || '');
     } else if (details.reason === SDK.DebuggerModel.BreakReason.Exception) {
       var description = details.auxData['description'] || details.auxData['value'] || '';
-      var descriptionWithoutStack = Sources.DebuggerPausedMessage._descriptionWithoutStack(description);
-      messageWrapper = buildWrapper(Common.UIString('Paused on exception'), descriptionWithoutStack, description);
+      var descriptionFirstLine = description.split('\n', 1)[0];
+      messageWrapper = buildWrapper(Common.UIString('Paused on exception'), descriptionFirstLine, description);
     } else if (details.reason === SDK.DebuggerModel.BreakReason.PromiseRejection) {
       var description = details.auxData['description'] || details.auxData['value'] || '';
-      var descriptionWithoutStack = Sources.DebuggerPausedMessage._descriptionWithoutStack(description);
-      messageWrapper =
-          buildWrapper(Common.UIString('Paused on promise rejection'), descriptionWithoutStack, description);
+      var descriptionFirstLine = description.split('\n', 1)[0];
+      messageWrapper = buildWrapper(Common.UIString('Paused on promise rejection'), descriptionFirstLine, description);
     } else if (details.reason === SDK.DebuggerModel.BreakReason.Assert) {
       messageWrapper = buildWrapper(Common.UIString('Paused on assertion'));
     } else if (details.reason === SDK.DebuggerModel.BreakReason.DebugCommand) {
diff --git a/ui/gfx/geometry/rect_f.cc b/ui/gfx/geometry/rect_f.cc
index a08e3847..bb474ba6 100644
--- a/ui/gfx/geometry/rect_f.cc
+++ b/ui/gfx/geometry/rect_f.cc
@@ -5,12 +5,7 @@
 #include "ui/gfx/geometry/rect_f.h"
 
 #include <algorithm>
-
-#if defined(OS_IOS)
-#include <CoreGraphics/CoreGraphics.h>
-#elif defined(OS_MACOSX)
-#include <ApplicationServices/ApplicationServices.h>
-#endif
+#include <limits>
 
 #include "base/logging.h"
 #include "base/strings/stringprintf.h"
@@ -18,6 +13,12 @@
 #include "ui/gfx/geometry/insets_f.h"
 #include "ui/gfx/geometry/safe_integer_conversions.h"
 
+#if defined(OS_IOS)
+#include <CoreGraphics/CoreGraphics.h>
+#elif defined(OS_MACOSX)
+#include <ApplicationServices/ApplicationServices.h>
+#endif
+
 namespace gfx {
 
 static void AdjustAlongAxis(float dst_origin,
@@ -47,8 +48,8 @@
 
 void RectF::Inset(float left, float top, float right, float bottom) {
   origin_ += Vector2dF(left, top);
-  set_width(std::max(width() - left - right, static_cast<float>(0)));
-  set_height(std::max(height() - top - bottom, static_cast<float>(0)));
+  set_width(std::max(width() - left - right, 0.0f));
+  set_height(std::max(height() - top - bottom, 0.0f));
 }
 
 void RectF::Offset(float horizontal, float vertical) {
@@ -71,30 +72,27 @@
 }
 
 bool RectF::operator<(const RectF& other) const {
-  if (origin_ == other.origin_) {
-    if (width() == other.width()) {
-      return height() < other.height();
-    } else {
-      return width() < other.width();
-    }
-  } else {
+  if (origin_ != other.origin_)
     return origin_ < other.origin_;
-  }
+
+  if (width() == other.width())
+    return height() < other.height();
+  return width() < other.width();
 }
 
 bool RectF::Contains(float point_x, float point_y) const {
-  return (point_x >= x()) && (point_x < right()) && (point_y >= y()) &&
-         (point_y < bottom());
+  return point_x >= x() && point_x < right() && point_y >= y() &&
+         point_y < bottom();
 }
 
 bool RectF::Contains(const RectF& rect) const {
-  return (rect.x() >= x() && rect.right() <= right() && rect.y() >= y() &&
-          rect.bottom() <= bottom());
+  return rect.x() >= x() && rect.right() <= right() && rect.y() >= y() &&
+         rect.bottom() <= bottom();
 }
 
 bool RectF::Intersects(const RectF& rect) const {
-  return !(IsEmpty() || rect.IsEmpty() || rect.x() >= right() ||
-           rect.right() <= x() || rect.y() >= bottom() || rect.bottom() <= y());
+  return !IsEmpty() && !rect.IsEmpty() && rect.x() < right() &&
+         rect.right() > x() && rect.y() < bottom() && rect.bottom() > y();
 }
 
 void RectF::Intersect(const RectF& rect) {
@@ -108,8 +106,10 @@
   float rr = std::min(right(), rect.right());
   float rb = std::min(bottom(), rect.bottom());
 
-  if (rx >= rr || ry >= rb)
-    rx = ry = rr = rb = 0;  // non-intersecting
+  if (rx >= rr || ry >= rb) {
+    SetRect(0, 0, 0, 0);
+    return;
+  }
 
   SetRect(rx, ry, rr - rx, rb - ry);
 }
@@ -133,7 +133,7 @@
 void RectF::Subtract(const RectF& rect) {
   if (!Intersects(rect))
     return;
-  if (rect.Contains(*static_cast<const RectF*>(this))) {
+  if (rect.Contains(*this)) {
     SetRect(0, 0, 0, 0);
     return;
   }
@@ -212,7 +212,7 @@
   RectF c(*this);
   c.Union(rect);
 
-  static const float kEpsilon = std::numeric_limits<float>::epsilon();
+  static constexpr float kEpsilon = std::numeric_limits<float>::epsilon();
   float x = std::max(0.f, c.width() - width() - rect.width() + kEpsilon);
   float y = std::max(0.f, c.height() - height() - rect.height() + kEpsilon);
   return x + y;