diff --git a/DEPS b/DEPS
index 3effac4..51829dd42 100644
--- a/DEPS
+++ b/DEPS
@@ -78,7 +78,7 @@
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling Skia
   # and whatever else without interference from each other.
-  'skia_revision': 'e4efc862935af8961568773973be1688c173bcbc',
+  'skia_revision': '7557bbbe19b0d56484fe039171e4d97b75f209b3',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling V8
   # and whatever else without interference from each other.
@@ -134,7 +134,7 @@
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling catapult
   # and whatever else without interference from each other.
-  'catapult_revision': '3b3f9e1e789dbed2726dcd3c97d9dcd080ca7f23',
+  'catapult_revision': '08db5c9b282272f8105fe9fefe453bea0dbed057',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling libFuzzer
   # and whatever else without interference from each other.
@@ -438,7 +438,7 @@
     Var('chromium_git') + '/external/libaddressinput.git' + '@' + 'a575c63de328d0c72237c55d1a05e191c245122a',
 
   'src/third_party/libaom/source/libaom': {
-    'url': Var('aomedia_git') + '/aom.git' + '@' +  'cccda0db727c2282375b174104294b40911d1447',
+    'url': Var('aomedia_git') + '/aom.git' + '@' +  'cc92258a08d98f469dff1be288acbc322632377b',
     'condition': 'checkout_libaom',
   },
 
@@ -643,7 +643,7 @@
     Var('chromium_git') + '/external/khronosgroup/webgl.git' + '@' + 'd458ada06171a85af00367251a4ed55db7fe2018',
 
   'src/third_party/webrtc':
-    Var('webrtc_git') + '/src.git' + '@' + '23f35d99ae2af40e3d366d75fbbdd80aa76b851a', # commit position 20628
+    Var('webrtc_git') + '/src.git' + '@' + 'a102f0f112df264bc9554e271e8549b18d11eec4', # commit position 20628
 
   'src/third_party/xdg-utils': {
       'url': Var('chromium_git') + '/chromium/deps/xdg-utils.git' + '@' + 'd80274d5869b17b8c9067a1022e4416ee7ed5e0d',
diff --git a/cc/tiles/tile_manager_unittest.cc b/cc/tiles/tile_manager_unittest.cc
index f713e67..cfc87e5 100644
--- a/cc/tiles/tile_manager_unittest.cc
+++ b/cc/tiles/tile_manager_unittest.cc
@@ -2952,5 +2952,81 @@
   host_impl()->client()->reset_did_request_impl_side_invalidation();
 }
 
+class VerifyImageProviderRasterBuffer : public RasterBuffer {
+ public:
+  VerifyImageProviderRasterBuffer() = default;
+  ~VerifyImageProviderRasterBuffer() override { EXPECT_TRUE(did_raster_); }
+
+  void Playback(
+      const RasterSource* raster_source,
+      const gfx::Rect& raster_full_rect,
+      const gfx::Rect& raster_dirty_rect,
+      uint64_t new_content_id,
+      const gfx::AxisTransform2d& transform,
+      const RasterSource::PlaybackSettings& playback_settings) override {
+    did_raster_ = true;
+    EXPECT_TRUE(playback_settings.image_provider);
+  }
+
+ private:
+  bool did_raster_ = false;
+};
+
+class VerifyImageProviderRasterBufferProvider
+    : public FakeRasterBufferProviderImpl {
+ public:
+  VerifyImageProviderRasterBufferProvider() = default;
+  ~VerifyImageProviderRasterBufferProvider() override {
+    EXPECT_GT(buffer_count_, 0);
+  }
+
+  std::unique_ptr<RasterBuffer> AcquireBufferForRaster(
+      const Resource* resource,
+      uint64_t resource_content_id,
+      uint64_t previous_content_id) override {
+    buffer_count_++;
+    return std::make_unique<VerifyImageProviderRasterBuffer>();
+  }
+
+ private:
+  int buffer_count_ = 0;
+};
+
+class SynchronousRasterTileManagerTest : public TileManagerTest {
+ public:
+  std::unique_ptr<TaskGraphRunner> CreateTaskGraphRunner() override {
+    return std::make_unique<SynchronousTaskGraphRunner>();
+  }
+};
+
+TEST_F(SynchronousRasterTileManagerTest, AlwaysUseImageCache) {
+  // Tests that we always use the ImageDecodeCache during raster.
+  VerifyImageProviderRasterBufferProvider raster_buffer_provider;
+  host_impl()->tile_manager()->SetRasterBufferProviderForTesting(
+      &raster_buffer_provider);
+
+  gfx::Size layer_bounds(500, 500);
+  scoped_refptr<FakeRasterSource> raster_source =
+      FakeRasterSource::CreateFilled(layer_bounds);
+  Region invalidation((gfx::Rect(layer_bounds)));
+  SetupPendingTree(raster_source, layer_bounds, invalidation);
+  PictureLayerTilingSet* tiling_set =
+      pending_layer()->picture_layer_tiling_set();
+  PictureLayerTiling* pending_tiling = tiling_set->tiling_at(0);
+  pending_tiling->set_resolution(HIGH_RESOLUTION);
+  pending_tiling->CreateAllTilesForTesting();
+  pending_tiling->SetTilePriorityRectsForTesting(
+      gfx::Rect(layer_bounds),   // Visible rect.
+      gfx::Rect(layer_bounds),   // Skewport rect.
+      gfx::Rect(layer_bounds),   // Soon rect.
+      gfx::Rect(layer_bounds));  // Eventually rect.
+
+  host_impl()->tile_manager()->PrepareTiles(host_impl()->global_tile_state());
+  static_cast<SynchronousTaskGraphRunner*>(task_graph_runner())->RunUntilIdle();
+
+  // Destroy the LTHI since it accesses the RasterBufferProvider during cleanup.
+  TakeHostImpl();
+}
+
 }  // namespace
 }  // namespace cc
diff --git a/chrome/VERSION b/chrome/VERSION
index f1e35a64..3a076d3 100644
--- a/chrome/VERSION
+++ b/chrome/VERSION
@@ -1,4 +1,4 @@
 MAJOR=65
 MINOR=0
-BUILD=3303
+BUILD=3304
 PATCH=0
diff --git a/chrome/browser/chromeos/BUILD.gn b/chrome/browser/chromeos/BUILD.gn
index 6a47b37..1f84895 100644
--- a/chrome/browser/chromeos/BUILD.gn
+++ b/chrome/browser/chromeos/BUILD.gn
@@ -1410,10 +1410,6 @@
     "printing/cups_printers_manager.h",
     "printing/external_printers.cc",
     "printing/external_printers.h",
-    "printing/external_printers_factory.cc",
-    "printing/external_printers_factory.h",
-    "printing/external_printers_pref_bridge.cc",
-    "printing/external_printers_pref_bridge.h",
     "printing/ppd_provider_factory.cc",
     "printing/ppd_provider_factory.h",
     "printing/printer_configurer.cc",
diff --git a/chrome/browser/chromeos/arc/arc_session_manager.cc b/chrome/browser/chromeos/arc/arc_session_manager.cc
index 643145e..9521ec9 100644
--- a/chrome/browser/chromeos/arc/arc_session_manager.cc
+++ b/chrome/browser/chromeos/arc/arc_session_manager.cc
@@ -238,7 +238,8 @@
     scoped_opt_in_tracker_->TrackError();
 
   if (result == ProvisioningResult::CHROME_SERVER_COMMUNICATION_ERROR) {
-    if (IsArcKioskMode()) {
+    // TODO(poromov): Consider PublicSession offline mode.
+    if (IsRobotAccountMode()) {
       VLOG(1) << "Robot account auth code fetching error";
       // Log out the user. All the cleanup will be done in Shutdown() method.
       // The callback is not called because auth code is empty.
@@ -280,12 +281,17 @@
     // * In case ARC is enabled from OOBE.
     // * In ARC Kiosk mode, because the only one UI in kiosk mode must be the
     //   kiosk app and device is not needed for opt-in;
+    // * In Public Session mode, because Play Store will be hidden from users
+    //   and only apps configured by policy should be installed.
     // * When ARC is managed and all OptIn preferences are managed/unused, too,
     //   because the whole OptIn flow should happen as seamless as possible for
     //   the user.
+    // For Active Directory users we always show a page notifying them that they
+    // have to authenticate with their identity provider (through SAML) to make
+    // it less weird that a browser window pops up.
     const bool suppress_play_store_app =
         !IsPlayStoreAvailable() || IsArcOptInVerificationDisabled() ||
-        IsArcKioskMode() || oobe_start_ ||
+        IsRobotAccountMode() || oobe_start_ ||
         (IsArcPlayStoreEnabledPreferenceManagedForProfile(profile_) &&
          AreArcAllOptInPreferencesIgnorableForProfile(profile_));
     if (!suppress_play_store_app) {
@@ -395,7 +401,7 @@
   // in typical use case there will be no one nearby the kiosk device, who can
   // do some action to solve the problem be means of UI.
   if (!g_disable_ui_for_testing && !IsArcOptInVerificationDisabled() &&
-      !IsArcKioskMode()) {
+      !IsRobotAccountMode()) {
     DCHECK(!support_host_);
     support_host_ = std::make_unique<ArcSupportHost>(profile_);
     support_host_->SetErrorDelegate(this);
@@ -595,11 +601,12 @@
   // not available, then directly start ARC with skipping Play Store ToS.
   // For Kiosk mode, skip ToS because it is very likely that near the device
   // there will be no one who is eligible to accept them.
-  // If opt-in verification is disabled, skip negotiation, too. This is for
-  // testing purpose.
+  // In Public Session mode ARC should be started silently without user
+  // interaction. If opt-in verification is disabled, skip negotiation, too.
+  // This is for testing purpose.
   const bool start_arc_directly =
-      prefs->GetBoolean(prefs::kArcSignedIn) || !arc::IsPlayStoreAvailable() ||
-      IsArcKioskMode() || IsArcOptInVerificationDisabled();
+      prefs->GetBoolean(prefs::kArcSignedIn) || ShouldArcAlwaysStart() ||
+      IsRobotAccountMode() || IsArcOptInVerificationDisabled();
 
   // When ARC is blocked because of filesystem compatibility, do not proceed
   // to starting ARC nor follow further state transitions.
@@ -690,9 +697,9 @@
   DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
   DCHECK(profile_);
   DCHECK(!terms_of_service_negotiator_);
-  // In Kiosk-mode, Terms of Service negotiation should be skipped.
-  // See also RequestEnableImpl().
-  DCHECK(!IsArcKioskMode());
+  // In Kiosk and Public Session mode, Terms of Service negotiation should be
+  // skipped. See also RequestEnableImpl().
+  DCHECK(!IsRobotAccountMode());
   // If opt-in verification is disabled, Terms of Service negotiation should
   // be skipped, too. See also RequestEnableImpl().
   DCHECK(!IsArcOptInVerificationDisabled());
@@ -858,9 +865,9 @@
   DCHECK(!android_management_checker_);
 
   // Skip Android management check for testing.
-  // We also skip if Android management check for Kiosk mode,
-  // because there are no managed human users for Kiosk exist.
-  if (IsArcOptInVerificationDisabled() || IsArcKioskMode() ||
+  // We also skip if Android management check for Kiosk and Public Session mode,
+  // because there are no managed human users for them exist.
+  if (IsArcOptInVerificationDisabled() || IsRobotAccountMode() ||
       (g_disable_ui_for_testing &&
        !g_enable_check_android_management_for_testing)) {
     return;
diff --git a/chrome/browser/chromeos/arc/arc_util_unittest.cc b/chrome/browser/chromeos/arc/arc_util_unittest.cc
index a6af9eb..4f087d0 100644
--- a/chrome/browser/chromeos/arc/arc_util_unittest.cc
+++ b/chrome/browser/chromeos/arc/arc_util_unittest.cc
@@ -263,7 +263,7 @@
   ScopedLogIn login(GetFakeUserManager(),
                     AccountId::FromUserEmail("public_user@gmail.com"),
                     user_manager::USER_TYPE_PUBLIC_ACCOUNT);
-  EXPECT_FALSE(IsArcAllowedForProfileOnFirstCall(profile()));
+  EXPECT_TRUE(IsArcAllowedForProfile(profile()));
 }
 
 TEST_F(ChromeArcUtilTest, IsArcAllowedForProfile_ActiveDirectoryEnabled) {
@@ -344,7 +344,7 @@
       {"", "--arc-availability=officially-supported"});
   ScopedLogIn login(GetFakeUserManager(),
                     GetFakeUserManager()->GetGuestAccountId());
-  EXPECT_FALSE(IsArcAllowedForProfileOnFirstCall(profile()));
+  EXPECT_TRUE(IsArcAllowedForProfileOnFirstCall(profile()));
 }
 
 // Demo account is interpreted as EphemeralDataUser.
@@ -352,7 +352,7 @@
   base::CommandLine::ForCurrentProcess()->InitFromArgv(
       {"", "--arc-availability=officially-supported"});
   ScopedLogIn login(GetFakeUserManager(), user_manager::DemoAccountId());
-  EXPECT_FALSE(IsArcAllowedForProfileOnFirstCall(profile()));
+  EXPECT_TRUE(IsArcAllowedForProfileOnFirstCall(profile()));
 }
 
 TEST_F(ChromeArcUtilTest, IsArcCompatibleFileSystemUsedForProfile) {
diff --git a/chrome/browser/chromeos/arc/auth/arc_auth_service.cc b/chrome/browser/chromeos/arc/auth/arc_auth_service.cc
index 6dfdd913..113ff2a 100644
--- a/chrome/browser/chromeos/arc/auth/arc_auth_service.cc
+++ b/chrome/browser/chromeos/arc/auth/arc_auth_service.cc
@@ -90,8 +90,8 @@
 }
 
 mojom::ChromeAccountType GetAccountType() {
-  return IsArcKioskMode() ? mojom::ChromeAccountType::ROBOT_ACCOUNT
-                          : mojom::ChromeAccountType::USER_ACCOUNT;
+  return IsRobotAccountMode() ? mojom::ChromeAccountType::ROBOT_ACCOUNT
+                              : mojom::ChromeAccountType::USER_ACCOUNT;
 }
 
 mojom::AccountInfoPtr CreateAccountInfo(bool is_enforced,
@@ -236,8 +236,8 @@
   }
   // For non-AD enrolled devices an auth code is fetched.
   std::unique_ptr<ArcAuthCodeFetcher> auth_code_fetcher;
-  if (IsArcKioskMode()) {
-    // In Kiosk mode, use Robot auth code fetching.
+  if (IsRobotAccountMode()) {
+    // In Kiosk and public session mode, use Robot auth code fetching.
     auth_code_fetcher = std::make_unique<ArcRobotAuthCodeFetcher>();
   } else {
     // Optionally retrieve auth code in silent mode.
diff --git a/chrome/browser/chromeos/login/auth/cryptohome_authenticator_unittest.cc b/chrome/browser/chromeos/login/auth/cryptohome_authenticator_unittest.cc
index a8168a5..fbb3934 100644
--- a/chrome/browser/chromeos/login/auth/cryptohome_authenticator_unittest.cc
+++ b/chrome/browser/chromeos/login/auth/cryptohome_authenticator_unittest.cc
@@ -30,6 +30,7 @@
 #include "chrome/test/base/testing_profile_manager.h"
 #include "chromeos/chromeos_switches.h"
 #include "chromeos/cryptohome/cryptohome_parameters.h"
+#include "chromeos/cryptohome/cryptohome_util.h"
 #include "chromeos/cryptohome/homedir_methods.h"
 #include "chromeos/cryptohome/mock_async_method_caller.h"
 #include "chromeos/cryptohome/system_salt_getter.h"
@@ -316,7 +317,7 @@
 
     // Add the key to the fake.
     cryptohome::AddKeyRequest request;
-    KeyDefinitionToKey(key_definition, request.mutable_key());
+    cryptohome::KeyDefinitionToKey(key_definition, request.mutable_key());
     fake_cryptohome_client_->AddKeyEx(
         cryptohome::Identification(user_context_.GetAccountId()),
         cryptohome::AuthorizationRequest(), request,
diff --git a/chrome/browser/chromeos/login/easy_unlock/easy_unlock_create_keys_operation.cc b/chrome/browser/chromeos/login/easy_unlock/easy_unlock_create_keys_operation.cc
index fede50ad..d288cde 100644
--- a/chrome/browser/chromeos/login/easy_unlock/easy_unlock_create_keys_operation.cc
+++ b/chrome/browser/chromeos/login/easy_unlock/easy_unlock_create_keys_operation.cc
@@ -16,6 +16,7 @@
 #include "base/strings/string_util.h"
 #include "chrome/browser/chromeos/login/easy_unlock/easy_unlock_key_manager.h"
 #include "chrome/browser/chromeos/login/easy_unlock/easy_unlock_types.h"
+#include "chromeos/cryptohome/cryptohome_util.h"
 #include "chromeos/cryptohome/homedir_methods.h"
 #include "chromeos/cryptohome/system_salt_getter.h"
 #include "chromeos/dbus/dbus_thread_manager.h"
@@ -343,7 +344,7 @@
     auth_key->Transform(Key::KEY_TYPE_SALTED_SHA256_TOP_HALF, system_salt);
 
   cryptohome::AddKeyRequest request;
-  KeyDefinitionToKey(key_def, request.mutable_key());
+  cryptohome::KeyDefinitionToKey(key_def, request.mutable_key());
   request.set_clobber_if_exists(true);
   cryptohome::HomedirMethods::GetInstance()->AddKeyEx(
       cryptohome::Identification(user_context_.GetAccountId()),
diff --git a/chrome/browser/chromeos/login/easy_unlock/easy_unlock_remove_keys_operation.cc b/chrome/browser/chromeos/login/easy_unlock/easy_unlock_remove_keys_operation.cc
index d94cad4..3cd5eb2a 100644
--- a/chrome/browser/chromeos/login/easy_unlock/easy_unlock_remove_keys_operation.cc
+++ b/chrome/browser/chromeos/login/easy_unlock/easy_unlock_remove_keys_operation.cc
@@ -6,6 +6,7 @@
 
 #include "base/bind.h"
 #include "chrome/browser/chromeos/login/easy_unlock/easy_unlock_key_manager.h"
+#include "chromeos/cryptohome/cryptohome_util.h"
 #include "chromeos/cryptohome/homedir_methods.h"
 #include "chromeos/cryptohome/system_salt_getter.h"
 #include "google_apis/gaia/gaia_auth_util.h"
diff --git a/chrome/browser/chromeos/printing/external_printers.cc b/chrome/browser/chromeos/printing/external_printers.cc
index 7311b79..1e1b325 100644
--- a/chrome/browser/chromeos/printing/external_printers.cc
+++ b/chrome/browser/chromeos/printing/external_printers.cc
@@ -5,367 +5,229 @@
 #include "chrome/browser/chromeos/printing/external_printers.h"
 
 #include <set>
+#include <utility>
 
-#include "base/feature_list.h"
 #include "base/json/json_reader.h"
 #include "base/memory/ptr_util.h"
 #include "base/memory/weak_ptr.h"
 #include "base/observer_list.h"
 #include "base/sequence_checker.h"
-#include "base/sequenced_task_runner.h"
 #include "base/stl_util.h"
-#include "base/task_runner_util.h"
-#include "base/task_scheduler/post_task.h"
-#include "base/threading/thread_restrictions.h"
 #include "base/values.h"
-#include "chrome/common/chrome_features.h"
 #include "chromeos/printing/printer_translator.h"
 
 namespace chromeos {
-
 namespace {
 
 constexpr int kMaxRecords = 20000;
 
-using PrinterCache = std::vector<std::unique_ptr<Printer>>;
-using PrinterView = std::map<const std::string, const Printer>;
-
-// Parses |data|, a JSON blob, into a vector of Printers.  If |data| cannot be
-// parsed, returns nullptr.  This is run off the UI thread as it could be very
-// slow.
-std::unique_ptr<PrinterCache> ParsePrinters(std::unique_ptr<std::string> data) {
-  int error_code = 0;
-  int error_line = 0;
-
-  // This could be really slow.
-  base::AssertBlockingAllowed();
-  std::unique_ptr<base::Value> json_blob = base::JSONReader::ReadAndReturnError(
-      *data, base::JSONParserOptions::JSON_PARSE_RFC, &error_code,
-      nullptr /* error_msg_out */, &error_line);
-  // It's not valid JSON.  Give up.
-  if (!json_blob || !json_blob->is_list()) {
-    LOG(WARNING) << "Failed to parse printers policy (" << error_code
-                 << ") on line " << error_line;
-    return nullptr;
-  }
-
-  const base::Value::ListStorage& printer_list = json_blob->GetList();
-  if (printer_list.size() > kMaxRecords) {
-    LOG(WARNING) << "Too many records in printers policy: "
-                 << printer_list.size();
-    return nullptr;
-  }
-
-  auto parsed_printers = std::make_unique<PrinterCache>();
-  parsed_printers->reserve(printer_list.size());
-  for (const base::Value& val : printer_list) {
-    // TODO(skau): Convert to the new Value APIs.
-    const base::DictionaryValue* printer_dict;
-    if (!val.GetAsDictionary(&printer_dict)) {
-      LOG(WARNING) << "Entry in printers policy skipped.  Not a dictionary.";
-      continue;
-    }
-
-    auto printer = RecommendedPrinterToPrinter(*printer_dict);
-    if (!printer) {
-      LOG(WARNING) << "Failed to parse printer configuration.  Skipped.";
-      continue;
-    }
-    parsed_printers->push_back(std::move(printer));
-  }
-
-  return parsed_printers;
-}
-
-// Computes the effective printer list using the access mode and
-// blacklist/whitelist.  Methods are required to be sequenced.  This object is
-// the owner of all the policy data.
-class Restrictions {
+class ExternalPrintersImpl : public ExternalPrinters {
  public:
-  Restrictions() : printers_cache_(nullptr) {
-    DETACH_FROM_SEQUENCE(sequence_checker_);
-  }
-  ~Restrictions() { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); }
+  ExternalPrintersImpl() = default;
+  ~ExternalPrintersImpl() override = default;
 
-  // Sets the printer cache using the policy blob |data|.  If the policy can be
-  // computed, returns the computed list.  Otherwise, nullptr.
-  std::unique_ptr<PrinterView> SetData(std::unique_ptr<std::string> data) {
+  // Resets the printer state fields.
+  void ClearData() override {
     DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
-    base::AssertBlockingAllowed();
-    printers_cache_ = ParsePrinters(std::move(data));
-    return ComputePrinters();
+    bool notify = !printers_.empty();
+    policy_retrieved_ = false;
+    printers_ready_ = false;
+
+    // Swap with empty vectors to release the allocated memory.
+    std::vector<Printer> empty;
+    printers_.swap(empty);
+    std::vector<std::unique_ptr<Printer>> empty_ptrs;
+    all_printers_.swap(empty_ptrs);
+
+    if (notify) {
+      Notify();
+    }
   }
 
-  // Clear the printer cache.  Computed lists will be invalid until we receive
-  // new data.
-  void ClearData() {
+  void SetData(std::unique_ptr<std::string> data) override {
     DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
-    printers_cache_.reset();
+
+    int error_code;
+    int error_line;
+    std::unique_ptr<base::Value> json_blob =
+        base::JSONReader::ReadAndReturnError(
+            *data, base::JSONParserOptions::JSON_PARSE_RFC, &error_code,
+            nullptr /* error_msg_out */, &error_line);
+    // It's not valid JSON.  Invalidate config.
+    if (!json_blob || !json_blob->is_list()) {
+      LOG(WARNING) << "Failed to parse external policy (" << error_code
+                   << ") on line " << error_line;
+      ClearData();
+      return;
+    }
+
+    const base::Value::ListStorage& printer_list = json_blob->GetList();
+    if (printer_list.size() > kMaxRecords) {
+      LOG(ERROR) << "Too many records: " << printer_list.size();
+      ClearData();
+      return;
+    }
+
+    for (const base::Value& val : printer_list) {
+      // TODO(skau): Convert to the new Value APIs.
+      const base::DictionaryValue* printer_dict;
+      if (!val.GetAsDictionary(&printer_dict)) {
+        LOG(WARNING) << "Entry is not a dictionary.";
+        continue;
+      }
+
+      auto printer = RecommendedPrinterToPrinter(*printer_dict);
+      if (!printer) {
+        LOG(WARNING) << "Failed to parse printer configuration.";
+        continue;
+      }
+      all_printers_.push_back(std::move(printer));
+    }
+
+    policy_retrieved_ = true;
+    RecomputePrinters();
   }
 
-  // Sets the access mode to |mode|.  If the policy can be computed, returns the
-  // computed list.  Otherwise, nullptr.
-  std::unique_ptr<PrinterView> UpdateAccessMode(
-      ExternalPrinters::AccessMode mode) {
+  void AddObserver(Observer* observer) override {
+    observers_.AddObserver(observer);
+  }
+
+  void RemoveObserver(Observer* observer) override {
+    observers_.RemoveObserver(observer);
+  }
+
+  void SetAccessMode(AccessMode mode) override {
     DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
     mode_ = mode;
-    return ComputePrinters();
+    RecomputePrinters();
   }
 
-  // Sets the blacklist to |blacklist|.  If the policy can be computed, returns
-  // the computed list. Otherwise, nullptr.
-  std::unique_ptr<PrinterView> UpdateBlacklist(
-      const std::vector<std::string>& blacklist) {
+  void SetBlacklist(const std::vector<std::string>& blacklist) override {
     DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+    blacklist_.clear();
+    blacklist_.insert(blacklist.begin(), blacklist.end());
     has_blacklist_ = true;
-    blacklist_ = std::set<std::string>(blacklist.begin(), blacklist.end());
-    return ComputePrinters();
+    RecomputePrinters();
   }
 
-  // Sets the whitelist to |whitelist|.  If the policy can be computed, returns
-  // the computed list.  Otherwise, nullptr.
-  std::unique_ptr<PrinterView> UpdateWhitelist(
-      const std::vector<std::string>& whitelist) {
+  void SetWhitelist(const std::vector<std::string>& whitelist) override {
     DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+    whitelist_.clear();
+    whitelist_.insert(whitelist.begin(), whitelist.end());
     has_whitelist_ = true;
-    whitelist_ = std::set<std::string>(whitelist.begin(), whitelist.end());
-    return ComputePrinters();
+    RecomputePrinters();
+  }
+
+  // Returns true if the printer configuration has been downloaded and parsed.
+  bool IsPolicySet() const override {
+    DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+    return printers_ready_;
+  }
+
+  // Returns all the printers available from the policy.
+  const std::vector<Printer>& GetPrinters() const override {
+    DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+    return printers_;
   }
 
  private:
-  // Returns true if we have enough data to compute the effective printer list.
+  // Returns true if all required attributes have been set to compute the list
+  // of printers.
   bool IsReady() const {
-    DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
-    if (!printers_cache_) {
+    if (!policy_retrieved_) {
       return false;
     }
 
     switch (mode_) {
-      case ExternalPrinters::AccessMode::ALL_ACCESS:
+      case AccessMode::ALL_ACCESS:
         return true;
-      case ExternalPrinters::AccessMode::BLACKLIST_ONLY:
+      case AccessMode::BLACKLIST_ONLY:
         return has_blacklist_;
-      case ExternalPrinters::AccessMode::WHITELIST_ONLY:
+      case AccessMode::WHITELIST_ONLY:
         return has_whitelist_;
-      case ExternalPrinters::AccessMode::UNSET:
+      case AccessMode::UNSET:
         return false;
     }
     NOTREACHED();
     return false;
   }
 
-  // Returns the effective printer list based on |mode_| from the entries in
-  // |printers_cache_|.
-  std::unique_ptr<PrinterView> ComputePrinters() {
-    DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
-
+  void RecomputePrinters() {
+    // Assume we're not ready.
+    printers_ready_ = false;
     if (!IsReady()) {
-      return nullptr;
+      return;
     }
 
-    auto view = std::make_unique<PrinterView>();
+    // Drop all printers, we're recomputing.
+    printers_.clear();
     switch (mode_) {
-      case ExternalPrinters::UNSET:
+      case UNSET:
         NOTREACHED();
         break;
-      case ExternalPrinters::WHITELIST_ONLY:
-        for (const auto& printer : *printers_cache_) {
+      case WHITELIST_ONLY:
+        for (const auto& printer : all_printers_) {
           if (base::ContainsKey(whitelist_, printer->id())) {
-            view->insert({printer->id(), *printer});
+            printers_.push_back(*printer);
           }
         }
         break;
-      case ExternalPrinters::BLACKLIST_ONLY:
-        for (const auto& printer : *printers_cache_) {
+      case BLACKLIST_ONLY:
+        for (const auto& printer : all_printers_) {
           if (!base::ContainsKey(blacklist_, printer->id())) {
-            view->insert({printer->id(), *printer});
+            printers_.push_back(*printer);
           }
         }
         break;
-      case ExternalPrinters::ALL_ACCESS:
-        for (const auto& printer : *printers_cache_) {
-          view->insert({printer->id(), *printer});
+      case ALL_ACCESS:
+        for (const auto& printer : all_printers_) {
+          printers_.push_back(*printer);
         }
         break;
     }
 
-    return view;
+    // Everything has been computed.  Results are ready.
+    printers_ready_ = true;
+
+    // We assume something changed.  Notify now.
+    Notify();
   }
 
-  // Cache of the parsed printer configuration file.
-  std::unique_ptr<PrinterCache> printers_cache_;
+  void Notify() {
+    DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+    for (auto& observer : observers_) {
+      observer.OnPrintersChanged();
+    }
+  }
 
-  // The type of restriction which is enforced.
-  ExternalPrinters::AccessMode mode_ = ExternalPrinters::UNSET;
-  // The list of ids which should not appear in the final list.
+  // True if all necessary information has been set to compute the set of
+  // printers.
+  bool printers_ready_ = false;
+  // Only true after the external policy has been downloaded.
+  bool policy_retrieved_ = false;
+
+  AccessMode mode_ = UNSET;
   bool has_blacklist_ = false;
   std::set<std::string> blacklist_;
-  // The list of the only ids which should appear in the final list.
   bool has_whitelist_ = false;
   std::set<std::string> whitelist_;
 
-  SEQUENCE_CHECKER(sequence_checker_);
-  DISALLOW_COPY_AND_ASSIGN(Restrictions);
-};
-
-class ExternalPrintersImpl : public ExternalPrinters {
- public:
-  ExternalPrintersImpl()
-      : restrictions_(std::make_unique<Restrictions>()),
-        restrictions_runner_(base::CreateSequencedTaskRunnerWithTraits(
-            {base::TaskPriority::BACKGROUND, base::MayBlock(),
-             base::TaskShutdownBehavior::SKIP_ON_SHUTDOWN})),
-        weak_ptr_factory_(this) {}
-  ~ExternalPrintersImpl() override {
-    bool success =
-        restrictions_runner_->DeleteSoon(FROM_HERE, std::move(restrictions_));
-    if (!success) {
-      LOG(WARNING) << "Unable to schedule deletion of policy object.";
-    }
-  }
-
-  void AddObserver(Observer* observer) override {
-    DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
-    observers_.AddObserver(observer);
-  }
-
-  void RemoveObserver(Observer* observer) override {
-    DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
-    observers_.RemoveObserver(observer);
-  }
-
-  // Resets the printer state fields.
-  void ClearData() override {
-    DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
-    if (!base::FeatureList::IsEnabled(features::kBulkPrinters)) {
-      return;
-    }
-
-    // Update restrictions then clear our local cache on return so we don't get
-    // out of sequence.
-    restrictions_runner_->PostTaskAndReply(
-        FROM_HERE,
-        base::BindOnce(&Restrictions::ClearData,
-                       base::Unretained(restrictions_.get())),
-        base::BindOnce(&ExternalPrintersImpl::OnComputationComplete,
-                       weak_ptr_factory_.GetWeakPtr(), nullptr));
-  }
-
-  void SetData(std::unique_ptr<std::string> data) override {
-    DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
-    if (!base::FeatureList::IsEnabled(features::kBulkPrinters)) {
-      return;
-    }
-
-    if (!data) {
-      LOG(WARNING) << "Received null data";
-      return;
-    }
-
-    // Forward data to Restrictions for computation.
-    base::PostTaskAndReplyWithResult(
-        restrictions_runner_.get(), FROM_HERE,
-        base::BindOnce(&Restrictions::SetData,
-                       base::Unretained(restrictions_.get()), std::move(data)),
-        base::BindOnce(&ExternalPrintersImpl::OnComputationComplete,
-                       weak_ptr_factory_.GetWeakPtr()));
-  }
-
-  void SetAccessMode(AccessMode mode) override {
-    DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
-    base::PostTaskAndReplyWithResult(
-        restrictions_runner_.get(), FROM_HERE,
-        base::BindOnce(&Restrictions::UpdateAccessMode,
-                       base::Unretained(restrictions_.get()), mode),
-        base::BindOnce(&ExternalPrintersImpl::OnComputationComplete,
-                       weak_ptr_factory_.GetWeakPtr()));
-  }
-
-  void SetBlacklist(const std::vector<std::string>& blacklist) override {
-    DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
-    base::PostTaskAndReplyWithResult(
-        restrictions_runner_.get(), FROM_HERE,
-        base::BindOnce(&Restrictions::UpdateBlacklist,
-                       base::Unretained(restrictions_.get()), blacklist),
-        base::BindOnce(&ExternalPrintersImpl::OnComputationComplete,
-                       weak_ptr_factory_.GetWeakPtr()));
-  }
-
-  void SetWhitelist(const std::vector<std::string>& whitelist) override {
-    DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
-    base::PostTaskAndReplyWithResult(
-        restrictions_runner_.get(), FROM_HERE,
-        base::BindOnce(&Restrictions::UpdateWhitelist,
-                       base::Unretained(restrictions_.get()), whitelist),
-        base::BindOnce(&ExternalPrintersImpl::OnComputationComplete,
-                       weak_ptr_factory_.GetWeakPtr()));
-  }
-
-  bool IsPolicySet() const override {
-    DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
-    return received_data_;
-  }
-
-  const std::map<const std::string, const Printer>& GetPrinters()
-      const override {
-    DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
-    return printers_;
-  }
-
- private:
-  // Called on computation completion.  |view| is the computed printers which a
-  // user should be able to see.  If |view| is nullptr, it's taken to mean that
-  // the list is now invalid and will be cleared.
-  void OnComputationComplete(std::unique_ptr<PrinterView> view) {
-    DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
-    bool valid;
-    if (!view) {
-      // Printers are dropped if parsing failed.  We can no longer determine
-      // what the domain owner wanted.
-      printers_.clear();
-      valid = false;
-    } else {
-      printers_.swap(*view);
-      valid = true;
-    }
-
-    // Maybe notify that the computed list has changed.
-    // Do not notify for invalid->invalid transitions
-    if (!valid && !received_data_) {
-      return;
-    }
-
-    received_data_ = valid;
-    for (auto& observer : observers_) {
-      // We rely on the assumption that this is sequenced with the rest of our
-      // code to guarantee that printers_ remains valid.
-      observer.OnPrintersChanged(received_data_, printers_);
-    }
-  }
-
-  // Holds the blacklist and whitelist.  Computes the effective printer list.
-  std::unique_ptr<Restrictions> restrictions_;
-  // Off UI sequence for computing the printer view.
-  scoped_refptr<base::SequencedTaskRunner> restrictions_runner_;
-
-  // True if printers_ is based on a current policy.
-  bool received_data_ = false;
+  // Cache of the parsed printer configuration file.
+  std::vector<std::unique_ptr<Printer>> all_printers_;
   // The computed set of printers.
-  PrinterView printers_;
+  std::vector<Printer> printers_;
 
   base::ObserverList<ExternalPrinters::Observer> observers_;
 
   SEQUENCE_CHECKER(sequence_checker_);
-  base::WeakPtrFactory<ExternalPrintersImpl> weak_ptr_factory_;
 
   DISALLOW_COPY_AND_ASSIGN(ExternalPrintersImpl);
 };
-
 }  // namespace
 
 // static
 std::unique_ptr<ExternalPrinters> ExternalPrinters::Create() {
-  return std::make_unique<ExternalPrintersImpl>();
+  return base::MakeUnique<ExternalPrintersImpl>();
 }
 
 }  // namespace chromeos
diff --git a/chrome/browser/chromeos/printing/external_printers.h b/chrome/browser/chromeos/printing/external_printers.h
index a180fbd..e7a6033 100644
--- a/chrome/browser/chromeos/printing/external_printers.h
+++ b/chrome/browser/chromeos/printing/external_printers.h
@@ -5,30 +5,30 @@
 #ifndef CHROME_BROWSER_CHROMEOS_PRINTING_EXTERNAL_PRINTERS_H_
 #define CHROME_BROWSER_CHROMEOS_PRINTING_EXTERNAL_PRINTERS_H_
 
-#include <map>
 #include <memory>
 #include <string>
 #include <utility>
 #include <vector>
 
-#include "chromeos/chromeos_export.h"
+#include "base/macros.h"
+#include "chrome/browser/chromeos/policy/cloud_external_data_policy_observer.h"
 #include "chromeos/printing/printer_configuration.h"
 
 namespace chromeos {
 
 // Manages download and parsing of the external policy printer configuration and
 // enforces restrictions.
-class CHROMEOS_EXPORT ExternalPrinters {
+class ExternalPrinters {
  public:
   // Choose the policy for printer access.
   enum AccessMode {
-    UNSET = -1,
+    UNSET,
     // Printers in the blacklist are disallowed.  Others are allowed.
-    BLACKLIST_ONLY = 0,
+    BLACKLIST_ONLY,
     // Only printers in the whitelist are allowed.
-    WHITELIST_ONLY = 1,
+    WHITELIST_ONLY,
     // All printers in the policy are allowed.
-    ALL_ACCESS = 2
+    ALL_ACCESS
   };
 
   // Observer is notified when the computed set of printers change.  It is
@@ -36,12 +36,8 @@
   // observing.
   class Observer {
    public:
-    // Called when the printers have changed and should be queried.  |valid| is
-    // true if |printers| is based on a valid policy.  |printers| are the
-    // printers that should be available to the user.
-    virtual void OnPrintersChanged(
-        bool valid,
-        const std::map<const std::string, const Printer>& printers) = 0;
+    // Called when the computed set of printers changes.
+    virtual void OnPrintersChanged() = 0;
   };
 
   // Creates a handler for the external printer policies.
@@ -49,35 +45,24 @@
 
   virtual ~ExternalPrinters() = default;
 
-  virtual void AddObserver(Observer* observer) = 0;
-  virtual void RemoveObserver(Observer* observer) = 0;
-
   // Parses |data| which is the contents of the bulk printes file and extracts
   // printer information.  The file format is assumed to be JSON.
   virtual void SetData(std::unique_ptr<std::string> data) = 0;
   // Removes all printer data and invalidates the configuration.
   virtual void ClearData() = 0;
 
-  // Set the access mode which chooses the type of filtering that is performed.
+  virtual void AddObserver(Observer* observer) = 0;
+  virtual void RemoveObserver(Observer* observer) = 0;
+
   virtual void SetAccessMode(AccessMode mode) = 0;
-  // Set the |blacklist| which excludes printers with the given id if access
-  // mode is BLACKLIST_ONLY.
   virtual void SetBlacklist(const std::vector<std::string>& blacklist) = 0;
-  // Set the |whitelist| which is the complete list of printers that are show to
-  // the user.  This is in effect if access mode is WHITELIST_ONLY.
   virtual void SetWhitelist(const std::vector<std::string>& whitelist) = 0;
 
-  // Returns true if the printer map has been computed from a valid policy.
-  // Returns false otherwise.  This is computed asynchronously.  Observe
-  // OnPrintersChanged() to be notified when it is updated.  This may never
-  // become true if a user does not have the appropriate printer policies.
+  // Returns true if the printer configuration has been downloaded and parsed.
   virtual bool IsPolicySet() const = 0;
 
-  // Returns a refernce to a map of the computed set of printers.  The map is
-  // empty if either the policy was empty or we are yet to receive the full
-  // policy. Use IsPolicySet() to differentiate betweeen the two.
-  virtual const std::map<const std::string, const Printer>& GetPrinters()
-      const = 0;
+  // Returns all the printers available from the policy.
+  virtual const std::vector<Printer>& GetPrinters() const = 0;
 };
 
 }  // namespace chromeos
diff --git a/chrome/browser/chromeos/printing/external_printers_factory.cc b/chrome/browser/chromeos/printing/external_printers_factory.cc
deleted file mode 100644
index f4daea0..0000000
--- a/chrome/browser/chromeos/printing/external_printers_factory.cc
+++ /dev/null
@@ -1,64 +0,0 @@
-// Copyright 2017 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "chrome/browser/chromeos/printing/external_printers_factory.h"
-
-#include <memory>
-
-#include "base/lazy_instance.h"
-#include "chrome/browser/chromeos/printing/external_printers.h"
-#include "chrome/browser/chromeos/profiles/profile_helper.h"
-#include "chrome/browser/profiles/profile.h"
-#include "components/user_manager/user.h"
-
-namespace chromeos {
-
-namespace {
-
-base::LazyInstance<ExternalPrintersFactory>::DestructorAtExit
-    g_printers_factory = LAZY_INSTANCE_INITIALIZER;
-
-}  // namespace
-
-// static
-ExternalPrintersFactory* ExternalPrintersFactory::Get() {
-  return g_printers_factory.Pointer();
-}
-
-ExternalPrinters* ExternalPrintersFactory::GetForAccountId(
-    const AccountId& account_id) {
-  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
-  auto found = printers_by_user_.find(account_id);
-  if (found != printers_by_user_.end()) {
-    return found->second.get();
-  }
-
-  printers_by_user_[account_id] = ExternalPrinters::Create();
-  return printers_by_user_[account_id].get();
-}
-
-ExternalPrinters* ExternalPrintersFactory::GetForProfile(Profile* profile) {
-  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
-  const user_manager::User* user =
-      ProfileHelper::Get()->GetUserByProfile(profile);
-  if (!user)
-    return nullptr;
-
-  return GetForAccountId(user->GetAccountId());
-}
-
-void ExternalPrintersFactory::RemoveForUserId(const AccountId& account_id) {
-  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
-  printers_by_user_.erase(account_id);
-}
-
-void ExternalPrintersFactory::Shutdown() {
-  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
-  printers_by_user_.clear();
-}
-
-ExternalPrintersFactory::ExternalPrintersFactory() = default;
-ExternalPrintersFactory::~ExternalPrintersFactory() = default;
-
-}  // namespace chromeos
diff --git a/chrome/browser/chromeos/printing/external_printers_factory.h b/chrome/browser/chromeos/printing/external_printers_factory.h
deleted file mode 100644
index b546bd4..0000000
--- a/chrome/browser/chromeos/printing/external_printers_factory.h
+++ /dev/null
@@ -1,58 +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 CHROME_BROWSER_CHROMEOS_PRINTING_EXTERNAL_PRINTERS_FACTORY_H_
-#define CHROME_BROWSER_CHROMEOS_PRINTING_EXTERNAL_PRINTERS_FACTORY_H_
-
-#include <map>
-#include <memory>
-
-#include "base/lazy_instance.h"
-#include "base/macros.h"
-#include "base/sequence_checker.h"
-#include "chrome/browser/chromeos/printing/external_printers.h"
-#include "components/signin/core/account_id/account_id.h"
-
-class Profile;
-
-namespace chromeos {
-
-// Dispenses ExternalPrinters objects based on account id.  Access to this
-// object should be sequenced.
-class ExternalPrintersFactory {
- public:
-  static ExternalPrintersFactory* Get();
-
-  // Returns a pointer to the ExternalPrinters registered for |account_id|. If
-  // an ExternalPrinters does not exist, one will be created for |account_id|.
-  // The returned object remains valid until RemoveForUserId or Shutdown is
-  // called.
-  ExternalPrinters* GetForAccountId(const AccountId& account_id);
-
-  // Returns a pointer to the ExternalPrinters registered for |profile| which
-  // could be null if |profile| does not map to a valid AccountId. The returned
-  // object remains valid until RemoveForUserId or Shutdown is called.
-  ExternalPrinters* GetForProfile(Profile* profile);
-
-  // Deletes the ExternalPrinters registered for |account_id|.
-  void RemoveForUserId(const AccountId& account_id);
-
-  // Tear down all ExternalPrinters.
-  void Shutdown();
-
- private:
-  friend struct base::LazyInstanceTraitsBase<ExternalPrintersFactory>;
-
-  ExternalPrintersFactory();
-  ~ExternalPrintersFactory();
-
-  std::map<AccountId, std::unique_ptr<ExternalPrinters>> printers_by_user_;
-  SEQUENCE_CHECKER(sequence_checker_);
-
-  DISALLOW_COPY_AND_ASSIGN(ExternalPrintersFactory);
-};
-
-}  // namespace chromeos
-
-#endif  // CHROME_BROWSER_CHROMEOS_PRINTING_EXTERNAL_PRINTERS_FACTORY_H_
diff --git a/chrome/browser/chromeos/printing/external_printers_pref_bridge.cc b/chrome/browser/chromeos/printing/external_printers_pref_bridge.cc
deleted file mode 100644
index ebc6fe8a..0000000
--- a/chrome/browser/chromeos/printing/external_printers_pref_bridge.cc
+++ /dev/null
@@ -1,108 +0,0 @@
-// Copyright 2016 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "chrome/browser/chromeos/printing/external_printers_pref_bridge.h"
-
-#include <string>
-#include <vector>
-
-#include "base/values.h"
-#include "chrome/browser/chromeos/printing/external_printers.h"
-#include "chrome/browser/chromeos/printing/external_printers_factory.h"
-#include "chrome/browser/profiles/profile.h"
-#include "chrome/common/pref_names.h"
-#include "components/policy/policy_constants.h"
-#include "components/pref_registry/pref_registry_syncable.h"
-#include "components/prefs/pref_service.h"
-
-namespace chromeos {
-
-namespace {
-
-// Extracts the list of strings named |policy_name| from |prefs| and returns it.
-std::vector<std::string> FromPrefs(const PrefService* prefs,
-                                   const std::string& policy_name) {
-  std::vector<std::string> string_list;
-  const base::ListValue* list = prefs->GetList(policy_name);
-  for (const base::Value& value : *list) {
-    if (value.is_string()) {
-      string_list.push_back(value.GetString());
-    }
-  }
-
-  return string_list;
-}
-
-}  // namespace
-
-// static
-void ExternalPrintersPrefBridge::RegisterProfilePrefs(
-    user_prefs::PrefRegistrySyncable* registry,
-    const ExternalPrinterPolicies& policies) {
-  // Default value for access mode is blacklist.
-  registry->RegisterIntegerPref(policies.access_mode,
-                                ExternalPrinters::BLACKLIST_ONLY);
-  registry->RegisterListPref(policies.blacklist);
-  registry->RegisterListPref(policies.whitelist);
-}
-
-ExternalPrintersPrefBridge::ExternalPrintersPrefBridge(
-    const ExternalPrinterPolicies& policies,
-    Profile* profile)
-    : profile_(profile), policies_(policies) {
-  pref_change_registrar_.Init(profile_->GetPrefs());
-
-  pref_change_registrar_.Add(
-      policies_.access_mode,
-      base::BindRepeating(&ExternalPrintersPrefBridge::AccessModeUpdated,
-                          base::Unretained(this)));
-  pref_change_registrar_.Add(
-      policies_.blacklist,
-      base::BindRepeating(&ExternalPrintersPrefBridge::BlacklistUpdated,
-                          base::Unretained(this)));
-  pref_change_registrar_.Add(
-      policies_.whitelist,
-      base::BindRepeating(&ExternalPrintersPrefBridge::WhitelistUpdated,
-                          base::Unretained(this)));
-  Initialize();
-}
-
-void ExternalPrintersPrefBridge::Initialize() {
-  BlacklistUpdated();
-  WhitelistUpdated();
-  AccessModeUpdated();
-}
-
-void ExternalPrintersPrefBridge::AccessModeUpdated() {
-  const PrefService* prefs = profile_->GetPrefs();
-  ExternalPrinters::AccessMode mode = ExternalPrinters::UNSET;
-  int mode_val = prefs->GetInteger(policies_.access_mode);
-  if (mode_val >= ExternalPrinters::BLACKLIST_ONLY &&
-      mode_val <= ExternalPrinters::ALL_ACCESS) {
-    mode = static_cast<ExternalPrinters::AccessMode>(mode_val);
-  } else {
-    LOG(ERROR) << "Unrecognized access mode";
-    return;
-  }
-
-  auto* printers = ExternalPrintersFactory::Get()->GetForProfile(profile_);
-  if (printers)
-    printers->SetAccessMode(mode);
-}
-
-void ExternalPrintersPrefBridge::BlacklistUpdated() {
-  auto* printers = ExternalPrintersFactory::Get()->GetForProfile(profile_);
-  if (printers)
-    printers->SetBlacklist(
-        FromPrefs(profile_->GetPrefs(), policies_.blacklist));
-}
-
-void ExternalPrintersPrefBridge::WhitelistUpdated() {
-  auto* printers = ExternalPrintersFactory::Get()->GetForProfile(profile_);
-  if (printers)
-    printers->SetWhitelist(
-        FromPrefs(profile_->GetPrefs(), policies_.whitelist));
-}
-
-}  // namespace chromeos
diff --git a/chrome/browser/chromeos/printing/external_printers_pref_bridge.h b/chrome/browser/chromeos/printing/external_printers_pref_bridge.h
deleted file mode 100644
index 656c2a9..0000000
--- a/chrome/browser/chromeos/printing/external_printers_pref_bridge.h
+++ /dev/null
@@ -1,61 +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 CHROME_BROWSER_CHROMEOS_PRINTING_EXTERNAL_PRINTERS_PREF_BRIDGE_H_
-#define CHROME_BROWSER_CHROMEOS_PRINTING_EXTERNAL_PRINTERS_PREF_BRIDGE_H_
-
-#include <string>
-
-#include "base/macros.h"
-#include "components/prefs/pref_change_registrar.h"
-
-class Profile;
-
-namespace user_prefs {
-class PrefRegistrySyncable;
-}
-
-namespace chromeos {
-
-class ExternalPrinters;
-
-// A collection of preference names representing the external printer fields.
-struct ExternalPrinterPolicies {
-  std::string access_mode;
-  std::string blacklist;
-  std::string whitelist;
-};
-
-// Observe preference changes and propogate changes to ExternalPrinters.
-class ExternalPrintersPrefBridge {
- public:
-  static void RegisterProfilePrefs(user_prefs::PrefRegistrySyncable* registry,
-                                   const ExternalPrinterPolicies& policies);
-
-  ExternalPrintersPrefBridge(const ExternalPrinterPolicies& policies,
-                             Profile* profile);
-
- private:
-  // Retrieve initial values for preferences.
-  void Initialize();
-
-  // Handle update for the access mode policy.
-  void AccessModeUpdated();
-
-  // Handle updates for the blacklist policy.
-  void BlacklistUpdated();
-
-  // Handle updates for the whitelist policy.
-  void WhitelistUpdated();
-
-  Profile* profile_;
-  const ExternalPrinterPolicies policies_;
-  PrefChangeRegistrar pref_change_registrar_;
-
-  DISALLOW_COPY_AND_ASSIGN(ExternalPrintersPrefBridge);
-};
-
-}  // namespace chromeos
-
-#endif  // CHROME_BROWSER_CHROMEOS_PRINTING_EXTERNAL_PRINTERS_PREF_BRIDGE_H_
diff --git a/chrome/browser/chromeos/printing/external_printers_unittest.cc b/chrome/browser/chromeos/printing/external_printers_unittest.cc
index e880df9..9ce3f10 100644
--- a/chrome/browser/chromeos/printing/external_printers_unittest.cc
+++ b/chrome/browser/chromeos/printing/external_printers_unittest.cc
@@ -8,11 +8,9 @@
 #include <vector>
 
 #include "base/bind.h"
+#include "base/memory/ptr_util.h"
 #include "base/strings/stringprintf.h"
-#include "base/test/scoped_feature_list.h"
 #include "base/test/scoped_task_environment.h"
-#include "chrome/common/chrome_features.h"
-#include "chromeos/printing/printer_configuration.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
 namespace chromeos {
@@ -60,53 +58,17 @@
   }
 ])json";
 
-// A different bulk printer configuration file.
-constexpr char kMoreContentsJson[] = R"json(
-[
-  {
-    "id": "ThirdPrime",
-    "display_name": "Printy McPrinter",
-    "description": "Laser on the test shelf",
-    "manufacturer": "CrosInc.",
-    "model": "MS610de",
-    "uri": "ipp://192.168.1.5",
-    "ppd_resource": {
-      "effective_model": "MS610de"
-    }
-  }
-])json";
-
-// Observer that counts the number of times it has been called.
-class TestObserver : public ExternalPrinters::Observer {
- public:
-  void OnPrintersChanged(
-      bool valid,
-      const std::map<const std::string, const Printer>& /* printers */)
-      override {
-    last_valid = valid;
-    called++;
-  }
-
-  // Counts the number of times the observer is invoked.
-  int called = 0;
-  // Holds the most recent value of valid.
-  bool last_valid = false;
-};
-
 class ExternalPrintersTest : public testing::Test {
  public:
   ExternalPrintersTest() : scoped_task_environment_() {
-    scoped_feature_list_.InitAndEnableFeature(
-        base::Feature(features::kBulkPrinters));
     external_printers_ = ExternalPrinters::Create();
   }
 
  protected:
   std::unique_ptr<ExternalPrinters> external_printers_;
-  base::test::ScopedTaskEnvironment scoped_task_environment_;
 
  private:
-  base::test::ScopedFeatureList scoped_feature_list_;
+  base::test::ScopedTaskEnvironment scoped_task_environment_;
 };
 
 // Verify that we're initiall unset and empty.
@@ -115,83 +77,61 @@
   EXPECT_TRUE(external_printers_->GetPrinters().empty());
 }
 
-// Verify that the object can be destroyed while parsing is in progress.
-TEST_F(ExternalPrintersTest, DestructionIsSafe) {
-  {
-    std::unique_ptr<ExternalPrinters> printers = ExternalPrinters::Create();
-    printers->SetAccessMode(ExternalPrinters::BLACKLIST_ONLY);
-    printers->SetBlacklist({"Third"});
-    printers->SetData(std::make_unique<std::string>(kBulkPolicyContentsJson));
-    // Data is valid.  Computation is proceeding.
-  }
-  // printers is out of scope.  Destructor has run.  Pump the message queue to
-  // see if anything strange happens.
-  scoped_task_environment_.RunUntilIdle();
-}
-
 // Verifies that all IsPolicySet returns false until all necessary data is set.
 TEST_F(ExternalPrintersTest, PolicyUnsetWithMissingData) {
-  auto data = std::make_unique<std::string>(kBulkPolicyContentsJson);
+  auto data = base::MakeUnique<std::string>(kBulkPolicyContentsJson);
   external_printers_->ClearData();
   external_printers_->SetData(std::move(data));
 
   // Waiting for AccessMode.
-  scoped_task_environment_.RunUntilIdle();
   EXPECT_FALSE(external_printers_->IsPolicySet());
 
   external_printers_->SetAccessMode(ExternalPrinters::AccessMode::ALL_ACCESS);
-  scoped_task_environment_.RunUntilIdle();
   EXPECT_TRUE(external_printers_->IsPolicySet());
 
   external_printers_->SetAccessMode(
       ExternalPrinters::AccessMode::WHITELIST_ONLY);
-  scoped_task_environment_.RunUntilIdle();
   EXPECT_FALSE(external_printers_->IsPolicySet());  // Waiting for Whitelist.
 
   std::vector<std::string> whitelist = {"First", "Third"};
   external_printers_->SetWhitelist(whitelist);
-  scoped_task_environment_.RunUntilIdle();
   EXPECT_TRUE(external_printers_->IsPolicySet());  // Everything is set.
 
   external_printers_->SetAccessMode(
       ExternalPrinters::AccessMode::BLACKLIST_ONLY);
-  scoped_task_environment_.RunUntilIdle();
   EXPECT_FALSE(external_printers_->IsPolicySet());  // Blacklist needed now.
 
   std::vector<std::string> blacklist = {"Second"};
   external_printers_->SetBlacklist(blacklist);
-  scoped_task_environment_.RunUntilIdle();
   EXPECT_TRUE(
       external_printers_->IsPolicySet());  // Blacklist was set.  Ready again.
 }
 
 // Verify printer list after all attributes have been set.
 TEST_F(ExternalPrintersTest, AllPoliciesResultInPrinters) {
-  auto data = std::make_unique<std::string>(kBulkPolicyContentsJson);
+  auto data = base::MakeUnique<std::string>(kBulkPolicyContentsJson);
   external_printers_->SetAccessMode(ExternalPrinters::AccessMode::ALL_ACCESS);
+  external_printers_->ClearData();
   external_printers_->SetData(std::move(data));
 
-  scoped_task_environment_.RunUntilIdle();
-  const auto& printers = external_printers_->GetPrinters();
   EXPECT_TRUE(external_printers_->IsPolicySet());
+  const std::vector<Printer>& printers = external_printers_->GetPrinters();
   EXPECT_EQ(kNumPrinters, printers.size());
-  EXPECT_EQ("LexaPrint", printers.at("First").display_name());
-  EXPECT_EQ("Color Laser", printers.at("Second").display_name());
-  EXPECT_EQ("YaLP", printers.at("Third").display_name());
+  EXPECT_EQ("First", printers[0].id());
+  EXPECT_EQ("Second", printers[1].id());
+  EXPECT_EQ("Third", printers[2].id());
 }
 
 // The external policy was cleared, results should be invalidated.
 TEST_F(ExternalPrintersTest, PolicyClearedNowUnset) {
-  auto data = std::make_unique<std::string>(kBulkPolicyContentsJson);
+  auto data = base::MakeUnique<std::string>(kBulkPolicyContentsJson);
   external_printers_->SetAccessMode(ExternalPrinters::AccessMode::ALL_ACCESS);
   external_printers_->ClearData();
   external_printers_->SetData(std::move(data));
 
-  scoped_task_environment_.RunUntilIdle();
   ASSERT_TRUE(external_printers_->IsPolicySet());
 
   external_printers_->ClearData();
-  scoped_task_environment_.RunUntilIdle();
   EXPECT_FALSE(external_printers_->IsPolicySet());
   EXPECT_TRUE(external_printers_->GetPrinters().empty());
 }
@@ -200,116 +140,33 @@
 // blacklist policy should not be available.  Printers not in the blackslist
 // should be available.
 TEST_F(ExternalPrintersTest, BlacklistPolicySet) {
-  auto data = std::make_unique<std::string>(kBulkPolicyContentsJson);
+  auto data = base::MakeUnique<std::string>(kBulkPolicyContentsJson);
   external_printers_->ClearData();
   external_printers_->SetData(std::move(data));
   external_printers_->SetAccessMode(ExternalPrinters::BLACKLIST_ONLY);
-  scoped_task_environment_.RunUntilIdle();
   EXPECT_FALSE(external_printers_->IsPolicySet());
   external_printers_->SetBlacklist({"Second", "Third"});
-  scoped_task_environment_.RunUntilIdle();
   EXPECT_TRUE(external_printers_->IsPolicySet());
 
-  scoped_task_environment_.RunUntilIdle();
-  const auto& printers = external_printers_->GetPrinters();
-  EXPECT_EQ(1U, printers.size());
-  EXPECT_EQ("LexaPrint", printers.at("First").display_name());
+  auto printers = external_printers_->GetPrinters();
+  ASSERT_EQ(1U, printers.size());
+  EXPECT_EQ(printers[0].id(), "First");
 }
 
 // Verify that the whitelist policy is correctly applied.  Only printers
 // available in the whitelist are available.
 TEST_F(ExternalPrintersTest, WhitelistPolicySet) {
-  auto data = std::make_unique<std::string>(kBulkPolicyContentsJson);
+  auto data = base::MakeUnique<std::string>(kBulkPolicyContentsJson);
   external_printers_->ClearData();
   external_printers_->SetData(std::move(data));
   external_printers_->SetAccessMode(ExternalPrinters::WHITELIST_ONLY);
-  scoped_task_environment_.RunUntilIdle();
   EXPECT_FALSE(external_printers_->IsPolicySet());
   external_printers_->SetWhitelist({"First"});
-
-  scoped_task_environment_.RunUntilIdle();
   EXPECT_TRUE(external_printers_->IsPolicySet());
-  const auto& printers = external_printers_->GetPrinters();
-  EXPECT_EQ(1U, printers.size());
-  EXPECT_EQ("LexaPrint", printers.at("First").display_name());
-}
 
-// Verify that switching from whitelist to blacklist behaves correctly.
-TEST_F(ExternalPrintersTest, BlacklistToWhitelistSwap) {
-  auto data = std::make_unique<std::string>(kBulkPolicyContentsJson);
-  external_printers_->ClearData();
-  external_printers_->SetData(std::move(data));
-  external_printers_->SetAccessMode(ExternalPrinters::BLACKLIST_ONLY);
-  external_printers_->SetWhitelist({"First"});
-  external_printers_->SetBlacklist({"First"});
-
-  // This should result in 2 printers.  But we're switching the mode anyway.
-
-  external_printers_->SetAccessMode(ExternalPrinters::WHITELIST_ONLY);
-  scoped_task_environment_.RunUntilIdle();
-  EXPECT_TRUE(external_printers_->IsPolicySet());
-  const auto& printers = external_printers_->GetPrinters();
-  EXPECT_EQ(1U, printers.size());
-  EXPECT_EQ("LexaPrint", printers.at("First").display_name());
-}
-
-// Verify that updated configurations are handled properly.
-TEST_F(ExternalPrintersTest, MultipleUpdates) {
-  auto data = std::make_unique<std::string>(kBulkPolicyContentsJson);
-  external_printers_->ClearData();
-  external_printers_->SetData(std::move(data));
-  external_printers_->SetAccessMode(ExternalPrinters::ALL_ACCESS);
-  // There will be 3 printers here.  But we don't want to wait for compuation to
-  // complete to verify the final value gets used.
-
-  auto new_data = std::make_unique<std::string>(kMoreContentsJson);
-  external_printers_->SetData(std::move(new_data));
-  scoped_task_environment_.RunUntilIdle();
-  const auto& printers = external_printers_->GetPrinters();
+  auto printers = external_printers_->GetPrinters();
   ASSERT_EQ(1U, printers.size());
-  EXPECT_EQ("ThirdPrime", printers.at("ThirdPrime").id());
-}
-
-// Verifies that the observer is called at the expected times.
-TEST_F(ExternalPrintersTest, ObserverTest) {
-  TestObserver obs;
-  external_printers_->AddObserver(&obs);
-
-  external_printers_->SetAccessMode(ExternalPrinters::ALL_ACCESS);
-  external_printers_->SetWhitelist(std::vector<std::string>());
-  external_printers_->SetBlacklist(std::vector<std::string>());
-  external_printers_->ClearData();
-  scoped_task_environment_.RunUntilIdle();
-  EXPECT_EQ(0, obs.called);
-
-  external_printers_->SetData(
-      std::make_unique<std::string>(kBulkPolicyContentsJson));
-
-  scoped_task_environment_.RunUntilIdle();
-  EXPECT_TRUE(external_printers_->IsPolicySet());
-  EXPECT_EQ(1, obs.called);
-  EXPECT_TRUE(obs.last_valid);  // ready now
-  // Printer list is correct after notification.
-  EXPECT_EQ(kNumPrinters, external_printers_->GetPrinters().size());
-
-  external_printers_->SetAccessMode(ExternalPrinters::WHITELIST_ONLY);
-  scoped_task_environment_.RunUntilIdle();
-  EXPECT_EQ(2, obs.called);  // effective list changed.  Notified.
-  EXPECT_TRUE(obs.last_valid);
-
-  external_printers_->SetAccessMode(ExternalPrinters::BLACKLIST_ONLY);
-  scoped_task_environment_.RunUntilIdle();
-  EXPECT_EQ(3, obs.called);  // effective list changed.  Notified.
-  EXPECT_TRUE(obs.last_valid);
-
-  external_printers_->ClearData();
-  scoped_task_environment_.RunUntilIdle();
-  EXPECT_EQ(4, obs.called);  // Called for transition to invalid policy.
-  EXPECT_FALSE(obs.last_valid);
-  EXPECT_TRUE(external_printers_->GetPrinters().empty());
-
-  // cleanup
-  external_printers_->RemoveObserver(&obs);
+  EXPECT_EQ(printers[0].id(), "First");
 }
 
 }  // namespace
diff --git a/chrome/browser/resource_coordinator/tab_manager.cc b/chrome/browser/resource_coordinator/tab_manager.cc
index 98fbbb0..633dc40 100644
--- a/chrome/browser/resource_coordinator/tab_manager.cc
+++ b/chrome/browser/resource_coordinator/tab_manager.cc
@@ -675,7 +675,6 @@
           contents->GetPageImportanceSignals().had_form_interaction;
       stats.discard_count = GetWebContentsData(contents)->DiscardCount();
       stats.last_active = contents->GetLastActiveTime();
-      stats.last_hidden = contents->GetLastHiddenTime();
       stats.render_process_host = contents->GetMainFrame()->GetProcess();
       stats.renderer_handle =
           contents->GetMainFrame()->GetProcess()->GetHandle();
diff --git a/chrome/browser/resource_coordinator/tab_stats.h b/chrome/browser/resource_coordinator/tab_stats.h
index 77aa50b..7dd270d 100644
--- a/chrome/browser/resource_coordinator/tab_stats.h
+++ b/chrome/browser/resource_coordinator/tab_stats.h
@@ -43,7 +43,6 @@
   int discard_count = 0;
   bool has_beforeunload_handler = false;
   base::TimeTicks last_active;
-  base::TimeTicks last_hidden;
   content::RenderProcessHost* render_process_host = nullptr;
   base::ProcessHandle renderer_handle = 0;
   int child_process_host_id = 0;
diff --git a/chromeos/BUILD.gn b/chromeos/BUILD.gn
index 661b58a..0339fee 100644
--- a/chromeos/BUILD.gn
+++ b/chromeos/BUILD.gn
@@ -120,6 +120,8 @@
     "cryptohome/async_method_caller.h",
     "cryptohome/cryptohome_parameters.cc",
     "cryptohome/cryptohome_parameters.h",
+    "cryptohome/cryptohome_util.cc",
+    "cryptohome/cryptohome_util.h",
     "cryptohome/homedir_methods.cc",
     "cryptohome/homedir_methods.h",
     "cryptohome/system_salt_getter.cc",
diff --git a/chromeos/cryptohome/cryptohome_util.cc b/chromeos/cryptohome/cryptohome_util.cc
new file mode 100644
index 0000000..cb8e972
--- /dev/null
+++ b/chromeos/cryptohome/cryptohome_util.cc
@@ -0,0 +1,156 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chromeos/cryptohome/cryptohome_util.h"
+
+#include <string>
+
+#include "chromeos/cryptohome/cryptohome_parameters.h"
+#include "chromeos/dbus/cryptohome/key.pb.h"
+#include "chromeos/dbus/cryptohome/rpc.pb.h"
+#include "third_party/cros_system_api/dbus/service_constants.h"
+
+namespace cryptohome {
+
+AuthorizationRequest CreateAuthorizationRequest(const std::string& label,
+                                                const std::string& secret) {
+  cryptohome::AuthorizationRequest auth_request;
+  Key* key = auth_request.mutable_key();
+  if (!label.empty())
+    key->mutable_data()->set_label(label);
+
+  key->set_secret(secret);
+  return auth_request;
+}
+
+void KeyDefinitionToKey(const KeyDefinition& key_def, Key* key) {
+  key->set_secret(key_def.secret);
+  KeyData* data = key->mutable_data();
+  DCHECK_EQ(KeyDefinition::TYPE_PASSWORD, key_def.type);
+  data->set_type(KeyData::KEY_TYPE_PASSWORD);
+  data->set_label(key_def.label);
+
+  if (key_def.revision > 0)
+    data->set_revision(key_def.revision);
+
+  if (key_def.privileges != 0) {
+    KeyPrivileges* privileges = data->mutable_privileges();
+    privileges->set_mount(key_def.privileges & PRIV_MOUNT);
+    privileges->set_add(key_def.privileges & PRIV_ADD);
+    privileges->set_remove(key_def.privileges & PRIV_REMOVE);
+    privileges->set_update(key_def.privileges & PRIV_MIGRATE);
+    privileges->set_authorized_update(key_def.privileges &
+                                      PRIV_AUTHORIZED_UPDATE);
+  }
+
+  for (const auto& current_auth_data : key_def.authorization_data) {
+    KeyAuthorizationData* auth_data = data->add_authorization_data();
+    switch (current_auth_data.type) {
+      case KeyDefinition::AuthorizationData::TYPE_HMACSHA256:
+        auth_data->set_type(
+            KeyAuthorizationData::KEY_AUTHORIZATION_TYPE_HMACSHA256);
+        break;
+      case KeyDefinition::AuthorizationData::TYPE_AES256CBC_HMACSHA256:
+        auth_data->set_type(
+            KeyAuthorizationData::KEY_AUTHORIZATION_TYPE_AES256CBC_HMACSHA256);
+        break;
+    }
+
+    for (const auto& current_secret : current_auth_data.secrets) {
+      KeyAuthorizationSecret* secret = auth_data->add_secrets();
+      secret->mutable_usage()->set_encrypt(current_secret.encrypt);
+      secret->mutable_usage()->set_sign(current_secret.sign);
+      secret->set_wrapped(current_secret.wrapped);
+      if (!current_secret.symmetric_key.empty())
+        secret->set_symmetric_key(current_secret.symmetric_key);
+
+      if (!current_secret.public_key.empty())
+        secret->set_public_key(current_secret.public_key);
+    }
+  }
+
+  for (const auto& provider_data : key_def.provider_data) {
+    KeyProviderData::Entry* entry = data->mutable_provider_data()->add_entry();
+    entry->set_name(provider_data.name);
+    if (provider_data.number)
+      entry->set_number(*provider_data.number);
+
+    if (provider_data.bytes)
+      entry->set_bytes(*provider_data.bytes);
+  }
+}
+
+MountError CryptohomeErrorToMountError(CryptohomeErrorCode code) {
+  switch (code) {
+    case CRYPTOHOME_ERROR_NOT_SET:
+      return MOUNT_ERROR_NONE;
+    case CRYPTOHOME_ERROR_ACCOUNT_NOT_FOUND:
+      return MOUNT_ERROR_USER_DOES_NOT_EXIST;
+    case CRYPTOHOME_ERROR_NOT_IMPLEMENTED:
+    case CRYPTOHOME_ERROR_MOUNT_FATAL:
+    case CRYPTOHOME_ERROR_KEY_QUOTA_EXCEEDED:
+    case CRYPTOHOME_ERROR_BACKING_STORE_FAILURE:
+      return MOUNT_ERROR_FATAL;
+    case CRYPTOHOME_ERROR_AUTHORIZATION_KEY_NOT_FOUND:
+    case CRYPTOHOME_ERROR_KEY_NOT_FOUND:
+    case CRYPTOHOME_ERROR_AUTHORIZATION_KEY_FAILED:
+      return MOUNT_ERROR_KEY_FAILURE;
+    case CRYPTOHOME_ERROR_TPM_COMM_ERROR:
+      return MOUNT_ERROR_TPM_COMM_ERROR;
+    case CRYPTOHOME_ERROR_TPM_DEFEND_LOCK:
+      return MOUNT_ERROR_TPM_DEFEND_LOCK;
+    case CRYPTOHOME_ERROR_MOUNT_MOUNT_POINT_BUSY:
+      return MOUNT_ERROR_MOUNT_POINT_BUSY;
+    case CRYPTOHOME_ERROR_TPM_NEEDS_REBOOT:
+      return MOUNT_ERROR_TPM_NEEDS_REBOOT;
+    case CRYPTOHOME_ERROR_AUTHORIZATION_KEY_DENIED:
+    case CRYPTOHOME_ERROR_KEY_LABEL_EXISTS:
+    case CRYPTOHOME_ERROR_UPDATE_SIGNATURE_INVALID:
+      return MOUNT_ERROR_KEY_FAILURE;
+    case CRYPTOHOME_ERROR_MOUNT_OLD_ENCRYPTION:
+      return MOUNT_ERROR_OLD_ENCRYPTION;
+    case CRYPTOHOME_ERROR_MOUNT_PREVIOUS_MIGRATION_INCOMPLETE:
+      return MOUNT_ERROR_PREVIOUS_MIGRATION_INCOMPLETE;
+    // TODO(crbug.com/797563): Split the error space and/or handle everything.
+    case CRYPTOHOME_ERROR_LOCKBOX_SIGNATURE_INVALID:
+    case CRYPTOHOME_ERROR_LOCKBOX_CANNOT_SIGN:
+    case CRYPTOHOME_ERROR_BOOT_ATTRIBUTE_NOT_FOUND:
+    case CRYPTOHOME_ERROR_BOOT_ATTRIBUTES_CANNOT_SIGN:
+    case CRYPTOHOME_ERROR_TPM_EK_NOT_AVAILABLE:
+    case CRYPTOHOME_ERROR_ATTESTATION_NOT_READY:
+    case CRYPTOHOME_ERROR_CANNOT_CONNECT_TO_CA:
+    case CRYPTOHOME_ERROR_CA_REFUSED_ENROLLMENT:
+    case CRYPTOHOME_ERROR_CA_REFUSED_CERTIFICATE:
+    case CRYPTOHOME_ERROR_INTERNAL_ATTESTATION_ERROR:
+    case CRYPTOHOME_ERROR_FIRMWARE_MANAGEMENT_PARAMETERS_INVALID:
+    case CRYPTOHOME_ERROR_FIRMWARE_MANAGEMENT_PARAMETERS_CANNOT_STORE:
+    case CRYPTOHOME_ERROR_FIRMWARE_MANAGEMENT_PARAMETERS_CANNOT_REMOVE:
+      NOTREACHED();
+      return MOUNT_ERROR_FATAL;
+  }
+}
+
+void KeyAuthorizationDataToAuthorizationData(
+    const KeyAuthorizationData& authorization_data_proto,
+    KeyDefinition::AuthorizationData* authorization_data) {
+  switch (authorization_data_proto.type()) {
+    case KeyAuthorizationData::KEY_AUTHORIZATION_TYPE_HMACSHA256:
+      authorization_data->type =
+          KeyDefinition::AuthorizationData::TYPE_HMACSHA256;
+      break;
+    case KeyAuthorizationData::KEY_AUTHORIZATION_TYPE_AES256CBC_HMACSHA256:
+      authorization_data->type =
+          KeyDefinition::AuthorizationData::TYPE_AES256CBC_HMACSHA256;
+      break;
+  }
+
+  for (const auto& secret : authorization_data_proto.secrets()) {
+    authorization_data->secrets.push_back(
+        KeyDefinition::AuthorizationData::Secret(
+            secret.usage().encrypt(), secret.usage().sign(),
+            secret.symmetric_key(), secret.public_key(), secret.wrapped()));
+  }
+}
+
+}  // namespace cryptohome
diff --git a/chromeos/cryptohome/cryptohome_util.h b/chromeos/cryptohome/cryptohome_util.h
new file mode 100644
index 0000000..8659ae2
--- /dev/null
+++ b/chromeos/cryptohome/cryptohome_util.h
@@ -0,0 +1,38 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROMEOS_CRYPTOHOME_CRYPTOHOME_UTIL_H_
+#define CHROMEOS_CRYPTOHOME_CRYPTOHOME_UTIL_H_
+
+#include <string>
+
+#include "chromeos/chromeos_export.h"
+#include "chromeos/cryptohome/cryptohome_parameters.h"
+#include "chromeos/dbus/cryptohome/key.pb.h"
+#include "chromeos/dbus/cryptohome/rpc.pb.h"
+#include "third_party/cros_system_api/dbus/service_constants.h"
+
+namespace cryptohome {
+
+// Creates an AuthorizationRequest from the given secret and label.
+AuthorizationRequest CHROMEOS_EXPORT
+CreateAuthorizationRequest(const std::string& label, const std::string& secret);
+
+// Converts the given KeyDefinition to a Key.
+void CHROMEOS_EXPORT KeyDefinitionToKey(const KeyDefinition& key_def, Key* key);
+
+// Converts CryptohomeErrorCode to MountError.
+CHROMEOS_EXPORT MountError
+CryptohomeErrorToMountError(CryptohomeErrorCode code);
+
+// Converts the given KeyAuthorizationData to AuthorizationData pointed to by
+// |authorization_data|.
+CHROMEOS_EXPORT
+void KeyAuthorizationDataToAuthorizationData(
+    const KeyAuthorizationData& authorization_data_proto,
+    KeyDefinition::AuthorizationData* authorization_data);
+
+}  // namespace cryptohome
+
+#endif  // CHROMEOS_CRYPTOHOME_CRYPTOHOME_UTIL_H_
diff --git a/chromeos/cryptohome/homedir_methods.cc b/chromeos/cryptohome/homedir_methods.cc
index 14ba3df..d0e9147 100644
--- a/chromeos/cryptohome/homedir_methods.cc
+++ b/chromeos/cryptohome/homedir_methods.cc
@@ -10,11 +10,11 @@
 #include "base/bind.h"
 #include "base/logging.h"
 #include "base/macros.h"
+#include "chromeos/cryptohome/cryptohome_util.h"
 #include "chromeos/dbus/cryptohome/key.pb.h"
 #include "chromeos/dbus/cryptohome/rpc.pb.h"
 #include "chromeos/dbus/dbus_thread_manager.h"
 #include "components/device_event_log/device_event_log.h"
-#include "third_party/protobuf/src/google/protobuf/repeated_field.h"
 
 using chromeos::DBusThreadManager;
 using google::protobuf::RepeatedPtrField;
@@ -25,72 +25,6 @@
 
 HomedirMethods* g_homedir_methods = NULL;
 
-void ParseAuthorizationDataProtobuf(
-    const KeyAuthorizationData& authorization_data_proto,
-    KeyDefinition::AuthorizationData* authorization_data) {
-  switch (authorization_data_proto.type()) {
-    case KeyAuthorizationData::KEY_AUTHORIZATION_TYPE_HMACSHA256:
-      authorization_data->type =
-          KeyDefinition::AuthorizationData::TYPE_HMACSHA256;
-      break;
-    case KeyAuthorizationData::KEY_AUTHORIZATION_TYPE_AES256CBC_HMACSHA256:
-      authorization_data->type =
-          KeyDefinition::AuthorizationData::TYPE_AES256CBC_HMACSHA256;
-      break;
-    default:
-      NOTREACHED();
-      return;
-  }
-
-  for (RepeatedPtrField<KeyAuthorizationSecret>::const_iterator it =
-          authorization_data_proto.secrets().begin();
-       it != authorization_data_proto.secrets().end(); ++it) {
-    authorization_data->secrets.push_back(
-        KeyDefinition::AuthorizationData::Secret(it->usage().encrypt(),
-                                                 it->usage().sign(),
-                                                 it->symmetric_key(),
-                                                 it->public_key(),
-                                                 it->wrapped()));
-  }
-}
-
-MountError MapError(CryptohomeErrorCode code) {
-  switch (code) {
-    case CRYPTOHOME_ERROR_NOT_SET:
-      return MOUNT_ERROR_NONE;
-    case CRYPTOHOME_ERROR_ACCOUNT_NOT_FOUND:
-      return MOUNT_ERROR_USER_DOES_NOT_EXIST;
-    case CRYPTOHOME_ERROR_NOT_IMPLEMENTED:
-    case CRYPTOHOME_ERROR_MOUNT_FATAL:
-    case CRYPTOHOME_ERROR_KEY_QUOTA_EXCEEDED:
-    case CRYPTOHOME_ERROR_BACKING_STORE_FAILURE:
-      return MOUNT_ERROR_FATAL;
-    case CRYPTOHOME_ERROR_AUTHORIZATION_KEY_NOT_FOUND:
-    case CRYPTOHOME_ERROR_KEY_NOT_FOUND:
-    case CRYPTOHOME_ERROR_AUTHORIZATION_KEY_FAILED:
-      return MOUNT_ERROR_KEY_FAILURE;
-    case CRYPTOHOME_ERROR_TPM_COMM_ERROR:
-      return MOUNT_ERROR_TPM_COMM_ERROR;
-    case CRYPTOHOME_ERROR_TPM_DEFEND_LOCK:
-      return MOUNT_ERROR_TPM_DEFEND_LOCK;
-    case CRYPTOHOME_ERROR_MOUNT_MOUNT_POINT_BUSY:
-      return MOUNT_ERROR_MOUNT_POINT_BUSY;
-    case CRYPTOHOME_ERROR_TPM_NEEDS_REBOOT:
-      return MOUNT_ERROR_TPM_NEEDS_REBOOT;
-    case CRYPTOHOME_ERROR_AUTHORIZATION_KEY_DENIED:
-    case CRYPTOHOME_ERROR_KEY_LABEL_EXISTS:
-    case CRYPTOHOME_ERROR_UPDATE_SIGNATURE_INVALID:
-      return MOUNT_ERROR_KEY_FAILURE;
-    case CRYPTOHOME_ERROR_MOUNT_OLD_ENCRYPTION:
-      return MOUNT_ERROR_OLD_ENCRYPTION;
-    case CRYPTOHOME_ERROR_MOUNT_PREVIOUS_MIGRATION_INCOMPLETE:
-      return MOUNT_ERROR_PREVIOUS_MIGRATION_INCOMPLETE;
-    default:
-      NOTREACHED();
-      return MOUNT_ERROR_FATAL;
-  }
-}
-
 // The implementation of HomedirMethods
 class HomedirMethodsImpl : public HomedirMethods {
  public:
@@ -183,7 +117,7 @@
       return;
     }
     if (reply->has_error() && reply->error() != CRYPTOHOME_ERROR_NOT_SET) {
-      callback.Run(false, MapError(reply->error()),
+      callback.Run(false, CryptohomeErrorToMountError(reply->error()),
                    std::vector<KeyDefinition>());
       return;
     }
@@ -226,9 +160,8 @@
            auth_it != it->authorization_data().end(); ++auth_it) {
         key_definition.authorization_data.push_back(
             KeyDefinition::AuthorizationData());
-        ParseAuthorizationDataProtobuf(
-            *auth_it,
-            &key_definition.authorization_data.back());
+        KeyAuthorizationDataToAuthorizationData(
+            *auth_it, &key_definition.authorization_data.back());
       }
 
       // Extract |provider_data|.
@@ -273,7 +206,8 @@
     if (reply->has_error() && reply->error() != CRYPTOHOME_ERROR_NOT_SET) {
       LOGIN_LOG(ERROR) << "HomedirMethods MountEx error (CryptohomeErrorCode): "
                        << reply->error();
-      callback.Run(false, MapError(reply->error()), std::string());
+      callback.Run(false, CryptohomeErrorToMountError(reply->error()),
+                   std::string());
       return;
     }
     if (!reply->HasExtension(MountReply::reply)) {
@@ -313,7 +247,7 @@
       return;
     }
     if (reply->has_error() && reply->error() != CRYPTOHOME_ERROR_NOT_SET) {
-      callback.Run(false, MapError(reply->error()));
+      callback.Run(false, CryptohomeErrorToMountError(reply->error()));
       return;
     }
     callback.Run(true, MOUNT_ERROR_NONE);
@@ -326,82 +260,6 @@
 
 }  // namespace
 
-void KeyDefinitionToKey(const KeyDefinition& key_def, Key* key) {
-  key->set_secret(key_def.secret);
-  KeyData* data = key->mutable_data();
-  DCHECK_EQ(KeyDefinition::TYPE_PASSWORD, key_def.type);
-  data->set_type(KeyData::KEY_TYPE_PASSWORD);
-  data->set_label(key_def.label);
-
-  if (key_def.revision > 0)
-    data->set_revision(key_def.revision);
-
-  if (key_def.privileges != 0) {
-    KeyPrivileges* privileges = data->mutable_privileges();
-    privileges->set_mount(key_def.privileges & PRIV_MOUNT);
-    privileges->set_add(key_def.privileges & PRIV_ADD);
-    privileges->set_remove(key_def.privileges & PRIV_REMOVE);
-    privileges->set_update(key_def.privileges & PRIV_MIGRATE);
-    privileges->set_authorized_update(key_def.privileges &
-                                      PRIV_AUTHORIZED_UPDATE);
-  }
-
-  for (std::vector<KeyDefinition::AuthorizationData>::const_iterator auth_it =
-           key_def.authorization_data.begin();
-       auth_it != key_def.authorization_data.end(); ++auth_it) {
-    KeyAuthorizationData* auth_data = data->add_authorization_data();
-    switch (auth_it->type) {
-      case KeyDefinition::AuthorizationData::TYPE_HMACSHA256:
-        auth_data->set_type(
-            KeyAuthorizationData::KEY_AUTHORIZATION_TYPE_HMACSHA256);
-        break;
-      case KeyDefinition::AuthorizationData::TYPE_AES256CBC_HMACSHA256:
-        auth_data->set_type(
-            KeyAuthorizationData::KEY_AUTHORIZATION_TYPE_AES256CBC_HMACSHA256);
-        break;
-      default:
-        NOTREACHED();
-        break;
-    }
-
-    for (std::vector<KeyDefinition::AuthorizationData::Secret>::const_iterator
-             secret_it = auth_it->secrets.begin();
-         secret_it != auth_it->secrets.end(); ++secret_it) {
-      KeyAuthorizationSecret* secret = auth_data->add_secrets();
-      secret->mutable_usage()->set_encrypt(secret_it->encrypt);
-      secret->mutable_usage()->set_sign(secret_it->sign);
-      if (!secret_it->symmetric_key.empty())
-        secret->set_symmetric_key(secret_it->symmetric_key);
-      if (!secret_it->public_key.empty())
-        secret->set_public_key(secret_it->public_key);
-      secret->set_wrapped(secret_it->wrapped);
-    }
-  }
-
-  for (std::vector<KeyDefinition::ProviderData>::const_iterator it =
-           key_def.provider_data.begin();
-       it != key_def.provider_data.end(); ++it) {
-    KeyProviderData::Entry* entry = data->mutable_provider_data()->add_entry();
-    entry->set_name(it->name);
-    if (it->number)
-      entry->set_number(*it->number);
-    if (it->bytes)
-      entry->set_bytes(*it->bytes);
-  }
-}
-
-cryptohome::AuthorizationRequest CreateAuthorizationRequest(
-    const std::string& label,
-    const std::string& secret) {
-  cryptohome::AuthorizationRequest auth_request;
-  Key* key = auth_request.mutable_key();
-  if (!label.empty())
-    key->mutable_data()->set_label(label);
-
-  key->set_secret(secret);
-  return auth_request;
-}
-
 // static
 void HomedirMethods::Initialize() {
   if (g_homedir_methods) {
diff --git a/chromeos/cryptohome/homedir_methods.h b/chromeos/cryptohome/homedir_methods.h
index 9ef4c33..a209b8b 100644
--- a/chromeos/cryptohome/homedir_methods.h
+++ b/chromeos/cryptohome/homedir_methods.h
@@ -20,13 +20,6 @@
 
 namespace cryptohome {
 
-// Converts the given KeyDefinition to a Key.
-void CHROMEOS_EXPORT KeyDefinitionToKey(const KeyDefinition& key_def, Key* key);
-
-// Creates an AuthorizationRequest from the given secret and label.
-AuthorizationRequest CHROMEOS_EXPORT
-CreateAuthorizationRequest(const std::string& label, const std::string& secret);
-
 // This class manages calls to Cryptohome service's home directory methods:
 // Mount, CheckKey, Add/UpdateKey.
 class CHROMEOS_EXPORT HomedirMethods {
diff --git a/chromeos/login/auth/cryptohome_authenticator.cc b/chromeos/login/auth/cryptohome_authenticator.cc
index 4fc3bb5..a5836fbf 100644
--- a/chromeos/login/auth/cryptohome_authenticator.cc
+++ b/chromeos/login/auth/cryptohome_authenticator.cc
@@ -17,6 +17,7 @@
 #include "chromeos/chromeos_switches.h"
 #include "chromeos/cryptohome/async_method_caller.h"
 #include "chromeos/cryptohome/cryptohome_parameters.h"
+#include "chromeos/cryptohome/cryptohome_util.h"
 #include "chromeos/cryptohome/homedir_methods.h"
 #include "chromeos/cryptohome/system_salt_getter.h"
 #include "chromeos/dbus/cryptohome_client.h"
@@ -172,7 +173,7 @@
   if (ephemeral)
     mount.set_require_ephemeral(true);
   if (create_if_nonexistent) {
-    KeyDefinitionToKey(
+    cryptohome::KeyDefinitionToKey(
         cryptohome::KeyDefinition(key->GetSecret(), kCryptohomeGAIAKeyLabel,
                                   cryptohome::PRIV_DEFAULT),
         mount.mutable_create()->add_keys());
@@ -424,7 +425,7 @@
     mount.set_force_dircrypto_if_available(true);
   mount.set_public_mount(true);
   // Set the request to create a new homedir when missing.
-  KeyDefinitionToKey(
+  cryptohome::KeyDefinitionToKey(
       cryptohome::KeyDefinition(std::string(), kCryptohomePublicMountKeyLabel,
                                 cryptohome::PRIV_DEFAULT),
       mount.mutable_create()->add_keys());
diff --git a/chromeos/login/auth/extended_authenticator_impl.cc b/chromeos/login/auth/extended_authenticator_impl.cc
index a08d9b2..375c6f6 100644
--- a/chromeos/login/auth/extended_authenticator_impl.cc
+++ b/chromeos/login/auth/extended_authenticator_impl.cc
@@ -11,6 +11,7 @@
 #include "base/strings/string_util.h"
 #include "chromeos/cryptohome/async_method_caller.h"
 #include "chromeos/cryptohome/cryptohome_parameters.h"
+#include "chromeos/cryptohome/cryptohome_util.h"
 #include "chromeos/cryptohome/homedir_methods.h"
 #include "chromeos/cryptohome/system_salt_getter.h"
 #include "chromeos/dbus/cryptohome_client.h"
@@ -90,7 +91,7 @@
   cryptohome::Identification id(account_id);
   cryptohome::MountRequest mount;
   for (size_t i = 0; i < keys.size(); i++) {
-    KeyDefinitionToKey(keys[i], mount.mutable_create()->add_keys());
+    cryptohome::KeyDefinitionToKey(keys[i], mount.mutable_create()->add_keys());
   }
   UserContext context(account_id);
   Key key(keys.front().secret);
@@ -216,7 +217,7 @@
   RecordStartMarker("AddKeyEx");
 
   cryptohome::AddKeyRequest request;
-  KeyDefinitionToKey(key, request.mutable_key());
+  cryptohome::KeyDefinitionToKey(key, request.mutable_key());
   request.set_clobber_if_exists(clobber_if_exists);
   const Key* const auth_key = user_context.GetKey();
   cryptohome::HomedirMethods::GetInstance()->AddKeyEx(
diff --git a/components/arc/arc_util.cc b/components/arc/arc_util.cc
index b12b5ceb..56c3e774 100644
--- a/components/arc/arc_util.cc
+++ b/components/arc/arc_util.cc
@@ -82,6 +82,8 @@
 }
 
 bool IsPlayStoreAvailable() {
+  if (IsRobotAccountMode())
+    return false;
   const auto* command_line = base::CommandLine::ForCurrentProcess();
   if (!command_line->HasSwitch(chromeos::switches::kArcStartMode))
     return true;
@@ -135,6 +137,12 @@
          user_manager::UserManager::Get()->IsLoggedInAsArcKioskApp();
 }
 
+bool IsRobotAccountMode() {
+  return user_manager::UserManager::IsInitialized() &&
+         (user_manager::UserManager::Get()->IsLoggedInAsArcKioskApp() ||
+          user_manager::UserManager::Get()->IsLoggedInAsPublicAccount());
+}
+
 bool IsArcAllowedForUser(const user_manager::User* user) {
   if (!user) {
     VLOG(1) << "No ARC for nullptr user.";
@@ -145,23 +153,18 @@
   // - Users have Gaia accounts;
   // - Active directory users;
   // - ARC kiosk session;
+  // - Public Session users;
   //   USER_TYPE_ARC_KIOSK_APP check is compatible with IsArcKioskMode()
   //   above because ARC kiosk user is always the primary/active user of a
-  //   user session.
+  //   user session. The same for USER_TYPE_PUBLIC_ACCOUNT.
   if (!user->HasGaiaAccount() && !user->IsActiveDirectoryUser() &&
-      user->GetType() != user_manager::USER_TYPE_ARC_KIOSK_APP) {
+      user->GetType() != user_manager::USER_TYPE_ARC_KIOSK_APP &&
+      user->GetType() != user_manager::USER_TYPE_PUBLIC_ACCOUNT) {
     VLOG(1) << "Users without GAIA or AD accounts, or not ARC kiosk apps are "
                "not supported in ARC.";
     return false;
   }
 
-  // Do not allow for ephemeral data user. cf) b/26402681
-  if (user_manager::UserManager::Get()->IsUserCryptohomeDataEphemeral(
-          user->GetAccountId())) {
-    VLOG(1) << "Users with ephemeral data are not supported in ARC.";
-    return false;
-  }
-
   if (user->GetType() == user_manager::USER_TYPE_CHILD) {
     VLOG(1) << "ARC usage by Child users is prohibited";
     return false;
diff --git a/components/arc/arc_util.h b/components/arc/arc_util.h
index 3214545..5af1de1 100644
--- a/components/arc/arc_util.h
+++ b/components/arc/arc_util.h
@@ -75,6 +75,13 @@
 // should also return true in that case.
 bool IsArcKioskMode();
 
+// Returns true if current user is a robot account user.
+// These are Public Session and ARC Kiosk users.
+// As it can return true only when user is already initialized, it implies
+// that ARC availability was checked before.
+// The check is basically IsArcKioskMode() | IsPublicSessionMode().
+bool IsRobotAccountMode();
+
 // Returns true if ARC is allowed for the given user. Note this should not be
 // used as a signal of whether ARC is allowed alone because it only considers
 // user meta data. e.g. a user could be allowed for ARC but if the user signs in
diff --git a/components/arc/arc_util_unittest.cc b/components/arc/arc_util_unittest.cc
index bc476ad..65c952f 100644
--- a/components/arc/arc_util_unittest.cc
+++ b/components/arc/arc_util_unittest.cc
@@ -194,7 +194,7 @@
   } const kTestCases[] = {
       {user_manager::USER_TYPE_REGULAR, true},
       {user_manager::USER_TYPE_GUEST, false},
-      {user_manager::USER_TYPE_PUBLIC_ACCOUNT, false},
+      {user_manager::USER_TYPE_PUBLIC_ACCOUNT, true},
       {user_manager::USER_TYPE_SUPERVISED, false},
       {user_manager::USER_TYPE_KIOSK_APP, false},
       {user_manager::USER_TYPE_CHILD, false},
@@ -218,8 +218,8 @@
   ASSERT_TRUE(fake_user_manager->IsUserCryptohomeDataEphemeral(
       ephemeral_user->GetAccountId()));
 
-  // Ephemeral user is not allowed for ARC.
-  EXPECT_FALSE(IsArcAllowedForUser(ephemeral_user));
+  // Ephemeral user is also allowed for ARC.
+  EXPECT_TRUE(IsArcAllowedForUser(ephemeral_user));
 }
 
 TEST_F(ArcUtilTest, ArcStartModeDefault) {
diff --git a/components/autofill/core/browser/BUILD.gn b/components/autofill/core/browser/BUILD.gn
index b619cfa..a8402deb 100644
--- a/components/autofill/core/browser/BUILD.gn
+++ b/components/autofill/core/browser/BUILD.gn
@@ -292,12 +292,16 @@
     "test_autofill_driver.h",
     "test_autofill_external_delegate.cc",
     "test_autofill_external_delegate.h",
+    "test_autofill_manager.cc",
+    "test_autofill_manager.h",
     "test_autofill_provider.cc",
     "test_autofill_provider.h",
     "test_credit_card_save_manager.cc",
     "test_credit_card_save_manager.h",
     "test_form_data_importer.cc",
     "test_form_data_importer.h",
+    "test_form_structure.cc",
+    "test_form_structure.h",
     "test_personal_data_manager.cc",
     "test_personal_data_manager.h",
     "test_region_data_loader.cc",
diff --git a/components/autofill/core/browser/autofill_manager_unittest.cc b/components/autofill/core/browser/autofill_manager_unittest.cc
index 6b92be0..4ba0cbf 100644
--- a/components/autofill/core/browser/autofill_manager_unittest.cc
+++ b/components/autofill/core/browser/autofill_manager_unittest.cc
@@ -18,12 +18,10 @@
 #include "base/memory/ref_counted.h"
 #include "base/metrics/field_trial.h"
 #include "base/metrics/metrics_hashes.h"
-#include "base/run_loop.h"
 #include "base/strings/string16.h"
 #include "base/strings/string_number_conversions.h"
 #include "base/strings/string_util.h"
 #include "base/strings/stringprintf.h"
-#include "base/strings/utf_string_conversions.h"
 #include "base/test/histogram_tester.h"
 #include "base/test/scoped_feature_list.h"
 #include "base/test/scoped_task_environment.h"
@@ -42,6 +40,8 @@
 #include "components/autofill/core/browser/test_autofill_clock.h"
 #include "components/autofill/core/browser/test_autofill_driver.h"
 #include "components/autofill/core/browser/test_autofill_external_delegate.h"
+#include "components/autofill/core/browser/test_autofill_manager.h"
+#include "components/autofill/core/browser/test_form_structure.h"
 #include "components/autofill/core/browser/test_personal_data_manager.h"
 #include "components/autofill/core/browser/validation.h"
 #include "components/autofill/core/browser/webdata/autofill_webdata_service.h"
@@ -321,137 +321,6 @@
   DISALLOW_COPY_AND_ASSIGN(MockAutofillDriver);
 };
 
-class TestAutofillManager : public AutofillManager {
- public:
-  TestAutofillManager(AutofillDriver* driver,
-                      AutofillClient* client,
-                      TestPersonalDataManager* personal_data)
-      : AutofillManager(driver, client, personal_data),
-        personal_data_(personal_data),
-        context_getter_(driver->GetURLRequestContext()),
-        autofill_enabled_(true),
-        credit_card_enabled_(true),
-        expected_observed_submission_(true),
-        call_parent_upload_form_data_(false) {
-    set_payments_client(new payments::PaymentsClient(
-        context_getter_, client->GetPrefs(), client->GetIdentityProvider(),
-        /*unmask_delegate=*/this,
-        /*save_delegate=*/nullptr));
-  }
-  ~TestAutofillManager() override {}
-
-  bool IsAutofillEnabled() const override { return autofill_enabled_; }
-
-  void set_autofill_enabled(bool autofill_enabled) {
-    autofill_enabled_ = autofill_enabled;
-  }
-
-  bool IsCreditCardAutofillEnabled() override { return credit_card_enabled_; }
-
-  void set_credit_card_enabled(bool credit_card_enabled) {
-    credit_card_enabled_ = credit_card_enabled;
-    if (!credit_card_enabled_)
-      // Credit card data is refreshed when this pref is changed.
-      personal_data_->ClearCreditCards();
-  }
-
-  void set_expected_submitted_field_types(
-      const std::vector<ServerFieldTypeSet>& expected_types) {
-    expected_submitted_field_types_ = expected_types;
-  }
-
-  void set_expected_observed_submission(bool expected) {
-    expected_observed_submission_ = expected;
-  }
-
-  void set_call_parent_upload_form_data(bool value) {
-    call_parent_upload_form_data_ = value;
-  }
-
-  void UploadFormDataAsyncCallback(const FormStructure* submitted_form,
-                                   const base::TimeTicks& load_time,
-                                   const base::TimeTicks& interaction_time,
-                                   const base::TimeTicks& submission_time,
-                                   bool observed_submission) override {
-    run_loop_->Quit();
-
-    EXPECT_EQ(expected_observed_submission_, observed_submission);
-
-    // If we have expected field types set, make sure they match.
-    if (!expected_submitted_field_types_.empty()) {
-      ASSERT_EQ(expected_submitted_field_types_.size(),
-                submitted_form->field_count());
-      for (size_t i = 0; i < expected_submitted_field_types_.size(); ++i) {
-        SCOPED_TRACE(base::StringPrintf(
-            "Field %d with value %s", static_cast<int>(i),
-            base::UTF16ToUTF8(submitted_form->field(i)->value).c_str()));
-        const ServerFieldTypeSet& possible_types =
-            submitted_form->field(i)->possible_types();
-        EXPECT_EQ(expected_submitted_field_types_[i].size(),
-                  possible_types.size());
-        for (ServerFieldTypeSet::const_iterator it =
-                 expected_submitted_field_types_[i].begin();
-             it != expected_submitted_field_types_[i].end(); ++it) {
-          EXPECT_TRUE(possible_types.count(*it))
-              << "Expected type: " << AutofillType(*it).ToString();
-        }
-      }
-    }
-
-    AutofillManager::UploadFormDataAsyncCallback(
-        submitted_form, load_time, interaction_time, submission_time,
-        observed_submission);
-  }
-
-  // Resets the run loop so that it can wait for an asynchronous form
-  // submission to complete.
-  void ResetRunLoop() { run_loop_.reset(new base::RunLoop()); }
-
-  // Wait for the asynchronous calls within StartUploadProcess() to complete.
-  void WaitForAsyncUploadProcess() { run_loop_->Run(); }
-
-  void UploadFormData(const FormStructure& submitted_form,
-                      bool observed_submission) override {
-    submitted_form_signature_ = submitted_form.FormSignatureAsStr();
-
-    if (call_parent_upload_form_data_)
-      AutofillManager::UploadFormData(submitted_form, observed_submission);
-  }
-
-  const std::string GetSubmittedFormSignature() {
-    return submitted_form_signature_;
-  }
-
-  int GetPackedCreditCardID(int credit_card_id) {
-    std::string credit_card_guid =
-        base::StringPrintf("00000000-0000-0000-0000-%012d", credit_card_id);
-
-    return MakeFrontendID(credit_card_guid, std::string());
-  }
-
-  void AddSeenForm(std::unique_ptr<FormStructure> form) {
-    form->set_form_parsed_timestamp(base::TimeTicks::Now());
-    form_structures()->push_back(std::move(form));
-  }
-
-  void ClearFormStructures() { form_structures()->clear(); }
-
- private:
-  TestPersonalDataManager* personal_data_;        // Weak reference.
-  net::URLRequestContextGetter* context_getter_;  // Weak reference.
-  bool autofill_enabled_;
-  bool credit_card_enabled_;
-  bool expected_observed_submission_;
-  bool call_parent_upload_form_data_;
-
-  std::unique_ptr<base::RunLoop> run_loop_;
-
-  std::string submitted_form_signature_;
-  std::vector<ServerFieldTypeSet> expected_submitted_field_types_;
-
-  DISALLOW_COPY_AND_ASSIGN(TestAutofillManager);
-};
-
 class TestAutofillExternalDelegate : public AutofillExternalDelegate {
  public:
   explicit TestAutofillExternalDelegate(AutofillManager* autofill_manager,
@@ -827,30 +696,6 @@
   }
 };
 
-class TestFormStructure : public FormStructure {
- public:
-  explicit TestFormStructure(const FormData& form) : FormStructure(form) {}
-  ~TestFormStructure() override {}
-
-  void SetFieldTypes(const std::vector<ServerFieldType>& heuristic_types,
-                     const std::vector<ServerFieldType>& server_types) {
-    ASSERT_EQ(field_count(), heuristic_types.size());
-    ASSERT_EQ(field_count(), server_types.size());
-
-    for (size_t i = 0; i < field_count(); ++i) {
-      AutofillField* form_field = field(i);
-      ASSERT_TRUE(form_field);
-      form_field->set_heuristic_type(heuristic_types[i]);
-      form_field->set_overall_server_type(server_types[i]);
-    }
-
-    UpdateAutofillCount();
-  }
-
- private:
-  DISALLOW_COPY_AND_ASSIGN(TestFormStructure);
-};
-
 // Test that calling OnFormsSeen with an empty set of forms (such as when
 // reloading a page or when the renderer processes a set of forms but detects
 // no changes) does not load the forms again.
@@ -1330,7 +1175,7 @@
   FormsSeen(forms);
 
   // Disable Autofill.
-  autofill_manager_->set_autofill_enabled(false);
+  autofill_manager_->SetAutofillEnabled(false);
 
   const FormFieldData& field = form.fields[0];
   GetAutofillSuggestions(form, field);
@@ -4050,7 +3895,7 @@
   TestAutofillClient client;
   autofill_manager_.reset(
       new TestAutofillManager(autofill_driver_.get(), &client, nullptr));
-  autofill_manager_->set_autofill_enabled(false);
+  autofill_manager_->SetAutofillEnabled(false);
 
   // Set up our form data.
   FormData form;
@@ -4067,7 +3912,7 @@
   TestAutofillClient client;
   autofill_manager_.reset(
       new TestAutofillManager(autofill_driver_.get(), &client, nullptr));
-  autofill_manager_->set_autofill_enabled(false);
+  autofill_manager_->SetAutofillEnabled(false);
   autofill_manager_->SetExternalDelegate(external_delegate_.get());
 
   // Set up our form data.
@@ -4091,7 +3936,7 @@
   TestAutofillClient client;
   autofill_manager_.reset(
       new TestAutofillManager(autofill_driver_.get(), &client, nullptr));
-  autofill_manager_->set_autofill_enabled(false);
+  autofill_manager_->SetAutofillEnabled(false);
   autofill_manager_->SetExternalDelegate(external_delegate_.get());
 
   // Set up our form data.
@@ -4163,7 +4008,7 @@
   TestAutofillClient client;
   autofill_manager_.reset(
       new TestAutofillManager(autofill_driver_.get(), &client, nullptr));
-  autofill_manager_->set_autofill_enabled(false);
+  autofill_manager_->SetAutofillEnabled(false);
   autofill_manager_->SetExternalDelegate(external_delegate_.get());
 
   // Set up our form data.
@@ -4189,7 +4034,7 @@
   TestAutofillClient client;
   autofill_manager_.reset(
       new TestAutofillManager(autofill_driver_.get(), &client, nullptr));
-  autofill_manager_->set_autofill_enabled(false);
+  autofill_manager_->SetAutofillEnabled(false);
   autofill_manager_->SetExternalDelegate(external_delegate_.get());
 
   // Set up our form data.
@@ -4235,7 +4080,7 @@
   TestAutofillClient client;
   autofill_manager_.reset(
       new TestAutofillManager(autofill_driver_.get(), &client, nullptr));
-  autofill_manager_->set_autofill_enabled(false);
+  autofill_manager_->SetAutofillEnabled(false);
   autofill_manager_->SetExternalDelegate(external_delegate_.get());
 
   MockAutocompleteHistoryManager* m = RecreateMockAutocompleteHistoryManager();
@@ -4262,7 +4107,7 @@
   // |form_structure| will be owned by |autofill_manager_|.
   TestFormStructure* form_structure = new TestFormStructure(form);
   form_structure->DetermineHeuristicTypes(nullptr /* ukm_recorder */);
-  autofill_manager_->AddSeenForm(base::WrapUnique(form_structure));
+  autofill_manager_->AddSeenFormStructure(base::WrapUnique(form_structure));
 
   // Similarly, a second form.
   FormData form2;
@@ -4282,7 +4127,7 @@
 
   TestFormStructure* form_structure2 = new TestFormStructure(form2);
   form_structure2->DetermineHeuristicTypes(nullptr /* ukm_recorder */);
-  autofill_manager_->AddSeenForm(base::WrapUnique(form_structure2));
+  autofill_manager_->AddSeenFormStructure(base::WrapUnique(form_structure2));
 
   AutofillQueryResponseContents response;
   response.add_field()->set_overall_type_prediction(3);
@@ -4334,7 +4179,7 @@
   // |form_structure| will be owned by |autofill_manager_|.
   TestFormStructure* form_structure = new TestFormStructure(form);
   form_structure->DetermineHeuristicTypes(nullptr /* ukm_recorder */);
-  autofill_manager_->AddSeenForm(base::WrapUnique(form_structure));
+  autofill_manager_->AddSeenFormStructure(base::WrapUnique(form_structure));
 
   AutofillQueryResponseContents response;
   response.add_field()->set_overall_type_prediction(3);
@@ -4381,7 +4226,7 @@
     server_types.push_back(form_structure->field(i)->heuristic_type());
   }
   form_structure->SetFieldTypes(heuristic_types, server_types);
-  autofill_manager_->AddSeenForm(base::WrapUnique(form_structure));
+  autofill_manager_->AddSeenFormStructure(base::WrapUnique(form_structure));
 
   // Fill the form.
   const char guid[] = "00000000-0000-0000-0000-000000000001";
@@ -4438,12 +4283,12 @@
   type_set.insert(UNKNOWN_TYPE);
   std::vector<ServerFieldTypeSet> unknown_types(expected_types.size(),
                                                 type_set);
-  autofill_manager_->set_expected_submitted_field_types(unknown_types);
+  autofill_manager_->SetExpectedSubmittedFieldTypes(unknown_types);
   FormSubmitted(response_data);
   ASSERT_EQ(1u, personal_data_.GetProfiles().size());
 
   // The second submission should now have data by which to infer types.
-  autofill_manager_->set_expected_submitted_field_types(expected_types);
+  autofill_manager_->SetExpectedSubmittedFieldTypes(expected_types);
   FormSubmitted(response_data);
   ASSERT_EQ(1u, personal_data_.GetProfiles().size());
 }
@@ -4706,7 +4551,7 @@
     form.fields[i].value = expected_values[i];
   }
 
-  autofill_manager_->set_expected_submitted_field_types(expected_types);
+  autofill_manager_->SetExpectedSubmittedFieldTypes(expected_types);
   FormSubmitted(form);
 }
 
@@ -4961,8 +4806,8 @@
 
   // We will expect these types in the upload and no observed submission (the
   // callback initiated by WaitForAsyncUploadProcess checks these expectations.)
-  autofill_manager_->set_expected_submitted_field_types(expected_types);
-  autofill_manager_->set_expected_observed_submission(false);
+  autofill_manager_->SetExpectedSubmittedFieldTypes(expected_types);
+  autofill_manager_->SetExpectedObservedSubmission(false);
 
   // The fields are edited after calling FormsSeen on them. This is because
   // default values are not used for upload comparisons.
@@ -5014,8 +4859,8 @@
 
   // We will expect these types in the upload and no observed submission. (the
   // callback initiated by WaitForAsyncUploadProcess checks these expectations.)
-  autofill_manager_->set_expected_submitted_field_types(expected_types);
-  autofill_manager_->set_expected_observed_submission(false);
+  autofill_manager_->SetExpectedSubmittedFieldTypes(expected_types);
+  autofill_manager_->SetExpectedObservedSubmission(false);
 
   // The fields are edited after calling FormsSeen on them. This is because
   // default values are not used for upload comparisons.
@@ -5068,8 +4913,8 @@
 
   // We will expect these types in the upload and no observed submission. (the
   // callback initiated by WaitForAsyncUploadProcess checks these expectations.)
-  autofill_manager_->set_expected_submitted_field_types(expected_types);
-  autofill_manager_->set_expected_observed_submission(false);
+  autofill_manager_->SetExpectedSubmittedFieldTypes(expected_types);
+  autofill_manager_->SetExpectedObservedSubmission(false);
 
   // Form was autofilled with user data.
   form.fields[0].value = ASCIIToUTF16("Elvis");
@@ -5263,7 +5108,7 @@
 }
 
 TEST_F(AutofillManagerTest, CreditCardDisabledDoesNotFillFormData) {
-  autofill_manager_->set_credit_card_enabled(false);
+  autofill_manager_->SetCreditCardEnabled(false);
 
   // Set up our form data.
   FormData form;
@@ -5281,7 +5126,7 @@
 }
 
 TEST_F(AutofillManagerTest, CreditCardDisabledDoesNotSuggest) {
-  autofill_manager_->set_credit_card_enabled(false);
+  autofill_manager_->SetCreditCardEnabled(false);
 
   // Set up our form data.
   FormData form;
@@ -5716,7 +5561,7 @@
   EXPECT_TRUE(autofill_manager_->ShouldUploadForm(FormStructure(form)));
 
   // Autofill disabled.
-  autofill_manager_->set_autofill_enabled(false);
+  autofill_manager_->SetAutofillEnabled(false);
   EXPECT_FALSE(autofill_manager_->ShouldUploadForm(FormStructure(form)));
 }
 
@@ -5890,7 +5735,7 @@
   const std::vector<ServerFieldType> server_types{NAME_FIRST, NAME_MIDDLE,
                                                   NAME_LAST};
   form_structure->SetFieldTypes(heuristic_types, server_types);
-  autofill_manager_->AddSeenForm(std::move(form_structure));
+  autofill_manager_->AddSeenFormStructure(std::move(form_structure));
 
   // Make sure the form can be autofilled.
   for (const FormFieldData& field : form.fields) {
@@ -5980,9 +5825,9 @@
 
   // We will expect these types in the upload and no observed submission. (the
   // callback initiated by WaitForAsyncUploadProcess checks these expectations.)
-  autofill_manager_->set_expected_submitted_field_types(expected_types);
-  autofill_manager_->set_expected_observed_submission(true);
-  autofill_manager_->set_call_parent_upload_form_data(true);
+  autofill_manager_->SetExpectedSubmittedFieldTypes(expected_types);
+  autofill_manager_->SetExpectedObservedSubmission(true);
+  autofill_manager_->SetCallParentUploadFormData(true);
   autofill_manager_->ResetRunLoop();
 
   std::unique_ptr<FormStructure> form_structure(new FormStructure(form));
@@ -6040,9 +5885,9 @@
 
   // Setup expectation on the test autofill manager (these are validated
   // during the simlulated submit).
-  autofill_manager_->set_expected_submitted_field_types({{CREDIT_CARD_NUMBER}});
-  autofill_manager_->set_expected_observed_submission(true);
-  autofill_manager_->set_call_parent_upload_form_data(true);
+  autofill_manager_->SetExpectedSubmittedFieldTypes({{CREDIT_CARD_NUMBER}});
+  autofill_manager_->SetExpectedObservedSubmission(true);
+  autofill_manager_->SetCallParentUploadFormData(true);
   EXPECT_CALL(*download_manager_,
               StartUploadRequest(_, false, _, std::string(), true));
 
diff --git a/components/autofill/core/browser/autofill_metrics_unittest.cc b/components/autofill/core/browser/autofill_metrics_unittest.cc
index 54e9887..0481bd01 100644
--- a/components/autofill/core/browser/autofill_metrics_unittest.cc
+++ b/components/autofill/core/browser/autofill_metrics_unittest.cc
@@ -13,9 +13,7 @@
 #include "base/feature_list.h"
 #include "base/macros.h"
 #include "base/metrics/metrics_hashes.h"
-#include "base/run_loop.h"
 #include "base/strings/string16.h"
-#include "base/strings/utf_string_conversions.h"
 #include "base/test/histogram_tester.h"
 #include "base/test/scoped_feature_list.h"
 #include "base/test/scoped_task_environment.h"
@@ -23,13 +21,13 @@
 #include "base/time/time.h"
 #include "components/autofill/core/browser/autofill_experiments.h"
 #include "components/autofill/core/browser/autofill_external_delegate.h"
-#include "components/autofill/core/browser/autofill_manager.h"
 #include "components/autofill/core/browser/autofill_test_utils.h"
-#include "components/autofill/core/browser/payments/payments_client.h"
 #include "components/autofill/core/browser/personal_data_manager.h"
 #include "components/autofill/core/browser/popup_item_ids.h"
 #include "components/autofill/core/browser/test_autofill_client.h"
 #include "components/autofill/core/browser/test_autofill_driver.h"
+#include "components/autofill/core/browser/test_autofill_manager.h"
+#include "components/autofill/core/browser/test_form_structure.h"
 #include "components/autofill/core/browser/test_personal_data_manager.h"
 #include "components/autofill/core/browser/webdata/autofill_webdata_service.h"
 #include "components/autofill/core/common/autofill_clock.h"
@@ -78,103 +76,6 @@
 using ExpectedUkmMetrics =
     std::vector<std::vector<std::pair<const char*, int64_t>>>;
 
-class TestFormStructure : public FormStructure {
- public:
-  explicit TestFormStructure(const FormData& form) : FormStructure(form) {}
-  ~TestFormStructure() override {}
-
-  void SetFieldTypes(const std::vector<ServerFieldType>& heuristic_types,
-                     const std::vector<ServerFieldType>& server_types) {
-    ASSERT_EQ(field_count(), heuristic_types.size());
-    ASSERT_EQ(field_count(), server_types.size());
-
-    for (size_t i = 0; i < field_count(); ++i) {
-      AutofillField* form_field = field(i);
-      ASSERT_TRUE(form_field);
-      form_field->set_heuristic_type(heuristic_types[i]);
-      form_field->set_overall_server_type(server_types[i]);
-    }
-
-    UpdateAutofillCount();
-  }
-
- private:
-  DISALLOW_COPY_AND_ASSIGN(TestFormStructure);
-};
-
-class TestAutofillManager : public AutofillManager {
- public:
-  TestAutofillManager(AutofillDriver* driver,
-                      AutofillClient* autofill_client,
-                      TestPersonalDataManager* personal_manager)
-      : AutofillManager(driver, autofill_client, personal_manager),
-        autofill_enabled_(true) {}
-  ~TestAutofillManager() override {}
-
-  bool IsAutofillEnabled() const override { return autofill_enabled_; }
-
-  void set_autofill_enabled(bool autofill_enabled) {
-    autofill_enabled_ = autofill_enabled;
-  }
-
-  void AddSeenForm(const FormData& form,
-                   const std::vector<ServerFieldType>& heuristic_types,
-                   const std::vector<ServerFieldType>& server_types) {
-    FormData empty_form = form;
-    for (size_t i = 0; i < empty_form.fields.size(); ++i) {
-      empty_form.fields[i].value = base::string16();
-    }
-
-    std::unique_ptr<TestFormStructure> form_structure =
-        std::make_unique<TestFormStructure>(empty_form);
-    form_structure->SetFieldTypes(heuristic_types, server_types);
-    form_structure->set_form_parsed_timestamp(TimeTicks::Now());
-    form_structures()->push_back(std::move(form_structure));
-
-    form_interactions_ukm_logger()->OnFormsParsed(
-        form.main_frame_origin.GetURL());
-  }
-
-  // Calls AutofillManager::OnWillSubmitForm and waits for it to complete.
-  void WillSubmitForm(const FormData& form, const TimeTicks& timestamp) {
-    ResetRunLoop();
-    if (!OnWillSubmitForm(form, timestamp))
-      return;
-
-    // Wait for the asynchronous OnWillSubmitForm() call to complete.
-    RunRunLoop();
-  }
-
-  // Calls both AutofillManager::OnWillSubmitForm and
-  // AutofillManager::OnFormSubmitted.
-  void SubmitForm(const FormData& form, const TimeTicks& timestamp) {
-    WillSubmitForm(form, timestamp);
-    OnFormSubmitted(form);
-  }
-
-  // Control the run loop from within tests.
-  void ResetRunLoop() { run_loop_ = std::make_unique<base::RunLoop>(); }
-  void RunRunLoop() { run_loop_->Run(); }
-
-  void UploadFormDataAsyncCallback(const FormStructure* submitted_form,
-                                   const TimeTicks& load_time,
-                                   const TimeTicks& interaction_time,
-                                   const TimeTicks& submission_time,
-                                   bool observed_submission) override {
-    run_loop_->Quit();
-
-    AutofillManager::UploadFormDataAsyncCallback(
-        submitted_form, load_time, interaction_time, submission_time,
-        observed_submission);
-  }
-
- private:
-  bool autofill_enabled_;
-  std::unique_ptr<base::RunLoop> run_loop_;
-
-  DISALLOW_COPY_AND_ASSIGN(TestAutofillManager);
-};
-
 void VerifyDeveloperEngagementUkm(
     const ukm::TestAutoSetUkmRecorder& ukm_recorder,
     const FormData& form,
@@ -5188,7 +5089,7 @@
 // Test that we log that Autofill is enabled when filling a form.
 TEST_F(AutofillMetricsTest, AutofillIsEnabledAtPageLoad) {
   base::HistogramTester histogram_tester;
-  autofill_manager_->set_autofill_enabled(true);
+  autofill_manager_->SetAutofillEnabled(true);
   autofill_manager_->OnFormsSeen(std::vector<FormData>(), TimeTicks());
   histogram_tester.ExpectUniqueSample("Autofill.IsEnabled.PageLoad", true, 1);
 }
@@ -5196,7 +5097,7 @@
 // Test that we log that Autofill is disabled when filling a form.
 TEST_F(AutofillMetricsTest, AutofillIsDisabledAtPageLoad) {
   base::HistogramTester histogram_tester;
-  autofill_manager_->set_autofill_enabled(false);
+  autofill_manager_->SetAutofillEnabled(false);
   autofill_manager_->OnFormsSeen(std::vector<FormData>(), TimeTicks());
   histogram_tester.ExpectUniqueSample("Autofill.IsEnabled.PageLoad", false, 1);
 }
diff --git a/components/autofill/core/browser/credit_card_save_manager_unittest.cc b/components/autofill/core/browser/credit_card_save_manager_unittest.cc
index 7fe197c1..d50666f3 100644
--- a/components/autofill/core/browser/credit_card_save_manager_unittest.cc
+++ b/components/autofill/core/browser/credit_card_save_manager_unittest.cc
@@ -16,9 +16,6 @@
 
 #include "base/guid.h"
 #include "base/metrics/metrics_hashes.h"
-#include "base/run_loop.h"
-#include "base/strings/stringprintf.h"
-#include "base/strings/utf_string_conversions.h"
 #include "base/test/histogram_tester.h"
 #include "base/test/scoped_feature_list.h"
 #include "base/test/scoped_task_environment.h"
@@ -26,19 +23,17 @@
 #include "base/time/time.h"
 #include "build/build_config.h"
 #include "components/autofill/core/browser/autofill_experiments.h"
-#include "components/autofill/core/browser/autofill_manager.h"
 #include "components/autofill/core/browser/autofill_metrics.h"
 #include "components/autofill/core/browser/autofill_profile.h"
 #include "components/autofill/core/browser/autofill_test_utils.h"
 #include "components/autofill/core/browser/credit_card.h"
-#include "components/autofill/core/browser/form_structure.h"
 #include "components/autofill/core/browser/payments/test_payments_client.h"
 #include "components/autofill/core/browser/personal_data_manager.h"
 #include "components/autofill/core/browser/test_autofill_client.h"
 #include "components/autofill/core/browser/test_autofill_clock.h"
 #include "components/autofill/core/browser/test_autofill_driver.h"
+#include "components/autofill/core/browser/test_autofill_manager.h"
 #include "components/autofill/core/browser/test_credit_card_save_manager.h"
-#include "components/autofill/core/browser/test_form_data_importer.h"
 #include "components/autofill/core/browser/test_personal_data_manager.h"
 #include "components/autofill/core/browser/validation.h"
 #include "components/autofill/core/browser/webdata/autofill_webdata_service.h"
@@ -56,7 +51,6 @@
 #include "url/gurl.h"
 
 using base::ASCIIToUTF16;
-using base::UTF8ToUTF16;
 using testing::_;
 using testing::AtLeast;
 using testing::Return;
@@ -91,92 +85,6 @@
   DISALLOW_COPY_AND_ASSIGN(MockAutofillClient);
 };
 
-class TestAutofillManager : public AutofillManager {
- public:
-  TestAutofillManager(AutofillDriver* driver,
-                      AutofillClient* client,
-                      CreditCardSaveManager* credit_card_save_manager,
-                      payments::TestPaymentsClient* payments_client,
-                      TestPersonalDataManager* personal_data)
-      : AutofillManager(driver, client, personal_data),
-        personal_data_(personal_data),
-        test_form_data_importer_(
-            new TestFormDataImporter(client,
-                                     payments_client,
-                                     credit_card_save_manager,
-                                     personal_data,
-                                     "en-US")) {
-    set_payments_client(payments_client);
-    set_form_data_importer(test_form_data_importer_);
-  }
-  ~TestAutofillManager() override {}
-
-  bool IsAutofillEnabled() const override { return true; }
-
-  bool IsCreditCardAutofillEnabled() override { return credit_card_enabled_; }
-
-  void SetCreditCardEnabled(bool credit_card_enabled) {
-    credit_card_enabled_ = credit_card_enabled;
-    if (!credit_card_enabled_) {
-      // Credit card data is refreshed when this pref is changed.
-      personal_data_->ClearCreditCards();
-    }
-  }
-
-  void UploadFormDataAsyncCallback(const FormStructure* submitted_form,
-                                   const base::TimeTicks& load_time,
-                                   const base::TimeTicks& interaction_time,
-                                   const base::TimeTicks& submission_time,
-                                   bool observed_submission) override {
-    run_loop_->Quit();
-
-    EXPECT_TRUE(observed_submission);
-
-    // If we have expected field types set, make sure they match.
-    if (!expected_submitted_field_types_.empty()) {
-      ASSERT_EQ(expected_submitted_field_types_.size(),
-                submitted_form->field_count());
-      for (size_t i = 0; i < expected_submitted_field_types_.size(); ++i) {
-        SCOPED_TRACE(base::StringPrintf(
-            "Field %d with value %s", static_cast<int>(i),
-            base::UTF16ToUTF8(submitted_form->field(i)->value).c_str()));
-        const ServerFieldTypeSet& possible_types =
-            submitted_form->field(i)->possible_types();
-        EXPECT_EQ(expected_submitted_field_types_[i].size(),
-                  possible_types.size());
-        for (ServerFieldTypeSet::const_iterator it =
-                 expected_submitted_field_types_[i].begin();
-             it != expected_submitted_field_types_[i].end(); ++it) {
-          EXPECT_TRUE(possible_types.count(*it))
-              << "Expected type: " << AutofillType(*it).ToString();
-        }
-      }
-    }
-
-    AutofillManager::UploadFormDataAsyncCallback(
-        submitted_form, load_time, interaction_time, submission_time,
-        observed_submission);
-  }
-
-  // Resets the run loop so that it can wait for an asynchronous form
-  // submission to complete.
-  void ResetRunLoop() { run_loop_ = std::make_unique<base::RunLoop>(); }
-
-  // Wait for the asynchronous calls within StartUploadProcess() to complete.
-  void WaitForAsyncUploadProcess() { run_loop_->Run(); }
-
- private:
-  TestPersonalDataManager* personal_data_;        // Weak reference.
-  TestFormDataImporter* test_form_data_importer_;
-  bool credit_card_enabled_ = true;
-
-  std::unique_ptr<base::RunLoop> run_loop_;
-
-  std::vector<ServerFieldTypeSet> expected_submitted_field_types_;
-
-  DISALLOW_COPY_AND_ASSIGN(TestAutofillManager);
-};
-
 }  // anonymous namespace
 
 class CreditCardSaveManagerTest : public testing::Test {
@@ -199,8 +107,9 @@
         new TestCreditCardSaveManager(autofill_driver_.get(), &autofill_client_,
                                       payments_client_, &personal_data_);
     autofill_manager_.reset(new TestAutofillManager(
-        autofill_driver_.get(), &autofill_client_, credit_card_save_manager_,
-        payments_client_, &personal_data_));
+        autofill_driver_.get(), &autofill_client_, &personal_data_,
+        credit_card_save_manager_, payments_client_));
+    autofill_manager_->SetExpectedObservedSubmission(true);
   }
 
   void TearDown() override {
diff --git a/components/autofill/core/browser/test_autofill_manager.cc b/components/autofill/core/browser/test_autofill_manager.cc
new file mode 100644
index 0000000..f368727
--- /dev/null
+++ b/components/autofill/core/browser/test_autofill_manager.cc
@@ -0,0 +1,192 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/autofill/core/browser/test_autofill_manager.h"
+
+#include "base/strings/stringprintf.h"
+#include "base/strings/utf_string_conversions.h"
+#include "components/autofill/core/browser/field_types.h"
+#include "components/autofill/core/browser/payments/payments_client.h"
+#include "components/autofill/core/browser/test_form_structure.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace autofill {
+
+TestAutofillManager::TestAutofillManager(AutofillDriver* driver,
+                                         AutofillClient* client,
+                                         TestPersonalDataManager* personal_data)
+    : AutofillManager(driver, client, personal_data),
+      personal_data_(personal_data),
+      context_getter_(driver->GetURLRequestContext()) {
+  set_payments_client(new payments::PaymentsClient(
+      context_getter_, client->GetPrefs(), client->GetIdentityProvider(),
+      /*unmask_delegate=*/this,
+      /*save_delegate=*/nullptr));
+}
+
+TestAutofillManager::TestAutofillManager(
+    AutofillDriver* driver,
+    AutofillClient* client,
+    TestPersonalDataManager* personal_data,
+    CreditCardSaveManager* credit_card_save_manager,
+    payments::TestPaymentsClient* payments_client)
+    : AutofillManager(driver, client, personal_data),
+      personal_data_(personal_data),
+      test_form_data_importer_(
+          new TestFormDataImporter(client,
+                                   payments_client,
+                                   credit_card_save_manager,
+                                   personal_data,
+                                   "en-US")) {
+  set_payments_client(payments_client);
+  set_form_data_importer(test_form_data_importer_);
+}
+
+TestAutofillManager::~TestAutofillManager() {}
+
+bool TestAutofillManager::IsAutofillEnabled() const {
+  return autofill_enabled_;
+}
+
+bool TestAutofillManager::IsCreditCardAutofillEnabled() {
+  return credit_card_enabled_;
+}
+
+void TestAutofillManager::UploadFormData(const FormStructure& submitted_form,
+                                         bool observed_submission) {
+  submitted_form_signature_ = submitted_form.FormSignatureAsStr();
+
+  if (call_parent_upload_form_data_)
+    AutofillManager::UploadFormData(submitted_form, observed_submission);
+}
+
+void TestAutofillManager::UploadFormDataAsyncCallback(
+    const FormStructure* submitted_form,
+    const base::TimeTicks& load_time,
+    const base::TimeTicks& interaction_time,
+    const base::TimeTicks& submission_time,
+    bool observed_submission) {
+  run_loop_->Quit();
+
+  if (expected_observed_submission_ != base::nullopt)
+    EXPECT_EQ(expected_observed_submission_, observed_submission);
+
+  // If we have expected field types set, make sure they match.
+  if (!expected_submitted_field_types_.empty()) {
+    ASSERT_EQ(expected_submitted_field_types_.size(),
+              submitted_form->field_count());
+    for (size_t i = 0; i < expected_submitted_field_types_.size(); ++i) {
+      SCOPED_TRACE(base::StringPrintf(
+          "Field %d with value %s", static_cast<int>(i),
+          base::UTF16ToUTF8(submitted_form->field(i)->value).c_str()));
+      const ServerFieldTypeSet& possible_types =
+          submitted_form->field(i)->possible_types();
+      EXPECT_EQ(expected_submitted_field_types_[i].size(),
+                possible_types.size());
+      for (ServerFieldTypeSet::const_iterator it =
+               expected_submitted_field_types_[i].begin();
+           it != expected_submitted_field_types_[i].end(); ++it) {
+        EXPECT_TRUE(possible_types.count(*it))
+            << "Expected type: " << AutofillType(*it).ToString();
+      }
+    }
+  }
+
+  AutofillManager::UploadFormDataAsyncCallback(
+      submitted_form, load_time, interaction_time, submission_time,
+      observed_submission);
+}
+
+void TestAutofillManager::ResetRunLoop() {
+  run_loop_.reset(new base::RunLoop());
+}
+
+void TestAutofillManager::RunRunLoop() {
+  run_loop_->Run();
+}
+
+void TestAutofillManager::WaitForAsyncUploadProcess() {
+  run_loop_->Run();
+}
+
+int TestAutofillManager::GetPackedCreditCardID(int credit_card_id) {
+  std::string credit_card_guid =
+      base::StringPrintf("00000000-0000-0000-0000-%012d", credit_card_id);
+
+  return MakeFrontendID(credit_card_guid, std::string());
+}
+
+void TestAutofillManager::AddSeenForm(
+    const FormData& form,
+    const std::vector<ServerFieldType>& heuristic_types,
+    const std::vector<ServerFieldType>& server_types) {
+  FormData empty_form = form;
+  for (size_t i = 0; i < empty_form.fields.size(); ++i) {
+    empty_form.fields[i].value = base::string16();
+  }
+
+  std::unique_ptr<TestFormStructure> form_structure =
+      std::make_unique<TestFormStructure>(empty_form);
+  form_structure->SetFieldTypes(heuristic_types, server_types);
+  AddSeenFormStructure(std::move(form_structure));
+
+  form_interactions_ukm_logger()->OnFormsParsed(
+      form.main_frame_origin.GetURL());
+}
+
+void TestAutofillManager::AddSeenFormStructure(
+    std::unique_ptr<FormStructure> form_structure) {
+  form_structure->set_form_parsed_timestamp(base::TimeTicks::Now());
+  form_structures()->push_back(std::move(form_structure));
+}
+
+void TestAutofillManager::WillSubmitForm(const FormData& form,
+                                         const TimeTicks& timestamp) {
+  ResetRunLoop();
+  if (!OnWillSubmitForm(form, timestamp))
+    return;
+
+  // Wait for the asynchronous OnWillSubmitForm() call to complete.
+  RunRunLoop();
+}
+
+void TestAutofillManager::SubmitForm(const FormData& form,
+                                     const TimeTicks& timestamp) {
+  WillSubmitForm(form, timestamp);
+  OnFormSubmitted(form);
+}
+
+void TestAutofillManager::ClearFormStructures() {
+  form_structures()->clear();
+}
+
+const std::string TestAutofillManager::GetSubmittedFormSignature() {
+  return submitted_form_signature_;
+}
+
+void TestAutofillManager::SetAutofillEnabled(bool autofill_enabled) {
+  autofill_enabled_ = autofill_enabled;
+}
+
+void TestAutofillManager::SetCreditCardEnabled(bool credit_card_enabled) {
+  credit_card_enabled_ = credit_card_enabled;
+  if (!credit_card_enabled_)
+    // Credit card data is refreshed when this pref is changed.
+    personal_data_->ClearCreditCards();
+}
+
+void TestAutofillManager::SetExpectedSubmittedFieldTypes(
+    const std::vector<ServerFieldTypeSet>& expected_types) {
+  expected_submitted_field_types_ = expected_types;
+}
+
+void TestAutofillManager::SetExpectedObservedSubmission(bool expected) {
+  expected_observed_submission_ = expected;
+}
+
+void TestAutofillManager::SetCallParentUploadFormData(bool value) {
+  call_parent_upload_form_data_ = value;
+}
+
+}  // namespace autofill
diff --git a/components/autofill/core/browser/test_autofill_manager.h b/components/autofill/core/browser/test_autofill_manager.h
new file mode 100644
index 0000000..5ad28798e3
--- /dev/null
+++ b/components/autofill/core/browser/test_autofill_manager.h
@@ -0,0 +1,114 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef COMPONENTS_AUTOFILL_CORE_BROWSER_TEST_AUTOFILL_MANAGER_H_
+#define COMPONENTS_AUTOFILL_CORE_BROWSER_TEST_AUTOFILL_MANAGER_H_
+
+#include <string>
+#include <vector>
+
+#include "base/optional.h"
+#include "base/run_loop.h"
+#include "components/autofill/core/browser/autofill_manager.h"
+#include "components/autofill/core/browser/payments/test_payments_client.h"
+#include "components/autofill/core/browser/test_form_data_importer.h"
+#include "components/autofill/core/browser/test_personal_data_manager.h"
+
+using base::TimeTicks;
+
+namespace net {
+class URLRequestContextGetter;
+}
+
+namespace autofill {
+
+class AutofillClient;
+class AutofillDriver;
+class FormStructure;
+
+class TestAutofillManager : public AutofillManager {
+ public:
+  // Called by AutofillManagerTest and AutofillMetricsTest.
+  TestAutofillManager(AutofillDriver* driver,
+                      AutofillClient* client,
+                      TestPersonalDataManager* personal_data);
+  // Called by CreditCardSaveManagerTest.
+  TestAutofillManager(AutofillDriver* driver,
+                      AutofillClient* client,
+                      TestPersonalDataManager* personal_data,
+                      CreditCardSaveManager* credit_card_save_manager,
+                      payments::TestPaymentsClient* payments_client);
+  ~TestAutofillManager() override;
+
+  // AutofillManager overrides.
+  bool IsAutofillEnabled() const override;
+  bool IsCreditCardAutofillEnabled() override;
+  void UploadFormData(const FormStructure& submitted_form,
+                      bool observed_submission) override;
+  void UploadFormDataAsyncCallback(const FormStructure* submitted_form,
+                                   const base::TimeTicks& load_time,
+                                   const base::TimeTicks& interaction_time,
+                                   const base::TimeTicks& submission_time,
+                                   bool observed_submission) override;
+
+  // Unique to TestAutofillManager:
+
+  // Resets the run loop so that it can wait for an asynchronous form
+  // submission to complete.
+  void ResetRunLoop();
+  void RunRunLoop();
+
+  // Wait for the asynchronous calls within StartUploadProcess() to complete.
+  void WaitForAsyncUploadProcess();
+
+  int GetPackedCreditCardID(int credit_card_id);
+
+  void AddSeenForm(const FormData& form,
+                   const std::vector<ServerFieldType>& heuristic_types,
+                   const std::vector<ServerFieldType>& server_types);
+
+  void AddSeenFormStructure(std::unique_ptr<FormStructure> form_structure);
+
+  // Calls AutofillManager::OnWillSubmitForm and waits for it to complete.
+  void WillSubmitForm(const FormData& form, const TimeTicks& timestamp);
+
+  // Calls both AutofillManager::OnWillSubmitForm and
+  // AutofillManager::OnFormSubmitted.
+  void SubmitForm(const FormData& form, const TimeTicks& timestamp);
+
+  void ClearFormStructures();
+
+  const std::string GetSubmittedFormSignature();
+
+  void SetAutofillEnabled(bool autofill_enabled);
+
+  void SetCreditCardEnabled(bool credit_card_enabled);
+
+  void SetExpectedSubmittedFieldTypes(
+      const std::vector<ServerFieldTypeSet>& expected_types);
+
+  void SetExpectedObservedSubmission(bool expected);
+
+  void SetCallParentUploadFormData(bool value);
+
+ private:
+  TestPersonalDataManager* personal_data_;                  // Weak reference.
+  net::URLRequestContextGetter* context_getter_ = nullptr;  // Weak reference.
+  TestFormDataImporter* test_form_data_importer_ = nullptr;
+  bool autofill_enabled_ = true;
+  bool credit_card_enabled_ = true;
+  bool call_parent_upload_form_data_ = false;
+  base::Optional<bool> expected_observed_submission_;
+
+  std::unique_ptr<base::RunLoop> run_loop_;
+
+  std::string submitted_form_signature_;
+  std::vector<ServerFieldTypeSet> expected_submitted_field_types_;
+
+  DISALLOW_COPY_AND_ASSIGN(TestAutofillManager);
+};
+
+}  // namespace autofill
+
+#endif  // COMPONENTS_AUTOFILL_CORE_BROWSER_TEST_AUTOFILL_MANAGER_H_
diff --git a/components/autofill/core/browser/test_form_structure.cc b/components/autofill/core/browser/test_form_structure.cc
new file mode 100644
index 0000000..b31106c
--- /dev/null
+++ b/components/autofill/core/browser/test_form_structure.cc
@@ -0,0 +1,32 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/autofill/core/browser/test_form_structure.h"
+
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace autofill {
+
+TestFormStructure::TestFormStructure(const FormData& form)
+    : FormStructure(form) {}
+
+TestFormStructure::~TestFormStructure() {}
+
+void TestFormStructure::SetFieldTypes(
+    const std::vector<ServerFieldType>& heuristic_types,
+    const std::vector<ServerFieldType>& server_types) {
+  ASSERT_EQ(field_count(), heuristic_types.size());
+  ASSERT_EQ(field_count(), server_types.size());
+
+  for (size_t i = 0; i < field_count(); ++i) {
+    AutofillField* form_field = field(i);
+    ASSERT_TRUE(form_field);
+    form_field->set_heuristic_type(heuristic_types[i]);
+    form_field->set_overall_server_type(server_types[i]);
+  }
+
+  UpdateAutofillCount();
+}
+
+}  // namespace autofill
diff --git a/components/autofill/core/browser/test_form_structure.h b/components/autofill/core/browser/test_form_structure.h
new file mode 100644
index 0000000..c9cfc83
--- /dev/null
+++ b/components/autofill/core/browser/test_form_structure.h
@@ -0,0 +1,28 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef COMPONENTS_AUTOFILL_CORE_BROWSER_TEST_FORM_STRUCTURE_H_
+#define COMPONENTS_AUTOFILL_CORE_BROWSER_TEST_FORM_STRUCTURE_H_
+
+#include <vector>
+
+#include "components/autofill/core/browser/form_structure.h"
+
+namespace autofill {
+
+class TestFormStructure : public FormStructure {
+ public:
+  explicit TestFormStructure(const FormData& form);
+  ~TestFormStructure() override;
+
+  void SetFieldTypes(const std::vector<ServerFieldType>& heuristic_types,
+                     const std::vector<ServerFieldType>& server_types);
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(TestFormStructure);
+};
+
+}  // namespace autofill
+
+#endif  // COMPONENTS_AUTOFILL_CORE_BROWSER_TEST_FORM_STRUCTURE_H_
diff --git a/components/supervised_user_error_page/resources/supervised_user_block_interstitial.js b/components/supervised_user_error_page/resources/supervised_user_block_interstitial.js
index 164bbac..fba80f8 100644
--- a/components/supervised_user_error_page/resources/supervised_user_block_interstitial.js
+++ b/components/supervised_user_error_page/resources/supervised_user_block_interstitial.js
@@ -66,8 +66,8 @@
       $('custodian-avatar-img').style.content =
           makeImageSet(avatarURL1x, avatarURL2x);
     }
-    $('custodian-name').innerHTML = custodianName;
-    $('custodian-email').innerHTML = loadTimeData.getString('custodianEmail');
+    $('custodian-name').textContent = custodianName;
+    $('custodian-email').textContent = loadTimeData.getString('custodianEmail');
     var secondAvatarURL1x = loadTimeData.getString('secondAvatarURL1x');
     var secondAvatarURL2x = loadTimeData.getString('secondAvatarURL2x');
     var secondCustodianName = loadTimeData.getString('secondCustodianName');
@@ -78,8 +78,8 @@
         $('second-custodian-avatar-img').style.content =
             makeImageSet(secondAvatarURL1x, secondAvatarURL2x);
       }
-      $('second-custodian-name').innerHTML = secondCustodianName;
-      $('second-custodian-email').innerHTML = loadTimeData.getString(
+      $('second-custodian-name').textContent = secondCustodianName;
+      $('second-custodian-email').textContent = loadTimeData.getString(
           'secondCustodianEmail');
     }
   }
diff --git a/content/browser/BUILD.gn b/content/browser/BUILD.gn
index 9285fc7..a0118f9a 100644
--- a/content/browser/BUILD.gn
+++ b/content/browser/BUILD.gn
@@ -956,8 +956,6 @@
     "keyboard_lock/keyboard_lock_service_impl.h",
     "leveldb_wrapper_impl.cc",
     "leveldb_wrapper_impl.h",
-    "loader/async_resource_handler.cc",
-    "loader/async_resource_handler.h",
     "loader/cross_site_document_resource_handler.cc",
     "loader/cross_site_document_resource_handler.h",
     "loader/detachable_resource_handler.cc",
@@ -1003,8 +1001,6 @@
     "loader/resource_loader.cc",
     "loader/resource_loader.h",
     "loader/resource_loader_delegate.h",
-    "loader/resource_message_delegate.cc",
-    "loader/resource_message_delegate.h",
     "loader/resource_message_filter.cc",
     "loader/resource_message_filter.h",
     "loader/resource_request_info_impl.cc",
@@ -1019,8 +1015,6 @@
     "loader/stream_resource_handler.h",
     "loader/stream_writer.cc",
     "loader/stream_writer.h",
-    "loader/sync_resource_handler.cc",
-    "loader/sync_resource_handler.h",
     "loader/temporary_file_stream.cc",
     "loader/temporary_file_stream.h",
     "loader/throttling_resource_handler.cc",
@@ -1429,6 +1423,8 @@
     "renderer_host/render_widget_host_view_mac_dictionary_helper.mm",
     "renderer_host/render_widget_host_view_mac_editcommand_helper.h",
     "renderer_host/render_widget_host_view_mac_editcommand_helper.mm",
+    "renderer_host/render_widget_targeter.cc",
+    "renderer_host/render_widget_targeter.h",
     "renderer_host/text_input_client_mac.h",
     "renderer_host/text_input_client_mac.mm",
     "renderer_host/text_input_client_message_filter.h",
diff --git a/content/browser/frame_host/render_frame_host_impl.cc b/content/browser/frame_host/render_frame_host_impl.cc
index 31562f3..ceddb61 100644
--- a/content/browser/frame_host/render_frame_host_impl.cc
+++ b/content/browser/frame_host/render_frame_host_impl.cc
@@ -1246,7 +1246,10 @@
       render_widget_host_->SetWidgetInputHandler(std::move(widget_handler),
                                                  std::move(host_request));
     }
-
+    viz::mojom::InputTargetClientPtr input_target_client;
+    remote_interfaces_->GetInterface(&input_target_client);
+    input_target_client_ = input_target_client.get();
+    render_widget_host_->SetInputTargetClient(std::move(input_target_client));
     render_widget_host_->InitForFrame();
   }
 
@@ -3645,7 +3648,6 @@
   } else {
     legacy_frame_input_handler_.reset(new LegacyIPCFrameInputHandler(this));
   }
-  remote_interfaces_->GetInterface(&input_target_client_);
 }
 
 void RenderFrameHostImpl::InvalidateMojoConnection() {
diff --git a/content/browser/frame_host/render_frame_host_impl.h b/content/browser/frame_host/render_frame_host_impl.h
index f4b1a4a..0370f8e 100644
--- a/content/browser/frame_host/render_frame_host_impl.h
+++ b/content/browser/frame_host/render_frame_host_impl.h
@@ -264,7 +264,7 @@
   mojom::FrameInputHandler* GetFrameInputHandler();
 
   viz::mojom::InputTargetClient* GetInputTargetClient() {
-    return input_target_client_.get();
+    return input_target_client_;
   }
 
   // Creates a RenderFrame in the renderer process.
@@ -1367,7 +1367,7 @@
   // have created one yet.
   base::Optional<base::UnguessableToken> overlay_routing_token_;
 
-  viz::mojom::InputTargetClientPtr input_target_client_;
+  viz::mojom::InputTargetClient* input_target_client_ = nullptr;
   mojom::FrameInputHandlerPtr frame_input_handler_;
   std::unique_ptr<LegacyIPCFrameInputHandler> legacy_frame_input_handler_;
 
diff --git a/content/browser/loader/async_resource_handler.cc b/content/browser/loader/async_resource_handler.cc
deleted file mode 100644
index aeea9dc4..0000000
--- a/content/browser/loader/async_resource_handler.cc
+++ /dev/null
@@ -1,440 +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/browser/loader/async_resource_handler.h"
-
-#include <algorithm>
-#include <vector>
-
-#include "base/containers/hash_tables.h"
-#include "base/debug/alias.h"
-#include "base/logging.h"
-#include "base/macros.h"
-#include "base/memory/ptr_util.h"
-#include "base/memory/shared_memory.h"
-#include "base/metrics/histogram_macros.h"
-#include "base/time/time.h"
-#include "content/browser/loader/resource_buffer.h"
-#include "content/browser/loader/resource_controller.h"
-#include "content/browser/loader/resource_dispatcher_host_impl.h"
-#include "content/browser/loader/resource_message_filter.h"
-#include "content/browser/loader/resource_request_info_impl.h"
-#include "content/common/resource_messages.h"
-#include "content/common/view_messages.h"
-#include "content/network/upload_progress_tracker.h"
-#include "content/public/common/resource_response.h"
-#include "ipc/ipc_message_macros.h"
-#include "net/base/io_buffer.h"
-#include "net/base/load_flags.h"
-#include "net/base/upload_progress.h"
-#include "net/url_request/redirect_info.h"
-#include "services/network/public/cpp/url_loader_completion_status.h"
-
-using base::TimeDelta;
-using base::TimeTicks;
-
-namespace content {
-namespace {
-
-static int g_async_loader_buffer_size = 1024 * 512;
-static int g_async_loader_min_buffer_allocation_size = 1024 * 4;
-static int g_async_loader_max_buffer_allocation_size = 1024 * 32;
-
-}  // namespace
-
-// Used to write into an existing IOBuffer at a given offset. This is
-// very similar to DependentIOBufferForRedirectToFile and
-// DependentIOBufferForMimeSniffing but not identical.
-class DependentIOBufferForAsyncLoading : public net::WrappedIOBuffer {
- public:
-  DependentIOBufferForAsyncLoading(ResourceBuffer* backing, char* memory)
-      : net::WrappedIOBuffer(memory), backing_(backing) {}
-
- private:
-  ~DependentIOBufferForAsyncLoading() override {}
-  scoped_refptr<ResourceBuffer> backing_;
-};
-
-AsyncResourceHandler::AsyncResourceHandler(net::URLRequest* request,
-                                           ResourceDispatcherHostImpl* rdh)
-    : ResourceHandler(request),
-      ResourceMessageDelegate(request),
-      rdh_(rdh),
-      pending_data_count_(0),
-      allocation_size_(0),
-      total_read_body_bytes_(0),
-      has_checked_for_sufficient_resources_(false),
-      sent_received_response_msg_(false),
-      sent_data_buffer_msg_(false),
-      reported_transfer_size_(0) {
-  DCHECK(GetRequestInfo()->requester_info()->IsRenderer());
-  InitializeResourceBufferConstants();
-}
-
-AsyncResourceHandler::~AsyncResourceHandler() {
-  if (has_checked_for_sufficient_resources_)
-    rdh_->FinishedWithResourcesForRequest(request());
-}
-
-void AsyncResourceHandler::InitializeResourceBufferConstants() {
-  static bool did_init = false;
-  if (did_init)
-    return;
-  did_init = true;
-
-  GetNumericArg("resource-buffer-size", &g_async_loader_buffer_size);
-  GetNumericArg("resource-buffer-min-allocation-size",
-                &g_async_loader_min_buffer_allocation_size);
-  GetNumericArg("resource-buffer-max-allocation-size",
-                &g_async_loader_max_buffer_allocation_size);
-}
-
-bool AsyncResourceHandler::OnMessageReceived(const IPC::Message& message) {
-  bool handled = true;
-  IPC_BEGIN_MESSAGE_MAP(AsyncResourceHandler, message)
-    IPC_MESSAGE_HANDLER(ResourceHostMsg_FollowRedirect, OnFollowRedirect)
-    IPC_MESSAGE_HANDLER(ResourceHostMsg_DataReceived_ACK, OnDataReceivedACK)
-    IPC_MESSAGE_HANDLER(ResourceHostMsg_UploadProgress_ACK, OnUploadProgressACK)
-    IPC_MESSAGE_UNHANDLED(handled = false)
-  IPC_END_MESSAGE_MAP()
-  return handled;
-}
-
-void AsyncResourceHandler::OnFollowRedirect(int request_id) {
-  if (!request()->status().is_success()) {
-    DVLOG(1) << "OnFollowRedirect for invalid request";
-    return;
-  }
-
-  ResumeIfDeferred();
-}
-
-void AsyncResourceHandler::OnDataReceivedACK(int request_id) {
-  if (pending_data_count_) {
-    --pending_data_count_;
-
-    buffer_->RecycleLeastRecentlyAllocated();
-    if (buffer_->CanAllocate())
-      ResumeIfDeferred();
-  }
-}
-
-void AsyncResourceHandler::OnUploadProgressACK(int request_id) {
-  if (upload_progress_tracker_)
-    upload_progress_tracker_->OnAckReceived();
-}
-
-void AsyncResourceHandler::OnRequestRedirected(
-    const net::RedirectInfo& redirect_info,
-    ResourceResponse* response,
-    std::unique_ptr<ResourceController> controller) {
-  ResourceMessageFilter* filter = GetFilter();
-  if (!filter) {
-    controller->Cancel();
-    return;
-  }
-
-  response->head.encoded_data_length = request()->GetTotalReceivedBytes();
-  reported_transfer_size_ = 0;
-  response->head.request_start = request()->creation_time();
-  response->head.response_start = TimeTicks::Now();
-  // TODO(davidben): Is it necessary to pass the new first party URL for
-  // cookies? The only case where it can change is top-level navigation requests
-  // and hopefully those will eventually all be owned by the browser. It's
-  // possible this is still needed while renderer-owned ones exist.
-  if (filter->Send(new ResourceMsg_ReceivedRedirect(
-          GetRequestID(), redirect_info, response->head))) {
-    OnDefer(std::move(controller));
-  } else {
-    controller->Cancel();
-  }
-}
-
-void AsyncResourceHandler::OnResponseStarted(
-    ResourceResponse* response,
-    std::unique_ptr<ResourceController> controller) {
-  // For changes to the main frame, inform the renderer of the new URL's
-  // per-host settings before the request actually commits.  This way the
-  // renderer will be able to set these precisely at the time the
-  // request commits, avoiding the possibility of e.g. zooming the old content
-  // or of having to layout the new content twice.
-  DCHECK(!has_controller());
-
-  response_started_ticks_ = base::TimeTicks::Now();
-
-  // We want to send a final upload progress message prior to sending the
-  // response complete message even if we're waiting for an ack to to a
-  // previous upload progress message.
-  if (upload_progress_tracker_) {
-    upload_progress_tracker_->OnUploadCompleted();
-    upload_progress_tracker_ = nullptr;
-  }
-
-  const ResourceRequestInfoImpl* info = GetRequestInfo();
-  ResourceMessageFilter* filter = GetFilter();
-  if (!filter) {
-    controller->Cancel();
-    return;
-  }
-
-  response->head.encoded_data_length = request()->raw_header_size();
-
-  // If the parent handler downloaded the resource to a file, grant the child
-  // read permissions on it.
-  if (!response->head.download_file_path.empty()) {
-    rdh_->RegisterDownloadedTempFile(
-        info->GetChildID(), info->GetRequestID(),
-        response->head.download_file_path);
-  }
-
-  response->head.request_start = request()->creation_time();
-  response->head.response_start = TimeTicks::Now();
-  filter->Send(
-      new ResourceMsg_ReceivedResponse(GetRequestID(), response->head));
-  sent_received_response_msg_ = true;
-
-  if (request()->response_info().metadata.get()) {
-    std::vector<uint8_t> copy(request()->response_info().metadata->data(),
-                              request()->response_info().metadata->data() +
-                                  request()->response_info().metadata->size());
-    filter->Send(new ResourceMsg_ReceivedCachedMetadata(GetRequestID(), copy));
-  }
-
-  controller->Resume();
-}
-
-void AsyncResourceHandler::OnWillStart(
-    const GURL& url,
-    std::unique_ptr<ResourceController> controller) {
-  ResourceMessageFilter* filter = GetFilter();
-  if (!filter) {
-    controller->Cancel();
-    return;
-  }
-
-  if (GetRequestInfo()->is_upload_progress_enabled() &&
-      request()->has_upload()) {
-    upload_progress_tracker_ = std::make_unique<UploadProgressTracker>(
-        FROM_HERE,
-        base::BindRepeating(&AsyncResourceHandler::SendUploadProgress,
-                            base::Unretained(this)),
-        request());
-  }
-  controller->Resume();
-}
-
-void AsyncResourceHandler::OnWillRead(
-    scoped_refptr<net::IOBuffer>* buf,
-    int* buf_size,
-    std::unique_ptr<ResourceController> controller) {
-  DCHECK(!has_controller());
-
-  if (!CheckForSufficientResource()) {
-    controller->CancelWithError(net::ERR_INSUFFICIENT_RESOURCES);
-    return;
-  }
-
-  if (!EnsureResourceBufferIsInitialized()) {
-    controller->CancelWithError(net::ERR_INSUFFICIENT_RESOURCES);
-    return;
-  }
-
-  DCHECK(buffer_->CanAllocate());
-  char* memory = buffer_->Allocate(&allocation_size_);
-  CHECK(memory);
-
-  *buf = new DependentIOBufferForAsyncLoading(buffer_.get(), memory);
-  *buf_size = allocation_size_;
-
-  controller->Resume();
-}
-
-void AsyncResourceHandler::OnReadCompleted(
-    int bytes_read,
-    std::unique_ptr<ResourceController> controller) {
-  DCHECK(!has_controller());
-  DCHECK_GE(bytes_read, 0);
-
-  if (!bytes_read) {
-    controller->Resume();
-    return;
-  }
-
-  ResourceMessageFilter* filter = GetFilter();
-  if (!filter) {
-    controller->Cancel();
-    return;
-  }
-
-  int encoded_data_length = CalculateEncodedDataLengthToReport();
-  if (!first_chunk_read_)
-    encoded_data_length -= request()->raw_header_size();
-
-  first_chunk_read_ = true;
-
-  buffer_->ShrinkLastAllocation(bytes_read);
-
-  total_read_body_bytes_ += bytes_read;
-
-  if (!sent_data_buffer_msg_) {
-    base::SharedMemoryHandle handle = base::SharedMemory::DuplicateHandle(
-        buffer_->GetSharedMemory().handle());
-    if (!base::SharedMemory::IsHandleValid(handle)) {
-      controller->Cancel();
-      return;
-    }
-    filter->Send(new ResourceMsg_SetDataBuffer(
-        GetRequestID(), handle, buffer_->GetSharedMemory().mapped_size()));
-    sent_data_buffer_msg_ = true;
-  }
-
-  int data_offset = buffer_->GetLastAllocationOffset();
-
-  filter->Send(new ResourceMsg_DataReceived(GetRequestID(), data_offset,
-                                            bytes_read, encoded_data_length));
-  ++pending_data_count_;
-
-  if (!buffer_->CanAllocate()) {
-    OnDefer(std::move(controller));
-  } else {
-    controller->Resume();
-  }
-}
-
-void AsyncResourceHandler::OnDataDownloaded(int bytes_downloaded) {
-  int encoded_data_length = CalculateEncodedDataLengthToReport();
-
-  ResourceMessageFilter* filter = GetFilter();
-  if (filter) {
-    filter->Send(new ResourceMsg_DataDownloaded(
-        GetRequestID(), bytes_downloaded, encoded_data_length));
-  }
-}
-
-void AsyncResourceHandler::OnResponseCompleted(
-    const net::URLRequestStatus& request_status,
-    std::unique_ptr<ResourceController> controller) {
-  ResourceMessageFilter* filter = GetFilter();
-  if (!filter) {
-    controller->Resume();
-    return;
-  }
-
-  // Ensure sending the final upload progress message here, since
-  // OnResponseCompleted can be called without OnResponseStarted on cancellation
-  // or error cases.
-  if (upload_progress_tracker_) {
-    upload_progress_tracker_->OnUploadCompleted();
-    upload_progress_tracker_ = nullptr;
-  }
-
-  // If we crash here, figure out what URL the renderer was requesting.
-  // http://crbug.com/107692
-  char url_buf[128];
-  base::strlcpy(url_buf, request()->url().spec().c_str(), arraysize(url_buf));
-  base::debug::Alias(url_buf);
-
-  // TODO(gavinp): Remove this CHECK when we figure out the cause of
-  // http://crbug.com/124680 . This check mirrors closely check in
-  // WebURLLoaderImpl::OnCompletedRequest that routes this message to a WebCore
-  // ResourceHandleInternal which asserts on its state and crashes. By crashing
-  // when the message is sent, we should get better crash reports.
-  CHECK(request_status.status() != net::URLRequestStatus::SUCCESS ||
-        sent_received_response_msg_);
-
-  int error_code = request_status.error();
-
-  DCHECK(request_status.status() != net::URLRequestStatus::IO_PENDING);
-
-  network::URLLoaderCompletionStatus loader_status;
-  loader_status.error_code = error_code;
-  loader_status.exists_in_cache = request()->response_info().was_cached;
-  loader_status.completion_time = TimeTicks::Now();
-  loader_status.encoded_data_length = request()->GetTotalReceivedBytes();
-  loader_status.encoded_body_length = request()->GetRawBodyBytes();
-  loader_status.decoded_body_length = total_read_body_bytes_;
-  filter->Send(new ResourceMsg_RequestComplete(GetRequestID(), loader_status));
-
-  if (request_status.is_success())
-    RecordHistogram();
-  controller->Resume();
-}
-
-bool AsyncResourceHandler::EnsureResourceBufferIsInitialized() {
-  DCHECK(has_checked_for_sufficient_resources_);
-
-  if (buffer_.get() && buffer_->IsInitialized())
-    return true;
-
-  buffer_ = new ResourceBuffer();
-  return buffer_->Initialize(g_async_loader_buffer_size,
-                             g_async_loader_min_buffer_allocation_size,
-                             g_async_loader_max_buffer_allocation_size);
-}
-
-void AsyncResourceHandler::ResumeIfDeferred() {
-  if (has_controller()) {
-    request()->LogUnblocked();
-    Resume();
-  }
-}
-
-void AsyncResourceHandler::OnDefer(
-    std::unique_ptr<ResourceController> controller) {
-  HoldController(std::move(controller));
-  request()->LogBlockedBy("AsyncResourceHandler");
-}
-
-bool AsyncResourceHandler::CheckForSufficientResource() {
-  if (has_checked_for_sufficient_resources_)
-    return true;
-  has_checked_for_sufficient_resources_ = true;
-
-  if (rdh_->HasSufficientResourcesForRequest(request()))
-    return true;
-
-  return false;
-}
-
-int AsyncResourceHandler::CalculateEncodedDataLengthToReport() {
-  const auto transfer_size = request()->GetTotalReceivedBytes();
-  const auto difference =  transfer_size - reported_transfer_size_;
-  reported_transfer_size_ = transfer_size;
-  return difference;
-}
-
-void AsyncResourceHandler::RecordHistogram() {
-  int64_t elapsed_time =
-      (base::TimeTicks::Now() - response_started_ticks_).InMicroseconds();
-  int64_t encoded_length = request()->GetTotalReceivedBytes();
-  if (encoded_length < 2 * 1024) {
-    // The resource was smaller than the smallest required buffer size.
-    UMA_HISTOGRAM_CUSTOM_COUNTS("Net.ResourceLoader.ResponseStartToEnd.LT_2kB",
-                                elapsed_time, 1, 100000, 100);
-  } else if (encoded_length < 32 * 1024) {
-    // The resource was smaller than single chunk.
-    UMA_HISTOGRAM_CUSTOM_COUNTS("Net.ResourceLoader.ResponseStartToEnd.LT_32kB",
-                                elapsed_time, 1, 100000, 100);
-  } else if (encoded_length < 512 * 1024) {
-    // The resource was smaller than single chunk.
-    UMA_HISTOGRAM_CUSTOM_COUNTS(
-        "Net.ResourceLoader.ResponseStartToEnd.LT_512kB",
-        elapsed_time, 1, 100000, 100);
-  } else {
-    UMA_HISTOGRAM_CUSTOM_COUNTS(
-        "Net.ResourceLoader.ResponseStartToEnd.Over_512kB",
-        elapsed_time, 1, 100000, 100);
-  }
-}
-
-void AsyncResourceHandler::SendUploadProgress(
-    const net::UploadProgress& progress) {
-  ResourceMessageFilter* filter = GetFilter();
-  if (!filter)
-    return;
-  filter->Send(new ResourceMsg_UploadProgress(
-      GetRequestID(), progress.position(), progress.size()));
-}
-
-}  // namespace content
diff --git a/content/browser/loader/async_resource_handler.h b/content/browser/loader/async_resource_handler.h
deleted file mode 100644
index 1ddccd83..0000000
--- a/content/browser/loader/async_resource_handler.h
+++ /dev/null
@@ -1,109 +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_BROWSER_LOADER_ASYNC_RESOURCE_HANDLER_H_
-#define CONTENT_BROWSER_LOADER_ASYNC_RESOURCE_HANDLER_H_
-
-#include <stdint.h>
-
-#include <memory>
-#include <string>
-
-#include "base/macros.h"
-#include "base/memory/ref_counted.h"
-#include "content/browser/loader/resource_handler.h"
-#include "content/browser/loader/resource_message_delegate.h"
-#include "content/common/content_export.h"
-#include "net/base/io_buffer.h"
-#include "url/gurl.h"
-
-namespace net {
-class URLRequest;
-class UploadProgress;
-}
-
-namespace content {
-class ResourceBuffer;
-class ResourceController;
-class ResourceDispatcherHostImpl;
-class UploadProgressTracker;
-
-// Used to complete an asynchronous resource request in response to resource
-// load events from the resource dispatcher host.
-class CONTENT_EXPORT AsyncResourceHandler : public ResourceHandler,
-                                            public ResourceMessageDelegate {
- public:
-  AsyncResourceHandler(net::URLRequest* request,
-                       ResourceDispatcherHostImpl* rdh);
-  ~AsyncResourceHandler() override;
-
-  bool OnMessageReceived(const IPC::Message& message) override;
-
-  // ResourceHandler implementation:
-  void OnRequestRedirected(
-      const net::RedirectInfo& redirect_info,
-      ResourceResponse* response,
-      std::unique_ptr<ResourceController> controller) override;
-  void OnResponseStarted(
-      ResourceResponse* response,
-      std::unique_ptr<ResourceController> controller) override;
-  void OnWillStart(const GURL& url,
-                   std::unique_ptr<ResourceController> controller) override;
-  void OnWillRead(scoped_refptr<net::IOBuffer>* buf,
-                  int* buf_size,
-                  std::unique_ptr<ResourceController> controller) override;
-  void OnReadCompleted(int bytes_read,
-                       std::unique_ptr<ResourceController> controller) override;
-  void OnResponseCompleted(
-      const net::URLRequestStatus& status,
-      std::unique_ptr<ResourceController> controller) override;
-  void OnDataDownloaded(int bytes_downloaded) override;
-
- private:
-  // IPC message handlers:
-  void OnFollowRedirect(int request_id);
-  void OnDataReceivedACK(int request_id);
-  void OnUploadProgressACK(int request_id);
-
-  bool EnsureResourceBufferIsInitialized();
-  void ResumeIfDeferred();
-  void OnDefer(std::unique_ptr<ResourceController> controller);
-  bool CheckForSufficientResource();
-  int CalculateEncodedDataLengthToReport();
-  int CalculateEncodedBodyLengthToReport();
-  void RecordHistogram();
-  void SendUploadProgress(const net::UploadProgress& progress);
-  static void InitializeResourceBufferConstants();
-
-  scoped_refptr<ResourceBuffer> buffer_;
-  ResourceDispatcherHostImpl* rdh_;
-
-  // Number of messages we've sent to the renderer that we haven't gotten an
-  // ACK for. This allows us to avoid having too many messages in flight.
-  int pending_data_count_;
-
-  int allocation_size_;
-
-  // Size of received body. Used for comparison with expected content size,
-  // which is reported to UMA.
-  int64_t total_read_body_bytes_;
-
-  bool first_chunk_read_ = false;
-
-  bool has_checked_for_sufficient_resources_;
-  bool sent_received_response_msg_;
-  bool sent_data_buffer_msg_;
-
-  base::TimeTicks response_started_ticks_;
-
-  std::unique_ptr<UploadProgressTracker> upload_progress_tracker_;
-
-  int64_t reported_transfer_size_;
-
-  DISALLOW_COPY_AND_ASSIGN(AsyncResourceHandler);
-};
-
-}  // namespace content
-
-#endif  // CONTENT_BROWSER_LOADER_ASYNC_RESOURCE_HANDLER_H_
diff --git a/content/browser/loader/async_resource_handler_browsertest.cc b/content/browser/loader/async_resource_handler_browsertest.cc
deleted file mode 100644
index 4dae1a2..0000000
--- a/content/browser/loader/async_resource_handler_browsertest.cc
+++ /dev/null
@@ -1,111 +0,0 @@
-// Copyright 2015 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "content/browser/loader/async_resource_handler.h"
-
-#include <stddef.h>
-#include <string>
-#include <utility>
-
-#include "base/format_macros.h"
-#include "base/strings/string_util.h"
-#include "base/strings/stringprintf.h"
-#include "build/build_config.h"
-#include "content/public/common/content_switches.h"
-#include "content/public/test/browser_test_utils.h"
-#include "content/public/test/content_browser_test.h"
-#include "content/public/test/content_browser_test_utils.h"
-#include "content/shell/browser/shell.h"
-#include "net/test/embedded_test_server/embedded_test_server.h"
-#include "net/test/embedded_test_server/http_request.h"
-#include "net/test/embedded_test_server/http_response.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace content {
-
-namespace {
-
-const char kPostPath[] = "/post";
-const char kRedirectPostPath[] = "/redirect";
-
-// ThreadSanitizer is too slow to perform the full upload, so tests
-// using that build get an easier test which might not show two distinct
-// progress events. See crbug.com/526985. In addition, OSX buildbots have
-// experienced slowdowns on this test (crbug.com/548819), give them the easier
-// test too.
-#if defined(THREAD_SANITIZER) || defined(OS_MACOSX)
-const size_t kPayloadSize = 1062882;  // 2*3^12
-#else
-const size_t kPayloadSize = 28697814;  // 2*3^15
-#endif
-
-std::unique_ptr<net::test_server::HttpResponse> HandlePostAndRedirectURLs(
-    const std::string& request_path,
-    const net::test_server::HttpRequest& request) {
-  std::unique_ptr<net::test_server::BasicHttpResponse> http_response(
-      new net::test_server::BasicHttpResponse());
-  if (base::StartsWith(request.relative_url, kRedirectPostPath,
-                       base::CompareCase::SENSITIVE)) {
-    http_response->set_code(net::HTTP_TEMPORARY_REDIRECT);
-    http_response->AddCustomHeader("Location", kPostPath);
-    EXPECT_EQ(request.content.length(), kPayloadSize);
-    return std::move(http_response);
-  } else if (base::StartsWith(request.relative_url, kPostPath,
-                              base::CompareCase::SENSITIVE)) {
-    http_response->set_content("hello");
-    http_response->set_content_type("text/plain");
-    EXPECT_EQ(request.content.length(), kPayloadSize);
-    return std::move(http_response);
-  } else {
-    return std::unique_ptr<net::test_server::HttpResponse>();
-  }
-}
-
-}  // namespace
-
-// https://crbug.com/788748
-#if defined(OS_ANDROID) && defined(ADDRESS_SANITIZER)
-#define MAYBE_AsyncResourceHandlerBrowserTest \
-  DISABLED_AsyncResourceHandlerBrowserTest
-#else
-#define MAYBE_AsyncResourceHandlerBrowserTest AsyncResourceHandlerBrowserTest
-#endif  // defined(OS_ANDROID) && defined(ADDRESS_SANITIZER)
-class MAYBE_AsyncResourceHandlerBrowserTest : public ContentBrowserTest {};
-
-IN_PROC_BROWSER_TEST_F(MAYBE_AsyncResourceHandlerBrowserTest, UploadProgress) {
-  net::EmbeddedTestServer* test_server = embedded_test_server();
-  test_server->RegisterRequestHandler(
-      base::Bind(&HandlePostAndRedirectURLs, kPostPath));
-  ASSERT_TRUE(test_server->Start());
-
-  NavigateToURL(shell(),
-                test_server->GetURL("/loader/async_resource_handler.html"));
-
-  std::string js_result;
-  EXPECT_TRUE(ExecuteScriptAndExtractString(
-      shell(), base::StringPrintf("WaitForAsyncXHR('%s', %" PRIuS ")",
-                                  kPostPath, kPayloadSize),
-      &js_result));
-  EXPECT_EQ(js_result, "success");
-}
-
-IN_PROC_BROWSER_TEST_F(MAYBE_AsyncResourceHandlerBrowserTest,
-                       UploadProgressRedirect) {
-  net::EmbeddedTestServer* test_server = embedded_test_server();
-  test_server->RegisterRequestHandler(
-      base::Bind(&HandlePostAndRedirectURLs, kRedirectPostPath));
-  ASSERT_TRUE(test_server->Start());
-
-  NavigateToURL(shell(),
-                test_server->GetURL("/loader/async_resource_handler.html"));
-
-  std::string js_result;
-  EXPECT_TRUE(ExecuteScriptAndExtractString(
-      shell(), base::StringPrintf("WaitForAsyncXHR('%s', %" PRIuS ")",
-                                  kRedirectPostPath, kPayloadSize),
-      &js_result));
-  EXPECT_EQ(js_result, "success");
-}
-
-}  // namespace content
diff --git a/content/browser/loader/async_resource_handler_unittest.cc b/content/browser/loader/async_resource_handler_unittest.cc
deleted file mode 100644
index ef8d97c..0000000
--- a/content/browser/loader/async_resource_handler_unittest.cc
+++ /dev/null
@@ -1,311 +0,0 @@
-// Copyright 2016 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "content/browser/loader/async_resource_handler.h"
-
-#include <stddef.h>
-#include <stdint.h>
-#include <memory>
-#include <string>
-#include <tuple>
-#include <utility>
-#include <vector>
-
-#include "base/bind.h"
-#include "base/bind_helpers.h"
-#include "base/format_macros.h"
-#include "base/logging.h"
-#include "base/memory/ptr_util.h"
-#include "base/memory/ref_counted.h"
-#include "base/memory/weak_ptr.h"
-#include "base/process/process.h"
-#include "base/run_loop.h"
-#include "base/strings/stringprintf.h"
-#include "base/test/scoped_feature_list.h"
-#include "content/browser/loader/resource_dispatcher_host_impl.h"
-#include "content/browser/loader/resource_loader.h"
-#include "content/browser/loader/resource_loader_delegate.h"
-#include "content/browser/loader/resource_message_filter.h"
-#include "content/browser/loader/resource_request_info_impl.h"
-#include "content/common/resource_messages.h"
-#include "content/public/browser/resource_context.h"
-#include "content/public/browser/resource_request_info.h"
-#include "content/public/common/content_features.h"
-#include "content/public/common/previews_state.h"
-#include "content/public/common/resource_request.h"
-#include "content/public/common/resource_type.h"
-#include "content/public/test/mock_resource_context.h"
-#include "content/public/test/test_browser_thread_bundle.h"
-#include "ipc/ipc_message.h"
-#include "ipc/ipc_message_macros.h"
-#include "net/http/http_response_headers.h"
-#include "net/http/http_util.h"
-#include "net/ssl/client_cert_store.h"
-#include "net/traffic_annotation/network_traffic_annotation_test_helper.h"
-#include "net/url_request/url_request.h"
-#include "net/url_request/url_request_context.h"
-#include "net/url_request/url_request_job.h"
-#include "net/url_request/url_request_job_factory_impl.h"
-#include "net/url_request/url_request_test_job.h"
-#include "net/url_request/url_request_test_util.h"
-#include "testing/gtest/include/gtest/gtest.h"
-#include "third_party/WebKit/common/page/page_visibility_state.mojom.h"
-#include "ui/base/page_transition_types.h"
-#include "url/gurl.h"
-
-namespace content {
-
-namespace {
-
-std::string GenerateHeader(size_t response_data_size) {
-  return base::StringPrintf(
-      "HTTP/1.1 200 OK\n"
-      "Content-type: text/html\n"
-      "Content-Length: %" PRIuS "\n",
-      response_data_size);
-}
-
-int64_t TotalReceivedBytes(size_t response_data_size) {
-  return response_data_size + GenerateHeader(response_data_size).size();
-}
-
-std::string GenerateData(size_t response_data_size) {
-  return std::string(response_data_size, 'a');
-}
-
-class TestProtocolHandler : public net::URLRequestJobFactory::ProtocolHandler {
- public:
-  TestProtocolHandler(size_t response_data_size)
-      : response_data_size_(response_data_size) {}
-
-  net::URLRequestJob* MaybeCreateJob(
-      net::URLRequest* request,
-      net::NetworkDelegate* network_delegate) const override {
-    return new net::URLRequestTestJob(request, network_delegate,
-                                      GenerateHeader(response_data_size_),
-                                      GenerateData(response_data_size_), true);
-  }
-
- private:
-  size_t response_data_size_;
-};
-
-// A subclass of ResourceMessageFilter that records IPC messages that are sent.
-class RecordingResourceMessageFilter : public ResourceMessageFilter {
- public:
-  RecordingResourceMessageFilter(ResourceContext* resource_context,
-                                 net::URLRequestContext* request_context)
-      : ResourceMessageFilter(
-            0,
-            nullptr,
-            nullptr,
-            nullptr,
-            nullptr,
-            base::Bind(&RecordingResourceMessageFilter::GetContexts,
-                       base::Unretained(this)),
-            BrowserThread::GetTaskRunnerForThread(BrowserThread::IO)),
-        resource_context_(resource_context),
-        request_context_(request_context) {
-    InitializeForTest();
-    set_peer_process_for_testing(base::Process::Current());
-  }
-
-  const std::vector<std::unique_ptr<IPC::Message>>& messages() const {
-    return messages_;
-  }
-
-  // IPC::Sender implementation:
-  bool Send(IPC::Message* message) override {
-    // Unpickle the base::SharedMemoryHandle to avoid warnings about
-    // "MessageAttachmentSet destroyed with unconsumed descriptors".
-    if (message->type() == ResourceMsg_SetDataBuffer::ID) {
-      ResourceMsg_SetDataBuffer::Param params;
-      ResourceMsg_SetDataBuffer::Read(message, &params);
-    }
-    messages_.push_back(base::WrapUnique(message));
-    return true;
-  }
-
- private:
-  ~RecordingResourceMessageFilter() override {}
-
-  void GetContexts(ResourceType resource_type,
-                   ResourceContext** resource_context,
-                   net::URLRequestContext** request_context) {
-    *resource_context = resource_context_;
-    *request_context = request_context_;
-  }
-
-  ResourceContext* const resource_context_;
-  net::URLRequestContext* const request_context_;
-  std::vector<std::unique_ptr<IPC::Message>> messages_;
-};
-
-class AsyncResourceHandlerTest : public ::testing::Test,
-                                 public ResourceLoaderDelegate {
- protected:
-  AsyncResourceHandlerTest()
-      : thread_bundle_(TestBrowserThreadBundle::IO_MAINLOOP), context_(true) {}
-
-  void TearDown() override {
-    if (filter_)
-      filter_->OnChannelClosing();
-    // Prevent memory leaks.
-    filter_ = nullptr;
-    rdh_.Shutdown();
-    base::RunLoop().RunUntilIdle();
-  }
-
-  void CreateRequestWithResponseDataSize(size_t response_data_size) {
-    test_job_factory_.SetProtocolHandler(
-        "test", std::make_unique<TestProtocolHandler>(response_data_size));
-    context_.set_job_factory(&test_job_factory_);
-    context_.Init();
-    std::unique_ptr<net::URLRequest> request =
-        context_.CreateRequest(GURL("test:test"), net::DEFAULT_PRIORITY,
-                               nullptr, TRAFFIC_ANNOTATION_FOR_TESTS);
-    resource_context_ = std::make_unique<MockResourceContext>(&context_);
-    filter_ =
-        new RecordingResourceMessageFilter(resource_context_.get(), &context_);
-    ResourceRequestInfoImpl* info = new ResourceRequestInfoImpl(
-        filter_->requester_info_for_test(),
-        0,                                 // route_id
-        -1,                                // frame_tree_node_id
-        0,                                 // origin_pid
-        0,                                 // request_id
-        0,                                 // render_frame_id
-        false,                             // is_main_frame
-        RESOURCE_TYPE_IMAGE,               // resource_type
-        ui::PAGE_TRANSITION_LINK,          // transition_type
-        false,                             // should_replace_current_entry
-        false,                             // is_download
-        false,                             // is_stream
-        false,                             // allow_download
-        false,                             // has_user_gesture
-        false,                             // enable load timing
-        false,                             // enable upload progress
-        false,                             // do_not_prompt_for_login
-        false,                             // keep_alive
-        blink::kWebReferrerPolicyDefault,  // referrer_policy
-        blink::mojom::PageVisibilityState::kVisible,  // visibility_state
-        resource_context_.get(),                      // context
-        false,                                        // report_raw_headers
-        true,                                         // is_async
-        PREVIEWS_OFF,                                 // previews_state
-        nullptr,                                      // body
-        false);  // initiated_in_secure_context
-    info->AssociateWithRequest(request.get());
-    std::unique_ptr<AsyncResourceHandler> handler =
-        std::make_unique<AsyncResourceHandler>(request.get(), &rdh_);
-    loader_ = std::make_unique<ResourceLoader>(std::move(request),
-                                               std::move(handler), this);
-  }
-
-  void StartRequestAndWaitWithResponseDataSize(size_t response_data_size) {
-    CreateRequestWithResponseDataSize(response_data_size);
-    loader_->StartRequest();
-    finish_waiter_.reset(new base::RunLoop);
-    finish_waiter_->Run();
-  }
-
-  scoped_refptr<RecordingResourceMessageFilter> filter_;
-
- private:
-  // ResourceLoaderDelegate implementation:
-  ResourceDispatcherHostLoginDelegate* CreateLoginDelegate(
-      ResourceLoader* loader,
-      net::AuthChallengeInfo* auth_info) override {
-    return nullptr;
-  }
-
-  bool HandleExternalProtocol(ResourceLoader* loader,
-                              const GURL& url) override {
-    return false;
-  }
-  void DidStartRequest(ResourceLoader* loader) override {}
-  void DidReceiveRedirect(ResourceLoader* loader,
-                          const GURL& new_url,
-                          ResourceResponse* response) override {}
-  void DidReceiveResponse(ResourceLoader* loader,
-                          ResourceResponse* response) override {}
-  void DidFinishLoading(ResourceLoader* loader) override {
-    loader_.reset();
-    finish_waiter_->Quit();
-  }
-  std::unique_ptr<net::ClientCertStore> CreateClientCertStore(
-      ResourceLoader* loader) override {
-    return nullptr;
-  }
-
-  TestBrowserThreadBundle thread_bundle_;
-  ResourceDispatcherHostImpl rdh_;
-  net::TestURLRequestContext context_;
-  net::URLRequestJobFactoryImpl test_job_factory_;
-  std::unique_ptr<MockResourceContext> resource_context_;
-  std::unique_ptr<ResourceLoader> loader_;
-  std::unique_ptr<base::RunLoop> finish_waiter_;
-};
-
-TEST_F(AsyncResourceHandlerTest, Construct) {
-  CreateRequestWithResponseDataSize(1);
-}
-
-TEST_F(AsyncResourceHandlerTest, OneChunkLengths) {
-  // Larger than kInlinedLeadingChunkSize and smaller than
-  // kMaxAllocationSize.
-  constexpr auto kDataSize = 4096;
-  StartRequestAndWaitWithResponseDataSize(kDataSize);
-  const auto& messages = filter_->messages();
-  ASSERT_EQ(4u, messages.size());
-  ASSERT_EQ(static_cast<uint32_t>(ResourceMsg_DataReceived::ID),
-            messages[2]->type());
-  ResourceMsg_DataReceived::Param params;
-  ResourceMsg_DataReceived::Read(messages[2].get(), &params);
-
-  int encoded_data_length = std::get<3>(params);
-  EXPECT_EQ(kDataSize, encoded_data_length);
-
-  ASSERT_EQ(static_cast<uint32_t>(ResourceMsg_RequestComplete::ID),
-            messages[3]->type());
-  ResourceMsg_RequestComplete::Param completion_params;
-  ResourceMsg_RequestComplete::Read(messages[3].get(), &completion_params);
-  network::URLLoaderCompletionStatus status = std::get<1>(completion_params);
-
-  EXPECT_EQ(TotalReceivedBytes(kDataSize), status.encoded_data_length);
-  EXPECT_EQ(kDataSize, status.encoded_body_length);
-}
-
-TEST_F(AsyncResourceHandlerTest, TwoChunksLengths) {
-  // Larger than kMaxAllocationSize.
-  constexpr auto kDataSize = 64 * 1024;
-  StartRequestAndWaitWithResponseDataSize(kDataSize);
-  const auto& messages = filter_->messages();
-  ASSERT_EQ(5u, messages.size());
-  ASSERT_EQ(static_cast<uint32_t>(ResourceMsg_DataReceived::ID),
-            messages[2]->type());
-  ResourceMsg_DataReceived::Param params;
-  ResourceMsg_DataReceived::Read(messages[2].get(), &params);
-
-  int encoded_data_length = std::get<3>(params);
-  EXPECT_EQ(32768, encoded_data_length);
-
-  ASSERT_EQ(static_cast<uint32_t>(ResourceMsg_DataReceived::ID),
-            messages[3]->type());
-  ResourceMsg_DataReceived::Read(messages[3].get(), &params);
-
-  encoded_data_length = std::get<3>(params);
-  EXPECT_EQ(32768, encoded_data_length);
-
-  ASSERT_EQ(static_cast<uint32_t>(ResourceMsg_RequestComplete::ID),
-            messages[4]->type());
-  ResourceMsg_RequestComplete::Param completion_params;
-  ResourceMsg_RequestComplete::Read(messages[4].get(), &completion_params);
-  network::URLLoaderCompletionStatus status = std::get<1>(completion_params);
-  EXPECT_EQ(TotalReceivedBytes(kDataSize), status.encoded_data_length);
-  EXPECT_EQ(kDataSize, status.encoded_body_length);
-}
-
-}  // namespace
-
-}  // namespace content
diff --git a/content/browser/loader/resource_dispatcher_host_impl.cc b/content/browser/loader/resource_dispatcher_host_impl.cc
index d767a79c..74bcb61 100644
--- a/content/browser/loader/resource_dispatcher_host_impl.cc
+++ b/content/browser/loader/resource_dispatcher_host_impl.cc
@@ -43,7 +43,6 @@
 #include "content/browser/browsing_data/clear_site_data_throttle.h"
 #include "content/browser/child_process_security_policy_impl.h"
 #include "content/browser/frame_host/navigation_request_info.h"
-#include "content/browser/loader/async_resource_handler.h"
 #include "content/browser/loader/cross_site_document_resource_handler.h"
 #include "content/browser/loader/detachable_resource_handler.h"
 #include "content/browser/loader/intercepting_resource_handler.h"
@@ -60,7 +59,6 @@
 #include "content/browser/loader/resource_requester_info.h"
 #include "content/browser/loader/resource_scheduler.h"
 #include "content/browser/loader/stream_resource_handler.h"
-#include "content/browser/loader/sync_resource_handler.h"
 #include "content/browser/loader/throttling_resource_handler.h"
 #include "content/browser/loader/upload_data_stream_builder.h"
 #include "content/browser/loader/wake_lock_resource_throttle.h"
@@ -74,7 +72,6 @@
 #include "content/browser/streams/stream_registry.h"
 #include "content/common/loader_util.h"
 #include "content/common/net/url_request_service_worker_data.h"
-#include "content/common/resource_messages.h"
 #include "content/common/view_messages.h"
 #include "content/public/browser/browser_child_process_host.h"
 #include "content/public/browser/browser_thread.h"
@@ -94,8 +91,6 @@
 #include "content/public/common/origin_util.h"
 #include "content/public/common/resource_request.h"
 #include "content/public/common/resource_request_body.h"
-#include "ipc/ipc_message_macros.h"
-#include "ipc/ipc_message_start.h"
 #include "net/base/auth.h"
 #include "net/base/load_flags.h"
 #include "net/base/mime_util.h"
@@ -133,8 +128,6 @@
 using base::TimeDelta;
 using base::TimeTicks;
 using storage::ShareableFileReference;
-using SyncLoadResultCallback =
-    content::ResourceDispatcherHostImpl::SyncLoadResultCallback;
 
 // ----------------------------------------------------------------------------
 
@@ -177,14 +170,8 @@
 // Aborts a request before an URLRequest has actually been created.
 void AbortRequestBeforeItStarts(
     IPC::Sender* sender,
-    const SyncLoadResultCallback& sync_result_handler,
     int request_id,
     mojom::URLLoaderClientPtr url_loader_client) {
-  if (sync_result_handler) {
-    SyncLoadResult result;
-    result.error_code = net::ERR_ABORTED;
-    sync_result_handler.Run(&result);
-  } else {
     // Tell the renderer that this request was disallowed.
     network::URLLoaderCompletionStatus status;
     status.error_code = net::ERR_ABORTED;
@@ -193,12 +180,7 @@
     status.completion_time = base::TimeTicks();
     status.encoded_data_length = 0;
     status.encoded_body_length = 0;
-    if (url_loader_client) {
-      url_loader_client->OnComplete(status);
-    } else {
-      sender->Send(new ResourceMsg_RequestComplete(request_id, status));
-    }
-  }
+    url_loader_client->OnComplete(status);
 }
 
 void RemoveDownloadFileFromChildSecurityPolicy(int child_id,
@@ -238,22 +220,6 @@
   return previews_state;
 }
 
-// Sends back the result of a synchronous loading result to the renderer through
-// Chrome IPC.
-void HandleSyncLoadResult(base::WeakPtr<ResourceMessageFilter> filter,
-                          std::unique_ptr<IPC::Message> sync_result,
-                          const SyncLoadResult* result) {
-  if (!filter)
-    return;
-
-  if (result) {
-    ResourceHostMsg_SyncLoad::WriteReplyParams(sync_result.get(), *result);
-  } else {
-    sync_result->set_reply_error();
-  }
-  filter->Send(sync_result.release());
-}
-
 bool ValidatePluginChildId(int plugin_child_id) {
   if (plugin_child_id == ChildProcessHost::kInvalidUniqueID)
     return true;
@@ -754,60 +720,6 @@
   scheduler_.reset();
 }
 
-bool ResourceDispatcherHostImpl::OnMessageReceived(
-    const IPC::Message& message,
-    ResourceRequesterInfo* requester_info) {
-  DCHECK(io_thread_task_runner_->BelongsToCurrentThread());
-
-  bool handled = true;
-  IPC_BEGIN_MESSAGE_MAP_WITH_PARAM(ResourceDispatcherHostImpl, message,
-                                   requester_info)
-    IPC_MESSAGE_HANDLER(ResourceHostMsg_RequestResource, OnRequestResource)
-    IPC_MESSAGE_HANDLER_WITH_PARAM_DELAY_REPLY(ResourceHostMsg_SyncLoad,
-                                               OnSyncLoad)
-    IPC_MESSAGE_HANDLER(ResourceHostMsg_ReleaseDownloadedFile,
-                        OnReleaseDownloadedFile)
-    IPC_MESSAGE_HANDLER(ResourceHostMsg_CancelRequest, OnCancelRequest)
-    IPC_MESSAGE_HANDLER(ResourceHostMsg_DidChangePriority, OnDidChangePriority)
-    IPC_MESSAGE_UNHANDLED(handled = false)
-  IPC_END_MESSAGE_MAP()
-
-  if (!handled && IPC_MESSAGE_ID_CLASS(message.type()) == ResourceMsgStart) {
-    base::PickleIterator iter(message);
-    int request_id = -1;
-    bool ok = iter.ReadInt(&request_id);
-    DCHECK(ok);
-    GlobalRequestID id(requester_info->child_id(), request_id);
-    DelegateMap::iterator it = delegate_map_.find(id);
-    if (it != delegate_map_.end()) {
-      for (auto& delegate : *it->second) {
-        if (delegate.OnMessageReceived(message)) {
-          handled = true;
-          break;
-        }
-      }
-    }
-
-    // As the unhandled resource message effectively has no consumer, mark it as
-    // handled to prevent needless propagation through the filter pipeline.
-    handled = true;
-  }
-
-  return handled;
-}
-
-void ResourceDispatcherHostImpl::OnRequestResource(
-    ResourceRequesterInfo* requester_info,
-    int routing_id,
-    int request_id,
-    const ResourceRequest& request_data,
-    net::MutableNetworkTrafficAnnotationTag traffic_annotation) {
-  OnRequestResourceInternal(
-      requester_info, routing_id, request_id, false /* is_sync_load */,
-      request_data, nullptr, nullptr,
-      net::NetworkTrafficAnnotationTag(traffic_annotation));
-}
-
 void ResourceDispatcherHostImpl::OnRequestResourceInternal(
     ResourceRequesterInfo* requester_info,
     int routing_id,
@@ -819,31 +731,10 @@
     const net::NetworkTrafficAnnotationTag& traffic_annotation) {
   DCHECK(requester_info->IsRenderer() || requester_info->IsNavigationPreload());
   BeginRequest(requester_info, request_id, request_data, is_sync_load,
-               SyncLoadResultCallback(), routing_id, std::move(mojo_request),
+               routing_id, std::move(mojo_request),
                std::move(url_loader_client), traffic_annotation);
 }
 
-// Begins a resource request with the given params on behalf of the specified
-// child process.  Responses will be dispatched through the given receiver. The
-// process ID is used to lookup WebContentsImpl from routing_id's in the case of
-// a request from a renderer.  request_context is the cookie/cache context to be
-// used for this request.
-//
-// If sync_result is non-null, then a SyncLoad reply will be generated, else
-// a normal asynchronous set of response messages will be generated.
-void ResourceDispatcherHostImpl::OnSyncLoad(
-    ResourceRequesterInfo* requester_info,
-    int request_id,
-    const ResourceRequest& request_data,
-    IPC::Message* sync_result) {
-  SyncLoadResultCallback callback =
-      base::Bind(&HandleSyncLoadResult, requester_info->filter()->GetWeakPtr(),
-                 base::Passed(WrapUnique(sync_result)));
-  BeginRequest(requester_info, request_id, request_data,
-               true /* is_sync_load */, callback, sync_result->routing_id(),
-               nullptr, nullptr, GetTrafficAnnotation());
-}
-
 bool ResourceDispatcherHostImpl::IsRequestIDInUse(
     const GlobalRequestID& id) const {
   if (pending_loaders_.find(id) != pending_loaders_.end())
@@ -911,17 +802,6 @@
       blocked_loaders_map_.erase(old_routing_id);
     }
   }
-  if (old_request_id != new_request_id) {
-    DelegateMap::iterator it = delegate_map_.find(old_request_id);
-    if (it != delegate_map_.end()) {
-      // Tell each delegate that the request ID has changed.
-      for (auto& delegate : *it->second)
-        delegate.set_request_id(new_request_id);
-      // Now store the observer list under the new request ID.
-      delegate_map_[new_request_id] = delegate_map_[old_request_id];
-      delegate_map_.erase(old_request_id);
-    }
-  }
 
   AppCacheInterceptor::CompleteCrossSiteTransfer(
       loader_ptr->request(), child_id, request_data.appcache_host_id,
@@ -999,7 +879,6 @@
     int request_id,
     const ResourceRequest& request_data,
     bool is_sync_load,
-    const SyncLoadResultCallback& sync_result_handler,  // only valid for sync
     int route_id,
     mojom::URLLoaderRequest mojo_request,
     mojom::URLLoaderClientPtr url_loader_client,
@@ -1066,8 +945,8 @@
   if (is_shutdown_ ||
       !ShouldServiceRequest(child_id, request_data, request_data.headers,
                             requester_info, resource_context)) {
-    AbortRequestBeforeItStarts(requester_info->filter(), sync_result_handler,
-                               request_id, std::move(url_loader_client));
+    AbortRequestBeforeItStarts(requester_info->filter(), request_id,
+                               std::move(url_loader_client));
     return;
   }
 
@@ -1086,8 +965,7 @@
         // will be used in UploadDataStream and ServiceWorkerURLRequestJob.
         if (!GetBodyBlobDataHandles(request_data.request_body.get(),
                                     resource_context, &blob_handles)) {
-          AbortRequestBeforeItStarts(requester_info->filter(),
-                                     sync_result_handler, request_id,
+          AbortRequestBeforeItStarts(requester_info->filter(), request_id,
                                      std::move(url_loader_client));
           return;
         }
@@ -1117,9 +995,8 @@
               base::Bind(
                   &ResourceDispatcherHostImpl::ContinuePendingBeginRequest,
                   base::Unretained(this), base::WrapRefCounted(requester_info),
-                  request_id, request_data, is_sync_load, sync_result_handler,
-                  route_id, request_data.headers,
-                  base::Passed(std::move(mojo_request)),
+                  request_id, request_data, is_sync_load, route_id,
+                  request_data.headers, base::Passed(std::move(mojo_request)),
                   base::Passed(std::move(url_loader_client)),
                   base::Passed(std::move(blob_handles)), traffic_annotation));
           return;
@@ -1127,12 +1004,11 @@
       }
     }
   }
-  ContinuePendingBeginRequest(requester_info, request_id, request_data,
-                              is_sync_load, sync_result_handler, route_id,
-                              request_data.headers, std::move(mojo_request),
-                              std::move(url_loader_client),
-                              std::move(blob_handles), traffic_annotation,
-                              HeaderInterceptorResult::CONTINUE);
+  ContinuePendingBeginRequest(
+      requester_info, request_id, request_data, is_sync_load, route_id,
+      request_data.headers, std::move(mojo_request),
+      std::move(url_loader_client), std::move(blob_handles), traffic_annotation,
+      HeaderInterceptorResult::CONTINUE);
 }
 
 void ResourceDispatcherHostImpl::ContinuePendingBeginRequest(
@@ -1140,7 +1016,6 @@
     int request_id,
     const ResourceRequest& request_data,
     bool is_sync_load,
-    const SyncLoadResultCallback& sync_result_handler,  // only valid for sync
     int route_id,
     const net::HttpRequestHeaders& headers,
     mojom::URLLoaderRequest mojo_request,
@@ -1149,7 +1024,6 @@
     const net::NetworkTrafficAnnotationTag& traffic_annotation,
     HeaderInterceptorResult interceptor_result) {
   DCHECK(requester_info->IsRenderer() || requester_info->IsNavigationPreload());
-  DCHECK(!sync_result_handler || is_sync_load);
   if (interceptor_result != HeaderInterceptorResult::CONTINUE) {
     if (requester_info->IsRenderer() &&
         interceptor_result == HeaderInterceptorResult::KILL) {
@@ -1159,8 +1033,8 @@
       bad_message::ReceivedBadMessage(requester_info->filter(),
                                       bad_message::RDH_ILLEGAL_ORIGIN);
     }
-    AbortRequestBeforeItStarts(requester_info->filter(), sync_result_handler,
-                               request_id, std::move(url_loader_client));
+    AbortRequestBeforeItStarts(requester_info->filter(), request_id,
+                               std::move(url_loader_client));
     return;
   }
   int child_id = requester_info->child_id();
@@ -1183,8 +1057,8 @@
                                                   request_data.url,
                                                   request_data.resource_type,
                                                   resource_context)) {
-    AbortRequestBeforeItStarts(requester_info->filter(), sync_result_handler,
-                               request_id, std::move(url_loader_client));
+    AbortRequestBeforeItStarts(requester_info->filter(), request_id,
+                               std::move(url_loader_client));
     return;
   }
 
@@ -1389,10 +1263,10 @@
         new_request.get(), requester_info->appcache_service(), child_id,
         request_data.appcache_host_id, request_data.resource_type,
         request_data.should_reset_appcache);
-    handler = CreateResourceHandler(
-        requester_info.get(), new_request.get(), request_data,
-        sync_result_handler, route_id, child_id, resource_context,
-        std::move(mojo_request), std::move(url_loader_client));
+    handler = CreateResourceHandler(requester_info.get(), new_request.get(),
+                                    request_data, route_id, child_id,
+                                    resource_context, std::move(mojo_request),
+                                    std::move(url_loader_client));
   }
   if (handler)
     BeginRequestInternal(std::move(new_request), std::move(handler));
@@ -1403,7 +1277,6 @@
     ResourceRequesterInfo* requester_info,
     net::URLRequest* request,
     const ResourceRequest& request_data,
-    const SyncLoadResultCallback& sync_result_handler,
     int route_id,
     int child_id,
     ResourceContext* resource_context,
@@ -1412,36 +1285,21 @@
   DCHECK(requester_info->IsRenderer() || requester_info->IsNavigationPreload());
   // Construct the IPC resource handler.
   std::unique_ptr<ResourceHandler> handler;
-  if (sync_result_handler) {
-    // download_to_file is not supported for synchronous requests.
-    if (request_data.download_to_file) {
-      DCHECK(requester_info->IsRenderer());
-      bad_message::ReceivedBadMessage(requester_info->filter(),
-                                      bad_message::RDH_BAD_DOWNLOAD);
-      return std::unique_ptr<ResourceHandler>();
-    }
+  handler = CreateBaseResourceHandler(request, std::move(mojo_request),
+                                      std::move(url_loader_client),
+                                      request_data.resource_type);
 
-    DCHECK(!mojo_request.is_pending());
-    DCHECK(!url_loader_client);
-    handler.reset(new SyncResourceHandler(request, sync_result_handler, this));
-  } else {
-    handler = CreateBaseResourceHandler(request, std::move(mojo_request),
-                                        std::move(url_loader_client),
-                                        request_data.resource_type);
-
-    // The RedirectToFileResourceHandler depends on being next in the chain.
-    if (request_data.download_to_file) {
-      handler.reset(
-          new RedirectToFileResourceHandler(std::move(handler), request));
-    }
+  // The RedirectToFileResourceHandler depends on being next in the chain.
+  if (request_data.download_to_file) {
+    handler.reset(
+        new RedirectToFileResourceHandler(std::move(handler), request));
   }
 
   bool start_detached = request_data.download_to_network_cache_only;
 
   // Prefetches and <a ping> requests outlive their child process.
-  if (!sync_result_handler &&
-      (start_detached || request_data.resource_type == RESOURCE_TYPE_PREFETCH ||
-       request_data.keepalive)) {
+  if (start_detached || request_data.resource_type == RESOURCE_TYPE_PREFETCH ||
+      request_data.keepalive) {
     auto timeout =
         base::TimeDelta::FromMilliseconds(kDefaultDetachableCancelDelayMs);
     int timeout_set_by_finch_in_sec = base::GetFieldTrialParamByFeatureAsInt(
@@ -1475,14 +1333,10 @@
     mojom::URLLoaderClientPtr url_loader_client,
     ResourceType resource_type) {
   std::unique_ptr<ResourceHandler> handler;
-  if (mojo_request.is_pending()) {
-    handler.reset(new MojoAsyncResourceHandler(
-        request, this, std::move(mojo_request), std::move(url_loader_client),
-        resource_type,
-        false));  // defer_on_response_started.
-  } else {
-    handler.reset(new AsyncResourceHandler(request, this));
-  }
+  handler.reset(
+      new MojoAsyncResourceHandler(request, this, std::move(mojo_request),
+                                   std::move(url_loader_client), resource_type,
+                                   false));  // defer_on_response_started.
   return handler;
 }
 
@@ -1596,27 +1450,6 @@
   return handler;
 }
 
-void ResourceDispatcherHostImpl::OnReleaseDownloadedFile(
-    ResourceRequesterInfo* requester_info,
-    int request_id) {
-  UnregisterDownloadedTempFile(requester_info->child_id(), request_id);
-}
-
-void ResourceDispatcherHostImpl::OnDidChangePriority(
-    ResourceRequesterInfo* requester_info,
-    int request_id,
-    net::RequestPriority new_priority,
-    int intra_priority_value) {
-  ResourceLoader* loader = GetLoader(requester_info->child_id(), request_id);
-  // The request may go away before processing this message, so |loader| can
-  // legitimately be null.
-  if (!loader)
-    return;
-
-  scheduler_->ReprioritizeRequest(loader->request(), new_priority,
-                                  intra_priority_value);
-}
-
 void ResourceDispatcherHostImpl::RegisterDownloadedTempFile(
     int child_id, int request_id, const base::FilePath& file_path) {
   scoped_refptr<ShareableFileReference> reference =
@@ -1653,18 +1486,6 @@
   // when all file refs are deleted (see RegisterDownloadedTempFile).
 }
 
-bool ResourceDispatcherHostImpl::Send(IPC::Message* message) {
-  delete message;
-  return false;
-}
-
-void ResourceDispatcherHostImpl::OnCancelRequest(
-    ResourceRequesterInfo* requester_info,
-    int request_id) {
-  CancelRequestFromRenderer(
-      GlobalRequestID(requester_info->child_id(), request_id));
-}
-
 ResourceRequestInfoImpl* ResourceDispatcherHostImpl::CreateRequestInfo(
     int child_id,
     int render_view_route_id,
@@ -2634,31 +2455,6 @@
   return GetLoader(GlobalRequestID(child_id, request_id));
 }
 
-void ResourceDispatcherHostImpl::RegisterResourceMessageDelegate(
-    const GlobalRequestID& id, ResourceMessageDelegate* delegate) {
-  DelegateMap::iterator it = delegate_map_.find(id);
-  if (it == delegate_map_.end()) {
-    it = delegate_map_.insert(
-                           std::make_pair(
-                               id,
-                               new base::ObserverList<ResourceMessageDelegate>))
-             .first;
-  }
-  it->second->AddObserver(delegate);
-}
-
-void ResourceDispatcherHostImpl::UnregisterResourceMessageDelegate(
-    const GlobalRequestID& id, ResourceMessageDelegate* delegate) {
-  DCHECK(base::ContainsKey(delegate_map_, id));
-  DelegateMap::iterator it = delegate_map_.find(id);
-  DCHECK(it->second->HasObserver(delegate));
-  it->second->RemoveObserver(delegate);
-  if (!it->second->might_have_observers()) {
-    delete it->second;
-    delegate_map_.erase(it);
-  }
-}
-
 bool ResourceDispatcherHostImpl::ShouldServiceRequest(
     int child_id,
     const ResourceRequest& request_data,
diff --git a/content/browser/loader/resource_dispatcher_host_impl.h b/content/browser/loader/resource_dispatcher_host_impl.h
index 19b8912..d92a4e3 100644
--- a/content/browser/loader/resource_dispatcher_host_impl.h
+++ b/content/browser/loader/resource_dispatcher_host_impl.h
@@ -38,7 +38,6 @@
 #include "content/public/common/request_context_type.h"
 #include "content/public/common/resource_type.h"
 #include "content/public/common/url_loader.mojom.h"
-#include "ipc/ipc_message.h"
 #include "net/base/load_states.h"
 #include "net/base/request_priority.h"
 #include "net/traffic_annotation/network_traffic_annotation.h"
@@ -87,11 +86,6 @@
     : public ResourceDispatcherHost,
       public ResourceLoaderDelegate {
  public:
-  // Used to handle the result of SyncLoad IPC. |result| is null if it's
-  // unavailable due to an error.
-  using SyncLoadResultCallback =
-      base::Callback<void(const SyncLoadResult* result)>;
-
   // This constructor should be used if we want downloads to work correctly.
   // TODO(ananta)
   // Work on moving creation of download handlers out of
@@ -126,10 +120,6 @@
   // for it are dead.
   void CancelRequestsForContext(ResourceContext* context);
 
-  // Returns true if the message was a resource message that was processed.
-  bool OnMessageReceived(const IPC::Message& message,
-                         ResourceRequesterInfo* requester_info);
-
   // Cancels the given request if it still exists.
   void CancelRequest(int child_id, int request_id);
 
@@ -208,9 +198,6 @@
       const base::FilePath& file_path);
   void UnregisterDownloadedTempFile(int child_id, int request_id);
 
-  // Needed for the sync IPC message dispatcher macros.
-  bool Send(IPC::Message* message);
-
   // Indicates whether third-party sub-content can pop-up HTTP basic auth
   // dialog boxes.
   bool allow_cross_origin_auth_prompt();
@@ -535,13 +522,6 @@
       const GlobalFrameRoutingId& global_routing_id,
       bool cancel_requests);
 
-  void OnRequestResource(
-      ResourceRequesterInfo* requester_info,
-      int routing_id,
-      int request_id,
-      const ResourceRequest& request_data,
-      net::MutableNetworkTrafficAnnotationTag traffic_annotation);
-
   void OnRequestResourceInternal(
       ResourceRequesterInfo* requester_info,
       int routing_id,
@@ -552,11 +532,6 @@
       mojom::URLLoaderClientPtr url_loader_client,
       const net::NetworkTrafficAnnotationTag& traffic_annotation);
 
-  void OnSyncLoad(ResourceRequesterInfo* requester_info,
-                  int request_id,
-                  const ResourceRequest& request_data,
-                  IPC::Message* sync_result);
-
   bool IsRequestIDInUse(const GlobalRequestID& id) const;
 
   // Update the ResourceRequestInfo and internal maps when a request is
@@ -583,7 +558,6 @@
       int request_id,
       const ResourceRequest& request_data,
       bool is_sync_load,
-      const SyncLoadResultCallback& sync_result_handler,  // only valid for sync
       int route_id,
       mojom::URLLoaderRequest mojo_request,
       mojom::URLLoaderClientPtr url_loader_client,
@@ -602,7 +576,6 @@
       int request_id,
       const ResourceRequest& request_data,
       bool is_sync_load,
-      const SyncLoadResultCallback& sync_result_handler,  // only valid for sync
       int route_id,
       const net::HttpRequestHeaders& headers,
       mojom::URLLoaderRequest mojo_request,
@@ -617,7 +590,6 @@
       ResourceRequesterInfo* requester_info,
       net::URLRequest* request,
       const ResourceRequest& request_data,
-      const SyncLoadResultCallback& sync_result_handler,
       int route_id,
       int child_id,
       ResourceContext* resource_context,
@@ -651,14 +623,6 @@
       NavigationURLLoaderImplCore* navigation_loader_core,
       std::unique_ptr<StreamHandle> stream_handle);
 
-  void OnCancelRequest(ResourceRequesterInfo* requester_info, int request_id);
-  void OnReleaseDownloadedFile(ResourceRequesterInfo* requester_info,
-                               int request_id);
-  void OnDidChangePriority(ResourceRequesterInfo* requester_info,
-                           int request_id,
-                           net::RequestPriority new_priority,
-                           int intra_priority_value);
-
   // Creates ResourceRequestInfoImpl for a download or page save.
   // |download| should be true if the request is a file download.
   ResourceRequestInfoImpl* CreateRequestInfo(
@@ -691,13 +655,6 @@
   ResourceLoader* GetLoader(const GlobalRequestID& id) const;
   ResourceLoader* GetLoader(int child_id, int request_id) const;
 
-  // Registers |delegate| to receive resource IPC messages targeted to the
-  // specified |id|.
-  void RegisterResourceMessageDelegate(const GlobalRequestID& id,
-                                       ResourceMessageDelegate* delegate);
-  void UnregisterResourceMessageDelegate(const GlobalRequestID& id,
-                                         ResourceMessageDelegate* delegate);
-
   // Consults the RendererSecurity policy to determine whether the
   // ResourceDispatcherHostImpl should service this request.  A request might
   // be disallowed if the renderer is not authorized to retrieve the request
@@ -828,10 +785,6 @@
 
   bool allow_cross_origin_auth_prompt_;
 
-  typedef std::map<GlobalRequestID,
-                   base::ObserverList<ResourceMessageDelegate>*> DelegateMap;
-  DelegateMap delegate_map_;
-
   std::unique_ptr<ResourceScheduler> scheduler_;
 
   // Used to invoke an interceptor for the HTTP header.
diff --git a/content/browser/loader/resource_loader_unittest.cc b/content/browser/loader/resource_loader_unittest.cc
index f8f3b77..3c27727 100644
--- a/content/browser/loader/resource_loader_unittest.cc
+++ b/content/browser/loader/resource_loader_unittest.cc
@@ -33,7 +33,6 @@
 #include "content/public/test/test_renderer_host.h"
 #include "content/test/test_content_browser_client.h"
 #include "content/test/test_web_contents.h"
-#include "ipc/ipc_message.h"
 #include "net/base/chunked_upload_data_stream.h"
 #include "net/base/io_buffer.h"
 #include "net/base/net_errors.h"
diff --git a/content/browser/loader/resource_message_delegate.cc b/content/browser/loader/resource_message_delegate.cc
deleted file mode 100644
index 01d3595..0000000
--- a/content/browser/loader/resource_message_delegate.cc
+++ /dev/null
@@ -1,24 +0,0 @@
-// Copyright (c) 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "content/browser/loader/resource_message_delegate.h"
-
-#include "content/browser/loader/resource_dispatcher_host_impl.h"
-#include "content/browser/loader/resource_request_info_impl.h"
-#include "net/url_request/url_request.h"
-
-namespace content {
-
-ResourceMessageDelegate::ResourceMessageDelegate(const net::URLRequest* request)
-    : id_(ResourceRequestInfoImpl::ForRequest(request)->GetGlobalRequestID()) {
-  ResourceDispatcherHostImpl* rdh = ResourceDispatcherHostImpl::Get();
-  rdh->RegisterResourceMessageDelegate(id_, this);
-}
-
-ResourceMessageDelegate::~ResourceMessageDelegate() {
-  ResourceDispatcherHostImpl* rdh = ResourceDispatcherHostImpl::Get();
-  rdh->UnregisterResourceMessageDelegate(id_, this);
-}
-
-}  // namespace content
diff --git a/content/browser/loader/resource_message_delegate.h b/content/browser/loader/resource_message_delegate.h
deleted file mode 100644
index f007f1c..0000000
--- a/content/browser/loader/resource_message_delegate.h
+++ /dev/null
@@ -1,45 +0,0 @@
-// Copyright (c) 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CONTENT_BROWSER_LOADER_RESOURCE_MESSAGE_DELEGATE_H_
-#define CONTENT_BROWSER_LOADER_RESOURCE_MESSAGE_DELEGATE_H_
-
-#include "base/macros.h"
-#include "content/common/content_export.h"
-#include "content/public/browser/global_request_id.h"
-
-namespace IPC {
-class Message;
-}
-
-namespace net {
-class URLRequest;
-}
-
-namespace content {
-
-// A ResourceMessageDelegate receives IPC ResourceMsg_* messages for a specified
-// URLRequest. The delegate should implement its own IPC handler. It will
-// receive the message _after_ the ResourceDispatcherHost has handled it.
-class CONTENT_EXPORT ResourceMessageDelegate {
- public:
-  ResourceMessageDelegate(const net::URLRequest* request);
-  virtual ~ResourceMessageDelegate();
-
-  // Called when the ResourceDispatcherHostImpl receives a message specifically
-  // for this delegate.
-  virtual bool OnMessageReceived(const IPC::Message& message) = 0;
-
-  void set_request_id(const GlobalRequestID& new_request_id) {
-    id_ = new_request_id;
-  }
-
- private:
-  GlobalRequestID id_;
-  DISALLOW_IMPLICIT_CONSTRUCTORS(ResourceMessageDelegate);
-};
-
-}  // namespace content
-
-#endif  // CONTENT_BROWSER_LOADER_RESOURCE_MESSAGE_DELEGATE_H_
diff --git a/content/browser/loader/resource_message_filter.cc b/content/browser/loader/resource_message_filter.cc
index 88f35647..99d348a 100644
--- a/content/browser/loader/resource_message_filter.cc
+++ b/content/browser/loader/resource_message_filter.cc
@@ -72,10 +72,7 @@
 
 bool ResourceMessageFilter::OnMessageReceived(const IPC::Message& message) {
   DCHECK(io_thread_task_runner_->BelongsToCurrentThread());
-  // Check if InitializeOnIOThread() has been called.
-  DCHECK_EQ(this, requester_info_->filter());
-  return ResourceDispatcherHostImpl::Get()->OnMessageReceived(
-      message, requester_info_.get());
+  return false;
 }
 
 void ResourceMessageFilter::OnDestruct() const {
diff --git a/content/browser/loader/sync_resource_handler.cc b/content/browser/loader/sync_resource_handler.cc
deleted file mode 100644
index e65d9e5..0000000
--- a/content/browser/loader/sync_resource_handler.cc
+++ /dev/null
@@ -1,132 +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/browser/loader/sync_resource_handler.h"
-
-#include "base/callback_helpers.h"
-#include "base/logging.h"
-#include "content/browser/loader/resource_controller.h"
-#include "content/browser/loader/resource_dispatcher_host_impl.h"
-#include "content/browser/loader/resource_request_info_impl.h"
-#include "content/common/resource_messages.h"
-#include "content/public/browser/resource_dispatcher_host_delegate.h"
-#include "content/public/browser/resource_request_info.h"
-#include "net/base/io_buffer.h"
-#include "net/http/http_response_headers.h"
-#include "net/url_request/redirect_info.h"
-
-namespace content {
-
-SyncResourceHandler::SyncResourceHandler(
-    net::URLRequest* request,
-    const SyncLoadResultCallback& result_handler,
-    ResourceDispatcherHostImpl* resource_dispatcher_host)
-    : ResourceHandler(request),
-      read_buffer_(new net::IOBuffer(kReadBufSize)),
-      result_handler_(result_handler),
-      rdh_(resource_dispatcher_host),
-      total_transfer_size_(0) {
-  result_.final_url = request->url();
-}
-
-SyncResourceHandler::~SyncResourceHandler() {
-  if (result_handler_)
-    result_handler_.Run(nullptr);
-}
-
-void SyncResourceHandler::OnRequestRedirected(
-    const net::RedirectInfo& redirect_info,
-    ResourceResponse* response,
-    std::unique_ptr<ResourceController> controller) {
-  if (rdh_->delegate()) {
-    rdh_->delegate()->OnRequestRedirected(
-        redirect_info.new_url, request(), GetRequestInfo()->GetContext(),
-        response);
-  }
-
-  // TODO(darin): It would be much better if this could live in WebCore, but
-  // doing so requires API changes at all levels.  Similar code exists in
-  // WebCore/platform/network/cf/ResourceHandleCFNet.cpp :-(
-  if (redirect_info.new_url.GetOrigin() != result_.final_url.GetOrigin()) {
-    LOG(ERROR) << "Cross origin redirect denied";
-    controller->Cancel();
-    return;
-  }
-  result_.final_url = redirect_info.new_url;
-
-  total_transfer_size_ += request()->GetTotalReceivedBytes();
-  controller->Resume();
-}
-
-void SyncResourceHandler::OnResponseStarted(
-    ResourceResponse* response,
-    std::unique_ptr<ResourceController> controller) {
-  ResourceRequestInfoImpl* info = GetRequestInfo();
-  DCHECK(info->requester_info()->IsRenderer());
-  if (!info->requester_info()->filter()) {
-    controller->Cancel();
-    return;
-  }
-
-  if (rdh_->delegate()) {
-    rdh_->delegate()->OnResponseStarted(request(), info->GetContext(),
-                                        response);
-  }
-
-  // We don't care about copying the status here.
-  result_.headers = response->head.headers;
-  result_.mime_type = response->head.mime_type;
-  result_.charset = response->head.charset;
-  result_.download_file_path = response->head.download_file_path;
-  result_.request_time = response->head.request_time;
-  result_.response_time = response->head.response_time;
-  result_.load_timing = response->head.load_timing;
-  result_.devtools_info = response->head.devtools_info;
-  result_.socket_address = response->head.socket_address;
-  controller->Resume();
-}
-
-void SyncResourceHandler::OnWillStart(
-    const GURL& url,
-    std::unique_ptr<ResourceController> controller) {
-  controller->Resume();
-}
-
-void SyncResourceHandler::OnWillRead(
-    scoped_refptr<net::IOBuffer>* buf,
-    int* buf_size,
-    std::unique_ptr<ResourceController> controller) {
-  *buf = read_buffer_.get();
-  *buf_size = kReadBufSize;
-  controller->Resume();
-}
-
-void SyncResourceHandler::OnReadCompleted(
-    int bytes_read,
-    std::unique_ptr<ResourceController> controller) {
-  if (bytes_read)
-    result_.data.append(read_buffer_->data(), bytes_read);
-  controller->Resume();
-}
-
-void SyncResourceHandler::OnResponseCompleted(
-    const net::URLRequestStatus& status,
-    std::unique_ptr<ResourceController> controller) {
-  result_.error_code = status.error();
-
-  int total_transfer_size = request()->GetTotalReceivedBytes();
-  result_.encoded_data_length = total_transfer_size_ + total_transfer_size;
-  result_.encoded_body_length = request()->GetRawBodyBytes();
-
-  base::ResetAndReturn(&result_handler_).Run(&result_);
-
-  controller->Resume();
-}
-
-void SyncResourceHandler::OnDataDownloaded(int bytes_downloaded) {
-  // Sync requests don't involve ResourceMsg_DataDownloaded messages
-  // being sent back to renderers as progress is made.
-}
-
-}  // namespace content
diff --git a/content/browser/loader/sync_resource_handler.h b/content/browser/loader/sync_resource_handler.h
deleted file mode 100644
index 881be7f..0000000
--- a/content/browser/loader/sync_resource_handler.h
+++ /dev/null
@@ -1,68 +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_BROWSER_LOADER_SYNC_RESOURCE_HANDLER_H_
-#define CONTENT_BROWSER_LOADER_SYNC_RESOURCE_HANDLER_H_
-
-#include <stdint.h>
-
-#include <string>
-
-#include "content/browser/loader/resource_dispatcher_host_impl.h"
-#include "content/browser/loader/resource_handler.h"
-#include "content/public/common/resource_response.h"
-
-namespace net {
-class IOBuffer;
-class URLRequest;
-}
-
-namespace content {
-class ResourceController;
-
-// Used to complete a synchronous resource request in response to resource load
-// events from the resource dispatcher host.
-class SyncResourceHandler : public ResourceHandler {
- public:
-  using SyncLoadResultCallback =
-      ResourceDispatcherHostImpl::SyncLoadResultCallback;
-
-  SyncResourceHandler(net::URLRequest* request,
-                      const SyncLoadResultCallback& sync_result_handler,
-                      ResourceDispatcherHostImpl* resource_dispatcher_host);
-  ~SyncResourceHandler() override;
-
-  void OnRequestRedirected(
-      const net::RedirectInfo& redirect_info,
-      ResourceResponse* response,
-      std::unique_ptr<ResourceController> controller) override;
-  void OnResponseStarted(
-      ResourceResponse* response,
-      std::unique_ptr<ResourceController> controller) override;
-  void OnWillStart(const GURL& url,
-                   std::unique_ptr<ResourceController> controller) override;
-  void OnWillRead(scoped_refptr<net::IOBuffer>* buf,
-                  int* buf_size,
-                  std::unique_ptr<ResourceController> controller) override;
-  void OnReadCompleted(int bytes_read,
-                       std::unique_ptr<ResourceController> controller) override;
-  void OnResponseCompleted(
-      const net::URLRequestStatus& status,
-      std::unique_ptr<ResourceController> controller) override;
-  void OnDataDownloaded(int bytes_downloaded) override;
-
- private:
-  enum { kReadBufSize = 3840 };
-
-  scoped_refptr<net::IOBuffer> read_buffer_;
-
-  SyncLoadResult result_;
-  SyncLoadResultCallback result_handler_;
-  ResourceDispatcherHostImpl* rdh_;
-  int64_t total_transfer_size_;
-};
-
-}  // namespace content
-
-#endif  // CONTENT_BROWSER_LOADER_SYNC_RESOURCE_HANDLER_H_
diff --git a/content/browser/renderer_host/DEPS b/content/browser/renderer_host/DEPS
index eb2fa51..535dcfd 100644
--- a/content/browser/renderer_host/DEPS
+++ b/content/browser/renderer_host/DEPS
@@ -56,4 +56,13 @@
   "render_widget_host_input_event_router.cc": [
     "+content/browser/frame_host/render_widget_host_view_guest.h",
   ],
+  # TODO(crbug.com/797362): The dependency is required to find the correct
+  # target from a FrameSinkId. This should be removed from here, and instead
+  # provided through a delegate interface that is implemented in web_contents.
+  "render_widget_targeter.cc": [
+    "+content/browser/frame_host/frame_tree_node.h",
+    "+content/browser/frame_host/render_frame_host_impl.h",
+    "+content/browser/frame_host/render_frame_host_manager.h",
+    "+content/browser/frame_host/render_frame_proxy_host.h",
+  ],
 }
diff --git a/content/browser/renderer_host/render_widget_host_impl.cc b/content/browser/renderer_host/render_widget_host_impl.cc
index 9889acc..bba9a45 100644
--- a/content/browser/renderer_host/render_widget_host_impl.cc
+++ b/content/browser/renderer_host/render_widget_host_impl.cc
@@ -2890,6 +2890,11 @@
   }
 }
 
+void RenderWidgetHostImpl::SetInputTargetClient(
+    viz::mojom::InputTargetClientPtr input_target_client) {
+  input_target_client_ = std::move(input_target_client);
+}
+
 void RenderWidgetHostImpl::SetWidget(mojom::WidgetPtr widget) {
   if (widget && base::FeatureList::IsEnabled(features::kMojoInputMessages)) {
     // If we have a bound handler ensure that we destroy the old input router.
diff --git a/content/browser/renderer_host/render_widget_host_impl.h b/content/browser/renderer_host/render_widget_host_impl.h
index 5ada4f00f..8e50a95 100644
--- a/content/browser/renderer_host/render_widget_host_impl.h
+++ b/content/browser/renderer_host/render_widget_host_impl.h
@@ -51,6 +51,7 @@
 #include "ipc/ipc_listener.h"
 #include "mojo/public/cpp/bindings/binding.h"
 #include "services/viz/public/interfaces/compositing/compositor_frame_sink.mojom.h"
+#include "services/viz/public/interfaces/hit_test/input_target_client.mojom.h"
 #include "third_party/WebKit/public/platform/WebDisplayMode.h"
 #include "ui/base/ime/text_input_mode.h"
 #include "ui/base/ime/text_input_type.h"
@@ -614,6 +615,13 @@
       mojom::WidgetInputHandlerHostRequest host_request);
   void SetWidget(mojom::WidgetPtr widget);
 
+  viz::mojom::InputTargetClient* input_target_client() {
+    return input_target_client_.get();
+  }
+
+  void SetInputTargetClient(
+      viz::mojom::InputTargetClientPtr input_target_client);
+
   // InputRouterImplClient overrides.
   mojom::WidgetInputHandler* GetWidgetInputHandler() override;
   void OnImeCompositionRangeChanged(
@@ -1040,6 +1048,7 @@
   mojom::WidgetInputHandlerAssociatedPtr associated_widget_input_handler_;
   mojom::WidgetInputHandlerPtr widget_input_handler_;
   std::unique_ptr<mojom::WidgetInputHandler> legacy_widget_input_handler_;
+  viz::mojom::InputTargetClientPtr input_target_client_;
 
   base::WeakPtrFactory<RenderWidgetHostImpl> weak_factory_;
 
diff --git a/content/browser/renderer_host/render_widget_host_input_event_router.cc b/content/browser/renderer_host/render_widget_host_input_event_router.cc
index eb2bc32..4c22f678 100644
--- a/content/browser/renderer_host/render_widget_host_input_event_router.cc
+++ b/content/browser/renderer_host/render_widget_host_input_event_router.cc
@@ -21,7 +21,6 @@
 #include "content/browser/renderer_host/render_widget_host_view_child_frame.h"
 #include "content/common/frame_messages.h"
 #include "third_party/WebKit/public/platform/WebInputEvent.h"
-#include "ui/events/blink/web_input_event_traits.h"
 
 namespace {
 
@@ -157,7 +156,9 @@
       last_mouse_move_root_view_(nullptr),
       active_touches_(0),
       in_touchscreen_gesture_pinch_(false),
-      gesture_pinch_did_send_scroll_begin_(false) {
+      gesture_pinch_did_send_scroll_begin_(false),
+      event_targeter_(std::make_unique<RenderWidgetTargeter>(this)),
+      weak_ptr_factory_(this) {
   enable_viz_ =
       base::CommandLine::ForCurrentProcess()->HasSwitch(switches::kEnableViz);
 }
@@ -168,10 +169,9 @@
   ClearAllObserverRegistrations();
 }
 
-RenderWidgetHostViewBase* RenderWidgetHostInputEventRouter::FindEventTarget(
+RenderWidgetTargetResult RenderWidgetHostInputEventRouter::FindMouseEventTarget(
     RenderWidgetHostViewBase* root_view,
-    const blink::WebMouseEvent& event,
-    gfx::PointF* transformed_point) const {
+    const blink::WebMouseEvent& event) const {
   RenderWidgetHostViewBase* target = nullptr;
   bool needs_transform_point = true;
   if (root_view->IsMouseLocked()) {
@@ -194,10 +194,15 @@
     target = mouse_capture_target_.target;
   }
 
+  gfx::PointF transformed_point;
   if (!target) {
-    target = FindViewAtLocation(root_view, event.PositionInWidget(),
-                                event.PositionInScreen(),
-                                viz::EventSource::MOUSE, transformed_point);
+    auto result = FindViewAtLocation(
+        root_view, event.PositionInWidget(), event.PositionInScreen(),
+        viz::EventSource::MOUSE, &transformed_point);
+    if (result.should_query_view) {
+      return {result.view, true, transformed_point};
+    }
+    target = result.view;
     // |transformed_point| is already transformed.
     needs_transform_point = false;
   }
@@ -218,20 +223,21 @@
       needs_transform_point = true;
     } else {
       needs_transform_point = false;
-      *transformed_point = event.PositionInWidget();
+      transformed_point = event.PositionInWidget();
     }
     target = owner_view;
   }
 
   if (needs_transform_point) {
     if (!root_view->TransformPointToCoordSpaceForView(
-            event.PositionInWidget(), target, transformed_point))
-      return nullptr;
+            event.PositionInWidget(), target, &transformed_point)) {
+      return {nullptr, false, base::nullopt};
+    }
   }
-  return target;
+  return {target, false, transformed_point};
 }
 
-RenderWidgetHostViewBase* RenderWidgetHostInputEventRouter::FindViewAtLocation(
+RenderWidgetTargetResult RenderWidgetHostInputEventRouter::FindViewAtLocation(
     RenderWidgetHostViewBase* root_view,
     const gfx::PointF& point,
     const gfx::PointF& point_in_screen,
@@ -239,13 +245,14 @@
     gfx::PointF* transformed_point) const {
   viz::FrameSinkId frame_sink_id;
 
+  bool query_renderer = false;
   if (enable_viz_) {
     const auto& display_hit_test_query_map =
         GetHostFrameSinkManager()->display_hit_test_query();
     const auto iter =
         display_hit_test_query_map.find(root_view->GetRootFrameSinkId());
     if (iter == display_hit_test_query_map.end())
-      return root_view;
+      return {root_view, false, base::nullopt};
     // |point| is in the coordinate space of of the screen, but the display
     // HitTestQuery does a hit test in the coordinate space of the root
     // window. The following translation should account for that discrepancy.
@@ -268,18 +275,13 @@
     // hit testing.
     if (owner_map_.size() <= 1) {
       *transformed_point = point;
-      return root_view;
+      return {root_view, false, *transformed_point};
     }
 
     // The hittest delegate is used to reject hittesting quads based on extra
     // hittesting data send by the renderer.
     HittestDelegate delegate(hittest_data_);
 
-    // TODO(kenrb, sadrul): If this is set to true by FrameSinkIdAtPoint,
-    // invoke the InputTargetClient interface on the root view's frame (and on
-    // any OOPIFs also, if any are hit).
-    bool query_renderer = false;
-
     // The conversion of point to transform_point is done over the course of the
     // hit testing, and reflect transformations that would normally be applied
     // in the renderer process if the event was being routed between frames
@@ -294,38 +296,40 @@
   // If the point hit a Surface whose namspace is no longer in the map, then
   // it likely means the RenderWidgetHostView has been destroyed but its
   // parent frame has not sent a new compositor frame since that happened.
-  return (iter == owner_map_.end()) ? root_view : iter->second;
+  return {(iter == owner_map_.end()) ? root_view : iter->second, query_renderer,
+          *transformed_point};
 }
 
 void RenderWidgetHostInputEventRouter::RouteMouseEvent(
     RenderWidgetHostViewBase* root_view,
     blink::WebMouseEvent* event,
     const ui::LatencyInfo& latency) {
-  gfx::PointF transformed_point;
-  RenderWidgetHostViewBase* const target =
-      FindEventTarget(root_view, *event, &transformed_point);
-  if (!target)
-    return;
+  event_targeter_->FindTargetAndDispatch(root_view, *event, latency);
+}
 
-  if (event->GetType() == blink::WebInputEvent::kMouseUp)
+void RenderWidgetHostInputEventRouter::DispatchMouseEvent(
+    RenderWidgetHostViewBase* root_view,
+    RenderWidgetHostViewBase* target,
+    const blink::WebMouseEvent& mouse_event,
+    const ui::LatencyInfo& latency) {
+  if (mouse_event.GetType() == blink::WebInputEvent::kMouseUp)
     mouse_capture_target_.target = nullptr;
-  else if (event->GetType() == blink::WebInputEvent::kMouseDown)
+  else if (mouse_event.GetType() == blink::WebInputEvent::kMouseDown)
     mouse_capture_target_.target = target;
 
   // SendMouseEnterOrLeaveEvents is called with the original event
   // coordinates, which are transformed independently for each view that will
   // receive an event. Also, since the view under the mouse has changed,
   // notify the CursorManager that it might need to change the cursor.
-  if ((event->GetType() == blink::WebInputEvent::kMouseLeave ||
-       event->GetType() == blink::WebInputEvent::kMouseMove) &&
+  if ((mouse_event.GetType() == blink::WebInputEvent::kMouseLeave ||
+       mouse_event.GetType() == blink::WebInputEvent::kMouseMove) &&
       target != last_mouse_move_target_) {
-    SendMouseEnterOrLeaveEvents(event, target, root_view);
+    SendMouseEnterOrLeaveEvents(mouse_event, target, root_view);
     if (root_view->GetCursorManager())
       root_view->GetCursorManager()->UpdateViewUnderCursor(target);
   }
 
-  event->SetPositionInWidget(transformed_point.x(), transformed_point.y());
-  target->ProcessMouseEvent(*event, latency);
+  target->ProcessMouseEvent(mouse_event, latency);
 }
 
 void RenderWidgetHostInputEventRouter::RouteMouseWheelEvent(
@@ -348,9 +352,11 @@
     }
   } else if (root_view->wheel_scroll_latching_enabled()) {
     if (event->phase == blink::WebMouseWheelEvent::kPhaseBegan) {
-      wheel_target_.target = FindViewAtLocation(
+      auto result = FindViewAtLocation(
           root_view, event->PositionInWidget(), event->PositionInScreen(),
           viz::EventSource::MOUSE, &transformed_point);
+      // TOOD(crbug.com/796656): Do not ignore |result.should_query_view|.
+      wheel_target_.target = result.view;
       wheel_target_.delta = transformed_point - event->PositionInWidget();
       target = wheel_target_.target;
     } else {
@@ -376,9 +382,11 @@
 
   } else {  // !root_view->IsMouseLocked() &&
     // !root_view->wheel_scroll_latching_enabled()
-    target = FindViewAtLocation(root_view, event->PositionInWidget(),
-                                event->PositionInScreen(),
-                                viz::EventSource::MOUSE, &transformed_point);
+    auto result = FindViewAtLocation(
+        root_view, event->PositionInWidget(), event->PositionInScreen(),
+        viz::EventSource::MOUSE, &transformed_point);
+    // TOOD(crbug.com/796656): Do not ignore |result.should_query_view|.
+    target = result.view;
   }
 
   if (!target) {
@@ -485,9 +493,11 @@
         gfx::PointF original_point_in_screen(
             event->touches[0].PositionInScreen().x,
             event->touches[0].PositionInScreen().y);
-        touch_target_.target = FindViewAtLocation(
+        auto result = FindViewAtLocation(
             root_view, original_point, original_point_in_screen,
             viz::EventSource::TOUCH, &transformed_point);
+        // TOOD(crbug.com/796656): Do not ignore |result.should_query_view|.
+        touch_target_.target = result.view;
 
         // TODO(wjmaclean): Instead of just computing a delta, we should extract
         // the complete transform. We assume it doesn't change for the duration
@@ -560,7 +570,7 @@
 }
 
 void RenderWidgetHostInputEventRouter::SendMouseEnterOrLeaveEvents(
-    blink::WebMouseEvent* event,
+    const blink::WebMouseEvent& event,
     RenderWidgetHostViewBase* target,
     RenderWidgetHostViewBase* root_view) {
   // This method treats RenderWidgetHostViews as a tree, where the mouse
@@ -638,13 +648,13 @@
   gfx::PointF transformed_point;
   // Send MouseLeaves.
   for (auto* view : exited_views) {
-    blink::WebMouseEvent mouse_leave(*event);
+    blink::WebMouseEvent mouse_leave(event);
     mouse_leave.SetType(blink::WebInputEvent::kMouseLeave);
     // There is a chance of a race if the last target has recently created a
     // new compositor surface. The SurfaceID for that might not have
     // propagated to its embedding surface, which makes it impossible to
     // compute the transformation for it
-    if (!root_view->TransformPointToCoordSpaceForView(event->PositionInWidget(),
+    if (!root_view->TransformPointToCoordSpaceForView(event.PositionInWidget(),
                                                       view, &transformed_point))
       transformed_point = gfx::PointF();
     mouse_leave.SetPositionInWidget(transformed_point.x(),
@@ -654,10 +664,10 @@
 
   // The ancestor might need to trigger MouseOut handlers.
   if (common_ancestor && common_ancestor != target) {
-    blink::WebMouseEvent mouse_move(*event);
+    blink::WebMouseEvent mouse_move(event);
     mouse_move.SetType(blink::WebInputEvent::kMouseMove);
     if (!root_view->TransformPointToCoordSpaceForView(
-            event->PositionInWidget(), common_ancestor, &transformed_point))
+            event.PositionInWidget(), common_ancestor, &transformed_point))
       transformed_point = gfx::PointF();
     mouse_move.SetPositionInWidget(transformed_point.x(),
                                    transformed_point.y());
@@ -668,9 +678,9 @@
   for (auto* view : entered_views) {
     if (view == target)
       continue;
-    blink::WebMouseEvent mouse_enter(*event);
+    blink::WebMouseEvent mouse_enter(event);
     mouse_enter.SetType(blink::WebInputEvent::kMouseMove);
-    if (!root_view->TransformPointToCoordSpaceForView(event->PositionInWidget(),
+    if (!root_view->TransformPointToCoordSpaceForView(event.PositionInWidget(),
                                                       view, &transformed_point))
       transformed_point = gfx::PointF();
     mouse_enter.SetPositionInWidget(transformed_point.x(),
@@ -926,7 +936,7 @@
   return RenderWidgetHostImpl::From(
       FindViewAtLocation(root_view, point, gfx::PointF(),
                          viz::EventSource::MOUSE, transformed_point)
-          ->GetRenderWidgetHost());
+          .view->GetRenderWidgetHost());
 }
 
 void RenderWidgetHostInputEventRouter::RouteTouchscreenGestureEvent(
@@ -1006,9 +1016,11 @@
     gfx::PointF transformed_point;
     gfx::PointF original_point(event->x, event->y);
     gfx::PointF original_point_in_screen(event->global_x, event->global_y);
-    touchscreen_gesture_target_.target =
+    auto result =
         FindViewAtLocation(root_view, original_point, original_point_in_screen,
                            viz::EventSource::TOUCH, &transformed_point);
+    // TOOD(crbug.com/796656): Do not ignore |result.should_query_view|.
+    touchscreen_gesture_target_.target = result.view;
     touchscreen_gesture_target_.delta = transformed_point - original_point;
   } else if (is_gesture_start) {
     touchscreen_gesture_target_ = gesture_target_it->second;
@@ -1047,9 +1059,11 @@
     gfx::PointF transformed_point;
     gfx::PointF original_point(event->x, event->y);
     gfx::PointF original_point_in_screen(event->global_x, event->global_y);
-    touchpad_gesture_target_.target =
+    auto result =
         FindViewAtLocation(root_view, original_point, original_point_in_screen,
                            viz::EventSource::TOUCH, &transformed_point);
+    // TOOD(crbug.com/796656): Do not ignore |result.should_query_view|.
+    touchpad_gesture_target_.target = result.view;
     // TODO(mohsen): Instead of just computing a delta, we should extract the
     // complete transform. We assume it doesn't change for the duration of the
     // touchpad gesture sequence, though this could be wrong; a better approach
@@ -1088,4 +1102,32 @@
   return hosts;
 }
 
+RenderWidgetTargetResult
+RenderWidgetHostInputEventRouter::FindTargetSynchronously(
+    RenderWidgetHostViewBase* root_view,
+    const blink::WebInputEvent& event) {
+  if (blink::WebInputEvent::IsMouseEventType(event.GetType())) {
+    return FindMouseEventTarget(
+        root_view, static_cast<const blink::WebMouseEvent&>(event));
+  }
+  // TODO(crbug.com/796656): Handle other types of events.
+  NOTREACHED();
+  return RenderWidgetTargetResult();
+}
+
+void RenderWidgetHostInputEventRouter::DispatchEventToTarget(
+    RenderWidgetHostViewBase* root_view,
+    RenderWidgetHostViewBase* target,
+    const blink::WebInputEvent& event,
+    const ui::LatencyInfo& latency) {
+  if (blink::WebInputEvent::IsMouseEventType(event.GetType())) {
+    DispatchMouseEvent(root_view, target,
+                       static_cast<const blink::WebMouseEvent&>(event),
+                       latency);
+    return;
+  }
+  // TODO(crbug.com/796656): Handle other types of events.
+  NOTREACHED();
+}
+
 }  // namespace content
diff --git a/content/browser/renderer_host/render_widget_host_input_event_router.h b/content/browser/renderer_host/render_widget_host_input_event_router.h
index b4b5d33..38544508 100644
--- a/content/browser/renderer_host/render_widget_host_input_event_router.h
+++ b/content/browser/renderer_host/render_widget_host_input_event_router.h
@@ -14,10 +14,12 @@
 #include "base/containers/hash_tables.h"
 #include "base/gtest_prod_util.h"
 #include "base/macros.h"
+#include "base/memory/weak_ptr.h"
 #include "components/viz/common/surfaces/surface_id.h"
 #include "components/viz/host/hit_test/hit_test_query.h"
 #include "components/viz/service/surfaces/surface_hittest_delegate.h"
 #include "content/browser/renderer_host/render_widget_host_view_base_observer.h"
+#include "content/browser/renderer_host/render_widget_targeter.h"
 #include "content/common/content_export.h"
 #include "ui/gfx/geometry/vector2d_conversions.h"
 
@@ -25,6 +27,7 @@
 
 namespace blink {
 class WebGestureEvent;
+class WebInputEvent;
 class WebMouseEvent;
 class WebMouseWheelEvent;
 class WebTouchEvent;
@@ -44,6 +47,7 @@
 class RenderWidgetHostImpl;
 class RenderWidgetHostView;
 class RenderWidgetHostViewBase;
+class RenderWidgetTargeter;
 
 // Class owned by WebContentsImpl for the purpose of directing input events
 // to the correct RenderWidgetHost on pages with multiple RenderWidgetHosts.
@@ -52,7 +56,8 @@
 // this class requests a Surface hit test from the provided |root_view| and
 // forwards the event to the owning RWHV of the returned Surface ID.
 class CONTENT_EXPORT RenderWidgetHostInputEventRouter
-    : public RenderWidgetHostViewBaseObserver {
+    : public RenderWidgetHostViewBaseObserver,
+      public RenderWidgetTargeter::Delegate {
  public:
   RenderWidgetHostInputEventRouter();
   ~RenderWidgetHostInputEventRouter() final;
@@ -131,12 +136,7 @@
   using TargetMap = std::map<uint32_t, TargetData>;
 
   void ClearAllObserverRegistrations();
-  RenderWidgetHostViewBase* FindEventTarget(
-      RenderWidgetHostViewBase* root_view,
-      const blink::WebMouseEvent& event,
-      gfx::PointF* transformed_point) const;
-
-  RenderWidgetHostViewBase* FindViewAtLocation(
+  RenderWidgetTargetResult FindViewAtLocation(
       RenderWidgetHostViewBase* root_view,
       const gfx::PointF& point,
       const gfx::PointF& point_in_screen,
@@ -155,7 +155,7 @@
   // properly fire. This method determines which RenderWidgetHostViews other
   // than the actual target require notification, and sends the appropriate
   // events to them.
-  void SendMouseEnterOrLeaveEvents(blink::WebMouseEvent* event,
+  void SendMouseEnterOrLeaveEvents(const blink::WebMouseEvent& event,
                                    RenderWidgetHostViewBase* target,
                                    RenderWidgetHostViewBase* root_view);
 
@@ -167,6 +167,26 @@
   void SendGestureScrollEnd(RenderWidgetHostViewBase* view,
                             const blink::WebGestureEvent& event);
 
+  // Helper functions to implement RenderWidgetTargeter::Delegate functions.
+  RenderWidgetTargetResult FindMouseEventTarget(
+      RenderWidgetHostViewBase* root_view,
+      const blink::WebMouseEvent& event) const;
+
+  // |mouse_event| is in the coord-space of |target|.
+  void DispatchMouseEvent(RenderWidgetHostViewBase* root_view,
+                          RenderWidgetHostViewBase* target,
+                          const blink::WebMouseEvent& mouse_event,
+                          const ui::LatencyInfo& latency);
+
+  // RenderWidgetTargeter::Delegate:
+  RenderWidgetTargetResult FindTargetSynchronously(
+      RenderWidgetHostViewBase* root_view,
+      const blink::WebInputEvent& event) override;
+  void DispatchEventToTarget(RenderWidgetHostViewBase* root_view,
+                             RenderWidgetHostViewBase* target,
+                             const blink::WebInputEvent& event,
+                             const ui::LatencyInfo& latency) override;
+
   FrameSinkIdOwnerMap owner_map_;
   TargetMap touchscreen_gesture_target_map_;
   TargetData touch_target_;
@@ -193,8 +213,11 @@
   std::unordered_map<viz::SurfaceId, HittestData, viz::SurfaceIdHash>
       hittest_data_;
 
+  std::unique_ptr<RenderWidgetTargeter> event_targeter_;
   bool enable_viz_ = false;
 
+  base::WeakPtrFactory<RenderWidgetHostInputEventRouter> weak_ptr_factory_;
+
   DISALLOW_COPY_AND_ASSIGN(RenderWidgetHostInputEventRouter);
   friend class RenderWidgetHostInputEventRouterTest;
   FRIEND_TEST_ALL_PREFIXES(SitePerProcessBrowserTest,
diff --git a/content/browser/renderer_host/render_widget_targeter.cc b/content/browser/renderer_host/render_widget_targeter.cc
new file mode 100644
index 0000000..81efe59
--- /dev/null
+++ b/content/browser/renderer_host/render_widget_targeter.cc
@@ -0,0 +1,221 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/browser/renderer_host/render_widget_targeter.h"
+
+#include "content/browser/frame_host/frame_tree_node.h"
+#include "content/browser/frame_host/render_frame_host_impl.h"
+#include "content/browser/frame_host/render_frame_host_manager.h"
+#include "content/browser/frame_host/render_frame_proxy_host.h"
+#include "content/browser/renderer_host/render_widget_host_impl.h"
+#include "content/browser/renderer_host/render_widget_host_view_base.h"
+#include "third_party/WebKit/public/platform/WebInputEvent.h"
+
+namespace content {
+
+namespace {
+
+blink::WebMouseEvent Convert(RenderWidgetHostViewBase* root_view,
+                             RenderWidgetHostViewBase* target,
+                             const blink::WebMouseEvent& event) {
+  if (root_view != target) {
+    auto mouse_event = event;
+    gfx::PointF transformed_point;
+    if (!root_view->TransformPointToCoordSpaceForView(
+            mouse_event.PositionInWidget(), target, &transformed_point)) {
+      return blink::WebMouseEvent();
+    }
+    mouse_event.SetPositionInWidget(transformed_point.x(),
+                                    transformed_point.y());
+    return mouse_event;
+  }
+  return event;
+}
+
+// TODO(crbug.com/796656): Currently merges only mouse-move events. This needs
+// to handle more events (e.g. wheel, touch-move etc.).
+bool MergeEventIfPossible(const blink::WebInputEvent& event,
+                          ui::WebScopedInputEvent* blink_event) {
+  if (event.GetType() == blink::WebInputEvent::kMouseMove &&
+      (*blink_event)->GetType() == event.GetType() &&
+      (*blink_event)->GetModifiers() == event.GetModifiers()) {
+    *blink_event = ui::WebInputEventTraits::Clone(event);
+    return true;
+  }
+  return false;
+}
+
+}  // namespace
+
+RenderWidgetTargetResult::RenderWidgetTargetResult() = default;
+
+RenderWidgetTargetResult::RenderWidgetTargetResult(
+    const RenderWidgetTargetResult&) = default;
+
+RenderWidgetTargetResult::RenderWidgetTargetResult(
+    RenderWidgetHostViewBase* in_view,
+    bool in_should_query_view,
+    base::Optional<gfx::PointF> in_location)
+    : view(in_view),
+      should_query_view(in_should_query_view),
+      target_location(in_location) {}
+
+RenderWidgetTargetResult::~RenderWidgetTargetResult() = default;
+
+RenderWidgetTargeter::TargetingRequest::TargetingRequest() = default;
+
+RenderWidgetTargeter::TargetingRequest::TargetingRequest(
+    TargetingRequest&& request) = default;
+
+RenderWidgetTargeter::TargetingRequest& RenderWidgetTargeter::TargetingRequest::
+operator=(TargetingRequest&&) = default;
+
+RenderWidgetTargeter::TargetingRequest::~TargetingRequest() = default;
+
+RenderWidgetTargeter::RenderWidgetTargeter(Delegate* delegate)
+    : delegate_(delegate), weak_ptr_factory_(this) {
+  DCHECK(delegate_);
+}
+
+RenderWidgetTargeter::~RenderWidgetTargeter() = default;
+
+void RenderWidgetTargeter::FindTargetAndDispatch(
+    RenderWidgetHostViewBase* root_view,
+    const blink::WebInputEvent& event,
+    const ui::LatencyInfo& latency) {
+  if (request_in_flight_) {
+    if (!requests_.empty()) {
+      auto& request = requests_.back();
+      if (MergeEventIfPossible(event, &request.event))
+        return;
+    }
+    TargetingRequest request;
+    request.root_view = root_view->GetWeakPtr();
+    request.event = ui::WebInputEventTraits::Clone(event);
+    request.latency = latency;
+    requests_.push(std::move(request));
+    return;
+  }
+
+  RenderWidgetTargetResult result =
+      delegate_->FindTargetSynchronously(root_view, event);
+  if (!result.view)
+    return;
+
+  RenderWidgetHostViewBase* target = result.view;
+  auto* event_ptr = &event;
+  if (result.should_query_view) {
+    QueryClient(root_view, target, *event_ptr, latency, result.target_location);
+  } else {
+    FoundTarget(root_view, target, *event_ptr, latency, result.target_location);
+  }
+}
+
+void RenderWidgetTargeter::QueryClient(
+    RenderWidgetHostViewBase* root_view,
+    RenderWidgetHostViewBase* target,
+    const blink::WebInputEvent& event,
+    const ui::LatencyInfo& latency,
+    const base::Optional<gfx::PointF>& target_location) {
+  DCHECK(!request_in_flight_);
+  DCHECK(blink::WebInputEvent::IsMouseEventType(event.GetType()));
+  auto mouse_event = static_cast<const blink::WebMouseEvent&>(event);
+  if (target_location.has_value()) {
+    mouse_event.SetPositionInWidget(target_location->x(), target_location->y());
+  } else {
+    mouse_event = Convert(root_view, target, mouse_event);
+  }
+  if (mouse_event.GetType() == blink::WebInputEvent::kUndefined)
+    return;
+  request_in_flight_ = true;
+  float scale_factor = root_view->current_device_scale_factor();
+  auto* target_client =
+      target->GetRenderWidgetHostImpl()->input_target_client();
+  target_client->FrameSinkIdAt(
+      gfx::ScaleToCeiledPoint(
+          gfx::ToCeiledPoint(mouse_event.PositionInWidget()), scale_factor,
+          scale_factor),
+      base::BindOnce(&RenderWidgetTargeter::FoundFrameSinkId,
+                     weak_ptr_factory_.GetWeakPtr(), root_view->GetWeakPtr(),
+                     target->GetWeakPtr(),
+                     static_cast<const blink::WebMouseEvent&>(event), latency,
+                     target_location));
+}
+
+void RenderWidgetTargeter::FlushEventQueue() {
+  while (!request_in_flight_ && !requests_.empty()) {
+    auto request = std::move(requests_.front());
+    requests_.pop();
+    // The root-view has gone away. Ignore this event, and try to process the
+    // next event.
+    if (!request.root_view) {
+      continue;
+    }
+    FindTargetAndDispatch(request.root_view.get(), *request.event,
+                          request.latency);
+  }
+}
+
+void RenderWidgetTargeter::FoundFrameSinkId(
+    base::WeakPtr<RenderWidgetHostViewBase> root_view,
+    base::WeakPtr<RenderWidgetHostViewBase> target,
+    const blink::WebInputEvent& event,
+    const ui::LatencyInfo& latency,
+    const base::Optional<gfx::PointF>& target_location,
+    const viz::FrameSinkId& frame_sink_id) {
+  request_in_flight_ = false;
+  auto* frame_proxy_host = RenderFrameProxyHost::FromID(
+      frame_sink_id.client_id(), frame_sink_id.sink_id());
+  if (!frame_proxy_host || !root_view || !target) {
+    auto* frame_host = RenderFrameHostImpl::FromID(frame_sink_id.client_id(),
+                                                   frame_sink_id.sink_id());
+    if (frame_host) {
+      FoundTarget(root_view.get(), target.get(), event, latency,
+                  target_location);
+    }
+    FlushEventQueue();
+    return;
+  }
+
+  auto* view =
+      static_cast<RenderWidgetHostViewBase*>(frame_proxy_host->frame_tree_node()
+                                                 ->render_manager()
+                                                 ->current_frame_host()
+                                                 ->GetView());
+  // If a client was asked to find a target, then it is necessary to keep
+  // asking the clients until a client claims an event for itself.
+  if (view == target.get()) {
+    FoundTarget(root_view.get(), view, event, latency, target_location);
+  } else {
+    QueryClient(root_view.get(), view, event, latency, target_location);
+  }
+}
+
+void RenderWidgetTargeter::FoundTarget(
+    RenderWidgetHostViewBase* root_view,
+    RenderWidgetHostViewBase* target,
+    const blink::WebInputEvent& event,
+    const ui::LatencyInfo& latency,
+    const base::Optional<gfx::PointF>& target_location) {
+  if (!root_view)
+    return;
+  if (!blink::WebInputEvent::IsMouseEventType(event.GetType())) {
+    // TODO(crbug.com/796656): Handle other types of events.
+    NOTREACHED();
+    return;
+  }
+
+  blink::WebMouseEvent mouse_event =
+      static_cast<const blink::WebMouseEvent&>(event);
+  if (target_location.has_value()) {
+    mouse_event.SetPositionInWidget(target_location->x(), target_location->y());
+  } else {
+    mouse_event = Convert(root_view, target, mouse_event);
+  }
+  if (mouse_event.GetType() != blink::WebInputEvent::kUndefined)
+    delegate_->DispatchEventToTarget(root_view, target, mouse_event, latency);
+  FlushEventQueue();
+}
+
+}  // namespace content
diff --git a/content/browser/renderer_host/render_widget_targeter.h b/content/browser/renderer_host/render_widget_targeter.h
new file mode 100644
index 0000000..38364f46
--- /dev/null
+++ b/content/browser/renderer_host/render_widget_targeter.h
@@ -0,0 +1,123 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CONTENT_BROWSER_RENDERER_HOST_RENDER_WIDGET_TARGETER_H_
+#define CONTENT_BROWSER_RENDERER_HOST_RENDER_WIDGET_TARGETER_H_
+
+#include <queue>
+
+#include "base/memory/weak_ptr.h"
+#include "base/optional.h"
+#include "ui/events/blink/web_input_event_traits.h"
+#include "ui/latency/latency_info.h"
+
+namespace blink {
+class WebInputEvent;
+}  // namespace blink
+
+namespace gfx {
+class PointF;
+}
+
+namespace viz {
+class FrameSinkId;
+}
+
+namespace content {
+
+class RenderWidgetHostViewBase;
+
+struct RenderWidgetTargetResult {
+  RenderWidgetTargetResult();
+  RenderWidgetTargetResult(const RenderWidgetTargetResult&);
+  RenderWidgetTargetResult(RenderWidgetHostViewBase* view,
+                           bool should_query_view,
+                           base::Optional<gfx::PointF> location);
+  ~RenderWidgetTargetResult();
+
+  RenderWidgetHostViewBase* view = nullptr;
+  bool should_query_view = false;
+  base::Optional<gfx::PointF> target_location = base::nullopt;
+};
+
+class RenderWidgetTargeter {
+ public:
+  class Delegate {
+   public:
+    virtual ~Delegate() {}
+
+    virtual RenderWidgetTargetResult FindTargetSynchronously(
+        RenderWidgetHostViewBase* root_view,
+        const blink::WebInputEvent& event) = 0;
+
+    virtual void DispatchEventToTarget(RenderWidgetHostViewBase* root_view,
+                                       RenderWidgetHostViewBase* target,
+                                       const blink::WebInputEvent& event,
+                                       const ui::LatencyInfo& latency) = 0;
+  };
+
+  // The delegate must outlive this targeter.
+  explicit RenderWidgetTargeter(Delegate* delegate);
+  ~RenderWidgetTargeter();
+
+  // Finds the appropriate target inside |root_view| for |event|, and dispatches
+  // it through the delegate. |event| is in the coord-space of |root_view|.
+  void FindTargetAndDispatch(RenderWidgetHostViewBase* root_view,
+                             const blink::WebInputEvent& event,
+                             const ui::LatencyInfo& latency);
+
+ private:
+  // Attempts to target and dispatch all events in the queue. It stops if it has
+  // to query a client, or if the queue becomes empty.
+  void FlushEventQueue();
+
+  // Queries |target| to find the correct target for |event|.
+  // |event| is in the coordinate space of |root_view|.
+  // |target_location|, if set, is the location in |target|'s coordinate space.
+  void QueryClient(RenderWidgetHostViewBase* root_view,
+                   RenderWidgetHostViewBase* target,
+                   const blink::WebInputEvent& event,
+                   const ui::LatencyInfo& latency,
+                   const base::Optional<gfx::PointF>& target_location);
+
+  // |event| is in the coordinate space of |root_view|. |target_location|, if
+  // set, is the location in |target|'s coordinate space.
+  void FoundFrameSinkId(base::WeakPtr<RenderWidgetHostViewBase> root_view,
+                        base::WeakPtr<RenderWidgetHostViewBase> target,
+                        const blink::WebInputEvent& event,
+                        const ui::LatencyInfo& latency,
+                        const base::Optional<gfx::PointF>& target_location,
+                        const viz::FrameSinkId& frame_sink_id);
+
+  // |event| is in the coordinate space of |root_view|. |target_location|, if
+  // set, is the location in |target|'s coordinate space.
+  void FoundTarget(RenderWidgetHostViewBase* root_view,
+                   RenderWidgetHostViewBase* target,
+                   const blink::WebInputEvent& event,
+                   const ui::LatencyInfo& latency,
+                   const base::Optional<gfx::PointF>& target_location);
+
+  struct TargetingRequest {
+    TargetingRequest();
+    TargetingRequest(TargetingRequest&& request);
+    TargetingRequest& operator=(TargetingRequest&& other);
+    ~TargetingRequest();
+
+    base::WeakPtr<RenderWidgetHostViewBase> root_view;
+    ui::WebScopedInputEvent event;
+    ui::LatencyInfo latency;
+  };
+
+  bool request_in_flight_ = false;
+  std::queue<TargetingRequest> requests_;
+
+  Delegate* const delegate_;
+  base::WeakPtrFactory<RenderWidgetTargeter> weak_ptr_factory_;
+
+  DISALLOW_COPY_AND_ASSIGN(RenderWidgetTargeter);
+};
+
+}  // namespace content
+
+#endif  // CONTENT_BROWSER_RENDERER_HOST_RENDER_WIDGET_TARGETER_H_
diff --git a/content/browser/site_per_process_browsertest.cc b/content/browser/site_per_process_browsertest.cc
index 8f648a4..37445b29 100644
--- a/content/browser/site_per_process_browsertest.cc
+++ b/content/browser/site_per_process_browsertest.cc
@@ -291,6 +291,17 @@
       .page_scale_factor;
 }
 
+void RouteMouseEventAndWaitUntilDispatch(
+    RenderWidgetHostInputEventRouter* router,
+    RenderWidgetHostViewBase* root_view,
+    RenderWidgetHostViewBase* expected_target,
+    blink::WebMouseEvent* event) {
+  InputEventAckWaiter waiter(expected_target->GetRenderWidgetHost(),
+                             event->GetType());
+  router->RouteMouseEvent(root_view, event, ui::LatencyInfo());
+  waiter.Wait();
+}
+
 // Helper function that performs a surface hittest.
 void SurfaceHitTestTestHelper(
     Shell* shell,
@@ -372,7 +383,8 @@
 
   main_frame_monitor.ResetEventReceived();
   child_frame_monitor.ResetEventReceived();
-  router->RouteMouseEvent(root_view, &child_event, ui::LatencyInfo());
+  RouteMouseEventAndWaitUntilDispatch(router, root_view, rwhv_child,
+                                      &child_event);
 
   EXPECT_TRUE(child_frame_monitor.EventWasReceived());
   // The expected result coordinates are (5, 5), but can get slightly
@@ -392,7 +404,8 @@
   main_event.SetPositionInWidget(2, 2);
   main_event.click_count = 1;
   // Ladies and gentlemen, THIS is the main_event!
-  router->RouteMouseEvent(root_view, &main_event, ui::LatencyInfo());
+  RouteMouseEventAndWaitUntilDispatch(router, root_view, root_view,
+                                      &main_event);
 
   EXPECT_FALSE(child_frame_monitor.EventWasReceived());
   EXPECT_TRUE(main_frame_monitor.EventWasReceived());
@@ -2269,7 +2282,11 @@
   nested_event.click_count = 1;
   nested_frame_monitor.ResetEventReceived();
   main_frame_monitor.ResetEventReceived();
-  router->RouteMouseEvent(root_view, &nested_event, ui::LatencyInfo());
+  auto* rwhv_child = nested_iframe_node->current_frame_host()
+                         ->GetRenderWidgetHost()
+                         ->GetView();
+  RouteMouseEventAndWaitUntilDispatch(router, root_view, rwhv_child,
+                                      &nested_event);
 
   EXPECT_TRUE(nested_frame_monitor.EventWasReceived());
   EXPECT_NEAR(10, nested_frame_monitor.event().PositionInWidget().x, 2);
@@ -2414,8 +2431,8 @@
   // Next send a MouseMove to B frame, which shouldn't affect C or D but
   // A should receive a MouseMove event.
   mouse_event.SetPositionInWidget(point_in_b_frame.x(), point_in_b_frame.y());
-  web_contents()->GetInputEventRouter()->RouteMouseEvent(rwhv_a, &mouse_event,
-                                                         ui::LatencyInfo());
+  auto* router = web_contents()->GetInputEventRouter();
+  RouteMouseEventAndWaitUntilDispatch(router, rwhv_a, rwhv_b, &mouse_event);
   EXPECT_TRUE(a_frame_monitor.EventWasReceived());
   EXPECT_EQ(a_frame_monitor.event().GetType(),
             blink::WebInputEvent::kMouseMove);
@@ -2428,8 +2445,7 @@
   // Next send a MouseMove to D frame, which should have side effects in every
   // other RenderWidgetHostView.
   mouse_event.SetPositionInWidget(point_in_d_frame.x(), point_in_d_frame.y());
-  web_contents()->GetInputEventRouter()->RouteMouseEvent(rwhv_a, &mouse_event,
-                                                         ui::LatencyInfo());
+  RouteMouseEventAndWaitUntilDispatch(router, rwhv_a, rwhv_d, &mouse_event);
   EXPECT_TRUE(a_frame_monitor.EventWasReceived());
   EXPECT_EQ(a_frame_monitor.event().GetType(),
             blink::WebInputEvent::kMouseMove);
@@ -2496,7 +2512,8 @@
   mouse_event.click_count = 1;
   main_frame_monitor.ResetEventReceived();
   child_frame_monitor.ResetEventReceived();
-  router->RouteMouseEvent(root_view, &mouse_event, ui::LatencyInfo());
+  RouteMouseEventAndWaitUntilDispatch(router, root_view, rwhv_child,
+                                      &mouse_event);
 
   EXPECT_FALSE(main_frame_monitor.EventWasReceived());
   EXPECT_TRUE(child_frame_monitor.EventWasReceived());
@@ -2514,7 +2531,8 @@
   main_frame_monitor.ResetEventReceived();
   child_frame_monitor.ResetEventReceived();
   mouse_event.SetPositionInWidget(1, 5);
-  router->RouteMouseEvent(root_view, &mouse_event, ui::LatencyInfo());
+  RouteMouseEventAndWaitUntilDispatch(router, root_view, rwhv_child,
+                                      &mouse_event);
 
   EXPECT_FALSE(main_frame_monitor.EventWasReceived());
   EXPECT_TRUE(child_frame_monitor.EventWasReceived());
@@ -2525,7 +2543,8 @@
   mouse_event.SetPositionInWidget(child_frame_target_x, child_frame_target_y);
   main_frame_monitor.ResetEventReceived();
   child_frame_monitor.ResetEventReceived();
-  router->RouteMouseEvent(root_view, &mouse_event, ui::LatencyInfo());
+  RouteMouseEventAndWaitUntilDispatch(router, root_view, rwhv_child,
+                                      &mouse_event);
 
   EXPECT_FALSE(main_frame_monitor.EventWasReceived());
   EXPECT_TRUE(child_frame_monitor.EventWasReceived());
@@ -6271,7 +6290,8 @@
   int last_set_cursor_routing_id() const { return last_set_cursor_routing_id_; }
 
   void Wait() {
-    last_set_cursor_routing_id_ = MSG_ROUTING_NONE;
+    // Do not reset the cursor, as the cursor may already have been set (and
+    // Quit() already called on |message_loop_runner_|).
     message_loop_runner_->Run();
   }
 
@@ -6333,8 +6353,9 @@
                                    blink::WebInputEvent::kNoModifiers,
                                    blink::WebInputEvent::kTimeStampForTesting);
   mouse_event.SetPositionInWidget(60, 60);
-  web_contents()->GetInputEventRouter()->RouteMouseEvent(
-      root_view, &mouse_event, ui::LatencyInfo());
+  auto* router = web_contents()->GetInputEventRouter();
+  RouteMouseEventAndWaitUntilDispatch(router, root_view, child_view,
+                                      &mouse_event);
 
   // CursorMessageFilter::Wait() implicitly tests whether we receive a
   // ViewHostMsg_SetCursor message from the renderer process, because it does
@@ -6351,7 +6372,9 @@
     loop.Run();
   }
 
-  EXPECT_FALSE(
+  // The |root_view| ends up getting a mouse-leave event, causing it to send an
+  // updated cursor for the view.
+  EXPECT_TRUE(
       root_view->GetCursorManager()->GetCursorForTesting(root_view, cursor));
   EXPECT_TRUE(
       root_view->GetCursorManager()->GetCursorForTesting(child_view, cursor));
diff --git a/content/browser/web_contents/web_contents_impl.cc b/content/browser/web_contents/web_contents_impl.cc
index 5c7d67f5..c61d4ff 100644
--- a/content/browser/web_contents/web_contents_impl.cc
+++ b/content/browser/web_contents/web_contents_impl.cc
@@ -1475,10 +1475,6 @@
   last_active_time_ = last_active_time;
 }
 
-base::TimeTicks WebContentsImpl::GetLastHiddenTime() const {
-  return last_hidden_time_;
-}
-
 void WebContentsImpl::WasShown() {
   controller_.SetActive(true);
 
@@ -1521,8 +1517,6 @@
     SendPageMessage(new PageMsg_WasHidden(MSG_ROUTING_NONE));
   }
 
-  last_hidden_time_ = base::TimeTicks::Now();
-
   for (auto& observer : observers_)
     observer.WasHidden();
 
diff --git a/content/browser/web_contents/web_contents_impl.h b/content/browser/web_contents/web_contents_impl.h
index c17ad4b..60b40ef 100644
--- a/content/browser/web_contents/web_contents_impl.h
+++ b/content/browser/web_contents/web_contents_impl.h
@@ -356,7 +356,6 @@
   void OnAudioStateChanged(bool is_audible) override;
   base::TimeTicks GetLastActiveTime() const override;
   void SetLastActiveTime(base::TimeTicks last_active_time) override;
-  base::TimeTicks GetLastHiddenTime() const override;
   void WasShown() override;
   void WasHidden() override;
   bool IsVisible() const override;
@@ -1496,10 +1495,6 @@
   // the WebContents creation time.
   base::TimeTicks last_active_time_;
 
-  // The time that this WebContents was last made hidden. The initial value is
-  // zero.
-  base::TimeTicks last_hidden_time_;
-
   // See description above setter.
   bool closed_by_user_gesture_;
 
diff --git a/content/browser/web_contents/web_contents_view_android.cc b/content/browser/web_contents/web_contents_view_android.cc
index 6f9bd8c4..bb6d1f6 100644
--- a/content/browser/web_contents/web_contents_view_android.cc
+++ b/content/browser/web_contents/web_contents_view_android.cc
@@ -340,14 +340,14 @@
     RenderWidgetHostImpl* source_rwh) {
   if (drop_data.text.is_null()) {
     // Need to clear drag and drop state in blink.
-    OnDragEnded();
+    OnSystemDragEnded();
     return;
   }
 
   gfx::NativeView native_view = GetNativeView();
   if (!native_view) {
     // Need to clear drag and drop state in blink.
-    OnDragEnded();
+    OnSystemDragEnded();
     return;
   }
 
@@ -370,7 +370,7 @@
 
   if (!native_view->StartDragAndDrop(jtext, gfx::ConvertToJavaBitmap(bitmap))) {
     // Need to clear drag and drop state in blink.
-    OnDragEnded();
+    OnSystemDragEnded();
     return;
   }
 
@@ -446,6 +446,9 @@
 
 void WebContentsViewAndroid::OnDragUpdated(const gfx::PointF& location,
                                            const gfx::PointF& screen_location) {
+  drag_location_ = location;
+  drag_screen_location_ = screen_location;
+
   blink::WebDragOperationsMask allowed_ops =
       static_cast<blink::WebDragOperationsMask>(blink::kWebDragOperationCopy |
                                                 blink::kWebDragOperationMove);
@@ -466,10 +469,19 @@
       *drop_data, location, screen_location, 0);
 }
 
-void WebContentsViewAndroid::OnDragEnded() {
+void WebContentsViewAndroid::OnSystemDragEnded() {
   web_contents_->GetRenderViewHost()->GetWidget()->DragSourceSystemDragEnded();
 }
 
+void WebContentsViewAndroid::OnDragEnded() {
+  web_contents_->GetRenderViewHost()->GetWidget()->DragSourceEndedAt(
+      drag_location_, drag_screen_location_, blink::kWebDragOperationNone);
+  OnSystemDragEnded();
+
+  drag_location_ = gfx::PointF();
+  drag_screen_location_ = gfx::PointF();
+}
+
 void WebContentsViewAndroid::GotFocus(
     RenderWidgetHostImpl* render_widget_host) {
   web_contents_->NotifyWebContentsFocused(render_widget_host);
diff --git a/content/browser/web_contents/web_contents_view_android.h b/content/browser/web_contents/web_contents_view_android.h
index 1cc56ecb..047d454e 100644
--- a/content/browser/web_contents/web_contents_view_android.h
+++ b/content/browser/web_contents/web_contents_view_android.h
@@ -128,6 +128,7 @@
                      const gfx::PointF& location,
                      const gfx::PointF& screen_location);
   void OnDragEnded();
+  void OnSystemDragEnded();
 
   // The WebContents whose contents we display.
   WebContentsImpl* web_contents_;
@@ -147,6 +148,9 @@
   // Interface used to get notified of events from the synchronous compositor.
   SynchronousCompositorClient* synchronous_compositor_client_;
 
+  gfx::PointF drag_location_;
+  gfx::PointF drag_screen_location_;
+
   DISALLOW_COPY_AND_ASSIGN(WebContentsViewAndroid);
 };
 
diff --git a/content/common/resource_messages.h b/content/common/resource_messages.h
index 6a42a43..f4e8b4b 100644
--- a/content/common/resource_messages.h
+++ b/content/common/resource_messages.h
@@ -7,6 +7,7 @@
 
 // IPC messages for resource loading.
 //
+// WE ARE DEPRECATING THIS FILE. DO NOT ADD A NEW MESSAGE.
 // NOTE: All messages must send an |int request_id| as their first parameter.
 
 #include <stdint.h>
@@ -259,109 +260,4 @@
   IPC_STRUCT_TRAITS_MEMBER(ssl_info)
 IPC_STRUCT_TRAITS_END()
 
-// Resource messages sent from the browser to the renderer.
-
-// Sent when the headers are available for a resource request.
-IPC_MESSAGE_CONTROL2(ResourceMsg_ReceivedResponse,
-                     int /* request_id */,
-                     content::ResourceResponseHead)
-
-// Sent when cached metadata from a resource request is ready.
-IPC_MESSAGE_CONTROL2(ResourceMsg_ReceivedCachedMetadata,
-                     int /* request_id */,
-                     std::vector<uint8_t> /* data */)
-
-// Sent as upload progress is being made.
-IPC_MESSAGE_CONTROL3(ResourceMsg_UploadProgress,
-                     int /* request_id */,
-                     int64_t /* position */,
-                     int64_t /* size */)
-
-// Sent when the request has been redirected.  The receiver is expected to
-// respond with either a FollowRedirect message (if the redirect is to be
-// followed) or a CancelRequest message (if it should not be followed).
-IPC_MESSAGE_CONTROL3(ResourceMsg_ReceivedRedirect,
-                     int /* request_id */,
-                     net::RedirectInfo /* redirect_info */,
-                     content::ResourceResponseHead)
-
-// Sent to set the shared memory buffer to be used to transmit response data to
-// the renderer.  Subsequent DataReceived messages refer to byte ranges in the
-// shared memory buffer.  The shared memory buffer should be retained by the
-// renderer until the resource request completes.
-//
-// NOTE: The shared memory handle should already be mapped into the process
-// that receives this message.
-IPC_MESSAGE_CONTROL3(ResourceMsg_SetDataBuffer,
-                     int /* request_id */,
-                     base::SharedMemoryHandle /* shm_handle */,
-                     int /* shm_size */)
-
-// Sent when some data from a resource request is ready.  The data offset and
-// length specify a byte range into the shared memory buffer provided by the
-// SetDataBuffer message.
-IPC_MESSAGE_CONTROL4(ResourceMsg_DataReceived,
-                     int /* request_id */,
-                     int /* data_offset */,
-                     int /* data_length */,
-                     int /* encoded_data_length */)
-
-// Sent when some data from a resource request has been downloaded to
-// file. This is only called in the 'download_to_file' case and replaces
-// ResourceMsg_DataReceived in the call sequence in that case.
-IPC_MESSAGE_CONTROL3(ResourceMsg_DataDownloaded,
-                     int /* request_id */,
-                     int /* data_len */,
-                     int /* encoded_data_length */)
-
-// Sent when the request has been completed.
-IPC_MESSAGE_CONTROL2(ResourceMsg_RequestComplete,
-                     int /* request_id */,
-                     network::URLLoaderCompletionStatus)
-
-// Resource messages sent from the renderer to the browser.
-
-// Makes a resource request via the browser.
-IPC_MESSAGE_CONTROL4(
-    ResourceHostMsg_RequestResource,
-    int /* routing_id */,
-    int /* request_id */,
-    content::ResourceRequest,
-    net::MutableNetworkTrafficAnnotationTag /* network_traffic_annotation */)
-
-// Cancels a resource request with the ID given as the parameter.
-IPC_MESSAGE_CONTROL1(ResourceHostMsg_CancelRequest,
-                     int /* request_id */)
-
-// Follows a redirect that occured for the resource request with the ID given
-// as the parameter.
-IPC_MESSAGE_CONTROL1(ResourceHostMsg_FollowRedirect,
-                     int /* request_id */)
-
-// Makes a synchronous resource request via the browser.
-IPC_SYNC_MESSAGE_ROUTED2_1(ResourceHostMsg_SyncLoad,
-                           int /* request_id */,
-                           content::ResourceRequest,
-                           content::SyncLoadResult)
-
-// Sent when the renderer process is done processing a DataReceived
-// message.
-IPC_MESSAGE_CONTROL1(ResourceHostMsg_DataReceived_ACK,
-                     int /* request_id */)
-
-// Sent by the renderer process to acknowledge receipt of a
-// UploadProgress message.
-IPC_MESSAGE_CONTROL1(ResourceHostMsg_UploadProgress_ACK,
-                     int /* request_id */)
-
-// Sent when the renderer process deletes a resource loader.
-IPC_MESSAGE_CONTROL1(ResourceHostMsg_ReleaseDownloadedFile,
-                     int /* request_id */)
-
-// Sent by the renderer when a resource request changes priority.
-IPC_MESSAGE_CONTROL3(ResourceHostMsg_DidChangePriority,
-                     int /* request_id */,
-                     net::RequestPriority,
-                     int /* intra_priority_value */)
-
 #endif  // CONTENT_COMMON_RESOURCE_MESSAGES_H_
diff --git a/content/public/browser/web_contents.h b/content/public/browser/web_contents.h
index 3003cc14..3a9fa49 100644
--- a/content/public/browser/web_contents.h
+++ b/content/public/browser/web_contents.h
@@ -424,9 +424,6 @@
   virtual base::TimeTicks GetLastActiveTime() const = 0;
   virtual void SetLastActiveTime(base::TimeTicks last_active_time) = 0;
 
-  // Get the last time that the WebContents was made hidden.
-  virtual base::TimeTicks GetLastHiddenTime() const = 0;
-
   // Invoked when the WebContents becomes shown/hidden. A hidden WebContents
   // isn't painted on the screen.
   virtual void WasShown() = 0;
diff --git a/content/public/test/test_browser_thread_bundle.h b/content/public/test/test_browser_thread_bundle.h
index 62d5245..de319651 100644
--- a/content/public/test/test_browser_thread_bundle.h
+++ b/content/public/test/test_browser_thread_bundle.h
@@ -2,18 +2,18 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-// TestBrowserThreadBundle is a convenience class for creating a set of
-// TestBrowserThreads and a task scheduler in unit tests. For most tests, it is
-// sufficient to just instantiate the TestBrowserThreadBundle as a member
-// variable. It is a good idea to put the TestBrowserThreadBundle as the first
-// member variable in test classes, so it is destroyed last, and the test
-// threads always exist from the perspective of other classes.
+// TestBrowserThreadBundle is a convenience class which allows usage of these
+// APIs within its scope:
+// - Same APIs as base::test::ScopedTaskEnvironment.
+// - content::BrowserThread.
 //
-// By default, all of the created TestBrowserThreads will be backed by a single
-// shared MessageLoop. If a test truly needs separate threads, it can do so by
-// passing the appropriate combination of option values during the
-// TestBrowserThreadBundle construction. TaskScheduler tasks always run on
-// dedicated threads.
+// Only tests that need the BrowserThread API should instantiate a
+// TestBrowserThreadBundle. Use base::test::ScopedTaskEnvironment otherwise.
+//
+// By default, BrowserThread::UI/IO are backed by a single shared MessageLoop on
+// the main thread. If a test truly needs BrowserThread::IO tasks to run on a
+// separate thread, it can pass the REAL_IO_THREAD option to the constructor.
+// TaskScheduler tasks always run on dedicated threads.
 //
 // To synchronously run tasks from the shared MessageLoop:
 //
@@ -36,10 +36,10 @@
 // running tasks from the shared MessageLoop:
 //    base::TaskScheduler::GetInstance()->FlushForTesting();
 //
-// The destructor of TestBrowserThreadBundle runs remaining TestBrowserThreads
-// tasks and remaining task scheduler tasks.
+// The destructor of TestBrowserThreadBundle runs remaining UI/IO tasks and
+// remaining task scheduler tasks.
 //
-// If a test needs a MessageLoopForIO on the main thread, it should use the
+// If a test needs to pump IO messages on the main thread, it should use the
 // IO_MAINLOOP option. Most of the time, IO_MAINLOOP avoids needing to use a
 // REAL_IO_THREAD.
 //
diff --git a/content/renderer/BUILD.gn b/content/renderer/BUILD.gn
index 40741ec3..a18f955e 100644
--- a/content/renderer/BUILD.gn
+++ b/content/renderer/BUILD.gn
@@ -236,8 +236,6 @@
     "java/gin_java_function_invocation_helper.h",
     "layout_test_dependencies.cc",
     "layout_test_dependencies.h",
-    "loader/child_resource_message_filter.cc",
-    "loader/child_resource_message_filter.h",
     "loader/child_url_loader_factory_getter_impl.cc",
     "loader/child_url_loader_factory_getter_impl.h",
     "loader/cors_url_loader.cc",
@@ -250,12 +248,8 @@
     "loader/request_extra_data.h",
     "loader/resource_dispatcher.cc",
     "loader/resource_dispatcher.h",
-    "loader/resource_scheduling_filter.cc",
-    "loader/resource_scheduling_filter.h",
     "loader/shared_memory_data_consumer_handle.cc",
     "loader/shared_memory_data_consumer_handle.h",
-    "loader/shared_memory_received_data_factory.cc",
-    "loader/shared_memory_received_data_factory.h",
     "loader/site_isolation_stats_gatherer.cc",
     "loader/site_isolation_stats_gatherer.h",
     "loader/sync_load_context.cc",
@@ -419,8 +413,6 @@
     "sad_plugin.h",
     "savable_resources.cc",
     "savable_resources.h",
-    "scheduler/resource_dispatch_throttler.cc",
-    "scheduler/resource_dispatch_throttler.h",
     "screen_orientation/screen_orientation_dispatcher.cc",
     "screen_orientation/screen_orientation_dispatcher.h",
     "seccomp_sandbox_status_android.cc",
@@ -457,8 +449,12 @@
     "service_worker/service_worker_type_converters.h",
     "service_worker/service_worker_type_util.cc",
     "service_worker/service_worker_type_util.h",
+    "service_worker/thread_safe_script_container.cc",
+    "service_worker/thread_safe_script_container.h",
     "service_worker/web_service_worker_impl.cc",
     "service_worker/web_service_worker_impl.h",
+    "service_worker/web_service_worker_installed_scripts_manager_impl.cc",
+    "service_worker/web_service_worker_installed_scripts_manager_impl.h",
     "service_worker/web_service_worker_provider_impl.cc",
     "service_worker/web_service_worker_provider_impl.h",
     "service_worker/web_service_worker_registration_impl.cc",
diff --git a/content/renderer/loader/child_resource_message_filter.cc b/content/renderer/loader/child_resource_message_filter.cc
deleted file mode 100644
index 542dc86f..0000000
--- a/content/renderer/loader/child_resource_message_filter.cc
+++ /dev/null
@@ -1,35 +0,0 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "content/renderer/loader/child_resource_message_filter.h"
-
-#include "base/bind.h"
-#include "base/single_thread_task_runner.h"
-#include "base/threading/thread_task_runner_handle.h"
-#include "content/common/resource_messages.h"
-#include "content/renderer/loader/resource_dispatcher.h"
-
-namespace content {
-
-ChildResourceMessageFilter::ChildResourceMessageFilter(
-    ResourceDispatcher* resource_dispatcher)
-    : main_thread_task_runner_(base::ThreadTaskRunnerHandle::Get()),
-      resource_dispatcher_(resource_dispatcher) {}
-
-ChildResourceMessageFilter::~ChildResourceMessageFilter() {}
-
-bool ChildResourceMessageFilter::OnMessageReceived(
-    const IPC::Message& message) {
-  if (message.type() == ResourceMsg_RequestComplete::ID ||
-      message.type() == ResourceMsg_ReceivedResponse::ID ||
-      message.type() == ResourceMsg_ReceivedRedirect::ID) {
-    main_thread_task_runner_->PostTask(
-        FROM_HERE, base::BindOnce(&ResourceDispatcher::set_io_timestamp,
-                                  base::Unretained(resource_dispatcher_),
-                                  base::TimeTicks::Now()));
-  }
-  return false;
-}
-
-}  // namespace content
diff --git a/content/renderer/loader/child_resource_message_filter.h b/content/renderer/loader/child_resource_message_filter.h
deleted file mode 100644
index a8315fc..0000000
--- a/content/renderer/loader/child_resource_message_filter.h
+++ /dev/null
@@ -1,54 +0,0 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CONTENT_RENDERER_LOADER_CHILD_RESOURCE_MESSAGE_FILTER_H_
-#define CONTENT_RENDERER_LOADER_CHILD_RESOURCE_MESSAGE_FILTER_H_
-
-#include "base/macros.h"
-#include "base/memory/ref_counted.h"
-#include "ipc/message_filter.h"
-
-namespace base {
-class SingleThreadTaskRunner;
-}
-
-namespace content {
-class ResourceDispatcher;
-
-// Supplies ResourceDispatcher with timestamps for some resource messages.
-//
-// Background: ResourceDispatcher converts browser process time to child
-// process time. This is done to achieve coherent timeline. Conversion is
-// a linear transformation such that given browser process time range is
-// mapped to corresponding child process time range. Timestamps for child
-// process time range should be taken by IO thread when resource messages
-// arrive. Otherwise, timestamps may be affected by long rendering / JS task.
-//
-// When specific message is processed by this filter, new task charged
-// with timestamp is posted to main thread. This task is processed just before
-// resource message and invokes ResourceDispatcher::set_io_timestamp.
-class ChildResourceMessageFilter : public IPC::MessageFilter {
- public:
-  explicit ChildResourceMessageFilter(ResourceDispatcher* resource_dispatcher);
-
-  // IPC::MessageFilter implementation.
-  bool OnMessageReceived(const IPC::Message& message) override;
-
-  void SetMainThreadTaskRunner(
-      scoped_refptr<base::SingleThreadTaskRunner> main_thread_task_runner) {
-    main_thread_task_runner_ = main_thread_task_runner;
-  }
-
- private:
-  ~ChildResourceMessageFilter() override;
-
-  scoped_refptr<base::SingleThreadTaskRunner> main_thread_task_runner_;
-  ResourceDispatcher* resource_dispatcher_;
-
-  DISALLOW_COPY_AND_ASSIGN(ChildResourceMessageFilter);
-};
-
-}  // namespace content
-
-#endif  // CONTENT_RENDERER_LOADER_CHILD_RESOURCE_MESSAGE_FILTER_H_
diff --git a/content/renderer/loader/request_extra_data.cc b/content/renderer/loader/request_extra_data.cc
index 6d0bbf1..a18495c 100644
--- a/content/renderer/loader/request_extra_data.cc
+++ b/content/renderer/loader/request_extra_data.cc
@@ -7,7 +7,6 @@
 #include "content/common/service_worker/service_worker_types.h"
 #include "content/public/common/resource_request.h"
 #include "content/public/common/service_worker_modes.h"
-#include "ipc/ipc_message.h"
 #include "third_party/WebKit/common/page/page_visibility_state.mojom.h"
 
 using blink::WebString;
diff --git a/content/renderer/loader/resource_dispatcher.cc b/content/renderer/loader/resource_dispatcher.cc
index a9a9e7e..3b7afd6 100644
--- a/content/renderer/loader/resource_dispatcher.cc
+++ b/content/renderer/loader/resource_dispatcher.cc
@@ -15,7 +15,6 @@
 #include "base/debug/stack_trace.h"
 #include "base/files/file_path.h"
 #include "base/memory/ptr_util.h"
-#include "base/memory/shared_memory.h"
 #include "base/message_loop/message_loop.h"
 #include "base/metrics/histogram_macros.h"
 #include "base/strings/string_util.h"
@@ -24,7 +23,6 @@
 #include "build/build_config.h"
 #include "content/common/inter_process_time_ticks_converter.h"
 #include "content/common/navigation_params.h"
-#include "content/common/resource_messages.h"
 #include "content/common/throttling_url_loader.h"
 #include "content/public/common/content_features.h"
 #include "content/public/common/resource_request.h"
@@ -34,8 +32,6 @@
 #include "content/public/renderer/request_peer.h"
 #include "content/public/renderer/resource_dispatcher_delegate.h"
 #include "content/renderer/loader/request_extra_data.h"
-#include "content/renderer/loader/resource_scheduling_filter.h"
-#include "content/renderer/loader/shared_memory_received_data_factory.h"
 #include "content/renderer/loader/site_isolation_stats_gatherer.h"
 #include "content/renderer/loader/sync_load_context.h"
 #include "content/renderer/loader/sync_load_response.h"
@@ -59,14 +55,6 @@
   *time = converter.ToLocalTimeTicks(remote_time).ToTimeTicks();
 }
 
-void CrashOnMapFailure() {
-#if defined(OS_WIN)
-  DWORD last_err = GetLastError();
-  base::debug::Alias(&last_err);
-#endif
-  CHECK(false);
-}
-
 void CheckSchemeForReferrerPolicy(const ResourceRequest& request) {
   if ((request.referrer_policy == Referrer::GetDefaultReferrerPolicy() ||
        request.referrer_policy ==
@@ -122,53 +110,14 @@
 }
 
 ResourceDispatcher::ResourceDispatcher(
-    IPC::Sender* sender,
     scoped_refptr<base::SingleThreadTaskRunner> thread_task_runner)
-    : message_sender_(sender),
-      delegate_(nullptr),
-      io_timestamp_(base::TimeTicks()),
+    : delegate_(nullptr),
       thread_task_runner_(thread_task_runner),
       weak_factory_(this) {}
 
 ResourceDispatcher::~ResourceDispatcher() {
 }
 
-bool ResourceDispatcher::OnMessageReceived(const IPC::Message& message) {
-  if (!IsResourceDispatcherMessage(message)) {
-    return false;
-  }
-
-  int request_id;
-
-  base::PickleIterator iter(message);
-  if (!iter.ReadInt(&request_id)) {
-    NOTREACHED() << "malformed resource message";
-    return true;
-  }
-
-  PendingRequestInfo* request_info = GetPendingRequestInfo(request_id);
-  if (!request_info) {
-    // Release resources in the message if it is a data message.
-    ReleaseResourcesInDataMessage(message);
-    return true;
-  }
-
-  if (request_info->is_deferred) {
-    request_info->deferred_message_queue.push_back(new IPC::Message(message));
-    return true;
-  }
-
-  // Make sure any deferred messages are dispatched before we dispatch more.
-  if (!request_info->deferred_message_queue.empty()) {
-    request_info->deferred_message_queue.push_back(new IPC::Message(message));
-    FlushDeferredMessages(request_id);
-    return true;
-  }
-
-  DispatchMessage(message);
-  return true;
-}
-
 ResourceDispatcher::PendingRequestInfo*
 ResourceDispatcher::GetPendingRequestInfo(int request_id) {
   PendingRequestMap::iterator it = pending_requests_.find(request_id);
@@ -187,13 +136,6 @@
     return;
 
   request_info->peer->OnUploadProgress(position, size);
-
-  // URLLoaderClientImpl has its own acknowledgement, and doesn't need the IPC
-  // message here.
-  if (!request_info->url_loader) {
-    // Acknowledge receipt
-    message_sender_->Send(new ResourceHostMsg_UploadProgress_ACK(request_id));
-  }
 }
 
 void ResourceDispatcher::OnReceivedResponse(
@@ -202,7 +144,7 @@
   PendingRequestInfo* request_info = GetPendingRequestInfo(request_id);
   if (!request_info)
     return;
-  request_info->response_start = ConsumeIOTimestamp();
+  request_info->response_start = base::TimeTicks::Now();
 
   if (delegate_) {
     std::unique_ptr<RequestPeer> new_peer = delegate_->OnReceivedResponse(
@@ -242,80 +184,6 @@
   }
 }
 
-void ResourceDispatcher::OnSetDataBuffer(int request_id,
-                                         base::SharedMemoryHandle shm_handle,
-                                         int shm_size) {
-  TRACE_EVENT0("loader", "ResourceDispatcher::OnSetDataBuffer");
-  PendingRequestInfo* request_info = GetPendingRequestInfo(request_id);
-  if (!request_info)
-    return;
-
-  bool shm_valid = base::SharedMemory::IsHandleValid(shm_handle);
-  CHECK((shm_valid && shm_size > 0) || (!shm_valid && !shm_size));
-
-  request_info->buffer.reset(
-      new base::SharedMemory(shm_handle, true));  // read only
-  request_info->received_data_factory =
-      base::MakeRefCounted<SharedMemoryReceivedDataFactory>(
-          message_sender_, request_id, request_info->buffer);
-
-  bool ok = request_info->buffer->Map(shm_size);
-  if (!ok) {
-    base::SharedMemoryHandle shm_handle_copy = shm_handle;
-    base::debug::Alias(&shm_handle_copy);
-
-    CrashOnMapFailure();
-    return;
-  }
-
-  // TODO(erikchen): Temporary debugging. http://crbug.com/527588.
-  CHECK_GE(shm_size, 0);
-  CHECK_LE(shm_size, 512 * 1024);
-  request_info->buffer_size = shm_size;
-}
-
-void ResourceDispatcher::OnReceivedData(int request_id,
-                                        int data_offset,
-                                        int data_length,
-                                        int encoded_data_length) {
-  TRACE_EVENT0("loader", "ResourceDispatcher::OnReceivedData");
-  DCHECK_GT(data_length, 0);
-  PendingRequestInfo* request_info = GetPendingRequestInfo(request_id);
-  bool send_ack = true;
-  if (request_info && data_length > 0) {
-    CHECK(base::SharedMemory::IsHandleValid(request_info->buffer->handle()));
-    CHECK_GE(request_info->buffer_size, data_offset + data_length);
-
-    const char* data_start = static_cast<char*>(request_info->buffer->memory());
-    CHECK(data_start);
-    CHECK(data_start + data_offset);
-    const char* data_ptr = data_start + data_offset;
-
-    // Check whether this response data is compliant with our cross-site
-    // document blocking policy. We only do this for the first chunk of data.
-    if (request_info->site_isolation_metadata.get()) {
-      SiteIsolationStatsGatherer::OnReceivedFirstChunk(
-          request_info->site_isolation_metadata, data_ptr, data_length);
-      request_info->site_isolation_metadata.reset();
-    }
-
-    std::unique_ptr<RequestPeer::ReceivedData> data =
-        request_info->received_data_factory->Create(data_offset, data_length);
-    // |data| takes care of ACKing.
-    send_ack = false;
-    request_info->peer->OnReceivedData(std::move(data));
-  }
-
-  // Get the request info again as the client callback may modify the info.
-  request_info = GetPendingRequestInfo(request_id);
-  if (request_info && encoded_data_length > 0)
-    request_info->peer->OnTransferSizeUpdated(encoded_data_length);
-
-  // Acknowledge the reception of this data.
-  if (send_ack)
-    message_sender_->Send(new ResourceHostMsg_DataReceived_ACK(request_id));
-}
-
 void ResourceDispatcher::OnDownloadedData(int request_id,
                                           int data_len,
                                           int encoded_data_length) {
@@ -334,7 +202,7 @@
   PendingRequestInfo* request_info = GetPendingRequestInfo(request_id);
   if (!request_info)
     return;
-  request_info->response_start = ConsumeIOTimestamp();
+  request_info->response_start = base::TimeTicks::Now();
 
   ResourceResponseInfo renderer_response_info;
   ToResourceResponseInfo(*request_info, response_head, &renderer_response_info);
@@ -350,8 +218,7 @@
     request_info->response_url = redirect_info.new_url;
     request_info->response_method = redirect_info.new_method;
     request_info->response_referrer = GURL(redirect_info.new_referrer);
-    request_info->pending_redirect_message.reset(
-        new ResourceHostMsg_FollowRedirect(request_id));
+    request_info->has_pending_redirect = true;
     if (!request_info->is_deferred) {
       FollowPendingRedirect(request_info);
     }
@@ -362,14 +229,9 @@
 
 void ResourceDispatcher::FollowPendingRedirect(
     PendingRequestInfo* request_info) {
-  IPC::Message* msg = request_info->pending_redirect_message.release();
-  if (msg) {
-    if (request_info->url_loader) {
-      request_info->url_loader->FollowRedirect();
-      delete msg;
-    } else {
-      message_sender_->Send(msg);
-    }
+  if (request_info->has_pending_redirect) {
+    request_info->has_pending_redirect = false;
+    request_info->url_loader->FollowRedirect();
   }
 }
 
@@ -381,11 +243,8 @@
   PendingRequestInfo* request_info = GetPendingRequestInfo(request_id);
   if (!request_info)
     return;
-  request_info->completion_time = ConsumeIOTimestamp();
+  request_info->completion_time = base::TimeTicks::Now();
   request_info->buffer.reset();
-  if (request_info->received_data_factory)
-    request_info->received_data_factory->Stop();
-  request_info->received_data_factory = nullptr;
   request_info->buffer_size = 0;
 
   RequestPeer* peer = request_info->peer.get();
@@ -415,15 +274,6 @@
   if (it == pending_requests_.end())
     return false;
 
-  PendingRequestInfo* request_info = it->second.get();
-
-  // |url_loader_client| releases the downloaded file. Otherwise (i.e., we
-  // are using Chrome IPC), we should release it here.
-  bool release_downloaded_file =
-      request_info->download_to_file && !it->second->url_loader_client;
-
-  ReleaseResourcesInMessageQueue(&request_info->deferred_message_queue);
-
   // Cancel loading.
   it->second->url_loader = nullptr;
   // Clear URLLoaderClient to stop receiving further Mojo IPC from the browser
@@ -436,14 +286,6 @@
   thread_task_runner_->DeleteSoon(FROM_HERE, it->second.release());
   pending_requests_.erase(it);
 
-  if (release_downloaded_file) {
-    message_sender_->Send(
-        new ResourceHostMsg_ReleaseDownloadedFile(request_id));
-  }
-
-  if (resource_scheduling_filter_.get())
-    resource_scheduling_filter_->ClearRequestIdTaskRunner(request_id);
-
   return true;
 }
 
@@ -456,9 +298,6 @@
 
   // Cancel the request if it didn't complete, and clean it up so the bridge
   // will receive no more messages.
-  const PendingRequestInfo& info = *it->second;
-  if (info.completion_time.is_null() && !info.url_loader)
-    message_sender_->Send(new ResourceHostMsg_CancelRequest(request_id));
   RemovePendingRequest(request_id);
 }
 
@@ -470,19 +309,12 @@
   }
   if (value) {
     request_info->is_deferred = value;
-    if (request_info->url_loader_client)
-      request_info->url_loader_client->SetDefersLoading();
+    request_info->url_loader_client->SetDefersLoading();
   } else if (request_info->is_deferred) {
     request_info->is_deferred = false;
-
-    if (request_info->url_loader_client)
-      request_info->url_loader_client->UnsetDefersLoading();
+    request_info->url_loader_client->UnsetDefersLoading();
 
     FollowPendingRedirect(request_info);
-
-    thread_task_runner_->PostTask(
-        FROM_HERE, base::BindOnce(&ResourceDispatcher::FlushDeferredMessages,
-                                  weak_factory_.GetWeakPtr(), request_id));
   }
 }
 
@@ -491,12 +323,7 @@
                                            int intra_priority_value) {
   PendingRequestInfo* request_info = GetPendingRequestInfo(request_id);
   DCHECK(request_info);
-  if (request_info->url_loader) {
-    request_info->url_loader->SetPriority(new_priority, intra_priority_value);
-  } else {
-    message_sender_->Send(new ResourceHostMsg_DidChangePriority(
-        request_id, new_priority, intra_priority_value));
-  }
+  request_info->url_loader->SetPriority(new_priority, intra_priority_value);
 }
 
 void ResourceDispatcher::OnTransferSizeUpdated(int request_id,
@@ -534,71 +361,16 @@
 ResourceDispatcher::PendingRequestInfo::~PendingRequestInfo() {
 }
 
-void ResourceDispatcher::DispatchMessage(const IPC::Message& message) {
-  IPC_BEGIN_MESSAGE_MAP(ResourceDispatcher, message)
-    IPC_MESSAGE_HANDLER(ResourceMsg_UploadProgress, OnUploadProgress)
-    IPC_MESSAGE_HANDLER(ResourceMsg_ReceivedResponse, OnReceivedResponse)
-    IPC_MESSAGE_HANDLER(ResourceMsg_ReceivedCachedMetadata,
-                        OnReceivedCachedMetadata)
-    IPC_MESSAGE_HANDLER(ResourceMsg_ReceivedRedirect, OnReceivedRedirect)
-    IPC_MESSAGE_HANDLER(ResourceMsg_SetDataBuffer, OnSetDataBuffer)
-    IPC_MESSAGE_HANDLER(ResourceMsg_DataReceived, OnReceivedData)
-    IPC_MESSAGE_HANDLER(ResourceMsg_DataDownloaded, OnDownloadedData)
-    IPC_MESSAGE_HANDLER(ResourceMsg_RequestComplete, OnRequestComplete)
-  IPC_END_MESSAGE_MAP()
-}
-
-void ResourceDispatcher::FlushDeferredMessages(int request_id) {
-  PendingRequestInfo* request_info = GetPendingRequestInfo(request_id);
-  if (!request_info || request_info->is_deferred)
-    return;
-
-  if (request_info->url_loader) {
-    DCHECK(request_info->deferred_message_queue.empty());
-    request_info->url_loader_client->FlushDeferredMessages();
-    return;
-  }
-
-  // Because message handlers could result in request_info being destroyed,
-  // we need to work with a stack reference to the deferred queue.
-  MessageQueue q;
-  q.swap(request_info->deferred_message_queue);
-  while (!q.empty()) {
-    IPC::Message* m = q.front();
-    q.pop_front();
-    DispatchMessage(*m);
-    delete m;
-    // We need to find the request again in the list as it may have completed
-    // by now and the request_info instance above may be invalid.
-    request_info = GetPendingRequestInfo(request_id);
-    if (!request_info) {
-      // The recipient is gone, the messages won't be handled and
-      // resources they might hold won't be released. Explicitly release
-      // them from here so that they won't leak.
-      ReleaseResourcesInMessageQueue(&q);
-      return;
-    }
-    // If this request is deferred in the context of the above message, then
-    // we should honor the same and stop dispatching further messages.
-    if (request_info->is_deferred) {
-      request_info->deferred_message_queue.swap(q);
-      return;
-    }
-  }
-}
-
 void ResourceDispatcher::StartSync(
     std::unique_ptr<ResourceRequest> request,
     int routing_id,
     const url::Origin& frame_origin,
     const net::NetworkTrafficAnnotationTag& traffic_annotation,
     SyncLoadResponse* response,
-    blink::WebURLRequest::LoadingIPCType ipc_type,
     mojom::URLLoaderFactory* url_loader_factory,
     std::vector<std::unique_ptr<URLLoaderThrottle>> throttles) {
   CheckSchemeForReferrerPolicy(*request);
 
-  if (ipc_type == blink::WebURLRequest::LoadingIPCType::kMojo) {
     mojom::URLLoaderFactoryPtrInfo url_loader_factory_copy;
     url_loader_factory->Clone(mojo::MakeRequest(&url_loader_factory_copy));
     base::WaitableEvent event(base::WaitableEvent::ResetPolicy::MANUAL,
@@ -621,32 +393,6 @@
                        base::Unretained(&event)));
 
     event.Wait();
-  } else {
-    SyncLoadResult result;
-    IPC::SyncMessage* msg = new ResourceHostMsg_SyncLoad(
-        routing_id, MakeRequestID(), *request, &result);
-
-    // NOTE: This may pump events (see RenderThread::Send).
-    if (!message_sender_->Send(msg)) {
-      response->error_code = net::ERR_FAILED;
-      return;
-    }
-
-    response->error_code = result.error_code;
-    response->url = result.final_url;
-    response->headers = result.headers;
-    response->mime_type = result.mime_type;
-    response->charset = result.charset;
-    response->request_time = result.request_time;
-    response->response_time = result.response_time;
-    response->load_timing = result.load_timing;
-    response->devtools_info = result.devtools_info;
-    response->data.swap(result.data);
-    response->download_file_path = result.download_file_path;
-    response->socket_address = result.socket_address;
-    response->encoded_data_length = result.encoded_data_length;
-    response->encoded_body_length = result.encoded_body_length;
-  }
 }
 
 int ResourceDispatcher::StartAsync(
@@ -657,7 +403,6 @@
     const net::NetworkTrafficAnnotationTag& traffic_annotation,
     bool is_sync,
     std::unique_ptr<RequestPeer> peer,
-    blink::WebURLRequest::LoadingIPCType ipc_type,
     mojom::URLLoaderFactory* url_loader_factory,
     std::vector<std::unique_ptr<URLLoaderThrottle>> throttles,
     mojom::URLLoaderClientEndpointsPtr url_loader_client_endpoints) {
@@ -670,11 +415,6 @@
       frame_origin, request->url, request->method, request->referrer,
       request->download_to_file);
 
-  if (resource_scheduling_filter_.get() && loading_task_runner) {
-    resource_scheduling_filter_->SetRequestIdTaskRunner(request_id,
-                                                        loading_task_runner);
-  }
-
   scoped_refptr<base::SingleThreadTaskRunner> task_runner =
       loading_task_runner ? loading_task_runner : thread_task_runner_;
 
@@ -690,35 +430,27 @@
     return request_id;
   }
 
-  if (ipc_type == blink::WebURLRequest::LoadingIPCType::kMojo) {
-    scoped_refptr<base::SingleThreadTaskRunner> task_runner =
-        loading_task_runner ? loading_task_runner : thread_task_runner_;
-    std::unique_ptr<URLLoaderClientImpl> client(
-        new URLLoaderClientImpl(request_id, this, task_runner));
+  std::unique_ptr<URLLoaderClientImpl> client(
+      new URLLoaderClientImpl(request_id, this, task_runner));
 
-    uint32_t options = mojom::kURLLoadOptionNone;
-    // TODO(jam): use this flag for ResourceDispatcherHost code path once
-    // MojoLoading is the only IPC code path.
-    if (base::FeatureList::IsEnabled(features::kNetworkService) &&
-        request->fetch_request_context_type != REQUEST_CONTEXT_TYPE_FETCH) {
-      // MIME sniffing should be disabled for a request initiated by fetch().
-      options |= mojom::kURLLoadOptionSniffMimeType;
-    }
-    if (is_sync)
-      options |= mojom::kURLLoadOptionSynchronous;
-
-    std::unique_ptr<ThrottlingURLLoader> url_loader =
-        ThrottlingURLLoader::CreateLoaderAndStart(
-            url_loader_factory, std::move(throttles), routing_id, request_id,
-            options, *request, client.get(), traffic_annotation,
-            std::move(task_runner));
-    pending_requests_[request_id]->url_loader = std::move(url_loader);
-    pending_requests_[request_id]->url_loader_client = std::move(client);
-  } else {
-    message_sender_->Send(new ResourceHostMsg_RequestResource(
-        routing_id, request_id, *request,
-        net::MutableNetworkTrafficAnnotationTag(traffic_annotation)));
+  uint32_t options = mojom::kURLLoadOptionNone;
+  // TODO(jam): use this flag for ResourceDispatcherHost code path once
+  // MojoLoading is the only IPC code path.
+  if (base::FeatureList::IsEnabled(features::kNetworkService) &&
+      request->fetch_request_context_type != REQUEST_CONTEXT_TYPE_FETCH) {
+    // MIME sniffing should be disabled for a request initiated by fetch().
+    options |= mojom::kURLLoadOptionSniffMimeType;
   }
+  if (is_sync)
+    options |= mojom::kURLLoadOptionSynchronous;
+
+  std::unique_ptr<ThrottlingURLLoader> url_loader =
+      ThrottlingURLLoader::CreateLoaderAndStart(
+          url_loader_factory, std::move(throttles), routing_id, request_id,
+          options, *request, client.get(), traffic_annotation,
+          std::move(task_runner));
+  pending_requests_[request_id]->url_loader = std::move(url_loader);
+  pending_requests_[request_id]->url_loader_client = std::move(client);
 
   return request_id;
 }
@@ -778,14 +510,6 @@
   return base::TimeTicks::FromInternalValue(result);
 }
 
-base::TimeTicks ResourceDispatcher::ConsumeIOTimestamp() {
-  if (io_timestamp_ == base::TimeTicks())
-    return base::TimeTicks::Now();
-  base::TimeTicks result = io_timestamp_;
-  io_timestamp_ = base::TimeTicks();
-  return result;
-}
-
 void ResourceDispatcher::ContinueForNavigation(
     int request_id,
     mojom::URLLoaderClientEndpointsPtr url_loader_client_endpoints) {
@@ -811,63 +535,4 @@
   client_ptr->Bind(std::move(url_loader_client_endpoints));
 }
 
-// static
-bool ResourceDispatcher::IsResourceDispatcherMessage(
-    const IPC::Message& message) {
-  switch (message.type()) {
-    case ResourceMsg_UploadProgress::ID:
-    case ResourceMsg_ReceivedResponse::ID:
-    case ResourceMsg_ReceivedCachedMetadata::ID:
-    case ResourceMsg_ReceivedRedirect::ID:
-    case ResourceMsg_SetDataBuffer::ID:
-    case ResourceMsg_DataReceived::ID:
-    case ResourceMsg_DataDownloaded::ID:
-    case ResourceMsg_RequestComplete::ID:
-      return true;
-
-    default:
-      break;
-  }
-
-  return false;
-}
-
-// static
-void ResourceDispatcher::ReleaseResourcesInDataMessage(
-    const IPC::Message& message) {
-  base::PickleIterator iter(message);
-  int request_id;
-  if (!iter.ReadInt(&request_id)) {
-    NOTREACHED() << "malformed resource message";
-    return;
-  }
-
-  // If the message contains a shared memory handle, we should close the handle
-  // or there will be a memory leak.
-  if (message.type() == ResourceMsg_SetDataBuffer::ID) {
-    base::SharedMemoryHandle shm_handle;
-    if (IPC::ParamTraits<base::SharedMemoryHandle>::Read(&message,
-                                                         &iter,
-                                                         &shm_handle)) {
-      if (base::SharedMemory::IsHandleValid(shm_handle))
-        base::SharedMemory::CloseHandle(shm_handle);
-    }
-  }
-}
-
-// static
-void ResourceDispatcher::ReleaseResourcesInMessageQueue(MessageQueue* queue) {
-  while (!queue->empty()) {
-    IPC::Message* message = queue->front();
-    ReleaseResourcesInDataMessage(*message);
-    queue->pop_front();
-    delete message;
-  }
-}
-
-void ResourceDispatcher::SetResourceSchedulingFilter(
-    scoped_refptr<ResourceSchedulingFilter> resource_scheduling_filter) {
-  resource_scheduling_filter_ = resource_scheduling_filter;
-}
-
 }  // namespace content
diff --git a/content/renderer/loader/resource_dispatcher.h b/content/renderer/loader/resource_dispatcher.h
index c0f96e9..d8f2479e 100644
--- a/content/renderer/loader/resource_dispatcher.h
+++ b/content/renderer/loader/resource_dispatcher.h
@@ -25,8 +25,6 @@
 #include "content/public/common/resource_type.h"
 #include "content/public/common/url_loader.mojom.h"
 #include "content/public/common/url_loader_throttle.h"
-#include "ipc/ipc_listener.h"
-#include "ipc/ipc_sender.h"
 #include "mojo/public/cpp/system/data_pipe.h"
 #include "net/base/request_priority.h"
 #include "net/traffic_annotation/network_traffic_annotation.h"
@@ -45,11 +43,9 @@
 namespace content {
 class RequestPeer;
 class ResourceDispatcherDelegate;
-class ResourceSchedulingFilter;
 struct ResourceResponseInfo;
 struct ResourceRequest;
 struct ResourceResponseHead;
-class SharedMemoryReceivedDataFactory;
 struct SiteIsolationResponseMetaData;
 struct SyncLoadResponse;
 class ThrottlingURLLoader;
@@ -62,7 +58,7 @@
 // This class serves as a communication interface to the ResourceDispatcherHost
 // in the browser process. It can be used from any child process.
 // Virtual methods are for tests.
-class CONTENT_EXPORT ResourceDispatcher : public IPC::Listener {
+class CONTENT_EXPORT ResourceDispatcher {
  public:
   // Generates ids for requests initiated by child processes unique to the
   // particular process, counted up from 0 (browser initiated requests count
@@ -73,13 +69,9 @@
   // CORS preflight requests.
   static int MakeRequestID();
 
-  ResourceDispatcher(
-      IPC::Sender* sender,
+  explicit ResourceDispatcher(
       scoped_refptr<base::SingleThreadTaskRunner> thread_task_runner);
-  ~ResourceDispatcher() override;
-
-  // IPC::Listener implementation.
-  bool OnMessageReceived(const IPC::Message& message) override;
+  virtual ~ResourceDispatcher();
 
   // Call this method to load the resource synchronously (i.e., in one shot).
   // This is an alternative to the StartAsync method. Be warned that this method
@@ -97,14 +89,12 @@
       const url::Origin& frame_origin,
       const net::NetworkTrafficAnnotationTag& traffic_annotation,
       SyncLoadResponse* response,
-      blink::WebURLRequest::LoadingIPCType ipc_type,
       mojom::URLLoaderFactory* url_loader_factory,
       std::vector<std::unique_ptr<URLLoaderThrottle>> throttles);
 
   // Call this method to initiate the request. If this method succeeds, then
   // the peer's methods will be called asynchronously to report various events.
-  // Returns the request id. |url_loader_factory| must be non-null if and only
-  // if |ipc_type| is LoadingIPCType::Mojo.
+  // Returns the request id. |url_loader_factory| must be non-null.
   //
   // |routing_id| is used to associated the bridge with a frame's network
   // context.
@@ -119,7 +109,6 @@
       const net::NetworkTrafficAnnotationTag& traffic_annotation,
       bool is_sync,
       std::unique_ptr<RequestPeer> peer,
-      blink::WebURLRequest::LoadingIPCType ipc_type,
       mojom::URLLoaderFactory* url_loader_factory,
       std::vector<std::unique_ptr<URLLoaderThrottle>> throttles,
       mojom::URLLoaderClientEndpointsPtr url_loader_client_endpoints);
@@ -140,31 +129,17 @@
                          net::RequestPriority new_priority,
                          int intra_priority_value);
 
-  void set_message_sender(IPC::Sender* sender) {
-    DCHECK(sender);
-    DCHECK(pending_requests_.empty());
-    message_sender_ = sender;
-  }
-
   // This does not take ownership of the delegate. It is expected that the
   // delegate have a longer lifetime than the ResourceDispatcher.
   void set_delegate(ResourceDispatcherDelegate* delegate) {
     delegate_ = delegate;
   }
 
-  // Remembers IO thread timestamp for next resource message.
-  void set_io_timestamp(base::TimeTicks io_timestamp) {
-    io_timestamp_ = io_timestamp;
-  }
-
   void SetThreadTaskRunner(
       scoped_refptr<base::SingleThreadTaskRunner> thread_task_runner) {
     thread_task_runner_ = thread_task_runner;
   }
 
-  void SetResourceSchedulingFilter(
-      scoped_refptr<ResourceSchedulingFilter> resource_scheduling_filter);
-
   base::WeakPtr<ResourceDispatcher> GetWeakPtr() {
     return weak_factory_.GetWeakPtr();
   }
@@ -176,7 +151,6 @@
   friend class URLResponseBodyConsumer;
   friend class ResourceDispatcherTest;
 
-  using MessageQueue = base::circular_deque<IPC::Message*>;
   struct PendingRequestInfo {
     PendingRequestInfo(std::unique_ptr<RequestPeer> peer,
                        ResourceType resource_type,
@@ -192,7 +166,6 @@
     std::unique_ptr<RequestPeer> peer;
     ResourceType resource_type;
     int render_frame_id;
-    MessageQueue deferred_message_queue;
     bool is_deferred = false;
     // Original requested url.
     GURL url;
@@ -204,12 +177,11 @@
     std::string response_method;
     GURL response_referrer;
     bool download_to_file;
-    std::unique_ptr<IPC::Message> pending_redirect_message;
+    bool has_pending_redirect = false;
     base::TimeTicks request_start;
     base::TimeTicks response_start;
     base::TimeTicks completion_time;
     linked_ptr<base::SharedMemory> buffer;
-    scoped_refptr<SharedMemoryReceivedDataFactory> received_data_factory;
     std::unique_ptr<SiteIsolationResponseMetaData> site_isolation_metadata;
     int buffer_size;
 
@@ -234,24 +206,10 @@
   void OnReceivedRedirect(int request_id,
                           const net::RedirectInfo& redirect_info,
                           const ResourceResponseHead& response_head);
-  void OnSetDataBuffer(int request_id,
-                       base::SharedMemoryHandle shm_handle,
-                       int shm_size);
-  void OnReceivedData(int request_id,
-                      int data_offset,
-                      int data_length,
-                      int encoded_data_length);
   void OnDownloadedData(int request_id, int data_len, int encoded_data_length);
   void OnRequestComplete(int request_id,
                          const network::URLLoaderCompletionStatus& status);
 
-  // Dispatch the message to one of the message response handlers.
-  void DispatchMessage(const IPC::Message& message);
-
-  // Dispatch any deferred messages for the given request, provided it is not
-  // again in the deferred state. This method may mutate |pending_requests_|.
-  void FlushDeferredMessages(int request_id);
-
   void ToResourceResponseInfo(const PendingRequestInfo& request_info,
                               const ResourceResponseHead& browser_info,
                               ResourceResponseInfo* renderer_info) const;
@@ -260,41 +218,16 @@
       const PendingRequestInfo& request_info,
       const base::TimeTicks& browser_completion_time) const;
 
-  // Returns timestamp provided by IO thread. If no timestamp is supplied,
-  // then current time is returned. Saved timestamp is reset, so following
-  // invocations will return current time until set_io_timestamp is called.
-  base::TimeTicks ConsumeIOTimestamp();
-
   void ContinueForNavigation(
       int request_id,
       mojom::URLLoaderClientEndpointsPtr url_loader_client_endpoints);
 
-  // Returns true if the message passed in is a resource related message.
-  static bool IsResourceDispatcherMessage(const IPC::Message& message);
-
-  // ViewHostMsg_Resource_DataReceived is not POD, it has a shared memory
-  // handle in it that we should cleanup it up nicely. This method accepts any
-  // message and determine whether the message is
-  // ViewHostMsg_Resource_DataReceived and clean up the shared memory handle.
-  static void ReleaseResourcesInDataMessage(const IPC::Message& message);
-
-  // Iterate through a message queue and clean up the messages by calling
-  // ReleaseResourcesInDataMessage and removing them from the queue. Intended
-  // for use on deferred message queues that are no longer needed.
-  static void ReleaseResourcesInMessageQueue(MessageQueue* queue);
-
-  IPC::Sender* message_sender_;
-
   // All pending requests issued to the host
   PendingRequestMap pending_requests_;
 
   ResourceDispatcherDelegate* delegate_;
 
-  // IO thread timestamp for ongoing IPC message.
-  base::TimeTicks io_timestamp_;
-
   scoped_refptr<base::SingleThreadTaskRunner> thread_task_runner_;
-  scoped_refptr<ResourceSchedulingFilter> resource_scheduling_filter_;
 
   base::WeakPtrFactory<ResourceDispatcher> weak_factory_;
 
diff --git a/content/renderer/loader/resource_dispatcher_unittest.cc b/content/renderer/loader/resource_dispatcher_unittest.cc
index 1b107ce..71890a9 100644
--- a/content/renderer/loader/resource_dispatcher_unittest.cc
+++ b/content/renderer/loader/resource_dispatcher_unittest.cc
@@ -21,7 +21,6 @@
 #include "base/run_loop.h"
 #include "base/test/scoped_feature_list.h"
 #include "content/common/appcache_interfaces.h"
-#include "content/common/resource_messages.h"
 #include "content/public/common/content_features.h"
 #include "content/public/common/resource_request.h"
 #include "content/public/common/resource_request_body.h"
@@ -44,169 +43,51 @@
 
 namespace content {
 
-static const char kTestPageUrl[] = "http://www.google.com/";
-static const char kTestPageHeaders[] =
-  "HTTP/1.1 200 OK\nContent-Type:text/html\n\n";
-static const char kTestPageMimeType[] = "text/html";
-static const char kTestPageCharset[] = "";
-static const char kTestPageContents[] =
-  "<html><head><title>Google</title></head><body><h1>Google</h1></body></html>";
-static const char kTestRedirectHeaders[] =
-  "HTTP/1.1 302 Found\nLocation:http://www.google.com/\n\n";
+static constexpr char kTestPageUrl[] = "http://www.google.com/";
+static constexpr char kTestPageHeaders[] =
+    "HTTP/1.1 200 OK\nContent-Type:text/html\n\n";
+static constexpr char kTestPageMimeType[] = "text/html";
+static constexpr char kTestPageCharset[] = "";
+static constexpr char kTestPageContents[] =
+    "<html><head><title>Google</title></head><body><h1>Google</h1></body></"
+    "html>";
 
 // Sets up the message sender override for the unit test.
-class ResourceDispatcherTest : public testing::Test, public IPC::Sender {
+class ResourceDispatcherTest : public testing::Test,
+                               public mojom::URLLoaderFactory {
  public:
   ResourceDispatcherTest()
-      : dispatcher_(new ResourceDispatcher(this, message_loop_.task_runner())) {
-  }
+      : dispatcher_(new ResourceDispatcher(message_loop_.task_runner())) {}
 
   ~ResourceDispatcherTest() override {
-    shared_memory_map_.clear();
     dispatcher_.reset();
     base::RunLoop().RunUntilIdle();
   }
 
-  // Emulates IPC send operations (IPC::Sender) by adding
-  // pending messages to the queue.
-  bool Send(IPC::Message* msg) override {
-    message_queue_.push_back(IPC::Message(*msg));
-    delete msg;
-    return true;
+  void CreateLoaderAndStart(
+      mojom::URLLoaderRequest request,
+      int32_t routing_id,
+      int32_t request_id,
+      uint32_t options,
+      const ResourceRequest& url_request,
+      mojom::URLLoaderClientPtr client,
+      const net::MutableNetworkTrafficAnnotationTag& annotation) override {
+    loader_and_clients_.emplace_back(std::move(request), std::move(client));
   }
 
-  size_t queued_messages() const { return message_queue_.size(); }
+  void Clone(mojom::URLLoaderFactoryRequest request) override { NOTREACHED(); }
 
-  // Returns the ID of the consumed request.  Can't make assumptions about the
-  // ID, because numbering is based on a global.
-  int ConsumeRequestResource() {
-    if (message_queue_.empty()) {
-      ADD_FAILURE() << "Missing resource request message";
-      return -1;
-    }
-
-    ResourceHostMsg_RequestResource::Param params;
-    if (static_cast<uint32_t>(ResourceHostMsg_RequestResource::ID) !=
-            message_queue_[0].type() ||
-        !ResourceHostMsg_RequestResource::Read(&message_queue_[0], &params)) {
-      ADD_FAILURE() << "Expected ResourceHostMsg_RequestResource message";
-      return -1;
-    }
-    ResourceRequest request = std::get<2>(params);
-    EXPECT_EQ(kTestPageUrl, request.url.spec());
-    message_queue_.erase(message_queue_.begin());
-    return std::get<1>(params);
-  }
-
-  void ConsumeFollowRedirect(int expected_request_id) {
-    ASSERT_FALSE(message_queue_.empty());
-    std::tuple<int> args;
-    ASSERT_EQ(static_cast<uint32_t>(ResourceHostMsg_FollowRedirect::ID),
-              message_queue_[0].type());
-    ASSERT_TRUE(ResourceHostMsg_FollowRedirect::Read(
-        &message_queue_[0], &args));
-    EXPECT_EQ(expected_request_id, std::get<0>(args));
-    message_queue_.erase(message_queue_.begin());
-  }
-
-  void ConsumeDataReceived_ACK(int expected_request_id) {
-    ASSERT_FALSE(message_queue_.empty());
-    std::tuple<int> args;
-    ASSERT_EQ(static_cast<uint32_t>(ResourceHostMsg_DataReceived_ACK::ID),
-              message_queue_[0].type());
-    ASSERT_TRUE(ResourceHostMsg_DataReceived_ACK::Read(
-        &message_queue_[0], &args));
-    EXPECT_EQ(expected_request_id, std::get<0>(args));
-    message_queue_.erase(message_queue_.begin());
-  }
-
-  void ConsumeReleaseDownloadedFile(int expected_request_id) {
-    ASSERT_FALSE(message_queue_.empty());
-    std::tuple<int> args;
-    ASSERT_EQ(static_cast<uint32_t>(ResourceHostMsg_ReleaseDownloadedFile::ID),
-              message_queue_[0].type());
-    ASSERT_TRUE(ResourceHostMsg_ReleaseDownloadedFile::Read(
-        &message_queue_[0], &args));
-    EXPECT_EQ(expected_request_id, std::get<0>(args));
-    message_queue_.erase(message_queue_.begin());
-  }
-
-  void ConsumeCancelRequest(int expected_request_id) {
-    ASSERT_FALSE(message_queue_.empty());
-    std::tuple<int> args;
-    ASSERT_EQ(static_cast<uint32_t>(ResourceHostMsg_CancelRequest::ID),
-              message_queue_[0].type());
-    ASSERT_TRUE(ResourceHostMsg_CancelRequest::Read(
-        &message_queue_[0], &args));
-    EXPECT_EQ(expected_request_id, std::get<0>(args));
-    message_queue_.erase(message_queue_.begin());
-  }
-
-  void NotifyReceivedRedirect(int request_id) {
-    ResourceResponseHead head;
-    std::string raw_headers(kTestRedirectHeaders);
-    std::replace(raw_headers.begin(), raw_headers.end(), '\n', '\0');
-    head.headers = new net::HttpResponseHeaders(raw_headers);
-    net::RedirectInfo redirect_info;
-    redirect_info.status_code = 302;
-    redirect_info.new_method = "GET";
-    redirect_info.new_url = GURL(kTestPageUrl);
-    redirect_info.new_site_for_cookies = GURL(kTestPageUrl);
-    EXPECT_EQ(true, dispatcher_->OnMessageReceived(ResourceMsg_ReceivedRedirect(
-                        request_id, redirect_info, head)));
-  }
-
-  void NotifyReceivedResponse(int request_id) {
+  void CallOnReceiveResponse(mojom::URLLoaderClient* client) {
     ResourceResponseHead head;
     std::string raw_headers(kTestPageHeaders);
     std::replace(raw_headers.begin(), raw_headers.end(), '\n', '\0');
     head.headers = new net::HttpResponseHeaders(raw_headers);
     head.mime_type = kTestPageMimeType;
     head.charset = kTestPageCharset;
-    EXPECT_EQ(true, dispatcher_->OnMessageReceived(
-                        ResourceMsg_ReceivedResponse(request_id, head)));
+    client->OnReceiveResponse(head, {}, {});
   }
 
-  void NotifySetDataBuffer(int request_id, size_t buffer_size) {
-    base::SharedMemory* shared_memory = new base::SharedMemory();
-    ASSERT_FALSE(shared_memory_map_[request_id]);
-    shared_memory_map_[request_id] = base::WrapUnique(shared_memory);
-    EXPECT_TRUE(shared_memory->CreateAndMapAnonymous(buffer_size));
-
-    base::SharedMemoryHandle duplicate_handle =
-        shared_memory->handle().Duplicate();
-    EXPECT_TRUE(duplicate_handle.IsValid());
-    EXPECT_TRUE(dispatcher_->OnMessageReceived(ResourceMsg_SetDataBuffer(
-        request_id, duplicate_handle, shared_memory->requested_size())));
-  }
-
-  void NotifyDataReceived(int request_id, const std::string& data) {
-    ASSERT_LE(data.length(), shared_memory_map_[request_id]->requested_size());
-    memcpy(shared_memory_map_[request_id]->memory(), data.c_str(),
-           data.length());
-
-    EXPECT_TRUE(dispatcher_->OnMessageReceived(ResourceMsg_DataReceived(
-        request_id, 0, data.length(), data.length())));
-  }
-
-  void NotifyDataDownloaded(int request_id,
-                            int decoded_length,
-                            int encoded_data_length) {
-    EXPECT_TRUE(dispatcher_->OnMessageReceived(ResourceMsg_DataDownloaded(
-        request_id, decoded_length, encoded_data_length)));
-  }
-
-  void NotifyRequestComplete(int request_id, size_t total_size) {
-    network::URLLoaderCompletionStatus status;
-    status.error_code = net::OK;
-    status.exists_in_cache = false;
-    status.encoded_data_length = total_size;
-    EXPECT_TRUE(dispatcher_->OnMessageReceived(
-        ResourceMsg_RequestComplete(request_id, status)));
-  }
-
-  std::unique_ptr<ResourceRequest> CreateResourceRequest(
-      bool download_to_file) {
+  std::unique_ptr<ResourceRequest> CreateResourceRequest() {
     std::unique_ptr<ResourceRequest> request(new ResourceRequest());
 
     request->method = "GET";
@@ -217,7 +98,6 @@
     request->priority = net::LOW;
     request->fetch_request_mode = network::mojom::FetchRequestMode::kNoCORS;
     request->fetch_frame_type = network::mojom::RequestContextFrameType::kNone;
-    request->download_to_file = download_to_file;
 
     const RequestExtraData extra_data;
     extra_data.CopyToResourceRequest(request.get());
@@ -234,19 +114,16 @@
         new TestRequestPeer(dispatcher(), peer_context));
     int request_id = dispatcher()->StartAsync(
         std::move(request), 0, nullptr, url::Origin(),
-        TRAFFIC_ANNOTATION_FOR_TESTS, false, std::move(peer),
-        blink::WebURLRequest::LoadingIPCType::kChromeIPC, nullptr,
+        TRAFFIC_ANNOTATION_FOR_TESTS, false, std::move(peer), this,
         std::vector<std::unique_ptr<URLLoaderThrottle>>(),
         mojom::URLLoaderClientEndpointsPtr());
     peer_context->request_id = request_id;
     return request_id;
   }
 
- private:
-  // Map of request IDs to shared memory.
-  std::map<int, std::unique_ptr<base::SharedMemory>> shared_memory_map_;
-
-  std::vector<IPC::Message> message_queue_;
+ protected:
+  std::vector<std::pair<mojom::URLLoaderRequest, mojom::URLLoaderClientPtr>>
+      loader_and_clients_;
   base::MessageLoop message_loop_;
   std::unique_ptr<ResourceDispatcher> dispatcher_;
 };
@@ -261,133 +138,6 @@
   EXPECT_GE(first_id, 0);
 }
 
-// Does a simple request and tests that the correct data is received.  Simulates
-// two reads.
-TEST_F(ResourceDispatcherTest, RoundTrip) {
-  // Number of bytes received in the first read.
-  const size_t kFirstReceiveSize = 2;
-  ASSERT_LT(kFirstReceiveSize, strlen(kTestPageContents));
-
-  std::unique_ptr<ResourceRequest> request(CreateResourceRequest(false));
-  TestRequestPeer::Context peer_context;
-  StartAsync(std::move(request), nullptr, &peer_context);
-
-  int id = ConsumeRequestResource();
-  EXPECT_EQ(0u, queued_messages());
-
-  NotifyReceivedResponse(id);
-  EXPECT_EQ(0u, queued_messages());
-  EXPECT_TRUE(peer_context.received_response);
-
-  NotifySetDataBuffer(id, strlen(kTestPageContents));
-  NotifyDataReceived(id, std::string(kTestPageContents, kFirstReceiveSize));
-  ConsumeDataReceived_ACK(id);
-  EXPECT_EQ(0u, queued_messages());
-
-  NotifyDataReceived(id, kTestPageContents + kFirstReceiveSize);
-  ConsumeDataReceived_ACK(id);
-  EXPECT_EQ(0u, queued_messages());
-
-  NotifyRequestComplete(id, strlen(kTestPageContents));
-  EXPECT_EQ(kTestPageContents, peer_context.data);
-  EXPECT_TRUE(peer_context.complete);
-  EXPECT_EQ(0u, queued_messages());
-}
-
-// Tests that the request IDs are straight when there are two interleaving
-// requests.
-TEST_F(ResourceDispatcherTest, MultipleRequests) {
-  const char kTestPageContents2[] = "Not kTestPageContents";
-
-  std::unique_ptr<ResourceRequest> request1(CreateResourceRequest(false));
-  TestRequestPeer::Context peer_context1;
-  StartAsync(std::move(request1), nullptr, &peer_context1);
-
-  std::unique_ptr<ResourceRequest> request2(CreateResourceRequest(false));
-  TestRequestPeer::Context peer_context2;
-  StartAsync(std::move(request2), nullptr, &peer_context2);
-
-  int id1 = ConsumeRequestResource();
-  int id2 = ConsumeRequestResource();
-  EXPECT_EQ(0u, queued_messages());
-
-  NotifyReceivedResponse(id1);
-  EXPECT_TRUE(peer_context1.received_response);
-  EXPECT_FALSE(peer_context2.received_response);
-  NotifyReceivedResponse(id2);
-  EXPECT_TRUE(peer_context2.received_response);
-  EXPECT_EQ(0u, queued_messages());
-
-  NotifySetDataBuffer(id2, strlen(kTestPageContents2));
-  NotifyDataReceived(id2, kTestPageContents2);
-  ConsumeDataReceived_ACK(id2);
-  NotifySetDataBuffer(id1, strlen(kTestPageContents));
-  NotifyDataReceived(id1, kTestPageContents);
-  ConsumeDataReceived_ACK(id1);
-  EXPECT_EQ(0u, queued_messages());
-
-  NotifyRequestComplete(id1, strlen(kTestPageContents));
-  EXPECT_EQ(kTestPageContents, peer_context1.data);
-  EXPECT_TRUE(peer_context1.complete);
-  EXPECT_FALSE(peer_context2.complete);
-
-  NotifyRequestComplete(id2, strlen(kTestPageContents2));
-  EXPECT_EQ(kTestPageContents2, peer_context2.data);
-  EXPECT_TRUE(peer_context2.complete);
-
-  EXPECT_EQ(0u, queued_messages());
-}
-
-// Tests that the cancel method prevents other messages from being received.
-TEST_F(ResourceDispatcherTest, Cancel) {
-  std::unique_ptr<ResourceRequest> request(CreateResourceRequest(false));
-  TestRequestPeer::Context peer_context;
-  int request_id = StartAsync(std::move(request), nullptr, &peer_context);
-
-  int id = ConsumeRequestResource();
-  EXPECT_EQ(0u, queued_messages());
-
-  // Cancel the request.
-  dispatcher()->Cancel(request_id);
-  ConsumeCancelRequest(id);
-
-  // Any future messages related to the request should be ignored.
-  NotifyReceivedResponse(id);
-  NotifySetDataBuffer(id, strlen(kTestPageContents));
-  NotifyDataReceived(id, kTestPageContents);
-  NotifyRequestComplete(id, strlen(kTestPageContents));
-
-  EXPECT_EQ(0u, queued_messages());
-  EXPECT_EQ("", peer_context.data);
-  EXPECT_FALSE(peer_context.received_response);
-  EXPECT_FALSE(peer_context.complete);
-}
-
-// Tests that calling cancel during a callback works as expected.
-TEST_F(ResourceDispatcherTest, CancelDuringCallback) {
-  std::unique_ptr<ResourceRequest> request(CreateResourceRequest(false));
-  TestRequestPeer::Context peer_context;
-  StartAsync(std::move(request), nullptr, &peer_context);
-  peer_context.cancel_on_receive_response = true;
-
-  int id = ConsumeRequestResource();
-  EXPECT_EQ(0u, queued_messages());
-
-  NotifyReceivedResponse(id);
-  EXPECT_TRUE(peer_context.received_response);
-  // Request should have been cancelled.
-  ConsumeCancelRequest(id);
-
-  // Any future messages related to the request should be ignored.
-  NotifySetDataBuffer(id, strlen(kTestPageContents));
-  NotifyDataReceived(id, kTestPageContents);
-  NotifyRequestComplete(id, strlen(kTestPageContents));
-
-  EXPECT_EQ(0u, queued_messages());
-  EXPECT_EQ("", peer_context.data);
-  EXPECT_FALSE(peer_context.complete);
-}
-
 class TestResourceDispatcherDelegate : public ResourceDispatcherDelegate {
  public:
   TestResourceDispatcherDelegate() {}
@@ -453,409 +203,97 @@
 };
 
 TEST_F(ResourceDispatcherTest, DelegateTest) {
-  std::unique_ptr<ResourceRequest> request(CreateResourceRequest(false));
+  std::unique_ptr<ResourceRequest> request(CreateResourceRequest());
   TestRequestPeer::Context peer_context;
   StartAsync(std::move(request), nullptr, &peer_context);
 
+  ASSERT_EQ(1u, loader_and_clients_.size());
+  mojom::URLLoaderClientPtr client = std::move(loader_and_clients_[0].second);
+  loader_and_clients_.clear();
+
   // Set the delegate that inserts a new peer in OnReceivedResponse.
   TestResourceDispatcherDelegate delegate;
   dispatcher()->set_delegate(&delegate);
 
-  // Run a simple round-trip.
-  const size_t kFirstReceiveSize = 2;
-  ASSERT_LT(kFirstReceiveSize, strlen(kTestPageContents));
-
-  int id = ConsumeRequestResource();
-  EXPECT_EQ(0u, queued_messages());
-
   // The wrapper eats all messages until RequestComplete message is sent.
-  NotifyReceivedResponse(id);
-  NotifySetDataBuffer(id, strlen(kTestPageContents));
-  NotifyDataReceived(id, std::string(kTestPageContents, kFirstReceiveSize));
-  ConsumeDataReceived_ACK(id);
-  NotifyDataReceived(id, kTestPageContents + kFirstReceiveSize);
-  ConsumeDataReceived_ACK(id);
+  CallOnReceiveResponse(client.get());
+
+  mojo::DataPipe data_pipe;
+  client->OnStartLoadingResponseBody(std::move(data_pipe.consumer_handle));
+
+  uint32_t size = strlen(kTestPageContents);
+  auto result = data_pipe.producer_handle->WriteData(kTestPageContents, &size,
+                                                     MOJO_WRITE_DATA_FLAG_NONE);
+  ASSERT_EQ(result, MOJO_RESULT_OK);
+  ASSERT_EQ(size, strlen(kTestPageContents));
+
+  data_pipe.producer_handle.reset();
+
+  base::RunLoop().RunUntilIdle();
 
   EXPECT_FALSE(peer_context.received_response);
-  EXPECT_EQ(0u, queued_messages());
 
   // This lets the wrapper peer pass all the messages to the original
   // peer at once.
-  NotifyRequestComplete(id, strlen(kTestPageContents));
+  network::URLLoaderCompletionStatus status;
+  status.error_code = net::OK;
+  status.exists_in_cache = false;
+  status.encoded_data_length = strlen(kTestPageContents);
+  client->OnComplete(status);
+
+  base::RunLoop().RunUntilIdle();
 
   EXPECT_TRUE(peer_context.received_response);
   EXPECT_EQ(kTestPageContents, peer_context.data);
   EXPECT_TRUE(peer_context.complete);
-  EXPECT_EQ(0u, queued_messages());
 }
 
 TEST_F(ResourceDispatcherTest, CancelDuringCallbackWithWrapperPeer) {
-  std::unique_ptr<ResourceRequest> request(CreateResourceRequest(false));
+  std::unique_ptr<ResourceRequest> request(CreateResourceRequest());
   TestRequestPeer::Context peer_context;
   StartAsync(std::move(request), nullptr, &peer_context);
   peer_context.cancel_on_receive_response = true;
 
+  ASSERT_EQ(1u, loader_and_clients_.size());
+  mojom::URLLoaderClientPtr client = std::move(loader_and_clients_[0].second);
+  loader_and_clients_.clear();
+
   // Set the delegate that inserts a new peer in OnReceivedResponse.
   TestResourceDispatcherDelegate delegate;
   dispatcher()->set_delegate(&delegate);
 
-  int id = ConsumeRequestResource();
-  EXPECT_EQ(0u, queued_messages());
+  CallOnReceiveResponse(client.get());
+  mojo::DataPipe data_pipe;
+  client->OnStartLoadingResponseBody(std::move(data_pipe.consumer_handle));
+  uint32_t size = strlen(kTestPageContents);
+  auto result = data_pipe.producer_handle->WriteData(kTestPageContents, &size,
+                                                     MOJO_WRITE_DATA_FLAG_NONE);
+  ASSERT_EQ(result, MOJO_RESULT_OK);
+  ASSERT_EQ(size, strlen(kTestPageContents));
+  data_pipe.producer_handle.reset();
 
-  // The wrapper eats all messages until RequestComplete message is sent.
-  NotifyReceivedResponse(id);
-  NotifySetDataBuffer(id, strlen(kTestPageContents));
-  NotifyDataReceived(id, kTestPageContents);
-  ConsumeDataReceived_ACK(id);
-
+  base::RunLoop().RunUntilIdle();
   EXPECT_FALSE(peer_context.received_response);
-  EXPECT_EQ(0u, queued_messages());
 
   // This lets the wrapper peer pass all the messages to the original
   // peer at once, but the original peer cancels right after it receives
   // the response. (This will remove pending request info from
   // ResourceDispatcher while the wrapper peer is still running
   // OnCompletedRequest, but it should not lead to crashes.)
-  NotifyRequestComplete(id, strlen(kTestPageContents));
+  network::URLLoaderCompletionStatus status;
+  status.error_code = net::OK;
+  status.exists_in_cache = false;
+  status.encoded_data_length = strlen(kTestPageContents);
+  client->OnComplete(status);
 
+  base::RunLoop().RunUntilIdle();
   EXPECT_TRUE(peer_context.received_response);
   // Request should have been cancelled with no additional messages.
-  EXPECT_EQ(0u, queued_messages());
   EXPECT_TRUE(peer_context.cancelled);
-
-  // Any future messages related to the request should be ignored.
-  NotifyDataReceived(id, kTestPageContents);
-  NotifyRequestComplete(id, strlen(kTestPageContents));
-
-  EXPECT_EQ(0u, queued_messages());
   EXPECT_EQ("", peer_context.data);
   EXPECT_FALSE(peer_context.complete);
 }
 
-// Checks that redirects work as expected.
-TEST_F(ResourceDispatcherTest, Redirect) {
-  std::unique_ptr<ResourceRequest> request(CreateResourceRequest(false));
-  TestRequestPeer::Context peer_context;
-  StartAsync(std::move(request), nullptr, &peer_context);
-
-  int id = ConsumeRequestResource();
-
-  NotifyReceivedRedirect(id);
-  ConsumeFollowRedirect(id);
-  EXPECT_EQ(1, peer_context.seen_redirects);
-
-  NotifyReceivedRedirect(id);
-  ConsumeFollowRedirect(id);
-  EXPECT_EQ(2, peer_context.seen_redirects);
-
-  NotifyReceivedResponse(id);
-  EXPECT_TRUE(peer_context.received_response);
-
-  NotifySetDataBuffer(id, strlen(kTestPageContents));
-  NotifyDataReceived(id, kTestPageContents);
-  ConsumeDataReceived_ACK(id);
-
-  NotifyRequestComplete(id, strlen(kTestPageContents));
-  EXPECT_EQ(kTestPageContents, peer_context.data);
-  EXPECT_TRUE(peer_context.complete);
-  EXPECT_EQ(0u, queued_messages());
-  EXPECT_EQ(2, peer_context.seen_redirects);
-}
-
-// Tests that that cancelling during a redirect method prevents other messages
-// from being received.
-TEST_F(ResourceDispatcherTest, CancelDuringRedirect) {
-  std::unique_ptr<ResourceRequest> request(CreateResourceRequest(false));
-  TestRequestPeer::Context peer_context;
-  StartAsync(std::move(request), nullptr, &peer_context);
-  peer_context.follow_redirects = false;
-
-  int id = ConsumeRequestResource();
-  EXPECT_EQ(0u, queued_messages());
-
-  // Redirect the request, which triggers a cancellation.
-  NotifyReceivedRedirect(id);
-  ConsumeCancelRequest(id);
-  EXPECT_EQ(1, peer_context.seen_redirects);
-  EXPECT_EQ(0u, queued_messages());
-
-  // Any future messages related to the request should be ignored.  In practice,
-  // only the NotifyRequestComplete should be received after this point.
-  NotifyReceivedRedirect(id);
-  NotifyReceivedResponse(id);
-  NotifySetDataBuffer(id, strlen(kTestPageContents));
-  NotifyDataReceived(id, kTestPageContents);
-  NotifyRequestComplete(id, strlen(kTestPageContents));
-
-  EXPECT_EQ(0u, queued_messages());
-  EXPECT_EQ("", peer_context.data);
-  EXPECT_FALSE(peer_context.complete);
-  EXPECT_EQ(1, peer_context.seen_redirects);
-}
-
-// Checks that deferring a request delays messages until it's resumed.
-TEST_F(ResourceDispatcherTest, Defer) {
-  std::unique_ptr<ResourceRequest> request(CreateResourceRequest(false));
-  TestRequestPeer::Context peer_context;
-  int request_id = StartAsync(std::move(request), nullptr, &peer_context);
-
-  int id = ConsumeRequestResource();
-  EXPECT_EQ(0u, queued_messages());
-
-  dispatcher()->SetDefersLoading(request_id, true);
-  NotifyReceivedResponse(id);
-  NotifySetDataBuffer(id, strlen(kTestPageContents));
-  NotifyDataReceived(id, kTestPageContents);
-  NotifyRequestComplete(id, strlen(kTestPageContents));
-
-  // None of the messages should have been processed yet, so no queued messages
-  // to the browser process, and no data received by the peer.
-  EXPECT_EQ(0u, queued_messages());
-  EXPECT_EQ("", peer_context.data);
-  EXPECT_FALSE(peer_context.complete);
-  EXPECT_EQ(0, peer_context.seen_redirects);
-
-  // Resuming the request should asynchronously unleash the deferred messages.
-  dispatcher()->SetDefersLoading(request_id, false);
-  base::RunLoop().RunUntilIdle();
-
-  ConsumeDataReceived_ACK(id);
-  EXPECT_EQ(0u, queued_messages());
-  EXPECT_TRUE(peer_context.received_response);
-  EXPECT_EQ(kTestPageContents, peer_context.data);
-  EXPECT_TRUE(peer_context.complete);
-}
-
-// Checks that deferring a request during a redirect delays messages until it's
-// resumed.
-TEST_F(ResourceDispatcherTest, DeferOnRedirect) {
-  std::unique_ptr<ResourceRequest> request(CreateResourceRequest(false));
-  TestRequestPeer::Context peer_context;
-  int request_id = StartAsync(std::move(request), nullptr, &peer_context);
-  peer_context.defer_on_redirect = true;
-
-  int id = ConsumeRequestResource();
-  EXPECT_EQ(0u, queued_messages());
-
-  // The request should be deferred during the redirect, including the message
-  // to follow the redirect.
-  NotifyReceivedRedirect(id);
-  NotifyReceivedResponse(id);
-  NotifySetDataBuffer(id, strlen(kTestPageContents));
-  NotifyDataReceived(id, kTestPageContents);
-  NotifyRequestComplete(id, strlen(kTestPageContents));
-
-  // None of the messages should have been processed yet, so no queued messages
-  // to the browser process, and no data received by the peer.
-  EXPECT_EQ(0u, queued_messages());
-  EXPECT_EQ("", peer_context.data);
-  EXPECT_FALSE(peer_context.complete);
-  EXPECT_EQ(1, peer_context.seen_redirects);
-
-  // Resuming the request should asynchronously unleash the deferred messages.
-  dispatcher()->SetDefersLoading(request_id, false);
-  base::RunLoop().RunUntilIdle();
-
-  ConsumeFollowRedirect(id);
-  ConsumeDataReceived_ACK(id);
-
-  EXPECT_EQ(0u, queued_messages());
-  EXPECT_TRUE(peer_context.received_response);
-  EXPECT_EQ(kTestPageContents, peer_context.data);
-  EXPECT_TRUE(peer_context.complete);
-  EXPECT_EQ(1, peer_context.seen_redirects);
-}
-
-// Checks that a deferred request that's cancelled doesn't receive any messages.
-TEST_F(ResourceDispatcherTest, CancelDeferredRequest) {
-  std::unique_ptr<ResourceRequest> request(CreateResourceRequest(false));
-  TestRequestPeer::Context peer_context;
-  int request_id = StartAsync(std::move(request), nullptr, &peer_context);
-
-  int id = ConsumeRequestResource();
-  EXPECT_EQ(0u, queued_messages());
-
-  dispatcher()->SetDefersLoading(request_id, true);
-  NotifyReceivedRedirect(id);
-  dispatcher()->Cancel(request_id);
-  ConsumeCancelRequest(id);
-
-  NotifyRequestComplete(id, 0);
-  base::RunLoop().RunUntilIdle();
-
-  // None of the messages should have been processed.
-  EXPECT_EQ(0u, queued_messages());
-  EXPECT_EQ("", peer_context.data);
-  EXPECT_FALSE(peer_context.complete);
-  EXPECT_EQ(0, peer_context.seen_redirects);
-}
-
-// Checks cancelling a request while flushing deferred requests from
-// the FlushDeferredMessages() task.
-TEST_F(ResourceDispatcherTest, CancelWhileFlushingDeferredRequests) {
-  std::unique_ptr<ResourceRequest> request(CreateResourceRequest(false));
-  TestRequestPeer::Context peer_context;
-  int request_id = StartAsync(std::move(request), nullptr, &peer_context);
-
-  // Cancel the request when the data message is handled.
-  peer_context.cancel_on_receive_data = true;
-
-  int id = ConsumeRequestResource();
-  EXPECT_EQ(0u, queued_messages());
-
-  dispatcher()->SetDefersLoading(request_id, true);
-  NotifyReceivedResponse(id);
-  NotifySetDataBuffer(id, strlen(kTestPageContents));
-  NotifyDataReceived(id, kTestPageContents);
-
-  // None of the messages should have been processed yet.
-  EXPECT_EQ("", peer_context.data);
-  EXPECT_FALSE(peer_context.complete);
-  EXPECT_EQ(0u, queued_messages());
-
-  dispatcher()->SetDefersLoading(request_id, false);
-
-  // Make sure that the FlushDeferredMessages() task posted from
-  // SetDefersLoading() is run. It should dispatch all the deferred
-  // messages.
-  base::RunLoop().RunUntilIdle();
-
-  // When the deferred DataReceived is dispatched, the handler will
-  // cancel the request, but the ACK is sent after the handler
-  // returns, so the cancel request ends up before the ACK in the
-  // message queue.
-  ConsumeCancelRequest(id);
-  ConsumeDataReceived_ACK(id);
-
-  // The data was consumed before the handler canceled
-  // the request, so the data should have been received.
-  EXPECT_EQ(kTestPageContents, peer_context.data);
-  EXPECT_FALSE(peer_context.complete);
-  EXPECT_EQ(0u, queued_messages());
-}
-
-// Checks cancelling a request while flushing deferred requests from
-// OnMessageReceived().
-TEST_F(ResourceDispatcherTest,
-       CancelWhileFlushingDeferredRequestsFromOnMessageReceived) {
-  std::unique_ptr<ResourceRequest> request(CreateResourceRequest(false));
-  TestRequestPeer::Context peer_context;
-  int request_id = StartAsync(std::move(request), nullptr, &peer_context);
-
-  // Cancel the request when the data message is handled.
-  peer_context.cancel_on_receive_data = true;
-
-  int id = ConsumeRequestResource();
-  EXPECT_EQ(0u, queued_messages());
-
-  dispatcher()->SetDefersLoading(request_id, true);
-  NotifyReceivedResponse(id);
-  NotifySetDataBuffer(id, strlen(kTestPageContents));
-  NotifyDataReceived(id, kTestPageContents);
-
-  // None of the messages should have been processed yet.
-  EXPECT_EQ("", peer_context.data);
-  EXPECT_FALSE(peer_context.complete);
-  EXPECT_EQ(0u, queued_messages());
-
-  dispatcher()->SetDefersLoading(request_id, false);
-
-  // SetDefersLoading() posts a task to run FlushDeferredMessages() to dispatch
-  // the deferred messages. Since the message loop hasn't been run yet the
-  // task hasn't been run either and no IPC-messages should have been
-  // dispatched.
-  EXPECT_EQ("", peer_context.data);
-  EXPECT_FALSE(peer_context.complete);
-  EXPECT_EQ(0u, queued_messages());
-
-  // Calling NotifyRequestComplete() here, before the task from
-  // SetDefersLoading() has been run, triggers the flush in
-  // OnMessageReceived().
-  NotifyRequestComplete(id, strlen(kTestPageContents));
-
-  // When the deferred DataReceived is dispatched, the handler will
-  // cancel the request, but the ACK is sent after the handler
-  // returns, so the cancel request ends up before the ACK in the
-  // message queue.
-  ConsumeCancelRequest(id);
-  ConsumeDataReceived_ACK(id);
-
-  // The data was consumed before the handler canceled
-  // the request, so the data should have been received.
-  EXPECT_EQ(kTestPageContents, peer_context.data);
-  EXPECT_FALSE(peer_context.complete);
-  EXPECT_EQ(0u, queued_messages());
-
-  // Make sure that the FlushDeferredMessages() task posted from
-  // SetDefersLoading() is run. The messages should already have been
-  // flushed above, so it should be a NOOP.
-  base::RunLoop().RunUntilIdle();
-
-  // Check that the task didn't change anything.
-  EXPECT_EQ(kTestPageContents, peer_context.data);
-  EXPECT_FALSE(peer_context.complete);
-  EXPECT_EQ(0u, queued_messages());
-}
-
-TEST_F(ResourceDispatcherTest, DownloadToFile) {
-  std::unique_ptr<ResourceRequest> request(CreateResourceRequest(true));
-  TestRequestPeer::Context peer_context;
-  int request_id = StartAsync(std::move(request), nullptr, &peer_context);
-  const int kDownloadedIncrement = 100;
-  const int kEncodedIncrement = 50;
-
-  int id = ConsumeRequestResource();
-  EXPECT_EQ(0u, queued_messages());
-
-  NotifyReceivedResponse(id);
-  EXPECT_EQ(0u, queued_messages());
-  EXPECT_TRUE(peer_context.received_response);
-
-  int expected_total_downloaded_length = 0;
-  int expected_total_encoded_data_length = 0;
-  for (int i = 0; i < 10; ++i) {
-    NotifyDataDownloaded(id, kDownloadedIncrement, kEncodedIncrement);
-    expected_total_downloaded_length += kDownloadedIncrement;
-    expected_total_encoded_data_length += kEncodedIncrement;
-    EXPECT_EQ(expected_total_downloaded_length,
-              peer_context.total_downloaded_data_length);
-    EXPECT_EQ(expected_total_encoded_data_length,
-              peer_context.total_encoded_data_length);
-  }
-
-  NotifyRequestComplete(id, strlen(kTestPageContents));
-  EXPECT_EQ("", peer_context.data);
-  EXPECT_TRUE(peer_context.complete);
-  EXPECT_EQ(0u, queued_messages());
-
-  dispatcher()->RemovePendingRequest(request_id);
-  ConsumeReleaseDownloadedFile(id);
-  EXPECT_EQ(0u, queued_messages());
-  EXPECT_EQ(expected_total_downloaded_length,
-            peer_context.total_downloaded_data_length);
-  EXPECT_EQ(expected_total_encoded_data_length,
-            peer_context.total_encoded_data_length);
-}
-
-// Make sure that when a download to file is cancelled, the file is destroyed.
-TEST_F(ResourceDispatcherTest, CancelDownloadToFile) {
-  std::unique_ptr<ResourceRequest> request(CreateResourceRequest(true));
-  TestRequestPeer::Context peer_context;
-  int request_id = StartAsync(std::move(request), nullptr, &peer_context);
-
-  int id = ConsumeRequestResource();
-  EXPECT_EQ(0u, queued_messages());
-
-  NotifyReceivedResponse(id);
-  EXPECT_EQ(0u, queued_messages());
-  EXPECT_TRUE(peer_context.received_response);
-
-  // Cancelling the request deletes the file.
-  dispatcher()->Cancel(request_id);
-  ConsumeCancelRequest(id);
-  ConsumeReleaseDownloadedFile(id);
-}
-
 TEST_F(ResourceDispatcherTest, Cookies) {
   // FIXME
 }
@@ -866,18 +304,15 @@
 
 class TimeConversionTest : public ResourceDispatcherTest {
  public:
-  bool Send(IPC::Message* msg) override {
-    delete msg;
-    return true;
-  }
-
   void PerformTest(const ResourceResponseHead& response_head) {
-    std::unique_ptr<ResourceRequest> request(CreateResourceRequest(false));
+    std::unique_ptr<ResourceRequest> request(CreateResourceRequest());
     TestRequestPeer::Context peer_context;
     StartAsync(std::move(request), nullptr, &peer_context);
 
-    dispatcher()->OnMessageReceived(
-        ResourceMsg_ReceivedResponse(0, response_head));
+    ASSERT_EQ(1u, loader_and_clients_.size());
+    auto client = std::move(loader_and_clients_[0].second);
+    loader_and_clients_.clear();
+    client->OnReceiveResponse(response_head, {}, {});
   }
 
   const ResourceResponseInfo& response_info() const { return response_info_; }
diff --git a/content/renderer/loader/resource_scheduling_filter.cc b/content/renderer/loader/resource_scheduling_filter.cc
deleted file mode 100644
index ca0cb037..0000000
--- a/content/renderer/loader/resource_scheduling_filter.cc
+++ /dev/null
@@ -1,77 +0,0 @@
-// Copyright (c) 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "content/renderer/loader/resource_scheduling_filter.h"
-
-#include <utility>
-
-#include "base/bind.h"
-#include "base/location.h"
-#include "content/renderer/loader/resource_dispatcher.h"
-#include "ipc/ipc_message.h"
-#include "ipc/ipc_message_start.h"
-
-namespace content {
-
-ResourceSchedulingFilter::ResourceSchedulingFilter(
-    const scoped_refptr<base::SingleThreadTaskRunner>& main_thread_task_runner,
-    ResourceDispatcher* resource_dispatcher)
-    : main_thread_task_runner_(main_thread_task_runner),
-      resource_dispatcher_(resource_dispatcher->GetWeakPtr()),
-      weak_ptr_factory_(this) {
-  DCHECK(main_thread_task_runner_.get());
-}
-
-ResourceSchedulingFilter::~ResourceSchedulingFilter() {
-}
-
-bool ResourceSchedulingFilter::OnMessageReceived(const IPC::Message& message) {
-  base::AutoLock lock(request_id_to_task_runner_map_lock_);
-  int request_id;
-
-  base::PickleIterator pickle_iterator(message);
-  if (!pickle_iterator.ReadInt(&request_id)) {
-    NOTREACHED() << "malformed resource message";
-    return true;
-  }
-  // Dispatch the message on the request id specific task runner, if there is
-  // one, or on the general main_thread_task_runner if there isn't.
-  RequestIdToTaskRunnerMap::const_iterator iter =
-      request_id_to_task_runner_map_.find(request_id);
-  scoped_refptr<base::SingleThreadTaskRunner> task_runner;
-  if (iter != request_id_to_task_runner_map_.end()) {
-    task_runner = iter->second;
-  } else {
-    task_runner = main_thread_task_runner_;
-  }
-  task_runner->PostTask(
-      FROM_HERE, base::BindOnce(&ResourceSchedulingFilter::DispatchMessage,
-                                weak_ptr_factory_.GetWeakPtr(), message));
-  return true;
-}
-
-void ResourceSchedulingFilter::SetRequestIdTaskRunner(
-    int id,
-    const scoped_refptr<base::SingleThreadTaskRunner>& task_runner) {
-  base::AutoLock lock(request_id_to_task_runner_map_lock_);
-  request_id_to_task_runner_map_.insert(std::make_pair(id, task_runner));
-}
-
-void ResourceSchedulingFilter::ClearRequestIdTaskRunner(int id) {
-  base::AutoLock lock(request_id_to_task_runner_map_lock_);
-  request_id_to_task_runner_map_.erase(id);
-}
-
-bool ResourceSchedulingFilter::GetSupportedMessageClasses(
-    std::vector<uint32_t>* supported_message_classes) const {
-  supported_message_classes->push_back(ResourceMsgStart);
-  return true;
-}
-
-void ResourceSchedulingFilter::DispatchMessage(const IPC::Message& message) {
-  if (resource_dispatcher_)
-    resource_dispatcher_->OnMessageReceived(message);
-}
-
-}  // namespace content
diff --git a/content/renderer/loader/resource_scheduling_filter.h b/content/renderer/loader/resource_scheduling_filter.h
deleted file mode 100644
index 63233b1..0000000
--- a/content/renderer/loader/resource_scheduling_filter.h
+++ /dev/null
@@ -1,67 +0,0 @@
-// Copyright (c) 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CONTENT_RENDERER_LOADER_RESOURCE_SCHEDULING_FILTER_H_
-#define CONTENT_RENDERER_LOADER_RESOURCE_SCHEDULING_FILTER_H_
-
-#include <stdint.h>
-
-#include <map>
-#include <memory>
-
-#include "base/containers/hash_tables.h"
-#include "base/macros.h"
-#include "base/memory/weak_ptr.h"
-#include "base/single_thread_task_runner.h"
-#include "content/common/content_export.h"
-#include "ipc/message_filter.h"
-
-namespace content {
-class ResourceDispatcher;
-
-// This filter is used to dispatch resource messages on a specific
-// SingleThreadTaskRunner to facilitate task scheduling.
-class CONTENT_EXPORT ResourceSchedulingFilter : public IPC::MessageFilter {
- public:
-  ResourceSchedulingFilter(const scoped_refptr<base::SingleThreadTaskRunner>&
-                               main_thread_task_runner,
-                           ResourceDispatcher* resource_dispatcher);
-
-  // IPC::MessageFilter overrides:
-  bool OnMessageReceived(const IPC::Message& message) override;
-
-  bool GetSupportedMessageClasses(
-      std::vector<uint32_t>* supported_message_classes) const override;
-
-  // Sets the task runner associated with request messages with |id|.
-  void SetRequestIdTaskRunner(
-      int id,
-      const scoped_refptr<base::SingleThreadTaskRunner>& task_runner);
-
-  // Removes the task runner associated with |id|.
-  void ClearRequestIdTaskRunner(int id);
-
-  void DispatchMessage(const IPC::Message& message);
-
- private:
-  ~ResourceSchedulingFilter() override;
-
-  using RequestIdToTaskRunnerMap =
-      std::map<int, scoped_refptr<base::SingleThreadTaskRunner>>;
-
-  // This lock guards |request_id_to_task_runner_map_|
-  base::Lock request_id_to_task_runner_map_lock_;
-  RequestIdToTaskRunnerMap request_id_to_task_runner_map_;
-
-  scoped_refptr<base::SingleThreadTaskRunner> main_thread_task_runner_;
-  base::WeakPtr<ResourceDispatcher> resource_dispatcher_;
-  base::WeakPtrFactory<ResourceSchedulingFilter> weak_ptr_factory_;
-
- private:
-  DISALLOW_COPY_AND_ASSIGN(ResourceSchedulingFilter);
-};
-
-}  // namespace content
-
-#endif  // CONTENT_RENDERER_LOADER_RESOURCE_SCHEDULING_FILTER_H_
diff --git a/content/renderer/loader/shared_memory_received_data_factory.cc b/content/renderer/loader/shared_memory_received_data_factory.cc
deleted file mode 100644
index b9530d50a..0000000
--- a/content/renderer/loader/shared_memory_received_data_factory.cc
+++ /dev/null
@@ -1,126 +0,0 @@
-// Copyright 2015 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "content/renderer/loader/shared_memory_received_data_factory.h"
-
-#include <algorithm>
-
-#include "base/macros.h"
-#include "base/memory/ptr_util.h"
-#include "content/common/resource_messages.h"
-#include "ipc/ipc_sender.h"
-
-namespace content {
-
-class SharedMemoryReceivedDataFactory::SharedMemoryReceivedData final
-    : public RequestPeer::ReceivedData {
- public:
-  SharedMemoryReceivedData(
-      const char* payload,
-      int length,
-      scoped_refptr<SharedMemoryReceivedDataFactory> factory,
-      SharedMemoryReceivedDataFactory::TicketId id)
-      : payload_(payload),
-        length_(length),
-        factory_(factory),
-        id_(id) {}
-
-  ~SharedMemoryReceivedData() override { factory_->Reclaim(id_); }
-
-  const char* payload() const override { return payload_; }
-  int length() const override { return length_; }
-
- private:
-  const char* const payload_;
-  const int length_;
-
-  scoped_refptr<SharedMemoryReceivedDataFactory> factory_;
-  SharedMemoryReceivedDataFactory::TicketId id_;
-
-  DISALLOW_COPY_AND_ASSIGN(SharedMemoryReceivedData);
-};
-
-SharedMemoryReceivedDataFactory::SharedMemoryReceivedDataFactory(
-    IPC::Sender* message_sender,
-    int request_id,
-    linked_ptr<base::SharedMemory> memory)
-    : id_(0),
-      oldest_(0),
-      message_sender_(message_sender),
-      request_id_(request_id),
-      is_stopped_(false),
-      memory_(memory) {
-}
-
-SharedMemoryReceivedDataFactory::~SharedMemoryReceivedDataFactory() {
-  if (!is_stopped_)
-    SendAck(released_tickets_.size());
-}
-
-std::unique_ptr<RequestPeer::ReceivedData>
-SharedMemoryReceivedDataFactory::Create(int offset, int length) {
-  const char* start = static_cast<char*>(memory_->memory());
-  const char* payload = start + offset;
-  TicketId id = id_++;
-
-  return std::make_unique<SharedMemoryReceivedData>(payload, length, this, id);
-}
-
-void SharedMemoryReceivedDataFactory::Stop() {
-  is_stopped_ = true;
-  released_tickets_.clear();
-  message_sender_ = nullptr;
-}
-
-class SharedMemoryReceivedDataFactory::TicketComparator final {
- public:
-  explicit TicketComparator(TicketId oldest) : oldest_(oldest) {}
-  bool operator()(TicketId x, TicketId y) const {
-    if ((oldest_ <= x) == (oldest_ <= y))
-      return x <= y;
-
-    return (oldest_ <= x);
-  }
-
- private:
-  TicketId oldest_;
-};
-
-void SharedMemoryReceivedDataFactory::Reclaim(TicketId id) {
-  if (is_stopped_)
-    return;
-  if (oldest_ != id) {
-    released_tickets_.push_back(id);
-    return;
-  }
-
-  ++oldest_;
-  SendAck(1);
-  if (released_tickets_.empty()) {
-    // Fast path: (hopefully) the most typical case.
-    return;
-  }
-  std::sort(released_tickets_.begin(), released_tickets_.end(),
-            TicketComparator(oldest_));
-  size_t count = 0;
-  for (size_t i = 0;; ++i) {
-    if (i == released_tickets_.size() ||
-        released_tickets_[i] != static_cast<TicketId>(id + i + 1)) {
-      count = i;
-      break;
-    }
-  }
-  released_tickets_.erase(released_tickets_.begin(),
-                          released_tickets_.begin() + count);
-  oldest_ += count;
-  SendAck(count);
-}
-
-void SharedMemoryReceivedDataFactory::SendAck(size_t count) {
-  for (size_t i = 0; i < count; ++i) {
-    message_sender_->Send(new ResourceHostMsg_DataReceived_ACK(request_id_));
-  }
-}
-
-}  // namespace content
diff --git a/content/renderer/loader/shared_memory_received_data_factory.h b/content/renderer/loader/shared_memory_received_data_factory.h
deleted file mode 100644
index 72018cb7..0000000
--- a/content/renderer/loader/shared_memory_received_data_factory.h
+++ /dev/null
@@ -1,69 +0,0 @@
-// Copyright 2015 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CONTENT_RENDERER_LOADER_SHARED_MEMORY_RECEIVED_DATA_FACTORY_H_
-#define CONTENT_RENDERER_LOADER_SHARED_MEMORY_RECEIVED_DATA_FACTORY_H_
-
-#include <stddef.h>
-#include <stdint.h>
-
-#include <memory>
-#include <vector>
-
-#include "base/macros.h"
-#include "base/memory/linked_ptr.h"
-#include "base/memory/ref_counted.h"
-#include "base/memory/shared_memory.h"
-#include "content/common/content_export.h"
-#include "content/public/renderer/request_peer.h"
-
-namespace IPC {
-class Sender;
-}  // namespace IPC
-
-namespace content {
-
-class CONTENT_EXPORT SharedMemoryReceivedDataFactory final
-    : public base::RefCounted<SharedMemoryReceivedDataFactory> {
- public:
-  SharedMemoryReceivedDataFactory(IPC::Sender* message_sender,
-                                  int request_id,
-                                  linked_ptr<base::SharedMemory> memory);
-
-  std::unique_ptr<RequestPeer::ReceivedData> Create(int offset, int length);
-
-  // Stops this factory. After calling this function, releasing issued data
-  // won't send ack signal to the browser process.
-  void Stop();
-
- private:
-  // Here TicketId is uint32_t, but a factory may issue more data by reusing id.
-  using TicketId = uint32_t;
-
-  class SharedMemoryReceivedData;
-  // Called by SharedMemoryReceivedData.
-  void Reclaim(TicketId id);
-
-  class TicketComparator;
-  friend class base::RefCounted<SharedMemoryReceivedDataFactory>;
-  ~SharedMemoryReceivedDataFactory();
-
-  void SendAck(size_t count);
-
-  TicketId id_;
-  TicketId oldest_;
-  std::vector<TicketId> released_tickets_;
-  // We assume that |message_sender_| is valid until |Stop| is called.
-  IPC::Sender* message_sender_;
-  int request_id_;
-  bool is_stopped_;
-  // Just to keep the payload alive while issued data is alive.
-  linked_ptr<base::SharedMemory> memory_;
-
-  DISALLOW_COPY_AND_ASSIGN(SharedMemoryReceivedDataFactory);
-};
-
-}  // namespace content
-
-#endif  // CONTENT_RENDERER_LOADER_SHARED_MEMORY_RECEIVED_DATA_FACTORY_H_
diff --git a/content/renderer/loader/shared_memory_received_data_factory_unittest.cc b/content/renderer/loader/shared_memory_received_data_factory_unittest.cc
deleted file mode 100644
index 8957d3ff..0000000
--- a/content/renderer/loader/shared_memory_received_data_factory_unittest.cc
+++ /dev/null
@@ -1,225 +0,0 @@
-// Copyright 2015 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "content/renderer/loader/shared_memory_received_data_factory.h"
-
-#include <stddef.h>
-#include <tuple>
-
-#include "content/common/resource_messages.h"
-#include "ipc/ipc_message.h"
-#include "ipc/ipc_sender.h"
-#include "testing/gmock/include/gmock/gmock.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace content {
-
-namespace {
-
-using ::testing::_;
-using ::testing::InSequence;
-using ::testing::MockFunction;
-using ::testing::Return;
-using ::testing::StrictMock;
-
-using Checkpoint = StrictMock<MockFunction<void(int)>>;
-using ReceivedData = RequestPeer::ReceivedData;
-
-class MockSender : public IPC::Sender {
- public:
-  bool Send(IPC::Message* message) override {
-    bool result = false;
-    if (message->type() == ResourceHostMsg_DataReceived_ACK::ID) {
-      std::tuple<int> args;
-      ResourceHostMsg_DataReceived_ACK::Read(message, &args);
-      result = SendAck(std::get<0>(args));
-    } else {
-      result = SendOtherwise(message);
-    }
-    delete message;
-    return result;
-  }
-  MOCK_METHOD1(SendAck, bool(int));
-  MOCK_METHOD1(SendOtherwise, bool(IPC::Message*));
-};
-
-class SharedMemoryReceivedDataFactoryTest : public ::testing::Test {
- protected:
-  void SetUp() override {
-    sender_.reset(new StrictMock<MockSender>);
-    request_id_ = 0xdeadbeaf;
-    memory_.reset(new base::SharedMemory);
-    factory_ = base::MakeRefCounted<SharedMemoryReceivedDataFactory>(
-        sender_.get(), request_id_, memory_);
-    ASSERT_TRUE(memory_->CreateAndMapAnonymous(memory_size));
-
-    ON_CALL(*sender_, SendAck(_)).WillByDefault(Return(true));
-    ON_CALL(*sender_, SendOtherwise(_)).WillByDefault(Return(true));
-  }
-
-  static const size_t memory_size = 4 * 1024;
-  std::unique_ptr<MockSender> sender_;
-  int request_id_;
-  linked_ptr<base::SharedMemory> memory_;
-  scoped_refptr<SharedMemoryReceivedDataFactory> factory_;
-};
-
-TEST_F(SharedMemoryReceivedDataFactoryTest, Create) {
-  Checkpoint checkpoint;
-  InSequence s;
-  EXPECT_CALL(checkpoint, Call(0));
-  EXPECT_CALL(*sender_, SendAck(request_id_));
-  EXPECT_CALL(checkpoint, Call(1));
-
-  std::unique_ptr<ReceivedData> data = factory_->Create(12, 34);
-  const char* memory_start = static_cast<const char*>(memory_->memory());
-
-  ASSERT_TRUE(data);
-  EXPECT_EQ(memory_start + 12, data->payload());
-  EXPECT_EQ(34, data->length());
-
-  checkpoint.Call(0);
-  data.reset();
-  checkpoint.Call(1);
-}
-
-TEST_F(SharedMemoryReceivedDataFactoryTest, CreateMultiple) {
-  Checkpoint checkpoint;
-  InSequence s;
-  EXPECT_CALL(checkpoint, Call(0));
-  EXPECT_CALL(*sender_, SendAck(request_id_));
-  EXPECT_CALL(checkpoint, Call(1));
-  EXPECT_CALL(*sender_, SendAck(request_id_));
-  EXPECT_CALL(checkpoint, Call(2));
-  EXPECT_CALL(*sender_, SendAck(request_id_));
-  EXPECT_CALL(checkpoint, Call(3));
-
-  std::unique_ptr<ReceivedData> data1 = factory_->Create(0, 1);
-  std::unique_ptr<ReceivedData> data2 = factory_->Create(1, 1);
-  std::unique_ptr<ReceivedData> data3 = factory_->Create(2, 1);
-
-  EXPECT_TRUE(data1);
-  EXPECT_TRUE(data2);
-  EXPECT_TRUE(data3);
-
-  checkpoint.Call(0);
-  data1.reset();
-  checkpoint.Call(1);
-  data2.reset();
-  checkpoint.Call(2);
-  data3.reset();
-  checkpoint.Call(3);
-}
-
-TEST_F(SharedMemoryReceivedDataFactoryTest, ReclaimOutOfOrder) {
-  Checkpoint checkpoint;
-  InSequence s;
-  EXPECT_CALL(checkpoint, Call(0));
-  EXPECT_CALL(checkpoint, Call(1));
-  EXPECT_CALL(checkpoint, Call(2));
-  EXPECT_CALL(*sender_, SendAck(request_id_));
-  EXPECT_CALL(*sender_, SendAck(request_id_));
-  EXPECT_CALL(*sender_, SendAck(request_id_));
-  EXPECT_CALL(checkpoint, Call(3));
-
-  std::unique_ptr<ReceivedData> data1 = factory_->Create(0, 1);
-  std::unique_ptr<ReceivedData> data2 = factory_->Create(1, 1);
-  std::unique_ptr<ReceivedData> data3 = factory_->Create(2, 1);
-
-  EXPECT_TRUE(data1);
-  EXPECT_TRUE(data2);
-  EXPECT_TRUE(data3);
-
-  checkpoint.Call(0);
-  data3.reset();
-  checkpoint.Call(1);
-  data2.reset();
-  checkpoint.Call(2);
-  data1.reset();
-  checkpoint.Call(3);
-}
-
-TEST_F(SharedMemoryReceivedDataFactoryTest, ReclaimOutOfOrderPartially) {
-  Checkpoint checkpoint;
-  InSequence s;
-  EXPECT_CALL(checkpoint, Call(0));
-  EXPECT_CALL(checkpoint, Call(1));
-  EXPECT_CALL(*sender_, SendAck(request_id_));
-  EXPECT_CALL(*sender_, SendAck(request_id_));
-  EXPECT_CALL(*sender_, SendAck(request_id_));
-  EXPECT_CALL(checkpoint, Call(2));
-  EXPECT_CALL(checkpoint, Call(3));
-  EXPECT_CALL(*sender_, SendAck(request_id_));
-  EXPECT_CALL(*sender_, SendAck(request_id_));
-  EXPECT_CALL(*sender_, SendAck(request_id_));
-  EXPECT_CALL(checkpoint, Call(4));
-
-  std::unique_ptr<ReceivedData> data1 = factory_->Create(0, 1);
-  std::unique_ptr<ReceivedData> data2 = factory_->Create(1, 1);
-  std::unique_ptr<ReceivedData> data3 = factory_->Create(2, 1);
-  std::unique_ptr<ReceivedData> data4 = factory_->Create(3, 1);
-  std::unique_ptr<ReceivedData> data5 = factory_->Create(4, 1);
-  std::unique_ptr<ReceivedData> data6 = factory_->Create(5, 1);
-
-  EXPECT_TRUE(data1);
-  EXPECT_TRUE(data2);
-  EXPECT_TRUE(data3);
-  EXPECT_TRUE(data4);
-  EXPECT_TRUE(data5);
-  EXPECT_TRUE(data6);
-
-  checkpoint.Call(0);
-  data3.reset();
-  data6.reset();
-  data2.reset();
-  checkpoint.Call(1);
-  data1.reset();
-  checkpoint.Call(2);
-  data5.reset();
-  checkpoint.Call(3);
-  data4.reset();
-  checkpoint.Call(4);
-}
-
-TEST_F(SharedMemoryReceivedDataFactoryTest, Stop) {
-  Checkpoint checkpoint;
-  InSequence s;
-  EXPECT_CALL(checkpoint, Call(0));
-  EXPECT_CALL(checkpoint, Call(1));
-  EXPECT_CALL(*sender_, SendAck(request_id_));
-  EXPECT_CALL(*sender_, SendAck(request_id_));
-  EXPECT_CALL(*sender_, SendAck(request_id_));
-  EXPECT_CALL(checkpoint, Call(2));
-  EXPECT_CALL(checkpoint, Call(3));
-
-  std::unique_ptr<ReceivedData> data1 = factory_->Create(0, 1);
-  std::unique_ptr<ReceivedData> data2 = factory_->Create(1, 1);
-  std::unique_ptr<ReceivedData> data3 = factory_->Create(2, 1);
-  std::unique_ptr<ReceivedData> data4 = factory_->Create(3, 1);
-  std::unique_ptr<ReceivedData> data5 = factory_->Create(4, 1);
-  std::unique_ptr<ReceivedData> data6 = factory_->Create(5, 1);
-
-  EXPECT_TRUE(data1);
-  EXPECT_TRUE(data2);
-  EXPECT_TRUE(data3);
-  EXPECT_TRUE(data4);
-  EXPECT_TRUE(data5);
-  EXPECT_TRUE(data6);
-
-  checkpoint.Call(0);
-  data3.reset();
-  data6.reset();
-  data2.reset();
-  checkpoint.Call(1);
-  data1.reset();
-  checkpoint.Call(2);
-  factory_->Stop();
-  data5.reset();
-  data4.reset();
-  checkpoint.Call(3);
-}
-
-}  // namespace
-
-}  // namespace content
diff --git a/content/renderer/loader/sync_load_context.cc b/content/renderer/loader/sync_load_context.cc
index 898e358d..7fa320b 100644
--- a/content/renderer/loader/sync_load_context.cc
+++ b/content/renderer/loader/sync_load_context.cc
@@ -32,7 +32,6 @@
   context->request_id_ = context->resource_dispatcher_->StartAsync(
       std::move(request), routing_id, nullptr, frame_origin, traffic_annotation,
       true /* is_sync */, base::WrapUnique(context),
-      blink::WebURLRequest::LoadingIPCType::kMojo,
       context->url_loader_factory_.get(), std::move(throttles),
       mojom::URLLoaderClientEndpointsPtr());
 }
@@ -46,8 +45,8 @@
   url_loader_factory_.Bind(std::move(url_loader_factory));
 
   // Constructs a new ResourceDispatcher specifically for this request.
-  resource_dispatcher_ = std::make_unique<ResourceDispatcher>(
-      nullptr, base::ThreadTaskRunnerHandle::Get());
+  resource_dispatcher_ =
+      std::make_unique<ResourceDispatcher>(base::ThreadTaskRunnerHandle::Get());
 
   // Initialize the final URL with the original request URL. It will be
   // overwritten on redirects.
diff --git a/content/renderer/loader/url_loader_client_impl.cc b/content/renderer/loader/url_loader_client_impl.cc
index 5d756db..87059b5 100644
--- a/content/renderer/loader/url_loader_client_impl.cc
+++ b/content/renderer/loader/url_loader_client_impl.cc
@@ -8,7 +8,6 @@
 
 #include "base/callback.h"
 #include "base/single_thread_task_runner.h"
-#include "content/common/resource_messages.h"
 #include "content/renderer/loader/resource_dispatcher.h"
 #include "content/renderer/loader/url_response_body_consumer.h"
 #include "net/url_request/redirect_info.h"
@@ -144,10 +143,15 @@
 
 void URLLoaderClientImpl::UnsetDefersLoading() {
   is_deferred_ = false;
+
+  task_runner_->PostTask(
+      FROM_HERE, base::BindOnce(&URLLoaderClientImpl::FlushDeferredMessages,
+                                weak_factory_.GetWeakPtr()));
 }
 
 void URLLoaderClientImpl::FlushDeferredMessages() {
-  DCHECK(!is_deferred_);
+  if (is_deferred_)
+    return;
   std::vector<std::unique_ptr<DeferredMessage>> messages;
   messages.swap(deferred_messages_);
   bool has_completion_message = false;
diff --git a/content/renderer/loader/url_loader_client_impl_unittest.cc b/content/renderer/loader/url_loader_client_impl_unittest.cc
index 9bb5741..4438d9c9 100644
--- a/content/renderer/loader/url_loader_client_impl_unittest.cc
+++ b/content/renderer/loader/url_loader_client_impl_unittest.cc
@@ -11,7 +11,6 @@
 #include "content/public/common/url_loader_factory.mojom.h"
 #include "content/renderer/loader/resource_dispatcher.h"
 #include "content/renderer/loader/test_request_peer.h"
-#include "ipc/ipc_sender.h"
 #include "mojo/public/cpp/bindings/binding.h"
 #include "mojo/public/cpp/bindings/interface_ptr.h"
 #include "net/traffic_annotation/network_traffic_annotation_test_helper.h"
@@ -21,11 +20,10 @@
 namespace content {
 
 class URLLoaderClientImplTest : public ::testing::Test,
-                                IPC::Sender,
                                 mojom::URLLoaderFactory {
  protected:
   URLLoaderClientImplTest()
-      : dispatcher_(new ResourceDispatcher(this, message_loop_.task_runner())),
+      : dispatcher_(new ResourceDispatcher(message_loop_.task_runner())),
         mojo_binding_(this) {
     mojo_binding_.Bind(mojo::MakeRequest(&url_loader_factory_proxy_));
 
@@ -34,7 +32,6 @@
         TRAFFIC_ANNOTATION_FOR_TESTS, false,
         std::make_unique<TestRequestPeer>(dispatcher_.get(),
                                           &request_peer_context_),
-        blink::WebURLRequest::LoadingIPCType::kMojo,
         url_loader_factory_proxy_.get(),
         std::vector<std::unique_ptr<URLLoaderThrottle>>(),
         mojom::URLLoaderClientEndpointsPtr());
@@ -49,11 +46,6 @@
     url_loader_factory_proxy_ = nullptr;
   }
 
-  bool Send(IPC::Message* message) override {
-    ADD_FAILURE() << "IPC::Sender::Send should not be called.";
-    return false;
-  }
-
   void CreateLoaderAndStart(mojom::URLLoaderRequest request,
                             int32_t routing_id,
                             int32_t request_id,
@@ -518,4 +510,42 @@
   EXPECT_FALSE(request_peer_context_.cancelled);
 }
 
+TEST_F(URLLoaderClientImplTest, CancelOnReceiveDataWhileFlushing) {
+  request_peer_context_.cancel_on_receive_data = true;
+  dispatcher_->SetDefersLoading(request_id_, true);
+
+  ResourceResponseHead response_head;
+  network::URLLoaderCompletionStatus status;
+
+  mojo::DataPipe data_pipe(DataPipeOptions());
+  uint32_t size = 5;
+  MojoResult result = data_pipe.producer_handle->WriteData(
+      "hello", &size, MOJO_WRITE_DATA_FLAG_NONE);
+  ASSERT_EQ(MOJO_RESULT_OK, result);
+  EXPECT_EQ(5u, size);
+
+  url_loader_client_->OnReceiveResponse(response_head, base::nullopt, nullptr);
+  url_loader_client_->OnStartLoadingResponseBody(
+      std::move(data_pipe.consumer_handle));
+  url_loader_client_->OnComplete(status);
+
+  base::RunLoop().RunUntilIdle();
+  EXPECT_FALSE(request_peer_context_.received_response);
+  EXPECT_EQ("", request_peer_context_.data);
+  EXPECT_FALSE(request_peer_context_.complete);
+  EXPECT_FALSE(request_peer_context_.cancelled);
+
+  dispatcher_->SetDefersLoading(request_id_, false);
+  EXPECT_FALSE(request_peer_context_.received_response);
+  EXPECT_EQ("", request_peer_context_.data);
+  EXPECT_FALSE(request_peer_context_.complete);
+  EXPECT_FALSE(request_peer_context_.cancelled);
+
+  base::RunLoop().RunUntilIdle();
+  EXPECT_TRUE(request_peer_context_.received_response);
+  EXPECT_EQ("hello", request_peer_context_.data);
+  EXPECT_FALSE(request_peer_context_.complete);
+  EXPECT_TRUE(request_peer_context_.cancelled);
+}
+
 }  // namespace content
diff --git a/content/renderer/loader/url_response_body_consumer.cc b/content/renderer/loader/url_response_body_consumer.cc
index 0ffa014..0379b99 100644
--- a/content/renderer/loader/url_response_body_consumer.cc
+++ b/content/renderer/loader/url_response_body_consumer.cc
@@ -8,7 +8,6 @@
 #include "base/bind.h"
 #include "base/macros.h"
 #include "base/memory/ptr_util.h"
-#include "content/common/resource_messages.h"
 #include "content/public/renderer/request_peer.h"
 #include "content/renderer/loader/resource_dispatcher.h"
 #include "content/renderer/loader/site_isolation_stats_gatherer.h"
diff --git a/content/renderer/loader/url_response_body_consumer_unittest.cc b/content/renderer/loader/url_response_body_consumer_unittest.cc
index 6d699d5..6db7348 100644
--- a/content/renderer/loader/url_response_body_consumer_unittest.cc
+++ b/content/renderer/loader/url_response_body_consumer_unittest.cc
@@ -11,7 +11,6 @@
 #include "base/message_loop/message_loop.h"
 #include "base/run_loop.h"
 #include "base/single_thread_task_runner.h"
-#include "content/common/resource_messages.h"
 #include "content/public/common/resource_request.h"
 #include "content/public/common/service_worker_modes.h"
 #include "content/public/renderer/request_peer.h"
@@ -88,23 +87,38 @@
   DISALLOW_COPY_AND_ASSIGN(TestRequestPeer);
 };
 
-class URLResponseBodyConsumerTest : public ::testing::Test,
-                                    public ::IPC::Sender {
+class URLResponseBodyConsumerTest : public ::testing::Test {
  protected:
+  // A URLResponseBodyConsumer needs an associated PendingRequestInfo, and
+  // we need a URLLoaderFactory to create a PendingRequestInfo. We don't need
+  // a true URLLoaderFactory, so here we define a no-op (other than keeping
+  // clients to avoid connection error notifications) factory.
+  class NoopURLLoaderFactory final : public mojom::URLLoaderFactory {
+   public:
+    void CreateLoaderAndStart(mojom::URLLoaderRequest request,
+                              int32_t routing_id,
+                              int32_t request_id,
+                              uint32_t options,
+                              const ResourceRequest& url_request,
+                              mojom::URLLoaderClientPtr client,
+                              const net::MutableNetworkTrafficAnnotationTag&
+                                  traffic_annotation) override {
+      clients_.push_back(std::move(client));
+    }
+
+    void Clone(mojom::URLLoaderFactoryRequest request) override {}
+
+    std::vector<mojom::URLLoaderClientPtr> clients_;
+  };
+
   URLResponseBodyConsumerTest()
-      : dispatcher_(new ResourceDispatcher(this, message_loop_.task_runner())) {
-  }
+      : dispatcher_(new ResourceDispatcher(message_loop_.task_runner())) {}
 
   ~URLResponseBodyConsumerTest() override {
     dispatcher_.reset();
     base::RunLoop().RunUntilIdle();
   }
 
-  bool Send(IPC::Message* message) override {
-    delete message;
-    return true;
-  }
-
   std::unique_ptr<ResourceRequest> CreateResourceRequest() {
     std::unique_ptr<ResourceRequest> request(new ResourceRequest);
 
@@ -137,8 +151,7 @@
         std::move(request), 0, nullptr, url::Origin(),
         TRAFFIC_ANNOTATION_FOR_TESTS, false,
         std::make_unique<TestRequestPeer>(context, message_loop_.task_runner()),
-        blink::WebURLRequest::LoadingIPCType::kChromeIPC, nullptr,
-        std::vector<std::unique_ptr<URLLoaderThrottle>>(),
+        &factory_, std::vector<std::unique_ptr<URLLoaderThrottle>>(),
         mojom::URLLoaderClientEndpointsPtr());
   }
 
@@ -149,6 +162,7 @@
   }
 
   base::MessageLoop message_loop_;
+  NoopURLLoaderFactory factory_;
   std::unique_ptr<ResourceDispatcher> dispatcher_;
   static const MojoWriteDataFlags kNone = MOJO_WRITE_DATA_FLAG_NONE;
 };
diff --git a/content/renderer/loader/web_url_loader_impl.cc b/content/renderer/loader/web_url_loader_impl.cc
index 39994db..9be05695 100644
--- a/content/renderer/loader/web_url_loader_impl.cc
+++ b/content/renderer/loader/web_url_loader_impl.cc
@@ -26,7 +26,6 @@
 #include "build/build_config.h"
 #include "content/child/child_thread_impl.h"
 #include "content/child/scoped_child_process_reference.h"
-#include "content/common/resource_messages.h"
 #include "content/common/service_worker/service_worker_types.h"
 #include "content/public/common/browser_side_navigation_policy.h"
 #include "content/public/common/content_features.h"
@@ -693,7 +692,7 @@
     resource_dispatcher_->StartSync(
         std::move(resource_request), request.RequestorID(),
         extra_data->frame_origin(), GetTrafficAnnotationTag(request),
-        sync_load_response, request.GetLoadingIPCType(), url_loader_factory_,
+        sync_load_response, url_loader_factory_,
         extra_data->TakeURLLoaderThrottles());
     return;
   }
@@ -705,8 +704,7 @@
       extra_data->frame_origin(), GetTrafficAnnotationTag(request),
       false /* is_sync */,
       std::make_unique<WebURLLoaderImpl::RequestPeerImpl>(this),
-      request.GetLoadingIPCType(), url_loader_factory_,
-      extra_data->TakeURLLoaderThrottles(),
+      url_loader_factory_, extra_data->TakeURLLoaderThrottles(),
       std::move(url_loader_client_endpoints));
 
   if (defers_loading_ != NOT_DEFERRING)
diff --git a/content/renderer/loader/web_url_loader_impl_unittest.cc b/content/renderer/loader/web_url_loader_impl_unittest.cc
index f59565e79..2c5cf15 100644
--- a/content/renderer/loader/web_url_loader_impl_unittest.cc
+++ b/content/renderer/loader/web_url_loader_impl_unittest.cc
@@ -63,11 +63,8 @@
 
 class TestResourceDispatcher : public ResourceDispatcher {
  public:
-  TestResourceDispatcher() :
-      ResourceDispatcher(nullptr, nullptr),
-      canceled_(false),
-      defers_loading_(false) {
-  }
+  TestResourceDispatcher()
+      : ResourceDispatcher(nullptr), canceled_(false), defers_loading_(false) {}
 
   ~TestResourceDispatcher() override {}
 
@@ -79,7 +76,6 @@
       const url::Origin& frame_origin,
       const net::NetworkTrafficAnnotationTag& traffic_annotation,
       SyncLoadResponse* response,
-      blink::WebURLRequest::LoadingIPCType ipc_type,
       mojom::URLLoaderFactory* url_loader_factory,
       std::vector<std::unique_ptr<URLLoaderThrottle>> throttles) override {
     *response = sync_load_response_;
@@ -93,7 +89,6 @@
       const net::NetworkTrafficAnnotationTag& traffic_annotation,
       bool is_sync,
       std::unique_ptr<RequestPeer> peer,
-      blink::WebURLRequest::LoadingIPCType ipc_type,
       mojom::URLLoaderFactory* url_loader_factory,
       std::vector<std::unique_ptr<URLLoaderThrottle>> throttles,
       mojom::URLLoaderClientEndpointsPtr url_loader_client_endpoints) override {
diff --git a/content/renderer/render_thread_impl.cc b/content/renderer/render_thread_impl.cc
index b0f96d14..186a82a0 100644
--- a/content/renderer/render_thread_impl.cc
+++ b/content/renderer/render_thread_impl.cc
@@ -68,7 +68,6 @@
 #include "content/common/frame_messages.h"
 #include "content/common/frame_owner_properties.h"
 #include "content/common/gpu_stream_constants.h"
-#include "content/common/resource_messages.h"
 #include "content/common/view_messages.h"
 #include "content/public/common/content_constants.h"
 #include "content/public/common/content_features.h"
@@ -102,9 +101,7 @@
 #include "content/renderer/input/input_event_filter.h"
 #include "content/renderer/input/input_handler_manager.h"
 #include "content/renderer/input/main_thread_input_event_filter.h"
-#include "content/renderer/loader/child_resource_message_filter.h"
 #include "content/renderer/loader/resource_dispatcher.h"
-#include "content/renderer/loader/resource_scheduling_filter.h"
 #include "content/renderer/mash_util.h"
 #include "content/renderer/media/audio_input_message_filter.h"
 #include "content/renderer/media/audio_message_filter.h"
@@ -124,7 +121,6 @@
 #include "content/renderer/render_process_impl.h"
 #include "content/renderer/render_view_impl.h"
 #include "content/renderer/renderer_blink_platform_impl.h"
-#include "content/renderer/scheduler/resource_dispatch_throttler.h"
 #include "content/renderer/service_worker/embedded_worker_instance_client_impl.h"
 #include "content/renderer/service_worker/service_worker_context_client.h"
 #include "content/renderer/service_worker/service_worker_context_message_filter.h"
@@ -244,16 +240,6 @@
 const int64_t kInitialIdleHandlerDelayMs = 1000;
 const int64_t kLongIdleHandlerDelayMs = 30 * 1000;
 
-#if defined(OS_ANDROID)
-// On Android, resource messages can each take ~1.5ms to dispatch on the browser
-// IO thread. Limiting the message rate to 3/frame at 60hz ensures that the
-// induced work takes but a fraction (~1/4) of the overall frame budget.
-const int kMaxResourceRequestsPerFlushWhenThrottled = 3;
-#else
-const int kMaxResourceRequestsPerFlushWhenThrottled = 8;
-#endif
-const double kThrottledResourceRequestFlushPeriodS = 1. / 60.;
-
 // Maximum allocation size allowed for image scaling filters that
 // require pre-scaling. Skia will fallback to a filter that doesn't
 // require pre-scaling if the default filter would require an
@@ -721,11 +707,8 @@
       new NotificationDispatcher(thread_safe_sender());
   AddFilter(notification_dispatcher_->GetFilter());
 
-  resource_dispatcher_.reset(new ResourceDispatcher(
-      this, message_loop()->task_runner()));
-  resource_message_filter_ =
-      new ChildResourceMessageFilter(resource_dispatcher_.get());
-  AddFilter(resource_message_filter_.get());
+  resource_dispatcher_.reset(
+      new ResourceDispatcher(message_loop()->task_runner()));
   quota_dispatcher_.reset(new QuotaDispatcher(message_loop()->task_runner()));
 
   auto registry = std::make_unique<service_manager::BinderRegistry>();
@@ -751,14 +734,6 @@
       new CacheStorageDispatcher(thread_safe_sender()));
   file_system_dispatcher_.reset(new FileSystemDispatcher());
 
-  // Note: This may reorder messages from the ResourceDispatcher with respect to
-  // other subsystems.
-  resource_dispatch_throttler_.reset(new ResourceDispatchThrottler(
-      static_cast<RenderThread*>(this), renderer_scheduler_.get(),
-      base::TimeDelta::FromSecondsD(kThrottledResourceRequestFlushPeriodS),
-      kMaxResourceRequestsPerFlushWhenThrottled));
-  resource_dispatcher_->set_message_sender(resource_dispatch_throttler_.get());
-
   blob_message_filter_ = new BlobMessageFilter(GetFileThreadTaskRunner());
   AddFilter(blob_message_filter_.get());
   vc_manager_.reset(new VideoCaptureImplManager());
@@ -1272,18 +1247,8 @@
   } else {
     resource_task_queue2 = renderer_scheduler_->LoadingTaskRunner();
   }
-  // Add a filter that forces resource messages to be dispatched via a
-  // particular task runner.
-  scoped_refptr<ResourceSchedulingFilter> filter(
-      new ResourceSchedulingFilter(
-          resource_task_queue2, resource_dispatcher_.get()));
-  channel()->AddFilter(filter.get());
-  resource_dispatcher_->SetResourceSchedulingFilter(filter);
-
-  // The ChildResourceMessageFilter and the ResourceDispatcher need to use the
-  // same queue to ensure tasks are executed in the expected order.
-  resource_message_filter_->SetMainThreadTaskRunner(
-      resource_task_queue2);
+  // The ResourceDispatcher needs to use the same queue to ensure tasks are
+  // executed in the expected order.
   resource_dispatcher_->SetThreadTaskRunner(resource_task_queue2);
 
   if (!command_line.HasSwitch(switches::kDisableThreadedCompositing))
@@ -1619,9 +1584,6 @@
 }
 
 bool RenderThreadImpl::OnMessageReceived(const IPC::Message& msg) {
-  // Resource responses are sent to the resource dispatcher.
-  if (resource_dispatcher_->OnMessageReceived(msg))
-    return true;
   if (file_system_dispatcher_->OnMessageReceived(msg))
     return true;
   return ChildThreadImpl::OnMessageReceived(msg);
diff --git a/content/renderer/render_thread_impl.h b/content/renderer/render_thread_impl.h
index 7ede741b..fb53ccc 100644
--- a/content/renderer/render_thread_impl.h
+++ b/content/renderer/render_thread_impl.h
@@ -134,7 +134,6 @@
 class BrowserPluginManager;
 class CacheStorageDispatcher;
 class CategorizedWorkerPool;
-class ChildResourceMessageFilter;
 class CompositorForwardingMessageFilter;
 class DomStorageDispatcher;
 class FileSystemDispatcher;
@@ -151,7 +150,6 @@
 class RenderThreadObserver;
 class RendererBlinkPlatformImpl;
 class ResourceDispatcher;
-class ResourceDispatchThrottler;
 class ServiceWorkerMessageFilter;
 class VideoCaptureImplManager;
 
@@ -647,7 +645,6 @@
   std::unique_ptr<blink::scheduler::RendererScheduler> renderer_scheduler_;
   std::unique_ptr<RendererBlinkPlatformImpl> blink_platform_impl_;
   std::unique_ptr<ResourceDispatcher> resource_dispatcher_;
-  std::unique_ptr<ResourceDispatchThrottler> resource_dispatch_throttler_;
   std::unique_ptr<CacheStorageDispatcher> main_thread_cache_storage_dispatcher_;
   std::unique_ptr<FileSystemDispatcher> file_system_dispatcher_;
   std::unique_ptr<QuotaDispatcher> quota_dispatcher_;
@@ -657,7 +654,6 @@
   scoped_refptr<AudioInputMessageFilter> audio_input_message_filter_;
   scoped_refptr<MidiMessageFilter> midi_message_filter_;
   scoped_refptr<ServiceWorkerMessageFilter> service_worker_message_filter_;
-  scoped_refptr<ChildResourceMessageFilter> resource_message_filter_;
 
   std::unique_ptr<BrowserPluginManager> browser_plugin_manager_;
 
diff --git a/content/renderer/render_thread_impl_browsertest.cc b/content/renderer/render_thread_impl_browsertest.cc
index 28957f2..1cb95d5 100644
--- a/content/renderer/render_thread_impl_browsertest.cc
+++ b/content/renderer/render_thread_impl_browsertest.cc
@@ -24,7 +24,6 @@
 #include "components/viz/common/resources/buffer_to_texture_target_map.h"
 #include "content/app/mojo/mojo_init.h"
 #include "content/common/in_process_child_thread_params.h"
-#include "content/common/resource_messages.h"
 #include "content/common/service_manager/child_connection.h"
 #include "content/public/browser/browser_thread.h"
 #include "content/public/browser/content_browser_client.h"
@@ -307,16 +306,6 @@
 
 // Disabled under LeakSanitizer due to memory leaks.
 TEST_F(RenderThreadImplBrowserTest,
-       WILL_LEAK(ResourceDispatchIPCTasksGoThroughScheduler)) {
-  sender()->Send(new ResourceHostMsg_FollowRedirect(0));
-  sender()->Send(new TestMsg_QuitRunLoop());
-
-  run_loop_->Run();
-  EXPECT_EQ(1, test_task_counter_->NumTasksPosted());
-}
-
-// Disabled under LeakSanitizer due to memory leaks.
-TEST_F(RenderThreadImplBrowserTest,
        WILL_LEAK(NonResourceDispatchIPCTasksDontGoThroughScheduler)) {
   // NOTE other than not being a resource message, the actual message is
   // unimportant.
diff --git a/content/renderer/scheduler/resource_dispatch_throttler.cc b/content/renderer/scheduler/resource_dispatch_throttler.cc
deleted file mode 100644
index 6eae599..0000000
--- a/content/renderer/scheduler/resource_dispatch_throttler.cc
+++ /dev/null
@@ -1,155 +0,0 @@
-// Copyright 2015 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "content/renderer/scheduler/resource_dispatch_throttler.h"
-
-#include "base/auto_reset.h"
-#include "base/containers/circular_deque.h"
-#include "base/trace_event/trace_event.h"
-#include "content/common/resource_messages.h"
-#include "ipc/ipc_message_macros.h"
-#include "third_party/WebKit/public/platform/scheduler/renderer/renderer_scheduler.h"
-
-namespace content {
-namespace {
-
-bool IsResourceRequest(const IPC::Message& msg) {
-  return msg.type() == ResourceHostMsg_RequestResource::ID;
-}
-
-}  // namespace
-
-ResourceDispatchThrottler::ResourceDispatchThrottler(
-    IPC::Sender* proxied_sender,
-    blink::scheduler::RendererScheduler* scheduler,
-    base::TimeDelta flush_period,
-    uint32_t max_requests_per_flush)
-    : proxied_sender_(proxied_sender),
-      scheduler_(scheduler),
-      flush_period_(flush_period),
-      max_requests_per_flush_(max_requests_per_flush),
-      flush_timer_(
-          FROM_HERE,
-          flush_period_,
-          base::Bind(&ResourceDispatchThrottler::Flush, base::Unretained(this)),
-          false /* is_repeating */),
-      sent_requests_since_last_flush_(0) {
-  DCHECK(proxied_sender);
-  DCHECK(scheduler);
-  DCHECK_NE(flush_period_, base::TimeDelta());
-  DCHECK(max_requests_per_flush_);
-  flush_timer_.SetTaskRunner(scheduler->LoadingTaskRunner());
-}
-
-ResourceDispatchThrottler::~ResourceDispatchThrottler() {
-  FlushAll();
-}
-
-bool ResourceDispatchThrottler::Send(IPC::Message* msg) {
-  DCHECK(thread_checker_.CalledOnValidThread());
-  if (msg->is_sync()) {
-    // Flush any pending requests, preserving dispatch order between async and
-    // sync requests.
-    FlushAll();
-    return ForwardMessage(msg);
-  }
-
-  // Always defer message forwarding if there are pending messages, ensuring
-  // message dispatch ordering consistency.
-  if (!throttled_messages_.empty()) {
-    TRACE_EVENT_INSTANT0("loader", "ResourceDispatchThrottler::ThrottleMessage",
-                         TRACE_EVENT_SCOPE_THREAD);
-    throttled_messages_.push_back(msg);
-    return true;
-  }
-
-  if (!IsResourceRequest(*msg))
-    return ForwardMessage(msg);
-
-  if (!scheduler_->IsHighPriorityWorkAnticipated()) {
-    // Treat an unthrottled request as a flush.
-    LogFlush();
-    return ForwardMessage(msg);
-  }
-
-  if (Now() > (last_flush_time_ + flush_period_)) {
-    // If sufficient time has passed since the previous flush, we can
-    // effectively mark the pipeline as flushed.
-    LogFlush();
-    return ForwardMessage(msg);
-  }
-
-  if (sent_requests_since_last_flush_ < max_requests_per_flush_)
-    return ForwardMessage(msg);
-
-  TRACE_EVENT_INSTANT0("loader", "ResourceDispatchThrottler::ThrottleRequest",
-                       TRACE_EVENT_SCOPE_THREAD);
-  throttled_messages_.push_back(msg);
-  ScheduleFlush();
-  return true;
-}
-
-base::TimeTicks ResourceDispatchThrottler::Now() const {
-  return base::TimeTicks::Now();
-}
-
-void ResourceDispatchThrottler::ScheduleFlush() {
-  DCHECK(!flush_timer_.IsRunning());
-  flush_timer_.Reset();
-}
-
-void ResourceDispatchThrottler::Flush() {
-  DCHECK(thread_checker_.CalledOnValidThread());
-  TRACE_EVENT1("loader", "ResourceDispatchThrottler::Flush",
-               "total_throttled_messages", throttled_messages_.size());
-  LogFlush();
-
-  // If high-priority work is no longer anticipated, dispatch can be safely
-  // accelerated. Avoid completely flushing in such case in the event that
-  // a large number of requests have been throttled.
-  uint32_t max_requests = scheduler_->IsHighPriorityWorkAnticipated()
-                              ? max_requests_per_flush_
-                              : max_requests_per_flush_ * 2;
-
-  while (!throttled_messages_.empty() &&
-         (sent_requests_since_last_flush_ < max_requests ||
-          !IsResourceRequest(*throttled_messages_.front()))) {
-    IPC::Message* msg = throttled_messages_.front();
-    throttled_messages_.pop_front();
-    ForwardMessage(msg);
-  }
-
-  if (!throttled_messages_.empty())
-    ScheduleFlush();
-}
-
-void ResourceDispatchThrottler::FlushAll() {
-  LogFlush();
-  if (throttled_messages_.empty())
-    return;
-
-  TRACE_EVENT1("loader", "ResourceDispatchThrottler::FlushAll",
-               "total_throttled_messages", throttled_messages_.size());
-  base::circular_deque<IPC::Message*> throttled_messages;
-  throttled_messages.swap(throttled_messages_);
-  for (auto* message : throttled_messages)
-    ForwardMessage(message);
-  // There shouldn't be re-entrancy issues when forwarding an IPC, but validate
-  // as a safeguard.
-  DCHECK(throttled_messages_.empty());
-}
-
-void ResourceDispatchThrottler::LogFlush() {
-  sent_requests_since_last_flush_ = 0;
-  last_flush_time_ = Now();
-}
-
-bool ResourceDispatchThrottler::ForwardMessage(IPC::Message* msg) {
-  if (IsResourceRequest(*msg))
-    ++sent_requests_since_last_flush_;
-
-  return proxied_sender_->Send(msg);
-}
-
-}  // namespace content
diff --git a/content/renderer/scheduler/resource_dispatch_throttler.h b/content/renderer/scheduler/resource_dispatch_throttler.h
deleted file mode 100644
index 6c4c933..0000000
--- a/content/renderer/scheduler/resource_dispatch_throttler.h
+++ /dev/null
@@ -1,77 +0,0 @@
-// Copyright 2015 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CONTENT_RENDERER_SCHEDULER_RESOURCE_DISPATCH_THROTTLER_H_
-#define CONTENT_RENDERER_SCHEDULER_RESOURCE_DISPATCH_THROTTLER_H_
-
-#include <stdint.h>
-
-#include "base/containers/circular_deque.h"
-#include "base/macros.h"
-#include "base/threading/thread_checker.h"
-#include "base/time/time.h"
-#include "base/timer/timer.h"
-#include "content/common/content_export.h"
-#include "ipc/ipc_sender.h"
-
-namespace blink {
-namespace scheduler {
-class RendererScheduler;
-}
-}
-
-namespace content {
-
-// Utility class for throttling a stream of resource requests targetted to a
-// specific IPC sender. The throttling itself is very basic:
-//  * When there is no high-priority work imminent to the main thread, as
-//    indicated by the RendererScheduler, throttling is disabled.
-//  * When >= N requests have been sent in a given time window, requests are
-//    throttled. A timer periodically flushes a portion of the queued requests
-//    until all such requests have been flushed.
-// TODO(jdduke): Remove this class after resource requests become sufficiently
-// cheap on the IO thread, crbug.com/440037.
-class CONTENT_EXPORT ResourceDispatchThrottler : public IPC::Sender {
- public:
-  // |flush_period| and |max_requests_per_flush| must be strictly positive
-  // in duration/value.
-  ResourceDispatchThrottler(IPC::Sender* proxied_sender,
-                            blink::scheduler::RendererScheduler* scheduler,
-                            base::TimeDelta flush_period,
-                            uint32_t max_requests_per_flush);
-  ~ResourceDispatchThrottler() override;
-
-  // IPC::Sender implementation:
-  bool Send(IPC::Message* msg) override;
-
- private:
-  friend class ResourceDispatchThrottlerForTest;
-
-  // Virtual for testing.
-  virtual base::TimeTicks Now() const;
-  virtual void ScheduleFlush();
-
-  void Flush();
-  void FlushAll();
-  void LogFlush();
-  bool ForwardMessage(IPC::Message* msg);
-
-  base::ThreadChecker thread_checker_;
-
-  IPC::Sender* const proxied_sender_;
-  blink::scheduler::RendererScheduler* const scheduler_;
-  const base::TimeDelta flush_period_;
-  const uint32_t max_requests_per_flush_;
-
-  base::Timer flush_timer_;
-  base::TimeTicks last_flush_time_;
-  uint32_t sent_requests_since_last_flush_;
-  base::circular_deque<IPC::Message*> throttled_messages_;
-
-  DISALLOW_COPY_AND_ASSIGN(ResourceDispatchThrottler);
-};
-
-}  // namespace content
-
-#endif  // CONTENT_RENDERER_SCHEDULER_RESOURCE_DISPATCH_THROTTLER_H_
diff --git a/content/renderer/scheduler/resource_dispatch_throttler_unittest.cc b/content/renderer/scheduler/resource_dispatch_throttler_unittest.cc
deleted file mode 100644
index f18bfb1..0000000
--- a/content/renderer/scheduler/resource_dispatch_throttler_unittest.cc
+++ /dev/null
@@ -1,424 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "content/renderer/scheduler/resource_dispatch_throttler.h"
-
-#include <stddef.h>
-#include <stdint.h>
-
-#include <memory>
-#include <vector>
-
-#include "base/macros.h"
-#include "base/memory/ptr_util.h"
-#include "content/common/resource_messages.h"
-#include "content/public/common/resource_request.h"
-#include "net/traffic_annotation/network_traffic_annotation_test_helper.h"
-#include "testing/gtest/include/gtest/gtest.h"
-#include "third_party/WebKit/public/platform/scheduler/test/fake_renderer_scheduler.h"
-
-namespace content {
-namespace {
-
-const uint32_t kRequestsPerFlush = 4;
-const double kFlushPeriodSeconds = 1.f / 60;
-const int kRoutingId = 1;
-
-typedef std::vector<std::unique_ptr<IPC::Message>> ScopedMessages;
-
-int GetRequestId(const IPC::Message& msg) {
-  int request_id = -1;
-  switch (msg.type()) {
-    case ResourceHostMsg_RequestResource::ID: {
-      base::PickleIterator iter(msg);
-      int routing_id = -1;
-      if (!iter.ReadInt(&routing_id) || !iter.ReadInt(&request_id))
-        NOTREACHED() << "Invalid id for resource request message.";
-    } break;
-
-    case ResourceHostMsg_DidChangePriority::ID:
-    case ResourceHostMsg_ReleaseDownloadedFile::ID:
-    case ResourceHostMsg_CancelRequest::ID:
-      if (!base::PickleIterator(msg).ReadInt(&request_id))
-        NOTREACHED() << "Invalid id for resource message.";
-      break;
-
-    default:
-      NOTREACHED() << "Invalid message for resource throttling.";
-      break;
-  }
-  return request_id;
-}
-
-class RendererSchedulerForTest
-    : public blink::scheduler::FakeRendererScheduler {
- public:
-  RendererSchedulerForTest() : high_priority_work_anticipated_(false) {}
-  ~RendererSchedulerForTest() override {}
-
-  // RendererScheduler implementation:
-  bool IsHighPriorityWorkAnticipated() override {
-    return high_priority_work_anticipated_;
-  }
-
-  void set_high_priority_work_anticipated(bool anticipated) {
-    high_priority_work_anticipated_ = anticipated;
-  }
-
- private:
-  bool high_priority_work_anticipated_;
-};
-
-}  // namespace
-
-class ResourceDispatchThrottlerForTest : public ResourceDispatchThrottler {
- public:
-  ResourceDispatchThrottlerForTest(
-      IPC::Sender* sender,
-      blink::scheduler::RendererScheduler* scheduler)
-      : ResourceDispatchThrottler(
-            sender,
-            scheduler,
-            base::TimeDelta::FromSecondsD(kFlushPeriodSeconds),
-            kRequestsPerFlush),
-        now_(base::TimeTicks() + base::TimeDelta::FromDays(1)),
-        flush_scheduled_(false) {}
-  ~ResourceDispatchThrottlerForTest() override {}
-
-  void Advance(base::TimeDelta delta) { now_ += delta; }
-
-  bool RunScheduledFlush() {
-    if (!flush_scheduled_)
-      return false;
-
-    flush_scheduled_ = false;
-    Flush();
-    return true;
-  }
-
-  bool flush_scheduled() const { return flush_scheduled_; }
-
- private:
-  // ResourceDispatchThrottler overrides:
-  base::TimeTicks Now() const override { return now_; }
-  void ScheduleFlush() override { flush_scheduled_ = true; }
-
-  base::TimeTicks now_;
-  bool flush_scheduled_;
-};
-
-class ResourceDispatchThrottlerTest : public testing::Test, public IPC::Sender {
- public:
-  ResourceDispatchThrottlerTest() : last_request_id_(0) {
-    throttler_.reset(new ResourceDispatchThrottlerForTest(this, &scheduler_));
-  }
-  ~ResourceDispatchThrottlerTest() override {}
-
-  // IPC::Sender implementation:
-  bool Send(IPC::Message* msg) override {
-    sent_messages_.push_back(base::WrapUnique(msg));
-    return true;
-  }
-
- protected:
-  void SetHighPriorityWorkAnticipated(bool anticipated) {
-    scheduler_.set_high_priority_work_anticipated(anticipated);
-  }
-
-  void Advance(base::TimeDelta delta) { throttler_->Advance(delta); }
-
-  bool RunScheduledFlush() { return throttler_->RunScheduledFlush(); }
-
-  bool FlushScheduled() { return throttler_->flush_scheduled(); }
-
-  bool RequestResource() {
-    ResourceRequest request;
-    request.download_to_file = true;
-    return throttler_->Send(new ResourceHostMsg_RequestResource(
-        kRoutingId, ++last_request_id_, request,
-        net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS)));
-  }
-
-  bool RequestResourceSync() {
-    SyncLoadResult result;
-    return throttler_->Send(new ResourceHostMsg_SyncLoad(
-        kRoutingId, ++last_request_id_, ResourceRequest(), &result));
-  }
-
-  void RequestResourcesUntilThrottled() {
-    SetHighPriorityWorkAnticipated(true);
-    GetAndResetSentMessageCount();
-    RequestResource();
-    while (GetAndResetSentMessageCount())
-      RequestResource();
-  }
-
-  bool UpdateRequestPriority(int request_id, net::RequestPriority priority) {
-    return throttler_->Send(
-        new ResourceHostMsg_DidChangePriority(request_id, priority, 0));
-  }
-
-  bool ReleaseDownloadedFile(int request_id) {
-    return throttler_->Send(
-        new ResourceHostMsg_ReleaseDownloadedFile(request_id));
-  }
-
-  bool CancelRequest(int request_id) {
-    return throttler_->Send(new ResourceHostMsg_CancelRequest(request_id));
-  }
-
-  size_t GetAndResetSentMessageCount() {
-    size_t sent_message_count = sent_messages_.size();
-    sent_messages_.clear();
-    return sent_message_count;
-  }
-
-  const IPC::Message* LastSentMessage() const {
-    return sent_messages_.empty() ? nullptr : sent_messages_.back().get();
-  }
-
-  int LastSentRequestId() const {
-    const IPC::Message* msg = LastSentMessage();
-    if (!msg)
-      return -1;
-
-    int routing_id = -1;
-    int request_id = -1;
-    base::PickleIterator iter(*msg);
-    CHECK(IPC::ReadParam(msg, &iter, &routing_id));
-    CHECK(IPC::ReadParam(msg, &iter, &request_id));
-    return request_id;
-  }
-
-  int last_request_id() const { return last_request_id_; }
-
-  ScopedMessages sent_messages_;
-
- private:
-  std::unique_ptr<ResourceDispatchThrottlerForTest> throttler_;
-  RendererSchedulerForTest scheduler_;
-  int last_request_id_;
-
-  DISALLOW_COPY_AND_ASSIGN(ResourceDispatchThrottlerTest);
-};
-
-TEST_F(ResourceDispatchThrottlerTest, NotThrottledByDefault) {
-  SetHighPriorityWorkAnticipated(false);
-  for (size_t i = 0; i < kRequestsPerFlush * 2; ++i) {
-    RequestResource();
-    EXPECT_EQ(i + 1, sent_messages_.size());
-  }
-}
-
-TEST_F(ResourceDispatchThrottlerTest, NotThrottledIfSendLimitNotReached) {
-  SetHighPriorityWorkAnticipated(true);
-  for (size_t i = 0; i < kRequestsPerFlush; ++i) {
-    RequestResource();
-    EXPECT_EQ(i + 1, sent_messages_.size());
-  }
-}
-
-TEST_F(ResourceDispatchThrottlerTest, ThrottledWhenHighPriorityWork) {
-  SetHighPriorityWorkAnticipated(true);
-  for (size_t i = 0; i < kRequestsPerFlush; ++i)
-    RequestResource();
-  ASSERT_EQ(kRequestsPerFlush, GetAndResetSentMessageCount());
-
-  RequestResource();
-  EXPECT_EQ(0U, sent_messages_.size());
-
-  EXPECT_TRUE(RunScheduledFlush());
-  EXPECT_EQ(1U, sent_messages_.size());
-}
-
-TEST_F(ResourceDispatchThrottlerTest,
-       ThrottledWhenDeferredMessageQueueNonEmpty) {
-  SetHighPriorityWorkAnticipated(true);
-  for (size_t i = 0; i < kRequestsPerFlush; ++i)
-    RequestResource();
-  ASSERT_EQ(kRequestsPerFlush, GetAndResetSentMessageCount());
-
-  RequestResource();
-  EXPECT_EQ(0U, sent_messages_.size());
-  SetHighPriorityWorkAnticipated(false);
-  RequestResource();
-  EXPECT_EQ(0U, sent_messages_.size());
-
-  EXPECT_TRUE(RunScheduledFlush());
-  EXPECT_EQ(2U, sent_messages_.size());
-}
-
-TEST_F(ResourceDispatchThrottlerTest, NotThrottledIfSufficientTimePassed) {
-  SetHighPriorityWorkAnticipated(true);
-
-  for (size_t i = 0; i < kRequestsPerFlush * 2; ++i) {
-    Advance(base::TimeDelta::FromSecondsD(kFlushPeriodSeconds * 2));
-    RequestResource();
-    EXPECT_EQ(1U, GetAndResetSentMessageCount());
-    EXPECT_FALSE(FlushScheduled());
-  }
-}
-
-TEST_F(ResourceDispatchThrottlerTest, NotThrottledIfSendRateSufficientlyLow) {
-  SetHighPriorityWorkAnticipated(true);
-
-  // Continuous dispatch of resource requests below the allowed send rate
-  // should never throttled.
-  const base::TimeDelta kAllowedContinuousSendInterval =
-      base::TimeDelta::FromSecondsD((kFlushPeriodSeconds / kRequestsPerFlush) +
-                                    .00001);
-  for (size_t i = 0; i < kRequestsPerFlush * 10; ++i) {
-    Advance(kAllowedContinuousSendInterval);
-    RequestResource();
-    EXPECT_EQ(1U, GetAndResetSentMessageCount());
-    EXPECT_FALSE(FlushScheduled());
-  }
-}
-
-TEST_F(ResourceDispatchThrottlerTest, ThrottledIfSendRateSufficientlyHigh) {
-  SetHighPriorityWorkAnticipated(true);
-
-  // Continuous dispatch of resource requests above the allowed send rate
-  // should be throttled.
-  const base::TimeDelta kThrottledContinuousSendInterval =
-      base::TimeDelta::FromSecondsD((kFlushPeriodSeconds / kRequestsPerFlush) -
-                                    .00001);
-
-  for (size_t i = 0; i < kRequestsPerFlush * 10; ++i) {
-    Advance(kThrottledContinuousSendInterval);
-    RequestResource();
-    // Only the first batch of requests under the limit should be unthrottled.
-    if (i < kRequestsPerFlush) {
-      EXPECT_EQ(1U, GetAndResetSentMessageCount());
-      EXPECT_FALSE(FlushScheduled());
-    } else {
-      EXPECT_EQ(0U, GetAndResetSentMessageCount());
-      EXPECT_TRUE(FlushScheduled());
-    }
-  }
-}
-
-TEST_F(ResourceDispatchThrottlerTest, NotThrottledIfSyncMessage) {
-  SetHighPriorityWorkAnticipated(true);
-
-  RequestResourceSync();
-  EXPECT_EQ(1U, GetAndResetSentMessageCount());
-
-  // Saturate the queue.
-  for (size_t i = 0; i < kRequestsPerFlush * 2; ++i)
-    RequestResource();
-  ASSERT_EQ(kRequestsPerFlush, GetAndResetSentMessageCount());
-
-  // Synchronous messages should flush any previously throttled messages.
-  RequestResourceSync();
-  EXPECT_EQ(1U + kRequestsPerFlush, GetAndResetSentMessageCount());
-  RequestResourceSync();
-  EXPECT_EQ(1U, GetAndResetSentMessageCount());
-
-  // Previously throttled messages should already have been flushed.
-  RunScheduledFlush();
-  EXPECT_EQ(0U, GetAndResetSentMessageCount());
-}
-
-TEST_F(ResourceDispatchThrottlerTest, MultipleFlushes) {
-  SetHighPriorityWorkAnticipated(true);
-  for (size_t i = 0; i < kRequestsPerFlush * 4; ++i)
-    RequestResource();
-  ASSERT_EQ(kRequestsPerFlush, GetAndResetSentMessageCount());
-
-  for (size_t i = 0; i < 3; ++i) {
-    SCOPED_TRACE(i);
-    EXPECT_TRUE(RunScheduledFlush());
-    EXPECT_EQ(kRequestsPerFlush, GetAndResetSentMessageCount());
-  }
-
-  EXPECT_FALSE(FlushScheduled());
-  EXPECT_EQ(0U, sent_messages_.size());
-}
-
-TEST_F(ResourceDispatchThrottlerTest, MultipleFlushesWhileReceiving) {
-  SetHighPriorityWorkAnticipated(true);
-  for (size_t i = 0; i < kRequestsPerFlush * 4; ++i)
-    RequestResource();
-  ASSERT_EQ(kRequestsPerFlush, GetAndResetSentMessageCount());
-
-  for (size_t i = 0; i < 3; ++i) {
-    SCOPED_TRACE(i);
-    EXPECT_TRUE(RunScheduledFlush());
-    EXPECT_EQ(kRequestsPerFlush, GetAndResetSentMessageCount());
-    for (size_t j = 0; j < kRequestsPerFlush; ++j)
-      RequestResource();
-    EXPECT_EQ(0U, sent_messages_.size());
-  }
-
-  for (size_t i = 0; i < 3; ++i) {
-    EXPECT_TRUE(RunScheduledFlush());
-    EXPECT_EQ(kRequestsPerFlush, GetAndResetSentMessageCount());
-  }
-
-  EXPECT_FALSE(FlushScheduled());
-  EXPECT_EQ(0U, sent_messages_.size());
-}
-
-TEST_F(ResourceDispatchThrottlerTest, NonRequestsNeverTriggerThrottling) {
-  RequestResource();
-  ASSERT_EQ(1U, GetAndResetSentMessageCount());
-
-  for (size_t i = 0; i < kRequestsPerFlush * 3; ++i)
-    UpdateRequestPriority(last_request_id(), net::HIGHEST);
-  EXPECT_EQ(kRequestsPerFlush * 3, sent_messages_.size());
-
-  RequestResource();
-  EXPECT_EQ(1U + kRequestsPerFlush * 3, GetAndResetSentMessageCount());
-}
-
-TEST_F(ResourceDispatchThrottlerTest, NonRequestsDeferredWhenThrottling) {
-  RequestResource();
-  ASSERT_EQ(1U, GetAndResetSentMessageCount());
-
-  RequestResourcesUntilThrottled();
-  UpdateRequestPriority(last_request_id(), net::HIGHEST);
-  ReleaseDownloadedFile(last_request_id());
-  CancelRequest(last_request_id());
-
-  EXPECT_TRUE(RunScheduledFlush());
-  EXPECT_EQ(4U, GetAndResetSentMessageCount());
-  EXPECT_FALSE(FlushScheduled());
-}
-
-TEST_F(ResourceDispatchThrottlerTest, MessageOrderingPreservedWhenThrottling) {
-  SetHighPriorityWorkAnticipated(true);
-  for (size_t i = 0; i < kRequestsPerFlush; ++i)
-    RequestResource();
-  ASSERT_EQ(kRequestsPerFlush, GetAndResetSentMessageCount());
-
-  for (size_t i = 0; i < kRequestsPerFlush; ++i) {
-    RequestResource();
-    UpdateRequestPriority(last_request_id(), net::HIGHEST);
-    CancelRequest(last_request_id() - 1);
-  }
-  ASSERT_EQ(0U, sent_messages_.size());
-
-  EXPECT_TRUE(RunScheduledFlush());
-  ASSERT_EQ(kRequestsPerFlush * 3, sent_messages_.size());
-  for (size_t i = 0; i < sent_messages_.size(); i += 3) {
-    SCOPED_TRACE(i);
-    const auto& request_msg = *sent_messages_[i];
-    const auto& priority_msg = *sent_messages_[i + 1];
-    const auto& cancel_msg = *sent_messages_[i + 2];
-
-    EXPECT_EQ(request_msg.type(),
-              static_cast<uint32_t>(ResourceHostMsg_RequestResource::ID));
-    EXPECT_EQ(priority_msg.type(),
-              static_cast<uint32_t>(ResourceHostMsg_DidChangePriority::ID));
-    EXPECT_EQ(cancel_msg.type(),
-              static_cast<uint32_t>(ResourceHostMsg_CancelRequest::ID));
-
-    EXPECT_EQ(GetRequestId(request_msg), GetRequestId(priority_msg));
-    EXPECT_EQ(GetRequestId(request_msg) - 1, GetRequestId(cancel_msg));
-  }
-  EXPECT_FALSE(FlushScheduled());
-}
-
-}  // namespace content
diff --git a/content/renderer/service_worker/embedded_worker_instance_client_impl.cc b/content/renderer/service_worker/embedded_worker_instance_client_impl.cc
index 892f21c..61caa76 100644
--- a/content/renderer/service_worker/embedded_worker_instance_client_impl.cc
+++ b/content/renderer/service_worker/embedded_worker_instance_client_impl.cc
@@ -15,9 +15,11 @@
 #include "content/public/common/content_client.h"
 #include "content/renderer/service_worker/embedded_worker_devtools_agent.h"
 #include "content/renderer/service_worker/service_worker_context_client.h"
+#include "content/renderer/service_worker/web_service_worker_installed_scripts_manager_impl.h"
 #include "third_party/WebKit/public/platform/WebContentSettingsClient.h"
 #include "third_party/WebKit/public/platform/WebSecurityOrigin.h"
 #include "third_party/WebKit/public/platform/WebURL.h"
+#include "third_party/WebKit/public/platform/modules/serviceworker/WebServiceWorkerInstalledScriptsManager.h"
 #include "third_party/WebKit/public/web/WebEmbeddedWorker.h"
 #include "third_party/WebKit/public/web/WebEmbeddedWorkerStartData.h"
 
@@ -133,29 +135,19 @@
     std::unique_ptr<ServiceWorkerContextClient> context_client,
     blink::mojom::WorkerContentSettingsProxyPtr content_settings_proxy,
     service_manager::mojom::InterfaceProviderPtr interface_provider) {
-  std::unique_ptr<blink::WebServiceWorkerInstalledScriptsManagerParams>
-      installed_scripts_manager_params;
+  std::unique_ptr<blink::WebServiceWorkerInstalledScriptsManager> manager;
   // |installed_scripts_info| is null if scripts should be served by net layer,
   // when the worker is not installed, or the worker is launched for checking
   // the update.
   if (ServiceWorkerUtils::IsScriptStreamingEnabled() &&
       installed_scripts_info) {
-    installed_scripts_manager_params = std::make_unique<
-        blink::WebServiceWorkerInstalledScriptsManagerParams>();
-    installed_scripts_manager_params->installed_scripts_urls =
-        std::move(installed_scripts_info->installed_urls);
-    installed_scripts_manager_params->manager_request =
-        installed_scripts_info->manager_request.PassMessagePipe();
-    installed_scripts_manager_params->manager_host_ptr =
-        installed_scripts_info->manager_host_ptr.PassHandle();
-    DCHECK(installed_scripts_manager_params->manager_request.is_valid());
-    DCHECK(installed_scripts_manager_params->manager_host_ptr.is_valid());
+    manager = WebServiceWorkerInstalledScriptsManagerImpl::Create(
+        std::move(installed_scripts_info), io_thread_runner_);
   }
 
   auto wrapper = std::make_unique<WorkerWrapper>(
       blink::WebEmbeddedWorker::Create(
-          std::move(context_client),
-          std::move(installed_scripts_manager_params),
+          std::move(context_client), std::move(manager),
           content_settings_proxy.PassInterface().PassHandle(),
           interface_provider.PassInterface().PassHandle()),
       params->worker_devtools_agent_route_id);
diff --git a/content/renderer/service_worker/service_worker_fetch_context_impl.cc b/content/renderer/service_worker/service_worker_fetch_context_impl.cc
index 2e0afc7..bbdfd0a 100644
--- a/content/renderer/service_worker/service_worker_fetch_context_impl.cc
+++ b/content/renderer/service_worker/service_worker_fetch_context_impl.cc
@@ -25,8 +25,8 @@
 
 void ServiceWorkerFetchContextImpl::InitializeOnWorkerThread(
     scoped_refptr<base::SingleThreadTaskRunner> loading_task_runner) {
-  resource_dispatcher_ = std::make_unique<ResourceDispatcher>(
-      nullptr, std::move(loading_task_runner));
+  resource_dispatcher_ =
+      std::make_unique<ResourceDispatcher>(std::move(loading_task_runner));
 
   url_loader_factory_getter_ = url_loader_factory_getter_info_.Bind();
 }
diff --git a/content/renderer/service_worker/thread_safe_script_container.cc b/content/renderer/service_worker/thread_safe_script_container.cc
new file mode 100644
index 0000000..6f6e038
--- /dev/null
+++ b/content/renderer/service_worker/thread_safe_script_container.cc
@@ -0,0 +1,78 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/renderer/service_worker/thread_safe_script_container.h"
+
+#include "base/stl_util.h"
+
+namespace content {
+
+ThreadSafeScriptContainer::ThreadSafeScriptContainer()
+    : lock_(), waiting_cv_(&lock_), are_all_data_added_(false) {}
+
+void ThreadSafeScriptContainer::AddOnIOThread(const GURL& url,
+                                              std::unique_ptr<Data> data) {
+  base::AutoLock lock(lock_);
+  script_data_[url] = std::move(data);
+  if (url == waiting_url_)
+    waiting_cv_.Signal();
+}
+
+ThreadSafeScriptContainer::ScriptStatus
+ThreadSafeScriptContainer::GetStatusOnWorkerThread(const GURL& url) {
+  base::AutoLock lock(lock_);
+  auto it = script_data_.find(url);
+  if (it == script_data_.end())
+    return ScriptStatus::kPending;
+  if (!it->second)
+    return ScriptStatus::kTaken;
+  if (!it->second->IsValid())
+    return ScriptStatus::kFailed;
+  return ScriptStatus::kReceived;
+}
+
+void ThreadSafeScriptContainer::ResetOnWorkerThread(const GURL& url) {
+  base::AutoLock lock(lock_);
+  script_data_.erase(url);
+}
+
+bool ThreadSafeScriptContainer::WaitOnWorkerThread(const GURL& url) {
+  base::AutoLock lock(lock_);
+  DCHECK(waiting_url_.is_empty())
+      << "The script container is unexpectedly shared among worker threads.";
+  waiting_url_ = url;
+  while (script_data_.find(url) == script_data_.end()) {
+    // If waiting script hasn't been added yet though all data are received,
+    // that means something went wrong.
+    if (are_all_data_added_) {
+      waiting_url_ = GURL();
+      return false;
+    }
+    // This is possible to be waken up spuriously, so that it's necessary to
+    // check if the entry is really added.
+    waiting_cv_.Wait();
+  }
+  waiting_url_ = GURL();
+  // TODO(shimazu): Keep the status for each entries instead of using IsValid().
+  const auto& data = script_data_[url];
+  return !data || data->IsValid();
+}
+
+std::unique_ptr<ThreadSafeScriptContainer::Data>
+ThreadSafeScriptContainer::TakeOnWorkerThread(const GURL& url) {
+  base::AutoLock lock(lock_);
+  DCHECK(base::ContainsKey(script_data_, url))
+      << "Script should be added before calling Take.";
+  return std::move(script_data_[url]);
+}
+
+void ThreadSafeScriptContainer::OnAllDataAddedOnIOThread() {
+  base::AutoLock lock(lock_);
+  are_all_data_added_ = true;
+  waiting_cv_.Broadcast();
+}
+
+ThreadSafeScriptContainer::~ThreadSafeScriptContainer() = default;
+
+}  // namespace content
diff --git a/content/renderer/service_worker/thread_safe_script_container.h b/content/renderer/service_worker/thread_safe_script_container.h
new file mode 100644
index 0000000..037a072
--- /dev/null
+++ b/content/renderer/service_worker/thread_safe_script_container.h
@@ -0,0 +1,93 @@
+// 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 <map>
+#include <memory>
+
+#include "base/memory/ref_counted.h"
+#include "base/synchronization/condition_variable.h"
+#include "base/synchronization/lock.h"
+#include "content/common/content_export.h"
+#include "third_party/WebKit/public/platform/modules/serviceworker/WebServiceWorkerInstalledScriptsManager.h"
+
+#ifndef CONTENT_RENDERER_SERVICE_WORKER_THREAD_SAFE_SCRIPT_CONTAINER_H_
+#define CONTENT_RENDERER_SERVICE_WORKER_THREAD_SAFE_SCRIPT_CONTAINER_H_
+
+namespace content {
+
+// ThreadSafeScriptContainer stores the scripts of a service worker for
+// startup. This container is created for each service worker. The IO thread
+// adds scripts to the container, and the worker thread takes the scripts.
+//
+// This class uses explicit synchronization because it needs to support
+// synchronous importScripts() from the worker thread.
+//
+// This class is RefCounted because there is no ordering guarantee of lifetime
+// of its owners, i.e. WebServiceWorkerInstalledScriptsManagerImpl and its
+// Internal class. WebSWInstalledScriptsManagerImpl is destroyed earlier than
+// Internal if the worker is terminated before all scripts are streamed, and
+// Internal is destroyed earlier if all of scripts are received before finishing
+// script evaluation.
+class CONTENT_EXPORT ThreadSafeScriptContainer
+    : public base::RefCountedThreadSafe<ThreadSafeScriptContainer> {
+ public:
+  using Data = blink::WebServiceWorkerInstalledScriptsManager::RawScriptData;
+
+  REQUIRE_ADOPTION_FOR_REFCOUNTED_TYPE();
+  ThreadSafeScriptContainer();
+
+  enum class ScriptStatus {
+    // The script data has been received.
+    kReceived,
+    // The script data has been received but it has already been taken.
+    kTaken,
+    // Receiving the script has failed.
+    kFailed,
+    // The script data has not been received yet.
+    kPending
+  };
+
+  // Called on the IO thread.
+  void AddOnIOThread(const GURL& url, std::unique_ptr<Data> data);
+
+  // Called on the worker thread.
+  ScriptStatus GetStatusOnWorkerThread(const GURL& url);
+
+  // Removes the script. After calling this, ScriptStatus for the
+  // script will be kPending.
+  // Called on the worker thread.
+  void ResetOnWorkerThread(const GURL& url);
+
+  // Waits until the script is added. The thread is blocked until the script is
+  // available or receiving the script fails. Returns false if an error happens
+  // and the waiting script won't be available forever.
+  // Called on the worker thread.
+  bool WaitOnWorkerThread(const GURL& url);
+
+  // Called on the worker thread.
+  std::unique_ptr<Data> TakeOnWorkerThread(const GURL& url);
+
+  // Called if no more data will be added.
+  // Called on the IO thread.
+  void OnAllDataAddedOnIOThread();
+
+ private:
+  friend class base::RefCountedThreadSafe<ThreadSafeScriptContainer>;
+  ~ThreadSafeScriptContainer();
+
+  // |lock_| protects |waiting_cv_|, |script_data_|, |waiting_url_| and
+  // |are_all_data_added_|.
+  base::Lock lock_;
+  // |waiting_cv_| is signaled when a script whose url matches to |waiting_url|
+  // is added, or OnAllDataAdded is called. The worker thread waits on this, and
+  // the IO thread signals it.
+  base::ConditionVariable waiting_cv_;
+  std::map<GURL, std::unique_ptr<Data>> script_data_;
+  GURL waiting_url_;
+  bool are_all_data_added_;
+};
+
+}  // namespace content
+
+#endif  // CONTENT_RENDERER_SERVICE_WORKER_THREAD_SAFE_SCRIPT_CONTAINER_H_
diff --git a/content/renderer/service_worker/thread_safe_script_container_unittest.cc b/content/renderer/service_worker/thread_safe_script_container_unittest.cc
new file mode 100644
index 0000000..a6853ed
--- /dev/null
+++ b/content/renderer/service_worker/thread_safe_script_container_unittest.cc
@@ -0,0 +1,226 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/renderer/service_worker/thread_safe_script_container.h"
+
+#include "base/bind.h"
+#include "base/synchronization/waitable_event.h"
+#include "base/threading/thread.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace content {
+
+using ScriptStatus = ThreadSafeScriptContainer::ScriptStatus;
+
+class ThreadSafeScriptContainerTest : public testing::Test {
+ public:
+  ThreadSafeScriptContainerTest()
+      : writer_thread_("writer_thread"),
+        reader_thread_("reader_thread"),
+        writer_waiter_(base::WaitableEvent::ResetPolicy::AUTOMATIC,
+                       base::WaitableEvent::InitialState::NOT_SIGNALED),
+        reader_waiter_(base::WaitableEvent::ResetPolicy::AUTOMATIC,
+                       base::WaitableEvent::InitialState::NOT_SIGNALED),
+        container_(base::MakeRefCounted<ThreadSafeScriptContainer>()) {}
+
+ protected:
+  void SetUp() override {
+    ASSERT_TRUE(writer_thread_.Start());
+    ASSERT_TRUE(reader_thread_.Start());
+    writer_task_runner_ = writer_thread_.task_runner();
+    reader_task_runner_ = reader_thread_.task_runner();
+  }
+
+  void TearDown() override {
+    writer_thread_.Stop();
+    reader_thread_.Stop();
+  }
+
+  base::WaitableEvent* AddOnWriterThread(
+      const GURL& url,
+      ThreadSafeScriptContainer::Data** out_data) {
+    writer_task_runner_->PostTask(
+        FROM_HERE,
+        base::BindOnce(
+            [](scoped_refptr<ThreadSafeScriptContainer> container,
+               const GURL& url, ThreadSafeScriptContainer::Data** out_data,
+               base::WaitableEvent* waiter) {
+              auto data = ThreadSafeScriptContainer::Data::Create(
+                  blink::WebString::FromUTF8("utf-8") /* encoding */,
+                  blink::WebVector<blink::WebVector<char>>() /* script_text */,
+                  blink::WebVector<blink::WebVector<char>>() /* meta_data */);
+              *out_data = data.get();
+              container->AddOnIOThread(url, std::move(data));
+              waiter->Signal();
+            },
+            container_, url, out_data, &writer_waiter_));
+    return &writer_waiter_;
+  }
+
+  base::WaitableEvent* OnAllDataAddedOnWriterThread() {
+    writer_task_runner_->PostTask(
+        FROM_HERE, base::BindOnce(
+                       [](scoped_refptr<ThreadSafeScriptContainer> container,
+                          base::WaitableEvent* waiter) {
+                         container->OnAllDataAddedOnIOThread();
+                         waiter->Signal();
+                       },
+                       container_, &writer_waiter_));
+    return &writer_waiter_;
+  }
+
+  base::WaitableEvent* GetStatusOnReaderThread(const GURL& url,
+                                               ScriptStatus* out_status) {
+    reader_task_runner_->PostTask(
+        FROM_HERE, base::BindOnce(
+                       [](scoped_refptr<ThreadSafeScriptContainer> container,
+                          const GURL& url, ScriptStatus* out_status,
+                          base::WaitableEvent* waiter) {
+                         *out_status = container->GetStatusOnWorkerThread(url);
+                         waiter->Signal();
+                       },
+                       container_, url, out_status, &reader_waiter_));
+    return &reader_waiter_;
+  }
+
+  base::WaitableEvent* WaitOnReaderThread(const GURL& url, bool* out_exists) {
+    reader_task_runner_->PostTask(
+        FROM_HERE,
+        base::BindOnce(
+            [](scoped_refptr<ThreadSafeScriptContainer> container,
+               const GURL& url, bool* out_exists, base::WaitableEvent* waiter) {
+              *out_exists = container->WaitOnWorkerThread(url);
+              waiter->Signal();
+            },
+            container_, url, out_exists, &reader_waiter_));
+    return &reader_waiter_;
+  }
+
+  base::WaitableEvent* TakeOnReaderThread(
+      const GURL& url,
+      ThreadSafeScriptContainer::Data** out_data) {
+    reader_task_runner_->PostTask(
+        FROM_HERE,
+        base::BindOnce(
+            [](scoped_refptr<ThreadSafeScriptContainer> container,
+               const GURL& url, ThreadSafeScriptContainer::Data** out_data,
+               base::WaitableEvent* waiter) {
+              auto data = container->TakeOnWorkerThread(url);
+              *out_data = data.get();
+              waiter->Signal();
+            },
+            container_, url, out_data, &reader_waiter_));
+    return &reader_waiter_;
+  }
+
+ private:
+  base::Thread writer_thread_;
+  base::Thread reader_thread_;
+
+  scoped_refptr<base::SingleThreadTaskRunner> writer_task_runner_;
+  scoped_refptr<base::SingleThreadTaskRunner> reader_task_runner_;
+
+  base::WaitableEvent writer_waiter_;
+  base::WaitableEvent reader_waiter_;
+
+  scoped_refptr<ThreadSafeScriptContainer> container_;
+};
+
+TEST_F(ThreadSafeScriptContainerTest, WaitExistingKey) {
+  const GURL kKey("https://example.com/key");
+  {
+    ScriptStatus result = ScriptStatus::kReceived;
+    GetStatusOnReaderThread(kKey, &result)->Wait();
+    EXPECT_EQ(ScriptStatus::kPending, result);
+  }
+
+  ThreadSafeScriptContainer::Data* added_data;
+  {
+    bool result = false;
+    base::WaitableEvent* pending_wait = WaitOnReaderThread(kKey, &result);
+    // This should not be signaled until data is added.
+    EXPECT_FALSE(pending_wait->IsSignaled());
+    base::WaitableEvent* pending_write = AddOnWriterThread(kKey, &added_data);
+    pending_wait->Wait();
+    pending_write->Wait();
+    EXPECT_TRUE(result);
+  }
+
+  {
+    ScriptStatus result = ScriptStatus::kFailed;
+    GetStatusOnReaderThread(kKey, &result)->Wait();
+    EXPECT_EQ(ScriptStatus::kReceived, result);
+  }
+
+  {
+    ThreadSafeScriptContainer::Data* taken_data;
+    TakeOnReaderThread(kKey, &taken_data)->Wait();
+    EXPECT_EQ(added_data, taken_data);
+  }
+
+  {
+    ScriptStatus result = ScriptStatus::kFailed;
+    GetStatusOnReaderThread(kKey, &result)->Wait();
+    // The record of |kKey| should be exist though it's already taken.
+    EXPECT_EQ(ScriptStatus::kTaken, result);
+  }
+
+  {
+    bool result = false;
+    WaitOnReaderThread(kKey, &result)->Wait();
+    // Waiting for |kKey| should succeed.
+    EXPECT_TRUE(result);
+
+    ThreadSafeScriptContainer::Data* taken_data;
+    TakeOnReaderThread(kKey, &taken_data)->Wait();
+    // |taken_data| should be nullptr because it's already taken.
+    EXPECT_EQ(nullptr, taken_data);
+  }
+
+  // Finish adding data.
+  OnAllDataAddedOnWriterThread()->Wait();
+
+  {
+    bool result = false;
+    WaitOnReaderThread(kKey, &result)->Wait();
+    // The record has been already added, so Wait shouldn't fail.
+    EXPECT_TRUE(result);
+
+    ThreadSafeScriptContainer::Data* taken_data;
+    TakeOnReaderThread(kKey, &taken_data)->Wait();
+    // |taken_data| should be nullptr because it's already taken.
+    EXPECT_EQ(nullptr, taken_data);
+  }
+}
+
+TEST_F(ThreadSafeScriptContainerTest, WaitNonExistingKey) {
+  const GURL kKey("https://example.com/key");
+  {
+    ScriptStatus result = ScriptStatus::kReceived;
+    GetStatusOnReaderThread(kKey, &result)->Wait();
+    EXPECT_EQ(ScriptStatus::kPending, result);
+  }
+
+  {
+    bool result = true;
+    base::WaitableEvent* pending_wait = WaitOnReaderThread(kKey, &result);
+    // This should not be signaled until OnAllDataAdded is called.
+    EXPECT_FALSE(pending_wait->IsSignaled());
+    base::WaitableEvent* pending_on_all_data_added =
+        OnAllDataAddedOnWriterThread();
+    pending_wait->Wait();
+    pending_on_all_data_added->Wait();
+    // Aborted wait should return false.
+    EXPECT_FALSE(result);
+  }
+
+  {
+    bool result = true;
+    WaitOnReaderThread(kKey, &result)->Wait();
+    // Wait fails immediately because OnAllDataAdded is called.
+    EXPECT_FALSE(result);
+  }
+}
+
+}  // namespace content
diff --git a/content/renderer/service_worker/web_service_worker_installed_scripts_manager_impl.cc b/content/renderer/service_worker/web_service_worker_installed_scripts_manager_impl.cc
new file mode 100644
index 0000000..157340b
--- /dev/null
+++ b/content/renderer/service_worker/web_service_worker_installed_scripts_manager_impl.cc
@@ -0,0 +1,298 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/renderer/service_worker/web_service_worker_installed_scripts_manager_impl.h"
+
+#include "base/barrier_closure.h"
+#include "base/memory/ptr_util.h"
+#include "base/stl_util.h"
+#include "base/threading/thread_checker.h"
+#include "mojo/public/cpp/bindings/strong_binding.h"
+
+namespace content {
+
+namespace {
+
+// Receiver is a class to read a Mojo data pipe. Received data are stored in
+// chunks. Lives on the IO thread. Receiver is owned by Internal via
+// BundledReceivers. It is created to read the script body or metadata from a
+// data pipe, and is destroyed when the read finishes.
+class Receiver {
+ public:
+  using BytesChunk = blink::WebVector<char>;
+
+  Receiver(mojo::ScopedDataPipeConsumerHandle handle, uint64_t total_bytes)
+      : handle_(std::move(handle)),
+        watcher_(FROM_HERE, mojo::SimpleWatcher::ArmingPolicy::MANUAL),
+        remaining_bytes_(total_bytes) {}
+
+  void Start(base::OnceClosure callback) {
+    if (!handle_.is_valid()) {
+      std::move(callback).Run();
+      return;
+    }
+    callback_ = std::move(callback);
+    // base::Unretained is safe because |watcher_| is owned by |this|.
+    MojoResult rv = watcher_.Watch(
+        handle_.get(), MOJO_HANDLE_SIGNAL_READABLE,
+        base::Bind(&Receiver::OnReadable, base::Unretained(this)));
+    DCHECK_EQ(MOJO_RESULT_OK, rv);
+    watcher_.ArmOrNotify();
+  }
+
+  void OnReadable(MojoResult) {
+    // It isn't necessary to handle MojoResult here since BeginReadDataRaw()
+    // returns an equivalent error.
+    const void* buffer = nullptr;
+    uint32_t bytes_read = 0;
+    MojoResult rv =
+        handle_->BeginReadData(&buffer, &bytes_read, MOJO_READ_DATA_FLAG_NONE);
+    switch (rv) {
+      case MOJO_RESULT_BUSY:
+      case MOJO_RESULT_INVALID_ARGUMENT:
+        NOTREACHED();
+        return;
+      case MOJO_RESULT_FAILED_PRECONDITION:
+        // Closed by peer.
+        OnCompleted();
+        return;
+      case MOJO_RESULT_SHOULD_WAIT:
+        watcher_.ArmOrNotify();
+        return;
+      case MOJO_RESULT_OK:
+        break;
+      default:
+        // mojo::BeginReadDataRaw() should not return any other values.
+        // Notify the error to the browser by resetting the handle even though
+        // it's in the middle of data transfer.
+        OnCompleted();
+        return;
+    }
+
+    if (bytes_read > 0)
+      chunks_.emplace_back(static_cast<const char*>(buffer), bytes_read);
+
+    rv = handle_->EndReadData(bytes_read);
+    DCHECK_EQ(rv, MOJO_RESULT_OK);
+    CHECK_GE(remaining_bytes_, bytes_read);
+    remaining_bytes_ -= bytes_read;
+    watcher_.ArmOrNotify();
+  }
+
+  bool is_running() const { return handle_.is_valid(); }
+  bool has_received_all_data() const { return remaining_bytes_ == 0; }
+
+  blink::WebVector<BytesChunk> TakeChunks() {
+    DCHECK(!is_running());
+    return blink::WebVector<BytesChunk>(std::move(chunks_));
+  }
+
+ private:
+  void OnCompleted() {
+    handle_.reset();
+    watcher_.Cancel();
+    if (!has_received_all_data())
+      chunks_.clear();
+    DCHECK(callback_);
+    std::move(callback_).Run();
+  }
+
+  base::OnceClosure callback_;
+  mojo::ScopedDataPipeConsumerHandle handle_;
+  mojo::SimpleWatcher watcher_;
+
+  // std::vector is internally used because blink::WebVector is immutable and
+  // cannot append data.
+  std::vector<BytesChunk> chunks_;
+  uint64_t remaining_bytes_;
+};
+
+using RawScriptData =
+    blink::WebServiceWorkerInstalledScriptsManager::RawScriptData;
+
+// BundledReceivers is a helper class to wait for the end of reading body and
+// meta data. Lives on the IO thread.
+class BundledReceivers {
+ public:
+  BundledReceivers(mojo::ScopedDataPipeConsumerHandle meta_data_handle,
+                   uint64_t meta_data_size,
+                   mojo::ScopedDataPipeConsumerHandle body_handle,
+                   uint64_t body_size)
+      : meta_data_(std::move(meta_data_handle), meta_data_size),
+        body_(std::move(body_handle), body_size) {}
+
+  // Starts reading the pipes and invokes |callback| when both are finished.
+  void Start(base::OnceClosure callback) {
+    base::RepeatingClosure wait_all_closure =
+        base::BarrierClosure(2, std::move(callback));
+    meta_data_.Start(wait_all_closure);
+    body_.Start(wait_all_closure);
+  }
+
+  Receiver* meta_data() { return &meta_data_; }
+  Receiver* body() { return &body_; }
+
+ private:
+  Receiver meta_data_;
+  Receiver body_;
+};
+
+// Internal lives on the IO thread. This receives
+// blink::mojom::ServiceWorkerScriptInfo for all installed scripts and then
+// starts reading the body and meta data from the browser. This instance will be
+// kept alive as long as the Mojo's connection is established.
+class Internal : public blink::mojom::ServiceWorkerInstalledScriptsManager {
+ public:
+  // Called on the IO thread.
+  // Creates and binds a new Internal instance to |request|.
+  static void Create(
+      scoped_refptr<ThreadSafeScriptContainer> script_container,
+      blink::mojom::ServiceWorkerInstalledScriptsManagerRequest request) {
+    mojo::MakeStrongBinding(
+        std::make_unique<Internal>(std::move(script_container)),
+        std::move(request));
+  }
+
+  Internal(scoped_refptr<ThreadSafeScriptContainer> script_container)
+      : script_container_(std::move(script_container)), weak_factory_(this) {}
+
+  ~Internal() override {
+    DCHECK_CALLED_ON_VALID_THREAD(io_thread_checker_);
+    // Wake up a waiting thread so it does not wait forever. If the script has
+    // not been added yet, that means something went wrong. From here,
+    // script_container_->Wait() will return false if the script hasn't been
+    // added yet.
+    script_container_->OnAllDataAddedOnIOThread();
+  }
+
+  // Implements blink::mojom::ServiceWorkerInstalledScriptsManager.
+  // Called on the IO thread.
+  void TransferInstalledScript(
+      blink::mojom::ServiceWorkerScriptInfoPtr script_info) override {
+    DCHECK_CALLED_ON_VALID_THREAD(io_thread_checker_);
+    GURL script_url = script_info->script_url;
+    auto receivers = std::make_unique<BundledReceivers>(
+        std::move(script_info->meta_data), script_info->meta_data_size,
+        std::move(script_info->body), script_info->body_size);
+    receivers->Start(base::BindOnce(&Internal::OnScriptReceived,
+                                    weak_factory_.GetWeakPtr(),
+                                    base::Passed(&script_info)));
+    DCHECK(!base::ContainsKey(running_receivers_, script_url));
+    running_receivers_[script_url] = std::move(receivers);
+  }
+
+  // Called on the IO thread.
+  void OnScriptReceived(blink::mojom::ServiceWorkerScriptInfoPtr script_info) {
+    DCHECK_CALLED_ON_VALID_THREAD(io_thread_checker_);
+    const GURL& script_url = script_info->script_url;
+    auto iter = running_receivers_.find(script_url);
+    DCHECK(iter != running_receivers_.end());
+    std::unique_ptr<BundledReceivers> receivers = std::move(iter->second);
+    DCHECK(receivers);
+    if (!receivers->body()->has_received_all_data() ||
+        !receivers->meta_data()->has_received_all_data()) {
+      script_container_->AddOnIOThread(script_url,
+                                       RawScriptData::CreateInvalidInstance());
+      running_receivers_.erase(iter);
+      return;
+    }
+
+    auto script_data = RawScriptData::Create(
+        blink::WebString::FromUTF8(script_info->encoding),
+        receivers->body()->TakeChunks(), receivers->meta_data()->TakeChunks());
+    for (const auto& entry : script_info->headers) {
+      script_data->AddHeader(blink::WebString::FromUTF8(entry.first),
+                             blink::WebString::FromUTF8(entry.second));
+    }
+    script_container_->AddOnIOThread(script_url, std::move(script_data));
+    running_receivers_.erase(iter);
+  }
+
+ private:
+  THREAD_CHECKER(io_thread_checker_);
+  std::map<GURL, std::unique_ptr<BundledReceivers>> running_receivers_;
+  scoped_refptr<ThreadSafeScriptContainer> script_container_;
+  base::WeakPtrFactory<Internal> weak_factory_;
+};
+
+}  // namespace
+
+// static
+std::unique_ptr<blink::WebServiceWorkerInstalledScriptsManager>
+WebServiceWorkerInstalledScriptsManagerImpl::Create(
+    blink::mojom::ServiceWorkerInstalledScriptsInfoPtr installed_scripts_info,
+    scoped_refptr<base::SingleThreadTaskRunner> io_task_runner) {
+  auto script_container = base::MakeRefCounted<ThreadSafeScriptContainer>();
+  blink::mojom::ServiceWorkerInstalledScriptsManagerHostPtr manager_host_ptr(
+      std::move(installed_scripts_info->manager_host_ptr));
+  std::unique_ptr<blink::WebServiceWorkerInstalledScriptsManager> manager =
+      base::WrapUnique<WebServiceWorkerInstalledScriptsManagerImpl>(
+          new WebServiceWorkerInstalledScriptsManagerImpl(
+              std::move(installed_scripts_info->installed_urls),
+              script_container, std::move(manager_host_ptr)));
+  io_task_runner->PostTask(
+      FROM_HERE,
+      base::BindOnce(&Internal::Create, script_container,
+                     std::move(installed_scripts_info->manager_request)));
+  return manager;
+}
+
+WebServiceWorkerInstalledScriptsManagerImpl::
+    WebServiceWorkerInstalledScriptsManagerImpl(
+        std::vector<GURL>&& installed_urls,
+        scoped_refptr<ThreadSafeScriptContainer> script_container,
+        blink::mojom::ServiceWorkerInstalledScriptsManagerHostPtr manager_host)
+    : installed_urls_(installed_urls.begin(), installed_urls.end()),
+      script_container_(std::move(script_container)),
+      manager_host_(
+          blink::mojom::ThreadSafeServiceWorkerInstalledScriptsManagerHostPtr::
+              Create(std::move(manager_host))) {}
+
+WebServiceWorkerInstalledScriptsManagerImpl::
+    ~WebServiceWorkerInstalledScriptsManagerImpl() = default;
+
+bool WebServiceWorkerInstalledScriptsManagerImpl::IsScriptInstalled(
+    const blink::WebURL& script_url) const {
+  return base::ContainsKey(installed_urls_, script_url);
+}
+
+std::unique_ptr<RawScriptData>
+WebServiceWorkerInstalledScriptsManagerImpl::GetRawScriptData(
+    const blink::WebURL& script_url) {
+  TRACE_EVENT1("ServiceWorker",
+               "WebServiceWorkerInstalledScriptsManagerImpl::GetRawScriptData",
+               "script_url", script_url.GetString().Utf8());
+  if (!IsScriptInstalled(script_url))
+    return nullptr;
+
+  ThreadSafeScriptContainer::ScriptStatus status =
+      script_container_->GetStatusOnWorkerThread(script_url);
+  // If the script has already been taken, request the browser to send the
+  // script.
+  if (status == ThreadSafeScriptContainer::ScriptStatus::kTaken) {
+    script_container_->ResetOnWorkerThread(script_url);
+    (*manager_host_)->RequestInstalledScript(script_url);
+    status = script_container_->GetStatusOnWorkerThread(script_url);
+  }
+
+  // If the script has not been received at this point, wait for arrival by
+  // blocking the worker thread.
+  if (status == ThreadSafeScriptContainer::ScriptStatus::kPending) {
+    // Wait for arrival of the script.
+    const bool success = script_container_->WaitOnWorkerThread(script_url);
+    // It can fail due to an error on Mojo pipes.
+    if (!success)
+      return RawScriptData::CreateInvalidInstance();
+    status = script_container_->GetStatusOnWorkerThread(script_url);
+    DCHECK_NE(ThreadSafeScriptContainer::ScriptStatus::kPending, status);
+  }
+
+  if (status == ThreadSafeScriptContainer::ScriptStatus::kFailed)
+    return RawScriptData::CreateInvalidInstance();
+  DCHECK_EQ(ThreadSafeScriptContainer::ScriptStatus::kReceived, status);
+
+  return script_container_->TakeOnWorkerThread(script_url);
+}
+
+}  // namespace content
diff --git a/content/renderer/service_worker/web_service_worker_installed_scripts_manager_impl.h b/content/renderer/service_worker/web_service_worker_installed_scripts_manager_impl.h
new file mode 100644
index 0000000..9df608af
--- /dev/null
+++ b/content/renderer/service_worker/web_service_worker_installed_scripts_manager_impl.h
@@ -0,0 +1,48 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CONTENT_RENDERER_SERVICE_WORKER_WEB_SERVICE_WORKER_INSTALLED_SCRIPTS_MANAGER_IMPL_H_
+#define CONTENT_RENDERER_SERVICE_WORKER_WEB_SERVICE_WORKER_INSTALLED_SCRIPTS_MANAGER_IMPL_H_
+
+#include <set>
+#include <vector>
+
+#include "content/renderer/service_worker/thread_safe_script_container.h"
+#include "third_party/WebKit/common/service_worker/service_worker_installed_scripts_manager.mojom.h"
+#include "third_party/WebKit/public/platform/modules/serviceworker/WebServiceWorkerInstalledScriptsManager.h"
+
+namespace content {
+
+class CONTENT_EXPORT WebServiceWorkerInstalledScriptsManagerImpl final
+    : public blink::WebServiceWorkerInstalledScriptsManager {
+ public:
+  // Called on the main thread.
+  static std::unique_ptr<blink::WebServiceWorkerInstalledScriptsManager> Create(
+      blink::mojom::ServiceWorkerInstalledScriptsInfoPtr installed_scripts_info,
+      scoped_refptr<base::SingleThreadTaskRunner> io_task_runner);
+
+  ~WebServiceWorkerInstalledScriptsManagerImpl() override;
+
+  // WebServiceWorkerInstalledScriptsManager implementation.
+  bool IsScriptInstalled(const blink::WebURL& script_url) const override;
+  std::unique_ptr<RawScriptData> GetRawScriptData(
+      const blink::WebURL& script_url) override;
+
+ private:
+  WebServiceWorkerInstalledScriptsManagerImpl(
+      std::vector<GURL>&& installed_urls,
+      scoped_refptr<ThreadSafeScriptContainer> script_container,
+      blink::mojom::ServiceWorkerInstalledScriptsManagerHostPtr manager_host);
+
+  const std::set<GURL> installed_urls_;
+  scoped_refptr<ThreadSafeScriptContainer> script_container_;
+
+  scoped_refptr<
+      blink::mojom::ThreadSafeServiceWorkerInstalledScriptsManagerHostPtr>
+      manager_host_;
+};
+
+}  // namespace content
+
+#endif  // CONTENT_RENDERER_SERVICE_WORKER_WEB_SERVICE_WORKER_INSTALLED_SCRIPTS_MANAGER_IMPL_H_
diff --git a/third_party/WebKit/Source/modules/serviceworkers/ServiceWorkerInstalledScriptsManagerTest.cpp b/content/renderer/service_worker/web_service_worker_installed_scripts_manager_impl_unittest.cc
similarity index 62%
rename from third_party/WebKit/Source/modules/serviceworkers/ServiceWorkerInstalledScriptsManagerTest.cpp
rename to content/renderer/service_worker/web_service_worker_installed_scripts_manager_impl_unittest.cc
index 11e0345..5b24150 100644
--- a/third_party/WebKit/Source/modules/serviceworkers/ServiceWorkerInstalledScriptsManagerTest.cpp
+++ b/content/renderer/service_worker/web_service_worker_installed_scripts_manager_impl_unittest.cc
@@ -2,53 +2,44 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "modules/serviceworkers/ServiceWorkerInstalledScriptsManager.h"
+#include "content/renderer/service_worker/web_service_worker_installed_scripts_manager_impl.h"
 
-#include <memory>
+#include "base/bind.h"
+#include "base/message_loop/message_loop.h"
 #include "base/run_loop.h"
+#include "base/synchronization/waitable_event.h"
+#include "base/threading/thread.h"
+#include "content/public/test/test_browser_thread_bundle.h"
 #include "mojo/public/cpp/bindings/binding.h"
-#include "platform/CrossThreadFunctional.h"
-#include "platform/WaitableEvent.h"
-#include "platform/wtf/Functional.h"
-#include "public/platform/Platform.h"
-#include "public/platform/WebThread.h"
 #include "testing/gtest/include/gtest/gtest.h"
-#include "third_party/WebKit/common/service_worker/service_worker_installed_scripts_manager.mojom-blink.h"
 
-namespace blink {
-
-namespace {
+namespace content {
 
 class BrowserSideSender
-    : mojom::blink::ServiceWorkerInstalledScriptsManagerHost {
+    : blink::mojom::ServiceWorkerInstalledScriptsManagerHost {
  public:
   BrowserSideSender() : binding_(this) {}
   ~BrowserSideSender() override = default;
 
-  mojom::blink::ServiceWorkerInstalledScriptsInfoPtr CreateAndBind(
-      const WTF::Vector<KURL>& installed_urls) {
+  blink::mojom::ServiceWorkerInstalledScriptsInfoPtr CreateAndBind(
+      const std::vector<GURL>& installed_urls) {
     EXPECT_FALSE(manager_.is_bound());
     EXPECT_FALSE(body_handle_.is_valid());
     EXPECT_FALSE(meta_data_handle_.is_valid());
-    auto scripts_info = mojom::blink::ServiceWorkerInstalledScriptsInfo::New();
+    auto scripts_info = blink::mojom::ServiceWorkerInstalledScriptsInfo::New();
     scripts_info->installed_urls = installed_urls;
     scripts_info->manager_request = mojo::MakeRequest(&manager_);
     binding_.Bind(mojo::MakeRequest(&scripts_info->manager_host_ptr));
     return scripts_info;
   }
 
-  void TransferInstalledScript(
-      const KURL& script_url,
-      const WTF::String& encoding,
-      const WTF::HashMap<WTF::String, WTF::String>& headers,
-      int64_t body_size,
-      int64_t meta_data_size) {
+  void TransferInstalledScript(const GURL& script_url,
+                               int64_t body_size,
+                               int64_t meta_data_size) {
     EXPECT_FALSE(body_handle_.is_valid());
     EXPECT_FALSE(meta_data_handle_.is_valid());
-    auto script_info = mojom::blink::ServiceWorkerScriptInfo::New();
+    auto script_info = blink::mojom::ServiceWorkerScriptInfo::New();
     script_info->script_url = script_url;
-    script_info->encoding = encoding;
-    script_info->headers = headers;
     EXPECT_EQ(MOJO_RESULT_OK,
               mojo::CreateDataPipe(nullptr, &body_handle_, &script_info->body));
     EXPECT_EQ(MOJO_RESULT_OK, mojo::CreateDataPipe(nullptr, &meta_data_handle_,
@@ -72,7 +63,7 @@
 
   void ResetManager() { manager_.reset(); }
 
-  void WaitForRequestInstalledScript(const KURL& script_url) {
+  void WaitForRequestInstalledScript(const GURL& script_url) {
     waiting_requested_url_ = script_url;
     base::RunLoop loop;
     requested_script_closure_ = loop.QuitClosure();
@@ -80,7 +71,7 @@
   }
 
  private:
-  void RequestInstalledScript(const KURL& script_url) override {
+  void RequestInstalledScript(const GURL& script_url) override {
     EXPECT_EQ(waiting_requested_url_, script_url);
     ASSERT_TRUE(requested_script_closure_);
     std::move(requested_script_closure_).Run();
@@ -98,10 +89,10 @@
   }
 
   base::OnceClosure requested_script_closure_;
-  KURL waiting_requested_url_;
+  GURL waiting_requested_url_;
 
-  mojom::blink::ServiceWorkerInstalledScriptsManagerPtr manager_;
-  mojo::Binding<mojom::blink::ServiceWorkerInstalledScriptsManagerHost>
+  blink::mojom::ServiceWorkerInstalledScriptsManagerPtr manager_;
+  mojo::Binding<blink::mojom::ServiceWorkerInstalledScriptsManagerHost>
       binding_;
 
   mojo::ScopedDataPipeProducerHandle body_handle_;
@@ -110,93 +101,96 @@
   DISALLOW_COPY_AND_ASSIGN(BrowserSideSender);
 };
 
-CrossThreadHTTPHeaderMapData ToCrossThreadHTTPHeaderMapData(
-    const WTF::HashMap<WTF::String, WTF::String>& headers) {
-  CrossThreadHTTPHeaderMapData data;
-  for (auto it : headers)
-    data.emplace_back(it.key, it.value);
-  return data;
-}
-
-}  // namespace
-
-class ServiceWorkerInstalledScriptsManagerTest : public ::testing::Test {
+class WebServiceWorkerInstalledScriptsManagerImplTest : public testing::Test {
  public:
-  ServiceWorkerInstalledScriptsManagerTest()
-      : io_thread_(Platform::Current()->CreateThread("io thread")),
-        worker_thread_(Platform::Current()->CreateThread("worker thread")),
-        io_task_runner_(io_thread_->GetSingleThreadTaskRunner()),
-        worker_task_runner_(worker_thread_->GetSingleThreadTaskRunner()) {}
+  WebServiceWorkerInstalledScriptsManagerImplTest()
+      : io_thread_("io thread"),
+        worker_thread_("worker thread"),
+        worker_waiter_(base::WaitableEvent::ResetPolicy::AUTOMATIC,
+                       base::WaitableEvent::InitialState::NOT_SIGNALED) {}
 
  protected:
-  using RawScriptData = ThreadSafeScriptContainer::RawScriptData;
+  using RawScriptData =
+      blink::WebServiceWorkerInstalledScriptsManager::RawScriptData;
 
-  void CreateInstalledScriptsManager(
-      mojom::blink::ServiceWorkerInstalledScriptsInfoPtr
-          installed_scripts_info) {
-    installed_scripts_manager_ =
-        std::make_unique<ServiceWorkerInstalledScriptsManager>(
-            std::move(installed_scripts_info->installed_urls),
-            std::move(installed_scripts_info->manager_request),
-            std::move(installed_scripts_info->manager_host_ptr),
-            io_task_runner_);
+  void SetUp() override {
+    ASSERT_TRUE(io_thread_.Start());
+    ASSERT_TRUE(worker_thread_.Start());
+    io_task_runner_ = io_thread_.task_runner();
+    worker_task_runner_ = worker_thread_.task_runner();
   }
 
-  WaitableEvent* IsScriptInstalledOnWorkerThread(const KURL& script_url,
-                                                 bool* out_installed) {
+  void TearDown() override {
+    io_thread_.Stop();
+    worker_thread_.Stop();
+  }
+
+  void CreateInstalledScriptsManager(
+      blink::mojom::ServiceWorkerInstalledScriptsInfoPtr
+          installed_scripts_info) {
+    installed_scripts_manager_ =
+        WebServiceWorkerInstalledScriptsManagerImpl::Create(
+            std::move(installed_scripts_info), io_task_runner_);
+  }
+
+  base::WaitableEvent* IsScriptInstalledOnWorkerThread(const GURL& script_url,
+                                                       bool* out_installed) {
     worker_task_runner_->PostTask(
         FROM_HERE,
-        ConvertToBaseCallback(CrossThreadBind(
-            [](ServiceWorkerInstalledScriptsManager* installed_scripts_manager,
-               const KURL& script_url, bool* out_installed,
-               WaitableEvent* waiter) {
+        base::BindOnce(
+            [](blink::WebServiceWorkerInstalledScriptsManager*
+                   installed_scripts_manager,
+               const blink::WebURL& script_url, bool* out_installed,
+               base::WaitableEvent* waiter) {
               *out_installed =
                   installed_scripts_manager->IsScriptInstalled(script_url);
               waiter->Signal();
             },
-            CrossThreadUnretained(installed_scripts_manager_.get()), script_url,
-            CrossThreadUnretained(out_installed),
-            CrossThreadUnretained(&worker_waiter_))));
+            installed_scripts_manager_.get(), script_url, out_installed,
+            &worker_waiter_));
     return &worker_waiter_;
   }
 
-  WaitableEvent* GetRawScriptDataOnWorkerThread(
-      const KURL& script_url,
+  base::WaitableEvent* GetRawScriptDataOnWorkerThread(
+      const GURL& script_url,
       std::unique_ptr<RawScriptData>* out_data) {
     worker_task_runner_->PostTask(
         FROM_HERE,
-        ConvertToBaseCallback(CrossThreadBind(
-            &ServiceWorkerInstalledScriptsManagerTest::CallGetRawScriptData,
-            CrossThreadUnretained(this), script_url,
-            CrossThreadUnretained(out_data),
-            CrossThreadUnretained(&worker_waiter_))));
+        base::BindOnce(
+            [](blink::WebServiceWorkerInstalledScriptsManager*
+                   installed_scripts_manager,
+               const blink::WebURL& script_url,
+               std::unique_ptr<RawScriptData>* out_data,
+               base::WaitableEvent* waiter) {
+              *out_data =
+                  installed_scripts_manager->GetRawScriptData(script_url);
+              waiter->Signal();
+            },
+            installed_scripts_manager_.get(), script_url, out_data,
+            &worker_waiter_));
     return &worker_waiter_;
   }
 
  private:
-  void CallGetRawScriptData(const KURL& script_url,
-                            std::unique_ptr<RawScriptData>* out_data,
-                            WaitableEvent* waiter) {
-    *out_data = installed_scripts_manager_->GetRawScriptData(script_url);
-    waiter->Signal();
-  }
+  // Provides SingleThreadTaskRunner for this test.
+  const base::MessageLoop message_loop_;
 
-  std::unique_ptr<WebThread> io_thread_;
-  std::unique_ptr<WebThread> worker_thread_;
+  base::Thread io_thread_;
+  base::Thread worker_thread_;
   scoped_refptr<base::SingleThreadTaskRunner> io_task_runner_;
   scoped_refptr<base::SingleThreadTaskRunner> worker_task_runner_;
 
-  WaitableEvent worker_waiter_;
+  base::WaitableEvent worker_waiter_;
 
-  std::unique_ptr<ServiceWorkerInstalledScriptsManager>
+  std::unique_ptr<blink::WebServiceWorkerInstalledScriptsManager>
       installed_scripts_manager_;
 
-  DISALLOW_COPY_AND_ASSIGN(ServiceWorkerInstalledScriptsManagerTest);
+  DISALLOW_COPY_AND_ASSIGN(WebServiceWorkerInstalledScriptsManagerImplTest);
 };
 
-TEST_F(ServiceWorkerInstalledScriptsManagerTest, GetRawScriptData) {
-  const KURL kScriptUrl("https://example.com/installed1.js");
-  const KURL kUnknownScriptUrl("https://example.com/not_installed.js");
+TEST_F(WebServiceWorkerInstalledScriptsManagerImplTest, GetRawScriptData) {
+  const GURL kScriptUrl = GURL("https://example.com/installed1.js");
+  const GURL kUnknownScriptUrl = GURL("https://example.com/not_installed.js");
 
   BrowserSideSender sender;
   CreateInstalledScriptsManager(sender.CreateAndBind({kScriptUrl}));
@@ -221,16 +215,11 @@
     std::unique_ptr<RawScriptData> script_data;
     const std::string kExpectedBody = "This is a script body.";
     const std::string kExpectedMetaData = "This is a meta data.";
-    const WTF::String kScriptInfoEncoding("utf8");
-    const WTF::HashMap<WTF::String, WTF::String> kScriptInfoHeaders(
-        {{"Cache-Control", "no-cache"}, {"User-Agent", "Chrome"}});
-
-    WaitableEvent* get_raw_script_data_waiter =
+    base::WaitableEvent* get_raw_script_data_waiter =
         GetRawScriptDataOnWorkerThread(kScriptUrl, &script_data);
 
     // Start transferring the script. +1 for null terminator.
-    sender.TransferInstalledScript(kScriptUrl, kScriptInfoEncoding,
-                                   kScriptInfoHeaders, kExpectedBody.size() + 1,
+    sender.TransferInstalledScript(kScriptUrl, kExpectedBody.size() + 1,
                                    kExpectedMetaData.size() + 1);
     sender.PushBody(kExpectedBody);
     sender.PushMetaData(kExpectedMetaData);
@@ -254,29 +243,22 @@
               script_data->MetaDataChunks()[0].size());
     EXPECT_STREQ(kExpectedMetaData.data(),
                  script_data->MetaDataChunks()[0].Data());
-    EXPECT_EQ(kScriptInfoEncoding, script_data->Encoding());
-    EXPECT_EQ(ToCrossThreadHTTPHeaderMapData(kScriptInfoHeaders),
-              *(script_data->TakeHeaders()));
   }
 
   {
     std::unique_ptr<RawScriptData> script_data;
     const std::string kExpectedBody = "This is another script body.";
     const std::string kExpectedMetaData = "This is another meta data.";
-    const WTF::String kScriptInfoEncoding("ASCII");
-    const WTF::HashMap<WTF::String, WTF::String> kScriptInfoHeaders(
-        {{"Connection", "keep-alive"}, {"Content-Length", "512"}});
 
     // Request the same script again.
-    WaitableEvent* get_raw_script_data_waiter =
+    base::WaitableEvent* get_raw_script_data_waiter =
         GetRawScriptDataOnWorkerThread(kScriptUrl, &script_data);
 
     // It should call a Mojo IPC "RequestInstalledScript()" to the browser.
     sender.WaitForRequestInstalledScript(kScriptUrl);
 
     // Start transferring the script. +1 for null terminator.
-    sender.TransferInstalledScript(kScriptUrl, kScriptInfoEncoding,
-                                   kScriptInfoHeaders, kExpectedBody.size() + 1,
+    sender.TransferInstalledScript(kScriptUrl, kExpectedBody.size() + 1,
                                    kExpectedMetaData.size() + 1);
     sender.PushBody(kExpectedBody);
     sender.PushMetaData(kExpectedMetaData);
@@ -300,15 +282,13 @@
               script_data->MetaDataChunks()[0].size());
     EXPECT_STREQ(kExpectedMetaData.data(),
                  script_data->MetaDataChunks()[0].Data());
-    EXPECT_EQ(kScriptInfoEncoding, script_data->Encoding());
-    EXPECT_EQ(ToCrossThreadHTTPHeaderMapData(kScriptInfoHeaders),
-              *(script_data->TakeHeaders()));
   }
 }
 
-TEST_F(ServiceWorkerInstalledScriptsManagerTest, EarlyDisconnectionBody) {
-  const KURL kScriptUrl("https://example.com/installed1.js");
-  const KURL kUnknownScriptUrl("https://example.com/not_installed.js");
+TEST_F(WebServiceWorkerInstalledScriptsManagerImplTest,
+       EarlyDisconnectionBody) {
+  const GURL kScriptUrl = GURL("https://example.com/installed1.js");
+  const GURL kUnknownScriptUrl = GURL("https://example.com/not_installed.js");
 
   BrowserSideSender sender;
   CreateInstalledScriptsManager(sender.CreateAndBind({kScriptUrl}));
@@ -317,16 +297,14 @@
     std::unique_ptr<RawScriptData> script_data;
     const std::string kExpectedBody = "This is a script body.";
     const std::string kExpectedMetaData = "This is a meta data.";
-    WaitableEvent* get_raw_script_data_waiter =
+    base::WaitableEvent* get_raw_script_data_waiter =
         GetRawScriptDataOnWorkerThread(kScriptUrl, &script_data);
 
     // Start transferring the script.
     // Body is expected to be 100 bytes larger than kExpectedBody, but sender
     // only sends kExpectedBody and a null byte (kExpectedBody.size() + 1 bytes
     // in total).
-    sender.TransferInstalledScript(kScriptUrl, WTF::String::FromUTF8("utf8"),
-                                   WTF::HashMap<WTF::String, WTF::String>(),
-                                   kExpectedBody.size() + 100,
+    sender.TransferInstalledScript(kScriptUrl, kExpectedBody.size() + 100,
                                    kExpectedMetaData.size() + 1);
     sender.PushBody(kExpectedBody);
     sender.PushMetaData(kExpectedMetaData);
@@ -354,9 +332,10 @@
   }
 }
 
-TEST_F(ServiceWorkerInstalledScriptsManagerTest, EarlyDisconnectionMetaData) {
-  const KURL kScriptUrl("https://example.com/installed1.js");
-  const KURL kUnknownScriptUrl("https://example.com/not_installed.js");
+TEST_F(WebServiceWorkerInstalledScriptsManagerImplTest,
+       EarlyDisconnectionMetaData) {
+  const GURL kScriptUrl = GURL("https://example.com/installed1.js");
+  const GURL kUnknownScriptUrl = GURL("https://example.com/not_installed.js");
 
   BrowserSideSender sender;
   CreateInstalledScriptsManager(sender.CreateAndBind({kScriptUrl}));
@@ -365,16 +344,14 @@
     std::unique_ptr<RawScriptData> script_data;
     const std::string kExpectedBody = "This is a script body.";
     const std::string kExpectedMetaData = "This is a meta data.";
-    WaitableEvent* get_raw_script_data_waiter =
+    base::WaitableEvent* get_raw_script_data_waiter =
         GetRawScriptDataOnWorkerThread(kScriptUrl, &script_data);
 
     // Start transferring the script.
     // Meta data is expected to be 100 bytes larger than kExpectedMetaData, but
     // sender only sends kExpectedMetaData and a null byte
     // (kExpectedMetaData.size() + 1 bytes in total).
-    sender.TransferInstalledScript(kScriptUrl, WTF::String::FromUTF8("utf8"),
-                                   WTF::HashMap<WTF::String, WTF::String>(),
-                                   kExpectedBody.size() + 1,
+    sender.TransferInstalledScript(kScriptUrl, kExpectedBody.size() + 1,
                                    kExpectedMetaData.size() + 100);
     sender.PushBody(kExpectedBody);
     sender.PushMetaData(kExpectedMetaData);
@@ -402,16 +379,17 @@
   }
 }
 
-TEST_F(ServiceWorkerInstalledScriptsManagerTest, EarlyDisconnectionManager) {
-  const KURL kScriptUrl("https://example.com/installed1.js");
-  const KURL kUnknownScriptUrl("https://example.com/not_installed.js");
+TEST_F(WebServiceWorkerInstalledScriptsManagerImplTest,
+       EarlyDisconnectionManager) {
+  const GURL kScriptUrl = GURL("https://example.com/installed1.js");
+  const GURL kUnknownScriptUrl = GURL("https://example.com/not_installed.js");
 
   BrowserSideSender sender;
   CreateInstalledScriptsManager(sender.CreateAndBind({kScriptUrl}));
 
   {
     std::unique_ptr<RawScriptData> script_data;
-    WaitableEvent* get_raw_script_data_waiter =
+    base::WaitableEvent* get_raw_script_data_waiter =
         GetRawScriptDataOnWorkerThread(kScriptUrl, &script_data);
 
     // Reset the Mojo connection before sending the script.
@@ -436,4 +414,4 @@
   }
 }
 
-}  // namespace blink
+}  // namespace content
diff --git a/content/renderer/service_worker/worker_fetch_context_impl.cc b/content/renderer/service_worker/worker_fetch_context_impl.cc
index 5ff6dc6..322c85f 100644
--- a/content/renderer/service_worker/worker_fetch_context_impl.cc
+++ b/content/renderer/service_worker/worker_fetch_context_impl.cc
@@ -118,8 +118,8 @@
   DCHECK(loading_task_runner->RunsTasksInCurrentSequence());
   DCHECK(!resource_dispatcher_);
   DCHECK(!binding_.is_bound());
-  resource_dispatcher_ = std::make_unique<ResourceDispatcher>(
-      nullptr, std::move(loading_task_runner));
+  resource_dispatcher_ =
+      std::make_unique<ResourceDispatcher>(std::move(loading_task_runner));
 
   url_loader_factory_getter_ = url_loader_factory_getter_info_.Bind();
   if (service_worker_client_request_.is_pending())
diff --git a/content/test/BUILD.gn b/content/test/BUILD.gn
index b09cd0d5..a6491e1 100644
--- a/content/test/BUILD.gn
+++ b/content/test/BUILD.gn
@@ -733,7 +733,6 @@
     "../browser/indexed_db/mock_browsertest_indexed_db_class_factory.cc",
     "../browser/indexed_db/mock_browsertest_indexed_db_class_factory.h",
     "../browser/isolated_origin_browsertest.cc",
-    "../browser/loader/async_resource_handler_browsertest.cc",
     "../browser/loader/cross_site_document_blocking_browsertest.cc",
     "../browser/loader/cross_site_resource_handler_browsertest.cc",
     "../browser/loader/reload_cache_control_browsertest.cc",
@@ -1295,7 +1294,6 @@
     "../browser/indexed_db/mock_mojo_indexed_db_database_callbacks.cc",
     "../browser/indexed_db/mock_mojo_indexed_db_database_callbacks.h",
     "../browser/leveldb_wrapper_impl_unittest.cc",
-    "../browser/loader/async_resource_handler_unittest.cc",
     "../browser/loader/cross_site_document_resource_handler_unittest.cc",
     "../browser/loader/detachable_resource_handler_unittest.cc",
     "../browser/loader/intercepting_resource_handler_unittest.cc",
@@ -1563,7 +1561,6 @@
     "../renderer/loader/cors_url_loader_unittest.cc",
     "../renderer/loader/resource_dispatcher_unittest.cc",
     "../renderer/loader/shared_memory_data_consumer_handle_unittest.cc",
-    "../renderer/loader/shared_memory_received_data_factory_unittest.cc",
     "../renderer/loader/site_isolation_stats_gatherer_unittest.cc",
     "../renderer/loader/test_request_peer.cc",
     "../renderer/loader/test_request_peer.h",
@@ -1590,12 +1587,13 @@
     "../renderer/presentation/test_presentation_connection.h",
     "../renderer/render_thread_impl_unittest.cc",
     "../renderer/render_widget_unittest.cc",
-    "../renderer/scheduler/resource_dispatch_throttler_unittest.cc",
     "../renderer/service_worker/service_worker_context_client_unittest.cc",
     "../renderer/service_worker/service_worker_dispatcher_unittest.cc",
     "../renderer/service_worker/service_worker_provider_context_unittest.cc",
     "../renderer/service_worker/service_worker_subresource_loader_unittest.cc",
     "../renderer/service_worker/service_worker_timeout_timer_unittest.cc",
+    "../renderer/service_worker/thread_safe_script_container_unittest.cc",
+    "../renderer/service_worker/web_service_worker_installed_scripts_manager_impl_unittest.cc",
     "../renderer/skia_benchmarking_extension_unittest.cc",
     "../renderer/v8_value_converter_impl_unittest.cc",
     "../renderer/worker_thread_registry_unittest.cc",
diff --git a/extensions/common/extension_icon_set.cc b/extensions/common/extension_icon_set.cc
index 45e0bd2e..1fb584a2 100644
--- a/extensions/common/extension_icon_set.cc
+++ b/extensions/common/extension_icon_set.cc
@@ -4,10 +4,41 @@
 
 #include "extensions/common/extension_icon_set.h"
 
+#include <vector>
+
 #include "base/files/file_path.h"
 #include "base/logging.h"
 #include "base/strings/string_util.h"
 
+namespace {
+
+// Normalize relative path that does not reference to parent directory. Removes
+// ".". Returns false if path can not be normalized, i.e. it references parent
+// or empty after normalization.
+bool NormalizeRelativePath(const base::FilePath& path, base::FilePath* result) {
+  DCHECK(result);
+
+  if (path.ReferencesParent())
+    return false;
+
+  std::vector<base::FilePath::StringType> components;
+  path.GetComponents(&components);
+
+  base::FilePath rv;
+  for (const auto& path_component : components) {
+    if (path_component != base::FilePath::kCurrentDirectory)
+      rv = rv.Append(path_component);
+  }
+
+  if (rv.empty())
+    return false;
+
+  *result = std::move(rv);
+  return true;
+}
+
+}  // namespace
+
 ExtensionIconSet::ExtensionIconSet() {}
 
 ExtensionIconSet::ExtensionIconSet(const ExtensionIconSet& other) = default;
@@ -75,6 +106,11 @@
 
 void ExtensionIconSet::GetPaths(std::set<base::FilePath>* paths) const {
   CHECK(paths);
-  for (auto iter : map())
-    paths->insert(base::FilePath::FromUTF8Unsafe(iter.second));
+  for (const auto& iter : map()) {
+    base::FilePath normalized_path;
+    if (NormalizeRelativePath(base::FilePath::FromUTF8Unsafe(iter.second),
+                              &normalized_path)) {
+      paths->emplace(std::move(normalized_path));
+    }
+  }
 }
diff --git a/extensions/common/extension_icon_set.h b/extensions/common/extension_icon_set.h
index 80d0a340..7c347d9b 100644
--- a/extensions/common/extension_icon_set.h
+++ b/extensions/common/extension_icon_set.h
@@ -44,7 +44,7 @@
   void Add(int size, const std::string& path);
 
   // Gets path value of the icon found when searching for |size| using
-  // |mathc_type|.
+  // |match_type|.
   const std::string& Get(int size, MatchType match_type) const;
 
   // Returns true iff the set contains the specified path.
diff --git a/extensions/common/extension_icon_set_unittest.cc b/extensions/common/extension_icon_set_unittest.cc
index 3903fa0..6288b610 100644
--- a/extensions/common/extension_icon_set_unittest.cc
+++ b/extensions/common/extension_icon_set_unittest.cc
@@ -90,4 +90,31 @@
             icons.GetIconSizeFromPath("foo"));
 }
 
+TEST(ExtensionIconSetTest, CollapsesSameRelativePaths) {
+  ExtensionIconSet icons;
+  icons.Add(extension_misc::EXTENSION_ICON_BITTY, "foo/icon.jpg");
+  icons.Add(extension_misc::EXTENSION_ICON_SMALL, "./foo/icon.jpg");
+  icons.Add(extension_misc::EXTENSION_ICON_LARGE, "./bar/../foo/icon.jpg");
+
+  std::set<base::FilePath> paths;
+  icons.GetPaths(&paths);
+
+  const std::set<base::FilePath> expected_paths = {
+      base::FilePath::FromUTF8Unsafe("foo").AppendASCII("icon.jpg")};
+  EXPECT_EQ(expected_paths, paths);
+}
+
+TEST(ExtensionIconSetTest, IgnoresIncorrectRelativePaths) {
+  ExtensionIconSet icons;
+  icons.Add(extension_misc::EXTENSION_ICON_BITTY, "foo/../../icon.jpg");
+  icons.Add(extension_misc::EXTENSION_ICON_SMALL, "../icon.jpg");
+  icons.Add(extension_misc::EXTENSION_ICON_LARGE, "./foo/icons/../..");
+  icons.Add(extension_misc::EXTENSION_ICON_GIGANTOR, "./foo/../..");
+
+  std::set<base::FilePath> paths;
+  icons.GetPaths(&paths);
+
+  EXPECT_TRUE(paths.empty());
+}
+
 }  // namespace
diff --git a/third_party/WebKit/LayoutTests/FlagExpectations/enable-blink-features=LayoutNG b/third_party/WebKit/LayoutTests/FlagExpectations/enable-blink-features=LayoutNG
index 7c1f4232..abf9546 100644
--- a/third_party/WebKit/LayoutTests/FlagExpectations/enable-blink-features=LayoutNG
+++ b/third_party/WebKit/LayoutTests/FlagExpectations/enable-blink-features=LayoutNG
@@ -176,10 +176,10 @@
 crbug.com/591099 compositing/geometry/composited-html-size.html [ Failure ]
 crbug.com/591099 compositing/geometry/composited-in-columns.html [ Failure ]
 crbug.com/591099 compositing/geometry/fixed-in-composited.html [ Failure ]
-crbug.com/591099 compositing/geometry/fixed-position-composited-page-scale-down.html [ Failure ]
-crbug.com/591099 compositing/geometry/fixed-position-composited-page-scale.html [ Failure ]
-crbug.com/591099 compositing/geometry/fixed-position-transform-composited-page-scale-down.html [ Failure ]
-crbug.com/591099 compositing/geometry/fixed-position-transform-composited-page-scale.html [ Failure ]
+crbug.com/591099 compositing/geometry/fixed-position-composited-page-scale-down.html [ Failure Pass ]
+crbug.com/591099 compositing/geometry/fixed-position-composited-page-scale.html [ Failure Pass ]
+crbug.com/591099 compositing/geometry/fixed-position-transform-composited-page-scale-down.html [ Failure Pass ]
+crbug.com/591099 compositing/geometry/fixed-position-transform-composited-page-scale.html [ Failure Pass ]
 crbug.com/591099 compositing/geometry/fixed-position.html [ Failure ]
 crbug.com/591099 compositing/geometry/foreground-layer.html [ Crash Failure ]
 crbug.com/591099 compositing/geometry/layer-due-to-layer-children-deep.html [ Failure ]
@@ -293,7 +293,6 @@
 crbug.com/591099 compositing/overflow/overflow-positioning.html [ Failure ]
 crbug.com/591099 compositing/overflow/overflow-scroll-with-local-image-background.html [ Failure ]
 crbug.com/591099 compositing/overflow/overflow-scroll.html [ Failure ]
-crbug.com/591099 compositing/overflow/overflow-with-negative-z-index-child.html [ Failure Pass ]
 crbug.com/591099 compositing/overflow/parent-overflow.html [ Failure ]
 crbug.com/591099 compositing/overflow/remove-overflow-crash2.html [ Failure ]
 crbug.com/714962 compositing/overflow/rtl-overflow.html [ Failure ]
@@ -2225,15 +2224,8 @@
 crbug.com/714962 external/wpt/css/CSS2/linebox/inline-formatting-context-015.xht [ Failure ]
 crbug.com/714962 external/wpt/css/CSS2/linebox/vertical-align-baseline-005a.xht [ Failure ]
 crbug.com/591099 external/wpt/css/CSS2/normal-flow/block-in-inline-percents-001.xht [ Failure ]
-crbug.com/591099 external/wpt/css/CSS2/normal-flow/block-non-replaced-width-001.xht [ Failure Pass ]
-crbug.com/591099 external/wpt/css/CSS2/normal-flow/inline-block-replaced-height-004.xht [ Failure Pass ]
-crbug.com/591099 external/wpt/css/CSS2/normal-flow/inline-block-replaced-height-005.xht [ Failure Pass ]
-crbug.com/591099 external/wpt/css/CSS2/normal-flow/inline-block-replaced-height-007.xht [ Failure Pass ]
 crbug.com/714962 external/wpt/css/CSS2/normal-flow/inline-block-zorder-001.xht [ Failure ]
 crbug.com/714962 external/wpt/css/CSS2/normal-flow/inline-block-zorder-002.xht [ Failure ]
-crbug.com/591099 external/wpt/css/CSS2/normal-flow/inline-replaced-height-004.xht [ Failure Pass ]
-crbug.com/591099 external/wpt/css/CSS2/normal-flow/inline-replaced-height-005.xht [ Failure Pass ]
-crbug.com/591099 external/wpt/css/CSS2/normal-flow/inline-replaced-height-007.xht [ Failure Pass ]
 crbug.com/714962 external/wpt/css/CSS2/normal-flow/inline-table-zorder-001.xht [ Failure ]
 crbug.com/714962 external/wpt/css/CSS2/normal-flow/inline-table-zorder-002.xht [ Failure ]
 crbug.com/591099 external/wpt/css/CSS2/normal-flow/max-height-percentage-002.xht [ Failure ]
@@ -2243,8 +2235,8 @@
 crbug.com/714962 external/wpt/css/CSS2/normal-flow/min-height-104.xht [ Failure ]
 crbug.com/714962 external/wpt/css/CSS2/normal-flow/min-height-106.xht [ Failure ]
 crbug.com/591099 external/wpt/css/CSS2/normal-flow/root-box-001.xht [ Failure ]
-crbug.com/591099 external/wpt/css/CSS2/positioning/absolute-replaced-height-001.xht [ Failure ]
-crbug.com/591099 external/wpt/css/CSS2/positioning/abspos-007.xht [ Failure Pass ]
+crbug.com/591099 external/wpt/css/CSS2/positioning/absolute-replaced-height-001.xht [ Failure Pass ]
+crbug.com/591099 external/wpt/css/CSS2/positioning/abspos-007.xht [ Failure ]
 crbug.com/591099 external/wpt/css/CSS2/positioning/relpos-calcs-004.xht [ Failure ]
 crbug.com/591099 external/wpt/css/CSS2/positioning/relpos-calcs-005.xht [ Failure ]
 crbug.com/591099 external/wpt/css/CSS2/text/text-decoration-applies-to-015.xht [ Failure ]
@@ -2418,6 +2410,14 @@
 crbug.com/591099 external/wpt/css/css-multicol/multicol-zero-height-001.xht [ Failure ]
 crbug.com/714962 external/wpt/css/css-paint-api/style-before-pseudo.https.html [ Failure ]
 crbug.com/714962 external/wpt/css/css-paint-api/style-first-letter-pseudo.https.html [ Failure ]
+crbug.com/591099 external/wpt/css/css-position/position-relative-table-tbody-left-absolute-child.html [ Crash Pass ]
+crbug.com/591099 external/wpt/css/css-position/position-relative-table-tbody-top-absolute-child.html [ Crash Pass ]
+crbug.com/591099 external/wpt/css/css-position/position-relative-table-tfoot-left-absolute-child.html [ Crash Pass ]
+crbug.com/591099 external/wpt/css/css-position/position-relative-table-tfoot-top-absolute-child.html [ Crash Pass ]
+crbug.com/591099 external/wpt/css/css-position/position-relative-table-thead-left-absolute-child.html [ Crash Pass ]
+crbug.com/591099 external/wpt/css/css-position/position-relative-table-thead-top-absolute-child.html [ Crash Pass ]
+crbug.com/591099 external/wpt/css/css-position/position-relative-table-tr-left-absolute-child.html [ Crash Pass ]
+crbug.com/591099 external/wpt/css/css-position/position-relative-table-tr-top-absolute-child.html [ Crash Pass ]
 crbug.com/591099 external/wpt/css/css-position/position-sticky-nested-inline.html [ Crash ]
 crbug.com/591099 external/wpt/css/css-position/position-sticky-writing-modes.html [ Failure Pass ]
 crbug.com/591099 external/wpt/css/css-rhythm/line-height-step-basic-001.html [ Failure ]
@@ -2628,10 +2628,10 @@
 crbug.com/714962 external/wpt/css/css-writing-modes/abs-pos-non-replaced-vlr-013.xht [ Failure ]
 crbug.com/714962 external/wpt/css/css-writing-modes/abs-pos-non-replaced-vlr-015.xht [ Failure Pass ]
 crbug.com/591099 external/wpt/css/css-writing-modes/abs-pos-non-replaced-vlr-017.xht [ Failure Pass ]
-crbug.com/714962 external/wpt/css/css-writing-modes/abs-pos-non-replaced-vlr-019.xht [ Failure ]
+crbug.com/714962 external/wpt/css/css-writing-modes/abs-pos-non-replaced-vlr-019.xht [ Failure Pass ]
 crbug.com/714962 external/wpt/css/css-writing-modes/abs-pos-non-replaced-vlr-021.xht [ Failure Pass ]
 crbug.com/714962 external/wpt/css/css-writing-modes/abs-pos-non-replaced-vlr-023.xht [ Failure Pass ]
-crbug.com/714962 external/wpt/css/css-writing-modes/abs-pos-non-replaced-vlr-025.xht [ Failure ]
+crbug.com/714962 external/wpt/css/css-writing-modes/abs-pos-non-replaced-vlr-025.xht [ Failure Pass ]
 crbug.com/714962 external/wpt/css/css-writing-modes/abs-pos-non-replaced-vlr-027.xht [ Failure Pass ]
 crbug.com/591099 external/wpt/css/css-writing-modes/abs-pos-non-replaced-vlr-029.xht [ Failure Pass ]
 crbug.com/714962 external/wpt/css/css-writing-modes/abs-pos-non-replaced-vlr-031.xht [ Failure Pass ]
@@ -2654,7 +2654,7 @@
 crbug.com/591099 external/wpt/css/css-writing-modes/abs-pos-non-replaced-vlr-065.xht [ Failure Pass ]
 crbug.com/714962 external/wpt/css/css-writing-modes/abs-pos-non-replaced-vlr-067.xht [ Failure Pass ]
 crbug.com/714962 external/wpt/css/css-writing-modes/abs-pos-non-replaced-vlr-069.xht [ Failure Pass ]
-crbug.com/714962 external/wpt/css/css-writing-modes/abs-pos-non-replaced-vlr-071.xht [ Failure Pass ]
+crbug.com/591099 external/wpt/css/css-writing-modes/abs-pos-non-replaced-vlr-071.xht [ Failure ]
 crbug.com/714962 external/wpt/css/css-writing-modes/abs-pos-non-replaced-vlr-073.xht [ Failure Pass ]
 crbug.com/714962 external/wpt/css/css-writing-modes/abs-pos-non-replaced-vlr-075.xht [ Failure ]
 crbug.com/591099 external/wpt/css/css-writing-modes/abs-pos-non-replaced-vlr-077.xht [ Failure Pass ]
@@ -2699,7 +2699,7 @@
 crbug.com/714962 external/wpt/css/css-writing-modes/abs-pos-non-replaced-vlr-159.xht [ Failure Pass ]
 crbug.com/714962 external/wpt/css/css-writing-modes/abs-pos-non-replaced-vlr-161.xht [ Failure Pass ]
 crbug.com/714962 external/wpt/css/css-writing-modes/abs-pos-non-replaced-vlr-163.xht [ Failure Pass ]
-crbug.com/714962 external/wpt/css/css-writing-modes/abs-pos-non-replaced-vlr-165.xht [ Failure ]
+crbug.com/714962 external/wpt/css/css-writing-modes/abs-pos-non-replaced-vlr-165.xht [ Failure Pass ]
 crbug.com/714962 external/wpt/css/css-writing-modes/abs-pos-non-replaced-vlr-167.xht [ Failure Pass ]
 crbug.com/591099 external/wpt/css/css-writing-modes/abs-pos-non-replaced-vlr-169.xht [ Failure Pass ]
 crbug.com/714962 external/wpt/css/css-writing-modes/abs-pos-non-replaced-vlr-171.xht [ Failure Pass ]
@@ -2712,7 +2712,7 @@
 crbug.com/591099 external/wpt/css/css-writing-modes/abs-pos-non-replaced-vlr-185.xht [ Failure Pass ]
 crbug.com/714962 external/wpt/css/css-writing-modes/abs-pos-non-replaced-vlr-187.xht [ Failure Pass ]
 crbug.com/591099 external/wpt/css/css-writing-modes/abs-pos-non-replaced-vlr-189.xht [ Failure Pass ]
-crbug.com/714962 external/wpt/css/css-writing-modes/abs-pos-non-replaced-vlr-191.xht [ Failure ]
+crbug.com/714962 external/wpt/css/css-writing-modes/abs-pos-non-replaced-vlr-191.xht [ Failure Pass ]
 crbug.com/714962 external/wpt/css/css-writing-modes/abs-pos-non-replaced-vlr-193.xht [ Failure Pass ]
 crbug.com/714962 external/wpt/css/css-writing-modes/abs-pos-non-replaced-vlr-195.xht [ Failure Pass ]
 crbug.com/714962 external/wpt/css/css-writing-modes/abs-pos-non-replaced-vlr-197.xht [ Failure Pass ]
@@ -2720,7 +2720,7 @@
 crbug.com/591099 external/wpt/css/css-writing-modes/abs-pos-non-replaced-vlr-201.xht [ Failure Pass ]
 crbug.com/714962 external/wpt/css/css-writing-modes/abs-pos-non-replaced-vlr-203.xht [ Failure Pass ]
 crbug.com/591099 external/wpt/css/css-writing-modes/abs-pos-non-replaced-vlr-205.xht [ Failure Pass ]
-crbug.com/714962 external/wpt/css/css-writing-modes/abs-pos-non-replaced-vlr-207.xht [ Failure ]
+crbug.com/714962 external/wpt/css/css-writing-modes/abs-pos-non-replaced-vlr-207.xht [ Failure Pass ]
 crbug.com/714962 external/wpt/css/css-writing-modes/abs-pos-non-replaced-vlr-209.xht [ Failure Pass ]
 crbug.com/714962 external/wpt/css/css-writing-modes/abs-pos-non-replaced-vlr-211.xht [ Failure Pass ]
 crbug.com/714962 external/wpt/css/css-writing-modes/abs-pos-non-replaced-vlr-213.xht [ Failure Pass ]
@@ -2778,7 +2778,7 @@
 crbug.com/591099 external/wpt/css/css-writing-modes/abs-pos-non-replaced-vrl-088.xht [ Failure Pass ]
 crbug.com/714962 external/wpt/css/css-writing-modes/abs-pos-non-replaced-vrl-090.xht [ Failure ]
 crbug.com/714962 external/wpt/css/css-writing-modes/abs-pos-non-replaced-vrl-092.xht [ Failure ]
-crbug.com/714962 external/wpt/css/css-writing-modes/abs-pos-non-replaced-vrl-094.xht [ Failure ]
+crbug.com/714962 external/wpt/css/css-writing-modes/abs-pos-non-replaced-vrl-094.xht [ Failure Pass ]
 crbug.com/714962 external/wpt/css/css-writing-modes/abs-pos-non-replaced-vrl-096.xht [ Failure ]
 crbug.com/714962 external/wpt/css/css-writing-modes/abs-pos-non-replaced-vrl-102.xht [ Failure ]
 crbug.com/591099 external/wpt/css/css-writing-modes/abs-pos-non-replaced-vrl-104.xht [ Failure Pass ]
@@ -2812,7 +2812,7 @@
 crbug.com/591099 external/wpt/css/css-writing-modes/abs-pos-non-replaced-vrl-160.xht [ Failure Pass ]
 crbug.com/714962 external/wpt/css/css-writing-modes/abs-pos-non-replaced-vrl-162.xht [ Failure ]
 crbug.com/714962 external/wpt/css/css-writing-modes/abs-pos-non-replaced-vrl-164.xht [ Failure ]
-crbug.com/714962 external/wpt/css/css-writing-modes/abs-pos-non-replaced-vrl-166.xht [ Failure ]
+crbug.com/714962 external/wpt/css/css-writing-modes/abs-pos-non-replaced-vrl-166.xht [ Failure Pass ]
 crbug.com/714962 external/wpt/css/css-writing-modes/abs-pos-non-replaced-vrl-168.xht [ Failure Pass ]
 crbug.com/714962 external/wpt/css/css-writing-modes/abs-pos-non-replaced-vrl-170.xht [ Failure ]
 crbug.com/591099 external/wpt/css/css-writing-modes/abs-pos-non-replaced-vrl-172.xht [ Failure Pass ]
@@ -2829,7 +2829,7 @@
 crbug.com/714962 external/wpt/css/css-writing-modes/abs-pos-non-replaced-vrl-194.xht [ Failure ]
 crbug.com/714962 external/wpt/css/css-writing-modes/abs-pos-non-replaced-vrl-196.xht [ Failure Pass ]
 crbug.com/714962 external/wpt/css/css-writing-modes/abs-pos-non-replaced-vrl-198.xht [ Failure ]
-crbug.com/714962 external/wpt/css/css-writing-modes/abs-pos-non-replaced-vrl-200.xht [ Failure ]
+crbug.com/714962 external/wpt/css/css-writing-modes/abs-pos-non-replaced-vrl-200.xht [ Failure Pass ]
 crbug.com/714962 external/wpt/css/css-writing-modes/abs-pos-non-replaced-vrl-202.xht [ Failure ]
 crbug.com/591099 external/wpt/css/css-writing-modes/abs-pos-non-replaced-vrl-204.xht [ Failure Pass ]
 crbug.com/714962 external/wpt/css/css-writing-modes/abs-pos-non-replaced-vrl-206.xht [ Failure ]
@@ -2869,7 +2869,7 @@
 crbug.com/591099 external/wpt/css/css-writing-modes/float-contiguous-vrl-008.xht [ Failure ]
 crbug.com/714962 external/wpt/css/css-writing-modes/float-shrink-to-fit-vrl-008.xht [ Failure ]
 crbug.com/714962 external/wpt/css/css-writing-modes/float-vlr-005.xht [ Failure Pass ]
-crbug.com/714962 external/wpt/css/css-writing-modes/float-vlr-007.xht [ Failure ]
+crbug.com/714962 external/wpt/css/css-writing-modes/float-vlr-007.xht [ Failure Pass ]
 crbug.com/591099 external/wpt/css/css-writing-modes/float-vlr-013.xht [ Failure ]
 crbug.com/591099 external/wpt/css/css-writing-modes/float-vrl-004.xht [ Failure Pass ]
 crbug.com/591099 external/wpt/css/css-writing-modes/float-vrl-006.xht [ Failure Pass ]
@@ -2946,8 +2946,8 @@
 crbug.com/714962 external/wpt/css/css-writing-modes/text-align-vlr-005.xht [ Failure Pass ]
 crbug.com/714962 external/wpt/css/css-writing-modes/text-align-vlr-007.xht [ Failure Pass ]
 crbug.com/714962 external/wpt/css/css-writing-modes/text-align-vlr-009.xht [ Failure Pass ]
-crbug.com/714962 external/wpt/css/css-writing-modes/text-align-vlr-011.xht [ Failure Pass ]
-crbug.com/714962 external/wpt/css/css-writing-modes/text-align-vlr-013.xht [ Failure ]
+crbug.com/591099 external/wpt/css/css-writing-modes/text-align-vlr-011.xht [ Failure ]
+crbug.com/714962 external/wpt/css/css-writing-modes/text-align-vlr-013.xht [ Failure Pass ]
 crbug.com/714962 external/wpt/css/css-writing-modes/text-align-vlr-015.xht [ Failure Pass ]
 crbug.com/714962 external/wpt/css/css-writing-modes/text-align-vlr-017.xht [ Failure Pass ]
 crbug.com/714962 external/wpt/css/css-writing-modes/text-align-vlr-019.xht [ Failure Pass ]
@@ -3474,7 +3474,7 @@
 crbug.com/591099 fast/block/float/float-in-float-hit-testing.html [ Failure ]
 crbug.com/591099 fast/block/float/float-in-float-painting.html [ Failure ]
 crbug.com/591099 fast/block/float/float-inserted-into-clean-line.html [ Failure ]
-crbug.com/591099 fast/block/float/float-on-line-obeys-container-padding.html [ Failure ]
+crbug.com/591099 fast/block/float/float-on-line-obeys-container-padding.html [ Failure Pass ]
 crbug.com/714962 fast/block/float/float-should-dirty-line-when-adjacent-to-line-breaks-2.html [ Failure ]
 crbug.com/714962 fast/block/float/float-should-dirty-line-when-adjacent-to-line-breaks.html [ Failure ]
 crbug.com/591099 fast/block/float/floats-and-text-indent-rl.html [ Failure ]
@@ -3526,7 +3526,7 @@
 crbug.com/591099 fast/block/positioning/059.html [ Failure ]
 crbug.com/591099 fast/block/positioning/061.html [ Failure ]
 crbug.com/591099 fast/block/positioning/abs-inside-inline-rel.html [ Crash ]
-crbug.com/591099 fast/block/positioning/absolute-appended-to-inline.html [ Failure ]
+crbug.com/591099 fast/block/positioning/absolute-appended-to-inline.html [ Failure Pass ]
 crbug.com/591099 fast/block/positioning/absolute-in-inline-dynamic.html [ Failure ]
 crbug.com/591099 fast/block/positioning/absolute-in-inline-ltr-2.html [ Crash Failure ]
 crbug.com/591099 fast/block/positioning/absolute-in-inline-ltr-3.html [ Crash Failure ]
@@ -3540,19 +3540,17 @@
 crbug.com/591099 fast/block/positioning/abspos-auto-left-and-width-change-parent-margin-left.html [ Failure ]
 crbug.com/591099 fast/block/positioning/abspositioned-object-under-split-relpositioned-inline-crash.html [ Crash ]
 crbug.com/591099 fast/block/positioning/auto-height-with-top-and-bottom.html [ Failure ]
-crbug.com/591099 fast/block/positioning/auto/005.html [ Failure ]
-crbug.com/591099 fast/block/positioning/auto/vertical-lr/005.html [ Failure ]
+crbug.com/591099 fast/block/positioning/auto/005.html [ Failure Pass ]
+crbug.com/591099 fast/block/positioning/auto/vertical-lr/005.html [ Failure Pass ]
 crbug.com/591099 fast/block/positioning/auto/vertical-lr/007.html [ Failure ]
-crbug.com/591099 fast/block/positioning/auto/vertical-rl/005.html [ Failure ]
+crbug.com/591099 fast/block/positioning/auto/vertical-rl/005.html [ Failure Pass ]
 crbug.com/714962 fast/block/positioning/auto/vertical-rl/006.html [ Failure ]
 crbug.com/591099 fast/block/positioning/auto/vertical-rl/007.html [ Failure ]
 crbug.com/591099 fast/block/positioning/child-of-fixed-pos-after-movement.html [ Crash ]
 crbug.com/591099 fast/block/positioning/complex-positioned-movement-inline-ancestor.html [ Crash ]
 crbug.com/591099 fast/block/positioning/complex-positioned-movement-inline.html [ Crash ]
 crbug.com/591099 fast/block/positioning/fixed-in-abs-height-change.html [ Crash ]
-crbug.com/591099 fast/block/positioning/fixed-positioning-scrollbar-bug.html [ Failure Pass ]
 crbug.com/591099 fast/block/positioning/hittest-on-relative-positioned-children.html [ Failure ]
-crbug.com/591099 fast/block/positioning/inline-block-relposition.html [ Failure Pass ]
 crbug.com/591099 fast/block/positioning/insert-positioned-in-anonymous-crash.html [ Crash ]
 crbug.com/591099 fast/block/positioning/leftmargin-topmargin.html [ Failure ]
 crbug.com/591099 fast/block/positioning/move-with-auto-width.html [ Failure ]
@@ -3560,16 +3558,18 @@
 crbug.com/591099 fast/block/positioning/positioned-child-inside-relative-positioned-anonymous-block.html [ Crash ]
 crbug.com/591099 fast/block/positioning/positioned-movement-layout-when-height-changes.html [ Crash ]
 crbug.com/591099 fast/block/positioning/rel-positioned-inline-changes-width.html [ Crash ]
-crbug.com/591099 fast/block/positioning/relative-overflow-block.html [ Failure ]
+crbug.com/591099 fast/block/positioning/relative-overflow-block.html [ Failure Pass ]
 crbug.com/591099 fast/block/positioning/relative-overflow-replaced.html [ Failure ]
 crbug.com/591099 fast/block/positioning/relayout-nested-positioned-elements-crash-2.html [ Failure ]
 crbug.com/591099 fast/block/positioning/removing-inside-relpositioned-inline-crash.html [ Crash ]
 crbug.com/591099 fast/block/positioning/rtl-static-positioning.html [ Failure ]
 crbug.com/591099 fast/block/positioning/table-cell-static-position.html [ Failure Pass ]
+crbug.com/591099 fast/block/positioning/trailing-space-test.html [ Failure Pass ]
 crbug.com/591099 fast/block/positioning/vertical-lr/001.html [ Failure ]
 crbug.com/591099 fast/block/positioning/vertical-rl/001.html [ Failure ]
 crbug.com/591099 fast/block/positioning/vertical-rl/002.html [ Failure ]
 crbug.com/591099 fast/block/scrollbar-wider-than-border-box.html [ Failure ]
+crbug.com/591099 fast/block/sticky-position-containing-block-crash.html [ Crash Pass ]
 crbug.com/591099 fast/block/strip-anonymous-blocks-when-block-child-becomes-float.html [ Failure ]
 crbug.com/591099 fast/block/update-midpoints-for-trailing-boxes-crash.html [ Failure Pass ]
 crbug.com/591099 fast/body-propagation/background-color/001-xhtml.xhtml [ Failure ]
@@ -3715,16 +3715,14 @@
 crbug.com/714962 fast/canvas/image-object-in-canvas.html [ Failure ]
 crbug.com/591099 fast/canvas/patternfill-repeat.html [ Failure ]
 crbug.com/714962 fast/canvas/setWidthResetAfterForcedRender.html [ Crash Failure ]
-crbug.com/591099 fast/clip/001.html [ Failure Pass ]
-crbug.com/591099 fast/clip/004.html [ Failure ]
-crbug.com/591099 fast/clip/009.html [ Failure ]
-crbug.com/591099 fast/clip/010.html [ Failure ]
-crbug.com/591099 fast/clip/011.html [ Failure ]
-crbug.com/591099 fast/clip/012.html [ Failure ]
-crbug.com/591099 fast/clip/013.html [ Failure ]
-crbug.com/591099 fast/clip/014.html [ Failure ]
-crbug.com/591099 fast/clip/nestedTransparencyClip.html [ Failure Pass ]
-crbug.com/591099 fast/clip/outline-overflowClip.html [ Failure ]
+crbug.com/591099 fast/clip/004.html [ Failure Pass ]
+crbug.com/591099 fast/clip/009.html [ Failure Pass ]
+crbug.com/591099 fast/clip/010.html [ Failure Pass ]
+crbug.com/591099 fast/clip/011.html [ Failure Pass ]
+crbug.com/591099 fast/clip/012.html [ Failure Pass ]
+crbug.com/591099 fast/clip/013.html [ Failure Pass ]
+crbug.com/591099 fast/clip/014.html [ Failure Pass ]
+crbug.com/591099 fast/clip/outline-overflowClip.html [ Failure Pass ]
 crbug.com/591099 fast/clip/overflow-border-radius-combinations.html [ Failure ]
 crbug.com/591099 fast/clip/overflow-border-radius-composited-parent.html [ Failure ]
 crbug.com/591099 fast/clip/overflow-border-radius-composited.html [ Failure ]
@@ -4176,7 +4174,6 @@
 crbug.com/714962 fast/css/sticky/replaced-sticky.html [ Failure ]
 crbug.com/714962 fast/css/sticky/sticky-both-sides-bottom-right-constrained.html [ Failure ]
 crbug.com/591099 fast/css/sticky/sticky-top-overflow-scroll-by-fragment.html [ Crash Failure ]
-crbug.com/591099 fast/css/sticky/sticky-vertically-overconstrained.html [ Failure Pass ]
 crbug.com/591099 fast/css/style-outside-head.html [ Failure ]
 crbug.com/591099 fast/css/style-parsed-outside-head.html [ Failure ]
 crbug.com/591099 fast/css/table-text-align-quirk.html [ Failure ]
@@ -4569,7 +4566,7 @@
 crbug.com/591099 fast/events/submit-reset-nested-bubble.html [ Failure ]
 crbug.com/591099 fast/events/tab-imagemap.html [ Failure ]
 crbug.com/591099 fast/events/tabindex-focus-blur-all.html [ Crash ]
-crbug.com/591099 fast/events/touch/compositor-touch-hit-rects-non-composited-scroll.html [ Failure ]
+crbug.com/591099 fast/events/touch/compositor-touch-hit-rects-non-composited-scroll.html [ Failure Pass ]
 crbug.com/591099 fast/events/touch/compositor-touch-hit-rects-scroll.html [ Failure ]
 crbug.com/591099 fast/events/touch/compositor-touch-hit-rects.html [ Failure ]
 crbug.com/591099 fast/events/touch/gesture/gesture-click-on-inline-continations.html [ Failure ]
@@ -5763,7 +5760,7 @@
 crbug.com/714962 fast/overflow/005.html [ Failure ]
 crbug.com/714962 fast/overflow/006.html [ Failure ]
 crbug.com/591099 fast/overflow/007.html [ Failure ]
-crbug.com/591099 fast/overflow/add-visual-overflow-and-change-container-position.html [ Failure ]
+crbug.com/591099 fast/overflow/add-visual-overflow-and-change-container-position.html [ Failure Pass ]
 crbug.com/714962 fast/overflow/childFocusRingClip.html [ Failure ]
 crbug.com/714962 fast/overflow/dynamic-hidden.html [ Failure ]
 crbug.com/591099 fast/overflow/height-during-simplified-layout.html [ Failure ]
@@ -6201,7 +6198,6 @@
 crbug.com/591099 fast/table/change-row-border-width-floating-container.html [ Failure ]
 crbug.com/591099 fast/table/change-table-border-width.html [ Failure ]
 crbug.com/591099 fast/table/change-tbody-border-width.html [ Failure ]
-crbug.com/591099 fast/table/collapsed-border-overflow-hidden.html [ Failure Pass ]
 crbug.com/591099 fast/table/column-in-inline.html [ Failure ]
 crbug.com/591099 fast/table/dynamic-descendant-percentage-height.html [ Failure ]
 crbug.com/591099 fast/table/empty-table-percent-height.html [ Failure ]
@@ -6351,7 +6347,6 @@
 crbug.com/714962 fast/text/ellipsis-in-justified-text.html [ Failure ]
 crbug.com/591099 fast/text/ellipsis-in-relative-inline-right.html [ Failure ]
 crbug.com/591099 fast/text/ellipsis-in-relative-inline.html [ Failure ]
-crbug.com/591099 fast/text/ellipsis-ltr-text-in-ltr-flow-underline.html [ Failure Pass ]
 crbug.com/591099 fast/text/ellipsis-ltr-text-in-rtl-flow-leading-space.html [ Failure ]
 crbug.com/591099 fast/text/ellipsis-ltr-text-in-rtl-flow-underline.html [ Failure ]
 crbug.com/591099 fast/text/ellipsis-ltr-text-in-rtl-flow.html [ Failure ]
@@ -6362,7 +6357,6 @@
 crbug.com/591099 fast/text/ellipsis-platform-font-change.html [ Failure ]
 crbug.com/591099 fast/text/ellipsis-rtl-text-in-ltr-flow-underline.html [ Failure ]
 crbug.com/591099 fast/text/ellipsis-rtl-text-in-ltr-flow.html [ Failure ]
-crbug.com/591099 fast/text/ellipsis-rtl-text-in-rtl-flow-underline.html [ Failure Pass ]
 crbug.com/591099 fast/text/ellipsis-with-list-marker-in-ltr-flow.html [ Failure ]
 crbug.com/591099 fast/text/ellipsis-with-list-marker-in-rtl-flow.html [ Failure ]
 crbug.com/591099 fast/text/emoji-web-font.html [ Pass ]
@@ -6375,7 +6369,7 @@
 crbug.com/591099 fast/text/find-kana.html [ Timeout ]
 crbug.com/714962 fast/text/font-fallback-synthetic-italics.html [ Failure ]
 crbug.com/714962 fast/text/font-ligature-letter-spacing.html [ Failure ]
-crbug.com/591099 fast/text/font-smallcaps-layout.html [ Failure ]
+crbug.com/591099 fast/text/font-smallcaps-layout.html [ Failure Pass ]
 crbug.com/714962 fast/text/font-variant-width.html [ Failure ]
 crbug.com/714962 fast/text/fractional-word-and-letter-spacing-with-kerning.html [ Failure ]
 crbug.com/714962 fast/text/get-client-rects-grapheme.html [ Failure ]
@@ -6648,6 +6642,7 @@
 crbug.com/591099 fullscreen/full-screen-css.html [ Crash ]
 crbug.com/591099 fullscreen/full-screen-element-stack.html [ Crash ]
 crbug.com/591099 fullscreen/full-screen-iframe-not-allowed.html [ Failure Timeout ]
+crbug.com/591099 fullscreen/full-screen-remove-ancestor-after.html [ Crash ]
 crbug.com/591099 fullscreen/full-screen-ruleset-crash.html [ Crash Pass ]
 crbug.com/591099 fullscreen/full-screen-twice-newapi.html [ Crash ]
 crbug.com/591099 fullscreen/full-screen-with-css-reference-filter.html [ Crash ]
@@ -6828,10 +6823,10 @@
 crbug.com/714962 http/tests/devtools/elements/edit/undo-dom-edits-2.js [ Crash ]
 crbug.com/714962 http/tests/devtools/elements/edit/undo-dom-edits.js [ Crash ]
 crbug.com/714962 http/tests/devtools/elements/edit/undo-set-outer-html-2.js [ Crash ]
-crbug.com/714962 http/tests/devtools/elements/edit/undo-set-outer-html.js [ Crash ]
+crbug.com/591099 http/tests/devtools/elements/edit/undo-set-outer-html.js [ Crash ]
 crbug.com/591099 http/tests/devtools/elements/elements-delete-inline-style.js [ Crash Pass ]
 crbug.com/714962 http/tests/devtools/elements/elements-linkify-attributes.js [ Crash Pass ]
-crbug.com/714962 http/tests/devtools/elements/elements-panel-limited-children.js [ Crash Pass ]
+crbug.com/591099 http/tests/devtools/elements/elements-panel-limited-children.js [ Crash ]
 crbug.com/591099 http/tests/devtools/elements/elements-panel-rewrite-href.js [ Crash Failure Pass ]
 crbug.com/591099 http/tests/devtools/elements/elements-panel-search.js [ Crash Pass ]
 crbug.com/714962 http/tests/devtools/elements/elements-panel-selection-after-delete.js [ Crash ]
@@ -7146,13 +7141,11 @@
 crbug.com/714962 ietestcenter/css3/multicolumn/column-width-applies-to-003.htm [ Failure ]
 crbug.com/714962 ietestcenter/css3/multicolumn/column-width-applies-to-004.htm [ Failure ]
 crbug.com/591099 ietestcenter/css3/multicolumn/column-width-applies-to-007.htm [ Failure Pass ]
-crbug.com/591099 ietestcenter/css3/multicolumn/column-width-applies-to-008.htm [ Failure Pass ]
 crbug.com/591099 ietestcenter/css3/multicolumn/column-width-applies-to-009.htm [ Failure ]
 crbug.com/591099 ietestcenter/css3/multicolumn/column-width-applies-to-010.htm [ Failure ]
 crbug.com/591099 ietestcenter/css3/multicolumn/column-width-applies-to-012.htm [ Failure ]
 crbug.com/714962 ietestcenter/css3/multicolumn/column-width-applies-to-013.htm [ Failure ]
 crbug.com/591099 ietestcenter/css3/multicolumn/column-width-applies-to-014.htm [ Failure ]
-crbug.com/714962 ietestcenter/css3/multicolumn/column-width-applies-to-015.htm [ Failure Pass ]
 crbug.com/591099 ietestcenter/css3/text/textshadow-002.htm [ Failure ]
 crbug.com/714962 ietestcenter/css3/text/textshadow-003.htm [ Failure ]
 crbug.com/591099 ietestcenter/css3/text/textshadow-010.htm [ Failure ]
@@ -7177,6 +7170,7 @@
 crbug.com/591099 images/color-profile-layer-filter.html [ Failure ]
 crbug.com/591099 images/color-profile-layer.html [ Failure ]
 crbug.com/591099 images/color-profile-mask-image-svg.html [ Failure ]
+crbug.com/591099 images/color-profile-munsell-adobe-to-srgb.html [ Failure ]
 crbug.com/591099 images/color-profile-svg-foreign-object.html [ Failure ]
 crbug.com/591099 images/cross-fade-background-size.html [ Failure ]
 crbug.com/591099 images/cross-fade-blending.html [ Failure ]
@@ -7374,7 +7368,6 @@
 crbug.com/714962 paint/invalidation/caret-outside-block.html [ Failure ]
 crbug.com/714962 paint/invalidation/caret-subpixel.html [ Failure ]
 crbug.com/591099 paint/invalidation/clip/caret-ancestor-clip-change.html [ Failure ]
-crbug.com/591099 paint/invalidation/clip/clip-unclip-and-change.html [ Failure Pass ]
 crbug.com/591099 paint/invalidation/clip/clip-with-layout-delta.html [ Failure ]
 crbug.com/591099 paint/invalidation/clip/clip-with-transform-resize.html [ Failure ]
 crbug.com/591099 paint/invalidation/clip/clipped-relative.html [ Failure ]
@@ -7412,7 +7405,6 @@
 crbug.com/591099 paint/invalidation/compositing/invalidate-when-leaving-squashed-layer.html [ Failure ]
 crbug.com/591099 paint/invalidation/compositing/layer-repaint-rects.html [ Failure ]
 crbug.com/591099 paint/invalidation/compositing/layer-repaint.html [ Failure ]
-crbug.com/591099 paint/invalidation/compositing/multi-subsequence-composited.html [ Failure Pass ]
 crbug.com/591099 paint/invalidation/compositing/new-stacking-context.html [ Failure ]
 crbug.com/591099 paint/invalidation/compositing/opacity-between-absolute.html [ Failure ]
 crbug.com/591099 paint/invalidation/compositing/opacity-between-absolute2.html [ Failure ]
@@ -7601,7 +7593,7 @@
 crbug.com/591099 paint/invalidation/overflow/opacity-change-on-overflow-float.html [ Failure ]
 crbug.com/591099 paint/invalidation/overflow/overflow-changed-on-child-of-composited-layer.html [ Failure ]
 crbug.com/714962 paint/invalidation/overflow/overflow-delete-line.html [ Failure ]
-crbug.com/591099 paint/invalidation/overflow/overflow-hidden-to-visible.html [ Failure ]
+crbug.com/591099 paint/invalidation/overflow/overflow-hidden-to-visible.html [ Failure Pass ]
 crbug.com/591099 paint/invalidation/overflow/overflow-hide.html [ Failure ]
 crbug.com/591099 paint/invalidation/overflow/overflow-into-content.html [ Failure ]
 crbug.com/714962 paint/invalidation/overflow/overflow-outline-repaint.html [ Failure ]
@@ -8633,7 +8625,6 @@
 crbug.com/714962 tables/mozilla/bugs/bug48827.html [ Failure ]
 crbug.com/591099 tables/mozilla/bugs/bug50695-1.html [ Failure ]
 crbug.com/591099 tables/mozilla/bugs/bug50695-2.html [ Failure ]
-crbug.com/591099 tables/mozilla/bugs/bug51140.html [ Failure Pass ]
 crbug.com/714962 tables/mozilla/bugs/bug5188.html [ Failure ]
 crbug.com/591099 tables/mozilla/bugs/bug53690-2.html [ Failure ]
 crbug.com/591099 tables/mozilla/bugs/bug5538.html [ Failure ]
@@ -8934,6 +8925,7 @@
 crbug.com/591099 virtual/gpu-rasterization/images/color-profile-layer-filter.html [ Timeout ]
 crbug.com/591099 virtual/gpu-rasterization/images/color-profile-layer.html [ Failure ]
 crbug.com/591099 virtual/gpu-rasterization/images/color-profile-mask-image-svg.html [ Failure ]
+crbug.com/591099 virtual/gpu-rasterization/images/color-profile-munsell-adobe-to-srgb.html [ Failure ]
 crbug.com/591099 virtual/gpu-rasterization/images/color-profile-reflection.html [ Failure Timeout ]
 crbug.com/591099 virtual/gpu-rasterization/images/color-profile-svg-foreign-object.html [ Failure ]
 crbug.com/591099 virtual/gpu-rasterization/images/cross-fade-background-size.html [ Failure ]
@@ -9176,7 +9168,7 @@
 crbug.com/591099 virtual/mouseevent_fractional/fast/events/submit-reset-nested-bubble.html [ Failure ]
 crbug.com/591099 virtual/mouseevent_fractional/fast/events/tab-imagemap.html [ Failure ]
 crbug.com/591099 virtual/mouseevent_fractional/fast/events/tabindex-focus-blur-all.html [ Crash ]
-crbug.com/591099 virtual/mouseevent_fractional/fast/events/touch/compositor-touch-hit-rects-non-composited-scroll.html [ Failure ]
+crbug.com/591099 virtual/mouseevent_fractional/fast/events/touch/compositor-touch-hit-rects-non-composited-scroll.html [ Failure Pass ]
 crbug.com/591099 virtual/mouseevent_fractional/fast/events/touch/compositor-touch-hit-rects-scroll.html [ Failure ]
 crbug.com/591099 virtual/mouseevent_fractional/fast/events/touch/compositor-touch-hit-rects.html [ Failure ]
 crbug.com/591099 virtual/mouseevent_fractional/fast/events/touch/gesture/gesture-click-on-inline-continations.html [ Failure ]
@@ -9224,7 +9216,6 @@
 crbug.com/591099 virtual/scroll_customization/ [ Skip ]
 crbug.com/591099 virtual/scroll_customization/fast/events/touch/compositor-touch-hit-rects-animation.html [ Pass ]
 crbug.com/591099 virtual/scroll_customization/fast/events/touch/compositor-touch-hit-rects-global.html [ Pass ]
-crbug.com/591099 virtual/scroll_customization/fast/events/touch/compositor-touch-hit-rects-non-composited-scroll.html [ Failure ]
 crbug.com/591099 virtual/scroll_customization/fast/events/touch/compositor-touch-hit-rects-transform-changed-nolayout.html [ Pass ]
 crbug.com/591099 virtual/scroll_customization/fast/events/touch/compositor-touch-hit-rects.html [ Failure ]
 crbug.com/591099 virtual/service-worker-script-streaming/ [ Skip ]
diff --git a/third_party/WebKit/LayoutTests/LeakExpectations b/third_party/WebKit/LayoutTests/LeakExpectations
index 3b13355..1aa0639 100644
--- a/third_party/WebKit/LayoutTests/LeakExpectations
+++ b/third_party/WebKit/LayoutTests/LeakExpectations
@@ -42,9 +42,6 @@
 crbug.com/762353 external/wpt/beacon/headers/header-referrer-no-referrer.html [ Leak Pass ]
 crbug.com/651742 external/wpt/content-security-policy/connect-src/connect-src-beacon-allowed.sub.html [ Leak Pass ]
 crbug.com/780386 external/wpt/html/dom/reflection-grouping.html [ Leak Pass ]
-crbug.com/796944 [ Linux ] external/wpt/fetch/api/request/request-keepalive-quota.html [ Leak Pass ]
-crbug.com/796944 [ Linux ] virtual/mojo-blobs/external/wpt/fetch/api/request/request-keepalive-quota.html [ Leak Pass ]
-crbug.com/796944 [ Linux ] virtual/outofblink-cors/external/wpt/fetch/api/request/request-keepalive-quota.html [ Leak Pass ]
 crbug.com/796944 [ Linux ] synthetic_gestures/synthetic-pinch-zoom-gesture.html [ Leak Pass ]
 
 # -----------------------------------------------------------------
diff --git a/third_party/WebKit/LayoutTests/external/wpt/fetch/api/request/request-keepalive-quota.html b/third_party/WebKit/LayoutTests/external/wpt/fetch/api/request/request-keepalive-quota.html
index 079346b1..19596cea 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/fetch/api/request/request-keepalive-quota.html
+++ b/third_party/WebKit/LayoutTests/external/wpt/fetch/api/request/request-keepalive-quota.html
@@ -64,10 +64,10 @@
             // Ensure only the correct amount of Quota becomes available when a fetch completes.
             promise_test(function(test) {
                 // Create a fetch that uses all but 1 Byte of the Quota and runs for 2x as long as the other requests.
-                var first = fetchKeepAliveRequest(standardDelay * 2, expectedQuota - 1);
+                const first = fetchKeepAliveRequest(standardDelay * 2, expectedQuota - 1);
 
                 // Now create a single Byte request that will complete quicker.
-                let second = fetchKeepAliveRequest(standardDelay, 1 /* bodySize */).then(() => {
+                const second = fetchKeepAliveRequest(standardDelay, 1 /* bodySize */).then(() => {
                     // We shouldn't be able to create a 2 Byte request right now as only 1 Byte should have freed up.
                     return promise_rejects(test, TypeError(), fetchKeepAliveRequest(noDelay, 2 /* bodySize */));
                 }).then(() => {
@@ -81,9 +81,10 @@
             // Test rejecting a fetch() after the quota is used up.
             promise_test(function (test) {
                 // Fill our Quota then try to send a second fetch.
-                fetchKeepAliveRequest(standardDelay, expectedQuota);
+                const p = fetchKeepAliveRequest(standardDelay, expectedQuota);
 
-                return promise_rejects(test, TypeError(), fetchKeepAliveRequest(noDelay, 1 /* bodySize */));
+                const q = promise_rejects(test, TypeError(), fetchKeepAliveRequest(noDelay, 1 /* bodySize */));
+                return Promise.all([p, q]);
             }, 'A Keep-Alive fetch() should not be allowed if the Quota is used up.');
 
         </script>
diff --git a/third_party/WebKit/LayoutTests/platform/win7/external/wpt/fetch/api/request/request-keepalive-quota-expected.txt b/third_party/WebKit/LayoutTests/platform/win7/external/wpt/fetch/api/request/request-keepalive-quota-expected.txt
index a4f1254..14d6d4c0 100644
--- a/third_party/WebKit/LayoutTests/platform/win7/external/wpt/fetch/api/request/request-keepalive-quota-expected.txt
+++ b/third_party/WebKit/LayoutTests/platform/win7/external/wpt/fetch/api/request/request-keepalive-quota-expected.txt
@@ -4,6 +4,6 @@
 PASS A Keep-Alive fetch() with a body over the Quota Limit should reject.
 FAIL A Keep-Alive fetch() should return its allocated Quota upon promise resolution. promise_test: Unhandled rejection with value: object "TypeError: Failed to fetch"
 FAIL A Keep-Alive fetch() should return only its allocated Quota upon promise resolution. promise_test: Unhandled rejection with value: object "TypeError: Failed to fetch"
-PASS A Keep-Alive fetch() should not be allowed if the Quota is used up.
+FAIL A Keep-Alive fetch() should not be allowed if the Quota is used up. promise_test: Unhandled rejection with value: object "TypeError: Failed to fetch"
 Harness: the test ran to completion.
 
diff --git a/third_party/WebKit/Source/bindings/core/v8/BUILD.gn b/third_party/WebKit/Source/bindings/core/v8/BUILD.gn
index d064a31..4e4393f 100644
--- a/third_party/WebKit/Source/bindings/core/v8/BUILD.gn
+++ b/third_party/WebKit/Source/bindings/core/v8/BUILD.gn
@@ -64,6 +64,8 @@
   "$bindings_core_v8_output_dir/node_or_string.h",
   "$bindings_core_v8_output_dir/radio_node_list_or_element.cc",
   "$bindings_core_v8_output_dir/radio_node_list_or_element.h",
+  "$bindings_core_v8_output_dir/request_or_usv_string.cc",
+  "$bindings_core_v8_output_dir/request_or_usv_string.h",
   "$bindings_core_v8_output_dir/scroll_into_view_options_or_boolean.cc",
   "$bindings_core_v8_output_dir/scroll_into_view_options_or_boolean.h",
   "$bindings_core_v8_output_dir/string_or_array_buffer.cc",
@@ -134,6 +136,8 @@
   "$bindings_core_v8_output_dir/v8_resize_observer_callback.h",
   "$bindings_core_v8_output_dir/v8_update_function.cc",
   "$bindings_core_v8_output_dir/v8_update_function.h",
+  "$bindings_core_v8_output_dir/v8_void_function.cc",
+  "$bindings_core_v8_output_dir/v8_void_function.h",
 ]
 
 generate_origin_trial_features("bindings_core_origin_trial_features") {
@@ -147,8 +151,11 @@
   ]
 }
 
-if (is_win || use_jumbo_build) {
+if ((is_win && is_official_build) || use_jumbo_build) {
   # On Windows Official release builds, we try to preserve symbol space.
+  # is_official_build adds /GL option and /LTCG is automatically enabled in
+  # link.exe. But link.exe cannot make binary smaller than its size limit from
+  # many obj files for bindings_core_impl.lib.
   bindings_core_generated_interface_files =
       [ "$bindings_core_v8_output_dir/V8GeneratedCoreBindings.cpp" ]
 } else {
@@ -175,7 +182,7 @@
   public_deps = [
     ":bindings_core_impl_generated",
   ]
-  if (is_win || use_jumbo_build) {
+  if ((is_win && is_official_build) || use_jumbo_build) {
     public_deps += [ ":generate_bindings_core_v8_all_interfaces" ]
   } else {
     public_deps += [ ":generate_bindings_core_v8_interfaces" ]
diff --git a/third_party/WebKit/Source/bindings/modules/v8/generated.gni b/third_party/WebKit/Source/bindings/modules/v8/generated.gni
index 1118887..5fd6d68 100644
--- a/third_party/WebKit/Source/bindings/modules/v8/generated.gni
+++ b/third_party/WebKit/Source/bindings/modules/v8/generated.gni
@@ -56,8 +56,6 @@
   "$bindings_modules_v8_output_dir/rtc_ice_candidate_init_or_rtc_ice_candidate.h",
   "$bindings_modules_v8_output_dir/rendering_context.cc",
   "$bindings_modules_v8_output_dir/rendering_context.h",
-  "$bindings_modules_v8_output_dir/request_or_usv_string.cc",
-  "$bindings_modules_v8_output_dir/request_or_usv_string.h",
   "$bindings_modules_v8_output_dir/request_or_usv_string_or_request_or_usv_string_sequence.cc",
   "$bindings_modules_v8_output_dir/request_or_usv_string_or_request_or_usv_string_sequence.h",
   "$bindings_modules_v8_output_dir/string_or_array_buffer_or_nfc_message.cc",
diff --git a/third_party/WebKit/Source/bindings/modules/v8/wasm/WasmResponseExtensions.cpp b/third_party/WebKit/Source/bindings/modules/v8/wasm/WasmResponseExtensions.cpp
index af8b9d4..3fd444c 100644
--- a/third_party/WebKit/Source/bindings/modules/v8/wasm/WasmResponseExtensions.cpp
+++ b/third_party/WebKit/Source/bindings/modules/v8/wasm/WasmResponseExtensions.cpp
@@ -8,7 +8,7 @@
 #include "bindings/core/v8/ExceptionState.h"
 #include "bindings/core/v8/ScriptPromise.h"
 #include "bindings/core/v8/ScriptPromiseResolver.h"
-#include "bindings/modules/v8/V8Response.h"
+#include "bindings/core/v8/V8Response.h"
 #include "core/dom/ExecutionContext.h"
 #include "core/fetch/BodyStreamBuffer.h"
 #include "core/fetch/FetchDataLoader.h"
diff --git a/third_party/WebKit/Source/core/BUILD.gn b/third_party/WebKit/Source/core/BUILD.gn
index b81457c..8a2e042 100644
--- a/third_party/WebKit/Source/core/BUILD.gn
+++ b/third_party/WebKit/Source/core/BUILD.gn
@@ -261,6 +261,10 @@
   ]
 
   sources = [
+    "fetch/testing/InternalsFetch.cpp",
+    "fetch/testing/InternalsFetch.h",
+    "fetch/testing/WorkerInternalsFetch.cpp",
+    "fetch/testing/WorkerInternalsFetch.h",
     "testing/CallbackFunctionTest.cpp",
     "testing/CallbackFunctionTest.h",
     "testing/DeathAwareScriptWrappable.cpp",
@@ -1768,9 +1772,12 @@
     "fetch/DataConsumerHandleTestUtil.h",
     "fetch/FetchDataLoaderTest.cpp",
     "fetch/FetchHeaderListTest.cpp",
+    "fetch/FetchResponseDataTest.cpp",
     "fetch/FormDataBytesConsumerTest.cpp",
     "fetch/MultipartParserTest.cpp",
     "fetch/ReadableStreamBytesConsumerTest.cpp",
+    "fetch/RequestTest.cpp",
+    "fetch/ResponseTest.cpp",
     "fileapi/FileListTest.cpp",
     "fileapi/FileTest.cpp",
     "frame/BrowserControlsTest.cpp",
diff --git a/third_party/WebKit/Source/core/core_idl_files.gni b/third_party/WebKit/Source/core/core_idl_files.gni
index 0b8b8b8..50623f372 100644
--- a/third_party/WebKit/Source/core/core_idl_files.gni
+++ b/third_party/WebKit/Source/core/core_idl_files.gni
@@ -167,6 +167,8 @@
                     "events/WheelEvent.idl",
                     "fetch/Body.idl",
                     "fetch/Headers.idl",
+                    "fetch/Request.idl",
+                    "fetch/Response.idl",
                     "fileapi/Blob.idl",
                     "fileapi/File.idl",
                     "fileapi/FileList.idl",
@@ -492,6 +494,8 @@
                     "dom/ParentNode.idl",
                     "dom/events/EventListener.idl",
                     "events/NavigatorEvents.idl",
+                    "fetch/WindowFetch.idl",
+                    "fetch/WorkerFetch.idl",
                     "fileapi/URLFileAPI.idl",
                     "frame/NavigatorAutomationInformation.idl",
                     "frame/NavigatorConcurrentHardware.idl",
@@ -526,7 +530,6 @@
                     "dom/CommonDefinitions.idl",
                     "timing/DOMHighResTimeStamp.idl",
                     "timing/PerformanceEntryList.idl",
-                    "workers/RequestCredentials.idl",
                   ],
                   "abspath")
 
@@ -535,6 +538,7 @@
                     "dom/FrameRequestCallback.idl",
                     "dom/FunctionStringCallback.idl",
                     "dom/IdleRequestCallback.idl",
+                    "dom/VoidFunction.idl",
                   ],
                   "abspath")
 
@@ -586,6 +590,7 @@
                     "events/TransitionEventInit.idl",
                     "events/UIEventInit.idl",
                     "events/WheelEventInit.idl",
+                    "fetch/ResponseInit.idl",
                     "fileapi/BlobPropertyBag.idl",
                     "fileapi/FilePropertyBag.idl",
                     "frame/ScrollIntoViewOptions.idl",
@@ -652,19 +657,21 @@
                     "testing/SequenceTest.idl",
                     "testing/TypeConversions.idl",
                     "testing/UnionTypesTest.idl",
+                    "testing/WorkerInternals.idl",
                   ],
                   "abspath")
 
 # Testing IDL files that have partial interfaces in modules.
 webcore_testing_idl_with_modules_dependency_files =
-    get_path_info([
-                    "testing/Internals.idl",
-                    "testing/WorkerInternals.idl",
-                  ],
-                  "abspath")
+    get_path_info([ "testing/Internals.idl" ], "abspath")
 
 webcore_testing_dependency_idl_files =
-    get_path_info([ "testing/OriginTrialsTestPartial.idl" ], "abspath")
+    get_path_info([
+                    "fetch/testing/InternalsFetch.idl",
+                    "fetch/testing/WorkerInternalsFetch.idl",
+                    "testing/OriginTrialsTestPartial.idl",
+                  ],
+                  "abspath")
 
 if (snake_case_source_files) {
   generated_webcore_testing_idl_files =
diff --git a/third_party/WebKit/Source/core/dom/VoidFunction.idl b/third_party/WebKit/Source/core/dom/VoidFunction.idl
new file mode 100644
index 0000000..994e74f
--- /dev/null
+++ b/third_party/WebKit/Source/core/dom/VoidFunction.idl
@@ -0,0 +1,6 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// https://heycam.github.io/webidl/#VoidFunction
+callback VoidFunction = void ();
diff --git a/third_party/WebKit/Source/core/fetch/BUILD.gn b/third_party/WebKit/Source/core/fetch/BUILD.gn
index b2bef16..35532018 100644
--- a/third_party/WebKit/Source/core/fetch/BUILD.gn
+++ b/third_party/WebKit/Source/core/fetch/BUILD.gn
@@ -20,43 +20,32 @@
     "FetchDataLoader.h",
     "FetchHeaderList.cpp",
     "FetchHeaderList.h",
-
-    # TODO(nhiroki): Move these files from modules/fetch to core/fetch.
-    # (https://crbug.com/794837)
-    # "FetchManager.cpp",
-    # "FetchManager.h",
-    # "FetchRequestData.cpp",
-    # "FetchRequestData.h",
-    # "FetchResponseData.cpp",
-    # "FetchResponseData.h",
-
+    "FetchManager.cpp",
+    "FetchManager.h",
+    "FetchRequestData.cpp",
+    "FetchRequestData.h",
+    "FetchResponseData.cpp",
+    "FetchResponseData.h",
     "FormDataBytesConsumer.cpp",
     "FormDataBytesConsumer.h",
-
-    # TODO(nhiroki): Move these files from modules/fetch to core/fetch.
-    # (https://crbug.com/794837)
-    # "GlobalFetch.cpp",
-    # "GlobalFetch.h",
-
+    "GlobalFetch.cpp",
+    "GlobalFetch.h",
     "Headers.cpp",
     "Headers.h",
     "MultipartParser.cpp",
     "MultipartParser.h",
     "ReadableStreamBytesConsumer.cpp",
     "ReadableStreamBytesConsumer.h",
-
-    # TODO(nhiroki): Move these files from modules/fetch to core/fetch.
-    # (https://crbug.com/794837)
-    # "Request.cpp",
-    # "Request.h",
-    # "RequestInit.cpp",
-    # "RequestInit.h",
-    # "Response.cpp",
-    # "Response.h",
+    "Request.cpp",
+    "Request.h",
+    "RequestInit.cpp",
+    "RequestInit.h",
+    "Response.cpp",
+    "Response.h",
   ]
 
   if (is_win && is_component_build) {
-    # Body.cpp exports a class (MODULES_EXPORT) that inherits from
+    # Body.cpp exports a class (CORE_EXPORT) that inherits from
     # PairIterable<String, String> that is also used as base class by an
     # imported (CORE_EXPORT) class and that confuses the Windows
     # linker/compiler. https://crbug.com/739340
diff --git a/third_party/WebKit/Source/modules/fetch/FetchManager.cpp b/third_party/WebKit/Source/core/fetch/FetchManager.cpp
similarity index 99%
rename from third_party/WebKit/Source/modules/fetch/FetchManager.cpp
rename to third_party/WebKit/Source/core/fetch/FetchManager.cpp
index 323d1e2..be11fc4c 100644
--- a/third_party/WebKit/Source/modules/fetch/FetchManager.cpp
+++ b/third_party/WebKit/Source/core/fetch/FetchManager.cpp
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "modules/fetch/FetchManager.h"
+#include "core/fetch/FetchManager.h"
 
 #include <memory>
 #include "bindings/core/v8/ExceptionState.h"
@@ -12,7 +12,10 @@
 #include "core/fetch/BodyStreamBuffer.h"
 #include "core/fetch/BytesConsumer.h"
 #include "core/fetch/BytesConsumerForDataConsumerHandle.h"
+#include "core/fetch/FetchRequestData.h"
 #include "core/fetch/FormDataBytesConsumer.h"
+#include "core/fetch/Response.h"
+#include "core/fetch/ResponseInit.h"
 #include "core/fileapi/Blob.h"
 #include "core/frame/Frame.h"
 #include "core/frame/csp/ContentSecurityPolicy.h"
@@ -24,9 +27,6 @@
 #include "core/page/Page.h"
 #include "core/probe/CoreProbes.h"
 #include "core/typed_arrays/DOMArrayBuffer.h"
-#include "modules/fetch/FetchRequestData.h"
-#include "modules/fetch/Response.h"
-#include "modules/fetch/ResponseInit.h"
 #include "platform/bindings/ScriptState.h"
 #include "platform/bindings/V8ThrowException.h"
 #include "platform/exported/WrappedResourceResponse.h"
@@ -824,9 +824,10 @@
   failed_ = true;
   if (execution_context_->IsContextDestroyed())
     return;
-  if (!message.IsEmpty())
+  if (!message.IsEmpty()) {
     execution_context_->AddConsoleMessage(
         ConsoleMessage::Create(kJSMessageSource, kErrorMessageLevel, message));
+  }
   if (resolver_) {
     ScriptState* state = resolver_->GetScriptState();
     ScriptState::Scope scope(state);
diff --git a/third_party/WebKit/Source/modules/fetch/FetchManager.h b/third_party/WebKit/Source/core/fetch/FetchManager.h
similarity index 83%
rename from third_party/WebKit/Source/modules/fetch/FetchManager.h
rename to third_party/WebKit/Source/core/fetch/FetchManager.h
index f016142..1cad19a3 100644
--- a/third_party/WebKit/Source/modules/fetch/FetchManager.h
+++ b/third_party/WebKit/Source/core/fetch/FetchManager.h
@@ -6,6 +6,7 @@
 #define FetchManager_h
 
 #include "bindings/core/v8/ScriptPromise.h"
+#include "core/CoreExport.h"
 #include "core/dom/ContextLifecycleObserver.h"
 #include "platform/heap/Handle.h"
 
@@ -15,8 +16,8 @@
 class FetchRequestData;
 class ScriptState;
 
-class FetchManager final : public GarbageCollected<FetchManager>,
-                           public ContextLifecycleObserver {
+class CORE_EXPORT FetchManager final : public GarbageCollected<FetchManager>,
+                                       public ContextLifecycleObserver {
   USING_GARBAGE_COLLECTED_MIXIN(FetchManager);
 
  public:
diff --git a/third_party/WebKit/Source/modules/fetch/FetchRequestData.cpp b/third_party/WebKit/Source/core/fetch/FetchRequestData.cpp
similarity index 98%
rename from third_party/WebKit/Source/modules/fetch/FetchRequestData.cpp
rename to third_party/WebKit/Source/core/fetch/FetchRequestData.cpp
index 6138cd1..05d6e8a 100644
--- a/third_party/WebKit/Source/modules/fetch/FetchRequestData.cpp
+++ b/third_party/WebKit/Source/core/fetch/FetchRequestData.cpp
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "modules/fetch/FetchRequestData.h"
+#include "core/fetch/FetchRequestData.h"
 
 #include "core/dom/ExecutionContext.h"
 #include "core/fetch/BlobBytesConsumer.h"
diff --git a/third_party/WebKit/Source/modules/fetch/FetchRequestData.h b/third_party/WebKit/Source/core/fetch/FetchRequestData.h
similarity index 100%
rename from third_party/WebKit/Source/modules/fetch/FetchRequestData.h
rename to third_party/WebKit/Source/core/fetch/FetchRequestData.h
diff --git a/third_party/WebKit/Source/modules/fetch/FetchResponseData.cpp b/third_party/WebKit/Source/core/fetch/FetchResponseData.cpp
similarity index 99%
rename from third_party/WebKit/Source/modules/fetch/FetchResponseData.cpp
rename to third_party/WebKit/Source/core/fetch/FetchResponseData.cpp
index 1a644a19..81faa0d2 100644
--- a/third_party/WebKit/Source/modules/fetch/FetchResponseData.cpp
+++ b/third_party/WebKit/Source/core/fetch/FetchResponseData.cpp
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "modules/fetch/FetchResponseData.h"
+#include "core/fetch/FetchResponseData.h"
 
 #include "core/fetch/BodyStreamBuffer.h"
 #include "core/fetch/FetchHeaderList.h"
diff --git a/third_party/WebKit/Source/modules/fetch/FetchResponseData.h b/third_party/WebKit/Source/core/fetch/FetchResponseData.h
similarity index 97%
rename from third_party/WebKit/Source/modules/fetch/FetchResponseData.h
rename to third_party/WebKit/Source/core/fetch/FetchResponseData.h
index 14260bc5..5fc34fb 100644
--- a/third_party/WebKit/Source/modules/fetch/FetchResponseData.h
+++ b/third_party/WebKit/Source/core/fetch/FetchResponseData.h
@@ -9,7 +9,7 @@
 
 #include "base/macros.h"
 #include "base/memory/scoped_refptr.h"
-#include "modules/ModulesExport.h"
+#include "core/CoreExport.h"
 #include "platform/heap/Handle.h"
 #include "platform/weborigin/KURL.h"
 #include "platform/wtf/Time.h"
@@ -27,7 +27,7 @@
 class ScriptState;
 class WebServiceWorkerResponse;
 
-class MODULES_EXPORT FetchResponseData final
+class CORE_EXPORT FetchResponseData final
     : public GarbageCollectedFinalized<FetchResponseData> {
  public:
   // "A response can have an associated termination reason which is one of
diff --git a/third_party/WebKit/Source/modules/fetch/FetchResponseDataTest.cpp b/third_party/WebKit/Source/core/fetch/FetchResponseDataTest.cpp
similarity index 99%
rename from third_party/WebKit/Source/modules/fetch/FetchResponseDataTest.cpp
rename to third_party/WebKit/Source/core/fetch/FetchResponseDataTest.cpp
index e17c59f..dfbc85c2 100644
--- a/third_party/WebKit/Source/modules/fetch/FetchResponseDataTest.cpp
+++ b/third_party/WebKit/Source/core/fetch/FetchResponseDataTest.cpp
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "modules/fetch/FetchResponseData.h"
+#include "core/fetch/FetchResponseData.h"
 
 #include "core/fetch/FetchHeaderList.h"
 #include "core/typed_arrays/DOMArrayBuffer.h"
diff --git a/third_party/WebKit/Source/modules/fetch/GlobalFetch.cpp b/third_party/WebKit/Source/core/fetch/GlobalFetch.cpp
similarity index 97%
rename from third_party/WebKit/Source/modules/fetch/GlobalFetch.cpp
rename to third_party/WebKit/Source/core/fetch/GlobalFetch.cpp
index 4fffb2b..2ab54d8e 100644
--- a/third_party/WebKit/Source/modules/fetch/GlobalFetch.cpp
+++ b/third_party/WebKit/Source/core/fetch/GlobalFetch.cpp
@@ -2,14 +2,14 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "modules/fetch/GlobalFetch.h"
+#include "core/fetch/GlobalFetch.h"
 
+#include "core/fetch/FetchManager.h"
+#include "core/fetch/Request.h"
 #include "core/frame/LocalDOMWindow.h"
 #include "core/frame/UseCounter.h"
 #include "core/probe/CoreProbes.h"
 #include "core/workers/WorkerGlobalScope.h"
-#include "modules/fetch/FetchManager.h"
-#include "modules/fetch/Request.h"
 #include "platform/Supplementable.h"
 #include "platform/heap/Handle.h"
 
diff --git a/third_party/WebKit/Source/modules/fetch/GlobalFetch.h b/third_party/WebKit/Source/core/fetch/GlobalFetch.h
similarity index 89%
rename from third_party/WebKit/Source/modules/fetch/GlobalFetch.h
rename to third_party/WebKit/Source/core/fetch/GlobalFetch.h
index 2cdb7af..5714c2b7 100644
--- a/third_party/WebKit/Source/modules/fetch/GlobalFetch.h
+++ b/third_party/WebKit/Source/core/fetch/GlobalFetch.h
@@ -6,8 +6,8 @@
 #define GlobalFetch_h
 
 #include "bindings/core/v8/ScriptPromise.h"
-#include "modules/ModulesExport.h"
-#include "modules/fetch/Request.h"
+#include "core/CoreExport.h"
+#include "core/fetch/Request.h"
 
 namespace blink {
 
@@ -17,11 +17,11 @@
 class ScriptState;
 class WorkerGlobalScope;
 
-class GlobalFetch {
+class CORE_EXPORT GlobalFetch {
   STATIC_ONLY(GlobalFetch);
 
  public:
-  class MODULES_EXPORT ScopedFetcher : public GarbageCollectedMixin {
+  class CORE_EXPORT ScopedFetcher : public GarbageCollectedMixin {
    public:
     virtual ~ScopedFetcher();
 
diff --git a/third_party/WebKit/Source/modules/fetch/Request.cpp b/third_party/WebKit/Source/core/fetch/Request.cpp
similarity index 97%
rename from third_party/WebKit/Source/modules/fetch/Request.cpp
rename to third_party/WebKit/Source/core/fetch/Request.cpp
index 7e9b284..5bfdf49 100644
--- a/third_party/WebKit/Source/modules/fetch/Request.cpp
+++ b/third_party/WebKit/Source/core/fetch/Request.cpp
@@ -2,14 +2,14 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "modules/fetch/Request.h"
+#include "core/fetch/Request.h"
 
 #include "bindings/core/v8/Dictionary.h"
 #include "core/dom/ExecutionContext.h"
 #include "core/fetch/BodyStreamBuffer.h"
+#include "core/fetch/FetchManager.h"
+#include "core/fetch/RequestInit.h"
 #include "core/loader/ThreadableLoader.h"
-#include "modules/fetch/FetchManager.h"
-#include "modules/fetch/RequestInit.h"
 #include "platform/bindings/V8PrivateProperty.h"
 #include "platform/loader/fetch/FetchUtils.h"
 #include "platform/loader/fetch/ResourceLoaderOptions.h"
@@ -238,15 +238,12 @@
   // |fallbackCredentials| otherwise."
   // "If |credentials| is non-null, set |request|'s credentials mode to
   // |credentials|."
-  if (init.Credentials() == "omit") {
+
+  network::mojom::FetchCredentialsMode credentials_mode;
+  if (ParseCredentialsMode(init.Credentials(), &credentials_mode)) {
+    request->SetCredentials(credentials_mode);
+  } else if (!input_request) {
     request->SetCredentials(network::mojom::FetchCredentialsMode::kOmit);
-  } else if (init.Credentials() == "same-origin") {
-    request->SetCredentials(network::mojom::FetchCredentialsMode::kSameOrigin);
-  } else if (init.Credentials() == "include") {
-    request->SetCredentials(network::mojom::FetchCredentialsMode::kInclude);
-  } else {
-    if (!input_request)
-      request->SetCredentials(network::mojom::FetchCredentialsMode::kOmit);
   }
 
   // "If |init|'s cache member is present, set |request|'s cache mode to it."
@@ -466,6 +463,24 @@
   return new Request(script_state, request);
 }
 
+bool Request::ParseCredentialsMode(
+    const String& credentials_mode,
+    network::mojom::FetchCredentialsMode* result) {
+  if (credentials_mode == "omit") {
+    *result = network::mojom::FetchCredentialsMode::kOmit;
+    return true;
+  }
+  if (credentials_mode == "same-origin") {
+    *result = network::mojom::FetchCredentialsMode::kSameOrigin;
+    return true;
+  }
+  if (credentials_mode == "include") {
+    *result = network::mojom::FetchCredentialsMode::kInclude;
+    return true;
+  }
+  return false;
+}
+
 Request::Request(ScriptState* script_state,
                  FetchRequestData* request,
                  Headers* headers)
diff --git a/third_party/WebKit/Source/modules/fetch/Request.h b/third_party/WebKit/Source/core/fetch/Request.h
similarity index 86%
rename from third_party/WebKit/Source/modules/fetch/Request.h
rename to third_party/WebKit/Source/core/fetch/Request.h
index c03c5f3..04316c31 100644
--- a/third_party/WebKit/Source/modules/fetch/Request.h
+++ b/third_party/WebKit/Source/core/fetch/Request.h
@@ -6,16 +6,17 @@
 #define Request_h
 
 #include "bindings/core/v8/Dictionary.h"
-#include "bindings/modules/v8/request_or_usv_string.h"
+#include "bindings/core/v8/request_or_usv_string.h"
+#include "core/CoreExport.h"
 #include "core/fetch/Body.h"
+#include "core/fetch/FetchRequestData.h"
 #include "core/fetch/Headers.h"
-#include "modules/ModulesExport.h"
-#include "modules/fetch/FetchRequestData.h"
 #include "platform/bindings/ScriptWrappable.h"
 #include "platform/heap/Handle.h"
 #include "platform/weborigin/KURL.h"
 #include "platform/wtf/text/WTFString.h"
 #include "public/platform/WebURLRequest.h"
+#include "services/network/public/interfaces/fetch_api.mojom-shared.h"
 
 namespace blink {
 
@@ -25,7 +26,7 @@
 
 using RequestInfo = RequestOrUSVString;
 
-class MODULES_EXPORT Request final : public Body {
+class CORE_EXPORT Request final : public Body {
   DEFINE_WRAPPERTYPEINFO();
   WTF_MAKE_NONCOPYABLE(Request);
 
@@ -51,6 +52,11 @@
   static Request* Create(ScriptState*, FetchRequestData*);
   static Request* Create(ScriptState*, const WebServiceWorkerRequest&);
 
+  // Returns false if |credentials_mode| doesn't represent a valid credentials
+  // mode.
+  static bool ParseCredentialsMode(const String& credentials_mode,
+                                   network::mojom::FetchCredentialsMode*);
+
   // From Request.idl:
   String method() const;
   KURL url() const;
diff --git a/third_party/WebKit/Source/modules/fetch/Request.idl b/third_party/WebKit/Source/core/fetch/Request.idl
similarity index 100%
rename from third_party/WebKit/Source/modules/fetch/Request.idl
rename to third_party/WebKit/Source/core/fetch/Request.idl
diff --git a/third_party/WebKit/Source/modules/fetch/RequestInit.cpp b/third_party/WebKit/Source/core/fetch/RequestInit.cpp
similarity index 99%
rename from third_party/WebKit/Source/modules/fetch/RequestInit.cpp
rename to third_party/WebKit/Source/core/fetch/RequestInit.cpp
index 5a80160..5d8907927 100644
--- a/third_party/WebKit/Source/modules/fetch/RequestInit.cpp
+++ b/third_party/WebKit/Source/core/fetch/RequestInit.cpp
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "modules/fetch/RequestInit.h"
+#include "core/fetch/RequestInit.h"
 
 #include "bindings/core/v8/Dictionary.h"
 #include "bindings/core/v8/ExceptionState.h"
diff --git a/third_party/WebKit/Source/modules/fetch/RequestInit.h b/third_party/WebKit/Source/core/fetch/RequestInit.h
similarity index 100%
rename from third_party/WebKit/Source/modules/fetch/RequestInit.h
rename to third_party/WebKit/Source/core/fetch/RequestInit.h
diff --git a/third_party/WebKit/Source/modules/fetch/RequestTest.cpp b/third_party/WebKit/Source/core/fetch/RequestTest.cpp
similarity index 98%
rename from third_party/WebKit/Source/modules/fetch/RequestTest.cpp
rename to third_party/WebKit/Source/core/fetch/RequestTest.cpp
index 0a7dd95d..0f38c285 100644
--- a/third_party/WebKit/Source/modules/fetch/RequestTest.cpp
+++ b/third_party/WebKit/Source/core/fetch/RequestTest.cpp
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "modules/fetch/Request.h"
+#include "core/fetch/Request.h"
 
 #include <memory>
 #include "bindings/core/v8/ExceptionState.h"
@@ -75,9 +75,10 @@
   web_request.SetCacheMode(kCacheMode);
   web_request.SetRedirectMode(kRedirectMode);
   web_request.SetRequestContext(kContext);
-  for (int i = 0; headers[i].key; ++i)
+  for (int i = 0; headers[i].key; ++i) {
     web_request.SetHeader(WebString::FromUTF8(headers[i].key),
                           WebString::FromUTF8(headers[i].value));
+  }
   web_request.SetReferrer(referrer, kReferrerPolicy);
 
   Request* request = Request::Create(scope.GetScriptState(), web_request);
diff --git a/third_party/WebKit/Source/modules/fetch/Response.cpp b/third_party/WebKit/Source/core/fetch/Response.cpp
similarity index 99%
rename from third_party/WebKit/Source/modules/fetch/Response.cpp
rename to third_party/WebKit/Source/core/fetch/Response.cpp
index 76f2d44c..71bb2141 100644
--- a/third_party/WebKit/Source/modules/fetch/Response.cpp
+++ b/third_party/WebKit/Source/core/fetch/Response.cpp
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "modules/fetch/Response.h"
+#include "core/fetch/Response.h"
 
 #include <memory>
 #include "base/memory/scoped_refptr.h"
@@ -18,6 +18,7 @@
 #include "core/fetch/BlobBytesConsumer.h"
 #include "core/fetch/BodyStreamBuffer.h"
 #include "core/fetch/FormDataBytesConsumer.h"
+#include "core/fetch/ResponseInit.h"
 #include "core/fileapi/Blob.h"
 #include "core/frame/UseCounter.h"
 #include "core/html/forms/FormData.h"
@@ -25,7 +26,6 @@
 #include "core/typed_arrays/DOMArrayBuffer.h"
 #include "core/typed_arrays/DOMArrayBufferView.h"
 #include "core/url/URLSearchParams.h"
-#include "modules/fetch/ResponseInit.h"
 #include "platform/bindings/ScriptState.h"
 #include "platform/bindings/V8PrivateProperty.h"
 #include "platform/loader/fetch/FetchUtils.h"
diff --git a/third_party/WebKit/Source/modules/fetch/Response.h b/third_party/WebKit/Source/core/fetch/Response.h
similarity index 96%
rename from third_party/WebKit/Source/modules/fetch/Response.h
rename to third_party/WebKit/Source/core/fetch/Response.h
index 56dc7096..ad1eb93 100644
--- a/third_party/WebKit/Source/modules/fetch/Response.h
+++ b/third_party/WebKit/Source/core/fetch/Response.h
@@ -7,11 +7,11 @@
 
 #include "bindings/core/v8/Dictionary.h"
 #include "bindings/core/v8/ScriptValue.h"
+#include "core/CoreExport.h"
 #include "core/fetch/Body.h"
 #include "core/fetch/BodyStreamBuffer.h"
+#include "core/fetch/FetchResponseData.h"
 #include "core/fetch/Headers.h"
-#include "modules/ModulesExport.h"
-#include "modules/fetch/FetchResponseData.h"
 #include "platform/bindings/ScriptWrappable.h"
 #include "platform/blob/BlobData.h"
 #include "platform/heap/Handle.h"
@@ -25,7 +25,7 @@
 class ScriptState;
 class WebServiceWorkerResponse;
 
-class MODULES_EXPORT Response final : public Body {
+class CORE_EXPORT Response final : public Body {
   DEFINE_WRAPPERTYPEINFO();
   WTF_MAKE_NONCOPYABLE(Response);
 
diff --git a/third_party/WebKit/Source/modules/fetch/Response.idl b/third_party/WebKit/Source/core/fetch/Response.idl
similarity index 100%
rename from third_party/WebKit/Source/modules/fetch/Response.idl
rename to third_party/WebKit/Source/core/fetch/Response.idl
diff --git a/third_party/WebKit/Source/modules/fetch/ResponseInit.idl b/third_party/WebKit/Source/core/fetch/ResponseInit.idl
similarity index 100%
rename from third_party/WebKit/Source/modules/fetch/ResponseInit.idl
rename to third_party/WebKit/Source/core/fetch/ResponseInit.idl
diff --git a/third_party/WebKit/Source/modules/fetch/ResponseTest.cpp b/third_party/WebKit/Source/core/fetch/ResponseTest.cpp
similarity index 98%
rename from third_party/WebKit/Source/modules/fetch/ResponseTest.cpp
rename to third_party/WebKit/Source/core/fetch/ResponseTest.cpp
index 4905804a..61a7f59 100644
--- a/third_party/WebKit/Source/modules/fetch/ResponseTest.cpp
+++ b/third_party/WebKit/Source/core/fetch/ResponseTest.cpp
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "modules/fetch/Response.h"
+#include "core/fetch/Response.h"
 
 #include <memory>
 #include "bindings/core/v8/ExceptionState.h"
@@ -12,9 +12,9 @@
 #include "core/fetch/BytesConsumer.h"
 #include "core/fetch/BytesConsumerTestUtil.h"
 #include "core/fetch/DataConsumerHandleTestUtil.h"
+#include "core/fetch/FetchResponseData.h"
 #include "core/frame/Frame.h"
 #include "core/testing/DummyPageHolder.h"
-#include "modules/fetch/FetchResponseData.h"
 #include "platform/bindings/ScriptState.h"
 #include "platform/blob/BlobData.h"
 #include "platform/testing/UnitTestHelpers.h"
@@ -45,9 +45,10 @@
   web_response->SetStatus(kStatus);
   web_response->SetStatusText(status_text);
   web_response->SetResponseType(network::mojom::FetchResponseType::kDefault);
-  for (int i = 0; headers[i].key; ++i)
+  for (int i = 0; headers[i].key; ++i) {
     web_response->SetHeader(WebString::FromUTF8(headers[i].key),
                             WebString::FromUTF8(headers[i].value));
+  }
   return web_response;
 }
 
diff --git a/third_party/WebKit/Source/modules/fetch/WindowFetch.idl b/third_party/WebKit/Source/core/fetch/WindowFetch.idl
similarity index 100%
rename from third_party/WebKit/Source/modules/fetch/WindowFetch.idl
rename to third_party/WebKit/Source/core/fetch/WindowFetch.idl
diff --git a/third_party/WebKit/Source/modules/fetch/WorkerFetch.idl b/third_party/WebKit/Source/core/fetch/WorkerFetch.idl
similarity index 100%
rename from third_party/WebKit/Source/modules/fetch/WorkerFetch.idl
rename to third_party/WebKit/Source/core/fetch/WorkerFetch.idl
diff --git a/third_party/WebKit/Source/modules/fetch/testing/InternalsFetch.cpp b/third_party/WebKit/Source/core/fetch/testing/InternalsFetch.cpp
similarity index 88%
rename from third_party/WebKit/Source/modules/fetch/testing/InternalsFetch.cpp
rename to third_party/WebKit/Source/core/fetch/testing/InternalsFetch.cpp
index 3a42336..13f87f7 100644
--- a/third_party/WebKit/Source/modules/fetch/testing/InternalsFetch.cpp
+++ b/third_party/WebKit/Source/core/fetch/testing/InternalsFetch.cpp
@@ -2,9 +2,9 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "modules/fetch/testing/InternalsFetch.h"
+#include "core/fetch/testing/InternalsFetch.h"
 
-#include "modules/fetch/Response.h"
+#include "core/fetch/Response.h"
 #include "platform/wtf/Vector.h"
 
 namespace blink {
diff --git a/third_party/WebKit/Source/modules/fetch/testing/InternalsFetch.h b/third_party/WebKit/Source/core/fetch/testing/InternalsFetch.h
similarity index 100%
rename from third_party/WebKit/Source/modules/fetch/testing/InternalsFetch.h
rename to third_party/WebKit/Source/core/fetch/testing/InternalsFetch.h
diff --git a/third_party/WebKit/Source/modules/fetch/testing/InternalsFetch.idl b/third_party/WebKit/Source/core/fetch/testing/InternalsFetch.idl
similarity index 100%
rename from third_party/WebKit/Source/modules/fetch/testing/InternalsFetch.idl
rename to third_party/WebKit/Source/core/fetch/testing/InternalsFetch.idl
diff --git a/third_party/WebKit/Source/modules/fetch/testing/WorkerInternalsFetch.cpp b/third_party/WebKit/Source/core/fetch/testing/WorkerInternalsFetch.cpp
similarity index 86%
rename from third_party/WebKit/Source/modules/fetch/testing/WorkerInternalsFetch.cpp
rename to third_party/WebKit/Source/core/fetch/testing/WorkerInternalsFetch.cpp
index 86e1134..e841ee5 100644
--- a/third_party/WebKit/Source/modules/fetch/testing/WorkerInternalsFetch.cpp
+++ b/third_party/WebKit/Source/core/fetch/testing/WorkerInternalsFetch.cpp
@@ -2,9 +2,9 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "modules/fetch/testing/WorkerInternalsFetch.h"
+#include "core/fetch/testing/WorkerInternalsFetch.h"
 
-#include "modules/fetch/Response.h"
+#include "core/fetch/Response.h"
 #include "platform/wtf/Vector.h"
 
 namespace blink {
diff --git a/third_party/WebKit/Source/modules/fetch/testing/WorkerInternalsFetch.h b/third_party/WebKit/Source/core/fetch/testing/WorkerInternalsFetch.h
similarity index 100%
rename from third_party/WebKit/Source/modules/fetch/testing/WorkerInternalsFetch.h
rename to third_party/WebKit/Source/core/fetch/testing/WorkerInternalsFetch.h
diff --git a/third_party/WebKit/Source/modules/fetch/testing/WorkerInternalsFetch.idl b/third_party/WebKit/Source/core/fetch/testing/WorkerInternalsFetch.idl
similarity index 100%
rename from third_party/WebKit/Source/modules/fetch/testing/WorkerInternalsFetch.idl
rename to third_party/WebKit/Source/core/fetch/testing/WorkerInternalsFetch.idl
diff --git a/third_party/WebKit/Source/core/layout/ng/inline/ng_inline_layout_algorithm.cc b/third_party/WebKit/Source/core/layout/ng/inline/ng_inline_layout_algorithm.cc
index bf7aeaf..2d2251d 100644
--- a/third_party/WebKit/Source/core/layout/ng/inline/ng_inline_layout_algorithm.cc
+++ b/third_party/WebKit/Source/core/layout/ng/inline/ng_inline_layout_algorithm.cc
@@ -546,7 +546,7 @@
 
     Vector<NGOutOfFlowPositionedDescendant> descendant_candidates;
     container_builder_.GetAndClearOutOfFlowDescendantCandidates(
-        &descendant_candidates);
+        &descendant_candidates, nullptr);
     for (auto& descendant : descendant_candidates)
       container_builder_.AddOutOfFlowDescendant(descendant);
 
@@ -638,7 +638,7 @@
 
   Vector<NGOutOfFlowPositionedDescendant> descendant_candidates;
   container_builder_.GetAndClearOutOfFlowDescendantCandidates(
-      &descendant_candidates);
+      &descendant_candidates, nullptr);
   for (auto& descendant : descendant_candidates)
     container_builder_.AddOutOfFlowDescendant(descendant);
   return container_builder_.ToLineBoxFragment();
diff --git a/third_party/WebKit/Source/core/layout/ng/layout_ng_block_flow.cc b/third_party/WebKit/Source/core/layout/ng/layout_ng_block_flow.cc
index 253074c..8fe9a534 100644
--- a/third_party/WebKit/Source/core/layout/ng/layout_ng_block_flow.cc
+++ b/third_party/WebKit/Source/core/layout/ng/layout_ng_block_flow.cc
@@ -164,17 +164,14 @@
       NGStaticPosition::Create(parent_style->GetWritingMode(),
                                parent_style->Direction(), static_location);
 
-  container_builder.AddOutOfFlowLegacyCandidate(NGBlockNode(this),
-                                                static_position);
-
-  // LayoutObject::ContainingBlock() is not equal to LayoutObject::Container()
-  // when css container is inline. NG uses css container's style to determine
-  // whether containing block can contain the node, and therefore must use
-  // ::Container() because that object has the right Style().
   LayoutObject* css_container = Container();
-  DCHECK(css_container->IsBox());
-  NGOutOfFlowLayoutPart(NGBlockNode(ToLayoutBox(css_container)),
-                        *constraint_space, *container_style, &container_builder)
+  // Set correct container for inline containing blocks.
+  container_builder.AddOutOfFlowLegacyCandidate(
+      NGBlockNode(this), static_position,
+      css_container->IsBox() ? nullptr : css_container);
+
+  NGOutOfFlowLayoutPart(NGBlockNode(container), *constraint_space,
+                        *container_style, &container_builder)
       .Run(/* update_legacy */ false);
   scoped_refptr<NGLayoutResult> result = container_builder.ToBoxFragment();
   // These are the unpositioned OOF descendants of the current OOF block.
diff --git a/third_party/WebKit/Source/core/layout/ng/ng_block_node.cc b/third_party/WebKit/Source/core/layout/ng/ng_block_node.cc
index 6a75a07a..e354f06 100644
--- a/third_party/WebKit/Source/core/layout/ng/ng_block_node.cc
+++ b/third_party/WebKit/Source/core/layout/ng/ng_block_node.cc
@@ -631,11 +631,17 @@
 }
 
 // Save static position for legacy AbsPos layout.
-void NGBlockNode::SaveStaticOffsetForLegacy(const NGLogicalOffset& offset) {
+void NGBlockNode::SaveStaticOffsetForLegacy(
+    const NGLogicalOffset& offset,
+    const LayoutObject* offset_container) {
   DCHECK(box_->IsOutOfFlowPositioned());
-  DCHECK(box_->Layer());
-  box_->Layer()->SetStaticBlockPosition(offset.block_offset);
-  box_->Layer()->SetStaticInlinePosition(offset.inline_offset);
+  // Only set static position if the current offset container
+  // is one that Legacy layout expects static offset from.
+  if (box_->Parent() == offset_container) {
+    DCHECK(box_->Layer());
+    box_->Layer()->SetStaticBlockPosition(offset.block_offset);
+    box_->Layer()->SetStaticInlinePosition(offset.inline_offset);
+  }
 }
 
 }  // namespace blink
diff --git a/third_party/WebKit/Source/core/layout/ng/ng_block_node.h b/third_party/WebKit/Source/core/layout/ng/ng_block_node.h
index 3fb01c6..81fa842 100644
--- a/third_party/WebKit/Source/core/layout/ng/ng_block_node.h
+++ b/third_party/WebKit/Source/core/layout/ng/ng_block_node.h
@@ -59,7 +59,8 @@
   void UseOldOutOfFlowPositioning();
 
   // Save static position for legacy AbsPos layout.
-  void SaveStaticOffsetForLegacy(const NGLogicalOffset&);
+  void SaveStaticOffsetForLegacy(const NGLogicalOffset&,
+                                 const LayoutObject* offset_container);
 
   bool CanUseNewLayout() const;
 
diff --git a/third_party/WebKit/Source/core/layout/ng/ng_container_fragment_builder.cc b/third_party/WebKit/Source/core/layout/ng/ng_container_fragment_builder.cc
index d04e0f9e..892c515a 100644
--- a/third_party/WebKit/Source/core/layout/ng/ng_container_fragment_builder.cc
+++ b/third_party/WebKit/Source/core/layout/ng/ng_container_fragment_builder.cc
@@ -124,7 +124,6 @@
                                           NGPhysicalOffset())},
       child_offset));
 
-  child.SaveStaticOffsetForLegacy(child_offset);
   return *this;
 }
 
@@ -146,7 +145,6 @@
           inline_container),
       child_offset, line_direction));
 
-  child.SaveStaticOffsetForLegacy(child_offset);
   return *this;
 }
 
@@ -157,7 +155,8 @@
 }
 
 void NGContainerFragmentBuilder::GetAndClearOutOfFlowDescendantCandidates(
-    Vector<NGOutOfFlowPositionedDescendant>* descendant_candidates) {
+    Vector<NGOutOfFlowPositionedDescendant>* descendant_candidates,
+    const LayoutObject* current_container) {
   DCHECK(descendant_candidates->IsEmpty());
 
   descendant_candidates->ReserveCapacity(oof_positioned_candidates_.size());
@@ -181,6 +180,12 @@
     descendant_candidates->push_back(NGOutOfFlowPositionedDescendant(
         candidate.descendant.node, builder_relative_position,
         candidate.descendant.inline_container));
+    NGLogicalOffset container_offset =
+        builder_relative_position.offset.ConvertToLogical(
+            GetWritingMode(), Direction(), builder_physical_size,
+            NGPhysicalSize());
+    candidate.descendant.node.SaveStaticOffsetForLegacy(container_offset,
+                                                        current_container);
   }
 
   // Clear our current canidate list. This may get modified again if the
diff --git a/third_party/WebKit/Source/core/layout/ng/ng_container_fragment_builder.h b/third_party/WebKit/Source/core/layout/ng/ng_container_fragment_builder.h
index 83fc260..0a6dd2c 100644
--- a/third_party/WebKit/Source/core/layout/ng/ng_container_fragment_builder.h
+++ b/third_party/WebKit/Source/core/layout/ng/ng_container_fragment_builder.h
@@ -105,7 +105,8 @@
       NGOutOfFlowPositionedDescendant);
 
   void GetAndClearOutOfFlowDescendantCandidates(
-      Vector<NGOutOfFlowPositionedDescendant>* descendant_candidates);
+      Vector<NGOutOfFlowPositionedDescendant>* descendant_candidates,
+      const LayoutObject* container);
 
 #ifndef NDEBUG
   String ToString() const;
diff --git a/third_party/WebKit/Source/core/layout/ng/ng_fragment_builder.cc b/third_party/WebKit/Source/core/layout/ng/ng_fragment_builder.cc
index cd230ac..300445ec 100644
--- a/third_party/WebKit/Source/core/layout/ng/ng_fragment_builder.cc
+++ b/third_party/WebKit/Source/core/layout/ng/ng_fragment_builder.cc
@@ -130,14 +130,15 @@
   return *this;
 }
 
-
 void NGFragmentBuilder::AddOutOfFlowLegacyCandidate(
     NGBlockNode node,
-    const NGStaticPosition& static_position) {
+    const NGStaticPosition& static_position,
+    LayoutObject* inline_container) {
   DCHECK_GE(inline_size_, LayoutUnit());
   DCHECK_GE(block_size_, LayoutUnit());
 
-  NGOutOfFlowPositionedDescendant descendant{node, static_position};
+  NGOutOfFlowPositionedDescendant descendant{node, static_position,
+                                             inline_container};
   // Need 0,0 physical coordinates as child offset. Because offset
   // is stored as logical, must convert physical 0,0 to logical.
   NGLogicalOffset zero_offset;
diff --git a/third_party/WebKit/Source/core/layout/ng/ng_fragment_builder.h b/third_party/WebKit/Source/core/layout/ng/ng_fragment_builder.h
index d34403f..baa547a4 100644
--- a/third_party/WebKit/Source/core/layout/ng/ng_fragment_builder.h
+++ b/third_party/WebKit/Source/core/layout/ng/ng_fragment_builder.h
@@ -60,7 +60,9 @@
   NGFragmentBuilder& PropagateBreak(scoped_refptr<NGLayoutResult>);
   NGFragmentBuilder& PropagateBreak(scoped_refptr<NGPhysicalFragment>);
 
-  void AddOutOfFlowLegacyCandidate(NGBlockNode, const NGStaticPosition&);
+  void AddOutOfFlowLegacyCandidate(NGBlockNode,
+                                   const NGStaticPosition&,
+                                   LayoutObject* inline_container);
 
   // Set how much of the block size we've used so far for this box.
   NGFragmentBuilder& SetUsedBlockSize(LayoutUnit used_block_size) {
@@ -147,6 +149,8 @@
       HashMap<const LayoutObject*, FragmentPair>* inline_container_fragments,
       NGLogicalSize* container_size);
 
+  LayoutObject* GetLayoutObject() { return layout_object_; }
+
  private:
   NGLayoutInputNode node_;
   LayoutObject* layout_object_;
diff --git a/third_party/WebKit/Source/core/layout/ng/ng_out_of_flow_layout_part.cc b/third_party/WebKit/Source/core/layout/ng/ng_out_of_flow_layout_part.cc
index 8d5a538..2a137c37 100644
--- a/third_party/WebKit/Source/core/layout/ng/ng_out_of_flow_layout_part.cc
+++ b/third_party/WebKit/Source/core/layout/ng/ng_out_of_flow_layout_part.cc
@@ -50,7 +50,7 @@
 void NGOutOfFlowLayoutPart::Run(bool update_legacy) {
   Vector<NGOutOfFlowPositionedDescendant> descendant_candidates;
   container_builder_->GetAndClearOutOfFlowDescendantCandidates(
-      &descendant_candidates);
+      &descendant_candidates, container_builder_->GetLayoutObject());
 
   while (descendant_candidates.size() > 0) {
     ComputeInlineContainingBlocks(descendant_candidates);
@@ -70,7 +70,7 @@
     // This happens when an absolute container has a fixed child.
     descendant_candidates.clear();
     container_builder_->GetAndClearOutOfFlowDescendantCandidates(
-        &descendant_candidates);
+        &descendant_candidates, container_builder_->GetLayoutObject());
   }
 }
 
@@ -108,6 +108,13 @@
           default_containing_block_.style->GetWritingMode());
   // Translate start/end fragments into ContainingBlockInfo.
   for (auto& block_info : inline_container_fragments) {
+    if (!block_info.value.start_fragment) {
+      // This happens when Legacy block is the default container.
+      // In this case, container builder does not have any fragments because
+      // ng layout algorithm did not run.
+      DCHECK(false);
+      // TODO(atotic) ContainingBlockInfo must be computed from Legacy algorithm
+    }
     NGLogicalOffset inline_content_offset;
     NGPhysicalOffset inline_content_physical_offset;
     NGLogicalSize inline_cb_size;
diff --git a/third_party/WebKit/Source/core/loader/WorkerFetchContext.cpp b/third_party/WebKit/Source/core/loader/WorkerFetchContext.cpp
index e943087..ee4c802 100644
--- a/third_party/WebKit/Source/core/loader/WorkerFetchContext.cpp
+++ b/third_party/WebKit/Source/core/loader/WorkerFetchContext.cpp
@@ -245,7 +245,6 @@
   DCHECK(!user_agent.IsNull());
   request.SetHTTPUserAgent(AtomicString(user_agent));
 
-  request.OverrideLoadingIPCType(WebURLRequest::LoadingIPCType::kMojo);
   WrappedResourceRequest webreq(request);
   web_context_->WillSendRequest(webreq);
 }
diff --git a/third_party/WebKit/Source/core/workers/DedicatedWorkerMessagingProxy.cpp b/third_party/WebKit/Source/core/workers/DedicatedWorkerMessagingProxy.cpp
index 97a4a6aa..65cb665 100644
--- a/third_party/WebKit/Source/core/workers/DedicatedWorkerMessagingProxy.cpp
+++ b/third_party/WebKit/Source/core/workers/DedicatedWorkerMessagingProxy.cpp
@@ -9,6 +9,7 @@
 #include "core/dom/Document.h"
 #include "core/events/ErrorEvent.h"
 #include "core/events/MessageEvent.h"
+#include "core/fetch/Request.h"
 #include "core/frame/csp/ContentSecurityPolicy.h"
 #include "core/inspector/MainThreadDebugger.h"
 #include "core/workers/DedicatedWorker.h"
@@ -21,6 +22,7 @@
 #include "platform/WebTaskRunner.h"
 #include "platform/wtf/WTF.h"
 #include "public/platform/TaskType.h"
+#include "services/network/public/interfaces/fetch_api.mojom-shared.h"
 
 namespace blink {
 
@@ -66,8 +68,11 @@
     GetWorkerThread()->EvaluateClassicScript(
         script_url, source_code, nullptr /* cached_meta_data */, stack_id);
   } else if (options.type() == "module") {
-    GetWorkerThread()->ImportModuleScript(
-        script_url, ParseCredentialsOption(options.credentials()));
+    network::mojom::FetchCredentialsMode credentials_mode;
+    bool result =
+        Request::ParseCredentialsMode(options.credentials(), &credentials_mode);
+    DCHECK(result);
+    GetWorkerThread()->ImportModuleScript(script_url, credentials_mode);
   } else {
     NOTREACHED();
   }
@@ -176,19 +181,6 @@
   ThreadedMessagingProxyBase::Trace(visitor);
 }
 
-network::mojom::FetchCredentialsMode
-DedicatedWorkerMessagingProxy::ParseCredentialsOption(
-    const String& credentials_option) {
-  if (credentials_option == "omit")
-    return network::mojom::FetchCredentialsMode::kOmit;
-  if (credentials_option == "same-origin")
-    return network::mojom::FetchCredentialsMode::kSameOrigin;
-  if (credentials_option == "include")
-    return network::mojom::FetchCredentialsMode::kInclude;
-  NOTREACHED();
-  return network::mojom::FetchCredentialsMode::kOmit;
-}
-
 WTF::Optional<WorkerBackingThreadStartupData>
 DedicatedWorkerMessagingProxy::CreateBackingThreadStartupData(
     v8::Isolate* isolate) {
diff --git a/third_party/WebKit/Source/core/workers/DedicatedWorkerMessagingProxy.h b/third_party/WebKit/Source/core/workers/DedicatedWorkerMessagingProxy.h
index 5cea19ca..a83cc300 100644
--- a/third_party/WebKit/Source/core/workers/DedicatedWorkerMessagingProxy.h
+++ b/third_party/WebKit/Source/core/workers/DedicatedWorkerMessagingProxy.h
@@ -16,7 +16,6 @@
 #include "platform/heap/Handle.h"
 #include "platform/weborigin/ReferrerPolicy.h"
 #include "platform/wtf/Optional.h"
-#include "services/network/public/interfaces/fetch_api.mojom-shared.h"
 
 namespace v8_inspector {
 struct V8StackTraceId;
@@ -71,11 +70,6 @@
  private:
   friend class DedicatedWorkerMessagingProxyForTest;
 
-  // TODO(nhiroki): Merge this into ParseCredentialsOption() in Worklet.cpp, or
-  // move this into core/fetch (see https://crbug.com/794837).
-  static network::mojom::FetchCredentialsMode ParseCredentialsOption(
-      const String& credentials_option);
-
   WTF::Optional<WorkerBackingThreadStartupData> CreateBackingThreadStartupData(
       v8::Isolate*);
 
diff --git a/third_party/WebKit/Source/core/workers/RequestCredentials.idl b/third_party/WebKit/Source/core/workers/RequestCredentials.idl
deleted file mode 100644
index 1212237..0000000
--- a/third_party/WebKit/Source/core/workers/RequestCredentials.idl
+++ /dev/null
@@ -1,10 +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.
-
-// https://fetch.spec.whatwg.org/#requestcredentials
-// Copied from modules/fetch/Request.idl because it's not accessible from core/
-// directory.
-// TODO(nhiroki): Consider how to reuse the existing enum (e.g.,
-// https://crbug.com/794837)
-enum RequestCredentials { "omit", "same-origin", "include" };
diff --git a/third_party/WebKit/Source/core/workers/Worklet.cpp b/third_party/WebKit/Source/core/workers/Worklet.cpp
index 5b89388..b3a1274 100644
--- a/third_party/WebKit/Source/core/workers/Worklet.cpp
+++ b/third_party/WebKit/Source/core/workers/Worklet.cpp
@@ -7,30 +7,16 @@
 #include "bindings/core/v8/ScriptPromiseResolver.h"
 #include "core/dom/DOMException.h"
 #include "core/dom/Document.h"
+#include "core/fetch/Request.h"
 #include "core/workers/WorkletPendingTasks.h"
 #include "platform/WebTaskRunner.h"
 #include "platform/wtf/WTF.h"
 #include "public/platform/TaskType.h"
 #include "public/platform/WebURLRequest.h"
+#include "services/network/public/interfaces/fetch_api.mojom-shared.h"
 
 namespace blink {
 
-namespace {
-
-network::mojom::FetchCredentialsMode ParseCredentialsOption(
-    const String& credentials_option) {
-  if (credentials_option == "omit")
-    return network::mojom::FetchCredentialsMode::kOmit;
-  if (credentials_option == "same-origin")
-    return network::mojom::FetchCredentialsMode::kSameOrigin;
-  if (credentials_option == "include")
-    return network::mojom::FetchCredentialsMode::kInclude;
-  NOTREACHED();
-  return network::mojom::FetchCredentialsMode::kOmit;
-}
-
-}  // namespace
-
 Worklet::Worklet(Document* document)
     : ContextLifecycleObserver(document),
       module_responses_map_(
@@ -110,9 +96,10 @@
     return;
 
   // Step 6: "Let credentialOptions be the credentials member of options."
-  // TODO(nhiroki): Add tests for credentialOptions (https://crbug.com/710837).
-  network::mojom::FetchCredentialsMode credentials_mode =
-      ParseCredentialsOption(options.credentials());
+  network::mojom::FetchCredentialsMode credentials_mode;
+  bool result =
+      Request::ParseCredentialsMode(options.credentials(), &credentials_mode);
+  DCHECK(result);
 
   // Step 7: "Let outsideSettings be the relevant settings object of this."
   // In the specification, outsideSettings is used for posting a task to the
diff --git a/third_party/WebKit/Source/modules/BUILD.gn b/third_party/WebKit/Source/modules/BUILD.gn
index 4ef12f6..4b065843 100644
--- a/third_party/WebKit/Source/modules/BUILD.gn
+++ b/third_party/WebKit/Source/modules/BUILD.gn
@@ -113,7 +113,6 @@
     "//third_party/WebKit/Source/modules/encryptedmedia",
     "//third_party/WebKit/Source/modules/eventsource",
     "//third_party/WebKit/Source/modules/exported",
-    "//third_party/WebKit/Source/modules/fetch",
     "//third_party/WebKit/Source/modules/filesystem",
     "//third_party/WebKit/Source/modules/gamepad",
     "//third_party/WebKit/Source/modules/geolocation",
@@ -180,10 +179,6 @@
   sources = [
     "accessibility/testing/InternalsAccessibility.cpp",
     "accessibility/testing/InternalsAccessibility.h",
-    "fetch/testing/InternalsFetch.cpp",
-    "fetch/testing/InternalsFetch.h",
-    "fetch/testing/WorkerInternalsFetch.cpp",
-    "fetch/testing/WorkerInternalsFetch.h",
     "mediastream/testing/InternalsMediaStream.cpp",
     "mediastream/testing/InternalsMediaStream.h",
     "navigatorcontentutils/testing/InternalsNavigatorContentUtils.cpp",
@@ -209,15 +204,11 @@
     sources += [
       "$bindings_modules_v8_output_dir/v8_internals_partial.cc",
       "$bindings_modules_v8_output_dir/v8_internals_partial.h",
-      "$bindings_modules_v8_output_dir/v8_worker_internals_partial.cc",
-      "$bindings_modules_v8_output_dir/v8_worker_internals_partial.h",
     ]
   } else {
     sources += [
       "$bindings_modules_v8_output_dir/V8InternalsPartial.cpp",
       "$bindings_modules_v8_output_dir/V8InternalsPartial.h",
-      "$bindings_modules_v8_output_dir/V8WorkerInternalsPartial.cpp",
-      "$bindings_modules_v8_output_dir/V8WorkerInternalsPartial.h",
     ]
   }
 
@@ -263,9 +254,6 @@
     "csspaint/PaintWorkletTest.cpp",
     "document_metadata/CopylessPasteExtractorTest.cpp",
     "eventsource/EventSourceParserTest.cpp",
-    "fetch/FetchResponseDataTest.cpp",
-    "fetch/RequestTest.cpp",
-    "fetch/ResponseTest.cpp",
     "filesystem/DOMFileSystemBaseTest.cpp",
     "indexeddb/IDBKeyPathTest.cpp",
     "indexeddb/IDBRequestTest.cpp",
@@ -311,8 +299,6 @@
     "push_messaging/PushMessageDataTest.cpp",
     "remoteplayback/RemotePlaybackTest.cpp",
     "serviceworkers/ServiceWorkerContainerTest.cpp",
-    "serviceworkers/ServiceWorkerInstalledScriptsManagerTest.cpp",
-    "serviceworkers/ThreadSafeScriptContainerTest.cpp",
     "serviceworkers/WebEmbeddedWorkerImplTest.cpp",
     "wake_lock/ScreenWakeLockTest.cpp",
     "webaudio/AudioBasicProcessorHandlerTest.cpp",
diff --git a/third_party/WebKit/Source/modules/background_fetch/BackgroundFetchFailEvent.cpp b/third_party/WebKit/Source/modules/background_fetch/BackgroundFetchFailEvent.cpp
index 1cdacc3..d0b335c6 100644
--- a/third_party/WebKit/Source/modules/background_fetch/BackgroundFetchFailEvent.cpp
+++ b/third_party/WebKit/Source/modules/background_fetch/BackgroundFetchFailEvent.cpp
@@ -4,11 +4,11 @@
 
 #include "modules/background_fetch/BackgroundFetchFailEvent.h"
 
+#include "core/fetch/Request.h"
+#include "core/fetch/Response.h"
 #include "modules/background_fetch/BackgroundFetchFailEventInit.h"
 #include "modules/background_fetch/BackgroundFetchSettledFetch.h"
 #include "modules/event_modules_names.h"
-#include "modules/fetch/Request.h"
-#include "modules/fetch/Response.h"
 #include "public/platform/modules/background_fetch/WebBackgroundFetchSettledFetch.h"
 
 namespace blink {
diff --git a/third_party/WebKit/Source/modules/background_fetch/BackgroundFetchFetch.cpp b/third_party/WebKit/Source/modules/background_fetch/BackgroundFetchFetch.cpp
index 65a2f9a..f14ef33 100644
--- a/third_party/WebKit/Source/modules/background_fetch/BackgroundFetchFetch.cpp
+++ b/third_party/WebKit/Source/modules/background_fetch/BackgroundFetchFetch.cpp
@@ -4,7 +4,7 @@
 
 #include "modules/background_fetch/BackgroundFetchFetch.h"
 
-#include "modules/fetch/Request.h"
+#include "core/fetch/Request.h"
 
 namespace blink {
 
diff --git a/third_party/WebKit/Source/modules/background_fetch/BackgroundFetchManager.cpp b/third_party/WebKit/Source/modules/background_fetch/BackgroundFetchManager.cpp
index bd4f551..ec3a8308 100644
--- a/third_party/WebKit/Source/modules/background_fetch/BackgroundFetchManager.cpp
+++ b/third_party/WebKit/Source/modules/background_fetch/BackgroundFetchManager.cpp
@@ -5,10 +5,11 @@
 #include "modules/background_fetch/BackgroundFetchManager.h"
 
 #include "bindings/core/v8/ScriptPromiseResolver.h"
-#include "bindings/modules/v8/request_or_usv_string.h"
+#include "bindings/core/v8/request_or_usv_string.h"
 #include "bindings/modules/v8/request_or_usv_string_or_request_or_usv_string_sequence.h"
 #include "core/dom/DOMException.h"
 #include "core/dom/ExceptionCode.h"
+#include "core/fetch/Request.h"
 #include "core/frame/Deprecation.h"
 #include "core/frame/UseCounter.h"
 #include "core/frame/csp/ContentSecurityPolicy.h"
@@ -16,7 +17,6 @@
 #include "modules/background_fetch/BackgroundFetchBridge.h"
 #include "modules/background_fetch/BackgroundFetchOptions.h"
 #include "modules/background_fetch/BackgroundFetchRegistration.h"
-#include "modules/fetch/Request.h"
 #include "modules/serviceworkers/ServiceWorkerRegistration.h"
 #include "platform/bindings/ScriptState.h"
 #include "platform/bindings/V8ThrowException.h"
diff --git a/third_party/WebKit/Source/modules/background_fetch/BackgroundFetchManagerTest.cpp b/third_party/WebKit/Source/modules/background_fetch/BackgroundFetchManagerTest.cpp
index e937094..7bce8987 100644
--- a/third_party/WebKit/Source/modules/background_fetch/BackgroundFetchManagerTest.cpp
+++ b/third_party/WebKit/Source/modules/background_fetch/BackgroundFetchManagerTest.cpp
@@ -8,10 +8,10 @@
 #include "bindings/core/v8/ExceptionState.h"
 #include "bindings/core/v8/V8BindingForCore.h"
 #include "bindings/core/v8/V8BindingForTesting.h"
-#include "bindings/modules/v8/request_or_usv_string.h"
+#include "bindings/core/v8/request_or_usv_string.h"
 #include "bindings/modules/v8/request_or_usv_string_or_request_or_usv_string_sequence.h"
 #include "core/dom/ExceptionCode.h"
-#include "modules/fetch/Request.h"
+#include "core/fetch/Request.h"
 #include "platform/bindings/ScriptState.h"
 #include "public/platform/modules/serviceworker/WebServiceWorkerRequest.h"
 #include "testing/gtest/include/gtest/gtest.h"
diff --git a/third_party/WebKit/Source/modules/background_fetch/BackgroundFetchSettledFetch.cpp b/third_party/WebKit/Source/modules/background_fetch/BackgroundFetchSettledFetch.cpp
index de258cd..c4a93fa 100644
--- a/third_party/WebKit/Source/modules/background_fetch/BackgroundFetchSettledFetch.cpp
+++ b/third_party/WebKit/Source/modules/background_fetch/BackgroundFetchSettledFetch.cpp
@@ -4,7 +4,7 @@
 
 #include "modules/background_fetch/BackgroundFetchSettledFetch.h"
 
-#include "modules/fetch/Response.h"
+#include "core/fetch/Response.h"
 
 namespace blink {
 
diff --git a/third_party/WebKit/Source/modules/background_fetch/BackgroundFetchedEvent.cpp b/third_party/WebKit/Source/modules/background_fetch/BackgroundFetchedEvent.cpp
index 466f0fc..f1896bc 100644
--- a/third_party/WebKit/Source/modules/background_fetch/BackgroundFetchedEvent.cpp
+++ b/third_party/WebKit/Source/modules/background_fetch/BackgroundFetchedEvent.cpp
@@ -6,12 +6,12 @@
 
 #include "bindings/core/v8/ScriptPromiseResolver.h"
 #include "core/dom/DOMException.h"
+#include "core/fetch/Request.h"
+#include "core/fetch/Response.h"
 #include "modules/background_fetch/BackgroundFetchBridge.h"
 #include "modules/background_fetch/BackgroundFetchSettledFetch.h"
 #include "modules/background_fetch/BackgroundFetchedEventInit.h"
 #include "modules/event_modules_names.h"
-#include "modules/fetch/Request.h"
-#include "modules/fetch/Response.h"
 #include "platform/bindings/ScriptState.h"
 #include "public/platform/modules/background_fetch/WebBackgroundFetchSettledFetch.h"
 
diff --git a/third_party/WebKit/Source/modules/cachestorage/Cache.cpp b/third_party/WebKit/Source/modules/cachestorage/Cache.cpp
index 5f1c7ceb..d2695e1 100644
--- a/third_party/WebKit/Source/modules/cachestorage/Cache.cpp
+++ b/third_party/WebKit/Source/modules/cachestorage/Cache.cpp
@@ -12,18 +12,17 @@
 #include "bindings/core/v8/NativeValueTraitsImpl.h"
 #include "bindings/core/v8/ScriptPromiseResolver.h"
 #include "bindings/core/v8/V8BindingForCore.h"
+#include "bindings/core/v8/V8Response.h"
 #include "bindings/core/v8/V8ScriptRunner.h"
-#include "bindings/modules/v8/V8Response.h"
 #include "core/dom/DOMException.h"
 #include "core/dom/ExecutionContext.h"
 #include "core/fetch/BodyStreamBuffer.h"
 #include "core/fetch/FetchDataLoader.h"
+#include "core/fetch/Request.h"
+#include "core/fetch/Response.h"
 #include "core/html/parser/TextResourceDecoder.h"
 #include "core/inspector/ConsoleMessage.h"
 #include "modules/cachestorage/CacheStorageError.h"
-#include "modules/fetch/GlobalFetch.h"
-#include "modules/fetch/Request.h"
-#include "modules/fetch/Response.h"
 #include "modules/serviceworkers/ServiceWorkerGlobalScope.h"
 #include "platform/Histogram.h"
 #include "platform/bindings/ScriptState.h"
diff --git a/third_party/WebKit/Source/modules/cachestorage/Cache.h b/third_party/WebKit/Source/modules/cachestorage/Cache.h
index e90de0d..a400891 100644
--- a/third_party/WebKit/Source/modules/cachestorage/Cache.h
+++ b/third_party/WebKit/Source/modules/cachestorage/Cache.h
@@ -7,9 +7,9 @@
 
 #include <memory>
 #include "bindings/core/v8/ScriptPromise.h"
+#include "core/fetch/GlobalFetch.h"
 #include "modules/ModulesExport.h"
 #include "modules/cachestorage/CacheQueryOptions.h"
-#include "modules/fetch/GlobalFetch.h"
 #include "platform/bindings/ScriptWrappable.h"
 #include "platform/wtf/Forward.h"
 #include "platform/wtf/Noncopyable.h"
diff --git a/third_party/WebKit/Source/modules/cachestorage/CacheStorage.cpp b/third_party/WebKit/Source/modules/cachestorage/CacheStorage.cpp
index bfd496b..4af3b86 100644
--- a/third_party/WebKit/Source/modules/cachestorage/CacheStorage.cpp
+++ b/third_party/WebKit/Source/modules/cachestorage/CacheStorage.cpp
@@ -12,10 +12,10 @@
 #include "core/dom/DOMException.h"
 #include "core/dom/ExceptionCode.h"
 #include "core/dom/ExecutionContext.h"
+#include "core/fetch/Request.h"
+#include "core/fetch/Response.h"
 #include "core/inspector/ConsoleMessage.h"
 #include "modules/cachestorage/CacheStorageError.h"
-#include "modules/fetch/Request.h"
-#include "modules/fetch/Response.h"
 #include "platform/bindings/ScriptState.h"
 #include "platform/network/http_names.h"
 #include "public/platform/modules/cache_storage/cache_storage.mojom-blink.h"
diff --git a/third_party/WebKit/Source/modules/cachestorage/CacheStorage.h b/third_party/WebKit/Source/modules/cachestorage/CacheStorage.h
index 9edbd43f..0079aec 100644
--- a/third_party/WebKit/Source/modules/cachestorage/CacheStorage.h
+++ b/third_party/WebKit/Source/modules/cachestorage/CacheStorage.h
@@ -7,9 +7,9 @@
 
 #include <memory>
 #include "bindings/core/v8/ScriptPromise.h"
+#include "core/fetch/GlobalFetch.h"
 #include "modules/cachestorage/Cache.h"
 #include "modules/cachestorage/CacheQueryOptions.h"
-#include "modules/fetch/GlobalFetch.h"
 #include "platform/bindings/ScriptState.h"
 #include "platform/bindings/ScriptWrappable.h"
 #include "platform/wtf/Forward.h"
diff --git a/third_party/WebKit/Source/modules/cachestorage/CacheTest.cpp b/third_party/WebKit/Source/modules/cachestorage/CacheTest.cpp
index 74d9264..2b0dac7e 100644
--- a/third_party/WebKit/Source/modules/cachestorage/CacheTest.cpp
+++ b/third_party/WebKit/Source/modules/cachestorage/CacheTest.cpp
@@ -17,18 +17,18 @@
 #include "bindings/core/v8/ScriptPromiseResolver.h"
 #include "bindings/core/v8/ScriptValue.h"
 #include "bindings/core/v8/V8BindingForCore.h"
-#include "bindings/modules/v8/V8Request.h"
-#include "bindings/modules/v8/V8Response.h"
+#include "bindings/core/v8/V8Request.h"
+#include "bindings/core/v8/V8Response.h"
 #include "core/dom/Document.h"
 #include "core/dom/ExecutionContext.h"
 #include "core/fetch/BodyStreamBuffer.h"
 #include "core/fetch/FormDataBytesConsumer.h"
+#include "core/fetch/GlobalFetch.h"
+#include "core/fetch/Request.h"
+#include "core/fetch/Response.h"
+#include "core/fetch/ResponseInit.h"
 #include "core/frame/Frame.h"
 #include "core/testing/DummyPageHolder.h"
-#include "modules/fetch/GlobalFetch.h"
-#include "modules/fetch/Request.h"
-#include "modules/fetch/Response.h"
-#include "modules/fetch/ResponseInit.h"
 #include "public/platform/WebURLResponse.h"
 #include "public/platform/modules/cache_storage/cache_storage.mojom-blink.h"
 #include "public/platform/modules/serviceworker/WebServiceWorkerCache.h"
diff --git a/third_party/WebKit/Source/modules/exported/WebEmbeddedWorkerImpl.cpp b/third_party/WebKit/Source/modules/exported/WebEmbeddedWorkerImpl.cpp
index 4e7ee19..0697862 100644
--- a/third_party/WebKit/Source/modules/exported/WebEmbeddedWorkerImpl.cpp
+++ b/third_party/WebKit/Source/modules/exported/WebEmbeddedWorkerImpl.cpp
@@ -59,7 +59,7 @@
 #include "platform/runtime_enabled_features.h"
 #include "platform/weborigin/SecurityOrigin.h"
 #include "platform/wtf/Functional.h"
-#include "public/platform/Platform.h"
+#include "platform/wtf/PtrUtil.h"
 #include "public/platform/TaskType.h"
 #include "public/platform/WebURLRequest.h"
 #include "public/platform/WebWorkerFetchContext.h"
@@ -69,19 +69,17 @@
 #include "public/web/WebDevToolsAgent.h"
 #include "public/web/WebSettings.h"
 #include "public/web/modules/serviceworker/WebServiceWorkerContextClient.h"
-#include "third_party/WebKit/common/service_worker/service_worker_installed_scripts_manager.mojom-blink.h"
 
 namespace blink {
 
-// static
 std::unique_ptr<WebEmbeddedWorker> WebEmbeddedWorker::Create(
     std::unique_ptr<WebServiceWorkerContextClient> client,
-    std::unique_ptr<WebServiceWorkerInstalledScriptsManagerParams>
-        installed_scripts_manager_params,
+    std::unique_ptr<WebServiceWorkerInstalledScriptsManager>
+        installed_scripts_manager,
     mojo::ScopedMessagePipeHandle content_settings_handle,
     mojo::ScopedMessagePipeHandle interface_provider) {
   return std::make_unique<WebEmbeddedWorkerImpl>(
-      std::move(client), std::move(installed_scripts_manager_params),
+      std::move(client), std::move(installed_scripts_manager),
       std::make_unique<ServiceWorkerContentSettingsProxy>(
           // Chrome doesn't use interface versioning.
           mojom::blink::WorkerContentSettingsProxyPtrInfo(
@@ -91,25 +89,10 @@
           service_manager::mojom::blink::InterfaceProvider::Version_));
 }
 
-// static
-std::unique_ptr<WebEmbeddedWorkerImpl> WebEmbeddedWorkerImpl::CreateForTesting(
-    std::unique_ptr<WebServiceWorkerContextClient> client,
-    std::unique_ptr<ServiceWorkerInstalledScriptsManager>
-        installed_scripts_manager) {
-  auto worker_impl = std::make_unique<WebEmbeddedWorkerImpl>(
-      std::move(client), nullptr /* installed_scripts_manager_params */,
-      std::make_unique<ServiceWorkerContentSettingsProxy>(
-          nullptr /* host_info */),
-      nullptr /* interface_provider_info */);
-  worker_impl->installed_scripts_manager_ =
-      std::move(installed_scripts_manager);
-  return worker_impl;
-}
-
 WebEmbeddedWorkerImpl::WebEmbeddedWorkerImpl(
     std::unique_ptr<WebServiceWorkerContextClient> client,
-    std::unique_ptr<WebServiceWorkerInstalledScriptsManagerParams>
-        installed_scripts_manager_params,
+    std::unique_ptr<WebServiceWorkerInstalledScriptsManager>
+        installed_scripts_manager,
     std::unique_ptr<ServiceWorkerContentSettingsProxy> content_settings_client,
     service_manager::mojom::blink::InterfaceProviderPtrInfo
         interface_provider_info)
@@ -120,18 +103,10 @@
       waiting_for_debugger_state_(kNotWaitingForDebugger),
       interface_provider_info_(std::move(interface_provider_info)) {
   if (RuntimeEnabledFeatures::ServiceWorkerScriptStreamingEnabled() &&
-      installed_scripts_manager_params) {
-    DCHECK(installed_scripts_manager_params->manager_request.is_valid());
-    DCHECK(installed_scripts_manager_params->manager_host_ptr.is_valid());
-    installed_scripts_manager_ = std::make_unique<
-        ServiceWorkerInstalledScriptsManager>(
-        std::move(installed_scripts_manager_params->installed_scripts_urls),
-        mojom::blink::ServiceWorkerInstalledScriptsManagerRequest(
-            std::move(installed_scripts_manager_params->manager_request)),
-        mojom::blink::ServiceWorkerInstalledScriptsManagerHostPtrInfo(
-            std::move(installed_scripts_manager_params->manager_host_ptr),
-            mojom::blink::ServiceWorkerInstalledScriptsManagerHost::Version_),
-        Platform::Current()->GetIOTaskRunner());
+      installed_scripts_manager) {
+    installed_scripts_manager_ =
+        std::make_unique<ServiceWorkerInstalledScriptsManager>(
+            std::move(installed_scripts_manager));
   }
 }
 
diff --git a/third_party/WebKit/Source/modules/exported/WebEmbeddedWorkerImpl.h b/third_party/WebKit/Source/modules/exported/WebEmbeddedWorkerImpl.h
index e2930b2..befbf04 100644
--- a/third_party/WebKit/Source/modules/exported/WebEmbeddedWorkerImpl.h
+++ b/third_party/WebKit/Source/modules/exported/WebEmbeddedWorkerImpl.h
@@ -61,7 +61,7 @@
  public:
   WebEmbeddedWorkerImpl(
       std::unique_ptr<WebServiceWorkerContextClient>,
-      std::unique_ptr<WebServiceWorkerInstalledScriptsManagerParams>,
+      std::unique_ptr<WebServiceWorkerInstalledScriptsManager>,
       std::unique_ptr<ServiceWorkerContentSettingsProxy>,
       service_manager::mojom::blink::InterfaceProviderPtrInfo);
   ~WebEmbeddedWorkerImpl() override;
@@ -93,10 +93,6 @@
       WebApplicationCacheHostClient*) override;
   void OnShadowPageInitialized() override;
 
-  static std::unique_ptr<WebEmbeddedWorkerImpl> CreateForTesting(
-      std::unique_ptr<WebServiceWorkerContextClient>,
-      std::unique_ptr<ServiceWorkerInstalledScriptsManager>);
-
  private:
   // WebDevToolsAgentClient overrides.
   void SendProtocolMessage(int session_id,
diff --git a/third_party/WebKit/Source/modules/exported/WebTestingSupport.cpp b/third_party/WebKit/Source/modules/exported/WebTestingSupport.cpp
index 90c7031..9f21f79 100644
--- a/third_party/WebKit/Source/modules/exported/WebTestingSupport.cpp
+++ b/third_party/WebKit/Source/modules/exported/WebTestingSupport.cpp
@@ -26,7 +26,6 @@
 #include "public/web/WebTestingSupport.h"
 
 #include "bindings/modules/v8/V8InternalsPartial.h"
-#include "bindings/modules/v8/V8WorkerInternalsPartial.h"
 #include "core/testing/v8/WebCoreTestSupport.h"
 #include "public/web/WebLocalFrame.h"
 #include "v8/include/v8.h"
@@ -46,7 +45,6 @@
 
 void WebTestingSupport::InjectInternalsObject(v8::Local<v8::Context> context) {
   V8InternalsPartial::initialize();
-  V8WorkerInternalsPartial::initialize();
   v8::HandleScope handle_scope(v8::Isolate::GetCurrent());
   WebCoreTestSupport::InjectInternalsObject(context);
 }
diff --git a/third_party/WebKit/Source/modules/fetch/BUILD.gn b/third_party/WebKit/Source/modules/fetch/BUILD.gn
deleted file mode 100644
index ebf5680..0000000
--- a/third_party/WebKit/Source/modules/fetch/BUILD.gn
+++ /dev/null
@@ -1,28 +0,0 @@
-# Copyright 2016 The Chromium Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-import("//third_party/WebKit/Source/modules/modules.gni")
-
-blink_modules_sources("fetch") {
-  sources = [
-    "FetchManager.cpp",
-    "FetchManager.h",
-    "FetchRequestData.cpp",
-    "FetchRequestData.h",
-    "FetchResponseData.cpp",
-    "FetchResponseData.h",
-    "GlobalFetch.cpp",
-    "GlobalFetch.h",
-    "Request.cpp",
-    "Request.h",
-    "RequestInit.cpp",
-    "RequestInit.h",
-    "Response.cpp",
-    "Response.h",
-  ]
-
-  public_deps = [
-    "//third_party/WebKit/Source/platform",
-  ]
-}
diff --git a/third_party/WebKit/Source/modules/fetch/DEPS b/third_party/WebKit/Source/modules/fetch/DEPS
deleted file mode 100644
index 94ed0b5..0000000
--- a/third_party/WebKit/Source/modules/fetch/DEPS
+++ /dev/null
@@ -1,11 +0,0 @@
-include_rules = [
-    "+gin/public",
-    "-modules",
-    "+modules/ModulesExport.h",
-    "+modules/fetch",
-    "+mojo/common/data_pipe_utils.h",
-    "+mojo/public/cpp/bindings/binding_set.h",
-    "+mojo/public/cpp/system/data_pipe.h",
-    "+mojo/public/cpp/system/simple_watcher.h",
-    "+services/network/public/interfaces",
-]
diff --git a/third_party/WebKit/Source/modules/fetch/OWNERS b/third_party/WebKit/Source/modules/fetch/OWNERS
deleted file mode 100644
index d6b556d..0000000
--- a/third_party/WebKit/Source/modules/fetch/OWNERS
+++ /dev/null
@@ -1,7 +0,0 @@
-hiroshige@chromium.org
-horo@chromium.org
-tyoshino@chromium.org
-yhirano@chromium.org
-
-# TEAM: blink-network-dev@chromium.org
-# COMPONENT: Blink>Network>FetchAPI
diff --git a/third_party/WebKit/Source/modules/modules_idl_files.gni b/third_party/WebKit/Source/modules/modules_idl_files.gni
index b21459e..b3cf1ae 100644
--- a/third_party/WebKit/Source/modules/modules_idl_files.gni
+++ b/third_party/WebKit/Source/modules/modules_idl_files.gni
@@ -116,8 +116,6 @@
           "encryptedmedia/MediaKeySystemAccess.idl",
           "encryptedmedia/MediaKeys.idl",
           "eventsource/EventSource.idl",
-          "fetch/Request.idl",
-          "fetch/Response.idl",
           "filesystem/DOMFileSystem.idl",
           "filesystem/DOMFileSystemSync.idl",
           "filesystem/DirectoryEntry.idl",
@@ -484,7 +482,6 @@
                     "encryptedmedia/MediaKeySystemConfiguration.idl",
                     "encryptedmedia/MediaKeySystemMediaCapability.idl",
                     "eventsource/EventSourceInit.idl",
-                    "fetch/ResponseInit.idl",
                     "filesystem/FileSystemFlags.idl",
                     "gamepad/GamepadEffectParameters.idl",
                     "gamepad/GamepadEventInit.idl",
@@ -663,8 +660,6 @@
           "encryptedmedia/HTMLMediaElementEncryptedMedia.idl",
           "encryptedmedia/MediaKeysGetStatusForPolicy.idl",
           "encryptedmedia/NavigatorRequestMediaKeySystemAccess.idl",
-          "fetch/WindowFetch.idl",
-          "fetch/WorkerFetch.idl",
           "filesystem/DataTransferItemFileSystem.idl",
           "filesystem/DedicatedWorkerGlobalScopeFileSystem.idl",
           "filesystem/DevToolsHostFileSystem.idl",
@@ -734,8 +729,6 @@
     get_path_info(
         [
           "accessibility/testing/InternalsAccessibility.idl",
-          "fetch/testing/InternalsFetch.idl",
-          "fetch/testing/WorkerInternalsFetch.idl",
           "mediastream/testing/InternalsMediaStream.idl",
           "navigatorcontentutils/testing/InternalsNavigatorContentUtils.idl",
           "peerconnection/testing/InternalsRTCCertificate.idl",
diff --git a/third_party/WebKit/Source/modules/serviceworkers/BUILD.gn b/third_party/WebKit/Source/modules/serviceworkers/BUILD.gn
index df54e9c..f1797a5 100644
--- a/third_party/WebKit/Source/modules/serviceworkers/BUILD.gn
+++ b/third_party/WebKit/Source/modules/serviceworkers/BUILD.gn
@@ -56,8 +56,6 @@
     "ServiceWorkerWindowClient.h",
     "ServiceWorkerWindowClientCallback.cpp",
     "ServiceWorkerWindowClientCallback.h",
-    "ThreadSafeScriptContainer.cpp",
-    "ThreadSafeScriptContainer.h",
     "WaitUntilObserver.cpp",
     "WaitUntilObserver.h",
   ]
@@ -65,8 +63,4 @@
   public_deps = [
     "//third_party/WebKit/Source/platform",
   ]
-
-  deps = [
-    "//base",
-  ]
 }
diff --git a/third_party/WebKit/Source/modules/serviceworkers/DEPS b/third_party/WebKit/Source/modules/serviceworkers/DEPS
index 4f9af63..3b5a86b6 100644
--- a/third_party/WebKit/Source/modules/serviceworkers/DEPS
+++ b/third_party/WebKit/Source/modules/serviceworkers/DEPS
@@ -1,13 +1,10 @@
 include_rules = [
-    "+base/barrier_closure.h",
-    "+base/threading/thread_checker.h",
     "-modules",
     "+modules/EventModules.h",
     "+modules/EventTargetModules.h",
     "+modules/ModulesExport.h",
     "+modules/fetch",
     "+modules/serviceworkers",
-    "+mojo/public/cpp/bindings/strong_binding.h",
     "+mojo/public/cpp/system/data_pipe.h",
     "+services/network/public/interfaces",
 ]
@@ -21,11 +18,4 @@
         "+modules/payments",
         "+modules/push_messaging",
     ],
-    "ServiceWorkerInstalledScriptsManagerTest\.cpp": [
-        "+base/run_loop.h",
-        "+mojo/public/cpp/bindings/binding.h",
-    ],
-    "WebEmbeddedWorkerImplTest\.cpp": [
-        "+modules/exported",
-    ],
 }
diff --git a/third_party/WebKit/Source/modules/serviceworkers/FetchEvent.cpp b/third_party/WebKit/Source/modules/serviceworkers/FetchEvent.cpp
index 2057f6df..fd0cc5f 100644
--- a/third_party/WebKit/Source/modules/serviceworkers/FetchEvent.cpp
+++ b/third_party/WebKit/Source/modules/serviceworkers/FetchEvent.cpp
@@ -8,10 +8,10 @@
 #include "bindings/core/v8/ToV8ForCore.h"
 #include "core/dom/ExecutionContext.h"
 #include "core/fetch/BytesConsumerForDataConsumerHandle.h"
+#include "core/fetch/Request.h"
+#include "core/fetch/Response.h"
 #include "core/frame/UseCounter.h"
 #include "core/timing/WorkerGlobalScopePerformance.h"
-#include "modules/fetch/Request.h"
-#include "modules/fetch/Response.h"
 #include "modules/serviceworkers/FetchRespondWithObserver.h"
 #include "modules/serviceworkers/ServiceWorkerError.h"
 #include "modules/serviceworkers/ServiceWorkerGlobalScope.h"
diff --git a/third_party/WebKit/Source/modules/serviceworkers/FetchEvent.h b/third_party/WebKit/Source/modules/serviceworkers/FetchEvent.h
index b852bd0..cd1328e 100644
--- a/third_party/WebKit/Source/modules/serviceworkers/FetchEvent.h
+++ b/third_party/WebKit/Source/modules/serviceworkers/FetchEvent.h
@@ -11,9 +11,9 @@
 #include "bindings/core/v8/ScriptPromise.h"
 #include "bindings/core/v8/ScriptPromiseProperty.h"
 #include "core/dom/ContextLifecycleObserver.h"
+#include "core/fetch/Request.h"
 #include "modules/EventModules.h"
 #include "modules/ModulesExport.h"
-#include "modules/fetch/Request.h"
 #include "modules/serviceworkers/ExtendableEvent.h"
 #include "modules/serviceworkers/FetchEventInit.h"
 #include "modules/serviceworkers/WaitUntilObserver.h"
diff --git a/third_party/WebKit/Source/modules/serviceworkers/FetchRespondWithObserver.cpp b/third_party/WebKit/Source/modules/serviceworkers/FetchRespondWithObserver.cpp
index b9554454..6d5a0f6 100644
--- a/third_party/WebKit/Source/modules/serviceworkers/FetchRespondWithObserver.cpp
+++ b/third_party/WebKit/Source/modules/serviceworkers/FetchRespondWithObserver.cpp
@@ -10,7 +10,7 @@
 #include <v8.h>
 #include "bindings/core/v8/ScriptValue.h"
 #include "bindings/core/v8/V8BindingForCore.h"
-#include "bindings/modules/v8/V8Response.h"
+#include "bindings/core/v8/V8Response.h"
 #include "core/dom/ExecutionContext.h"
 #include "core/fetch/BodyStreamBuffer.h"
 #include "core/fetch/BytesConsumer.h"
diff --git a/third_party/WebKit/Source/modules/serviceworkers/ServiceWorkerGlobalScope.cpp b/third_party/WebKit/Source/modules/serviceworkers/ServiceWorkerGlobalScope.cpp
index e5db7e3..06df22b 100644
--- a/third_party/WebKit/Source/modules/serviceworkers/ServiceWorkerGlobalScope.cpp
+++ b/third_party/WebKit/Source/modules/serviceworkers/ServiceWorkerGlobalScope.cpp
@@ -41,6 +41,7 @@
 #include "core/dom/ExceptionCode.h"
 #include "core/dom/ExecutionContext.h"
 #include "core/dom/events/Event.h"
+#include "core/fetch/GlobalFetch.h"
 #include "core/inspector/ConsoleMessage.h"
 #include "core/inspector/WorkerInspectorController.h"
 #include "core/inspector/WorkerThreadDebugger.h"
@@ -51,7 +52,6 @@
 #include "core/workers/WorkerClients.h"
 #include "core/workers/WorkerReportingProxy.h"
 #include "modules/EventTargetModules.h"
-#include "modules/fetch/GlobalFetch.h"
 #include "modules/serviceworkers/RespondWithObserver.h"
 #include "modules/serviceworkers/ServiceWorkerClients.h"
 #include "modules/serviceworkers/ServiceWorkerGlobalScopeClient.h"
diff --git a/third_party/WebKit/Source/modules/serviceworkers/ServiceWorkerGlobalScope.h b/third_party/WebKit/Source/modules/serviceworkers/ServiceWorkerGlobalScope.h
index 89709cb2..bb00358 100644
--- a/third_party/WebKit/Source/modules/serviceworkers/ServiceWorkerGlobalScope.h
+++ b/third_party/WebKit/Source/modules/serviceworkers/ServiceWorkerGlobalScope.h
@@ -31,7 +31,7 @@
 #define ServiceWorkerGlobalScope_h
 
 #include <memory>
-#include "bindings/modules/v8/request_or_usv_string.h"
+#include "bindings/core/v8/request_or_usv_string.h"
 #include "core/workers/WorkerGlobalScope.h"
 #include "modules/ModulesExport.h"
 #include "platform/heap/Handle.h"
diff --git a/third_party/WebKit/Source/modules/serviceworkers/ServiceWorkerGlobalScopeClient.cpp b/third_party/WebKit/Source/modules/serviceworkers/ServiceWorkerGlobalScopeClient.cpp
index 94f8444f..b4deda6a 100644
--- a/third_party/WebKit/Source/modules/serviceworkers/ServiceWorkerGlobalScopeClient.cpp
+++ b/third_party/WebKit/Source/modules/serviceworkers/ServiceWorkerGlobalScopeClient.cpp
@@ -33,8 +33,8 @@
 #include <memory>
 #include <utility>
 #include "core/dom/ExecutionContext.h"
+#include "core/fetch/Response.h"
 #include "core/workers/WorkerGlobalScope.h"
-#include "modules/fetch/Response.h"
 #include "public/platform/WebURL.h"
 #include "public/platform/modules/payments/WebPaymentHandlerResponse.h"
 #include "public/platform/modules/serviceworker/WebServiceWorkerResponse.h"
diff --git a/third_party/WebKit/Source/modules/serviceworkers/ServiceWorkerInstalledScriptsManager.cpp b/third_party/WebKit/Source/modules/serviceworkers/ServiceWorkerInstalledScriptsManager.cpp
index 9828e1cf..626ca79e 100644
--- a/third_party/WebKit/Source/modules/serviceworkers/ServiceWorkerInstalledScriptsManager.cpp
+++ b/third_party/WebKit/Source/modules/serviceworkers/ServiceWorkerInstalledScriptsManager.cpp
@@ -7,247 +7,21 @@
 #include <memory>
 #include <utility>
 
-#include "base/barrier_closure.h"
-#include "base/threading/thread_checker.h"
 #include "core/html/parser/TextResourceDecoder.h"
 #include "modules/serviceworkers/ServiceWorkerThread.h"
-#include "mojo/public/cpp/bindings/strong_binding.h"
-#include "platform/CrossThreadFunctional.h"
-#include "platform/wtf/Functional.h"
-#include "platform/wtf/HashMap.h"
-#include "platform/wtf/Vector.h"
 #include "platform/wtf/text/StringBuilder.h"
-#include "public/platform/WebURL.h"
-#include "public/platform/WebVector.h"
 
 namespace blink {
 
-using RawScriptData = ThreadSafeScriptContainer::RawScriptData;
-
-namespace {
-
-// Receiver is a class to read a Mojo data pipe. Received data are stored in
-// chunks. Lives on the IO thread. Receiver is owned by Internal via
-// BundledReceivers. It is created to read the script body or metadata from a
-// data pipe, and is destroyed when the read finishes.
-class Receiver {
- public:
-  using BytesChunk = WebVector<char>;
-
-  Receiver(mojo::ScopedDataPipeConsumerHandle handle, uint64_t total_bytes)
-      : handle_(std::move(handle)),
-        watcher_(FROM_HERE, mojo::SimpleWatcher::ArmingPolicy::MANUAL),
-        remaining_bytes_(total_bytes) {}
-
-  void Start(base::OnceClosure callback) {
-    if (!handle_.is_valid()) {
-      std::move(callback).Run();
-      return;
-    }
-    callback_ = std::move(callback);
-    // Unretained is safe because |watcher_| is owned by |this|.
-    MojoResult rv = watcher_.Watch(
-        handle_.get(), MOJO_HANDLE_SIGNAL_READABLE,
-        WTF::BindRepeating(&Receiver::OnReadable, WTF::Unretained(this)));
-    DCHECK_EQ(MOJO_RESULT_OK, rv);
-    watcher_.ArmOrNotify();
-  }
-
-  void OnReadable(MojoResult) {
-    // It isn't necessary to handle MojoResult here since BeginReadDataRaw()
-    // returns an equivalent error.
-    const void* buffer = nullptr;
-    uint32_t bytes_read = 0;
-    MojoResult rv =
-        handle_->BeginReadData(&buffer, &bytes_read, MOJO_READ_DATA_FLAG_NONE);
-    switch (rv) {
-      case MOJO_RESULT_BUSY:
-      case MOJO_RESULT_INVALID_ARGUMENT:
-        NOTREACHED();
-        return;
-      case MOJO_RESULT_FAILED_PRECONDITION:
-        // Closed by peer.
-        OnCompleted();
-        return;
-      case MOJO_RESULT_SHOULD_WAIT:
-        watcher_.ArmOrNotify();
-        return;
-      case MOJO_RESULT_OK:
-        break;
-      default:
-        // mojo::BeginReadDataRaw() should not return any other values.
-        // Notify the error to the browser by resetting the handle even though
-        // it's in the middle of data transfer.
-        OnCompleted();
-        return;
-    }
-
-    if (bytes_read > 0)
-      chunks_.emplace_back(static_cast<const char*>(buffer), bytes_read);
-
-    rv = handle_->EndReadData(bytes_read);
-    DCHECK_EQ(rv, MOJO_RESULT_OK);
-    CHECK_GE(remaining_bytes_, bytes_read);
-    remaining_bytes_ -= bytes_read;
-    watcher_.ArmOrNotify();
-  }
-
-  bool is_running() const { return handle_.is_valid(); }
-  bool has_received_all_data() const { return remaining_bytes_ == 0; }
-
-  WTF::Vector<BytesChunk> TakeChunks() {
-    DCHECK(!is_running());
-    return std::move(chunks_);
-  }
-
- private:
-  void OnCompleted() {
-    handle_.reset();
-    watcher_.Cancel();
-    if (!has_received_all_data())
-      chunks_.clear();
-    DCHECK(callback_);
-    std::move(callback_).Run();
-  }
-
-  base::OnceClosure callback_;
-  mojo::ScopedDataPipeConsumerHandle handle_;
-  mojo::SimpleWatcher watcher_;
-
-  WTF::Vector<BytesChunk> chunks_;
-  uint64_t remaining_bytes_;
-};
-
-// BundledReceivers is a helper class to wait for the end of reading body and
-// meta data. Lives on the IO thread.
-class BundledReceivers {
- public:
-  BundledReceivers(mojo::ScopedDataPipeConsumerHandle meta_data_handle,
-                   uint64_t meta_data_size,
-                   mojo::ScopedDataPipeConsumerHandle body_handle,
-                   uint64_t body_size)
-      : meta_data_(std::move(meta_data_handle), meta_data_size),
-        body_(std::move(body_handle), body_size) {}
-
-  // Starts reading the pipes and invokes |callback| when both are finished.
-  void Start(base::OnceClosure callback) {
-    base::RepeatingClosure wait_all_closure =
-        base::BarrierClosure(2, std::move(callback));
-    meta_data_.Start(wait_all_closure);
-    body_.Start(wait_all_closure);
-  }
-
-  Receiver* meta_data() { return &meta_data_; }
-  Receiver* body() { return &body_; }
-
- private:
-  Receiver meta_data_;
-  Receiver body_;
-};
-
-// Internal lives on the IO thread. This receives
-// mojom::blink::ServiceWorkerScriptInfo for all installed scripts and then
-// starts reading the body and meta data from the browser. This instance will be
-// kept alive as long as the Mojo's connection is established.
-class Internal : public mojom::blink::ServiceWorkerInstalledScriptsManager {
- public:
-  // Called on the IO thread.
-  // Creates and binds a new Internal instance to |request|.
-  static void Create(
-      scoped_refptr<ThreadSafeScriptContainer> script_container,
-      mojom::blink::ServiceWorkerInstalledScriptsManagerRequest request) {
-    mojo::MakeStrongBinding(
-        std::make_unique<Internal>(std::move(script_container)),
-        std::move(request));
-  }
-
-  Internal(scoped_refptr<ThreadSafeScriptContainer> script_container)
-      : script_container_(std::move(script_container)), weak_factory_(this) {}
-
-  ~Internal() override {
-    DCHECK_CALLED_ON_VALID_THREAD(io_thread_checker_);
-    // Wake up a waiting thread so it does not wait forever. If the script has
-    // not been added yet, that means something went wrong. From here,
-    // script_container_->Wait() will return false if the script hasn't been
-    // added yet.
-    script_container_->OnAllDataAddedOnIOThread();
-  }
-
-  // Implements mojom::blink::ServiceWorkerInstalledScriptsManager.
-  // Called on the IO thread.
-  void TransferInstalledScript(
-      mojom::blink::ServiceWorkerScriptInfoPtr script_info) override {
-    DCHECK_CALLED_ON_VALID_THREAD(io_thread_checker_);
-    KURL script_url(script_info->script_url);
-    auto receivers = std::make_unique<BundledReceivers>(
-        std::move(script_info->meta_data), script_info->meta_data_size,
-        std::move(script_info->body), script_info->body_size);
-    receivers->Start(WTF::Bind(&Internal::OnScriptReceived,
-                               weak_factory_.GetWeakPtr(),
-                               std::move(script_info)));
-    DCHECK(!running_receivers_.Contains(script_url));
-    running_receivers_.insert(script_url, std::move(receivers));
-  }
-
-  // Called on the IO thread.
-  void OnScriptReceived(mojom::blink::ServiceWorkerScriptInfoPtr script_info) {
-    DCHECK_CALLED_ON_VALID_THREAD(io_thread_checker_);
-    auto iter = running_receivers_.find(script_info->script_url);
-    DCHECK(iter != running_receivers_.end());
-    std::unique_ptr<BundledReceivers> receivers = std::move(iter->value);
-    DCHECK(receivers);
-    if (!receivers->body()->has_received_all_data() ||
-        !receivers->meta_data()->has_received_all_data()) {
-      script_container_->AddOnIOThread(script_info->script_url,
-                                       RawScriptData::CreateInvalidInstance());
-      running_receivers_.erase(iter);
-      return;
-    }
-
-    auto script_data = RawScriptData::Create(
-        script_info->encoding, receivers->body()->TakeChunks(),
-        receivers->meta_data()->TakeChunks());
-    for (auto it : script_info->headers) {
-      script_data->AddHeader(it.key, it.value);
-    }
-    script_container_->AddOnIOThread(script_info->script_url,
-                                     std::move(script_data));
-    running_receivers_.erase(iter);
-  }
-
- private:
-  THREAD_CHECKER(io_thread_checker_);
-  HashMap<KURL, std::unique_ptr<BundledReceivers>> running_receivers_;
-  scoped_refptr<ThreadSafeScriptContainer> script_container_;
-  base::WeakPtrFactory<Internal> weak_factory_;
-};
-
-}  // namespace
-
 ServiceWorkerInstalledScriptsManager::ServiceWorkerInstalledScriptsManager(
-    WebVector<WebURL> installed_urls,
-    mojom::blink::ServiceWorkerInstalledScriptsManagerRequest manager_request,
-    mojom::blink::ServiceWorkerInstalledScriptsManagerHostPtrInfo
-        manager_host_ptr,
-    scoped_refptr<base::SingleThreadTaskRunner> io_task_runner)
-    : script_container_(base::MakeRefCounted<ThreadSafeScriptContainer>()) {
-  // We're on the main thread now, but |installed_urls_| will be accessed on the
-  // worker thread later, so make a deep copy of |url| as key.
-  for (WebURL& url : installed_urls)
-    installed_urls_.insert(KURL(url).Copy());
-  manager_host_ =
-      mojom::blink::ThreadSafeServiceWorkerInstalledScriptsManagerHostPtr::
-          Create(mojom::blink::ServiceWorkerInstalledScriptsManagerHostPtr(
-              std::move(manager_host_ptr)));
-  io_task_runner->PostTask(
-      FROM_HERE, ConvertToBaseCallback(
-                     CrossThreadBind(&Internal::Create, script_container_,
-                                     WTF::Passed(std::move(manager_request)))));
+    std::unique_ptr<WebServiceWorkerInstalledScriptsManager> manager)
+    : manager_(std::move(manager)) {
+  DCHECK(manager_);
 }
 
 bool ServiceWorkerInstalledScriptsManager::IsScriptInstalled(
     const KURL& script_url) const {
-  return installed_urls_.Contains(script_url);
+  return manager_->IsScriptInstalled(script_url);
 }
 
 InstalledScriptsManager::ScriptStatus
@@ -256,7 +30,8 @@
     InstalledScriptsManager::ScriptData* out_script_data) {
   DCHECK(!IsMainThread());
   // This blocks until the script is received from the browser.
-  std::unique_ptr<RawScriptData> raw_script_data = GetRawScriptData(script_url);
+  std::unique_ptr<WebServiceWorkerInstalledScriptsManager::RawScriptData>
+      raw_script_data = manager_->GetRawScriptData(script_url);
   DCHECK(raw_script_data);
   if (!raw_script_data->IsValid()) {
     *out_script_data = InstalledScriptsManager::ScriptData();
@@ -293,38 +68,4 @@
   return ScriptStatus::kSuccess;
 }
 
-std::unique_ptr<RawScriptData>
-ServiceWorkerInstalledScriptsManager::GetRawScriptData(const KURL& script_url) {
-  if (!IsScriptInstalled(script_url))
-    return nullptr;
-
-  ThreadSafeScriptContainer::ScriptStatus status =
-      script_container_->GetStatusOnWorkerThread(script_url);
-  // If the script has already been taken, request the browser to send the
-  // script.
-  if (status == ThreadSafeScriptContainer::ScriptStatus::kTaken) {
-    script_container_->ResetOnWorkerThread(script_url);
-    (*manager_host_)->RequestInstalledScript(script_url);
-    status = script_container_->GetStatusOnWorkerThread(script_url);
-  }
-
-  // If the script has not been received at this point, wait for arrival by
-  // blocking the worker thread.
-  if (status == ThreadSafeScriptContainer::ScriptStatus::kPending) {
-    // Wait for arrival of the script.
-    const bool success = script_container_->WaitOnWorkerThread(script_url);
-    // It can fail due to an error on Mojo pipes.
-    if (!success)
-      return RawScriptData::CreateInvalidInstance();
-    status = script_container_->GetStatusOnWorkerThread(script_url);
-    DCHECK_NE(ThreadSafeScriptContainer::ScriptStatus::kPending, status);
-  }
-
-  if (status == ThreadSafeScriptContainer::ScriptStatus::kFailed)
-    return RawScriptData::CreateInvalidInstance();
-  DCHECK_EQ(ThreadSafeScriptContainer::ScriptStatus::kReceived, status);
-
-  return script_container_->TakeOnWorkerThread(script_url);
-}
-
 }  // namespace blink
diff --git a/third_party/WebKit/Source/modules/serviceworkers/ServiceWorkerInstalledScriptsManager.h b/third_party/WebKit/Source/modules/serviceworkers/ServiceWorkerInstalledScriptsManager.h
index 71dd1c16..a6910cd07 100644
--- a/third_party/WebKit/Source/modules/serviceworkers/ServiceWorkerInstalledScriptsManager.h
+++ b/third_party/WebKit/Source/modules/serviceworkers/ServiceWorkerInstalledScriptsManager.h
@@ -6,30 +6,18 @@
 #define ServiceWorkerInstalledScriptsManager_h
 
 #include "core/workers/InstalledScriptsManager.h"
-#include "modules/ModulesExport.h"
-#include "modules/serviceworkers/ThreadSafeScriptContainer.h"
-#include "platform/weborigin/KURL.h"
-#include "platform/weborigin/KURLHash.h"
-#include "platform/wtf/HashSet.h"
-#include "public/platform/WebVector.h"
-#include "third_party/WebKit/common/service_worker/service_worker_installed_scripts_manager.mojom-blink.h"
+#include "public/platform/modules/serviceworker/WebServiceWorkerInstalledScriptsManager.h"
 
 namespace blink {
 
-class WebURL;
-
 // ServiceWorkerInstalledScriptsManager provides the main script and imported
 // scripts of an installed service worker. The scripts are streamed from the
 // browser process in parallel with worker thread initialization.
-class MODULES_EXPORT ServiceWorkerInstalledScriptsManager
+class ServiceWorkerInstalledScriptsManager final
     : public InstalledScriptsManager {
  public:
-  ServiceWorkerInstalledScriptsManager(
-      WebVector<WebURL> installed_urls,
-      mojom::blink::ServiceWorkerInstalledScriptsManagerRequest,
-      mojom::blink::ServiceWorkerInstalledScriptsManagerHostPtrInfo,
-      scoped_refptr<base::SingleThreadTaskRunner> io_task_runner);
-  virtual ~ServiceWorkerInstalledScriptsManager() = default;
+  explicit ServiceWorkerInstalledScriptsManager(
+      std::unique_ptr<WebServiceWorkerInstalledScriptsManager>);
 
   // InstalledScriptsManager implementation.
   bool IsScriptInstalled(const KURL& script_url) const override;
@@ -37,18 +25,9 @@
                              ScriptData* out_script_data) override;
 
  private:
-  friend class ServiceWorkerInstalledScriptsManagerTest;
-
-  std::unique_ptr<ThreadSafeScriptContainer::RawScriptData> GetRawScriptData(
-      const KURL& script_url);
-
-  WTF::HashSet<KURL> installed_urls_;
-  scoped_refptr<ThreadSafeScriptContainer> script_container_;
-  scoped_refptr<
-      mojom::blink::ThreadSafeServiceWorkerInstalledScriptsManagerHostPtr>
-      manager_host_;
+  std::unique_ptr<WebServiceWorkerInstalledScriptsManager> manager_;
 };
 
 }  // namespace blink
 
-#endif  // ServiceWorkerInstalledScriptsManager_h
+#endif  // WorkerInstalledScriptsManager_h
diff --git a/third_party/WebKit/Source/modules/serviceworkers/ThreadSafeScriptContainer.cpp b/third_party/WebKit/Source/modules/serviceworkers/ThreadSafeScriptContainer.cpp
deleted file mode 100644
index ccbe7bbf..0000000
--- a/third_party/WebKit/Source/modules/serviceworkers/ThreadSafeScriptContainer.cpp
+++ /dev/null
@@ -1,119 +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 "modules/serviceworkers/ThreadSafeScriptContainer.h"
-
-namespace blink {
-
-// static
-std::unique_ptr<ThreadSafeScriptContainer::RawScriptData>
-ThreadSafeScriptContainer::RawScriptData::Create(
-    const WTF::String& encoding,
-    WTF::Vector<BytesChunk> script_text,
-    WTF::Vector<BytesChunk> meta_data) {
-  return WTF::WrapUnique(new RawScriptData(encoding, std::move(script_text),
-                                           std::move(meta_data),
-                                           true /* is_valid */));
-}
-
-// static
-std::unique_ptr<ThreadSafeScriptContainer::RawScriptData>
-ThreadSafeScriptContainer::RawScriptData::CreateInvalidInstance() {
-  return WTF::WrapUnique(
-      new RawScriptData(WTF::String() /* encoding */, WTF::Vector<BytesChunk>(),
-                        WTF::Vector<BytesChunk>(), false /* is_valid */));
-}
-
-ThreadSafeScriptContainer::RawScriptData::RawScriptData(
-    const WTF::String& encoding,
-    WTF::Vector<BytesChunk> script_text,
-    WTF::Vector<BytesChunk> meta_data,
-    bool is_valid)
-    : is_valid_(is_valid),
-      encoding_(encoding.IsolatedCopy()),
-      script_text_(std::move(script_text)),
-      meta_data_(std::move(meta_data)),
-      headers_(std::make_unique<CrossThreadHTTPHeaderMapData>()) {}
-
-ThreadSafeScriptContainer::RawScriptData::~RawScriptData() = default;
-
-void ThreadSafeScriptContainer::RawScriptData::AddHeader(
-    const WTF::String& key,
-    const WTF::String& value) {
-  headers_->emplace_back(key.IsolatedCopy(), value.IsolatedCopy());
-}
-
-ThreadSafeScriptContainer::ThreadSafeScriptContainer()
-    : are_all_data_added_(false) {}
-
-void ThreadSafeScriptContainer::AddOnIOThread(
-    const KURL& url,
-    std::unique_ptr<RawScriptData> data) {
-  WTF::MutexLocker locker(mutex_);
-  DCHECK(!script_data_.Contains(url));
-  // |script_data_| is also accessed on the worker thread, so make a deep copy
-  // of |url| as key.
-  script_data_.insert(url.Copy(), std::move(data));
-  if (url == waiting_url_)
-    waiting_cv_.Signal();
-}
-
-ThreadSafeScriptContainer::ScriptStatus
-ThreadSafeScriptContainer::GetStatusOnWorkerThread(const KURL& url) {
-  WTF::MutexLocker locker(mutex_);
-  auto it = script_data_.find(url);
-  if (it == script_data_.end())
-    return ScriptStatus::kPending;
-  if (!it->value)
-    return ScriptStatus::kTaken;
-  if (!it->value->IsValid())
-    return ScriptStatus::kFailed;
-  return ScriptStatus::kReceived;
-}
-
-void ThreadSafeScriptContainer::ResetOnWorkerThread(const KURL& url) {
-  WTF::MutexLocker locker(mutex_);
-  script_data_.erase(url);
-}
-
-bool ThreadSafeScriptContainer::WaitOnWorkerThread(const KURL& url) {
-  WTF::MutexLocker locker(mutex_);
-  DCHECK(waiting_url_.IsEmpty())
-      << "The script container is unexpectedly shared among worker threads.";
-  waiting_url_ = url;
-  while (script_data_.find(url) == script_data_.end()) {
-    // If waiting script hasn't been added yet though all data are received,
-    // that means something went wrong.
-    if (are_all_data_added_) {
-      waiting_url_ = KURL();
-      return false;
-    }
-    // This is possible to be waken up spuriously, so that it's necessary to
-    // check if the entry is really added.
-    waiting_cv_.Wait(mutex_);
-  }
-  waiting_url_ = KURL();
-  // TODO(shimazu): Keep the status for each entries instead of using IsValid().
-  const auto& data = script_data_.at(url);
-  // Returns true if |data| has already been taken or is valid.
-  return !data || data->IsValid();
-}
-
-std::unique_ptr<ThreadSafeScriptContainer::RawScriptData>
-ThreadSafeScriptContainer::TakeOnWorkerThread(const KURL& url) {
-  WTF::MutexLocker locker(mutex_);
-  DCHECK(script_data_.Contains(url))
-      << "Script should be added before calling Take.";
-  return std::move(script_data_.find(url)->value);
-}
-
-void ThreadSafeScriptContainer::OnAllDataAddedOnIOThread() {
-  WTF::MutexLocker locker(mutex_);
-  are_all_data_added_ = true;
-  waiting_cv_.Broadcast();
-}
-
-ThreadSafeScriptContainer::~ThreadSafeScriptContainer() = default;
-
-}  // namespace blink
diff --git a/third_party/WebKit/Source/modules/serviceworkers/ThreadSafeScriptContainer.h b/third_party/WebKit/Source/modules/serviceworkers/ThreadSafeScriptContainer.h
deleted file mode 100644
index 6aa54139..0000000
--- a/third_party/WebKit/Source/modules/serviceworkers/ThreadSafeScriptContainer.h
+++ /dev/null
@@ -1,151 +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 ThreadSafeScriptContainer_h
-#define ThreadSafeScriptContainer_h
-
-#include <memory>
-
-#include "modules/ModulesExport.h"
-#include "platform/network/HTTPHeaderMap.h"
-#include "platform/weborigin/KURL.h"
-#include "platform/weborigin/KURLHash.h"
-#include "platform/wtf/HashMap.h"
-#include "platform/wtf/ThreadSafeRefCounted.h"
-#include "platform/wtf/ThreadingPrimitives.h"
-#include "platform/wtf/Vector.h"
-#include "platform/wtf/text/WTFString.h"
-#include "public/platform/WebVector.h"
-
-namespace blink {
-
-// ThreadSafeScriptContainer stores the scripts of a service worker for
-// startup. This container is created for each service worker. The IO thread
-// adds scripts to the container, and the worker thread takes the scripts.
-//
-// This class uses explicit synchronization because it needs to support
-// synchronous importScripts() from the worker thread.
-//
-// This class is ThreadSafeRefCounted because there is no ordering guarantee of
-// lifetime of its owners, i.e. ServiceWorkerInstalledScriptsManager and its
-// Internal class. ServiceWorkerInstalledScriptsManager is destroyed earlier
-// than Internal if the worker is terminated before all scripts are streamed,
-// and Internal is destroyed earlier if all of scripts are received before
-// finishing script evaluation.
-class MODULES_EXPORT ThreadSafeScriptContainer final
-    : public WTF::ThreadSafeRefCounted<ThreadSafeScriptContainer> {
- public:
-  // TODO(leonhsl): Eliminate RawScriptData struct and use
-  // InstalledScriptsManager::ScriptData directly.
-  using BytesChunk = WebVector<char>;
-
-  // Container of a script. All the fields of this class need to be
-  // cross-thread-transfer-safe.
-  class MODULES_EXPORT RawScriptData {
-   public:
-    static std::unique_ptr<RawScriptData> Create(
-        const WTF::String& encoding,
-        WTF::Vector<BytesChunk> script_text,
-        WTF::Vector<BytesChunk> meta_data);
-    static std::unique_ptr<RawScriptData> CreateInvalidInstance();
-
-    ~RawScriptData();
-
-    void AddHeader(const WTF::String& key, const WTF::String& value);
-
-    // Returns false if it fails to receive the script from the browser.
-    bool IsValid() const { return is_valid_; }
-    // The encoding of the script text.
-    const WTF::String& Encoding() const {
-      DCHECK(is_valid_);
-      return encoding_;
-    }
-    // An array of raw byte chunks of the script text.
-    const WTF::Vector<BytesChunk>& ScriptTextChunks() const {
-      DCHECK(is_valid_);
-      return script_text_;
-    }
-    // An array of raw byte chunks of the scripts's meta data from the script's
-    // V8 code cache.
-    const WTF::Vector<BytesChunk>& MetaDataChunks() const {
-      DCHECK(is_valid_);
-      return meta_data_;
-    }
-
-    // The HTTP headers of the script.
-    std::unique_ptr<CrossThreadHTTPHeaderMapData> TakeHeaders() {
-      DCHECK(is_valid_);
-      return std::move(headers_);
-    }
-
-   private:
-    RawScriptData(const WTF::String& encoding,
-                  WTF::Vector<BytesChunk> script_text,
-                  WTF::Vector<BytesChunk> meta_data,
-                  bool is_valid);
-    const bool is_valid_;
-    WTF::String encoding_;
-    WTF::Vector<BytesChunk> script_text_;
-    WTF::Vector<BytesChunk> meta_data_;
-    std::unique_ptr<CrossThreadHTTPHeaderMapData> headers_;
-  };
-
-  REQUIRE_ADOPTION_FOR_REFCOUNTED_TYPE();
-  ThreadSafeScriptContainer();
-
-  enum class ScriptStatus {
-    // The script data has been received.
-    kReceived,
-    // The script data has been received but it has already been taken.
-    kTaken,
-    // Receiving the script has failed.
-    kFailed,
-    // The script data has not been received yet.
-    kPending
-  };
-
-  // Called on the IO thread.
-  void AddOnIOThread(const KURL& script_url,
-                     std::unique_ptr<RawScriptData> raw_data);
-
-  // Called on the worker thread.
-  ScriptStatus GetStatusOnWorkerThread(const KURL& script_url);
-
-  // Removes the script. After calling this, ScriptStatus for the
-  // script will be kPending.
-  // Called on the worker thread.
-  void ResetOnWorkerThread(const KURL& script_url);
-
-  // Waits until the script is added. The thread is blocked until the script is
-  // available or receiving the script fails. Returns false if an error happens
-  // and the waiting script won't be available forever.
-  // Called on the worker thread.
-  bool WaitOnWorkerThread(const KURL& script_url);
-
-  // Called on the worker thread.
-  std::unique_ptr<RawScriptData> TakeOnWorkerThread(const KURL& script_url);
-
-  // Called if no more data will be added.
-  // Called on the IO thread.
-  void OnAllDataAddedOnIOThread();
-
- private:
-  friend class WTF::ThreadSafeRefCounted<ThreadSafeScriptContainer>;
-  ~ThreadSafeScriptContainer();
-
-  // |mutex_| protects |waiting_cv_|, |script_data_|, |waiting_url_| and
-  // |are_all_data_added_|.
-  WTF::Mutex mutex_;
-  // |waiting_cv_| is signaled when a script whose url matches to |waiting_url|
-  // is added, or OnAllDataAdded is called. The worker thread waits on this, and
-  // the IO thread signals it.
-  ThreadCondition waiting_cv_;
-  WTF::HashMap<KURL, std::unique_ptr<RawScriptData>> script_data_;
-  KURL waiting_url_;
-  bool are_all_data_added_;
-};
-
-}  // namespace blink
-
-#endif  // ThreadSafeScriptContainer_h
diff --git a/third_party/WebKit/Source/modules/serviceworkers/ThreadSafeScriptContainerTest.cpp b/third_party/WebKit/Source/modules/serviceworkers/ThreadSafeScriptContainerTest.cpp
deleted file mode 100644
index d0c59d7..0000000
--- a/third_party/WebKit/Source/modules/serviceworkers/ThreadSafeScriptContainerTest.cpp
+++ /dev/null
@@ -1,219 +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 "modules/serviceworkers/ThreadSafeScriptContainer.h"
-
-#include <memory>
-#include "platform/CrossThreadFunctional.h"
-#include "platform/WaitableEvent.h"
-#include "platform/wtf/Functional.h"
-#include "public/platform/Platform.h"
-#include "public/platform/WebThread.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace blink {
-
-using ScriptStatus = ThreadSafeScriptContainer::ScriptStatus;
-
-class ThreadSafeScriptContainerTest : public ::testing::Test {
- public:
-  ThreadSafeScriptContainerTest()
-      : writer_thread_(Platform::Current()->CreateThread("writer_thread")),
-        reader_thread_(Platform::Current()->CreateThread("reader_thread")),
-        writer_task_runner_(writer_thread_->GetSingleThreadTaskRunner()),
-        reader_task_runner_(reader_thread_->GetSingleThreadTaskRunner()),
-        container_(base::MakeRefCounted<ThreadSafeScriptContainer>()) {}
-
- protected:
-  WaitableEvent* AddOnWriterThread(
-      const KURL& url,
-      ThreadSafeScriptContainer::RawScriptData** out_data) {
-    writer_task_runner_->PostTask(
-        FROM_HERE,
-        ConvertToBaseCallback(CrossThreadBind(
-            [](scoped_refptr<ThreadSafeScriptContainer> container,
-               const KURL& url,
-               ThreadSafeScriptContainer::RawScriptData** out_data,
-               WaitableEvent* waiter) {
-              auto data = ThreadSafeScriptContainer::RawScriptData::Create(
-                  WTF::String::FromUTF8("utf-8") /* encoding */,
-                  WTF::Vector<WebVector<char>>() /* script_text */,
-                  WTF::Vector<WebVector<char>>() /* meta_data */);
-              *out_data = data.get();
-              container->AddOnIOThread(url, std::move(data));
-              waiter->Signal();
-            },
-            container_, url, CrossThreadUnretained(out_data),
-            CrossThreadUnretained(&writer_waiter_))));
-    return &writer_waiter_;
-  }
-
-  WaitableEvent* OnAllDataAddedOnWriterThread() {
-    writer_task_runner_->PostTask(
-        FROM_HERE, ConvertToBaseCallback(CrossThreadBind(
-                       [](scoped_refptr<ThreadSafeScriptContainer> container,
-                          WaitableEvent* waiter) {
-                         container->OnAllDataAddedOnIOThread();
-                         waiter->Signal();
-                       },
-                       container_, CrossThreadUnretained(&writer_waiter_))));
-    return &writer_waiter_;
-  }
-
-  WaitableEvent* GetStatusOnReaderThread(const KURL& url,
-                                         ScriptStatus* out_status) {
-    reader_task_runner_->PostTask(
-        FROM_HERE, ConvertToBaseCallback(CrossThreadBind(
-                       [](scoped_refptr<ThreadSafeScriptContainer> container,
-                          const KURL& url, ScriptStatus* out_status,
-                          WaitableEvent* waiter) {
-                         *out_status = container->GetStatusOnWorkerThread(url);
-                         waiter->Signal();
-                       },
-                       container_, url, CrossThreadUnretained(out_status),
-                       CrossThreadUnretained(&reader_waiter_))));
-    return &reader_waiter_;
-  }
-
-  WaitableEvent* WaitOnReaderThread(const KURL& url, bool* out_exists) {
-    reader_task_runner_->PostTask(
-        FROM_HERE,
-        ConvertToBaseCallback(CrossThreadBind(
-            [](scoped_refptr<ThreadSafeScriptContainer> container,
-               const KURL& url, bool* out_exists, WaitableEvent* waiter) {
-              *out_exists = container->WaitOnWorkerThread(url);
-              waiter->Signal();
-            },
-            container_, url, CrossThreadUnretained(out_exists),
-            CrossThreadUnretained(&reader_waiter_))));
-    return &reader_waiter_;
-  }
-
-  WaitableEvent* TakeOnReaderThread(
-      const KURL& url,
-      ThreadSafeScriptContainer::RawScriptData** out_data) {
-    reader_task_runner_->PostTask(
-        FROM_HERE, ConvertToBaseCallback(CrossThreadBind(
-                       [](scoped_refptr<ThreadSafeScriptContainer> container,
-                          const KURL& url,
-                          ThreadSafeScriptContainer::RawScriptData** out_data,
-                          WaitableEvent* waiter) {
-                         auto data = container->TakeOnWorkerThread(url);
-                         *out_data = data.get();
-                         waiter->Signal();
-                       },
-                       container_, url, CrossThreadUnretained(out_data),
-                       CrossThreadUnretained(&reader_waiter_))));
-    return &reader_waiter_;
-  }
-
- private:
-  std::unique_ptr<WebThread> writer_thread_;
-  std::unique_ptr<WebThread> reader_thread_;
-
-  scoped_refptr<base::SingleThreadTaskRunner> writer_task_runner_;
-  scoped_refptr<base::SingleThreadTaskRunner> reader_task_runner_;
-
-  WaitableEvent writer_waiter_;
-  WaitableEvent reader_waiter_;
-
-  scoped_refptr<ThreadSafeScriptContainer> container_;
-};
-
-TEST_F(ThreadSafeScriptContainerTest, WaitExistingKey) {
-  const KURL kKey("https://example.com/key");
-  {
-    ScriptStatus result = ScriptStatus::kReceived;
-    GetStatusOnReaderThread(kKey, &result)->Wait();
-    EXPECT_EQ(ScriptStatus::kPending, result);
-  }
-
-  ThreadSafeScriptContainer::RawScriptData* added_data;
-  {
-    bool result = false;
-    WaitableEvent* pending_wait = WaitOnReaderThread(kKey, &result);
-    // This should not be signaled until data is added.
-    EXPECT_FALSE(pending_wait->IsSignaled());
-    WaitableEvent* pending_write = AddOnWriterThread(kKey, &added_data);
-    pending_wait->Wait();
-    pending_write->Wait();
-    EXPECT_TRUE(result);
-  }
-
-  {
-    ScriptStatus result = ScriptStatus::kFailed;
-    GetStatusOnReaderThread(kKey, &result)->Wait();
-    EXPECT_EQ(ScriptStatus::kReceived, result);
-  }
-
-  {
-    ThreadSafeScriptContainer::RawScriptData* taken_data;
-    TakeOnReaderThread(kKey, &taken_data)->Wait();
-    EXPECT_EQ(added_data, taken_data);
-  }
-
-  {
-    ScriptStatus result = ScriptStatus::kFailed;
-    GetStatusOnReaderThread(kKey, &result)->Wait();
-    // The record of |kKey| should be exist though it's already taken.
-    EXPECT_EQ(ScriptStatus::kTaken, result);
-  }
-
-  {
-    bool result = false;
-    WaitOnReaderThread(kKey, &result)->Wait();
-    // Waiting for |kKey| should succeed.
-    EXPECT_TRUE(result);
-
-    ThreadSafeScriptContainer::RawScriptData* taken_data;
-    TakeOnReaderThread(kKey, &taken_data)->Wait();
-    // |taken_data| should be nullptr because it's already taken.
-    EXPECT_EQ(nullptr, taken_data);
-  }
-
-  // Finish adding data.
-  OnAllDataAddedOnWriterThread()->Wait();
-
-  {
-    bool result = false;
-    WaitOnReaderThread(kKey, &result)->Wait();
-    // The record has been already added, so Wait shouldn't fail.
-    EXPECT_TRUE(result);
-
-    ThreadSafeScriptContainer::RawScriptData* taken_data;
-    TakeOnReaderThread(kKey, &taken_data)->Wait();
-    // |taken_data| should be nullptr because it's already taken.
-    EXPECT_EQ(nullptr, taken_data);
-  }
-}
-
-TEST_F(ThreadSafeScriptContainerTest, WaitNonExistingKey) {
-  const KURL kKey("https://example.com/key");
-  {
-    ScriptStatus result = ScriptStatus::kReceived;
-    GetStatusOnReaderThread(kKey, &result)->Wait();
-    EXPECT_EQ(ScriptStatus::kPending, result);
-  }
-
-  {
-    bool result = true;
-    WaitableEvent* pending_wait = WaitOnReaderThread(kKey, &result);
-    // This should not be signaled until OnAllDataAdded is called.
-    EXPECT_FALSE(pending_wait->IsSignaled());
-    WaitableEvent* pending_on_all_data_added = OnAllDataAddedOnWriterThread();
-    pending_wait->Wait();
-    pending_on_all_data_added->Wait();
-    // Aborted wait should return false.
-    EXPECT_FALSE(result);
-  }
-
-  {
-    bool result = true;
-    WaitOnReaderThread(kKey, &result)->Wait();
-    // Wait fails immediately because OnAllDataAdded is called.
-    EXPECT_FALSE(result);
-  }
-}
-
-}  // namespace blink
diff --git a/third_party/WebKit/Source/modules/serviceworkers/WebEmbeddedWorkerImplTest.cpp b/third_party/WebKit/Source/modules/serviceworkers/WebEmbeddedWorkerImplTest.cpp
index dcfcbd0..6d57f00 100644
--- a/third_party/WebKit/Source/modules/serviceworkers/WebEmbeddedWorkerImplTest.cpp
+++ b/third_party/WebKit/Source/modules/serviceworkers/WebEmbeddedWorkerImplTest.cpp
@@ -5,9 +5,6 @@
 #include "public/web/WebEmbeddedWorker.h"
 
 #include <memory>
-#include "modules/exported/WebEmbeddedWorkerImpl.h"
-#include "modules/serviceworkers/ServiceWorkerInstalledScriptsManager.h"
-#include "modules/serviceworkers/ThreadSafeScriptContainer.h"
 #include "platform/WaitableEvent.h"
 #include "platform/WebTaskRunner.h"
 #include "platform/loader/fetch/ResourceError.h"
@@ -18,6 +15,7 @@
 #include "public/platform/WebContentSettingsClient.h"
 #include "public/platform/WebURLLoaderMockFactory.h"
 #include "public/platform/WebURLResponse.h"
+#include "public/platform/modules/serviceworker/WebServiceWorkerInstalledScriptsManager.h"
 #include "public/platform/modules/serviceworker/WebServiceWorkerNetworkProvider.h"
 #include "public/platform/modules/serviceworker/WebServiceWorkerProvider.h"
 #include "public/web/WebEmbeddedWorkerStartData.h"
@@ -26,7 +24,6 @@
 #include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "third_party/WebKit/common/message_port/message_port_channel.h"
-#include "third_party/WebKit/common/service_worker/service_worker_installed_scripts_manager.mojom-blink.h"
 
 namespace blink {
 namespace {
@@ -106,26 +103,11 @@
 };
 
 class MockServiceWorkerInstalledScriptsManager
-    : public ServiceWorkerInstalledScriptsManager {
+    : public WebServiceWorkerInstalledScriptsManager {
  public:
-  MockServiceWorkerInstalledScriptsManager()
-      : ServiceWorkerInstalledScriptsManager(
-            WebVector<WebURL>() /* installed_urls */,
-            mojom::blink::ServiceWorkerInstalledScriptsManagerRequest(
-                mojo::MessagePipe().handle1),
-            mojom::blink::ServiceWorkerInstalledScriptsManagerHostPtrInfo(
-                mojo::MessagePipe().handle0,
-                mojom::blink::ServiceWorkerInstalledScriptsManagerHost::
-                    Version_),
-            // Pass a temporary task runner to ensure
-            // ServiceWorkerInstalledScriptsManager construction succeeds.
-            Platform::Current()
-                ->CreateThread("io thread")
-                ->GetSingleThreadTaskRunner()){};
-  MOCK_CONST_METHOD1(IsScriptInstalled, bool(const KURL& script_url));
+  MOCK_CONST_METHOD1(IsScriptInstalled, bool(const WebURL& script_url));
   MOCK_METHOD1(GetRawScriptData,
-               std::unique_ptr<ThreadSafeScriptContainer::RawScriptData>(
-                   const KURL& script_url));
+               std::unique_ptr<RawScriptData>(const WebURL& script_url));
 };
 
 class WebEmbeddedWorkerImplTest : public ::testing::Test {
@@ -140,8 +122,9 @@
     } else {
       mock_installed_scripts_manager_ = nullptr;
     }
-    worker_ = WebEmbeddedWorkerImpl::CreateForTesting(
-        std::move(client), std::move(installed_scripts_manager));
+    worker_ = WebEmbeddedWorker::Create(
+        std::move(client), std::move(installed_scripts_manager),
+        mojo::ScopedMessagePipeHandle(), mojo::ScopedMessagePipeHandle());
 
     WebURL script_url = URLTestHelpers::ToKURL("https://www.example.com/sw.js");
     WebURLResponse response;
@@ -168,7 +151,7 @@
   WebEmbeddedWorkerStartData start_data_;
   MockServiceWorkerContextClient* mock_client_;
   MockServiceWorkerInstalledScriptsManager* mock_installed_scripts_manager_;
-  std::unique_ptr<WebEmbeddedWorkerImpl> worker_;
+  std::unique_ptr<WebEmbeddedWorker> worker_;
 };
 
 }  // namespace
@@ -205,7 +188,7 @@
       .WillOnce(::testing::Return(nullptr));
   if (mock_installed_scripts_manager_) {
     EXPECT_CALL(*mock_installed_scripts_manager_,
-                IsScriptInstalled(KURL(start_data_.script_url)))
+                IsScriptInstalled(start_data_.script_url))
         .Times(1)
         .WillOnce(::testing::Return(false));
   }
@@ -234,7 +217,7 @@
       .WillOnce(::testing::Return(nullptr));
   if (mock_installed_scripts_manager_) {
     EXPECT_CALL(*mock_installed_scripts_manager_,
-                IsScriptInstalled(KURL(start_data_.script_url)))
+                IsScriptInstalled(start_data_.script_url))
         .Times(1)
         .WillOnce(::testing::Return(false));
   }
@@ -278,7 +261,7 @@
       .WillOnce(::testing::Return(nullptr));
   if (mock_installed_scripts_manager_) {
     EXPECT_CALL(*mock_installed_scripts_manager_,
-                IsScriptInstalled(KURL(start_data_.script_url)))
+                IsScriptInstalled(start_data_.script_url))
         .Times(1)
         .WillOnce(::testing::Return(false));
   }
@@ -307,7 +290,7 @@
       .WillOnce(::testing::Return(nullptr));
   if (mock_installed_scripts_manager_) {
     EXPECT_CALL(*mock_installed_scripts_manager_,
-                IsScriptInstalled(KURL(start_data_.script_url)))
+                IsScriptInstalled(start_data_.script_url))
         .Times(1)
         .WillOnce(::testing::Return(false));
   }
@@ -325,7 +308,7 @@
   // This is called on the worker thread.
   if (mock_installed_scripts_manager_) {
     EXPECT_CALL(*mock_installed_scripts_manager_,
-                IsScriptInstalled(KURL(start_data_.script_url)))
+                IsScriptInstalled(start_data_.script_url))
         .Times(1)
         .WillOnce(::testing::Return(false));
   }
@@ -355,7 +338,7 @@
       .WillOnce(::testing::Return(nullptr));
   if (mock_installed_scripts_manager_) {
     EXPECT_CALL(*mock_installed_scripts_manager_,
-                IsScriptInstalled(KURL(start_data_.script_url)))
+                IsScriptInstalled(start_data_.script_url))
         .Times(1)
         .WillOnce(::testing::Return(false));
   }
@@ -378,7 +361,7 @@
   // This is called on the worker thread.
   if (mock_installed_scripts_manager_) {
     EXPECT_CALL(*mock_installed_scripts_manager_,
-                IsScriptInstalled(KURL(start_data_.script_url)))
+                IsScriptInstalled(start_data_.script_url))
         .Times(1)
         .WillOnce(::testing::Return(false));
   }
diff --git a/third_party/WebKit/Source/platform/BUILD.gn b/third_party/WebKit/Source/platform/BUILD.gn
index 644edb04..7f8e906 100644
--- a/third_party/WebKit/Source/platform/BUILD.gn
+++ b/third_party/WebKit/Source/platform/BUILD.gn
@@ -672,6 +672,7 @@
     "exported/WebScrollbarThemeGeometryNative.h",
     "exported/WebScrollbarThemePainter.cpp",
     "exported/WebSecurityOrigin.cpp",
+    "exported/WebServiceWorkerInstalledScriptsManager.cpp",
     "exported/WebServiceWorkerRequest.cpp",
     "exported/WebServiceWorkerResponse.cpp",
     "exported/WebServiceWorkerStreamHandle.cpp",
diff --git a/third_party/WebKit/Source/platform/WaitableEvent.cpp b/third_party/WebKit/Source/platform/WaitableEvent.cpp
index cd61b2f..c00f606 100644
--- a/third_party/WebKit/Source/platform/WaitableEvent.cpp
+++ b/third_party/WebKit/Source/platform/WaitableEvent.cpp
@@ -37,10 +37,6 @@
   impl_->Signal();
 }
 
-bool WaitableEvent::IsSignaled() {
-  return impl_->IsSignaled();
-}
-
 size_t WaitableEvent::WaitMultiple(const WTF::Vector<WaitableEvent*>& events) {
   std::vector<base::WaitableEvent*> base_events;
   for (size_t i = 0; i < events.size(); ++i)
diff --git a/third_party/WebKit/Source/platform/WaitableEvent.h b/third_party/WebKit/Source/platform/WaitableEvent.h
index 6fe0550..106b0201 100644
--- a/third_party/WebKit/Source/platform/WaitableEvent.h
+++ b/third_party/WebKit/Source/platform/WaitableEvent.h
@@ -70,10 +70,6 @@
   // a waiting thread has been released.
   void Signal();
 
-  // Returns true if the event is in the signaled state, else false.  If this
-  // is not a manual reset event, then this test will cause a reset.
-  bool IsSignaled();
-
   // Waits on multiple events and returns the index of the object that
   // has been signaled. Any event objects given to this method must
   // not deleted while this wait is happening.
diff --git a/third_party/WebKit/Source/platform/exported/WebServiceWorkerInstalledScriptsManager.cpp b/third_party/WebKit/Source/platform/exported/WebServiceWorkerInstalledScriptsManager.cpp
new file mode 100644
index 0000000..3ba7905
--- /dev/null
+++ b/third_party/WebKit/Source/platform/exported/WebServiceWorkerInstalledScriptsManager.cpp
@@ -0,0 +1,51 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "public/platform/modules/serviceworker/WebServiceWorkerInstalledScriptsManager.h"
+
+#include <memory>
+
+namespace blink {
+
+// static
+std::unique_ptr<WebServiceWorkerInstalledScriptsManager::RawScriptData>
+WebServiceWorkerInstalledScriptsManager::RawScriptData::Create(
+    WebString encoding,
+    WebVector<BytesChunk> script_text,
+    WebVector<BytesChunk> meta_data) {
+  return WTF::WrapUnique(
+      new RawScriptData(std::move(encoding), std::move(script_text),
+                        std::move(meta_data), true /* is_valid */));
+}
+
+// static
+std::unique_ptr<WebServiceWorkerInstalledScriptsManager::RawScriptData>
+WebServiceWorkerInstalledScriptsManager::RawScriptData::
+    CreateInvalidInstance() {
+  return WTF::WrapUnique(
+      new RawScriptData(WebString() /* encoding */, WebVector<BytesChunk>(),
+                        WebVector<BytesChunk>(), false /* is_valid */));
+}
+
+WebServiceWorkerInstalledScriptsManager::RawScriptData::RawScriptData(
+    WebString encoding,
+    WebVector<BytesChunk> script_text,
+    WebVector<BytesChunk> meta_data,
+    bool is_valid)
+    : is_valid_(is_valid),
+      encoding_(std::move(encoding)),
+      script_text_(std::move(script_text)),
+      meta_data_(std::move(meta_data)),
+      headers_(std::make_unique<CrossThreadHTTPHeaderMapData>()) {}
+
+WebServiceWorkerInstalledScriptsManager::RawScriptData::~RawScriptData() =
+    default;
+
+void WebServiceWorkerInstalledScriptsManager::RawScriptData::AddHeader(
+    const WebString& key,
+    const WebString& value) {
+  headers_->emplace_back(key, value);
+}
+
+}  // namespace blink
diff --git a/third_party/WebKit/Source/platform/exported/WebURLRequest.cpp b/third_party/WebKit/Source/platform/exported/WebURLRequest.cpp
index 0e2d50a..39c346c4 100644
--- a/third_party/WebKit/Source/platform/exported/WebURLRequest.cpp
+++ b/third_party/WebKit/Source/platform/exported/WebURLRequest.cpp
@@ -408,10 +408,6 @@
   return resource_request_->CORSPreflightPolicy();
 }
 
-WebURLRequest::LoadingIPCType WebURLRequest::GetLoadingIPCType() const {
-  return resource_request_->GetLoadingIPCType();
-}
-
 void WebURLRequest::SetNavigationStartTime(double navigation_start_seconds) {
   resource_request_->SetNavigationStartTime(navigation_start_seconds);
 }
diff --git a/third_party/WebKit/Source/platform/loader/fetch/ResourceRequest.cpp b/third_party/WebKit/Source/platform/loader/fetch/ResourceRequest.cpp
index a6976e9..d1ca12b 100644
--- a/third_party/WebKit/Source/platform/loader/fetch/ResourceRequest.cpp
+++ b/third_party/WebKit/Source/platform/loader/fetch/ResourceRequest.cpp
@@ -77,7 +77,6 @@
       is_external_request_(false),
       cors_preflight_policy_(
           network::mojom::CORSPreflightPolicy::kConsiderPreflight),
-      loading_ipc_type_(WebURLRequest::LoadingIPCType::kMojo),
       is_same_document_navigation_(false),
       input_perf_metric_report_policy_(
           InputToLoadPerfMetricReportPolicy::kNoReport),
@@ -119,7 +118,6 @@
   ui_start_time_ = data->ui_start_time_;
   is_external_request_ = data->is_external_request_;
   cors_preflight_policy_ = data->cors_preflight_policy_;
-  loading_ipc_type_ = data->loading_ipc_type_;
   input_perf_metric_report_policy_ = data->input_perf_metric_report_policy_;
   redirect_status_ = data->redirect_status_;
 }
@@ -206,7 +204,6 @@
   data->ui_start_time_ = ui_start_time_;
   data->is_external_request_ = is_external_request_;
   data->cors_preflight_policy_ = cors_preflight_policy_;
-  data->loading_ipc_type_ = loading_ipc_type_;
   data->input_perf_metric_report_policy_ = input_perf_metric_report_policy_;
   data->redirect_status_ = redirect_status_;
   return data;
diff --git a/third_party/WebKit/Source/platform/loader/fetch/ResourceRequest.h b/third_party/WebKit/Source/platform/loader/fetch/ResourceRequest.h
index 54c4bac7..d63cab1 100644
--- a/third_party/WebKit/Source/platform/loader/fetch/ResourceRequest.h
+++ b/third_party/WebKit/Source/platform/loader/fetch/ResourceRequest.h
@@ -334,13 +334,6 @@
     cors_preflight_policy_ = policy;
   }
 
-  void OverrideLoadingIPCType(WebURLRequest::LoadingIPCType loading_ipc_type) {
-    loading_ipc_type_ = loading_ipc_type;
-  }
-  WebURLRequest::LoadingIPCType GetLoadingIPCType() const {
-    return loading_ipc_type_;
-  }
-
   InputToLoadPerfMetricReportPolicy InputPerfMetricReportPolicy() const {
     return input_perf_metric_report_policy_;
   }
@@ -402,7 +395,6 @@
   double ui_start_time_;
   bool is_external_request_;
   network::mojom::CORSPreflightPolicy cors_preflight_policy_;
-  WebURLRequest::LoadingIPCType loading_ipc_type_;
   bool is_same_document_navigation_;
   InputToLoadPerfMetricReportPolicy input_perf_metric_report_policy_;
   RedirectStatus redirect_status_;
@@ -464,7 +456,6 @@
   double ui_start_time_;
   bool is_external_request_;
   network::mojom::CORSPreflightPolicy cors_preflight_policy_;
-  WebURLRequest::LoadingIPCType loading_ipc_type_;
   InputToLoadPerfMetricReportPolicy input_perf_metric_report_policy_;
   ResourceRequest::RedirectStatus redirect_status_;
 };
diff --git a/third_party/WebKit/Tools/Scripts/audit-non-blink-usage.py b/third_party/WebKit/Tools/Scripts/audit-non-blink-usage.py
index 0797088..5fc8252 100755
--- a/third_party/WebKit/Tools/Scripts/audit-non-blink-usage.py
+++ b/third_party/WebKit/Tools/Scripts/audit-non-blink-usage.py
@@ -34,7 +34,6 @@
             'base::Location',
             'base::MakeRefCounted',
             'base::Optional',
-            'base::RunLoop',
             'base::SingleThreadTaskRunner',
             'base::UnguessableToken',
             'base::WeakPtr',
@@ -47,7 +46,6 @@
 
             # //base/callback.h is allowed, but you need to use WTF::Bind or
             # WTF::BindRepeating to create callbacks in Blink.
-            'base::BarrierClosure',
             'base::OnceCallback',
             'base::OnceClosure',
             'base::RepeatingCallback',
diff --git a/third_party/WebKit/public/BUILD.gn b/third_party/WebKit/public/BUILD.gn
index 6c56d379..53ed3df 100644
--- a/third_party/WebKit/public/BUILD.gn
+++ b/third_party/WebKit/public/BUILD.gn
@@ -431,6 +431,7 @@
     "platform/modules/serviceworker/WebServiceWorkerClientsClaimCallbacks.h",
     "platform/modules/serviceworker/WebServiceWorkerClientsInfo.h",
     "platform/modules/serviceworker/WebServiceWorkerError.h",
+    "platform/modules/serviceworker/WebServiceWorkerInstalledScriptsManager.h",
     "platform/modules/serviceworker/WebServiceWorkerNetworkProvider.h",
     "platform/modules/serviceworker/WebServiceWorkerProvider.h",
     "platform/modules/serviceworker/WebServiceWorkerProviderClient.h",
diff --git a/third_party/WebKit/public/platform/WebURLRequest.h b/third_party/WebKit/public/platform/WebURLRequest.h
index a298dcd..286c7be 100644
--- a/third_party/WebKit/public/platform/WebURLRequest.h
+++ b/third_party/WebKit/public/platform/WebURLRequest.h
@@ -155,11 +155,6 @@
     kNone
   };
 
-  enum class LoadingIPCType : uint8_t {
-    kChromeIPC,
-    kMojo,
-  };
-
   class ExtraData {
    public:
     virtual ~ExtraData() = default;
@@ -341,8 +336,6 @@
   BLINK_PLATFORM_EXPORT network::mojom::CORSPreflightPolicy
   GetCORSPreflightPolicy() const;
 
-  BLINK_PLATFORM_EXPORT LoadingIPCType GetLoadingIPCType() const;
-
   BLINK_PLATFORM_EXPORT void SetNavigationStartTime(double);
 
   // PlzNavigate: specify that the request was intended to be loaded as a same
diff --git a/third_party/WebKit/public/platform/modules/serviceworker/WebServiceWorkerInstalledScriptsManager.h b/third_party/WebKit/public/platform/modules/serviceworker/WebServiceWorkerInstalledScriptsManager.h
new file mode 100644
index 0000000..fc46584
--- /dev/null
+++ b/third_party/WebKit/public/platform/modules/serviceworker/WebServiceWorkerInstalledScriptsManager.h
@@ -0,0 +1,97 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef WebServiceWorkerInstalledScriptsManager_h
+#define WebServiceWorkerInstalledScriptsManager_h
+
+#include "public/platform/WebString.h"
+#include "public/platform/WebURL.h"
+#include "public/platform/WebVector.h"
+
+#if INSIDE_BLINK
+#include <memory>
+#include "platform/network/HTTPHeaderMap.h"
+#endif  // INSIDE_BLINK
+
+namespace blink {
+
+// WebServiceWorkerInstalledScriptsManager provides installed main script and
+// imported scripts to the service worker thread. This is used by multiple
+// threads, so implementation needs to be thread safe.
+class WebServiceWorkerInstalledScriptsManager {
+ public:
+  using BytesChunk = WebVector<char>;
+  // Container of a script. All the fields of this class need to be
+  // cross-thread-transfer-safe.
+  class BLINK_PLATFORM_EXPORT RawScriptData {
+   public:
+    static std::unique_ptr<RawScriptData> Create(
+        WebString encoding,
+        WebVector<BytesChunk> script_text,
+        WebVector<BytesChunk> meta_data);
+    static std::unique_ptr<RawScriptData> CreateInvalidInstance();
+
+    // Implementation of the destructor should be in the Blink side because only
+    // Blink can know all of members.
+    ~RawScriptData();
+
+    void AddHeader(const WebString& key, const WebString& value);
+
+    // Returns false if it fails to receive the script from the browser.
+    bool IsValid() const { return is_valid_; }
+    // The encoding of the script text.
+    const WebString& Encoding() const {
+      DCHECK(is_valid_);
+      return encoding_;
+    }
+    // An array of raw byte chunks of the script text.
+    const WebVector<BytesChunk>& ScriptTextChunks() const {
+      DCHECK(is_valid_);
+      return script_text_;
+    }
+    // An array of raw byte chunks of the scripts's meta data from the script's
+    // V8 code cache.
+    const WebVector<BytesChunk>& MetaDataChunks() const {
+      DCHECK(is_valid_);
+      return meta_data_;
+    }
+
+#if INSIDE_BLINK
+    // The HTTP headers of the script.
+    std::unique_ptr<CrossThreadHTTPHeaderMapData> TakeHeaders() {
+      DCHECK(is_valid_);
+      return std::move(headers_);
+    }
+#endif  // INSIDE_BLINK
+
+   private:
+    // This instance must be created on the Blink side because only Blink can
+    // know the exact size of this instance.
+    RawScriptData(WebString encoding,
+                  WebVector<BytesChunk> script_text,
+                  WebVector<BytesChunk> meta_data,
+                  bool is_valid);
+    const bool is_valid_;
+    WebString encoding_;
+    WebVector<BytesChunk> script_text_;
+    WebVector<BytesChunk> meta_data_;
+#if INSIDE_BLINK
+    std::unique_ptr<CrossThreadHTTPHeaderMapData> headers_;
+#endif  // INSIDE_BLINK
+  };
+
+  virtual ~WebServiceWorkerInstalledScriptsManager() = default;
+
+  // Called on the main or worker thread.
+  virtual bool IsScriptInstalled(const blink::WebURL& script_url) const = 0;
+  // Returns the script data for |script_url|. When an error happened during
+  // receiving the script, returns an invalid instance.
+  // Called on the worker thread.
+  virtual std::unique_ptr<RawScriptData> GetRawScriptData(
+      const WebURL& script_url) = 0;
+};
+
+}  // namespace blink
+
+#endif  // WebServiceWorkerInstalledScriptsManager_h
diff --git a/third_party/WebKit/public/web/WebEmbeddedWorker.h b/third_party/WebKit/public/web/WebEmbeddedWorker.h
index df2e84c..26c74050 100644
--- a/third_party/WebKit/public/web/WebEmbeddedWorker.h
+++ b/third_party/WebKit/public/web/WebEmbeddedWorker.h
@@ -35,27 +35,16 @@
 
 #include "mojo/public/cpp/system/message_pipe.h"
 #include "public/platform/WebCommon.h"
-#include "public/platform/WebVector.h"
 
 namespace blink {
 
 class WebContentSettingsClient;
 class WebServiceWorkerContextClient;
+class WebServiceWorkerInstalledScriptsManager;
 class WebString;
-class WebURL;
 struct WebConsoleMessage;
 struct WebEmbeddedWorkerStartData;
 
-// As we're on the border line between non-Blink and Blink variants, we need
-// to use mojo::ScopedMessagePipeHandle to pass Mojo types.
-struct WebServiceWorkerInstalledScriptsManagerParams {
-  WebVector<WebURL> installed_scripts_urls;
-  // A handle for mojom::blink::ServiceWorkerInstalledScriptsManagerRequest.
-  mojo::ScopedMessagePipeHandle manager_request;
-  // A handle for mojom::blink::ServiceWorkerInstalledScriptsManagerHostPtrInfo.
-  mojo::ScopedMessagePipeHandle manager_host_ptr;
-};
-
 // An interface to start and terminate an embedded worker.
 // All methods of this class must be called on the main thread.
 class BLINK_EXPORT WebEmbeddedWorker {
@@ -66,10 +55,8 @@
   // WorkerGlobalScope.
   static std::unique_ptr<WebEmbeddedWorker> Create(
       std::unique_ptr<WebServiceWorkerContextClient>,
-      std::unique_ptr<WebServiceWorkerInstalledScriptsManagerParams>,
-      // A handle for mojom::blink::WorkerContentSettingsProxyPtrInfo.
+      std::unique_ptr<WebServiceWorkerInstalledScriptsManager>,
       mojo::ScopedMessagePipeHandle content_settings_handle,
-      // A handle for service_manager::mojom::blink::InterfaceProviderPtrInfo.
       mojo::ScopedMessagePipeHandle interface_provider);
 
   virtual ~WebEmbeddedWorker() {}
diff --git a/third_party/libaom/README.chromium b/third_party/libaom/README.chromium
index 63876dd9..12dcf82 100644
--- a/third_party/libaom/README.chromium
+++ b/third_party/libaom/README.chromium
@@ -2,9 +2,9 @@
 Short Name: libaom
 URL: https://aomedia.googlesource.com/aom/
 Version: 0
-Date: Monday November 20 2017
+Date: Saturday December 23 2017
 Branch: test-20170915
-Commit: cccda0db727c2282375b174104294b40911d1447
+Commit: cc92258a08d98f469dff1be288acbc322632377b
 License: BSD
 License File: source/libaom/LICENSE
 Security Critical: yes
diff --git a/tools/metrics/histograms/enums.xml b/tools/metrics/histograms/enums.xml
index 793e1c8e..9a74baed 100644
--- a/tools/metrics/histograms/enums.xml
+++ b/tools/metrics/histograms/enums.xml
@@ -7591,6 +7591,7 @@
   <int value="16" label="TSS communication error"/>
   <int value="17" label="TSS invalid handle"/>
   <int value="18" label="Keyset wrapped both by TPM and Scrypt"/>
+  <int value="19" label="Failed to clean up ephemeral cryptohome"/>
 </enum>
 
 <enum name="CryptohomeMigrationToGaiaId">
diff --git a/ui/message_center/message_center.cc b/ui/message_center/message_center.cc
index cd725869..1e6e6e1 100644
--- a/ui/message_center/message_center.cc
+++ b/ui/message_center/message_center.cc
@@ -22,7 +22,6 @@
 
 // static
 MessageCenter* MessageCenter::Get() {
-  DCHECK(g_message_center);
   return g_message_center;
 }